From 5b80bfd7bffd4c20d80b7c70a7130529e9a755dd Mon Sep 17 00:00:00 2001 From: ToshikazuOhiwa Date: Mon, 30 Mar 2020 09:24:26 +0900 Subject: agl-basesystem --- .../linux-renesas/0001-spi-sh-msiof-fixes.patch | 33 + .../0002-spi-spidev-add-spi-gpio-into-spidev.patch | 27 + .../0003-spi-spi-gpio-fix-CPOL-mode.patch | 42 + ...pi-spi-gpio-fix-set-CPOL-default-inverted.patch | 30 + ...rcar-pcie-Add-bus-notifier-so-we-can-limi.patch | 59 + ...heck-parent-bus-restrictions-in-dma_capab.patch | 94 + ...r_can-add-enable-and-standby-control-pins.patch | 156 + ...canfd-add-enable-and-standby-control-pins.patch | 119 + .../0012-mtd-Add-RPC-HyperFlash-driver.patch | 1028 ++ .../0013-IMR-driver-interim-patch.patch | 2002 +++ .../0014-lib-swiotlb-reduce-verbosity.patch | 40 + .../0015-gpio-max732x-fix-gpio-set.patch | 29 + .../0016-gpio-gpiolib-suppress-gpiod-warning.patch | 29 + ...0017-media-soc_camera-add-legacy-VIN-CSI2.patch | 5162 +++++++ ...as-r8a7797-Add-Renesas-R8A7797-SoC-suppor.patch | 5340 +++++++ ...a-v4l2-async-remove-unneeded-.registered_.patch | 51 + .../0020-ti-st-add-device-tree-support.patch | 236 + ...-btwilink-add-minimal-device-tree-support.patch | 54 + ...-check-condition-of-multiple-bindings-of-.patch | 49 + .../0023-ASoC-add-dummy-Si468x-driver.patch | 122 + ...4-wl18xx-do-not-invert-IRQ-on-WLxxxx-side.patch | 47 + ...-Enable-HPD-interrupts-to-support-hotplug.patch | 29 + ...11-add-polling-mode-when-no-irq-available.patch | 30 + ...ridge-adv7511-Add-interlaced-mode-support.patch | 44 + .../linux-renesas/0030-Gen3-LVDS-cameras.patch | 11563 +++++++++++++++ .../0031-media-i2c-Add-ov5647-sensor.patch | 951 ++ .../0032-media-i2c-Add-ov5642-sensor.patch | 2155 +++ ...-media-soc-camera-fix-parallel-i-f-in-VIN.patch | 69 + ...amera-Fix-VIDIOC_S_SELECTION-ioctl-miscal.patch | 50 + .../0036-Add-MOST-support-for-r8a77965.patch | 100 + ...c_camera-rcar_vin-Fix-VnCSI_IFMD-settings.patch | 98 + ...soc_camera-rcar_vin-Add-R-Car-M3N-support.patch | 236 + ...oc_camera-rcar_csi2-Add-R-Car-M3N-support.patch | 49 + .../0040-arm64-dts-renesas-add-ADAS-boards.patch | 13885 +++++++++++++++++++ ...enesas-ulcb-kf-Move-panel-configuration-t.patch | 125 + ...s-renesas-r8a7795-es1-h3ulcb-disable-eMMC.patch | 27 + ...pfc-pfc-r8a77965-Add-missing-avb_mii-pin-.patch | 154 + .../0045-clk-r8a779x-add-mlp-clock.patch | 38 + ...6-arm64-dts-renesas-r8a779x-add-mlp-nodes.patch | 62 + ...0047-arm64-dts-renesas-ulcb-kf-enable-sd3.patch | 28 + ...048-arm64-dts-renesas-ulcb-kf-enable-most.patch | 28 + .../0049-clk-r8a779x-add-IMP-clock.patch | 40 + ...0-arm64-dts-renesas-r8a779x-add-IMP-nodes.patch | 198 + ...as-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch | 6490 +++++++++ ...-rcar-sysc-Add-workaround-for-A3-PD-issue.patch | 278 + .../0062-IIO-lsm9ds0-add-IMU-driver.patch | 958 ++ ...-PCM3168A-add-TDM-modes-merge-ADC-and-DAC.patch | 474 + ...adv7511-Add-frequency-and-vrefresh-limita.patch | 96 + ...0066-pci-pcie-rcar-add-regulators-support.patch | 100 + ...ti-st-use-proper-way-to-get-shutdown-gpio.patch | 61 + ...68-drm-adv7511-use-smbus-to-retrieve-edid.patch | 53 + ...SoC-add-dummy-device-for-WL18xx-PCM-audio.patch | 128 + ...usb-hub-disable-autosuspend-for-SMSC-hubs.patch | 51 + .../0073-MOST-dim2-add-device-tree-support.patch | 169 + ...ST-dim2-add-R-Car3-related-initialization.patch | 63 + ...-MOST-core-fix-memory-allocation-at-arm64.patch | 54 + .../0076-MOST-dim2-Renesas-R-Car3-variant.patch | 120 + .../0077-MOST-dim2-add-timeouts.patch | 46 + .../0078-MOST-aim-fix-null-pointer-crash.patch | 29 + ...ngine-rcar-dmac-use-TCRB-instead-of-TCR-f.patch | 31 + .../0082-gpio-pca953x-fix-interrupt-trigger.patch | 28 + ...ixup-rsnd_ssi_master_clk_start-user-count.patch | 41 + .../linux-renesas/0100-LVDS-ar0132-use-raw12.patch | 152 + .../0101-LVDS-ar0132-use-context-swwitch.patch | 119 + ...gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch | 546 + ...0104-media-vsp1-extend-DRM-VSP1-interface.patch | 367 + ...ia-rcar-imr-IMR-driver-updates-for-raw-DL.patch | 538 + .../0106-media-rcar-imr-Add-RSE-support.patch | 327 + ...erial-sh-sci-Fix-minimal-rx_timeout-value.patch | 34 + .../0110-mmc-tmio-Add-SDHI-SEQUENCER-support.patch | 295 + ...c-renesas_sdhi-Add-SDHI-SEQUENCER-support.patch | 747 + ...enesas-ulcb-Make-AK4613-sound-device-name.patch | 34 + ...lcb-kf-increase-SDIO-frequency-for-WLAN-c.patch | 32 + .../linux-renesas/0114-Sony-IMX219-driver.patch | 1115 ++ ...-dts-renesas-ulcb-kf-enable-enable-IMX219.patch | 95 + ...-i2c-soc_camera-Fix-Bad-of_node_put-error.patch | 250 + .../0117-rcar-vin-fix-get_selection-use.patch | 48 + ...pio-Allow-GPIO-to-sleep-in-set-get_parent.patch | 43 + ...954x-reset-mux-in-case-of-error-during-bu.patch | 102 + ...lcb-kf-pcm3168a-reset-earlier-i2c-mux-dis.patch | 82 + ...enesas-ulcb-kf-Set-KOE-TX31D200VM0BAA-128.patch | 64 + ...enesas-ulcb-kf-Set-Mitsubishi-AA104XD12-1.patch | 64 + ...enesas-ulcb-kf-Set-Mitsubishi-AA121TD01-1.patch | 71 + .../0122-block-blk-mq-Fix-IO-hang.patch | 78 + ...around-Samsung-970-Pro-power-state-issues.patch | 33 + .../0124-nvme-pci-add-SGL-support.patch | 393 + ...-nvme-pci-don-t-open-code-nvme_reset_ctrl.patch | 36 + ...mit-max-IO-size-and-segments-to-avoid-hig.patch | 164 + ...pect-DMA_ATTR_NO_WARN-in-swiotlb_map_sg_a.patch | 33 + ...arm64-dts-Add-H3ULCB-VideoBox-2.1-support.patch | 292 + ...canfd-fix-possible-IRQ-storm-on-high-load.patch | 63 + .../0130-LVDS-ar0132-use-context-swwitch.patch | 119 + ...a-i2c-soc_camera-Bunch-update-from-2.23.1.patch | 13431 ++++++++++++++++++ ...fix-frame-sync-time-for-different-ref-clo.patch | 85 + .../0133-lvds-add-AR0323-imager.patch | 1998 +++ .../0134-lvds-add-ISX016-imager.patch | 729 + ...0135-LVDS-ar0233-set-frame-size-1920x1200.patch | 104 + .../0136-lvds-AR0233-add-different-vendor.patch | 258 + ...-lvds-poll-ub960-deserializer-lock-status.patch | 70 + ...0138-lvds-AR0231-modify-with-rev7-silicon.patch | 633 + ...0139-lvds-AR0233-modify-with-rev2-silicon.patch | 1349 ++ ...9x4-fix-remote-gpio-enablement-for-4-cams.patch | 81 + ...ia-soc_camera-imx390-Add-new-V4L-controls.patch | 122 + .../0142-lvds-AR233-add-rev1-silion-setup.patch | 1788 +++ ...0143-LVDS-AR0231-add-rev6-rev4-on-max9286.patch | 663 + .../0144-lvds-add-OV10640-imager.patch | 3174 +++++ ...ti9x4-fix-remote-gpio-enablement-on-UB913.patch | 37 + .../0146-lvds-add-dummy-imager-driver.patch | 350 + .../0147-lvds-ti9x4-use-REFCLK-23.0MHz.patch | 39 + .../0148-lvds-ar0231-fix-comments.patch | 48 + .../0149-lvds-ISX019-rename-isx016-to-isx019.patch | 1402 ++ .../0150-lvds-add-ISX016-imager.patch | 705 + ...0151-lvds-ti9x4-add-DVP-LSB-MSB-selection.patch | 67 + .../0152-lvds-AR323-fix-reset-gpio-nadling.patch | 145 + .../0153-lvds-OV495-fix-reset-gpio-handling.patch | 65 + ...lvds-AR0323-replace-with-REV2-setup-table.patch | 2888 ++++ .../0155-AR0143-add-original-ONSEMI-setup.patch | 1552 +++ .../0156-AR0143-enable-3exp-in-custom-setup.patch | 61 + .../0157-AR0143-add-choose-of-imager-setup.patch | 132 + ...8-MAX9286-fix-BWS-setup-to-reserve-reboot.patch | 85 + ...9286-adjust-POC-trigger-for-unstable-link.patch | 88 + .../0160-lvds-onsemi-fix-revsion-parsing.patch | 89 + ...-lvds-AR0233-add-module-trigger-parameter.patch | 116 + ...62-lvds-AR0233-migrate-to-composed-tables.patch | 539 + ...163-lvds-AP0101-AR014X-add-TI-serializers.patch | 76 + .../linux-renesas/0164-lvds-fix-vendor-names.patch | 125 + .../0165-LVDS-add-GW5200-IMX390-camera.patch | 673 + .../0166-lvds-AR0233-add-superexposure-plus.patch | 1251 ++ ...R0233-fix-matrix-size-set-default-h-vflip.patch | 90 + ...SX019-fix-add-address-intf-fix-read-write.patch | 228 + ...s-OVT-add-dvp_order-parameter-for-ov10635.patch | 67 + .../0170-media-i2c-add-AR0147-imager.patch | 2224 +++ ...ds-ONSEMI-fix-matrix-position-during-crop.patch | 130 + ...c-ar0147-fix-super-exposure-artifact-line.patch | 28 + .../0173-lvds-ti9x4-fix-remote-gpio-setup.patch | 132 + ...enesas-ulcb-vb2-Drive-CAN-controller-rese.patch | 89 + .../0175-lvds-ov2775-add-exposure-gain.patch | 76 + ...vds-geosemi-put-imager-to-autodetect-tail.patch | 58 + .../0177-media-rcar_vin-add-GREY-Y8-bypass.patch | 85 + .../0178-lvds-add-OV2311-imager.patch | 935 ++ ...oc_camera-Fix-more-Bad-of_node_put-errors.patch | 139 + .../0180-media-i2c-ov490-add-LI-cameras.patch | 61 + ...emove-conflicting-with-mainline-V3M-and-V.patch | 635 + .../0182-iommu-msm-Claim-bus-ops-on-probe.patch | 58 + .../0183-iommu-Clean-up-of_iommu_init_fn.patch | 163 + ...-vmsa-Hook-up-r8a779-70-95-DT-matching-co.patch | 67 + ...-display-bridge-Document-THC63LVD1024-LVD.patch | 96 + ...0186-gpio-rcar-document-R8A77980-bindings.patch | 32 + ...rm64-dts-renesas-r8a77980-add-SMP-support.patch | 93 + ...4-dts-renesas-r8a77980-add-GEther-support.patch | 47 + ...rm64-dts-renesas-v3hsk-add-GEther-support.patch | 61 + ...rm64-dts-renesas-r8a77980-add-I2C-support.patch | 145 + ...arm64-dts-renesas-condor-add-I2C0-support.patch | 67 + ...m64-dts-renesas-r8a77980-add-GPIO-support.patch | 123 + ...enesas-condor-v3hsk-specify-Ethernet-PHY-.patch | 50 + ...enesas-r8a77980-add-FCPVD-VSPD-DU-LVDS-su.patch | 112 + .../0195-sh_eth-fix-enum-RPADIR_BIT.patch | 38 + ...h_eth-remove-sh_eth_cpu_data-rpadir_value.patch | 95 + .../0197-sh_eth-fix-enum-A-M-PR_BIT.patch | 62 + ...-vmsa-Document-R-Car-V3H-and-E3-IPMMU-DT-.patch | 36 + ...-phy-Renesas-R-Car-Gen3-PCIe-PHY-bindings.patch | 54 + ...00-phy-Renesas-R-Car-gen3-PCIe-PHY-driver.patch | 208 + ...-irqchip-renesas-irqc-Document-r8a77980-s.patch | 33 + ...-dts-renesas-r8a77980-add-INTC-EX-support.patch | 49 + ...y-allow-scanning-busses-with-missing-phys.patch | 50 + ...m64-dts-renesas-r8a77980-add-RWDT-support.patch | 79 + ...64-enable-CMT-TMU-support-for-Renesas-SoC.patch | 33 + ...enesas-r8a77980-add-Cortex-A53-PMU-suppor.patch | 44 + ...m64-dts-renesas-r8a77980-move-IPMMU-nodes.patch | 164 + ...-renesas-r8a779-7-8-0-move-CAN-clock-node.patch | 86 + ...dts-renesas-r8a77980-add-CSI2-VIN-support.patch | 411 + ...rm64-dts-renesas-r8a77970-add-MMC-support.patch | 44 + ...-arm64-dts-renesas-v3msk-add-eMMC-support.patch | 72 + ...enesas-condor-v3hsk-add-DU-LVDS-HDMI-supp.patch | 312 + ...m64-dts-renesas-r8a77980-add-PCIe-support.patch | 96 + ...arm64-dts-renesas-condor-add-PCIe-support.patch | 45 + ...5-arm64-dts-renesas-v3hsk-Move-lvds0-node.patch | 61 + ...enesas-r8a77980-Attach-the-SYS-DMAC-to-th.patch | 54 + ...-dts-renesas-r8a779-7-8-0-add-CMT-support.patch | 185 + ...-timer-renesas-tmu-document-R8A779-7-8-0-.patch | 34 + ...-dts-renesas-r8a779-7-8-0-add-TPU-support.patch | 66 + ...-dts-renesas-r8a779-7-8-0-add-PWM-support.patch | 145 + ...Use-header-display-lists-for-all-WPF-outp.patch | 274 + ...-dts-renesas-r8a77970-add-thermal-support.patch | 72 + ...-dts-renesas-r8a77980-add-thermal-support.patch | 93 + ...-dts-renesas-r8a779-7-8-0-add-TMU-support.patch | 174 + ...ts-renesas-r8a779-7-8-0-add-MSIOF-support.patch | 163 + ...enesas-r8a77980-Connect-R-Car-V3H-AVB-to-.patch | 32 + ...-r8a77980-Add-OSC-predivider-configuratio.patch | 72 + ...esas-r8a77980-Add-RCLK-for-watchdog-timer.patch | 55 + ...229-drm-rcar-du-lvds-add-R8A77980-support.patch | 31 + ...flag-buses-which-demand-DMA-configuration.patch | 139 + ...x-Call-of_dma_configure-after-setting-bus.patch | 39 + ...-host1x-Cleanup-on-initialization-failure.patch | 48 + ...-move-dma-configuration-to-bus-infrastruc.patch | 261 + ...-drivers-remove-force-dma-flag-from-buses.patch | 252 + .../0235-clk-renesas-r8a77980-Add-CMT-clocks.patch | 36 + ...sas-r8a77970-Add-SD0H-SD0-clocks-for-SDHI.patch | 169 + .../0237-clk-renesas-r8a77970-Add-CMT-clocks.patch | 37 + .../0238-clk-renesas-r8a77970-Add-TMU-clocks.patch | 38 + ...-display-renesas-du-document-R8A77980-bin.patch | 43 + ...-display-renesas-lvds-document-R8A77980-b.patch | 34 + .../0241-clk-renesas-r8a77970-Add-TPU-clock.patch | 35 + ..._sdhi_internal_dmac-add-R8A77970-to-white.patch | 35 + ...-mmc-tmio_mmc-document-Renesas-R8A77970-b.patch | 33 + ...-thermal-rcar-gen3-thermal-document-R8A77.patch | 49 + ...al-rcar_gen3_thermal-add-R8A77980-support.patch | 39 + ...-thermal-rcar-thermal-document-R8A77970-b.patch | 54 + ...thermal-rcar_thermal-add-R8A77970-support.patch | 37 + .../0248-clk-renesas-r8a77970-Add-RPC-clocks.patch | 41 + ...pfc-r8a77970-Add-QSPI-pins-groups-and-fun.patch | 128 + ...pfc-r8a77980-Add-QSPI-pins-groups-and-fun.patch | 127 + ...-rcar-rcar-csi2-Update-V3M-E3-PHTW-tables.patch | 94 + ...-r8a77970-sysc-Remove-non-existent-CR7-po.patch | 50 + ...-r8a77970-sysc-Correct-names-of-A2DP-A2CN.patch | 61 + ...-r8a77980-sysc-Correct-names-of-A2DP-01-p.patch | 56 + ...-r8a77980-sysc-Correct-A3VIP-012-power-do.patch | 57 + .../0256-clk-renesas-r8a77970-Add-CPEX-clock.patch | 31 + ...0257-media-rcar-csi2-add-R8A77980-support.patch | 62 + .../0258-media-rcar-vin-add-R8A77980-support.patch | 87 + ...h-pfc-r8a77970-Add-missing-MOD_SEL0-field.patch | 34 + ...h-pfc-r8a77980-Add-missing-MOD_SEL0-field.patch | 34 + ...car-csi2-Fix-PHTW-table-values-for-E3-V3M.patch | 99 + ...pfc-Reduce-kernel-size-for-narrow-VIN-cha.patch | 165 + ...pfc-r8a77970-Deduplicate-VIN-01-pin-defin.patch | 186 + ...pfc-r8a77980-Deduplicate-VIN1-pin-definit.patch | 110 + ...ts-renesas-v3msk-specify-EtherAVB-PHY-IRQ.patch | 33 + ...sh_eth-rename-sh_eth_cpu_data-hw_checksum.patch | 104 + .../0267-sh_eth-RX-checksum-offload-support.patch | 232 + ...68-sh_eth-offload-RX-checksum-on-R7S72100.patch | 31 + ...269-sh_eth-offload-RX-checksum-on-R8A7740.patch | 32 + ...70-sh_eth-offload-RX-checksum-on-R8A77980.patch | 31 + ...0271-sh_eth-offload-RX-checksum-on-SH7734.patch | 31 + ...0272-sh_eth-offload-RX-checksum-on-SH7763.patch | 31 + ...nesas-rcar-gen3-Factor-out-cpg_reg_modify.patch | 119 + .../0274-clk-renesas-rcar-gen3-Add-spinlock.patch | 52 + ...0275-clk-renesas-rcar-gen3-Add-RPC-clocks.patch | 169 + .../0276-clk-renesas-r8a77980-Add-RPC-clocks.patch | 55 + ...-sh-pfc-r8a77970-Rename-IOCTRLx-registers.patch | 65 + ...-sh-pfc-r8a77980-Rename-IOCTRLx-registers.patch | 77 + ...-r8a77980-Fix-RPC-IF-module-clock-s-paren.patch | 34 + ...ts-renesas-r8a77980-Add-renesas-id-to-VIN.patch | 157 + ...0281-arm64-dts-renesas-eagle-Add-x1-clock.patch | 43 + ...enesas-r8a77980-condor-Add-GEther-support.patch | 80 + ...283-iommu-ipmmu-vmsa-Add-r8a77980-support.patch | 45 + ...u-ipmmu-vmsa-Fix-NULL-pointer-dereference.patch | 29 + ...mmu-ipmmu-vmsa-Add-r8a779-7-8-0-whitelist.patch | 65 + ...-renesas-r8a77980-cpg-mssr-Add-VIN-clocks.patch | 34 + ...-renesas-r8a77970-cpg-mssr-Add-IMR-clocks.patch | 30 + ...-renesas-r8a77980-cpg-mssr-Add-IMR-clocks.patch | 39 + ...k-renesas-r8a77970-cpg-mssr-Add-ISP-clock.patch | 27 + ...-renesas-r8a77980-cpg-mssr-Add-ISP-clocks.patch | 28 + ...-renesas-r8a77980-cpg-mssr-Add-IMP-clocks.patch | 36 + ...-renesas-r8a77980-cpg-mssr-Add-VIP-clocks.patch | 43 + ...-renesas-r8a77970-cpg-mssr-Add-IMP-clocks.patch | 33 + ...camera-Add-CONFIG_VIDEO_ADV_DEBUG-support.patch | 78 + ...form-soc_camera-Add-V4L2-R-Car-ISP-driver.patch | 2150 +++ ...orm-soc_camera-rcar_isp-Fix-unused-variab.patch | 51 + ...orm-soc_camera-rcar_vin-Update-R-Car-V3M-.patch | 57 + ...orm-soc_camera-rcar_vin-Add-r8a77980-supp.patch | 256 + ...orm-soc_camera-rcar_csi2-r8a77970-Update-.patch | 73 + ...orm-soc_camera-rcar_csi2-Add-r8a77980-sup.patch | 89 + ...enesas-r8a77970-Convert-VIN-nodes-to-soc_.patch | 116 + ...enesas-r8a77980-Convert-VIN-nodes-to-soc_.patch | 212 + ...enesas-r8a77970-Convert-SCI2-nodes-to-soc.patch | 56 + ...enesas-r8a77980-Convert-CSI2-nodes-to-soc.patch | 92 + ...-arm64-dts-renesas-r8a77970-Add-IMR-nodes.patch | 66 + ...-arm64-dts-renesas-r8a77980-Add-IMR-nodes.patch | 84 + ...7-arm64-dts-renesas-r8a77970-Add-ISP-node.patch | 36 + ...-arm64-dts-renesas-r8a77980-Add-ISP-nodes.patch | 46 + ...dts-renesas-eagle-Add-video-input-support.patch | 326 + ...ts-renesas-condor-Add-video-input-support.patch | 587 + ...s-renesas-v3msk-Add-reserved-memory-nodes.patch | 53 + ...s-renesas-v3hsk-Add-reserved-memory-nodes.patch | 53 + ...s-renesas-eagle-Add-reserved-memory-nodes.patch | 53 + ...-renesas-condor-Add-reserved-memory-nodes.patch | 54 + ...enesas-v3msk-Add-mmngr-and-mmngrbuf-nodes.patch | 36 + ...enesas-v3hsk-Add-mmngr-and-mmngrbuf-nodes.patch | 36 + ...enesas-eagle-Add-mmngr-and-mmngrbuf-nodes.patch | 36 + ...enesas-condor-Add-mmngr-and-mmngrbuf-node.patch | 36 + ...-arm64-dts-renesas-v3msk-Add-vspm_if-node.patch | 30 + ...-arm64-dts-renesas-v3hsk-Add-vspm_if-node.patch | 30 + ...-arm64-dts-renesas-eagle-Add-vspm_if-node.patch | 30 + ...arm64-dts-renesas-condor-Add-vspm_if-node.patch | 30 + ...4-dts-renesas-eagle-Add-Dialog-DA9063-MFD.patch | 56 + ...enesas-Add-r8a77970-eagle-function-suppor.patch | 41 + ...rm64-dts-renesas-Add-r8a77970-es1-support.patch | 131 + ...s-renesas-Add-r8a77970-v3msk-view-support.patch | 39 + ...dts-renesas-Add-r8a77970-v3msk-kf-support.patch | 39 + ...ts-renesas-Add-r8a77970-v3msk-vbm-support.patch | 44 + ...64-dts-renesas-Add-r8a77970-v3mzf-support.patch | 114 + ...ts-renesas-Add-r8a77980-v3hsk-vbm-support.patch | 57 + ...-dts-renesas-r8a779-7-8-0-Add-IMP-devices.patch | 321 + ...-arm64-dts-renesas-r8a77980-Add-VIP-nodes.patch | 183 + ...enesas-r8a779-78-0-Add-linux-multimedia-r.patch | 108 + .../0334-IMR-UIO-Driver-initial-version.patch | 816 ++ ...ia-rcar-imr-IMR-driver-updates-for-raw-DL.patch | 538 + .../0336-media-rcar-imr-Add-RSE-support.patch | 348 + ...7-rcar_imr-v4l2-driver-Fix-module-support.patch | 278 + ...r-and-V3Msk-Eagle-Remove-cma-default-area.patch | 103 + ...edia-rcar_imr-Enable-LUCE-for-NV16-format.patch | 49 + .../0340-clk-cs2000-add-support-for-cs2300.patch | 256 + ...port-for-8-4-channel-VideoBox-board-from-.patch | 1626 +++ ...s-r8a77970-Videobox-Mini-V3-board-support.patch | 95 + ...enesas-r8a77970-v3msk-Add-ethernet0-alias.patch | 31 + ...arm64-dts-renesas-r8a77970-Add-ISP0-alias.patch | 36 + ...rm64-dts-renesas-r8a77980-Add-ISP-aliases.patch | 46 + ...oc_camera-Add-soc_camera-host-preregister.patch | 74 + ...47-arm64-renesas-r8a77980-use-CSI-4-lanes.patch | 339 + ...Bunch-update-of-r8a77980-v3hsk-vb-4ch.dts.patch | 139 + ...enesas-r8a77980-VideoBox-Mini-fix-csi-spe.patch | 26 + ...enesas-r8a77980-v3hsk-vb-4ch-and-8ch-fix-.patch | 193 + ...enesas-r8a77980-VB-4ch-and-8ch-Add-PCIE-p.patch | 44 + ...r_du-Fix-physical-address-of-the-CMA-back.patch | 30 + ...oc_camera-rcar_csi2-add-dump-module-param.patch | 65 + ...edia-rcar_csi2-Disable-data-type-matching.patch | 58 + ...gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch | 547 + ...a-platform-vsp1-Extend-DRM-VSP1-interface.patch | 374 + ...r-du-rcar_du_vsp-Check-if-gem-buffer-has-.patch | 29 + ...orm-vsp1-Add-cropping-handling-to-VSP-alp.patch | 56 + ...orm-rcar_imr-Clean-up-to-avoid-compiler-w.patch | 106 + ...enesas-r8a77970-and-r8a77980-Add-CPU-oper.patch | 206 + .../0361-V3H-DTS-Add-FCPR-devices.patch | 70 + ...64-dts-r8a77980-v3hsk-Enable-onboard-eMMC.patch | 69 + ...enesas-r8a77980-v3hsk-vb-Xch-Fix-Ethernet.patch | 50 + ...rce-drivers-sh_cmt-Add-R-Car-gen3-support.patch | 37 + ...td-spi-nor-Add-R-Car-Gen3-RPC-QSPI-driver.patch | 1334 ++ ...-renesas-rpc-Workaround-256-byte-data-siz.patch | 35 + ...-Add-s25fs512s-and-s25fs128s-01-SPI-NOR-f.patch | 37 + ...64-dts-renesas-r8a77970-Add-RPC-QSPI-node.patch | 41 + ...64-dts-renesas-r8a77980-Add-RPC-QSPI-node.patch | 41 + ...enesas-v3msk-Add-s25fs512s-QSPI-flash-nod.patch | 107 + ...enesas-v3mzf-Add-s25fs512s-QSPI-flash-nod.patch | 104 + ...enesas-eagle-Add-s25fs512s-QSPI-flash-nod.patch | 107 + ...enesas-v3hsk-Add-s25fs512s-QSPI-flash-nod.patch | 101 + ...enesas-condor-Add-s25fs512s-QSPI-flash-no.patch | 108 + ...-renesas-rpc-Support-single-mode-write-co.patch | 61 + ...-spi-nor-renesas-rpc-Add-DMA-read-support.patch | 219 + .../0377-r8a779-78-dtsi-Add-iccom-nodes.patch | 196 + ...-renesas-Add-temperature-emergency-levels.patch | 52 + ...9-r8a77980-dts-Add-vbm-v3-on-r8a77980-SoC.patch | 70 + ...380-arm64-dts-r8a77970-Enable-TMU-and-CMT.patch | 101 + ...381-arm64-dts-r8a77980-Enable-TMU-and-CMT.patch | 101 + ...enesas-r8a77970-and-r8a77980-Add-QoS-node.patch | 46 + ...-renesas-r8a77970-cpg-mssr-Add-sadc-clock.patch | 26 + ...-arm64-dts-renesas-r8a77970-Add-sadc-node.patch | 37 + .../0385-iio-adc-Add-R-Car-SADC-driver.patch | 456 + .../0386-rcar-vin-add-ISP-source-enable.patch | 66 + .../0387-media-soc_camera-Add-events-support.patch | 426 + ...-media-rcar-imr-Add-stride-support-to-IMR.patch | 216 + ...64-renesas-r8a77980-VB-use-REFCLK-23.0MHZ.patch | 78 + ...-renesas-Add-V3x-VideoBox-FDPLink-support.patch | 123 + ...enesas-Enable-FDPLink-output-on-V3x-Video.patch | 71 + ...dge-thc63-Set-upper-clock-limit-to-150-MH.patch | 32 + ...ia-soc_camera-dummy-add-mbus-controls-ids.patch | 338 + .../0394-media-i2c-ar0233-fix-superexposure.patch | 31 + .../0395-media-i2c-ap0101-add-V-H-flip.patch | 63 + ...ia-i2c-ap0101-ar014x-get-OTP-more-complex.patch | 72 + ...dia-i2c-ar0147-add-mipi-rev3-lvds-support.patch | 1083 ++ .../0398-media-i2c-ar0147-add-SE-mode.patch | 284 + ...dia-i2c-ar0233-fix-artifact-line-at-vflip.patch | 59 + ...tform-soc_mediabus-add-Bayer-16bit-format.patch | 36 + ...-media-i2c-ov490_ov10640-add-group-switch.patch | 103 + ...402-media-i2c-gw5200-detection-workaround.patch | 118 + ...3-media-i2c-ov2311-put-to-autodetect-head.patch | 48 + ...2c-onsemi-imager-correct-trigger-handling.patch | 165 + .../0405-media-i2c-ov10640-fix-controls.patch | 70 + ...6-Add-new-custom_ioctl-ops-for-soc-camera.patch | 58 + ...ts-renesas-r8a77970-v3msk-Fix-memory-size.patch | 28 + ...enesas-v3hsk-Add-GEther-PHY-GPIO-reset-pi.patch | 36 + ...enesas-condor-Add-GEther-PHY-GPIO-reset-p.patch | 28 + ...enesas-eagle-Add-RAVB-PHY-GPIO-reset-pin-.patch | 28 + ...0411-media-soc_camera-add-MAX9288-support.patch | 956 ++ ...oc_camera-differenciate-max9286-and-max92.patch | 351 + .../0413-media-i2c-max9288-fix-stream-on-off.patch | 57 + ...414-gpio-pca953x-do-not-ignore-i2c-errors.patch | 33 + ...-xhci-rcar-Add-XHCI_TRUST_TX_LENGTH-quirk.patch | 37 + ...4-dtb-renesas-vb2.1-enable-usb2-channel-3.patch | 55 + ...1-add-simple-driver-to-start-device-over-.patch | 288 + ...64-dts-renesas-ulcb-vb2-fix-USB30-and-HUB.patch | 116 + ...r-gen3-usb2-power-on-port-in-host-mode-to.patch | 62 + .../recipes-kernel/linux/linux-renesas/cma.cfg | 2 + .../recipes-kernel/linux/linux-renesas/condor.cfg | 34 + .../linux/linux-renesas/disable-unused.cfg | 33 + .../recipes-kernel/linux/linux-renesas/eagle.cfg | 35 + .../linux/linux-renesas/hyperflash.cfg | 2 + .../recipes-kernel/linux/linux-renesas/imr.cfg | 3 + .../recipes-kernel/linux/linux-renesas/nvme.cfg | 2 + .../recipes-kernel/linux/linux-renesas/qspi.cfg | 3 + .../linux/linux-renesas/renesas-not-applied.scc | 16 + .../recipes-kernel/linux/linux-renesas/renesas.scc | 357 + .../linux/linux-renesas/salvator-x.cfg | 27 + .../linux/linux-renesas/sdhi_seq.cfg | 2 + .../recipes-kernel/linux/linux-renesas/ulcb.cfg | 87 + .../recipes-kernel/linux/linux-renesas/v3hsk.cfg | 43 + .../recipes-kernel/linux/linux-renesas/v3msk.cfg | 39 + .../recipes-kernel/linux/linux-renesas/v3mzf.cfg | 25 + .../linux/linux-renesas_4.14.bbappend | 134 + 398 files changed, 132088 insertions(+) create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0001-spi-sh-msiof-fixes.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0002-spi-spidev-add-spi-gpio-into-spidev.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0003-spi-spi-gpio-fix-CPOL-mode.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0006-spi-spi-gpio-fix-set-CPOL-default-inverted.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0008-Revert-PCI-rcar-pcie-Add-bus-notifier-so-we-can-limi.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0009-arm64-dma-check-parent-bus-restrictions-in-dma_capab.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0010-can-rcar_can-add-enable-and-standby-control-pins.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0011-can-rcar_canfd-add-enable-and-standby-control-pins.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0012-mtd-Add-RPC-HyperFlash-driver.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0013-IMR-driver-interim-patch.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0014-lib-swiotlb-reduce-verbosity.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0015-gpio-max732x-fix-gpio-set.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0016-gpio-gpiolib-suppress-gpiod-warning.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0017-media-soc_camera-add-legacy-VIN-CSI2.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0018-arm64-renesas-r8a7797-Add-Renesas-R8A7797-SoC-suppor.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0019-Revert-media-v4l2-async-remove-unneeded-.registered_.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0020-ti-st-add-device-tree-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0021-btwilink-add-minimal-device-tree-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0022-ASoC-Modify-check-condition-of-multiple-bindings-of-.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0023-ASoC-add-dummy-Si468x-driver.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0024-wl18xx-do-not-invert-IRQ-on-WLxxxx-side.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0025-drm-adv7511-Enable-HPD-interrupts-to-support-hotplug.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0026-drm-adv7511-add-polling-mode-when-no-irq-available.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0027-gpu-drm-bridge-adv7511-Add-interlaced-mode-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0030-Gen3-LVDS-cameras.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0031-media-i2c-Add-ov5647-sensor.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0032-media-i2c-Add-ov5642-sensor.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0033-media-soc-camera-fix-parallel-i-f-in-VIN.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0034-media-soc_camera-Fix-VIDIOC_S_SELECTION-ioctl-miscal.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0036-Add-MOST-support-for-r8a77965.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0037-media-soc_camera-rcar_vin-Fix-VnCSI_IFMD-settings.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0038-media-soc_camera-rcar_vin-Add-R-Car-M3N-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0039-media-soc_camera-rcar_csi2-Add-R-Car-M3N-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0041-arm64-dts-renesas-ulcb-kf-Move-panel-configuration-t.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0042-arm64-dts-renesas-r8a7795-es1-h3ulcb-disable-eMMC.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0043-pinctrl-sh-pfc-pfc-r8a77965-Add-missing-avb_mii-pin-.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0045-clk-r8a779x-add-mlp-clock.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0046-arm64-dts-renesas-r8a779x-add-mlp-nodes.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0047-arm64-dts-renesas-ulcb-kf-enable-sd3.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0048-arm64-dts-renesas-ulcb-kf-enable-most.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0049-clk-r8a779x-add-IMP-clock.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0050-arm64-dts-renesas-r8a779x-add-IMP-nodes.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0052-soc-renesas-rcar-sysc-Add-workaround-for-A3-PD-issue.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0062-IIO-lsm9ds0-add-IMU-driver.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0063-ASoC-PCM3168A-add-TDM-modes-merge-ADC-and-DAC.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0064-drm-bridge-adv7511-Add-frequency-and-vrefresh-limita.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0066-pci-pcie-rcar-add-regulators-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0067-ti-st-use-proper-way-to-get-shutdown-gpio.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0068-drm-adv7511-use-smbus-to-retrieve-edid.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0071-ASoC-add-dummy-device-for-WL18xx-PCM-audio.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0072-usb-hub-disable-autosuspend-for-SMSC-hubs.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0073-MOST-dim2-add-device-tree-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0074-MOST-dim2-add-R-Car3-related-initialization.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0075-MOST-core-fix-memory-allocation-at-arm64.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0076-MOST-dim2-Renesas-R-Car3-variant.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0077-MOST-dim2-add-timeouts.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0078-MOST-aim-fix-null-pointer-crash.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0079-Revert-dmaengine-rcar-dmac-use-TCRB-instead-of-TCR-f.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0082-gpio-pca953x-fix-interrupt-trigger.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0090-ASoC-rsnd-fixup-rsnd_ssi_master_clk_start-user-count.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0100-LVDS-ar0132-use-raw12.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0101-LVDS-ar0132-use-context-swwitch.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0103-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0104-media-vsp1-extend-DRM-VSP1-interface.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0105-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0106-media-rcar-imr-Add-RSE-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0109-serial-sh-sci-Fix-minimal-rx_timeout-value.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0110-mmc-tmio-Add-SDHI-SEQUENCER-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0111-mmc-renesas_sdhi-Add-SDHI-SEQUENCER-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0112-ARM64-dts-renesas-ulcb-Make-AK4613-sound-device-name.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0113-arm64-dts-ulcb-kf-increase-SDIO-frequency-for-WLAN-c.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0114-Sony-IMX219-driver.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0115-arm64-dts-renesas-ulcb-kf-enable-enable-IMX219.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0116-media-i2c-soc_camera-Fix-Bad-of_node_put-error.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0117-rcar-vin-fix-get_selection-use.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0118-clk-clk-gpio-Allow-GPIO-to-sleep-in-set-get_parent.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0119-i2c-mix-pca954x-reset-mux-in-case-of-error-during-bu.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0120-arm64-dts-ulcb-kf-pcm3168a-reset-earlier-i2c-mux-dis.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0121-arm64-dts-renesas-ulcb-kf-Set-KOE-TX31D200VM0BAA-128.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0121-arm64-dts-renesas-ulcb-kf-Set-Mitsubishi-AA104XD12-1.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0121-arm64-dts-renesas-ulcb-kf-Set-Mitsubishi-AA121TD01-1.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0122-block-blk-mq-Fix-IO-hang.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0123-nvme-Workaround-Samsung-970-Pro-power-state-issues.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0124-nvme-pci-add-SGL-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0125-nvme-pci-don-t-open-code-nvme_reset_ctrl.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0126-nvme-pci-limit-max-IO-size-and-segments-to-avoid-hig.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0127-swiotlb-Respect-DMA_ATTR_NO_WARN-in-swiotlb_map_sg_a.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0128-arm64-dts-Add-H3ULCB-VideoBox-2.1-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0129-can-rcar_canfd-fix-possible-IRQ-storm-on-high-load.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0130-LVDS-ar0132-use-context-swwitch.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0131-media-i2c-soc_camera-Bunch-update-from-2.23.1.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0132-lvds-ti960-fix-frame-sync-time-for-different-ref-clo.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0133-lvds-add-AR0323-imager.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0134-lvds-add-ISX016-imager.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0135-LVDS-ar0233-set-frame-size-1920x1200.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0136-lvds-AR0233-add-different-vendor.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0137-lvds-poll-ub960-deserializer-lock-status.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0138-lvds-AR0231-modify-with-rev7-silicon.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0139-lvds-AR0233-modify-with-rev2-silicon.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0140-lvds-ti9x4-fix-remote-gpio-enablement-for-4-cams.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0141-media-soc_camera-imx390-Add-new-V4L-controls.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0142-lvds-AR233-add-rev1-silion-setup.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0143-LVDS-AR0231-add-rev6-rev4-on-max9286.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0144-lvds-add-OV10640-imager.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0145-lvds-ti9x4-fix-remote-gpio-enablement-on-UB913.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0146-lvds-add-dummy-imager-driver.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0147-lvds-ti9x4-use-REFCLK-23.0MHz.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0148-lvds-ar0231-fix-comments.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0149-lvds-ISX019-rename-isx016-to-isx019.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0150-lvds-add-ISX016-imager.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0151-lvds-ti9x4-add-DVP-LSB-MSB-selection.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0152-lvds-AR323-fix-reset-gpio-nadling.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0153-lvds-OV495-fix-reset-gpio-handling.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0154-lvds-AR0323-replace-with-REV2-setup-table.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0155-AR0143-add-original-ONSEMI-setup.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0156-AR0143-enable-3exp-in-custom-setup.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0157-AR0143-add-choose-of-imager-setup.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0158-MAX9286-fix-BWS-setup-to-reserve-reboot.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0159-MAX9286-adjust-POC-trigger-for-unstable-link.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0160-lvds-onsemi-fix-revsion-parsing.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0161-lvds-AR0233-add-module-trigger-parameter.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0162-lvds-AR0233-migrate-to-composed-tables.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0163-lvds-AP0101-AR014X-add-TI-serializers.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0164-lvds-fix-vendor-names.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0165-LVDS-add-GW5200-IMX390-camera.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0166-lvds-AR0233-add-superexposure-plus.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0167-lvds-AR0233-fix-matrix-size-set-default-h-vflip.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0168-lvds-ISX019-fix-add-address-intf-fix-read-write.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0169-lvds-OVT-add-dvp_order-parameter-for-ov10635.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0170-media-i2c-add-AR0147-imager.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0171-lvds-ONSEMI-fix-matrix-position-during-crop.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0172-media-i2c-ar0147-fix-super-exposure-artifact-line.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0173-lvds-ti9x4-fix-remote-gpio-setup.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0174-arm64-dts-renesas-ulcb-vb2-Drive-CAN-controller-rese.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0175-lvds-ov2775-add-exposure-gain.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0176-lvds-geosemi-put-imager-to-autodetect-tail.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0177-media-rcar_vin-add-GREY-Y8-bypass.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0178-lvds-add-OV2311-imager.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0179-media-i2c-soc_camera-Fix-more-Bad-of_node_put-errors.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0180-media-i2c-ov490-add-LI-cameras.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0181-ARM64-dts-Remove-conflicting-with-mainline-V3M-and-V.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0182-iommu-msm-Claim-bus-ops-on-probe.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0183-iommu-Clean-up-of_iommu_init_fn.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0184-iommu-ipmmu-vmsa-Hook-up-r8a779-70-95-DT-matching-co.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0185-dt-bindings-display-bridge-Document-THC63LVD1024-LVD.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0186-gpio-rcar-document-R8A77980-bindings.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0187-arm64-dts-renesas-r8a77980-add-SMP-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0188-arm64-dts-renesas-r8a77980-add-GEther-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0189-arm64-dts-renesas-v3hsk-add-GEther-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0190-arm64-dts-renesas-r8a77980-add-I2C-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0191-arm64-dts-renesas-condor-add-I2C0-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0192-arm64-dts-renesas-r8a77980-add-GPIO-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0193-arm64-dts-renesas-condor-v3hsk-specify-Ethernet-PHY-.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0194-arm64-dts-renesas-r8a77980-add-FCPVD-VSPD-DU-LVDS-su.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0195-sh_eth-fix-enum-RPADIR_BIT.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0196-sh_eth-remove-sh_eth_cpu_data-rpadir_value.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0197-sh_eth-fix-enum-A-M-PR_BIT.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0198-iommu-ipmmu-vmsa-Document-R-Car-V3H-and-E3-IPMMU-DT-.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0199-dt-bindings-phy-Renesas-R-Car-Gen3-PCIe-PHY-bindings.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0200-phy-Renesas-R-Car-gen3-PCIe-PHY-driver.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0201-dt-bindings-irqchip-renesas-irqc-Document-r8a77980-s.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0202-arm64-dts-renesas-r8a77980-add-INTC-EX-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0203-net-phy-allow-scanning-busses-with-missing-phys.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0204-arm64-dts-renesas-r8a77980-add-RWDT-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0205-arm64-enable-CMT-TMU-support-for-Renesas-SoC.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0206-arm64-dts-renesas-r8a77980-add-Cortex-A53-PMU-suppor.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0207-arm64-dts-renesas-r8a77980-move-IPMMU-nodes.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0208-arm64-dts-renesas-r8a779-7-8-0-move-CAN-clock-node.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0209-arm64-dts-renesas-r8a77980-add-CSI2-VIN-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0210-arm64-dts-renesas-r8a77970-add-MMC-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0211-arm64-dts-renesas-v3msk-add-eMMC-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0212-arm64-dts-renesas-condor-v3hsk-add-DU-LVDS-HDMI-supp.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0213-arm64-dts-renesas-r8a77980-add-PCIe-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0214-arm64-dts-renesas-condor-add-PCIe-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0215-arm64-dts-renesas-v3hsk-Move-lvds0-node.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0216-arm64-dts-renesas-r8a77980-Attach-the-SYS-DMAC-to-th.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0217-arm64-dts-renesas-r8a779-7-8-0-add-CMT-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0218-dt-bindings-timer-renesas-tmu-document-R8A779-7-8-0-.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0219-arm64-dts-renesas-r8a779-7-8-0-add-TPU-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0220-arm64-dts-renesas-r8a779-7-8-0-add-PWM-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0221-media-vsp1-Use-header-display-lists-for-all-WPF-outp.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0222-arm64-dts-renesas-r8a77970-add-thermal-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0223-arm64-dts-renesas-r8a77980-add-thermal-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0224-arm64-dts-renesas-r8a779-7-8-0-add-TMU-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0225-arm64-dts-renesas-r8a779-7-8-0-add-MSIOF-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0226-arm64-dts-renesas-r8a77980-Connect-R-Car-V3H-AVB-to-.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0227-clk-renesas-r8a77980-Add-OSC-predivider-configuratio.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0228-clk-renesas-r8a77980-Add-RCLK-for-watchdog-timer.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0229-drm-rcar-du-lvds-add-R8A77980-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0230-drivers-flag-buses-which-demand-DMA-configuration.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0231-gpu-host1x-Call-of_dma_configure-after-setting-bus.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0232-gpu-host1x-Cleanup-on-initialization-failure.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0233-dma-mapping-move-dma-configuration-to-bus-infrastruc.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0234-drivers-remove-force-dma-flag-from-buses.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0235-clk-renesas-r8a77980-Add-CMT-clocks.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0236-clk-renesas-r8a77970-Add-SD0H-SD0-clocks-for-SDHI.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0237-clk-renesas-r8a77970-Add-CMT-clocks.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0238-clk-renesas-r8a77970-Add-TMU-clocks.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0239-dt-bindings-display-renesas-du-document-R8A77980-bin.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0240-dt-bindings-display-renesas-lvds-document-R8A77980-b.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0241-clk-renesas-r8a77970-Add-TPU-clock.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0242-mmc-renesas_sdhi_internal_dmac-add-R8A77970-to-white.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0243-dt-bindings-mmc-tmio_mmc-document-Renesas-R8A77970-b.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0244-dt-bindings-thermal-rcar-gen3-thermal-document-R8A77.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0245-thermal-rcar_gen3_thermal-add-R8A77980-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0246-dt-bindings-thermal-rcar-thermal-document-R8A77970-b.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0247-thermal-rcar_thermal-add-R8A77970-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0248-clk-renesas-r8a77970-Add-RPC-clocks.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0249-pinctrl-sh-pfc-r8a77970-Add-QSPI-pins-groups-and-fun.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0250-pinctrl-sh-pfc-r8a77980-Add-QSPI-pins-groups-and-fun.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0251-media-rcar-rcar-csi2-Update-V3M-E3-PHTW-tables.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0252-soc-renesas-r8a77970-sysc-Remove-non-existent-CR7-po.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0253-soc-renesas-r8a77970-sysc-Correct-names-of-A2DP-A2CN.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0254-soc-renesas-r8a77980-sysc-Correct-names-of-A2DP-01-p.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0255-soc-renesas-r8a77980-sysc-Correct-A3VIP-012-power-do.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0256-clk-renesas-r8a77970-Add-CPEX-clock.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0257-media-rcar-csi2-add-R8A77980-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0258-media-rcar-vin-add-R8A77980-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0259-pinctrl-sh-pfc-r8a77970-Add-missing-MOD_SEL0-field.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0260-pinctrl-sh-pfc-r8a77980-Add-missing-MOD_SEL0-field.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0261-media-rcar-csi2-Fix-PHTW-table-values-for-E3-V3M.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0262-pinctrl-sh-pfc-Reduce-kernel-size-for-narrow-VIN-cha.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0263-pinctrl-sh-pfc-r8a77970-Deduplicate-VIN-01-pin-defin.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0264-pinctrl-sh-pfc-r8a77980-Deduplicate-VIN1-pin-definit.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0265-arm64-dts-renesas-v3msk-specify-EtherAVB-PHY-IRQ.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0266-sh_eth-rename-sh_eth_cpu_data-hw_checksum.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0267-sh_eth-RX-checksum-offload-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0268-sh_eth-offload-RX-checksum-on-R7S72100.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0269-sh_eth-offload-RX-checksum-on-R8A7740.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0270-sh_eth-offload-RX-checksum-on-R8A77980.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0271-sh_eth-offload-RX-checksum-on-SH7734.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0272-sh_eth-offload-RX-checksum-on-SH7763.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0273-clk-renesas-rcar-gen3-Factor-out-cpg_reg_modify.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0274-clk-renesas-rcar-gen3-Add-spinlock.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0275-clk-renesas-rcar-gen3-Add-RPC-clocks.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0276-clk-renesas-r8a77980-Add-RPC-clocks.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0277-pinctrl-sh-pfc-r8a77970-Rename-IOCTRLx-registers.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0278-pinctrl-sh-pfc-r8a77980-Rename-IOCTRLx-registers.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0279-clk-renesas-r8a77980-Fix-RPC-IF-module-clock-s-paren.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0280-arm64-dts-renesas-r8a77980-Add-renesas-id-to-VIN.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0281-arm64-dts-renesas-eagle-Add-x1-clock.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0282-arm64-dts-renesas-r8a77980-condor-Add-GEther-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0283-iommu-ipmmu-vmsa-Add-r8a77980-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0284-iommu-ipmmu-vmsa-Fix-NULL-pointer-dereference.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0285-iommu-ipmmu-vmsa-Add-r8a779-7-8-0-whitelist.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0286-clk-renesas-r8a77980-cpg-mssr-Add-VIN-clocks.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0287-clk-renesas-r8a77970-cpg-mssr-Add-IMR-clocks.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0288-clk-renesas-r8a77980-cpg-mssr-Add-IMR-clocks.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0289-clk-renesas-r8a77970-cpg-mssr-Add-ISP-clock.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0290-clk-renesas-r8a77980-cpg-mssr-Add-ISP-clocks.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0291-clk-renesas-r8a77980-cpg-mssr-Add-IMP-clocks.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0292-clk-renesas-r8a77980-cpg-mssr-Add-VIP-clocks.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0293-clk-renesas-r8a77970-cpg-mssr-Add-IMP-clocks.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0294-media-soc_camera-Add-CONFIG_VIDEO_ADV_DEBUG-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0295-media-platform-soc_camera-Add-V4L2-R-Car-ISP-driver.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0296-media-platform-soc_camera-rcar_isp-Fix-unused-variab.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0297-media-platform-soc_camera-rcar_vin-Update-R-Car-V3M-.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0298-media-platform-soc_camera-rcar_vin-Add-r8a77980-supp.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0299-media-platform-soc_camera-rcar_csi2-r8a77970-Update-.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0300-media-platform-soc_camera-rcar_csi2-Add-r8a77980-sup.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0301-arm64-dts-renesas-r8a77970-Convert-VIN-nodes-to-soc_.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0302-arm64-dts-renesas-r8a77980-Convert-VIN-nodes-to-soc_.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0303-arm64-dts-renesas-r8a77970-Convert-SCI2-nodes-to-soc.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0304-arm64-dts-renesas-r8a77980-Convert-CSI2-nodes-to-soc.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0305-arm64-dts-renesas-r8a77970-Add-IMR-nodes.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0306-arm64-dts-renesas-r8a77980-Add-IMR-nodes.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0307-arm64-dts-renesas-r8a77970-Add-ISP-node.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0308-arm64-dts-renesas-r8a77980-Add-ISP-nodes.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0309-arm64-dts-renesas-eagle-Add-video-input-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0310-arm64-dts-renesas-condor-Add-video-input-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0311-arm64-dts-renesas-v3msk-Add-reserved-memory-nodes.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0312-arm64-dts-renesas-v3hsk-Add-reserved-memory-nodes.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0313-arm64-dts-renesas-eagle-Add-reserved-memory-nodes.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0314-arm64-dts-renesas-condor-Add-reserved-memory-nodes.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0315-arm64-dts-renesas-v3msk-Add-mmngr-and-mmngrbuf-nodes.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0316-arm64-dts-renesas-v3hsk-Add-mmngr-and-mmngrbuf-nodes.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0317-arm64-dts-renesas-eagle-Add-mmngr-and-mmngrbuf-nodes.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0318-arm64-dts-renesas-condor-Add-mmngr-and-mmngrbuf-node.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0319-arm64-dts-renesas-v3msk-Add-vspm_if-node.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0320-arm64-dts-renesas-v3hsk-Add-vspm_if-node.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0321-arm64-dts-renesas-eagle-Add-vspm_if-node.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0322-arm64-dts-renesas-condor-Add-vspm_if-node.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0323-arm64-dts-renesas-eagle-Add-Dialog-DA9063-MFD.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0324-arm64-dts-renesas-Add-r8a77970-eagle-function-suppor.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0325-arm64-dts-renesas-Add-r8a77970-es1-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0326-arm64-dts-renesas-Add-r8a77970-v3msk-view-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0327-arm64-dts-renesas-Add-r8a77970-v3msk-kf-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0328-arm64-dts-renesas-Add-r8a77970-v3msk-vbm-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0329-arm64-dts-renesas-Add-r8a77970-v3mzf-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0330-arm64-dts-renesas-Add-r8a77980-v3hsk-vbm-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0331-arm64-dts-renesas-r8a779-7-8-0-Add-IMP-devices.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0332-arm64-dts-renesas-r8a77980-Add-VIP-nodes.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0333-arm64-dts-renesas-r8a779-78-0-Add-linux-multimedia-r.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0334-IMR-UIO-Driver-initial-version.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0335-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0336-media-rcar-imr-Add-RSE-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0337-rcar_imr-v4l2-driver-Fix-module-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0338-V3Hsk-Condor-and-V3Msk-Eagle-Remove-cma-default-area.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0339-media-rcar_imr-Enable-LUCE-for-NV16-format.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0340-clk-cs2000-add-support-for-cs2300.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0341-V3H-add-support-for-8-4-channel-VideoBox-board-from-.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0342-arm64-dts-r8a77970-Videobox-Mini-V3-board-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0343-arm64-dts-renesas-r8a77970-v3msk-Add-ethernet0-alias.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0344-arm64-dts-renesas-r8a77970-Add-ISP0-alias.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0345-arm64-dts-renesas-r8a77980-Add-ISP-aliases.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0346-media-soc_camera-Add-soc_camera-host-preregister.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0347-arm64-renesas-r8a77980-use-CSI-4-lanes.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0348-Bunch-update-of-r8a77980-v3hsk-vb-4ch.dts.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0349-arm64-dts-renesas-r8a77980-VideoBox-Mini-fix-csi-spe.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0350-arm64-dts-renesas-r8a77980-v3hsk-vb-4ch-and-8ch-fix-.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0351-arm64-dts-renesas-r8a77980-VB-4ch-and-8ch-Add-PCIE-p.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0352-gpu-drm-rcar_du-Fix-physical-address-of-the-CMA-back.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0353-media-soc_camera-rcar_csi2-add-dump-module-param.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0354-media-rcar_csi2-Disable-data-type-matching.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0355-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0356-media-platform-vsp1-Extend-DRM-VSP1-interface.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0357-gpu-drm-rcar-du-rcar_du_vsp-Check-if-gem-buffer-has-.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0358-media-platform-vsp1-Add-cropping-handling-to-VSP-alp.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0359-media-platform-rcar_imr-Clean-up-to-avoid-compiler-w.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0360-arm64-dts-renesas-r8a77970-and-r8a77980-Add-CPU-oper.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0361-V3H-DTS-Add-FCPR-devices.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0362-arm64-dts-r8a77980-v3hsk-Enable-onboard-eMMC.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0363-arm64-dts-renesas-r8a77980-v3hsk-vb-Xch-Fix-Ethernet.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0364-clocksource-drivers-sh_cmt-Add-R-Car-gen3-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0365-mtd-spi-nor-Add-R-Car-Gen3-RPC-QSPI-driver.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0366-mtd-spi-nor-renesas-rpc-Workaround-256-byte-data-siz.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0367-mtd-spi-nor-Add-s25fs512s-and-s25fs128s-01-SPI-NOR-f.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0368-arm64-dts-renesas-r8a77970-Add-RPC-QSPI-node.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0369-arm64-dts-renesas-r8a77980-Add-RPC-QSPI-node.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0370-arm64-dts-renesas-v3msk-Add-s25fs512s-QSPI-flash-nod.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0371-arm64-dts-renesas-v3mzf-Add-s25fs512s-QSPI-flash-nod.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0372-arm64-dts-renesas-eagle-Add-s25fs512s-QSPI-flash-nod.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0373-arm64-dts-renesas-v3hsk-Add-s25fs512s-QSPI-flash-nod.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0374-arm64-dts-renesas-condor-Add-s25fs512s-QSPI-flash-no.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0375-mtd-spi-nor-renesas-rpc-Support-single-mode-write-co.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0376-mtd-spi-nor-renesas-rpc-Add-DMA-read-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0377-r8a779-78-dtsi-Add-iccom-nodes.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0378-arm64-dts-renesas-Add-temperature-emergency-levels.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0379-r8a77980-dts-Add-vbm-v3-on-r8a77980-SoC.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0380-arm64-dts-r8a77970-Enable-TMU-and-CMT.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0381-arm64-dts-r8a77980-Enable-TMU-and-CMT.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0382-arm64-dts-renesas-r8a77970-and-r8a77980-Add-QoS-node.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0383-clk-renesas-r8a77970-cpg-mssr-Add-sadc-clock.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0384-arm64-dts-renesas-r8a77970-Add-sadc-node.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0385-iio-adc-Add-R-Car-SADC-driver.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0386-rcar-vin-add-ISP-source-enable.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0387-media-soc_camera-Add-events-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0388-media-rcar-imr-Add-stride-support-to-IMR.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0389-arm64-renesas-r8a77980-VB-use-REFCLK-23.0MHZ.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0390-arm64-dts-renesas-Add-V3x-VideoBox-FDPLink-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0391-arm64-dts-renesas-Enable-FDPLink-output-on-V3x-Video.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0392-gpu-drm-bridge-thc63-Set-upper-clock-limit-to-150-MH.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0393-media-soc_camera-dummy-add-mbus-controls-ids.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0394-media-i2c-ar0233-fix-superexposure.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0395-media-i2c-ap0101-add-V-H-flip.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0396-media-i2c-ap0101-ar014x-get-OTP-more-complex.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0397-media-i2c-ar0147-add-mipi-rev3-lvds-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0398-media-i2c-ar0147-add-SE-mode.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0399-media-i2c-ar0233-fix-artifact-line-at-vflip.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0400-media-platform-soc_mediabus-add-Bayer-16bit-format.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0401-media-i2c-ov490_ov10640-add-group-switch.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0402-media-i2c-gw5200-detection-workaround.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0403-media-i2c-ov2311-put-to-autodetect-head.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0404-media-i2c-onsemi-imager-correct-trigger-handling.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0405-media-i2c-ov10640-fix-controls.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0406-Add-new-custom_ioctl-ops-for-soc-camera.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0407-arm64-dts-renesas-r8a77970-v3msk-Fix-memory-size.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0408-arm64-dts-renesas-v3hsk-Add-GEther-PHY-GPIO-reset-pi.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0409-arm64-dts-renesas-condor-Add-GEther-PHY-GPIO-reset-p.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0410-arm64-dts-renesas-eagle-Add-RAVB-PHY-GPIO-reset-pin-.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0411-media-soc_camera-add-MAX9288-support.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0412-media-i2c-soc_camera-differenciate-max9286-and-max92.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0413-media-i2c-max9288-fix-stream-on-off.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0414-gpio-pca953x-do-not-ignore-i2c-errors.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0415-usb-host-xhci-rcar-Add-XHCI_TRUST_TX_LENGTH-quirk.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0416-arm64-dtb-renesas-vb2.1-enable-usb2-channel-3.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0417-USB-tusb8041-add-simple-driver-to-start-device-over-.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0418-arm64-dts-renesas-ulcb-vb2-fix-USB30-and-HUB.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0419-phy-rcar-gen3-usb2-power-on-port-in-host-mode-to.patch create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/cma.cfg create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/disable-unused.cfg create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/hyperflash.cfg create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/imr.cfg create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/nvme.cfg create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/qspi.cfg create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/renesas-not-applied.scc create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/renesas.scc create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/salvator-x.cfg create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/sdhi_seq.cfg create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3hsk.cfg create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3mzf.cfg create mode 100644 bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.14.bbappend (limited to 'bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux') diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0001-spi-sh-msiof-fixes.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0001-spi-sh-msiof-fixes.patch new file mode 100644 index 00000000..2e75272a --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0001-spi-sh-msiof-fixes.patch @@ -0,0 +1,33 @@ +From 7fcc40a9b19ca41bf140eb9ebe9a7dbd5871b54e Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Sun, 15 May 2016 21:53:13 +0300 +Subject: [PATCH 001/122] spi: sh-msiof: fixes + +speed up polling of CTR register + +Signed-off-by: Vladimir Barinov +--- + drivers/spi/spi-sh-msiof.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c +index d32e631..6a27bca 100644 +--- a/drivers/spi/spi-sh-msiof.c ++++ b/drivers/spi/spi-sh-msiof.c +@@ -253,11 +253,11 @@ static int sh_msiof_modify_ctr_wait(struct sh_msiof_spi_priv *p, + data |= set; + sh_msiof_write(p, CTR, data); + +- for (k = 100; k > 0; k--) { ++ for (k = 1000; k > 0; k--) { + if ((sh_msiof_read(p, CTR) & mask) == set) + break; + +- udelay(10); ++ udelay(1); + } + + return k > 0 ? 0 : -ETIMEDOUT; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0002-spi-spidev-add-spi-gpio-into-spidev.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0002-spi-spidev-add-spi-gpio-into-spidev.patch new file mode 100644 index 00000000..f3da1092 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0002-spi-spidev-add-spi-gpio-into-spidev.patch @@ -0,0 +1,27 @@ +From 3130e4c0eed99cafc5e2431e7a7bbc0f85398aec Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Sun, 15 May 2016 21:47:02 +0300 +Subject: [PATCH 002/122] spi: spidev: add spi-gpio into spidev + +Add spi-gpio to spidev + +Signed-off-by: Vladimir Barinov +--- + drivers/spi/spidev.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c +index cda1071..788d2d6 100644 +--- a/drivers/spi/spidev.c ++++ b/drivers/spi/spidev.c +@@ -669,6 +669,7 @@ static const struct of_device_id spidev_dt_ids[] = { + { .compatible = "lineartechnology,ltc2488" }, + { .compatible = "ge,achc" }, + { .compatible = "semtech,sx1301" }, ++ { .compatible = "spi-gpio" }, + {}, + }; + MODULE_DEVICE_TABLE(of, spidev_dt_ids); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0003-spi-spi-gpio-fix-CPOL-mode.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0003-spi-spi-gpio-fix-CPOL-mode.patch new file mode 100644 index 00000000..a9f69be8 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0003-spi-spi-gpio-fix-CPOL-mode.patch @@ -0,0 +1,42 @@ +From 9995ac251006b1ca4989c009129e13ecac8b3e50 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Sun, 29 May 2016 23:18:49 +0300 +Subject: [PATCH 003/122] spi: spi-gpio: fix CPOL mode + +This fixes the SPI SPOL mode, since the cs_gpios is already used +in generic code spi.c + +Signed-off-by: Vladimir Barinov +--- + drivers/spi/spi-gpio.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c +index 1c34c93..6e60521 100644 +--- a/drivers/spi/spi-gpio.c ++++ b/drivers/spi/spi-gpio.c +@@ -218,10 +218,6 @@ static void spi_gpio_chipselect(struct spi_device *spi, int is_active) + struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); + unsigned long cs = spi_gpio->cs_gpios[spi->chip_select]; + +- /* set initial clock polarity */ +- if (is_active) +- setsck(spi, spi->mode & SPI_CPOL); +- + if (cs != SPI_GPIO_NO_CHIPSELECT) { + /* SPI is normally active-low */ + gpio_set_value_cansleep(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active); +@@ -257,6 +253,10 @@ static int spi_gpio_setup(struct spi_device *spi) + !(spi->mode & SPI_CS_HIGH)); + } + } ++ ++ /* set initial clock polarity */ ++ setsck(spi, spi->mode & SPI_CPOL); ++ + if (!status) { + /* in case it was initialized from static board data */ + spi_gpio->cs_gpios[spi->chip_select] = cs; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0006-spi-spi-gpio-fix-set-CPOL-default-inverted.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0006-spi-spi-gpio-fix-set-CPOL-default-inverted.patch new file mode 100644 index 00000000..45da60a7 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0006-spi-spi-gpio-fix-set-CPOL-default-inverted.patch @@ -0,0 +1,30 @@ +From c6a4047e20e95dd01e0c5ec629b77a50b3bc73d0 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Sun, 29 May 2016 23:18:49 +0300 +Subject: [PATCH 004/122] spi: spi-gpio: set CPOL default inverted + +Workaround: + Set default value at probe to 1 due to issue with H3ULCB.HAD FPGA + ethernet switch + +Signed-off-by: Vladimir Barinov +--- + drivers/spi/spi-gpio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c +index 6e60521..428417d 100644 +--- a/drivers/spi/spi-gpio.c ++++ b/drivers/spi/spi-gpio.c +@@ -289,7 +289,7 @@ static int spi_gpio_alloc(unsigned pin, const char *label, bool is_in) + if (is_in) + value = gpio_direction_input(pin); + else +- value = gpio_direction_output(pin, 0); ++ value = gpio_direction_output(pin, 1); + } + return value; + } +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0008-Revert-PCI-rcar-pcie-Add-bus-notifier-so-we-can-limi.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0008-Revert-PCI-rcar-pcie-Add-bus-notifier-so-we-can-limi.patch new file mode 100644 index 00000000..83f5cbbb --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0008-Revert-PCI-rcar-pcie-Add-bus-notifier-so-we-can-limi.patch @@ -0,0 +1,59 @@ +From d01c738d46c186bd58b9314d348e5897ef1fd344 Mon Sep 17 00:00:00 2001 +From: Nikita Yushchenko +Date: Sun, 24 Jun 2018 17:56:22 +0300 +Subject: [PATCH 005/122] Revert "PCI: rcar-pcie: Add bus notifier so we can + limit the dma range" + +This reverts commit 56c039c504f32e68e2e8decbf01ea34d7f7ee03e. + +Resetting dma_mask this way is racy. If driver configures 64-bit +dma_mask in it's probe method and then immediately issues I/O, this +will be handled with dma_mask set to 64-bit. + +Thus different workaround is needed, and this workaround must be +reverted. + +Signed-off-by: Nikita Yushchenko +--- + drivers/pci/host/pcie-rcar.c | 28 ---------------------------- + 1 file changed, 28 deletions(-) + +diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c +index 3679e8e..46b2622 100644 +--- a/drivers/pci/host/pcie-rcar.c ++++ b/drivers/pci/host/pcie-rcar.c +@@ -1377,31 +1377,3 @@ static struct platform_driver rcar_pcie_driver = { + .probe = rcar_pcie_probe, + }; + builtin_platform_driver(rcar_pcie_driver); +- +-static int rcar_pcie_pci_notifier(struct notifier_block *nb, +- unsigned long action, void *data) +-{ +- struct device *dev = data; +- +- switch (action) { +- case BUS_NOTIFY_BOUND_DRIVER: +- /* Force the DMA mask to lower 32-bits */ +- dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); +- break; +- default: +- return NOTIFY_DONE; +- } +- +- return NOTIFY_OK; +-} +- +-static struct notifier_block device_nb = { +- .notifier_call = rcar_pcie_pci_notifier, +-}; +- +-static int __init register_rcar_pcie_pci_notifier(void) +-{ +- return bus_register_notifier(&pci_bus_type, &device_nb); +-} +- +-arch_initcall(register_rcar_pcie_pci_notifier); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0009-arm64-dma-check-parent-bus-restrictions-in-dma_capab.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0009-arm64-dma-check-parent-bus-restrictions-in-dma_capab.patch new file mode 100644 index 00000000..7aa80114 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0009-arm64-dma-check-parent-bus-restrictions-in-dma_capab.patch @@ -0,0 +1,94 @@ +From 98081ba7f59438b1c8f9176b5467b924b9b392f5 Mon Sep 17 00:00:00 2001 +From: Nikita Yushchenko +Date: Sun, 24 Jun 2018 18:04:23 +0300 +Subject: [PATCH 006/122] arm64: dma: check parent bus restrictions in + dma_capable() + +It may happen that although hardware device is capable of full 64-bit +addressing in DMA operations, way device is connected to the system +imposes addressing limitations. Example: NVMe device connected to PCIe +host sitting on AXI bus with 32-bit addressing (and no iommu configured). + +There is no agreement on setting dma_mask in this case. For low level, +dma_mask must be 32-bit - that's what hardware provides for software. +But for higher level, dma_mask must be 64-bit - that's what platform +(hardware + swiotlb) provides for higher levels. + +dma_capable() is swiotlb's check if current address is DMAable by device +directly or swiotlb should provide bounce buffer for it. Using dma_mask +in dma_capable() assumes that dma_mask is set for low level - which does +not always match reality. + +This patch changes dma_capable() to check additional restrictions. + +It is a workaround against ambiguous dma_mask semantics. + +Signed-off-by: Nikita Yushchenko +--- + arch/arm64/include/asm/device.h | 1 + + arch/arm64/include/asm/dma-mapping.h | 9 ++++++++- + arch/arm64/mm/dma-mapping.c | 13 ++++++++++++- + 3 files changed, 21 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/include/asm/device.h b/arch/arm64/include/asm/device.h +index 5a5fa47..ac3eb0c 100644 +--- a/arch/arm64/include/asm/device.h ++++ b/arch/arm64/include/asm/device.h +@@ -24,6 +24,7 @@ struct dev_archdata { + const struct dma_map_ops *dev_dma_ops; + #endif + bool dma_coherent; ++ u64 parent_dma_mask; + }; + + struct pdev_archdata { +diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h +index 0df756b..15edb0c 100644 +--- a/arch/arm64/include/asm/dma-mapping.h ++++ b/arch/arm64/include/asm/dma-mapping.h +@@ -66,10 +66,17 @@ static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dev_addr) + + static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) + { ++ u64 mask; ++ + if (!dev->dma_mask) + return false; + +- return addr + size - 1 <= *dev->dma_mask; ++ mask = *dev->dma_mask; ++ if (dev->archdata.parent_dma_mask && ++ mask > dev->archdata.parent_dma_mask) ++ mask = dev->archdata.parent_dma_mask; ++ ++ return addr + size - 1 <= mask; + } + + static inline void dma_mark_clean(void *addr, size_t size) +diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c +index 58470b1..c9c1892 100644 +--- a/arch/arm64/mm/dma-mapping.c ++++ b/arch/arm64/mm/dma-mapping.c +@@ -928,7 +928,18 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, + dev->dma_ops = &swiotlb_dma_ops; + + dev->archdata.dma_coherent = coherent; +- __iommu_setup_dma_ops(dev, dma_base, size, iommu); ++ ++ if (!iommu) { ++ /* ++ * we don't yet support buses that have a non-zero mapping. ++ * Let's hope we won't need it ++ */ ++ WARN_ON(dma_base != 0); ++ ++ /* save parent_dma_mask for swiotlb's dma_capable() */ ++ dev->archdata.parent_dma_mask = size - 1; ++ } else ++ __iommu_setup_dma_ops(dev, dma_base, size, iommu); + + #ifdef CONFIG_XEN + if (xen_initial_domain()) { +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0010-can-rcar_can-add-enable-and-standby-control-pins.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0010-can-rcar_can-add-enable-and-standby-control-pins.patch new file mode 100644 index 00000000..a9b9fdc4 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0010-can-rcar_can-add-enable-and-standby-control-pins.patch @@ -0,0 +1,156 @@ +From ff03f1075bd445d1dbb5bb087c8d8d3f3b29a025 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Mon, 2 May 2016 22:05:53 +0300 +Subject: [PATCH 007/122] can: rcar_can: add enable and standby control pins + +Add enable and standby can transceiver control pins + +Signed-off-by: Vladimir Barinov +--- + .../devicetree/bindings/net/can/rcar_can.txt | 4 ++ + drivers/net/can/rcar/rcar_can.c | 58 +++++++++++++++++----- + include/linux/can/platform/rcar_can.h | 2 + + 3 files changed, 51 insertions(+), 13 deletions(-) + +diff --git a/Documentation/devicetree/bindings/net/can/rcar_can.txt b/Documentation/devicetree/bindings/net/can/rcar_can.txt +index 94a7f33..5860349 100644 +--- a/Documentation/devicetree/bindings/net/can/rcar_can.txt ++++ b/Documentation/devicetree/bindings/net/can/rcar_can.txt +@@ -43,6 +43,7 @@ Optional properties: + <0x0> (default) : Peripheral clock (clkp1) + <0x1> : Peripheral clock (clkp2) + <0x3> : Externally input clock ++- gpios: GPIO used for controlling the enable pin and standby pin + + Example + ------- +@@ -64,5 +65,8 @@ Board specific .dts file: + &can0 { + pinctrl-0 = <&can0_pins>; + pinctrl-names = "default"; ++ gpios = <&gpio5 29 GPIO_ACTIVE_HIGH /* enable */ ++ &gpio5 30 GPIO_ACTIVE_LOW /* standby */ ++ >; + status = "okay"; + }; +diff --git a/drivers/net/can/rcar/rcar_can.c b/drivers/net/can/rcar/rcar_can.c +index 11662f4..8d2c709 100644 +--- a/drivers/net/can/rcar/rcar_can.c ++++ b/drivers/net/can/rcar/rcar_can.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + #define RCAR_CAN_DRV_NAME "rcar_can" + +@@ -94,6 +95,8 @@ struct rcar_can_priv { + u32 tx_tail; + u8 clock_select; + u8 ier; ++ unsigned int enable_pin; /* transceiver enable */ ++ unsigned int standby_pin; /* transceiver standby */ + }; + + static const struct can_bittiming_const rcar_can_bittiming_const = { +@@ -505,6 +508,10 @@ static int rcar_can_open(struct net_device *ndev) + struct rcar_can_priv *priv = netdev_priv(ndev); + int err; + ++ /* transceiver normal mode */ ++ if (gpio_is_valid(priv->standby_pin)) ++ gpio_set_value(priv->standby_pin, 1); ++ + err = clk_prepare_enable(priv->clk); + if (err) { + netdev_err(ndev, +@@ -581,6 +588,9 @@ static int rcar_can_close(struct net_device *ndev) + clk_disable_unprepare(priv->clk); + close_candev(ndev); + can_led_event(ndev, CAN_LED_EVENT_STOP); ++ /* transceiver stanby mode */ ++ if (gpio_is_valid(priv->standby_pin)) ++ gpio_set_value(priv->standby_pin, 0); + return 0; + } + +@@ -743,20 +753,9 @@ static int rcar_can_probe(struct platform_device *pdev) + struct resource *mem; + void __iomem *addr; + u32 clock_select = CLKR_CLKP1; +- int err = -ENODEV; ++ int err = -ENODEV, ret; + int irq; +- +- if (pdev->dev.of_node) { +- of_property_read_u32(pdev->dev.of_node, +- "renesas,can-clock-select", &clock_select); +- } else { +- pdata = dev_get_platdata(&pdev->dev); +- if (!pdata) { +- dev_err(&pdev->dev, "No platform data provided!\n"); +- goto fail; +- } +- clock_select = pdata->clock_select; +- } ++ enum of_gpio_flags enable_flags, standby_flags; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { +@@ -826,6 +825,39 @@ static int rcar_can_probe(struct platform_device *pdev) + + devm_can_led_init(ndev); + ++ if (pdev->dev.of_node) { ++ of_property_read_u32(pdev->dev.of_node, ++ "renesas,can-clock-select", &clock_select); ++ priv->enable_pin = of_get_gpio_flags(pdev->dev.of_node, 0, &enable_flags); ++ priv->standby_pin = of_get_gpio_flags(pdev->dev.of_node, 1, &standby_flags); ++ } else { ++ pdata = dev_get_platdata(&pdev->dev); ++ if (!pdata) { ++ dev_err(&pdev->dev, "No platform data provided!\n"); ++ goto fail; ++ } ++ clock_select = pdata->clock_select; ++ priv->enable_pin = pdata->enable_pin; ++ priv->standby_pin = pdata->standby_pin; ++ } ++ ++ if (gpio_is_valid(priv->enable_pin)) { ++ int val = enable_flags & OF_GPIO_ACTIVE_LOW ? ++ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH; ++ ret = devm_gpio_request_one(&pdev->dev, priv->enable_pin, val, "enable"); ++ if (ret) ++ dev_info(&pdev->dev, "Failed to request enable pin\n"); ++ } ++ ++ if (gpio_is_valid(priv->standby_pin)) { ++ int val = standby_flags & OF_GPIO_ACTIVE_LOW ? ++ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH; ++ /* transceiver standby mode */ ++ ret = devm_gpio_request_one(&pdev->dev, priv->standby_pin, val, "standby"); ++ if (ret) ++ dev_info(&pdev->dev, "Failed to request standby pin\n"); ++ } ++ + dev_info(&pdev->dev, "device registered (IRQ%d)\n", ndev->irq); + + return 0; +diff --git a/include/linux/can/platform/rcar_can.h b/include/linux/can/platform/rcar_can.h +index a43dcd0..8f23659 100644 +--- a/include/linux/can/platform/rcar_can.h ++++ b/include/linux/can/platform/rcar_can.h +@@ -13,6 +13,8 @@ enum CLKR { + + struct rcar_can_platform_data { + enum CLKR clock_select; /* Clock source select */ ++ unsigned int enable_pin; ++ unsigned int standby_pin; + }; + + #endif /* !_CAN_PLATFORM_RCAR_CAN_H_ */ +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0011-can-rcar_canfd-add-enable-and-standby-control-pins.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0011-can-rcar_canfd-add-enable-and-standby-control-pins.patch new file mode 100644 index 00000000..bdcd4054 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0011-can-rcar_canfd-add-enable-and-standby-control-pins.patch @@ -0,0 +1,119 @@ +From e22e679c7dc63204157d70e04df1fc23cb5b009f Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Mon, 30 May 2016 01:51:47 +0300 +Subject: [PATCH 008/122] can: rcar_canfd: add enable and standby control pins + +Add enable and standby can transceiver control pins + +Signed-off-by: Vladimir Barinov +--- + .../devicetree/bindings/net/can/rcar_canfd.txt | 5 ++++ + drivers/net/can/rcar/rcar_canfd.c | 33 +++++++++++++++++++++- + 2 files changed, 37 insertions(+), 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/net/can/rcar_canfd.txt b/Documentation/devicetree/bindings/net/can/rcar_canfd.txt +index ac71daa..829604a 100644 +--- a/Documentation/devicetree/bindings/net/can/rcar_canfd.txt ++++ b/Documentation/devicetree/bindings/net/can/rcar_canfd.txt +@@ -19,6 +19,7 @@ Required properties: + - clock-names: 3 clock input name strings: "fck", "canfd", "can_clk". + - pinctrl-0: pin control group to be used for this controller. + - pinctrl-names: must be "default". ++- gpios: GPIO used for controlling the enable pin and standby pin + + Required child nodes: + The controller supports two channels and each is represented as a child node. +@@ -62,6 +63,10 @@ SoC common .dtsi file: + power-domains = <&cpg>; + status = "disabled"; + ++ gpios = <&gpio5 29 GPIO_ACTIVE_HIGH /* enable */ ++ &gpio5 30 GPIO_ACTIVE_LOW /* standby */ ++ >; ++ + channel0 { + status = "disabled"; + }; +diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c +index 602c19e..5b98f8c 100644 +--- a/drivers/net/can/rcar/rcar_canfd.c ++++ b/drivers/net/can/rcar/rcar_canfd.c +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -517,6 +518,8 @@ struct rcar_canfd_global { + enum rcar_canfd_fcanclk fcan; /* CANFD or Ext clock */ + unsigned long channels_mask; /* Enabled channels mask */ + bool fdmode; /* CAN FD or Classical CAN only mode */ ++ unsigned int enable_pin; /* transceiver enable */ ++ unsigned int standby_pin; /* transceiver standby */ + }; + + /* CAN FD mode nominal rate constants */ +@@ -1268,6 +1271,10 @@ static int rcar_canfd_open(struct net_device *ndev) + struct rcar_canfd_global *gpriv = priv->gpriv; + int err; + ++ /* transceiver normal mode */ ++ if (gpio_is_valid(gpriv->standby_pin)) ++ gpio_set_value(gpriv->standby_pin, 1); ++ + /* Peripheral clock is already enabled in probe */ + err = clk_prepare_enable(gpriv->can_clk); + if (err) { +@@ -1336,6 +1343,9 @@ static int rcar_canfd_close(struct net_device *ndev) + clk_disable_unprepare(gpriv->can_clk); + close_candev(ndev); + can_led_event(ndev, CAN_LED_EVENT_STOP); ++ /* transceiver stanby mode */ ++ if (gpio_is_valid(gpriv->standby_pin)) ++ gpio_set_value(gpriv->standby_pin, 0); + return 0; + } + +@@ -1639,8 +1649,9 @@ static int rcar_canfd_probe(struct platform_device *pdev) + struct rcar_canfd_global *gpriv; + struct device_node *of_child; + unsigned long channels_mask = 0; +- int err, ch_irq, g_irq; ++ int err, ret, ch_irq, g_irq; + bool fdmode = true; /* CAN FD only mode - default */ ++ enum of_gpio_flags enable_flags, standby_flags; + + if (of_property_read_bool(pdev->dev.of_node, "renesas,no-can-fd")) + fdmode = false; /* Classical CAN only mode */ +@@ -1785,6 +1796,26 @@ static int rcar_canfd_probe(struct platform_device *pdev) + goto fail_channel; + } + ++ gpriv->enable_pin = of_get_gpio_flags(pdev->dev.of_node, 0, &enable_flags); ++ gpriv->standby_pin = of_get_gpio_flags(pdev->dev.of_node, 1, &standby_flags); ++ ++ if (gpio_is_valid(gpriv->enable_pin)) { ++ int val = enable_flags & OF_GPIO_ACTIVE_LOW ? ++ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH; ++ ret = devm_gpio_request_one(&pdev->dev, gpriv->enable_pin, val, "enable"); ++ if (ret) ++ dev_info(&pdev->dev, "Failed to request enable pin\n"); ++ } ++ ++ if (gpio_is_valid(gpriv->standby_pin)) { ++ int val = standby_flags & OF_GPIO_ACTIVE_LOW ? ++ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH; ++ /* transceiver standby mode */ ++ ret = devm_gpio_request_one(&pdev->dev, gpriv->standby_pin, val, "standby"); ++ if (ret) ++ dev_info(&pdev->dev, "Failed to request standby pin\n"); ++ } ++ + platform_set_drvdata(pdev, gpriv); + dev_info(&pdev->dev, "global operational state (clk %d, fdmode %d)\n", + gpriv->fcan, gpriv->fdmode); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0012-mtd-Add-RPC-HyperFlash-driver.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0012-mtd-Add-RPC-HyperFlash-driver.patch new file mode 100644 index 00000000..ccf9216e --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0012-mtd-Add-RPC-HyperFlash-driver.patch @@ -0,0 +1,1028 @@ +From 86cb4077ff3911412e1452de00e2e0c61ad79395 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Fri, 3 Jun 2016 23:04:20 +0300 +Subject: [PATCH 009/122] mtd: Add RPC HyperFlash driver + +This adds RPC HyperFlash driver. + +Signed-off-by: Valentine Barshak +--- + drivers/mtd/Kconfig | 5 + + drivers/mtd/Makefile | 1 + + drivers/mtd/rpc_hyperflash.c | 976 +++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 982 insertions(+) + create mode 100644 drivers/mtd/rpc_hyperflash.c + +diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig +index 5a2d717..0619e1f 100644 +--- a/drivers/mtd/Kconfig ++++ b/drivers/mtd/Kconfig +@@ -11,6 +11,11 @@ menuconfig MTD + particular hardware and users of MTD devices. If unsure, say N. + + if MTD ++config MTD_RPC_HYPERFLASH ++ tristate "MTD Renesas R-Car Gen3 RPC HyperFlash" ++ depends on ARCH_R8A7795 ++ ---help--- ++ This option includes Renesas R-Car Gen3 RPC HyperFlash support. + + config MTD_TESTS + tristate "MTD tests support (DANGEROUS)" +diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile +index d6f8f62..f3fb2b0 100644 +--- a/drivers/mtd/Makefile ++++ b/drivers/mtd/Makefile +@@ -15,6 +15,7 @@ obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o + obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o + obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o + obj-y += parsers/ ++obj-$(CONFIG_MTD_RPC_HYPERFLASH) += rpc_hyperflash.o + + # 'Users' - code which presents functionality to userspace. + obj-$(CONFIG_MTD_BLKDEVS) += mtd_blkdevs.o +diff --git a/drivers/mtd/rpc_hyperflash.c b/drivers/mtd/rpc_hyperflash.c +new file mode 100644 +index 0000000..cf4d56e +--- /dev/null ++++ b/drivers/mtd/rpc_hyperflash.c +@@ -0,0 +1,976 @@ ++/* ++ * Linux driver for R-Car Gen3 RPC HyperFlash ++ * ++ * Copyright (C) 2016 Renesas Electronics Corporation ++ * Copyright (C) 2016 Cogent Embedded, 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* RPC */ ++#define RPC_BASE 0xEE200000 ++#define RPC_SIZE 0x8100 ++#define RPC_FLASH_BASE 0x08000000 ++#define RPC_FLASH_SIZE 0x04000000 ++ ++#define RPC_CMNCR 0x0000 /* R/W */ ++#define RPC_CMNCR_MD (0x1 << 31) ++#define RPC_CMNCR_MOIIO0(val) (((val) & 0x3) << 16) ++#define RPC_CMNCR_MOIIO1(val) (((val) & 0x3) << 18) ++#define RPC_CMNCR_MOIIO2(val) (((val) & 0x3) << 20) ++#define RPC_CMNCR_MOIIO3(val) (((val) & 0x3) << 22) ++#define RPC_CMNCR_MOIIO_HIZ (RPC_CMNCR_MOIIO0(3) | RPC_CMNCR_MOIIO1(3) | \ ++ RPC_CMNCR_MOIIO2(3) | RPC_CMNCR_MOIIO3(3)) ++#define RPC_CMNCR_IO0FV(val) (((val) & 0x3) << 8) ++#define RPC_CMNCR_IO2FV(val) (((val) & 0x3) << 12) ++#define RPC_CMNCR_IO3FV(val) (((val) & 0x3) << 14) ++#define RPC_CMNCR_IOFV_HIZ (RPC_CMNCR_IO0FV(3) | RPC_CMNCR_IO2FV(3) | \ ++ RPC_CMNCR_IO3FV(3)) ++#define RPC_CMNCR_BSZ(val) (((val) & 0x3) << 0) ++ ++#define RPC_SSLDR 0x0004 /* R/W */ ++#define RPC_SSLDR_SPNDL(d) (((d) & 0x7) << 16) ++#define RPC_SSLDR_SLNDL(d) (((d) & 0x7) << 8) ++#define RPC_SSLDR_SCKDL(d) (((d) & 0x7) << 0) ++ ++#define RPC_DRCR 0x000C /* R/W */ ++#define RPC_DRCR_SSLN (0x1 << 24) ++#define RPC_DRCR_RBURST(v) (((v) & 0x1F) << 16) ++#define RPC_DRCR_RCF (0x1 << 9) ++#define RPC_DRCR_RBE (0x1 << 8) ++#define RPC_DRCR_SSLE (0x1 << 0) ++ ++#define RPC_DRCMR 0x0010 /* R/W */ ++#define RPC_DRCMR_CMD(c) (((c) & 0xFF) << 16) ++#define RPC_DRCMR_OCMD(c) (((c) & 0xFF) << 0) ++ ++#define RPC_DREAR 0x0014 /* R/W */ ++#define RPC_DREAR_EAV(v) (((v) & 0xFF) << 16) ++#define RPC_DREAR_EAC(v) (((v) & 0x7) << 0) ++ ++#define RPC_DROPR 0x0018 /* R/W */ ++#define RPC_DROPR_OPD3(o) (((o) & 0xFF) << 24) ++#define RPC_DROPR_OPD2(o) (((o) & 0xFF) << 16) ++#define RPC_DROPR_OPD1(o) (((o) & 0xFF) << 8) ++#define RPC_DROPR_OPD0(o) (((o) & 0xFF) << 0) ++ ++#define RPC_DRENR 0x001C /* R/W */ ++#define RPC_DRENR_CDB(o) (((o) & 0x3) << 30) ++#define RPC_DRENR_OCDB(o) (((o) & 0x3) << 28) ++#define RPC_DRENR_ADB(o) (((o) & 0x3) << 24) ++#define RPC_DRENR_OPDB(o) (((o) & 0x3) << 20) ++#define RPC_DRENR_SPIDB(o) (((o) & 0x3) << 16) ++#define RPC_DRENR_DME (0x1 << 15) ++#define RPC_DRENR_CDE (0x1 << 14) ++#define RPC_DRENR_OCDE (0x1 << 12) ++#define RPC_DRENR_ADE(v) (((v) & 0xF) << 8) ++#define RPC_DRENR_OPDE(v) (((v) & 0xF) << 4) ++ ++#define RPC_SMCR 0x0020 /* R/W */ ++#define RPC_SMCR_SSLKP (0x1 << 8) ++#define RPC_SMCR_SPIRE (0x1 << 2) ++#define RPC_SMCR_SPIWE (0x1 << 1) ++#define RPC_SMCR_SPIE (0x1 << 0) ++ ++#define RPC_SMCMR 0x0024 /* R/W */ ++#define RPC_SMCMR_CMD(c) (((c) & 0xFF) << 16) ++#define RPC_SMCMR_OCMD(c) (((c) & 0xFF) << 0) ++ ++#define RPC_SMADR 0x0028 /* R/W */ ++#define RPC_SMOPR 0x002C /* R/W */ ++#define RPC_SMOPR_OPD0(o) (((o) & 0xFF) << 0) ++#define RPC_SMOPR_OPD1(o) (((o) & 0xFF) << 8) ++#define RPC_SMOPR_OPD2(o) (((o) & 0xFF) << 16) ++#define RPC_SMOPR_OPD3(o) (((o) & 0xFF) << 24) ++ ++#define RPC_SMENR 0x0030 /* R/W */ ++#define RPC_SMENR_CDB(o) (((o) & 0x3) << 30) ++#define RPC_SMENR_OCDB(o) (((o) & 0x3) << 28) ++#define RPC_SMENR_ADB(o) (((o) & 0x3) << 24) ++#define RPC_SMENR_OPDB(o) (((o) & 0x3) << 20) ++#define RPC_SMENR_SPIDB(o) (((o) & 0x3) << 16) ++#define RPC_SMENR_DME (0x1 << 15) ++#define RPC_SMENR_CDE (0x1 << 14) ++#define RPC_SMENR_OCDE (0x1 << 12) ++#define RPC_SMENR_ADE(v) (((v) & 0xF) << 8) ++#define RPC_SMENR_OPDE(v) (((v) & 0xF) << 4) ++#define RPC_SMENR_SPIDE(v) (((v) & 0xF) << 0) ++ ++#define RPC_SMRDR0 0x0038 /* R */ ++#define RPC_SMRDR1 0x003C /* R */ ++#define RPC_SMWDR0 0x0040 /* R/W */ ++#define RPC_SMWDR1 0x0044 /* R/W */ ++#define RPC_CMNSR 0x0048 /* R */ ++#define RPC_CMNSR_SSLF (0x1 << 1) ++#define RPC_CMNSR_TEND (0x1 << 0) ++ ++#define RPC_DRDMCR 0x0058 /* R/W */ ++#define RPC_DRDMCR_DMCYC(v) (((v) & 0xF) << 0) ++ ++#define RPC_DRDRENR 0x005C /* R/W */ ++#define RPC_DRDRENR_HYPE (0x5 << 12) ++#define RPC_DRDRENR_ADDRE (0x1 << 0x8) ++#define RPC_DRDRENR_OPDRE (0x1 << 0x4) ++#define RPC_DRDRENR_DRDRE (0x1 << 0x0) ++ ++#define RPC_SMDMCR 0x0060 /* R/W */ ++#define RPC_SMDMCR_DMCYC(v) (((v) & 0xF) << 0) ++ ++#define RPC_SMDRENR 0x0064 /* R/W */ ++#define RPC_SMDRENR_HYPE (0x5 << 12) ++#define RPC_SMDRENR_ADDRE (0x1 << 0x8) ++#define RPC_SMDRENR_OPDRE (0x1 << 0x4) ++#define RPC_SMDRENR_SPIDRE (0x1 << 0x0) ++ ++#define RPC_PHYCNT 0x007C /* R/W */ ++#define RPC_PHYCNT_CAL (0x1 << 31) ++#define PRC_PHYCNT_OCTA_AA (0x1 << 22) ++#define PRC_PHYCNT_OCTA_SA (0x2 << 22) ++#define PRC_PHYCNT_EXDS (0x1 << 21) ++#define RPC_PHYCNT_OCT (0x1 << 20) ++#define RPC_PHYCNT_WBUF2 (0x1 << 4) ++#define RPC_PHYCNT_WBUF (0x1 << 2) ++#define RPC_PHYCNT_MEM(v) (((v) & 0x3) << 0) ++ ++#define RPC_PHYINT 0x0088 /* R/W */ ++#define RPC_PHYINT_RSTEN (0x1 << 18) ++#define RPC_PHYINT_WPEN (0x1 << 17) ++#define RPC_PHYINT_INTEN (0x1 << 16) ++#define RPC_PHYINT_RST (0x1 << 2) ++#define RPC_PHYINT_WP (0x1 << 1) ++#define RPC_PHYINT_INT (0x1 << 0) ++ ++#define RPC_WBUF 0x8000 /* R/W size=4/8/16/32/64Bytes */ ++#define RPC_WBUF_SIZE 0x100 ++ ++struct rpc_info { ++ struct rw_semaphore lock; ++ void __iomem *rpc_base; ++ void __iomem *flash_base; ++ struct resource *rpc_res; ++ struct resource *flash_res; ++ u32 flash_id; ++ struct mtd_info mtd; ++}; ++ ++static inline void __iomem *rpc_addr(struct rpc_info *info, u32 offset) ++{ ++ return info->rpc_base + offset; ++} ++ ++static inline u32 rpc_readl(struct rpc_info *info, u32 offset) ++{ ++ u32 val; ++ ++ val = readl(rpc_addr(info, offset)); ++ return val; ++} ++ ++static inline void rpc_writel(struct rpc_info *info, u32 offset, u32 val) ++{ ++ writel(val, rpc_addr(info, offset)); ++} ++ ++static inline void rpc_setl(struct rpc_info *info, u32 offset, u32 mask, u32 set) ++{ ++ void __iomem *addr; ++ u32 val; ++ ++ addr = rpc_addr(info, offset); ++ val = readl(addr); ++ val &= mask; ++ val |= set; ++ writel(val, addr); ++} ++ ++static void rpc_wait_tend(struct rpc_info *info) ++{ ++ while (!(rpc_readl(info, RPC_CMNSR) & RPC_CMNSR_TEND)) ++ cpu_relax(); ++} ++ ++/* RPC HyperFlash */ ++#define RPC_HF_CMD_CA47 (0x1 << 7) /* Read */ ++#define RPC_HF_CMD_CA46 (0x1 << 6) /* Register space */ ++#define RPC_HF_CMD_CA45 (0x1 << 5) /* Liner burst */ ++ ++#define RPC_HF_CMD_READ_REG (RPC_HF_CMD_CA47 | RPC_HF_CMD_CA46) ++#define RPC_HF_CMD_READ_MEM RPC_HF_CMD_CA47 ++#define RPC_HF_CMD_WRITE_REG RPC_HF_CMD_CA46 ++#define RPC_HF_CMD_WRITE_MEM 0x0 ++ ++#define RPC_HF_ERASE_SIZE 0x40000 ++ ++#define RPC_CFI_STATUS_DRB (0x1 << 7) ++#define RPC_CFI_STATUS_ESSB (0x1 << 6) ++#define RPC_CFI_STATUS_ESB (0x1 << 5) ++#define RPC_CFI_STATUS_PSB (0x1 << 4) ++#define RPC_CFI_STATUS_WBASB (0x1 << 3) ++#define RPC_CFI_STATUS_PSSB (0x1 << 2) ++#define RPC_CFI_STATUS_SLSB (0x1 << 1) ++#define RPC_CFI_STATUS_ESTAT (0x1 << 0) ++ ++#define RPC_CFI_UNLOCK1 (0x555 << 1) ++#define RPC_CFI_UNLOCK2 (0x2AA << 1) ++ ++#define RPC_CFI_CMD_UNLOCK_START 0xAA ++#define RPC_CFI_CMD_UNLOCK_ACK 0x55 ++#define RPC_CFI_CMD_RESET 0xF0 ++#define RPC_CFI_CMD_READ_STATUS 0x70 ++#define RPC_CFI_CMD_READ_ID 0x90 ++#define RPC_CFI_CMD_WRITE 0xA0 ++#define RPC_CFI_CMD_ERASE_START 0x80 ++#define RPC_CFI_CMD_ERASE_SECTOR 0x30 ++ ++#define RPC_CFI_ID_MASK 0x000F ++#define RPC_CFI_ID_MAN_SPANSION 0x0001 ++#define RPC_CFI_ID_TYPE_HYPERFLASH 0x000E ++ ++enum rpc_hf_size { ++ RPC_HF_SIZE_16BIT = RPC_SMENR_SPIDE(0x8), ++ RPC_HF_SIZE_32BIT = RPC_SMENR_SPIDE(0xC), ++ RPC_HF_SIZE_64BIT = RPC_SMENR_SPIDE(0xF), ++}; ++ ++struct rpc_info *rpc_info; ++ ++static void rpc_hf_mode_man(struct rpc_info *info) ++{ ++ rpc_wait_tend(info); ++ ++ /* ++ * RPC_PHYCNT = 0x80000263 ++ * bit31 CAL = 1 : PHY calibration ++ * bit1-0 PHYMEM[1:0] = 11 : HyperFlash ++ */ ++ rpc_setl(info, RPC_PHYCNT, ++ ~(RPC_PHYCNT_WBUF | RPC_PHYCNT_WBUF2 | ++ RPC_PHYCNT_CAL | RPC_PHYCNT_MEM(3)), ++ RPC_PHYCNT_CAL | RPC_PHYCNT_MEM(3)); ++ ++ /* ++ * RPC_CMNCR = 0x81FFF301 ++ * bit31 MD = 1 : Manual mode ++ * bit1-0 BSZ[1:0] = 01 : QSPI Flash x 2 or HyperFlash ++ */ ++ rpc_setl(info, RPC_CMNCR, ++ ~(RPC_CMNCR_MD | RPC_CMNCR_BSZ(3)), ++ RPC_CMNCR_MOIIO_HIZ | RPC_CMNCR_IOFV_HIZ | ++ RPC_CMNCR_MD | RPC_CMNCR_BSZ(1)); ++} ++ ++static void rpc_hf_mode_ext(struct rpc_info *info) ++{ ++ rpc_wait_tend(info); ++ ++ /* ++ * RPC_PHYCNT = 0x80000263 ++ * bit31 CAL = 1 : PHY calibration ++ * bit1-0 PHYMEM[1:0] = 11 : HyperFlash ++ */ ++ rpc_setl(info, RPC_PHYCNT, ++ ~(RPC_PHYCNT_WBUF | RPC_PHYCNT_WBUF2 | ++ RPC_PHYCNT_CAL | RPC_PHYCNT_MEM(3)), ++ RPC_PHYCNT_CAL | RPC_PHYCNT_MEM(3)); ++ ++ /* ++ * RPC_CMNCR = 0x81FFF301 ++ * bit31 MD = 1 : Manual mode ++ * bit1-0 BSZ[1:0] = 01 : QSPI Flash x 2 or HyperFlash ++ */ ++ rpc_setl(info, RPC_CMNCR, ++ ~(RPC_CMNCR_MD | RPC_CMNCR_BSZ(3)), ++ RPC_CMNCR_MOIIO_HIZ | RPC_CMNCR_IOFV_HIZ | ++ RPC_CMNCR_BSZ(1)); ++ ++ /* ++ * RPC_DRCR = 0x001F0100 ++ * bit21-16 RBURST[4:0] = 11111 : Read burst 32 64-bit data units ++ * bit9 RCF = 1 : Clear cache ++ * bit8 RBE = 1 : Read burst enable ++ */ ++ rpc_writel(info, RPC_DRCR, ++ RPC_DRCR_RBURST(0x1F) | RPC_DRCR_RCF | RPC_DRCR_RBE); ++ ++ rpc_writel(info, RPC_DRCMR, RPC_DRCMR_CMD(0xA0)); ++ rpc_writel(info, RPC_DRENR, ++ RPC_DRENR_CDB(2) | RPC_DRENR_OCDB(2) | ++ RPC_DRENR_ADB(2) | RPC_DRENR_SPIDB(2) | ++ RPC_DRENR_CDE | RPC_DRENR_OCDE | RPC_DRENR_ADE(4)); ++ rpc_writel(info, RPC_DRDMCR, RPC_DRDMCR_DMCYC(0xE)); ++ rpc_writel(info, RPC_DRDRENR, ++ RPC_DRDRENR_HYPE | RPC_DRDRENR_ADDRE | RPC_DRDRENR_DRDRE); ++ ++ /* Dummy read */ ++ rpc_readl(info, RPC_DRCR); ++} ++ ++static void rpc_hf_xfer(struct rpc_info *info, u32 addr, u16 *data, ++ enum rpc_hf_size size, u8 cmd) ++{ ++ u32 val; ++ ++ rpc_hf_mode_man(info); ++ ++ /* ++ * bit23-21 CMD[7:5] : CA47-45 ++ * CA47 = 0/1 : Write/Read ++ * CA46 = 0/1 : Memory Space/Register Space ++ * CA45 = 0/1 : Wrapped Burst/Linear Burst ++ */ ++ rpc_writel(info, RPC_SMCMR, RPC_SMCMR_CMD(cmd)); ++ ++ rpc_writel(info, RPC_SMADR, addr >> 1); ++ ++ rpc_writel(info, RPC_SMOPR, 0x0); ++ ++ /* ++ * RPC_SMDRENR = 0x00005101 ++ * bit14-12 HYPE = 101: Hyperflash mode ++ * bit8 ADDRE = 1 : Address DDR transfer ++ * bit0 SPIDRE = 1 : DATA DDR transfer ++ */ ++ rpc_writel(info, RPC_SMDRENR, ++ RPC_SMDRENR_HYPE | RPC_SMDRENR_ADDRE | RPC_SMDRENR_SPIDRE); ++ ++ val = RPC_SMENR_CDB(2) | RPC_SMENR_OCDB(2) | ++ RPC_SMENR_ADB(2) | RPC_SMENR_SPIDB(2) | ++ RPC_SMENR_CDE | RPC_SMENR_OCDE | RPC_SMENR_ADE(4) | size; ++ ++ if (cmd & RPC_HF_CMD_CA47) ++ goto read_transfer; ++ ++ /* ++ * RPC_SMENR = 0xA222540x ++ * bit31-30 CDB[1:0] = 10 : 4bit width command ++ * bit25-24 ADB[1:0] = 10 : 4bit width address ++ * bit17-16 SPIDB[1:0] = 10 : 4bit width transfer data ++ * bit15 DME = 0 : dummy cycle disable ++ * bit14 CDE = 1 : Command enable ++ * bit12 OCDE = 1 : Option Command enable ++ * bit11-8 ADE[3:0] = 0100 : ADR[23:0] output ++ * bit7-4 OPDE[3:0] = 0000 : Option data disable ++ * bit3-0 SPIDE[3:0] = xxxx : Transfer size ++ */ ++ rpc_writel(info, RPC_SMENR, val); ++ ++ switch (size) { ++ case RPC_HF_SIZE_64BIT: ++ val = cmd & RPC_HF_CMD_CA46 ? ++ cpu_to_be16(data[0]) | cpu_to_be16(data[1]) << 16 : ++ data[0] | data[1] << 16; ++ rpc_writel(info, RPC_SMWDR1, val); ++ val = cmd & RPC_HF_CMD_CA46 ? ++ cpu_to_be16(data[2]) | cpu_to_be16(data[3]) << 16 : ++ data[2] | data[3] << 16; ++ break; ++ case RPC_HF_SIZE_32BIT: ++ val = cmd & RPC_HF_CMD_CA46 ? ++ cpu_to_be16(data[0]) | cpu_to_be16(data[1]) << 16 : ++ data[0] | data[1] << 16; ++ break; ++ default: ++ val = cmd & RPC_HF_CMD_CA46 ? ++ cpu_to_be16(data[0]) << 16 : ++ data[0] << 16; ++ break; ++ } ++ ++ rpc_writel(info, RPC_SMWDR0, val); ++ /* ++ * RPC_SMCR = 0x00000003 ++ * bit1 SPIWE = 1 : Data write enable ++ * bit0 SPIE = 1 : SPI transfer start ++ */ ++ rpc_writel(info, RPC_SMCR, RPC_SMCR_SPIWE | RPC_SMCR_SPIE); ++ return; ++ ++read_transfer: ++ rpc_writel(info, RPC_SMDMCR, RPC_SMDMCR_DMCYC(0xE)); ++ val |= RPC_SMENR_DME; ++ ++ /* ++ * RPC_SMENR = 0xA222D40x ++ * bit31-30 CDB[1:0] = 10 : 4bit width command ++ * bit25-24 ADB[1:0] = 10 : 4bit width address ++ * bit17-16 SPIDB[1:0] = 10 : 4bit width transfer data ++ * bit15 DME = 1 : dummy cycle disable ++ * bit14 CDE = 1 : Command enable ++ * bit12 OCDE = 1 : Option Command enable ++ * bit11-8 ADE[3:0] = 0100 : ADR[23:0] output (24 Bit Address) ++ * bit7-4 OPDE[3:0] = 0000 : Option data disable ++ * bit3-0 SPIDE[3:0] = xxxx : Transfer size ++ */ ++ rpc_writel(info, RPC_SMENR, val); ++ ++ /* ++ * RPC_SMCR = 0x00000005 ++ * bit2 SPIRE = 1 : Data read disable ++ * bit0 SPIE = 1 : SPI transfer start ++ */ ++ rpc_writel(info, RPC_SMCR, RPC_SMCR_SPIRE | RPC_SMCR_SPIE); ++ ++ rpc_wait_tend(info); ++ val = rpc_readl(info, RPC_SMRDR0); ++ ++ /* ++ * Read data from either register or memory space. ++ * Register space is always big-endian. ++ */ ++ switch (size) { ++ case RPC_HF_SIZE_64BIT: ++ if (cmd & RPC_HF_CMD_CA46) { ++ data[3] = be16_to_cpu((val >> 16) & 0xFFFF); ++ data[2] = be16_to_cpu(val & 0xFFFF); ++ } else { ++ data[3] = (val >> 16) & 0xFFFF; ++ data[2] = val & 0xFFFF; ++ } ++ val = rpc_readl(info, RPC_SMRDR1); ++ if (cmd & RPC_HF_CMD_CA46) { ++ data[1] = be16_to_cpu((val >> 16) & 0xFFFF); ++ data[0] = be16_to_cpu(val & 0xFFFF); ++ } else { ++ data[1] = (val >> 16) & 0xFFFF; ++ data[0] = val & 0xFFFF; ++ } ++ break; ++ case RPC_HF_SIZE_32BIT: ++ if (cmd & RPC_HF_CMD_CA46) { ++ data[1] = be16_to_cpu((val >> 16) & 0xFFFF); ++ data[0] = be16_to_cpu(val & 0xFFFF); ++ } else { ++ data[1] = (val >> 16) & 0xFFFF; ++ data[0] = val & 0xFFFF; ++ } ++ break; ++ default: ++ data[0] = cmd & RPC_HF_CMD_CA46 ? ++ be16_to_cpu((val >> 16) & 0xFFFF) : ++ (val >> 16) & 0xFFFF; ++ break; ++ } ++} ++ ++static void rpc_hf_wbuf_enable(struct rpc_info *info) ++{ ++ rpc_wait_tend(info); ++ ++ /* ++ * RPC_PHYCNT = 0x80000277 ++ * bit31 CAL = 1 : PHY calibration ++ * bit4 WBUF2 = 1 : Write buffer enable 2 ++ * bit2 WBUF = 1 : Write buffer enable ++ * bit1-0 PHYMEM[1:0] = 11 : HyperFlash ++ */ ++ rpc_setl(info, RPC_PHYCNT, ++ ~(RPC_PHYCNT_WBUF2 | RPC_PHYCNT_WBUF | ++ RPC_PHYCNT_CAL | RPC_PHYCNT_MEM(3)), ++ RPC_PHYCNT_WBUF2 | RPC_PHYCNT_WBUF | ++ RPC_PHYCNT_CAL | RPC_PHYCNT_MEM(3)); ++ ++ /* ++ * RPC_DRCR = 0x001F0100 ++ * bit21-16 RBURST[4:0] = 11111 : Read burst 32 64-bit data units ++ * bit9 RCF = 1 : Clear cache ++ * bit8 RBE = 1 : Read burst enable ++ */ ++ rpc_writel(info, RPC_DRCR, ++ RPC_DRCR_RBURST(0x1F) | RPC_DRCR_RCF | RPC_DRCR_RBE); ++ ++ rpc_writel(info, RPC_SMCMR, RPC_SMCMR_CMD(RPC_HF_CMD_WRITE_MEM)); ++ ++ rpc_writel(info, RPC_SMOPR, 0x0); ++ ++ /* ++ * RPC_SMDRENR = 0x00005101 ++ * bit14-12 HYPE = 101:Hyperflash mode ++ * bit8 ADDRE = 1 : Address DDR transfer ++ * bit0 SPIDRE = 1 : DATA DDR transfer ++ */ ++ rpc_writel(info, RPC_SMDRENR, ++ RPC_SMDRENR_HYPE | RPC_SMDRENR_ADDRE | RPC_SMDRENR_SPIDRE); ++ ++ /* ++ * RPC_SMENR = 0xA222540F ++ * bit31-30 CDB[1:0] = 10 : 4bit width command ++ * bit25-24 ADB[1:0] = 10 : 4bit width address ++ * bit17-16 SPIDB[1:0] = 10 : 4bit width transfer data ++ * bit15 DME = 0 : dummy cycle disable ++ * bit14 CDE = 1 : Command enable ++ * bit12 OCDE = 1 : Option Command enable ++ * bit11-8 ADE[3:0] = 0100 : ADR[23:0] output (24 Bit Address) ++ * bit7-4 OPDE[3:0] = 0000 : Option data disable ++ * bit3-0 SPIDE[3:0] = 1111 : 64-bit transfer size ++ */ ++ rpc_writel(info, RPC_SMENR, ++ RPC_SMENR_CDB(2) | RPC_SMENR_OCDB(2) | ++ RPC_SMENR_ADB(2) | RPC_SMENR_SPIDB(2) | ++ RPC_SMENR_CDE | RPC_SMENR_OCDE | ++ RPC_SMENR_ADE(4) | RPC_HF_SIZE_64BIT); ++ ++ /* Dummy read */ ++ rpc_readl(info, RPC_DRCR); ++} ++ ++static inline void rpc_hf_write_cmd(struct rpc_info *info, u32 addr, u16 cmd) ++{ ++ rpc_hf_xfer(info, addr, &cmd, RPC_HF_SIZE_16BIT, RPC_HF_CMD_WRITE_REG); ++} ++ ++static inline void rpc_hf_read_reg(struct rpc_info *info, u32 addr, u16 *data, ++ enum rpc_hf_size size) ++{ ++ rpc_hf_xfer(info, addr, data, size, RPC_HF_CMD_READ_REG); ++} ++ ++static inline void rpc_hf_write_reg(struct rpc_info *info, u32 addr, u16 *data, ++ enum rpc_hf_size size) ++{ ++ rpc_hf_xfer(info, addr, data, size, RPC_HF_CMD_WRITE_REG); ++} ++ ++static inline void rpc_hf_read_mem(struct rpc_info *info, u32 addr, u16 *data, ++ enum rpc_hf_size size) ++{ ++ rpc_hf_xfer(info, addr, data, size, RPC_HF_CMD_READ_MEM); ++} ++ ++static inline void rpc_hf_write_mem(struct rpc_info *info, u32 addr, u16 *data, ++ enum rpc_hf_size size) ++{ ++ rpc_hf_xfer(info, addr, data, size, RPC_HF_CMD_WRITE_MEM); ++} ++ ++static void rpc_hf_wp(struct rpc_info *info, int enable) ++{ ++ rpc_setl(info, RPC_PHYINT, ~RPC_PHYINT_WP, enable ? RPC_PHYINT_WP : 0); ++} ++ ++static void rpc_hf_unlock(struct rpc_info *info, u32 addr) ++{ ++ rpc_hf_write_cmd(info, addr + RPC_CFI_UNLOCK1, ++ RPC_CFI_CMD_UNLOCK_START); ++ rpc_hf_write_cmd(info, addr + RPC_CFI_UNLOCK2, ++ RPC_CFI_CMD_UNLOCK_ACK); ++} ++ ++static inline int rpc_hf_status(struct rpc_info *info, u32 addr, ++ int iterations, int delay) ++{ ++ int retval; ++ u16 status = 0; ++ ++ while (iterations-- > 0) { ++ rpc_hf_write_cmd(info, addr + RPC_CFI_UNLOCK1, RPC_CFI_CMD_READ_STATUS); ++ rpc_hf_read_reg(info, addr, &status, RPC_HF_SIZE_16BIT); ++ ++ if (status & RPC_CFI_STATUS_DRB) ++ break; ++ ++ if (delay < 10000) ++ usleep_range(delay, delay * 2); ++ else ++ msleep(delay / 1000); ++ } ++ ++ if (!(status & RPC_CFI_STATUS_DRB)) { ++ retval = -ETIMEDOUT; ++ goto out; ++ } ++ ++ if (status & (RPC_CFI_STATUS_PSB | RPC_CFI_STATUS_ESB)) { ++ retval = -EIO; ++ goto out; ++ } ++ ++ return 0; ++ ++out: ++ /* Reset the flash */ ++ rpc_hf_write_cmd(info, 0, RPC_CFI_CMD_RESET); ++ return retval; ++} ++ ++static int rpc_hf_sector_erase(struct rpc_info *info, u32 addr) ++{ ++ rpc_hf_unlock(info, addr); ++ rpc_hf_write_cmd(info, addr + RPC_CFI_UNLOCK1, RPC_CFI_CMD_ERASE_START); ++ rpc_hf_unlock(info, addr); ++ rpc_hf_write_cmd(info, addr, RPC_CFI_CMD_ERASE_SECTOR); ++ ++ return rpc_hf_status(info, addr, 1000, 10000); ++} ++ ++/* Flash read */ ++static int rpc_hf_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, ++ size_t *retlen, u_char *buf) ++{ ++ struct rpc_info *info = mtd->priv; ++ ++ down_read(&info->lock); ++ memcpy_fromio(buf, info->flash_base + from, len); ++ up_read(&info->lock); ++ ++ *retlen = len; ++ return 0; ++} ++ ++/* Flash erase */ ++static int rpc_hf_mtd_erase(struct mtd_info *mtd, struct erase_info *instr) ++{ ++ struct rpc_info *info = mtd->priv; ++ u32 addr, end; ++ int retval = 0; ++ ++ if (mtd_mod_by_eb(instr->addr, mtd)) { ++ pr_debug("%s: unaligned address\n", __func__); ++ return -EINVAL; ++ } ++ ++ if (mtd_mod_by_eb(instr->len, mtd)) { ++ pr_debug("%s: unaligned length\n", __func__); ++ return -EINVAL; ++ } ++ ++ end = instr->addr + instr->len; ++ ++ down_write(&info->lock); ++ for (addr = instr->addr; addr < end; addr += mtd->erasesize) { ++ retval = rpc_hf_sector_erase(info, addr); ++ ++ if (retval) ++ break; ++ } ++ ++ rpc_hf_mode_ext(info); ++ up_write(&info->lock); ++ ++ instr->state = retval ? MTD_ERASE_FAILED : MTD_ERASE_DONE; ++ mtd_erase_callback(instr); ++ ++ return retval; ++} ++ ++/* Copy memory to flash */ ++static int rpc_hf_mtd_write(struct mtd_info *mtd, loff_t offset, size_t len, ++ size_t *retlen, const u_char *src) ++{ ++ struct rpc_info *info = mtd->priv; ++ union { ++ u8 b[4]; ++ u16 w[2]; ++ u32 d; ++ } data; ++ loff_t addr; ++ size_t size, cnt; ++ int retval, idx; ++ u8 last; ++ ++ retval = 0; ++ *retlen = 0; ++ cnt = len; ++ idx = 0; ++ ++ down_write(&info->lock); ++ ++ /* Handle unaligned start */ ++ if (offset & 0x1) { ++ offset--; ++ data.b[idx] = readb(info->flash_base + offset); ++ idx++; ++ } ++ ++ /* Handle unaligned end */ ++ addr = offset + idx + len; ++ last = addr & 0x1 ? readb(info->flash_base + addr) : 0xFF; ++ ++ addr = offset - mtd_mod_by_eb(offset, mtd); ++ size = mtd->erasesize - (offset - addr); ++ ++ while (cnt) { ++ if (size > cnt) ++ size = cnt; ++ ++ cnt -= size; ++ while (size) { ++ rpc_hf_unlock(info, addr); ++ rpc_hf_write_cmd(info, ++ addr + RPC_CFI_UNLOCK1, ++ RPC_CFI_CMD_WRITE); ++ ++ if (size > 0x7) { ++ u32 wbuf = RPC_WBUF; ++ int block = size >= RPC_WBUF_SIZE ? ++ RPC_WBUF_SIZE : size & ~0x7; ++ ++ rpc_hf_wbuf_enable(info); ++ ++ rpc_writel(info, RPC_SMADR, offset >> 1); ++ offset += block; ++ ++ block >>= 3; ++ while (block--) { ++ while (idx < 4) { ++ data.b[idx++] = *src++; ++ size--; ++ } ++ rpc_writel(info, wbuf, data.d); ++ wbuf += 4; ++ ++ idx = 0; ++ while (idx < 4) { ++ data.b[idx++] = *src++; ++ size--; ++ } ++ rpc_writel(info, wbuf, data.d); ++ wbuf += 4; ++ ++ idx = 0; ++ } ++ ++ rpc_writel(info, RPC_SMCR, ++ RPC_SMCR_SPIWE | RPC_SMCR_SPIE); ++ } else { ++ enum rpc_hf_size bits; ++ ++ while (idx < 4) { ++ data.b[idx++] = *src++; ++ size--; ++ ++ if (!size) ++ break; ++ } ++ ++ if (idx & 0x1) ++ data.b[idx++] = last; ++ ++ switch (idx) { ++ case 2: ++ bits = RPC_HF_SIZE_16BIT; ++ break; ++ default: ++ bits = RPC_HF_SIZE_32BIT; ++ break; ++ } ++ ++ rpc_hf_write_mem(info, offset, data.w, bits); ++ offset += idx; ++ idx = 0; ++ } ++ ++ retval = rpc_hf_status(info, addr, 1000000, 10); ++ if (retval) ++ goto out; ++ } ++ ++ size = mtd->erasesize; ++ addr += size; ++ offset = addr; ++ *retlen = len - cnt; ++ } ++ ++out: ++ rpc_hf_mode_ext(info); ++ up_write(&info->lock); ++ return retval; ++} ++ ++static struct mtd_partition partition_info[]={ ++ { ++ .name = "bootparam", ++ .offset = 0, ++ .size = 0x40000, ++ }, { ++ .name = "bl2", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x140000 ++ }, { ++ .name = "cert_header", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x40000, ++ }, { ++ .name = "bl31", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x40000, ++ }, { ++ .name = "optee", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x440000, ++ }, { ++ .name = "u-boot", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x80000, ++ }, { ++ .name = "reserved", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x80000, ++ }, { ++ .name = "u-boot-env", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x40000, ++ }, { ++ .name = "dtb", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x80000, ++ }, { ++ .name = "kernel", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x1000000, ++ }, { ++ .name = "user", ++ .offset = MTDPART_OFS_APPEND, ++ .size = MTDPART_SIZ_FULL, ++ }, ++}; ++ ++static int rpc_hf_init_mtd(struct rpc_info *info) ++{ ++ struct mtd_info *mtd = &info->mtd; ++ u16 data[2] = { 0, 0 }; ++ u32 id, size; ++ int retval; ++ ++ rpc_hf_mode_ext(info); ++ ++ rpc_hf_wp(info, 0); ++ ++ rpc_hf_unlock(info, 0); ++ rpc_hf_write_cmd(info, RPC_CFI_UNLOCK1, RPC_CFI_CMD_READ_ID); ++ ++ rpc_hf_read_reg(info, 0x0, data, RPC_HF_SIZE_32BIT); ++ if ((data[0] & RPC_CFI_ID_MASK) != RPC_CFI_ID_MAN_SPANSION || ++ (data[1] & RPC_CFI_ID_MASK) != RPC_CFI_ID_TYPE_HYPERFLASH) { ++ retval = -ENODEV; ++ goto out; ++ } ++ ++ id = data[0] | data[1] << 16; ++ ++ rpc_hf_read_reg(info, 0x27 << 1, data, RPC_HF_SIZE_16BIT); ++ size = 1 << data[0]; ++ ++ if (size > resource_size(info->flash_res)) ++ size = resource_size(info->flash_res); ++ ++ if (size & (RPC_HF_ERASE_SIZE - 1)) { ++ retval = -EINVAL; ++ goto out; ++ } ++ ++ init_rwsem(&info->lock); ++ info->flash_id = id; ++ mtd->name = "HyperFlash"; ++ mtd->type = MTD_NORFLASH; ++ mtd->flags = MTD_CAP_NORFLASH; ++ mtd->size = size; ++ mtd->writesize = 1; ++ mtd->writebufsize = RPC_WBUF_SIZE; ++ mtd->erasesize = RPC_HF_ERASE_SIZE; ++ mtd->owner = THIS_MODULE; ++ mtd->priv = info; ++ mtd->_erase = rpc_hf_mtd_erase; ++ mtd->_write = rpc_hf_mtd_write; ++ mtd->_read = rpc_hf_mtd_read; ++ retval = mtd_device_register(mtd, partition_info, ++ ARRAY_SIZE(partition_info)); ++out: ++ rpc_hf_write_cmd(info, 0, RPC_CFI_CMD_RESET); ++ rpc_hf_mode_ext(info); ++ return retval; ++} ++ ++static int rpc_flash_init(void) ++{ ++ struct rpc_info *info; ++ struct resource *res; ++ void __iomem *base; ++ int retval = -ENODEV; ++ ++ if (!of_machine_is_compatible("renesas,r8a7795")) ++ return -ENODEV; ++ ++ info = kzalloc(sizeof(*info), GFP_KERNEL); ++ if (!info) ++ return -ENOMEM; ++ ++ res = request_mem_region(RPC_BASE, RPC_SIZE, "RPC"); ++ if (!res) ++ goto out_info; ++ ++ info->rpc_res = res; ++ base = ioremap(res->start, resource_size(res)); ++ if (!base) ++ goto out_rpc_res; ++ ++ info->rpc_base = base; ++ res = request_mem_region(RPC_FLASH_BASE, RPC_FLASH_SIZE, "RPC-ext"); ++ if (!res) ++ goto out_rpc_base; ++ ++ info->flash_res = res; ++ base = ioremap(res->start, resource_size(res)); ++ if (!base) ++ goto out_flash_res; ++ ++ info->flash_base = base; ++ retval = rpc_hf_init_mtd(info); ++ if (retval) ++ goto out_flash_base; ++ ++ pr_info("HyperFlash Id: %x\n", info->flash_id); ++ ++ rpc_info = info; ++ return 0; ++ ++out_flash_base: ++ iounmap(info->flash_base); ++out_flash_res: ++ release_mem_region(info->flash_res->start, ++ resource_size(info->flash_res)); ++out_rpc_base: ++ iounmap(info->rpc_base); ++out_rpc_res: ++ release_mem_region(info->rpc_res->start, ++ resource_size(info->rpc_res)); ++out_info: ++ kfree(info); ++ return retval; ++} ++ ++static void rpc_flash_exit(void) ++{ ++ struct rpc_info *info = rpc_info; ++ ++ if (!info) ++ return; ++ ++ rpc_info = NULL; ++ ++ mtd_device_unregister(&info->mtd); ++ ++ iounmap(info->flash_base); ++ release_mem_region(info->flash_res->start, ++ resource_size(info->flash_res)); ++ iounmap(info->rpc_base); ++ release_mem_region(info->rpc_res->start, ++ resource_size(info->rpc_res)); ++ kfree(info); ++} ++ ++module_init(rpc_flash_init); ++module_exit(rpc_flash_exit); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("Renesas RPC HyperFlash MTD driver"); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0013-IMR-driver-interim-patch.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0013-IMR-driver-interim-patch.patch new file mode 100644 index 00000000..2ef0fafb --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0013-IMR-driver-interim-patch.patch @@ -0,0 +1,2002 @@ +From 1b3ded1c8d137c417f7f75e6adffb9811d8e21a9 Mon Sep 17 00:00:00 2001 +From: Konstantin Kozhevnikov +Date: Wed, 7 Sep 2016 22:55:37 +0300 +Subject: [PATCH 010/122] IMR driver - interim patch + +Signed-off-by: Konstantin Kozhevnikov +--- + drivers/media/platform/Kconfig | 11 + + drivers/media/platform/Makefile | 1 + + drivers/media/platform/rcar_imr.c | 1840 +++++++++++++++++++++++++++++++++++++ + include/uapi/linux/rcar-imr.h | 98 ++ + 4 files changed, 1950 insertions(+) + create mode 100644 drivers/media/platform/rcar_imr.c + create mode 100644 include/uapi/linux/rcar-imr.h + +diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig +index 63f434c..3e165fc 100644 +--- a/drivers/media/platform/Kconfig ++++ b/drivers/media/platform/Kconfig +@@ -454,6 +454,17 @@ config VIDEO_RENESAS_FCP + To compile this driver as a module, choose M here: the module + will be called rcar-fcp. + ++config VIDEO_RENESAS_IMR ++ tristate "Renesas Image Renderer (Distortion Correction) Unit" ++ depends on VIDEO_DEV && VIDEO_V4L2 ++ select VIDEOBUF2_DMA_CONTIG ++ select V4L2_MEM2MEM_DEV ++ ---help--- ++ This is a V4L2 driver for the Renesas IMR-X2/LX2/LX4 Processing Unit. ++ ++ To compile this driver as a module, choose M here: the module ++ will be called rcar_imr. ++ + config VIDEO_RENESAS_VSP1 + tristate "Renesas VSP1 Video Processing Engine" + depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && HAS_DMA +diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile +index 76149a1..d985603 100644 +--- a/drivers/media/platform/Makefile ++++ b/drivers/media/platform/Makefile +@@ -62,6 +62,7 @@ obj-$(CONFIG_VIDEO_RENESAS_CEU) += renesas-ceu.o + obj-$(CONFIG_VIDEO_RENESAS_FCP) += rcar-fcp.o + obj-$(CONFIG_VIDEO_RENESAS_FDP1) += rcar_fdp1.o + obj-$(CONFIG_VIDEO_RENESAS_JPU) += rcar_jpu.o ++obj-$(CONFIG_VIDEO_RENESAS_IMR) += rcar_imr.o + obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1/ + + obj-y += omap/ +diff --git a/drivers/media/platform/rcar_imr.c b/drivers/media/platform/rcar_imr.c +new file mode 100644 +index 0000000..30c6742 +--- /dev/null ++++ b/drivers/media/platform/rcar_imr.c +@@ -0,0 +1,1840 @@ ++/* ++ * rcar_imr.c -- R-Car IMR-LX4 Driver ++ * ++ * Copyright (C) 2015 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRV_NAME "rcar_imr" ++ ++/******************************************************************************* ++ * Module parameters ++ ******************************************************************************/ ++ ++static int debug; ++module_param(debug, int, 0644); ++MODULE_PARM_DESC(debug, "Debug level (0-4)"); ++ ++/******************************************************************************* ++ * Local types definitions ++ ******************************************************************************/ ++ ++/* ...configuration data */ ++struct imr_cfg { ++ /* ...display-list main program data */ ++ void *dl_vaddr; ++ dma_addr_t dl_dma_addr; ++ u32 dl_size; ++ u32 dl_start_offset; ++ ++ /* ...pointers to the source/destination planes */ ++ u32 *src_pa_ptr[2]; ++ u32 *dst_pa_ptr[2]; ++ ++ /* ...subpixel destination coordinates space */ ++ int dst_subpixel; ++ ++ /* ...reference counter */ ++ u32 refcount; ++ ++ /* ...identifier (for debug output) */ ++ u32 id; ++}; ++ ++struct imr_buffer { ++ /* ...standard M2M buffer descriptor */ ++ struct v4l2_m2m_buffer buf; ++ ++ /* ...pointer to mesh configuration for processing */ ++ struct imr_cfg *cfg; ++}; ++ ++struct imr_q_data { ++ /* ...latched pixel format */ ++ struct v4l2_pix_format fmt; ++ ++ /* ...current format flags */ ++ u32 flags; ++}; ++ ++struct imr_format_info { ++ char *name; ++ u32 fourcc; ++ u32 flags; ++}; ++ ++/* ...per-device data */ ++struct imr_device { ++ struct device *dev; ++ struct clk *clock; ++ void __iomem *mmio; ++ int irq; ++ struct mutex mutex; ++ spinlock_t lock; ++ ++ struct v4l2_device v4l2_dev; ++ struct video_device video_dev; ++ struct v4l2_m2m_dev *m2m_dev; ++ ++ /* ...do we need that counter really? framework counts fh structures for us - tbd */ ++ int refcount; ++ ++ /* ...should we include media-dev? likely, no - tbd */ ++}; ++ ++/* ...per file-handle context */ ++struct imr_ctx { ++ struct v4l2_fh fh; ++ struct imr_device *imr; ++ struct v4l2_m2m_ctx *m2m_ctx; ++ struct imr_q_data queue[2]; ++ ++ /* ...current job configuration */ ++ struct imr_cfg *cfg; ++ ++ /* ...frame sequence counter */ ++ u32 sequence; ++ ++ /* ...cropping parameters (in pixels) */ ++ u16 crop[4]; ++ ++ /* ...number of active configurations (debugging) */ ++ u32 cfg_num; ++}; ++ ++/******************************************************************************* ++ * IMR registers ++ ******************************************************************************/ ++ ++#define IMR_CR 0x08 ++#define IMR_CR_RS (1 << 0) ++#define IMR_CR_SWRST (1 << 15) ++ ++#define IMR_SR 0x0C ++#define IMR_SRCR 0x10 ++#define IMR_SR_TRA (1 << 0) ++#define IMR_SR_IER (1 << 1) ++#define IMR_SR_INT (1 << 2) ++#define IMR_SR_REN (1 << 5) ++ ++#define IMR_ICR 0x14 ++#define IMR_IMR 0x18 ++#define IMR_ICR_TRAEN (1 << 0) ++#define IMR_ICR_IEREN (1 << 1) ++#define IMR_ICR_INTEN (1 << 2) ++ ++#define IMR_DLSP 0x1C ++#define IMR_DLSR 0x20 ++#define IMR_DLSAR 0x30 ++ ++#define IMR_DSAR 0x34 ++#define IMR_SSAR 0x38 ++#define IMR_DSTR 0x3C ++#define IMR_SSTR 0x40 ++#define IMR_DSOR 0x50 ++ ++#define IMR_CMRCR 0x54 ++#define IMR_CMRCSR 0x58 ++#define IMR_CMRCCR 0x5C ++#define IMR_CMR_LUCE (1 << 1) ++#define IMR_CMR_CLCE (1 << 2) ++#define IMR_CMR_DUV_SHIFT 3 ++#define IMR_CMR_DUV_MASK (3 << IMR_CMR_DUV_SHIFT) ++#define IMR_CMR_SUV_SHIFT 5 ++#define IMR_CMR_SUV_MASK (3 << IMR_CMR_SUV_SHIFT) ++#define IMR_CMR_YISM (1 << 7) ++#define IMR_CMR_DY10 (1 << 8) ++#define IMR_CMR_DY12 (1 << 9) ++#define IMR_CMR_SY10 (1 << 11) ++#define IMR_CMR_SY12 (1 << 12) ++#define IMR_CMR_YCM (1 << 14) ++#define IMR_CMR_CP16E (1 << 15) ++ ++#define IMR_CMRCR2 0xE4 ++#define IMR_CMRCSR2 0xE8 ++#define IMR_CMRCCR2 0xEC ++#define IMR_CMR2_LUTE (1 << 0) ++#define IMR_CMR2_YUV422E (1 << 2) ++#define IMR_CMR2_YUV422FORM (1 << 5) ++#define IMR_CMR2_UVFORM (1 << 6) ++#define IMR_CMR2_TCTE (1 << 12) ++#define IMR_CMR2_DCTE (1 << 15) ++ ++#define IMR_TRIMR 0x60 ++#define IMR_TRIMSR 0x64 ++#define IMR_TRIMCR 0x68 ++#define IMR_TRIM_TME (1 << 0) ++#define IMR_TRIM_BFE (1 << 1) ++#define IMR_TRIM_AUTODG (1 << 2) ++#define IMR_TRIM_AUTOSG (1 << 3) ++#define IMR_TRIM_DYDXM (1 << 4) ++#define IMR_TRIM_DUDVM (1 << 5) ++#define IMR_TRIM_TCM (1 << 6) ++ ++#define IMR_TRICR 0x6C ++#define IMR_TRIC_YCFORM (1 << 31) ++ ++#define IMR_UVDPOR 0x70 ++#define IMR_SUSR 0x74 ++#define IMR_SVSR 0x78 ++ ++#define IMR_XMINR 0x80 ++#define IMR_YMINR 0x84 ++#define IMR_XMAXR 0x88 ++#define IMR_YMAXR 0x8C ++ ++#define IMR_AMXSR 0x90 ++#define IMR_AMYSR 0x94 ++#define IMR_AMXOR 0x98 ++#define IMR_AMYOR 0x9C ++ ++#define IMR_CPDPOR 0xD0 ++#define IMR_CPDP_YLDPO_SHIFT 8 ++#define IMR_CPDP_UBDPO_SHIFT 4 ++#define IMR_CPDP_VRDPO_SHIFT 0 ++ ++/******************************************************************************* ++ * Auxiliary helpers ++ ******************************************************************************/ ++ ++static inline struct imr_ctx * fh_to_ctx(struct v4l2_fh *fh) ++{ ++ return container_of(fh, struct imr_ctx, fh); ++} ++ ++static inline struct imr_buffer * to_imr_buffer(struct vb2_v4l2_buffer *vbuf) ++{ ++ struct v4l2_m2m_buffer *b = container_of(vbuf, struct v4l2_m2m_buffer, vb); ++ ++ return container_of(b, struct imr_buffer, buf); ++} ++ ++/******************************************************************************* ++ * Local constants definition ++ ******************************************************************************/ ++ ++#define IMR_F_Y8 (1 << 0) ++#define IMR_F_Y10 (1 << 1) ++#define IMR_F_Y12 (1 << 2) ++#define IMR_F_UV8 (1 << 3) ++#define IMR_F_UV10 (1 << 4) ++#define IMR_F_UV12 (1 << 5) ++#define IMR_F_PLANAR (1 << 6) ++#define IMR_F_INTERLEAVED (1 << 7) ++#define IMR_F_PLANES_MASK ((1 << 8) - 1) ++#define IMR_F_UV_SWAP (1 << 8) ++#define IMR_F_YUV_SWAP (1 << 9) ++ ++/* ...get common planes bits */ ++static inline u32 __imr_flags_common(u32 iflags, u32 oflags) ++{ ++ return (iflags & oflags) & IMR_F_PLANES_MASK; ++} ++ ++static const struct imr_format_info imr_lx4_formats[] = { ++ { ++ .name = "YUV 4:2:2 semiplanar (NV16)", ++ .fourcc = V4L2_PIX_FMT_NV16, ++ .flags = IMR_F_Y8 | IMR_F_UV8 | IMR_F_PLANAR, ++ }, ++ { ++ .name = "YVU 4:2:2 semiplanar (NV61)", ++ .fourcc = V4L2_PIX_FMT_NV61, ++ .flags = IMR_F_Y8 | IMR_F_UV8 | IMR_F_PLANAR | IMR_F_UV_SWAP, ++ }, ++ { ++ .name = "YUV 4:2:2 interleaved (YUYV)", ++ .fourcc = V4L2_PIX_FMT_YUYV, ++ .flags = IMR_F_Y8 | IMR_F_UV8, ++ }, ++ { ++ .name = "YUV 4:2:2 interleaved (UYVY)", ++ .fourcc = V4L2_PIX_FMT_UYVY, ++ .flags = IMR_F_Y8 | IMR_F_UV8 | IMR_F_YUV_SWAP, ++ }, ++ { ++ .name = "YUV 4:2:2 interleaved (YVYU)", ++ .fourcc = V4L2_PIX_FMT_YVYU, ++ .flags = IMR_F_Y8 | IMR_F_UV8 | IMR_F_UV_SWAP, ++ }, ++ { ++ .name = "YUV 4:2:2 interleaved (UYVY)", ++ .fourcc = V4L2_PIX_FMT_VYUY, ++ .flags = IMR_F_Y8 | IMR_F_UV8 | IMR_F_UV_SWAP | IMR_F_YUV_SWAP, ++ }, ++ { ++ .name = "Greyscale 8-bit", ++ .fourcc = V4L2_PIX_FMT_GREY, ++ .flags = IMR_F_Y8 | IMR_F_PLANAR, ++ }, ++ { ++ .name = "Greyscale 10-bit", ++ .fourcc = V4L2_PIX_FMT_Y10, ++ .flags = IMR_F_Y8 | IMR_F_Y10 | IMR_F_PLANAR, ++ }, ++ { ++ .name = "Greyscale 12-bit", ++ .fourcc = V4L2_PIX_FMT_Y12, ++ .flags = IMR_F_Y8 | IMR_F_Y10 | IMR_F_Y12 | IMR_F_PLANAR, ++ }, ++ { ++ .name = "Chrominance UV 8-bit", ++ .fourcc = V4L2_PIX_FMT_UV8, ++ .flags = IMR_F_UV8 | IMR_F_PLANAR, ++ }, ++}; ++ ++/* ...mesh configuration constructor */ ++static struct imr_cfg * imr_cfg_create(struct imr_ctx *ctx, u32 dl_size, u32 dl_start) ++{ ++ struct imr_device *imr = ctx->imr; ++ struct imr_cfg *cfg; ++ ++ /* ...allocate configuration descriptor */ ++ cfg = kmalloc(sizeof(*cfg), GFP_KERNEL); ++ if (!cfg) { ++ v4l2_err(&imr->v4l2_dev, "failed to allocate configuration descriptor\n"); ++ return ERR_PTR(-ENOMEM); ++ } ++ ++ /* ...allocate contiguous memory for a display list */ ++ cfg->dl_vaddr = dma_alloc_writecombine(imr->dev, dl_size, &cfg->dl_dma_addr, GFP_KERNEL); ++ if (!cfg->dl_vaddr) { ++ v4l2_err(&imr->v4l2_dev, "failed to allocate %u bytes for a DL\n", dl_size); ++ kfree(cfg); ++ return ERR_PTR(-ENOMEM); ++ } ++ ++ cfg->dl_size = dl_size; ++ cfg->dl_start_offset = dl_start; ++ cfg->refcount = 1; ++ cfg->id = ctx->sequence; ++ ++ /* ...for debugging purposes, advance number of active configurations */ ++ ctx->cfg_num++; ++ ++ return cfg; ++} ++ ++/* ...add reference to the current configuration */ ++static inline struct imr_cfg * imr_cfg_ref(struct imr_ctx *ctx) ++{ ++ struct imr_cfg *cfg = ctx->cfg; ++ ++ BUG_ON(!cfg); ++ cfg->refcount++; ++ return cfg; ++} ++ ++/* ...mesh configuration destructor */ ++static void imr_cfg_unref(struct imr_ctx *ctx, struct imr_cfg *cfg) ++{ ++ struct imr_device *imr = ctx->imr; ++ ++ /* ...no atomicity is required as operation is locked with device mutex */ ++ if (!cfg || --cfg->refcount) ++ return; ++ ++ /* ...release memory allocated for a display list */ ++ if (cfg->dl_vaddr) ++ dma_free_writecombine(imr->dev, cfg->dl_size, cfg->dl_vaddr, cfg->dl_dma_addr); ++ ++ /* ...destroy the configuration structure */ ++ kfree(cfg); ++ ++ /* ...decrement number of active configurations (debugging) */ ++ WARN_ON(!ctx->cfg_num--); ++} ++ ++ ++ ++/******************************************************************************* ++ * Context processing queue ++ ******************************************************************************/ ++ ++static int imr_queue_setup(struct vb2_queue *vq, ++ unsigned int *nbuffers, unsigned int *nplanes, ++ unsigned int sizes[], struct device *alloc_devs[]) ++{ ++ struct imr_ctx *ctx = vb2_get_drv_priv(vq); ++ struct imr_q_data *q_data = &ctx->queue[V4L2_TYPE_IS_OUTPUT(vq->type) ? 0 : 1]; ++ int w = q_data->fmt.width; ++ int h = q_data->fmt.height; ++ ++ /* ...we use only single-plane formats */ ++ *nplanes = 1; ++ ++ /* ...specify plane size */ ++ switch (q_data->fmt.pixelformat) { ++ case V4L2_PIX_FMT_UYVY: ++ case V4L2_PIX_FMT_YUYV: ++ case V4L2_PIX_FMT_VYUY: ++ case V4L2_PIX_FMT_YVYU: ++ case V4L2_PIX_FMT_NV16: ++ case V4L2_PIX_FMT_Y10: ++ case V4L2_PIX_FMT_Y16: ++ sizes[0] = w * h * 2; ++ break; ++ ++ case V4L2_PIX_FMT_UV8: ++ case V4L2_PIX_FMT_GREY: ++ sizes[0] = w * h; ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int imr_buf_prepare(struct vb2_buffer *vb) ++{ ++ /* ...unclear yet if we want to prepare a buffer somehow (cache invalidation? - tbd) */ ++ return 0; ++} ++ ++static void imr_buf_queue(struct vb2_buffer *vb) ++{ ++ struct vb2_queue *q = vb->vb2_queue; ++ struct imr_ctx *ctx = vb2_get_drv_priv(q); ++ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); ++ ++ WARN_ON_ONCE(!mutex_is_locked(&ctx->imr->mutex)); ++ ++ v4l2_dbg(3, debug, &ctx->imr->v4l2_dev, "%sput buffer <0x%08llx> submitted\n", ++ q->is_output ? "in" : "out", ++ vb2_dma_contig_plane_dma_addr(vb, 0)); ++ ++ /* ...for input buffer, put current configuration pointer (add reference) */ ++ if (q->is_output) ++ to_imr_buffer(vbuf)->cfg = imr_cfg_ref(ctx); ++ ++ v4l2_m2m_buf_queue(ctx->m2m_ctx, vbuf); ++} ++ ++static void imr_buf_finish(struct vb2_buffer *vb) ++{ ++ struct vb2_queue *q = vb->vb2_queue; ++ struct imr_ctx *ctx = vb2_get_drv_priv(q); ++ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); ++ ++ WARN_ON(!mutex_is_locked(&ctx->imr->mutex)); ++ ++ /* ...any special processing of completed buffer? - tbd */ ++ v4l2_dbg(3, debug, &ctx->imr->v4l2_dev, "%sput buffer <0x%08llx> done\n", ++ q->is_output ? "in" : "out", ++ vb2_dma_contig_plane_dma_addr(vb, 0)); ++ ++ /* ...unref configuration pointer as needed */ ++ if (q->is_output) ++ imr_cfg_unref(ctx, to_imr_buffer(vbuf)->cfg); ++} ++ ++static int imr_start_streaming(struct vb2_queue *vq, unsigned int count) ++{ ++ struct imr_ctx *ctx = vb2_get_drv_priv(vq); ++ int ret; ++ ++ ret = 0;//pm_runtime_get_sync(ctx->imr->dev); ++ if (ret < 0) { ++ v4l2_err(&ctx->imr->v4l2_dev, "failed to start %s streaming: %d\n", ++ (V4L2_TYPE_IS_OUTPUT(vq->type) ? "output" : "capture"), ret); ++ return ret; ++ } else { ++ v4l2_dbg(1, debug, &ctx->imr->v4l2_dev, "%s streaming started\n", ++ (V4L2_TYPE_IS_OUTPUT(vq->type) ? "output" : "capture")); ++ return 0; ++ } ++} ++ ++static void imr_stop_streaming(struct vb2_queue *vq) ++{ ++ struct imr_ctx *ctx = vb2_get_drv_priv(vq); ++ struct vb2_v4l2_buffer *vb; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ctx->imr->lock, flags); ++ ++ /* ...purge all buffers from a queue */ ++ if (V4L2_TYPE_IS_OUTPUT(vq->type)) { ++ while ((vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx)) != NULL) ++ v4l2_m2m_buf_done(vb, VB2_BUF_STATE_ERROR); ++ } else { ++ while ((vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx)) != NULL) ++ v4l2_m2m_buf_done(vb, VB2_BUF_STATE_ERROR); ++ } ++ ++ spin_unlock_irqrestore(&ctx->imr->lock, flags); ++ ++ v4l2_dbg(1, debug, &ctx->imr->v4l2_dev, "%s streaming stopped\n", ++ (V4L2_TYPE_IS_OUTPUT(vq->type) ? "output" : "capture")); ++ ++ //pm_runtime_put(ctx->imr->dev); ++} ++ ++/* ...buffer queue operations */ ++static struct vb2_ops imr_qops = { ++ .queue_setup = imr_queue_setup, ++ .buf_prepare = imr_buf_prepare, ++ .buf_queue = imr_buf_queue, ++ .buf_finish = imr_buf_finish, ++ .start_streaming = imr_start_streaming, ++ .stop_streaming = imr_stop_streaming, ++ .wait_prepare = vb2_ops_wait_prepare, ++ .wait_finish = vb2_ops_wait_finish, ++}; ++ ++/* ...M2M device processing queue initialization */ ++static int imr_queue_init(void *priv, struct vb2_queue *src_vq, ++ struct vb2_queue *dst_vq) ++{ ++ struct imr_ctx *ctx = priv; ++ int ret; ++ ++ memset(src_vq, 0, sizeof(*src_vq)); ++ src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; ++ src_vq->drv_priv = ctx; ++ src_vq->buf_struct_size = sizeof(struct imr_buffer); ++ src_vq->ops = &imr_qops; ++ src_vq->mem_ops = &vb2_dma_contig_memops; ++ src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; ++ src_vq->lock = &ctx->imr->mutex; ++ src_vq->dev = ctx->imr->v4l2_dev.dev; ++ ret = vb2_queue_init(src_vq); ++ if (ret) ++ return ret; ++ ++ memset(dst_vq, 0, sizeof(*dst_vq)); ++ dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; ++ dst_vq->drv_priv = ctx; ++ dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); ++ dst_vq->ops = &imr_qops; ++ dst_vq->mem_ops = &vb2_dma_contig_memops; ++ dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; ++ dst_vq->lock = &ctx->imr->mutex; ++ ret = vb2_queue_init(dst_vq); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++/******************************************************************************* ++ * Display list commands ++ ******************************************************************************/ ++ ++/* ...display list opcodes */ ++#define IMR_OP_TRI(n) ((0x8A << 24) | ((n) & 0xFFFF)) ++#define IMR_OP_LINE(n) ((0x8B << 24) | ((n) & 0xFFFF)) ++#define IMR_OP_NOP(n) ((0x80 << 24) | ((n) & 0xFFFF)) ++#define IMR_OP_TRAP ((0x8F << 24)) ++#define IMR_OP_WTL(add, n) ((0x81 << 24) | (((add) / 4) << 16) | ((n) & 0xFFFF)) ++#define IMR_OP_WTS(add, data) ((0x82 << 24) | (((add) / 4) << 16) | ((data) & 0xFFFF)) ++#define IMR_OP_WTL2(add, n) ((0x83 << 24) | (((add) / 4) << 10) | ((n) & 0x3FF)) ++#define IMR_OP_INT ((0x88 << 24)) ++#define IMR_OP_SYNCM ((0x86 << 24)) ++#define IMR_OP_GOSUB ((0x8C << 24)) ++#define IMR_OP_RET ((0x8D << 24)) ++ ++/******************************************************************************* ++ * Operation type decoding helpers ++ ******************************************************************************/ ++ ++static inline u16 __imr_auto_sg_dg_tcm(u32 type) ++{ ++ return (type & IMR_MAP_AUTOSG ? IMR_TRIM_AUTOSG : (type & IMR_MAP_AUTODG ? IMR_TRIM_AUTODG : 0)) | ++ (type & IMR_MAP_TCM ? IMR_TRIM_TCM : 0); ++} ++ ++static inline u16 __imr_uvdp(u32 type) ++{ ++ return __IMR_MAP_UVDPOR(type) | (type & IMR_MAP_DDP ? (1 << 8) : 0); ++} ++ ++static inline u16 __imr_cpdp(u32 type) ++{ ++ return (__IMR_MAP_YLDPO(type) << 8) | (__IMR_MAP_UBDPO(type) << 4) | __IMR_MAP_VRDPO(type); ++} ++ ++static inline u16 __imr_luce(u32 type) ++{ ++ return (type & IMR_MAP_LUCE ? IMR_CMR_LUCE : 0); ++} ++ ++static inline u16 __imr_clce(u32 type) ++{ ++ return (type & IMR_MAP_CLCE ? IMR_CMR_CLCE : 0); ++} ++ ++/******************************************************************************* ++ * Type A (absolute coordinates of source/destination) mapping ++ ******************************************************************************/ ++ ++/* ...return size of the subroutine for type "a" mapping */ ++static inline u32 imr_tri_type_a_get_length(struct imr_mesh *mesh, int item_size) ++{ ++ return ((mesh->columns * (item_size / 2) + 1) * (mesh->rows - 1) + 1) * sizeof(u32); ++} ++ ++/* ...set a mesh rows * columns using absolute coordinates */ ++static inline u32 * imr_tri_set_type_a(u32 *dl, void *map, struct imr_mesh *mesh, int item_size) ++{ ++ int rows = mesh->rows; ++ int columns = mesh->columns; ++ u32 stride = item_size * columns; ++ int i, j; ++ ++ /* ...convert lattice into set of stripes */ ++ for (i = 0; i < rows - 1; i++) { ++ *dl++ = IMR_OP_TRI(columns * 2); ++ for (j = 0; j < columns; j++) { ++ memcpy((void *)dl, map, item_size); ++ memcpy((void *)dl + item_size, map + stride, item_size); ++ dl += item_size / 2; ++ map += item_size; ++ } ++ } ++ ++ *dl++ = IMR_OP_RET; ++ return dl; ++} ++ ++/******************************************************************************* ++ * Type B mapping (automatically generated source or destination coordinates) ++ ******************************************************************************/ ++ ++/* ...calculate length of a type "b" mapping */ ++static inline u32 imr_tri_type_b_get_length(struct imr_mesh *mesh, int item_size) ++{ ++ return ((mesh->columns * (item_size / 2) + 2) * (mesh->rows - 1) + 4) * sizeof(u32); ++} ++ ++/* ...set an auto-generated mesh n * m for a source/destination */ ++static inline u32 * imr_tri_set_type_b(u32 *dl, void *map, struct imr_mesh *mesh, int item_size) ++{ ++ int rows = mesh->rows; ++ int columns = mesh->columns; ++ int x0 = mesh->x0; ++ int y0 = mesh->y0; ++ int dx = mesh->dx; ++ int dy = mesh->dy; ++ int stride = item_size * columns; ++ int i, j; ++ ++ /* ...set mesh configuration */ ++ *dl++ = IMR_OP_WTS(IMR_AMXSR, dx); ++ *dl++ = IMR_OP_WTS(IMR_AMYSR, dy); ++ ++ /* ...origin by "x" coordinate is the same across all rows */ ++ *dl++ = IMR_OP_WTS(IMR_AMXOR, x0); ++ ++ /* ...convert lattice into set of stripes */ ++ for (i = 0; i < rows - 1; i++, y0 += dy) { ++ /* ...set origin by "y" coordinate for a current row */ ++ *dl++ = IMR_OP_WTS(IMR_AMYOR, y0); ++ *dl++ = IMR_OP_TRI(2 * columns); ++ ++ /* ...fill single row */ ++ for (j = 0; j < columns; j++) { ++ memcpy((void *)dl, map, item_size); ++ memcpy((void *)dl + item_size, map + stride, item_size); ++ dl += item_size / 2; ++ map += item_size; ++ } ++ } ++ ++ *dl++ = IMR_OP_RET; ++ return dl; ++} ++ ++/******************************************************************************* ++ * Type C mapping (vertex-buffer-object) ++ ******************************************************************************/ ++ ++/* ...calculate length of a type "c" mapping */ ++static inline u32 imr_tri_type_c_get_length(struct imr_vbo *vbo, int item_size) ++{ ++ return ((4 + 3 * item_size) * vbo->num + 4); ++} ++ ++/* ...set a VBO mapping using absolute coordinates */ ++static inline u32 * imr_tri_set_type_c(u32 *dl, void *map, struct imr_vbo *vbo, int item_size) ++{ ++ int num = vbo->num; ++ int i; ++ ++ /* ...prepare list of triangles to draw */ ++ for (i = 0; i < num; i++) { ++ *dl++ = IMR_OP_TRI(3); ++ memcpy((void *)dl, map, 3 * item_size); ++ dl += 3 * item_size / 4; ++ map += 3 * item_size; ++ } ++ ++ *dl++ = IMR_OP_RET; ++ return dl; ++} ++ ++/******************************************************************************* ++ * DL program creation ++ ******************************************************************************/ ++ ++/* ...return length of a DL main program */ ++static inline u32 imr_dl_program_length(struct imr_ctx *ctx) ++{ ++ u32 iflags = ctx->queue[0].flags; ++ u32 oflags = ctx->queue[1].flags; ++ u32 cflags = __imr_flags_common(iflags, oflags); ++ ++ /* ...check if formats are compatible */ ++ if (((iflags & IMR_F_PLANAR) != 0 && (oflags & IMR_F_PLANAR) == 0) || (cflags == 0)) { ++ v4l2_err(&ctx->imr->v4l2_dev, "formats are incompatible: if=%x, of=%x, cf=%x\n", iflags, oflags, cflags); ++ return 0; ++ } ++ ++ /* ...maximal possible length of the program is 27 32-bits words; round up to 32 */ ++ return 32 << 2; ++} ++ ++/* ...setup DL for Y/YUV planar/interleaved processing */ ++static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg, u32 type, u32 *dl, u32 subaddr) ++{ ++ u32 iflags = ctx->queue[0].flags; ++ u32 oflags = ctx->queue[1].flags; ++ u32 cflags = __imr_flags_common(iflags, oflags); ++ u16 src_y_fmt = (iflags & IMR_F_Y12 ? IMR_CMR_SY12 : (iflags & IMR_F_Y10 ? IMR_CMR_SY10 : 0)); ++ u16 src_uv_fmt = (iflags & IMR_F_UV12 ? 2 : (iflags & IMR_F_UV10 ? 1 : 0)) << IMR_CMR_SUV_SHIFT; ++ u16 dst_y_fmt = (cflags & IMR_F_Y12 ? IMR_CMR_DY12 : (cflags & IMR_F_Y10 ? IMR_CMR_DY10 : 0)); ++ u16 dst_uv_fmt = (cflags & IMR_F_UV12 ? 2 : (cflags & IMR_F_UV10 ? 1 : 0)) << IMR_CMR_DUV_SHIFT; ++ int w = ctx->queue[0].fmt.width; ++ int h = ctx->queue[0].fmt.height; ++ int W = ctx->queue[1].fmt.width; ++ int H = ctx->queue[1].fmt.height; ++ ++ v4l2_dbg(2, debug, &ctx->imr->v4l2_dev, "setup %u*%u -> %u*%u mapping (type=%x)\n", w, h, W, H, type); ++ ++ /* ...set triangle mode register from user-supplied descriptor */ ++ *dl++ = IMR_OP_WTS(IMR_TRIMCR, 0xFFFF); ++ ++ /* ...set automatic source / destination coordinates generation flags */ ++ *dl++ = IMR_OP_WTS(IMR_TRIMSR, __imr_auto_sg_dg_tcm(type) | IMR_TRIM_BFE | IMR_TRIM_TME); ++ ++ /* ...set source / destination coordinate precision */ ++ *dl++ = IMR_OP_WTS(IMR_UVDPOR, __imr_uvdp(type)); ++ ++ /* ...set luminance/chromacity correction parameters precision */ ++ *dl++ = IMR_OP_WTS(IMR_CPDPOR, __imr_cpdp(type)); ++ ++ /* ...reset rendering mode registers */ ++ *dl++ = IMR_OP_WTS(IMR_CMRCCR, 0xFFFF); ++ *dl++ = IMR_OP_WTS(IMR_CMRCCR2, 0xFFFF); ++ ++ /* ...set source/destination addresses of Y/UV plane */ ++ *dl++ = IMR_OP_WTL(IMR_DSAR, 2); ++ cfg->dst_pa_ptr[0] = dl++; ++ cfg->src_pa_ptr[0] = dl++; ++ ++ /* ...select planar/interleaved mode basing on input format */ ++ if (iflags & IMR_F_PLANAR) { ++ /* ...planar input means planar output; set Y-plane precision */ ++ if (cflags & IMR_F_Y8) { ++ /* ...setup Y-plane processing: YCM=0, SY/DY=xx, SUV/DUV=0 */ ++ *dl++ = IMR_OP_WTS(IMR_CMRCSR, src_y_fmt | src_uv_fmt | dst_y_fmt | dst_uv_fmt | __imr_luce(type)); ++ ++ /* ...set source/destination strides basing on Y-plane precision */ ++ *dl++ = IMR_OP_WTS(IMR_DSTR, W << (cflags & IMR_F_Y10 ? 1 : 0)); ++ *dl++ = IMR_OP_WTS(IMR_SSTR, w << (iflags & IMR_F_Y10 ? 1 : 0)); ++ } else { ++ /* ...setup UV-plane processing only */ ++ *dl++ = IMR_OP_WTS(IMR_CMRCSR, IMR_CMR_YCM | src_uv_fmt | dst_uv_fmt | __imr_clce(type)); ++ ++ /* ...set source/destination strides basing on UV-plane precision */ ++ *dl++ = IMR_OP_WTS(IMR_DSTR, W << (cflags & IMR_F_UV10 ? 1 : 0)); ++ *dl++ = IMR_OP_WTS(IMR_SSTR, w << (iflags & IMR_F_UV10 ? 1 : 0)); ++ } ++ } else { ++ u16 src_fmt = (iflags & IMR_F_UV_SWAP ? IMR_CMR2_UVFORM : 0) | (iflags & IMR_F_YUV_SWAP ? IMR_CMR2_YUV422FORM : 0); ++ u32 dst_fmt = (oflags & IMR_F_YUV_SWAP ? IMR_TRIC_YCFORM : 0); ++ ++ /* ...interleaved input; output is either interleaved or planar */ ++ *dl++ = IMR_OP_WTS(IMR_CMRCSR2, IMR_CMR2_YUV422E | src_fmt); ++ ++ /* ...destination is always YUYV or UYVY */ ++ *dl++ = IMR_OP_WTL(IMR_TRICR, 1); ++ *dl++ = dst_fmt; ++ ++ /* ...set precision of Y/UV planes and required correction */ ++ *dl++ = IMR_OP_WTS(IMR_CMRCSR, src_y_fmt | src_uv_fmt | dst_y_fmt | dst_uv_fmt | __imr_clce(type) | __imr_luce(type)); ++ ++ /* ...set source stride basing on precision (2 or 4 bytes/pixel) */ ++ *dl++ = IMR_OP_WTS(IMR_SSTR, w << (iflags & IMR_F_Y10 ? 2 : 1)); ++ ++ /* ...if output is planar, put the offset value */ ++ if (oflags & IMR_F_PLANAR) { ++ /* ...specify offset of a destination UV plane */ ++ *dl++ = IMR_OP_WTL(IMR_DSOR, 1); ++ *dl++ = W * H; ++ ++ /* ...destination stride is 1 or 2 bytes/pixel (same for both Y and UV planes) */ ++ *dl++ = IMR_OP_WTS(IMR_DSTR, W << (cflags & IMR_F_Y10 ? 1 : 0)); ++ } else { ++ /* ...destination stride if 2 or 4 bytes/pixel (Y and UV planes interleaved) */ ++ *dl++ = IMR_OP_WTS(IMR_DSTR, W << (cflags & IMR_F_Y10 ? 2 : 1)); ++ } ++ } ++ ++ /* ...set source width/height of Y/UV plane (for Y plane upper part of SUSR is ignored) */ ++ *dl++ = IMR_OP_WTL(IMR_SUSR, 2); ++ *dl++ = ((w - 2) << 16) | (w - 1); ++ *dl++ = h - 1; ++ ++ /* ...invoke subroutine for triangles drawing */ ++ *dl++ = IMR_OP_GOSUB; ++ *dl++ = subaddr; ++ ++ /* ...if we have a planar output with both Y and UV planes available */ ++ if ((cflags & (IMR_F_PLANAR | IMR_F_Y8 | IMR_F_UV8)) == (IMR_F_PLANAR | IMR_F_Y8 | IMR_F_UV8)) { ++ /* ...select UV-plane processing mode; put sync before switching */ ++ *dl++ = IMR_OP_SYNCM; ++ ++ /* ...setup UV-plane source/destination addresses */ ++ *dl++ = IMR_OP_WTL(IMR_DSAR, 2); ++ cfg->dst_pa_ptr[1] = dl++; ++ cfg->src_pa_ptr[1] = dl++; ++ ++ /* ...select correction mode */ ++ *dl++ = IMR_OP_WTS(IMR_CMRCSR, IMR_CMR_YCM | __imr_clce(type)); ++ ++ /* ...luminance correction bit must be cleared (if it was set) */ ++ *dl++ = IMR_OP_WTS(IMR_CMRCCR, IMR_CMR_LUCE); ++ ++ /* ...draw triangles */ ++ *dl++ = IMR_OP_GOSUB; ++ *dl++ = subaddr; ++ } else { ++ /* ...clear pointers to the source/destination UV-planes addresses */ ++ cfg->src_pa_ptr[1] = cfg->dst_pa_ptr[1] = NULL; ++ } ++ ++ /* ...signal completion of the operation */ ++ *dl++ = IMR_OP_SYNCM; ++ *dl++ = IMR_OP_TRAP; ++} ++ ++/******************************************************************************* ++ * Mapping specification processing ++ ******************************************************************************/ ++ ++/* ...set mapping data (function called with video device lock held) */ ++static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc) ++{ ++ struct imr_device *imr = ctx->imr; ++ struct imr_mesh *mesh; ++ struct imr_vbo *vbo; ++ struct imr_cfg *cfg; ++ void *buf, *map; ++ u32 type; ++ u32 length, item_size; ++ u32 tri_length; ++ void *dl_vaddr; ++ u32 dl_size; ++ u32 dl_start_offset; ++ dma_addr_t dl_dma_addr; ++ int ret; ++ ++ /* ...read remainder of data into temporary buffer */ ++ length = desc->size; ++ buf = kmalloc(length, GFP_KERNEL); ++ if (!buf) { ++ v4l2_err(&imr->v4l2_dev, "failed to allocate %u bytes for mapping reading\n", length); ++ return -ENOMEM; ++ } ++ ++ /* ...copy mesh data */ ++ if (copy_from_user(buf, (void __user *)desc->data, length)) { ++ v4l2_err(&imr->v4l2_dev, "failed to read %u bytes of mapping specification\n", length); ++ ret = -EFAULT; ++ goto out; ++ } ++ ++ type = desc->type; ++ ++ /* ...mesh item size calculation */ ++ item_size = (type & IMR_MAP_LUCE ? 4 : 0) + (type & IMR_MAP_CLCE ? 4 : 0); ++ ++ /* ...calculate the length of a display list */ ++ if (type & IMR_MAP_MESH) { ++ /* ...assure we have proper mesh descriptor */ ++ if (length < sizeof(struct imr_mesh)) { ++ v4l2_err(&imr->v4l2_dev, "invalid mesh specification size: %u\n", length); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ mesh = (struct imr_mesh *)buf; ++ length -= sizeof(struct imr_mesh); ++ map = buf + sizeof(struct imr_mesh); ++ ++ if (type & (IMR_MAP_AUTODG | IMR_MAP_AUTOSG)) { ++ /* ...source / destination vertex size is 4 bytes */ ++ item_size += 4; ++ ++ /* ...mapping is given using automatic generation pattern; check size */ ++ if (mesh->rows * mesh->columns * item_size != length) { ++ v4l2_err(&imr->v4l2_dev, "invalid mesh size: %u*%u*%u != %u\n", mesh->rows, mesh->columns, item_size, length); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ /* ...calculate size of triangles drawing subroutine */ ++ tri_length = imr_tri_type_b_get_length(mesh, item_size); ++ } else { ++ /* ...source / destination vertes size if 8 bytes */ ++ item_size += 8; ++ ++ /* ...mapping is done with absolute coordinates */ ++ if (mesh->rows * mesh->columns * item_size != length) { ++ v4l2_err(&imr->v4l2_dev, "invalid mesh size: %u*%u*%u != %u\n", mesh->rows, mesh->columns, item_size, length); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ /* ...calculate size of triangles drawing subroutine */ ++ tri_length = imr_tri_type_a_get_length(mesh, item_size); ++ } ++ } else { ++ /* ...assure we have proper VBO descriptor */ ++ if (length < sizeof(struct imr_vbo)) { ++ v4l2_err(&imr->v4l2_dev, "invalid vbo specification size: %u\n", length); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ /* ...make sure there is no automatic-generation flags */ ++ if (type & (IMR_MAP_AUTODG | IMR_MAP_AUTOSG)) { ++ v4l2_err(&imr->v4l2_dev, "invalid auto-dg/sg flags: 0x%x\n", type); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ vbo = (struct imr_vbo *)buf; ++ length -= sizeof(struct imr_vbo); ++ map = buf + sizeof(struct imr_vbo); ++ ++ /* ...vertex is given with absolute coordinates */ ++ item_size += 8; ++ ++ /* ...check the length is sane */ ++ if (length != vbo->num * 3 * item_size) { ++ v4l2_err(&imr->v4l2_dev, "invalid vbo size: %u*%u*3 != %u\n", vbo->num, item_size, length); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ /* ...calculate size of trangles drawing subroutine */ ++ tri_length = imr_tri_type_c_get_length(vbo, item_size); ++ } ++ ++ /* ...DL main program shall start with 8-byte aligned address */ ++ dl_start_offset = (tri_length + 7) & ~7; ++ ++ /* ...calculate main routine length */ ++ dl_size = imr_dl_program_length(ctx); ++ if (!dl_size) { ++ v4l2_err(&imr->v4l2_dev, "format configuration error\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ /* ...we use a single display list, with TRI subroutine prepending MAIN */ ++ dl_size += dl_start_offset; ++ ++ /* ...unref current configuration (will not be used by subsequent jobs) */ ++ imr_cfg_unref(ctx, ctx->cfg); ++ ++ /* ...create new configuration */ ++ ctx->cfg = cfg = imr_cfg_create(ctx, dl_size, dl_start_offset); ++ if (IS_ERR(cfg)) { ++ ret = PTR_ERR(cfg); ++ v4l2_err(&imr->v4l2_dev, "failed to create configuration: %d\n", ret); ++ goto out; ++ } ++ ++ /* ...get pointer to the new display list */ ++ dl_vaddr = cfg->dl_vaddr; ++ dl_dma_addr = cfg->dl_dma_addr; ++ ++ /* ...prepare a triangles drawing subroutine */ ++ if (type & IMR_MAP_MESH) { ++ if (type & (IMR_MAP_AUTOSG | IMR_MAP_AUTODG)) { ++ imr_tri_set_type_b(dl_vaddr, map, mesh, item_size); ++ } else { ++ imr_tri_set_type_a(dl_vaddr, map, mesh, item_size); ++ } ++ } else { ++ imr_tri_set_type_c(dl_vaddr, map, vbo, item_size); ++ } ++ ++ /* ...prepare main DL-program */ ++ imr_dl_program_setup(ctx, cfg, type, dl_vaddr + dl_start_offset, (u32)dl_dma_addr); ++ ++ /* ...update cropping parameters */ ++ cfg->dst_subpixel = (type & IMR_MAP_DDP ? 2 : 0); ++ ++ /* ...display list updated successfully */ ++ v4l2_dbg(2, debug, &ctx->imr->v4l2_dev, "display-list created: #%u[%08X]:%u[%u]\n", ++ cfg->id, (u32)dl_dma_addr, dl_size, dl_start_offset); ++ ++ if (debug >= 4) ++ print_hex_dump_bytes("DL-", DUMP_PREFIX_OFFSET, dl_vaddr + dl_start_offset, dl_size - dl_start_offset); ++ ++ /* ...success */ ++ ret = 0; ++ ++out: ++ /* ...release interim buffer */ ++ kfree(buf); ++ ++ return ret; ++} ++ ++/******************************************************************************* ++ * V4L2 I/O controls ++ ******************************************************************************/ ++ ++/* ...test for a format supported */ ++static int __imr_try_fmt(struct imr_ctx *ctx, struct v4l2_format *f) ++{ ++ struct v4l2_pix_format *pix = &f->fmt.pix; ++ u32 fourcc = pix->pixelformat; ++ int i; ++ ++ /* ...both output and capture interface have the same set of supported formats */ ++ for (i = 0; i < ARRAY_SIZE(imr_lx4_formats); i++) { ++ if (fourcc == imr_lx4_formats[i].fourcc) { ++ /* ...fix-up format specification as needed */ ++ pix->field = V4L2_FIELD_NONE; ++ ++ v4l2_dbg(1, debug, &ctx->imr->v4l2_dev, "format request: '%c%c%c%c', %d*%d\n", ++ (fourcc >> 0) & 0xff, (fourcc >> 8) & 0xff, ++ (fourcc >> 16) & 0xff, (fourcc >> 24) & 0xff, ++ pix->width, pix->height); ++ ++ /* ...verify source/destination image dimensions */ ++ if (V4L2_TYPE_IS_OUTPUT(f->type)) ++ v4l_bound_align_image(&pix->width, 128, 2048, 7, &pix->height, 1, 2048, 0, 0); ++ else ++ v4l_bound_align_image(&pix->width, 64, 2048, 6, &pix->height, 1, 2048, 0, 0); ++ ++ return i; ++ } ++ } ++ ++ v4l2_err(&ctx->imr->v4l2_dev, "unsupported format request: '%c%c%c%c'\n", ++ (fourcc >> 0) & 0xff, (fourcc >> 8) & 0xff, ++ (fourcc >> 16) & 0xff, (fourcc >> 24) & 0xff); ++ ++ return -EINVAL; ++} ++ ++/* ...capabilities query */ ++static int imr_querycap(struct file *file, void *priv, struct v4l2_capability *cap) ++{ ++ strlcpy(cap->driver, DRV_NAME, sizeof(cap->driver)); ++ strlcpy(cap->card, DRV_NAME, sizeof(cap->card)); ++ strlcpy(cap->bus_info, DRV_NAME, sizeof(cap->bus_info)); ++ ++ cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | ++ V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; ++ ++ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; ++ ++ return 0; ++} ++ ++/* ...enumerate supported formats */ ++static int imr_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f) ++{ ++ /* ...no distinction between output/capture formats */ ++ if (f->index < ARRAY_SIZE(imr_lx4_formats)) { ++ const struct imr_format_info *fmt = &imr_lx4_formats[f->index]; ++ strlcpy(f->description, fmt->name, sizeof(f->description)); ++ f->pixelformat = fmt->fourcc; ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++/* ...retrieve current queue format; operation is locked ? */ ++static int imr_g_fmt(struct file *file, void *priv, struct v4l2_format *f) ++{ ++ struct imr_ctx *ctx = fh_to_ctx(priv); ++ struct vb2_queue *vq; ++ struct imr_q_data *q_data; ++ ++ vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); ++ if (!vq) ++ return -EINVAL; ++ ++ q_data = &ctx->queue[V4L2_TYPE_IS_OUTPUT(f->type) ? 0 : 1]; ++ ++ /* ...processing is locked? tbd */ ++ f->fmt.pix = q_data->fmt; ++ ++ return 0; ++} ++ ++/* ...test particular format; operation is not locked */ ++static int imr_try_fmt(struct file *file, void *priv, struct v4l2_format *f) ++{ ++ struct imr_ctx *ctx = fh_to_ctx(priv); ++ struct vb2_queue *vq; ++ ++ /* ...make sure we have a queue of particular type */ ++ vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); ++ if (!vq) ++ return -EINVAL; ++ ++ /* ...test if format is supported (adjust as appropriate) */ ++ return (__imr_try_fmt(ctx, f) >= 0 ? 0 : -EINVAL); ++} ++ ++/* ...apply queue format; operation is locked ? */ ++static int imr_s_fmt(struct file *file, void *priv, struct v4l2_format *f) ++{ ++ struct imr_ctx *ctx = fh_to_ctx(priv); ++ struct vb2_queue *vq; ++ struct imr_q_data *q_data; ++ int i; ++ ++ vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); ++ if (!vq) ++ return -EINVAL; ++ ++ /* ...check if queue is busy */ ++ if (vb2_is_busy(vq)) ++ return -EBUSY; ++ ++ /* ...test if format is supported (adjust as appropriate) */ ++ i = __imr_try_fmt(ctx, f); ++ if (i < 0) ++ return -EINVAL; ++ ++ /* ...format is supported; save current format in a queue-specific data */ ++ q_data = &ctx->queue[V4L2_TYPE_IS_OUTPUT(f->type) ? 0 : 1]; ++ ++ /* ...processing is locked? tbd */ ++ q_data->fmt = f->fmt.pix; ++ q_data->flags = imr_lx4_formats[i].flags; ++ ++ /* ...set default crop factors */ ++ if (V4L2_TYPE_IS_OUTPUT(f->type) == 0) { ++ ctx->crop[0] = 0; ++ ctx->crop[1] = f->fmt.pix.width - 1; ++ ctx->crop[2] = 0; ++ ctx->crop[3] = f->fmt.pix.height - 1; ++ } ++ ++ return 0; ++} ++ ++static int imr_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *reqbufs) ++{ ++ struct imr_ctx *ctx = fh_to_ctx(priv); ++ ++ return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); ++} ++ ++static int imr_querybuf(struct file *file, void *priv, struct v4l2_buffer *buf) ++{ ++ struct imr_ctx *ctx = fh_to_ctx(priv); ++ ++ return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); ++} ++ ++static int imr_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) ++{ ++ struct imr_ctx *ctx = fh_to_ctx(priv); ++ ++ /* ...operation is protected with a queue lock */ ++ WARN_ON(!mutex_is_locked(&ctx->imr->mutex)); ++ ++ /* ...verify the configuration is complete */ ++ if (!V4L2_TYPE_IS_OUTPUT(buf->type) && !ctx->cfg) { ++ v4l2_err(&ctx->imr->v4l2_dev, "stream configuration is not complete\n"); ++ return -EINVAL; ++ } ++ ++ return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); ++} ++ ++static int imr_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) ++{ ++ struct imr_ctx *ctx = fh_to_ctx(priv); ++ ++ return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); ++} ++ ++static int imr_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *eb) ++{ ++ struct imr_ctx *ctx = fh_to_ctx(priv); ++ ++ return v4l2_m2m_expbuf(file, ctx->m2m_ctx, eb); ++} ++ ++static int imr_streamon(struct file *file, void *priv, enum v4l2_buf_type type) ++{ ++ struct imr_ctx *ctx = fh_to_ctx(priv); ++ ++ /* ...context is prepared for a streaming */ ++ return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); ++} ++ ++static int imr_streamoff(struct file *file, void *priv, enum v4l2_buf_type type) ++{ ++ struct imr_ctx *ctx = fh_to_ctx(priv); ++ ++ return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); ++} ++ ++static int imr_g_crop(struct file *file, void *priv, struct v4l2_crop *cr) ++{ ++ struct imr_ctx *ctx = fh_to_ctx(priv); ++ ++ /* ...subpixel resolution of output buffer is not counted here */ ++ cr->c.left = ctx->crop[0]; ++ cr->c.top = ctx->crop[2]; ++ cr->c.width = ctx->crop[1] - ctx->crop[0]; ++ cr->c.height = ctx->crop[3] - ctx->crop[2]; ++ ++ return 0; ++} ++ ++static int imr_s_crop(struct file *file, void *priv, const struct v4l2_crop *cr) ++{ ++ struct imr_ctx *ctx = fh_to_ctx(priv); ++ int x0 = cr->c.left; ++ int y0 = cr->c.top; ++ int x1 = x0 + cr->c.width; ++ int y1 = y0 + cr->c.height; ++ ++ if (x0 < 0 || x1 >= 2048 || y0 < 0 || y1 >= 2048) { ++ v4l2_err(&ctx->imr->v4l2_dev, "invalid cropping: %d/%d/%d/%d\n", x0, x1, y0, y1); ++ return -EINVAL; ++ } ++ ++ /* ...subpixel resolution of output buffer is not counted here */ ++ ctx->crop[0] = x0; ++ ctx->crop[1] = x1; ++ ctx->crop[2] = y0; ++ ctx->crop[3] = y1; ++ ++ return 0; ++} ++ ++/* ...customized I/O control processing */ ++static long imr_default(struct file *file, void *fh, bool valid_prio, unsigned int cmd, void *arg) ++{ ++ struct imr_ctx *ctx = fh_to_ctx(fh); ++ ++ switch (cmd) { ++ case VIDIOC_IMR_MESH: ++ /* ...set mesh data */ ++ return imr_ioctl_map(ctx, (struct imr_map_desc *)arg); ++ ++ default: ++ return -ENOIOCTLCMD; ++ } ++} ++ ++static const struct v4l2_ioctl_ops imr_ioctl_ops = { ++ .vidioc_querycap = imr_querycap, ++ ++ .vidioc_enum_fmt_vid_cap = imr_enum_fmt, ++ .vidioc_enum_fmt_vid_out = imr_enum_fmt, ++ .vidioc_g_fmt_vid_cap = imr_g_fmt, ++ .vidioc_g_fmt_vid_out = imr_g_fmt, ++ .vidioc_try_fmt_vid_cap = imr_try_fmt, ++ .vidioc_try_fmt_vid_out = imr_try_fmt, ++ .vidioc_s_fmt_vid_cap = imr_s_fmt, ++ .vidioc_s_fmt_vid_out = imr_s_fmt, ++ ++ .vidioc_reqbufs = imr_reqbufs, ++ .vidioc_querybuf = imr_querybuf, ++ .vidioc_qbuf = imr_qbuf, ++ .vidioc_dqbuf = imr_dqbuf, ++ .vidioc_expbuf = imr_expbuf, ++ .vidioc_streamon = imr_streamon, ++ .vidioc_streamoff = imr_streamoff, ++ ++ .vidioc_g_crop = imr_g_crop, ++ .vidioc_s_crop = imr_s_crop, ++ ++ .vidioc_default = imr_default, ++}; ++ ++/******************************************************************************* ++ * Generic device file operations ++ ******************************************************************************/ ++ ++static int imr_open(struct file *file) ++{ ++ struct imr_device *imr = video_drvdata(file); ++ struct video_device *vfd = video_devdata(file); ++ struct imr_ctx *ctx; ++ int ret; ++ ++ /* ...allocate processing context associated with given instance */ ++ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); ++ if (!ctx) ++ return -ENOMEM; ++ ++ /* ...initialize per-file-handle structure */ ++ v4l2_fh_init(&ctx->fh, vfd); ++ //ctx->fh.ctrl_handler = &ctx->ctrl_handler; ++ file->private_data = &ctx->fh; ++ v4l2_fh_add(&ctx->fh); ++ ++ /* ...set default source / destination formats - need that? */ ++ ctx->imr = imr; ++ ctx->queue[0].fmt.pixelformat = 0; ++ ctx->queue[1].fmt.pixelformat = 0; ++ ++ /* ...set default cropping parameters */ ++ ctx->crop[1] = ctx->crop[3] = 0x3FF; ++ ++ /* ...initialize M2M processing context */ ++ ctx->m2m_ctx = v4l2_m2m_ctx_init(imr->m2m_dev, ctx, imr_queue_init); ++ if (IS_ERR(ctx->m2m_ctx)) { ++ ret = PTR_ERR(ctx->m2m_ctx); ++ goto v4l_prepare_rollback; ++ } ++ ++#if 0 ++ /* ...initialize controls and stuff */ ++ ret = imr_controls_create(ctx); ++ if (ret < 0) ++ goto v4l_prepare_rollback; ++#endif ++ ++ /* ...lock access to global device data */ ++ if (mutex_lock_interruptible(&imr->mutex)) { ++ ret = -ERESTARTSYS; ++ goto v4l_prepare_rollback; ++ } ++ ++ /* ...bring-up device as needed */ ++ if (imr->refcount == 0) { ++ ret = clk_prepare_enable(imr->clock); ++ if (ret < 0) ++ goto device_prepare_rollback; ++ } ++ ++ imr->refcount++; ++ ++ mutex_unlock(&imr->mutex); ++ ++ v4l2_dbg(1, debug, &imr->v4l2_dev, "IMR device opened (refcount=%u)\n", imr->refcount); ++ ++ return 0; ++ ++device_prepare_rollback: ++ /* ...unlock global device data */ ++ mutex_unlock(&imr->mutex); ++ ++v4l_prepare_rollback: ++ /* ...destroy context */ ++ v4l2_fh_del(&ctx->fh); ++ v4l2_fh_exit(&ctx->fh); ++ kfree(ctx); ++ ++ return ret; ++} ++ ++static int imr_release(struct file *file) ++{ ++ struct imr_device *imr = video_drvdata(file); ++ struct imr_ctx *ctx = fh_to_ctx(file->private_data); ++ ++ /* ...I don't need to get a device-scope lock here really - tbd */ ++ mutex_lock(&imr->mutex); ++ ++ /* ...destroy M2M device processing context */ ++ v4l2_m2m_ctx_release(ctx->m2m_ctx); ++ //v4l2_ctrl_handler_free(&ctx->ctrl_handler); ++ v4l2_fh_del(&ctx->fh); ++ v4l2_fh_exit(&ctx->fh); ++ ++ /* ...drop active configuration as needed */ ++ imr_cfg_unref(ctx, ctx->cfg); ++ ++ /* ...make sure there are no more active configs */ ++ WARN_ON(ctx->cfg_num); ++ ++ /* ...destroy context data */ ++ kfree(ctx); ++ ++ /* ...disable hardware operation */ ++ if (--imr->refcount == 0) ++ clk_disable_unprepare(imr->clock); ++ ++ mutex_unlock(&imr->mutex); ++ ++ v4l2_dbg(1, debug, &imr->v4l2_dev, "closed device instance\n"); ++ ++ return 0; ++} ++ ++static unsigned int imr_poll(struct file *file, struct poll_table_struct *wait) ++{ ++ struct imr_device *imr = video_drvdata(file); ++ struct imr_ctx *ctx = fh_to_ctx(file->private_data); ++ unsigned int res; ++ ++ if (mutex_lock_interruptible(&imr->mutex)) ++ return -ERESTARTSYS; ++ ++ res = v4l2_m2m_poll(file, ctx->m2m_ctx, wait); ++ mutex_unlock(&imr->mutex); ++ ++ return res; ++} ++ ++static int imr_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ struct imr_device *imr = video_drvdata(file); ++ struct imr_ctx *ctx = fh_to_ctx(file->private_data); ++ int ret; ++ ++ /* ...should we protect all M2M operations with mutex? - tbd */ ++ if (mutex_lock_interruptible(&imr->mutex)) ++ return -ERESTARTSYS; ++ ++ ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); ++ ++ mutex_unlock(&imr->mutex); ++ ++ return ret; ++} ++ ++static const struct v4l2_file_operations imr_fops = { ++ .owner = THIS_MODULE, ++ .open = imr_open, ++ .release = imr_release, ++ .poll = imr_poll, ++ .mmap = imr_mmap, ++ .unlocked_ioctl = video_ioctl2, ++}; ++ ++/******************************************************************************* ++ * M2M device interface ++ ******************************************************************************/ ++ ++#if 0 ++/* ...job cleanup function */ ++static void imr_cleanup(struct imr_ctx *ctx) ++{ ++ struct imr_device *imr = ctx->imr; ++ struct vb2_v4l2_buffer *src_buf, *dst_buf; ++ unsigned long flags; ++ ++ /* ...interlock buffer handling with interrupt */ ++ spin_lock_irqsave(&imr->lock, flags); ++ ++ while ((src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx)) != NULL) ++ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); ++ ++ while ((dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx)) != NULL) ++ v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR); ++ ++ /* ...release lock before we mark current job as finished */ ++ spin_unlock_irqrestore(&imr->lock, flags); ++} ++#endif ++ ++/* ...job execution function */ ++static void imr_device_run(void *priv) ++{ ++ struct imr_ctx *ctx = priv; ++ struct imr_device *imr = ctx->imr; ++ struct imr_cfg *cfg; ++ struct vb2_buffer *src_buf, *dst_buf; ++ u32 src_addr, dst_addr; ++ unsigned long flags; ++ ++ v4l2_dbg(3, debug, &imr->v4l2_dev, "run next job...\n"); ++ ++ /* ...protect access to internal device state */ ++ spin_lock_irqsave(&imr->lock, flags); ++ ++ /* ...retrieve input/output buffers */ ++ src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); ++ dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); ++ ++ /* ...take configuration pointer associated with input buffer */ ++ cfg = to_imr_buffer(to_vb2_v4l2_buffer(src_buf))->cfg; ++ ++ /* ...cancel software reset state as needed */ ++ iowrite32(0, imr->mmio + IMR_CR); ++ ++ /* ...set cropping data with respect to destination sub-pixel mode */ ++ iowrite32(ctx->crop[0] << cfg->dst_subpixel, imr->mmio + IMR_XMINR); ++ iowrite32(ctx->crop[1] << cfg->dst_subpixel, imr->mmio + IMR_XMAXR); ++ iowrite32(ctx->crop[2] << cfg->dst_subpixel, imr->mmio + IMR_YMINR); ++ iowrite32(ctx->crop[3] << cfg->dst_subpixel, imr->mmio + IMR_YMAXR); ++ ++ /* ...adjust source/destination parameters of the program (interleaved / semiplanar) */ ++ *cfg->src_pa_ptr[0] = src_addr = (u32)vb2_dma_contig_plane_dma_addr(src_buf, 0); ++ *cfg->dst_pa_ptr[0] = dst_addr = (u32)vb2_dma_contig_plane_dma_addr(dst_buf, 0); ++ ++ /* ...adjust source/destination parameters of the UV-plane as needed */ ++ if (cfg->src_pa_ptr[1] && cfg->dst_pa_ptr[1]) { ++ *cfg->src_pa_ptr[1] = src_addr + ctx->queue[0].fmt.width * ctx->queue[0].fmt.height; ++ *cfg->dst_pa_ptr[1] = dst_addr + ctx->queue[1].fmt.width * ctx->queue[1].fmt.height; ++ } ++ ++ v4l2_dbg(3, debug, &imr->v4l2_dev, "process buffer-pair 0x%08x:0x%08x\n", ++ *cfg->src_pa_ptr[0], *cfg->dst_pa_ptr[0]); ++ ++ /* ...force clearing of status register bits */ ++ iowrite32(0x7, imr->mmio + IMR_SRCR); ++ ++ /* ...unmask/enable interrupts */ ++ iowrite32(ioread32(imr->mmio + IMR_ICR) | (IMR_ICR_TRAEN | IMR_ICR_IEREN | IMR_ICR_INTEN), imr->mmio + IMR_ICR); ++ iowrite32(ioread32(imr->mmio + IMR_IMR) & ~(IMR_ICR_TRAEN | IMR_ICR_IEREN | IMR_ICR_INTEN), imr->mmio + IMR_IMR); ++ ++ /* ...set display list address */ ++ iowrite32(cfg->dl_dma_addr + cfg->dl_start_offset, imr->mmio + IMR_DLSAR); ++ ++ /* ...explicitly flush any pending write operations (don't need that, I guess) */ ++ wmb(); ++ ++ /* ...start rendering operation */ ++ iowrite32(IMR_CR_RS, imr->mmio + IMR_CR); ++ ++ /* ...timestamp input buffer */ ++ src_buf->timestamp = ktime_get_ns(); ++ ++ /* ...unlock device access */ ++ spin_unlock_irqrestore(&imr->lock, flags); ++ ++ v4l2_dbg(1, debug, &imr->v4l2_dev, "rendering started: status=%X, DLSAR=0x%08X, DLPR=0x%08X\n", ioread32(imr->mmio + IMR_SR), ioread32(imr->mmio + IMR_DLSAR), ioread32(imr->mmio + IMR_DLSR)); ++} ++ ++/* ...check whether a job is ready for execution */ ++static int imr_job_ready(void *priv) ++{ ++ /* ...no specific requirements on the job readiness */ ++ return 1; ++} ++ ++/* ...abort currently processed job */ ++static void imr_job_abort(void *priv) ++{ ++ struct imr_ctx *ctx = priv; ++ struct imr_device *imr = ctx->imr; ++ unsigned long flags; ++ ++ /* ...protect access to internal device state */ ++ spin_lock_irqsave(&imr->lock, flags); ++ ++ /* ...make sure current job is still current (may get finished by interrupt already) */ ++ if (v4l2_m2m_get_curr_priv(imr->m2m_dev) == ctx) { ++ v4l2_dbg(1, debug, &imr->v4l2_dev, "abort job: status=%X, DLSAR=0x%08X, DLPR=0x%08X\n", ++ ioread32(imr->mmio + IMR_SR), ioread32(imr->mmio + IMR_DLSAR), ioread32(imr->mmio + IMR_DLSR)); ++ ++ /* ...force device reset to stop processing of the buffers */ ++ //iowrite32(IMR_CR_SWRST, imr->mmio + IMR_CR); ++ ++ /* ...resetting the module while operation is active may lead to hw-stall */ ++ spin_unlock_irqrestore(&imr->lock, flags); ++ ++ /* ...finish current job as interrupt will probably not occur */ ++ //v4l2_m2m_job_finish(imr->m2m_dev, ctx->m2m_ctx); ++ } else { ++ spin_unlock_irqrestore(&imr->lock, flags); ++ v4l2_dbg(1, debug, &imr->v4l2_dev, "job has completed already\n"); ++ } ++} ++ ++/* ...M2M interface definition */ ++static struct v4l2_m2m_ops imr_m2m_ops = { ++ .device_run = imr_device_run, ++ .job_ready = imr_job_ready, ++ .job_abort = imr_job_abort, ++}; ++ ++/******************************************************************************* ++ * Interrupt handling ++ ******************************************************************************/ ++ ++static irqreturn_t imr_irq_handler(int irq, void *data) ++{ ++ struct imr_device *imr = data; ++ struct imr_ctx *ctx; ++ struct vb2_v4l2_buffer *src_buf, *dst_buf; ++ u32 status; ++ irqreturn_t ret = IRQ_NONE; ++ ++ /* ...check and ack interrupt status */ ++ status = ioread32(imr->mmio + IMR_SR); ++ iowrite32(status, imr->mmio + IMR_SRCR); ++ if (!(status & (IMR_SR_INT | IMR_SR_IER | IMR_SR_TRA))) { ++ v4l2_err(&imr->v4l2_dev, "spurious interrupt: %x\n", status); ++ return ret; ++ } ++ ++ /* ...protect access to current context */ ++ spin_lock(&imr->lock); ++ ++ /* ...get current job context (may have been cancelled already) */ ++ ctx = v4l2_m2m_get_curr_priv(imr->m2m_dev); ++ if (!ctx) { ++ v4l2_dbg(3, debug, &imr->v4l2_dev, "no active job\n"); ++ goto handled; ++ } ++ ++ /* ...remove buffers (may have been removed already?) */ ++ src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); ++ dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); ++ if (!src_buf || !dst_buf) { ++ v4l2_dbg(3, debug, &imr->v4l2_dev, "no buffers associated with current context\n"); ++ goto handled; ++ } ++ ++ /* ...check for a TRAP interrupt indicating completion of current DL */ ++ if (status & IMR_SR_TRA) { ++ /* ...operation completed normally; timestamp output buffer */ ++ dst_buf->vb2_buf.timestamp = ktime_get_ns(); ++ if (src_buf->flags & V4L2_BUF_FLAG_TIMECODE) ++ dst_buf->timecode = src_buf->timecode; ++ dst_buf->flags = src_buf->flags & (V4L2_BUF_FLAG_TIMECODE | V4L2_BUF_FLAG_KEYFRAME | ++ V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | V4L2_BUF_FLAG_TSTAMP_SRC_MASK); ++ dst_buf->sequence = src_buf->sequence = ctx->sequence++; ++ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); ++ v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); ++ ++ v4l2_dbg(3, debug, &imr->v4l2_dev, "buffers <0x%08x,0x%08x> done\n", ++ (u32)vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0), ++ (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0)); ++ } else { ++ /* ...operation completed in error; no way to understand what exactly went wrong */ ++ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); ++ v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR); ++ ++ v4l2_dbg(3, debug, &imr->v4l2_dev, "buffers <0x%08x,0x%08x> done in error\n", ++ (u32)vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0), ++ (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0)); ++ } ++ ++ spin_unlock(&imr->lock); ++ ++ /* ...finish current job (and start any pending) */ ++ v4l2_m2m_job_finish(imr->m2m_dev, ctx->m2m_ctx); ++ ++ return IRQ_HANDLED; ++ ++handled: ++ /* ...again, what exactly is to be protected? */ ++ spin_unlock(&imr->lock); ++ ++ return IRQ_HANDLED; ++} ++ ++/******************************************************************************* ++ * Device probing / removal interface ++ ******************************************************************************/ ++ ++static int imr_probe(struct platform_device *pdev) ++{ ++ struct imr_device *imr; ++ struct resource *res; ++ int ret; ++ ++ imr = devm_kzalloc(&pdev->dev, sizeof(*imr), GFP_KERNEL); ++ if (!imr) ++ return -ENOMEM; ++ ++ mutex_init(&imr->mutex); ++ spin_lock_init(&imr->lock); ++ imr->dev = &pdev->dev; ++ ++ /* ...memory-mapped registers */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "cannot get memory region\n"); ++ return -EINVAL; ++ } ++ ++ imr->mmio = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(imr->mmio)) ++ return PTR_ERR(imr->mmio); ++ ++ /* ...interrupt service routine registration */ ++ imr->irq = ret = platform_get_irq(pdev, 0); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "cannot find IRQ\n"); ++ return ret; ++ } ++ ++ ret = devm_request_irq(&pdev->dev, imr->irq, imr_irq_handler, 0, dev_name(&pdev->dev), imr); ++ if (ret) { ++ dev_err(&pdev->dev, "cannot claim IRQ %d\n", imr->irq); ++ return ret; ++ } ++ ++ imr->clock = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(imr->clock)) { ++ dev_err(&pdev->dev, "cannot get clock\n"); ++ return PTR_ERR(imr->clock); ++ } ++ ++ /* ...create v4l2 device */ ++ ret = v4l2_device_register(&pdev->dev, &imr->v4l2_dev); ++ if (ret) { ++ dev_err(&pdev->dev, "Failed to register v4l2 device\n"); ++ return ret; ++ } ++ ++ /* ...create mem2mem device handle */ ++ imr->m2m_dev = v4l2_m2m_init(&imr_m2m_ops); ++ if (IS_ERR(imr->m2m_dev)) { ++ v4l2_err(&imr->v4l2_dev, "Failed to init mem2mem device\n"); ++ ret = PTR_ERR(imr->m2m_dev); ++ goto device_register_rollback; ++ } ++ ++ strlcpy(imr->video_dev.name, dev_name(&pdev->dev), sizeof(imr->video_dev.name)); ++ imr->video_dev.fops = &imr_fops; ++ imr->video_dev.ioctl_ops = &imr_ioctl_ops; ++ imr->video_dev.minor = -1; ++ imr->video_dev.release = video_device_release_empty; ++ imr->video_dev.lock = &imr->mutex; ++ imr->video_dev.v4l2_dev = &imr->v4l2_dev; ++ imr->video_dev.vfl_dir = VFL_DIR_M2M; ++ ++ ret = video_register_device(&imr->video_dev, VFL_TYPE_GRABBER, -1); ++ if (ret) { ++ v4l2_err(&imr->v4l2_dev, "Failed to register video device\n"); ++ goto m2m_init_rollback; ++ } ++ ++ video_set_drvdata(&imr->video_dev, imr); ++ platform_set_drvdata(pdev, imr); ++ //pm_runtime_enable(&pdev->dev); ++ ++ v4l2_info(&imr->v4l2_dev, "IMR device (pdev: %d) registered as /dev/video%d\n", pdev->id, imr->video_dev.num); ++ ++ return 0; ++ ++m2m_init_rollback: ++ v4l2_m2m_release(imr->m2m_dev); ++ ++device_register_rollback: ++ v4l2_device_unregister(&imr->v4l2_dev); ++ ++ return ret; ++} ++ ++static int imr_remove(struct platform_device *pdev) ++{ ++ struct imr_device *imr = platform_get_drvdata(pdev); ++ ++ //pm_runtime_disable(imr->v4l2_dev.dev); ++ video_unregister_device(&imr->video_dev); ++ v4l2_m2m_release(imr->m2m_dev); ++ v4l2_device_unregister(&imr->v4l2_dev); ++ ++ return 0; ++} ++ ++/******************************************************************************* ++ * Power management ++ ******************************************************************************/ ++ ++#ifdef CONFIG_PM_SLEEP ++ ++/* ...device suspend hook; clock control only - tbd */ ++static int imr_pm_suspend(struct device *dev) ++{ ++ struct imr_device *imr = dev_get_drvdata(dev); ++ ++ WARN_ON(mutex_is_locked(&imr->mutex)); ++ ++ if (imr->refcount == 0) ++ return 0; ++ ++ clk_disable_unprepare(imr->clock); ++ ++ return 0; ++} ++ ++/* ...device resume hook; clock control only */ ++static int imr_pm_resume(struct device *dev) ++{ ++ struct imr_device *imr = dev_get_drvdata(dev); ++ ++ WARN_ON(mutex_is_locked(&imr->mutex)); ++ ++ if (imr->refcount == 0) ++ return 0; ++ ++ clk_prepare_enable(imr->clock); ++ ++ return 0; ++} ++ ++#endif /* CONFIG_PM_SLEEP */ ++ ++/* ...power management callbacks */ ++static const struct dev_pm_ops imr_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(imr_pm_suspend, imr_pm_resume) ++}; ++ ++/* ...device table */ ++static const struct of_device_id imr_of_match[] = { ++ { .compatible = "renesas,imr-lx4" }, ++ { }, ++}; ++ ++/* ...platform driver interface */ ++static struct platform_driver imr_platform_driver = { ++ .probe = imr_probe, ++ .remove = imr_remove, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "imr", ++ .pm = &imr_pm_ops, ++ .of_match_table = imr_of_match, ++ }, ++}; ++ ++module_platform_driver(imr_platform_driver); ++ ++MODULE_ALIAS("imr"); ++MODULE_AUTHOR("Cogent Embedded Inc. "); ++MODULE_DESCRIPTION("Renesas IMR-LX4 Driver"); ++MODULE_LICENSE("GPL"); +diff --git a/include/uapi/linux/rcar-imr.h b/include/uapi/linux/rcar-imr.h +new file mode 100644 +index 0000000..d02082f +--- /dev/null ++++ b/include/uapi/linux/rcar-imr.h +@@ -0,0 +1,98 @@ ++/* ++ * imr.h -- R-Car IMR-LX4 Driver UAPI ++ * ++ * Copyright (C) 2016 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++#ifndef RCAR_IMR_USER_H ++#define RCAR_IMR_USER_H ++ ++#include ++ ++/******************************************************************************* ++ * Mapping specification descriptor ++ ******************************************************************************/ ++ ++struct imr_map_desc { ++ /* ...mapping types */ ++ u32 type; ++ ++ /* ...total size of the mesh structure */ ++ u32 size; ++ ++ /* ...map-specific user-pointer */ ++ void *data; ++ ++} __attribute__((packed)); ++ ++/* ...regular mesh specification */ ++#define IMR_MAP_MESH (1 << 0) ++ ++/* ...auto-generated source coordinates */ ++#define IMR_MAP_AUTODG (1 << 1) ++ ++/* ...auto-generated destination coordinates */ ++#define IMR_MAP_AUTOSG (1 << 2) ++ ++/* ...luminance correction flag */ ++#define IMR_MAP_LUCE (1 << 3) ++ ++/* ...chromacity correction flag */ ++#define IMR_MAP_CLCE (1 << 4) ++ ++/* ...vertex clockwise-mode order */ ++#define IMR_MAP_TCM (1 << 5) ++ ++/* ...source coordinate decimal point position bit index */ ++#define __IMR_MAP_UVDPOR_SHIFT 8 ++#define __IMR_MAP_UVDPOR(v) (((v) >> __IMR_MAP_UVDPOR_SHIFT) & 0x7) ++#define IMR_MAP_UVDPOR(n) ((n & 0x7) << __IMR_MAP_UVDPOR_SHIFT) ++ ++/* ...destination coordinate sub-pixel mode */ ++#define IMR_MAP_DDP (1 << 11) ++ ++/* ...luminance correction offset decimal point position */ ++#define __IMR_MAP_YLDPO_SHIFT 12 ++#define __IMR_MAP_YLDPO(v) (((v) >> __IMR_MAP_YLDPO_SHIFT) & 0x7) ++#define IMR_MAP_YLDPO(n) ((n & 0x7) << __IMR_MAP_YLDPO_SHIFT) ++ ++/* ...chromacity (U) correction offset decimal point position */ ++#define __IMR_MAP_UBDPO_SHIFT 15 ++#define __IMR_MAP_UBDPO(v) (((v) >> __IMR_MAP_UBDPO_SHIFT) & 0x7) ++#define IMR_MAP_UBDPO(n) ((n & 0x7) << __IMR_MAP_UBDPO_SHIFT) ++ ++/* ...chromacity (V) correction offset decimal point position */ ++#define __IMR_MAP_VRDPO_SHIFT 18 ++#define __IMR_MAP_VRDPO(v) (((v) >> __IMR_MAP_VRDPO_SHIFT) & 0x7) ++#define IMR_MAP_VRDPO(n) ((n & 0x7) << __IMR_MAP_VRDPO_SHIFT) ++ ++/* ...regular mesh specification */ ++struct imr_mesh { ++ /* ...rectangular mesh size */ ++ u16 rows, columns; ++ ++ /* ...mesh parameters */ ++ u16 x0, y0, dx, dy; ++ ++} __attribute__((packed)); ++ ++/* ...VBO descriptor */ ++struct imr_vbo { ++ /* ...number of triangles */ ++ u16 num; ++ ++} __attribute__((packed)); ++ ++ ++/******************************************************************************* ++ * Private IOCTL codes ++ ******************************************************************************/ ++ ++#define VIDIOC_IMR_MESH _IOW('V', BASE_VIDIOC_PRIVATE + 0, struct imr_map_desc) ++ ++#endif /* RCAR_IMR_USER_H */ +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0014-lib-swiotlb-reduce-verbosity.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0014-lib-swiotlb-reduce-verbosity.patch new file mode 100644 index 00000000..6cb5f65c --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0014-lib-swiotlb-reduce-verbosity.patch @@ -0,0 +1,40 @@ +From f52105d57c1ec04f8dac9b403232d8b1965a02ca Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Thu, 26 Jan 2017 16:37:50 +0300 +Subject: [PATCH] lib: swiotlb: reduce verbosity + +Signed-off-by: Nikita Yushchenko +Signed-off-by: Vladimir Barinov +--- + lib/swiotlb.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/lib/swiotlb.c b/lib/swiotlb.c +index 771234d..b395abc 100644 +--- a/lib/swiotlb.c ++++ b/lib/swiotlb.c +@@ -513,8 +513,10 @@ phys_addr_t swiotlb_tbl_map_single(struct device *hwdev, + + not_found: + spin_unlock_irqrestore(&io_tlb_lock, flags); ++#if 0 + if (printk_ratelimit()) + dev_warn(hwdev, "swiotlb buffer is full (sz: %zd bytes)\n", size); ++#endif + return SWIOTLB_MAP_ERROR; + found: + spin_unlock_irqrestore(&io_tlb_lock, flags); +@@ -714,8 +714,10 @@ swiotlb_full(struct device *dev, size_t size, enum dma_data_direction dir, + * When the mapping is small enough return a static buffer to limit + * the damage, or panic when the transfer is too big. + */ ++#if 0 + dev_err_ratelimited(dev, "DMA: Out of SW-IOMMU space for %zu bytes\n", + size); ++#endif + + if (size <= io_tlb_overflow || !do_panic) + return; +-- +1.9.1 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0015-gpio-max732x-fix-gpio-set.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0015-gpio-max732x-fix-gpio-set.patch new file mode 100644 index 00000000..e40c9292 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0015-gpio-max732x-fix-gpio-set.patch @@ -0,0 +1,29 @@ +From d3dd821694e6e2a99089bb4916ba4013de54c503 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Tue, 11 Apr 2017 20:12:56 +0300 +Subject: [PATCH 011/122] gpio: max732x: fix gpio set + +gpio set value/direction must 0 or 1, but +gpiolib sets it to not binary values + +Signed-off-by: Vladimir Barinov +--- + drivers/gpio/gpio-max732x.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c +index 7f4d26c..a8ccf56 100644 +--- a/drivers/gpio/gpio-max732x.c ++++ b/drivers/gpio/gpio-max732x.c +@@ -237,7 +237,7 @@ static void max732x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) + unsigned base = off & ~0x7; + uint8_t mask = 1u << (off & 0x7); + +- max732x_gpio_set_mask(gc, base, mask, val << (off & 0x7)); ++ max732x_gpio_set_mask(gc, base, mask, (!!val) << (off & 0x7)); + } + + static void max732x_gpio_set_multiple(struct gpio_chip *gc, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0016-gpio-gpiolib-suppress-gpiod-warning.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0016-gpio-gpiolib-suppress-gpiod-warning.patch new file mode 100644 index 00000000..da491501 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0016-gpio-gpiolib-suppress-gpiod-warning.patch @@ -0,0 +1,29 @@ +From 365985d00dadb9231ad51d9a518d99e2120dc525 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Thu, 13 Apr 2017 12:18:18 +0300 +Subject: [PATCH 012/122] gpio: gpiolib: suppress gpiod warning + +Suppress warning about use gpiod instead gpio deprecated callbacks + +Signed-off-by: Vladimir Barinov +--- + drivers/gpio/gpiolib.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c +index d4226e4..7c16e76 100644 +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -2670,7 +2670,9 @@ void gpiod_set_raw_value(struct gpio_desc *desc, int value) + { + VALIDATE_DESC_VOID(desc); + /* Should be using gpiod_set_value_cansleep() */ ++#if 0 + WARN_ON(desc->gdev->chip->can_sleep); ++#endif + _gpiod_set_raw_value(desc, value); + } + EXPORT_SYMBOL_GPL(gpiod_set_raw_value); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0017-media-soc_camera-add-legacy-VIN-CSI2.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0017-media-soc_camera-add-legacy-VIN-CSI2.patch new file mode 100644 index 00000000..69ee2ee3 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0017-media-soc_camera-add-legacy-VIN-CSI2.patch @@ -0,0 +1,5162 @@ +From 36b7bfbe6c0c45fdbb201f7a79899c7bd934fb17 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Sun, 14 May 2017 13:43:24 +0300 +Subject: [PATCH 013/122] media: soc_camera: add legacy VIN/CSI2 + +Add legacy/old R-CAR VIN/CSI2 drivers + +Signed-off-by: Vladimir Barinov +--- + arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi | 133 - + arch/arm64/boot/dts/renesas/r8a7795.dtsi | 271 -- + arch/arm64/boot/dts/renesas/r8a7796.dtsi | 259 -- + arch/arm64/boot/dts/renesas/r8a77965.dtsi | 258 -- + arch/arm64/boot/dts/renesas/salvator-common.dtsi | 33 - + drivers/media/platform/soc_camera/Kconfig | 28 + + drivers/media/platform/soc_camera/Makefile | 2 + + drivers/media/platform/soc_camera/rcar_csi2.c | 708 +++++ + drivers/media/platform/soc_camera/rcar_vin.c | 3071 ++++++++++++++++++++++ + include/media/rcar_csi2.h | 66 + + 10 files changed, 3875 insertions(+), 954 deletions(-) + create mode 100644 drivers/media/platform/soc_camera/rcar_csi2.c + create mode 100644 drivers/media/platform/soc_camera/rcar_vin.c + create mode 100644 include/media/rcar_csi2.h + +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi b/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi +index 81e7625..a8c976e 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi +@@ -201,51 +201,6 @@ + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + resets = <&cpg 713>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- csi21vin0: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&vin0csi21>; +- }; +- csi21vin1: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&vin1csi21>; +- }; +- csi21vin2: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&vin2csi21>; +- }; +- csi21vin3: endpoint@3 { +- reg = <3>; +- remote-endpoint = <&vin3csi21>; +- }; +- csi21vin4: endpoint@4 { +- reg = <4>; +- remote-endpoint = <&vin4csi21>; +- }; +- csi21vin5: endpoint@5 { +- reg = <5>; +- remote-endpoint = <&vin5csi21>; +- }; +- csi21vin6: endpoint@6 { +- reg = <6>; +- remote-endpoint = <&vin6csi21>; +- }; +- csi21vin7: endpoint@7 { +- reg = <7>; +- remote-endpoint = <&vin7csi21>; +- }; +- }; +- }; + }; + }; + +@@ -284,91 +239,3 @@ + &du { + vsps = <&vspd0 &vspd1 &vspd2 &vspd3>; + }; +- +-&vin0 { +- ports { +- port@1 { +- vin0csi21: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&csi21vin0>; +- }; +- }; +- }; +-}; +- +-&vin1 { +- ports { +- port@1 { +- vin1csi21: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&csi21vin1>; +- }; +- }; +- }; +-}; +- +-&vin2 { +- ports { +- port@1 { +- vin2csi21: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&csi21vin2>; +- }; +- }; +- }; +-}; +- +-&vin3 { +- ports { +- port@1 { +- vin3csi21: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&csi21vin3>; +- }; +- }; +- }; +-}; +- +-&vin4 { +- ports { +- port@1 { +- vin4csi21: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&csi21vin4>; +- }; +- }; +- }; +-}; +- +-&vin5 { +- ports { +- port@1 { +- vin5csi21: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&csi21vin5>; +- }; +- }; +- }; +-}; +- +-&vin6 { +- ports { +- port@1 { +- vin6csi21: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&csi21vin6>; +- }; +- }; +- }; +-}; +- +-&vin7 { +- ports { +- port@1 { +- vin7csi21: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&csi21vin7>; +- }; +- }; +- }; +-}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi +index 8c5b5fe..f15d587 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi +@@ -1943,27 +1943,6 @@ + resets = <&cpg 811>; + renesas,id = <0>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin0csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&csi20vin0>; +- }; +- vin0csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&csi40vin0>; +- }; +- }; +- }; + }; + + vin1: video@e6ef1000 { +@@ -1975,27 +1954,6 @@ + resets = <&cpg 810>; + renesas,id = <1>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin1csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&csi20vin1>; +- }; +- vin1csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&csi40vin1>; +- }; +- }; +- }; + }; + + vin2: video@e6ef2000 { +@@ -2007,27 +1965,6 @@ + resets = <&cpg 809>; + renesas,id = <2>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin2csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&csi20vin2>; +- }; +- vin2csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&csi40vin2>; +- }; +- }; +- }; + }; + + vin3: video@e6ef3000 { +@@ -2039,27 +1976,6 @@ + resets = <&cpg 808>; + renesas,id = <3>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin3csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&csi20vin3>; +- }; +- vin3csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&csi40vin3>; +- }; +- }; +- }; + }; + + vin4: video@e6ef4000 { +@@ -2071,27 +1987,6 @@ + resets = <&cpg 807>; + renesas,id = <4>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin4csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&csi20vin4>; +- }; +- vin4csi41: endpoint@3 { +- reg = <3>; +- remote-endpoint = <&csi41vin4>; +- }; +- }; +- }; + }; + + vin5: video@e6ef5000 { +@@ -2103,27 +1998,6 @@ + resets = <&cpg 806>; + renesas,id = <5>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin5csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&csi20vin5>; +- }; +- vin5csi41: endpoint@3 { +- reg = <3>; +- remote-endpoint = <&csi41vin5>; +- }; +- }; +- }; + }; + + vin6: video@e6ef6000 { +@@ -2135,27 +2009,6 @@ + resets = <&cpg 805>; + renesas,id = <6>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin6csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&csi20vin6>; +- }; +- vin6csi41: endpoint@3 { +- reg = <3>; +- remote-endpoint = <&csi41vin6>; +- }; +- }; +- }; + }; + + vin7: video@e6ef7000 { +@@ -2167,27 +2020,6 @@ + resets = <&cpg 804>; + renesas,id = <7>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin7csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&csi20vin7>; +- }; +- vin7csi41: endpoint@3 { +- reg = <3>; +- remote-endpoint = <&csi41vin7>; +- }; +- }; +- }; + }; + + drif00: rif@e6f40000 { +@@ -3258,51 +3090,6 @@ + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + resets = <&cpg 714>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- csi20vin0: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&vin0csi20>; +- }; +- csi20vin1: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&vin1csi20>; +- }; +- csi20vin2: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&vin2csi20>; +- }; +- csi20vin3: endpoint@3 { +- reg = <3>; +- remote-endpoint = <&vin3csi20>; +- }; +- csi20vin4: endpoint@4 { +- reg = <4>; +- remote-endpoint = <&vin4csi20>; +- }; +- csi20vin5: endpoint@5 { +- reg = <5>; +- remote-endpoint = <&vin5csi20>; +- }; +- csi20vin6: endpoint@6 { +- reg = <6>; +- remote-endpoint = <&vin6csi20>; +- }; +- csi20vin7: endpoint@7 { +- reg = <7>; +- remote-endpoint = <&vin7csi20>; +- }; +- }; +- }; + }; + + csi40: csi2@feaa0000 { +@@ -3313,35 +3100,6 @@ + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + resets = <&cpg 716>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- csi40vin0: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&vin0csi40>; +- }; +- csi40vin1: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&vin1csi40>; +- }; +- csi40vin2: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&vin2csi40>; +- }; +- csi40vin3: endpoint@3 { +- reg = <3>; +- remote-endpoint = <&vin3csi40>; +- }; +- }; +- }; + }; + + csi41: csi2@feab0000 { +@@ -3352,35 +3110,6 @@ + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + resets = <&cpg 715>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- csi41vin4: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&vin4csi41>; +- }; +- csi41vin5: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&vin5csi41>; +- }; +- csi41vin6: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&vin6csi41>; +- }; +- csi41vin7: endpoint@3 { +- reg = <3>; +- remote-endpoint = <&vin7csi41>; +- }; +- }; +- }; + }; + + hdmi0: hdmi@fead0000 { +diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi +index 19f2199..00433dc 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7796.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi +@@ -1849,27 +1849,6 @@ + resets = <&cpg 811>; + renesas,id = <0>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin0csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&csi20vin0>; +- }; +- vin0csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&csi40vin0>; +- }; +- }; +- }; + }; + + vin1: video@e6ef1000 { +@@ -1881,27 +1860,6 @@ + resets = <&cpg 810>; + renesas,id = <1>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin1csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&csi20vin1>; +- }; +- vin1csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&csi40vin1>; +- }; +- }; +- }; + }; + + vin2: video@e6ef2000 { +@@ -1913,27 +1871,6 @@ + resets = <&cpg 809>; + renesas,id = <2>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin2csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&csi20vin2>; +- }; +- vin2csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&csi40vin2>; +- }; +- }; +- }; + }; + + vin3: video@e6ef3000 { +@@ -1945,27 +1882,6 @@ + resets = <&cpg 808>; + renesas,id = <3>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin3csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&csi20vin3>; +- }; +- vin3csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&csi40vin3>; +- }; +- }; +- }; + }; + + vin4: video@e6ef4000 { +@@ -1977,27 +1893,6 @@ + resets = <&cpg 807>; + renesas,id = <4>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin4csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&csi20vin4>; +- }; +- vin4csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&csi40vin4>; +- }; +- }; +- }; + }; + + vin5: video@e6ef5000 { +@@ -2009,27 +1904,6 @@ + resets = <&cpg 806>; + renesas,id = <5>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin5csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&csi20vin5>; +- }; +- vin5csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&csi40vin5>; +- }; +- }; +- }; + }; + + vin6: video@e6ef6000 { +@@ -2041,27 +1915,6 @@ + resets = <&cpg 805>; + renesas,id = <6>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin6csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&csi20vin6>; +- }; +- vin6csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&csi40vin6>; +- }; +- }; +- }; + }; + + vin7: video@e6ef7000 { +@@ -2073,27 +1926,6 @@ + resets = <&cpg 804>; + renesas,id = <7>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin7csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&csi20vin7>; +- }; +- vin7csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&csi40vin7>; +- }; +- }; +- }; + }; + + drif00: rif@e6f40000 { +@@ -2989,51 +2821,6 @@ + power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; + resets = <&cpg 714>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- csi20vin0: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&vin0csi20>; +- }; +- csi20vin1: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&vin1csi20>; +- }; +- csi20vin2: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&vin2csi20>; +- }; +- csi20vin3: endpoint@3 { +- reg = <3>; +- remote-endpoint = <&vin3csi20>; +- }; +- csi20vin4: endpoint@4 { +- reg = <4>; +- remote-endpoint = <&vin4csi20>; +- }; +- csi20vin5: endpoint@5 { +- reg = <5>; +- remote-endpoint = <&vin5csi20>; +- }; +- csi20vin6: endpoint@6 { +- reg = <6>; +- remote-endpoint = <&vin6csi20>; +- }; +- csi20vin7: endpoint@7 { +- reg = <7>; +- remote-endpoint = <&vin7csi20>; +- }; +- }; +- }; + }; + + csi40: csi2@feaa0000 { +@@ -3044,52 +2831,6 @@ + power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; + resets = <&cpg 716>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- csi40vin0: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&vin0csi40>; +- }; +- csi40vin1: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&vin1csi40>; +- }; +- csi40vin2: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&vin2csi40>; +- }; +- csi40vin3: endpoint@3 { +- reg = <3>; +- remote-endpoint = <&vin3csi40>; +- }; +- csi40vin4: endpoint@4 { +- reg = <4>; +- remote-endpoint = <&vin4csi40>; +- }; +- csi40vin5: endpoint@5 { +- reg = <5>; +- remote-endpoint = <&vin5csi40>; +- }; +- csi40vin6: endpoint@6 { +- reg = <6>; +- remote-endpoint = <&vin6csi40>; +- }; +- csi40vin7: endpoint@7 { +- reg = <7>; +- remote-endpoint = <&vin7csi40>; +- }; +- }; +- +- }; + }; + + hdmi0: hdmi@fead0000 { +diff --git a/arch/arm64/boot/dts/renesas/r8a77965.dtsi b/arch/arm64/boot/dts/renesas/r8a77965.dtsi +index a58fba8..e682d10 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77965.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77965.dtsi +@@ -1263,27 +1263,6 @@ + resets = <&cpg 811>; + renesas,id = <0>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin0csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&csi20vin0>; +- }; +- vin0csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&csi40vin0>; +- }; +- }; +- }; + }; + + vin1: video@e6ef1000 { +@@ -1295,27 +1274,6 @@ + resets = <&cpg 810>; + renesas,id = <1>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin1csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&csi20vin1>; +- }; +- vin1csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&csi40vin1>; +- }; +- }; +- }; + }; + + vin2: video@e6ef2000 { +@@ -1327,27 +1285,6 @@ + resets = <&cpg 809>; + renesas,id = <2>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin2csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&csi20vin2>; +- }; +- vin2csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&csi40vin2>; +- }; +- }; +- }; + }; + + vin3: video@e6ef3000 { +@@ -1359,27 +1296,6 @@ + resets = <&cpg 808>; + renesas,id = <3>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin3csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&csi20vin3>; +- }; +- vin3csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&csi40vin3>; +- }; +- }; +- }; + }; + + vin4: video@e6ef4000 { +@@ -1391,27 +1307,6 @@ + resets = <&cpg 807>; + renesas,id = <4>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin4csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&csi20vin4>; +- }; +- vin4csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&csi40vin4>; +- }; +- }; +- }; + }; + + vin5: video@e6ef5000 { +@@ -1423,27 +1318,6 @@ + resets = <&cpg 806>; + renesas,id = <5>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin5csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&csi20vin5>; +- }; +- vin5csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&csi40vin5>; +- }; +- }; +- }; + }; + + vin6: video@e6ef6000 { +@@ -1455,27 +1329,6 @@ + resets = <&cpg 805>; + renesas,id = <6>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin6csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&csi20vin6>; +- }; +- vin6csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&csi40vin6>; +- }; +- }; +- }; + }; + + vin7: video@e6ef7000 { +@@ -1487,27 +1340,6 @@ + resets = <&cpg 804>; + renesas,id = <7>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin7csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&csi20vin7>; +- }; +- vin7csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&csi40vin7>; +- }; +- }; +- }; + }; + + rcar_sound: sound@ec500000 { +@@ -2230,51 +2062,6 @@ + power-domains = <&sysc R8A77965_PD_ALWAYS_ON>; + resets = <&cpg 714>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- csi20vin0: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&vin0csi20>; +- }; +- csi20vin1: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&vin1csi20>; +- }; +- csi20vin2: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&vin2csi20>; +- }; +- csi20vin3: endpoint@3 { +- reg = <3>; +- remote-endpoint = <&vin3csi20>; +- }; +- csi20vin4: endpoint@4 { +- reg = <4>; +- remote-endpoint = <&vin4csi20>; +- }; +- csi20vin5: endpoint@5 { +- reg = <5>; +- remote-endpoint = <&vin5csi20>; +- }; +- csi20vin6: endpoint@6 { +- reg = <6>; +- remote-endpoint = <&vin6csi20>; +- }; +- csi20vin7: endpoint@7 { +- reg = <7>; +- remote-endpoint = <&vin7csi20>; +- }; +- }; +- }; + }; + + csi40: csi2@feaa0000 { +@@ -2285,51 +2072,6 @@ + power-domains = <&sysc R8A77965_PD_ALWAYS_ON>; + resets = <&cpg 716>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- csi40vin0: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&vin0csi40>; +- }; +- csi40vin1: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&vin1csi40>; +- }; +- csi40vin2: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&vin2csi40>; +- }; +- csi40vin3: endpoint@3 { +- reg = <3>; +- remote-endpoint = <&vin3csi40>; +- }; +- csi40vin4: endpoint@4 { +- reg = <4>; +- remote-endpoint = <&vin4csi40>; +- }; +- csi40vin5: endpoint@5 { +- reg = <5>; +- remote-endpoint = <&vin5csi40>; +- }; +- csi40vin6: endpoint@6 { +- reg = <6>; +- remote-endpoint = <&vin6csi40>; +- }; +- csi40vin7: endpoint@7 { +- reg = <7>; +- remote-endpoint = <&vin7csi40>; +- }; +- }; +- }; + }; + + hdmi0: hdmi@fead0000 { +diff --git a/arch/arm64/boot/dts/renesas/salvator-common.dtsi b/arch/arm64/boot/dts/renesas/salvator-common.dtsi +index 1b191af..788d38f 100644 +--- a/arch/arm64/boot/dts/renesas/salvator-common.dtsi ++++ b/arch/arm64/boot/dts/renesas/salvator-common.dtsi +@@ -341,37 +341,6 @@ + }; + }; + +-&csi20 { +- status = "okay"; +- +- ports { +- port@0 { +- reg = <0>; +- csi20_in: endpoint { +- clock-lanes = <0>; +- data-lanes = <1>; +- remote-endpoint = <&adv7482_txb>; +- }; +- }; +- }; +-}; +- +-&csi40 { +- status = "okay"; +- +- ports { +- port@0 { +- reg = <0>; +- +- csi40_in: endpoint { +- clock-lanes = <0>; +- data-lanes = <1 2 3 4>; +- remote-endpoint = <&adv7482_txa>; +- }; +- }; +- }; +-}; +- + &du { + pinctrl-0 = <&du_pins>; + pinctrl-names = "default"; +@@ -531,7 +500,6 @@ + adv7482_txa: endpoint { + clock-lanes = <0>; + data-lanes = <1 2 3 4>; +- remote-endpoint = <&csi40_in>; + }; + }; + +@@ -541,7 +509,6 @@ + adv7482_txb: endpoint { + clock-lanes = <0>; + data-lanes = <1>; +- remote-endpoint = <&csi20_in>; + }; + }; + }; +diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig +index f5979c1..a3bf60d 100644 +--- a/drivers/media/platform/soc_camera/Kconfig ++++ b/drivers/media/platform/soc_camera/Kconfig +@@ -16,6 +16,34 @@ config SOC_CAMERA_PLATFORM + help + This is a generic SoC camera platform driver, useful for testing + ++config VIDEO_RCAR_VIN_LEGACY ++ tristate "R-Car Video Input (VIN) support" ++ depends on VIDEO_DEV && SOC_CAMERA ++ depends on ARCH_RENESAS || COMPILE_TEST ++ depends on HAS_DMA ++ select VIDEOBUF2_DMA_CONTIG ++ select SOC_CAMERA_SCALE_CROP ++ select V4L2_FWNODE ++ ---help--- ++ This is a v4l2 driver for the R-Car VIN Interface ++ ++config VIDEO_RCAR_VIN_LEGACY_DEBUG ++ bool "Renesas VIN overflow debug messages" ++ depends on VIDEO_RCAR_VIN_LEGACY ++ ---help--- ++ Enable debug overflow messages on R-Car Video ++ Input driver. ++ If you set to enable, When an overflow occurred, ++ a debug overflow message is output. ++ ++config VIDEO_RCAR_CSI2_LEGACY ++ tristate "R-Car MIPI CSI-2 Interface driver" ++ depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK ++ depends on ARCH_R8A7795 || ARCH_R8A7796 || COMPILE_TEST ++ select V4L2_FWNODE ++ ---help--- ++ This is a v4l2 driver for the R-Car CSI-2 Interface ++ + config VIDEO_SH_MOBILE_CEU + tristate "SuperH Mobile CEU Interface driver" + depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA && HAVE_CLK +diff --git a/drivers/media/platform/soc_camera/Makefile b/drivers/media/platform/soc_camera/Makefile +index 07a451e..1a70361 100644 +--- a/drivers/media/platform/soc_camera/Makefile ++++ b/drivers/media/platform/soc_camera/Makefile +@@ -7,3 +7,5 @@ obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o + + # soc-camera host drivers have to be linked after camera drivers + obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o ++obj-$(CONFIG_VIDEO_RCAR_CSI2_LEGACY) += rcar_csi2.o ++obj-$(CONFIG_VIDEO_RCAR_VIN_LEGACY) += rcar_vin.o +diff --git a/drivers/media/platform/soc_camera/rcar_csi2.c b/drivers/media/platform/soc_camera/rcar_csi2.c +new file mode 100644 +index 0000000..05f623468 +--- /dev/null ++++ b/drivers/media/platform/soc_camera/rcar_csi2.c +@@ -0,0 +1,708 @@ ++/* ++ * drivers/media/platform/soc_camera/rcar_csi2.c ++ * This file is the driver for the R-Car MIPI CSI-2 unit. ++ * ++ * Copyright (C) 2015-2016 Renesas Electronics Corporation ++ * ++ * This file is based on the drivers/media/platform/soc_camera/sh_mobile_csi2.c ++ * ++ * Driver for the SH-Mobile MIPI CSI-2 unit ++ * ++ * Copyright (C) 2010, Guennadi Liakhovetski ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define DRV_NAME "rcar_csi2" ++#define CONNECT_SLAVE_NAME "adv7482" ++#define VC_MAX_CHANNEL 4 ++ ++#define RCAR_CSI2_TREF 0x00 ++#define RCAR_CSI2_SRST 0x04 ++#define RCAR_CSI2_PHYCNT 0x08 ++#define RCAR_CSI2_CHKSUM 0x0C ++#define RCAR_CSI2_VCDT 0x10 ++ ++#define RCAR_CSI2_VCDT2 0x14 /* Channel Data Type Select */ ++#define RCAR_CSI2_FRDT 0x18 /* Frame Data Type Select */ ++#define RCAR_CSI2_FLD 0x1C /* Field Detection Control */ ++#define RCAR_CSI2_ASTBY 0x20 /* Automatic standby control */ ++#define RCAR_CSI2_LNGDT0 0x28 ++#define RCAR_CSI2_LNGDT1 0x2C ++#define RCAR_CSI2_INTEN 0x30 ++#define RCAR_CSI2_INTCLOSE 0x34 ++#define RCAR_CSI2_INTSTATE 0x38 ++#define RCAR_CSI2_INTERRSTATE 0x3C ++ ++#define RCAR_CSI2_SHPDAT 0x40 ++#define RCAR_CSI2_SHPCNT 0x44 ++ ++#define RCAR_CSI2_LINKCNT 0x48 ++#define RCAR_CSI2_LSWAP 0x4C ++#define RCAR_CSI2_PHTC 0x58 ++#define RCAR_CSI2_PHYPLL 0x68 ++ ++#define RCAR_CSI2_PHEERM 0x74 ++#define RCAR_CSI2_PHCLM 0x78 ++#define RCAR_CSI2_PHDLM 0x7C ++ ++#define RCAR_CSI2_PHYCNT_SHUTDOWNZ (1 << 17) ++#define RCAR_CSI2_PHYCNT_RSTZ (1 << 16) ++#define RCAR_CSI2_PHYCNT_ENABLECLK (1 << 4) ++#define RCAR_CSI2_PHYCNT_ENABLE_3 (1 << 3) ++#define RCAR_CSI2_PHYCNT_ENABLE_2 (1 << 2) ++#define RCAR_CSI2_PHYCNT_ENABLE_1 (1 << 1) ++#define RCAR_CSI2_PHYCNT_ENABLE_0 (1 << 0) ++ ++#define RCAR_CSI2_VCDT_VCDTN_EN (1 << 15) ++#define RCAR_CSI2_VCDT_SEL_VCN (1 << 8) ++#define RCAR_CSI2_VCDT_SEL_DTN_ON (1 << 6) ++#define RCAR_CSI2_VCDT_SEL_DTN (1 << 0) ++ ++#define RCAR_CSI2_LINKCNT_MONITOR_EN (1 << 31) ++#define RCAR_CSI2_LINKCNT_REG_MONI_PACT_EN (1 << 25) ++ ++#define RCAR_CSI2_LSWAP_L3SEL_PLANE0 (0 << 6) ++#define RCAR_CSI2_LSWAP_L3SEL_PLANE1 (1 << 6) ++#define RCAR_CSI2_LSWAP_L3SEL_PLANE2 (2 << 6) ++#define RCAR_CSI2_LSWAP_L3SEL_PLANE3 (3 << 6) ++ ++#define RCAR_CSI2_LSWAP_L2SEL_PLANE0 (0 << 4) ++#define RCAR_CSI2_LSWAP_L2SEL_PLANE1 (1 << 4) ++#define RCAR_CSI2_LSWAP_L2SEL_PLANE2 (2 << 4) ++#define RCAR_CSI2_LSWAP_L2SEL_PLANE3 (3 << 4) ++ ++#define RCAR_CSI2_LSWAP_L1SEL_PLANE0 (0 << 2) ++#define RCAR_CSI2_LSWAP_L1SEL_PLANE1 (1 << 2) ++#define RCAR_CSI2_LSWAP_L1SEL_PLANE2 (2 << 2) ++#define RCAR_CSI2_LSWAP_L1SEL_PLANE3 (3 << 2) ++ ++#define RCAR_CSI2_LSWAP_L0SEL_PLANE0 (0 << 0) ++#define RCAR_CSI2_LSWAP_L0SEL_PLANE1 (1 << 0) ++#define RCAR_CSI2_LSWAP_L0SEL_PLANE2 (2 << 0) ++#define RCAR_CSI2_LSWAP_L0SEL_PLANE3 (3 << 0) ++ ++#define RCAR_CSI2_PHTC_TESTCLR (1 << 0) ++ ++/* interrupt status registers */ ++#define RCAR_CSI2_INTSTATE_EBD_CH1 (1 << 29) ++#define RCAR_CSI2_INTSTATE_LESS_THAN_WC (1 << 28) ++#define RCAR_CSI2_INTSTATE_AFIFO_OF (1 << 27) ++#define RCAR_CSI2_INTSTATE_VD4_START (1 << 26) ++#define RCAR_CSI2_INTSTATE_VD4_END (1 << 25) ++#define RCAR_CSI2_INTSTATE_VD3_START (1 << 24) ++#define RCAR_CSI2_INTSTATE_VD3_END (1 << 23) ++#define RCAR_CSI2_INTSTATE_VD2_START (1 << 22) ++#define RCAR_CSI2_INTSTATE_VD2_END (1 << 21) ++#define RCAR_CSI2_INTSTATE_VD1_START (1 << 20) ++#define RCAR_CSI2_INTSTATE_VD1_END (1 << 19) ++#define RCAR_CSI2_INTSTATE_SHP (1 << 18) ++#define RCAR_CSI2_INTSTATE_FSFE (1 << 17) ++#define RCAR_CSI2_INTSTATE_LNP (1 << 16) ++#define RCAR_CSI2_INTSTATE_CRC_ERR (1 << 15) ++#define RCAR_CSI2_INTSTATE_HD_WC_ZERO (1 << 14) ++#define RCAR_CSI2_INTSTATE_FRM_SEQ_ERR1 (1 << 13) ++#define RCAR_CSI2_INTSTATE_FRM_SEQ_ERR2 (1 << 12) ++#define RCAR_CSI2_INTSTATE_ECC_ERR (1 << 11) ++#define RCAR_CSI2_INTSTATE_ECC_CRCT_ERR (1 << 10) ++#define RCAR_CSI2_INTSTATE_LPDT_START (1 << 9) ++#define RCAR_CSI2_INTSTATE_LPDT_END (1 << 8) ++#define RCAR_CSI2_INTSTATE_ULPS_START (1 << 7) ++#define RCAR_CSI2_INTSTATE_ULPS_END (1 << 6) ++#define RCAR_CSI2_INTSTATE_RESERVED (1 << 5) ++#define RCAR_CSI2_INTSTATE_ERRSOTHS (1 << 4) ++#define RCAR_CSI2_INTSTATE_ERRSOTSYNCCHS (1 << 3) ++#define RCAR_CSI2_INTSTATE_ERRESC (1 << 2) ++#define RCAR_CSI2_INTSTATE_ERRSYNCESC (1 << 1) ++#define RCAR_CSI2_INTSTATE_ERRCONTROL (1 << 0) ++ ++/* monitoring registers of interrupt error status */ ++#define RCAR_CSI2_INTSTATE_ECC_ERR (1 << 11) ++#define RCAR_CSI2_INTSTATE_ECC_CRCT_ERR (1 << 10) ++#define RCAR_CSI2_INTSTATE_LPDT_START (1 << 9) ++#define RCAR_CSI2_INTSTATE_LPDT_END (1 << 8) ++#define RCAR_CSI2_INTSTATE_ULPS_START (1 << 7) ++#define RCAR_CSI2_INTSTATE_ULPS_END (1 << 6) ++#define RCAR_CSI2_INTSTATE_RESERVED (1 << 5) ++#define RCAR_CSI2_INTSTATE_ERRSOTHS (1 << 4) ++#define RCAR_CSI2_INTSTATE_ERRSOTSYNCCHS (1 << 3) ++#define RCAR_CSI2_INTSTATE_ERRESC (1 << 2) ++#define RCAR_CSI2_INTSTATE_ERRSYNCESC (1 << 1) ++#define RCAR_CSI2_INTSTATE_ERRCONTROL (1 << 0) ++ ++enum chip_id { ++ RCAR_GEN3, ++ RCAR_GEN2, ++}; ++ ++enum decoder_input_interface { ++ DECODER_INPUT_INTERFACE_RGB888, ++ DECODER_INPUT_INTERFACE_YCBCR422, ++ DECODER_INPUT_INTERFACE_NONE, ++}; ++ ++/** ++ * struct rcar_csi2_link_config - Describes rcar_csi2 hardware configuration ++ * @input_colorspace: The input colorspace (RGB, YUV444, YUV422) ++ */ ++struct rcar_csi2_link_config { ++ enum decoder_input_interface input_interface; ++ unsigned char lanes; ++ unsigned long vcdt; ++ unsigned long vcdt2; ++}; ++ ++#define INIT_RCAR_CSI2_LINK_CONFIG(m) \ ++{ \ ++ m.input_interface = DECODER_INPUT_INTERFACE_NONE; \ ++ m.lanes = 0; \ ++} ++ ++struct rcar_csi_irq_counter_log { ++ unsigned long crc_err; ++}; ++ ++struct rcar_csi2 { ++ struct v4l2_subdev subdev; ++ struct v4l2_mbus_framefmt *mf; ++ unsigned int irq; ++ unsigned long mipi_flags; ++ void __iomem *base; ++ struct platform_device *pdev; ++ struct rcar_csi2_client_config *client; ++ unsigned long vcdt; ++ unsigned long vcdt2; ++ ++ unsigned int field; ++ unsigned int code; ++ unsigned int lanes; ++ spinlock_t lock; ++}; ++ ++#define RCAR_CSI_80MBPS 0 ++#define RCAR_CSI_90MBPS 1 ++#define RCAR_CSI_100MBPS 2 ++#define RCAR_CSI_110MBPS 3 ++#define RCAR_CSI_120MBPS 4 ++#define RCAR_CSI_130MBPS 5 ++#define RCAR_CSI_140MBPS 6 ++#define RCAR_CSI_150MBPS 7 ++#define RCAR_CSI_160MBPS 8 ++#define RCAR_CSI_170MBPS 9 ++#define RCAR_CSI_180MBPS 10 ++#define RCAR_CSI_190MBPS 11 ++#define RCAR_CSI_205MBPS 12 ++#define RCAR_CSI_220MBPS 13 ++#define RCAR_CSI_235MBPS 14 ++#define RCAR_CSI_250MBPS 15 ++#define RCAR_CSI_275MBPS 16 ++#define RCAR_CSI_300MBPS 17 ++#define RCAR_CSI_325MBPS 18 ++#define RCAR_CSI_350MBPS 19 ++#define RCAR_CSI_400MBPS 20 ++#define RCAR_CSI_450MBPS 21 ++#define RCAR_CSI_500MBPS 22 ++#define RCAR_CSI_550MBPS 23 ++#define RCAR_CSI_600MBPS 24 ++#define RCAR_CSI_650MBPS 25 ++#define RCAR_CSI_700MBPS 26 ++#define RCAR_CSI_750MBPS 27 ++#define RCAR_CSI_800MBPS 28 ++#define RCAR_CSI_850MBPS 29 ++#define RCAR_CSI_900MBPS 30 ++#define RCAR_CSI_950MBPS 31 ++#define RCAR_CSI_1000MBPS 32 ++#define RCAR_CSI_1050MBPS 33 ++#define RCAR_CSI_1100MBPS 34 ++#define RCAR_CSI_1150MBPS 35 ++#define RCAR_CSI_1200MBPS 36 ++#define RCAR_CSI_1250MBPS 37 ++#define RCAR_CSI_1300MBPS 38 ++#define RCAR_CSI_1350MBPS 39 ++#define RCAR_CSI_1400MBPS 40 ++#define RCAR_CSI_1450MBPS 41 ++#define RCAR_CSI_1500MBPS 42 ++ ++static int rcar_csi2_set_phy_freq(struct rcar_csi2 *priv) ++{ ++ const uint32_t const hs_freq_range[43] = { ++ 0x00, 0x10, 0x20, 0x30, 0x01, /* 0-4 */ ++ 0x11, 0x21, 0x31, 0x02, 0x12, /* 5-9 */ ++ 0x22, 0x32, 0x03, 0x13, 0x23, /* 10-14 */ ++ 0x33, 0x04, 0x14, 0x05, 0x15, /* 15-19 */ ++ 0x25, 0x06, 0x16, 0x07, 0x17, /* 20-24 */ ++ 0x08, 0x18, 0x09, 0x19, 0x29, /* 25-29 */ ++ 0x39, 0x0A, 0x1A, 0x2A, 0x3A, /* 30-34 */ ++ 0x0B, 0x1B, 0x2B, 0x3B, 0x0C, /* 35-39 */ ++ 0x1C, 0x2C, 0x3C /* 40-42 */ ++ }; ++ uint32_t bps_per_lane = RCAR_CSI_190MBPS; ++ ++ dev_dbg(&priv->pdev->dev, "Input size (%dx%d%c)\n", ++ priv->mf->width, priv->mf->height, ++ (priv->mf->field == V4L2_FIELD_NONE) ? 'p' : 'i'); ++ ++ switch (priv->lanes) { ++ case 1: ++ bps_per_lane = RCAR_CSI_400MBPS; ++ break; ++ case 4: ++ if (priv->mf->field == V4L2_FIELD_NONE) { ++ if ((priv->mf->width == 1920) && ++ (priv->mf->height == 1080)) ++ bps_per_lane = RCAR_CSI_900MBPS; ++ else if ((priv->mf->width == 1280) && ++ (priv->mf->height == 720)) ++ bps_per_lane = RCAR_CSI_450MBPS; ++ else if ((priv->mf->width == 720) && ++ (priv->mf->height == 480)) ++ bps_per_lane = RCAR_CSI_190MBPS; ++ else if ((priv->mf->width == 720) && ++ (priv->mf->height == 576)) ++ bps_per_lane = RCAR_CSI_190MBPS; ++ else if ((priv->mf->width == 640) && ++ (priv->mf->height == 480)) ++ bps_per_lane = RCAR_CSI_100MBPS; ++ else ++ goto error; ++ } else { ++ if ((priv->mf->width == 1920) && ++ (priv->mf->height == 1080)) ++ bps_per_lane = RCAR_CSI_450MBPS; ++ else ++ goto error; ++ } ++ break; ++ default: ++ dev_err(&priv->pdev->dev, "ERROR: lanes is invalid (%d)\n", ++ priv->lanes); ++ return -EINVAL; ++ } ++ ++ dev_dbg(&priv->pdev->dev, "bps_per_lane (%d)\n", bps_per_lane); ++ ++ iowrite32((hs_freq_range[bps_per_lane] << 16), ++ priv->base + RCAR_CSI2_PHYPLL); ++ return 0; ++ ++error: ++ dev_err(&priv->pdev->dev, "Not support resolution (%dx%d%c)\n", ++ priv->mf->width, priv->mf->height, ++ (priv->mf->field == V4L2_FIELD_NONE) ? 'p' : 'i'); ++ return -EINVAL; ++} ++ ++static irqreturn_t rcar_csi2_irq(int irq, void *data) ++{ ++ struct rcar_csi2 *priv = data; ++ u32 int_status; ++ unsigned int handled = 0; ++ ++ spin_lock(&priv->lock); ++ ++ int_status = ioread32(priv->base + RCAR_CSI2_INTSTATE); ++ if (!int_status) ++ goto done; ++ ++ /* ack interrupts */ ++ iowrite32(int_status, priv->base + RCAR_CSI2_INTSTATE); ++ handled = 1; ++ ++done: ++ spin_unlock(&priv->lock); ++ ++ return IRQ_RETVAL(handled); ++ ++} ++ ++static void rcar_csi2_hwdeinit(struct rcar_csi2 *priv) ++{ ++ iowrite32(0, priv->base + RCAR_CSI2_PHYCNT); ++ ++ /* reset CSI2 hardware */ ++ iowrite32(0x00000001, priv->base + RCAR_CSI2_SRST); ++ udelay(5); ++ iowrite32(0x00000000, priv->base + RCAR_CSI2_SRST); ++} ++ ++static int rcar_csi2_hwinit(struct rcar_csi2 *priv) ++{ ++ int ret; ++ __u32 tmp = 0x10; /* Enable MIPI CSI clock lane */ ++ ++ /* Reflect registers immediately */ ++ iowrite32(0x00000001, priv->base + RCAR_CSI2_TREF); ++ /* reset CSI2 hardware */ ++ iowrite32(0x00000001, priv->base + RCAR_CSI2_SRST); ++ udelay(5); ++ iowrite32(0x00000000, priv->base + RCAR_CSI2_SRST); ++ ++ iowrite32(0x00000000, priv->base + RCAR_CSI2_PHTC); ++ ++ /* setting HS reception frequency */ ++ { ++ switch (priv->lanes) { ++ case 1: ++ /* First field number setting */ ++ iowrite32(0x0001000f, priv->base + RCAR_CSI2_FLD); ++ tmp |= 0x1; ++ break; ++ case 4: ++ /* First field number setting */ ++ iowrite32(0x0002000f, priv->base + RCAR_CSI2_FLD); ++ tmp |= 0xF; ++ break; ++ default: ++ dev_err(&priv->pdev->dev, ++ "ERROR: lanes is invalid (%d)\n", ++ priv->lanes); ++ return -EINVAL; ++ } ++ ++ /* set PHY frequency */ ++ ret = rcar_csi2_set_phy_freq(priv); ++ if (ret < 0) ++ return ret; ++ ++ /* Enable lanes */ ++ iowrite32(tmp, priv->base + RCAR_CSI2_PHYCNT); ++ ++ iowrite32(tmp | RCAR_CSI2_PHYCNT_SHUTDOWNZ, ++ priv->base + RCAR_CSI2_PHYCNT); ++ iowrite32(tmp | (RCAR_CSI2_PHYCNT_SHUTDOWNZ | ++ RCAR_CSI2_PHYCNT_RSTZ), ++ priv->base + RCAR_CSI2_PHYCNT); ++ } ++ ++ iowrite32(0x00000003, priv->base + RCAR_CSI2_CHKSUM); ++ iowrite32(priv->vcdt, priv->base + RCAR_CSI2_VCDT); ++ iowrite32(priv->vcdt2, priv->base + RCAR_CSI2_VCDT2); ++ iowrite32(0x00010000, priv->base + RCAR_CSI2_FRDT); ++ udelay(10); ++ iowrite32(0x83000000, priv->base + RCAR_CSI2_LINKCNT); ++ iowrite32(0x000000e4, priv->base + RCAR_CSI2_LSWAP); ++ ++ dev_dbg(&priv->pdev->dev, "CSI2 VCDT: 0x%x\n", ++ ioread32(priv->base + RCAR_CSI2_VCDT)); ++ dev_dbg(&priv->pdev->dev, "CSI2 VCDT2: 0x%x\n", ++ ioread32(priv->base + RCAR_CSI2_VCDT2)); ++ ++ /* wait until video decoder power off */ ++ msleep(10); ++ { ++ int timeout = 100; ++ ++ /* Read the PHY clock lane monitor register (PHCLM). */ ++ while (!(ioread32(priv->base + RCAR_CSI2_PHCLM) & 0x01) ++ && timeout) { ++ timeout--; ++ } ++ if (timeout == 0) ++ dev_err(&priv->pdev->dev, ++ "Timeout of reading the PHY clock lane\n"); ++ else ++ dev_dbg(&priv->pdev->dev, ++ "Detected the PHY clock lane\n"); ++ ++ timeout = 100; ++ ++ /* Read the PHY data lane monitor register (PHDLM). */ ++ while (!(ioread32(priv->base + RCAR_CSI2_PHDLM) & 0x01) ++ && timeout) { ++ timeout--; ++ } ++ if (timeout == 0) ++ dev_err(&priv->pdev->dev, ++ "Timeout of reading the PHY data lane\n"); ++ else ++ dev_dbg(&priv->pdev->dev, ++ "Detected the PHY data lane\n"); ++ } ++ ++ return 0; ++} ++ ++static int rcar_csi2_s_power(struct v4l2_subdev *sd, int on) ++{ ++ struct rcar_csi2 *priv = container_of(sd, struct rcar_csi2, subdev); ++ struct v4l2_subdev *tmp_sd; ++ struct v4l2_subdev_format fmt = { ++ .which = V4L2_SUBDEV_FORMAT_ACTIVE, ++ }; ++ struct v4l2_mbus_framefmt *mf = &fmt.format; ++ int ret = 0; ++ ++ if (on) { ++ v4l2_device_for_each_subdev(tmp_sd, sd->v4l2_dev) { ++ if (strncmp(tmp_sd->name, CONNECT_SLAVE_NAME, ++ sizeof(CONNECT_SLAVE_NAME) - 1) == 0) { ++ v4l2_subdev_call(tmp_sd, pad, get_fmt, ++ NULL, &fmt); ++ if (ret < 0) ++ return ret; ++ } ++ } ++ priv->mf = mf; ++ pm_runtime_get_sync(&priv->pdev->dev); ++ ret = rcar_csi2_hwinit(priv); ++ if (ret < 0) ++ return ret; ++ } else { ++ rcar_csi2_hwdeinit(priv); ++ pm_runtime_put_sync(&priv->pdev->dev); ++ } ++ ++ return ret; ++} ++ ++static struct v4l2_subdev_core_ops rcar_csi2_subdev_core_ops = { ++ .s_power = rcar_csi2_s_power, ++}; ++ ++static struct v4l2_subdev_ops rcar_csi2_subdev_ops = { ++ .core = &rcar_csi2_subdev_core_ops, ++}; ++ ++#ifdef CONFIG_OF ++static const struct of_device_id rcar_csi2_of_table[] = { ++ { .compatible = "renesas,r8a7796-csi2", .data = (void *)RCAR_GEN3 }, ++ { .compatible = "renesas,r8a7795-csi2", .data = (void *)RCAR_GEN3 }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, rcar_csi2_of_table); ++#endif ++ ++static struct platform_device_id rcar_csi2_id_table[] = { ++ { "r8a7796-csi2", RCAR_GEN3 }, ++ { "r8a7795-csi2", RCAR_GEN3 }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(platform, rcar_csi2_id_table); ++ ++static int rcar_csi2_parse_dt(struct device_node *np, ++ struct rcar_csi2_link_config *config) ++{ ++ struct v4l2_of_endpoint bus_cfg; ++ struct device_node *endpoint; ++ struct device_node *vc_np, *vc_ch; ++ const char *str; ++ char csi_name[9]; ++ int ret; ++ int i, ch; ++ ++ /* Parse the endpoint. */ ++ endpoint = of_graph_get_next_endpoint(np, NULL); ++ if (!endpoint) ++ return -EINVAL; ++ ++ v4l2_of_parse_endpoint(endpoint, &bus_cfg); ++ of_node_put(endpoint); ++ ++ config->lanes = bus_cfg.bus.mipi_csi2.num_data_lanes; ++ ++ ret = of_property_read_string(np, "adi,input-interface", &str); ++ if (ret < 0) ++ return ret; ++ ++ vc_np = of_get_child_by_name(np, "virtual,channel"); ++ ++ config->vcdt = 0; ++ config->vcdt2 = 0; ++ for (i = 0; i < VC_MAX_CHANNEL; i++) { ++ sprintf(csi_name, "csi2_vc%d", i); ++ ++ vc_ch = of_get_child_by_name(vc_np, csi_name); ++ if (!vc_ch) ++ continue; ++ ret = of_property_read_string(vc_ch, "data,type", &str); ++ if (ret < 0) ++ return ret; ++ ret = of_property_read_u32(vc_ch, "receive,vc", &ch); ++ if (ret < 0) ++ return ret; ++ ++ if (i < 2) { ++ if (!strcmp(str, "rgb888")) ++ config->vcdt |= (0x24 << (i * 16)); ++ else if (!strcmp(str, "ycbcr422")) ++ config->vcdt |= (0x1e << (i * 16)); ++ else ++ config->vcdt |= 0; ++ ++ config->vcdt |= (ch << (8 + (i * 16))); ++ config->vcdt |= (RCAR_CSI2_VCDT_VCDTN_EN << (i * 16)) | ++ (RCAR_CSI2_VCDT_SEL_DTN_ON << (i * 16)); ++ } ++ if (i >= 2) { ++ int j = (i - 2); ++ ++ if (!strcmp(str, "rgb888")) ++ config->vcdt2 |= (0x24 << (j * 16)); ++ else if (!strcmp(str, "ycbcr422")) ++ config->vcdt2 |= (0x1e << (j * 16)); ++ else ++ config->vcdt2 |= 0; ++ ++ config->vcdt2 |= (ch << (8 + (j * 16))); ++ config->vcdt2 |= (RCAR_CSI2_VCDT_VCDTN_EN << (j * 16)) | ++ (RCAR_CSI2_VCDT_SEL_DTN_ON << (j * 16)); ++ } ++ } ++ ++ return 0; ++} ++ ++static int rcar_csi2_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ unsigned int irq; ++ int ret; ++ struct rcar_csi2 *priv; ++ /* Platform data specify the PHY, lanes, ECC, CRC */ ++ struct rcar_csi2_pdata *pdata; ++ struct rcar_csi2_link_config link_config; ++ ++ dev_dbg(&pdev->dev, "CSI2 probed.\n"); ++ ++ INIT_RCAR_CSI2_LINK_CONFIG(link_config); ++ ++ if (pdev->dev.of_node) { ++ ret = rcar_csi2_parse_dt(pdev->dev.of_node, &link_config); ++ if (ret) ++ return ret; ++ ++ if (link_config.lanes == 4) ++ dev_info(&pdev->dev, ++ "Detected rgb888 in rcar_csi2_parse_dt\n"); ++ else ++ dev_info(&pdev->dev, ++ "Detected YCbCr422 in rcar_csi2_parse_dt\n"); ++ } else { ++ pdata = pdev->dev.platform_data; ++ if (!pdata) ++ return -EINVAL; ++ } ++ ++ priv = devm_kzalloc(&pdev->dev, sizeof(struct rcar_csi2), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ /* Interrupt unused so far */ ++ irq = platform_get_irq(pdev, 0); ++ ++ if (!res || (int)irq <= 0) { ++ dev_err(&pdev->dev, "Not enough CSI2 platform resources.\n"); ++ return -ENODEV; ++ } ++ ++ priv->irq = irq; ++ ++ priv->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(priv->base)) ++ return PTR_ERR(priv->base); ++ ++ ret = devm_request_irq(&pdev->dev, irq, rcar_csi2_irq, IRQF_SHARED, ++ dev_name(&pdev->dev), priv); ++ if (ret) ++ return ret; ++ ++ priv->pdev = pdev; ++ priv->subdev.owner = THIS_MODULE; ++ priv->subdev.dev = &pdev->dev; ++ priv->lanes = link_config.lanes; ++ priv->vcdt = link_config.vcdt; ++ priv->vcdt2 = link_config.vcdt2; ++ ++ platform_set_drvdata(pdev, &priv->subdev); ++ ++ v4l2_subdev_init(&priv->subdev, &rcar_csi2_subdev_ops); ++ v4l2_set_subdevdata(&priv->subdev, &pdev->dev); ++ ++ snprintf(priv->subdev.name, V4L2_SUBDEV_NAME_SIZE, "rcar_csi2.%s", ++ dev_name(&pdev->dev)); ++ ++ ret = v4l2_async_register_subdev(&priv->subdev); ++ if (ret < 0) ++ return ret; ++ ++ spin_lock_init(&priv->lock); ++ ++ pm_runtime_enable(&pdev->dev); ++ ++ dev_dbg(&pdev->dev, "CSI2 probed.\n"); ++ ++ return 0; ++} ++ ++static int rcar_csi2_remove(struct platform_device *pdev) ++{ ++ struct v4l2_subdev *subdev = platform_get_drvdata(pdev); ++ struct rcar_csi2 *priv = container_of(subdev, struct rcar_csi2, subdev); ++ ++ v4l2_async_unregister_subdev(&priv->subdev); ++ pm_runtime_disable(&pdev->dev); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int rcar_csi2_suspend(struct device *dev) ++{ ++ /* Empty function for now */ ++ return 0; ++} ++ ++static int rcar_csi2_resume(struct device *dev) ++{ ++ /* Empty function for now */ ++ return 0; ++} ++ ++static SIMPLE_DEV_PM_OPS(rcar_csi2_pm_ops, ++ rcar_csi2_suspend, rcar_csi2_resume); ++#define DEV_PM_OPS (&rcar_csi2_pm_ops) ++#else ++#define DEV_PM_OPS NULL ++#endif /* CONFIG_PM_SLEEP */ ++ ++static struct platform_driver __refdata rcar_csi2_pdrv = { ++ .remove = rcar_csi2_remove, ++ .probe = rcar_csi2_probe, ++ .driver = { ++ .name = DRV_NAME, ++ .pm = DEV_PM_OPS, ++ .of_match_table = of_match_ptr(rcar_csi2_of_table), ++ }, ++ .id_table = rcar_csi2_id_table, ++}; ++ ++module_platform_driver(rcar_csi2_pdrv); ++ ++MODULE_DESCRIPTION("Renesas R-Car MIPI CSI-2 driver"); ++MODULE_AUTHOR("Koji Matsuoka "); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:rcar-csi2"); +diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c +new file mode 100644 +index 0000000..400958b +--- /dev/null ++++ b/drivers/media/platform/soc_camera/rcar_vin.c +@@ -0,0 +1,3071 @@ ++/* ++ * SoC-camera host driver for Renesas R-Car VIN unit ++ * ++ * Copyright (C) 2015-2016 Renesas Electronics Corporation ++ * Copyright (C) 2011-2013 Renesas Solutions Corp. ++ * Copyright (C) 2013 Cogent Embedded, Inc., ++ * ++ * Based on V4L2 Driver for SuperH Mobile CEU interface "sh_mobile_ceu_camera.c" ++ * ++ * Copyright (C) 2008 Magnus Damm ++ * ++ * 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. ++ */ ++ ++#ifdef CONFIG_VIDEO_RCAR_VIN_LEGACY_DEBUG ++#define DEBUG ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "soc_scale_crop.h" ++ ++#define DRV_NAME "rcar_vin" ++ ++/* Register offsets for R-Car VIN */ ++#define VNMC_REG 0x00 /* Video n Main Control Register */ ++#define VNMS_REG 0x04 /* Video n Module Status Register */ ++#define VNFC_REG 0x08 /* Video n Frame Capture Register */ ++#define VNSLPRC_REG 0x0C /* Video n Start Line Pre-Clip Register */ ++#define VNELPRC_REG 0x10 /* Video n End Line Pre-Clip Register */ ++#define VNSPPRC_REG 0x14 /* Video n Start Pixel Pre-Clip Register */ ++#define VNEPPRC_REG 0x18 /* Video n End Pixel Pre-Clip Register */ ++#define VNSLPOC_REG 0x1C /* Video n Start Line Post-Clip Register */ ++#define VNELPOC_REG 0x20 /* Video n End Line Post-Clip Register */ ++#define VNSPPOC_REG 0x24 /* Video n Start Pixel Post-Clip Register */ ++#define VNEPPOC_REG 0x28 /* Video n End Pixel Post-Clip Register */ ++#define VNIS_REG 0x2C /* Video n Image Stride Register */ ++#define VNMB_REG(m) (0x30 + ((m) << 2)) /* Video n Memory Base m Register */ ++#define VNIE_REG 0x40 /* Video n Interrupt Enable Register */ ++#define VNINTS_REG 0x44 /* Video n Interrupt Status Register */ ++#define VNSI_REG 0x48 /* Video n Scanline Interrupt Register */ ++#define VNMTC_REG 0x4C /* Video n Memory Transfer Control Register */ ++#define VNYS_REG 0x50 /* Video n Y Scale Register */ ++#define VNXS_REG 0x54 /* Video n X Scale Register */ ++#define VNDMR_REG 0x58 /* Video n Data Mode Register */ ++#define VNDMR2_REG 0x5C /* Video n Data Mode Register 2 */ ++#define VNUVAOF_REG 0x60 /* Video n UV Address Offset Register */ ++#define VNC1A_REG 0x80 /* Video n Coefficient Set C1A Register */ ++#define VNC1B_REG 0x84 /* Video n Coefficient Set C1B Register */ ++#define VNC1C_REG 0x88 /* Video n Coefficient Set C1C Register */ ++#define VNC2A_REG 0x90 /* Video n Coefficient Set C2A Register */ ++#define VNC2B_REG 0x94 /* Video n Coefficient Set C2B Register */ ++#define VNC2C_REG 0x98 /* Video n Coefficient Set C2C Register */ ++#define VNC3A_REG 0xA0 /* Video n Coefficient Set C3A Register */ ++#define VNC3B_REG 0xA4 /* Video n Coefficient Set C3B Register */ ++#define VNC3C_REG 0xA8 /* Video n Coefficient Set C3C Register */ ++#define VNC4A_REG 0xB0 /* Video n Coefficient Set C4A Register */ ++#define VNC4B_REG 0xB4 /* Video n Coefficient Set C4B Register */ ++#define VNC4C_REG 0xB8 /* Video n Coefficient Set C4C Register */ ++#define VNC5A_REG 0xC0 /* Video n Coefficient Set C5A Register */ ++#define VNC5B_REG 0xC4 /* Video n Coefficient Set C5B Register */ ++#define VNC5C_REG 0xC8 /* Video n Coefficient Set C5C Register */ ++#define VNC6A_REG 0xD0 /* Video n Coefficient Set C6A Register */ ++#define VNC6B_REG 0xD4 /* Video n Coefficient Set C6B Register */ ++#define VNC6C_REG 0xD8 /* Video n Coefficient Set C6C Register */ ++#define VNC7A_REG 0xE0 /* Video n Coefficient Set C7A Register */ ++#define VNC7B_REG 0xE4 /* Video n Coefficient Set C7B Register */ ++#define VNC7C_REG 0xE8 /* Video n Coefficient Set C7C Register */ ++#define VNC8A_REG 0xF0 /* Video n Coefficient Set C8A Register */ ++#define VNC8B_REG 0xF4 /* Video n Coefficient Set C8B Register */ ++#define VNC8C_REG 0xF8 /* Video n Coefficient Set C8C Register */ ++ ++/* Register bit fields for R-Car VIN */ ++/* Video n Main Control Register bits */ ++#define VNMC_DPINE (1 << 27) ++#define VNMC_SCLE (1 << 26) ++#define VNMC_FOC (1 << 21) ++#define VNMC_YCAL (1 << 19) ++#define VNMC_INF_YUV8_BT656 (0 << 16) ++#define VNMC_INF_YUV8_BT601 (1 << 16) ++#define VNMC_INF_YUV10_BT656 (2 << 16) ++#define VNMC_INF_YUV10_BT601 (3 << 16) ++#define VNMC_INF_YUV16 (5 << 16) ++#define VNMC_INF_RGB888 (6 << 16) ++#define VNMC_INF_MASK (7 << 16) ++#define VNMC_VUP (1 << 10) ++#define VNMC_IM_ODD (0 << 3) ++#define VNMC_IM_ODD_EVEN (1 << 3) ++#define VNMC_IM_EVEN (2 << 3) ++#define VNMC_IM_FULL (3 << 3) ++#define VNMC_BPS (1 << 1) ++#define VNMC_ME (1 << 0) ++ ++/* Video n Module Status Register bits */ ++#define VNMS_FBS_MASK (3 << 3) ++#define VNMS_FBS_SHIFT 3 ++#define VNMS_AV (1 << 1) ++#define VNMS_CA (1 << 0) ++ ++/* Video n Frame Capture Register bits */ ++#define VNFC_C_FRAME (1 << 1) ++#define VNFC_S_FRAME (1 << 0) ++ ++/* Video n Interrupt Enable Register bits */ ++#define VNIE_FIE (1 << 4) ++#define VNIE_EFE (1 << 1) ++#define VNIE_FOE (1 << 0) ++ ++/* Video n Interrupt Status Register bits */ ++#define VNINTS_FIS (1 << 4) ++#define VNINTS_EFS (1 << 1) ++#define VNINTS_FOS (1 << 0) ++ ++/* Video n Data Mode Register bits */ ++#define VNDMR_EXRGB (1 << 8) ++#define VNDMR_BPSM (1 << 4) ++#define VNDMR_DTMD_YCSEP (1 << 1) ++#define VNDMR_DTMD_ARGB (1 << 0) ++#define VNDMR_DTMD_YCSEP_YCBCR420 (3 << 0) ++ ++/* Video n Data Mode Register 2 bits */ ++#define VNDMR2_VPS (1 << 30) ++#define VNDMR2_HPS (1 << 29) ++#define VNDMR2_FTEV (1 << 17) ++#define VNDMR2_VLV(n) ((n & 0xf) << 12) ++ ++/* setting CSI2 on R-Car Gen3*/ ++#define VNCSI_IFMD_REG 0x20 /* Video n CSI2 Interface Mode Register */ ++ ++#define VNCSI_IFMD_DES1 (1 << 26) /* CSI20 */ ++#define VNCSI_IFMD_DES0 (1 << 25) /* H3:CSI40/41, M3:CSI40 */ ++ ++#define VNCSI_IFMD_CSI_CHSEL(n) (n << 0) ++#define VNCSI_IFMD_SEL_NUMBER 5 ++ ++/* UDS */ ++#define VNUDS_CTRL_REG 0x80 /* Scaling Control Registers */ ++#define VNUDS_CTRL_AMD (1 << 30) ++#define VNUDS_CTRL_BC (1 << 20) ++#define VNUDS_CTRL_TDIPC (1 << 1) ++ ++#define VNUDS_SCALE_REG 0x84 /* Scaling Factor Register */ ++#define VNUDS_PASS_BWIDTH_REG 0x90 /* Passband Registers */ ++#define VNUDS_IPC_REG 0x98 /* 2D IPC Setting Register */ ++#define VNUDS_CLIP_SIZE_REG 0xA4 /* UDS Output Size Clipping Register */ ++ ++#define TIMEOUT_MS 100 ++ ++#define RCAR_VIN_HSYNC_ACTIVE_LOW (1 << 0) ++#define RCAR_VIN_VSYNC_ACTIVE_LOW (1 << 1) ++#define RCAR_VIN_BT601 (1 << 2) ++#define RCAR_VIN_BT656 (1 << 3) ++#define RCAR_VIN_CSI2 (1 << 4) ++ ++static int ifmd0_reg_match[VNCSI_IFMD_SEL_NUMBER]; ++static int ifmd4_reg_match[VNCSI_IFMD_SEL_NUMBER]; ++static int ifmd0_init = true; ++static int ifmd4_init = true; ++ ++enum chip_id { ++ RCAR_GEN3, ++ RCAR_M3, ++ RCAR_H3, ++ RCAR_GEN2, ++ RCAR_H1, ++ RCAR_M1, ++ RCAR_E1, ++}; ++ ++enum csi2_ch { ++ RCAR_CSI_CH_NONE = -1, ++ RCAR_CSI40, ++ RCAR_CSI20, ++ RCAR_CSI41, ++ RCAR_CSI21, ++ RCAR_CSI_MAX, ++}; ++ ++enum gen3_vin_ch { ++ RCAR_VIN_CH_NONE = -1, ++ RCAR_VIDEO_0, ++ RCAR_VIDEO_1, ++ RCAR_VIDEO_2, ++ RCAR_VIDEO_3, ++ RCAR_VIDEO_4, ++ RCAR_VIDEO_5, ++ RCAR_VIDEO_6, ++ RCAR_VIDEO_7, ++ RCAR_VIDEO_MAX, ++}; ++ ++enum virtual_ch { ++ RCAR_VIRTUAL_NONE = -1, ++ RCAR_VIRTUAL_CH0, ++ RCAR_VIRTUAL_CH1, ++ RCAR_VIRTUAL_CH2, ++ RCAR_VIRTUAL_CH3, ++ RCAR_VIRTUAL_MAX, ++}; ++ ++struct vin_gen3_virtual_sel { ++ enum csi2_ch csi2_ch; ++ enum virtual_ch vc; ++}; ++ ++struct vin_gen3_ifmd { ++ unsigned int set_reg; ++ struct vin_gen3_virtual_sel v_sel[8]; ++}; ++ ++static const struct vin_gen3_ifmd vin_h3_vc_ifmd[] = { ++ { 0x0000, ++ { ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH1}, ++ } ++ }, ++ { 0x0001, ++ { ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ } ++ }, ++ { 0x0002, ++ { ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ } ++ }, ++ { 0x0003, ++ { ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH3}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH3}, ++ } ++ }, ++ { 0x0004, ++ { ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH3}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH3}, ++ } ++ }, ++}; ++ ++static const struct vin_gen3_ifmd vin_m3_vc_ifmd[] = { ++ { 0x0000, ++ { ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ } ++ }, ++ { 0x0001, ++ { ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ } ++ }, ++ { 0x0002, ++ { ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ } ++ }, ++ { 0x0003, ++ { ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH3}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH3}, ++ } ++ }, ++ { 0x0004, ++ { ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH3}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH3}, ++ } ++ }, ++}; ++ ++enum csi2_fmt { ++ RCAR_CSI_FMT_NONE = -1, ++ RCAR_CSI_RGB888, ++ RCAR_CSI_YCBCR422, ++}; ++ ++struct vin_coeff { ++ unsigned short xs_value; ++ u32 coeff_set[24]; ++}; ++ ++static const struct vin_coeff vin_coeff_set[] = { ++ { 0x0000, { ++ 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000, 0x00000000 }, ++ }, ++ { 0x1000, { ++ 0x000fa400, 0x000fa400, 0x09625902, ++ 0x000003f8, 0x00000403, 0x3de0d9f0, ++ 0x001fffed, 0x00000804, 0x3cc1f9c3, ++ 0x001003de, 0x00000c01, 0x3cb34d7f, ++ 0x002003d2, 0x00000c00, 0x3d24a92d, ++ 0x00200bca, 0x00000bff, 0x3df600d2, ++ 0x002013cc, 0x000007ff, 0x3ed70c7e, ++ 0x00100fde, 0x00000000, 0x3f87c036 }, ++ }, ++ { 0x1200, { ++ 0x002ffff1, 0x002ffff1, 0x02a0a9c8, ++ 0x002003e7, 0x001ffffa, 0x000185bc, ++ 0x002007dc, 0x000003ff, 0x3e52859c, ++ 0x00200bd4, 0x00000002, 0x3d53996b, ++ 0x00100fd0, 0x00000403, 0x3d04ad2d, ++ 0x00000bd5, 0x00000403, 0x3d35ace7, ++ 0x3ff003e4, 0x00000801, 0x3dc674a1, ++ 0x3fffe800, 0x00000800, 0x3e76f461 }, ++ }, ++ { 0x1400, { ++ 0x00100be3, 0x00100be3, 0x04d1359a, ++ 0x00000fdb, 0x002003ed, 0x0211fd93, ++ 0x00000fd6, 0x002003f4, 0x0002d97b, ++ 0x000007d6, 0x002ffffb, 0x3e93b956, ++ 0x3ff003da, 0x001003ff, 0x3db49926, ++ 0x3fffefe9, 0x00100001, 0x3d655cee, ++ 0x3fffd400, 0x00000003, 0x3d65f4b6, ++ 0x000fb421, 0x00000402, 0x3dc6547e }, ++ }, ++ { 0x1600, { ++ 0x00000bdd, 0x00000bdd, 0x06519578, ++ 0x3ff007da, 0x00000be3, 0x03c24973, ++ 0x3ff003d9, 0x00000be9, 0x01b30d5f, ++ 0x3ffff7df, 0x001003f1, 0x0003c542, ++ 0x000fdfec, 0x001003f7, 0x3ec4711d, ++ 0x000fc400, 0x002ffffd, 0x3df504f1, ++ 0x001fa81a, 0x002ffc00, 0x3d957cc2, ++ 0x002f8c3c, 0x00100000, 0x3db5c891 }, ++ }, ++ { 0x1800, { ++ 0x3ff003dc, 0x3ff003dc, 0x0791e558, ++ 0x000ff7dd, 0x3ff007de, 0x05328554, ++ 0x000fe7e3, 0x3ff00be2, 0x03232546, ++ 0x000fd7ee, 0x000007e9, 0x0143bd30, ++ 0x001fb800, 0x000007ee, 0x00044511, ++ 0x002fa015, 0x000007f4, 0x3ef4bcee, ++ 0x002f8832, 0x001003f9, 0x3e4514c7, ++ 0x001f7853, 0x001003fd, 0x3de54c9f }, ++ }, ++ { 0x1a00, { ++ 0x000fefe0, 0x000fefe0, 0x08721d3c, ++ 0x001fdbe7, 0x000ffbde, 0x0652a139, ++ 0x001fcbf0, 0x000003df, 0x0463292e, ++ 0x002fb3ff, 0x3ff007e3, 0x0293a91d, ++ 0x002f9c12, 0x3ff00be7, 0x01241905, ++ 0x001f8c29, 0x000007ed, 0x3fe470eb, ++ 0x000f7c46, 0x000007f2, 0x3f04b8ca, ++ 0x3fef7865, 0x000007f6, 0x3e74e4a8 }, ++ }, ++ { 0x1c00, { ++ 0x001fd3e9, 0x001fd3e9, 0x08f23d26, ++ 0x002fbff3, 0x001fe3e4, 0x0712ad23, ++ 0x002fa800, 0x000ff3e0, 0x05631d1b, ++ 0x001f9810, 0x000ffbe1, 0x03b3890d, ++ 0x000f8c23, 0x000003e3, 0x0233e8fa, ++ 0x3fef843b, 0x000003e7, 0x00f430e4, ++ 0x3fbf8456, 0x3ff00bea, 0x00046cc8, ++ 0x3f8f8c72, 0x3ff00bef, 0x3f3490ac }, ++ }, ++ { 0x1e00, { ++ 0x001fbbf4, 0x001fbbf4, 0x09425112, ++ 0x001fa800, 0x002fc7ed, 0x0792b110, ++ 0x000f980e, 0x001fdbe6, 0x0613110a, ++ 0x3fff8c20, 0x001fe7e3, 0x04a368fd, ++ 0x3fcf8c33, 0x000ff7e2, 0x0343b8ed, ++ 0x3f9f8c4a, 0x000fffe3, 0x0203f8da, ++ 0x3f5f9c61, 0x000003e6, 0x00e428c5, ++ 0x3f1fb07b, 0x000003eb, 0x3fe440af }, ++ }, ++ { 0x2000, { ++ 0x000fa400, 0x000fa400, 0x09625902, ++ 0x3fff980c, 0x001fb7f5, 0x0812b0ff, ++ 0x3fdf901c, 0x001fc7ed, 0x06b2fcfa, ++ 0x3faf902d, 0x001fd3e8, 0x055348f1, ++ 0x3f7f983f, 0x001fe3e5, 0x04038ce3, ++ 0x3f3fa454, 0x001fefe3, 0x02e3c8d1, ++ 0x3f0fb86a, 0x001ff7e4, 0x01c3e8c0, ++ 0x3ecfd880, 0x000fffe6, 0x00c404ac }, ++ }, ++ { 0x2200, { ++ 0x3fdf9c0b, 0x3fdf9c0b, 0x09725cf4, ++ 0x3fbf9818, 0x3fffa400, 0x0842a8f1, ++ 0x3f8f9827, 0x000fb3f7, 0x0702f0ec, ++ 0x3f5fa037, 0x000fc3ef, 0x05d330e4, ++ 0x3f2fac49, 0x001fcfea, 0x04a364d9, ++ 0x3effc05c, 0x001fdbe7, 0x038394ca, ++ 0x3ecfdc6f, 0x001fe7e6, 0x0273b0bb, ++ 0x3ea00083, 0x001fefe6, 0x0183c0a9 }, ++ }, ++ { 0x2400, { ++ 0x3f9fa014, 0x3f9fa014, 0x098260e6, ++ 0x3f7f9c23, 0x3fcf9c0a, 0x08629ce5, ++ 0x3f4fa431, 0x3fefa400, 0x0742d8e1, ++ 0x3f1fb440, 0x3fffb3f8, 0x062310d9, ++ 0x3eefc850, 0x000fbbf2, 0x050340d0, ++ 0x3ecfe062, 0x000fcbec, 0x041364c2, ++ 0x3ea00073, 0x001fd3ea, 0x03037cb5, ++ 0x3e902086, 0x001fdfe8, 0x022388a5 }, ++ }, ++ { 0x2600, { ++ 0x3f5fa81e, 0x3f5fa81e, 0x096258da, ++ 0x3f3fac2b, 0x3f8fa412, 0x088290d8, ++ 0x3f0fbc38, 0x3fafa408, 0x0772c8d5, ++ 0x3eefcc47, 0x3fcfa800, 0x0672f4ce, ++ 0x3ecfe456, 0x3fefaffa, 0x05531cc6, ++ 0x3eb00066, 0x3fffbbf3, 0x047334bb, ++ 0x3ea01c77, 0x000fc7ee, 0x039348ae, ++ 0x3ea04486, 0x000fd3eb, 0x02b350a1 }, ++ }, ++ { 0x2800, { ++ 0x3f2fb426, 0x3f2fb426, 0x094250ce, ++ 0x3f0fc032, 0x3f4fac1b, 0x086284cd, ++ 0x3eefd040, 0x3f7fa811, 0x0782acc9, ++ 0x3ecfe84c, 0x3f9fa807, 0x06a2d8c4, ++ 0x3eb0005b, 0x3fbfac00, 0x05b2f4bc, ++ 0x3eb0186a, 0x3fdfb3fa, 0x04c308b4, ++ 0x3eb04077, 0x3fefbbf4, 0x03f31ca8, ++ 0x3ec06884, 0x000fbff2, 0x03031c9e }, ++ }, ++ { 0x2a00, { ++ 0x3f0fc42d, 0x3f0fc42d, 0x090240c4, ++ 0x3eefd439, 0x3f2fb822, 0x08526cc2, ++ 0x3edfe845, 0x3f4fb018, 0x078294bf, ++ 0x3ec00051, 0x3f6fac0f, 0x06b2b4bb, ++ 0x3ec0185f, 0x3f8fac07, 0x05e2ccb4, ++ 0x3ec0386b, 0x3fafac00, 0x0502e8ac, ++ 0x3ed05c77, 0x3fcfb3fb, 0x0432f0a3, ++ 0x3ef08482, 0x3fdfbbf6, 0x0372f898 }, ++ }, ++ { 0x2c00, { ++ 0x3eefdc31, 0x3eefdc31, 0x08e238b8, ++ 0x3edfec3d, 0x3f0fc828, 0x082258b9, ++ 0x3ed00049, 0x3f1fc01e, 0x077278b6, ++ 0x3ed01455, 0x3f3fb815, 0x06c294b2, ++ 0x3ed03460, 0x3f5fb40d, 0x0602acac, ++ 0x3ef0506c, 0x3f7fb006, 0x0542c0a4, ++ 0x3f107476, 0x3f9fb400, 0x0472c89d, ++ 0x3f309c80, 0x3fbfb7fc, 0x03b2cc94 }, ++ }, ++ { 0x2e00, { ++ 0x3eefec37, 0x3eefec37, 0x088220b0, ++ 0x3ee00041, 0x3effdc2d, 0x07f244ae, ++ 0x3ee0144c, 0x3f0fd023, 0x07625cad, ++ 0x3ef02c57, 0x3f1fc81a, 0x06c274a9, ++ 0x3f004861, 0x3f3fbc13, 0x060288a6, ++ 0x3f20686b, 0x3f5fb80c, 0x05529c9e, ++ 0x3f408c74, 0x3f6fb805, 0x04b2ac96, ++ 0x3f80ac7e, 0x3f8fb800, 0x0402ac8e }, ++ }, ++ { 0x3000, { ++ 0x3ef0003a, 0x3ef0003a, 0x084210a6, ++ 0x3ef01045, 0x3effec32, 0x07b228a7, ++ 0x3f00284e, 0x3f0fdc29, 0x073244a4, ++ 0x3f104058, 0x3f0fd420, 0x06a258a2, ++ 0x3f305c62, 0x3f2fc818, 0x0612689d, ++ 0x3f508069, 0x3f3fc011, 0x05728496, ++ 0x3f80a072, 0x3f4fc00a, 0x04d28c90, ++ 0x3fc0c07b, 0x3f6fbc04, 0x04429088 }, ++ }, ++ { 0x3200, { ++ 0x3f00103e, 0x3f00103e, 0x07f1fc9e, ++ 0x3f102447, 0x3f000035, 0x0782149d, ++ 0x3f203c4f, 0x3f0ff02c, 0x07122c9c, ++ 0x3f405458, 0x3f0fe424, 0x06924099, ++ 0x3f607061, 0x3f1fd41d, 0x06024c97, ++ 0x3f909068, 0x3f2fcc16, 0x05726490, ++ 0x3fc0b070, 0x3f3fc80f, 0x04f26c8a, ++ 0x0000d077, 0x3f4fc409, 0x04627484 }, ++ }, ++ { 0x3400, { ++ 0x3f202040, 0x3f202040, 0x07a1e898, ++ 0x3f303449, 0x3f100c38, 0x0741fc98, ++ 0x3f504c50, 0x3f10002f, 0x06e21495, ++ 0x3f706459, 0x3f1ff028, 0x06722492, ++ 0x3fa08060, 0x3f1fe421, 0x05f2348f, ++ 0x3fd09c67, 0x3f1fdc19, 0x05824c89, ++ 0x0000bc6e, 0x3f2fd014, 0x04f25086, ++ 0x0040dc74, 0x3f3fcc0d, 0x04825c7f }, ++ }, ++ { 0x3600, { ++ 0x3f403042, 0x3f403042, 0x0761d890, ++ 0x3f504848, 0x3f301c3b, 0x0701f090, ++ 0x3f805c50, 0x3f200c33, 0x06a2008f, ++ 0x3fa07458, 0x3f10002b, 0x06520c8d, ++ 0x3fd0905e, 0x3f1ff424, 0x05e22089, ++ 0x0000ac65, 0x3f1fe81d, 0x05823483, ++ 0x0030cc6a, 0x3f2fdc18, 0x04f23c81, ++ 0x0080e871, 0x3f2fd412, 0x0482407c }, ++ }, ++ { 0x3800, { ++ 0x3f604043, 0x3f604043, 0x0721c88a, ++ 0x3f80544a, 0x3f502c3c, 0x06d1d88a, ++ 0x3fb06851, 0x3f301c35, 0x0681e889, ++ 0x3fd08456, 0x3f30082f, 0x0611fc88, ++ 0x00009c5d, 0x3f200027, 0x05d20884, ++ 0x0030b863, 0x3f2ff421, 0x05621880, ++ 0x0070d468, 0x3f2fe81b, 0x0502247c, ++ 0x00c0ec6f, 0x3f2fe015, 0x04a22877 }, ++ }, ++ { 0x3a00, { ++ 0x3f904c44, 0x3f904c44, 0x06e1b884, ++ 0x3fb0604a, 0x3f70383e, 0x0691c885, ++ 0x3fe07451, 0x3f502c36, 0x0661d483, ++ 0x00009055, 0x3f401831, 0x0601ec81, ++ 0x0030a85b, 0x3f300c2a, 0x05b1f480, ++ 0x0070c061, 0x3f300024, 0x0562047a, ++ 0x00b0d867, 0x3f3ff41e, 0x05020c77, ++ 0x00f0f46b, 0x3f2fec19, 0x04a21474 }, ++ }, ++ { 0x3c00, { ++ 0x3fb05c43, 0x3fb05c43, 0x06c1b07e, ++ 0x3fe06c4b, 0x3f902c3f, 0x0681c081, ++ 0x0000844f, 0x3f703838, 0x0631cc7d, ++ 0x00309855, 0x3f602433, 0x05d1d47e, ++ 0x0060b459, 0x3f50142e, 0x0581e47b, ++ 0x00a0c85f, 0x3f400828, 0x0531f078, ++ 0x00e0e064, 0x3f300021, 0x0501fc73, ++ 0x00b0fc6a, 0x3f3ff41d, 0x04a20873 }, ++ }, ++ { 0x3e00, { ++ 0x3fe06444, 0x3fe06444, 0x0681a07a, ++ 0x00007849, 0x3fc0503f, 0x0641b07a, ++ 0x0020904d, 0x3fa0403a, 0x05f1c07a, ++ 0x0060a453, 0x3f803034, 0x05c1c878, ++ 0x0090b858, 0x3f70202f, 0x0571d477, ++ 0x00d0d05d, 0x3f501829, 0x0531e073, ++ 0x0110e462, 0x3f500825, 0x04e1e471, ++ 0x01510065, 0x3f40001f, 0x04a1f06d }, ++ }, ++ { 0x4000, { ++ 0x00007044, 0x00007044, 0x06519476, ++ 0x00208448, 0x3fe05c3f, 0x0621a476, ++ 0x0050984d, 0x3fc04c3a, 0x05e1b075, ++ 0x0080ac52, 0x3fa03c35, 0x05a1b875, ++ 0x00c0c056, 0x3f803030, 0x0561c473, ++ 0x0100d45b, 0x3f70202b, 0x0521d46f, ++ 0x0140e860, 0x3f601427, 0x04d1d46e, ++ 0x01810064, 0x3f500822, 0x0491dc6b }, ++ }, ++ { 0x5000, { ++ 0x0110a442, 0x0110a442, 0x0551545e, ++ 0x0140b045, 0x00e0983f, 0x0531585f, ++ 0x0160c047, 0x00c08c3c, 0x0511645e, ++ 0x0190cc4a, 0x00908039, 0x04f1685f, ++ 0x01c0dc4c, 0x00707436, 0x04d1705e, ++ 0x0200e850, 0x00506833, 0x04b1785b, ++ 0x0230f453, 0x00305c30, 0x0491805a, ++ 0x02710056, 0x0010542d, 0x04718059 }, ++ }, ++ { 0x6000, { ++ 0x01c0bc40, 0x01c0bc40, 0x04c13052, ++ 0x01e0c841, 0x01a0b43d, 0x04c13851, ++ 0x0210cc44, 0x0180a83c, 0x04a13453, ++ 0x0230d845, 0x0160a03a, 0x04913c52, ++ 0x0260e047, 0x01409838, 0x04714052, ++ 0x0280ec49, 0x01208c37, 0x04514c50, ++ 0x02b0f44b, 0x01008435, 0x04414c50, ++ 0x02d1004c, 0x00e07c33, 0x0431544f }, ++ }, ++ { 0x7000, { ++ 0x0230c83e, 0x0230c83e, 0x04711c4c, ++ 0x0250d03f, 0x0210c43c, 0x0471204b, ++ 0x0270d840, 0x0200b83c, 0x0451244b, ++ 0x0290dc42, 0x01e0b43a, 0x0441244c, ++ 0x02b0e443, 0x01c0b038, 0x0441284b, ++ 0x02d0ec44, 0x01b0a438, 0x0421304a, ++ 0x02f0f445, 0x0190a036, 0x04213449, ++ 0x0310f847, 0x01709c34, 0x04213848 }, ++ }, ++ { 0x8000, { ++ 0x0280d03d, 0x0280d03d, 0x04310c48, ++ 0x02a0d43e, 0x0270c83c, 0x04311047, ++ 0x02b0dc3e, 0x0250c83a, 0x04311447, ++ 0x02d0e040, 0x0240c03a, 0x04211446, ++ 0x02e0e840, 0x0220bc39, 0x04111847, ++ 0x0300e842, 0x0210b438, 0x04012445, ++ 0x0310f043, 0x0200b037, 0x04012045, ++ 0x0330f444, 0x01e0ac36, 0x03f12445 }, ++ }, ++ { 0xefff, { ++ 0x0340dc3a, 0x0340dc3a, 0x03b0ec40, ++ 0x0340e03a, 0x0330e039, 0x03c0f03e, ++ 0x0350e03b, 0x0330dc39, 0x03c0ec3e, ++ 0x0350e43a, 0x0320dc38, 0x03c0f43e, ++ 0x0360e43b, 0x0320d839, 0x03b0f03e, ++ 0x0360e83b, 0x0310d838, 0x03c0fc3b, ++ 0x0370e83b, 0x0310d439, 0x03a0f83d, ++ 0x0370e83c, 0x0300d438, 0x03b0fc3c }, ++ } ++}; ++ ++enum rcar_vin_state { ++ STOPPED = 0, ++ RUNNING, ++ STOPPING, ++}; ++ ++struct rcar_vin_async_client { ++ struct v4l2_async_subdev *sensor; ++ struct v4l2_async_notifier notifier; ++ struct platform_device *pdev; ++ struct list_head list; /* needed for clean up */ ++}; ++ ++struct soc_of_info { ++ struct soc_camera_async_subdev sasd; ++ struct rcar_vin_async_client sasc; ++ struct v4l2_async_subdev *subdev; ++}; ++ ++struct rcar_vin_priv { ++ void __iomem *base; ++ spinlock_t lock; ++ int sequence; ++ /* State of the VIN module in capturing mode */ ++ enum rcar_vin_state state; ++ struct soc_camera_host ici; ++ struct list_head capture; ++#define MAX_BUFFER_NUM 3 ++ struct vb2_v4l2_buffer *queue_buf[MAX_BUFFER_NUM]; ++ enum v4l2_field field; ++ unsigned int pdata_flags; ++ unsigned int vb_count; ++ unsigned int nr_hw_slots; ++ bool request_to_stop; ++ struct completion capture_stop; ++ enum chip_id chip; ++ unsigned int max_width; ++ unsigned int max_height; ++ unsigned int ratio_h; ++ unsigned int ratio_v; ++ bool error_flag; ++ enum csi2_ch csi_ch; ++ enum csi2_fmt csi_fmt; ++ enum virtual_ch vc; ++ bool csi_sync; ++ ++ struct rcar_vin_async_client *async_client; ++ /* Asynchronous CSI2 linking */ ++ struct v4l2_subdev *csi2_sd; ++ /* Synchronous probing compatibility */ ++ struct platform_device *csi2_pdev; ++ ++ unsigned int index; ++}; ++ ++#define is_continuous_transfer(priv) (priv->vb_count > MAX_BUFFER_NUM) ++ ++struct rcar_vin_buffer { ++ struct vb2_v4l2_buffer vb; ++ struct list_head list; ++}; ++ ++#define to_buf_list(vb2_buffer) (&container_of(vb2_buffer, \ ++ struct rcar_vin_buffer, \ ++ vb)->list) ++ ++struct rcar_vin_cam { ++ /* VIN offsets within the camera output, before the VIN scaler */ ++ unsigned int vin_left; ++ unsigned int vin_top; ++ /* Client output, as seen by the VIN */ ++ unsigned int width; ++ unsigned int height; ++ /* User window from S_FMT */ ++ unsigned int out_width; ++ unsigned int out_height; ++ /* ++ * User window from S_SELECTION / G_SELECTION, produced by client cropping and ++ * scaling, VIN scaling and VIN cropping, mapped back onto the client ++ * input window ++ */ ++ struct v4l2_rect subrect; ++ /* Camera cropping rectangle */ ++ struct v4l2_rect rect; ++ const struct soc_mbus_pixelfmt *extra_fmt; ++}; ++ ++#define VIN_UT_IRQ 0x01 ++ ++static unsigned int vin_debug; ++module_param_named(debug, vin_debug, int, 0600); ++static int overflow_video[RCAR_VIDEO_MAX]; ++module_param_array(overflow_video, int, NULL, 0600); ++ ++#ifdef CONFIG_VIDEO_RCAR_VIN_LEGACY_DEBUG ++#define VIN_IRQ_DEBUG(fmt, args...) \ ++ do { \ ++ if (unlikely(vin_debug & VIN_UT_IRQ)) \ ++ vin_ut_debug_printk(__func__, fmt, ##args); \ ++ } while (0) ++#else ++#define VIN_IRQ_DEBUG(fmt, args...) ++#endif ++ ++void vin_ut_debug_printk(const char *function_name, const char *format, ...) ++{ ++ struct va_format vaf; ++ va_list args; ++ ++ va_start(args, format); ++ vaf.fmt = format; ++ vaf.va = &args; ++ ++ pr_debug("[" DRV_NAME ":%s] %pV", function_name, &vaf); ++ ++ va_end(args); ++} ++ ++static void rcar_vin_cpg_enable_for_ifmd(unsigned int ch, bool enable) ++{ ++ void __iomem *smstpcr8; ++ ++ smstpcr8 = ioremap(0xE6150990, 0x04); ++ ++ if (enable) { ++ if (ch < RCAR_VIDEO_4) ++ iowrite32((ioread32(smstpcr8) & 0xFFFFF7FF), smstpcr8); ++ else ++ iowrite32((ioread32(smstpcr8) & 0xFFFFFF7F), smstpcr8); ++ } else { ++ if (ch < RCAR_VIDEO_4) ++ iowrite32((ioread32(smstpcr8) | 0x00000800), smstpcr8); ++ else ++ iowrite32((ioread32(smstpcr8) | 0x00000080), smstpcr8); ++ } ++ ++ iounmap(smstpcr8); ++} ++ ++static inline int is_scaling(struct rcar_vin_cam *cam) ++{ ++ struct v4l2_rect *cam_subrect = &cam->subrect; ++ ++ if ((cam_subrect->width != cam->out_width) || ++ (cam_subrect->height != cam->out_height)) ++ return 1; ++ ++ return 0; ++} ++ ++/* ++ * .queue_setup() is called to check whether the driver can accept the requested ++ * number of buffers and to fill in plane sizes for the current frame format if ++ * required ++ */ ++static int rcar_vin_videobuf_setup(struct vb2_queue *vq, ++ unsigned int *count, ++ unsigned int *num_planes, ++ unsigned int sizes[], struct device *alloc_devs[]) ++{ ++ struct soc_camera_device *icd = soc_camera_from_vb2q(vq); ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_vin_priv *priv = ici->priv; ++ struct rcar_vin_cam *cam = icd->host_priv; ++ ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if ((priv->ratio_h > 0x10000) || (priv->ratio_v > 0x10000)) { ++ dev_err(icd->parent, "Scaling rate parameter error\n"); ++ return -EINVAL; ++ } ++ if (is_scaling(cam) && (cam->out_width % 32)) { ++ dev_err(icd->parent, "Scaling parameter error\n"); ++ return -EINVAL; ++ } ++ if (!is_scaling(cam) && (cam->out_width % 16)) { ++ dev_err(icd->parent, "Image stride parameter error\n"); ++ return -EINVAL; ++ } ++ } ++ ++ if (!vq->num_buffers) ++ priv->sequence = 0; ++ ++ if (!*count) ++ *count = 2; ++ priv->vb_count = *count; ++ ++ /* Number of hardware slots */ ++ if (is_continuous_transfer(priv)) ++ priv->nr_hw_slots = MAX_BUFFER_NUM; ++ else ++ priv->nr_hw_slots = 1; ++ ++ if (*num_planes) ++ return sizes[0] < icd->sizeimage ? -EINVAL : 0; ++ ++ sizes[0] = icd->sizeimage; ++ *num_planes = 1; ++ ++ dev_dbg(icd->parent, "count=%d, size=%u\n", *count, sizes[0]); ++ ++ return 0; ++} ++ ++static int rcar_vin_setup(struct rcar_vin_priv *priv) ++{ ++ struct soc_camera_device *icd = priv->ici.icd; ++ struct rcar_vin_cam *cam = icd->host_priv; ++ u32 vnmc, dmr, interrupts; ++ bool progressive = false, output_is_yuv = false, input_is_yuv = false; ++ ++ switch (priv->field) { ++ case V4L2_FIELD_TOP: ++ vnmc = VNMC_IM_ODD; ++ break; ++ case V4L2_FIELD_BOTTOM: ++ vnmc = VNMC_IM_EVEN; ++ break; ++ case V4L2_FIELD_INTERLACED: ++ case V4L2_FIELD_INTERLACED_TB: ++ vnmc = VNMC_IM_FULL; ++ break; ++ case V4L2_FIELD_INTERLACED_BT: ++ vnmc = VNMC_IM_FULL | VNMC_FOC; ++ break; ++ case V4L2_FIELD_NONE: ++ if (is_continuous_transfer(priv)) { ++ vnmc = VNMC_IM_ODD_EVEN; ++ progressive = true; ++ } else { ++ vnmc = VNMC_IM_ODD; ++ } ++ break; ++ default: ++ vnmc = VNMC_IM_ODD; ++ break; ++ } ++ ++ /* input interface */ ++ switch (icd->current_fmt->code) { ++ case MEDIA_BUS_FMT_YUYV8_1X16: ++ /* BT.601/BT.1358 16bit YCbCr422 */ ++ vnmc |= VNMC_INF_YUV16; ++ input_is_yuv = true; ++ break; ++ case MEDIA_BUS_FMT_YUYV8_2X8: ++ /* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */ ++ vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ? ++ VNMC_INF_YUV8_BT656 : VNMC_INF_YUV8_BT601; ++ input_is_yuv = true; ++ break; ++ case MEDIA_BUS_FMT_RGB888_1X24: ++ vnmc |= VNMC_INF_RGB888; ++ break; ++ case MEDIA_BUS_FMT_YUYV10_2X10: ++ /* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */ ++ vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ? ++ VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601; ++ input_is_yuv = true; ++ break; ++ default: ++ break; ++ } ++ ++ /* output format */ ++ switch (icd->current_fmt->host_fmt->fourcc) { ++ case V4L2_PIX_FMT_NV12: ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ iowrite32(ALIGN((cam->out_width * cam->out_height), ++ 0x80), priv->base + VNUVAOF_REG); ++ dmr = VNDMR_DTMD_YCSEP_YCBCR420; ++ output_is_yuv = true; ++ } else { ++ dev_warn(icd->parent, "Not support format\n"); ++ return -EINVAL; ++ } ++ break; ++ case V4L2_PIX_FMT_NV16: ++ iowrite32(ALIGN((cam->out_width * cam->out_height), 0x80), ++ priv->base + VNUVAOF_REG); ++ dmr = VNDMR_DTMD_YCSEP; ++ output_is_yuv = true; ++ break; ++ case V4L2_PIX_FMT_YUYV: ++ dmr = VNDMR_BPSM; ++ output_is_yuv = true; ++ break; ++ case V4L2_PIX_FMT_UYVY: ++ dmr = 0; ++ output_is_yuv = true; ++ break; ++ case V4L2_PIX_FMT_ARGB555: ++ dmr = VNDMR_DTMD_ARGB; ++ break; ++ case V4L2_PIX_FMT_RGB565: ++ dmr = 0; ++ break; ++ case V4L2_PIX_FMT_XBGR32: ++ if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3 && ++ priv->chip != RCAR_GEN2 && priv->chip != RCAR_H1 && ++ priv->chip != RCAR_E1) ++ goto e_format; ++ ++ dmr = VNDMR_EXRGB; ++ break; ++ case V4L2_PIX_FMT_ABGR32: ++ if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3) ++ goto e_format; ++ ++ dmr = VNDMR_EXRGB | VNDMR_DTMD_ARGB; ++ break; ++ default: ++ goto e_format; ++ } ++ ++ /* Always update on field change */ ++ vnmc |= VNMC_VUP; ++ ++ /* If input and output use the same colorspace, use bypass mode */ ++ if (input_is_yuv == output_is_yuv) ++ vnmc |= VNMC_BPS; ++ ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->pdata_flags & RCAR_VIN_CSI2) ++ vnmc &= ~VNMC_DPINE; ++ else ++ vnmc |= VNMC_DPINE; ++ ++ if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12) ++ && is_scaling(cam)) ++ vnmc |= VNMC_SCLE; ++ } ++ ++ /* progressive or interlaced mode */ ++ interrupts = progressive ? VNIE_FIE : VNIE_EFE; ++ ++ /* Enable Overflow */ ++ if (vin_debug) ++ interrupts |= VNIE_FOE; ++ ++ /* ack interrupts */ ++ iowrite32(interrupts, priv->base + VNINTS_REG); ++ /* enable interrupts */ ++ iowrite32(interrupts, priv->base + VNIE_REG); ++ /* start capturing */ ++ iowrite32(dmr, priv->base + VNDMR_REG); ++ iowrite32(vnmc | VNMC_ME, priv->base + VNMC_REG); ++ ++ return 0; ++ ++e_format: ++ dev_warn(icd->parent, "Invalid fourcc format (0x%x)\n", ++ icd->current_fmt->host_fmt->fourcc); ++ return -EINVAL; ++} ++ ++static void rcar_vin_capture(struct rcar_vin_priv *priv) ++{ ++ if (is_continuous_transfer(priv)) ++ /* Continuous Frame Capture Mode */ ++ iowrite32(VNFC_C_FRAME, priv->base + VNFC_REG); ++ else ++ /* Single Frame Capture Mode */ ++ iowrite32(VNFC_S_FRAME, priv->base + VNFC_REG); ++} ++ ++static void rcar_vin_request_capture_stop(struct rcar_vin_priv *priv) ++{ ++ priv->state = STOPPING; ++ ++ /* set continuous & single transfer off */ ++ iowrite32(0, priv->base + VNFC_REG); ++ /* disable capture (release DMA buffer), reset */ ++ iowrite32(ioread32(priv->base + VNMC_REG) & ~VNMC_ME, ++ priv->base + VNMC_REG); ++ ++ /* update the status if stopped already */ ++ if (!(ioread32(priv->base + VNMS_REG) & VNMS_CA)) ++ priv->state = STOPPED; ++} ++ ++static int rcar_vin_get_free_hw_slot(struct rcar_vin_priv *priv) ++{ ++ int slot; ++ ++ for (slot = 0; slot < priv->nr_hw_slots; slot++) ++ if (priv->queue_buf[slot] == NULL) ++ return slot; ++ ++ return -1; ++} ++ ++static int rcar_vin_hw_ready(struct rcar_vin_priv *priv) ++{ ++ /* Ensure all HW slots are filled */ ++ return rcar_vin_get_free_hw_slot(priv) < 0 ? 1 : 0; ++} ++ ++/* Moves a buffer from the queue to the HW slots */ ++static int rcar_vin_fill_hw_slot(struct rcar_vin_priv *priv) ++{ ++ struct vb2_v4l2_buffer *vbuf; ++ dma_addr_t phys_addr_top; ++ int slot; ++ ++ if (list_empty(&priv->capture)) ++ return 0; ++ ++ /* Find a free HW slot */ ++ slot = rcar_vin_get_free_hw_slot(priv); ++ if (slot < 0) ++ return 0; ++ ++ vbuf = &list_entry(priv->capture.next, ++ struct rcar_vin_buffer, list)->vb; ++ list_del_init(to_buf_list(vbuf)); ++ priv->queue_buf[slot] = vbuf; ++ phys_addr_top = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0); ++ iowrite32(phys_addr_top, priv->base + VNMB_REG(slot)); ++ ++ return 1; ++} ++ ++static void rcar_vin_videobuf_queue(struct vb2_buffer *vb) ++{ ++ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); ++ struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_vin_priv *priv = ici->priv; ++ unsigned long size; ++ ++ size = icd->sizeimage; ++ ++ if (vb2_plane_size(vb, 0) < size) { ++ dev_err(icd->parent, "Buffer #%d too small (%lu < %lu)\n", ++ vb->index, vb2_plane_size(vb, 0), size); ++ goto error; ++ } ++ ++ vb2_set_plane_payload(vb, 0, size); ++ ++ dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, ++ vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); ++ ++ spin_lock_irq(&priv->lock); ++ ++ list_add_tail(to_buf_list(vbuf), &priv->capture); ++ rcar_vin_fill_hw_slot(priv); ++ ++ /* If we weren't running, and have enough buffers, start capturing! */ ++ if (priv->state != RUNNING && rcar_vin_hw_ready(priv)) { ++ if (rcar_vin_setup(priv)) { ++ /* Submit error */ ++ list_del_init(to_buf_list(vbuf)); ++ spin_unlock_irq(&priv->lock); ++ goto error; ++ } ++ priv->request_to_stop = false; ++ init_completion(&priv->capture_stop); ++ priv->state = RUNNING; ++ rcar_vin_capture(priv); ++ } ++ ++ spin_unlock_irq(&priv->lock); ++ ++ return; ++ ++error: ++ vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); ++} ++ ++/* ++ * Wait for capture to stop and all in-flight buffers to be finished with by ++ * the video hardware. This must be called under &priv->lock ++ * ++ */ ++static void rcar_vin_wait_stop_streaming(struct rcar_vin_priv *priv) ++{ ++ while (priv->state != STOPPED) { ++ /* issue stop if running */ ++ if (priv->state == RUNNING) ++ rcar_vin_request_capture_stop(priv); ++ ++ /* wait until capturing has been stopped */ ++ if (priv->state == STOPPING) { ++ priv->request_to_stop = true; ++ spin_unlock_irq(&priv->lock); ++ if (!wait_for_completion_timeout( ++ &priv->capture_stop, ++ msecs_to_jiffies(TIMEOUT_MS))) ++ priv->state = STOPPED; ++ spin_lock_irq(&priv->lock); ++ } ++ } ++} ++ ++static void rcar_vin_stop_streaming(struct vb2_queue *vq) ++{ ++ struct soc_camera_device *icd = soc_camera_from_vb2q(vq); ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_vin_priv *priv = ici->priv; ++ struct list_head *buf_head, *tmp; ++ int i; ++ ++ spin_lock_irq(&priv->lock); ++ rcar_vin_wait_stop_streaming(priv); ++ ++ for (i = 0; i < MAX_BUFFER_NUM; i++) { ++ if (priv->queue_buf[i]) { ++ vb2_buffer_done(&priv->queue_buf[i]->vb2_buf, ++ VB2_BUF_STATE_ERROR); ++ priv->queue_buf[i] = NULL; ++ } ++ } ++ ++ list_for_each_safe(buf_head, tmp, &priv->capture) { ++ vb2_buffer_done(&list_entry(buf_head, ++ struct rcar_vin_buffer, list)->vb.vb2_buf, ++ VB2_BUF_STATE_ERROR); ++ list_del_init(buf_head); ++ } ++ spin_unlock_irq(&priv->lock); ++} ++ ++static const struct vb2_ops rcar_vin_vb2_ops = { ++ .queue_setup = rcar_vin_videobuf_setup, ++ .buf_queue = rcar_vin_videobuf_queue, ++ .stop_streaming = rcar_vin_stop_streaming, ++ .wait_prepare = vb2_ops_wait_prepare, ++ .wait_finish = vb2_ops_wait_finish, ++}; ++ ++static irqreturn_t rcar_vin_irq(int irq, void *data) ++{ ++ struct rcar_vin_priv *priv = data; ++ u32 int_status; ++ bool can_run = false, hw_stopped; ++ int slot; ++ unsigned int handled = 0; ++ int vin_ovr_cnt = 0; ++ ++ spin_lock(&priv->lock); ++ ++ int_status = ioread32(priv->base + VNINTS_REG); ++ if (!int_status) ++ goto done; ++ ++ /* ack interrupts */ ++ iowrite32(int_status, priv->base + VNINTS_REG); ++ handled = 1; ++ ++ /* overflow occurs */ ++ if (vin_debug && (int_status & VNINTS_FOS)) { ++ vin_ovr_cnt = ++overflow_video[priv->index]; ++ VIN_IRQ_DEBUG("overflow occurrs num[%d] at VIN (%s)\n", ++ vin_ovr_cnt, dev_name(priv->ici.v4l2_dev.dev)); ++ } ++ ++ /* nothing to do if capture status is 'STOPPED' */ ++ if (priv->state == STOPPED) ++ goto done; ++ ++ hw_stopped = !(ioread32(priv->base + VNMS_REG) & VNMS_CA); ++ ++ if (!priv->request_to_stop) { ++ if (is_continuous_transfer(priv)) ++ slot = (ioread32(priv->base + VNMS_REG) & ++ VNMS_FBS_MASK) >> VNMS_FBS_SHIFT; ++ else ++ slot = 0; ++ ++ if (!is_continuous_transfer(priv) || ((priv->state == RUNNING) ++ && !list_empty(&priv->capture))) { ++ priv->queue_buf[slot]->field = priv->field; ++ priv->queue_buf[slot]->sequence = priv->sequence++; ++ priv->queue_buf[slot]->vb2_buf.timestamp = ++ ktime_get_ns(); ++ vb2_buffer_done(&priv->queue_buf[slot]->vb2_buf, ++ VB2_BUF_STATE_DONE); ++ priv->queue_buf[slot] = NULL; ++ ++ can_run = rcar_vin_fill_hw_slot(priv); ++ } ++ ++ if (is_continuous_transfer(priv)) { ++ if (hw_stopped) ++ priv->state = STOPPED; ++ else if (list_empty(&priv->capture) && ++ priv->state == RUNNING) ++ /* ++ * The continuous capturing requires an ++ * explicit stop operation when there is no ++ * buffer to be set into the VnMBm registers. ++ */ ++ rcar_vin_request_capture_stop(priv); ++ } else { ++ if (can_run) ++ rcar_vin_capture(priv); ++ else ++ priv->state = STOPPED; ++ } ++ } else if (hw_stopped) { ++ priv->state = STOPPED; ++ priv->request_to_stop = false; ++ complete(&priv->capture_stop); ++ } ++ ++done: ++ spin_unlock(&priv->lock); ++ ++ return IRQ_RETVAL(handled); ++} ++ ++static struct v4l2_subdev *find_csi2(struct rcar_vin_priv *pcdev) ++{ ++ struct v4l2_subdev *sd; ++ char name[] = "rcar_csi2"; ++ ++ v4l2_device_for_each_subdev(sd, &pcdev->ici.v4l2_dev) { ++ if (!strncmp(name, sd->name, sizeof(name) - 1)) { ++ pcdev->csi2_sd = sd; ++ return sd; ++ } ++ } ++ ++ return NULL; ++} ++ ++static int rcar_vin_add_device(struct soc_camera_device *icd) ++{ ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_vin_priv *priv = ici->priv; ++ int i; ++ ++ for (i = 0; i < MAX_BUFFER_NUM; i++) ++ priv->queue_buf[i] = NULL; ++ ++ pm_runtime_get_sync(ici->v4l2_dev.dev); ++ ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ struct v4l2_subdev *csi2_sd = find_csi2(priv); ++ int ret; ++ ++ if (csi2_sd) { ++ csi2_sd->grp_id = soc_camera_grp_id(icd); ++ v4l2_set_subdev_hostdata(csi2_sd, icd); ++ ++ ret = v4l2_subdev_call(csi2_sd, core, s_power, 1); ++ priv->csi_sync = true; ++ ++ if (ret < 0 && ret != -EINVAL) ++ priv->csi_sync = false; ++ ++ if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) ++ return ret; ++ } ++ /* ++ * -ENODEV is special: ++ * either csi2_sd == NULL or the CSI-2 driver ++ * has not found this soc-camera device among its clients ++ */ ++ if (csi2_sd && ret == -ENODEV) ++ csi2_sd->grp_id = 0; ++ ++ dev_dbg(icd->parent, ++ "R-Car VIN/CSI-2 driver attached to camera %d\n", ++ icd->devnum); ++ ++ } else ++ dev_dbg(icd->parent, "R-Car VIN driver attached to camera %d\n", ++ icd->devnum); ++ ++ priv->error_flag = false; ++ ++ return 0; ++} ++ ++static void rcar_vin_remove_device(struct soc_camera_device *icd) ++{ ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_vin_priv *priv = ici->priv; ++ struct vb2_v4l2_buffer *vbuf; ++ struct v4l2_subdev *csi2_sd = find_csi2(priv); ++ int i; ++ ++ /* disable capture, disable interrupts */ ++ iowrite32(ioread32(priv->base + VNMC_REG) & ~VNMC_ME, ++ priv->base + VNMC_REG); ++ iowrite32(0, priv->base + VNIE_REG); ++ ++ priv->state = STOPPED; ++ priv->request_to_stop = false; ++ priv->error_flag = false; ++ ++ /* make sure active buffer is cancelled */ ++ spin_lock_irq(&priv->lock); ++ for (i = 0; i < MAX_BUFFER_NUM; i++) { ++ vbuf = priv->queue_buf[i]; ++ if (vbuf) { ++ list_del_init(to_buf_list(vbuf)); ++ vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_ERROR); ++ } ++ } ++ spin_unlock_irq(&priv->lock); ++ ++ pm_runtime_put(ici->v4l2_dev.dev); ++ ++ if ((csi2_sd) && (priv->csi_sync)) ++ v4l2_subdev_call(csi2_sd, core, s_power, 0); ++ ++ dev_dbg(icd->parent, "R-Car VIN driver detached from camera %d\n", ++ icd->devnum); ++} ++ ++struct rcar_vin_uds_regs { ++ unsigned long ctrl; ++ unsigned long scale; ++ unsigned long pass_bwidth; ++ unsigned long clip_size; ++}; ++ ++static unsigned long rcar_vin_get_bwidth(unsigned long ratio) ++{ ++ unsigned long bwidth; ++ unsigned long mant, frac; ++ ++ mant = (ratio & 0xF000) >> 12; ++ frac = ratio & 0x0FFF; ++ if (mant) ++ bwidth = 64 * 4096 * mant / (4096 * mant + frac); ++ else ++ bwidth = 64; ++ ++ return bwidth; ++} ++ ++static unsigned long rcar_vin_compute_ratio(unsigned int input, ++ unsigned int output) ++{ ++ return ((input * 4096 / output) == 0x10000) ? ++ 0xFFFF : (input * 4096 / output); ++} ++ ++int rcar_vin_uds_set(struct rcar_vin_priv *priv, struct rcar_vin_cam *cam) ++{ ++ struct rcar_vin_uds_regs regs; ++ unsigned long ratio_h, ratio_v; ++ unsigned long bwidth_h, bwidth_v; ++ unsigned long ctrl; ++ unsigned long clip_size; ++ struct v4l2_rect *cam_subrect = &cam->subrect; ++ u32 vnmc; ++ ++ ratio_h = rcar_vin_compute_ratio(cam_subrect->width, cam->out_width); ++ ratio_v = rcar_vin_compute_ratio(cam_subrect->height, cam->out_height); ++ ++ priv->ratio_h = ratio_h; ++ priv->ratio_v = ratio_v; ++ ++ bwidth_h = rcar_vin_get_bwidth(ratio_h); ++ bwidth_v = rcar_vin_get_bwidth(ratio_v); ++ ++ ctrl = VNUDS_CTRL_AMD; ++ ++ if (priv->field == V4L2_FIELD_NONE) ++ clip_size = (cam->out_width << 16) | (cam->out_height); ++ else ++ clip_size = (cam->out_width << 16) | (cam->out_height / 2); ++ ++ regs.ctrl = ctrl; ++ regs.scale = (ratio_h << 16) | ratio_v; ++ regs.pass_bwidth = (bwidth_h << 16) | bwidth_v; ++ regs.clip_size = clip_size; ++ ++ vnmc = ioread32(priv->base + VNMC_REG); ++ iowrite32(vnmc | VNMC_SCLE, priv->base + VNMC_REG); ++ iowrite32(regs.ctrl, priv->base + VNUDS_CTRL_REG); ++ iowrite32(regs.scale, priv->base + VNUDS_SCALE_REG); ++ iowrite32(regs.pass_bwidth, priv->base + VNUDS_PASS_BWIDTH_REG); ++ iowrite32(regs.clip_size, priv->base + VNUDS_CLIP_SIZE_REG); ++ ++ return 0; ++} ++ ++static void set_coeff(struct rcar_vin_priv *priv, unsigned short xs) ++{ ++ int i; ++ const struct vin_coeff *p_prev_set = NULL; ++ const struct vin_coeff *p_set = NULL; ++ ++ /* Look for suitable coefficient values */ ++ for (i = 0; i < ARRAY_SIZE(vin_coeff_set); i++) { ++ p_prev_set = p_set; ++ p_set = &vin_coeff_set[i]; ++ ++ if (xs < p_set->xs_value) ++ break; ++ } ++ ++ /* Use previous value if its XS value is closer */ ++ if (p_prev_set && p_set && ++ xs - p_prev_set->xs_value < p_set->xs_value - xs) ++ p_set = p_prev_set; ++ ++ /* Set coefficient registers */ ++ iowrite32(p_set->coeff_set[0], priv->base + VNC1A_REG); ++ iowrite32(p_set->coeff_set[1], priv->base + VNC1B_REG); ++ iowrite32(p_set->coeff_set[2], priv->base + VNC1C_REG); ++ ++ iowrite32(p_set->coeff_set[3], priv->base + VNC2A_REG); ++ iowrite32(p_set->coeff_set[4], priv->base + VNC2B_REG); ++ iowrite32(p_set->coeff_set[5], priv->base + VNC2C_REG); ++ ++ iowrite32(p_set->coeff_set[6], priv->base + VNC3A_REG); ++ iowrite32(p_set->coeff_set[7], priv->base + VNC3B_REG); ++ iowrite32(p_set->coeff_set[8], priv->base + VNC3C_REG); ++ ++ iowrite32(p_set->coeff_set[9], priv->base + VNC4A_REG); ++ iowrite32(p_set->coeff_set[10], priv->base + VNC4B_REG); ++ iowrite32(p_set->coeff_set[11], priv->base + VNC4C_REG); ++ ++ iowrite32(p_set->coeff_set[12], priv->base + VNC5A_REG); ++ iowrite32(p_set->coeff_set[13], priv->base + VNC5B_REG); ++ iowrite32(p_set->coeff_set[14], priv->base + VNC5C_REG); ++ ++ iowrite32(p_set->coeff_set[15], priv->base + VNC6A_REG); ++ iowrite32(p_set->coeff_set[16], priv->base + VNC6B_REG); ++ iowrite32(p_set->coeff_set[17], priv->base + VNC6C_REG); ++ ++ iowrite32(p_set->coeff_set[18], priv->base + VNC7A_REG); ++ iowrite32(p_set->coeff_set[19], priv->base + VNC7B_REG); ++ iowrite32(p_set->coeff_set[20], priv->base + VNC7C_REG); ++ ++ iowrite32(p_set->coeff_set[21], priv->base + VNC8A_REG); ++ iowrite32(p_set->coeff_set[22], priv->base + VNC8B_REG); ++ iowrite32(p_set->coeff_set[23], priv->base + VNC8C_REG); ++} ++ ++/* rect is guaranteed to not exceed the scaled camera rectangle */ ++static int rcar_vin_set_rect(struct soc_camera_device *icd) ++{ ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_vin_cam *cam = icd->host_priv; ++ struct rcar_vin_priv *priv = ici->priv; ++ unsigned int left_offset, top_offset; ++ unsigned char dsize = 0; ++ struct v4l2_rect *cam_subrect = &cam->subrect; ++ u32 value; ++ int ret = 0; ++ ++ dev_dbg(icd->parent, "Crop %ux%u@%u:%u\n", ++ icd->user_width, icd->user_height, cam->vin_left, cam->vin_top); ++ ++ left_offset = cam->vin_left; ++ top_offset = cam->vin_top; ++ ++ if (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_XBGR32 && ++ priv->chip == RCAR_E1) ++ dsize = 1; ++ ++ dev_dbg(icd->parent, "Cam %ux%u@%u:%u\n", ++ cam->width, cam->height, cam->vin_left, cam->vin_top); ++ dev_dbg(icd->parent, "Cam subrect %ux%u@%u:%u\n", ++ cam_subrect->width, cam_subrect->height, ++ cam_subrect->left, cam_subrect->top); ++ ++ /* Set Start/End Pixel/Line Pre-Clip */ ++ iowrite32(left_offset << dsize, priv->base + VNSPPRC_REG); ++ iowrite32((left_offset + cam_subrect->width - 1) << dsize, ++ priv->base + VNEPPRC_REG); ++ switch (priv->field) { ++ case V4L2_FIELD_INTERLACED: ++ case V4L2_FIELD_INTERLACED_TB: ++ case V4L2_FIELD_INTERLACED_BT: ++ iowrite32(top_offset / 2, priv->base + VNSLPRC_REG); ++ iowrite32((top_offset + cam_subrect->height) / 2 - 1, ++ priv->base + VNELPRC_REG); ++ break; ++ default: ++ iowrite32(top_offset, priv->base + VNSLPRC_REG); ++ iowrite32(top_offset + cam_subrect->height - 1, ++ priv->base + VNELPRC_REG); ++ break; ++ } ++ ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12) ++ && is_scaling(cam)) { ++ ret = rcar_vin_uds_set(priv, cam); ++ if (ret < 0) ++ return ret; ++ } ++ if (is_scaling(cam) || ++ (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_NV16) || ++ (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_NV12)) ++ iowrite32(ALIGN(cam->out_width, 0x20), ++ priv->base + VNIS_REG); ++ else ++ iowrite32(ALIGN(cam->out_width, 0x10), ++ priv->base + VNIS_REG); ++ } else { ++ /* Set scaling coefficient */ ++ value = 0; ++ if (cam_subrect->height != cam->out_height) ++ value = (4096 * cam_subrect->height) / cam->out_height; ++ dev_dbg(icd->parent, "YS Value: %x\n", value); ++ iowrite32(value, priv->base + VNYS_REG); ++ ++ value = 0; ++ if (cam_subrect->width != cam->out_width) ++ value = (4096 * cam_subrect->width) / cam->out_width; ++ ++ /* Horizontal upscaling is up to double size */ ++ if (value < 2048) ++ value = 2048; ++ ++ dev_dbg(icd->parent, "XS Value: %x\n", value); ++ iowrite32(value, priv->base + VNXS_REG); ++ ++ /* Horizontal upscaling is carried out */ ++ /* by scaling down from double size */ ++ if (value < 4096) ++ value *= 2; ++ ++ set_coeff(priv, value); ++ ++ /* Set Start/End Pixel/Line Post-Clip */ ++ iowrite32(0, priv->base + VNSPPOC_REG); ++ iowrite32(0, priv->base + VNSLPOC_REG); ++ iowrite32((cam->out_width - 1) << dsize, ++ priv->base + VNEPPOC_REG); ++ switch (priv->field) { ++ case V4L2_FIELD_INTERLACED: ++ case V4L2_FIELD_INTERLACED_TB: ++ case V4L2_FIELD_INTERLACED_BT: ++ iowrite32(cam->out_height / 2 - 1, ++ priv->base + VNELPOC_REG); ++ break; ++ default: ++ iowrite32(cam->out_height - 1, ++ priv->base + VNELPOC_REG); ++ break; ++ } ++ ++ iowrite32(ALIGN(cam->out_width, 0x10), priv->base + VNIS_REG); ++ } ++ ++ return ret; ++} ++ ++static void capture_stop_preserve(struct rcar_vin_priv *priv, u32 *vnmc) ++{ ++ *vnmc = ioread32(priv->base + VNMC_REG); ++ /* module disable */ ++ iowrite32(*vnmc & ~VNMC_ME, priv->base + VNMC_REG); ++} ++ ++static void capture_restore(struct rcar_vin_priv *priv, u32 vnmc) ++{ ++ unsigned long timeout = jiffies + 10 * HZ; ++ ++ /* ++ * Wait until the end of the current frame. It can take a long time, ++ * but if it has been aborted by a MRST1 reset, it should exit sooner. ++ */ ++ while ((ioread32(priv->base + VNMS_REG) & VNMS_AV) && ++ time_before(jiffies, timeout)) ++ msleep(1); ++ ++ if (time_after(jiffies, timeout)) { ++ dev_err(priv->ici.v4l2_dev.dev, ++ "Timeout waiting for frame end! Interface problem?\n"); ++ return; ++ } ++ ++ iowrite32(vnmc, priv->base + VNMC_REG); ++} ++ ++#define VIN_MBUS_FLAGS (V4L2_MBUS_MASTER | \ ++ V4L2_MBUS_PCLK_SAMPLE_RISING | \ ++ V4L2_MBUS_HSYNC_ACTIVE_HIGH | \ ++ V4L2_MBUS_HSYNC_ACTIVE_LOW | \ ++ V4L2_MBUS_VSYNC_ACTIVE_HIGH | \ ++ V4L2_MBUS_VSYNC_ACTIVE_LOW | \ ++ V4L2_MBUS_DATA_ACTIVE_HIGH) ++ ++static int rcar_vin_set_bus_param(struct soc_camera_device *icd) ++{ ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_vin_priv *priv = ici->priv; ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ struct v4l2_mbus_config cfg; ++ unsigned long common_flags; ++ u32 vnmc; ++ u32 val; ++ int ret; ++ ++ capture_stop_preserve(priv, &vnmc); ++ ++ ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg); ++ if (!ret) { ++ common_flags = soc_mbus_config_compatible(&cfg, VIN_MBUS_FLAGS); ++ if (!common_flags) { ++ dev_warn(icd->parent, ++ "MBUS flags incompatible: camera 0x%x, host 0x%x\n", ++ cfg.flags, VIN_MBUS_FLAGS); ++ return -EINVAL; ++ } ++ } else if (ret != -ENOIOCTLCMD) { ++ return ret; ++ } else { ++ common_flags = VIN_MBUS_FLAGS; ++ } ++ ++ /* Make choises, based on platform preferences */ ++ if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) && ++ (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) { ++ if (priv->pdata_flags & RCAR_VIN_HSYNC_ACTIVE_LOW) ++ common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH; ++ else ++ common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW; ++ } ++ ++ if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) && ++ (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) { ++ if (priv->pdata_flags & RCAR_VIN_VSYNC_ACTIVE_LOW) ++ common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH; ++ else ++ common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW; ++ } ++ ++ cfg.flags = common_flags; ++ ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg); ++ if (ret < 0 && ret != -ENOIOCTLCMD) ++ return ret; ++ ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (cfg.type == V4L2_MBUS_CSI2) ++ vnmc &= ~VNMC_DPINE; ++ else ++ vnmc |= VNMC_DPINE; ++ } ++ ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) ++ val = VNDMR2_FTEV; ++ else ++ val = VNDMR2_FTEV | VNDMR2_VLV(1); ++ if (!(common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) ++ val |= VNDMR2_VPS; ++ if (!(common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) ++ val |= VNDMR2_HPS; ++ iowrite32(val, priv->base + VNDMR2_REG); ++ ++ ret = rcar_vin_set_rect(icd); ++ if (ret < 0) ++ return ret; ++ ++ capture_restore(priv, vnmc); ++ ++ return 0; ++} ++ ++static int rcar_vin_try_bus_param(struct soc_camera_device *icd, ++ unsigned char buswidth) ++{ ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ struct v4l2_mbus_config cfg; ++ int ret; ++ ++ ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg); ++ if (ret == -ENOIOCTLCMD) ++ return 0; ++ else if (ret) ++ return ret; ++ ++ if (buswidth > 24) ++ return -EINVAL; ++ ++ /* check is there common mbus flags */ ++ ret = soc_mbus_config_compatible(&cfg, VIN_MBUS_FLAGS); ++ if (ret) ++ return 0; ++ ++ dev_warn(icd->parent, ++ "MBUS flags incompatible: camera 0x%x, host 0x%x\n", ++ cfg.flags, VIN_MBUS_FLAGS); ++ ++ return -EINVAL; ++} ++ ++static bool rcar_vin_packing_supported(const struct soc_mbus_pixelfmt *fmt) ++{ ++ return fmt->packing == SOC_MBUS_PACKING_NONE || ++ (fmt->bits_per_sample > 8 && ++ fmt->packing == SOC_MBUS_PACKING_EXTEND16); ++} ++ ++static const struct soc_mbus_pixelfmt rcar_vin_formats[] = { ++ { ++ .fourcc = V4L2_PIX_FMT_NV12, ++ .name = "NV12", ++ .bits_per_sample = 8, ++ .packing = SOC_MBUS_PACKING_1_5X8, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PLANAR_2Y_C, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_NV16, ++ .name = "NV16", ++ .bits_per_sample = 8, ++ .packing = SOC_MBUS_PACKING_2X8_PADHI, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PLANAR_Y_C, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_YUYV, ++ .name = "YUYV", ++ .bits_per_sample = 16, ++ .packing = SOC_MBUS_PACKING_NONE, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_UYVY, ++ .name = "UYVY", ++ .bits_per_sample = 16, ++ .packing = SOC_MBUS_PACKING_NONE, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_RGB565, ++ .name = "RGB565", ++ .bits_per_sample = 16, ++ .packing = SOC_MBUS_PACKING_NONE, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_ARGB555, ++ .name = "ARGB1555", ++ .bits_per_sample = 16, ++ .packing = SOC_MBUS_PACKING_NONE, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_XBGR32, ++ .name = "RGB888", ++ .bits_per_sample = 32, ++ .packing = SOC_MBUS_PACKING_NONE, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_ABGR32, ++ .name = "ARGB8888", ++ .bits_per_sample = 32, ++ .packing = SOC_MBUS_PACKING_NONE, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, ++}; ++ ++static int rcar_vin_get_formats(struct soc_camera_device *icd, unsigned int idx, ++ struct soc_camera_format_xlate *xlate) ++{ ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ struct device *dev = icd->parent; ++ int ret, k, n; ++ int formats = 0; ++ struct rcar_vin_cam *cam; ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_vin_priv *priv = ici->priv; ++ struct v4l2_subdev_mbus_code_enum code = { ++ .which = V4L2_SUBDEV_FORMAT_ACTIVE, ++ .index = idx, ++ }; ++ const struct soc_mbus_pixelfmt *fmt; ++ ++ ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code); ++ if (ret < 0) ++ return 0; ++ ++ fmt = soc_mbus_get_fmtdesc(code.code); ++ if (!fmt) { ++ dev_warn(dev, "unsupported format code #%u: %d\n", idx, code.code); ++ return 0; ++ } ++ ++ ret = rcar_vin_try_bus_param(icd, fmt->bits_per_sample); ++ if (ret < 0) ++ return 0; ++ ++ if (!icd->host_priv) { ++ struct v4l2_subdev_format fmt = { ++ .which = V4L2_SUBDEV_FORMAT_ACTIVE, ++ }; ++ struct v4l2_mbus_framefmt *mf = &fmt.format; ++ struct v4l2_rect rect; ++ struct device *dev = icd->parent; ++ int shift; ++ ++ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt); ++ if (ret < 0) ++ return ret; ++ ++ /* Cache current client geometry */ ++ ret = soc_camera_client_g_rect(sd, &rect); ++ if (ret == -ENOIOCTLCMD) { ++ /* Sensor driver doesn't support cropping */ ++ rect.left = 0; ++ rect.top = 0; ++ rect.width = mf->width; ++ rect.height = mf->height; ++ } else if (ret < 0) { ++ return ret; ++ } ++ ++ /* ++ * If sensor proposes too large format then try smaller ones: ++ * 1280x960, 640x480, 320x240 ++ */ ++ for (shift = 0; shift < 3; shift++) { ++ if (mf->width <= priv->max_width && ++ mf->height <= priv->max_height) ++ break; ++ ++ mf->width = 1280 >> shift; ++ mf->height = 960 >> shift; ++ ret = v4l2_device_call_until_err(sd->v4l2_dev, ++ soc_camera_grp_id(icd), ++ pad, set_fmt, NULL, ++ &fmt); ++ if (ret < 0) ++ return ret; ++ } ++ ++ if (shift == 3) { ++ dev_err(dev, ++ "Failed to configure the client below %ux%u\n", ++ mf->width, mf->height); ++ return -EIO; ++ } ++ ++ dev_dbg(dev, "camera fmt %ux%u\n", mf->width, mf->height); ++ ++ cam = kzalloc(sizeof(*cam), GFP_KERNEL); ++ if (!cam) ++ return -ENOMEM; ++ /* ++ * We are called with current camera crop, ++ * initialise subrect with it ++ */ ++ cam->rect = rect; ++ cam->subrect = rect; ++ cam->width = mf->width; ++ cam->height = mf->height; ++ cam->out_width = mf->width; ++ cam->out_height = mf->height; ++ ++ icd->host_priv = cam; ++ } else { ++ cam = icd->host_priv; ++ } ++ ++ /* Beginning of a pass */ ++ if (!idx) ++ cam->extra_fmt = NULL; ++ ++ switch (code.code) { ++ case MEDIA_BUS_FMT_YUYV8_1X16: ++ case MEDIA_BUS_FMT_YUYV8_2X8: ++ case MEDIA_BUS_FMT_YUYV10_2X10: ++ case MEDIA_BUS_FMT_RGB888_1X24: ++ if (cam->extra_fmt) ++ break; ++ ++ /* Add all our formats that can be generated by VIN */ ++ cam->extra_fmt = rcar_vin_formats; ++ ++ n = ARRAY_SIZE(rcar_vin_formats); ++ formats += n; ++ for (k = 0; xlate && k < n; k++, xlate++) { ++ xlate->host_fmt = &rcar_vin_formats[k]; ++ xlate->code = code.code; ++ dev_dbg(dev, "Providing format %s using code %d\n", ++ rcar_vin_formats[k].name, code.code); ++ } ++ break; ++ default: ++ if (!rcar_vin_packing_supported(fmt)) ++ return 0; ++ ++ dev_dbg(dev, "Providing format %s in pass-through mode\n", ++ fmt->name); ++ break; ++ } ++ ++ /* Generic pass-through */ ++ formats++; ++ if (xlate) { ++ xlate->host_fmt = fmt; ++ xlate->code = code.code; ++ xlate++; ++ } ++ ++ return formats; ++} ++ ++static void rcar_vin_put_formats(struct soc_camera_device *icd) ++{ ++ kfree(icd->host_priv); ++ icd->host_priv = NULL; ++} ++ ++static int rcar_vin_set_selection(struct soc_camera_device *icd, ++ struct v4l2_selection *sel) ++{ ++ const struct v4l2_rect *rect = &sel->r; ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_vin_priv *priv = ici->priv; ++ struct v4l2_selection cam_sel; ++ struct rcar_vin_cam *cam = icd->host_priv; ++ struct v4l2_rect *cam_rect = &cam_sel.r; ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ struct device *dev = icd->parent; ++ struct v4l2_subdev_format fmt = { ++ .which = V4L2_SUBDEV_FORMAT_ACTIVE, ++ }; ++ struct v4l2_mbus_framefmt *mf = &fmt.format; ++ u32 vnmc; ++ int ret, i; ++ ++ dev_dbg(dev, "S_SELECTION(%ux%u@%u:%u)\n", rect->width, rect->height, ++ rect->left, rect->top); ++ ++ /* During camera cropping its output window can change too, stop VIN */ ++ capture_stop_preserve(priv, &vnmc); ++ dev_dbg(dev, "VNMC_REG 0x%x\n", vnmc); ++ ++ /* Apply iterative camera S_SELECTION for new input window. */ ++ ret = soc_camera_client_s_selection(sd, sel, &cam_sel, ++ &cam->rect, &cam->subrect); ++ if (ret < 0) ++ return ret; ++ ++ dev_dbg(dev, "camera cropped to %ux%u@%u:%u\n", ++ cam_rect->width, cam_rect->height, ++ cam_rect->left, cam_rect->top); ++ ++ /* On success cam_crop contains current camera crop */ ++ ++ /* Retrieve camera output window */ ++ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt); ++ if (ret < 0) ++ return ret; ++ ++ if (mf->width > priv->max_width || mf->height > priv->max_height) ++ return -EINVAL; ++ ++ /* Cache camera output window */ ++ cam->width = mf->width; ++ cam->height = mf->height; ++ ++ cam->vin_left = rect->left; ++ cam->vin_top = rect->top; ++ ++ /* Use VIN cropping to crop to the new window. */ ++ ret = rcar_vin_set_rect(icd); ++ if (ret < 0) ++ return ret; ++ ++ dev_dbg(dev, "VIN cropped to %ux%u@%u:%u\n", ++ icd->user_width, icd->user_height, ++ cam->vin_left, cam->vin_top); ++ ++ /* Restore capture */ ++ for (i = 0; i < MAX_BUFFER_NUM; i++) { ++ if (priv->queue_buf[i] && priv->state == STOPPED) { ++ vnmc |= VNMC_ME; ++ break; ++ } ++ } ++ capture_restore(priv, vnmc); ++ ++ /* Even if only camera cropping succeeded */ ++ return ret; ++} ++ ++static int rcar_vin_get_selection(struct soc_camera_device *icd, ++ struct v4l2_selection *sel) ++{ ++ struct rcar_vin_cam *cam = icd->host_priv; ++ ++ sel->r = cam->subrect; ++ ++ return 0; ++} ++ ++/* Similar to set_crop multistage iterative algorithm */ ++static int rcar_vin_set_fmt(struct soc_camera_device *icd, ++ struct v4l2_format *f) ++{ ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_vin_priv *priv = ici->priv; ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ struct rcar_vin_cam *cam = icd->host_priv; ++ struct v4l2_pix_format *pix = &f->fmt.pix; ++ struct v4l2_mbus_framefmt mf; ++ struct device *dev = icd->parent; ++ __u32 pixfmt = pix->pixelformat; ++ const struct soc_camera_format_xlate *xlate; ++ unsigned int vin_sub_width = 0, vin_sub_height = 0; ++ int ret; ++ bool can_scale; ++ enum v4l2_field field; ++ v4l2_std_id std; ++ ++ dev_dbg(dev, "S_FMT(pix=0x%x, %ux%u)\n", ++ pixfmt, pix->width, pix->height); ++ ++ /* At the time of NV16 capture format, the user has to specify */ ++ /* the width of the multiple of 32 for H/W specification. */ ++ if (priv->error_flag == false) ++ priv->error_flag = true; ++ else { ++ if (((pixfmt == V4L2_PIX_FMT_NV16) || ++ (pixfmt == V4L2_PIX_FMT_NV12)) && ++ (pix->width & 0x1F)) { ++ dev_dbg(icd->parent, ++ "specify width of 32 multiple in separate format.\n"); ++ return -EINVAL; ++ } ++ } ++ ++ switch (pix->field) { ++ default: ++ pix->field = V4L2_FIELD_NONE; ++ /* fall-through */ ++ case V4L2_FIELD_NONE: ++ case V4L2_FIELD_TOP: ++ case V4L2_FIELD_BOTTOM: ++ case V4L2_FIELD_INTERLACED_TB: ++ case V4L2_FIELD_INTERLACED_BT: ++ field = pix->field; ++ break; ++ case V4L2_FIELD_INTERLACED: ++ /* Query for standard if not explicitly mentioned _TB/_BT */ ++ ret = v4l2_subdev_call(sd, video, querystd, &std); ++ if (ret == -ENOIOCTLCMD) { ++ field = V4L2_FIELD_NONE; ++ } else if (ret < 0) { ++ return ret; ++ } else { ++ field = std & V4L2_STD_625_50 ? ++ V4L2_FIELD_INTERLACED_TB : ++ V4L2_FIELD_INTERLACED_BT; ++ } ++ break; ++ } ++ ++ xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); ++ if (!xlate) { ++ dev_warn(dev, "Format %x not found\n", pixfmt); ++ return -EINVAL; ++ } ++ /* Calculate client output geometry */ ++ soc_camera_calc_client_output(icd, &cam->rect, &cam->subrect, pix, &mf, ++ 12); ++ mf.field = pix->field; ++ mf.colorspace = pix->colorspace; ++ mf.code = xlate->code; ++ ++ switch (pixfmt) { ++ case V4L2_PIX_FMT_XBGR32: ++ can_scale = priv->chip != RCAR_E1; ++ break; ++ case V4L2_PIX_FMT_ABGR32: ++ case V4L2_PIX_FMT_UYVY: ++ case V4L2_PIX_FMT_YUYV: ++ case V4L2_PIX_FMT_RGB565: ++ case V4L2_PIX_FMT_ARGB555: ++ case V4L2_PIX_FMT_NV16: ++ can_scale = true; ++ break; ++ case V4L2_PIX_FMT_NV12: ++ default: ++ can_scale = false; ++ break; ++ } ++ ++ dev_dbg(dev, "request camera output %ux%u\n", mf.width, mf.height); ++ ++ ret = soc_camera_client_scale(icd, &cam->rect, &cam->subrect, ++ &mf, &vin_sub_width, &vin_sub_height, ++ can_scale, 12); ++ ++ /* Done with the camera. Now see if we can improve the result */ ++ dev_dbg(dev, "Camera %d fmt %ux%u, requested %ux%u\n", ++ ret, mf.width, mf.height, pix->width, pix->height); ++ ++ if (ret == -ENOIOCTLCMD) ++ dev_dbg(dev, "Sensor doesn't support scaling\n"); ++ else if (ret < 0) ++ return ret; ++ ++ if (mf.code != xlate->code) ++ return -EINVAL; ++ ++ /* Prepare VIN crop */ ++ cam->width = mf.width; ++ cam->height = mf.height; ++ ++ /* Use VIN scaling to scale to the requested user window. */ ++ ++ /* We cannot scale up */ ++ if (pix->width > vin_sub_width) ++ vin_sub_width = pix->width; ++ ++ if (pix->height > vin_sub_height) ++ vin_sub_height = pix->height; ++ ++ pix->colorspace = mf.colorspace; ++ ++ if (!can_scale) { ++ pix->width = vin_sub_width; ++ pix->height = vin_sub_height; ++ } ++ ++ /* ++ * We have calculated CFLCR, the actual configuration will be performed ++ * in rcar_vin_set_bus_param() ++ */ ++ ++ dev_dbg(dev, "W: %u : %u, H: %u : %u\n", ++ vin_sub_width, pix->width, vin_sub_height, pix->height); ++ ++ cam->out_width = pix->width; ++ cam->out_height = pix->height; ++ ++ icd->current_fmt = xlate; ++ ++ priv->field = field; ++ ++ return 0; ++} ++ ++static int rcar_vin_try_fmt(struct soc_camera_device *icd, ++ struct v4l2_format *f) ++{ ++ const struct soc_camera_format_xlate *xlate; ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_vin_priv *priv = ici->priv; ++ struct v4l2_pix_format *pix = &f->fmt.pix; ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ struct v4l2_subdev_pad_config pad_cfg; ++ struct v4l2_subdev_format format = { ++ .which = V4L2_SUBDEV_FORMAT_TRY, ++ }; ++ struct v4l2_mbus_framefmt *mf = &format.format; ++ __u32 pixfmt = pix->pixelformat; ++ int width, height; ++ int ret; ++ ++ xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); ++ if (!xlate) { ++ xlate = icd->current_fmt; ++ dev_dbg(icd->parent, "Format %x not found, keeping %x\n", ++ pixfmt, xlate->host_fmt->fourcc); ++ pixfmt = xlate->host_fmt->fourcc; ++ pix->pixelformat = pixfmt; ++ pix->colorspace = icd->colorspace; ++ } ++ ++ /* When performing a YCbCr-422 format output, even if it performs */ ++ /* odd number clipping by pixel post clip processing, */ ++ /* it is outputted to a memory per even pixels. */ ++ if ((pixfmt == V4L2_PIX_FMT_NV16) || (pixfmt == V4L2_PIX_FMT_NV12) || ++ (pixfmt == V4L2_PIX_FMT_YUYV) || (pixfmt == V4L2_PIX_FMT_UYVY)) ++ v4l_bound_align_image(&pix->width, 5, priv->max_width, 1, ++ &pix->height, 2, priv->max_height, 0, 0); ++ else ++ v4l_bound_align_image(&pix->width, 5, priv->max_width, 0, ++ &pix->height, 2, priv->max_height, 0, 0); ++ ++ width = pix->width; ++ height = pix->height; ++ ++ /* let soc-camera calculate these values */ ++ pix->bytesperline = 0; ++ pix->sizeimage = 0; ++ ++ /* limit to sensor capabilities */ ++ mf->width = pix->width; ++ mf->height = pix->height; ++ mf->field = pix->field; ++ mf->code = xlate->code; ++ mf->colorspace = pix->colorspace; ++ ++ ret = v4l2_device_call_until_err(sd->v4l2_dev, soc_camera_grp_id(icd), ++ pad, set_fmt, &pad_cfg, &format); ++ if (ret < 0) ++ return ret; ++ ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ /* Adjust max scaling size for Gen3 */ ++ if (pix->width > 4096) ++ pix->width = priv->max_width; ++ if (pix->height > 4096) ++ pix->height = priv->max_height; ++ } else { ++ /* Adjust only if VIN cannot scale */ ++ if (pix->width > mf->width * 2) ++ pix->width = mf->width * 2; ++ if (pix->height > mf->height * 3) ++ pix->height = mf->height * 3; ++ } ++ ++ pix->field = mf->field; ++ pix->colorspace = mf->colorspace; ++ ++ if (pixfmt == V4L2_PIX_FMT_NV16) { ++ /* FIXME: check against rect_max after converting soc-camera */ ++ /* We can scale precisely, need a bigger image from camera */ ++ if (pix->width < width || pix->height < height) { ++ /* ++ * We presume, the sensor behaves sanely, i.e. if ++ * requested a bigger rectangle, it will not return a ++ * smaller one. ++ */ ++ mf->width = priv->max_width; ++ mf->height = priv->max_height; ++ ret = v4l2_device_call_until_err(sd->v4l2_dev, ++ soc_camera_grp_id(icd), ++ pad, set_fmt, &pad_cfg, ++ &format); ++ if (ret < 0) { ++ dev_err(icd->parent, ++ "client try_fmt() = %d\n", ret); ++ return ret; ++ } ++ } ++ /* We will scale exactly */ ++ if (mf->width > width) ++ pix->width = width; ++ if (mf->height > height) ++ pix->height = height; ++ } ++ ++ return ret; ++} ++ ++static unsigned int rcar_vin_poll(struct file *file, poll_table *pt) ++{ ++ struct soc_camera_device *icd = file->private_data; ++ ++ return vb2_poll(&icd->vb2_vidq, file, pt); ++} ++ ++static int rcar_vin_querycap(struct soc_camera_host *ici, ++ struct v4l2_capability *cap) ++{ ++ strlcpy(cap->card, "R_Car_VIN", sizeof(cap->card)); ++ cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; ++ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; ++ snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s%d", DRV_NAME, ici->nr); ++ ++ return 0; ++} ++ ++static int rcar_vin_init_videobuf2(struct vb2_queue *vq, ++ struct soc_camera_device *icd) ++{ ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ ++ vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; ++ vq->drv_priv = icd; ++ vq->ops = &rcar_vin_vb2_ops; ++ vq->mem_ops = &vb2_dma_contig_memops; ++ vq->buf_struct_size = sizeof(struct rcar_vin_buffer); ++ vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; ++ vq->lock = &ici->host_lock; ++ vq->dev = ici->v4l2_dev.dev; ++ ++ return vb2_queue_init(vq); ++} ++ ++#if 0 ++static int rcar_vin_get_selection(struct soc_camera_device *icd, ++ struct v4l2_selection *sel) ++{ ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ struct v4l2_subdev_format fmt = { ++ .which = V4L2_SUBDEV_FORMAT_ACTIVE, ++ }; ++ struct v4l2_mbus_framefmt *mf = &fmt.format; ++ int ret; ++ ++ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt); ++ if (ret < 0) ++ return ret; ++ ++ if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = sel->r.top = 0; ++ sel->r.width = mf->width; ++ sel->r.height = mf->height; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int rcar_vin_cropcap(struct soc_camera_device *icd, ++ struct v4l2_cropcap *crop) ++{ ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ struct v4l2_subdev_format fmt = { ++ .which = V4L2_SUBDEV_FORMAT_ACTIVE, ++ }; ++ struct v4l2_mbus_framefmt *mf = &fmt.format; ++ int ret; ++ ++ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt); ++ if (ret < 0) ++ return ret; ++ ++ crop->bounds.left = 0; ++ crop->bounds.top = 0; ++ crop->bounds.width = mf->width; ++ crop->bounds.height = mf->height; ++ ++ /* default cropping rectangle */ ++ crop->defrect = crop->bounds; ++ crop->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ ++ return 0; ++} ++#endif ++ ++static struct soc_camera_host_ops rcar_vin_host_ops = { ++ .owner = THIS_MODULE, ++ .add = rcar_vin_add_device, ++ .remove = rcar_vin_remove_device, ++ .get_formats = rcar_vin_get_formats, ++ .put_formats = rcar_vin_put_formats, ++ .get_selection = rcar_vin_get_selection, ++ .set_selection = rcar_vin_set_selection, ++ .try_fmt = rcar_vin_try_fmt, ++ .set_fmt = rcar_vin_set_fmt, ++ .poll = rcar_vin_poll, ++ .querycap = rcar_vin_querycap, ++ .set_bus_param = rcar_vin_set_bus_param, ++ .init_videobuf2 = rcar_vin_init_videobuf2, ++#if 0 ++ .get_selection = rcar_vin_get_selection, ++ .cropcap = rcar_vin_cropcap, ++#endif ++}; ++ ++#ifdef CONFIG_OF ++static const struct of_device_id rcar_vin_of_table[] = { ++ { .compatible = "renesas,vin-r8a7796", .data = (void *)RCAR_M3 }, ++ { .compatible = "renesas,vin-r8a7795", .data = (void *)RCAR_H3 }, ++ { .compatible = "renesas,vin-r8a7794", .data = (void *)RCAR_GEN2 }, ++ { .compatible = "renesas,vin-r8a7793", .data = (void *)RCAR_GEN2 }, ++ { .compatible = "renesas,vin-r8a7791", .data = (void *)RCAR_GEN2 }, ++ { .compatible = "renesas,vin-r8a7790", .data = (void *)RCAR_GEN2 }, ++ { .compatible = "renesas,vin-r8a7779", .data = (void *)RCAR_H1 }, ++ { .compatible = "renesas,vin-r8a7778", .data = (void *)RCAR_M1 }, ++ { .compatible = "renesas,rcar-gen3-vin", .data = (void *)RCAR_GEN3 }, ++ { .compatible = "renesas,rcar-gen2-vin", .data = (void *)RCAR_GEN2 }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, rcar_vin_of_table); ++#endif ++ ++#define MAP_MAX_NUM 32 ++static DECLARE_BITMAP(device_map, MAP_MAX_NUM); ++static DEFINE_MUTEX(list_lock); ++ ++static int rcar_vin_dyn_pdev(struct soc_camera_desc *sdesc, ++ struct rcar_vin_async_client *sasc) ++{ ++ struct platform_device *pdev; ++ int ret, i; ++ ++ mutex_lock(&list_lock); ++ i = find_first_zero_bit(device_map, MAP_MAX_NUM); ++ if (i < MAP_MAX_NUM) ++ set_bit(i, device_map); ++ mutex_unlock(&list_lock); ++ if (i >= MAP_MAX_NUM) ++ return -ENOMEM; ++ ++ pdev = platform_device_alloc("soc-camera-pdrv", ((2 * i) + 1)); ++ if (!pdev) ++ return -ENOMEM; ++ ++ ret = platform_device_add_data(pdev, sdesc, sizeof(*sdesc)); ++ if (ret < 0) { ++ platform_device_put(pdev); ++ return ret; ++ } ++ ++ sasc->pdev = pdev; ++ ++ return 0; ++} ++ ++static int rcar_vin_async_bound(struct v4l2_async_notifier *notifier, ++ struct v4l2_subdev *sd, ++ struct v4l2_async_subdev *asd) ++{ ++ /* None. */ ++ return 0; ++} ++ ++static void rcar_vin_async_unbind(struct v4l2_async_notifier *notifier, ++ struct v4l2_subdev *sd, ++ struct v4l2_async_subdev *asd) ++{ ++ /* None. */ ++} ++ ++static int rcar_vin_async_probe(struct soc_camera_host *ici, ++ struct soc_camera_device *icd) ++{ ++ struct soc_camera_desc *sdesc = to_soc_camera_desc(icd); ++ struct soc_camera_host_desc *shd = &sdesc->host_desc; ++ struct device *control = NULL; ++ int ret; ++ ++ ret = v4l2_ctrl_handler_init(&icd->ctrl_handler, 16); ++ if (ret < 0) ++ return ret; ++ ++ if (shd->module_name) ++ ret = request_module(shd->module_name); ++ ++ ret = shd->add_device(icd); ++ ++ control = to_soc_camera_control(icd); ++ if (!control || !control->driver || !dev_get_drvdata(control) || ++ !try_module_get(control->driver->owner)) { ++ shd->del_device(icd); ++ ret = -ENODEV; ++ } ++ ++ return ret; ++} ++ ++static int rcar_vin_async_complete(struct v4l2_async_notifier *notifier) ++{ ++ struct rcar_vin_async_client *sasc = container_of(notifier, ++ struct rcar_vin_async_client, notifier); ++ struct soc_camera_device *icd = platform_get_drvdata(sasc->pdev); ++ ++ if (to_soc_camera_control(icd)) { ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ int ret; ++ ++ mutex_lock(&list_lock); ++ ret = rcar_vin_async_probe(ici, icd); ++ mutex_unlock(&list_lock); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static struct soc_camera_device *rcar_vin_add_pdev( ++ struct rcar_vin_async_client *sasc) ++{ ++ struct platform_device *pdev = sasc->pdev; ++ int ret; ++ ++ ret = platform_device_add(pdev); ++ ++ if (ret < 0 || !pdev->dev.driver) ++ return NULL; ++ ++ return platform_get_drvdata(pdev); ++} ++ ++static int rcar_vin_soc_of_bind(struct rcar_vin_priv *priv, ++ struct soc_camera_host *ici, ++ struct device_node *ep, ++ struct device_node *remote) ++{ ++ struct soc_camera_device *icd; ++ struct soc_camera_desc sdesc = {.host_desc.bus_id = ici->nr,}; ++ struct rcar_vin_async_client *sasc; ++ struct soc_of_info *info; ++ struct i2c_client *client; ++ char clk_name[V4L2_SUBDEV_NAME_SIZE]; ++ int ret; ++ ++ /* allocate a new subdev and add match info to it */ ++ info = devm_kzalloc(ici->v4l2_dev.dev, sizeof(struct soc_of_info), ++ GFP_KERNEL); ++ if (!info) ++ return -ENOMEM; ++ ++ info->sasd.asd.match.of.node = remote; ++ info->sasd.asd.match_type = V4L2_ASYNC_MATCH_OF; ++ info->subdev = &info->sasd.asd; ++ ++ /* Or shall this be managed by the soc-camera device? */ ++ sasc = &info->sasc; ++ ++ ret = rcar_vin_dyn_pdev(&sdesc, sasc); ++ if (ret < 0) ++ goto eallocpdev; ++ ++ sasc->sensor = &info->sasd.asd; ++ ++ icd = rcar_vin_add_pdev(sasc); ++ if (!icd) { ++ ret = -ENOMEM; ++ goto eaddpdev; ++ } ++ ++ sasc->notifier.subdevs = &info->subdev; ++ sasc->notifier.num_subdevs = 1; ++ sasc->notifier.bound = rcar_vin_async_bound; ++ sasc->notifier.unbind = rcar_vin_async_unbind; ++ sasc->notifier.complete = rcar_vin_async_complete; ++ ++ priv->async_client = sasc; ++ ++ client = of_find_i2c_device_by_node(remote); ++ ++ if (client) ++ snprintf(clk_name, sizeof(clk_name), "%d-%04x", ++ client->adapter->nr, client->addr); ++ else ++ snprintf(clk_name, sizeof(clk_name), "of-%s", ++ of_node_full_name(remote)); ++ ++ ret = v4l2_async_notifier_register(&ici->v4l2_dev, &sasc->notifier); ++ if (!ret) ++ return 0; ++ ++ platform_device_del(sasc->pdev); ++eaddpdev: ++ platform_device_put(sasc->pdev); ++eallocpdev: ++ devm_kfree(ici->v4l2_dev.dev, info); ++ dev_err(ici->v4l2_dev.dev, "group probe failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int rcar_vin_probe(struct platform_device *pdev) ++{ ++ const struct of_device_id *match = NULL; ++ struct rcar_vin_priv *priv; ++ struct v4l2_of_endpoint ep; ++ struct device_node *np; ++ struct resource *mem; ++ unsigned int pdata_flags; ++ int irq, ret; ++ const char *str; ++ unsigned int i; ++ struct device_node *epn = NULL, *ren = NULL; ++ bool csi_use = false; ++ ++ match = of_match_device(of_match_ptr(rcar_vin_of_table), &pdev->dev); ++ ++ np = of_graph_get_next_endpoint(pdev->dev.of_node, NULL); ++ if (!np) { ++ dev_err(&pdev->dev, "could not find endpoint\n"); ++ return -EINVAL; ++ } ++ ++ for (i = 0; ; i++) { ++ epn = of_graph_get_next_endpoint(pdev->dev.of_node, ++ epn); ++ if (!epn) ++ break; ++ ++ ren = of_graph_get_remote_port(epn); ++ if (!ren) { ++ dev_notice(&pdev->dev, "no remote for %s\n", ++ of_node_full_name(epn)); ++ continue; ++ } ++ ++ /* so we now have a remote node to connect */ ++ dev_dbg(&pdev->dev, "node name:%s\n", ++ of_node_full_name(ren->parent)); ++ ++ if (strcmp(ren->parent->name, "csi2") == 0) ++ csi_use = true; ++ ++ of_node_put(ren); ++ ++ if (i) ++ break; ++ } ++ ++ ret = v4l2_of_parse_endpoint(np, &ep); ++ if (ret) { ++ dev_err(&pdev->dev, "could not parse endpoint\n"); ++ return ret; ++ } ++ ++ if (ep.bus_type == V4L2_MBUS_BT656) ++ pdata_flags = RCAR_VIN_BT656; ++ else if (ep.bus_type == V4L2_MBUS_CSI2) ++ pdata_flags = RCAR_VIN_BT656 | RCAR_VIN_CSI2; ++ else { ++ pdata_flags = 0; ++ if (ep.bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW) ++ pdata_flags |= RCAR_VIN_HSYNC_ACTIVE_LOW; ++ if (ep.bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW) ++ pdata_flags |= RCAR_VIN_VSYNC_ACTIVE_LOW; ++ } ++ ++ of_node_put(np); ++ ++ dev_dbg(&pdev->dev, "pdata_flags = %08x\n", pdata_flags); ++ ++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (mem == NULL) ++ return -EINVAL; ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq <= 0) ++ return -EINVAL; ++ ++ priv = devm_kzalloc(&pdev->dev, sizeof(struct rcar_vin_priv), ++ GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->base = devm_ioremap_resource(&pdev->dev, mem); ++ if (IS_ERR(priv->base)) ++ return PTR_ERR(priv->base); ++ ++ ret = devm_request_irq(&pdev->dev, irq, rcar_vin_irq, IRQF_SHARED, ++ dev_name(&pdev->dev), priv); ++ if (ret) ++ return ret; ++ ++ priv->ici.priv = priv; ++ priv->ici.v4l2_dev.dev = &pdev->dev; ++ priv->ici.drv_name = dev_name(&pdev->dev); ++ priv->ici.ops = &rcar_vin_host_ops; ++ priv->csi_sync = false; ++ ++ priv->pdata_flags = pdata_flags; ++ if (!match) { ++ priv->ici.nr = pdev->id; ++ priv->chip = pdev->id_entry->driver_data; ++ } else { ++ priv->ici.nr = of_alias_get_id(pdev->dev.of_node, "vin"); ++ priv->chip = (enum chip_id)match->data; ++ } ++ ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ priv->max_width = 4096; ++ priv->max_height = 4096; ++ } else { ++ priv->max_width = 2048; ++ priv->max_height = 2048; ++ } ++ ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ u32 ifmd = 0; ++ bool match_flag = false; ++ const struct vin_gen3_ifmd *gen3_ifmd_table = NULL; ++ int vc, num; ++ ++ num = VNCSI_IFMD_SEL_NUMBER; ++ ++ if (strcmp(dev_name(priv->ici.v4l2_dev.dev), ++ "e6ef0000.video") == 0) ++ priv->index = RCAR_VIDEO_0; ++ else if (strcmp(dev_name(priv->ici.v4l2_dev.dev), ++ "e6ef1000.video") == 0) ++ priv->index = RCAR_VIDEO_1; ++ else if (strcmp(dev_name(priv->ici.v4l2_dev.dev), ++ "e6ef2000.video") == 0) ++ priv->index = RCAR_VIDEO_2; ++ else if (strcmp(dev_name(priv->ici.v4l2_dev.dev), ++ "e6ef3000.video") == 0) ++ priv->index = RCAR_VIDEO_3; ++ else if (strcmp(dev_name(priv->ici.v4l2_dev.dev), ++ "e6ef4000.video") == 0) ++ priv->index = RCAR_VIDEO_4; ++ else if (strcmp(dev_name(priv->ici.v4l2_dev.dev), ++ "e6ef5000.video") == 0) ++ priv->index = RCAR_VIDEO_5; ++ else if (strcmp(dev_name(priv->ici.v4l2_dev.dev), ++ "e6ef6000.video") == 0) ++ priv->index = RCAR_VIDEO_6; ++ else if (strcmp(dev_name(priv->ici.v4l2_dev.dev), ++ "e6ef7000.video") == 0) ++ priv->index = RCAR_VIDEO_7; ++ else ++ priv->index = RCAR_VIN_CH_NONE; ++ ++ ret = of_property_read_string(np, "csi,select", &str); ++ if (ret) { ++ dev_err(&pdev->dev, "could not parse csi,select\n"); ++ return ret; ++ } ++ ++ if (strcmp(str, "csi40") == 0) ++ priv->csi_ch = RCAR_CSI40; ++ else if (strcmp(str, "csi20") == 0) ++ priv->csi_ch = RCAR_CSI20; ++ else if (strcmp(str, "csi41") == 0) ++ priv->csi_ch = RCAR_CSI41; ++ else if (strcmp(str, "csi21") == 0) ++ priv->csi_ch = RCAR_CSI21; ++ else ++ priv->csi_ch = RCAR_CSI_CH_NONE; ++ ++ ret = of_property_read_u32(np, "virtual,channel", &vc); ++ if (ret) { ++ dev_err(&pdev->dev, ++ "could not parse virtual,channel\n"); ++ return ret; ++ } ++ ++ if (vc == 0) ++ priv->vc = RCAR_VIRTUAL_CH0; ++ else if (vc == 1) ++ priv->vc = RCAR_VIRTUAL_CH1; ++ else if (vc == 2) ++ priv->vc = RCAR_VIRTUAL_CH2; ++ else if (vc == 3) ++ priv->vc = RCAR_VIRTUAL_CH3; ++ else ++ priv->vc = RCAR_VIRTUAL_NONE; ++ ++ dev_dbg(&pdev->dev, "csi_ch:%d, vc:%d\n", ++ priv->csi_ch, priv->vc); ++ ++ ifmd = VNCSI_IFMD_DES1 | VNCSI_IFMD_DES0; ++ ++ if (priv->chip == RCAR_H3) ++ gen3_ifmd_table = vin_h3_vc_ifmd; ++ else if (priv->chip == RCAR_M3) ++ gen3_ifmd_table = vin_m3_vc_ifmd; ++ ++ for (i = 0; i < num; i++) { ++ if ((gen3_ifmd_table[i].v_sel[priv->index].csi2_ch ++ == priv->csi_ch) && ++ (gen3_ifmd_table[i].v_sel[priv->index].vc ++ == priv->vc)) { ++ if (priv->index < RCAR_VIDEO_4) { ++ if (ifmd0_init) { ++ ifmd0_reg_match[i] = true; ++ match_flag = true; ++ } else if (ifmd0_reg_match[i]) ++ match_flag = true; ++ } else { ++ if (ifmd4_init) { ++ ifmd4_reg_match[i] = true; ++ match_flag = true; ++ } else if (ifmd4_reg_match[i]) ++ match_flag = true; ++ } ++ } else { ++ if (priv->index < RCAR_VIDEO_4) ++ ifmd0_reg_match[i] = false; ++ else ++ ifmd4_reg_match[i] = false; ++ } ++ } ++ if (priv->index < RCAR_VIDEO_4) ++ ifmd0_init = false; ++ else ++ ifmd4_init = false; ++ ++ if (!match_flag) { ++ dev_err(&pdev->dev, ++ "Not match, virtual channel pattern error.\n"); ++ return -EINVAL; ++ } ++ ++ rcar_vin_cpg_enable_for_ifmd(priv->index, true); ++ ++ if (priv->index < RCAR_VIDEO_4) { ++ void __iomem *ifmd0_mem; ++ ++ for (i = 0; i < num; i++) { ++ if (ifmd0_reg_match[i]) { ++ ifmd |= gen3_ifmd_table[i].set_reg; ++ break; ++ } ++ } ++ ++ ifmd0_mem = ioremap(0xe6ef0000 + VNCSI_IFMD_REG, 0x04); ++ iowrite32(ifmd, ifmd0_mem); ++ iounmap(ifmd0_mem); ++ } else { ++ void __iomem *ifmd4_mem; ++ ++ for (i = 0; i < num; i++) { ++ if (ifmd4_reg_match[i]) { ++ ifmd |= gen3_ifmd_table[i].set_reg; ++ break; ++ } ++ } ++ ++ ifmd4_mem = ioremap(0xe6ef4000 + VNCSI_IFMD_REG, 0x04); ++ iowrite32(ifmd, ifmd4_mem); ++ iounmap(ifmd4_mem); ++ } ++ ++ rcar_vin_cpg_enable_for_ifmd(priv->index, false); ++ } ++ ++ spin_lock_init(&priv->lock); ++ INIT_LIST_HEAD(&priv->capture); ++ ++ priv->state = STOPPED; ++ ++ pm_suspend_ignore_children(&pdev->dev, true); ++ pm_runtime_enable(&pdev->dev); ++ ++ ret = soc_camera_host_register(&priv->ici); ++ if (ret) ++ goto cleanup; ++ ++ if (csi_use) { ++ ret = rcar_vin_soc_of_bind(priv, &priv->ici, epn, ren->parent); ++ if (ret) ++ goto cleanup; ++ } ++ ++ vin_debug = 0; ++ ++ return 0; ++ ++cleanup: ++ pm_runtime_disable(&pdev->dev); ++ ++ return ret; ++} ++ ++static int rcar_vin_remove(struct platform_device *pdev) ++{ ++ struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); ++ struct rcar_vin_priv *priv = container_of(soc_host, ++ struct rcar_vin_priv, ici); ++ ++ platform_device_del(priv->async_client->pdev); ++ platform_device_put(priv->async_client->pdev); ++ ++ v4l2_async_notifier_unregister(&priv->async_client->notifier); ++ ++ soc_camera_host_unregister(soc_host); ++ pm_runtime_disable(&pdev->dev); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int rcar_vin_suspend(struct device *dev) ++{ ++ /* Empty function for now */ ++ return 0; ++} ++ ++static int rcar_vin_resume(struct device *dev) ++{ ++ u32 ifmd = 0; ++ bool match_flag = false; ++ const struct vin_gen3_ifmd *gen3_ifmd_table = NULL; ++ int num; ++ unsigned int i; ++ struct soc_camera_host *soc_host = to_soc_camera_host(dev); ++ struct rcar_vin_priv *priv = container_of(soc_host, ++ struct rcar_vin_priv, ici); ++ num = VNCSI_IFMD_SEL_NUMBER; ++ ifmd0_init = true; ++ ifmd4_init = true; ++ ++ if (priv->chip == RCAR_H3) { ++ ifmd = VNCSI_IFMD_DES1 | VNCSI_IFMD_DES0; ++ gen3_ifmd_table = vin_h3_vc_ifmd; ++ } else if (priv->chip == RCAR_M3) { ++ ifmd = VNCSI_IFMD_DES1; ++ gen3_ifmd_table = vin_m3_vc_ifmd; ++ } ++ ++ for (i = 0; i < num; i++) { ++ if ((gen3_ifmd_table[i].v_sel[priv->index].csi2_ch ++ == priv->csi_ch) && ++ (gen3_ifmd_table[i].v_sel[priv->index].vc ++ == priv->vc)) { ++ if (priv->index < RCAR_VIDEO_4) { ++ if (ifmd0_init) { ++ ifmd0_reg_match[i] = true; ++ match_flag = true; ++ } else if (ifmd0_reg_match[i]) ++ match_flag = true; ++ } else { ++ if (ifmd4_init) { ++ ifmd4_reg_match[i] = true; ++ match_flag = true; ++ } else if (ifmd4_reg_match[i]) ++ match_flag = true; ++ } ++ } else { ++ if (priv->index < RCAR_VIDEO_4) ++ ifmd0_reg_match[i] = false; ++ else ++ ifmd4_reg_match[i] = false; ++ } ++ } ++ if (priv->index < RCAR_VIDEO_4) ++ ifmd0_init = false; ++ else ++ ifmd4_init = false; ++ ++ if (priv->index < RCAR_VIDEO_4) { ++ void __iomem *ifmd0_mem; ++ ++ for (i = 0; i < num; i++) { ++ if (ifmd0_reg_match[i]) { ++ ifmd |= gen3_ifmd_table[i].set_reg; ++ break; ++ } ++ } ++ ++ ifmd0_mem = ioremap(0xe6ef0000 + VNCSI_IFMD_REG, 0x04); ++ iowrite32(ifmd, ifmd0_mem); ++ iounmap(ifmd0_mem); ++ } else { ++ void __iomem *ifmd4_mem; ++ ++ for (i = 0; i < num; i++) { ++ if (ifmd4_reg_match[i]) { ++ ifmd |= gen3_ifmd_table[i].set_reg; ++ break; ++ } ++ } ++ ++ ifmd4_mem = ioremap(0xe6ef4000 + VNCSI_IFMD_REG, 0x04); ++ iowrite32(ifmd, ifmd4_mem); ++ iounmap(ifmd4_mem); ++ } ++ ++ return 0; ++} ++ ++static SIMPLE_DEV_PM_OPS(rcar_vin_pm_ops, ++ rcar_vin_suspend, rcar_vin_resume); ++#define DEV_PM_OPS (&rcar_vin_pm_ops) ++#else ++#define DEV_PM_OPS NULL ++#endif /* CONFIG_PM_SLEEP */ ++ ++static struct platform_driver rcar_vin_driver = { ++ .probe = rcar_vin_probe, ++ .remove = rcar_vin_remove, ++ .driver = { ++ .name = DRV_NAME, ++ .pm = DEV_PM_OPS, ++ .of_match_table = of_match_ptr(rcar_vin_of_table), ++ }, ++}; ++ ++module_platform_driver(rcar_vin_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:rcar_vin"); ++MODULE_DESCRIPTION("Renesas R-Car VIN camera host driver"); ++MODULE_AUTHOR("Koji Matsuoka "); +diff --git a/include/media/rcar_csi2.h b/include/media/rcar_csi2.h +new file mode 100644 +index 0000000..1a040fa +--- /dev/null ++++ b/include/media/rcar_csi2.h +@@ -0,0 +1,66 @@ ++/* ++ * include/media/rcar_csi2.h ++ * This file is the driver header ++ * for the Renesas R-Car MIPI CSI-2 unit. ++ * ++ * Copyright (C) 2015 Renesas Electronics Corporation ++ * ++ * This file is based on the include/media/sh_mobile_csi2.h ++ * ++ * Driver header for the SH-Mobile MIPI CSI-2 unit ++ * ++ * Copyright (C) 2010, Guennadi Liakhovetski ++ * ++ * 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. ++ */ ++ ++#ifndef RCAR_MIPI_CSI ++#define RCAR_MIPI_CSI ++ ++#include ++ ++enum rcar_csi2_phy { ++ RCAR_CSI2_PHY_CSI40, /* CSI0 */ ++ RCAR_CSI2_PHY_CSI20, /* CSI1 */ ++ RCAR_CSI2_PHY_CSI41, /* CSI2 */ ++ RCAR_CSI2_PHY_CSI21, /* CSI3 */ ++}; ++ ++enum rcar_csi2_link { ++ RCAR_CSI2_LINK_CSI40, ++ RCAR_CSI2_LINK_CSI20, ++ RCAR_CSI2_LINK_CSI41, ++ RCAR_CSI2_LINK_CSI21, ++}; ++ ++enum rcar_csi2_type { ++ RCAR_CSI2_CSI4X, ++ RCAR_CSI2_CSI2X, ++}; ++ ++#define RCAR_CSI2_CRC (1 << 0) ++#define RCAR_CSI2_ECC (1 << 1) ++ ++struct platform_device; ++ ++struct rcar_csi2_client_config { ++ enum rcar_csi2_phy phy; ++ enum rcar_csi2_link link; ++ unsigned char lanes; /* bitmask[3:0] */ ++ unsigned char channel; /* 0..3 */ ++ struct platform_device *pdev; /* client platform device */ ++ const char *name; /* async matching: client name */ ++}; ++ ++struct v4l2_device; ++ ++struct rcar_csi2_pdata { ++ enum rcar_csi2_type type; ++ unsigned int flags; ++ struct rcar_csi2_client_config *clients; ++ int num_clients; ++}; ++ ++#endif +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0018-arm64-renesas-r8a7797-Add-Renesas-R8A7797-SoC-suppor.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0018-arm64-renesas-r8a7797-Add-Renesas-R8A7797-SoC-suppor.patch new file mode 100644 index 00000000..1f2b11c7 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0018-arm64-renesas-r8a7797-Add-Renesas-R8A7797-SoC-suppor.patch @@ -0,0 +1,5340 @@ +From e8fd03e53c50c67a2aebf19f39a9f14b583f0e2d Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Sun, 14 May 2017 14:48:08 +0300 +Subject: [PATCH] arm64: renesas: r8a7797: Add Renesas R8A7797 SoC support + +This adds Renesas R8A7797 SoC support + +Signed-off-by: Vladimir Barinov +--- + arch/arm64/Kconfig.platforms | 8 + + arch/arm64/boot/dts/renesas/r8a7797.dtsi | 1156 +++++++++++ + drivers/clk/renesas/Kconfig | 1 + + drivers/clk/renesas/Makefile | 1 + + drivers/clk/renesas/r8a7797-cpg-mssr.c | 232 +++ + drivers/clk/renesas/rcar-gen3-cpg.c | 41 +- + drivers/clk/renesas/rcar-gen3-cpg.h | 6 + + drivers/clk/renesas/renesas-cpg-mssr.c | 6 + + drivers/clk/renesas/renesas-cpg-mssr.h | 1 + + drivers/cpufreq/cpufreq-dt-platdev.c | 1 + + drivers/gpio/gpio-rcar.c | 6 +- + drivers/gpu/drm/rcar-du/rcar_du_drv.c | 25 + + drivers/gpu/drm/rcar-du/rcar_du_group.c | 12 +- + drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c | 38 +- + drivers/i2c/busses/i2c-rcar.c | 1 + + drivers/iommu/ipmmu-vmsa.c | 7 +- + drivers/media/platform/soc_camera/Kconfig | 2 +- + drivers/media/platform/soc_camera/rcar_csi2.c | 26 +- + drivers/media/platform/soc_camera/rcar_vin.c | 86 +- + drivers/media/platform/vsp1/vsp1_drv.c | 9 + + drivers/media/platform/vsp1/vsp1_lif.c | 12 +- + drivers/media/platform/vsp1/vsp1_regs.h | 7 + + drivers/mmc/host/sh_mobile_sdhi.c | 1 + + drivers/net/ethernet/renesas/ravb_main.c | 1 + + drivers/pinctrl/sh-pfc/Kconfig | 5 + + drivers/pinctrl/sh-pfc/Makefile | 1 + + drivers/pinctrl/sh-pfc/core.c | 7 + + drivers/pinctrl/sh-pfc/pfc-r8a7797.c | 2628 +++++++++++++++++++++++++ + drivers/pinctrl/sh-pfc/sh_pfc.h | 12 + + drivers/soc/renesas/Makefile | 4 + + drivers/soc/renesas/r8a7797-sysc.c | 39 + + drivers/soc/renesas/rcar-rst.c | 1 + + drivers/soc/renesas/rcar-sysc.c | 3 + + drivers/soc/renesas/rcar-sysc.h | 1 + + drivers/soc/renesas/rcar_ems_ctrl.c | 10 + + drivers/soc/renesas/renesas-soc.c | 8 + + drivers/spi/spi-sh-msiof.c | 4 +- + drivers/thermal/rcar_gen3_thermal.c | 29 + + include/dt-bindings/clock/r8a7797-cpg-mssr.h | 48 + + include/dt-bindings/power/r8a7797-sysc.h | 32 + + 40 files changed, 4489 insertions(+), 29 deletions(-) + create mode 100644 arch/arm64/boot/dts/renesas/r8a7797.dtsi + create mode 100644 drivers/clk/renesas/r8a7797-cpg-mssr.c + create mode 100644 drivers/pinctrl/sh-pfc/pfc-r8a7797.c + create mode 100644 drivers/soc/renesas/r8a7797-sysc.c + create mode 100644 include/dt-bindings/clock/r8a7797-cpg-mssr.h + create mode 100644 include/dt-bindings/power/r8a7797-sysc.h + +diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms +index ebe0a37..9cebaad 100644 +--- a/arch/arm64/Kconfig.platforms ++++ b/arch/arm64/Kconfig.platforms +@@ -166,6 +166,14 @@ config ARCH_R8A77965 + help + This enables support for the Renesas R-Car M3N SoC. + ++config ARCH_R8A7797 ++ bool "Renesas R-Car V3M SoC Platform" ++ select SYS_SUPPORTS_SH_TMU ++ select SYS_SUPPORTS_SH_CMT ++ depends on ARCH_RENESAS ++ help ++ This enables support for the Renesas R-Car V3M SoC. ++ + config ARCH_STRATIX10 + bool "Altera's Stratix 10 SoCFPGA Family" + help +diff --git a/arch/arm64/boot/dts/renesas/r8a7797.dtsi b/arch/arm64/boot/dts/renesas/r8a7797.dtsi +new file mode 100644 +index 0000000..5319b1a +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7797.dtsi +@@ -0,0 +1,1156 @@ ++/* ++ * Device Tree Source for the r8a7797 SoC ++ * ++ * Copyright (C) 2016 - 2017 Renesas Electronics Corp. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include ++#include ++#include ++ ++/ { ++ compatible = "renesas,r8a7797"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ++ aliases { ++ csi2_40 = &csi2_40; ++ i2c0 = &i2c0; ++ i2c1 = &i2c1; ++ i2c2 = &i2c2; ++ i2c3 = &i2c3; ++ i2c4 = &i2c4; ++ spi1 = &msiof0; ++ spi2 = &msiof1; ++ spi3 = &msiof2; ++ spi4 = &msiof3; ++ vin0 = &vin0; ++ vin1 = &vin1; ++ vin2 = &vin2; ++ vin3 = &vin3; ++ tsc0 = &tsc1; ++ }; ++ ++ psci { ++ compatible = "arm,psci-1.0"; ++ method = "smc"; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ a53_0: cpu@0 { ++ compatible = "arm,cortex-a53", "arm,armv8"; ++ reg = <0x0>; ++ device_type = "cpu"; ++ power-domains = <&sysc R8A7797_PD_CA53_CPU0>; ++ next-level-cache = <&L2_CA53>; ++ enable-method = "psci"; ++ cpu-idle-states = <&CPU_SLEEP_0>; ++ #cooling-cells = <2>; ++ dynamic-power-coefficient = <277>; ++ cooling-min-level = <0>; ++ cooling-max-level = <2>; ++ clocks =<&cpg CPG_CORE R8A7797_CLK_Z2>; ++ operating-points-v2 = <&cluster0_opp_tb0>; ++ /*cpu-supply = <&vdd_dvfs>;*/ ++ }; ++ ++ a53_1: cpu@1 { ++ compatible = "arm,cortex-a53","arm,armv8"; ++ reg = <0x1>; ++ device_type = "cpu"; ++ power-domains = <&sysc R8A7797_PD_CA53_CPU1>; ++ next-level-cache = <&L2_CA53>; ++ enable-method = "psci"; ++ cpu-idle-states = <&CPU_SLEEP_0>; ++ operating-points-v2 = <&cluster0_opp_tb0>; ++ }; ++ ++ idle-states { ++ entry-method = "psci"; ++ ++ CPU_SLEEP_0: cpu-sleep-0 { ++ compatible = "arm,idle-state"; ++ arm,psci-suspend-param = <0x0010000>; ++ local-timer-stop; ++ entry-latency-us = <639>; ++ exit-latency-us = <680>; ++ min-residency-us = <1088>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ L2_CA53: cache-controller@1 { ++ compatible = "cache"; ++ power-domains = <&sysc R8A7797_PD_CA53_SCU>; ++ cache-unified; ++ cache-level = <2>; ++ }; ++ ++ cluster0_opp_tb0: opp_table0 { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp@800000000 { ++ opp-hz = /bits/ 64 <800000000>; ++ opp-microvolt = <850000>; ++ clock-latency-ns = <300000>; ++ }; ++ }; ++ ++ extal_clk: extal { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ /* This value must be overridden by the board */ ++ clock-frequency = <0>; ++ }; ++ ++ extalr_clk: extalr { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ /* This value must be overridden by the board */ ++ clock-frequency = <0>; ++ }; ++ ++ /* External CAN clock - to be overridden by boards that provide it */ ++ can_clk: can { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <0>; ++ }; ++ ++ /* External SCIF clock - to be overridden by boards that provide it */ ++ scif_clk: scif { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <0>; ++ }; ++ ++ /* DU input dot clock - tob be overriden by boards that probide it */ ++ du_dotclkin0: dclkin-0 { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <148500000>; ++ }; ++ ++ soc { ++ compatible = "simple-bus"; ++ interrupt-parent = <&gic>; ++ ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ gic: interrupt-controller@0xf1010000 { ++ compatible = "arm,gic-400"; ++ #interrupt-cells = <3>; ++ #address-cells = <0>; ++ interrupt-controller; ++ reg = <0x0 0xf1010000 0 0x1000>, ++ <0x0 0xf1020000 0 0x20000>, ++ <0x0 0xf1040000 0 0x20000>, ++ <0x0 0xf1060000 0 0x20000>; ++ interrupts = ; /* PPI9:Virtual maintenance interrupt */ ++/* clocks = <&cpg CPG_MOD 408>; ++ clock-names = "clk"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; */ ++ }; ++ ++ gpio0: gpio@e6050000 { ++ compatible = "renesas,gpio-r8a7797", ++ "renesas,gpio-rcar"; ++ reg = <0 0xe6050000 0 0x50>; ++ interrupts = ; /* SPI4:GPIO.ch0 */ ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 0 22>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 912>; /* RMSTPCR9/bit12:GPIO0 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ }; ++ ++ gpio1: gpio@e6051000 { ++ compatible = "renesas,gpio-r8a7797", ++ "renesas,gpio-rcar"; ++ reg = <0 0xe6051000 0 0x50>; ++ interrupts = ; /* SPI5:GPIO.ch1 */ ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 32 28>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 911>; /* RMSTPCR9/bit11:GPIO1 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ }; ++ ++ gpio2: gpio@e6052000 { ++ compatible = "renesas,gpio-r8a7797", ++ "renesas,gpio-rcar"; ++ reg = <0 0xe6052000 0 0x50>; ++ interrupts = ; /* SPI6:GPIO.ch2 */ ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 64 17>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 910>; /* RMSTPCR9/bit10:GPIO2 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ }; ++ ++ gpio3: gpio@e6053000 { ++ compatible = "renesas,gpio-r8a7797", ++ "renesas,gpio-rcar"; ++ reg = <0 0xe6053000 0 0x50>; ++ interrupts = ; /* SPI7:GPIO.ch3 */ ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 96 17>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 909>; /* RMSTPCR9/bit9:GPIO3 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ }; ++ ++ gpio4: gpio@e6054000 { ++ compatible = "renesas,gpio-r8a7797", ++ "renesas,gpio-rcar"; ++ reg = <0 0xe6054000 0 0x50>; ++ interrupts = ; /* SPI8:GPIO.ch4 */ ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 128 6>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 908>; /* RMSTPCR9/bit8:GPIO4 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ }; ++ ++ gpio5: gpio@e6055000 { ++ compatible = "renesas,gpio-r8a7797", ++ "renesas,gpio-rcar"; ++ reg = <0 0xe6055000 0 0x50>; ++ interrupts = ; /* SPI9:GPIO.ch5 */ ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 160 15>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 907>; /* RMSTPCR9/bit7:GPIO5 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ }; ++ ++ pmu_a53 { ++ compatible = "arm,cortex-a53-pmu"; ++ interrupts = , ++ ; /* SPI84:AP-System Core.CA53core0 pmu, SPI85:AP-System Core.CA53core1 pmu */ ++ interrupt-affinity = <&a53_0>, ++ <&a53_1>; ++ }; ++ ++ timer { ++ compatible = "arm,armv8-timer"; ++ interrupts = , ++ , ++ , ++ ; /* PPI13:Secure physical timer, PPI14:Non-secure physical timer, ++ PPI11:Virtual timer, PPI10:Hypervisor timer */ ++ }; ++ ++ wdt0: wdt@e6020000 { ++ compatible = "renesas,r8a7797-wdt", "renesas,rcar-gen3-wdt"; ++ reg = <0 0xe6020000 0 0x0c>; ++ clocks = <&cpg CPG_MOD 402>; /* RMSTPCR4/bit2:RWDT */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ cpg: clock-controller@e6150000 { ++ compatible = "renesas,r8a7797-cpg-mssr"; ++ reg = <0 0xe6150000 0 0x1000>; ++ clocks = <&extal_clk>, <&extalr_clk>; ++ clock-names = "extal", "extalr"; ++ #clock-cells = <2>; ++ #power-domain-cells = <0>; ++ }; ++ ++ csi2_40: csi2@feaa0000 { ++ compatible = "renesas,r8a7797-csi2"; ++ reg = <0 0xfeaa0000 0 0x10000>; ++ interrupts = ; /* SPI246:CSI2.ch2 */ ++ clocks = <&cpg CPG_MOD 716>; /* RMSTPCR7/bit16:CSI40 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ prr: chipid@fff00044 { ++ compatible = "renesas,prr"; ++ reg = <0 0xfff00044 0 4>; ++ }; ++ ++ rst: reset-controller@e6160000 { ++ compatible = "renesas,r8a7797-rst"; ++ reg = <0 0xe6160000 0 0x0200>; ++ }; ++ ++ sysc: system-controller@e6180000 { ++ compatible = "renesas,r8a7797-sysc"; ++ reg = <0 0xe6180000 0 0x0440>; ++ #power-domain-cells = <1>; ++ }; ++ ++ pfc: pfc@e6060000 { ++ compatible = "renesas,pfc-r8a7797"; ++ reg = <0 0xe6060000 0 0x50c>; ++ }; ++ ++ intc_ex: interrupt-controller@e61c0000 { ++ compatible = "renesas,intc-ex-r8a7797", "renesas,irqc"; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ reg = <0 0xe61c0000 0 0x200>; ++ interrupts = ; /* SPI1:IRQ1, SPI2:IRQ2, SPI3:IRQ3, SPI18:IRQ4, SPI161:IRQ5 */ ++ clocks = <&cpg CPG_MOD 407>; /* RMSTPCR4/bit7:INTC-EX */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ }; ++ ++ ipmmu_vi: mmu@febd0000 { ++ compatible = "renesas,ipmmu-r8a7797"; ++ reg = <0 0xfebd0000 0 0x1000>; /* IPMMU-VI */ ++ renesas,ipmmu-main = <&ipmmu_mm 11>; ++ #iommu-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ ipmmu_ir: mmu@ff8b0000 { ++ compatible = "renesas,ipmmu-r8a7797"; ++ reg = <0 0xff8b0000 0 0x1000>; /* IPMMU-IR */ ++ renesas,ipmmu-main = <&ipmmu_mm 3>; ++ #iommu-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ ipmmu_rt: mmu@ffc80000 { ++ compatible = "renesas,ipmmu-r8a7797"; ++ reg = <0 0xffc80000 0 0x1000>; /* IPMMU-RT */ ++ renesas,ipmmu-main = <&ipmmu_mm 7>; ++ #iommu-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ ipmmu_ds0: mmu@e6740000 { ++ compatible = "renesas,ipmmu-r8a7797"; ++ reg = <0 0xe6740000 0 0x1000>; /* IPMMU-DS0 */ ++ renesas,ipmmu-main = <&ipmmu_mm 0>; ++ #iommu-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ ipmmu_mm: mmu@e67b0000 { ++ compatible = "renesas,ipmmu-r8a7797"; ++ reg = <0 0xe67b0000 0 0x1000>; /* IPMMU-MM */ ++ interrupts = , ++ ; /* SPI196:IPMMU, SPI197:IPMMU sec */ ++ #iommu-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ dmac1: dma-controller@e7300000 { ++ compatible = "renesas,dmac-r8a7797", ++ "renesas,rcar-dmac"; ++ reg = <0 0xe7300000 0 0x10000>; ++ interrupts = ; /* SPI220::SYS-DMAC1 err, ++ SPI216~219:SYS-DMAC1.ch0~SYS-DMAC1.ch3, ++ SPI308~311:SYS-DMAC1.ch4~SYS-DMAC1.ch7 */ ++ interrupt-names = "error", ++ "ch0", "ch1", "ch2", "ch3", ++ "ch4", "ch5", "ch6", "ch7"; ++ clocks = <&cpg CPG_MOD 218>; /* RMSTPCR2/bit18:SYS-DMAC1 */ ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ #dma-cells = <1>; ++ dma-channels = <8>; ++ iommus = <&ipmmu_ds0 0>, <&ipmmu_ds0 1>, ++ <&ipmmu_ds0 2>, <&ipmmu_ds0 3>, ++ <&ipmmu_ds0 4>, <&ipmmu_ds0 5>, ++ <&ipmmu_ds0 6>, <&ipmmu_ds0 7>; /* @@ */ ++ }; ++ ++ dmac2: dma-controller@e7310000 { ++ compatible = "renesas,dmac-r8a7797", ++ "renesas,rcar-dmac"; ++ reg = <0 0xe7310000 0 0x10000>; ++ interrupts = ; /* SPI307::SYS-DMAC2 err, ++ SPI312~319:SYS-DMAC2.ch0~SYS-DMAC1.ch7 */ ++ interrupt-names = "error", ++ "ch0", "ch1", "ch2", "ch3", ++ "ch4", "ch5", "ch6", "ch7"; ++ clocks = <&cpg CPG_MOD 217>; /* RMSTPCR2/bit17:SYS-DMAC2 */ ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ #dma-cells = <1>; ++ dma-channels = <8>; ++ iommus = <&ipmmu_ds0 16>, <&ipmmu_ds0 17>, ++ <&ipmmu_ds0 18>, <&ipmmu_ds0 19>, ++ <&ipmmu_ds0 20>, <&ipmmu_ds0 21>, ++ <&ipmmu_ds0 22>, <&ipmmu_ds0 23>; /* @@ */ ++ }; ++ ++ avb: ethernet@e6800000 { ++ compatible = "renesas,etheravb-r8a7797", ++ "renesas,etheravb-rcar-gen3"; ++ reg = <0 0xe6800000 0 0x800>, <0 0xe6a00000 0 0x10000>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; /* SPI39~63:Ethernet AVB.ch0~24 */ ++ /* @@ errreq_avb_p[0]~[3] add (T.B.D) */ ++ interrupt-names = "ch0", "ch1", "ch2", "ch3", ++ "ch4", "ch5", "ch6", "ch7", ++ "ch8", "ch9", "ch10", "ch11", ++ "ch12", "ch13", "ch14", "ch15", ++ "ch16", "ch17", "ch18", "ch19", ++ "ch20", "ch21", "ch22", "ch23", ++ "ch24"; ++ clocks = <&cpg CPG_MOD 812>; /* RMSTPCR8/bit12:EAVB-IF */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ phy-mode = "rgmii-id"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ canfd: canfd@e66c0000 { ++ compatible = "renesas,r8a7797-canfd", ++ "renesas,rcar-gen3-canfd"; ++ reg = <0 0xe66c0000 0 0x8000>; ++ interrupts = , ++ ; ++ clocks = <&cpg CPG_MOD 914>, ++ <&cpg CPG_CORE R8A7797_CLK_CANFD>, ++ <&can_clk>; ++ clock-names = "fck", "canfd", "can_clk"; ++ assigned-clocks = <&cpg CPG_CORE R8A7797_CLK_CANFD>; ++ assigned-clock-rates = <40000000>; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ ++ channel0 { ++ status = "disabled"; ++ }; ++ ++ channel1 { ++ status = "disabled"; ++ }; ++ }; ++ ++ cmt0: timer@e60f0000 { ++ compatible = "renesas,cmt-48-r8a7797", "renesas,cmt-48-gen2"; ++ reg = <0 0xe60f0000 0 0x1004>; ++ interrupts = , ++ ; ++ clocks = <&cpg CPG_MOD 303>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ ++ renesas,channels-mask = <0x60>; ++ ++ status = "disabled"; ++ }; ++ ++ cmt1: timer@e6130000 { ++ compatible = "renesas,cmt-48-r8a7797", "renesas,cmt-48-gen2"; ++ reg = <0 0xe6130000 0 0x1004>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 302>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ ++ renesas,channels-mask = <0xff>; ++ ++ status = "disabled"; ++ }; ++ ++ cmt2: timer@e6140000 { ++ compatible = "renesas,cmt-48-r8a7797", "renesas,cmt-48-gen2"; ++ reg = <0 0xe6140000 0 0x1004>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 301>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ ++ renesas,channels-mask = <0xff>; ++ ++ status = "disabled"; ++ }; ++ ++ cmt3: timer@e6148000 { ++ compatible = "renesas,cmt-48-r8a7797", "renesas,cmt-48-gen2"; ++ reg = <0 0xe6148000 0 0x1004>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 300>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ ++ renesas,channels-mask = <0xff>; ++ ++ status = "disabled"; ++ }; ++ ++ tpu: pwm@e6e80000 { ++ compatible = "renesas,tpu-r8a7797", "renesas,tpu"; ++ reg = <0 0xe6e80000 0 0x100>; ++ clocks = <&cpg CPG_MOD 304>; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ #pwm-cells = <4>; ++ }; ++ ++ tmu0: timer@e61e0000 { ++ compatible = "renesas,tmu-r8a7797", "renesas,tmu"; ++ reg = <0 0xe61e0000 0 0x30>; ++ interrupts = , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 125>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ #renesas,channels = <3>; ++ status = "disabled"; ++ }; ++ ++ tmu1: timer@e6fc0000 { ++ compatible = "renesas,tmu-r8a7797", "renesas,tmu"; ++ reg = <0 0xe6fc0000 0 0x30>; ++ interrupts = , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 124>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ #renesas,channels = <3>; ++ status = "disabled"; ++ }; ++ ++ tmu2: timer@e6fd0000 { ++ compatible = "renesas,tmu-r8a7797", "renesas,tmu"; ++ reg = <0 0xe6fd0000 0 0x30>; ++ interrupts = , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 123>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ #renesas,channels = <3>; ++ status = "disabled"; ++ }; ++ ++ tmu3: timer@e6fe0000 { ++ compatible = "renesas,tmu-r8a7797", "renesas,tmu"; ++ reg = <0 0xe6fe0000 0 0x30>; ++ interrupts = , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 122>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ #renesas,channels = <3>; ++ status = "disabled"; ++ }; ++ ++ tmu4: timer@ffc00000 { ++ compatible = "renesas,tmu-r8a7797", "renesas,tmu"; ++ reg = <0 0xffc00000 0 0x30>; ++ interrupts = , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 121>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ #renesas,channels = <3>; ++ status = "disabled"; ++ }; ++ ++ pwm0: pwm@e6e30000 { ++ compatible = "renesas,pwm-r8a7797", "renesas,pwm-rcar"; ++ reg = <0 0xe6e30000 0 0x10>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; /* RMSTPCR5/bit23:PWM */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ pwm1: pwm@e6e31000 { ++ compatible = "renesas,pwm-r8a7797", "renesas,pwm-rcar"; ++ reg = <0 0xe6e31000 0 0x10>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; /* RMSTPCR5/bit23:PWM */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ pwm2: pwm@e6e32000 { ++ compatible = "renesas,pwm-r8a7797", "renesas,pwm-rcar"; ++ reg = <0 0xe6e32000 0 0x10>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; /* RMSTPCR5/bit23:PWM */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ pwm3: pwm@e6e33000 { ++ compatible = "renesas,pwm-r8a7797", "renesas,pwm-rcar"; ++ reg = <0 0xe6e33000 0 0x10>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; /* RMSTPCR5/bit23:PWM */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ pwm4: pwm@e6e34000 { ++ compatible = "renesas,pwm-r8a7797", "renesas,pwm-rcar"; ++ reg = <0 0xe6e34000 0 0x10>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; /* RMSTPCR5/bit23:PWM */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ hscif0: serial@e6540000 { ++ compatible = "renesas,hscif-r8a7797", ++ "renesas,rcar-gen3-hscif", ++ "renesas,hscif"; ++ reg = <0 0xe6540000 0 96>; ++ interrupts = ; /* SPI154:HSCIF.ch0 */ ++ clocks = <&cpg CPG_MOD 520>, ++ <&cpg CPG_CORE R8A7797_CLK_S2D1>, ++ <&scif_clk>; /* RMSTPCR5/bit20:HSCIF0 */ ++ clock-names = "fck", "brg_int", "scif_clk"; ++ dmas = <&dmac1 0x31>, <&dmac1 0x30>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ hscif1: serial@e6550000 { ++ compatible = "renesas,hscif-r8a7797", ++ "renesas,rcar-gen3-hscif", ++ "renesas,hscif"; ++ reg = <0 0xe6550000 0 96>; ++ interrupts = ; /* SPI155:HSCIF.ch1 */ ++ clocks = <&cpg CPG_MOD 519>, ++ <&cpg CPG_CORE R8A7797_CLK_S2D1>, ++ <&scif_clk>; /* RMSTPCR5/bit19:HSCIF1 */ ++ clock-names = "fck", "brg_int", "scif_clk"; ++ dmas = <&dmac1 0x33>, <&dmac1 0x32>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ hscif2: serial@e6560000 { ++ compatible = "renesas,hscif-r8a7797", ++ "renesas,rcar-gen3-hscif", ++ "renesas,hscif"; ++ reg = <0 0xe6560000 0 96>; ++ interrupts = ; /* SPI144:HSCIF.ch2 */ ++ clocks = <&cpg CPG_MOD 518>, ++ <&cpg CPG_CORE R8A7797_CLK_S2D1>, ++ <&scif_clk>; /* RMSTPCR5/bit18:HSCIF2 */ ++ clock-names = "fck", "brg_int", "scif_clk"; ++ dmas = <&dmac1 0x35>, <&dmac1 0x34>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ hscif3: serial@e66a0000 { ++ compatible = "renesas,hscif-r8a7797", ++ "renesas,rcar-gen3-hscif", ++ "renesas,hscif"; ++ reg = <0 0xe66a0000 0 96>; ++ interrupts = ; /* SPI145:HSCIF.ch3 */ ++ clocks = <&cpg CPG_MOD 517>, ++ <&cpg CPG_CORE R8A7797_CLK_S2D1>, ++ <&scif_clk>; /* RMSTPCR5/bit17:HSCIF3 */ ++ clock-names = "fck", "brg_int", "scif_clk"; ++ dmas = <&dmac1 0x37>, <&dmac1 0x36>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ scif0: serial@e6e60000 { ++ compatible = "renesas,scif-r8a7797", ++ "renesas,rcar-gen3-scif", "renesas,scif"; ++ reg = <0 0xe6e60000 0 64>; ++ interrupts = ; /* SPI152:SCIF.ch0 */ ++ clocks = <&cpg CPG_MOD 207>, ++ <&cpg CPG_CORE R8A7797_CLK_S2D1>, ++ <&scif_clk>; /* RMSTPCR2/bit7:SCIF0 */ ++ /*clock-names = "fck", "sck", "brg_int", "scif_clk"; */ ++ clock-names = "fck"; ++ dmas = <&dmac1 0x51>, <&dmac1 0x50>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ scif1: serial@e6e68000 { ++ compatible = "renesas,scif-r8a7797", ++ "renesas,rcar-gen3-scif", "renesas,scif"; ++ reg = <0 0xe6e68000 0 64>; ++ interrupts = ; /* SPI153:SCIF.ch1 */ ++ clocks = <&cpg CPG_MOD 206>, ++ <&cpg CPG_CORE R8A7797_CLK_S2D1>, ++ <&scif_clk>; /* RMSTPCR2/bit6:SCIF1 */ ++ clock-names = "fck", "brg_int", "scif_clk"; ++ dmas = <&dmac1 0x53>, <&dmac1 0x52>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ scif3: serial@e6c50000 { ++ compatible = "renesas,scif-r8a7797", ++ "renesas,rcar-gen3-scif", "renesas,scif"; ++ reg = <0 0xe6c50000 0 64>; ++ interrupts = ; /* SPI23:SCIF.ch3 */ ++ clocks = <&cpg CPG_MOD 204>, ++ <&cpg CPG_CORE R8A7797_CLK_S2D1>, ++ <&scif_clk>; /* RMSTPCR2/bit4:SCIF3 */ ++ clock-names = "fck", "brg_int", "scif_clk"; ++ dmas = <&dmac1 0x57>, <&dmac1 0x56>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ scif4: serial@e6c40000 { ++ compatible = "renesas,scif-r8a7797", ++ "renesas,rcar-gen3-scif", "renesas,scif"; ++ reg = <0 0xe6c40000 0 64>; ++ interrupts = ; /* SPI16:SCIF.ch4 */ ++ clocks = <&cpg CPG_MOD 203>, ++ <&cpg CPG_CORE R8A7797_CLK_S2D1>, ++ <&scif_clk>; /* RMSTPCR2/bit3:SCIF4 */ ++ clock-names = "fck", "brg_int", "scif_clk"; ++ dmas = <&dmac1 0x59>, <&dmac1 0x58>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ i2c0: i2c@e6500000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,i2c-r8a7797"; ++ reg = <0 0xe6500000 0 0x40>; ++ interrupts = ; /* SPI287:I2C.ch0 */ ++ clocks = <&cpg CPG_MOD 931>; /* RMSTPCR9/bit31:I2C-IF0 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ dmas = <&dmac1 0x91>, <&dmac1 0x90>; ++ dma-names = "tx", "rx"; ++ i2c-scl-internal-delay-ns = <6>; ++ status = "disabled"; ++ }; ++ ++ i2c1: i2c@e6508000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,i2c-r8a7797"; ++ reg = <0 0xe6508000 0 0x40>; ++ interrupts = ; /* SPI288:I2C.ch1 */ ++ clocks = <&cpg CPG_MOD 930>; /* RMSTPCR9/bit30:I2C-IF1 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ dmas = <&dmac1 0x93>, <&dmac1 0x92>; ++ dma-names = "tx", "rx"; ++ i2c-scl-internal-delay-ns = <6>; ++ status = "disabled"; ++ }; ++ ++ i2c2: i2c@e6510000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,i2c-r8a7797"; ++ reg = <0 0xe6510000 0 0x40>; ++ interrupts = ; /* SPI286:I2C.ch2 */ ++ clocks = <&cpg CPG_MOD 929>; /* RMSTPCR9/bit29:I2C-IF2 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ dmas = <&dmac1 0x95>, <&dmac1 0x94>; ++ dma-names = "tx", "rx"; ++ i2c-scl-internal-delay-ns = <6>; ++ status = "disabled"; ++ }; ++ ++ i2c3: i2c@e66d0000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,i2c-r8a7797"; ++ reg = <0 0xe66d0000 0 0x40>; ++ interrupts = ; /* SPI290:I2C.ch3 */ ++ clocks = <&cpg CPG_MOD 928>; /* RMSTPCR9/bit28:I2C-IF3 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ dmas = <&dmac1 0x97>, <&dmac1 0x96>; ++ dma-names = "tx", "rx"; ++ i2c-scl-internal-delay-ns = <6>; ++ status = "disabled"; ++ }; ++ ++ i2c4: i2c@e66d8000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,i2c-r8a7797"; ++ reg = <0 0xe66d8000 0 0x40>; ++ interrupts = ; /* SPI19:I2C.ch4 */ ++ clocks = <&cpg CPG_MOD 927>; /* RMSTPCR9/bit27:I2C-IF4 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ dmas = <&dmac1 0x99>, <&dmac1 0x98>; ++ dma-names = "tx", "rx"; ++ i2c-scl-internal-delay-ns = <6>; ++ status = "disabled"; ++ }; ++ ++ msiof0: spi@e6e90000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,msiof-r8a7797"; ++ reg = <0 0xe6e90000 0 0x64>; ++ interrupts = ; /* SPI156:MSIOF.ch0 */ ++ clocks = <&cpg CPG_MOD 211>, <&msiof_ref_clk>; /* RMSTPCR2/bit11:MSIOF0, @@ msiof_ref_clk->Eagle.dts */ ++ clock-names = "msiof_clk", "msiof_ref_clk"; ++ dmas = <&dmac1 0x41>, <&dmac1 0x40>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ msiof1: spi@e6ea0000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,msiof-r8a7797"; ++ reg = <0 0xe6ea0000 0 0x0064>; ++ interrupts = ; /* SPI157:MSIOF.ch1 */ ++ clocks = <&cpg CPG_MOD 210>, <&msiof_ref_clk>; /* RMSTPCR2/bit10:MSIOF1, @@ msiof_ref_clk->Eagle.dts */ ++ clock-names = "msiof_clk", "msiof_ref_clk"; ++ dmas = <&dmac1 0x43>, <&dmac1 0x42>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ msiof2: spi@e6c00000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,msiof-r8a7797"; ++ reg = <0 0xe6c00000 0 0x0064>; ++ interrupts = ; /* SPI158:MSIOF.ch2 */ ++ clocks = <&cpg CPG_MOD 209>, <&msiof_ref_clk>; /* RMSTPCR2/bit9:MSIOF2, @@ msiof_ref_clk->Eagle.dts */ ++ clock-names = "msiof_clk", "msiof_ref_clk"; ++ dmas = <&dmac1 0x45>, <&dmac1 0x44>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ msiof3: spi@e6c10000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,msiof-r8a7797"; ++ reg = <0 0xe6c10000 0 0x0064>; ++ interrupts = ; /* SPI159:MSIOF.ch3 */ ++ clocks = <&cpg CPG_MOD 208>, <&msiof_ref_clk>; /* RMSTPCR2/bit8:MSIOF3, @@ msiof_ref_clk->Eagle.dts */ ++ clock-names = "msiof_clk", "msiof_ref_clk"; ++ dmas = <&dmac1 0x47>, <&dmac1 0x46>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin0: video@e6ef0000 { ++ compatible = "renesas,vin-r8a7797"; ++ reg = <0 0xe6ef0000 0 0x1000>; ++ interrupts = ; /* SPI188:VIN.ch0 */ ++ clocks = <&cpg CPG_MOD 811>; /* RMSTPCR8/bit11:VIN0 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin1: video@e6ef1000 { ++ compatible = "renesas,vin-r8a7797"; ++ reg = <0 0xe6ef1000 0 0x1000>; ++ interrupts = ; /* SPI189:VIN.ch1 */ ++ clocks = <&cpg CPG_MOD 810>; /* RMSTPCR8/bit10:VIN1 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin2: video@e6ef2000 { ++ compatible = "renesas,vin-r8a7797"; ++ reg = <0 0xe6ef2000 0 0x1000>; ++ interrupts = ; /* SPI190:VIN.ch2 */ ++ clocks = <&cpg CPG_MOD 809>; /* RMSTPCR8/bit9:VIN2 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin3: video@e6ef3000 { ++ compatible = "renesas,vin-r8a7797"; ++ reg = <0 0xe6ef3000 0 0x1000>; ++ interrupts = ; /* SPI191:VIN.ch3 */ ++ clocks = <&cpg CPG_MOD 808>; /* RMSTPCR8/bit8:VIN3 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ sdhi2: sd@ee140000 { ++ compatible = "renesas,sdhi-r8a7797"; ++ reg = <0 0xee140000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 314>; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ renesas,clk-rate = <200000000>; ++ status = "disabled"; ++ }; ++ ++ qos@e67e0000 { ++ compatible = "renesas,qos"; ++ }; ++ ++ vspd0: vsp@fea20000 { ++ compatible = "renesas,vsp2"; ++ reg = <0 0xfea20000 0 0x4000>; ++ ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 623>; /* RMSTPCR6/bit23:VSP(VSPD0) */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ ++ renesas,fcp = <&fcpvd0>; ++ }; ++ ++ fcpvd0: fcp@fea27000 { ++ compatible = "renesas,r8a7797-fcpv", "renesas,fcpv"; ++ reg = <0 0xfea27000 0 0x200>; ++ clocks = <&cpg CPG_MOD 603>; /* RMSTPCR6/bit3:FCPVD0 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ }; ++ ++ du: display@feb00000 { ++ compatible = "renesas,du-r8a7797"; ++ reg = <0 0xfeb00000 0 0x80000>, ++ <0 0xfeb90000 0 0x14>; /* LDVS */ ++ reg-names = "du", "lvds.0"; ++ interrupts = ; /* SPI256:DU.ch0 */ ++ clocks = <&cpg CPG_MOD 724>, ++ <&cpg CPG_MOD 727>, ++ <&dclkin_p0>; ++ clock-names = "du.0", "lvds.0", "dclkin.0"; ++ status = "disabled"; ++ ++ vsps = <&vspd0>; ++ ++ interlaced = <1>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ du_out_lvds0: endpoint { ++ }; ++ }; ++ }; ++ }; ++ ++ tsc1: thermal@0xe6190000 { ++ compatible = "renesas,rcar-thermal"; ++ reg = <0 0xe6190000 0 0x14 ++ 0 0xe6190100 0 0x38>; ++ ++ interrupts = , ++ , ++ ; /* SPI67~69:Thermal Sensor.ch0~2 */ ++ clocks = <&cpg CPG_MOD 522>; /* RMSTPCR5/bit22:THS/TSC */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ #thermal-sensor-cells = <0>; ++ status = "okay"; ++ }; ++ ++ thermal-zones { ++ emergency { ++ polling-delay = <1000>; ++ on-temperature = <110000>; ++ off-temperature = <95000>; ++ target_cpus = <&a53_1>; ++ status = "disabled"; ++ }; ++ ++ sensor_thermal1: sensor-thermal1 { ++ polling-delay-passive = <250>; ++ polling-delay = <0>; ++ sustainable-power = <6313>; ++ ++ /* sensor ID */ ++ thermal-sensors = <&tsc1>; ++ ++ trips { ++ threshold: trip-point@0 { ++ /* miliCelsius */ ++ temperature = <90000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ ++ target: trip-point@1 { ++ /* miliCelsius */ ++ temperature = <100000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ ++ sensor1_crit: sensor1-crit { ++ temperature = <120000>; ++ hysteresis = <2000>; ++ type = "critical"; ++ }; ++ }; ++ ++ cooling-maps { ++ map0 { ++ trip = <&target>; ++ cooling-device = <&a53_0 0 2>; ++ contribution = <1024>; ++ }; ++ }; ++ }; ++ }; ++ ++ mfis: mfis@e6260000 { ++ compatible = "renesas,mfis-r8a7797", "renesas,mfis"; ++ reg = <0 0xe6260000 0 0x0200>; ++ clocks = <&cpg CPG_MOD 213>; ++ clock-names = "mfis"; ++ interrupts = ; ++ interrupt-names = "eicr0"; ++ status = "okay"; ++ }; ++ ++ mfis_lock: mfis-lock@e62600c0 { ++ compatible = "renesas,mfis-lock-r8a7797", ++ "renesas,mfis-lock"; ++ reg = <0 0xe62600c0 0 0x0020>; ++ status = "okay"; ++ }; ++ ++ imrlx4_ch0: imr-lx4@fe860000 { ++ compatible = "renesas,imr-lx4"; ++ reg = <0 0xfe860000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 823>; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ }; ++ ++ imrlx4_ch1: imr-lx4@fe870000 { ++ compatible = "renesas,imr-lx4"; ++ reg = <0 0xfe870000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 822>; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ }; ++ ++ imrlx4_ch2: imr-lx4@fe880000 { ++ compatible = "renesas,imr-lx4"; ++ reg = <0 0xfe880000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 821>; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ }; ++ ++ imrlx4_ch3: imr-lx4@fe890000 { ++ compatible = "renesas,imr-lx4"; ++ reg = <0 0xfe890000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 820>; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ }; ++ }; ++}; +diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig +index bbd9701..b52e907 100644 +--- a/drivers/clk/renesas/Kconfig ++++ b/drivers/clk/renesas/Kconfig +@@ -5,6 +5,7 @@ config CLK_RENESAS_CPG_MSSR + default y if ARCH_R8A7795 + default y if ARCH_R8A7796 + default y if ARCH_R8A77965 ++ default y if ARCH_R8A7797 + + config CLK_RENESAS_CPG_MSTP + bool +diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile +index 2c224e9..c2ef11e 100644 +--- a/drivers/clk/renesas/Makefile ++++ b/drivers/clk/renesas/Makefile +@@ -14,6 +14,7 @@ obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o clk-div6.o + obj-$(CONFIG_ARCH_R8A7795) += r8a7795-cpg-mssr.o rcar-gen3-cpg.o + obj-$(CONFIG_ARCH_R8A7796) += r8a7796-cpg-mssr.o rcar-gen3-cpg.o + obj-$(CONFIG_ARCH_R8A77965) += r8a77965-cpg-mssr.o rcar-gen3-cpg.o ++obj-$(CONFIG_ARCH_R8A7797) += r8a7797-cpg-mssr.o rcar-gen3-cpg.o + obj-$(CONFIG_ARCH_SH73A0) += clk-sh73a0.o clk-div6.o + + obj-$(CONFIG_CLK_RENESAS_CPG_MSSR) += renesas-cpg-mssr.o clk-div6.o +diff --git a/drivers/clk/renesas/r8a7797-cpg-mssr.c b/drivers/clk/renesas/r8a7797-cpg-mssr.c +new file mode 100644 +index 0000000..0460ed4 +--- /dev/null ++++ b/drivers/clk/renesas/r8a7797-cpg-mssr.c +@@ -0,0 +1,232 @@ ++/* ++ * r8a7797 Clock Pulse Generator / Module Standby and Software Reset ++ * ++ * Copyright (C) 2016 Glider bvba ++ * ++ * Based on r8a7795-cpg-mssr.c ++ * ++ * Copyright (C) 2016 Renesas Electronics Corp. ++ * ++ * 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; version 2 of the License. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "renesas-cpg-mssr.h" ++#include "rcar-gen3-cpg.h" ++ ++enum clk_ids { ++ /* Core Clock Outputs exported to DT */ ++ LAST_DT_CORE_CLK = R8A7797_CLK_OSC, ++ ++ /* External Input Clocks */ ++ CLK_EXTAL, ++ CLK_EXTALR, ++ ++ /* Internal Core Clocks */ ++ CLK_MAIN, ++ CLK_PLL0, ++ CLK_PLL1, ++ CLK_PLL3, ++ CLK_PLL1_DIV2, ++ CLK_PLL1_DIV4, ++ CLK_S1, ++ CLK_S2, ++ CLK_RINT, ++ ++ /* Module Clocks */ ++ MOD_CLK_BASE ++}; ++ ++static const struct cpg_core_clk r8a7797_core_clks[] __initconst = { ++ /* External Clock Inputs */ ++ DEF_INPUT("extal", CLK_EXTAL), ++ DEF_INPUT("extalr", CLK_EXTALR), ++ ++ /* Internal Core Clocks */ ++ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL), ++ DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN3_PLL0, CLK_MAIN), ++ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN), ++ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN), ++ ++ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1), ++ DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4, CLK_PLL1_DIV2, 2, 1), ++ DEF_FIXED(".s1", CLK_S1, CLK_PLL1_DIV2, 4, 1), ++ DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 6, 1), ++ ++ /* Core Clock Outputs */ ++ DEF_BASE("z2", R8A7797_CLK_Z2, CLK_TYPE_GEN3_Z2, CLK_PLL1_DIV4), ++ DEF_FIXED("ztr", R8A7797_CLK_ZTR, CLK_PLL1_DIV2, 6, 1), ++ DEF_FIXED("ztrd2", R8A7797_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1), ++ DEF_FIXED("zt", R8A7797_CLK_ZT, CLK_PLL1_DIV2, 4, 1), ++ DEF_FIXED("zx", R8A7797_CLK_ZX, CLK_PLL1_DIV2, 3, 1), ++ DEF_FIXED("s1d1", R8A7797_CLK_S1D1, CLK_S1, 1, 1), ++ DEF_FIXED("s1d2", R8A7797_CLK_S1D2, CLK_S1, 2, 1), ++ DEF_FIXED("s1d4", R8A7797_CLK_S1D4, CLK_S1, 4, 1), ++ DEF_FIXED("s2d1", R8A7797_CLK_S2D1, CLK_S2, 1, 1), ++ DEF_FIXED("s2d2", R8A7797_CLK_S2D2, CLK_S2, 2, 1), ++ DEF_FIXED("s2d4", R8A7797_CLK_S2D4, CLK_S2, 4, 1), ++ ++ DEF_GEN3_SD0H("sd0h", R8A7797_CLK_SD0H, CLK_PLL1_DIV4, 0x0074), ++ DEF_GEN3_SD0("sd0", R8A7797_CLK_SD0, CLK_PLL1_DIV4, 0x0074), ++ ++ DEF_FIXED("cl", R8A7797_CLK_CL, CLK_PLL1_DIV2, 48, 1), ++ DEF_FIXED("cp", R8A7797_CLK_CP, CLK_EXTAL, 2, 1), ++ ++ DEF_DIV6P1("mso", R8A7797_CLK_MSO, CLK_PLL1_DIV4, 0x014), ++ DEF_DIV6P1("canfd", R8A7797_CLK_CANFD, CLK_PLL1_DIV4, 0x244), ++ DEF_DIV6P1("csi0", R8A7797_CLK_CSI0, CLK_PLL1_DIV4, 0x00c), ++ ++ DEF_FIXED("osc", R8A7797_CLK_OSC, CLK_PLL1_DIV2, (12*1024), 1), ++ DEF_BASE("r_int", CLK_RINT, CLK_TYPE_GEN3_RINT, CLK_EXTAL), ++ ++ DEF_BASE("r", R8A7797_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT), ++}; ++ ++static const struct mssr_mod_clk r8a7797_mod_clks[] __initconst = { ++ DEF_MOD("tmu4", 121, R8A7797_CLK_S2D2), ++ DEF_MOD("tmu3", 122, R8A7797_CLK_S2D2), ++ DEF_MOD("tmu2", 123, R8A7797_CLK_S2D2), ++ DEF_MOD("tmu1", 124, R8A7797_CLK_S2D2), ++ DEF_MOD("tmu0", 125, R8A7797_CLK_CP), ++ DEF_MOD("ivcp1e", 127, R8A7797_CLK_S2D1), ++ DEF_MOD("scif4", 203, R8A7797_CLK_S2D4), /* @@ H3=S3D4 */ ++ DEF_MOD("scif3", 204, R8A7797_CLK_S2D4), /* @@ H3=S3D4 */ ++ DEF_MOD("scif1", 206, R8A7797_CLK_S2D4), /* @@ H3=S3D4 */ ++ DEF_MOD("scif0", 207, R8A7797_CLK_S2D4), /* @@ H3=S3D4 */ ++ DEF_MOD("msiof3", 208, R8A7797_CLK_MSO), ++ DEF_MOD("msiof2", 209, R8A7797_CLK_MSO), ++ DEF_MOD("msiof1", 210, R8A7797_CLK_MSO), ++ DEF_MOD("msiof0", 211, R8A7797_CLK_MSO), ++ DEF_MOD("mfis", 213, R8A7797_CLK_S2D2), /* @@ H3=S3D2 */ ++ DEF_MOD("sys-dmac2", 217, R8A7797_CLK_S2D1), /* @@ H3=S3D1 */ ++ DEF_MOD("sys-dmac1", 218, R8A7797_CLK_S2D1), /* @@ H3=S3D1 */ ++ DEF_MOD("cmt3", 300, R8A7797_CLK_R), ++ DEF_MOD("cmt2", 301, R8A7797_CLK_R), ++ DEF_MOD("cmt1", 302, R8A7797_CLK_R), ++ DEF_MOD("cmt0", 303, R8A7797_CLK_R), ++ DEF_MOD("tpu", 304, R8A7797_CLK_S2D4), ++ DEF_MOD("sdif", 314, R8A7797_CLK_SD0), ++ DEF_MOD("rwdt0", 402, R8A7797_CLK_R), ++ DEF_MOD("intc-ex", 407, R8A7797_CLK_CP), ++ DEF_MOD("intc-ap", 408, R8A7797_CLK_S2D1), /* @@ H3=S3D1 */ ++ DEF_MOD("hscif3", 517, R8A7797_CLK_S2D1), /* @@ H3=S3D1 */ ++ DEF_MOD("hscif2", 518, R8A7797_CLK_S2D1), /* @@ H3=S3D1 */ ++ DEF_MOD("hscif1", 519, R8A7797_CLK_S2D1), /* @@ H3=S3D1 */ ++ DEF_MOD("hscif0", 520, R8A7797_CLK_S2D1), /* @@ H3=S3D1 */ ++ DEF_MOD("thermal", 522, R8A7797_CLK_CP), ++ DEF_MOD("pwm", 523, R8A7797_CLK_S2D4), ++ DEF_MOD("fcpvd0", 603, R8A7797_CLK_S2D1), ++ DEF_MOD("vspd0", 623, R8A7797_CLK_S2D1), ++ DEF_MOD("csi40", 716, R8A7797_CLK_CSI0), ++ DEF_MOD("du0", 724, R8A7797_CLK_S2D1), ++ DEF_MOD("lvds", 727, R8A7797_CLK_S2D1), ++ DEF_MOD("vin3", 808, R8A7797_CLK_S2D1), ++ DEF_MOD("vin2", 809, R8A7797_CLK_S2D1), ++ DEF_MOD("vin1", 810, R8A7797_CLK_S2D1), ++ DEF_MOD("vin0", 811, R8A7797_CLK_S2D1), ++ DEF_MOD("etheravb", 812, R8A7797_CLK_S2D2), ++ DEF_MOD("isp", 817, R8A7797_CLK_S2D1), /* @@ Unknown Module Clock */ ++ DEF_MOD("imr3", 820, R8A7797_CLK_S2D1), ++ DEF_MOD("imr2", 821, R8A7797_CLK_S2D1), ++ DEF_MOD("imr1", 822, R8A7797_CLK_S2D1), ++ DEF_MOD("imr0", 823, R8A7797_CLK_S2D1), ++ DEF_MOD("gpio5", 907, R8A7797_CLK_CP), ++ DEF_MOD("gpio4", 908, R8A7797_CLK_CP), ++ DEF_MOD("gpio3", 909, R8A7797_CLK_CP), ++ DEF_MOD("gpio2", 910, R8A7797_CLK_CP), ++ DEF_MOD("gpio1", 911, R8A7797_CLK_CP), ++ DEF_MOD("gpio0", 912, R8A7797_CLK_CP), ++ DEF_MOD("can-fd", 914, R8A7797_CLK_S2D2), /* @@ H3=S3D2 */ ++ DEF_MOD("i2c4", 927, R8A7797_CLK_S2D2), ++ DEF_MOD("i2c3", 928, R8A7797_CLK_S2D2), ++ DEF_MOD("i2c2", 929, R8A7797_CLK_S2D2), ++ DEF_MOD("i2c1", 930, R8A7797_CLK_S2D2), ++ DEF_MOD("i2c0", 931, R8A7797_CLK_S2D2), ++}; ++ ++static const unsigned int r8a7797_crit_mod_clks[] __initconst = { ++ MOD_CLK_ID(408), /* INTC-AP (GIC) */ ++}; ++ ++ ++/* ++ * CPG Clock Data ++ */ ++ ++/* ++ * MD EXTAL PLL0 PLL1 PLL3 ++ * 14 13 19 (MHz) ++ *------------------------------------------------- ++ * 0 0 0 16.66 x 1 x192 x192 x96 ++ * 0 0 1 16.66 x 1 x192 x192 x80 ++ * 0 1 0 20 x 1 x160 x160 x80 ++ * 0 1 1 20 x 1 x160 x160 x66 ++ * 1 0 0 27 / 2 x236 x236 x118 ++ * 1 0 1 27 / 2 x236 x236 x98 ++ * 1 1 0 33.33 / 2 x192 x192 x96 ++ * 1 1 1 33.33 / 2 x192 x192 x80 ++ */ ++#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \ ++ (((md) & BIT(13)) >> 12) | \ ++ (((md) & BIT(19)) >> 19)) ++ ++static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[8] __initconst = { ++ /* EXTAL div PLL1 mult PLL3 mult */ ++ { 1, 192, 96, }, ++ { 1, 192, 80, }, ++ { 1, 160, 80, }, ++ { 1, 160, 66, }, ++ { 2, 236, 118, }, ++ { 2, 236, 98, }, ++ { 2, 192, 96, }, ++ { 2, 192, 80, }, ++}; ++ ++static int __init r8a7797_cpg_mssr_init(struct device *dev) ++{ ++ const struct rcar_gen3_cpg_pll_config *cpg_pll_config; ++ u32 cpg_mode; ++ int error; ++ ++ error = rcar_rst_read_mode_pins(&cpg_mode); ++ if (error) ++ return error; ++ ++ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)]; ++ if (!cpg_pll_config->extal_div) { ++ dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode); ++ return -EINVAL; ++ } ++ ++ return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode); ++} ++ ++const struct cpg_mssr_info r8a7797_cpg_mssr_info __initconst = { ++ /* Core Clocks */ ++ .core_clks = r8a7797_core_clks, ++ .num_core_clks = ARRAY_SIZE(r8a7797_core_clks), ++ .last_dt_core_clk = LAST_DT_CORE_CLK, ++ .num_total_core_clks = MOD_CLK_BASE, ++ ++ /* Module Clocks */ ++ .mod_clks = r8a7797_mod_clks, ++ .num_mod_clks = ARRAY_SIZE(r8a7797_mod_clks), ++ .num_hw_mod_clks = 12 * 32, ++ ++ /* Critical Module Clocks */ ++ .crit_mod_clks = r8a7797_crit_mod_clks, ++ .num_crit_mod_clks = ARRAY_SIZE(r8a7797_crit_mod_clks), ++ ++ /* Callbacks */ ++ .init = r8a7797_cpg_mssr_init, ++ .cpg_clk_register = rcar_gen3_cpg_clk_register, ++}; +diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c +index 1cd2c05..b145f14 100644 +--- a/drivers/clk/renesas/rcar-gen3-cpg.c ++++ b/drivers/clk/renesas/rcar-gen3-cpg.c +@@ -26,6 +26,13 @@ + #include "renesas-cpg-mssr.h" + #include "rcar-gen3-cpg.h" + ++static spinlock_t cpg_lock; ++ ++static const struct soc_device_attribute r8a7797[] = { ++ { .soc_id = "r8a7797" }, ++ { /* sentinel */ } ++}; ++ + #define CPG_PLL0CR 0x00d8 + #define CPG_PLL2CR 0x002c + #define CPG_PLL4CR 0x01f4 +@@ -228,7 +235,10 @@ static unsigned long cpg_z2_clk_recalc_rate(struct clk_hw *hw, + unsigned int val; + unsigned long rate; + +- val = (clk_readl(zclk->reg) & CPG_FRQCRC_Z2FC_MASK); ++ if (!soc_device_match(r8a7797)) ++ val = (clk_readl(zclk->reg) & CPG_FRQCRC_Z2FC_MASK); ++ else ++ val = 0; + mult = 32 - val; + + rate = div_u64((u64)parent_rate * mult + 16, 32); +@@ -372,6 +382,11 @@ static int cpg_z2_clk_set_rate(struct clk_hw *hw, unsigned long rate, + u32 val, kick; + unsigned int i; + ++ if (soc_device_match(r8a7797)){ ++ pr_info("Do not support V3M's Z2 clock changing\n"); ++ return 0; ++ } ++ + mult = div_u64((u64)rate * 32 + parent_rate/2, parent_rate); + mult = clamp(mult, 1U, 32U); + +@@ -566,6 +581,19 @@ static struct clk * __init cpg_zg_clk_register(const char *name, + /* + * SDn Clock + */ ++/* SDHI divisors */ ++static const struct clk_div_table cpg_sdh_div_table[] = { ++ { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 }, ++ { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 }, ++ { 8, 24 }, { 10, 36 }, { 11, 48 }, { 0, 0 }, ++}; ++ ++static const struct clk_div_table cpg_sd01_div_table[] = { ++ { 4, 8 }, ++ { 5, 12 }, { 6, 16 }, { 7, 18 }, { 8, 24 }, ++ { 10, 36 }, { 11, 48 }, { 12, 10 }, { 0, 0 }, ++}; ++ + #define CPG_SD_STP_HCK BIT(9) + #define CPG_SD_STP_CK BIT(8) + +@@ -864,6 +892,14 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, + case CLK_TYPE_GEN3_SD: + return cpg_sd_clk_register(core, base, __clk_get_name(parent)); + ++ case CLK_TYPE_GEN3_SD0: ++ return clk_register_divider_table(NULL, core->name, __clk_get_name(parent), 0, base + 0x0074, ++ 4, 4,0, cpg_sd01_div_table, &cpg_lock); ++ ++ case CLK_TYPE_GEN3_SD0H: ++ return clk_register_divider_table(NULL, core->name, __clk_get_name(parent), 0, base + 0x0074, ++ 8, 4,0, cpg_sdh_div_table, &cpg_lock); ++ + case CLK_TYPE_GEN3_RINT: + div = cpg_pll_config->rint; + break; +@@ -917,5 +953,8 @@ int __init rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config, + if (attr) + cpg_quirks = (uintptr_t)attr->data; + pr_debug("%s: mode = 0x%x quirks = 0x%x\n", __func__, mode, cpg_quirks); ++ ++ spin_lock_init(&cpg_lock); ++ + return 0; + } +diff --git a/drivers/clk/renesas/rcar-gen3-cpg.h b/drivers/clk/renesas/rcar-gen3-cpg.h +index 51ae7b8..694bedc 100644 +--- a/drivers/clk/renesas/rcar-gen3-cpg.h ++++ b/drivers/clk/renesas/rcar-gen3-cpg.h +@@ -19,6 +19,8 @@ enum rcar_gen3_clk_types { + CLK_TYPE_GEN3_PLL3, + CLK_TYPE_GEN3_PLL4, + CLK_TYPE_GEN3_SD, ++ CLK_TYPE_GEN3_SD0, ++ CLK_TYPE_GEN3_SD0H, + CLK_TYPE_GEN3_R, + CLK_TYPE_GEN3_Z, + CLK_TYPE_GEN3_Z2, +@@ -29,6 +31,10 @@ enum rcar_gen3_clk_types { + + #define DEF_GEN3_SD(_name, _id, _parent, _offset) \ + DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD, _parent, .offset = _offset) ++#define DEF_GEN3_SD0(_name, _id, _parent, _offset) \ ++ DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD0, _parent, .offset = _offset) ++#define DEF_GEN3_SD0H(_name, _id, _parent, _offset) \ ++ DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD0H, _parent, .offset = _offset) + + struct rcar_gen3_cpg_pll_config { + unsigned int extal_div; +diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c +index 8c261e1..bd901a6 100644 +--- a/drivers/clk/renesas/renesas-cpg-mssr.c ++++ b/drivers/clk/renesas/renesas-cpg-mssr.c +@@ -594,6 +594,12 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev, + .data = &r8a77965_cpg_mssr_info, + }, + #endif ++#ifdef CONFIG_ARCH_R8A7797 ++ { ++ .compatible = "renesas,r8a7797-cpg-mssr", ++ .data = &r8a7797_cpg_mssr_info, ++ }, ++#endif + { /* sentinel */ } + }; + +diff --git a/drivers/clk/renesas/renesas-cpg-mssr.h b/drivers/clk/renesas/renesas-cpg-mssr.h +index 145b738..ce3546a 100644 +--- a/drivers/clk/renesas/renesas-cpg-mssr.h ++++ b/drivers/clk/renesas/renesas-cpg-mssr.h +@@ -135,6 +135,7 @@ struct cpg_mssr_info { + extern const struct cpg_mssr_info r8a7795_cpg_mssr_info; + extern const struct cpg_mssr_info r8a7796_cpg_mssr_info; + extern const struct cpg_mssr_info r8a77965_cpg_mssr_info; ++extern const struct cpg_mssr_info r8a7797_cpg_mssr_info; + + + /* +diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c +index 515d0e7..5a2ec23 100644 +--- a/drivers/cpufreq/cpufreq-dt-platdev.c ++++ b/drivers/cpufreq/cpufreq-dt-platdev.c +@@ -60,6 +60,7 @@ + { .compatible = "renesas,r8a7795", }, + { .compatible = "renesas,r8a7796", }, + { .compatible = "renesas,r8a77965", }, ++ { .compatible = "renesas,r8a7797", }, + { .compatible = "renesas,sh73a0", }, + + { .compatible = "rockchip,rk2928", }, +diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c +index 6917932..fd15649 100644 +--- a/drivers/gpio/gpio-rcar.c ++++ b/drivers/gpio/gpio-rcar.c +@@ -1,7 +1,7 @@ + /* + * Renesas R-Car GPIO Support + * +- * Copyright (C) 2014 Renesas Electronics Corporation ++ * Copyright (C) 2014-2016 Renesas Electronics Corporation + * Copyright (C) 2013 Magnus Damm + * + * This program is free software; you can redistribute it and/or modify +@@ -367,6 +367,10 @@ struct gpio_rcar_info { + /* Gen3 GPIO is identical to Gen2. */ + .data = &gpio_rcar_info_gen2, + }, { ++ .compatible = "renesas,gpio-r8a7797", ++ /* Gen3 GPIO is identical to Gen2. */ ++ .data = &gpio_rcar_info_gen2, ++ }, { + .compatible = "renesas,gpio-rcar", + .data = &gpio_rcar_info_gen1, + }, { +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c +index b234918..f74f264 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c +@@ -312,6 +312,30 @@ + .skip_ch = BIT(2), + }; + ++static const struct rcar_du_device_info rcar_du_r8a7797_info = { ++ .gen = 3, ++ .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK ++ | RCAR_DU_FEATURE_EXT_CTRL_REGS ++ | RCAR_DU_FEATURE_VSP1_SOURCE ++ | RCAR_DU_FEATURE_GEN3_REGS, ++ .num_crtcs = 1, ++ .routes = { ++ /* R8A7797 has one RGB output, one LVDS output. */ ++ [RCAR_DU_OUTPUT_DPAD0] = { ++ .possible_crtcs = BIT(0), ++ .encoder_type = DRM_MODE_ENCODER_NONE, ++ .port = 1, ++ }, ++ [RCAR_DU_OUTPUT_LVDS0] = { ++ .possible_crtcs = BIT(0), ++ .encoder_type = DRM_MODE_ENCODER_LVDS, ++ .port = 0, ++ }, ++ }, ++ .num_lvds = 1, ++ .dpll_ch = BIT(1), ++}; ++ + static const struct soc_device_attribute ths_quirks_match[] = { + { .soc_id = "r8a7795", .revision = "ES1.*", + .data = (void *)(RCAR_DU_DPLL_DUTY_RATE_WA +@@ -335,6 +359,7 @@ + { .compatible = "renesas,du-r8a7795", .data = &rcar_du_r8a7795_info }, + { .compatible = "renesas,du-r8a7796", .data = &rcar_du_r8a7796_info }, + { .compatible = "renesas,du-r8a77965", .data = &rcar_du_r8a77965_info }, ++ { .compatible = "renesas,du-r8a7797", .data = &rcar_du_r8a7797_info }, + { } + }; + +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c +index 1af5eb7..3916b63 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c +@@ -29,11 +29,17 @@ + + #include + #include ++#include + + #include "rcar_du_drv.h" + #include "rcar_du_group.h" + #include "rcar_du_regs.h" + ++static const struct soc_device_attribute r8a7797[] = { ++ { .soc_id = "r8a7797" }, ++ { } ++}; ++ + u32 rcar_du_group_read(struct rcar_du_group *rgrp, u32 reg) + { + return rcar_du_read(rgrp->dev, rgrp->mmio_offset + reg); +@@ -155,8 +161,10 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp) + + /* Apply planes to CRTCs association. */ + mutex_lock(&rgrp->lock); +- rcar_du_group_write(rgrp, DPTSR, (rgrp->dptsr_planes << 16) | +- rgrp->dptsr_planes); ++ if (!soc_device_match(r8a7797)) ++ rcar_du_group_write(rgrp, DPTSR, (rgrp->dptsr_planes << 16) | ++ rgrp->dptsr_planes); ++ + mutex_unlock(&rgrp->lock); + } + +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c +index ecae864..d5fa06c 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c +@@ -17,12 +17,18 @@ + #include + #include + #include ++#include + + #include "rcar_du_drv.h" + #include "rcar_du_encoder.h" + #include "rcar_du_lvdsenc.h" + #include "rcar_lvds_regs.h" + ++static const struct soc_device_attribute r8a7797[] = { ++ { .soc_id = "r8a7797" }, ++ { } ++}; ++ + struct rcar_du_lvdsenc { + struct rcar_du_device *dev; + +@@ -96,14 +102,25 @@ static void rcar_du_lvdsenc_start_gen3(struct rcar_du_lvdsenc *lvds, + u32 pllcr; + + /* PLL clock configuration */ +- if (freq < 42000) +- pllcr = LVDPLLCR_PLLDIVCNT_42M; +- else if (freq < 85000) +- pllcr = LVDPLLCR_PLLDIVCNT_85M; +- else if (freq < 128000) +- pllcr = LVDPLLCR_PLLDIVCNT_128M; +- else +- pllcr = LVDPLLCR_PLLDIVCNT_148M; ++ if (soc_device_match(r8a7797)) { ++ if (freq < 39000) ++ pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M; ++ else if (freq < 61000) ++ pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M; ++ else if (freq < 121000) ++ pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M; ++ else ++ pllcr = LVDPLLCR_PLLDLYCNT_150M; ++ } else { ++ if (freq < 42000) ++ pllcr = LVDPLLCR_PLLDIVCNT_42M; ++ else if (freq < 85000) ++ pllcr = LVDPLLCR_PLLDIVCNT_85M; ++ else if (freq < 128000) ++ pllcr = LVDPLLCR_PLLDIVCNT_128M; ++ else ++ pllcr = LVDPLLCR_PLLDIVCNT_148M; ++ } + + rcar_lvds_write(lvds, LVDPLLCR, pllcr); + +@@ -123,6 +140,11 @@ static void rcar_du_lvdsenc_start_gen3(struct rcar_du_lvdsenc *lvds, + lvdcr0 |= LVDCR0_PWD; + rcar_lvds_write(lvds, LVDCR0, lvdcr0); + ++ if (soc_device_match(r8a7797)) { ++ lvdcr0 |= LVDCR0_LVEN; ++ rcar_lvds_write(lvds, LVDCR0, lvdcr0); ++ } ++ + usleep_range(100, 150); + + lvdcr0 |= LVDCR0_LVRES; +diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c +index 74c17d8..149c107 100644 +--- a/drivers/i2c/busses/i2c-rcar.c ++++ b/drivers/i2c/busses/i2c-rcar.c +@@ -807,6 +807,7 @@ static u32 rcar_i2c_func(struct i2c_adapter *adap) + { .compatible = "renesas,i2c-r8a7795", .data = (void *)I2C_RCAR_GEN3 }, + { .compatible = "renesas,i2c-r8a7796", .data = (void *)I2C_RCAR_GEN3 }, + { .compatible = "renesas,i2c-r8a77965", .data = (void *)I2C_RCAR_GEN3 }, ++ { .compatible = "renesas,i2c-r8a7797", .data = (void *)I2C_RCAR_GEN3 }, + {}, + }; + MODULE_DEVICE_TABLE(of, rcar_i2c_dt_ids); +diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c +index e2baed1..1ae9174 100644 +--- a/drivers/iommu/ipmmu-vmsa.c ++++ b/drivers/iommu/ipmmu-vmsa.c +@@ -1,7 +1,7 @@ + /* + * IPMMU VMSA + * +- * Copyright (C) 2014 Renesas Electronics Corporation ++ * Copyright (C) 2014-2016 Renesas Electronics Corporation + * + * 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 +@@ -1277,6 +1277,9 @@ static void ipmmu_device_reset(struct ipmmu_vmsa_device *mmu) + .compatible = "renesas,ipmmu-r8a7796", + .data = &ipmmu_features_rcar_gen3, + }, { ++ .compatible = "renesas,ipmmu-r8a7797", ++ .data = &ipmmu_features_rcar_gen3, ++ }, { + /* Terminator */ + }, + }; +@@ -1648,6 +1651,8 @@ static int __init ipmmu_vmsa_iommu_of_setup(struct device_node *np) + ipmmu_vmsa_iommu_of_setup); + IOMMU_OF_DECLARE(ipmmu_r8a7796_iommu_of, "renesas,ipmmu-r8a7796", + ipmmu_vmsa_iommu_of_setup); ++IOMMU_OF_DECLARE(ipmmu_r8a7797_iommu_of, "renesas,ipmmu-r8a7797", ++ ipmmu_vmsa_iommu_of_setup); + #endif + + MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU"); +diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig +index 17178ad..5539c5d 100644 +--- a/drivers/media/platform/soc_camera/Kconfig ++++ b/drivers/media/platform/soc_camera/Kconfig +@@ -39,7 +39,7 @@ config VIDEO_RCAR_VIN_LEGACY_DEBUG + config VIDEO_RCAR_CSI2_LEGACY + tristate "R-Car MIPI CSI-2 Interface driver" + depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK +- depends on ARCH_R8A7795 || ARCH_R8A7796 || COMPILE_TEST ++ depends on ARCH_R8A7795 || ARCH_R8A7796 || ARCH_R8A7797 || COMPILE_TEST + ---help--- + This is a v4l2 driver for the R-Car CSI-2 Interface + +diff --git a/drivers/media/platform/soc_camera/rcar_csi2.c b/drivers/media/platform/soc_camera/rcar_csi2.c +index 05f623468..4d95da6 100644 +--- a/drivers/media/platform/soc_camera/rcar_csi2.c ++++ b/drivers/media/platform/soc_camera/rcar_csi2.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -153,6 +154,11 @@ + #define RCAR_CSI2_INTSTATE_ERRSYNCESC (1 << 1) + #define RCAR_CSI2_INTSTATE_ERRCONTROL (1 << 0) + ++static const struct soc_device_attribute r8a7797[] = { ++ { .soc_id = "r8a7797" }, ++ { } ++}; ++ + enum chip_id { + RCAR_GEN3, + RCAR_GEN2, +@@ -248,6 +254,17 @@ struct rcar_csi2 { + + static int rcar_csi2_set_phy_freq(struct rcar_csi2 *priv) + { ++ const uint32_t const hs_freq_range_v3m[43] = { ++ 0x00, 0x00, 0x20, 0x40, 0x02, /* 80M, 90M, 100M, 110M, 120M */ ++ 0x02, 0x22, 0x42, 0x04, 0x04, /* 130M, 140M, 150M, 160M, 170M */ ++ 0x24, 0x44, 0x44, 0x06, 0x26, /* 180M, 190M, 205M, 220M, 235M */ ++ 0x46, 0x08, 0x28, 0x0a, 0x2a, /* 250M, 270M, 300M, 325M, 350M */ ++ 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, /* 400M, 450M, 500M, 550M, 600M */ ++ 0x10, 0x30, 0x12, 0x32, 0x52, /* 650M, 700M, 750M, 800M, 950M */ ++ 0x72, 0x14, 0x34, 0x52, 0x74, /* 900M, 950M, 1000M, 1050M, 1100M */ ++ 0x16, 0x36, 0x56, 0x76, 0x18, /* 1150M, 1200M, 1250M, 1300M, 1350M */ ++ 0x38, 0x58, 0x78 /* 1400M, 1450M, 1500M */ ++ }; + const uint32_t const hs_freq_range[43] = { + 0x00, 0x10, 0x20, 0x30, 0x01, /* 0-4 */ + 0x11, 0x21, 0x31, 0x02, 0x12, /* 5-9 */ +@@ -304,7 +321,12 @@ static int rcar_csi2_set_phy_freq(struct rcar_csi2 *priv) + + dev_dbg(&priv->pdev->dev, "bps_per_lane (%d)\n", bps_per_lane); + +- iowrite32((hs_freq_range[bps_per_lane] << 16), ++ if (soc_device_match(r8a7797)) ++ iowrite32((hs_freq_range_v3m[bps_per_lane] << 16) | ++ RCAR_CSI2_PHTW_DWEN | RCAR_CSI2_PHTW_CWEN | 0x44, ++ priv->base + RCAR_CSI2_PHTW); ++ else ++ iowrite32(hs_freq_range[bps_per_lane] << 16, + priv->base + RCAR_CSI2_PHYPLL); + return 0; + +@@ -488,6 +510,7 @@ static int rcar_csi2_s_power(struct v4l2_subdev *sd, int on) + + #ifdef CONFIG_OF + static const struct of_device_id rcar_csi2_of_table[] = { ++ { .compatible = "renesas,r8a7797-csi2", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,r8a7796-csi2", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,r8a7795-csi2", .data = (void *)RCAR_GEN3 }, + { }, +@@ -496,6 +519,7 @@ static int rcar_csi2_s_power(struct v4l2_subdev *sd, int on) + #endif + + static struct platform_device_id rcar_csi2_id_table[] = { ++ { "r8a7797-csi2", RCAR_GEN3 }, + { "r8a7796-csi2", RCAR_GEN3 }, + { "r8a7795-csi2", RCAR_GEN3 }, + {}, +diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c +index 400958b..74fb005 100644 +--- a/drivers/media/platform/soc_camera/rcar_vin.c ++++ b/drivers/media/platform/soc_camera/rcar_vin.c +@@ -154,7 +154,7 @@ + #define VNCSI_IFMD_REG 0x20 /* Video n CSI2 Interface Mode Register */ + + #define VNCSI_IFMD_DES1 (1 << 26) /* CSI20 */ +-#define VNCSI_IFMD_DES0 (1 << 25) /* H3:CSI40/41, M3:CSI40 */ ++#define VNCSI_IFMD_DES0 (1 << 25) /* H3:CSI40/41, M3:CSI40, V3M:CSI40 */ + + #define VNCSI_IFMD_CSI_CHSEL(n) (n << 0) + #define VNCSI_IFMD_SEL_NUMBER 5 +@@ -185,6 +185,7 @@ + + enum chip_id { + RCAR_GEN3, ++ RCAR_V3M, + RCAR_M3, + RCAR_H3, + RCAR_GEN2, +@@ -360,6 +361,49 @@ struct vin_gen3_ifmd { + }, + }; + ++static const struct vin_gen3_ifmd vin_v3_vc_ifmd[] = { ++ { 0x0000, ++ { ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ } ++ }, ++ { 0x0001, ++ { ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ } ++ }, ++ { 0x0002, ++ { ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ } ++ }, ++ { 0x0003, ++ { ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH3}, ++ } ++ }, ++ { 0x0004, ++ { ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ } ++ }, ++}; ++ + enum csi2_fmt { + RCAR_CSI_FMT_NONE = -1, + RCAR_CSI_RGB888, +@@ -849,7 +893,8 @@ static int rcar_vin_videobuf_setup(struct vb2_queue *vq, + struct rcar_vin_priv *priv = ici->priv; + struct rcar_vin_cam *cam = icd->host_priv; + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { + if ((priv->ratio_h > 0x10000) || (priv->ratio_v > 0x10000)) { + dev_err(icd->parent, "Scaling rate parameter error\n"); + return -EINVAL; +@@ -951,7 +996,8 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + /* output format */ + switch (icd->current_fmt->host_fmt->fourcc) { + case V4L2_PIX_FMT_NV12: +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { + iowrite32(ALIGN((cam->out_width * cam->out_height), + 0x80), priv->base + VNUVAOF_REG); + dmr = VNDMR_DTMD_YCSEP_YCBCR420; +@@ -983,6 +1029,7 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + break; + case V4L2_PIX_FMT_XBGR32: + if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3 && ++ priv->chip != RCAR_V3M && + priv->chip != RCAR_GEN2 && priv->chip != RCAR_H1 && + priv->chip != RCAR_E1) + goto e_format; +@@ -990,7 +1037,8 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + dmr = VNDMR_EXRGB; + break; + case V4L2_PIX_FMT_ABGR32: +- if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3) ++ if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3 && ++ priv->chip != RCAR_V3M) + goto e_format; + + dmr = VNDMR_EXRGB | VNDMR_DTMD_ARGB; +@@ -1006,7 +1054,8 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + if (input_is_yuv == output_is_yuv) + vnmc |= VNMC_BPS; + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { + if (priv->pdata_flags & RCAR_VIN_CSI2) + vnmc &= ~VNMC_DPINE; + else +@@ -1323,7 +1372,8 @@ static int rcar_vin_add_device(struct soc_camera_device *icd) + + pm_runtime_get_sync(ici->v4l2_dev.dev); + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { + struct v4l2_subdev *csi2_sd = find_csi2(priv); + int ret; + +@@ -1569,7 +1619,8 @@ static int rcar_vin_set_rect(struct soc_camera_device *icd) + break; + } + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { + if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12) + && is_scaling(cam)) { + ret = rcar_vin_uds_set(priv, cam); +@@ -1720,14 +1771,16 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd) + if (ret < 0 && ret != -ENOIOCTLCMD) + return ret; + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { + if (cfg.type == V4L2_MBUS_CSI2) + vnmc &= ~VNMC_DPINE; + else + vnmc |= VNMC_DPINE; + } + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) + val = VNDMR2_FTEV; + else + val = VNDMR2_FTEV | VNDMR2_VLV(1); +@@ -2289,7 +2342,8 @@ static int rcar_vin_try_fmt(struct soc_camera_device *icd, + if (ret < 0) + return ret; + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { + /* Adjust max scaling size for Gen3 */ + if (pix->width > 4096) + pix->width = priv->max_width; +@@ -2454,6 +2508,7 @@ static int rcar_vin_cropcap(struct soc_camera_device *icd, + + #ifdef CONFIG_OF + static const struct of_device_id rcar_vin_of_table[] = { ++ { .compatible = "renesas,vin-r8a7797", .data = (void *)RCAR_V3M }, + { .compatible = "renesas,vin-r8a7796", .data = (void *)RCAR_M3 }, + { .compatible = "renesas,vin-r8a7795", .data = (void *)RCAR_H3 }, + { .compatible = "renesas,vin-r8a7794", .data = (void *)RCAR_GEN2 }, +@@ -2754,7 +2809,8 @@ static int rcar_vin_probe(struct platform_device *pdev) + priv->chip = (enum chip_id)match->data; + } + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { + priv->max_width = 4096; + priv->max_height = 4096; + } else { +@@ -2762,7 +2818,8 @@ static int rcar_vin_probe(struct platform_device *pdev) + priv->max_height = 2048; + } + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { + u32 ifmd = 0; + bool match_flag = false; + const struct vin_gen3_ifmd *gen3_ifmd_table = NULL; +@@ -2841,6 +2898,8 @@ static int rcar_vin_probe(struct platform_device *pdev) + gen3_ifmd_table = vin_h3_vc_ifmd; + else if (priv->chip == RCAR_M3) + gen3_ifmd_table = vin_m3_vc_ifmd; ++ else if (priv->chip == RCAR_V3M) ++ gen3_ifmd_table = vin_v3_vc_ifmd; + + for (i = 0; i < num; i++) { + if ((gen3_ifmd_table[i].v_sel[priv->index].csi2_ch +@@ -2983,6 +3042,9 @@ static int rcar_vin_resume(struct device *dev) + } else if (priv->chip == RCAR_M3) { + ifmd = VNCSI_IFMD_DES1; + gen3_ifmd_table = vin_m3_vc_ifmd; ++ } else if (priv->chip == RCAR_V3M) { ++ ifmd = VNCSI_IFMD_DES1; ++ gen3_ifmd_table = vin_v3_vc_ifmd; + } + + for (i = 0; i < num; i++) { +diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c +index cdaa097..6daeab4 100644 +--- a/drivers/media/platform/vsp1/vsp1_drv.c ++++ b/drivers/media/platform/vsp1/vsp1_drv.c +@@ -893,6 +893,15 @@ void vsp1_device_put(struct vsp1_device *vsp1) + .wpf_count = 2, + .num_bru_inputs = 5, + .header_mode = true, ++ }, { ++ .version = VI6_IP_VERSION_MODEL_VSPD_V3M, ++ .model = "VSP2-D", ++ .gen = 3, ++ .features = VSP1_HAS_BRU | VSP1_HAS_LIF, ++ .rpf_count = 5, ++ .wpf_count = 1, ++ .num_bru_inputs = 5, ++ .header_mode = true, + }, + }; + +diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c +index b442d14..e79f9e6 100644 +--- a/drivers/media/platform/vsp1/vsp1_lif.c ++++ b/drivers/media/platform/vsp1/vsp1_lif.c +@@ -13,6 +13,7 @@ + + #include + #include ++#include + + #include + +@@ -23,6 +24,11 @@ + #define LIF_MIN_SIZE 2U + #define LIF_MAX_SIZE 8190U + ++static const struct soc_device_attribute r8a7797[] = { ++ { .soc_id = "r8a7797" }, ++ { } ++}; ++ + /* ----------------------------------------------------------------------------- + * Device Access + */ +@@ -145,7 +151,7 @@ static void lif_configure(struct vsp1_entity *entity, + format = vsp1_entity_get_pad_format(&lif->entity, lif->entity.config, + LIF_PAD_SOURCE); + +- if (vsp1_gen3_vspdl_check(vsp1)) ++ if (vsp1_gen3_vspdl_check(vsp1) || soc_device_match(r8a7797)) + obth = 1500; + else + obth = 3000; +@@ -158,6 +164,10 @@ static void lif_configure(struct vsp1_entity *entity, + (obth << VI6_LIF_CTRL_OBTH_SHIFT) | + (format->code == 0 ? VI6_LIF_CTRL_CFMT : 0) | + VI6_LIF_CTRL_REQSEL | VI6_LIF_CTRL_LIF_EN); ++ ++ if (soc_device_match(r8a7797)) ++ vsp1_lif_write(lif, dl, VI6_LIF_LBA, VI6_LIF_LBA_LBA0 | ++ VI6_LIF_LBA_LBA1); + } + + static const struct vsp1_entity_operations lif_entity_ops = { +diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h +index 9134dbd..6c971f7 100644 +--- a/drivers/media/platform/vsp1/vsp1_regs.h ++++ b/drivers/media/platform/vsp1/vsp1_regs.h +@@ -789,6 +789,12 @@ + #define VI6_LIF_CSBTH_LBTH_MASK (0x7ff << 0) + #define VI6_LIF_CSBTH_LBTH_SHIFT 0 + ++ ++#define VI6_LIF_LBA 0x3b0c ++#define VI6_LIF_LBA_LBA0 (1 << 31) ++#define VI6_LIF_LBA_LBA1 (0x600 << 16) ++ ++ + /* ----------------------------------------------------------------------------- + * Security Control Registers + */ +@@ -812,6 +818,7 @@ + #define VI6_IP_VERSION_MODEL_VSPBD_GEN3 (0x15 << 8) + #define VI6_IP_VERSION_MODEL_VSPBC_GEN3 (0x16 << 8) + #define VI6_IP_VERSION_MODEL_VSPD_GEN3 (0x17 << 8) ++#define VI6_IP_VERSION_MODEL_VSPD_V3M (0x18 << 8) + #define VI6_IP_VERSION_MODEL_VSPDL_GEN3 (0x19 << 8) + + #define VI6_IP_VERSION_SOC_MASK (0xff << 0) +diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c +index a7fb054..040f474 100644 +--- a/drivers/mmc/host/sh_mobile_sdhi.c ++++ b/drivers/mmc/host/sh_mobile_sdhi.c +@@ -140,6 +140,7 @@ struct sh_mobile_sdhi_of_data { + { .compatible = "renesas,sdhi-r8a7796", .data = &of_rcar_gen3_compatible, }, + { .compatible = "renesas,sdhi-r8a77965", + .data = &of_rcar_gen3_compatible, }, ++ { .compatible = "renesas,sdhi-r8a7797", .data = &of_rcar_gen3_compatible, }, + {}, + }; + MODULE_DEVICE_TABLE(of, sh_mobile_sdhi_of_match); +diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c +index 5ad4d13..73fa286 100644 +--- a/drivers/net/ethernet/renesas/ravb_main.c ++++ b/drivers/net/ethernet/renesas/ravb_main.c +@@ -1920,6 +1920,7 @@ static int ravb_mdio_release(struct ravb_private *priv) + { .compatible = "renesas,etheravb-r8a7795", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,etheravb-r8a7796", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,etheravb-r8a77965", .data = (void *)RCAR_GEN3 }, ++ { .compatible = "renesas,etheravb-r8a7797", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,etheravb-rcar-gen3", .data = (void *)RCAR_GEN3 }, + { } + }; +diff --git a/drivers/pinctrl/sh-pfc/Kconfig b/drivers/pinctrl/sh-pfc/Kconfig +index 6d2cdf8..4aaf0be 100644 +--- a/drivers/pinctrl/sh-pfc/Kconfig ++++ b/drivers/pinctrl/sh-pfc/Kconfig +@@ -84,6 +84,11 @@ config PINCTRL_PFC_R8A77965 + depends on ARCH_R8A77965 + select PINCTRL_SH_PFC + ++config PINCTRL_PFC_R8A7797 ++ def_bool y ++ depends on ARCH_R8A7797 ++ select PINCTRL_SH_PFC ++ + config PINCTRL_PFC_SH7203 + def_bool y + depends on CPU_SUBTYPE_SH7203 +diff --git a/drivers/pinctrl/sh-pfc/Makefile b/drivers/pinctrl/sh-pfc/Makefile +index f12017b..e263c14 100644 +--- a/drivers/pinctrl/sh-pfc/Makefile ++++ b/drivers/pinctrl/sh-pfc/Makefile +@@ -14,6 +14,7 @@ obj-$(CONFIG_PINCTRL_PFC_R8A7795) += pfc-r8a7795.o + obj-$(CONFIG_PINCTRL_PFC_R8A7795) += pfc-r8a7795-es1.o + obj-$(CONFIG_PINCTRL_PFC_R8A7796) += pfc-r8a7796.o + obj-$(CONFIG_PINCTRL_PFC_R8A77965) += pfc-r8a77965.o ++obj-$(CONFIG_PINCTRL_PFC_R8A7797) += pfc-r8a7797.o + obj-$(CONFIG_PINCTRL_PFC_SH7203) += pfc-sh7203.o + obj-$(CONFIG_PINCTRL_PFC_SH7264) += pfc-sh7264.o + obj-$(CONFIG_PINCTRL_PFC_SH7269) += pfc-sh7269.o +diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c +index a6a8f65..9aba933 100644 +--- a/drivers/pinctrl/sh-pfc/core.c ++++ b/drivers/pinctrl/sh-pfc/core.c +@@ -5,6 +5,7 @@ + * + * Copyright (C) 2008 Magnus Damm + * Copyright (C) 2009 - 2012 Paul Mundt ++ * Copyright (C) 2016 Renesas Electronics Corp. + * + * 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 +@@ -545,6 +546,12 @@ static int sh_pfc_init_ranges(struct sh_pfc *pfc) + .data = &r8a77965_pinmux_info, + }, + #endif ++#ifdef CONFIG_PINCTRL_PFC_R8A7797 ++ { ++ .compatible = "renesas,pfc-r8a7797", ++ .data = &r8a7797_pinmux_info, ++ }, ++#endif + #ifdef CONFIG_PINCTRL_PFC_SH73A0 + { + .compatible = "renesas,pfc-sh73a0", +diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7797.c b/drivers/pinctrl/sh-pfc/pfc-r8a7797.c +new file mode 100644 +index 0000000..6b83f44 +--- /dev/null ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a7797.c +@@ -0,0 +1,2628 @@ ++/* ++ * R8A7797 processor support - PFC hardware block. ++ * ++ * Copyright (C) 2016 Renesas Electronics Corp. ++ * ++ * This file is based on the drivers/pinctrl/sh-pfc/pfc-r8a7795.c ++ * ++ * R-Car Gen3 processor support - PFC hardware block. ++ * ++ * Copyright (C) 2015 Renesas Electronics Corporation ++ * ++ * 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; version 2 of the License. ++ */ ++ ++#include ++#include ++#include ++ ++#include "core.h" ++#include "sh_pfc.h" ++ ++#define CPU_ALL_PORT(fn, sfx) \ ++ PORT_GP_CFG_22(0, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \ ++ PORT_GP_CFG_28(1, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \ ++ PORT_GP_CFG_17(2, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \ ++ PORT_GP_CFG_17(3, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH | \ ++ SH_PFC_PIN_CFG_IO_VOLTAGE), \ ++ PORT_GP_CFG_6(4, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \ ++ PORT_GP_CFG_15(5, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH) ++/* ++ * F_() : just information ++ * FM() : macro for FN_xxx / xxx_MARK ++ */ ++ ++/* GPSR0 */ ++#define GPSR0_21 F_(DU_EXODDF_DU_ODDF_DISP_CDE, IP2_23_20) ++#define GPSR0_20 F_(DU_EXVSYNC_DU_VSYNC, IP2_19_16) ++#define GPSR0_19 F_(DU_EXHSYNC_DU_HSYNC, IP2_15_12) ++#define GPSR0_18 F_(DU_DOTCLKOUT, IP2_11_8) ++#define GPSR0_17 F_(DU_DB7, IP2_7_4) ++#define GPSR0_16 F_(DU_DB6, IP2_3_0) ++#define GPSR0_15 F_(DU_DB5, IP1_31_28) ++#define GPSR0_14 F_(DU_DB4, IP1_27_24) ++#define GPSR0_13 F_(DU_DB3, IP1_23_20) ++#define GPSR0_12 F_(DU_DB2, IP1_19_16) ++#define GPSR0_11 F_(DU_DG7, IP1_15_12) ++#define GPSR0_10 F_(DU_DG6, IP1_11_8) ++#define GPSR0_9 F_(DU_DG5, IP1_7_4) ++#define GPSR0_8 F_(DU_DG4, IP1_3_0) ++#define GPSR0_7 F_(DU_DG3, IP0_31_28) ++#define GPSR0_6 F_(DU_DG2, IP0_27_24) ++#define GPSR0_5 F_(DU_DR7, IP0_23_20) ++#define GPSR0_4 F_(DU_DR6, IP0_19_16) ++#define GPSR0_3 F_(DU_DR5, IP0_15_12) ++#define GPSR0_2 F_(DU_DR4, IP0_11_8) ++#define GPSR0_1 F_(DU_DR3, IP0_7_4) ++#define GPSR0_0 F_(DU_DR2, IP0_3_0) ++ ++/* GPSR1 */ ++#define GPSR1_27 F_(DIGRF_CLKOUT, IP8_27_24) ++#define GPSR1_26 F_(DIGRF_CLKIN, IP8_23_20) ++#define GPSR1_25 F_(CANFD_CLK_A, IP8_19_16) ++#define GPSR1_24 F_(CANFD1_RX, IP8_15_12) ++#define GPSR1_23 F_(CANFD1_TX, IP8_11_8) ++#define GPSR1_22 F_(CANFD0_RX_A, IP8_7_4) ++#define GPSR1_21 F_(CANFD0_TX_A, IP8_3_0) ++#define GPSR1_20 F_(AVB0_AVTP_CAPTURE, IP7_31_28) ++#define GPSR1_19 FM(AVB0_AVTP_MATCH) ++#define GPSR1_18 FM(AVB0_LINK) ++#define GPSR1_17 FM(AVB0_PHY_INT) ++#define GPSR1_16 FM(AVB0_MAGIC) ++#define GPSR1_15 FM(AVB0_MDC) ++#define GPSR1_14 FM(AVB0_MDIO) ++#define GPSR1_13 FM(AVB0_TXCREFCLK) ++#define GPSR1_12 FM(AVB0_TD3) ++#define GPSR1_11 FM(AVB0_TD2) ++#define GPSR1_10 FM(AVB0_TD1) ++#define GPSR1_9 FM(AVB0_TD0) ++#define GPSR1_8 FM(AVB0_TXC) ++#define GPSR1_7 FM(AVB0_TX_CTL) ++#define GPSR1_6 FM(AVB0_RD3) ++#define GPSR1_5 FM(AVB0_RD2) ++#define GPSR1_4 FM(AVB0_RD1) ++#define GPSR1_3 FM(AVB0_RD0) ++#define GPSR1_2 FM(AVB0_RXC) ++#define GPSR1_1 FM(AVB0_RX_CTL) ++#define GPSR1_0 F_(IRQ0, IP2_27_24) ++ ++/* GPSR2 */ ++#define GPSR2_16 F_(VI0_FIELD, IP4_31_28) ++#define GPSR2_15 F_(VI0_DATA11, IP4_27_24) ++#define GPSR2_14 F_(VI0_DATA10, IP4_23_20) ++#define GPSR2_13 F_(VI0_DATA9, IP4_19_16) ++#define GPSR2_12 F_(VI0_DATA8, IP4_15_12) ++#define GPSR2_11 F_(VI0_DATA7, IP4_11_8) ++#define GPSR2_10 F_(VI0_DATA6, IP4_7_4) ++#define GPSR2_9 F_(VI0_DATA5, IP4_3_0) ++#define GPSR2_8 F_(VI0_DATA4, IP3_31_28) ++#define GPSR2_7 F_(VI0_DATA3, IP3_27_24) ++#define GPSR2_6 F_(VI0_DATA2, IP3_23_20) ++#define GPSR2_5 F_(VI0_DATA1, IP3_19_16) ++#define GPSR2_4 F_(VI0_DATA0, IP3_15_12) ++#define GPSR2_3 F_(VI0_VSYNC_N, IP3_11_8) ++#define GPSR2_2 F_(VI0_HSYNC_N, IP3_7_4) ++#define GPSR2_1 F_(VI0_CLKENB, IP3_3_0) ++#define GPSR2_0 F_(VI0_CLK, IP2_31_28) ++ ++/* GPSR3 */ ++#define GPSR3_16 F_(VI1_FIELD, IP7_3_0) ++#define GPSR3_15 F_(VI1_DATA11, IP6_31_28) ++#define GPSR3_14 F_(VI1_DATA10, IP6_27_24) ++#define GPSR3_13 F_(VI1_DATA9, IP6_23_20) ++#define GPSR3_12 F_(VI1_DATA8, IP6_19_16) ++#define GPSR3_11 F_(VI1_DATA7, IP6_15_12) ++#define GPSR3_10 F_(VI1_DATA6, IP6_11_8) ++#define GPSR3_9 F_(VI1_DATA5, IP6_7_4) ++#define GPSR3_8 F_(VI1_DATA4, IP6_3_0) ++#define GPSR3_7 F_(VI1_DATA3, IP5_31_28) ++#define GPSR3_6 F_(VI1_DATA2, IP5_27_24) ++#define GPSR3_5 F_(VI1_DATA1, IP5_23_20) ++#define GPSR3_4 F_(VI1_DATA0, IP5_19_16) ++#define GPSR3_3 F_(VI1_VSYNC_N, IP5_15_12) ++#define GPSR3_2 F_(VI1_HSYNC_N, IP5_11_8) ++#define GPSR3_1 F_(VI1_CLKENB, IP5_7_4) ++#define GPSR3_0 F_(VI1_CLK, IP5_3_0) ++ ++/* GPSR4 */ ++#define GPSR4_5 F_(SDA2, IP7_27_24) ++#define GPSR4_4 F_(SCL2, IP7_23_20) ++#define GPSR4_3 F_(SDA1, IP7_19_16) ++#define GPSR4_2 F_(SCL1, IP7_15_12) ++#define GPSR4_1 F_(SDA0, IP7_11_8) ++#define GPSR4_0 F_(SCL0, IP7_7_4) ++ ++/* GPSR5 */ ++#define GPSR5_14 FM(RPC_INT_N) ++#define GPSR5_13 FM(RPC_WP_N) ++#define GPSR5_12 FM(RPC_RESET_N) ++#define GPSR5_11 FM(QSPI1_SSL) ++#define GPSR5_10 FM(QSPI1_IO3) ++#define GPSR5_9 FM(QSPI1_IO2) ++#define GPSR5_8 FM(QSPI1_MISO_IO1) ++#define GPSR5_7 FM(QSPI1_MOSI_IO0) ++#define GPSR5_6 FM(QSPI1_SPCLK) ++#define GPSR5_5 FM(QSPI0_SSL) ++#define GPSR5_4 FM(QSPI0_IO3) ++#define GPSR5_3 FM(QSPI0_IO2) ++#define GPSR5_2 FM(QSPI0_MISO_IO1) ++#define GPSR5_1 FM(QSPI0_MOSI_IO0) ++#define GPSR5_0 FM(QSPI0_SPCLK) ++ ++ ++/* IPSRx */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 */ /* 8 */ /* 9 */ /* A */ /* B */ /* C */ /* D */ /* E */ /* F */ ++#define IP0_3_0 FM(DU_DR2) FM(HSCK0) F_(0, 0) FM(A0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP0_7_4 FM(DU_DR3) FM(HRTS0_N) F_(0, 0) FM(A1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP0_11_8 FM(DU_DR4) FM(HCTS0_N) F_(0, 0) FM(A2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP0_15_12 FM(DU_DR5) FM(HTX0) F_(0, 0) FM(A3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP0_19_16 FM(DU_DR6) FM(MSIOF3_RXD) F_(0, 0) FM(A4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP0_23_20 FM(DU_DR7) FM(MSIOF3_TXD) F_(0, 0) FM(A5) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP0_27_24 FM(DU_DG2) FM(MSIOF3_SS1) F_(0, 0) FM(A6) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP0_31_28 FM(DU_DG3) FM(MSIOF3_SS2) F_(0, 0) FM(A7) FM(PWMFSW0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP1_3_0 FM(DU_DG4) F_(0, 0) F_(0, 0) FM(A8) FM(FSO_CFE_0_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP1_7_4 FM(DU_DG5) F_(0, 0) F_(0, 0) FM(A9) FM(FSO_CFE_1_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP1_11_8 FM(DU_DG6) F_(0, 0) F_(0, 0) FM(A10) FM(FSO_TOE_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP1_15_12 FM(DU_DG7) F_(0, 0) F_(0, 0) FM(A11) FM(IRQ1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP1_19_16 FM(DU_DB2) F_(0, 0) F_(0, 0) FM(A12) FM(IRQ2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP1_23_20 FM(DU_DB3) F_(0, 0) F_(0, 0) FM(A13) FM(FXR_CLKOUT1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP1_27_24 FM(DU_DB4) F_(0, 0) F_(0, 0) FM(A14) FM(FXR_CLKOUT2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP1_31_28 FM(DU_DB5) F_(0, 0) F_(0, 0) FM(A15) FM(FXR_TXENA_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP2_3_0 FM(DU_DB6) F_(0, 0) F_(0, 0) FM(A16) FM(FXR_TXENB_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP2_7_4 FM(DU_DB7) F_(0, 0) F_(0, 0) FM(A17) FM(STPWT_EXTFXR) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP2_11_8 FM(DU_DOTCLKOUT) FM(SCIF_CLK_A) F_(0, 0) FM(A18) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP2_15_12 FM(DU_EXHSYNC_DU_HSYNC) FM(HRX0) F_(0, 0) FM(A19) FM(IRQ3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP2_19_16 FM(DU_EXVSYNC_DU_VSYNC) FM(MSIOF3_SCK) F_(0, 0) FM(A20) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP2_23_20 FM(DU_EXODDF_DU_ODDF_DISP_CDE) FM(MSIOF3_SYNC) F_(0, 0) FM(A21) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP2_27_24 FM(IRQ0) FM(CC5_OSCOUT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP2_31_28 FM(VI0_CLK) FM(MSIOF2_SCK) FM(SCK3) F_(0, 0) FM(HSCK3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP3_3_0 FM(VI0_CLKENB) FM(MSIOF2_RXD) FM(RX3) FM(RD_WR_N) FM(HCTS3_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP3_7_4 FM(VI0_HSYNC_N) FM(MSIOF2_TXD) FM(TX3) F_(0, 0) FM(HRTS3_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP3_11_8 FM(VI0_VSYNC_N) FM(MSIOF2_SYNC) FM(CTS3_N) F_(0, 0) FM(HTX3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP3_15_12 FM(VI0_DATA0) FM(MSIOF2_SS1) FM(RTS3_N_TANS) F_(0, 0) FM(HRX3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP3_19_16 FM(VI0_DATA1) FM(MSIOF2_SS2) FM(SCK1) F_(0, 0) FM(SPEEDIN_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP3_23_20 FM(VI0_DATA2) FM(AVB0_AVTP_PPS) FM(SDA3_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP3_27_24 FM(VI0_DATA3) FM(HSCK1) FM(SCL3_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP3_31_28 FM(VI0_DATA4) FM(HRTS1_N) FM(RX1_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP4_3_0 FM(VI0_DATA5) FM(HCTS1_N) FM(TX1_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP4_7_4 FM(VI0_DATA6) FM(HTX1) FM(CTS1_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP4_11_8 FM(VI0_DATA7) FM(HRX1) FM(RTS1_N_TANS) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP4_15_12 FM(VI0_DATA8) FM(HSCK2) FM(PWM0_A) FM(A22) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP4_19_16 FM(VI0_DATA9) FM(HCTS2_N) FM(PWM1_A) FM(A23) FM(FSO_CFE_0_N_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP4_23_20 FM(VI0_DATA10) FM(HRTS2_N) FM(PWM2_A) FM(A24) FM(FSO_CFE_1_N_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP4_27_24 FM(VI0_DATA11) FM(HTX2) FM(PWM3_A) FM(A25) FM(FSO_TOE_N_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP4_31_28 FM(VI0_FIELD) FM(HRX2) FM(PWM4_A) FM(CS1_N_A26) FM(FSCLKST2_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP5_3_0 FM(VI1_CLK) FM(MSIOF1_RXD) F_(0, 0) FM(CS0_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP5_7_4 FM(VI1_CLKENB) FM(MSIOF1_TXD) F_(0, 0) FM(D0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP5_11_8 FM(VI1_HSYNC_N) FM(MSIOF1_SCK) F_(0, 0) FM(D1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP5_15_12 FM(VI1_VSYNC_N) FM(MSIOF1_SYNC) F_(0, 0) FM(D2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP5_19_16 FM(VI1_DATA0) FM(MSIOF1_SS1) F_(0, 0) FM(D3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP5_23_20 FM(VI1_DATA1) FM(MSIOF1_SS2) F_(0, 0) FM(D4) FM(MMC_CMD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP5_27_24 FM(VI1_DATA2) FM(CANFD0_TX_B) F_(0, 0) FM(D5) FM(MMC_D0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP5_31_28 FM(VI1_DATA3) FM(CANFD0_RX_B) F_(0, 0) FM(D6) FM(MMC_D1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP6_3_0 FM(VI1_DATA4) FM(CANFD_CLK_B) F_(0, 0) FM(D7) FM(MMC_D2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP6_7_4 FM(VI1_DATA5) F_(0,0) FM(SCK4) FM(D8) FM(MMC_D3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP6_11_8 FM(VI1_DATA6) F_(0,0) FM(RX4) FM(D9) FM(MMC_CLK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP6_15_12 FM(VI1_DATA7) F_(0,0) FM(TX4) FM(D10) FM(MMC_D4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP6_19_16 FM(VI1_DATA8) F_(0,0) FM(CTS4_N) FM(D11) FM(MMC_D5) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP6_23_20 FM(VI1_DATA9) F_(0,0) FM(RTS4_N_TANS) FM(D12) FM(MMC_D6) FM(SCL3_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP6_27_24 FM(VI1_DATA10) F_(0,0) F_(0, 0) FM(D13) FM(MMC_D7) FM(SDA3_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP6_31_28 FM(VI1_DATA11) FM(SCL4) FM(IRQ4) FM(D14) FM(MMC_WP) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP7_3_0 FM(VI1_FIELD) FM(SDA4) FM(IRQ5) FM(D15) FM(MMC_CD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP7_7_4 FM(SCL0) FM(DU_DR0) FM(TPU0TO0) FM(CLKOUT) F_(0, 0) FM(MSIOF0_RXD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP7_11_8 FM(SDA0) FM(DU_DR1) FM(TPU0TO1) FM(BS_N) FM(SCK0) FM(MSIOF0_TXD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP7_15_12 FM(SCL1) FM(DU_DG0) FM(TPU0TO2) FM(RD_N) FM(CTS0_N) FM(MSIOF0_SCK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP7_19_16 FM(SDA1) FM(DU_DG1) FM(TPU0TO3) FM(WE0_N) FM(RTS0_N_TANS) FM(MSIOF0_SYNC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP7_23_20 FM(SCL2) FM(DU_DB0) FM(TCLK1_A) FM(WE1_N) FM(RX0) FM(MSIOF0_SS1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP7_27_24 FM(SDA2) FM(DU_DB1) FM(TCLK2_A) FM(EX_WAIT0) FM(TX0) FM(MSIOF0_SS2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP7_31_28 FM(AVB0_AVTP_CAPTURE) F_(0, 0) F_(0, 0) F_(0, 0) FM(FSCLKST2_N_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP8_3_0 FM(CANFD0_TX_A) FM(FXR_TXDA) FM(PWM0_B) FM(DU_DISP) FM(FSCLKST2_N_C) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP8_7_4 FM(CANFD0_RX_A) FM(RXDA_EXTFXR) FM(PWM1_B) FM(DU_CDE) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP8_11_8 FM(CANFD1_TX) FM(FXR_TXDB) FM(PWM2_B) FM(TCLK1_B) FM(TX1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP8_15_12 FM(CANFD1_RX) FM(RXDB_EXTFXR) FM(PWM3_B) FM(TCLK2_B) FM(RX1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP8_19_16 FM(CANFD_CLK_A) FM(CLK_EXTFXR) FM(PWM4_B) FM(SPEEDIN_B) FM(SCIF_CLK_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP8_23_20 FM(DIGRF_CLKIN) FM(DIGRF_CLKEN_IN) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP8_27_24 FM(DIGRF_CLKOUT) FM(DIGRF_CLKEN_OUT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP8_31_28 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++ ++#define PINMUX_GPSR \ ++\ ++ GPSR1_27 \ ++ GPSR1_26 \ ++ GPSR1_25 \ ++ GPSR1_24 \ ++ GPSR1_23 \ ++ GPSR1_22 \ ++GPSR0_21 GPSR1_21 \ ++GPSR0_20 GPSR1_20 \ ++GPSR0_19 GPSR1_19 \ ++GPSR0_18 GPSR1_18 \ ++GPSR0_17 GPSR1_17 \ ++GPSR0_16 GPSR1_16 GPSR2_16 GPSR3_16 \ ++GPSR0_15 GPSR1_15 GPSR2_15 GPSR3_15 \ ++GPSR0_14 GPSR1_14 GPSR2_14 GPSR3_14 GPSR5_14 \ ++GPSR0_13 GPSR1_13 GPSR2_13 GPSR3_13 GPSR5_13 \ ++GPSR0_12 GPSR1_12 GPSR2_12 GPSR3_12 GPSR5_12 \ ++GPSR0_11 GPSR1_11 GPSR2_11 GPSR3_11 GPSR5_11 \ ++GPSR0_10 GPSR1_10 GPSR2_10 GPSR3_10 GPSR5_10 \ ++GPSR0_9 GPSR1_9 GPSR2_9 GPSR3_9 GPSR5_9 \ ++GPSR0_8 GPSR1_8 GPSR2_8 GPSR3_8 GPSR5_8 \ ++GPSR0_7 GPSR1_7 GPSR2_7 GPSR3_7 GPSR5_7 \ ++GPSR0_6 GPSR1_6 GPSR2_6 GPSR3_6 GPSR5_6 \ ++GPSR0_5 GPSR1_5 GPSR2_5 GPSR3_5 GPSR4_5 GPSR5_5 \ ++GPSR0_4 GPSR1_4 GPSR2_4 GPSR3_4 GPSR4_4 GPSR5_4 \ ++GPSR0_3 GPSR1_3 GPSR2_3 GPSR3_3 GPSR4_3 GPSR5_3 \ ++GPSR0_2 GPSR1_2 GPSR2_2 GPSR3_2 GPSR4_2 GPSR5_2 \ ++GPSR0_1 GPSR1_1 GPSR2_1 GPSR3_1 GPSR4_1 GPSR5_1 \ ++GPSR0_0 GPSR1_0 GPSR2_0 GPSR3_0 GPSR4_0 GPSR5_0 ++ ++#define PINMUX_IPSR \ ++\ ++FM(IP0_3_0) IP0_3_0 FM(IP1_3_0) IP1_3_0 FM(IP2_3_0) IP2_3_0 FM(IP3_3_0) IP3_3_0 \ ++FM(IP0_7_4) IP0_7_4 FM(IP1_7_4) IP1_7_4 FM(IP2_7_4) IP2_7_4 FM(IP3_7_4) IP3_7_4 \ ++FM(IP0_11_8) IP0_11_8 FM(IP1_11_8) IP1_11_8 FM(IP2_11_8) IP2_11_8 FM(IP3_11_8) IP3_11_8 \ ++FM(IP0_15_12) IP0_15_12 FM(IP1_15_12) IP1_15_12 FM(IP2_15_12) IP2_15_12 FM(IP3_15_12) IP3_15_12 \ ++FM(IP0_19_16) IP0_19_16 FM(IP1_19_16) IP1_19_16 FM(IP2_19_16) IP2_19_16 FM(IP3_19_16) IP3_19_16 \ ++FM(IP0_23_20) IP0_23_20 FM(IP1_23_20) IP1_23_20 FM(IP2_23_20) IP2_23_20 FM(IP3_23_20) IP3_23_20 \ ++FM(IP0_27_24) IP0_27_24 FM(IP1_27_24) IP1_27_24 FM(IP2_27_24) IP2_27_24 FM(IP3_27_24) IP3_27_24 \ ++FM(IP0_31_28) IP0_31_28 FM(IP1_31_28) IP1_31_28 FM(IP2_31_28) IP2_31_28 FM(IP3_31_28) IP3_31_28 \ ++\ ++FM(IP4_3_0) IP4_3_0 FM(IP5_3_0) IP5_3_0 FM(IP6_3_0) IP6_3_0 FM(IP7_3_0) IP7_3_0 \ ++FM(IP4_7_4) IP4_7_4 FM(IP5_7_4) IP5_7_4 FM(IP6_7_4) IP6_7_4 FM(IP7_7_4) IP7_7_4 \ ++FM(IP4_11_8) IP4_11_8 FM(IP5_11_8) IP5_11_8 FM(IP6_11_8) IP6_11_8 FM(IP7_11_8) IP7_11_8 \ ++FM(IP4_15_12) IP4_15_12 FM(IP5_15_12) IP5_15_12 FM(IP6_15_12) IP6_15_12 FM(IP7_15_12) IP7_15_12 \ ++FM(IP4_19_16) IP4_19_16 FM(IP5_19_16) IP5_19_16 FM(IP6_19_16) IP6_19_16 FM(IP7_19_16) IP7_19_16 \ ++FM(IP4_23_20) IP4_23_20 FM(IP5_23_20) IP5_23_20 FM(IP6_23_20) IP6_23_20 FM(IP7_23_20) IP7_23_20 \ ++FM(IP4_27_24) IP4_27_24 FM(IP5_27_24) IP5_27_24 FM(IP6_27_24) IP6_27_24 FM(IP7_27_24) IP7_27_24 \ ++FM(IP4_31_28) IP4_31_28 FM(IP5_31_28) IP5_31_28 FM(IP6_31_28) IP6_31_28 FM(IP7_31_28) IP7_31_28 \ ++\ ++FM(IP8_3_0) IP8_3_0 \ ++FM(IP8_7_4) IP8_7_4 \ ++FM(IP8_11_8) IP8_11_8 \ ++FM(IP8_15_12) IP8_15_12 \ ++FM(IP8_19_16) IP8_19_16 \ ++FM(IP8_23_20) IP8_23_20 \ ++FM(IP8_27_24) IP8_27_24 \ ++FM(IP8_31_28) IP8_31_28 ++ ++/* ++ Set Value = H'0 Set Value = H'1 ++Register Function Pin Function Pin ++------------------------------------------------------------ ++sel_i2c3 SDA3_A VI0_DATA2 SDA3_B VI1_DATA10 ++ SCL3_A VI0_DATA3 SCL3_B VI1_DATA9 ++sel_hscif0 HSCIF0_A SCIF_CLK HSCIF0_B SCIF_CLK ++sel_scif1 SCIF1_A RX1 SCIF1_B TX1 ++ SCIF1_A TX1 SCIF1_B RX1 ++sel_canfd0 CANFD0_A CANFD0_TX CANFD0_B CANFD0_TX ++ CANFD0_A CANFD0_RX CANFD0_B CANFD0_RX ++ CANFD0_A CANFD_CLK CANFD0_B CANFD_CLK ++sel_pwm4 PWM4_A PWM4 PWM4_B PWM4 ++sel_pwm3 PWM3_A PWM3 PWM3_B PWM3 ++sel_pwm2 PWM2_A PWM2 PWM2_B PWM2 ++sel_pwm1 PWM1_A PWM1 PWM1_B PWM1 ++sel_pwm0 PWM0_A PWM0 PWM0_B PWM0 ++sel_rfso RFSO_A FSO_CFE_0_N RFSO_B FSO_CFE_0_N ++ RFSO_A FSO_CFE_1_N RFSO_B FSO_CFE_1_N ++ RFSO_A FSO_TOE_N RFSO_B FSO_TOE_N ++sel_rsp RSP_A SPEEDIN RSP_B SPEEDIN ++sel_tmu TMU_A TCLK1 TMU_B TCLK1 ++ TMU_A TCLK2 TMU_B TCLK2 ++*/ ++/* MOD_SEL0 */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 */ ++#define MOD_SEL0_11 FM(SEL_I2C3_0) FM(SEL_I2C3_1) ++#define MOD_SEL0_10 FM(SEL_HSCIF0_0) FM(SEL_HSCIF0_1) ++#define MOD_SEL0_9 FM(SEL_SCIF1_0) FM(SEL_SCIF1_1) ++#define MOD_SEL0_8 FM(SEL_CANFD0_0) FM(SEL_CANFD0_1) ++#define MOD_SEL0_7 FM(SEL_PWM4_0) FM(SEL_PWM4_1) ++#define MOD_SEL0_6 FM(SEL_PWM3_0) FM(SEL_PWM3_1) ++#define MOD_SEL0_5 FM(SEL_PWM2_0) FM(SEL_PWM2_1) ++#define MOD_SEL0_4 FM(SEL_PWM1_0) FM(SEL_PWM1_1) ++#define MOD_SEL0_3 FM(SEL_PWM0_0) FM(SEL_PWM0_1) ++#define MOD_SEL0_2 FM(SEL_RFSO_0) FM(SEL_RFSO_1) ++#define MOD_SEL0_1 FM(SEL_RSP_0) FM(SEL_RSP_1) ++#define MOD_SEL0_0 FM(SEL_TMU_0) FM(SEL_TMU_1) ++ ++#define PINMUX_MOD_SELS \ ++\ ++MOD_SEL0_11 \ ++MOD_SEL0_10 \ ++MOD_SEL0_9 \ ++MOD_SEL0_8 \ ++MOD_SEL0_7 \ ++MOD_SEL0_6 \ ++MOD_SEL0_5 \ ++MOD_SEL0_4 \ ++MOD_SEL0_3 \ ++MOD_SEL0_2 \ ++MOD_SEL0_1 \ ++MOD_SEL0_0 ++ ++enum { ++ PINMUX_RESERVED = 0, ++ ++ PINMUX_DATA_BEGIN, ++ GP_ALL(DATA), ++ PINMUX_DATA_END, ++ ++#define F_(x, y) ++#define FM(x) FN_##x, ++ PINMUX_FUNCTION_BEGIN, ++ GP_ALL(FN), ++ PINMUX_GPSR ++ PINMUX_IPSR ++ PINMUX_MOD_SELS ++ PINMUX_FUNCTION_END, ++#undef F_ ++#undef FM ++ ++#define F_(x, y) ++#define FM(x) x##_MARK, ++ PINMUX_MARK_BEGIN, ++ PINMUX_GPSR ++ PINMUX_IPSR ++ PINMUX_MOD_SELS ++ PINMUX_MARK_END, ++#undef F_ ++#undef FM ++}; ++ ++static const u16 pinmux_data[] = { ++ PINMUX_DATA_GP_ALL(), ++ ++ PINMUX_SINGLE(AVB0_RX_CTL), ++ PINMUX_SINGLE(AVB0_RXC), ++ PINMUX_SINGLE(AVB0_RD0), ++ PINMUX_SINGLE(AVB0_RD1), ++ PINMUX_SINGLE(AVB0_RD2), ++ PINMUX_SINGLE(AVB0_RD3), ++ PINMUX_SINGLE(AVB0_TX_CTL), ++ PINMUX_SINGLE(AVB0_TXC), ++ PINMUX_SINGLE(AVB0_TD0), ++ PINMUX_SINGLE(AVB0_TD1), ++ PINMUX_SINGLE(AVB0_TD2), ++ PINMUX_SINGLE(AVB0_TD3), ++ PINMUX_SINGLE(AVB0_TXCREFCLK), ++ PINMUX_SINGLE(AVB0_MDIO), ++ PINMUX_SINGLE(AVB0_MDC), ++ PINMUX_SINGLE(AVB0_MAGIC), ++ PINMUX_SINGLE(AVB0_PHY_INT), ++ PINMUX_SINGLE(AVB0_LINK), ++ PINMUX_SINGLE(AVB0_AVTP_MATCH), ++ ++ PINMUX_SINGLE(QSPI0_SPCLK), ++ PINMUX_SINGLE(QSPI0_MOSI_IO0), ++ PINMUX_SINGLE(QSPI0_MISO_IO1), ++ PINMUX_SINGLE(QSPI0_IO2), ++ PINMUX_SINGLE(QSPI0_IO3), ++ PINMUX_SINGLE(QSPI0_SSL), ++ PINMUX_SINGLE(QSPI1_SPCLK), ++ PINMUX_SINGLE(QSPI1_MOSI_IO0), ++ PINMUX_SINGLE(QSPI1_MISO_IO1), ++ PINMUX_SINGLE(QSPI1_IO2), ++ PINMUX_SINGLE(QSPI1_IO3), ++ PINMUX_SINGLE(QSPI1_SSL), ++ PINMUX_SINGLE(RPC_RESET_N), ++ PINMUX_SINGLE(RPC_WP_N), ++ PINMUX_SINGLE(RPC_INT_N), ++ ++ /* IPSR0 */ ++ PINMUX_IPSR_GPSR(IP0_3_0, DU_DR2), ++ PINMUX_IPSR_GPSR(IP0_3_0, HSCK0), ++ PINMUX_IPSR_GPSR(IP0_3_0, A0), ++ ++ PINMUX_IPSR_GPSR(IP0_7_4, DU_DR3), ++ PINMUX_IPSR_GPSR(IP0_7_4, HRTS0_N), ++ PINMUX_IPSR_GPSR(IP0_7_4, A1), ++ ++ PINMUX_IPSR_GPSR(IP0_11_8, DU_DR4), ++ PINMUX_IPSR_GPSR(IP0_11_8, HCTS0_N), ++ PINMUX_IPSR_GPSR(IP0_11_8, A2), ++ ++ PINMUX_IPSR_GPSR(IP0_15_12, DU_DR5), ++ PINMUX_IPSR_GPSR(IP0_15_12, HTX0), ++ PINMUX_IPSR_GPSR(IP0_15_12, A3), ++ ++ PINMUX_IPSR_GPSR(IP0_19_16, DU_DR6), ++ PINMUX_IPSR_GPSR(IP0_19_16, MSIOF3_RXD), ++ PINMUX_IPSR_GPSR(IP0_19_16, A4), ++ ++ PINMUX_IPSR_GPSR(IP0_23_20, DU_DR7), ++ PINMUX_IPSR_GPSR(IP0_23_20, MSIOF3_TXD), ++ PINMUX_IPSR_GPSR(IP0_23_20, A5), ++ ++ PINMUX_IPSR_GPSR(IP0_27_24, DU_DG2), ++ PINMUX_IPSR_GPSR(IP0_27_24, MSIOF3_SS1), ++ PINMUX_IPSR_GPSR(IP0_27_24, A6), ++ ++ PINMUX_IPSR_GPSR(IP0_31_28, DU_DG3), ++ PINMUX_IPSR_GPSR(IP0_31_28, MSIOF3_SS2), ++ PINMUX_IPSR_GPSR(IP0_31_28, A7), ++ PINMUX_IPSR_GPSR(IP0_31_28, PWMFSW0), ++ ++ /* IPSR1 */ ++ PINMUX_IPSR_GPSR(IP1_3_0, DU_DG4), ++ PINMUX_IPSR_GPSR(IP1_3_0, A8), ++ PINMUX_IPSR_MSEL(IP1_3_0, FSO_CFE_0_N_A, SEL_RFSO_0), ++ ++ PINMUX_IPSR_GPSR(IP1_7_4, DU_DG5), ++ PINMUX_IPSR_GPSR(IP1_7_4, A9), ++ PINMUX_IPSR_MSEL(IP1_7_4, FSO_CFE_1_N_A, SEL_RFSO_0), ++ ++ PINMUX_IPSR_GPSR(IP1_11_8, DU_DG6), ++ PINMUX_IPSR_GPSR(IP1_11_8, A10), ++ PINMUX_IPSR_MSEL(IP1_11_8, FSO_TOE_N_A, SEL_RFSO_0), ++ ++ PINMUX_IPSR_GPSR(IP1_15_12, DU_DG7), ++ PINMUX_IPSR_GPSR(IP1_15_12, A11), ++ PINMUX_IPSR_GPSR(IP1_15_12, IRQ1), ++ ++ PINMUX_IPSR_GPSR(IP1_19_16, DU_DB2), ++ PINMUX_IPSR_GPSR(IP1_19_16, A12), ++ PINMUX_IPSR_GPSR(IP1_19_16, IRQ2), ++ ++ PINMUX_IPSR_GPSR(IP1_23_20, DU_DB3), ++ PINMUX_IPSR_GPSR(IP1_23_20, A13), ++ PINMUX_IPSR_GPSR(IP1_23_20, FXR_CLKOUT1), ++ ++ PINMUX_IPSR_GPSR(IP1_27_24, DU_DB4), ++ PINMUX_IPSR_GPSR(IP1_27_24, A14), ++ PINMUX_IPSR_GPSR(IP1_27_24, FXR_CLKOUT2), ++ ++ PINMUX_IPSR_GPSR(IP1_31_28, DU_DB5), ++ PINMUX_IPSR_GPSR(IP1_31_28, A15), ++ PINMUX_IPSR_GPSR(IP1_31_28, FXR_TXENA_N), ++ ++ /* IPSR2 */ ++ PINMUX_IPSR_GPSR(IP2_3_0, DU_DB6), ++ PINMUX_IPSR_GPSR(IP2_3_0, A16), ++ PINMUX_IPSR_GPSR(IP2_3_0, FXR_TXENB_N), ++ ++ PINMUX_IPSR_GPSR(IP2_7_4, DU_DB7), ++ PINMUX_IPSR_GPSR(IP2_7_4, A17), ++ PINMUX_IPSR_GPSR(IP2_7_4, STPWT_EXTFXR), ++ ++ PINMUX_IPSR_GPSR(IP2_11_8, DU_DOTCLKOUT), ++ PINMUX_IPSR_MSEL(IP2_11_8, SCIF_CLK_A, SEL_HSCIF0_0), ++ PINMUX_IPSR_GPSR(IP2_11_8, A18), ++ ++ PINMUX_IPSR_GPSR(IP2_15_12, DU_EXHSYNC_DU_HSYNC), ++ PINMUX_IPSR_GPSR(IP2_15_12, HRX0), ++ PINMUX_IPSR_GPSR(IP2_15_12, A19), ++ PINMUX_IPSR_GPSR(IP2_15_12, IRQ3), ++ ++ PINMUX_IPSR_GPSR(IP2_19_16, DU_EXVSYNC_DU_VSYNC), ++ PINMUX_IPSR_GPSR(IP2_19_16, MSIOF3_SCK), ++ PINMUX_IPSR_GPSR(IP2_19_16, A20), ++ ++ PINMUX_IPSR_GPSR(IP2_23_20, DU_EXODDF_DU_ODDF_DISP_CDE), ++ PINMUX_IPSR_GPSR(IP2_23_20, MSIOF3_SYNC), ++ PINMUX_IPSR_GPSR(IP2_23_20, A21), ++ ++ PINMUX_IPSR_GPSR(IP2_27_24, IRQ0), ++ PINMUX_IPSR_GPSR(IP2_27_24, CC5_OSCOUT), ++ ++ PINMUX_IPSR_GPSR(IP2_31_28, VI0_CLK), ++ PINMUX_IPSR_GPSR(IP2_31_28, MSIOF2_SCK), ++ PINMUX_IPSR_GPSR(IP2_31_28, SCK3), ++ PINMUX_IPSR_GPSR(IP2_31_28, HSCK3), ++ ++ /* IPSR3 */ ++ PINMUX_IPSR_GPSR(IP3_3_0, VI0_CLKENB), ++ PINMUX_IPSR_GPSR(IP3_3_0, MSIOF2_RXD), ++ PINMUX_IPSR_GPSR(IP3_3_0, RX3), ++ PINMUX_IPSR_GPSR(IP3_3_0, RD_WR_N), ++ PINMUX_IPSR_GPSR(IP3_3_0, HCTS3_N), ++ ++ PINMUX_IPSR_GPSR(IP3_7_4, VI0_HSYNC_N), ++ PINMUX_IPSR_GPSR(IP3_7_4, MSIOF2_TXD), ++ PINMUX_IPSR_GPSR(IP3_7_4, TX3), ++ PINMUX_IPSR_GPSR(IP3_7_4, HRTS3_N), ++ ++ PINMUX_IPSR_GPSR(IP3_11_8, VI0_VSYNC_N), ++ PINMUX_IPSR_GPSR(IP3_11_8, MSIOF2_SYNC), ++ PINMUX_IPSR_GPSR(IP3_11_8, CTS3_N), ++ PINMUX_IPSR_GPSR(IP3_11_8, HTX3), ++ ++ PINMUX_IPSR_GPSR(IP3_15_12, VI0_DATA0), ++ PINMUX_IPSR_GPSR(IP3_15_12, MSIOF2_SS1), ++ PINMUX_IPSR_GPSR(IP3_15_12, RTS3_N_TANS), ++ PINMUX_IPSR_GPSR(IP3_15_12, HRX3), ++ ++ PINMUX_IPSR_GPSR(IP3_19_16, VI0_DATA1), ++ PINMUX_IPSR_GPSR(IP3_19_16, MSIOF2_SS2), ++ PINMUX_IPSR_GPSR(IP3_19_16, SCK1), ++ PINMUX_IPSR_MSEL(IP3_19_16, SPEEDIN_A, SEL_RSP_1), ++ ++ PINMUX_IPSR_GPSR(IP3_23_20, VI0_DATA2), ++ PINMUX_IPSR_GPSR(IP3_23_20, AVB0_AVTP_PPS), ++ PINMUX_IPSR_GPSR(IP3_23_20, SDA3_A), ++ ++ PINMUX_IPSR_GPSR(IP3_27_24, VI0_DATA3), ++ PINMUX_IPSR_GPSR(IP3_27_24, HSCK1), ++ PINMUX_IPSR_GPSR(IP3_27_24, SCL3_A), ++ ++ PINMUX_IPSR_GPSR(IP3_31_28, VI0_DATA4), ++ PINMUX_IPSR_GPSR(IP3_31_28, HRTS1_N), ++ PINMUX_IPSR_MSEL(IP3_31_28, RX1_A, SEL_SCIF1_0), ++ ++ /* IPSR4 */ ++ PINMUX_IPSR_GPSR(IP4_3_0, VI0_DATA5), ++ PINMUX_IPSR_GPSR(IP4_3_0, HCTS1_N), ++ PINMUX_IPSR_MSEL(IP4_3_0, TX1_A, SEL_SCIF1_0), ++ ++ PINMUX_IPSR_GPSR(IP4_7_4, VI0_DATA6), ++ PINMUX_IPSR_GPSR(IP4_7_4, HTX1), ++ PINMUX_IPSR_GPSR(IP4_7_4, CTS1_N), ++ ++ PINMUX_IPSR_GPSR(IP4_11_8, VI0_DATA7), ++ PINMUX_IPSR_GPSR(IP4_11_8, HRX1), ++ PINMUX_IPSR_GPSR(IP4_11_8, RTS1_N_TANS), ++ ++ PINMUX_IPSR_GPSR(IP4_15_12, VI0_DATA8), ++ PINMUX_IPSR_GPSR(IP4_15_12, HSCK2), ++ PINMUX_IPSR_MSEL(IP4_15_12, PWM0_A, SEL_PWM0_0), ++ PINMUX_IPSR_GPSR(IP4_15_12, A22), ++ ++ PINMUX_IPSR_GPSR(IP4_19_16, VI0_DATA9), ++ PINMUX_IPSR_GPSR(IP4_19_16, HCTS2_N), ++ PINMUX_IPSR_MSEL(IP4_19_16, PWM1_A, SEL_PWM1_0), ++ PINMUX_IPSR_GPSR(IP4_19_16, A23), ++ PINMUX_IPSR_MSEL(IP4_19_16, FSO_CFE_0_N_B, SEL_RFSO_1), ++ ++ PINMUX_IPSR_GPSR(IP4_23_20, VI0_DATA10), ++ PINMUX_IPSR_GPSR(IP4_23_20, HRTS2_N), ++ PINMUX_IPSR_MSEL(IP4_23_20, PWM2_A, SEL_PWM2_0), ++ PINMUX_IPSR_GPSR(IP4_23_20, A24), ++ PINMUX_IPSR_MSEL(IP4_23_20, FSO_CFE_1_N_B, SEL_RFSO_1), ++ ++ PINMUX_IPSR_GPSR(IP4_27_24, VI0_DATA11), ++ PINMUX_IPSR_GPSR(IP4_27_24, HTX2), ++ PINMUX_IPSR_MSEL(IP4_27_24, PWM3_A, SEL_PWM3_0), ++ PINMUX_IPSR_GPSR(IP4_27_24, A25), ++ PINMUX_IPSR_MSEL(IP4_27_24, FSO_TOE_N_B, SEL_RFSO_1), ++ ++ PINMUX_IPSR_GPSR(IP4_31_28, VI0_FIELD), ++ PINMUX_IPSR_GPSR(IP4_31_28, HRX2), ++ PINMUX_IPSR_MSEL(IP4_31_28, PWM4_A, SEL_PWM4_0), ++ PINMUX_IPSR_GPSR(IP4_31_28, CS1_N_A26), ++ PINMUX_IPSR_GPSR(IP4_31_28, FSCLKST2_N_A), ++ ++ /* IPSR5 */ ++ PINMUX_IPSR_GPSR(IP5_3_0, VI1_CLK), ++ PINMUX_IPSR_GPSR(IP5_3_0, MSIOF1_RXD), ++ PINMUX_IPSR_GPSR(IP5_3_0, CS0_N), ++ ++ PINMUX_IPSR_GPSR(IP5_7_4, VI1_CLKENB), ++ PINMUX_IPSR_GPSR(IP5_7_4, MSIOF1_TXD), ++ PINMUX_IPSR_GPSR(IP5_7_4, D0), ++ ++ PINMUX_IPSR_GPSR(IP5_11_8, VI1_HSYNC_N), ++ PINMUX_IPSR_GPSR(IP5_11_8, MSIOF1_SCK), ++ PINMUX_IPSR_GPSR(IP5_11_8, D1), ++ ++ PINMUX_IPSR_GPSR(IP5_15_12, VI1_VSYNC_N), ++ PINMUX_IPSR_GPSR(IP5_15_12, MSIOF1_SYNC), ++ PINMUX_IPSR_GPSR(IP5_15_12, D2), ++ ++ PINMUX_IPSR_GPSR(IP5_19_16, VI1_DATA0), ++ PINMUX_IPSR_GPSR(IP5_19_16, MSIOF1_SS1), ++ PINMUX_IPSR_GPSR(IP5_19_16, D3), ++ ++ PINMUX_IPSR_GPSR(IP5_23_20, VI1_DATA1), ++ PINMUX_IPSR_GPSR(IP5_23_20, MSIOF1_SS2), ++ PINMUX_IPSR_GPSR(IP5_23_20, D4), ++ PINMUX_IPSR_GPSR(IP5_23_20, MMC_CMD), ++ ++ PINMUX_IPSR_GPSR(IP5_27_24, VI1_DATA2), ++ PINMUX_IPSR_MSEL(IP5_27_24, CANFD0_TX_B, SEL_CANFD0_1), ++ PINMUX_IPSR_GPSR(IP5_27_24, D5), ++ PINMUX_IPSR_GPSR(IP5_27_24, MMC_D0), ++ ++ PINMUX_IPSR_GPSR(IP5_31_28, VI1_DATA3), ++ PINMUX_IPSR_MSEL(IP5_31_28, CANFD0_RX_B, SEL_CANFD0_1), ++ PINMUX_IPSR_GPSR(IP5_31_28, D6), ++ PINMUX_IPSR_GPSR(IP5_31_28, MMC_D1), ++ ++ /* IPSR6 */ ++ PINMUX_IPSR_GPSR(IP6_3_0, VI1_DATA4), ++ PINMUX_IPSR_MSEL(IP6_3_0, CANFD_CLK_B, SEL_CANFD0_1), ++ PINMUX_IPSR_GPSR(IP6_3_0, D7), ++ PINMUX_IPSR_GPSR(IP6_3_0, MMC_D2), ++ ++ PINMUX_IPSR_GPSR(IP6_7_4, VI1_DATA5), ++ PINMUX_IPSR_GPSR(IP6_7_4, SCK4), ++ PINMUX_IPSR_GPSR(IP6_7_4, D8), ++ PINMUX_IPSR_GPSR(IP6_7_4, MMC_D3), ++ ++ PINMUX_IPSR_GPSR(IP6_11_8, VI1_DATA6), ++ PINMUX_IPSR_GPSR(IP6_11_8, RX4), ++ PINMUX_IPSR_GPSR(IP6_11_8, D9), ++ PINMUX_IPSR_GPSR(IP6_11_8, MMC_CLK), ++ ++ PINMUX_IPSR_GPSR(IP6_15_12, VI1_DATA7), ++ PINMUX_IPSR_GPSR(IP6_15_12, TX4), ++ PINMUX_IPSR_GPSR(IP6_15_12, D10), ++ PINMUX_IPSR_GPSR(IP6_15_12, MMC_D4), ++ ++ PINMUX_IPSR_GPSR(IP6_19_16, VI1_DATA8), ++ PINMUX_IPSR_GPSR(IP6_19_16, CTS4_N), ++ PINMUX_IPSR_GPSR(IP6_19_16, D11), ++ PINMUX_IPSR_GPSR(IP6_19_16, MMC_D5), ++ ++ PINMUX_IPSR_GPSR(IP6_23_20, VI1_DATA9), ++ PINMUX_IPSR_GPSR(IP6_23_20, RTS4_N_TANS), ++ PINMUX_IPSR_GPSR(IP6_23_20, D12), ++ PINMUX_IPSR_GPSR(IP6_23_20, MMC_D6), ++ PINMUX_IPSR_GPSR(IP6_23_20, SCL3_B), ++ ++ PINMUX_IPSR_GPSR(IP6_27_24, VI1_DATA10), ++ PINMUX_IPSR_GPSR(IP6_27_24, D13), ++ PINMUX_IPSR_GPSR(IP6_27_24, MMC_D7), ++ PINMUX_IPSR_GPSR(IP6_27_24, SDA3_B), ++ ++ PINMUX_IPSR_GPSR(IP6_31_28, VI1_DATA11), ++ PINMUX_IPSR_GPSR(IP6_31_28, SCL4), ++ PINMUX_IPSR_GPSR(IP6_31_28, IRQ4), ++ PINMUX_IPSR_GPSR(IP6_31_28, D14), ++ PINMUX_IPSR_GPSR(IP6_31_28, MMC_WP), ++ ++ /* IPSR7 */ ++ PINMUX_IPSR_GPSR(IP7_3_0, VI1_FIELD), ++ PINMUX_IPSR_GPSR(IP7_3_0, SDA4), ++ PINMUX_IPSR_GPSR(IP7_3_0, IRQ5), ++ PINMUX_IPSR_GPSR(IP7_3_0, D15), ++ PINMUX_IPSR_GPSR(IP7_3_0, MMC_CD), ++ ++ PINMUX_IPSR_GPSR(IP7_7_4, SCL0), ++ PINMUX_IPSR_GPSR(IP7_7_4, DU_DR0), ++ PINMUX_IPSR_GPSR(IP7_7_4, TPU0TO0), ++ PINMUX_IPSR_GPSR(IP7_7_4, CLKOUT), ++ PINMUX_IPSR_GPSR(IP7_7_4, MSIOF0_RXD), ++ ++ PINMUX_IPSR_GPSR(IP7_11_8, SDA0), ++ PINMUX_IPSR_GPSR(IP7_11_8, DU_DR1), ++ PINMUX_IPSR_GPSR(IP7_11_8, TPU0TO1), ++ PINMUX_IPSR_GPSR(IP7_11_8, BS_N), ++ PINMUX_IPSR_GPSR(IP7_11_8, SCK0), ++ PINMUX_IPSR_GPSR(IP7_11_8, MSIOF0_TXD), ++ ++ PINMUX_IPSR_GPSR(IP7_15_12, SCL1), ++ PINMUX_IPSR_GPSR(IP7_15_12, DU_DG0), ++ PINMUX_IPSR_GPSR(IP7_15_12, TPU0TO2), ++ PINMUX_IPSR_GPSR(IP7_15_12, RD_N), ++ PINMUX_IPSR_GPSR(IP7_15_12, CTS0_N), ++ PINMUX_IPSR_GPSR(IP7_15_12, MSIOF0_SCK), ++ ++ PINMUX_IPSR_GPSR(IP7_19_16, SDA1), ++ PINMUX_IPSR_GPSR(IP7_19_16, DU_DG1), ++ PINMUX_IPSR_GPSR(IP7_19_16, TPU0TO3), ++ PINMUX_IPSR_GPSR(IP7_19_16, WE0_N), ++ PINMUX_IPSR_GPSR(IP7_19_16, RTS0_N_TANS), ++ PINMUX_IPSR_GPSR(IP7_19_16, MSIOF0_SYNC), ++ ++ PINMUX_IPSR_GPSR(IP7_23_20, SCL2), ++ PINMUX_IPSR_GPSR(IP7_23_20, DU_DB0), ++ PINMUX_IPSR_MSEL(IP7_23_20, TCLK1_A, SEL_TMU_0), ++ PINMUX_IPSR_GPSR(IP7_23_20, WE1_N), ++ PINMUX_IPSR_GPSR(IP7_23_20, RX0), ++ PINMUX_IPSR_GPSR(IP7_23_20, MSIOF0_SS1), ++ ++ PINMUX_IPSR_GPSR(IP7_27_24, SDA2), ++ PINMUX_IPSR_GPSR(IP7_27_24, DU_DB1), ++ PINMUX_IPSR_MSEL(IP7_27_24, TCLK2_A, SEL_TMU_0), ++ PINMUX_IPSR_GPSR(IP7_27_24, EX_WAIT0), ++ PINMUX_IPSR_GPSR(IP7_27_24, TX0), ++ PINMUX_IPSR_GPSR(IP7_27_24, MSIOF0_SS2), ++ ++ PINMUX_IPSR_GPSR(IP7_31_28, AVB0_AVTP_CAPTURE), ++ PINMUX_IPSR_GPSR(IP7_31_28, FSCLKST2_N_B), ++ ++ /* IPSR8 */ ++ PINMUX_IPSR_MSEL(IP8_3_0, CANFD0_TX_A, SEL_CANFD0_0), ++ PINMUX_IPSR_GPSR(IP8_3_0, FXR_TXDA), ++ PINMUX_IPSR_MSEL(IP8_3_0, PWM0_B, SEL_PWM0_1), ++ PINMUX_IPSR_GPSR(IP8_3_0, DU_DISP), ++ PINMUX_IPSR_GPSR(IP8_3_0, FSCLKST2_N_C), ++ ++ PINMUX_IPSR_MSEL(IP8_7_4, CANFD0_RX_A, SEL_CANFD0_0), ++ PINMUX_IPSR_GPSR(IP8_7_4, RXDA_EXTFXR), ++ PINMUX_IPSR_MSEL(IP8_7_4, PWM1_B, SEL_PWM1_1), ++ PINMUX_IPSR_GPSR(IP8_7_4, DU_CDE), ++ ++ PINMUX_IPSR_GPSR(IP8_11_8, CANFD1_TX), ++ PINMUX_IPSR_GPSR(IP8_11_8, FXR_TXDB), ++ PINMUX_IPSR_MSEL(IP8_11_8, PWM2_B, SEL_PWM2_1), ++ PINMUX_IPSR_MSEL(IP8_11_8, TCLK1_B, SEL_TMU_1), ++ PINMUX_IPSR_MSEL(IP8_11_8, TX1_B, SEL_SCIF1_1), ++ ++ PINMUX_IPSR_GPSR(IP8_15_12, CANFD1_RX), ++ PINMUX_IPSR_GPSR(IP8_15_12, RXDB_EXTFXR), ++ PINMUX_IPSR_MSEL(IP8_15_12, PWM3_B, SEL_PWM3_1), ++ PINMUX_IPSR_MSEL(IP8_15_12, TCLK2_B, SEL_TMU_1), ++ PINMUX_IPSR_MSEL(IP8_15_12, RX1_B, SEL_SCIF1_1), ++ ++ PINMUX_IPSR_MSEL(IP8_19_16, CANFD_CLK_A, SEL_CANFD0_0), ++ PINMUX_IPSR_GPSR(IP8_19_16, CLK_EXTFXR), ++ PINMUX_IPSR_MSEL(IP8_19_16, PWM4_B, SEL_PWM4_1), ++ PINMUX_IPSR_MSEL(IP8_19_16, SPEEDIN_B, SEL_RSP_0), ++ PINMUX_IPSR_MSEL(IP8_19_16, SCIF_CLK_B, SEL_HSCIF0_1), ++ ++ PINMUX_IPSR_GPSR(IP8_23_20, DIGRF_CLKIN), ++ PINMUX_IPSR_GPSR(IP8_23_20, DIGRF_CLKEN_IN), ++ ++ PINMUX_IPSR_GPSR(IP8_27_24, DIGRF_CLKOUT), ++ PINMUX_IPSR_GPSR(IP8_27_24, DIGRF_CLKEN_OUT), ++}; ++ ++static const struct sh_pfc_pin pinmux_pins[] = { ++ PINMUX_GPIO_GP_ALL(), ++}; ++ ++/* - EtherAVB --------------------------------------------------------------- */ ++static const unsigned int avb0_rx_ctrl_pins[] = { ++ /* AVB0_RX_CTL */ ++ RCAR_GP_PIN(1, 1), ++}; ++static const unsigned int avb0_rx_ctrl_mux[] = { ++ AVB0_RX_CTL_MARK, ++}; ++static const unsigned int avb0_rxc_pins[] = { ++ /* AVB0_RXC */ ++ RCAR_GP_PIN(1, 2), ++}; ++static const unsigned int avb0_rxc_mux[] = { ++ AVB0_RXC_MARK, ++}; ++static const unsigned int avb0_rd0_pins[] = { ++ /* AVB0_RD[0] */ ++ RCAR_GP_PIN(1, 3), ++}; ++static const unsigned int avb0_rd0_mux[] = { ++ AVB0_RD0_MARK, ++}; ++static const unsigned int avb0_rd1_pins[] = { ++ /* AVB0_RD[1] */ ++ RCAR_GP_PIN(1, 4), ++}; ++static const unsigned int avb0_rd1_mux[] = { ++ AVB0_RD1_MARK, ++}; ++static const unsigned int avb0_rd2_pins[] = { ++ /* AVB0_RD[2] */ ++ RCAR_GP_PIN(1, 5), ++}; ++static const unsigned int avb0_rd2_mux[] = { ++ AVB0_RD2_MARK, ++}; ++static const unsigned int avb0_rd3_pins[] = { ++ /* AVB0_RD[3] */ ++ RCAR_GP_PIN(1, 6), ++}; ++static const unsigned int avb0_rd3_mux[] = { ++ AVB0_RD3_MARK, ++}; ++static const unsigned int avb0_rd4_pins[] = { ++ /* AVB0_RD[3:0] */ ++ RCAR_GP_PIN(1, 3), RCAR_GP_PIN(1, 4), ++ RCAR_GP_PIN(1, 5), RCAR_GP_PIN(1, 6), ++}; ++static const unsigned int avb0_rd4_mux[] = { ++ AVB0_RD0_MARK, AVB0_RD1_MARK, ++ AVB0_RD2_MARK, AVB0_RD3_MARK, ++}; ++static const unsigned int avb0_tx_ctrl_pins[] = { ++ /* AVB0_TX_CTL */ ++ RCAR_GP_PIN(1, 7), ++}; ++static const unsigned int avb0_tx_ctrl_mux[] = { ++ AVB0_TX_CTL_MARK, ++}; ++static const unsigned int avb0_txc_pins[] = { ++ /* AVB0_TXC */ ++ RCAR_GP_PIN(1, 8), ++}; ++static const unsigned int avb0_txc_mux[] = { ++ AVB0_TXC_MARK, ++}; ++static const unsigned int avb0_td0_pins[] = { ++ /* AVB0_TD[0] */ ++ RCAR_GP_PIN(1, 9), ++}; ++static const unsigned int avb0_td0_mux[] = { ++ AVB0_TD0_MARK, ++}; ++static const unsigned int avb0_td1_pins[] = { ++ /* AVB0_TD[1] */ ++ RCAR_GP_PIN(1, 10), ++}; ++static const unsigned int avb0_td1_mux[] = { ++ AVB0_TD1_MARK, ++}; ++static const unsigned int avb0_td2_pins[] = { ++ /* AVB0_TD[2] */ ++ RCAR_GP_PIN(1, 11), ++}; ++static const unsigned int avb0_td2_mux[] = { ++ AVB0_TD2_MARK, ++}; ++static const unsigned int avb0_td3_pins[] = { ++ /* AVB0_TD[3] */ ++ RCAR_GP_PIN(1, 12), ++}; ++static const unsigned int avb0_td3_mux[] = { ++ AVB0_TD3_MARK, ++}; ++static const unsigned int avb0_td4_pins[] = { ++ /* AVB0_TD[3:0] */ ++ RCAR_GP_PIN(1, 9), RCAR_GP_PIN(1, 10), ++ RCAR_GP_PIN(1, 11), RCAR_GP_PIN(1, 12), ++}; ++static const unsigned int avb0_td4_mux[] = { ++ AVB0_TD0_MARK, AVB0_TD1_MARK, ++ AVB0_TD2_MARK, AVB0_TD3_MARK, ++}; ++static const unsigned int avb0_txcrefclk_pins[] = { ++ /* AVB0_TXCREFCLK */ ++ RCAR_GP_PIN(1, 13), ++}; ++static const unsigned int avb0_txcrefclk_mux[] = { ++ AVB0_TXCREFCLK_MARK, ++}; ++static const unsigned int avb0_mdio_pins[] = { ++ /* AVB0_MDIO */ ++ RCAR_GP_PIN(1, 14), ++}; ++static const unsigned int avb0_mdio_mux[] = { ++ AVB0_MDIO_MARK, ++}; ++static const unsigned int avb0_mdc_pins[] = { ++ /* AVB0_MDC */ ++ RCAR_GP_PIN(1, 15), ++}; ++static const unsigned int avb0_mdc_mux[] = { ++ AVB0_MDC_MARK, ++}; ++static const unsigned int avb0_magic_pins[] = { ++ /* AVB0_MAGIC */ ++ RCAR_GP_PIN(1, 16), ++}; ++static const unsigned int avb0_magic_mux[] = { ++ AVB0_MAGIC_MARK, ++}; ++static const unsigned int avb0_phy_int_pins[] = { ++ /* AVB0_PHY_INT */ ++ RCAR_GP_PIN(1, 17), ++}; ++static const unsigned int avb0_phy_int_mux[] = { ++ AVB0_PHY_INT_MARK, ++}; ++static const unsigned int avb0_link_pins[] = { ++ /* AVB0_LINK */ ++ RCAR_GP_PIN(1, 18), ++}; ++static const unsigned int avb0_link_mux[] = { ++ AVB0_LINK_MARK, ++}; ++static const unsigned int avb0_avtp_match_pins[] = { ++ /* AVB0_AVTP_MATCH */ ++ RCAR_GP_PIN(1, 19), ++}; ++static const unsigned int avb0_avtp_match_mux[] = { ++ AVB0_AVTP_MATCH_MARK, ++}; ++static const unsigned int avb0_avtp_pps_pins[] = { ++ /* AVB0_AVTP_PPS */ ++ RCAR_GP_PIN(2, 6), ++}; ++static const unsigned int avb0_avtp_pps_mux[] = { ++ AVB0_AVTP_PPS_MARK, ++}; ++static const unsigned int avb0_avtp_capture_pins[] = { ++ /* AVB0_AVTP_CAPTURE */ ++ RCAR_GP_PIN(1, 20), ++}; ++static const unsigned int avb0_avtp_capture_mux[] = { ++ AVB0_AVTP_CAPTURE_MARK, ++}; ++ ++/* - CANFD0 ----------------------------------------------------------------- */ ++static const unsigned int canfd0_data_a_pins[] = { ++ /* TX, RX */ ++ RCAR_GP_PIN(1, 21), RCAR_GP_PIN(1, 22), ++}; ++static const unsigned int canfd0_data_a_mux[] = { ++ CANFD0_TX_A_MARK, CANFD0_RX_A_MARK, ++}; ++static const unsigned int canfd_clk_a_pins[] = { ++ /* CLK */ ++ RCAR_GP_PIN(1, 25), ++}; ++static const unsigned int canfd_clk_a_mux[] = { ++ CANFD_CLK_A_MARK, ++}; ++static const unsigned int canfd0_data_b_pins[] = { ++ /* TX, RX */ ++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), ++}; ++static const unsigned int canfd0_data_b_mux[] = { ++ CANFD0_TX_B_MARK, CANFD0_RX_B_MARK, ++}; ++static const unsigned int canfd_clk_b_pins[] = { ++ /* CLK */ ++ RCAR_GP_PIN(3, 8), ++}; ++static const unsigned int canfd_clk_b_mux[] = { ++ CANFD_CLK_B_MARK, ++}; ++ ++/* - CANFD1 ----------------------------------------------------------------- */ ++static const unsigned int canfd1_data_pins[] = { ++ /* TX, RX */ ++ RCAR_GP_PIN(1, 23), RCAR_GP_PIN(1, 24), ++}; ++static const unsigned int canfd1_data_mux[] = { ++ CANFD1_TX_MARK, CANFD1_RX_MARK, ++}; ++ ++/* - DU --------------------------------------------------------------------- */ ++static const unsigned int du_rgb666_pins[] = { ++ /* R[7:0] */ ++ RCAR_GP_PIN(0, 5), RCAR_GP_PIN(0, 4), ++ RCAR_GP_PIN(0, 3), RCAR_GP_PIN(0, 2), ++ RCAR_GP_PIN(0, 1), RCAR_GP_PIN(0, 0), ++ /* G[7:0] */ ++ RCAR_GP_PIN(0, 11), RCAR_GP_PIN(0, 10), ++ RCAR_GP_PIN(0, 9), RCAR_GP_PIN(0, 8), ++ RCAR_GP_PIN(0, 7), RCAR_GP_PIN(0, 6), ++ /* B[7:0] */ ++ RCAR_GP_PIN(0, 17), RCAR_GP_PIN(0, 16), ++ RCAR_GP_PIN(0, 15), RCAR_GP_PIN(0, 14), ++ RCAR_GP_PIN(0, 13), RCAR_GP_PIN(0, 12), ++}; ++static const unsigned int du_rgb666_mux[] = { ++ DU_DR7_MARK, DU_DR6_MARK, ++ DU_DR5_MARK, DU_DR4_MARK, ++ DU_DR3_MARK, DU_DR2_MARK, ++ DU_DG7_MARK, DU_DG6_MARK, ++ DU_DG5_MARK, DU_DG4_MARK, ++ DU_DG3_MARK, DU_DG2_MARK, ++ DU_DB7_MARK, DU_DB6_MARK, ++ DU_DB5_MARK, DU_DB4_MARK, ++ DU_DB3_MARK, DU_DB2_MARK, ++}; ++static const unsigned int du_clk_out_0_pins[] = { ++ /* CLKOUT0 */ ++ RCAR_GP_PIN(0, 18), ++}; ++static const unsigned int du_clk_out_0_mux[] = { ++ DU_DOTCLKOUT_MARK, ++}; ++static const unsigned int du_clk_out_1_pins[] = { ++ /* CLKOUT1 */ ++ RCAR_GP_PIN(0, 18), /* @@ */ ++}; ++static const unsigned int du_clk_out_1_mux[] = { ++ DU_DOTCLKOUT_MARK, ++}; ++static const unsigned int du_sync_pins[] = { ++ /* EXVSYNC/VSYNC, EXHSYNC/HSYNC */ ++ RCAR_GP_PIN(0, 20), RCAR_GP_PIN(0, 19), ++}; ++static const unsigned int du_sync_mux[] = { ++ DU_EXVSYNC_DU_VSYNC_MARK, DU_EXHSYNC_DU_HSYNC_MARK, ++}; ++static const unsigned int du_oddf_pins[] = { ++ /* EXDISP/EXODDF/EXCDE */ ++ RCAR_GP_PIN(0, 21), ++}; ++static const unsigned int du_oddf_mux[] = { ++ DU_EXODDF_DU_ODDF_DISP_CDE_MARK, ++}; ++static const unsigned int du_cde_pins[] = { ++ /* CDE */ ++ RCAR_GP_PIN(1, 22), ++}; ++static const unsigned int du_cde_mux[] = { ++ DU_CDE_MARK, ++}; ++static const unsigned int du_disp_pins[] = { ++ /* DISP */ ++ RCAR_GP_PIN(1, 21), ++}; ++static const unsigned int du_disp_mux[] = { ++ DU_DISP_MARK, ++}; ++ ++/* - HSCIF0 ----------------------------------------------------------------- */ ++static const unsigned int hscif0_data_pins[] = { ++ /* HRX0, HTX0 */ ++ RCAR_GP_PIN(0, 19), RCAR_GP_PIN(0, 3), ++}; ++static const unsigned int hscif0_data_mux[] = { ++ HRX0_MARK, HTX0_MARK, ++}; ++static const unsigned int hscif0_clk_pins[] = { ++ /* HSCK0 */ ++ RCAR_GP_PIN(0, 0), ++}; ++static const unsigned int hscif0_clk_mux[] = { ++ HSCK0_MARK, ++}; ++static const unsigned int hscif0_ctrl_pins[] = { ++ /* HRTS0#, HCTS0# */ ++ RCAR_GP_PIN(0, 1), RCAR_GP_PIN(0, 2), ++}; ++static const unsigned int hscif0_ctrl_mux[] = { ++ HRTS0_N_MARK, HCTS0_N_MARK, ++}; ++ ++/* - HSCIF1 ----------------------------------------------------------------- */ ++static const unsigned int hscif1_data_pins[] = { ++ /* HRX1, HTX1 */ ++ RCAR_GP_PIN(2, 11), RCAR_GP_PIN(2, 10), ++}; ++static const unsigned int hscif1_data_mux[] = { ++ HRX1_MARK, HTX1_MARK, ++}; ++static const unsigned int hscif1_clk_pins[] = { ++ /* HSCK1 */ ++ RCAR_GP_PIN(2, 7), ++}; ++static const unsigned int hscif1_clk_mux[] = { ++ HSCK1_MARK, ++}; ++static const unsigned int hscif1_ctrl_pins[] = { ++ /* HRTS1#, HCTS1# */ ++ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9), ++}; ++static const unsigned int hscif1_ctrl_mux[] = { ++ HRTS1_N_MARK, HCTS1_N_MARK, ++}; ++ ++/* - HSCIF2 ----------------------------------------------------------------- */ ++static const unsigned int hscif2_data_pins[] = { ++ /* HRX2, HTX2 */ ++ RCAR_GP_PIN(2, 16), RCAR_GP_PIN(2, 15), ++}; ++static const unsigned int hscif2_data_mux[] = { ++ HRX2_MARK, HTX2_MARK, ++}; ++static const unsigned int hscif2_clk_pins[] = { ++ /* HSCK2 */ ++ RCAR_GP_PIN(2, 12), ++}; ++static const unsigned int hscif2_clk_mux[] = { ++ HSCK2_MARK, ++}; ++static const unsigned int hscif2_ctrl_pins[] = { ++ /* HRTS2#, HCTS2# */ ++ RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 13), ++}; ++static const unsigned int hscif2_ctrl_mux[] = { ++ HRTS2_N_MARK, HCTS2_N_MARK, ++}; ++ ++/* - HSCIF3 ----------------------------------------------------------------- */ ++static const unsigned int hscif3_data_pins[] = { ++ /* HRX3, HTX3 */ ++ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 3), ++}; ++static const unsigned int hscif3_data_mux[] = { ++ HRX3_MARK, HTX3_MARK, ++}; ++static const unsigned int hscif3_clk_pins[] = { ++ /* HSCK3 */ ++ RCAR_GP_PIN(2, 0), ++}; ++static const unsigned int hscif3_clk_mux[] = { ++ HSCK3_MARK, ++}; ++static const unsigned int hscif3_ctrl_pins[] = { ++ /* HRTS3#, HCTS3# */ ++ RCAR_GP_PIN(2, 2), RCAR_GP_PIN(2, 1), ++}; ++static const unsigned int hscif3_ctrl_mux[] = { ++ HRTS3_N_MARK, HCTS3_N_MARK, ++}; ++ ++/* - SCIF Clock ------------------------------------------------------------- */ ++static const unsigned int scif_clk_a_pins[] = { ++ /* SCIF_CLK */ ++ RCAR_GP_PIN(0, 18), ++}; ++static const unsigned int scif_clk_a_mux[] = { ++ SCIF_CLK_A_MARK, ++}; ++static const unsigned int scif_clk_b_pins[] = { ++ /* SCIF_CLK */ ++ RCAR_GP_PIN(1, 25), ++}; ++static const unsigned int scif_clk_b_mux[] = { ++ SCIF_CLK_B_MARK, ++}; ++ ++/* - I2C -------------------------------------------------------------------- */ ++static const unsigned int i2c0_pins[] = { ++ /* SDA0, SCL0 */ ++ RCAR_GP_PIN(4, 1), RCAR_GP_PIN(4, 0), ++}; ++static const unsigned int i2c0_mux[] = { ++ SDA0_MARK, SCL0_MARK, ++}; ++static const unsigned int i2c1_pins[] = { ++ /* SDA1, SCL1 */ ++ RCAR_GP_PIN(4, 3), RCAR_GP_PIN(4, 2), ++}; ++static const unsigned int i2c1_mux[] = { ++ SDA1_MARK, SCL1_MARK, ++}; ++static const unsigned int i2c2_pins[] = { ++ /* SDA2, SCL2 */ ++ RCAR_GP_PIN(4, 5), RCAR_GP_PIN(4, 4), ++}; ++static const unsigned int i2c2_mux[] = { ++ SDA2_MARK, SCL2_MARK, ++}; ++static const unsigned int i2c3_pins[] = { ++ /* SDA3_A, SCL3_A */ ++ RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 5), ++}; ++static const unsigned int i2c3_mux[] = { ++ SDA3_A_MARK, SCL3_A_MARK, ++}; ++static const unsigned int i2c4_pins[] = { ++ /* SDA4, SCL4 */ ++ RCAR_GP_PIN(3, 16), RCAR_GP_PIN(3, 15), ++}; ++static const unsigned int i2c4_mux[] = { ++ SDA4_MARK, SCL4_MARK, ++}; ++ ++/* - INTC-EX ---------------------------------------------------------------- */ ++static const unsigned int intc_ex_irq0_pins[] = { ++ /* IRQ0 */ ++ RCAR_GP_PIN(1, 0), ++}; ++static const unsigned int intc_ex_irq0_mux[] = { ++ IRQ0_MARK, ++}; ++static const unsigned int intc_ex_irq1_pins[] = { ++ /* IRQ1 */ ++ RCAR_GP_PIN(0, 11), ++}; ++static const unsigned int intc_ex_irq1_mux[] = { ++ IRQ1_MARK, ++}; ++static const unsigned int intc_ex_irq2_pins[] = { ++ /* IRQ2 */ ++ RCAR_GP_PIN(0, 12), ++}; ++static const unsigned int intc_ex_irq2_mux[] = { ++ IRQ2_MARK, ++}; ++static const unsigned int intc_ex_irq3_pins[] = { ++ /* IRQ3 */ ++ RCAR_GP_PIN(0, 19), ++}; ++static const unsigned int intc_ex_irq3_mux[] = { ++ IRQ3_MARK, ++}; ++static const unsigned int intc_ex_irq4_pins[] = { ++ /* IRQ4 */ ++ RCAR_GP_PIN(3, 15), ++}; ++static const unsigned int intc_ex_irq4_mux[] = { ++ IRQ4_MARK, ++}; ++static const unsigned int intc_ex_irq5_pins[] = { ++ /* IRQ5 */ ++ RCAR_GP_PIN(3, 16), ++}; ++static const unsigned int intc_ex_irq5_mux[] = { ++ IRQ5_MARK, ++}; ++ ++/* - MSIOF0 ----------------------------------------------------------------- */ ++static const unsigned int msiof0_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(4, 2), ++}; ++static const unsigned int msiof0_clk_mux[] = { ++ MSIOF0_SCK_MARK, ++}; ++static const unsigned int msiof0_sync_pins[] = { ++ /* SYNC */ ++ RCAR_GP_PIN(4, 3), ++}; ++static const unsigned int msiof0_sync_mux[] = { ++ MSIOF0_SYNC_MARK, ++}; ++static const unsigned int msiof0_ss1_pins[] = { ++ /* SS1 */ ++ RCAR_GP_PIN(4, 4), ++}; ++static const unsigned int msiof0_ss1_mux[] = { ++ MSIOF0_SS1_MARK, ++}; ++static const unsigned int msiof0_ss2_pins[] = { ++ /* SS2 */ ++ RCAR_GP_PIN(4, 5), ++}; ++static const unsigned int msiof0_ss2_mux[] = { ++ MSIOF0_SS2_MARK, ++}; ++static const unsigned int msiof0_txd_pins[] = { ++ /* TXD */ ++ RCAR_GP_PIN(4, 1), ++}; ++static const unsigned int msiof0_txd_mux[] = { ++ MSIOF0_TXD_MARK, ++}; ++static const unsigned int msiof0_rxd_pins[] = { ++ /* RXD */ ++ RCAR_GP_PIN(4, 0), ++}; ++static const unsigned int msiof0_rxd_mux[] = { ++ MSIOF0_RXD_MARK, ++}; ++ ++/* - MSIOF1 ----------------------------------------------------------------- */ ++static const unsigned int msiof1_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(3, 2), ++}; ++static const unsigned int msiof1_clk_mux[] = { ++ MSIOF1_SCK_MARK, ++}; ++static const unsigned int msiof1_sync_pins[] = { ++ /* SYNC */ ++ RCAR_GP_PIN(3, 3), ++}; ++static const unsigned int msiof1_sync_mux[] = { ++ MSIOF1_SYNC_MARK, ++}; ++static const unsigned int msiof1_ss1_pins[] = { ++ /* SS1 */ ++ RCAR_GP_PIN(3, 4), ++}; ++static const unsigned int msiof1_ss1_mux[] = { ++ MSIOF1_SS1_MARK, ++}; ++static const unsigned int msiof1_ss2_pins[] = { ++ /* SS2 */ ++ RCAR_GP_PIN(3, 5), ++}; ++static const unsigned int msiof1_ss2_mux[] = { ++ MSIOF1_SS2_MARK, ++}; ++static const unsigned int msiof1_txd_pins[] = { ++ /* TXD */ ++ RCAR_GP_PIN(3, 1), ++}; ++static const unsigned int msiof1_txd_mux[] = { ++ MSIOF1_TXD_MARK, ++}; ++static const unsigned int msiof1_rxd_pins[] = { ++ /* RXD */ ++ RCAR_GP_PIN(3, 0), ++}; ++static const unsigned int msiof1_rxd_mux[] = { ++ MSIOF1_RXD_MARK, ++}; ++ ++/* - MSIOF2 ----------------------------------------------------------------- */ ++static const unsigned int msiof2_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(2, 0), ++}; ++static const unsigned int msiof2_clk_mux[] = { ++ MSIOF2_SCK_MARK, ++}; ++static const unsigned int msiof2_sync_pins[] = { ++ /* SYNC */ ++ RCAR_GP_PIN(2, 3), ++}; ++static const unsigned int msiof2_sync_mux[] = { ++ MSIOF2_SYNC_MARK, ++}; ++static const unsigned int msiof2_ss1_pins[] = { ++ /* SS1 */ ++ RCAR_GP_PIN(2, 4), ++}; ++static const unsigned int msiof2_ss1_mux[] = { ++ MSIOF2_SS1_MARK, ++}; ++static const unsigned int msiof2_ss2_pins[] = { ++ /* SS2 */ ++ RCAR_GP_PIN(2, 5), ++}; ++static const unsigned int msiof2_ss2_mux[] = { ++ MSIOF2_SS2_MARK, ++}; ++static const unsigned int msiof2_txd_pins[] = { ++ /* TXD */ ++ RCAR_GP_PIN(2, 2), ++}; ++static const unsigned int msiof2_txd_mux[] = { ++ MSIOF2_TXD_MARK, ++}; ++static const unsigned int msiof2_rxd_pins[] = { ++ /* RXD */ ++ RCAR_GP_PIN(2, 1), ++}; ++static const unsigned int msiof2_rxd_mux[] = { ++ MSIOF2_RXD_MARK, ++}; ++ ++/* - MSIOF3 ----------------------------------------------------------------- */ ++static const unsigned int msiof3_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(0, 20), ++}; ++static const unsigned int msiof3_clk_mux[] = { ++ MSIOF3_SCK_MARK, ++}; ++static const unsigned int msiof3_sync_pins[] = { ++ /* SYNC */ ++ RCAR_GP_PIN(0, 21), ++}; ++static const unsigned int msiof3_sync_mux[] = { ++ MSIOF3_SYNC_MARK, ++}; ++static const unsigned int msiof3_ss1_pins[] = { ++ /* SS1 */ ++ RCAR_GP_PIN(0, 6), ++}; ++static const unsigned int msiof3_ss1_mux[] = { ++ MSIOF3_SS1_MARK, ++}; ++static const unsigned int msiof3_ss2_pins[] = { ++ /* SS2 */ ++ RCAR_GP_PIN(0, 7), ++}; ++static const unsigned int msiof3_ss2_mux[] = { ++ MSIOF3_SS2_MARK, ++}; ++static const unsigned int msiof3_txd_pins[] = { ++ /* TXD */ ++ RCAR_GP_PIN(0, 5), ++}; ++static const unsigned int msiof3_txd_mux[] = { ++ MSIOF3_TXD_MARK, ++}; ++static const unsigned int msiof3_rxd_pins[] = { ++ /* RXD */ ++ RCAR_GP_PIN(0, 4), ++}; ++static const unsigned int msiof3_rxd_mux[] = { ++ MSIOF3_RXD_MARK, ++}; ++ ++/* - TPU ------------------------------------------------------------------- */ ++static const unsigned int tpu_to0_pins[] = { ++ /* TPU0TO0 */ ++ RCAR_GP_PIN(4, 0), ++}; ++static const unsigned int tpu_to0_mux[] = { ++ TPU0TO0_MARK, ++}; ++static const unsigned int tpu_to1_pins[] = { ++ /* TPU0TO1 */ ++ RCAR_GP_PIN(4, 1), ++}; ++static const unsigned int tpu_to1_mux[] = { ++ TPU0TO1_MARK, ++}; ++static const unsigned int tpu_to2_pins[] = { ++ /* TPU0TO2 */ ++ RCAR_GP_PIN(4, 2), ++}; ++static const unsigned int tpu_to2_mux[] = { ++ TPU0TO2_MARK, ++}; ++static const unsigned int tpu_to3_pins[] = { ++ /* TPU0TO3 */ ++ RCAR_GP_PIN(4, 3), ++}; ++static const unsigned int tpu_to3_mux[] = { ++ TPU0TO3_MARK, ++}; ++ ++/* - PWM0 ------------------------------------------------------------------- */ ++static const unsigned int pwm0_a_pins[] = { ++ /* PWM0 */ ++ RCAR_GP_PIN(2, 12), ++}; ++static const unsigned int pwm0_a_mux[] = { ++ PWM0_A_MARK, ++}; ++static const unsigned int pwm0_b_pins[] = { ++ /* PWM0 */ ++ RCAR_GP_PIN(1, 21), ++}; ++static const unsigned int pwm0_b_mux[] = { ++ PWM0_B_MARK, ++}; ++ ++/* - PWM1 ------------------------------------------------------------------- */ ++static const unsigned int pwm1_a_pins[] = { ++ /* PWM1 */ ++ RCAR_GP_PIN(2, 13), ++}; ++static const unsigned int pwm1_a_mux[] = { ++ PWM1_A_MARK, ++}; ++static const unsigned int pwm1_b_pins[] = { ++ /* PWM1 */ ++ RCAR_GP_PIN(1, 22), ++}; ++static const unsigned int pwm1_b_mux[] = { ++ PWM1_B_MARK, ++}; ++ ++/* - PWM2 ------------------------------------------------------------------- */ ++static const unsigned int pwm2_a_pins[] = { ++ /* PWM2 */ ++ RCAR_GP_PIN(2, 14), ++}; ++static const unsigned int pwm2_a_mux[] = { ++ PWM2_A_MARK, ++}; ++static const unsigned int pwm2_b_pins[] = { ++ /* PWM2 */ ++ RCAR_GP_PIN(1, 23), ++}; ++static const unsigned int pwm2_b_mux[] = { ++ PWM2_B_MARK, ++}; ++ ++/* - PWM3 ------------------------------------------------------------------- */ ++static const unsigned int pwm3_a_pins[] = { ++ /* PWM3 */ ++ RCAR_GP_PIN(2, 15), ++}; ++static const unsigned int pwm3_a_mux[] = { ++ PWM3_A_MARK, ++}; ++static const unsigned int pwm3_b_pins[] = { ++ /* PWM3 */ ++ RCAR_GP_PIN(1, 24), ++}; ++static const unsigned int pwm3_b_mux[] = { ++ PWM3_B_MARK, ++}; ++ ++/* - PWM4 ------------------------------------------------------------------- */ ++static const unsigned int pwm4_a_pins[] = { ++ /* PWM4 */ ++ RCAR_GP_PIN(2, 16), ++}; ++static const unsigned int pwm4_a_mux[] = { ++ PWM4_A_MARK, ++}; ++static const unsigned int pwm4_b_pins[] = { ++ /* PWM4 */ ++ RCAR_GP_PIN(1, 25), ++}; ++static const unsigned int pwm4_b_mux[] = { ++ PWM4_B_MARK, ++}; ++ ++/* - SCIF0 ------------------------------------------------------------------ */ ++static const unsigned int scif0_data_pins[] = { ++ /* RX, TX */ ++ RCAR_GP_PIN(4, 4), RCAR_GP_PIN(4, 5), ++}; ++static const unsigned int scif0_data_mux[] = { ++ RX0_MARK, TX0_MARK, ++}; ++static const unsigned int scif0_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(4, 1), ++}; ++static const unsigned int scif0_clk_mux[] = { ++ SCK0_MARK, ++}; ++ ++static const unsigned int scif0_ctrl_pins[] = { ++ /* RTS, CTS */ ++ RCAR_GP_PIN(4, 3), RCAR_GP_PIN(4, 2), ++}; ++static const unsigned int scif0_ctrl_mux[] = { ++ RTS0_N_TANS_MARK, CTS0_N_MARK, ++}; ++ ++/* - SCIF1 ------------------------------------------------------------------ */ ++static const unsigned int scif1_data_a_pins[] = { ++ /* RX, TX */ ++ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9), ++}; ++static const unsigned int scif1_data_a_mux[] = { ++ RX1_A_MARK, TX1_A_MARK, ++}; ++static const unsigned int scif1_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(2, 5), ++}; ++static const unsigned int scif1_clk_mux[] = { ++ SCK1_MARK, ++}; ++static const unsigned int scif1_ctrl_pins[] = { ++ /* RTS, CTS */ ++ RCAR_GP_PIN(2, 11), RCAR_GP_PIN(2, 10), ++}; ++static const unsigned int scif1_ctrl_mux[] = { ++ RTS1_N_TANS_MARK, CTS1_N_MARK, ++}; ++static const unsigned int scif1_data_b_pins[] = { ++ /* RX, TX */ ++ RCAR_GP_PIN(1, 24), RCAR_GP_PIN(1, 23), ++}; ++static const unsigned int scif1_data_b_mux[] = { ++ RX1_B_MARK, TX1_B_MARK, ++}; ++ ++/* - SCIF3 ------------------------------------------------------------------ */ ++static const unsigned int scif3_data_pins[] = { ++ /* RX, TX */ ++ RCAR_GP_PIN(2, 1), RCAR_GP_PIN(2, 2), ++}; ++static const unsigned int scif3_data_mux[] = { ++ RX3_MARK, TX3_MARK, ++}; ++static const unsigned int scif3_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(2, 0), ++}; ++static const unsigned int scif3_clk_mux[] = { ++ SCK3_MARK, ++}; ++static const unsigned int scif3_ctrl_pins[] = { ++ /* RTS, CTS */ ++ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 3), ++}; ++static const unsigned int scif3_ctrl_mux[] = { ++ RTS3_N_TANS_MARK, CTS3_N_MARK, ++}; ++ ++/* - SCIF4 ------------------------------------------------------------------ */ ++static const unsigned int scif4_data_pins[] = { ++ /* RX, TX */ ++ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11), ++}; ++static const unsigned int scif4_data_mux[] = { ++ RX4_MARK, TX4_MARK, ++}; ++static const unsigned int scif4_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(3, 9), ++}; ++static const unsigned int scif4_clk_mux[] = { ++ SCK4_MARK, ++}; ++static const unsigned int scif4_ctrl_pins[] = { ++ /* RTS, CTS */ ++ RCAR_GP_PIN(3, 13), RCAR_GP_PIN(3, 12), ++}; ++static const unsigned int scif4_ctrl_mux[] = { ++ RTS4_N_TANS_MARK, CTS4_N_MARK, ++}; ++ ++/* - MMC -------------------------------------------------------------------- */ ++static const unsigned int mmc_data1_pins[] = { ++ /* D0 */ ++ RCAR_GP_PIN(3, 6), ++}; ++static const unsigned int mmc_data1_mux[] = { ++ MMC_D0_MARK, ++}; ++static const unsigned int mmc_data4_pins[] = { ++ /* D[0:3] */ ++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), ++ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), ++}; ++static const unsigned int mmc_data4_mux[] = { ++ MMC_D0_MARK, MMC_D1_MARK, ++ MMC_D2_MARK, MMC_D3_MARK, ++}; ++static const unsigned int mmc_data8_pins[] = { ++ /* D[0:7] */ ++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), ++ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), ++ RCAR_GP_PIN(3, 11), RCAR_GP_PIN(3, 12), ++ RCAR_GP_PIN(3, 13), RCAR_GP_PIN(3, 14), ++}; ++static const unsigned int mmc_data8_mux[] = { ++ MMC_D0_MARK, MMC_D1_MARK, ++ MMC_D2_MARK, MMC_D3_MARK, ++ MMC_D4_MARK, MMC_D5_MARK, ++ MMC_D6_MARK, MMC_D7_MARK, ++}; ++static const unsigned int mmc_ctrl_pins[] = { ++ /* CLK, CMD */ ++ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 5), ++}; ++static const unsigned int mmc_ctrl_mux[] = { ++ MMC_CLK_MARK, MMC_CMD_MARK, ++}; ++static const unsigned int mmc_cd_pins[] = { ++ /* CD */ ++ RCAR_GP_PIN(3, 16), ++}; ++static const unsigned int mmc_cd_mux[] = { ++ MMC_CD_MARK, ++}; ++static const unsigned int mmc_wp_pins[] = { ++ /* WP */ ++ RCAR_GP_PIN(3, 15), ++}; ++static const unsigned int mmc_wp_mux[] = { ++ MMC_WP_MARK, ++}; ++ ++/* - TMU -------------------------------------------------------------------- */ ++static const unsigned int tmu_tclk1_a_pins[] = { ++ /* TCLK1 */ ++ RCAR_GP_PIN(4, 4), ++}; ++static const unsigned int tmu_tclk1_a_mux[] = { ++ TCLK1_A_MARK, ++}; ++static const unsigned int tmu_tclk1_b_pins[] = { ++ /* TCLK1 */ ++ RCAR_GP_PIN(1, 23), ++}; ++static const unsigned int tmu_tclk1_b_mux[] = { ++ TCLK1_B_MARK, ++}; ++static const unsigned int tmu_tclk2_a_pins[] = { ++ /* TCLK2 */ ++ RCAR_GP_PIN(4, 5), ++}; ++static const unsigned int tmu_tclk2_a_mux[] = { ++ TCLK2_A_MARK, ++}; ++static const unsigned int tmu_tclk2_b_pins[] = { ++ /* TCLK2 */ ++ RCAR_GP_PIN(1, 24), ++}; ++static const unsigned int tmu_tclk2_b_mux[] = { ++ TCLK2_B_MARK, ++}; ++ ++/* - VIN0 ------------------------------------------------------------------- */ ++static const unsigned int vin0_data8_pins[] = { ++ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 5), ++ RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 7), ++ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9), ++ RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11), ++}; ++static const unsigned int vin0_data8_mux[] = { ++ VI0_DATA0_MARK, VI0_DATA1_MARK, ++ VI0_DATA2_MARK, VI0_DATA3_MARK, ++ VI0_DATA4_MARK, VI0_DATA5_MARK, ++ VI0_DATA6_MARK, VI0_DATA7_MARK, ++}; ++static const unsigned int vin0_data10_pins[] = { ++ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 5), ++ RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 7), ++ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9), ++ RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11), ++ RCAR_GP_PIN(2, 12), RCAR_GP_PIN(2, 13), ++}; ++static const unsigned int vin0_data10_mux[] = { ++ VI0_DATA0_MARK, VI0_DATA1_MARK, ++ VI0_DATA2_MARK, VI0_DATA3_MARK, ++ VI0_DATA4_MARK, VI0_DATA5_MARK, ++ VI0_DATA6_MARK, VI0_DATA7_MARK, ++ VI0_DATA8_MARK, VI0_DATA9_MARK, ++}; ++static const unsigned int vin0_data12_pins[] = { ++ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 5), ++ RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 7), ++ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9), ++ RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11), ++ RCAR_GP_PIN(2, 12), RCAR_GP_PIN(2, 13), ++ RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 15), ++}; ++static const unsigned int vin0_data12_mux[] = { ++ VI0_DATA0_MARK, VI0_DATA1_MARK, ++ VI0_DATA2_MARK, VI0_DATA3_MARK, ++ VI0_DATA4_MARK, VI0_DATA5_MARK, ++ VI0_DATA6_MARK, VI0_DATA7_MARK, ++ VI0_DATA8_MARK, VI0_DATA9_MARK, ++ VI0_DATA10_MARK, VI0_DATA11_MARK, ++}; ++static const unsigned int vin0_sync_pins[] = { ++ /* VSYNC_N, HSYNC_N */ ++ RCAR_GP_PIN(2, 3), RCAR_GP_PIN(2, 2), ++}; ++static const unsigned int vin0_sync_mux[] = { ++ VI0_HSYNC_N_MARK, VI0_VSYNC_N_MARK, ++}; ++static const unsigned int vin0_field_pins[] = { ++ /* FIELD */ ++ RCAR_GP_PIN(2, 16), ++}; ++static const unsigned int vin0_field_mux[] = { ++ VI0_FIELD_MARK, ++}; ++static const unsigned int vin0_clkenb_pins[] = { ++ /* CLKENB */ ++ RCAR_GP_PIN(2, 1), ++}; ++static const unsigned int vin0_clkenb_mux[] = { ++ VI0_CLKENB_MARK, ++}; ++static const unsigned int vin0_clk_pins[] = { ++ /* CLK */ ++ RCAR_GP_PIN(2, 0), ++}; ++static const unsigned int vin0_clk_mux[] = { ++ VI0_CLK_MARK, ++}; ++/* - VIN1 ------------------------------------------------------------------- */ ++static const unsigned int vin1_data8_pins[] = { ++ RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5), ++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), ++ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), ++ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11), ++}; ++static const unsigned int vin1_data8_mux[] = { ++ VI1_DATA0_MARK, VI1_DATA1_MARK, ++ VI1_DATA2_MARK, VI1_DATA3_MARK, ++ VI1_DATA4_MARK, VI1_DATA5_MARK, ++ VI1_DATA6_MARK, VI1_DATA7_MARK, ++}; ++static const unsigned int vin1_data10_pins[] = { ++ RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5), ++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), ++ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), ++ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11), ++ RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 13), ++}; ++static const unsigned int vin1_data10_mux[] = { ++ VI1_DATA0_MARK, VI1_DATA1_MARK, ++ VI1_DATA2_MARK, VI1_DATA3_MARK, ++ VI1_DATA4_MARK, VI1_DATA5_MARK, ++ VI1_DATA6_MARK, VI1_DATA7_MARK, ++ VI1_DATA8_MARK, VI1_DATA9_MARK, ++}; ++static const unsigned int vin1_data12_pins[] = { ++ RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5), ++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), ++ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), ++ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11), ++ RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 13), ++ RCAR_GP_PIN(3, 14), RCAR_GP_PIN(3, 15), ++}; ++static const unsigned int vin1_data12_mux[] = { ++ VI1_DATA0_MARK, VI1_DATA1_MARK, ++ VI1_DATA2_MARK, VI1_DATA3_MARK, ++ VI1_DATA4_MARK, VI1_DATA5_MARK, ++ VI1_DATA6_MARK, VI1_DATA7_MARK, ++ VI1_DATA8_MARK, VI1_DATA9_MARK, ++ VI1_DATA10_MARK, VI1_DATA11_MARK, ++}; ++static const unsigned int vin1_sync_pins[] = { ++ /* VSYNC_N, HSYNC_N */ ++ RCAR_GP_PIN(3, 3), RCAR_GP_PIN(3, 2), ++}; ++static const unsigned int vin1_sync_mux[] = { ++ VI1_HSYNC_N_MARK, VI1_VSYNC_N_MARK, ++}; ++static const unsigned int vin1_field_pins[] = { ++ /* FIELD */ ++ RCAR_GP_PIN(3, 16), ++}; ++static const unsigned int vin1_field_mux[] = { ++ VI1_FIELD_MARK, ++}; ++static const unsigned int vin1_clkenb_pins[] = { ++ /* CLKENB */ ++ RCAR_GP_PIN(3, 1), ++}; ++static const unsigned int vin1_clkenb_mux[] = { ++ VI1_CLKENB_MARK, ++}; ++static const unsigned int vin1_clk_pins[] = { ++ /* CLK */ ++ RCAR_GP_PIN(3, 0), ++}; ++static const unsigned int vin1_clk_mux[] = { ++ VI1_CLK_MARK, ++}; ++ ++static const struct sh_pfc_pin_group pinmux_groups[] = { ++ SH_PFC_PIN_GROUP(avb0_rx_ctrl), ++ SH_PFC_PIN_GROUP(avb0_rxc), ++ SH_PFC_PIN_GROUP(avb0_rd0), ++ SH_PFC_PIN_GROUP(avb0_rd1), ++ SH_PFC_PIN_GROUP(avb0_rd2), ++ SH_PFC_PIN_GROUP(avb0_rd3), ++ SH_PFC_PIN_GROUP(avb0_rd4), ++ SH_PFC_PIN_GROUP(avb0_tx_ctrl), ++ SH_PFC_PIN_GROUP(avb0_txc), ++ SH_PFC_PIN_GROUP(avb0_td0), ++ SH_PFC_PIN_GROUP(avb0_td1), ++ SH_PFC_PIN_GROUP(avb0_td2), ++ SH_PFC_PIN_GROUP(avb0_td3), ++ SH_PFC_PIN_GROUP(avb0_td4), ++ SH_PFC_PIN_GROUP(avb0_txcrefclk), ++ SH_PFC_PIN_GROUP(avb0_mdio), ++ SH_PFC_PIN_GROUP(avb0_mdc), ++ SH_PFC_PIN_GROUP(avb0_magic), ++ SH_PFC_PIN_GROUP(avb0_phy_int), ++ SH_PFC_PIN_GROUP(avb0_link), ++ SH_PFC_PIN_GROUP(avb0_avtp_match), ++ SH_PFC_PIN_GROUP(avb0_avtp_pps), ++ SH_PFC_PIN_GROUP(avb0_avtp_capture), ++ SH_PFC_PIN_GROUP(canfd0_data_a), ++ SH_PFC_PIN_GROUP(canfd_clk_a), ++ SH_PFC_PIN_GROUP(canfd0_data_b), ++ SH_PFC_PIN_GROUP(canfd_clk_b), ++ SH_PFC_PIN_GROUP(canfd1_data), ++ SH_PFC_PIN_GROUP(du_rgb666), ++ SH_PFC_PIN_GROUP(du_clk_out_0), ++ SH_PFC_PIN_GROUP(du_clk_out_1), ++ SH_PFC_PIN_GROUP(du_sync), ++ SH_PFC_PIN_GROUP(du_oddf), ++ SH_PFC_PIN_GROUP(du_cde), ++ SH_PFC_PIN_GROUP(du_disp), ++ SH_PFC_PIN_GROUP(hscif0_data), ++ SH_PFC_PIN_GROUP(hscif0_clk), ++ SH_PFC_PIN_GROUP(hscif0_ctrl), ++ SH_PFC_PIN_GROUP(hscif1_data), ++ SH_PFC_PIN_GROUP(hscif1_clk), ++ SH_PFC_PIN_GROUP(hscif1_ctrl), ++ SH_PFC_PIN_GROUP(hscif2_data), ++ SH_PFC_PIN_GROUP(hscif2_clk), ++ SH_PFC_PIN_GROUP(hscif2_ctrl), ++ SH_PFC_PIN_GROUP(hscif3_data), ++ SH_PFC_PIN_GROUP(hscif3_clk), ++ SH_PFC_PIN_GROUP(hscif3_ctrl), ++ SH_PFC_PIN_GROUP(scif_clk_a), ++ SH_PFC_PIN_GROUP(scif_clk_b), ++ SH_PFC_PIN_GROUP(i2c0), ++ SH_PFC_PIN_GROUP(i2c1), ++ SH_PFC_PIN_GROUP(i2c2), ++ SH_PFC_PIN_GROUP(i2c3), ++ SH_PFC_PIN_GROUP(i2c4), ++ SH_PFC_PIN_GROUP(intc_ex_irq0), ++ SH_PFC_PIN_GROUP(intc_ex_irq1), ++ SH_PFC_PIN_GROUP(intc_ex_irq2), ++ SH_PFC_PIN_GROUP(intc_ex_irq3), ++ SH_PFC_PIN_GROUP(intc_ex_irq4), ++ SH_PFC_PIN_GROUP(intc_ex_irq5), ++ SH_PFC_PIN_GROUP(msiof0_clk), ++ SH_PFC_PIN_GROUP(msiof0_sync), ++ SH_PFC_PIN_GROUP(msiof0_ss1), ++ SH_PFC_PIN_GROUP(msiof0_ss2), ++ SH_PFC_PIN_GROUP(msiof0_txd), ++ SH_PFC_PIN_GROUP(msiof0_rxd), ++ SH_PFC_PIN_GROUP(msiof1_clk), ++ SH_PFC_PIN_GROUP(msiof1_sync), ++ SH_PFC_PIN_GROUP(msiof1_ss1), ++ SH_PFC_PIN_GROUP(msiof1_ss2), ++ SH_PFC_PIN_GROUP(msiof1_txd), ++ SH_PFC_PIN_GROUP(msiof1_rxd), ++ SH_PFC_PIN_GROUP(msiof2_clk), ++ SH_PFC_PIN_GROUP(msiof2_sync), ++ SH_PFC_PIN_GROUP(msiof2_ss1), ++ SH_PFC_PIN_GROUP(msiof2_ss2), ++ SH_PFC_PIN_GROUP(msiof2_txd), ++ SH_PFC_PIN_GROUP(msiof2_rxd), ++ SH_PFC_PIN_GROUP(msiof3_clk), ++ SH_PFC_PIN_GROUP(msiof3_sync), ++ SH_PFC_PIN_GROUP(msiof3_ss1), ++ SH_PFC_PIN_GROUP(msiof3_ss2), ++ SH_PFC_PIN_GROUP(msiof3_txd), ++ SH_PFC_PIN_GROUP(msiof3_rxd), ++ SH_PFC_PIN_GROUP(tpu_to0), ++ SH_PFC_PIN_GROUP(tpu_to1), ++ SH_PFC_PIN_GROUP(tpu_to2), ++ SH_PFC_PIN_GROUP(tpu_to3), ++ SH_PFC_PIN_GROUP(pwm0_a), ++ SH_PFC_PIN_GROUP(pwm0_b), ++ SH_PFC_PIN_GROUP(pwm1_a), ++ SH_PFC_PIN_GROUP(pwm1_b), ++ SH_PFC_PIN_GROUP(pwm2_a), ++ SH_PFC_PIN_GROUP(pwm2_b), ++ SH_PFC_PIN_GROUP(pwm3_a), ++ SH_PFC_PIN_GROUP(pwm3_b), ++ SH_PFC_PIN_GROUP(pwm4_a), ++ SH_PFC_PIN_GROUP(pwm4_b), ++ SH_PFC_PIN_GROUP(scif0_data), ++ SH_PFC_PIN_GROUP(scif0_clk), ++ SH_PFC_PIN_GROUP(scif0_ctrl), ++ SH_PFC_PIN_GROUP(scif1_data_a), ++ SH_PFC_PIN_GROUP(scif1_clk), ++ SH_PFC_PIN_GROUP(scif1_ctrl), ++ SH_PFC_PIN_GROUP(scif1_data_b), ++ SH_PFC_PIN_GROUP(scif3_data), ++ SH_PFC_PIN_GROUP(scif3_clk), ++ SH_PFC_PIN_GROUP(scif3_ctrl), ++ SH_PFC_PIN_GROUP(scif4_data), ++ SH_PFC_PIN_GROUP(scif4_clk), ++ SH_PFC_PIN_GROUP(scif4_ctrl), ++ SH_PFC_PIN_GROUP(mmc_data1), ++ SH_PFC_PIN_GROUP(mmc_data4), ++ SH_PFC_PIN_GROUP(mmc_data8), ++ SH_PFC_PIN_GROUP(mmc_ctrl), ++ SH_PFC_PIN_GROUP(mmc_cd), ++ SH_PFC_PIN_GROUP(mmc_wp), ++ SH_PFC_PIN_GROUP(tmu_tclk1_a), ++ SH_PFC_PIN_GROUP(tmu_tclk1_b), ++ SH_PFC_PIN_GROUP(tmu_tclk2_a), ++ SH_PFC_PIN_GROUP(tmu_tclk2_b), ++ SH_PFC_PIN_GROUP(vin0_data8), ++ SH_PFC_PIN_GROUP(vin0_data10), ++ SH_PFC_PIN_GROUP(vin0_data12), ++ SH_PFC_PIN_GROUP(vin0_sync), ++ SH_PFC_PIN_GROUP(vin0_field), ++ SH_PFC_PIN_GROUP(vin0_clkenb), ++ SH_PFC_PIN_GROUP(vin0_clk), ++ SH_PFC_PIN_GROUP(vin1_data8), ++ SH_PFC_PIN_GROUP(vin1_data10), ++ SH_PFC_PIN_GROUP(vin1_data12), ++ SH_PFC_PIN_GROUP(vin1_sync), ++ SH_PFC_PIN_GROUP(vin1_field), ++ SH_PFC_PIN_GROUP(vin1_clkenb), ++ SH_PFC_PIN_GROUP(vin1_clk), ++}; ++ ++static const char * const avb0_groups[] = { ++ "avb0_rx_ctrl", ++ "avb0_rxc", ++ "avb0_rd1", ++ "avb0_rd4", ++ "avb0_tx_ctrl", ++ "avb0_txc", ++ "avb0_td1", ++ "avb0_td4", ++ "avb0_txcrefclk", ++ "avb0_mdio", ++ "avb0_mdc", ++ "avb0_magic", ++ "avb0_phy_int", ++ "avb0_link", ++ "avb0_avtp_match", ++ "avb0_avtp_pps", ++ "avb0_avtp_capture", ++}; ++ ++static const char * const canfd0_groups[] = { ++ "canfd0_data_a", ++ "canfd_clk_a", ++ "canfd0_data_b", ++ "canfd_clk_b", ++}; ++ ++static const char * const canfd1_groups[] = { ++ "canfd1_data", ++}; ++ ++static const char * const du_groups[] = { ++ "du_rgb666", ++ "du_clk_out_0", ++ "du_clk_out_1", ++ "du_sync", ++ "du_oddf", ++ "du_cde", ++ "du_disp", ++}; ++ ++static const char * const hscif0_groups[] = { ++ "hscif0_data", ++ "hscif0_clk", ++ "hscif0_ctrl", ++}; ++ ++static const char * const hscif1_groups[] = { ++ "hscif1_data", ++ "hscif1_clk", ++ "hscif1_ctrl", ++}; ++ ++static const char * const hscif2_groups[] = { ++ "hscif2_data", ++ "hscif2_clk", ++ "hscif2_ctrl", ++}; ++ ++static const char * const hscif3_groups[] = { ++ "hscif3_data", ++ "hscif3_clk", ++ "hscif3_ctrl", ++}; ++ ++static const char * const scif_clk_groups[] = { ++ "scif_clk_a", ++ "scif_clk_b", ++}; ++ ++static const char * const i2c0_groups[] = { ++ "i2c0", ++}; ++ ++static const char * const i2c1_groups[] = { ++ "i2c1", ++}; ++ ++static const char * const i2c2_groups[] = { ++ "i2c2", ++}; ++ ++static const char * const i2c3_groups[] = { ++ "i2c3", ++}; ++ ++static const char * const i2c4_groups[] = { ++ "i2c4", ++}; ++ ++static const char * const intc_ex_groups[] = { ++ "intc_ex_irq0", ++ "intc_ex_irq1", ++ "intc_ex_irq2", ++ "intc_ex_irq3", ++ "intc_ex_irq4", ++ "intc_ex_irq5", ++}; ++ ++static const char * const msiof0_groups[] = { ++ "msiof0_clk", ++ "msiof0_sync", ++ "msiof0_ss1", ++ "msiof0_ss2", ++ "msiof0_txd", ++ "msiof0_rxd", ++}; ++ ++static const char * const msiof1_groups[] = { ++ "msiof1_clk", ++ "msiof1_sync", ++ "msiof1_ss1", ++ "msiof1_ss2", ++ "msiof1_txd", ++ "msiof1_rxd", ++}; ++ ++static const char * const msiof2_groups[] = { ++ "msiof2_clk", ++ "msiof2_sync", ++ "msiof2_ss1", ++ "msiof2_ss2", ++ "msiof2_txd", ++ "msiof2_rxd", ++}; ++ ++static const char * const msiof3_groups[] = { ++ "msiof3_clk", ++ "msiof3_sync", ++ "msiof3_ss1", ++ "msiof3_ss2", ++ "msiof3_txd", ++ "msiof3_rxd", ++}; ++ ++static const char * const tpu_groups[] = { ++ "tpu_to0", ++ "tpu_to1", ++ "tpu_to2", ++ "tpu_to3", ++}; ++ ++static const char * const pwm0_groups[] = { ++ "pwm0_a", ++ "pwm0_b", ++}; ++ ++static const char * const pwm1_groups[] = { ++ "pwm1_a", ++ "pwm1_b", ++}; ++ ++static const char * const pwm2_groups[] = { ++ "pwm2_a", ++ "pwm2_b", ++}; ++ ++static const char * const pwm3_groups[] = { ++ "pwm3_a", ++ "pwm3_b", ++}; ++ ++static const char * const pwm4_groups[] = { ++ "pwm4_a", ++ "pwm4_b", ++}; ++ ++static const char * const scif0_groups[] = { ++ "scif0_data", ++// "scif0_clk", ++// "scif0_ctrl", ++}; ++ ++static const char * const scif1_groups[] = { ++ "scif1_data_a", ++ "scif1_clk", ++ "scif1_ctrl", ++ "scif1_data_b", ++}; ++ ++static const char * const scif3_groups[] = { ++ "scif3_data", ++ "scif3_clk", ++ "scif3_ctrl", ++}; ++ ++static const char * const scif4_groups[] = { ++ "scif4_data", ++ "scif4_clk", ++ "scif4_ctrl", ++}; ++ ++static const char * const mmc_groups[] = { ++ "mmc_data1", ++ "mmc_data4", ++ "mmc_data8", ++ "mmc_ctrl", ++ "mmc_cd", ++ "mmc_wp", ++}; ++ ++static const char * const tmu_groups[] = { ++ "tmu_tclk1_a", ++ "tmu_tclk1_b", ++ "tmu_tclk2_a", ++ "tmu_tclk2_b", ++}; ++ ++static const char * const vin0_groups[] = { ++ "vin0_data8", ++ "vin0_data10", ++ "vin0_data12", ++ "vin0_sync", ++ "vin0_field", ++ "vin0_clkenb", ++ "vin0_clk", ++}; ++ ++static const char * const vin1_groups[] = { ++ "vin1_data8", ++ "vin1_data10", ++ "vin1_data12", ++ "vin1_sync", ++ "vin1_field", ++ "vin1_clkenb", ++ "vin1_clk", ++}; ++ ++#define POCCTRL0 0x380 ++#define POCCTRL1 0x384 ++#define PIN2POCCTRL0_SHIFT(a) ({ \ ++ int _gp = (a) >> 5; \ ++ int _bit = (a) & 0x1f; \ ++ ((_gp == 3) && (_bit < 17)) ? _bit + 7 : -1; \ ++}) ++ ++ ++static const struct sh_pfc_function pinmux_functions[] = { ++ SH_PFC_FUNCTION(avb0), ++ SH_PFC_FUNCTION(canfd0), ++ SH_PFC_FUNCTION(canfd1), ++ SH_PFC_FUNCTION(du), ++ SH_PFC_FUNCTION(hscif0), ++ SH_PFC_FUNCTION(hscif1), ++ SH_PFC_FUNCTION(hscif2), ++ SH_PFC_FUNCTION(hscif3), ++ SH_PFC_FUNCTION(scif_clk), ++ SH_PFC_FUNCTION(i2c0), ++ SH_PFC_FUNCTION(i2c1), ++ SH_PFC_FUNCTION(i2c2), ++ SH_PFC_FUNCTION(i2c3), ++ SH_PFC_FUNCTION(i2c4), ++ SH_PFC_FUNCTION(intc_ex), ++ SH_PFC_FUNCTION(msiof0), ++ SH_PFC_FUNCTION(msiof1), ++ SH_PFC_FUNCTION(msiof2), ++ SH_PFC_FUNCTION(msiof3), ++ SH_PFC_FUNCTION(tpu), ++ SH_PFC_FUNCTION(pwm0), ++ SH_PFC_FUNCTION(pwm1), ++ SH_PFC_FUNCTION(pwm2), ++ SH_PFC_FUNCTION(pwm3), ++ SH_PFC_FUNCTION(pwm4), ++ SH_PFC_FUNCTION(scif0), ++ SH_PFC_FUNCTION(scif1), ++ SH_PFC_FUNCTION(scif3), ++ SH_PFC_FUNCTION(scif4), ++ SH_PFC_FUNCTION(mmc), ++ SH_PFC_FUNCTION(tmu), ++ SH_PFC_FUNCTION(vin0), ++ SH_PFC_FUNCTION(vin1), ++}; ++ ++static const struct pinmux_cfg_reg pinmux_config_regs[] = { ++#define F_(x, y) FN_##y ++#define FM(x) FN_##x ++ { PINMUX_CFG_REG("GPSR0", 0xe6060100, 32, 1) { ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ GP_0_21_FN, GPSR0_21, ++ GP_0_20_FN, GPSR0_20, ++ GP_0_19_FN, GPSR0_19, ++ GP_0_18_FN, GPSR0_18, ++ GP_0_17_FN, GPSR0_17, ++ GP_0_16_FN, GPSR0_16, ++ GP_0_15_FN, GPSR0_15, ++ GP_0_14_FN, GPSR0_14, ++ GP_0_13_FN, GPSR0_13, ++ GP_0_12_FN, GPSR0_12, ++ GP_0_11_FN, GPSR0_11, ++ GP_0_10_FN, GPSR0_10, ++ GP_0_9_FN, GPSR0_9, ++ GP_0_8_FN, GPSR0_8, ++ GP_0_7_FN, GPSR0_7, ++ GP_0_6_FN, GPSR0_6, ++ GP_0_5_FN, GPSR0_5, ++ GP_0_4_FN, GPSR0_4, ++ GP_0_3_FN, GPSR0_3, ++ GP_0_2_FN, GPSR0_2, ++ GP_0_1_FN, GPSR0_1, ++ GP_0_0_FN, GPSR0_0, } ++ }, ++ { PINMUX_CFG_REG("GPSR1", 0xe6060104, 32, 1) { ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ GP_1_27_FN, GPSR1_27, ++ GP_1_26_FN, GPSR1_26, ++ GP_1_25_FN, GPSR1_25, ++ GP_1_24_FN, GPSR1_24, ++ GP_1_23_FN, GPSR1_23, ++ GP_1_22_FN, GPSR1_22, ++ GP_1_21_FN, GPSR1_21, ++ GP_1_20_FN, GPSR1_20, ++ GP_1_19_FN, GPSR1_19, ++ GP_1_18_FN, GPSR1_18, ++ GP_1_17_FN, GPSR1_17, ++ GP_1_16_FN, GPSR1_16, ++ GP_1_15_FN, GPSR1_15, ++ GP_1_14_FN, GPSR1_14, ++ GP_1_13_FN, GPSR1_13, ++ GP_1_12_FN, GPSR1_12, ++ GP_1_11_FN, GPSR1_11, ++ GP_1_10_FN, GPSR1_10, ++ GP_1_9_FN, GPSR1_9, ++ GP_1_8_FN, GPSR1_8, ++ GP_1_7_FN, GPSR1_7, ++ GP_1_6_FN, GPSR1_6, ++ GP_1_5_FN, GPSR1_5, ++ GP_1_4_FN, GPSR1_4, ++ GP_1_3_FN, GPSR1_3, ++ GP_1_2_FN, GPSR1_2, ++ GP_1_1_FN, GPSR1_1, ++ GP_1_0_FN, GPSR1_0, } ++ }, ++ { PINMUX_CFG_REG("GPSR2", 0xe6060108, 32, 1) { ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ GP_2_16_FN, GPSR2_16, ++ GP_2_15_FN, GPSR2_15, ++ GP_2_14_FN, GPSR2_14, ++ GP_2_13_FN, GPSR2_13, ++ GP_2_12_FN, GPSR2_12, ++ GP_2_11_FN, GPSR2_11, ++ GP_2_10_FN, GPSR2_10, ++ GP_2_9_FN, GPSR2_9, ++ GP_2_8_FN, GPSR2_8, ++ GP_2_7_FN, GPSR2_7, ++ GP_2_6_FN, GPSR2_6, ++ GP_2_5_FN, GPSR2_5, ++ GP_2_4_FN, GPSR2_4, ++ GP_2_3_FN, GPSR2_3, ++ GP_2_2_FN, GPSR2_2, ++ GP_2_1_FN, GPSR2_1, ++ GP_2_0_FN, GPSR2_0, } ++ }, ++ { PINMUX_CFG_REG("GPSR3", 0xe606010c, 32, 1) { ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ GP_3_16_FN, GPSR3_16, ++ GP_3_15_FN, GPSR3_15, ++ GP_3_14_FN, GPSR3_14, ++ GP_3_13_FN, GPSR3_13, ++ GP_3_12_FN, GPSR3_12, ++ GP_3_11_FN, GPSR3_11, ++ GP_3_10_FN, GPSR3_10, ++ GP_3_9_FN, GPSR3_9, ++ GP_3_8_FN, GPSR3_8, ++ GP_3_7_FN, GPSR3_7, ++ GP_3_6_FN, GPSR3_6, ++ GP_3_5_FN, GPSR3_5, ++ GP_3_4_FN, GPSR3_4, ++ GP_3_3_FN, GPSR3_3, ++ GP_3_2_FN, GPSR3_2, ++ GP_3_1_FN, GPSR3_1, ++ GP_3_0_FN, GPSR3_0, } ++ }, ++ { PINMUX_CFG_REG("GPSR4", 0xe6060110, 32, 1) { ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ GP_4_5_FN, GPSR4_5, ++ GP_4_4_FN, GPSR4_4, ++ GP_4_3_FN, GPSR4_3, ++ GP_4_2_FN, GPSR4_2, ++ GP_4_1_FN, GPSR4_1, ++ GP_4_0_FN, GPSR4_0, } ++ }, ++ { PINMUX_CFG_REG("GPSR5", 0xe6060114, 32, 1) { ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ GP_5_14_FN, GPSR5_14, ++ GP_5_13_FN, GPSR5_13, ++ GP_5_12_FN, GPSR5_12, ++ GP_5_11_FN, GPSR5_11, ++ GP_5_10_FN, GPSR5_10, ++ GP_5_9_FN, GPSR5_9, ++ GP_5_8_FN, GPSR5_8, ++ GP_5_7_FN, GPSR5_7, ++ GP_5_6_FN, GPSR5_6, ++ GP_5_5_FN, GPSR5_5, ++ GP_5_4_FN, GPSR5_4, ++ GP_5_3_FN, GPSR5_3, ++ GP_5_2_FN, GPSR5_2, ++ GP_5_1_FN, GPSR5_1, ++ GP_5_0_FN, GPSR5_0, } ++ }, ++#undef F_ ++#undef FM ++ ++#define F_(x, y) x, ++#define FM(x) FN_##x, ++ { PINMUX_CFG_REG("IPSR0", 0xe6060200, 32, 4) { ++ IP0_31_28 ++ IP0_27_24 ++ IP0_23_20 ++ IP0_19_16 ++ IP0_15_12 ++ IP0_11_8 ++ IP0_7_4 ++ IP0_3_0 } ++ }, ++ { PINMUX_CFG_REG("IPSR1", 0xe6060204, 32, 4) { ++ IP1_31_28 ++ IP1_27_24 ++ IP1_23_20 ++ IP1_19_16 ++ IP1_15_12 ++ IP1_11_8 ++ IP1_7_4 ++ IP1_3_0 } ++ }, ++ { PINMUX_CFG_REG("IPSR2", 0xe6060208, 32, 4) { ++ IP2_31_28 ++ IP2_27_24 ++ IP2_23_20 ++ IP2_19_16 ++ IP2_15_12 ++ IP2_11_8 ++ IP2_7_4 ++ IP2_3_0 } ++ }, ++ { PINMUX_CFG_REG("IPSR3", 0xe606020c, 32, 4) { ++ IP3_31_28 ++ IP3_27_24 ++ IP3_23_20 ++ IP3_19_16 ++ IP3_15_12 ++ IP3_11_8 ++ IP3_7_4 ++ IP3_3_0 } ++ }, ++ { PINMUX_CFG_REG("IPSR4", 0xe6060210, 32, 4) { ++ IP4_31_28 ++ IP4_27_24 ++ IP4_23_20 ++ IP4_19_16 ++ IP4_15_12 ++ IP4_11_8 ++ IP4_7_4 ++ IP4_3_0 } ++ }, ++ { PINMUX_CFG_REG("IPSR5", 0xe6060214, 32, 4) { ++ IP5_31_28 ++ IP5_27_24 ++ IP5_23_20 ++ IP5_19_16 ++ IP5_15_12 ++ IP5_11_8 ++ IP5_7_4 ++ IP5_3_0 } ++ }, ++ { PINMUX_CFG_REG("IPSR6", 0xe6060218, 32, 4) { ++ IP6_31_28 ++ IP6_27_24 ++ IP6_23_20 ++ IP6_19_16 ++ IP6_15_12 ++ IP6_11_8 ++ IP6_7_4 ++ IP6_3_0 } ++ }, ++ { PINMUX_CFG_REG("IPSR7", 0xe606021c, 32, 4) { ++ IP7_31_28 ++ IP7_27_24 ++ IP7_23_20 ++ IP7_19_16 ++ IP7_15_12 ++ IP7_11_8 ++ IP7_7_4 ++ IP7_3_0 } ++ }, ++ { PINMUX_CFG_REG("IPSR8", 0xe6060220, 32, 4) { ++ IP8_31_28 ++ IP8_27_24 ++ IP8_23_20 ++ IP8_19_16 ++ IP8_15_12 ++ IP8_11_8 ++ IP8_7_4 ++ IP8_3_0 } ++ }, ++#undef F_ ++#undef FM ++ ++#define F_(x, y) x, ++#define FM(x) FN_##x, ++ { PINMUX_CFG_REG("MOD_SEL0", 0xe6060500, 32, 1) { ++ /* RESERVED 31..12 */ ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ MOD_SEL0_11 ++ MOD_SEL0_10 ++ MOD_SEL0_9 ++ MOD_SEL0_8 ++ MOD_SEL0_7 ++ MOD_SEL0_6 ++ MOD_SEL0_5 ++ MOD_SEL0_4 ++ MOD_SEL0_3 ++ MOD_SEL0_2 ++ MOD_SEL0_1 ++ MOD_SEL0_0 } ++ }, ++ { }, ++}; ++ ++static int r8a7797_pin_to_pocctrl(struct sh_pfc *pfc, unsigned int pin, u32 *pocctrl) ++{ ++ int bit = -EINVAL; ++ ++ *pocctrl = 0xe6060384; ++ ++ if (pin >= RCAR_GP_PIN(3, 0) && pin <= RCAR_GP_PIN(3, 16)) ++ bit = (pin & 0x1f) + 7; ++ ++ return bit; ++} ++ ++static const struct sh_pfc_soc_operations pinmux_ops = { ++ .pin_to_pocctrl = r8a7797_pin_to_pocctrl, ++}; ++ ++const struct sh_pfc_soc_info r8a7797_pinmux_info = { ++ .name = "r8a77970_pfc", ++ .ops = &pinmux_ops, ++ .unlock_reg = 0xe6060000, /* PMMR */ ++ ++ .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END }, ++ ++ .pins = pinmux_pins, ++ .nr_pins = ARRAY_SIZE(pinmux_pins), ++ .groups = pinmux_groups, ++ .nr_groups = ARRAY_SIZE(pinmux_groups), ++ .functions = pinmux_functions, ++ .nr_functions = ARRAY_SIZE(pinmux_functions), ++ ++ .cfg_regs = pinmux_config_regs, ++ ++ .pinmux_data = pinmux_data, ++ .pinmux_data_size = ARRAY_SIZE(pinmux_data), ++}; +diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h +index 5a0da3c..062af89 100644 +--- a/drivers/pinctrl/sh-pfc/sh_pfc.h ++++ b/drivers/pinctrl/sh-pfc/sh_pfc.h +@@ -288,6 +288,7 @@ struct sh_pfc_soc_info { + extern const struct sh_pfc_soc_info r8a7795_es1_pinmux_info; + extern const struct sh_pfc_soc_info r8a7796_pinmux_info; + extern const struct sh_pfc_soc_info r8a77965_pinmux_info; ++extern const struct sh_pfc_soc_info r8a7797_pinmux_info; + extern const struct sh_pfc_soc_info sh7203_pinmux_info; + extern const struct sh_pfc_soc_info sh7264_pinmux_info; + extern const struct sh_pfc_soc_info sh7269_pinmux_info; +@@ -393,6 +394,11 @@ struct sh_pfc_soc_info { + PORT_GP_CFG_1(bank, 3, fn, sfx, cfg) + #define PORT_GP_4(bank, fn, sfx) PORT_GP_CFG_4(bank, fn, sfx, 0) + ++#define PORT_GP_CFG_6(bank, fn, sfx, cfg) \ ++ PORT_GP_CFG_4(bank, fn, sfx, cfg), \ ++ PORT_GP_CFG_1(bank, 4, fn, sfx, cfg), PORT_GP_CFG_1(bank, 5, fn, sfx, cfg) ++#define PORT_GP_6(bank, fn, sfx) PORT_GP_CFG_6(bank, fn, sfx, 0) ++ + #define PORT_GP_CFG_8(bank, fn, sfx, cfg) \ + PORT_GP_CFG_4(bank, fn, sfx, cfg), \ + PORT_GP_CFG_1(bank, 4, fn, sfx, cfg), \ +@@ -439,6 +445,12 @@ struct sh_pfc_soc_info { + PORT_GP_CFG_1(bank, 17, fn, sfx, cfg) + #define PORT_GP_18(bank, fn, sfx) PORT_GP_CFG_18(bank, fn, sfx, 0) + ++#define PORT_GP_CFG_22(bank, fn, sfx, cfg) \ ++ PORT_GP_CFG_18(bank, fn, sfx, cfg), \ ++ PORT_GP_CFG_1(bank, 18, fn, sfx, cfg), PORT_GP_CFG_1(bank, 19, fn, sfx, cfg), \ ++ PORT_GP_CFG_1(bank, 20, fn, sfx, cfg), PORT_GP_CFG_1(bank, 21, fn, sfx, cfg) ++#define PORT_GP_22(bank, fn, sfx) PORT_GP_CFG_22(bank, fn, sfx, 0) ++ + #define PORT_GP_CFG_23(bank, fn, sfx, cfg) \ + PORT_GP_CFG_18(bank, fn, sfx, cfg), \ + PORT_GP_CFG_1(bank, 18, fn, sfx, cfg), \ +diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile +index 29b8a4d..2ba6a76 100644 +--- a/drivers/soc/renesas/Makefile ++++ b/drivers/soc/renesas/Makefile +@@ -5,6 +5,7 @@ obj-$(CONFIG_ARCH_RCAR_GEN2) += rcar-rst.o + obj-$(CONFIG_ARCH_R8A7795) += rcar-rst.o + obj-$(CONFIG_ARCH_R8A7796) += rcar-rst.o + obj-$(CONFIG_ARCH_R8A77965) += rcar-rst.o ++obj-$(CONFIG_ARCH_R8A7797) += rcar-rst.o + + obj-$(CONFIG_ARCH_R8A7743) += rcar-sysc.o r8a7743-sysc.o + obj-$(CONFIG_ARCH_R8A7745) += rcar-sysc.o r8a7745-sysc.o +@@ -18,13 +19,16 @@ obj-$(CONFIG_ARCH_R8A7794) += rcar-sysc.o r8a7794-sysc.o + obj-$(CONFIG_ARCH_R8A7795) += rcar-sysc.o r8a7795-sysc.o + obj-$(CONFIG_ARCH_R8A7796) += rcar-sysc.o r8a7796-sysc.o + obj-$(CONFIG_ARCH_R8A77965) += rcar-sysc.o r8a77965-sysc.o ++obj-$(CONFIG_ARCH_R8A7797) += rcar-sysc.o r8a7797-sysc.o + + obj-$(CONFIG_ARCH_R8A7795) += rcar-avs.o + obj-$(CONFIG_ARCH_R8A7796) += rcar-avs.o + obj-$(CONFIG_ARCH_R8A77965) += rcar-avs.o ++obj-$(CONFIG_ARCH_R8A7797) += rcar-avs.o + # EMS for R-Car Gen3 + obj-$(CONFIG_ARCH_R8A7795) += rcar_ems_ctrl.o + obj-$(CONFIG_ARCH_R8A7796) += rcar_ems_ctrl.o + obj-$(CONFIG_ARCH_R8A77965) += rcar_ems_ctrl.o ++obj-$(CONFIG_ARCH_R8A7797) += rcar_ems_ctrl.o + + obj-$(CONFIG_RCAR_DDR_BACKUP) += s2ram_ddr_backup.o +diff --git a/drivers/soc/renesas/r8a7797-sysc.c b/drivers/soc/renesas/r8a7797-sysc.c +new file mode 100644 +index 0000000..cde7d9e +--- /dev/null ++++ b/drivers/soc/renesas/r8a7797-sysc.c +@@ -0,0 +1,39 @@ ++/* ++ * Renesas R-Car V3M System Controller ++ * ++ * Copyright (C) 2016 Glider bvba ++ * ++ * 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; version 2 of the License. ++ */ ++ ++#include ++#include ++ ++#include ++ ++#include "rcar-sysc.h" ++ ++static const struct rcar_sysc_area r8a7797_areas[] __initconst = { ++ { "always-on", 0, 0, R8A7797_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, ++ { "ca53-scu", 0x140, 0, R8A7797_PD_CA53_SCU, R8A7797_PD_ALWAYS_ON, ++ PD_SCU }, ++ { "ca53-cpu0", 0x200, 0, R8A7797_PD_CA53_CPU0, R8A7797_PD_CA53_SCU, ++ PD_CPU_NOCR }, ++ { "ca53-cpu1", 0x200, 1, R8A7797_PD_CA53_CPU1, R8A7797_PD_CA53_SCU, ++ PD_CPU_NOCR }, ++ { "cr7", 0x240, 0, R8A7797_PD_CR7, R8A7797_PD_ALWAYS_ON }, ++ { "a3ir", 0x180, 0, R8A7797_PD_A3IR, R8A7797_PD_ALWAYS_ON }, ++ { "a2ir0", 0x400, 0, R8A7797_PD_A2IR0, R8A7797_PD_A3IR }, ++ { "a2ir1", 0x400, 1, R8A7797_PD_A2IR1, R8A7797_PD_A3IR }, ++ { "a2ir2", 0x400, 2, R8A7797_PD_A2IR2, R8A7797_PD_A3IR }, ++ { "a2ir3", 0x400, 3, R8A7797_PD_A2IR3, R8A7797_PD_A3IR }, ++ { "a2sc0", 0x400, 4, R8A7797_PD_A2SC0, R8A7797_PD_A3IR }, ++ { "a2sc1", 0x400, 5, R8A7797_PD_A2SC1, R8A7797_PD_A3IR }, ++}; ++ ++const struct rcar_sysc_info r8a7797_sysc_info __initconst = { ++ .areas = r8a7797_areas, ++ .num_areas = ARRAY_SIZE(r8a7797_areas), ++}; +diff --git a/drivers/soc/renesas/rcar-rst.c b/drivers/soc/renesas/rcar-rst.c +index 61c2f2c..bc3632b 100644 +--- a/drivers/soc/renesas/rcar-rst.c ++++ b/drivers/soc/renesas/rcar-rst.c +@@ -42,6 +42,7 @@ struct rst_config { + { .compatible = "renesas,r8a7795-rst", .data = &rcar_rst_gen2 }, + { .compatible = "renesas,r8a7796-rst", .data = &rcar_rst_gen2 }, + { .compatible = "renesas,r8a77965-rst", .data = &rcar_rst_gen2 }, ++ { .compatible = "renesas,r8a7797-rst", .data = &rcar_rst_gen2 }, + { /* sentinel */ } + }; + +diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c +index b25c5cf..1d5d440 100644 +--- a/drivers/soc/renesas/rcar-sysc.c ++++ b/drivers/soc/renesas/rcar-sysc.c +@@ -324,6 +324,9 @@ static void __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd) + #ifdef CONFIG_ARCH_R8A77965 + { .compatible = "renesas,r8a77965-sysc", .data = &r8a77965_sysc_info }, + #endif ++#ifdef CONFIG_ARCH_R8A7797 ++ { .compatible = "renesas,r8a7797-sysc", .data = &r8a7797_sysc_info }, ++#endif + { /* sentinel */ } + }; + +diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h +index 04b5d01..1eb4e6d 100644 +--- a/drivers/soc/renesas/rcar-sysc.h ++++ b/drivers/soc/renesas/rcar-sysc.h +@@ -61,4 +61,5 @@ struct rcar_sysc_info { + extern const struct rcar_sysc_info r8a7795_sysc_info; + extern const struct rcar_sysc_info r8a7796_sysc_info; + extern const struct rcar_sysc_info r8a77965_sysc_info; ++extern const struct rcar_sysc_info r8a7797_sysc_info; + #endif /* __SOC_RENESAS_RCAR_SYSC_H__ */ +diff --git a/drivers/soc/renesas/rcar_ems_ctrl.c b/drivers/soc/renesas/rcar_ems_ctrl.c +index ca9af73..388c570 100644 +--- a/drivers/soc/renesas/rcar_ems_ctrl.c ++++ b/drivers/soc/renesas/rcar_ems_ctrl.c +@@ -24,11 +24,17 @@ + #include + #include + #include ++#include + + #include + + #define EMS_THERMAL_ZONE_MAX 10 + ++static const struct soc_device_attribute r8a7797[] = { ++ { .soc_id = "r8a7797" }, ++ { } ++}; ++ + static void rcar_ems_monitor(struct work_struct *ws); + static DECLARE_DELAYED_WORK(rcar_ems_monitor_work, rcar_ems_monitor); + +@@ -268,6 +274,10 @@ static int __init rcar_ems_cpu_shutdown_init(void) + + for_each_online_cpu(cpu) { + tmp_node = of_get_cpu_node(cpu, NULL); ++ if (soc_device_match(r8a7797)) { ++ if (!of_device_is_compatible(tmp_node, "arm,cortex-a53")) ++ continue; ++ } + if (!of_device_is_compatible(tmp_node, "arm,cortex-a57")) + continue; + for (i = 0; i < total_target_cpu; i++) { +diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c +index 1b33c50..63f943d 100644 +--- a/drivers/soc/renesas/renesas-soc.c ++++ b/drivers/soc/renesas/renesas-soc.c +@@ -139,6 +139,11 @@ struct renesas_soc { + .id = 0x55, + }; + ++static const struct renesas_soc soc_rcar_v3m __initconst __maybe_unused = { ++ .family = &fam_rcar_gen3, ++ .id = 0x54, ++}; ++ + static const struct renesas_soc soc_shmobile_ag5 __initconst __maybe_unused = { + .family = &fam_shmobile, + .id = 0x37, +@@ -191,6 +196,9 @@ struct renesas_soc { + #ifdef CONFIG_ARCH_R8A77965 + { .compatible = "renesas,r8a77965", .data = &soc_rcar_m3_n }, + #endif ++#ifdef CONFIG_ARCH_R8A7797 ++ { .compatible = "renesas,r8a7797", .data = &soc_rcar_v3m }, ++#endif + #ifdef CONFIG_ARCH_SH73A0 + { .compatible = "renesas,sh73a0", .data = &soc_shmobile_ag5 }, + #endif +diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c +index 36e70db..a2606fe 100644 +--- a/drivers/spi/spi-sh-msiof.c ++++ b/drivers/spi/spi-sh-msiof.c +@@ -216,7 +216,8 @@ static int msiof_rcar_is_gen3(struct device *dev) + + return of_device_is_compatible(node, "renesas,msiof-r8a7795") || + of_device_is_compatible(node, "renesas,msiof-r8a7796") || +- of_device_is_compatible(node, "renesas,msiof-r8a77965"); ++ of_device_is_compatible(node, "renesas,msiof-r8a77965") || ++ of_device_is_compatible(node, "renesas,msiof-r8a7797"); + } + + static u32 sh_msiof_read(struct sh_msiof_spi_priv *p, int reg_offs) +@@ -1190,6 +1191,7 @@ static int sh_msiof_transfer_one(struct spi_master *master, + { .compatible = "renesas,msiof-r8a7795", .data = &r8a779x_data }, + { .compatible = "renesas,msiof-r8a7796", .data = &r8a779x_data }, + { .compatible = "renesas,msiof-r8a77965", .data = &r8a779x_data }, ++ { .compatible = "renesas,msiof-r8a7797", .data = &r8a779x_data }, + {}, + }; + MODULE_DEVICE_TABLE(of, sh_msiof_match); +diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c +index 6eb7395..a23dd44 100644 +--- a/drivers/thermal/rcar_gen3_thermal.c ++++ b/drivers/thermal/rcar_gen3_thermal.c +@@ -391,6 +391,30 @@ static int rcar_gen3_r8a7795_thermal_init(struct rcar_thermal_priv *priv) + return 0; + } + ++/* @@ transitional */ ++static int rcar_gen3_r8a7797_thermal_init(struct rcar_thermal_priv *priv) ++{ ++#if 0 ++ unsigned long flags; ++ unsigned long reg_val; ++ ++ spin_lock_irqsave(&priv->lock, flags); ++ rcar_thermal_write(priv, REG_GEN3_THCTR, 0x0); ++ udelay(1000); ++ rcar_thermal_write(priv, REG_GEN3_IRQCTL, 0x3F); ++ rcar_thermal_write(priv, REG_GEN3_IRQEN, ++ IRQ_TEMP1_BIT | IRQ_TEMPD2_BIT); ++ rcar_thermal_write(priv, REG_GEN3_THCTR, CTCTL | THCNTSEN(BIT_LEN_12)); ++ reg_val = rcar_thermal_read(priv, REG_GEN3_THCTR); ++ reg_val &= ~CTCTL; ++ reg_val |= THSST; ++ rcar_thermal_write(priv, REG_GEN3_THCTR, reg_val); ++ ++ spin_unlock_irqrestore(&priv->lock, flags); ++#endif ++ return 0; ++} ++ + /* + * Interrupt + */ +@@ -472,10 +496,15 @@ static int rcar_gen3_thermal_remove(struct platform_device *pdev) + .thermal_init = rcar_gen3_r8a7796_thermal_init, + }; + ++static const struct rcar_thermal_data r8a7797_data = { ++ .thermal_init = rcar_gen3_r8a7797_thermal_init, ++}; ++ + static const struct of_device_id rcar_thermal_dt_ids[] = { + { .compatible = "renesas,thermal-r8a7795", .data = &r8a7795_data}, + { .compatible = "renesas,thermal-r8a7796", .data = &r8a7796_data}, + { .compatible = "renesas,thermal-r8a77965", .data = &r8a7796_data}, ++ { .compatible = "renesas,thermal-r8a7797", .data = &r8a7797_data}, + {}, + }; + MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids); +diff --git a/include/dt-bindings/clock/r8a7797-cpg-mssr.h b/include/dt-bindings/clock/r8a7797-cpg-mssr.h +new file mode 100644 +index 0000000..ae6b3af +--- /dev/null ++++ b/include/dt-bindings/clock/r8a7797-cpg-mssr.h +@@ -0,0 +1,48 @@ ++/* ++ * Copyright (C) 2016 Renesas Electronics Corp. ++ * ++ * 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. ++ */ ++#ifndef __DT_BINDINGS_CLOCK_R8A7797_CPG_MSSR_H__ ++#define __DT_BINDINGS_CLOCK_R8A7797_CPG_MSSR_H__ ++ ++#include ++ ++/* r8a7797 CPG Core Clocks */ ++#define R8A7797_CLK_Z2 0 ++#define R8A7797_CLK_ZR 1 ++#define R8A7797_CLK_ZTR 2 ++#define R8A7797_CLK_ZTRD2 3 ++#define R8A7797_CLK_ZT 4 ++#define R8A7797_CLK_ZX 5 ++#define R8A7797_CLK_S1D1 6 ++#define R8A7797_CLK_S1D2 7 ++#define R8A7797_CLK_S1D4 8 ++#define R8A7797_CLK_S2D1 9 ++#define R8A7797_CLK_S2D2 10 ++#define R8A7797_CLK_S2D4 11 ++#define R8A7797_CLK_LB 12 ++#define R8A7797_CLK_CL 13 ++#define R8A7797_CLK_ZB3 14 ++#define R8A7797_CLK_ZB3D2 15 ++#define R8A7797_CLK_DDR 16 ++#define R8A7797_CLK_CR 17 ++#define R8A7797_CLK_CRD2 18 ++#define R8A7797_CLK_SD0H 19 ++#define R8A7797_CLK_SD0 20 ++#define R8A7797_CLK_RPC 21 ++#define R8A7797_CLK_RPCD2 22 ++#define R8A7797_CLK_MSO 23 ++#define R8A7797_CLK_CANFD 24 ++#define R8A7797_CLK_CSI0 25 ++#define R8A7797_CLK_CSIREF 26 ++#define R8A7797_CLK_FRAY 27 ++#define R8A7797_CLK_CP 28 ++#define R8A7797_CLK_CPEX 29 ++#define R8A7797_CLK_R 30 ++#define R8A7797_CLK_OSC 31 ++ ++#endif /* __DT_BINDINGS_CLOCK_R8A7797_CPG_MSSR_H__ */ +diff --git a/include/dt-bindings/power/r8a7797-sysc.h b/include/dt-bindings/power/r8a7797-sysc.h +new file mode 100644 +index 0000000..5aef212 +--- /dev/null ++++ b/include/dt-bindings/power/r8a7797-sysc.h +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (C) 2016 Glider bvba ++ * ++ * 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; version 2 of the License. ++ */ ++#ifndef __DT_BINDINGS_POWER_R8A7797_SYSC_H__ ++#define __DT_BINDINGS_POWER_R8A7797_SYSC_H__ ++ ++/* ++ * These power domain indices match the numbers of the interrupt bits ++ * representing the power areas in the various Interrupt Registers ++ * (e.g. SYSCISR, Interrupt Status Register) ++ */ ++ ++#define R8A7797_PD_CA53_CPU0 5 ++#define R8A7797_PD_CA53_CPU1 6 ++#define R8A7797_PD_CR7 13 ++#define R8A7797_PD_CA53_SCU 21 ++#define R8A7797_PD_A2IR0 23 ++#define R8A7797_PD_A3IR 24 ++#define R8A7797_PD_A2IR1 27 ++#define R8A7797_PD_A2IR2 28 ++#define R8A7797_PD_A2IR3 29 ++#define R8A7797_PD_A2SC0 30 ++#define R8A7797_PD_A2SC1 31 ++ ++/* Always-on power area */ ++#define R8A7797_PD_ALWAYS_ON 32 ++ ++#endif /* __DT_BINDINGS_POWER_R8A7797_SYSC_H__ */ +-- +1.9.1 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0019-Revert-media-v4l2-async-remove-unneeded-.registered_.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0019-Revert-media-v4l2-async-remove-unneeded-.registered_.patch new file mode 100644 index 00000000..d75e56b7 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0019-Revert-media-v4l2-async-remove-unneeded-.registered_.patch @@ -0,0 +1,51 @@ +From f12f0b1d3fdb5acbe1490c0cbf086a7b250e0d12 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Sun, 14 May 2017 15:23:57 +0300 +Subject: [PATCH 014/122] Revert "[media] v4l2-async: remove unneeded + .registered_async callback" + +This reverts commit a53d2f299dc83340c695e153363a2f21641d5f58. +--- + drivers/media/v4l2-core/v4l2-async.c | 4 ++++ + include/media/v4l2-subdev.h | 3 +++ + 2 files changed, 7 insertions(+) + +diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c +index a7c3464..7b6c556 100644 +--- a/drivers/media/v4l2-core/v4l2-async.c ++++ b/drivers/media/v4l2-core/v4l2-async.c +@@ -225,6 +225,10 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier, + /* Move from the global subdevice list to notifier's done */ + list_move(&sd->async_list, ¬ifier->done); + ++ ret = v4l2_subdev_call(sd, core, registered_async); ++ if (ret < 0 && ret != -ENOIOCTLCMD) ++ return ret; ++ + /* + * See if the sub-device has a notifier. If not, return here. + */ +diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h +index ec399c7..c7f2a77 100644 +--- a/include/media/v4l2-subdev.h ++++ b/include/media/v4l2-subdev.h +@@ -184,6 +184,8 @@ struct v4l2_subdev_io_pin_config { + * for it to be warned when the value of a control changes. + * + * @unsubscribe_event: remove event subscription from the control framework. ++ * ++ * @registered_async: the subdevice has been registered async. + */ + struct v4l2_subdev_core_ops { + int (*log_status)(struct v4l2_subdev *sd); +@@ -209,6 +211,7 @@ struct v4l2_subdev_core_ops { + struct v4l2_event_subscription *sub); + int (*unsubscribe_event)(struct v4l2_subdev *sd, struct v4l2_fh *fh, + struct v4l2_event_subscription *sub); ++ int (*registered_async)(struct v4l2_subdev *sd); + }; + + /** +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0020-ti-st-add-device-tree-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0020-ti-st-add-device-tree-support.patch new file mode 100644 index 00000000..4493f7ac --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0020-ti-st-add-device-tree-support.patch @@ -0,0 +1,236 @@ +From b40d2c028af5fd365d8e6352b40264036e1a3dd2 Mon Sep 17 00:00:00 2001 +From: Eyal Reizer +Date: Thu, 23 May 2013 17:11:14 +0300 +Subject: [PATCH 015/122] ti-st: add device tree support + +When using device tree, driver configuration data need to be read from +device node. +Add support for getting the platform data information from the device +tree information stored in the .dtb file in case it exists. + +Change-Id: I74f7f869fc257a057edb9f35c5fd8cbafb810164 +Signed-off-by: Eyal Reizer +Signed-off-by: bvijay +Signed-off-by: Andrey Gusakov +--- + drivers/misc/ti-st/st_kim.c | 92 +++++++++++++++++++++++++++++++++++++++++---- + drivers/misc/ti-st/st_ll.c | 19 +++++++++- + 2 files changed, 102 insertions(+), 9 deletions(-) + +diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c +index dda3ed7..01edf9d 100644 +--- a/drivers/misc/ti-st/st_kim.c ++++ b/drivers/misc/ti-st/st_kim.c +@@ -43,6 +43,9 @@ static struct platform_device *st_kim_devices[MAX_ST_DEVICES]; + /**********************************************************************/ + /* internal functions */ + ++struct ti_st_plat_data *dt_pdata; ++static struct ti_st_plat_data *get_platform_data(struct device *dev); ++ + /** + * st_get_plat_device - + * function which returns the reference to the platform device +@@ -463,7 +466,12 @@ long st_kim_start(void *kim_data) + struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data; + + pr_info(" %s", __func__); +- pdata = kim_gdata->kim_pdev->dev.platform_data; ++ if (kim_gdata->kim_pdev->dev.of_node) { ++ pr_debug("use device tree data"); ++ pdata = dt_pdata; ++ } else { ++ pdata = kim_gdata->kim_pdev->dev.platform_data; ++ } + + do { + /* platform specific enabling code here */ +@@ -523,12 +531,17 @@ long st_kim_stop(void *kim_data) + { + long err = 0; + struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data; +- struct ti_st_plat_data *pdata = +- kim_gdata->kim_pdev->dev.platform_data; ++ struct ti_st_plat_data *pdata; + struct tty_struct *tty = kim_gdata->core_data->tty; + + reinit_completion(&kim_gdata->ldisc_installed); + ++ if (kim_gdata->kim_pdev->dev.of_node) { ++ pr_debug("use device tree data"); ++ pdata = dt_pdata; ++ } else ++ pdata = kim_gdata->kim_pdev->dev.platform_data; ++ + if (tty) { /* can be called before ldisc is installed */ + /* Flush any pending characters in the driver and discipline. */ + tty_ldisc_flush(tty); +@@ -720,13 +733,53 @@ static const struct file_operations list_debugfs_fops = { + * board-*.c file + */ + ++static const struct of_device_id kim_of_match[] = { ++{ ++ .compatible = "kim", ++ }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, kim_of_match); ++ ++static struct ti_st_plat_data *get_platform_data(struct device *dev) ++{ ++ struct device_node *np = dev->of_node; ++ const u32 *dt_property; ++ int len; ++ ++ dt_pdata = kzalloc(sizeof(*dt_pdata), GFP_KERNEL); ++ ++ if (!dt_pdata) ++ pr_err("Can't allocate device_tree platform data\n"); ++ ++ dt_property = of_get_property(np, "dev_name", &len); ++ if (dt_property) ++ memcpy(&dt_pdata->dev_name, dt_property, len); ++ of_property_read_u32(np, "nshutdown_gpio", ++ (u32 *)&dt_pdata->nshutdown_gpio); ++ of_property_read_u32(np, "flow_cntrl", (u32 *)&dt_pdata->flow_cntrl); ++ of_property_read_u32(np, "baud_rate", (u32 *)&dt_pdata->baud_rate); ++ ++ return dt_pdata; ++} ++ + static struct dentry *kim_debugfs_dir; + static int kim_probe(struct platform_device *pdev) + { + struct kim_data_s *kim_gdata; +- struct ti_st_plat_data *pdata = pdev->dev.platform_data; ++ struct ti_st_plat_data *pdata; + int err; + ++ if (pdev->dev.of_node) ++ pdata = get_platform_data(&pdev->dev); ++ else ++ pdata = pdev->dev.platform_data; ++ ++ if (pdata == NULL) { ++ dev_err(&pdev->dev, "Platform Data is missing\n"); ++ return -ENXIO; ++ } ++ + if ((pdev->id != -1) && (pdev->id < MAX_ST_DEVICES)) { + /* multiple devices could exist */ + st_kim_devices[pdev->id] = pdev; +@@ -807,9 +860,16 @@ static int kim_probe(struct platform_device *pdev) + static int kim_remove(struct platform_device *pdev) + { + /* free the GPIOs requested */ +- struct ti_st_plat_data *pdata = pdev->dev.platform_data; ++ struct ti_st_plat_data *pdata; + struct kim_data_s *kim_gdata; + ++ if (pdev->dev.of_node) { ++ pr_debug("use device tree data"); ++ pdata = dt_pdata; ++ } else { ++ pdata = pdev->dev.platform_data; ++ } ++ + kim_gdata = platform_get_drvdata(pdev); + + /* Free the Bluetooth/FM/GPIO +@@ -827,12 +887,22 @@ static int kim_remove(struct platform_device *pdev) + + kfree(kim_gdata); + kim_gdata = NULL; ++ kfree(dt_pdata); ++ dt_pdata = NULL; ++ + return 0; + } + + static int kim_suspend(struct platform_device *pdev, pm_message_t state) + { +- struct ti_st_plat_data *pdata = pdev->dev.platform_data; ++ struct ti_st_plat_data *pdata; ++ ++ if (pdev->dev.of_node) { ++ pr_debug("use device tree data"); ++ pdata = dt_pdata; ++ } else { ++ pdata = pdev->dev.platform_data; ++ } + + if (pdata->suspend) + return pdata->suspend(pdev, state); +@@ -842,7 +912,14 @@ static int kim_suspend(struct platform_device *pdev, pm_message_t state) + + static int kim_resume(struct platform_device *pdev) + { +- struct ti_st_plat_data *pdata = pdev->dev.platform_data; ++ struct ti_st_plat_data *pdata; ++ ++ if (pdev->dev.of_node) { ++ pr_debug("use device tree data"); ++ pdata = dt_pdata; ++ } else { ++ pdata = pdev->dev.platform_data; ++ } + + if (pdata->resume) + return pdata->resume(pdev); +@@ -859,6 +936,7 @@ static struct platform_driver kim_platform_driver = { + .resume = kim_resume, + .driver = { + .name = "kim", ++ .of_match_table = of_match_ptr(kim_of_match), + }, + }; + +diff --git a/drivers/misc/ti-st/st_ll.c b/drivers/misc/ti-st/st_ll.c +index 93b4d67..644f00e 100644 +--- a/drivers/misc/ti-st/st_ll.c ++++ b/drivers/misc/ti-st/st_ll.c +@@ -25,7 +25,10 @@ + #include + #include + ++extern struct ti_st_plat_data *dt_pdata; ++ + /**********************************************************************/ ++ + /* internal functions */ + static void send_ll_cmd(struct st_data_s *st_data, + unsigned char cmd) +@@ -53,7 +56,13 @@ static void ll_device_want_to_sleep(struct st_data_s *st_data) + + /* communicate to platform about chip asleep */ + kim_data = st_data->kim_data; +- pdata = kim_data->kim_pdev->dev.platform_data; ++ if (kim_data->kim_pdev->dev.of_node) { ++ pr_debug("use device tree data"); ++ pdata = dt_pdata; ++ } else { ++ pdata = kim_data->kim_pdev->dev.platform_data; ++ } ++ + if (pdata->chip_asleep) + pdata->chip_asleep(NULL); + } +@@ -86,7 +95,13 @@ static void ll_device_want_to_wakeup(struct st_data_s *st_data) + + /* communicate to platform about chip wakeup */ + kim_data = st_data->kim_data; +- pdata = kim_data->kim_pdev->dev.platform_data; ++ if (kim_data->kim_pdev->dev.of_node) { ++ pr_debug("use device tree data"); ++ pdata = dt_pdata; ++ } else { ++ pdata = kim_data->kim_pdev->dev.platform_data; ++ } ++ + if (pdata->chip_awake) + pdata->chip_awake(NULL); + } +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0021-btwilink-add-minimal-device-tree-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0021-btwilink-add-minimal-device-tree-support.patch new file mode 100644 index 00000000..0d79c3b6 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0021-btwilink-add-minimal-device-tree-support.patch @@ -0,0 +1,54 @@ +From e1a68682ff98b44c9614dad8e21d2bd12d8038d8 Mon Sep 17 00:00:00 2001 +From: Eyal Reizer +Date: Thu, 23 May 2013 17:15:21 +0300 +Subject: [PATCH 016/122] btwilink: add minimal device tree support + +Add minimal device tree support to the btwilink driver that is used +for binding bluetooth with the ti-st shared transport driver. + +Change-Id: I301c49d29046f20f8868bebb14347e82c12c8140 +Signed-off-by: Eyal Reizer +Signed-off-by: bvijay +Signed-off-by: Andrey Gusakov +--- + drivers/bluetooth/btwilink.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/bluetooth/btwilink.c b/drivers/bluetooth/btwilink.c +index 5ef8000..9f053f2 100644 +--- a/drivers/bluetooth/btwilink.c ++++ b/drivers/bluetooth/btwilink.c +@@ -30,6 +30,7 @@ + + #include + #include ++#include + + /* Bluetooth Driver Version */ + #define VERSION "1.0" +@@ -274,6 +275,14 @@ static int ti_st_send_frame(struct hci_dev *hdev, struct sk_buff *skb) + return 0; + } + ++static const struct of_device_id btwilink_of_match[] = { ++{ ++ .compatible = "btwilink", ++ }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, btwilink_of_match); ++ + static int bt_ti_probe(struct platform_device *pdev) + { + struct ti_st *hst; +@@ -337,6 +346,7 @@ static struct platform_driver btwilink_driver = { + .remove = bt_ti_remove, + .driver = { + .name = "btwilink", ++ .of_match_table = of_match_ptr(btwilink_of_match), + }, + }; + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0022-ASoC-Modify-check-condition-of-multiple-bindings-of-.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0022-ASoC-Modify-check-condition-of-multiple-bindings-of-.patch new file mode 100644 index 00000000..282a4eb6 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0022-ASoC-Modify-check-condition-of-multiple-bindings-of-.patch @@ -0,0 +1,49 @@ +From e27c2e3bb765958c217e46429776a0386c5b089f Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Tue, 13 Dec 2016 18:08:39 +0300 +Subject: [PATCH 017/122] ASoC: Modify check condition of multiple bindings of + components + +https://patchwork.kernel.org/patch/7385501/ +...and some more hacks to bind one component (with several DAIs) +to more than one sound card. + +KF has 4 sound cards (pcm3168a, ak4613, radio, wl18xx) and just one +compinent ec500000.sound that can not be bound to all 4 cards. +This is a lack of current implementation of sound/soc/sh/rcar/* ASoC stack +The ec500000.sound resources (PCM/DMA, dais) needs to be shared between +all 4 sound cards if we want all cards work runtime. +Or we have to enable only one of them in dts file as it is designed. + +Signed-off-by: Andrey Gusakov +--- + sound/soc/soc-core.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c +index 8771405..0ec3674 100644 +--- a/sound/soc/soc-core.c ++++ b/sound/soc/soc-core.c +@@ -1516,7 +1516,8 @@ static int soc_probe_component(struct snd_soc_card *card, + return 0; + + if (component->card) { +- if (component->card != card) { ++ if (component->card != card && ++ component->registered_as_component) { + dev_err(component->dev, + "Trying to bind component to card \"%s\" but is already bound to card \"%s\"\n", + card->name, component->card->name); +@@ -3471,7 +3472,8 @@ int snd_soc_add_component(struct device *dev, + goto err_free; + + component->ignore_pmdown_time = true; +- component->registered_as_component = true; ++ if (num_dai == 1) ++ component->registered_as_component = true; + + if (component_driver->endianness) { + for (i = 0; i < num_dai; i++) { +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0023-ASoC-add-dummy-Si468x-driver.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0023-ASoC-add-dummy-Si468x-driver.patch new file mode 100644 index 00000000..17111d96 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0023-ASoC-add-dummy-Si468x-driver.patch @@ -0,0 +1,122 @@ +From e4ed26d4d88b11516307ca0369c7f5f213bd3811 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Tue, 13 Dec 2016 18:07:13 +0300 +Subject: [PATCH 018/122] ASoC: add dummy Si468x driver + +Signed-off-by: Andrey Gusakov +--- + sound/soc/codecs/Kconfig | 3 +++ + sound/soc/codecs/Makefile | 2 ++ + sound/soc/codecs/si468x.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 71 insertions(+) + create mode 100644 sound/soc/codecs/si468x.c + +diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig +index c367d11..8d52af2 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -679,6 +679,9 @@ config SND_SOC_PCM3168A_SPI + select SND_SOC_PCM3168A + select REGMAP_SPI + ++config SND_SOC_SI468X ++ tristate "Dummy sound driver for Si468x radio" ++ + config SND_SOC_PCM5102A + tristate + +diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile +index 05018b7..79b4386 100644 +--- a/sound/soc/codecs/Makefile ++++ b/sound/soc/codecs/Makefile +@@ -139,6 +139,7 @@ snd-soc-sigmadsp-objs := sigmadsp.o + snd-soc-sigmadsp-i2c-objs := sigmadsp-i2c.o + snd-soc-sigmadsp-regmap-objs := sigmadsp-regmap.o + snd-soc-si476x-objs := si476x.o ++snd-soc-si468x-objs := si468x.o + snd-soc-sirf-audio-codec-objs := sirf-audio-codec.o + snd-soc-sn95031-objs := sn95031.o + snd-soc-spdif-tx-objs := spdif_transmitter.o +@@ -377,6 +378,7 @@ obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o + obj-$(CONFIG_SND_SOC_SIGMADSP_I2C) += snd-soc-sigmadsp-i2c.o + obj-$(CONFIG_SND_SOC_SIGMADSP_REGMAP) += snd-soc-sigmadsp-regmap.o + obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o ++obj-$(CONFIG_SND_SOC_SI468X) += snd-soc-si468x.o + obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o + obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o + obj-$(CONFIG_SND_SOC_SIRF_AUDIO_CODEC) += sirf-audio-codec.o +diff --git a/sound/soc/codecs/si468x.c b/sound/soc/codecs/si468x.c +new file mode 100644 +index 0000000..18b099f +--- /dev/null ++++ b/sound/soc/codecs/si468x.c +@@ -0,0 +1,66 @@ ++/* ++ * Dummy sound driver for Si468x DAB/FM/AM chips ++ * Copyright 2016 Andrey Gusakov ++ * ++ * Based on: Driver for the DFBM-CS320 bluetooth module ++ * Copyright 2011 Lars-Peter Clausen ++ * ++ * 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 ++#include ++#include ++ ++#include ++ ++static struct snd_soc_dai_driver si468x_dai = { ++ .name = "si468x-pcm", ++ .capture = { ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = SNDRV_PCM_RATE_48000, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE, ++ }, ++}; ++ ++static struct snd_soc_codec_driver soc_codec_dev_si468x; ++ ++static int si468x_probe(struct platform_device *pdev) ++{ ++ return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_si468x, ++ &si468x_dai, 1); ++} ++ ++static int si468x_remove(struct platform_device *pdev) ++{ ++ snd_soc_unregister_codec(&pdev->dev); ++ ++ return 0; ++} ++ ++static const struct of_device_id si468x_of_match[] = { ++ { .compatible = "si,si468x-pcm", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, si468x_of_match); ++ ++static struct platform_driver si468x_driver = { ++ .driver = { ++ .name = "si468x", ++ .of_match_table = si468x_of_match, ++ .owner = THIS_MODULE, ++ }, ++ .probe = si468x_probe, ++ .remove = si468x_remove, ++}; ++ ++module_platform_driver(si468x_driver); ++ ++MODULE_AUTHOR("Andrey Gusakov "); ++MODULE_DESCRIPTION("ASoC Si468x radio chip driver"); ++MODULE_LICENSE("GPL"); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0024-wl18xx-do-not-invert-IRQ-on-WLxxxx-side.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0024-wl18xx-do-not-invert-IRQ-on-WLxxxx-side.patch new file mode 100644 index 00000000..0b2c1fc7 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0024-wl18xx-do-not-invert-IRQ-on-WLxxxx-side.patch @@ -0,0 +1,47 @@ +From df629d74744e453f2d72f412698befb20bf56f73 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Mon, 22 May 2017 17:22:38 +0300 +Subject: [PATCH 019/122] wl18xx: do not invert IRQ on WLxxxx side + +Signed-off-by: Andrey Gusakov +--- + drivers/net/wireless/ti/wl18xx/main.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c +index 0cf3b40..b1c4cdb 100644 +--- a/drivers/net/wireless/ti/wl18xx/main.c ++++ b/drivers/net/wireless/ti/wl18xx/main.c +@@ -878,7 +878,9 @@ static int wl18xx_pre_upload(struct wl1271 *wl) + { + u32 tmp; + int ret; ++#if 0 + u16 irq_invert; ++#endif + + BUILD_BUG_ON(sizeof(struct wl18xx_mac_and_phy_params) > + WL18XX_PHY_INIT_MEM_SIZE); +@@ -931,6 +933,11 @@ static int wl18xx_pre_upload(struct wl1271 *wl) + if (ret < 0) + goto out; + ++#if 0 ++ /* We have level translator with inversion on IRQ line so we ++ * set IRQ_TYPE_EDGE_FALLING in DTS, but we do not need to ++ * invert IRQ logic on WLxxxx side! ++ */ + ret = irq_get_trigger_type(wl->irq); + if ((ret == IRQ_TYPE_LEVEL_LOW) || (ret == IRQ_TYPE_EDGE_FALLING)) { + wl1271_info("using inverted interrupt logic: %d", ret); +@@ -950,6 +957,7 @@ static int wl18xx_pre_upload(struct wl1271 *wl) + + ret = wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]); + } ++#endif + + out: + return ret; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0025-drm-adv7511-Enable-HPD-interrupts-to-support-hotplug.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0025-drm-adv7511-Enable-HPD-interrupts-to-support-hotplug.patch new file mode 100644 index 00000000..f4dfb8fa --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0025-drm-adv7511-Enable-HPD-interrupts-to-support-hotplug.patch @@ -0,0 +1,29 @@ +From 1bb61bdd98bc8980abd6359d5a839af3f4d75a2f Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Tue, 30 May 2017 17:41:21 +0300 +Subject: [PATCH 020/122] drm: adv7511: Enable HPD interrupts to support + hotplug + +This patch enables HPD (hot plug detect) interrupt support + +Signed-off-by: Andrey Gusakov +--- + drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +index dbc4642..69f605b 100644 +--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c ++++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +@@ -27,7 +27,7 @@ static const struct reg_sequence adv7511_fixed_registers[] = { + { 0x98, 0x03 }, + { 0x9a, 0xe0 }, + { 0x9c, 0x30 }, +- { 0x9d, 0x61 }, ++ { 0x9d, 0x01 }, + { 0xa2, 0xa4 }, + { 0xa3, 0xa4 }, + { 0xe0, 0xd0 }, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0026-drm-adv7511-add-polling-mode-when-no-irq-available.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0026-drm-adv7511-add-polling-mode-when-no-irq-available.patch new file mode 100644 index 00000000..3adfa21d --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0026-drm-adv7511-add-polling-mode-when-no-irq-available.patch @@ -0,0 +1,30 @@ +From 06473f51a6aa077cd56745bd14d114ff3269fe19 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Tue, 30 May 2017 18:42:09 +0300 +Subject: [PATCH] drm: adv7511: add polling mode (when no irq available) + +Signed-off-by: Andrey Gusakov +--- + drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +index a104b43b56a0..8be1baca05d0 100644 +--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c ++++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +@@ -838,7 +838,11 @@ static int adv7511_bridge_attach(struct drm_bridge *bridge) + return -ENODEV; + } + +- adv->connector.polled = DRM_CONNECTOR_POLL_HPD; ++ if (adv->i2c_main->irq) ++ adv->connector.polled = DRM_CONNECTOR_POLL_HPD; ++ else ++ adv->connector.polled = DRM_CONNECTOR_POLL_CONNECT | ++ DRM_CONNECTOR_POLL_DISCONNECT; + + ret = drm_connector_init(bridge->dev, &adv->connector, + &adv7511_connector_funcs, +-- +2.13.0 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0027-gpu-drm-bridge-adv7511-Add-interlaced-mode-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0027-gpu-drm-bridge-adv7511-Add-interlaced-mode-support.patch new file mode 100644 index 00000000..01983096 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0027-gpu-drm-bridge-adv7511-Add-interlaced-mode-support.patch @@ -0,0 +1,44 @@ +From bf8408f6e06e4d6e80940d0c8e08f7e8da330de7 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Wed, 21 Mar 2018 20:48:02 +0300 +Subject: [PATCH 021/122] gpu: drm: bridge: adv7511: Add interlaced mode + support + +This adds "interlace-allowed" DTS property +that allows interlaced mode support when set. + +Signed-off-by: Valentine Barshak +--- + Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt | 1 + + drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 3 +++ + 2 files changed, 4 insertions(+) + +diff --git a/Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt b/Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt +index 06668bc..e0a2360 100644 +--- a/Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt ++++ b/Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt +@@ -60,6 +60,7 @@ Optional properties: + - interrupts: Specifier for the ADV7511 interrupt + - pd-gpios: Specifier for the GPIO connected to the power down signal + ++- interlace-allowed - Allows interlaced modes when set. + - adi,clock-delay: Video data clock delay relative to the pixel clock, in ps + (-1200 ps .. 1600 ps). Defaults to no delay. + - adi,embedded-sync: The input uses synchronization signals embedded in the +diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +index 69f605b..808021f 100644 +--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c ++++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +@@ -863,6 +863,9 @@ static int adv7511_bridge_attach(struct drm_bridge *bridge) + adv->connector.polled = DRM_CONNECTOR_POLL_CONNECT | + DRM_CONNECTOR_POLL_DISCONNECT; + ++ adv->connector.interlace_allowed = ++ of_property_read_bool(bridge->of_node, "interlace-allowed"); ++ + ret = drm_connector_init(bridge->dev, &adv->connector, + &adv7511_connector_funcs, + DRM_MODE_CONNECTOR_HDMIA); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0030-Gen3-LVDS-cameras.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0030-Gen3-LVDS-cameras.patch new file mode 100644 index 00000000..3a3026b5 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0030-Gen3-LVDS-cameras.patch @@ -0,0 +1,11563 @@ +From ea57c63245c9f3e05b0981ac5ee621f37e52dc35 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Sun, 14 May 2017 15:20:01 +0300 +Subject: [PATCH 022/122] Gen3: LVDS cameras + +This add Gen3 LVDS cameras support: +- deserializers: MAX9286, DS90UB954/960/964 +- cameras: ov10635, ov490+ov10640, ov495+OV2775, ar0132, ar0220, + ap0101+ar014x, ov2775 + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/Kconfig | 18 + + drivers/media/i2c/soc_camera/Makefile | 4 + + drivers/media/i2c/soc_camera/ap0101_ar014x.c | 589 +++++++ + drivers/media/i2c/soc_camera/ap0101_ar014x.h | 28 + + drivers/media/i2c/soc_camera/ar0132.c | 566 +++++++ + drivers/media/i2c/soc_camera/ar0132.h | 213 +++ + drivers/media/i2c/soc_camera/ar0220.c | 532 +++++++ + drivers/media/i2c/soc_camera/ar0220.h | 43 + + drivers/media/i2c/soc_camera/max9286.c | 694 ++++++++ + drivers/media/i2c/soc_camera/max9286.h | 244 +++ + drivers/media/i2c/soc_camera/ov10635.c | 760 +++++++++ + drivers/media/i2c/soc_camera/ov10635.h | 1139 +++++++++++++ + drivers/media/i2c/soc_camera/ov10635_debug.h | 54 + + drivers/media/i2c/soc_camera/ov106xx.c | 139 ++ + drivers/media/i2c/soc_camera/ov2775.c | 528 +++++++ + drivers/media/i2c/soc_camera/ov2775.h | 1841 ++++++++++++++++++++++ + drivers/media/i2c/soc_camera/ov490_ov10640.c | 1134 +++++++++++++ + drivers/media/i2c/soc_camera/ov490_ov10640.h | 102 ++ + drivers/media/i2c/soc_camera/ov495_ov2775.c | 640 ++++++++ + drivers/media/i2c/soc_camera/ov495_ov2775.h | 23 + + drivers/media/i2c/soc_camera/ti9x4.c | 520 ++++++ + drivers/media/i2c/soc_camera/ti9x4.h | 156 ++ + drivers/media/platform/soc_camera/rcar_csi2.c | 330 ++-- + drivers/media/platform/soc_camera/rcar_vin.c | 309 +++- + drivers/media/platform/soc_camera/soc_camera.c | 17 +- + drivers/media/platform/soc_camera/soc_mediabus.c | 16 + + drivers/media/v4l2-core/v4l2-async.c | 2 + + include/media/drv-intf/soc_mediabus.h | 3 + + include/media/soc_camera.h | 1 + + 29 files changed, 10512 insertions(+), 133 deletions(-) + create mode 100644 drivers/media/i2c/soc_camera/ap0101_ar014x.c + create mode 100644 drivers/media/i2c/soc_camera/ap0101_ar014x.h + create mode 100644 drivers/media/i2c/soc_camera/ar0132.c + create mode 100644 drivers/media/i2c/soc_camera/ar0132.h + create mode 100644 drivers/media/i2c/soc_camera/ar0220.c + create mode 100644 drivers/media/i2c/soc_camera/ar0220.h + create mode 100644 drivers/media/i2c/soc_camera/max9286.c + create mode 100644 drivers/media/i2c/soc_camera/max9286.h + create mode 100644 drivers/media/i2c/soc_camera/ov10635.c + create mode 100644 drivers/media/i2c/soc_camera/ov10635.h + create mode 100644 drivers/media/i2c/soc_camera/ov10635_debug.h + create mode 100644 drivers/media/i2c/soc_camera/ov106xx.c + create mode 100644 drivers/media/i2c/soc_camera/ov2775.c + create mode 100644 drivers/media/i2c/soc_camera/ov2775.h + create mode 100644 drivers/media/i2c/soc_camera/ov490_ov10640.c + create mode 100644 drivers/media/i2c/soc_camera/ov490_ov10640.h + create mode 100644 drivers/media/i2c/soc_camera/ov495_ov2775.c + create mode 100644 drivers/media/i2c/soc_camera/ov495_ov2775.h + create mode 100644 drivers/media/i2c/soc_camera/ti9x4.c + create mode 100644 drivers/media/i2c/soc_camera/ti9x4.h + +diff --git a/drivers/media/i2c/soc_camera/Kconfig b/drivers/media/i2c/soc_camera/Kconfig +index 72b3698..d30a3f9 100644 +--- a/drivers/media/i2c/soc_camera/Kconfig ++++ b/drivers/media/i2c/soc_camera/Kconfig +@@ -76,3 +76,21 @@ config SOC_CAMERA_TW9910 + depends on SOC_CAMERA && I2C + help + This is a tw9910 video driver ++ ++config SOC_CAMERA_MAX9286 ++ tristate "max9286 GMSL support" ++ depends on SOC_CAMERA && I2C ++ help ++ This is a MAXIM max9286 GMSL driver ++ ++config SOC_CAMERA_TI9X4 ++ tristate "ti9x4 FPDLink3 support" ++ depends on SOC_CAMERA && I2C ++ help ++ This is an Texas Instruments ti9X4 FPDLink3 driver ++ ++config SOC_CAMERA_OV106XX ++ tristate "ov106xx camera support" ++ depends on SOC_CAMERA && I2C ++ help ++ This is a runtime detected GMSL/FPDLink3 sensors driver +diff --git a/drivers/media/i2c/soc_camera/Makefile b/drivers/media/i2c/soc_camera/Makefile +index faa2df8..1134c03 100644 +--- a/drivers/media/i2c/soc_camera/Makefile ++++ b/drivers/media/i2c/soc_camera/Makefile +@@ -10,3 +10,7 @@ obj-$(CONFIG_SOC_CAMERA_OV9640) += ov9640.o + obj-$(CONFIG_SOC_CAMERA_OV9740) += ov9740.o + obj-$(CONFIG_SOC_CAMERA_RJ54N1) += rj54n1cb0c.o + obj-$(CONFIG_SOC_CAMERA_TW9910) += tw9910.o ++obj-$(CONFIG_SOC_CAMERA_MAX9286) += max9286.o ++obj-$(CONFIG_SOC_CAMERA_TI9X4) += ti9x4.o ++obj-$(CONFIG_SOC_CAMERA_OV106XX) += ov106xx.o ++ +diff --git a/drivers/media/i2c/soc_camera/ap0101_ar014x.c b/drivers/media/i2c/soc_camera/ap0101_ar014x.c +new file mode 100644 +index 0000000..cae0b19 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ap0101_ar014x.c +@@ -0,0 +1,589 @@ ++/* ++ * ON Semiconductor AP0101-AR014X sensor camera driver ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "ap0101_ar014x.h" ++ ++#define AP0101_I2C_ADDR 0x5d ++ ++#define AP0101_PID 0x0000 ++#define AP0101_VERSION_REG 0x0160 ++ ++#define AP0101_MEDIA_BUS_FMT MEDIA_BUS_FMT_YUYV8_2X8 ++ ++static void ap0101_otp_id_read(struct i2c_client *client); ++ ++struct ap0101_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int init_complete; ++ u8 id[6]; ++ int exposure; ++ int gain; ++ int autogain; ++ /* serializers */ ++ int max9286_addr; ++ int max9271_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++}; ++ ++static inline struct ap0101_priv *to_ap0101(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct ap0101_priv, sd); ++} ++ ++static void ap0101_s_port(struct i2c_client *client, int fwd_en) ++{ ++ struct ap0101_priv *priv = to_ap0101(client); ++ int tmp_addr; ++ ++ if (priv->max9286_addr) { ++ tmp_addr = client->addr; ++ client->addr = priv->max9286_addr; /* Deserializer I2C address */ ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ client->addr = tmp_addr; ++ }; ++} ++ ++static int ap0101_set_regs(struct i2c_client *client, ++ const struct ap0101_reg *regs, int nr_regs) ++{ ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (regs[i].reg == AP0101_DELAY) { ++ mdelay(regs[i].val); ++ continue; ++ } ++ ++ reg16_write16(client, regs[i].reg, regs[i].val); ++ } ++ ++ return 0; ++} ++ ++static u16 ap0101_ar014x_read(struct i2c_client *client, u16 addr) ++{ ++ u16 reg_val = 0; ++ ++ reg16_write16(client, 0x0040, 0x8d00); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write16(client, 0xfc00, addr); ++ reg16_write16(client, 0xfc02, 0x0200); /* 2 bytes */ ++ reg16_write16(client, 0x0040, 0x8d05); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write16(client, 0x0040, 0x8d08); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_read16(client, 0xfc00, ®_val); ++ reg16_write16(client, 0x0040, 0x8d02); ++ usleep_range(100, 150); /* wait 100 us */ ++ ++ return reg_val; ++} ++ ++static void ap0101_ar014x_write(struct i2c_client *client, u16 addr, u16 val) ++{ ++ reg16_write16(client, 0x0040, 0x8d00); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write16(client, 0xfc00, addr); ++ reg16_write16(client, 0xfc02, 0x0200 | (val >> 8)); /* 2 bytes */ ++ reg16_write16(client, 0xfc04, (val & 0xff) << 8); ++ reg16_write16(client, 0x0040, 0x8d06); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write16(client, 0x0040, 0x8d08); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write16(client, 0x0040, 0x8d02); ++ usleep_range(100, 150); /* wait 100 us */ ++} ++ ++static int ap0101_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int ap0101_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ap0101_priv *priv = to_ap0101(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = AP0101_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int ap0101_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = AP0101_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int ap0101_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = AP0101_MEDIA_BUS_FMT; ++ ++ return 0; ++} ++ ++static int ap0101_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ap0101_priv *priv = to_ap0101(client); ++ ++ ap0101_otp_id_read(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = AP0101_VERSION_REG >> 8; ++ edid->edid[9] = AP0101_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int ap0101_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ap0101_priv *priv = to_ap0101(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > AP0101_MAX_WIDTH) || ++ (rect->top + rect->height > AP0101_MAX_HEIGHT)) ++ *rect = priv->rect; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ return 0; ++} ++ ++static int ap0101_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ap0101_priv *priv = to_ap0101(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = AP0101_MAX_WIDTH; ++ sel->r.height = AP0101_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = AP0101_MAX_WIDTH; ++ sel->r.height = AP0101_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ap0101_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int ap0101_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u16 val = 0; ++ ++ ret = reg16_read16(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int ap0101_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return reg16_write16(client, (u16)reg->reg, (u16)reg->val); ++} ++#endif ++ ++static struct v4l2_subdev_core_ops ap0101_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ap0101_g_register, ++ .s_register = ap0101_s_register, ++#endif ++}; ++ ++static int ap0101_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ap0101_priv *priv = to_ap0101(client); ++ int ret = -EINVAL; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ case V4L2_CID_CONTRAST: ++ case V4L2_CID_SATURATION: ++ case V4L2_CID_HUE: ++ case V4L2_CID_GAMMA: ++ case V4L2_CID_SHARPNESS: ++ case V4L2_CID_AUTOGAIN: ++ case V4L2_CID_GAIN: ++ case V4L2_CID_EXPOSURE: ++ case V4L2_CID_HFLIP: ++ case V4L2_CID_VFLIP: ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ap0101_ctrl_ops = { ++ .s_ctrl = ap0101_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops ap0101_video_ops = { ++ .s_stream = ap0101_s_stream, ++ .g_mbus_config = ap0101_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops ap0101_subdev_pad_ops = { ++ .get_edid = ap0101_get_edid, ++ .enum_mbus_code = ap0101_enum_mbus_code, ++ .get_selection = ap0101_get_selection, ++ .set_selection = ap0101_set_selection, ++ .get_fmt = ap0101_get_fmt, ++ .set_fmt = ap0101_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops ap0101_subdev_ops = { ++ .core = &ap0101_core_ops, ++ .video = &ap0101_video_ops, ++ .pad = &ap0101_subdev_pad_ops, ++}; ++ ++static void ap0101_otp_id_read(struct i2c_client *client) ++{ ++ struct ap0101_priv *priv = to_ap0101(client); ++ int i; ++ ++ /* read camera id from ar014x OTP memory */ ++ ap0101_ar014x_write(client, 0x3054, 0x400); ++ ap0101_ar014x_write(client, 0x304a, 0x110); ++ usleep_range(25000, 25500); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i += 2) { ++ /* first 4 bytes are equal on all ar014x */ ++ priv->id[i] = ap0101_ar014x_read(client, 0x3800 + i + 4) >> 8; ++ priv->id[i + 1] = ap0101_ar014x_read(client, 0x3800 + i + 4) & 0xff; ++ } ++} ++ ++static ssize_t ap0101_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ap0101_priv *priv = to_ap0101(client); ++ ++ ap0101_otp_id_read(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_ap0101, S_IRUGO, ap0101_otp_id_show, NULL); ++ ++static int ap0101_initialize(struct i2c_client *client) ++{ ++ struct ap0101_priv *priv = to_ap0101(client); ++ u16 pid = 0; ++ int ret = 0; ++ ++ ap0101_s_port(client, 1); ++ ++ /* check and show model ID */ ++ reg16_read16(client, AP0101_PID, &pid); ++ ++ if (pid != AP0101_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x\n", pid); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ /* Program wizard registers */ ++ ap0101_set_regs(client, ap0101_regs_wizard, ARRAY_SIZE(ap0101_regs_wizard)); ++ /* Read OTP IDs */ ++ ap0101_otp_id_read(client); ++ ++ dev_info(&client->dev, "ap0101 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, AP0101_MAX_WIDTH, AP0101_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ ap0101_s_port(client, 0); ++ ++ return ret; ++} ++ ++static int ap0101_parse_dt(struct device_node *np, struct ap0101_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ if (!priv->max9286_addr) { ++ dev_err(&client->dev, "deserializer does not present for AP0101\n"); ++ return -EINVAL; ++ } ++ ++ ap0101_s_port(client, 1); ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ ++ reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x0A, AP0101_I2C_ADDR << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ client->addr = tmp_addr; ++ ++ mdelay(10); ++ ++ return 0; ++} ++ ++static int ap0101_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ap0101_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &ap0101_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ priv->exposure = 0x100; ++ priv->gain = 0x100; ++ priv->autogain = 1; ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &ap0101_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ap0101_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ap0101_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &ap0101_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &ap0101_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ap0101_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &ap0101_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); ++ v4l2_ctrl_new_std(&priv->hdl, &ap0101_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); ++ v4l2_ctrl_new_std(&priv->hdl, &ap0101_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure); ++ v4l2_ctrl_new_std(&priv->hdl, &ap0101_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &ap0101_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = ap0101_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = ap0101_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = AP0101_MAX_WIDTH; ++ priv->rect.height = AP0101_MAX_HEIGHT; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ap0101) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_AP0101 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int ap0101_remove(struct i2c_client *client) ++{ ++ struct ap0101_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ap0101); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_AP0101 ++static const struct i2c_device_id ap0101_id[] = { ++ { "ap0101", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ap0101_id); ++ ++static const struct of_device_id ap0101_of_ids[] = { ++ { .compatible = "aptina,ap0101", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ap0101_of_ids); ++ ++static struct i2c_driver ap0101_i2c_driver = { ++ .driver = { ++ .name = "ap0101", ++ .of_match_table = ap0101_of_ids, ++ }, ++ .probe = ap0101_probe, ++ .remove = ap0101_remove, ++ .id_table = ap0101_id, ++}; ++ ++module_i2c_driver(ap0101_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for AP0101"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/ap0101_ar014x.h b/drivers/media/i2c/soc_camera/ap0101_ar014x.h +new file mode 100644 +index 0000000..16599a1 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ap0101_ar014x.h +@@ -0,0 +1,28 @@ ++/* ++ * ON Semiconductor ap0101-ar014x sensor camera wizard 1280x720@30/UYVY/BT601/8bit ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++#define AP0101_MAX_WIDTH 1280 ++#define AP0101_MAX_HEIGHT 720 ++ ++#define AP0101_DELAY 0xffff ++ ++struct ap0101_reg { ++ u16 reg; ++ u16 val; ++}; ++ ++static const struct ap0101_reg ap0101_regs_wizard[] = { ++/* enable FSIN */ ++{0xc88c, 0x0303}, ++{0xfc00, 0x2800}, ++{0x0040, 0x8100}, ++{AP0101_DELAY, 100}, ++}; +diff --git a/drivers/media/i2c/soc_camera/ar0132.c b/drivers/media/i2c/soc_camera/ar0132.c +new file mode 100644 +index 0000000..a7ee868 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0132.c +@@ -0,0 +1,566 @@ ++/* ++ * ON Semiconductor AR0132 sensor camera driver ++ * ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "ar0132.h" ++ ++#define AR0132_I2C_ADDR 0x18 ++//#define AR0132_I2C_ADDR 0x50 // eeprom ++ ++#define AR0132_PID 0x3000 ++#define AR0132_VERSION_REG 0x2400 ++ ++#define AR0132_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR12_1X12 ++ ++struct ar0132_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int init_complete; ++ u8 id[6]; ++ int exposure; ++ int gain; ++ int autogain; ++ int dvp_order; ++ /* serializers */ ++ int max9286_addr; ++ int max9271_addr; ++ int ti9x4_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++ ++}; ++ ++static inline struct ar0132_priv *to_ar0132(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct ar0132_priv, sd); ++} ++ ++static void ar0132_s_port(struct i2c_client *client, int fwd_en) ++{ ++ struct ar0132_priv *priv = to_ar0132(client); ++ int tmp_addr; ++ ++ if (priv->max9286_addr) { ++ tmp_addr = client->addr; ++ client->addr = priv->max9286_addr; /* Deserializer I2C address */ ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ client->addr = tmp_addr; ++ }; ++} ++ ++static int ar0132_set_regs(struct i2c_client *client, ++ const struct ar0132_reg *regs, int nr_regs) ++{ ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (regs[i].reg == AR0132_DELAY) { ++ mdelay(regs[i].val); ++ continue; ++ } ++ ++ reg16_write16(client, regs[i].reg, regs[i].val); ++ } ++ ++ return 0; ++} ++ ++static int ar0132_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int ar0132_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0132_priv *priv = to_ar0132(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = AR0132_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int ar0132_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = AR0132_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int ar0132_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = AR0132_MEDIA_BUS_FMT; ++ ++ return 0; ++} ++ ++static int ar0132_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0132_priv *priv = to_ar0132(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = AR0132_VERSION_REG >> 8; ++ edid->edid[9] = AR0132_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int ar0132_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0132_priv *priv = to_ar0132(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > AR0132_MAX_WIDTH) || ++ (rect->top + rect->height > AR0132_MAX_HEIGHT)) ++ *rect = priv->rect; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ return 0; ++} ++ ++static int ar0132_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0132_priv *priv = to_ar0132(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = AR0132_MAX_WIDTH; ++ sel->r.height = AR0132_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = AR0132_MAX_WIDTH; ++ sel->r.height = AR0132_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ar0132_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int ar0132_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u16 val = 0; ++ ++ ret = reg16_read16(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int ar0132_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return reg16_write16(client, (u16)reg->reg, (u16)reg->val); ++} ++#endif ++ ++static struct v4l2_subdev_core_ops ar0132_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ar0132_g_register, ++ .s_register = ar0132_s_register, ++#endif ++}; ++ ++static int ar0132_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0132_priv *priv = to_ar0132(client); ++ int ret = -EINVAL; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ case V4L2_CID_CONTRAST: ++ case V4L2_CID_SATURATION: ++ case V4L2_CID_HUE: ++ case V4L2_CID_GAMMA: ++ case V4L2_CID_SHARPNESS: ++ case V4L2_CID_AUTOGAIN: ++ case V4L2_CID_GAIN: ++ case V4L2_CID_EXPOSURE: ++ case V4L2_CID_HFLIP: ++ case V4L2_CID_VFLIP: ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ar0132_ctrl_ops = { ++ .s_ctrl = ar0132_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops ar0132_video_ops = { ++ .s_stream = ar0132_s_stream, ++ .g_mbus_config = ar0132_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops ar0132_subdev_pad_ops = { ++ .get_edid = ar0132_get_edid, ++ .enum_mbus_code = ar0132_enum_mbus_code, ++ .get_selection = ar0132_get_selection, ++ .set_selection = ar0132_set_selection, ++ .get_fmt = ar0132_get_fmt, ++ .set_fmt = ar0132_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops ar0132_subdev_ops = { ++ .core = &ar0132_core_ops, ++ .video = &ar0132_video_ops, ++ .pad = &ar0132_subdev_pad_ops, ++}; ++ ++static void ar0132_otp_id_read(struct i2c_client *client) ++{ ++} ++ ++static ssize_t ar0132_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0132_priv *priv = to_ar0132(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_ar0132, S_IRUGO, ar0132_otp_id_show, NULL); ++ ++static int ar0132_initialize(struct i2c_client *client) ++{ ++ struct ar0132_priv *priv = to_ar0132(client); ++ u16 val = 0; ++ u16 pid = 0; ++ int ret = 0; ++ ++ ar0132_s_port(client, 1); ++ ++ /* check and show model ID */ ++ reg16_read16(client, AR0132_PID, &pid); ++ ++ if (pid != AR0132_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x\n", pid); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ /* Program wizard registers */ ++ ar0132_set_regs(client, ar0132_regs_wizard, ARRAY_SIZE(ar0132_regs_wizard)); ++ ++ /* Enable stream */ ++ reg16_read16(client, 0x301a, &val); // read inital reset_register value ++ val |= (1 << 2); // Set streamOn bit ++ reg16_write16(client, 0x301a, val); // Start Streaming ++ ++ /* Read OTP IDs */ ++ ar0132_otp_id_read(client); ++ ++ dev_info(&client->dev, "ar0132 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, AR0132_MAX_WIDTH, AR0132_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ ar0132_s_port(client, 0); ++ ++ return ret; ++} ++ ++static int ar0132_parse_dt(struct device_node *np, struct ar0132_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order); ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ if (!priv->max9286_addr && !priv->ti9x4_addr) { ++ dev_err(&client->dev, "deserializer does not present for AR0132\n"); ++ return -EINVAL; ++ } ++ ++ ar0132_s_port(client, 1); ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ ++ reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x0A, AR0132_I2C_ADDR << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, AR0132_I2C_ADDR << 1); /* Sensor native I2C address */ ++ ++ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - reset, GPIO1 - fsin */ ++ } ++ client->addr = tmp_addr; ++ ++ mdelay(10); ++ ++ return 0; ++} ++ ++static int ar0132_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ar0132_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &ar0132_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ priv->exposure = 0x100; ++ priv->gain = 0x100; ++ priv->autogain = 1; ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = ar0132_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = ar0132_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = AR0132_MAX_WIDTH; ++ priv->rect.height = AR0132_MAX_HEIGHT; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ar0132) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_AR0132 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int ar0132_remove(struct i2c_client *client) ++{ ++ struct ar0132_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ar0132); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_AR0132 ++static const struct i2c_device_id ar0132_id[] = { ++ { "ar0132", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ar0132_id); ++ ++static const struct of_device_id ar0132_of_ids[] = { ++ { .compatible = "aptina,ar0132", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ar0132_of_ids); ++ ++static struct i2c_driver ar0132_i2c_driver = { ++ .driver = { ++ .name = "ar0132", ++ .of_match_table = ar0132_of_ids, ++ }, ++ .probe = ar0132_probe, ++ .remove = ar0132_remove, ++ .id_table = ar0132_id, ++}; ++ ++module_i2c_driver(ar0132_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for AR0132"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/ar0132.h b/drivers/media/i2c/soc_camera/ar0132.h +new file mode 100644 +index 0000000..bafa193 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0132.h +@@ -0,0 +1,213 @@ ++/* ++ * ON Semiconductor AR0132 sensor camera wizard 1110x620@30/BGGR/BT601/12bit ++ * ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++//#define AR0132_DISPLAY_PATTERN_FIXED ++//#define AR0132_DISPLAY_PATTERN_COLOR_BAR ++ ++#define AR0132_EMBEDDED_LINE ++ ++#define AR0132_MAX_WIDTH 1665 // (1110*3/2) ++#define AR0132_MAX_HEIGHT 624 ++ ++#define AR0132_DELAY 0xffff ++ ++#define AR0132_MAX_ROI_DIM_X 1288 ++#define AR0132_MAX_ROI_DIM_Y 968 ++#define AR0132_InfoLines 4 ++ ++#define AR0132_ROI_DIM_X 1110 // 1104 ++#define AR0132_ROI_DIM_Y 620 // AR0132_MAX_HEIGHT ++ ++#define AR0132_ROI_Y_START 0x00AE ++#define AR0132_ROI_X_START 0x005C ++#define AR0132_ROI_Y_END AR0132_ROI_Y_START+AR0132_ROI_DIM_Y-1 ++#define AR0132_ROI_X_END AR0132_ROI_X_START+AR0132_ROI_DIM_X-1 ++ ++#define AR0132_FrameLength_Lines 0x029E ++#define AR0132_LineLength_Ticks 0x06B6 ++ ++#define AR0132_PLL_VT_Pix_Clk_Div 0x0008 ++#define AR0132_PLL_VT_Sys_Clk_Div 0x0001 ++#define AR0132_PLL_Pre_Clk_Div 0x0004 ++#define AR0132_PLL_Multiplier 0x003C ++ ++#define AR0132_DigitalTest 0x2002 ++ ++struct ar0132_reg { ++ u16 reg; ++ u16 val; ++}; ++ ++static const struct ar0132_reg ar0132_regs_wizard[] = { ++{0x301A, 0x0001}, // reset ++{AR0132_DELAY, 100}, ++{0x301A, 0x10D8}, // Stream off and setup parallel ++{0x3070, 0x0001}, ++{0x3070, 0x0000}, // 1: Solid color test pattern, ++ // 2: Full color bar test pattern, ++ // 3: Fade to grey color bar test pattern, ++ //256: Walking 1 test pattern (12 bit) ++#ifdef AR0132_DISPLAY_PATTERN_FIXED ++{0x3070, 0x0001}, ++{0x3072, 0x0123}, // R ++{0x3074, 0x0456}, // G(GR row) ++{0x3076, 0x0abc}, // B ++{0x3078, 0x0def}, // G(GB row) ++#endif ++#ifdef AR0132_DISPLAY_PATTERN_COLOR_BAR ++{0x3070, 0x0002}, ++#endif ++{AR0132_DELAY, 250}, ++// patch begin ++{0x3088, 0x8000}, ++{0x3086, 0x0025}, {0x3086, 0x5050}, {0x3086, 0x2D26}, {0x3086, 0x0828}, {0x3086, 0x0D17}, {0x3086, 0x0926}, {0x3086, 0x0028}, {0x3086, 0x0526}, ++{0x3086, 0xA728}, {0x3086, 0x0725}, {0x3086, 0x8080}, {0x3086, 0x2925}, {0x3086, 0x0040}, {0x3086, 0x2702}, {0x3086, 0x1616}, {0x3086, 0x2706}, ++{0x3086, 0x1736}, {0x3086, 0x26A6}, {0x3086, 0x1703}, {0x3086, 0x26A4}, {0x3086, 0x171F}, {0x3086, 0x2805}, {0x3086, 0x2620}, {0x3086, 0x2804}, ++{0x3086, 0x2520}, {0x3086, 0x2027}, {0x3086, 0x0017}, {0x3086, 0x1D25}, {0x3086, 0x0020}, {0x3086, 0x1F17}, {0x3086, 0x1028}, {0x3086, 0x0519}, ++{0x3086, 0x1703}, {0x3086, 0x2706}, {0x3086, 0x1703}, {0x3086, 0x1741}, {0x3086, 0x2660}, {0x3086, 0x17AE}, {0x3086, 0x2500}, {0x3086, 0x9027}, ++{0x3086, 0x0026}, {0x3086, 0x1828}, {0x3086, 0x002E}, {0x3086, 0x2A28}, {0x3086, 0x081C}, {0x3086, 0x1470}, {0x3086, 0x7003}, {0x3086, 0x1470}, ++{0x3086, 0x7004}, {0x3086, 0x1470}, {0x3086, 0x7005}, {0x3086, 0x1470}, {0x3086, 0x7009}, {0x3086, 0x170C}, {0x3086, 0x0014}, {0x3086, 0x0020}, ++{0x3086, 0x2300}, {0x3086, 0x1400}, {0x3086, 0x5003}, {0x3086, 0x1400}, {0x3086, 0x2003}, {0x3086, 0x1400}, {0x3086, 0x5022}, {0x3086, 0x0414}, ++{0x3086, 0x0020}, {0x3086, 0x0414}, {0x3086, 0x0050}, {0x3086, 0x0514}, {0x3086, 0x0020}, {0x3086, 0x2405}, {0x3086, 0x1400}, {0x3086, 0x5001}, ++{0x3086, 0x2550}, {0x3086, 0x502D}, {0x3086, 0x2608}, {0x3086, 0x280D}, {0x3086, 0x1709}, {0x3086, 0x2600}, {0x3086, 0x2805}, {0x3086, 0x26A7}, ++{0x3086, 0x2807}, {0x3086, 0x2580}, {0x3086, 0x8029}, {0x3086, 0x2500}, {0x3086, 0x4027}, {0x3086, 0x0216}, {0x3086, 0x1627}, {0x3086, 0x0617}, ++{0x3086, 0x3626}, {0x3086, 0xA617}, {0x3086, 0x0326}, {0x3086, 0xA417}, {0x3086, 0x1F28}, {0x3086, 0x0526}, {0x3086, 0x2028}, {0x3086, 0x0425}, ++{0x3086, 0x2020}, {0x3086, 0x2700}, {0x3086, 0x171D}, {0x3086, 0x2500}, {0x3086, 0x2020}, {0x3086, 0x1710}, {0x3086, 0x2805}, {0x3086, 0x1A17}, ++{0x3086, 0x0327}, {0x3086, 0x0617}, {0x3086, 0x0317}, {0x3086, 0x4126}, {0x3086, 0x6017}, {0x3086, 0xAE25}, {0x3086, 0x0090}, {0x3086, 0x2700}, ++{0x3086, 0x2618}, {0x3086, 0x2800}, {0x3086, 0x2E2A}, {0x3086, 0x2808}, {0x3086, 0x1D05}, {0x3086, 0x1470}, {0x3086, 0x7009}, {0x3086, 0x1720}, ++{0x3086, 0x1400}, {0x3086, 0x2024}, {0x3086, 0x1400}, {0x3086, 0x5002}, {0x3086, 0x2550}, {0x3086, 0x502D}, {0x3086, 0x2608}, {0x3086, 0x280D}, ++{0x3086, 0x1709}, {0x3086, 0x2600}, {0x3086, 0x2805}, {0x3086, 0x26A7}, {0x3086, 0x2807}, {0x3086, 0x2580}, {0x3086, 0x8029}, {0x3086, 0x2500}, ++{0x3086, 0x4027}, {0x3086, 0x0216}, {0x3086, 0x1627}, {0x3086, 0x0617}, {0x3086, 0x3626}, {0x3086, 0xA617}, {0x3086, 0x0326}, {0x3086, 0xA417}, ++{0x3086, 0x1F28}, {0x3086, 0x0526}, {0x3086, 0x2028}, {0x3086, 0x0425}, {0x3086, 0x2020}, {0x3086, 0x2700}, {0x3086, 0x171D}, {0x3086, 0x2500}, ++{0x3086, 0x2021}, {0x3086, 0x1710}, {0x3086, 0x2805}, {0x3086, 0x1B17}, {0x3086, 0x0327}, {0x3086, 0x0617}, {0x3086, 0x0317}, {0x3086, 0x4126}, ++{0x3086, 0x6017}, {0x3086, 0xAE25}, {0x3086, 0x0090}, {0x3086, 0x2700}, {0x3086, 0x2618}, {0x3086, 0x2800}, {0x3086, 0x2E2A}, {0x3086, 0x2808}, ++{0x3086, 0x1E17}, {0x3086, 0x0A05}, {0x3086, 0x1470}, {0x3086, 0x7009}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, ++{0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, ++{0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1400}, {0x3086, 0x2024}, {0x3086, 0x1400}, {0x3086, 0x502B}, ++{0x3086, 0x302C}, {0x3086, 0x2C2C}, {0x3086, 0x2C00}, {0x3086, 0x0225}, {0x3086, 0x5050}, {0x3086, 0x2D26}, {0x3086, 0x0828}, {0x3086, 0x0D17}, ++{0x3086, 0x0926}, {0x3086, 0x0028}, {0x3086, 0x0526}, {0x3086, 0xA728}, {0x3086, 0x0725}, {0x3086, 0x8080}, {0x3086, 0x2917}, {0x3086, 0x0525}, ++{0x3086, 0x0040}, {0x3086, 0x2702}, {0x3086, 0x1616}, {0x3086, 0x2706}, {0x3086, 0x1736}, {0x3086, 0x26A6}, {0x3086, 0x1703}, {0x3086, 0x26A4}, ++{0x3086, 0x171F}, {0x3086, 0x2805}, {0x3086, 0x2620}, {0x3086, 0x2804}, {0x3086, 0x2520}, {0x3086, 0x2027}, {0x3086, 0x0017}, {0x3086, 0x1E25}, ++{0x3086, 0x0020}, {0x3086, 0x2117}, {0x3086, 0x1028}, {0x3086, 0x051B}, {0x3086, 0x1703}, {0x3086, 0x2706}, {0x3086, 0x1703}, {0x3086, 0x1747}, ++{0x3086, 0x2660}, {0x3086, 0x17AE}, {0x3086, 0x2500}, {0x3086, 0x9027}, {0x3086, 0x0026}, {0x3086, 0x1828}, {0x3086, 0x002E}, {0x3086, 0x2A28}, ++{0x3086, 0x081E}, {0x3086, 0x0831}, {0x3086, 0x1440}, {0x3086, 0x4014}, {0x3086, 0x2020}, {0x3086, 0x1410}, {0x3086, 0x1034}, {0x3086, 0x1400}, ++{0x3086, 0x1014}, {0x3086, 0x0020}, {0x3086, 0x1400}, {0x3086, 0x4013}, {0x3086, 0x1802}, {0x3086, 0x1470}, {0x3086, 0x7004}, {0x3086, 0x1470}, ++{0x3086, 0x7003}, {0x3086, 0x1470}, {0x3086, 0x7017}, {0x3086, 0x2002}, {0x3086, 0x1400}, {0x3086, 0x2002}, {0x3086, 0x1400}, {0x3086, 0x5004}, ++{0x3086, 0x1400}, {0x3086, 0x2004}, {0x3086, 0x1400}, {0x3086, 0x5022}, {0x3086, 0x0314}, {0x3086, 0x0020}, {0x3086, 0x0314}, {0x3086, 0x0050}, ++{0x3086, 0x2C2C}, {0x3086, 0x2C2C}, ++{0x309E, 0x0186}, ++{0x309E, 0x0186}, ++// patch end ++{AR0132_DELAY, 250}, ++{0x301A, 0x10D8}, // WR= RESET_REGISTER, 0x10D8 - stop streaming ++{0x3082, 0x0028}, // Set HiDy OPERATION_MODE_CTRL(A) Requested integration time ratio (T2 to T3): 8 & (T1 t0 T2): 16 ++{0x3084, 0x0028}, // Set HiDy OPERATION_MODE_CTRL(B) Requested integration time ratio (T2 to T3): 16 & (T1 t0 T2): 16 ++{0x301E, 0x00C8}, // set datapedestal to 200 to avoid clipping near saturation ++{0x3EDA, 0x0F03}, // Set vln_dac to 0x3 as recommended by Sergey ++{0x3EDE, 0xC007}, ++{0x3ED8, 0x01EF}, // Vrst_low = +1 ++{0x3EE2, 0xA46B}, ++{0x3EE0, 0x067D}, // enable anti eclipse and adjust setting for high conversion gain ++{0x3EDC, 0x0070}, // adjust anti eclipse setting for low conversion gain ++{0x3044, 0x0404}, // disable digital row noise correction and cancels TX during column correction ++{0x3EE6, 0x4303}, // Helps with column noise at low light ++{0x3EE4, 0xD208}, // enable analog row noise correction ++{0x3ED6, 0x00BD}, ++{0x3EE6, 0x8303}, // improves low light FPN ++{0x30E4, 0x6372}, // ADC settings to improve noise performance ++{0x30E2, 0x7253}, ++{0x30E0, 0x5470}, ++{0x30E6, 0xC4CC}, ++{0x30E8, 0x8050}, ++{AR0132_DELAY, 250}, ++{0x3058, 0x003F}, // WR= BLUE_GAIN, 0x003F ++{0x3014, 0}, // Fine_IT_Time(A) ++{0x3002, AR0132_ROI_Y_START}, // WR= Y_ADDR_START_(A) ++{0x3004, AR0132_ROI_X_START}, // WR= X_ADDR_START_(A) ++{0x3006, AR0132_ROI_Y_END}, // WR= Y_ADDR_END_(A) ++{0x3008, AR0132_ROI_X_END}, // WR= X_ADDR_END_(A) ++{0x300A, AR0132_FrameLength_Lines}, // WR= FRAME_LENGTH_LINES_(A) ++{0x3018, 0}, // Fine_IT_Time(B) ++{0x308C, AR0132_ROI_Y_START}, // Y_ADDR_START_(B) ++{0x308A, AR0132_ROI_X_START}, // X_ADDR_START_(B) ++{0x3090, AR0132_ROI_Y_END}, // Y_ADDR_END_(B) ++{0x308E, AR0132_ROI_X_END}, // X_ADDR_END_(B) ++{0x30AA, AR0132_FrameLength_Lines}, // FRAME_LENGTH_LINES_(B) ++{0x300C, AR0132_LineLength_Ticks}, // Line Length ++{0x301A, 0x10D8}, // Disable Streaming and setup parallel ++{0x31D0, 0x0001}, // Set to 12 bits ++{0x3028, 0x0010}, // ROW_SPEED = 16 ++{0x302A, AR0132_PLL_VT_Pix_Clk_Div}, ++{0x302C, AR0132_PLL_VT_Sys_Clk_Div}, ++{0x302E, AR0132_PLL_Pre_Clk_Div}, ++{0x3030, AR0132_PLL_Multiplier}, ++{0x3032, 0x0000}, // SCALING_MODE = 0 ++{0x3040, 0xC000}, // READ_MODE = read_mode_vert_flip | read_mode_horiz_mirror ++{0x3044, 0x0404}, // Dark Control = 1028 ++{0x30A6, 0x0001}, // Y Odd Inc. (A) = 1 ++{0x30A8, 0x0001}, // Y Odd Inc. (B) = 1 ++{0x30B0, AR0132_DigitalTest}, ++{AR0132_DELAY, 100}, ++#ifdef AR0132_EMBEDDED_LINE ++{0x3064, 0x1982}, // Embedded Data on ++#else ++{0x3064, 0x1802}, // Embedded Data off ++#endif ++{0x3100, 0x0084}, // WR= AECTRLREG, ++{0x3190, 0x6BA0}, ++{0x3194, 0x0E74}, ++{0x3196, 0x0ED8}, ++{0x3198, 0x0FA0}, ++{0x319E, 0x5040}, // resetvalue ++{0x31A2, 0x0FA0}, ++//FrontCamera Specific Section ++//Common ++#ifdef AR0132_EMBEDDED_LINE ++{0x3064, 0x1982}, ++#else ++{0x3064, 0x1802}, ++#endif ++{0x30B4, 0x0011}, ++{0x30ba, 0x0008}, ++{0x3180, 0xE000}, ++{0x3182, 0x012C}, ++{0x3190, 0x6BA0}, ++{0x3194, 0x0E74}, ++{0x3196, 0x0ED8}, ++{0x3198, 0x0FA0}, ++{0x319E, 0x5040}, ++{0x31A2, 0x0FA0}, ++//Context A:0 ++{0x3012, 0x0021}, ++{0x3014, 0x0000}, ++{0x30A6, 0x0001}, ++{0x3056, 0x0008}, ++{0x3058, 0x0008}, ++{0x305A, 0x0008}, ++{0x305C, 0x0008}, ++{0x305E, 0x0008}, ++{0x3082, 0x0014}, ++//Context B:0 ++{0x3016, 0x007F}, ++{0x3018, 0x0000}, ++{0x30A8, 0x0001}, ++{0x30BC, 0x0020}, ++{0x30BE, 0x0020}, ++{0x30C0, 0x0020}, ++{0x30C2, 0x0020}, ++{0x30C4, 0x0020}, ++{0x3084, 0x0028}, ++//not covered ++{0x301E, 0x00C8}, ++{0x3044, 0x0404}, ++{0x31D0, 0x0001}, ++{0x30B0, 0x2002}, ++}; +diff --git a/drivers/media/i2c/soc_camera/ar0220.c b/drivers/media/i2c/soc_camera/ar0220.c +new file mode 100644 +index 0000000..e00fe4a +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0220.c +@@ -0,0 +1,532 @@ ++/* ++ * ON Semiconductor AR0220 sensor camera driver ++ * ++ * Copyright (C) 2017-2018 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "ar0220.h" ++ ++#define AR0220_I2C_ADDR 0x10 ++//#define AR0220_I2C_ADDR 0x54 // eeprom ++ ++#define AR0220_PID 0x3000 ++#define AR0220_VERSION_REG 0x0C54 ++ ++#define AR0220_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR8_1X8 ++ ++struct ar0220_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int init_complete; ++ u8 id[6]; ++ int exposure; ++ int gain; ++ int autogain; ++ /* serializers */ ++ int ti9x4_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++ ++}; ++ ++static inline struct ar0220_priv *to_ar0220(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct ar0220_priv, sd); ++} ++ ++static int ar0220_set_regs(struct i2c_client *client, ++ const struct ar0220_reg *regs, int nr_regs) ++{ ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (regs[i].reg == AR0220_DELAY) { ++ mdelay(regs[i].val); ++ continue; ++ } ++ ++ reg16_write16(client, regs[i].reg, regs[i].val); ++ } ++ ++ return 0; ++} ++ ++static int ar0220_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int ar0220_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0220_priv *priv = to_ar0220(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = AR0220_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int ar0220_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = AR0220_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int ar0220_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = AR0220_MEDIA_BUS_FMT; ++ ++ return 0; ++} ++ ++static int ar0220_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0220_priv *priv = to_ar0220(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = AR0220_VERSION_REG >> 8; ++ edid->edid[9] = AR0220_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int ar0220_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0220_priv *priv = to_ar0220(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > AR0220_MAX_WIDTH) || ++ (rect->top + rect->height > AR0220_MAX_HEIGHT)) ++ *rect = priv->rect; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ return 0; ++} ++ ++static int ar0220_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0220_priv *priv = to_ar0220(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = AR0220_MAX_WIDTH; ++ sel->r.height = AR0220_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = AR0220_MAX_WIDTH; ++ sel->r.height = AR0220_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ar0220_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int ar0220_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u16 val = 0; ++ ++ ret = reg16_read16(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int ar0220_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return reg16_write16(client, (u16)reg->reg, (u16)reg->val); ++} ++#endif ++ ++static struct v4l2_subdev_core_ops ar0220_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ar0220_g_register, ++ .s_register = ar0220_s_register, ++#endif ++}; ++ ++static int ar0220_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0220_priv *priv = to_ar0220(client); ++ int ret = -EINVAL; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ case V4L2_CID_CONTRAST: ++ case V4L2_CID_SATURATION: ++ case V4L2_CID_HUE: ++ case V4L2_CID_GAMMA: ++ case V4L2_CID_SHARPNESS: ++ case V4L2_CID_AUTOGAIN: ++ case V4L2_CID_GAIN: ++ case V4L2_CID_EXPOSURE: ++ case V4L2_CID_HFLIP: ++ case V4L2_CID_VFLIP: ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ar0220_ctrl_ops = { ++ .s_ctrl = ar0220_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops ar0220_video_ops = { ++ .s_stream = ar0220_s_stream, ++ .g_mbus_config = ar0220_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops ar0220_subdev_pad_ops = { ++ .get_edid = ar0220_get_edid, ++ .enum_mbus_code = ar0220_enum_mbus_code, ++ .get_selection = ar0220_get_selection, ++ .set_selection = ar0220_set_selection, ++ .get_fmt = ar0220_get_fmt, ++ .set_fmt = ar0220_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops ar0220_subdev_ops = { ++ .core = &ar0220_core_ops, ++ .video = &ar0220_video_ops, ++ .pad = &ar0220_subdev_pad_ops, ++}; ++ ++static void ar0220_otp_id_read(struct i2c_client *client) ++{ ++} ++ ++static ssize_t ar0220_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0220_priv *priv = to_ar0220(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_ar0220, S_IRUGO, ar0220_otp_id_show, NULL); ++ ++static int ar0220_initialize(struct i2c_client *client) ++{ ++ struct ar0220_priv *priv = to_ar0220(client); ++ u16 val = 0; ++ u16 pid = 0; ++ int ret = 0; ++ ++ /* check and show model ID */ ++ reg16_read16(client, AR0220_PID, &pid); ++ ++ if (pid != AR0220_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x\n", pid); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ /* Program wizard registers */ ++ ar0220_set_regs(client, ar0220_regs_wizard, ARRAY_SIZE(ar0220_regs_wizard)); ++ ++ /* Enable stream */ ++ reg16_read16(client, 0x301a, &val); // read inital reset_register value ++ val |= (1 << 2); // Set streamOn bit ++ reg16_write16(client, 0x301a, val); // Start Streaming ++ ++ /* Read OTP IDs */ ++ ar0220_otp_id_read(client); ++ ++ dev_info(&client->dev, "ar0220 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, AR0220_MAX_WIDTH, AR0220_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ return ret; ++} ++ ++static int ar0220_parse_dt(struct device_node *np, struct ar0220_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ if (!priv->ti9x4_addr) { ++ dev_err(&client->dev, "deserializer does not present\n"); ++ return -EINVAL; ++ } ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, AR0220_I2C_ADDR << 1); /* Sensor native I2C address */ ++// reg8_write(client, 0x6e, 0xa9); /* GPIO0 - reset, GPIO1 - fsin */ ++ ++ client->addr = priv->ti9x3_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x06, 0x41); /* Set clock divider M */ ++ reg8_write(client, 0x07, 0x25); /* Set clock divider N = 27MHz */ ++ } ++ client->addr = tmp_addr; ++ ++ mdelay(10); ++ ++ return 0; ++} ++ ++static int ar0220_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ar0220_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &ar0220_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ priv->exposure = 0x100; ++ priv->gain = 0x100; ++ priv->autogain = 1; ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0220_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0220_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0220_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0220_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0220_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0220_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0220_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0220_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0220_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0220_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0220_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = ar0220_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = ar0220_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = AR0220_MAX_WIDTH; ++ priv->rect.height = AR0220_MAX_HEIGHT; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ar0220) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_AR0220 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int ar0220_remove(struct i2c_client *client) ++{ ++ struct ar0220_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ar0220); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_AR0220 ++static const struct i2c_device_id ar0220_id[] = { ++ { "ar0220", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ar0220_id); ++ ++static const struct of_device_id ar0220_of_ids[] = { ++ { .compatible = "aptina,ar0220", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ar0220_of_ids); ++ ++static struct i2c_driver ar0220_i2c_driver = { ++ .driver = { ++ .name = "ar0220", ++ .of_match_table = ar0220_of_ids, ++ }, ++ .probe = ar0220_probe, ++ .remove = ar0220_remove, ++ .id_table = ar0220_id, ++}; ++ ++module_i2c_driver(ar0220_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for AR0220"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/ar0220.h b/drivers/media/i2c/soc_camera/ar0220.h +new file mode 100644 +index 0000000..8ef557d +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0220.h +@@ -0,0 +1,43 @@ ++/* ++ * ON Semiconductor AR0220 sensor camera wizard 1820x940@44/RCCB/MIPI ++ * ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++//#define AR0220_DISPLAY_PATTERN_FIXED ++//#define AR0220_DISPLAY_PATTERN_COLOR_BAR ++ ++#define AR0220_MAX_WIDTH 3648 // (1820*2=3640) <- must be multiple of 16 - requred by R-CAR VIN ++#define AR0220_MAX_HEIGHT 944 ++ ++#define AR0220_DELAY 0xffff ++ ++struct ar0220_reg { ++ u16 reg; ++ u16 val; ++}; ++ ++static const struct ar0220_reg ar0220_regs_wizard[] = { ++{0x301A, 0x0018}, // RESET_REGISTER ++{AR0220_DELAY, 500}, // Wait 500ms ++{0x3070, 0x0000}, // 1: Solid color test pattern, ++ // 2: Full color bar test pattern, ++ // 3: Fade to grey color bar test pattern, ++ //256: Walking 1 test pattern (12 bit) ++{0x3072, 0x0123}, // R ++{0x3074, 0x0456}, // G(GR row) ++{0x3076, 0x0abc}, // B ++{0x3078, 0x0def}, // G(GB row) ++#ifdef AR0220_DISPLAY_PATTERN_FIXED ++{0x3070, 0x0001}, ++#endif ++#ifdef AR0220_DISPLAY_PATTERN_COLOR_BAR ++{0x3070, 0x0002}, ++#endif ++{AR0220_DELAY, 100}, // Wait 100ms ++}; +diff --git a/drivers/media/i2c/soc_camera/max9286.c b/drivers/media/i2c/soc_camera/max9286.c +new file mode 100644 +index 0000000..6a5d0889 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/max9286.c +@@ -0,0 +1,694 @@ ++/* ++ * MAXIM max9286 GMSL driver ++ * ++ * Copyright (C) 2015-2018 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "max9286.h" ++ ++#define MAXIM_I2C_I2C_SPEED_837KHZ (0x7 << 2) /* 837kbps */ ++#define MAXIM_I2C_I2C_SPEED_533KHZ (0x6 << 2) /* 533kbps */ ++#define MAXIM_I2C_I2C_SPEED_339KHZ (0x5 << 2) /* 339 kbps */ ++#define MAXIM_I2C_I2C_SPEED_173KHZ (0x4 << 2) /* 174kbps */ ++#define MAXIM_I2C_I2C_SPEED_105KHZ (0x3 << 2) /* 105 kbps */ ++#define MAXIM_I2C_I2C_SPEED_085KHZ (0x2 << 2) /* 84.7 kbps */ ++#define MAXIM_I2C_I2C_SPEED_028KHZ (0x1 << 2) /* 28.3 kbps */ ++#define MAXIM_I2C_I2C_SPEED MAXIM_I2C_I2C_SPEED_339KHZ ++ ++struct max9286_priv { ++ struct v4l2_subdev sd[4]; ++ struct fwnode_handle *sd_fwnode[4]; ++ int des_addr; ++ int des_quirk_addr; /* second MAX9286 on the same I2C bus */ ++ int links; ++ int links_mask; ++ int lanes; ++ int csi_rate; ++ const char *fsync_mode; ++ int fsync_period; ++ char pclk_rising_edge; ++ int gpio_resetb; ++ int active_low_resetb; ++ int him; ++ int hsync; ++ int vsync; ++ int timeout; ++ int poc_delay; ++ atomic_t use_count; ++ u32 csi2_outord; ++ struct i2c_client *client; ++ int max9271_addr_map[4]; ++ int ser_id; ++ struct gpio_desc *poc_gpio[4]; /* PoC power supply */ ++}; ++ ++static char fsync_mode_default[20] = "manual"; /* manual, automatic, semi-automatic, external */ ++ ++static int conf_link; ++module_param(conf_link, int, 0644); ++MODULE_PARM_DESC(conf_link, " Force configuration link. Used only if robust firmware flashing required (f.e. recovery)"); ++ ++static int poc_trig; ++module_param(poc_trig, int, 0644); ++MODULE_PARM_DESC(poc_trig, " Use PoC triggering during reverse channel setup. Useful on systems with dedicated PoC and unstable ser-des lock"); ++ ++static int him; ++module_param(him, int, 0644); ++MODULE_PARM_DESC(him, " Use High-Immunity mode (default: leagacy mode)"); ++ ++static int fsync_period; ++module_param(fsync_period, int, 0644); ++MODULE_PARM_DESC(fsync_period, " Frame sync period (default: 3.2MHz)"); ++ ++static int hsync; ++module_param(hsync, int, 0644); ++MODULE_PARM_DESC(hsync, " HSYNC invertion (default: 0 - not inverted)"); ++ ++static int vsync = 1; ++module_param(vsync, int, 0644); ++MODULE_PARM_DESC(vsync, " VSYNC invertion (default: 1 - inverted)"); ++ ++static int gpio_resetb; ++module_param(gpio_resetb, int, 0644); ++MODULE_PARM_DESC(gpio_resetb, " Serializer GPIO reset (default: 0 - not used)"); ++ ++static int active_low_resetb; ++module_param(active_low_resetb, int, 0644); ++MODULE_PARM_DESC(active_low_resetb, " Serializer GPIO reset level (default: 0 - active high)"); ++ ++static int poc_delay; ++module_param(poc_delay, int, 0644); ++MODULE_PARM_DESC(poc_delay, " Delay in ms after POC enable (default: 0 ms)"); ++ ++static char* ser_name(int id) ++{ ++ switch (id) { ++ case MAX9271_ID: ++ return "MAX9271"; ++ case MAX96705_ID: ++ return "MAX96705"; ++ default: ++ return "unknown"; ++ } ++} ++ ++static void max9286_preinit(struct i2c_client *client, int addr) ++{ ++ struct max9286_priv *priv = i2c_get_clientdata(client); ++ ++ client->addr = addr; /* MAX9286-CAMx I2C */ ++ reg8_write(client, 0x0a, 0x00); /* disable reverse control for all cams */ ++ reg8_write(client, 0x00, 0x00); /* disable all GMSL links [0:3] */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ reg8_write(client, 0x1c, priv->him ? 0xf4 : 0x04); /* high-immunity or legacy mode */ ++} ++ ++static void max9286_sensor_reset(struct i2c_client *client, int addr, int reset_on) ++{ ++ struct max9286_priv *priv = i2c_get_clientdata(client); ++ ++ if (priv->gpio_resetb < 1 || priv->gpio_resetb > 5) ++ return; ++ ++ /* sensor reset/unreset */ ++ client->addr = addr; /* MAX9271-CAMx I2C */ ++ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | /* set GPIOn value to reset/unreset */ ++ ((priv->active_low_resetb ? BIT(priv->gpio_resetb) : 0) ^ reset_on)); ++ reg8_write(client, 0x0e, 0x42 | BIT(priv->gpio_resetb)); /* set GPIOn direction output */ ++} ++ ++static void max9286_postinit(struct i2c_client *client, int addr) ++{ ++ struct max9286_priv *priv = i2c_get_clientdata(client); ++ int idx; ++ ++ for (idx = 0; idx < priv->links; idx++) { ++ client->addr = priv->des_addr; /* MAX9286 I2C */ ++ reg8_write(client, 0x0a, 0x11 << idx); /* enable reverse/forward control for CAMx */ ++ ++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C */ ++ max9286_sensor_reset(client, client->addr, 0); /* sensor unreset */ ++ } ++ ++ client->addr = addr; /* MAX9286 I2C */ ++ reg8_write(client, 0x0a, 0x00); /* disable reverse control for all cams */ ++ reg8_write(client, 0x00, 0xe0 | priv->links_mask); /* enable GMSL link for CAMs */ ++ reg8_write(client, 0x0b, priv->csi2_outord); /* CSI2 output order */ ++ reg8_write(client, 0x15, 0x9b); /* enable CSI output, VC is set accordingly to Link number, BIT7 magic must be set */ ++ reg8_write(client, 0x1b, priv->links_mask); /* enable equalizer for CAMs */ ++ usleep_range(5000, 5500); /* wait 2ms after any change of reverse channel settings */ ++ ++ if (strcmp(priv->fsync_mode, "manual") == 0) { ++ reg8_write(client, 0x01, 0x00); /* manual: FRAMESYNC set manually via [0x06:0x08] regs */ ++ } else if (strcmp(priv->fsync_mode, "automatic") == 0) { ++ reg8_write(client, 0x01, 0x02); /* automatic: FRAMESYNC taken from the slowest Link */ ++ } else if (strcmp(priv->fsync_mode, "semi-automatic") == 0) { ++ reg8_write(client, 0x01, 0x01); /* semi-automatic: FRAMESYNC taken from the slowest Link */ ++ } else if (strcmp(priv->fsync_mode, "external") == 0) { ++ reg8_write(client, 0x01, 0xc0); /* ECU (aka MCU) based FrameSync using GPI-to-GPO */ ++ } ++} ++ ++static int max9286_reverse_channel_setup(struct i2c_client *client, int idx) ++{ ++ struct max9286_priv *priv = i2c_get_clientdata(client); ++ u8 val = 0; ++ int timeout = priv->timeout; ++ char timeout_str[10]; ++ int ret = 0; ++ ++ /* Reverse channel enable */ ++ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ ++ reg8_write(client, 0x3f, 0x4f); /* enable custom reverse channel & first pulse length */ ++ reg8_write(client, 0x34, 0xa2 | MAXIM_I2C_I2C_SPEED); /* enable artificial ACKs, I2C speed set */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ reg8_write(client, 0x00, 0xe0 | BIT(idx)); /* enable GMSL link for CAMx */ ++ reg8_write(client, 0x0a, 0x11 << idx); /* enable reverse control for CAMx */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ ++ for (;;) { ++ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ ++ reg8_write(client, 0x3b, 0x1e); /* first pulse length rise time changed from 300ns to 200ns, amplitude 100mV */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ ++ client->addr = 0x40; /* MAX9271-CAMx I2C */ ++ reg8_write(client, 0x04, 0x43); /* wake-up, enable reverse_control/conf_link */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ reg8_write(client, 0x08, 0x01); /* reverse channel receiver high threshold enable */ ++ reg8_write(client, 0x97, priv->him ? 0xaf : 0x5f); /* enable reverse control channel programming (MAX96705-MAX96711 only) */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ ++ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ ++ reg8_write(client, 0x3b, 0x19); /* reverse channel increase amplitude 170mV to compensate high threshold enabled */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ ++ client->addr = 0x40; /* MAX9271-CAMx I2C */ ++ reg8_read(client, 0x1e, &val); /* read max9271 ID */ ++ if (val == MAX9271_ID || val == MAX96705_ID || --timeout == 0) { ++ priv->ser_id = val; ++ break; ++ } ++ ++ /* Check if already initialized (after reboot/reset ?) */ ++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C */ ++ reg8_read(client, 0x1e, &val); /* read max9271 ID */ ++ if (val == MAX9271_ID || val == MAX96705_ID) { ++ priv->ser_id = val; ++ reg8_write(client, 0x04, 0x43); /* enable reverse_control/conf_link */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ ret = -EADDRINUSE; ++ break; ++ } ++ ++ if (timeout == priv->timeout / 2 && poc_trig) { ++ if (!IS_ERR(priv->poc_gpio[idx])) { ++ gpiod_direction_output(priv->poc_gpio[idx], 0); /* POC power off */ ++ mdelay(200); ++ gpiod_direction_output(priv->poc_gpio[idx], 1); /* POC power on */ ++ mdelay(priv->poc_delay); ++ } ++ } ++ } ++ ++ max9286_sensor_reset(client, client->addr, 1); /* sensor reset */ ++ ++ if (!timeout) { ++ ret = -ETIMEDOUT; ++ goto out; ++ } ++ ++ priv->links_mask |= BIT(idx); ++ priv->csi2_outord &= ~(0x3 << (idx * 2)); ++ priv->csi2_outord |= ((hweight8(priv->links_mask) - 1) << (idx * 2)); ++ ++out: ++ sprintf(timeout_str, "retries=%d", priv->timeout - timeout); ++ dev_info(&client->dev, "link%d %s %sat 0x%x %s %s\n", idx, ser_name(priv->ser_id), ++ ret == -EADDRINUSE ? "already " : "", priv->max9271_addr_map[idx], ++ ret == -ETIMEDOUT ? "not found: timeout GMSL link establish" : "", ++ priv->timeout - timeout? timeout_str : ""); ++ ++ return ret; ++} ++ ++static void max9286_initial_setup(struct i2c_client *client) ++{ ++ struct max9286_priv *priv = i2c_get_clientdata(client); ++ ++ /* Initial setup */ ++ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ ++ reg8_write(client, 0x15, 0x13); /* disable CSI output, VC is set accordingly to Link number */ ++ reg8_write(client, 0x69, 0x0f); /* mask CSI forwarding from all links */ ++ switch (priv->lanes) { ++ case 1: ++ reg8_write(client, 0x12, 0x33); /* enable CSI-2 Lane D0, DBL mode, YUV422 8-bit*/ ++ break; ++ case 2: ++ reg8_write(client, 0x12, 0x73); /* enable CSI-2 Lanes D0,D1, DBL mode, YUV422 8-bit*/ ++ break; ++ case 3: ++ reg8_write(client, 0x12, 0xd3); /* enable CSI-2 Lanes D0-D2, DBL mode, YUV422 8-bit*/ ++ break; ++ case 4: ++ reg8_write(client, 0x12, 0xf3); /* enable CSI-2 Lanes D0-D3, DBL mode, YUV422 8-bit*/ ++ break; ++ default: ++ dev_err(&client->dev, "CSI2 lanes number is invalid (%d)\n", priv->lanes); ++ } ++ ++ /* Start GMSL initialization with FSYNC disabled. This is required for some odd LVDS cameras */ ++ reg8_write(client, 0x01, 0xc0); /* ECU (aka MCU) based FrameSync using GPI-to-GPO */ ++ reg8_write(client, 0x06, priv->fsync_period & 0xff); ++ reg8_write(client, 0x07, (priv->fsync_period >> 8) & 0xff); ++ reg8_write(client, 0x08, priv->fsync_period >> 16); ++ ++ reg8_write(client, 0x63, 0); /* disable overlap window */ ++ reg8_write(client, 0x64, 0); ++ reg8_write(client, 0x0c, 0x91 | (priv->vsync ? BIT(3) : 0) | (priv->hsync ? BIT(2) : 0)); /* enable HS/VS encoding, use D14/15 for HS/VS, invert HS/VS */ ++ reg8_write(client, 0x19, 0x0c); /* Drive HSTRAIL state for 120ns after the last payload bit */ ++} ++ ++static void max9286_gmsl_link_setup(struct i2c_client *client, int idx) ++{ ++ struct max9286_priv *priv = i2c_get_clientdata(client); ++ ++ /* GMSL setup */ ++ client->addr = 0x40; /* MAX9271-CAMx I2C */ ++ reg8_write(client, 0x0d, 0x22 | MAXIM_I2C_I2C_SPEED); /* disable artificial ACK, I2C speed set */ ++ reg8_write(client, 0x07, 0x84 | (priv->pclk_rising_edge ? 0 : 0x10)); /* RAW/YUV, PCLK edge, HS/VS encoding enabled */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x02, 0xff); /* spread spectrum +-4%, pclk range automatic, Gbps automatic */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ ++ if (priv->ser_id == MAX96705_ID) { ++ /* setup crossbar in DBL mode: reverse DVP bus */ ++ reg8_write(client, 0x20, 0x07); ++ reg8_write(client, 0x21, 0x06); ++ reg8_write(client, 0x22, 0x05); ++ reg8_write(client, 0x23, 0x04); ++ reg8_write(client, 0x24, 0x03); ++ reg8_write(client, 0x25, 0x02); ++ reg8_write(client, 0x26, 0x01); ++ reg8_write(client, 0x27, 0x00); ++ ++ reg8_write(client, 0x30, 0x17); ++ reg8_write(client, 0x31, 0x16); ++ reg8_write(client, 0x32, 0x15); ++ reg8_write(client, 0x33, 0x14); ++ reg8_write(client, 0x34, 0x13); ++ reg8_write(client, 0x35, 0x12); ++ reg8_write(client, 0x36, 0x11); ++ reg8_write(client, 0x37, 0x10); ++ } ++ ++ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ ++ reg8_write(client, 0x34, 0x22 | MAXIM_I2C_I2C_SPEED); /* disable artificial ACK, I2C speed set */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ ++ /* I2C translator setup */ ++ client->addr = 0x40; /* MAX9271-CAMx I2C */ ++// reg8_write(client, 0x09, maxim_map[2][idx] << 1); /* SENSOR I2C translated - must be set by sensor driver */ ++// reg8_write(client, 0x0A, 0x30 << 1); /* SENSOR I2C native - must be set by sensor driver */ ++ reg8_write(client, 0x0B, BROADCAST << 1); /* broadcast I2C */ ++ reg8_write(client, 0x0C, priv->max9271_addr_map[idx] << 1); /* MAX9271-CAMx I2C new */ ++ /* I2C addresse change */ ++ reg8_write(client, 0x01, priv->des_addr << 1); /* MAX9286 I2C */ ++ reg8_write(client, 0x00, priv->max9271_addr_map[idx] << 1); /* MAX9271-CAM0 I2C new */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ /* put MAX9271 in configuration link state */ ++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C new */ ++ reg8_write(client, 0x04, 0x43); /* enable reverse_control/conf_link */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++#ifdef MAXIM_DUMP ++ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ ++ maxim_max927x_dump_regs(client); ++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C new */ ++ maxim_max927x_dump_regs(client); ++#endif ++} ++ ++static int max9286_initialize(struct i2c_client *client) ++{ ++ struct max9286_priv *priv = i2c_get_clientdata(client); ++ int idx, ret; ++ ++ dev_info(&client->dev, "LINKs=%d, LANES=%d, FSYNC mode=%s, FSYNC period=%d, PCLK edge=%s\n", ++ priv->links, priv->lanes, priv->fsync_mode, priv->fsync_period, ++ priv->pclk_rising_edge ? "rising" : "falling"); ++ ++ if (priv->des_quirk_addr) ++ max9286_preinit(client, priv->des_quirk_addr); ++ ++ max9286_preinit(client, priv->des_addr); ++ max9286_initial_setup(client); ++ ++ for (idx = 0; idx < priv->links; idx++) { ++ if (!IS_ERR(priv->poc_gpio[idx])) { ++ gpiod_direction_output(priv->poc_gpio[idx], 1); /* POC power on */ ++ mdelay(priv->poc_delay); ++ } ++ ++ ret = max9286_reverse_channel_setup(client, idx); ++ if (ret) ++ continue; ++ max9286_gmsl_link_setup(client, idx); ++ } ++ ++ max9286_postinit(client, priv->des_addr); ++ ++ client->addr = priv->des_addr; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int max9286_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct max9286_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ int ret; ++ u8 val = 0; ++ ++ ret = reg8_read(client, (u8)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u8); ++ ++ return 0; ++} ++ ++static int max9286_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct max9286_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ ++ return reg8_write(client, (u8)reg->reg, (u8)reg->val); ++} ++#endif ++ ++static int max9286_s_power(struct v4l2_subdev *sd, int on) ++{ ++ struct max9286_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ ++ if (on) { ++ if (atomic_inc_return(&priv->use_count) == 1) ++ reg8_write(client, 0x69, priv->links_mask ^ 0x0f); /* unmask CSI forwarding from detected links */ ++ } else { ++ if (atomic_dec_return(&priv->use_count) == 0) ++ reg8_write(client, 0x69, 0x0f); /* mask CSI forwarding from all links */ ++ } ++ ++ return 0; ++} ++ ++static int max9286_registered_async(struct v4l2_subdev *sd) ++{ ++ struct max9286_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ int idx, tmp_addr; ++ ++ /* switch to GMSL serial_link for streaming video */ ++ tmp_addr = client->addr; ++ idx = sd->grp_id; ++ ++ client->addr = priv->des_addr; /* MAX9286 I2C */ ++ reg8_write(client, 0x0a, 0x11 << idx); /* enable reverse/forward control for CAMx */ ++ ++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx */ ++ reg8_write(client, 0x04, conf_link ? 0x43 : 0x83); /* enable serial_link */ ++ usleep_range(2000, 2500); /* wait 2ms after changing reverse_control */ ++ ++ client->addr = priv->des_addr; /* MAX9286 I2C */ ++ reg8_write(client, 0x0a, (priv->links_mask << 4) | priv->links_mask); /* enable reverse/forward control for all CAMs */ ++ ++ client->addr = tmp_addr; ++ ++ return 0; ++} ++ ++static struct v4l2_subdev_core_ops max9286_subdev_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = max9286_g_register, ++ .s_register = max9286_s_register, ++#endif ++ .s_power = max9286_s_power, ++ .registered_async = max9286_registered_async, ++}; ++ ++static struct v4l2_subdev_ops max9286_subdev_ops = { ++ .core = &max9286_subdev_core_ops, ++}; ++ ++static int max9286_parse_dt(struct i2c_client *client) ++{ ++ struct max9286_priv *priv = i2c_get_clientdata(client); ++ struct device_node *np = client->dev.of_node; ++ struct device_node *endpoint = NULL; ++ struct property *prop; ++ int err, pwen, i; ++ int sensor_delay, gpio0 = 1, gpio1 = 1; ++ u8 val = 0; ++ char poc_name[10]; ++ ++ if (of_property_read_u32(np, "maxim,links", &priv->links)) ++ priv->links = 4; ++ ++ if (of_property_read_u32(np, "maxim,lanes", &priv->lanes)) ++ priv->lanes = 4; ++ ++ pwen = of_get_gpio(np, 0); ++ if (pwen > 0) { ++ err = gpio_request_one(pwen, GPIOF_OUT_INIT_HIGH, dev_name(&client->dev)); ++ if (err) ++ dev_err(&client->dev, "cannot request PWEN gpio %d: %d\n", pwen, err); ++ } ++ ++ mdelay(250); ++ ++ for (i = 0; i < 4; i++) { ++ sprintf(poc_name, "POC%d", i); ++ priv->poc_gpio[i] = devm_gpiod_get_optional(&client->dev, poc_name, 0); ++ } ++ ++ reg8_read(client, 0x1e, &val); /* read max9286 ID */ ++ if (val != MAX9286_ID) { ++ prop = of_find_property(np, "reg", NULL); ++ if (prop) ++ of_remove_property(np, prop); ++ return -ENODEV; ++ } ++ ++ if (!of_property_read_u32(np, "maxim,gpio0", &gpio0) || ++ !of_property_read_u32(np, "maxim,gpio1", &gpio1)) ++ reg8_write(client, 0x0f, 0x08 | (gpio1 << 1) | gpio0); ++ ++ if (of_property_read_u32(np, "maxim,resetb-gpio", &priv->gpio_resetb)) { ++ priv->gpio_resetb = -1; ++ } else { ++ if (of_property_read_bool(np, "maxim,resetb-active-high")) ++ priv->active_low_resetb = 0; ++ else ++ priv->active_low_resetb = 1; ++ } ++ ++ if (!of_property_read_u32(np, "maxim,sensor_delay", &sensor_delay)) ++ mdelay(sensor_delay); ++ if (of_property_read_string(np, "maxim,fsync-mode", &priv->fsync_mode)) ++ priv->fsync_mode = fsync_mode_default; ++ if (of_property_read_u32(np, "maxim,fsync-period", &priv->fsync_period)) ++ priv->fsync_period = 3200000; /* 96MHz/30fps */ ++ priv->pclk_rising_edge = true; ++ if (of_property_read_bool(np, "maxim,pclk-falling-edge")) ++ priv->pclk_rising_edge = false; ++ if (of_property_read_u32(np, "maxim,timeout", &priv->timeout)) ++ priv->timeout = 100; ++ if (of_property_read_u32(np, "maxim,i2c-quirk", &priv->des_quirk_addr)) ++ priv->des_quirk_addr = 0; ++ if (of_property_read_u32(np, "maxim,him", &priv->him)) ++ priv->him = 0; ++ if (of_property_read_u32(np, "maxim,hsync", &priv->hsync)) ++ priv->hsync = 0; ++ if (of_property_read_u32(np, "maxim,vsync", &priv->vsync)) ++ priv->vsync = 1; ++ if (of_property_read_u32(np, "maxim,poc-delay", &priv->poc_delay)) ++ priv->poc_delay = 50; ++ ++ /* module params override dts */ ++ if (him) ++ priv->him = him; ++ if (fsync_period) { ++ priv->fsync_period = fsync_period; ++ priv->fsync_mode = fsync_mode_default; ++ } ++ if (hsync) ++ priv->hsync = hsync; ++ if (!vsync) ++ priv->vsync = vsync; ++ if (gpio_resetb) ++ priv->gpio_resetb = gpio_resetb; ++ if (active_low_resetb) ++ priv->active_low_resetb = active_low_resetb; ++ if (poc_delay) ++ priv->poc_delay = poc_delay; ++ ++ for (i = 0; i < priv->links; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ if (of_property_read_u32(endpoint, "max9271-addr", &priv->max9271_addr_map[i])) { ++ dev_err(&client->dev, "max9271-addr not set\n"); ++ return -EINVAL; ++ } ++ ++ priv->sd_fwnode[i] = of_fwnode_handle(endpoint); ++ } ++ ++ return 0; ++} ++ ++static void max9286_setup_remote_endpoint(struct i2c_client *client) ++{ ++ struct max9286_priv *priv = i2c_get_clientdata(client); ++ struct device_node *np = client->dev.of_node; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int i; ++ struct property *csi_rate_prop, *dvp_order_prop; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ csi_rate_prop = of_find_property(endpoint, "csi-rate", NULL); ++ if (csi_rate_prop) { ++ /* CSI2_RATE = PCLK*sizeof(YUV8)*links/lanes */ ++ priv->csi_rate = cpu_to_be32(100 * 8 * hweight8(priv->links_mask) / priv->lanes); ++ csi_rate_prop->value = &priv->csi_rate; ++ of_update_property(rendpoint, csi_rate_prop); ++ } ++ ++ dvp_order_prop = of_find_property(endpoint, "dvp-order", NULL); ++ if (dvp_order_prop) ++ of_update_property(rendpoint, dvp_order_prop); ++ } ++} ++ ++static int max9286_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct max9286_priv *priv; ++ int err, i; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ i2c_set_clientdata(client, priv); ++ priv->des_addr = client->addr; ++ priv->client = client; ++ atomic_set(&priv->use_count, 0); ++ priv->csi2_outord = 0xff; ++ ++ err = max9286_parse_dt(client); ++ if (err) ++ goto out; ++ ++ err = max9286_initialize(client); ++ if (err < 0) ++ goto out; ++ ++ max9286_setup_remote_endpoint(client); ++ ++ for (i = 0; i < 4; i++) { ++ v4l2_subdev_init(&priv->sd[i], &max9286_subdev_ops); ++ priv->sd[i].owner = client->dev.driver->owner; ++ priv->sd[i].dev = &client->dev; ++ priv->sd[i].grp_id = i; ++ v4l2_set_subdevdata(&priv->sd[i], priv); ++ priv->sd[i].fwnode = priv->sd_fwnode[i]; ++ ++ snprintf(priv->sd[i].name, V4L2_SUBDEV_NAME_SIZE, "%s.%d %d-%04x", ++ client->dev.driver->name, i, i2c_adapter_id(client->adapter), ++ client->addr); ++ ++ err = v4l2_async_register_subdev(&priv->sd[i]); ++ if (err < 0) ++ goto out; ++ } ++out: ++ return err; ++} ++ ++static int max9286_remove(struct i2c_client *client) ++{ ++ struct max9286_priv *priv = i2c_get_clientdata(client); ++ int i; ++ ++ for (i = 0; i < 4; i++) { ++ v4l2_async_unregister_subdev(&priv->sd[i]); ++ v4l2_device_unregister_subdev(&priv->sd[i]); ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id max9286_dt_ids[] = { ++ { .compatible = "maxim,max9286" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, max9286_dt_ids); ++ ++static const struct i2c_device_id max9286_id[] = { ++ { "max9286", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, max9286_id); ++ ++static struct i2c_driver max9286_i2c_driver = { ++ .driver = { ++ .name = "max9286", ++ .of_match_table = of_match_ptr(max9286_dt_ids), ++ }, ++ .probe = max9286_probe, ++ .remove = max9286_remove, ++ .id_table = max9286_id, ++}; ++ ++module_i2c_driver(max9286_i2c_driver); ++ ++MODULE_DESCRIPTION("GMSL driver for MAX9286"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/i2c/soc_camera/max9286.h b/drivers/media/i2c/soc_camera/max9286.h +new file mode 100644 +index 0000000..6c2a9e0 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/max9286.h +@@ -0,0 +1,244 @@ ++/* ++ * MAXIM max9286-max9271 GMSL driver include file ++ * ++ * Copyright (C) 2015-2017 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++#ifndef _MAX9286_MAX9271_H ++#define _MAX9286_MAX9271_H ++ ++//#define DEBUG ++#ifdef DEBUG ++//#define WRITE_VERIFY ++#define MAXIM_DUMP ++#undef dev_dbg ++#define dev_dbg dev_info ++#endif ++ ++#define REG8_NUM_RETRIES 1 /* number of read/write retries */ ++#define REG16_NUM_RETRIES 10 /* number of read/write retries */ ++#define MAX9271_ID 0x9 ++#define MAX96705_ID 0x41 ++#define MAX9286_ID 0x40 ++#define BROADCAST 0x6f ++ ++static inline int reg8_read(struct i2c_client *client, u8 reg, u8 *val) ++{ ++ int ret, retries; ++ ++ for (retries = REG8_NUM_RETRIES; retries; retries--) { ++ ret = i2c_smbus_read_byte_data(client, reg); ++ if (!(ret < 0)) ++ break; ++ } ++ ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "read fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } else { ++ *val = ret; ++ } ++ ++ return ret < 0 ? ret : 0; ++} ++ ++static inline int reg8_write(struct i2c_client *client, u8 reg, u8 val) ++{ ++ int ret, retries; ++ ++ for (retries = REG8_NUM_RETRIES; retries; retries--) { ++ ret = i2c_smbus_write_byte_data(client, reg, val); ++ if (!(ret < 0)) ++ break; ++ } ++ ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "write fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } else { ++#ifdef WRITE_VERIFY ++ u8 val2; ++ reg8_read(client, reg, &val2); ++ if (val != val2) ++ dev_err(&client->dev, ++ "write verify mismatch: chip 0x%x reg=0x%x " ++ "0x%x->0x%x\n", client->addr, reg, val, val2); ++#endif ++ } ++ ++ return ret < 0 ? ret : 0; ++} ++ ++static inline int reg16_read(struct i2c_client *client, u16 reg, u8 *val) ++{ ++ int ret, retries; ++ u8 buf[2] = {reg >> 8, reg & 0xff}; ++ ++ for (retries = REG16_NUM_RETRIES; retries; retries--) { ++ ret = i2c_master_send(client, buf, 2); ++ if (ret == 2) { ++ ret = i2c_master_recv(client, buf, 1); ++ if (ret == 1) ++ break; ++ } ++ } ++ ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "read fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } else { ++ *val = buf[0]; ++ } ++ ++ return ret < 0 ? ret : 0; ++} ++ ++static inline int reg16_write(struct i2c_client *client, u16 reg, u8 val) ++{ ++ int ret, retries; ++ u8 buf[3] = {reg >> 8, reg & 0xff, val}; ++ ++ for (retries = REG16_NUM_RETRIES; retries; retries--) { ++ ret = i2c_master_send(client, buf, 3); ++ if (ret == 3) ++ break; ++ } ++ ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "write fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } else { ++#ifdef WRITE_VERIFY ++ u8 val2; ++ reg16_read(client, reg, &val2); ++ if (val != val2) ++ dev_err(&client->dev, ++ "write verify mismatch: chip 0x%x reg=0x%x " ++ "0x%x->0x%x\n", client->addr, reg, val, val2); ++#endif ++ } ++ ++ return ret < 0 ? ret : 0; ++} ++ ++ ++static inline int reg16_read16(struct i2c_client *client, u16 reg, u16 *val) ++{ ++ int ret, retries; ++ u8 buf[2] = {reg >> 8, reg & 0xff}; ++ ++ for (retries = REG8_NUM_RETRIES; retries; retries--) { ++ ret = i2c_master_send(client, buf, 2); ++ if (ret == 2) { ++ ret = i2c_master_recv(client, buf, 2); ++ if (ret == 2) ++ break; ++ } ++ } ++ ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "read fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } else { ++ *val = ((u16)buf[0] << 8) | buf[1]; ++ } ++ ++ return ret < 0 ? ret : 0; ++} ++ ++static inline int reg16_write16(struct i2c_client *client, u16 reg, u16 val) ++{ ++ int ret, retries; ++ u8 buf[4] = {reg >> 8, reg & 0xff, val >> 8, val & 0xff}; ++ ++ for (retries = REG8_NUM_RETRIES; retries; retries--) { ++ ret = i2c_master_send(client, buf, 4); ++ if (ret == 4) ++ break; ++ } ++ ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "write fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } ++ ++ return ret < 0 ? ret : 0; ++} ++ ++ ++#ifdef MAXIM_DUMP ++static void maxim_ovsensor_dump_regs(struct i2c_client *client) ++{ ++ int ret, i; ++ u8 val = 0; ++ u16 regs[] = {0x300a, 0x300b, 0x300c}; ++ ++ dev_dbg(&client->dev, "dump regs 0x%x\n", client->addr); ++ ++ for (i = 0; i < sizeof(regs) / 2; i++) { ++ ret = reg16_read(client, regs[i], &val); ++ if (ret < 0) ++ dev_err(&client->dev, ++ "read fail: chip 0x%x register 0x%02x: %d\n", ++ client->addr, regs[i], ret); ++ printk("0x%02x -> 0x%x\n", regs[i], val); ++ } ++} ++ ++static void maxim_ov10635_dump_format_regs(struct i2c_client *client) ++{ ++ int ret, i; ++ u8 val; ++ u16 regs[] = {0x3003, 0x3004, 0x4300, ++ 0x4605, 0x3621, 0x3702, 0x3703, 0x3704, ++ 0x3802, 0x3803, 0x3806, 0x3807, 0x3808, 0x3809, 0x380a, ++ 0x380b, 0x380c, 0x380d, 0x380e, 0x380f, ++ 0x4606, 0x4607, 0x460a, 0x460b, ++ 0xc488, 0xc489, 0xc48a, 0xc48b, ++ 0xc4cc, 0xc4cd, 0xc4ce, 0xc4cf, 0xc512, 0xc513, ++ 0xc518, 0xc519, 0xc51a, 0xc51b, ++ }; ++ ++ dev_dbg(&client->dev, "dump regs 0x%x\n", client->addr); ++ ++ for (i = 0; i < sizeof(regs) / 2; i++) { ++ ret = reg16_read(client, regs[i], &val); ++ if (ret < 0) ++ dev_err(&client->dev, ++ "read fail: chip 0x%x register 0x%02x: %d\n", ++ client->addr, regs[i], ret); ++ printk("0x%02x -> 0x%x\n", regs[i], val); ++ } ++} ++ ++static void maxim_max927x_dump_regs(struct i2c_client *client) ++{ ++ int ret; ++ u8 reg; ++ ++ dev_dbg(&client->dev, "dump regs 0x%x\n", client->addr); ++ ++ for (reg = 0; reg < 0x20; reg++) { ++ ret = i2c_smbus_read_byte_data(client, reg); ++ if (ret < 0) ++ dev_err(&client->dev, ++ "read fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ printk("0x%02x ", ret); ++ if (((reg + 1) % 0x10) == 0) ++ printk("\n"); ++ } ++} ++#endif /* MAXIM_DUMP */ ++#endif /* _MAX9286_MAX9271_H */ +diff --git a/drivers/media/i2c/soc_camera/ov10635.c b/drivers/media/i2c/soc_camera/ov10635.c +new file mode 100644 +index 0000000..eacf015 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov10635.c +@@ -0,0 +1,760 @@ ++/* ++ * OmniVision ov10635 sensor camera driver ++ * ++ * Copyright (C) 2015-2017 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "max9286.h" ++#include "ov10635.h" ++ ++#define OV10635_I2C_ADDR 0x30 ++ ++#define OV10635_PID 0x300a ++#define OV10635_VER 0x300b ++#define OV10635_VERSION_REG 0xa635 ++#define OV10635_VERSION(pid, ver) (((pid) << 8) | ((ver) & 0xff)) ++ ++struct ov10635_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int subsampling; ++ int fps_denominator; ++ int init_complete; ++ u8 id[6]; ++ int dvp_order; ++ /* serializers */ ++ int max9286_addr; ++ int max9271_addr; ++ int ti964_addr; ++ int ti954_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++}; ++ ++static inline struct ov10635_priv *to_ov10635(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct ov10635_priv, sd); ++} ++ ++static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) ++{ ++ return &container_of(ctrl->handler, struct ov10635_priv, hdl)->sd; ++} ++ ++static void ov10635_s_port(struct i2c_client *client, int fwd_en) ++{ ++ struct ov10635_priv *priv = to_ov10635(client); ++ int tmp_addr; ++ ++ if (priv->max9286_addr) { ++ tmp_addr = client->addr; ++ client->addr = priv->max9286_addr; /* Deserializer I2C address */ ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ client->addr = tmp_addr; ++ }; ++} ++ ++static int ov10635_set_regs(struct i2c_client *client, ++ const struct ov10635_reg *regs, int nr_regs) ++{ ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (reg16_write(client, regs[i].reg, regs[i].val)) { ++ usleep_range(100, 150); /* wait 100ns */ ++ reg16_write(client, regs[i].reg, regs[i].val); ++ } ++ } ++ ++ return 0; ++} ++ ++static int ov10635_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int ov10635_set_window(struct v4l2_subdev *sd, int subsampling) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ ++ /* disable clocks */ ++ reg16_write(client, 0x302e, 0x00); ++ reg16_write(client, 0x301b, 0xff); ++ reg16_write(client, 0x301c, 0xff); ++ reg16_write(client, 0x301a, 0xff); ++ ++ /* setup resolution */ ++ reg16_write(client, 0x3808, priv->rect.width >> 8); ++ reg16_write(client, 0x3809, priv->rect.width & 0xff); ++ reg16_write(client, 0x380a, priv->rect.height >> 8); ++ reg16_write(client, 0x380b, priv->rect.height & 0xff); ++ ++ /* enable/disable subsampling */ ++ reg16_write(client, 0x5005, subsampling ? 0x89 : 0x08); ++ reg16_write(client, 0x3007, subsampling ? 0x02 : 0x01); ++ reg16_write(client, 0x4004, subsampling ? 0x02 : 0x04); ++ ++#if 0 /* This is implemented in VIN via SOC_CAMERA layer, hence skip */ ++ /* horiz crop start */ ++ reg16_write(client, 0x3800, priv->rect.left >> 8); ++ reg16_write(client, 0x3801, priv->rect.left & 0xff); ++ /* horiz crop end */ ++ reg16_write(client, 0x3804, (priv->rect.left + priv->rect.width + 1) >> 8); ++ reg16_write(client, 0x3805, (priv->rect.left + priv->rect.width + 1) & 0xff); ++ /* vert crop start */ ++ reg16_write(client, 0x3802, priv->rect.top >> 8); ++ reg16_write(client, 0x3803, priv->rect.top & 0xff); ++ /* vert crop end */ ++ reg16_write(client, 0x3806, (priv->rect.top + priv->rect.height + 1) >> 8); ++ reg16_write(client, 0x3807, (priv->rect.top + priv->rect.height + 1) & 0xff); ++#endif ++ /* enable clocks */ ++ reg16_write(client, 0x301b, 0xf0); ++ reg16_write(client, 0x301c, 0xf0); ++ reg16_write(client, 0x301a, 0xf0); ++ reg16_write(client, 0x302e, 0x01); ++ ++ return 0; ++}; ++ ++static int ov10635_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int ov10635_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int ov10635_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ ++ return 0; ++} ++ ++static int ov10635_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = OV10635_VERSION_REG >> 8; ++ edid->edid[9] = OV10635_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int ov10635_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ int subsampling = 0; ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > OV10635_MAX_WIDTH) || ++ (rect->top + rect->height > OV10635_MAX_HEIGHT)) ++ *rect = priv->rect; ++ ++ if (rect->width == OV10635_MAX_WIDTH / 2 && ++ rect->height == OV10635_MAX_HEIGHT / 2) ++ subsampling = 1; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ /* change window only for subsampling, crop is done by VIN */ ++ if (subsampling != priv->subsampling) { ++ ov10635_set_window(sd, subsampling); ++ priv->subsampling = subsampling; ++ } ++ ++ return 0; ++} ++ ++static int ov10635_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = OV10635_MAX_WIDTH; ++ sel->r.height = OV10635_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = OV10635_MAX_WIDTH; ++ sel->r.height = OV10635_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ov10635_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++static int ov10635_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ ++ memset(cp, 0, sizeof(struct v4l2_captureparm)); ++ cp->capability = V4L2_CAP_TIMEPERFRAME; ++ cp->timeperframe.numerator = 1; ++ cp->timeperframe.denominator = priv->fps_denominator; ++ ++ return 0; ++} ++ ++static int ov10635_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ int ret = 0; ++ ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ if (cp->extendedmode != 0) ++ return -EINVAL; ++ ++ if (priv->fps_denominator != cp->timeperframe.denominator) { ++ switch (cp->timeperframe.denominator) { ++ case 5: ++ ret = ov10635_set_regs(client, ov10635_regs_5fps, ++ ARRAY_SIZE(ov10635_regs_5fps)); ++ break; ++ case 10: ++ ret = ov10635_set_regs(client, ov10635_regs_10fps, ++ ARRAY_SIZE(ov10635_regs_10fps)); ++ break; ++ case 15: ++ ret = ov10635_set_regs(client, ov10635_regs_15fps, ++ ARRAY_SIZE(ov10635_regs_15fps)); ++ break; ++ case 30: ++ ret = ov10635_set_regs(client, ov10635_regs_30fps, ++ ARRAY_SIZE(ov10635_regs_30fps)); ++ break; ++ default: ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ priv->fps_denominator = cp->timeperframe.denominator; ++ } ++ ++out: ++ return ret; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int ov10635_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u8 val = 0; ++ ++ ret = reg16_read(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int ov10635_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return reg16_write(client, (u16)reg->reg, (u8)reg->val); ++} ++#endif ++ ++static struct v4l2_subdev_core_ops ov10635_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ov10635_g_register, ++ .s_register = ov10635_s_register, ++#endif ++}; ++ ++static int ov10635_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ int ret = -EINVAL; ++ u8 val = 0; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ /* AEC/AGC target */ ++ ret = reg16_write(client, 0xc46a, ctrl->val); ++ break; ++ case V4L2_CID_CONTRAST: ++ udelay(100); ++ ret = ov10635_set_regs(client, &ov10635_regs_contrast[ctrl->val][0], 18); ++ break; ++ case V4L2_CID_SATURATION: ++ ret = reg16_write(client, 0xc316, ctrl->val); ++ break; ++ case V4L2_CID_HUE: ++ /* CMX ? */ ++ ret = 0; ++ break; ++ case V4L2_CID_GAMMA: ++ ret = reg16_write(client, 0xc4be, ctrl->val >> 8); ++ ret |= reg16_write(client, 0xc4bf, ctrl->val & 0xff); ++ break; ++ case V4L2_CID_AUTOGAIN: ++ /* automatic gain/exposure */ ++ ret = reg16_write(client, 0x56d0, !ctrl->val); ++ break; ++ case V4L2_CID_GAIN: ++ /* manual gain */ ++ ret = reg16_write(client, 0x3504, 0); ++ ret |= reg16_write(client, 0x56d1, ctrl->val >> 8); ++ ret |= reg16_write(client, 0x56d2, ctrl->val & 0xff); ++ ret |= reg16_write(client, 0x3504, 1); /* validate gain */ ++ break; ++ case V4L2_CID_EXPOSURE: ++ /* manual exposure */ ++ ret = reg16_write(client, 0x3504, 0); ++ ret |= reg16_write(client, 0x56d5, ctrl->val >> 8); ++ ret |= reg16_write(client, 0x56d6, ctrl->val & 0xff); ++ ret |= reg16_write(client, 0x3504, 1); /* validate exposure */ ++ break; ++ case V4L2_CID_HFLIP: ++ ret = reg16_read(client, 0x381d, &val); ++ if (ret < 0) ++ goto out; ++ if (ctrl->val) ++ val |= 0x3; ++ else ++ val &= ~0x3; ++ ret = reg16_write(client, 0x381d, val); ++ break; ++ case V4L2_CID_VFLIP: ++ ret = reg16_read(client, 0x381c, &val); ++ if (ctrl->val) ++ val |= 0xc0; ++ else ++ val &= ~0xc0; ++ ret = reg16_write(client, 0x381c, val); ++ break; ++ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: ++ ret = 0; ++ break; ++ } ++ ++out: ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ov10635_ctrl_ops = { ++ .s_ctrl = ov10635_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops ov10635_video_ops = { ++ .s_stream = ov10635_s_stream, ++ .g_mbus_config = ov10635_g_mbus_config, ++ .g_parm = ov10635_g_parm, ++ .s_parm = ov10635_s_parm, ++}; ++ ++static const struct v4l2_subdev_pad_ops ov10635_subdev_pad_ops = { ++ .get_edid = ov10635_get_edid, ++ .enum_mbus_code = ov10635_enum_mbus_code, ++ .get_selection = ov10635_get_selection, ++ .set_selection = ov10635_set_selection, ++ .get_fmt = ov10635_get_fmt, ++ .set_fmt = ov10635_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops ov10635_subdev_ops = { ++ .core = &ov10635_core_ops, ++ .video = &ov10635_video_ops, ++ .pad = &ov10635_subdev_pad_ops, ++}; ++ ++static void ov10635_otp_id_read(struct i2c_client *client) ++{ ++ struct ov10635_priv *priv = to_ov10635(client); ++ int i; ++ ++ /* read camera id from OTP memory */ ++ reg16_write(client, 0x3d10, 1); ++ ++ usleep_range(15000, 16000); /* wait 15ms */ ++ ++ for (i = 0; i < 6; i++) ++ reg16_read(client, 0x3d00 + i, &priv->id[i]); ++} ++ ++static ssize_t ov10635_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_ov10635, S_IRUGO, ov10635_otp_id_show, NULL); ++ ++static int ov10635_initialize(struct i2c_client *client) ++{ ++ struct ov10635_priv *priv = to_ov10635(client); ++ u8 pid = 0, ver = 0; ++ int ret = 0; ++ ++ ov10635_s_port(client, 1); ++ ++ /* check and show product ID and manufacturer ID */ ++ reg16_read(client, OV10635_PID, &pid); ++ reg16_read(client, OV10635_VER, &ver); ++ ++ if (OV10635_VERSION(pid, ver) != OV10635_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x:%x\n", pid, ver); ++ ret = -ENODEV; ++ goto out; ++ } ++ ++ /* s/w reset sensor */ ++ reg16_write(client, 0x103, 0x1); ++ udelay(100); ++ /* Program wizard registers */ ++ ov10635_set_regs(client, ov10635_regs_wizard, ARRAY_SIZE(ov10635_regs_wizard)); ++ /* Set DVP bit swap */ ++ reg16_write(client, 0x4709, priv->dvp_order << 4); ++ /* Read OTP IDs */ ++ ov10635_otp_id_read(client); ++ ++ dev_info(&client->dev, "ov10635 Product ID %x Manufacturer ID %x OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, ver, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++out: ++ ov10635_s_port(client, 0); ++ ++ return ret; ++} ++ ++static int ov10635_parse_dt(struct device_node *np, struct ov10635_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order); ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti964-ti9x3") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti964_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti954-ti9x3") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti954_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ if (!priv->max9286_addr && !priv->ti964_addr && !priv->ti954_addr) { ++ dev_err(&client->dev, "deserializer does not present for OV10635\n"); ++ return -EINVAL; ++ } ++ ++ ov10635_s_port(client, 1); ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ ++ reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x0A, OV10635_I2C_ADDR << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ ++ if (priv->ti964_addr) { ++ client->addr = priv->ti964_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, OV10635_I2C_ADDR << 1); /* Sensor native I2C address */ ++ ++ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - resetb, GPIO1 - fsin */ ++ } ++ ++ if (priv->ti954_addr) { ++ client->addr = priv->ti954_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, OV10635_I2C_ADDR << 1); /* Sensor native I2C address */ ++ ++ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - resetb, GPIO1 - fsin */ ++ } ++ client->addr = tmp_addr; ++ ++ udelay(100); ++ ++ return 0; ++} ++ ++static int ov10635_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ov10635_priv *priv; ++ struct v4l2_ctrl *ctrl; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &ov10635_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = OV10635_MAX_WIDTH; ++ priv->rect.height = OV10635_MAX_HEIGHT; ++ priv->fps_denominator = 30; ++ ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 0xff, 1, 0x30); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 4, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 0xff, 1, 0xff); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_HUE, 0, 255, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_GAMMA, 0, 0xffff, 1, 0x233); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0x3ff, 1, 0x10); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, 0x80); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 9); ++ if (ctrl) ++ ctrl->flags &= ~V4L2_CTRL_FLAG_READ_ONLY; ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = ov10635_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = ov10635_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ov10635) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_OV10635 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int ov10635_remove(struct i2c_client *client) ++{ ++ struct ov10635_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ov10635); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_OV10635 ++static const struct i2c_device_id ov10635_id[] = { ++ { "ov10635", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ov10635_id); ++ ++static const struct of_device_id ov10635_of_ids[] = { ++ { .compatible = "ovti,ov10635", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ov10635_of_ids); ++ ++static struct i2c_driver ov10635_i2c_driver = { ++ .driver = { ++ .name = "ov10635", ++ .of_match_table = ov10635_of_ids, ++ }, ++ .probe = ov10635_probe, ++ .remove = ov10635_remove, ++ .id_table = ov10635_id, ++}; ++ ++module_i2c_driver(ov10635_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for OV10635"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/ov10635.h b/drivers/media/i2c/soc_camera/ov10635.h +new file mode 100644 +index 0000000..a0e510d +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov10635.h +@@ -0,0 +1,1139 @@ ++/* ++ * OmniVision ov10635 sensor camera wizard 1280x800@30/UYVY/BT601/8bit ++ * ++ * Copyright (C) 2015-2017 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++//#define OV10635_DISPLAY_PATTERN ++ ++#define OV10635_SENSOR_WIDTH 1312 ++#define OV10635_SENSOR_HEIGHT 814 ++ ++#define OV10635_MAX_WIDTH 1280 ++#define OV10635_MAX_HEIGHT 800 ++ ++//#define OV10635_PCLK_96MHZ ++#define OV10635_PCLK_88MHZ ++ ++#if defined(OV10635_PCLK_96MHZ) ++/* VTS=PCLK/FPS/HTS/2 (=96MHz/30/1600/2) */ ++ #define OV10635_HTS 1600 ++ #define OV10635_VTS 1000 /* fps=30 */ ++#elif defined(OV10635_PCLK_88MHZ) ++/* VTS=PCLK/FPS/HTS/2 (=88MHz/1572/30/2) */ ++ #define OV10635_HTS 1572 ++ #define OV10635_VTS 933 /* fps=29.9998 */ ++#else ++ #error PCLK not defined ++#endif ++ ++struct ov10635_reg { ++ u16 reg; ++ u8 val; ++}; ++ ++static const struct ov10635_reg ov10635_regs_wizard[] = { ++//{0x0103, 0x01}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x301B, 0xFF}, ++{0x301C, 0xFF}, ++{0x301A, 0xFF}, ++{0x3011, 0x42}, ++{0x6900, 0x0C}, ++{0x6901, 0x19}, ++{0x3503, 0x10}, ++{0x3025, 0x03}, ++#if defined(OV10635_PCLK_96MHZ) ++{0x3003, 0x20}, ++{0x3004, 0x21}, ++#elif defined(OV10635_PCLK_88MHZ) ++{0x3003, 0x16}, ++{0x3004, 0x30}, ++#endif ++{0x3005, 0x40}, ++{0x3006, 0x91}, ++{0x3600, 0x74}, ++{0x3601, 0x2B}, ++{0x3612, 0x00}, ++{0x3611, 0x67}, ++{0x3633, 0xCA}, ++{0x3602, 0xAF}, ++{0x3603, 0x04}, ++{0x3630, 0x28}, ++{0x3631, 0x16}, ++{0x3714, 0x10}, ++{0x371D, 0x01}, ++{0x4300, 0x3A}, ++{0x3007, 0x01}, ++{0x3024, 0x03}, ++{0x3020, 0x0A}, ++{0x3702, 0x0D}, ++{0x3703, 0x20}, ++{0x3704, 0x15}, ++{0x3709, 0xA8}, ++{0x370C, 0xC7}, ++{0x370D, 0x80}, ++{0x3712, 0x00}, ++{0x3713, 0x20}, ++{0x3715, 0x04}, ++{0x381D, 0x40}, ++{0x381C, 0x00}, ++{0x3822, 0x50}, ++{0x3824, 0x10}, ++{0x3815, 0x8C}, ++{0x3804, 0x05}, ++{0x3805, 0x1F}, ++{0x3800, 0x00}, ++{0x3801, 0x00}, ++{0x3806, 0x03}, ++{0x3807, 0x28}, ++{0x3802, 0x00}, ++{0x3803, 0x07}, ++{0x3808, 0x05}, ++{0x3809, 0x00}, ++{0x380A, 0x03}, ++{0x380B, 0x20}, ++{0x380C, OV10635_HTS >> 8}, ++{0x380D, OV10635_HTS & 0xff}, ++{0x380E, OV10635_VTS >> 8}, ++{0x380F, OV10635_VTS & 0xff}, ++{0x3813, 0x02}, ++{0x3811, 0x08}, ++{0x381F, 0x0C}, ++{0x3819, 0x04}, ++{0x3804, 0x01}, ++{0x3805, 0x00}, ++{0x3828, 0x03}, ++{0x3829, 0x10}, ++{0x382A, 0x10}, ++{0x3621, 0x63}, ++{0x5005, 0x08}, ++{0x56D5, 0x00}, ++{0x56D6, 0x80}, ++{0x56D7, 0x00}, ++{0x56D8, 0x00}, ++{0x56D9, 0x00}, ++{0x56DA, 0x80}, ++{0x56DB, 0x00}, ++{0x56DC, 0x00}, ++{0x56E8, 0x00}, ++{0x56E9, 0x7F}, ++{0x56EA, 0x00}, ++{0x56EB, 0x7F}, ++{0x5100, 0x00}, ++{0x5101, 0x80}, ++{0x5102, 0x00}, ++{0x5103, 0x80}, ++{0x5104, 0x00}, ++{0x5105, 0x80}, ++{0x5106, 0x00}, ++{0x5107, 0x80}, ++{0x5108, 0x00}, ++{0x5109, 0x00}, ++{0x510A, 0x00}, ++{0x510B, 0x00}, ++{0x510C, 0x00}, ++{0x510D, 0x00}, ++{0x510E, 0x00}, ++{0x510F, 0x00}, ++{0x5110, 0x00}, ++{0x5111, 0x80}, ++{0x5112, 0x00}, ++{0x5113, 0x80}, ++{0x5114, 0x00}, ++{0x5115, 0x80}, ++{0x5116, 0x00}, ++{0x5117, 0x80}, ++{0x5118, 0x00}, ++{0x5119, 0x00}, ++{0x511A, 0x00}, ++{0x511B, 0x00}, ++{0x511C, 0x00}, ++{0x511D, 0x00}, ++{0x511E, 0x00}, ++{0x511F, 0x00}, ++{0x56D0, 0x00}, ++{0x5006, 0x04}, ++{0x5608, 0x05}, ++{0x52D7, 0x06}, ++{0x528D, 0x08}, ++{0x5293, 0x12}, ++{0x52D3, 0x12}, ++{0x5288, 0x06}, ++{0x5289, 0x20}, ++{0x52C8, 0x06}, ++{0x52C9, 0x20}, ++{0x52CD, 0x04}, ++{0x5381, 0x00}, ++{0x5382, 0xFF}, ++{0x5589, 0x76}, ++{0x558A, 0x47}, ++{0x558B, 0xEF}, ++{0x558C, 0xC9}, ++{0x558D, 0x49}, ++{0x558E, 0x30}, ++{0x558F, 0x67}, ++{0x5590, 0x3F}, ++{0x5591, 0xF0}, ++{0x5592, 0x10}, ++{0x55A2, 0x6D}, ++{0x55A3, 0x55}, ++{0x55A4, 0xC3}, ++{0x55A5, 0xB5}, ++{0x55A6, 0x43}, ++{0x55A7, 0x38}, ++{0x55A8, 0x5F}, ++{0x55A9, 0x4B}, ++{0x55AA, 0xF0}, ++{0x55AB, 0x10}, ++{0x5581, 0x52}, ++{0x5300, 0x01}, ++{0x5301, 0x00}, ++{0x5302, 0x00}, ++{0x5303, 0x0E}, ++{0x5304, 0x00}, ++{0x5305, 0x0E}, ++{0x5306, 0x00}, ++{0x5307, 0x36}, ++{0x5308, 0x00}, ++{0x5309, 0xD9}, ++{0x530A, 0x00}, ++{0x530B, 0x0F}, ++{0x530C, 0x00}, ++{0x530D, 0x2C}, ++{0x530E, 0x00}, ++{0x530F, 0x59}, ++{0x5310, 0x00}, ++{0x5311, 0x7B}, ++{0x5312, 0x00}, ++{0x5313, 0x22}, ++{0x5314, 0x00}, ++{0x5315, 0xD5}, ++{0x5316, 0x00}, ++{0x5317, 0x13}, ++{0x5318, 0x00}, ++{0x5319, 0x18}, ++{0x531A, 0x00}, ++{0x531B, 0x26}, ++{0x531C, 0x00}, ++{0x531D, 0xDC}, ++{0x531E, 0x00}, ++{0x531F, 0x02}, ++{0x5320, 0x00}, ++{0x5321, 0x24}, ++{0x5322, 0x00}, ++{0x5323, 0x56}, ++{0x5324, 0x00}, ++{0x5325, 0x85}, ++{0x5326, 0x00}, ++{0x5327, 0x20}, ++{0x5609, 0x01}, ++{0x560A, 0x40}, ++{0x560B, 0x01}, ++{0x560C, 0x40}, ++{0x560D, 0x00}, ++{0x560E, 0xFA}, ++{0x560F, 0x00}, ++{0x5610, 0xFA}, ++{0x5611, 0x02}, ++{0x5612, 0x80}, ++{0x5613, 0x02}, ++{0x5614, 0x80}, ++{0x5615, 0x01}, ++{0x5616, 0x2C}, ++{0x5617, 0x01}, ++{0x5618, 0x2C}, ++{0x563B, 0x01}, ++{0x563C, 0x01}, ++{0x563D, 0x01}, ++{0x563E, 0x01}, ++{0x563F, 0x03}, ++{0x5640, 0x03}, ++{0x5641, 0x03}, ++{0x5642, 0x05}, ++{0x5643, 0x09}, ++{0x5644, 0x05}, ++{0x5645, 0x05}, ++{0x5646, 0x05}, ++{0x5647, 0x05}, ++{0x5651, 0x00}, ++{0x5652, 0x80}, ++{0x521A, 0x01}, ++{0x521B, 0x03}, ++{0x521C, 0x06}, ++{0x521D, 0x0A}, ++{0x521E, 0x0E}, ++{0x521F, 0x12}, ++{0x5220, 0x16}, ++{0x5223, 0x02}, ++{0x5225, 0x04}, ++{0x5227, 0x08}, ++{0x5229, 0x0C}, ++{0x522B, 0x12}, ++{0x522D, 0x18}, ++{0x522F, 0x1E}, ++{0x5241, 0x04}, ++{0x5242, 0x01}, ++{0x5243, 0x03}, ++{0x5244, 0x06}, ++{0x5245, 0x0A}, ++{0x5246, 0x0E}, ++{0x5247, 0x12}, ++{0x5248, 0x16}, ++{0x524A, 0x03}, ++{0x524C, 0x04}, ++{0x524E, 0x08}, ++{0x5250, 0x0C}, ++{0x5252, 0x12}, ++{0x5254, 0x18}, ++{0x5256, 0x1E}, ++{0x4606, (2*OV10635_HTS) >> 8}, /* fifo_line_length = 2*hts */ ++{0x4607, (2*OV10635_HTS) & 0xff}, ++{0x460a, (2*(OV10635_HTS-OV10635_MAX_WIDTH)) >> 8}, /* fifo_hsync_start = 2*(hts - xres) */ ++{0x460b, (2*(OV10635_HTS-OV10635_MAX_WIDTH)) & 0xff }, ++{0x460C, 0x00}, ++{0x4620, 0x0E}, ++#if 0 ++{0x4700, 0x02}, // BT656: mode is acceptable but artefact lines on left/bottom due to BT656 SAV/EAV are parsed as image data ++#else ++{0x4700, 0x04}, // BT601: 0x08 is also accaptable as HS/VS mode ++#endif ++{0x4701, 0x00}, ++{0x4702, 0x01}, ++{0x4004, 0x04}, ++{0x4005, 0x18}, ++{0x4001, 0x06}, ++{0x4050, 0x22}, ++{0x4051, 0x24}, ++{0x4052, 0x02}, ++{0x4057, 0x9C}, ++{0x405A, 0x00}, ++{0x4202, 0x02}, ++{0x3023, 0x10}, ++{0x0100, 0x01}, ++{0x0100, 0x01}, ++{0x6F10, 0x07}, ++{0x6F11, 0x82}, ++{0x6F12, 0x04}, ++{0x6F13, 0x00}, ++{0xD000, 0x19}, ++{0xD001, 0xA0}, ++{0xD002, 0x00}, ++{0xD003, 0x01}, ++{0xD004, 0xA9}, ++{0xD005, 0xAD}, ++{0xD006, 0x10}, ++{0xD007, 0x40}, ++{0xD008, 0x44}, ++{0xD009, 0x00}, ++{0xD00A, 0x68}, ++{0xD00B, 0x00}, ++{0xD00C, 0x15}, ++{0xD00D, 0x00}, ++{0xD00E, 0x00}, ++{0xD00F, 0x00}, ++{0xD040, 0x9C}, ++{0xD041, 0x21}, ++{0xD042, 0xFF}, ++{0xD043, 0xF8}, ++{0xD044, 0xD4}, ++{0xD045, 0x01}, ++{0xD046, 0x48}, ++{0xD047, 0x00}, ++{0xD048, 0xD4}, ++{0xD049, 0x01}, ++{0xD04A, 0x50}, ++{0xD04B, 0x04}, ++{0xD04C, 0x18}, ++{0xD04D, 0x60}, ++{0xD04E, 0x00}, ++{0xD04F, 0x01}, ++{0xD050, 0xA8}, ++{0xD051, 0x63}, ++{0xD052, 0x02}, ++{0xD053, 0xA4}, ++{0xD054, 0x85}, ++{0xD055, 0x43}, ++{0xD056, 0x00}, ++{0xD057, 0x00}, ++{0xD058, 0x18}, ++{0xD059, 0x60}, ++{0xD05A, 0x00}, ++{0xD05B, 0x01}, ++{0xD05C, 0xA8}, ++{0xD05D, 0x63}, ++{0xD05E, 0x03}, ++{0xD05F, 0xF0}, ++{0xD060, 0x98}, ++{0xD061, 0xA3}, ++{0xD062, 0x00}, ++{0xD063, 0x00}, ++{0xD064, 0x8C}, ++{0xD065, 0x6A}, ++{0xD066, 0x00}, ++{0xD067, 0x6E}, ++{0xD068, 0xE5}, ++{0xD069, 0x85}, ++{0xD06A, 0x18}, ++{0xD06B, 0x00}, ++{0xD06C, 0x10}, ++{0xD06D, 0x00}, ++{0xD06E, 0x00}, ++{0xD06F, 0x10}, ++{0xD070, 0x9C}, ++{0xD071, 0x80}, ++{0xD072, 0x00}, ++{0xD073, 0x03}, ++{0xD074, 0x18}, ++{0xD075, 0x60}, ++{0xD076, 0x00}, ++{0xD077, 0x01}, ++{0xD078, 0xA8}, ++{0xD079, 0x63}, ++{0xD07A, 0x07}, ++{0xD07B, 0x80}, ++{0xD07C, 0x07}, ++{0xD07D, 0xFF}, ++{0xD07E, 0xF9}, ++{0xD07F, 0x03}, ++{0xD080, 0x8C}, ++{0xD081, 0x63}, ++{0xD082, 0x00}, ++{0xD083, 0x00}, ++{0xD084, 0xA5}, ++{0xD085, 0x6B}, ++{0xD086, 0x00}, ++{0xD087, 0xFF}, ++{0xD088, 0x18}, ++{0xD089, 0x80}, ++{0xD08A, 0x00}, ++{0xD08B, 0x01}, ++{0xD08C, 0xA8}, ++{0xD08D, 0x84}, ++{0xD08E, 0x01}, ++{0xD08F, 0x04}, ++{0xD090, 0xE1}, ++{0xD091, 0x6B}, ++{0xD092, 0x58}, ++{0xD093, 0x00}, ++{0xD094, 0x94}, ++{0xD095, 0x6A}, ++{0xD096, 0x00}, ++{0xD097, 0x70}, ++{0xD098, 0xE1}, ++{0xD099, 0x6B}, ++{0xD09A, 0x20}, ++{0xD09B, 0x00}, ++{0xD09C, 0x95}, ++{0xD09D, 0x6B}, ++{0xD09E, 0x00}, ++{0xD09F, 0x00}, ++{0xD0A0, 0xE4}, ++{0xD0A1, 0x8B}, ++{0xD0A2, 0x18}, ++{0xD0A3, 0x00}, ++{0xD0A4, 0x0C}, ++{0xD0A5, 0x00}, ++{0xD0A6, 0x00}, ++{0xD0A7, 0x23}, ++{0xD0A8, 0x15}, ++{0xD0A9, 0x00}, ++{0xD0AA, 0x00}, ++{0xD0AB, 0x00}, ++{0xD0AC, 0x18}, ++{0xD0AD, 0x60}, ++{0xD0AE, 0x80}, ++{0xD0AF, 0x06}, ++{0xD0B0, 0xA8}, ++{0xD0B1, 0x83}, ++{0xD0B2, 0x40}, ++{0xD0B3, 0x08}, ++{0xD0B4, 0xA8}, ++{0xD0B5, 0xE3}, ++{0xD0B6, 0x38}, ++{0xD0B7, 0x2A}, ++{0xD0B8, 0xA8}, ++{0xD0B9, 0xC3}, ++{0xD0BA, 0x40}, ++{0xD0BB, 0x09}, ++{0xD0BC, 0xA8}, ++{0xD0BD, 0xA3}, ++{0xD0BE, 0x38}, ++{0xD0BF, 0x29}, ++{0xD0C0, 0x8C}, ++{0xD0C1, 0x65}, ++{0xD0C2, 0x00}, ++{0xD0C3, 0x00}, ++{0xD0C4, 0xD8}, ++{0xD0C5, 0x04}, ++{0xD0C6, 0x18}, ++{0xD0C7, 0x00}, ++{0xD0C8, 0x8C}, ++{0xD0C9, 0x67}, ++{0xD0CA, 0x00}, ++{0xD0CB, 0x00}, ++{0xD0CC, 0xD8}, ++{0xD0CD, 0x06}, ++{0xD0CE, 0x18}, ++{0xD0CF, 0x00}, ++{0xD0D0, 0x18}, ++{0xD0D1, 0x60}, ++{0xD0D2, 0x80}, ++{0xD0D3, 0x06}, ++{0xD0D4, 0xA8}, ++{0xD0D5, 0xE3}, ++{0xD0D6, 0x67}, ++{0xD0D7, 0x02}, ++{0xD0D8, 0xA9}, ++{0xD0D9, 0x03}, ++{0xD0DA, 0x67}, ++{0xD0DB, 0x03}, ++{0xD0DC, 0xA8}, ++{0xD0DD, 0xC3}, ++{0xD0DE, 0x3D}, ++{0xD0DF, 0x05}, ++{0xD0E0, 0x8C}, ++{0xD0E1, 0x66}, ++{0xD0E2, 0x00}, ++{0xD0E3, 0x00}, ++{0xD0E4, 0xB8}, ++{0xD0E5, 0x63}, ++{0xD0E6, 0x00}, ++{0xD0E7, 0x18}, ++{0xD0E8, 0xB8}, ++{0xD0E9, 0x63}, ++{0xD0EA, 0x00}, ++{0xD0EB, 0x98}, ++{0xD0EC, 0xBC}, ++{0xD0ED, 0x03}, ++{0xD0EE, 0x00}, ++{0xD0EF, 0x00}, ++{0xD0F0, 0x10}, ++{0xD0F1, 0x00}, ++{0xD0F2, 0x00}, ++{0xD0F3, 0x16}, ++{0xD0F4, 0xB8}, ++{0xD0F5, 0x83}, ++{0xD0F6, 0x00}, ++{0xD0F7, 0x19}, ++{0xD0F8, 0x8C}, ++{0xD0F9, 0x67}, ++{0xD0FA, 0x00}, ++{0xD0FB, 0x00}, ++{0xD0FC, 0xB8}, ++{0xD0FD, 0xA4}, ++{0xD0FE, 0x00}, ++{0xD0FF, 0x98}, ++{0xD100, 0xB8}, ++{0xD101, 0x83}, ++{0xD102, 0x00}, ++{0xD103, 0x08}, ++{0xD104, 0x8C}, ++{0xD105, 0x68}, ++{0xD106, 0x00}, ++{0xD107, 0x00}, ++{0xD108, 0xE0}, ++{0xD109, 0x63}, ++{0xD10A, 0x20}, ++{0xD10B, 0x04}, ++{0xD10C, 0xE0}, ++{0xD10D, 0x65}, ++{0xD10E, 0x18}, ++{0xD10F, 0x00}, ++{0xD110, 0xA4}, ++{0xD111, 0x83}, ++{0xD112, 0xFF}, ++{0xD113, 0xFF}, ++{0xD114, 0xB8}, ++{0xD115, 0x64}, ++{0xD116, 0x00}, ++{0xD117, 0x48}, ++{0xD118, 0xD8}, ++{0xD119, 0x07}, ++{0xD11A, 0x18}, ++{0xD11B, 0x00}, ++{0xD11C, 0xD8}, ++{0xD11D, 0x08}, ++{0xD11E, 0x20}, ++{0xD11F, 0x00}, ++{0xD120, 0x9C}, ++{0xD121, 0x60}, ++{0xD122, 0x00}, ++{0xD123, 0x00}, ++{0xD124, 0xD8}, ++{0xD125, 0x06}, ++{0xD126, 0x18}, ++{0xD127, 0x00}, ++{0xD128, 0x00}, ++{0xD129, 0x00}, ++{0xD12A, 0x00}, ++{0xD12B, 0x08}, ++{0xD12C, 0x15}, ++{0xD12D, 0x00}, ++{0xD12E, 0x00}, ++{0xD12F, 0x00}, ++{0xD130, 0x8C}, ++{0xD131, 0x6A}, ++{0xD132, 0x00}, ++{0xD133, 0x76}, ++{0xD134, 0xBC}, ++{0xD135, 0x23}, ++{0xD136, 0x00}, ++{0xD137, 0x00}, ++{0xD138, 0x13}, ++{0xD139, 0xFF}, ++{0xD13A, 0xFF}, ++{0xD13B, 0xE6}, ++{0xD13C, 0x18}, ++{0xD13D, 0x60}, ++{0xD13E, 0x80}, ++{0xD13F, 0x06}, ++{0xD140, 0x03}, ++{0xD141, 0xFF}, ++{0xD142, 0xFF}, ++{0xD143, 0xDD}, ++{0xD144, 0xA8}, ++{0xD145, 0x83}, ++{0xD146, 0x40}, ++{0xD147, 0x08}, ++{0xD148, 0x85}, ++{0xD149, 0x21}, ++{0xD14A, 0x00}, ++{0xD14B, 0x00}, ++{0xD14C, 0x85}, ++{0xD14D, 0x41}, ++{0xD14E, 0x00}, ++{0xD14F, 0x04}, ++{0xD150, 0x44}, ++{0xD151, 0x00}, ++{0xD152, 0x48}, ++{0xD153, 0x00}, ++{0xD154, 0x9C}, ++{0xD155, 0x21}, ++{0xD156, 0x00}, ++{0xD157, 0x08}, ++{0x6F0E, 0x03}, ++{0x6F0F, 0x00}, ++{0x460E, 0x08}, ++{0x460F, 0x01}, ++{0x4610, 0x00}, ++{0x4611, 0x01}, ++{0x4612, 0x00}, ++{0x4613, 0x01}, ++{0x4605, 0x08}, // 8bit ++//{0x4709, 0x10}, // swap data bits order [9:0] -> [0:9] ++{0x4608, 0x00}, ++{0x4609, 0x08}, ++{0x6804, 0x00}, ++{0x6805, 0x06}, ++{0x6806, 0x00}, ++{0x5120, 0x00}, ++{0x3510, 0x00}, ++{0x3504, 0x00}, ++{0x6800, 0x00}, ++{0x6F0D, 0x01}, ++{0x4708, 0x01}, // PCLK rising edge ++{0x5000, 0xFF}, ++{0x5001, 0xBF}, ++{0x5002, 0x7E}, ++#ifdef OV10635_DISPLAY_PATTERN ++{0x503d, 0x80}, ++#else ++{0x503D, 0x00}, ++#endif ++{0xC450, 0x01}, /* AA mode */ ++{0xC452, 0x04}, ++{0xC453, 0x00}, ++{0xC454, 0x00}, ++{0xC455, 0x01}, ++{0xC456, 0x01}, ++{0xC457, 0x00}, ++{0xC458, 0x00}, ++{0xC459, 0x00}, ++{0xC45B, 0x00}, ++{0xC45C, 0x01}, ++{0xC45D, 0x00}, ++{0xC45E, 0x00}, ++{0xC45F, 0x00}, ++{0xC460, 0x00}, ++{0xC461, 0x01}, ++{0xC462, 0x01}, ++{0xC464, 0x03}, ++{0xC465, 0x00}, ++{0xC466, 0x8A}, ++{0xC467, 0x00}, ++{0xC468, 0x86}, ++{0xC469, 0x00}, ++{0xC46A, 0x30}, ++{0xC46B, 0x50}, ++{0xC46C, 0x30}, ++{0xC46D, 0x28}, ++{0xC46E, 0x60}, ++{0xC46F, 0x40}, ++{0xC47C, 0x01}, ++{0xC47D, 0x38}, ++{0xC47E, 0x00}, ++{0xC47F, 0x00}, ++{0xC480, 0x00}, ++{0xC481, 0xFF}, ++{0xC482, 0x00}, ++{0xC483, 0x40}, ++{0xC484, 0x00}, ++{0xC485, 0x18}, ++{0xC486, 0x00}, ++{0xC487, 0x18}, ++{0xC488, (OV10635_VTS-8)*16 >> 8}, ++{0xC489, (OV10635_VTS-8)*16 & 0xff}, ++{0xC48A, (OV10635_VTS-8)*16 >> 8}, ++{0xC48B, (OV10635_VTS-8)*16 & 0xff}, ++{0xC48C, 0x00}, ++{0xC48D, 0x04}, ++{0xC48E, 0x00}, ++{0xC48F, 0x04}, ++{0xC490, 0x03}, ++{0xC492, 0x20}, ++{0xC493, 0x08}, ++{0xC498, 0x02}, ++{0xC499, 0x00}, ++{0xC49A, 0x02}, ++{0xC49B, 0x00}, ++{0xC49C, 0x02}, ++{0xC49D, 0x00}, ++{0xC49E, 0x02}, ++{0xC49F, 0x60}, ++{0xC4A0, 0x03}, ++{0xC4A1, 0x00}, ++{0xC4A2, 0x04}, ++{0xC4A3, 0x00}, ++{0xC4A4, 0x00}, ++{0xC4A5, 0x10}, ++{0xC4A6, 0x00}, ++{0xC4A7, 0x40}, ++{0xC4A8, 0x00}, ++{0xC4A9, 0x80}, ++{0xC4AA, 0x0D}, ++{0xC4AB, 0x00}, ++{0xC4AC, 0x0F}, ++{0xC4AD, 0xC0}, ++{0xC4B4, 0x01}, ++{0xC4B5, 0x01}, ++{0xC4B6, 0x00}, ++{0xC4B7, 0x01}, ++{0xC4B8, 0x00}, ++{0xC4B9, 0x01}, ++{0xC4BA, 0x01}, ++{0xC4BB, 0x00}, ++{0xC4BC, 0x01}, ++{0xC4BD, 0x60}, ++{0xC4BE, 0x02}, ++{0xC4BF, 0x33}, ++{0xC4C8, 0x03}, ++{0xC4C9, 0xD0}, ++{0xC4CA, 0x0E}, ++{0xC4CB, 0x00}, ++{0xC4CC, 0x0E}, ++{0xC4CD, 0x51}, ++{0xC4CE, 0x0E}, ++{0xC4CF, 0x51}, ++{0xC4D0, 0x04}, ++{0xC4D1, 0x80}, ++{0xC4E0, 0x04}, ++{0xC4E1, 0x02}, ++{0xC4E2, 0x01}, ++{0xC4E4, 0x10}, ++{0xC4E5, 0x20}, ++{0xC4E6, 0x30}, ++{0xC4E7, 0x40}, ++{0xC4E8, 0x50}, ++{0xC4E9, 0x60}, ++{0xC4EA, 0x70}, ++{0xC4EB, 0x80}, ++{0xC4EC, 0x90}, ++{0xC4ED, 0xA0}, ++{0xC4EE, 0xB0}, ++{0xC4EF, 0xC0}, ++{0xC4F0, 0xD0}, ++{0xC4F1, 0xE0}, ++{0xC4F2, 0xF0}, ++{0xC4F3, 0x80}, ++{0xC4F4, 0x00}, ++{0xC4F5, 0x20}, ++{0xC4F6, 0x02}, ++{0xC4F7, 0x00}, ++{0xC4F8, 0x00}, ++{0xC4F9, 0x00}, ++{0xC4FA, 0x00}, ++{0xC4FB, 0x01}, ++{0xC4FC, 0x01}, ++{0xC4FD, 0x00}, ++{0xC4FE, 0x04}, ++{0xC4FF, 0x02}, ++{0xC500, 0x48}, ++{0xC501, 0x74}, ++{0xC502, 0x58}, ++{0xC503, 0x80}, ++{0xC504, 0x05}, ++{0xC505, 0x80}, ++{0xC506, 0x03}, ++{0xC507, 0x80}, ++{0xC508, 0x01}, ++{0xC509, 0xC0}, ++{0xC50A, 0x01}, ++{0xC50B, 0xA0}, ++{0xC50C, 0x01}, ++{0xC50D, 0x2C}, ++{0xC50E, 0x01}, ++{0xC50F, 0x0A}, ++{0xC510, 0x00}, ++{0xC511, 0x00}, ++{0xC512, 0xE5}, ++{0xC513, 0x14}, ++{0xC514, 0x04}, ++{0xC515, 0x00}, ++{0xC518, OV10635_VTS >> 8}, ++{0xC519, OV10635_VTS & 0xff}, ++{0xC51A, OV10635_HTS >> 8}, ++{0xC51B, OV10635_HTS & 0xff}, ++{0xC2E0, 0x00}, ++{0xC2E1, 0x51}, ++{0xC2E2, 0x00}, ++{0xC2E3, 0xD6}, ++{0xC2E4, 0x01}, ++{0xC2E5, 0x5E}, ++{0xC2E9, 0x01}, ++{0xC2EA, 0x7A}, ++{0xC2EB, 0x90}, ++{0xC2ED, 0x00}, ++{0xC2EE, 0x7A}, ++{0xC2EF, 0x64}, ++{0xC308, 0x00}, ++{0xC309, 0x00}, ++{0xC30A, 0x00}, ++{0xC30C, 0x00}, ++{0xC30D, 0x01}, ++{0xC30E, 0x00}, ++{0xC30F, 0x00}, ++{0xC310, 0x01}, ++{0xC311, 0x60}, ++{0xC312, 0xFF}, ++{0xC313, 0x08}, ++{0xC314, 0x01}, ++{0xC315, 0x00}, /* min saturation gain */ ++{0xC316, 0xFF}, /* max saturation gain */ ++{0xC317, 0x0B}, ++{0xC318, 0x00}, ++{0xC319, 0x0C}, ++{0xC31A, 0x00}, ++{0xC31B, 0xE0}, ++{0xC31C, 0x00}, ++{0xC31D, 0x14}, ++{0xC31E, 0x00}, ++{0xC31F, 0xC5}, ++{0xC320, 0xFF}, ++{0xC321, 0x4B}, ++{0xC322, 0xFF}, ++{0xC323, 0xF0}, ++{0xC324, 0xFF}, ++{0xC325, 0xE8}, ++{0xC326, 0x00}, ++{0xC327, 0x46}, ++{0xC328, 0xFF}, ++{0xC329, 0xD2}, ++{0xC32A, 0xFF}, ++{0xC32B, 0xE4}, ++{0xC32C, 0xFF}, ++{0xC32D, 0xBB}, ++{0xC32E, 0x00}, ++{0xC32F, 0x61}, ++{0xC330, 0xFF}, ++{0xC331, 0xF9}, ++{0xC332, 0x00}, ++{0xC333, 0xD9}, ++{0xC334, 0x00}, ++{0xC335, 0x2E}, ++{0xC336, 0x00}, ++{0xC337, 0xB1}, ++{0xC338, 0xFF}, ++{0xC339, 0x64}, ++{0xC33A, 0xFF}, ++{0xC33B, 0xEB}, ++{0xC33C, 0xFF}, ++{0xC33D, 0xE8}, ++{0xC33E, 0x00}, ++{0xC33F, 0x48}, ++{0xC340, 0xFF}, ++{0xC341, 0xD0}, ++{0xC342, 0xFF}, ++{0xC343, 0xED}, ++{0xC344, 0xFF}, ++{0xC345, 0xAD}, ++{0xC346, 0x00}, ++{0xC347, 0x66}, ++{0xC348, 0x01}, ++{0xC349, 0x00}, ++{0x6700, 0x04}, ++{0x6701, 0x7B}, ++{0x6702, 0xFD}, ++{0x6703, 0xF9}, ++{0x6704, 0x3D}, ++{0x6705, 0x71}, ++{0x6706, 0x78}, ++{0x6708, 0x05}, ++{0x6F06, 0x6F}, ++{0x6F07, 0x00}, ++{0x6F0A, 0x6F}, ++{0x6F0B, 0x00}, ++{0x6F00, 0x03}, ++{0xC34C, 0x01}, ++{0xC34D, 0x00}, ++{0xC34E, 0x46}, ++{0xC34F, 0x55}, ++{0xC350, 0x00}, ++{0xC351, 0x40}, ++{0xC352, 0x00}, ++{0xC353, 0xFF}, ++{0xC354, 0x04}, ++{0xC355, 0x08}, ++{0xC356, 0x01}, ++{0xC357, 0xEF}, ++{0xC358, 0x30}, ++{0xC359, 0x01}, ++{0xC35A, 0x64}, ++{0xC35B, 0x46}, ++{0xC35C, 0x00}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0xC261, 0x01}, ++{0x301B, 0xF0}, ++{0x301C, 0xF0}, ++{0x301A, 0xF0}, ++{0x6F00, 0xC3}, ++{0xC46A, 0x30}, ++{0xC46D, 0x20}, ++{0xC464, 0x84}, ++{0xC465, 0x00}, ++{0x6F00, 0x03}, ++{0x6F00, 0x43}, ++{0x381C, 0x00}, ++{0x381D, 0x40}, ++{0xC454, 0x01}, ++{0x6F00, 0xC3}, ++{0xC454, 0x00}, ++{0xC4B1, 0x02}, ++{0xC4B2, 0x01}, ++{0xC4B3, 0x03}, ++{0x6F00, 0x03}, ++{0x6F00, 0x43}, ++/* enable FSIN (FRAMESYNC input) functionality */ ++{0x3832, (0x0d+2*0x20+0x15+38) >> 8}, ++{0x3833, (0x0d+2*0x20+0x15+38) & 0xff}, ++{0x3834, OV10635_VTS >> 8}, ++{0x3835, OV10635_VTS & 0xff}, ++{0x302E, 0x01}, ++}; ++ ++static const struct ov10635_reg ov10635_regs_30fps[] = { ++/* disable clocks */ ++{0x301b, 0xff}, ++{0x301c, 0xff}, ++{0x301a, 0xff}, ++/* clk = 24Mhz/2*32/2(1+1)=96Mhz, 30fps */ ++{0x3003, 0x20}, ++{0x3004, 0x21}, ++/* enable clocks */ ++{0x301b, 0xf0}, ++{0x301c, 0xf0}, ++{0x301a, 0xf0}, ++}; ++ ++static const struct ov10635_reg ov10635_regs_15fps[] = { ++/* disable clocks */ ++{0x301b, 0xff}, ++{0x301c, 0xff}, ++{0x301a, 0xff}, ++/* clk = 24Mhz/2*32/2(1+3)=48Mhz, 15fps */ ++{0x3003, 0x20}, ++{0x3004, 0x23}, ++/* enable clocks */ ++{0x301b, 0xf0}, ++{0x301c, 0xf0}, ++{0x301a, 0xf0}, ++}; ++ ++static const struct ov10635_reg ov10635_regs_10fps[] = { ++/* disable clocks */ ++{0x301b, 0xff}, ++{0x301c, 0xff}, ++{0x301a, 0xff}, ++/* clk = 24Mhz/2*32/2(1+5)=32Mhz, 10fps */ ++{0x3003, 0x20}, ++{0x3004, 0x25}, ++/* enable clocks */ ++{0x301b, 0xf0}, ++{0x301c, 0xf0}, ++{0x301a, 0xf0}, ++}; ++ ++static const struct ov10635_reg ov10635_regs_5fps[] = { ++/* disable clocks */ ++{0x301b, 0xff}, ++{0x301c, 0xff}, ++{0x301a, 0xff}, ++/* clk = 24Mhz/4*32/2(1+5)=96Mhz, 5fps */ ++{0x3003, 0x20}, ++{0x3004, 0x45}, ++/* enable clocks */ ++{0x301b, 0xf0}, ++{0x301c, 0xf0}, ++{0x301a, 0xf0}, ++}; ++ ++static const struct ov10635_reg ov10635_regs_contrast[5][18] = { ++{ ++ {0x6f00, 0xc3}, ++ {0xc4e4, 0x20}, ++ {0xc4e5, 0x40}, ++ {0xc4e6, 0x60}, ++ {0xc4e7, 0x80}, ++ {0xc4e8, 0xa0}, ++ {0xc4e9, 0xb4}, ++ {0xc4ea, 0xc0}, ++ {0xc4eb, 0xcb}, ++ {0xc4ec, 0xd5}, ++ {0xc4ed, 0xde}, ++ {0xc4ee, 0xe6}, ++ {0xc4ef, 0xed}, ++ {0xc4f0, 0xf3}, ++ {0xc4f1, 0xf8}, ++ {0xc4f2, 0xfc}, ++ {0x6f00, 0x03}, ++ {0x6f00, 0x43}, ++}, { ++ {0x6f00, 0xc3}, ++ {0xc4e4, 0x18}, ++ {0xc4e5, 0x30}, ++ {0xc4e6, 0x48}, ++ {0xc4e7, 0x60}, ++ {0xc4e8, 0x78}, ++ {0xc4e9, 0x90}, ++ {0xc4ea, 0xa4}, ++ {0xc4eb, 0xb4}, ++ {0xc4ec, 0xc2}, ++ {0xc4ed, 0xcf}, ++ {0xc4ee, 0xdb}, ++ {0xc4ef, 0xe5}, ++ {0xc4f0, 0xee}, ++ {0xc4f1, 0xf6}, ++ {0xc4f2, 0xfc}, ++ {0x6f00, 0x03}, ++ {0x6f00, 0x43}, ++}, { ++ {0x6f00, 0xc3}, ++ {0xc4e4, 0x10}, ++ {0xc4e5, 0x20}, ++ {0xc4e6, 0x30}, ++ {0xc4e7, 0x40}, ++ {0xc4e8, 0x50}, ++ {0xc4e9, 0x60}, ++ {0xc4ea, 0x70}, ++ {0xc4eb, 0x80}, ++ {0xc4ec, 0x90}, ++ {0xc4ed, 0xa0}, ++ {0xc4ee, 0xb0}, ++ {0xc4ef, 0xc0}, ++ {0xc4f0, 0xd0}, ++ {0xc4f1, 0xe0}, ++ {0xc4f2, 0xf0}, ++ {0x6f00, 0x03}, ++ {0x6f00, 0x43}, ++}, { ++ {0x6f00, 0xc3}, ++ {0xc4e4, 0x0c}, ++ {0xc4e5, 0x18}, ++ {0xc4e6, 0x24}, ++ {0xc4e7, 0x30}, ++ {0xc4e8, 0x3c}, ++ {0xc4e9, 0x48}, ++ {0xc4ea, 0x54}, ++ {0xc4eb, 0x62}, ++ {0xc4ec, 0x72}, ++ {0xc4ed, 0x84}, ++ {0xc4ee, 0x94}, ++ {0xc4ef, 0xa6}, ++ {0xc4f0, 0xb9}, ++ {0xc4f1, 0xcd}, ++ {0xc4f2, 0xe2}, ++ {0x6f00, 0x03}, ++ {0x6f00, 0x43}, ++}, { ++ {0x6f00, 0xc3}, ++ {0xc4e4, 0x06}, ++ {0xc4e5, 0x0d}, ++ {0xc4e6, 0x15}, ++ {0xc4e7, 0x1e}, ++ {0xc4e8, 0x28}, ++ {0xc4e9, 0x32}, ++ {0xc4ea, 0x3c}, ++ {0xc4eb, 0x48}, ++ {0xc4ec, 0x56}, ++ {0xc4ed, 0x66}, ++ {0xc4ee, 0x78}, ++ {0xc4ef, 0x8c}, ++ {0xc4f0, 0xa2}, ++ {0xc4f1, 0xba}, ++ {0xc4f2, 0xd4}, ++ {0x6f00, 0x03}, ++ {0x6f00, 0x43}, ++} ++}; +diff --git a/drivers/media/i2c/soc_camera/ov10635_debug.h b/drivers/media/i2c/soc_camera/ov10635_debug.h +new file mode 100644 +index 0000000..4c3515a +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov10635_debug.h +@@ -0,0 +1,54 @@ ++ ++#if 0 ++{0x4700, 0x02}, // BT656 ++{0x381d, 0x40}, // mirror off ++{0x381c, 0x00}, // flip off ++{0x4300, 0x3a}, // YUV: UYVY ++{0x4708, 0x00}, // PCLK rising edge ++ ++// clk = 24Mhz/3*22/2= 88Mhz ++{0x3003, 0x16}, ++{0x3004, 0x30}, ++#endif ++ ++#define WIDTH 1280 ++#define HEIGHT 720 ++ ++// DVP frame size ++{0x3808, WIDTH >> 8}, ++{0x3809, WIDTH & 0xff}, ++{0x380a, HEIGHT >> 8}, ++{0x380b, HEIGHT & 0xff}, ++ ++{0x3802, ((814 - HEIGHT)/2) >> 8}, // vert crop start ++{0x3803, ((814 - HEIGHT)/2) & 0xff}, ++{0x3806, ((814 - HEIGHT)/2 + HEIGHT + 1) >> 8}, // vert crop end ++{0x3807, ((814 - HEIGHT)/2 + HEIGHT + 1) & 0xff}, ++ ++#if 0 ++#define HTS 0x6f6 // got from above table 1782 ++#define VTS (0x2ec+80) // got from above table 748 + 80 ++ ++{0x380c, HTS >> 8}, // hts ++{0x380d, HTS & 0xff}, ++{0x380e, VTS >> 8}, // vts ++{0x380f, VTS & 0xff}, ++ ++// fifo ++{0x4606, (2*HTS) >> 8}, // fifo_line_length = 2*hts ++{0x4607, (2*HTS) & 0xff}, ++{0x460a, (2*(HTS-1280)) >> 8}, // fifo_hsync_start = 2*(hts - xres) ++{0x460b, (2*(HTS-1280)) & 0xff }, ++ ++// exposure ++{0xC488, (VTS-8)*16 >> 8}, ++{0xC489, (VTS-8)*16 & 0xff}, ++{0xC48A, (VTS-8)*16 >> 8}, ++{0xC48B, (VTS-8)*16 & 0xff}, ++ ++// vts/hts ++{0xC518, VTS >> 8}, ++{0xC519, VTS & 0xff}, ++{0xC51A, HTS >> 8}, ++{0xC51B, HTS & 0xff}, ++#endif +diff --git a/drivers/media/i2c/soc_camera/ov106xx.c b/drivers/media/i2c/soc_camera/ov106xx.c +new file mode 100644 +index 0000000..fa775ae +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov106xx.c +@@ -0,0 +1,139 @@ ++/* ++ * OmniVision ov10635/ov490-ov10640/ov495-ov2775 sensor camera driver ++ * ++ * Copyright (C) 2016-2017 Cogent Embedded, Inc. ++ * ++ * 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 "ov10635.c" ++#include "ov490_ov10640.c" ++#include "ov495_ov2775.c" ++#include "ar0132.c" ++#include "ar0220.c" ++#include "ap0101_ar014x.c" ++#include "ov2775.c" ++ ++static enum { ++ ID_OV10635, ++ ID_OV490_OV10640, ++ ID_OV495_OV2775, ++ ID_AR0132, ++ ID_AR0220, ++ ID_AP0101_AR014X, ++ ID_OV2775, ++} chip_id; ++ ++static int ov106xx_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ int ret; ++ chip_id = -EINVAL; ++ ++ ret = ov10635_probe(client, did); ++ if (!ret) { ++ chip_id = ID_OV10635; ++ goto out; ++ } ++ ++ ret = ov490_probe(client, did); ++ if (!ret) { ++ chip_id = ID_OV490_OV10640; ++ goto out; ++ } ++ ++ ret = ov495_probe(client, did); ++ if (!ret) { ++ chip_id = ID_OV495_OV2775; ++ goto out; ++ } ++ ++ ret = ar0132_probe(client, did); ++ if (!ret) { ++ chip_id = ID_AR0132; ++ goto out; ++ } ++ ++ ret = ar0220_probe(client, did); ++ if (!ret) { ++ chip_id = ID_AR0220; ++ goto out; ++ } ++ ++ ret = ap0101_probe(client, did); ++ if (!ret) { ++ chip_id = ID_AP0101_AR014X; ++ goto out; ++ } ++ ++ ret = ov2775_probe(client, did); ++ if (!ret) { ++ chip_id = ID_OV2775; ++ goto out; ++ } ++ ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++out: ++ return ret; ++} ++ ++static int ov106xx_remove(struct i2c_client *client) ++{ ++ switch (chip_id) { ++ case ID_OV10635: ++ ov10635_remove(client); ++ break; ++ case ID_OV490_OV10640: ++ ov490_remove(client); ++ break; ++ case ID_OV495_OV2775: ++ ov495_remove(client); ++ break; ++ case ID_AR0132: ++ ar0132_remove(client); ++ break; ++ case ID_AR0220: ++ ar0220_remove(client); ++ break; ++ case ID_AP0101_AR014X: ++ ap0101_remove(client); ++ break; ++ case ID_OV2775: ++ ov2775_remove(client); ++ break; ++ }; ++ ++ return 0; ++} ++ ++static const struct i2c_device_id ov106xx_id[] = { ++ { "ov106xx", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ov106xx_id); ++ ++static const struct of_device_id ov106xx_of_ids[] = { ++ { .compatible = "ovti,ov106xx", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ov106xx_of_ids); ++ ++static struct i2c_driver ov106xx_i2c_driver = { ++ .driver = { ++ .name = "ov106xx", ++ .of_match_table = ov106xx_of_ids, ++ }, ++ .probe = ov106xx_probe, ++ .remove = ov106xx_remove, ++ .id_table = ov106xx_id, ++}; ++ ++module_i2c_driver(ov106xx_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for OV10635, OV490/OV10640, OV495/OV2775, AR0132, AR0220, AP0101/AR014X"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/i2c/soc_camera/ov2775.c b/drivers/media/i2c/soc_camera/ov2775.c +new file mode 100644 +index 0000000..feb547f +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov2775.c +@@ -0,0 +1,528 @@ ++/* ++ * OmniVision OV2775 sensor camera driver ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "ov2775.h" ++ ++#define OV2775_I2C_ADDR 0x36 ++ ++#define OV2775_PID 0x300a ++#define OV2775_VER 0x300b ++#define OV2775_VERSION_REG 0x2770 ++ ++#define OV2775_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR8_1X8 ++ ++struct ov2775_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int init_complete; ++ u8 id[6]; ++ int exposure; ++ int gain; ++ int autogain; ++ /* serializers */ ++ int ti9x4_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++ ++}; ++ ++static inline struct ov2775_priv *to_ov2775(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct ov2775_priv, sd); ++} ++ ++static int ov2775_set_regs(struct i2c_client *client, ++ const struct ov2775_reg *regs, int nr_regs) ++{ ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (regs[i].reg == OV2775_DELAY) { ++ mdelay(regs[i].val); ++ continue; ++ } ++ ++ reg16_write(client, regs[i].reg, regs[i].val); ++ } ++ ++ return 0; ++} ++ ++static int ov2775_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int ov2775_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov2775_priv *priv = to_ov2775(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = OV2775_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int ov2775_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = OV2775_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int ov2775_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = OV2775_MEDIA_BUS_FMT; ++ ++ return 0; ++} ++ ++static int ov2775_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov2775_priv *priv = to_ov2775(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = OV2775_VERSION_REG >> 8; ++ edid->edid[9] = OV2775_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int ov2775_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov2775_priv *priv = to_ov2775(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > OV2775_MAX_WIDTH) || ++ (rect->top + rect->height > OV2775_MAX_HEIGHT)) ++ *rect = priv->rect; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ return 0; ++} ++ ++static int ov2775_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov2775_priv *priv = to_ov2775(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = OV2775_MAX_WIDTH; ++ sel->r.height = OV2775_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = OV2775_MAX_WIDTH; ++ sel->r.height = OV2775_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ov2775_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int ov2775_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u8 val = 0; ++ ++ ret = reg16_read(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u8); ++ ++ return 0; ++} ++ ++static int ov2775_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return reg16_write(client, (u16)reg->reg, (u8)reg->val); ++} ++#endif ++ ++static struct v4l2_subdev_core_ops ov2775_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ov2775_g_register, ++ .s_register = ov2775_s_register, ++#endif ++}; ++ ++static int ov2775_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov2775_priv *priv = to_ov2775(client); ++ int ret = -EINVAL; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ case V4L2_CID_CONTRAST: ++ case V4L2_CID_SATURATION: ++ case V4L2_CID_HUE: ++ case V4L2_CID_GAMMA: ++ case V4L2_CID_SHARPNESS: ++ case V4L2_CID_AUTOGAIN: ++ case V4L2_CID_GAIN: ++ case V4L2_CID_EXPOSURE: ++ case V4L2_CID_HFLIP: ++ case V4L2_CID_VFLIP: ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ov2775_ctrl_ops = { ++ .s_ctrl = ov2775_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops ov2775_video_ops = { ++ .s_stream = ov2775_s_stream, ++ .g_mbus_config = ov2775_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops ov2775_subdev_pad_ops = { ++ .get_edid = ov2775_get_edid, ++ .enum_mbus_code = ov2775_enum_mbus_code, ++ .get_selection = ov2775_get_selection, ++ .set_selection = ov2775_set_selection, ++ .get_fmt = ov2775_get_fmt, ++ .set_fmt = ov2775_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops ov2775_subdev_ops = { ++ .core = &ov2775_core_ops, ++ .video = &ov2775_video_ops, ++ .pad = &ov2775_subdev_pad_ops, ++}; ++ ++static void ov2775_otp_id_read(struct i2c_client *client) ++{ ++} ++ ++static ssize_t ov2775_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov2775_priv *priv = to_ov2775(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_ov2775, S_IRUGO, ov2775_otp_id_show, NULL); ++ ++static int ov2775_initialize(struct i2c_client *client) ++{ ++ struct ov2775_priv *priv = to_ov2775(client); ++ u8 val = 0; ++ u16 pid; ++ int ret = 0; ++ ++ /* check and show model ID */ ++ reg16_read(client, OV2775_PID, &val); ++ pid = val; ++ reg16_read(client, OV2775_VER, &val); ++ pid = (pid << 8) | val; ++ ++ if (pid != OV2775_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x\n", pid); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ /* Program wizard registers */ ++ ov2775_set_regs(client, ov2775_regs_wizard, ARRAY_SIZE(ov2775_regs_wizard)); ++ /* Read OTP IDs */ ++ ov2775_otp_id_read(client); ++ ++ dev_info(&client->dev, "ov2775 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, OV2775_MAX_WIDTH, OV2775_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ return ret; ++} ++ ++static int ov2775_parse_dt(struct device_node *np, struct ov2775_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ if (!priv->ti9x4_addr) { ++ dev_err(&client->dev, "deserializer does not present\n"); ++ return -EINVAL; ++ } ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, OV2775_I2C_ADDR << 1); /* Sensor native I2C address */ ++// reg8_write(client, 0x6e, 0xa9); /* GPIO0 - reset, GPIO1 - fsin */ ++ ++ client->addr = priv->ti9x3_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x0d, 0x03); /* unreset gpios */ ++ reg8_write(client, 0x0e, 0xf0); /* unreset gpios */ ++ } ++ client->addr = tmp_addr; ++ ++ mdelay(10); ++ ++ return 0; ++} ++ ++static int ov2775_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ov2775_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &ov2775_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ priv->exposure = 0x100; ++ priv->gain = 0x100; ++ priv->autogain = 1; ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2775_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2775_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2775_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2775_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2775_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2775_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2775_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2775_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2775_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2775_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2775_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = ov2775_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = ov2775_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = OV2775_MAX_WIDTH; ++ priv->rect.height = OV2775_MAX_HEIGHT; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ov2775) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_OV2775 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int ov2775_remove(struct i2c_client *client) ++{ ++ struct ov2775_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ov2775); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_OV2775 ++static const struct i2c_device_id ov2775_id[] = { ++ { "ov2775", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ov2775_id); ++ ++static const struct of_device_id ov2775_of_ids[] = { ++ { .compatible = "ovti,ov2775", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ov2775_of_ids); ++ ++static struct i2c_driver ov2775_i2c_driver = { ++ .driver = { ++ .name = "ov2775", ++ .of_match_table = ov2775_of_ids, ++ }, ++ .probe = ov2775_probe, ++ .remove = ov2775_remove, ++ .id_table = ov2775_id, ++}; ++ ++module_i2c_driver(ov2775_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for OV2775"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/ov2775.h b/drivers/media/i2c/soc_camera/ov2775.h +new file mode 100644 +index 0000000..1cdfb50 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov2775.h +@@ -0,0 +1,1841 @@ ++/* ++ * OmniVision OV2775 sensor camera wizard 1928x1088@30/RGGB/MIPI ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++//#define OV2775_DISPLAY_PATTERN_COLOR_BAR ++ ++#define OV2775_MAX_WIDTH 2880 // (1928*1.5=2892) <- must be multiple of 16 - requred by R-CAR VIN ++#define OV2775_MAX_HEIGHT 1088 ++ ++#define OV2775_DELAY 0xffff ++#define OV2775_DT 0x2c // MIPI Data Type ++ ++struct ov2775_reg { ++ u16 reg; ++ u8 val; ++}; ++ ++/* wizard: MIPI 1928x1088 RAW12 Linear 30fps 960Mbps */ ++static const struct ov2775_reg ov2775_regs_wizard[] = { ++{0x3013, 0x01}, // s/w reset ++{OV2775_DELAY, 10}, // Wait 10ms ++{0x3000, 0x02}, ++{0x3001, 0x28}, ++{0x3002, 0x03}, ++{0x3003, 0x01}, ++{0x3004, 0x02}, ++{0x3005, 0x26}, ++{0x3006, 0x00}, ++{0x3007, 0x07}, ++{0x3008, 0x01}, ++{0x3009, 0x00}, ++{0x300c, 0x6c}, ++{0x300e, 0x80}, ++{0x300f, 0x00}, ++{0x3012, 0x00}, ++{0x3013, 0x00}, ++{0x3014, 0xc4}, ++{0x3015, 0x00}, ++{0x3017, 0x00}, ++{0x3018, 0x00}, ++{0x3019, 0x00}, ++{0x301a, 0x00}, ++{0x301b, 0x01}, ++{0x301e, 0x17}, ++{0x301f, 0xe1}, ++{0x3030, 0x02}, ++{0x3031, 0x72}, ++{0x3032, 0xf0}, ++{0x3033, 0x30}, ++{0x3034, 0x3f}, ++{0x3035, 0x5f}, ++{0x3036, 0x02}, ++{0x3037, 0x9f}, ++{0x3038, 0x04}, ++{0x3039, 0xb7}, ++{0x303a, 0x04}, ++{0x303b, 0x07}, ++{0x303c, 0xf0}, ++{0x303d, 0x00}, ++{0x303e, 0x0b}, ++{0x303f, 0xe3}, ++{0x3040, 0xf3}, ++{0x3041, 0x29}, ++{0x3042, 0xf6}, ++{0x3043, 0x65}, ++{0x3044, 0x06}, ++{0x3045, 0x0f}, ++{0x3046, 0x59}, ++{0x3047, 0x07}, ++{0x3048, 0x82}, ++{0x3049, 0xcf}, ++{0x304a, 0x12}, ++{0x304b, 0x40}, ++{0x304c, 0x33}, ++{0x304d, 0xa4}, ++{0x304e, 0x0b}, ++{0x304f, 0x3d}, ++{0x3050, 0x10}, ++{0x3060, 0x00}, ++{0x3061, 0x64}, ++{0x3062, 0x00}, ++{0x3063, 0xe4}, ++{0x3066, 0x80}, ++{0x3080, 0x00}, ++{0x3081, 0x00}, ++{0x3082, 0x01}, ++{0x3083, 0xe3}, ++{0x3084, 0x06}, ++{0x3085, 0x00}, ++{0x3086, 0x10}, ++{0x3087, 0x10}, ++{0x3089, 0x00}, ++{0x308a, 0x01}, ++{0x3093, 0x00}, ++{0x30a0, 0x00}, ++{0x30a1, 0x00}, ++{0x30a2, 0x00}, ++{0x30a3, 0x00}, ++{0x30a4, 0x07}, ++{0x30a5, 0x8f}, ++{0x30a6, 0x04}, ++{0x30a7, 0x47}, ++{0x30a8, 0x00}, ++{0x30a9, 0x00}, ++{0x30aa, 0x00}, ++{0x30ab, 0x00}, ++{0x30ac, 0x07}, ++{0x30ad, 0x90}, ++{0x30ae, 0x04}, ++{0x30af, 0x48}, ++{0x30b0, 0x04}, ++{0x30b1, 0x7e}, ++{0x30b2, 0x04}, ++{0x30b3, 0x65}, ++{0x30b4, 0x00}, ++{0x30b5, 0x00}, ++{0x30b6, 0x00}, ++{0x30b7, 0x10}, ++{0x30b8, 0x00}, ++{0x30b9, 0x02}, ++{0x30ba, 0x10}, ++{0x30bb, 0x00}, ++{0x30bc, 0x00}, ++{0x30bd, 0x03}, ++{0x30be, 0x5c}, ++{0x30bf, 0x00}, ++{0x30c0, 0x01}, ++{0x30c1, 0x00}, ++{0x30c2, 0x20}, ++{0x30c3, 0x00}, ++{0x30c4, 0x4a}, ++{0x30c5, 0x00}, ++{0x30c7, 0x00}, ++{0x30c8, 0x00}, ++{0x30d1, 0x00}, ++{0x30d2, 0x00}, ++{0x30d3, 0x80}, ++{0x30d4, 0x00}, ++{0x30d9, 0x09}, ++{0x30da, 0x64}, ++{0x30dd, 0x00}, ++{0x30de, 0x16}, ++{0x30df, 0x00}, ++{0x30e0, 0x17}, ++{0x30e1, 0x00}, ++{0x30e2, 0x18}, ++{0x30e3, 0x10}, ++{0x30e4, 0x04}, ++{0x30e5, 0x00}, ++{0x30e6, 0x00}, ++{0x30e7, 0x00}, ++{0x30e8, 0x00}, ++{0x30e9, 0x00}, ++{0x30ea, 0x00}, ++{0x30eb, 0x00}, ++{0x30ec, 0x00}, ++{0x30ed, 0x00}, ++{0x3101, 0x00}, ++{0x3102, 0x00}, ++{0x3103, 0x00}, ++{0x3104, 0x00}, ++{0x3105, 0x8c}, ++{0x3106, 0x87}, ++{0x3107, 0xc0}, ++{0x3108, 0x9d}, ++{0x3109, 0x8d}, ++{0x310a, 0x8d}, ++{0x310b, 0x6a}, ++{0x310c, 0x3a}, ++{0x310d, 0x5a}, ++{0x310e, 0x00}, ++{0x3120, 0x00}, ++{0x3121, 0x00}, ++{0x3122, 0x00}, ++{0x3123, 0xf0}, ++{0x3124, 0x00}, ++{0x3125, 0x70}, ++{0x3126, 0x1f}, ++{0x3127, 0x0f}, ++{0x3128, 0x00}, ++{0x3129, 0x3a}, ++{0x312a, 0x02}, ++{0x312b, 0x0f}, ++{0x312c, 0x00}, ++{0x312d, 0x0f}, ++{0x312e, 0x1d}, ++{0x312f, 0x00}, ++{0x3130, 0x00}, ++{0x3131, 0x00}, ++{0x3132, 0x00}, ++{0x3140, 0x0a}, ++{0x3141, 0x03}, ++{0x3142, 0x00}, ++{0x3143, 0x00}, ++{0x3144, 0x00}, ++{0x3145, 0x00}, ++{0x3146, 0x00}, ++{0x3147, 0x00}, ++{0x3148, 0x00}, ++{0x3149, 0x00}, ++{0x314a, 0x00}, ++{0x314b, 0x00}, ++{0x314c, 0x00}, ++{0x314d, 0x00}, ++{0x314e, 0x1c}, ++{0x314f, 0xff}, ++{0x3150, 0xff}, ++{0x3151, 0xff}, ++{0x3152, 0x10}, ++{0x3153, 0x10}, ++{0x3154, 0x10}, ++{0x3155, 0x00}, ++{0x3156, 0x03}, ++{0x3157, 0x00}, ++{0x3158, 0x0f}, ++{0x3159, 0xff}, ++{0x315a, 0x01}, ++{0x315b, 0x00}, ++{0x315c, 0x01}, ++{0x315d, 0x00}, ++{0x315e, 0x01}, ++{0x315f, 0x00}, ++{0x3160, 0x00}, ++{0x3161, 0x40}, ++{0x3162, 0x00}, ++{0x3163, 0x40}, ++{0x3164, 0x00}, ++{0x3165, 0x40}, ++{0x3190, 0x08}, ++{0x3191, 0x99}, ++{0x3193, 0x08}, ++{0x3194, 0x13}, ++{0x3195, 0x33}, ++{0x3196, 0x00}, ++{0x3197, 0x10}, ++{0x3198, 0x00}, ++{0x3199, 0x7f}, ++{0x319a, 0x80}, ++{0x319b, 0xff}, ++{0x319c, 0x80}, ++{0x319d, 0xbf}, ++{0x319e, 0xc0}, ++{0x319f, 0xff}, ++{0x31a0, 0x24}, ++{0x31a1, 0x55}, ++{0x31a2, 0x00}, ++{0x31a3, 0x00}, ++{0x31a6, 0x00}, ++{0x31a7, 0x00}, ++{0x31b0, 0x00}, ++{0x31b1, 0x00}, ++{0x31b2, 0x02}, ++{0x31b3, 0x00}, ++{0x31b4, 0x00}, ++{0x31b5, 0x01}, ++{0x31b6, 0x00}, ++{0x31b7, 0x00}, ++{0x31b8, 0x00}, ++{0x31b9, 0x00}, ++{0x31ba, 0x00}, ++{0x31d0, 0x3c}, ++{0x31d1, 0x34}, ++{0x31d2, 0x3c}, ++{0x31d3, 0x00}, ++{0x31d4, 0x2d}, ++{0x31d5, 0x00}, ++{0x31d6, 0x01}, ++{0x31d7, 0x06}, ++{0x31d8, 0x00}, ++{0x31d9, 0x64}, ++{0x31da, 0x00}, ++{0x31db, 0x30}, ++{0x31dc, 0x04}, ++{0x31dd, 0x69}, ++{0x31de, 0x0a}, ++{0x31df, 0x3c}, ++{0x31e0, 0x04}, ++{0x31e1, 0x32}, ++{0x31e2, 0x00}, ++{0x31e3, 0x00}, ++{0x31e4, 0x08}, ++{0x31e5, 0x80}, ++{0x31e6, 0x00}, ++{0x31e7, OV2775_DT}, ++{0x31e8, 0x6c}, ++{0x31e9, 0xac}, ++{0x31ea, 0xec}, ++{0x31eb, 0x3f}, ++{0x31ec, 0x0f}, ++{0x31ed, 0x20}, ++{0x31ee, 0x04}, ++{0x31ef, 0x48}, ++{0x31f0, 0x07}, ++{0x31f1, 0x90}, ++{0x31f2, 0x04}, ++{0x31f3, 0x48}, ++{0x31f4, 0x07}, ++{0x31f5, 0x90}, ++{0x31f6, 0x04}, ++{0x31f7, 0x48}, ++{0x31f8, 0x07}, ++{0x31f9, 0x90}, ++{0x31fa, 0x04}, ++{0x31fb, 0x48}, ++{0x31fd, 0xcb}, ++{0x31fe, 0x0f}, ++{0x31ff, 0x03}, ++{0x3200, 0x00}, ++{0x3201, 0xff}, ++{0x3202, 0x00}, ++{0x3203, 0xff}, ++{0x3204, 0xff}, ++{0x3205, 0xff}, ++{0x3206, 0xff}, ++{0x3207, 0xff}, ++{0x3208, 0xff}, ++{0x3209, 0xff}, ++{0x320a, 0xff}, ++{0x320b, 0x1b}, ++{0x320c, 0x1f}, ++{0x320d, 0x1e}, ++{0x320e, 0x30}, ++{0x320f, 0x2d}, ++{0x3210, OV2775_DT}, ++{0x3211, 0x2b}, ++{0x3212, 0x2a}, ++{0x3213, 0x24}, ++{0x3214, 0x22}, ++{0x3215, 0x00}, ++{0x3216, 0x04}, ++{0x3217, OV2775_DT}, ++{0x3218, 0x6c}, ++{0x3219, 0xac}, ++{0x321a, 0xec}, ++{0x321b, 0x00}, ++{0x3230, 0x3a}, ++{0x3231, 0x00}, ++{0x3232, 0x80}, ++{0x3233, 0x00}, ++{0x3234, 0x10}, ++{0x3235, 0xaa}, ++{0x3236, 0x55}, ++{0x3237, 0x99}, ++{0x3238, 0x66}, ++{0x3239, 0x08}, ++{0x323a, 0x88}, ++{0x323b, 0x00}, ++{0x323c, 0x00}, ++{0x323d, 0x03}, ++{0x3250, 0x33}, ++{0x3251, 0x00}, ++{0x3252, 0x20}, ++#ifdef OV2775_DISPLAY_PATTERN_COLOR_BAR ++{0x3253, 0x80}, ++#else ++{0x3253, 0x00}, ++#endif ++{0x3254, 0x00}, ++{0x3255, 0x01}, ++{0x3256, 0x00}, ++{0x3257, 0x00}, ++{0x3258, 0x00}, ++{0x3270, 0x01}, ++{0x3271, 0x60}, ++{0x3272, 0xc0}, ++{0x3273, 0x00}, ++{0x3274, 0x80}, ++{0x3275, 0x40}, ++{0x3276, 0x02}, ++{0x3277, 0x08}, ++{0x3278, 0x10}, ++{0x3279, 0x04}, ++{0x327a, 0x00}, ++{0x327b, 0x03}, ++{0x327c, 0x10}, ++{0x327d, 0x60}, ++{0x327e, 0xc0}, ++{0x327f, 0x06}, ++{0x3288, 0x10}, ++{0x3289, 0x00}, ++{0x328a, 0x08}, ++{0x328b, 0x00}, ++{0x328c, 0x04}, ++{0x328d, 0x00}, ++{0x328e, 0x02}, ++{0x328f, 0x00}, ++{0x3290, 0x20}, ++{0x3291, 0x00}, ++{0x3292, 0x10}, ++{0x3293, 0x00}, ++{0x3294, 0x08}, ++{0x3295, 0x00}, ++{0x3296, 0x04}, ++{0x3297, 0x00}, ++{0x3298, 0x40}, ++{0x3299, 0x00}, ++{0x329a, 0x20}, ++{0x329b, 0x00}, ++{0x329c, 0x10}, ++{0x329d, 0x00}, ++{0x329e, 0x08}, ++{0x329f, 0x00}, ++{0x32a0, 0x7f}, ++{0x32a1, 0xff}, ++{0x32a2, 0x40}, ++{0x32a3, 0x00}, ++{0x32a4, 0x20}, ++{0x32a5, 0x00}, ++{0x32a6, 0x10}, ++{0x32a7, 0x00}, ++{0x32a8, 0x00}, ++{0x32a9, 0x00}, ++{0x32aa, 0x00}, ++{0x32ab, 0x00}, ++{0x32ac, 0x00}, ++{0x32ad, 0x00}, ++{0x32ae, 0x00}, ++{0x32af, 0x00}, ++{0x32b0, 0x00}, ++{0x32b1, 0x00}, ++{0x32b2, 0x00}, ++{0x32b3, 0x00}, ++{0x32b4, 0x00}, ++{0x32b5, 0x00}, ++{0x32b6, 0x00}, ++{0x32b7, 0x00}, ++{0x32b8, 0x00}, ++{0x32b9, 0x00}, ++{0x32ba, 0x00}, ++{0x32bb, 0x00}, ++{0x32bc, 0x00}, ++{0x32bd, 0x00}, ++{0x32be, 0x00}, ++{0x32bf, 0x00}, ++{0x32c0, 0x00}, ++{0x32c1, 0x00}, ++{0x32c2, 0x00}, ++{0x32c3, 0x00}, ++{0x32c4, 0x00}, ++{0x32c5, 0x00}, ++{0x32c6, 0x00}, ++{0x32c7, 0x00}, ++{0x32c8, 0x87}, ++{0x32c9, 0x00}, ++{0x3330, 0x03}, ++{0x3331, 0xc8}, ++{0x3332, 0x02}, ++{0x3333, 0x24}, ++{0x3334, 0x00}, ++{0x3335, 0x00}, ++{0x3336, 0x00}, ++{0x3337, 0x00}, ++{0x3338, 0x03}, ++{0x3339, 0xc8}, ++{0x333a, 0x02}, ++{0x333b, 0x24}, ++{0x333c, 0x00}, ++{0x333d, 0x00}, ++{0x333e, 0x00}, ++{0x333f, 0x00}, ++{0x3340, 0x03}, ++{0x3341, 0xc8}, ++{0x3342, 0x02}, ++{0x3343, 0x24}, ++{0x3344, 0x00}, ++{0x3345, 0x00}, ++{0x3346, 0x00}, ++{0x3347, 0x00}, ++{0x3348, 0x40}, ++{0x3349, 0x00}, ++{0x334a, 0x00}, ++{0x334b, 0x00}, ++{0x334c, 0x00}, ++{0x334d, 0x00}, ++{0x334e, 0x80}, ++{0x3360, 0x01}, ++{0x3361, 0x00}, ++{0x3362, 0x01}, ++{0x3363, 0x00}, ++{0x3364, 0x01}, ++{0x3365, 0x00}, ++{0x3366, 0x01}, ++{0x3367, 0x00}, ++{0x3368, 0x01}, ++{0x3369, 0x00}, ++{0x336a, 0x01}, ++{0x336b, 0x00}, ++{0x336c, 0x01}, ++{0x336d, 0x00}, ++{0x336e, 0x01}, ++{0x336f, 0x00}, ++{0x3370, 0x01}, ++{0x3371, 0x00}, ++{0x3372, 0x01}, ++{0x3373, 0x00}, ++{0x3374, 0x01}, ++{0x3375, 0x00}, ++{0x3376, 0x01}, ++{0x3377, 0x00}, ++{0x3378, 0x00}, ++{0x3379, 0x00}, ++{0x337a, 0x00}, ++{0x337b, 0x00}, ++{0x337c, 0x00}, ++{0x337d, 0x00}, ++{0x337e, 0x00}, ++{0x337f, 0x00}, ++{0x3380, 0x00}, ++{0x3381, 0x00}, ++{0x3382, 0x00}, ++{0x3383, 0x00}, ++{0x3384, 0x00}, ++{0x3385, 0x00}, ++{0x3386, 0x00}, ++{0x3387, 0x00}, ++{0x3388, 0x00}, ++{0x3389, 0x00}, ++{0x338a, 0x00}, ++{0x338b, 0x00}, ++{0x338c, 0x00}, ++{0x338d, 0x00}, ++{0x338e, 0x00}, ++{0x338f, 0x00}, ++{0x3390, 0x00}, ++{0x3391, 0x00}, ++{0x3392, 0x00}, ++{0x3393, 0x00}, ++{0x3394, 0x00}, ++{0x3395, 0x00}, ++{0x3396, 0x00}, ++{0x3397, 0x00}, ++{0x3398, 0x00}, ++{0x3399, 0x00}, ++{0x339a, 0x00}, ++{0x339b, 0x00}, ++{0x33b0, 0x00}, ++{0x33b1, 0x50}, ++{0x33b2, 0x01}, ++{0x33b3, 0xff}, ++{0x33b4, 0xe0}, ++{0x33b5, 0x6b}, ++{0x33b6, 0x00}, ++{0x33b7, 0x00}, ++{0x33b8, 0x00}, ++{0x33b9, 0x00}, ++{0x33ba, 0x00}, ++{0x33bb, 0x1f}, ++{0x33bc, 0x01}, ++{0x33bd, 0x01}, ++{0x33be, 0x01}, ++{0x33bf, 0x01}, ++{0x33c0, 0x00}, ++{0x33c1, 0x00}, ++{0x33c2, 0x00}, ++{0x33c3, 0x00}, ++{0x33e0, 0x14}, ++{0x33e1, 0x0f}, ++{0x33e2, 0x02}, ++{0x33e3, 0x01}, ++{0x33e4, 0x01}, ++{0x33e5, 0x01}, ++{0x33e6, 0x00}, ++{0x33e7, 0x04}, ++{0x33e8, 0x0c}, ++{0x33e9, 0x02}, ++{0x33ea, 0x02}, ++{0x33eb, 0x02}, ++{0x33ec, 0x03}, ++{0x33ed, 0x01}, ++{0x33ee, 0x02}, ++{0x33ef, 0x08}, ++{0x33f0, 0x08}, ++{0x33f1, 0x04}, ++{0x33f2, 0x04}, ++{0x33f3, 0x00}, ++{0x33f4, 0x03}, ++{0x33f5, 0x14}, ++{0x33f6, 0x0f}, ++{0x33f7, 0x02}, ++{0x33f8, 0x01}, ++{0x33f9, 0x01}, ++{0x33fa, 0x01}, ++{0x33fb, 0x00}, ++{0x33fc, 0x04}, ++{0x33fd, 0x0c}, ++{0x33fe, 0x02}, ++{0x33ff, 0x02}, ++{0x3400, 0x02}, ++{0x3401, 0x03}, ++{0x3402, 0x01}, ++{0x3403, 0x02}, ++{0x3404, 0x08}, ++{0x3405, 0x08}, ++{0x3406, 0x04}, ++{0x3407, 0x04}, ++{0x3408, 0x00}, ++{0x3409, 0x03}, ++{0x340a, 0x14}, ++{0x340b, 0x0f}, ++{0x340c, 0x04}, ++{0x340d, 0x02}, ++{0x340e, 0x01}, ++{0x340f, 0x01}, ++{0x3410, 0x00}, ++{0x3411, 0x04}, ++{0x3412, 0x0c}, ++{0x3413, 0x00}, ++{0x3414, 0x01}, ++{0x3415, 0x02}, ++{0x3416, 0x03}, ++{0x3417, 0x02}, ++{0x3418, 0x05}, ++{0x3419, 0x0a}, ++{0x341a, 0x08}, ++{0x341b, 0x04}, ++{0x341c, 0x04}, ++{0x341d, 0x00}, ++{0x341e, 0x03}, ++{0x3440, 0x00}, ++{0x3441, 0x00}, ++{0x3442, 0x00}, ++{0x3443, 0x00}, ++{0x3444, 0x02}, ++{0x3445, 0xf0}, ++{0x3446, 0x02}, ++{0x3447, 0x08}, ++{0x3448, 0x00}, ++{0x3460, 0x40}, ++{0x3461, 0x40}, ++{0x3462, 0x40}, ++{0x3463, 0x40}, ++{0x3464, 0x03}, ++{0x3465, 0x01}, ++{0x3466, 0x01}, ++{0x3467, 0x02}, ++{0x3468, 0x30}, ++{0x3469, 0x00}, ++{0x346a, 0x33}, ++{0x346b, 0xbf}, ++{0x3480, 0x40}, ++{0x3481, 0x00}, ++{0x3482, 0x00}, ++{0x3483, 0x00}, ++{0x3484, 0x0d}, ++{0x3485, 0x00}, ++{0x3486, 0x00}, ++{0x3487, 0x00}, ++{0x3488, 0x00}, ++{0x3489, 0x00}, ++{0x348a, 0x00}, ++{0x348b, 0x04}, ++{0x348c, 0x00}, ++{0x348d, 0x01}, ++{0x348f, 0x01}, ++{0x3030, 0x0a}, ++{0x3030, 0x02}, ++{0x7000, 0x58}, ++{0x7001, 0x7a}, ++{0x7002, 0x1a}, ++{0x7003, 0xc1}, ++{0x7004, 0x03}, ++{0x7005, 0xda}, ++{0x7006, 0xbd}, ++{0x7007, 0x03}, ++{0x7008, 0xbd}, ++{0x7009, 0x06}, ++{0x700a, 0xe6}, ++{0x700b, 0xec}, ++{0x700c, 0xbc}, ++{0x700d, 0xff}, ++{0x700e, 0xbc}, ++{0x700f, 0x73}, ++{0x7010, 0xda}, ++{0x7011, 0x72}, ++{0x7012, 0x76}, ++{0x7013, 0xb6}, ++{0x7014, 0xee}, ++{0x7015, 0xcf}, ++{0x7016, 0xac}, ++{0x7017, 0xd0}, ++{0x7018, 0xac}, ++{0x7019, 0xd1}, ++{0x701a, 0x50}, ++{0x701b, 0xac}, ++{0x701c, 0xd2}, ++{0x701d, 0xbc}, ++{0x701e, 0x2e}, ++{0x701f, 0xb4}, ++{0x7020, 0x00}, ++{0x7021, 0xdc}, ++{0x7022, 0xdf}, ++{0x7023, 0xb0}, ++{0x7024, 0x6e}, ++{0x7025, 0xbd}, ++{0x7026, 0x01}, ++{0x7027, 0xd7}, ++{0x7028, 0xed}, ++{0x7029, 0xe1}, ++{0x702a, 0x36}, ++{0x702b, 0x30}, ++{0x702c, 0xd3}, ++{0x702d, 0x2e}, ++{0x702e, 0x54}, ++{0x702f, 0x46}, ++{0x7030, 0xbc}, ++{0x7031, 0x22}, ++{0x7032, 0x66}, ++{0x7033, 0xbc}, ++{0x7034, 0x24}, ++{0x7035, 0x2c}, ++{0x7036, 0x28}, ++{0x7037, 0xbc}, ++{0x7038, 0x3c}, ++{0x7039, 0xa1}, ++{0x703a, 0xac}, ++{0x703b, 0xd8}, ++{0x703c, 0xd6}, ++{0x703d, 0xb4}, ++{0x703e, 0x04}, ++{0x703f, 0x46}, ++{0x7040, 0xb7}, ++{0x7041, 0x04}, ++{0x7042, 0xbe}, ++{0x7043, 0x08}, ++{0x7044, 0xc3}, ++{0x7045, 0xd9}, ++{0x7046, 0xad}, ++{0x7047, 0xc3}, ++{0x7048, 0xbc}, ++{0x7049, 0x19}, ++{0x704a, 0xc1}, ++{0x704b, 0x27}, ++{0x704c, 0xe7}, ++{0x704d, 0x00}, ++{0x704e, 0x50}, ++{0x704f, 0x20}, ++{0x7050, 0xb8}, ++{0x7051, 0x02}, ++{0x7052, 0xbc}, ++{0x7053, 0x17}, ++{0x7054, 0xdb}, ++{0x7055, 0xc7}, ++{0x7056, 0xb8}, ++{0x7057, 0x00}, ++{0x7058, 0x28}, ++{0x7059, 0x54}, ++{0x705a, 0xb4}, ++{0x705b, 0x14}, ++{0x705c, 0xab}, ++{0x705d, 0xbe}, ++{0x705e, 0x06}, ++{0x705f, 0xd8}, ++{0x7060, 0xd6}, ++{0x7061, 0x00}, ++{0x7062, 0xb4}, ++{0x7063, 0xc7}, ++{0x7064, 0x07}, ++{0x7065, 0xb9}, ++{0x7066, 0x05}, ++{0x7067, 0xee}, ++{0x7068, 0xe6}, ++{0x7069, 0xad}, ++{0x706a, 0xb4}, ++{0x706b, 0x26}, ++{0x706c, 0x19}, ++{0x706d, 0xc1}, ++{0x706e, 0x3a}, ++{0x706f, 0xc3}, ++{0x7070, 0xaf}, ++{0x7071, 0x00}, ++{0x7072, 0xc0}, ++{0x7073, 0x3c}, ++{0x7074, 0xc3}, ++{0x7075, 0xbe}, ++{0x7076, 0xe7}, ++{0x7077, 0x00}, ++{0x7078, 0x15}, ++{0x7079, 0xc2}, ++{0x707a, 0x40}, ++{0x707b, 0xc3}, ++{0x707c, 0xa4}, ++{0x707d, 0xc0}, ++{0x707e, 0x3c}, ++{0x707f, 0x00}, ++{0x7080, 0xb9}, ++{0x7081, 0x64}, ++{0x7082, 0x29}, ++{0x7083, 0x00}, ++{0x7084, 0xb8}, ++{0x7085, 0x12}, ++{0x7086, 0xbe}, ++{0x7087, 0x01}, ++{0x7088, 0xd0}, ++{0x7089, 0xbc}, ++{0x708a, 0x01}, ++{0x708b, 0xac}, ++{0x708c, 0x37}, ++{0x708d, 0xd2}, ++{0x708e, 0xac}, ++{0x708f, 0x45}, ++{0x7090, 0xad}, ++{0x7091, 0x28}, ++{0x7092, 0x00}, ++{0x7093, 0xb8}, ++{0x7094, 0x00}, ++{0x7095, 0xbc}, ++{0x7096, 0x01}, ++{0x7097, 0x36}, ++{0x7098, 0xd3}, ++{0x7099, 0x30}, ++{0x709a, 0x04}, ++{0x709b, 0xe0}, ++{0x709c, 0xd8}, ++{0x709d, 0xb4}, ++{0x709e, 0xe9}, ++{0x709f, 0x00}, ++{0x70a0, 0xbe}, ++{0x70a1, 0x05}, ++{0x70a2, 0x62}, ++{0x70a3, 0x07}, ++{0x70a4, 0xb9}, ++{0x70a5, 0x05}, ++{0x70a6, 0xad}, ++{0x70a7, 0xc3}, ++{0x70a8, 0xcf}, ++{0x70a9, 0x00}, ++{0x70aa, 0x15}, ++{0x70ab, 0xc2}, ++{0x70ac, 0x59}, ++{0x70ad, 0xc3}, ++{0x70ae, 0xc9}, ++{0x70af, 0xc0}, ++{0x70b0, 0x55}, ++{0x70b1, 0x00}, ++{0x70b2, 0x46}, ++{0x70b3, 0xa1}, ++{0x70b4, 0xb9}, ++{0x70b5, 0x64}, ++{0x70b6, 0x29}, ++{0x70b7, 0x00}, ++{0x70b8, 0xb8}, ++{0x70b9, 0x02}, ++{0x70ba, 0xbe}, ++{0x70bb, 0x02}, ++{0x70bc, 0xd0}, ++{0x70bd, 0xdc}, ++{0x70be, 0xac}, ++{0x70bf, 0xbc}, ++{0x70c0, 0x01}, ++{0x70c1, 0x37}, ++{0x70c2, 0xac}, ++{0x70c3, 0xd2}, ++{0x70c4, 0x45}, ++{0x70c5, 0xad}, ++{0x70c6, 0x28}, ++{0x70c7, 0x00}, ++{0x70c8, 0xb8}, ++{0x70c9, 0x00}, ++{0x70ca, 0xbc}, ++{0x70cb, 0x01}, ++{0x70cc, 0x36}, ++{0x70cd, 0x30}, ++{0x70ce, 0xe0}, ++{0x70cf, 0xd8}, ++{0x70d0, 0xb5}, ++{0x70d1, 0x0b}, ++{0x70d2, 0xd6}, ++{0x70d3, 0xbe}, ++{0x70d4, 0x07}, ++{0x70d5, 0x00}, ++{0x70d6, 0x62}, ++{0x70d7, 0x07}, ++{0x70d8, 0xb9}, ++{0x70d9, 0x05}, ++{0x70da, 0xad}, ++{0x70db, 0xc3}, ++{0x70dc, 0xcf}, ++{0x70dd, 0x46}, ++{0x70de, 0xcd}, ++{0x70df, 0x07}, ++{0x70e0, 0xcd}, ++{0x70e1, 0x00}, ++{0x70e2, 0xe3}, ++{0x70e3, 0x18}, ++{0x70e4, 0xc2}, ++{0x70e5, 0xa2}, ++{0x70e6, 0xb9}, ++{0x70e7, 0x64}, ++{0x70e8, 0xd1}, ++{0x70e9, 0xdd}, ++{0x70ea, 0xac}, ++{0x70eb, 0xcf}, ++{0x70ec, 0xdf}, ++{0x70ed, 0xb5}, ++{0x70ee, 0x19}, ++{0x70ef, 0x46}, ++{0x70f0, 0x50}, ++{0x70f1, 0xb6}, ++{0x70f2, 0xee}, ++{0x70f3, 0xe8}, ++{0x70f4, 0xe6}, ++{0x70f5, 0xbc}, ++{0x70f6, 0x31}, ++{0x70f7, 0xe1}, ++{0x70f8, 0x36}, ++{0x70f9, 0x30}, ++{0x70fa, 0xd3}, ++{0x70fb, 0x2e}, ++{0x70fc, 0x54}, ++{0x70fd, 0xbd}, ++{0x70fe, 0x03}, ++{0x70ff, 0xec}, ++{0x7100, 0x2c}, ++{0x7101, 0x50}, ++{0x7102, 0x20}, ++{0x7103, 0x04}, ++{0x7104, 0xb8}, ++{0x7105, 0x02}, ++{0x7106, 0xbc}, ++{0x7107, 0x18}, ++{0x7108, 0xc7}, ++{0x7109, 0xb8}, ++{0x710a, 0x00}, ++{0x710b, 0x28}, ++{0x710c, 0x54}, ++{0x710d, 0xbc}, ++{0x710e, 0x02}, ++{0x710f, 0xb4}, ++{0x7110, 0xda}, ++{0x7111, 0xbe}, ++{0x7112, 0x04}, ++{0x7113, 0xd6}, ++{0x7114, 0xd8}, ++{0x7115, 0xab}, ++{0x7116, 0x00}, ++{0x7117, 0x62}, ++{0x7118, 0x07}, ++{0x7119, 0xb9}, ++{0x711a, 0x05}, ++{0x711b, 0xad}, ++{0x711c, 0xc3}, ++{0x711d, 0xbc}, ++{0x711e, 0xe7}, ++{0x711f, 0xb9}, ++{0x7120, 0x64}, ++{0x7121, 0x29}, ++{0x7122, 0x00}, ++{0x7123, 0xb8}, ++{0x7124, 0x02}, ++{0x7125, 0xbe}, ++{0x7126, 0x00}, ++{0x7127, 0x45}, ++{0x7128, 0xad}, ++{0x7129, 0xe2}, ++{0x712a, 0x28}, ++{0x712b, 0x00}, ++{0x712c, 0xb8}, ++{0x712d, 0x00}, ++{0x712e, 0xe0}, ++{0x712f, 0xd8}, ++{0x7130, 0xb4}, ++{0x7131, 0xe9}, ++{0x7132, 0xbe}, ++{0x7133, 0x03}, ++{0x7134, 0x00}, ++{0x7135, 0x30}, ++{0x7136, 0x62}, ++{0x7137, 0x07}, ++{0x7138, 0xb9}, ++{0x7139, 0x05}, ++{0x713a, 0xad}, ++{0x713b, 0xc3}, ++{0x713c, 0xcf}, ++{0x713d, 0x42}, ++{0x713e, 0xe4}, ++{0x713f, 0xcd}, ++{0x7140, 0x07}, ++{0x7141, 0xcd}, ++{0x7142, 0x00}, ++{0x7143, 0x00}, ++{0x7144, 0x17}, ++{0x7145, 0xc2}, ++{0x7146, 0xbb}, ++{0x7147, 0xde}, ++{0x7148, 0xcf}, ++{0x7149, 0xdf}, ++{0x714a, 0xac}, ++{0x714b, 0xd1}, ++{0x714c, 0x44}, ++{0x714d, 0xac}, ++{0x714e, 0xb9}, ++{0x714f, 0x76}, ++{0x7150, 0xb8}, ++{0x7151, 0x08}, ++{0x7152, 0xb6}, ++{0x7153, 0xfe}, ++{0x7154, 0xb4}, ++{0x7155, 0xca}, ++{0x7156, 0xd6}, ++{0x7157, 0xd8}, ++{0x7158, 0xab}, ++{0x7159, 0x00}, ++{0x715a, 0xe1}, ++{0x715b, 0x36}, ++{0x715c, 0x30}, ++{0x715d, 0xd3}, ++{0x715e, 0xbc}, ++{0x715f, 0x29}, ++{0x7160, 0xb4}, ++{0x7161, 0x1f}, ++{0x7162, 0xaa}, ++{0x7163, 0xbd}, ++{0x7164, 0x01}, ++{0x7165, 0xb8}, ++{0x7166, 0x0c}, ++{0x7167, 0x45}, ++{0x7168, 0xa4}, ++{0x7169, 0xbd}, ++{0x716a, 0x03}, ++{0x716b, 0xec}, ++{0x716c, 0xbc}, ++{0x716d, 0x3d}, ++{0x716e, 0xc3}, ++{0x716f, 0xcf}, ++{0x7170, 0x42}, ++{0x7171, 0xb8}, ++{0x7172, 0x00}, ++{0x7173, 0xe4}, ++{0x7174, 0xd5}, ++{0x7175, 0x00}, ++{0x7176, 0xb6}, ++{0x7177, 0x00}, ++{0x7178, 0x74}, ++{0x7179, 0xbd}, ++{0x717a, 0x03}, ++{0x717b, 0x40}, ++{0x717c, 0xb5}, ++{0x717d, 0x39}, ++{0x717e, 0x58}, ++{0x717f, 0xdd}, ++{0x7180, 0x19}, ++{0x7181, 0xc1}, ++{0x7182, 0xc8}, ++{0x7183, 0xbd}, ++{0x7184, 0x06}, ++{0x7185, 0x17}, ++{0x7186, 0xc1}, ++{0x7187, 0xc6}, ++{0x7188, 0xe8}, ++{0x7189, 0x00}, ++{0x718a, 0xc0}, ++{0x718b, 0xc8}, ++{0x718c, 0xe6}, ++{0x718d, 0x95}, ++{0x718e, 0x15}, ++{0x718f, 0x00}, ++{0x7190, 0xbc}, ++{0x7191, 0x19}, ++{0x7192, 0xb9}, ++{0x7193, 0xf6}, ++{0x7194, 0x14}, ++{0x7195, 0xc1}, ++{0x7196, 0xd0}, ++{0x7197, 0xd1}, ++{0x7198, 0xac}, ++{0x7199, 0x37}, ++{0x719a, 0xbc}, ++{0x719b, 0x35}, ++{0x719c, 0x36}, ++{0x719d, 0x30}, ++{0x719e, 0xe1}, ++{0x719f, 0xd3}, ++{0x71a0, 0x7a}, ++{0x71a1, 0xb6}, ++{0x71a2, 0x0c}, ++{0x71a3, 0xff}, ++{0x71a4, 0xb4}, ++{0x71a5, 0xc7}, ++{0x71a6, 0xd9}, ++{0x71a7, 0x00}, ++{0x71a8, 0xbd}, ++{0x71a9, 0x01}, ++{0x71aa, 0x56}, ++{0x71ab, 0xc0}, ++{0x71ac, 0xda}, ++{0x71ad, 0xb4}, ++{0x71ae, 0x1f}, ++{0x71af, 0x56}, ++{0x71b0, 0xaa}, ++{0x71b1, 0xbc}, ++{0x71b2, 0x08}, ++{0x71b3, 0x00}, ++{0x71b4, 0x57}, ++{0x71b5, 0xe8}, ++{0x71b6, 0xb5}, ++{0x71b7, 0x36}, ++{0x71b8, 0x00}, ++{0x71b9, 0x54}, ++{0x71ba, 0xe7}, ++{0x71bb, 0xc8}, ++{0x71bc, 0xb4}, ++{0x71bd, 0x1f}, ++{0x71be, 0x56}, ++{0x71bf, 0xaa}, ++{0x71c0, 0xbc}, ++{0x71c1, 0x08}, ++{0x71c2, 0x57}, ++{0x71c3, 0x00}, ++{0x71c4, 0xb5}, ++{0x71c5, 0x36}, ++{0x71c6, 0x00}, ++{0x71c7, 0x54}, ++{0x71c8, 0xc8}, ++{0x71c9, 0xb5}, ++{0x71ca, 0x18}, ++{0x71cb, 0xd9}, ++{0x71cc, 0x00}, ++{0x71cd, 0xbd}, ++{0x71ce, 0x01}, ++{0x71cf, 0x56}, ++{0x71d0, 0x08}, ++{0x71d1, 0x57}, ++{0x71d2, 0xe8}, ++{0x71d3, 0xb4}, ++{0x71d4, 0x42}, ++{0x71d5, 0x00}, ++{0x71d6, 0x54}, ++{0x71d7, 0xe7}, ++{0x71d8, 0xc8}, ++{0x71d9, 0xab}, ++{0x71da, 0x00}, ++{0x71db, 0x66}, ++{0x71dc, 0x62}, ++{0x71dd, 0x06}, ++{0x71de, 0x74}, ++{0x71df, 0xb9}, ++{0x71e0, 0x05}, ++{0x71e1, 0xb7}, ++{0x71e2, 0x14}, ++{0x71e3, 0x0e}, ++{0x71e4, 0xb7}, ++{0x71e5, 0x04}, ++{0x71e6, 0xc8}, ++{0x7600, 0x04}, ++{0x7601, 0x80}, ++{0x7602, 0x07}, ++{0x7603, 0x44}, ++{0x7604, 0x05}, ++{0x7605, 0x33}, ++{0x7606, 0x0f}, ++{0x7607, 0x00}, ++{0x7608, 0x07}, ++{0x7609, 0x40}, ++{0x760a, 0x04}, ++{0x760b, 0xe5}, ++{0x760c, 0x06}, ++{0x760d, 0x50}, ++{0x760e, 0x04}, ++{0x760f, 0xe4}, ++{0x7610, 0x00}, ++{0x7611, 0x00}, ++{0x7612, 0x06}, ++{0x7613, 0x5c}, ++{0x7614, 0x00}, ++{0x7615, 0x0f}, ++{0x7616, 0x06}, ++{0x7617, 0x1c}, ++{0x7618, 0x00}, ++{0x7619, 0x02}, ++{0x761a, 0x06}, ++{0x761b, 0xa2}, ++{0x761c, 0x00}, ++{0x761d, 0x01}, ++{0x761e, 0x06}, ++{0x761f, 0xae}, ++{0x7620, 0x00}, ++{0x7621, 0x0e}, ++{0x7622, 0x05}, ++{0x7623, 0x30}, ++{0x7624, 0x07}, ++{0x7625, 0x00}, ++{0x7626, 0x0f}, ++{0x7627, 0x00}, ++{0x7628, 0x04}, ++{0x7629, 0xe5}, ++{0x762a, 0x05}, ++{0x762b, 0x33}, ++{0x762c, 0x06}, ++{0x762d, 0x12}, ++{0x762e, 0x00}, ++{0x762f, 0x01}, ++{0x7630, 0x06}, ++{0x7631, 0x52}, ++{0x7632, 0x00}, ++{0x7633, 0x01}, ++{0x7634, 0x06}, ++{0x7635, 0x5e}, ++{0x7636, 0x04}, ++{0x7637, 0xe4}, ++{0x7638, 0x00}, ++{0x7639, 0x01}, ++{0x763a, 0x05}, ++{0x763b, 0x30}, ++{0x763c, 0x0f}, ++{0x763d, 0x00}, ++{0x763e, 0x06}, ++{0x763f, 0xa6}, ++{0x7640, 0x00}, ++{0x7641, 0x02}, ++{0x7642, 0x06}, ++{0x7643, 0x26}, ++{0x7644, 0x00}, ++{0x7645, 0x02}, ++{0x7646, 0x05}, ++{0x7647, 0x33}, ++{0x7648, 0x06}, ++{0x7649, 0x20}, ++{0x764a, 0x0f}, ++{0x764b, 0x00}, ++{0x764c, 0x06}, ++{0x764d, 0x56}, ++{0x764e, 0x00}, ++{0x764f, 0x02}, ++{0x7650, 0x06}, ++{0x7651, 0x16}, ++{0x7652, 0x05}, ++{0x7653, 0x33}, ++{0x7654, 0x06}, ++{0x7655, 0x10}, ++{0x7656, 0x0f}, ++{0x7657, 0x00}, ++{0x7658, 0x06}, ++{0x7659, 0x10}, ++{0x765a, 0x0f}, ++{0x765b, 0x00}, ++{0x765c, 0x06}, ++{0x765d, 0x20}, ++{0x765e, 0x0f}, ++{0x765f, 0x00}, ++{0x7660, 0x00}, ++{0x7661, 0x00}, ++{0x7662, 0x00}, ++{0x7663, 0x02}, ++{0x7664, 0x04}, ++{0x7665, 0xe5}, ++{0x7666, 0x04}, ++{0x7667, 0xe4}, ++{0x7668, 0x0f}, ++{0x7669, 0x00}, ++{0x766a, 0x00}, ++{0x766b, 0x00}, ++{0x766c, 0x00}, ++{0x766d, 0x01}, ++{0x766e, 0x04}, ++{0x766f, 0xe5}, ++{0x7670, 0x04}, ++{0x7671, 0xe4}, ++{0x7672, 0x0f}, ++{0x7673, 0x00}, ++{0x7674, 0x00}, ++{0x7675, 0x02}, ++{0x7676, 0x04}, ++{0x7677, 0xe4}, ++{0x7678, 0x00}, ++{0x7679, 0x02}, ++{0x767a, 0x04}, ++{0x767b, 0xc4}, ++{0x767c, 0x00}, ++{0x767d, 0x02}, ++{0x767e, 0x04}, ++{0x767f, 0xc4}, ++{0x7680, 0x05}, ++{0x7681, 0x83}, ++{0x7682, 0x0f}, ++{0x7683, 0x00}, ++{0x7684, 0x00}, ++{0x7685, 0x02}, ++{0x7686, 0x04}, ++{0x7687, 0xe4}, ++{0x7688, 0x00}, ++{0x7689, 0x02}, ++{0x768a, 0x04}, ++{0x768b, 0xc4}, ++{0x768c, 0x00}, ++{0x768d, 0x02}, ++{0x768e, 0x04}, ++{0x768f, 0xc4}, ++{0x7690, 0x05}, ++{0x7691, 0x83}, ++{0x7692, 0x03}, ++{0x7693, 0x0b}, ++{0x7694, 0x05}, ++{0x7695, 0x83}, ++{0x7696, 0x00}, ++{0x7697, 0x07}, ++{0x7698, 0x05}, ++{0x7699, 0x03}, ++{0x769a, 0x00}, ++{0x769b, 0x05}, ++{0x769c, 0x05}, ++{0x769d, 0x32}, ++{0x769e, 0x05}, ++{0x769f, 0x30}, ++{0x76a0, 0x00}, ++{0x76a1, 0x02}, ++{0x76a2, 0x05}, ++{0x76a3, 0x78}, ++{0x76a4, 0x00}, ++{0x76a5, 0x01}, ++{0x76a6, 0x05}, ++{0x76a7, 0x7c}, ++{0x76a8, 0x03}, ++{0x76a9, 0x9a}, ++{0x76aa, 0x05}, ++{0x76ab, 0x83}, ++{0x76ac, 0x00}, ++{0x76ad, 0x04}, ++{0x76ae, 0x05}, ++{0x76af, 0x03}, ++{0x76b0, 0x00}, ++{0x76b1, 0x03}, ++{0x76b2, 0x05}, ++{0x76b3, 0x32}, ++{0x76b4, 0x05}, ++{0x76b5, 0x30}, ++{0x76b6, 0x00}, ++{0x76b7, 0x02}, ++{0x76b8, 0x05}, ++{0x76b9, 0x78}, ++{0x76ba, 0x00}, ++{0x76bb, 0x01}, ++{0x76bc, 0x05}, ++{0x76bd, 0x7c}, ++{0x76be, 0x03}, ++{0x76bf, 0x99}, ++{0x76c0, 0x05}, ++{0x76c1, 0x83}, ++{0x76c2, 0x00}, ++{0x76c3, 0x03}, ++{0x76c4, 0x05}, ++{0x76c5, 0x03}, ++{0x76c6, 0x00}, ++{0x76c7, 0x01}, ++{0x76c8, 0x05}, ++{0x76c9, 0x32}, ++{0x76ca, 0x05}, ++{0x76cb, 0x30}, ++{0x76cc, 0x00}, ++{0x76cd, 0x02}, ++{0x76ce, 0x05}, ++{0x76cf, 0x78}, ++{0x76d0, 0x00}, ++{0x76d1, 0x01}, ++{0x76d2, 0x05}, ++{0x76d3, 0x7c}, ++{0x76d4, 0x03}, ++{0x76d5, 0x98}, ++{0x76d6, 0x05}, ++{0x76d7, 0x83}, ++{0x76d8, 0x00}, ++{0x76d9, 0x00}, ++{0x76da, 0x05}, ++{0x76db, 0x03}, ++{0x76dc, 0x00}, ++{0x76dd, 0x01}, ++{0x76de, 0x05}, ++{0x76df, 0x32}, ++{0x76e0, 0x05}, ++{0x76e1, 0x30}, ++{0x76e2, 0x00}, ++{0x76e3, 0x02}, ++{0x76e4, 0x05}, ++{0x76e5, 0x78}, ++{0x76e6, 0x00}, ++{0x76e7, 0x01}, ++{0x76e8, 0x05}, ++{0x76e9, 0x7c}, ++{0x76ea, 0x03}, ++{0x76eb, 0x97}, ++{0x76ec, 0x05}, ++{0x76ed, 0x83}, ++{0x76ee, 0x00}, ++{0x76ef, 0x00}, ++{0x76f0, 0x05}, ++{0x76f1, 0x03}, ++{0x76f2, 0x05}, ++{0x76f3, 0x32}, ++{0x76f4, 0x05}, ++{0x76f5, 0x30}, ++{0x76f6, 0x00}, ++{0x76f7, 0x02}, ++{0x76f8, 0x05}, ++{0x76f9, 0x78}, ++{0x76fa, 0x00}, ++{0x76fb, 0x01}, ++{0x76fc, 0x05}, ++{0x76fd, 0x7c}, ++{0x76fe, 0x03}, ++{0x76ff, 0x96}, ++{0x7700, 0x05}, ++{0x7701, 0x83}, ++{0x7702, 0x05}, ++{0x7703, 0x03}, ++{0x7704, 0x05}, ++{0x7705, 0x32}, ++{0x7706, 0x05}, ++{0x7707, 0x30}, ++{0x7708, 0x00}, ++{0x7709, 0x02}, ++{0x770a, 0x05}, ++{0x770b, 0x78}, ++{0x770c, 0x00}, ++{0x770d, 0x01}, ++{0x770e, 0x05}, ++{0x770f, 0x7c}, ++{0x7710, 0x03}, ++{0x7711, 0x95}, ++{0x7712, 0x05}, ++{0x7713, 0x83}, ++{0x7714, 0x05}, ++{0x7715, 0x03}, ++{0x7716, 0x05}, ++{0x7717, 0x32}, ++{0x7718, 0x05}, ++{0x7719, 0x30}, ++{0x771a, 0x00}, ++{0x771b, 0x02}, ++{0x771c, 0x05}, ++{0x771d, 0x78}, ++{0x771e, 0x00}, ++{0x771f, 0x01}, ++{0x7720, 0x05}, ++{0x7721, 0x7c}, ++{0x7722, 0x03}, ++{0x7723, 0x94}, ++{0x7724, 0x05}, ++{0x7725, 0x83}, ++{0x7726, 0x00}, ++{0x7727, 0x01}, ++{0x7728, 0x05}, ++{0x7729, 0x03}, ++{0x772a, 0x00}, ++{0x772b, 0x01}, ++{0x772c, 0x05}, ++{0x772d, 0x32}, ++{0x772e, 0x05}, ++{0x772f, 0x30}, ++{0x7730, 0x00}, ++{0x7731, 0x02}, ++{0x7732, 0x05}, ++{0x7733, 0x78}, ++{0x7734, 0x00}, ++{0x7735, 0x01}, ++{0x7736, 0x05}, ++{0x7737, 0x7c}, ++{0x7738, 0x03}, ++{0x7739, 0x93}, ++{0x773a, 0x05}, ++{0x773b, 0x83}, ++{0x773c, 0x00}, ++{0x773d, 0x00}, ++{0x773e, 0x05}, ++{0x773f, 0x03}, ++{0x7740, 0x00}, ++{0x7741, 0x00}, ++{0x7742, 0x05}, ++{0x7743, 0x32}, ++{0x7744, 0x05}, ++{0x7745, 0x30}, ++{0x7746, 0x00}, ++{0x7747, 0x02}, ++{0x7748, 0x05}, ++{0x7749, 0x78}, ++{0x774a, 0x00}, ++{0x774b, 0x01}, ++{0x774c, 0x05}, ++{0x774d, 0x7c}, ++{0x774e, 0x03}, ++{0x774f, 0x92}, ++{0x7750, 0x05}, ++{0x7751, 0x83}, ++{0x7752, 0x05}, ++{0x7753, 0x03}, ++{0x7754, 0x00}, ++{0x7755, 0x00}, ++{0x7756, 0x05}, ++{0x7757, 0x32}, ++{0x7758, 0x05}, ++{0x7759, 0x30}, ++{0x775a, 0x00}, ++{0x775b, 0x02}, ++{0x775c, 0x05}, ++{0x775d, 0x78}, ++{0x775e, 0x00}, ++{0x775f, 0x01}, ++{0x7760, 0x05}, ++{0x7761, 0x7c}, ++{0x7762, 0x03}, ++{0x7763, 0x91}, ++{0x7764, 0x05}, ++{0x7765, 0x83}, ++{0x7766, 0x05}, ++{0x7767, 0x03}, ++{0x7768, 0x05}, ++{0x7769, 0x32}, ++{0x776a, 0x05}, ++{0x776b, 0x30}, ++{0x776c, 0x00}, ++{0x776d, 0x02}, ++{0x776e, 0x05}, ++{0x776f, 0x78}, ++{0x7770, 0x00}, ++{0x7771, 0x01}, ++{0x7772, 0x05}, ++{0x7773, 0x7c}, ++{0x7774, 0x03}, ++{0x7775, 0x90}, ++{0x7776, 0x05}, ++{0x7777, 0x83}, ++{0x7778, 0x05}, ++{0x7779, 0x03}, ++{0x777a, 0x05}, ++{0x777b, 0x32}, ++{0x777c, 0x05}, ++{0x777d, 0x30}, ++{0x777e, 0x00}, ++{0x777f, 0x02}, ++{0x7780, 0x05}, ++{0x7781, 0x78}, ++{0x7782, 0x00}, ++{0x7783, 0x01}, ++{0x7784, 0x05}, ++{0x7785, 0x7c}, ++{0x7786, 0x02}, ++{0x7787, 0x90}, ++{0x7788, 0x05}, ++{0x7789, 0x03}, ++{0x778a, 0x07}, ++{0x778b, 0x00}, ++{0x778c, 0x0f}, ++{0x778d, 0x00}, ++{0x778e, 0x08}, ++{0x778f, 0x30}, ++{0x7790, 0x08}, ++{0x7791, 0xee}, ++{0x7792, 0x0f}, ++{0x7793, 0x00}, ++{0x7794, 0x05}, ++{0x7795, 0x33}, ++{0x7796, 0x04}, ++{0x7797, 0xe5}, ++{0x7798, 0x06}, ++{0x7799, 0x52}, ++{0x779a, 0x04}, ++{0x779b, 0xe4}, ++{0x779c, 0x00}, ++{0x779d, 0x00}, ++{0x779e, 0x06}, ++{0x779f, 0x5e}, ++{0x77a0, 0x00}, ++{0x77a1, 0x0f}, ++{0x77a2, 0x06}, ++{0x77a3, 0x1e}, ++{0x77a4, 0x00}, ++{0x77a5, 0x02}, ++{0x77a6, 0x06}, ++{0x77a7, 0xa2}, ++{0x77a8, 0x00}, ++{0x77a9, 0x01}, ++{0x77aa, 0x06}, ++{0x77ab, 0xae}, ++{0x77ac, 0x00}, ++{0x77ad, 0x03}, ++{0x77ae, 0x05}, ++{0x77af, 0x30}, ++{0x77b0, 0x09}, ++{0x77b1, 0x19}, ++{0x77b2, 0x0f}, ++{0x77b3, 0x00}, ++{0x77b4, 0x05}, ++{0x77b5, 0x33}, ++{0x77b6, 0x04}, ++{0x77b7, 0xe5}, ++{0x77b8, 0x06}, ++{0x77b9, 0x52}, ++{0x77ba, 0x04}, ++{0x77bb, 0xe4}, ++{0x77bc, 0x00}, ++{0x77bd, 0x00}, ++{0x77be, 0x06}, ++{0x77bf, 0x5e}, ++{0x77c0, 0x00}, ++{0x77c1, 0x0f}, ++{0x77c2, 0x06}, ++{0x77c3, 0x1e}, ++{0x77c4, 0x00}, ++{0x77c5, 0x02}, ++{0x77c6, 0x06}, ++{0x77c7, 0xa2}, ++{0x77c8, 0x00}, ++{0x77c9, 0x01}, ++{0x77ca, 0x06}, ++{0x77cb, 0xae}, ++{0x77cc, 0x00}, ++{0x77cd, 0x03}, ++{0x77ce, 0x05}, ++{0x77cf, 0x30}, ++{0x77d0, 0x0f}, ++{0x77d1, 0x00}, ++{0x77d2, 0x00}, ++{0x77d3, 0x00}, ++{0x77d4, 0x00}, ++{0x77d5, 0x02}, ++{0x77d6, 0x04}, ++{0x77d7, 0xe5}, ++{0x77d8, 0x04}, ++{0x77d9, 0xe4}, ++{0x77da, 0x05}, ++{0x77db, 0x33}, ++{0x77dc, 0x07}, ++{0x77dd, 0x10}, ++{0x77de, 0x00}, ++{0x77df, 0x00}, ++{0x77e0, 0x01}, ++{0x77e1, 0xbb}, ++{0x77e2, 0x00}, ++{0x77e3, 0x00}, ++{0x77e4, 0x01}, ++{0x77e5, 0xaa}, ++{0x77e6, 0x00}, ++{0x77e7, 0x00}, ++{0x77e8, 0x01}, ++{0x77e9, 0x99}, ++{0x77ea, 0x00}, ++{0x77eb, 0x00}, ++{0x77ec, 0x01}, ++{0x77ed, 0x88}, ++{0x77ee, 0x00}, ++{0x77ef, 0x00}, ++{0x77f0, 0x01}, ++{0x77f1, 0x77}, ++{0x77f2, 0x00}, ++{0x77f3, 0x00}, ++{0x77f4, 0x01}, ++{0x77f5, 0x66}, ++{0x77f6, 0x00}, ++{0x77f7, 0x00}, ++{0x77f8, 0x01}, ++{0x77f9, 0x55}, ++{0x77fa, 0x00}, ++{0x77fb, 0x00}, ++{0x77fc, 0x01}, ++{0x77fd, 0x44}, ++{0x77fe, 0x00}, ++{0x77ff, 0x00}, ++{0x7800, 0x01}, ++{0x7801, 0x33}, ++{0x7802, 0x00}, ++{0x7803, 0x00}, ++{0x7804, 0x01}, ++{0x7805, 0x22}, ++{0x7806, 0x00}, ++{0x7807, 0x00}, ++{0x7808, 0x01}, ++{0x7809, 0x11}, ++{0x780a, 0x00}, ++{0x780b, 0x00}, ++{0x780c, 0x01}, ++{0x780d, 0x00}, ++{0x780e, 0x01}, ++{0x780f, 0xff}, ++{0x7810, 0x07}, ++{0x7811, 0x00}, ++{0x7812, 0x02}, ++{0x7813, 0xa0}, ++{0x7814, 0x0f}, ++{0x7815, 0x00}, ++{0x7816, 0x08}, ++{0x7817, 0x35}, ++{0x7818, 0x06}, ++{0x7819, 0x52}, ++{0x781a, 0x04}, ++{0x781b, 0xe4}, ++{0x781c, 0x00}, ++{0x781d, 0x00}, ++{0x781e, 0x06}, ++{0x781f, 0x5e}, ++{0x7820, 0x05}, ++{0x7821, 0x33}, ++{0x7822, 0x09}, ++{0x7823, 0x19}, ++{0x7824, 0x06}, ++{0x7825, 0x1e}, ++{0x7826, 0x05}, ++{0x7827, 0x33}, ++{0x7828, 0x00}, ++{0x7829, 0x01}, ++{0x782a, 0x06}, ++{0x782b, 0x24}, ++{0x782c, 0x06}, ++{0x782d, 0x20}, ++{0x782e, 0x0f}, ++{0x782f, 0x00}, ++{0x7830, 0x08}, ++{0x7831, 0x35}, ++{0x7832, 0x07}, ++{0x7833, 0x10}, ++{0x7834, 0x00}, ++{0x7835, 0x00}, ++{0x7836, 0x01}, ++{0x7837, 0xbb}, ++{0x7838, 0x00}, ++{0x7839, 0x00}, ++{0x783a, 0x01}, ++{0x783b, 0xaa}, ++{0x783c, 0x00}, ++{0x783d, 0x00}, ++{0x783e, 0x01}, ++{0x783f, 0x99}, ++{0x7840, 0x00}, ++{0x7841, 0x00}, ++{0x7842, 0x01}, ++{0x7843, 0x88}, ++{0x7844, 0x00}, ++{0x7845, 0x00}, ++{0x7846, 0x01}, ++{0x7847, 0x77}, ++{0x7848, 0x00}, ++{0x7849, 0x00}, ++{0x784a, 0x01}, ++{0x784b, 0x66}, ++{0x784c, 0x00}, ++{0x784d, 0x00}, ++{0x784e, 0x01}, ++{0x784f, 0x55}, ++{0x7850, 0x00}, ++{0x7851, 0x00}, ++{0x7852, 0x01}, ++{0x7853, 0x44}, ++{0x7854, 0x00}, ++{0x7855, 0x00}, ++{0x7856, 0x01}, ++{0x7857, 0x33}, ++{0x7858, 0x00}, ++{0x7859, 0x00}, ++{0x785a, 0x01}, ++{0x785b, 0x22}, ++{0x785c, 0x00}, ++{0x785d, 0x00}, ++{0x785e, 0x01}, ++{0x785f, 0x11}, ++{0x7860, 0x00}, ++{0x7861, 0x00}, ++{0x7862, 0x01}, ++{0x7863, 0x00}, ++{0x7864, 0x07}, ++{0x7865, 0x00}, ++{0x7866, 0x01}, ++{0x7867, 0xff}, ++{0x7868, 0x02}, ++{0x7869, 0xa0}, ++{0x786a, 0x0f}, ++{0x786b, 0x00}, ++{0x786c, 0x08}, ++{0x786d, 0x3a}, ++{0x786e, 0x08}, ++{0x786f, 0x6a}, ++{0x7870, 0x0f}, ++{0x7871, 0x00}, ++{0x7872, 0x04}, ++{0x7873, 0xc0}, ++{0x7874, 0x09}, ++{0x7875, 0x19}, ++{0x7876, 0x04}, ++{0x7877, 0x99}, ++{0x7878, 0x07}, ++{0x7879, 0x14}, ++{0x787a, 0x00}, ++{0x787b, 0x01}, ++{0x787c, 0x04}, ++{0x787d, 0xa4}, ++{0x787e, 0x00}, ++{0x787f, 0x0f}, ++{0x7880, 0x00}, ++{0x7881, 0x0f}, ++{0x7882, 0x04}, ++{0x7883, 0xa6}, ++{0x7884, 0x00}, ++{0x7885, 0x00}, ++{0x7886, 0x04}, ++{0x7887, 0xa0}, ++{0x7888, 0x04}, ++{0x7889, 0x80}, ++{0x788a, 0x04}, ++{0x788b, 0x00}, ++{0x788c, 0x05}, ++{0x788d, 0x03}, ++{0x788e, 0x06}, ++{0x788f, 0x00}, ++{0x7890, 0x0f}, ++{0x7891, 0x00}, ++{0x7892, 0x0f}, ++{0x7893, 0x00}, ++{0x7894, 0x0f}, ++{0x7895, 0x00}, ++{0x30a0, 0x00}, ++{0x30a1, 0x00}, ++{0x30a2, 0x00}, ++{0x30a3, 0x00}, ++{0x30a4, 0x07}, ++{0x30a5, 0x8f}, ++{0x30a6, 0x04}, ++{0x30a7, 0x47}, ++{0x30a8, 0x00}, ++{0x30a9, 0x04}, ++{0x30aa, 0x00}, ++{0x30ab, 0x04}, ++{0x30ac, 0x07}, ++{0x30ad, 0x88}, ++{0x30ae, 0x04}, ++{0x30af, 0x40}, ++{0x30b0, 0x0d}, ++{0x30b1, 0xde}, ++{0x30b2, 0x04}, ++{0x30b3, 0x66}, ++{0x3196, 0x00}, ++{0x3197, 0x0a}, ++{0x3195, 0x29}, ++{0x315a, 0x02}, ++{0x315b, 0x00}, ++{0x30bb, 0x40}, ++{0x3250, 0xf7}, ++{0x3012, 0x01}, ++}; +diff --git a/drivers/media/i2c/soc_camera/ov490_ov10640.c b/drivers/media/i2c/soc_camera/ov490_ov10640.c +new file mode 100644 +index 0000000..e698f59 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov490_ov10640.c +@@ -0,0 +1,1134 @@ ++/* ++ * OmniVision ov490-ov10640 sensor camera driver ++ * ++ * Copyright (C) 2016-2018 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "max9286.h" ++#include "ov490_ov10640.h" ++ ++#define OV490_I2C_ADDR 0x24 ++ ++#define OV490_PID 0x300a ++#define OV490_VER 0x300b ++#define OV490_VERSION_REG 0x0490 ++#define OV490_VERSION(pid, ver) (((pid) << 8) | ((ver) & 0xff)) ++ ++#define OV490_ISP_HSIZE_LOW 0x60 ++#define OV490_ISP_HSIZE_HIGH 0x61 ++#define OV490_ISP_VSIZE_LOW 0x62 ++#define OV490_ISP_VSIZE_HIGH 0x63 ++ ++struct ov490_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int max_width; ++ int max_height; ++ char is_fixed_sensor; ++ int init_complete; ++ u8 id[6]; ++ int exposure; ++ int gain; ++ int autogain; ++ int red; ++ int green_r; ++ int green_b; ++ int blue; ++ int awb; ++ int dvp_order; ++ /* serializers */ ++ int max9286_addr; ++ int max9271_addr; ++ int ti9x4_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int active_low_resetb; ++ int gpio_fsin; ++}; ++ ++static int conf_link; ++module_param(conf_link, int, 0644); ++MODULE_PARM_DESC(conf_link, " Force configuration link. Used only if robust firmware flashing required (f.e. recovery)"); ++ ++static int dvp_order; ++module_param(dvp_order, int, 0644); ++MODULE_PARM_DESC(dvp_order, " DVP bus bits order"); ++ ++static int max_width; ++module_param(max_width, int, 0644); ++MODULE_PARM_DESC(max_width, " Fixed sensor width"); ++ ++static int max_height; ++module_param(max_height, int, 0644); ++MODULE_PARM_DESC(max_height, " Fixed sensor height"); ++ ++static inline struct ov490_priv *to_ov490(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct ov490_priv, sd); ++} ++ ++static void ov490_s_port(struct i2c_client *client, int fwd_en) ++{ ++ struct ov490_priv *priv = to_ov490(client); ++ int tmp_addr; ++ ++ if (priv->max9286_addr) { ++ tmp_addr = client->addr; ++ client->addr = priv->max9286_addr; /* Deserializer I2C address */ ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ client->addr = tmp_addr; ++ }; ++} ++ ++static void ov490_reset(struct i2c_client *client) ++{ ++ struct ov490_priv *priv = to_ov490(client); ++ int tmp_addr; ++ ++ if (priv->max9286_addr) { ++ if (priv->gpio_resetb < 1 || priv->gpio_resetb > 5) ++ return; ++ ++ tmp_addr = client->addr; ++ /* get out from sensor reset */ ++ client->addr = priv->max9271_addr; /* MAX9271 I2C address */ ++ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | ++ (priv->active_low_resetb ? 0 : BIT(priv->gpio_resetb))); /* set GPIOn value to reset */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | ++ (priv->active_low_resetb ? BIT(priv->gpio_resetb) : 0)); /* set GPIOn value to un-reset */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ client->addr = tmp_addr; ++ } ++ ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* TI9x4 I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x6e, 0x8a); /* set GPIO1 value to reset */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x6e, 0x9a); /* set GPIO1 value to un-reset */ ++ } ++} ++ ++static int ov490_set_regs(struct i2c_client *client, ++ const struct ov490_reg *regs, int nr_regs) ++{ ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (reg16_write(client, regs[i].reg, regs[i].val)) { ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, regs[i].reg, regs[i].val); ++ } ++ } ++ ++ return 0; ++} ++ ++static u8 ov490_ov10640_read(struct i2c_client *client, u16 addr) ++{ ++ u8 reg_val = 0; ++ ++ reg16_write(client, 0xFFFD, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x5000, 0x01); /* read operation */ ++ reg16_write(client, 0x5001, addr >> 8); ++ reg16_write(client, 0x5002, addr & 0xff); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x00C0, 0xc1); ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(1000, 1500); /* wait 1 ms */ ++ reg16_read(client, 0x5000, ®_val); ++ ++ return reg_val; ++} ++ ++static void ov490_ov10640_write(struct i2c_client *client, u16 addr, u8 val) ++{ ++ reg16_write(client, 0xFFFD, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x5000, 0x00); /* write operation */ ++ reg16_write(client, 0x5001, addr >> 8); ++ reg16_write(client, 0x5002, addr & 0xff); ++ reg16_write(client, 0x5003, val); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x00C0, 0xc1); ++} ++ ++static int ov490_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int ov490_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov490_priv *priv = to_ov490(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int ov490_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int ov490_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ ++ return 0; ++} ++ ++static int ov490_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov490_priv *priv = to_ov490(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = OV490_VERSION_REG >> 8; ++ edid->edid[9] = OV490_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int ov490_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov490_priv *priv = to_ov490(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > priv->max_width) || ++ (rect->top + rect->height > priv->max_height)) ++ *rect = priv->rect; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ return 0; ++} ++ ++static int ov490_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov490_priv *priv = to_ov490(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = priv->max_width; ++ sel->r.height = priv->max_height; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = priv->max_width; ++ sel->r.height = priv->max_height; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ov490_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int ov490_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u8 val = 0; ++ ++ ret = reg16_read(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int ov490_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ ++ ret = reg16_write(client, (u16)reg->reg, (u8)reg->val); ++ if ((u8)reg->reg == 0xFFFD) ++ usleep_range(100, 150); /* wait 100 us */ ++ if ((u8)reg->reg == 0xFFFE) ++ usleep_range(100, 150); /* wait 100 us */ ++ return ret; ++} ++#endif ++ ++static struct v4l2_subdev_core_ops ov490_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ov490_g_register, ++ .s_register = ov490_s_register, ++#endif ++}; ++ ++static int ov490_s_gamma(int a, int ref) ++{ ++ if ((a + ref) > 0xff) ++ return 0xff; ++ ++ if ((a + ref) < 0) ++ return 0; ++ ++ return a + ref; ++} ++ ++static int ov490_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov490_priv *priv = to_ov490(client); ++ int ret = -EINVAL; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ /* SDE (rough) brightness */ ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); ++ ret |= reg16_write(client, 0x5001, ctrl->val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xf1); ++ break; ++ case V4L2_CID_CONTRAST: ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ctrl->val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xfd); ++ break; ++ case V4L2_CID_SATURATION: ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ctrl->val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xf3); ++ break; ++ case V4L2_CID_HUE: ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ctrl->val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xf5); ++ break; ++ case V4L2_CID_GAMMA: ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ov490_s_gamma(ctrl->val, 0x12)); ++ ret |= reg16_write(client, 0x5001, ov490_s_gamma(ctrl->val, 0x20)); ++ ret |= reg16_write(client, 0x5002, ov490_s_gamma(ctrl->val, 0x3b)); ++ ret |= reg16_write(client, 0x5003, ov490_s_gamma(ctrl->val, 0x5d)); ++ ret |= reg16_write(client, 0x5004, ov490_s_gamma(ctrl->val, 0x6a)); ++ ret |= reg16_write(client, 0x5005, ov490_s_gamma(ctrl->val, 0x76)); ++ ret |= reg16_write(client, 0x5006, ov490_s_gamma(ctrl->val, 0x81)); ++ ret |= reg16_write(client, 0x5007, ov490_s_gamma(ctrl->val, 0x8b)); ++ ret |= reg16_write(client, 0x5008, ov490_s_gamma(ctrl->val, 0x96)); ++ ret |= reg16_write(client, 0x5009, ov490_s_gamma(ctrl->val, 0x9e)); ++ ret |= reg16_write(client, 0x500a, ov490_s_gamma(ctrl->val, 0xae)); ++ ret |= reg16_write(client, 0x500b, ov490_s_gamma(ctrl->val, 0xbc)); ++ ret |= reg16_write(client, 0x500c, ov490_s_gamma(ctrl->val, 0xcf)); ++ ret |= reg16_write(client, 0x500d, ov490_s_gamma(ctrl->val, 0xde)); ++ ret |= reg16_write(client, 0x500e, ov490_s_gamma(ctrl->val, 0xec)); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xf9); ++ break; ++ case V4L2_CID_SHARPNESS: ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ctrl->val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xfb); ++ break; ++ case V4L2_CID_AUTOGAIN: ++ case V4L2_CID_GAIN: ++ case V4L2_CID_EXPOSURE: ++ if (ctrl->id == V4L2_CID_AUTOGAIN) ++ priv->autogain = ctrl->val; ++ if (ctrl->id == V4L2_CID_GAIN) ++ priv->gain = ctrl->val; ++ if (ctrl->id == V4L2_CID_EXPOSURE) ++ priv->exposure = ctrl->val; ++ ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, !priv->autogain); ++ ret |= reg16_write(client, 0x5001, priv->exposure >> 8); ++ ret |= reg16_write(client, 0x5002, priv->exposure & 0xff); ++ ret |= reg16_write(client, 0x5003, priv->exposure >> 8); ++ ret |= reg16_write(client, 0x5004, priv->exposure & 0xff); ++ ret |= reg16_write(client, 0x5005, priv->exposure >> 8); ++ ret |= reg16_write(client, 0x5006, priv->exposure & 0xff); ++ ret |= reg16_write(client, 0x5007, priv->gain >> 8); ++ ret |= reg16_write(client, 0x5008, priv->gain & 0xff); ++ ret |= reg16_write(client, 0x5009, priv->gain >> 8); ++ ret |= reg16_write(client, 0x500a, priv->gain & 0xff); ++ ret |= reg16_write(client, 0x500b, priv->gain >> 8); ++ ret |= reg16_write(client, 0x500c, priv->gain & 0xff); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xea); ++ break; ++ case V4L2_CID_AUTO_WHITE_BALANCE: ++ case V4L2_CID_RED_BALANCE: ++ case V4L2_CID_BLUE_BALANCE: ++ if (ctrl->id == V4L2_CID_AUTO_WHITE_BALANCE) ++ priv->awb = ctrl->val; ++ if (ctrl->id == V4L2_CID_RED_BALANCE) { ++ priv->red = ctrl->val; ++ priv->red <<= 8; ++ priv->green_r = priv->red / 2; ++ } ++ if (ctrl->id == V4L2_CID_BLUE_BALANCE) { ++ priv->blue = ctrl->val; ++ priv->blue <<= 8; ++ priv->green_b = priv->blue / 2; ++ } ++ ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, !priv->awb); ++ ret |= reg16_write(client, 0x5001, priv->red >> 8); ++ ret |= reg16_write(client, 0x5002, priv->red & 0xff); ++ ret |= reg16_write(client, 0x5003, priv->green_r >> 8); ++ ret |= reg16_write(client, 0x5004, priv->green_r & 0xff); ++ ret |= reg16_write(client, 0x5005, priv->green_b >> 8); ++ ret |= reg16_write(client, 0x5006, priv->green_b & 0xff); ++ ret |= reg16_write(client, 0x5007, priv->blue >> 8); ++ ret |= reg16_write(client, 0x5008, priv->blue & 0xff); ++ ret |= reg16_write(client, 0x5009, priv->red >> 8); ++ ret |= reg16_write(client, 0x500a, priv->red & 0xff); ++ ret |= reg16_write(client, 0x500b, priv->green_r >> 8); ++ ret |= reg16_write(client, 0x500c, priv->green_r & 0xff); ++ ret |= reg16_write(client, 0x500d, priv->green_b >> 8); ++ ret |= reg16_write(client, 0x500e, priv->green_b & 0xff); ++ ret |= reg16_write(client, 0x500f, priv->blue >> 8); ++ ret |= reg16_write(client, 0x5010, priv->blue & 0xff); ++ ret |= reg16_write(client, 0x5011, priv->red >> 8); ++ ret |= reg16_write(client, 0x5012, priv->red & 0xff); ++ ret |= reg16_write(client, 0x5013, priv->green_r >> 8); ++ ret |= reg16_write(client, 0x5014, priv->green_r & 0xff); ++ ret |= reg16_write(client, 0x5015, priv->green_b >> 8); ++ ret |= reg16_write(client, 0x5016, priv->green_b & 0xff); ++ ret |= reg16_write(client, 0x5017, priv->blue >> 8); ++ ret |= reg16_write(client, 0x5018, priv->blue & 0xff); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xeb); ++ break; ++ case V4L2_CID_HFLIP: ++#if 1 ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ctrl->val); ++ ret |= reg16_write(client, 0x5001, 0x00); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xdc); ++#else ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3128 ++ ret |= reg16_write(client, 0x5001, 0x31); ++ ret |= reg16_write(client, 0x5002, 0x28); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_read(client, 0x5000, &val); ++ val &= ~(0x1 << 0); ++ val |= (ctrl->val << 0); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3128 ++ ret |= reg16_write(client, 0x5001, 0x31); ++ ret |= reg16_write(client, 0x5002, 0x28); ++ ret |= reg16_write(client, 0x5003, val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3291 ++ ret |= reg16_write(client, 0x5001, 0x32); ++ ret |= reg16_write(client, 0x5002, 0x91); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_read(client, 0x5000, &val); ++ val &= ~(0x1 << 1); ++ val |= (ctrl->val << 1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3291 ++ ret |= reg16_write(client, 0x5001, 0x32); ++ ret |= reg16_write(client, 0x5002, 0x91); ++ ret |= reg16_write(client, 0x5003, val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3090 ++ ret |= reg16_write(client, 0x5001, 0x30); ++ ret |= reg16_write(client, 0x5002, 0x90); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_read(client, 0x5000, &val); ++ val &= ~(0x1 << 2); ++ val |= (ctrl->val << 2); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3090 ++ ret |= reg16_write(client, 0x5001, 0x30); ++ ret |= reg16_write(client, 0x5002, 0x90); ++ ret |= reg16_write(client, 0x5003, val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++#endif ++ break; ++ case V4L2_CID_VFLIP: ++#if 1 ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ctrl->val); ++ ret |= reg16_write(client, 0x5001, 0x01); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xdc); ++#else ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3128 ++ ret |= reg16_write(client, 0x5001, 0x31); ++ ret |= reg16_write(client, 0x5002, 0x28); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_read(client, 0x5000, &val); ++ val &= ~(0x1 << 1); ++ val |= (ctrl->val << 1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3128 ++ ret |= reg16_write(client, 0x5001, 0x31); ++ ret |= reg16_write(client, 0x5002, 0x28); ++ ret |= reg16_write(client, 0x5003, val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3291 ++ ret |= reg16_write(client, 0x5001, 0x32); ++ ret |= reg16_write(client, 0x5002, 0x91); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_read(client, 0x5000, &val); ++ val &= ~(0x1 << 2); ++ val |= (ctrl->val << 2); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3291 ++ ret |= reg16_write(client, 0x5001, 0x32); ++ ret |= reg16_write(client, 0x5002, 0x91); ++ ret |= reg16_write(client, 0x5003, val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3090 ++ ret |= reg16_write(client, 0x5001, 0x30); ++ ret |= reg16_write(client, 0x5002, 0x90); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_read(client, 0x5000, &val); ++ val &= ~(0x1 << 3); ++ val |= (ctrl->val << 3); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3090 ++ ret |= reg16_write(client, 0x5001, 0x30); ++ ret |= reg16_write(client, 0x5002, 0x90); ++ ret |= reg16_write(client, 0x5003, val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++#endif ++ break; ++ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: ++ ret = 0; ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ov490_ctrl_ops = { ++ .s_ctrl = ov490_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops ov490_video_ops = { ++ .s_stream = ov490_s_stream, ++ .g_mbus_config = ov490_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops ov490_subdev_pad_ops = { ++ .get_edid = ov490_get_edid, ++ .enum_mbus_code = ov490_enum_mbus_code, ++ .get_selection = ov490_get_selection, ++ .set_selection = ov490_set_selection, ++ .get_fmt = ov490_get_fmt, ++ .set_fmt = ov490_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops ov490_subdev_ops = { ++ .core = &ov490_core_ops, ++ .video = &ov490_video_ops, ++ .pad = &ov490_subdev_pad_ops, ++}; ++ ++static void ov490_otp_id_read(struct i2c_client *client) ++{ ++ struct ov490_priv *priv = to_ov490(client); ++ int i; ++ int otp_bank0_allzero = 1; ++ ++#if 0 ++ /* read camera id from ov490 OTP memory */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x28); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0xE084, 0x40); /* manual mode, bank#0 */ ++ reg16_write(client, 0xE081, 1); /* start OTP read */ ++ ++ usleep_range(25000, 26000); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i++) ++ reg16_read(client, 0xe000 + i + 4, &priv->id[i]); ++#else ++ /* read camera id from ov10640 OTP memory */ ++ ov490_ov10640_write(client, 0x349C, 1); ++ usleep_range(25000, 25500); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i++) { ++ /* first 6 bytes are equal on all ov10640 */ ++ priv->id[i] = ov490_ov10640_read(client, 0x349e + i + 6); ++ if (priv->id[i]) ++ otp_bank0_allzero = 0; ++ } ++ ++ if (otp_bank0_allzero) { ++ ov490_ov10640_write(client, 0x3495, 0x41); /* bank#1 */ ++ ov490_ov10640_write(client, 0x349C, 1); ++ usleep_range(25000, 25500); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i++) ++ priv->id[i] = ov490_ov10640_read(client, 0x34ae + i); ++ } ++#endif ++} ++ ++static ssize_t ov490_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov490_priv *priv = to_ov490(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_ov490, S_IRUGO, ov490_otp_id_show, NULL); ++ ++static int ov490_initialize(struct i2c_client *client) ++{ ++ struct ov490_priv *priv = to_ov490(client); ++ u8 val = 0; ++ u8 pid = 0, ver = 0; ++ int ret = 0, timeout, retry_timeout = 3; ++ ++ if (priv->is_fixed_sensor) { ++ dev_info(&client->dev, "ov490/ov10640 fixed-sensor res %dx%d\n", priv->max_width, priv->max_height); ++ return 0; ++ } ++ ++ ov490_s_port(client, 1); ++ ++ /* check and show product ID and manufacturer ID */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_read(client, OV490_PID, &pid); ++ reg16_read(client, OV490_VER, &ver); ++ ++ if (OV490_VERSION(pid, ver) != OV490_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x:%x\n", pid, ver); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ if (unlikely(conf_link)) ++ goto out; ++ ++again: ++ /* Check if firmware booted by reading stream-on status */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x29); ++ usleep_range(100, 150); /* wait 100 us */ ++ for (timeout = 300; timeout > 0; timeout--) { ++ reg16_read(client, 0xd000, &val); ++ if (val == 0x0c) ++ break; ++ mdelay(1); ++ } ++ ++ /* wait firmware apps started by reading OV10640 ID */ ++ for (;timeout > 0; timeout--) { ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x5000, 0x01); ++ reg16_write(client, 0x5001, 0x30); ++ reg16_write(client, 0x5002, 0x0a); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0xC0, 0xc1); ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(1000, 1500); /* wait 1 ms */ ++ reg16_read(client, 0x5000, &val); ++ if (val == 0xa6) ++ break; ++ mdelay(1); ++ } ++ ++ if (!timeout) { ++ dev_err(&client->dev, "Timeout firmware boot wait, retrying\n"); ++ /* reset OV10640 using RESETB pin controlled by OV490 GPIO0 */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x0050, 0x01); ++ reg16_write(client, 0x0054, 0x01); ++ reg16_write(client, 0x0058, 0x00); ++ mdelay(10); ++ reg16_write(client, 0x0058, 0x01); ++ /* reset OV490 using RESETB pin controlled by serializer */ ++ ov490_reset(client); ++ if (retry_timeout--) ++ goto again; ++ } ++ ++ /* read resolution used by current firmware */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x82); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_read(client, OV490_ISP_HSIZE_HIGH, &val); ++ priv->max_width = val; ++ reg16_read(client, OV490_ISP_HSIZE_LOW, &val); ++ priv->max_width = (priv->max_width << 8) | val; ++ reg16_read(client, OV490_ISP_VSIZE_HIGH, &val); ++ priv->max_height = val; ++ reg16_read(client, OV490_ISP_VSIZE_LOW, &val); ++ priv->max_height = (priv->max_height << 8) | val; ++ /* Program wizard registers */ ++ ov490_set_regs(client, ov490_regs_wizard, ARRAY_SIZE(ov490_regs_wizard)); ++ /* Set DVP bit swap */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x28); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x6009, priv->dvp_order << 4); ++ /* Read OTP IDs */ ++ ov490_otp_id_read(client); ++ ++out: ++ dev_info(&client->dev, "ov490/ov10640 PID %x%x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, ver, priv->max_width, priv->max_height, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ ov490_s_port(client, 0); ++ ++ return ret; ++} ++ ++static int ov490_parse_dt(struct device_node *np, struct ov490_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ const char *fixed_sensor; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order); ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) { ++ if (of_property_read_u32(rendpoint->parent->parent, "maxim,resetb-gpio", &priv->gpio_resetb)) { ++ priv->gpio_resetb = -1; ++ } else { ++ if (of_property_read_bool(rendpoint->parent->parent, "maxim,resetb-active-high")) ++ priv->active_low_resetb = false; ++ else ++ priv->active_low_resetb = true; ++ } ++ break; ++ } ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ if (!priv->max9286_addr && !priv->ti9x4_addr) { ++ dev_err(&client->dev, "deserializer does not present for OV490\n"); ++ return -EINVAL; ++ } ++ ++ ov490_s_port(client, 1); ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ ++ reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x0A, OV490_I2C_ADDR << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, OV490_I2C_ADDR << 1); /* Sensor native I2C address */ ++ ++ reg8_write(client, 0x6e, 0x9a); /* GPIO0 - fsin, GPIO1 - resetb */ ++ } ++ client->addr = tmp_addr; ++ ++ if (!of_property_read_string(np, "maxim,fixed-sensor", &fixed_sensor) && ++ strcmp(fixed_sensor, "ov490") == 0) { ++ if (of_property_read_u32(np, "maxim,width", &priv->max_width)) ++ priv->max_width = 1280; ++ ++ if (of_property_read_u32(np, "maxim,height", &priv->max_height)) ++ priv->max_height = 966; ++ ++ priv->is_fixed_sensor = true; ++ } ++ ++ /* module params override dts */ ++ if (dvp_order) ++ priv->dvp_order = dvp_order; ++ if (max_width && max_height) { ++ priv->max_width = max_width; ++ priv->max_height = max_height; ++ priv->is_fixed_sensor = true; ++ } ++ ++ return 0; ++} ++ ++static int ov490_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ov490_priv *priv; ++ struct v4l2_ctrl *ctrl; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &ov490_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ priv->exposure = 0x100; ++ priv->gain = 0x100; ++ priv->autogain = 1; ++ priv->red = 0x400; ++ priv->blue = 0x400; ++ priv->green_r = priv->red / 2; ++ priv->green_b = priv->blue / 2; ++ priv->awb = 1; ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, priv->autogain); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_RED_BALANCE, 2, 0xf, 1, priv->red >> 8); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_BLUE_BALANCE, 2, 0xf, 1, priv->blue >> 8); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 9); ++ if (ctrl) ++ ctrl->flags &= ~V4L2_CTRL_FLAG_READ_ONLY; ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = ov490_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = ov490_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = priv->max_width; ++ priv->rect.height = priv->max_height; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ov490) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_OV490_OV10640 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int ov490_remove(struct i2c_client *client) ++{ ++ struct ov490_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ov490); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_OV490_OV10640 ++static const struct i2c_device_id ov490_id[] = { ++ { "ov490-ov10640", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ov490_id); ++ ++static const struct of_device_id ov490_of_ids[] = { ++ { .compatible = "ovti,ov490-ov10640", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ov490_of_ids); ++ ++static struct i2c_driver ov490_i2c_driver = { ++ .driver = { ++ .name = "ov490-ov10640", ++ .of_match_table = ov490_of_ids, ++ }, ++ .probe = ov490_probe, ++ .remove = ov490_remove, ++ .id_table = ov490_id, ++}; ++ ++module_i2c_driver(ov490_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for OV490-OV10640"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/ov490_ov10640.h b/drivers/media/i2c/soc_camera/ov490_ov10640.h +new file mode 100644 +index 0000000..b22e93e +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov490_ov10640.h +@@ -0,0 +1,102 @@ ++/* ++ * OmniVision ov490-ov10640 sensor camera wizard 1280x1080@30/UYVY/BT601/8bit ++ * ++ * Copyright (C) 2016-2017 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++//#define OV490_DISPLAY_PATTERN ++ ++struct ov490_reg { ++ u16 reg; ++ u8 val; ++}; ++ ++static const struct ov490_reg ov490_regs_wizard[] = { ++/* The following registers should match firmware */ ++{0xfffd, 0x80}, ++{0xfffe, 0x82}, ++{0x0071, 0x11}, ++{0x0075, 0x11}, ++{0xfffe, 0x29}, ++{0x6010, 0x01}, ++/* ov490 EMB line disable in YUV and RAW data, NOTE: EMB line is still used in ISP and sensor */ ++{0xe000, 0x14}, ++#if 0 /* do not disable EMB line in ISP! */ ++{0x4017, 0x00}, ++#endif ++{0xfffe, 0x28}, ++{0x6000, 0x04}, ++{0x6004, 0x00}, ++{0x6008, 0x00}, // PCLK polarity - useless due to silicon bug -> use 0x808000bb register ++{0xfffe, 0x80}, ++{0x0091, 0x00}, ++{0x00bb, 0x1d}, // bit[3]=0 - PCLK polarity workaround ++/* ov10640 EMB line disable */ ++#if 0 /* do not disable EMB line in sensor! */ ++{0xfffe, 0x19}, ++{0x5000, 0x00}, ++{0x5001, 0x30}, ++{0x5002, 0x91}, ++{0x5003, 0x08}, ++{0xfffe, 0x80}, ++{0x00c0, 0xc1}, ++#endif ++/* Ov490 FSIN: app_fsin_from_fsync */ ++{0xfffe, 0x85}, ++{0x0008, 0x00}, ++{0x0009, 0x01}, ++{0x000A, 0x05}, // fsin0 src ++{0x000B, 0x00}, ++{0x0030, 0x02}, // fsin0_delay ++{0x0031, 0x00}, ++{0x0032, 0x00}, ++{0x0033, 0x00}, ++{0x0038, 0x02}, // fsin1_delay ++{0x0039, 0x00}, ++{0x003A, 0x00}, ++{0x003B, 0x00}, ++{0x0070, 0x2C}, // fsin0_length ++{0x0071, 0x01}, ++{0x0072, 0x00}, ++{0x0073, 0x00}, ++{0x0074, 0x64}, // fsin1_length ++{0x0075, 0x00}, ++{0x0076, 0x00}, ++{0x0077, 0x00}, ++{0x0000, 0x14}, ++{0x0001, 0x00}, ++{0x0002, 0x00}, ++{0x0003, 0x00}, ++{0x0004, 0x32}, // load fsin0,load fsin1,load other, it will be cleared automatically. ++{0x0005, 0x00}, ++{0x0006, 0x00}, ++{0x0007, 0x00}, ++{0xfffe, 0x80}, ++{0x0081, 0x00}, // 03;SENSOR FSIN ++/* ov10640 FSIN */ ++{0xfffe, 0x19}, ++{0x5000, 0x00}, ++{0x5001, 0x30}, ++{0x5002, 0x8c}, ++{0x5003, 0xb2}, ++{0xfffe, 0x80}, ++{0x00c0, 0xc1}, ++/* ov10640 HFLIP=1 by default */ ++{0xfffe, 0x19}, ++{0x5000, 0x01}, ++{0x5001, 0x00}, ++{0xfffe, 0x80}, ++{0x00c0, 0xdc}, ++#ifdef OV490_DISPLAY_PATTERN ++{0xfffd, 0x80}, ++{0xfffe, 0x19}, ++{0x5000, 0x02}, ++{0xfffe, 0x80}, ++{0x00c0, 0xd6}, ++#endif ++}; +diff --git a/drivers/media/i2c/soc_camera/ov495_ov2775.c b/drivers/media/i2c/soc_camera/ov495_ov2775.c +new file mode 100644 +index 0000000..bb5991c +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov495_ov2775.c +@@ -0,0 +1,640 @@ ++/* ++ * OmniVision ov495-ov2775 sensor camera driver ++ * ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "ov495_ov2775.h" ++ ++#define OV495_I2C_ADDR 0x24 ++ ++#define OV495_PID 0x300a ++#define OV495_VER 0x300b ++#define OV495_VERSION_REG 0x0495 ++#define OV495_VERSION(pid, ver) (((pid) << 8) | ((ver) & 0xff)) ++ ++#define OV495_ISP_HSIZE_LOW 0x60 ++#define OV495_ISP_HSIZE_HIGH 0x61 ++#define OV495_ISP_VSIZE_LOW 0x62 ++#define OV495_ISP_VSIZE_HIGH 0x63 ++ ++struct ov495_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int max_width; ++ int max_height; ++ int init_complete; ++ u8 id[6]; ++ int exposure; ++ int gain; ++ int autogain; ++ /* serializers */ ++ int max9286_addr; ++ int max9271_addr; ++ int ti9x4_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++ ++}; ++ ++static int force_conf_link; ++ ++static __init int ov495_force_conf_link(char *str) ++{ ++ /* force configuration link */ ++ /* used only if robust firmware flashing required (f.e. recovery) */ ++ force_conf_link = 1; ++ return 0; ++} ++early_param("force_conf_link", ov495_force_conf_link); ++ ++static inline struct ov495_priv *to_ov495(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct ov495_priv, sd); ++} ++ ++static int ov495_set_regs(struct i2c_client *client, ++ const struct ov495_reg *regs, int nr_regs) ++{ ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (reg16_write(client, regs[i].reg, regs[i].val)) { ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, regs[i].reg, regs[i].val); ++ } ++ } ++ ++ return 0; ++} ++ ++static int ov495_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int ov495_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov495_priv *priv = to_ov495(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int ov495_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int ov495_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ ++ return 0; ++} ++ ++static int ov495_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov495_priv *priv = to_ov495(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = OV495_VERSION_REG >> 8; ++ edid->edid[9] = OV495_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int ov495_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov495_priv *priv = to_ov495(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > priv->max_width) || ++ (rect->top + rect->height > priv->max_height)) ++ *rect = priv->rect; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ return 0; ++} ++ ++static int ov495_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov495_priv *priv = to_ov495(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = priv->max_width; ++ sel->r.height = priv->max_height; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = priv->max_width; ++ sel->r.height = priv->max_height; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ov495_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int ov495_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u8 val = 0; ++ ++ ret = reg16_read(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int ov495_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ ++ ret = reg16_write(client, (u16)reg->reg, (u8)reg->val); ++ if ((u8)reg->reg == 0xFFFD) ++ usleep_range(100, 150); /* wait 100 us */ ++ if ((u8)reg->reg == 0xFFFE) ++ usleep_range(100, 150); /* wait 100 us */ ++ return ret; ++} ++#endif ++ ++static struct v4l2_subdev_core_ops ov495_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ov495_g_register, ++ .s_register = ov495_s_register, ++#endif ++}; ++ ++static int ov495_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov495_priv *priv = to_ov495(client); ++ int ret = -EINVAL; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ break; ++ case V4L2_CID_CONTRAST: ++ break; ++ case V4L2_CID_SATURATION: ++ break; ++ case V4L2_CID_HUE: ++ break; ++ case V4L2_CID_GAMMA: ++ break; ++ case V4L2_CID_SHARPNESS: ++ break; ++ case V4L2_CID_AUTOGAIN: ++ case V4L2_CID_GAIN: ++ case V4L2_CID_EXPOSURE: ++ break; ++ case V4L2_CID_HFLIP: ++ ret = reg16_write(client, 0x3516, 0x00); ++ ret |= reg16_write(client, 0x0ffc, 0x00); ++ ret |= reg16_write(client, 0x0500, ctrl->val); ++ ret |= reg16_write(client, 0x0501, 0x00); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x30C0, 0xdc); ++ ret |= reg16_write(client, 0x3516, 0x01); ++ break; ++ case V4L2_CID_VFLIP: ++ ret = reg16_write(client, 0x3516, 0x00); ++ ret |= reg16_write(client, 0x0ffc, 0x00); ++ ret |= reg16_write(client, 0x0500, ctrl->val); ++ ret |= reg16_write(client, 0x0501, 0x01); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x30C0, 0xdc); ++ ret |= reg16_write(client, 0x3516, 0x01); ++ break; ++ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: ++ ret = 0; ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ov495_ctrl_ops = { ++ .s_ctrl = ov495_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops ov495_video_ops = { ++ .s_stream = ov495_s_stream, ++ .g_mbus_config = ov495_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops ov495_subdev_pad_ops = { ++ .get_edid = ov495_get_edid, ++ .enum_mbus_code = ov495_enum_mbus_code, ++ .get_selection = ov495_get_selection, ++ .set_selection = ov495_set_selection, ++ .get_fmt = ov495_get_fmt, ++ .set_fmt = ov495_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops ov495_subdev_ops = { ++ .core = &ov495_core_ops, ++ .video = &ov495_video_ops, ++ .pad = &ov495_subdev_pad_ops, ++}; ++ ++static void ov495_otp_id_read(struct i2c_client *client) ++{ ++ struct ov495_priv *priv = to_ov495(client); ++ int i; ++ ++#if 0 ++ /* read camera id from ov495 OTP memory */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x20); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x7384, 0x40); /* manual mode, bank#0 */ ++ reg16_write(client, 0x7381, 1); /* start OTP read */ ++ ++ usleep_range(25000, 26000); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i++) ++ reg16_read(client, 0x7300 + i + 4, &priv->id[i]); ++#else ++ /* read camera id from ov2775 OTP memory */ ++ reg16_write(client, 0x3516, 0x00); /* unlock write */ ++ reg16_write(client, 0x0FFC, 0); ++ reg16_write(client, 0x0500, 0x00); /* write 0x34a1 -> 1 */ ++ reg16_write(client, 0x0501, 0x34); ++ reg16_write(client, 0x0502, 0xa1); ++ reg16_write(client, 0x0503, 1); ++ reg16_write(client, 0x30C0, 0xc1); ++ ++ usleep_range(25000, 25500); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i++) { ++ reg16_write(client, 0x3516, 0x00); /* unlock write */ ++ reg16_write(client, 0x0500, 0x01); /* read (0x7a00 + i) */ ++ reg16_write(client, 0x0501, 0x7a); ++ reg16_write(client, 0x0502, 0x00 + i + (i < 3 ? 11 : 3)); /* take bytes 11,12,13,6,7,8 */ ++ reg16_write(client, 0x30C0, 0xc1); ++ usleep_range(1000, 1500); /* wait 1 ms */ ++ reg16_read(client, 0x0500, &priv->id[i]); ++ } ++#endif ++} ++ ++static ssize_t ov495_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov495_priv *priv = to_ov495(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_ov495, S_IRUGO, ov495_otp_id_show, NULL); ++ ++static int ov495_initialize(struct i2c_client *client) ++{ ++ struct ov495_priv *priv = to_ov495(client); ++ u8 pid = 0, ver = 0; ++ int ret = 0; ++ ++ /* check and show product ID and manufacturer ID */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_read(client, OV495_PID, &pid); ++ reg16_read(client, OV495_VER, &ver); ++ ++ if (OV495_VERSION(pid, ver) != OV495_VERSION_REG) { ++ dev_err(&client->dev, "Product ID error %x:%x\n", pid, ver); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ if (unlikely(force_conf_link)) ++ goto out; ++ ++#if 0 ++ /* read resolution used by current firmware */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x82); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_read(client, OV495_ISP_HSIZE_HIGH, &val); ++ priv->max_width = val; ++ reg16_read(client, OV495_ISP_HSIZE_LOW, &val); ++ priv->max_width = (priv->max_width << 8) | val; ++ reg16_read(client, OV495_ISP_VSIZE_HIGH, &val); ++ priv->max_height = val; ++ reg16_read(client, OV495_ISP_VSIZE_LOW, &val); ++ priv->max_height = (priv->max_height << 8) | val; ++#else ++ priv->max_width = 1920; ++ priv->max_height = 1080; ++#endif ++ ++ /* set virtual channel */ ++ ov495_regs_wizard[3].val = 0x1e | (priv->port << 6); ++ /* Program wizard registers */ ++ ov495_set_regs(client, ov495_regs_wizard, ARRAY_SIZE(ov495_regs_wizard)); ++ /* Read OTP IDs */ ++ ov495_otp_id_read(client); ++ ++out: ++ dev_info(&client->dev, "ov495/ov2775 PID %x%x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, ver, priv->max_width, priv->max_height, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ return ret; ++} ++ ++static int ov495_parse_dt(struct device_node *np, struct ov495_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ if (!priv->ti9x4_addr) { ++ dev_err(&client->dev, "deserializer does not present for OV495\n"); ++ return -EINVAL; ++ } ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, OV495_I2C_ADDR << 1); /* Sensor native I2C address */ ++ ++ reg8_write(client, 0x6e, 0x9a); /* GPIO0 - fsin, GPIO1 - resetb */ ++ /* TODO: why too long? move logic to workqueue? */ ++ mdelay(350); /* time needed to boot all sensor IPs */ ++ } ++ client->addr = tmp_addr; ++ ++ return 0; ++} ++ ++static int ov495_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ov495_priv *priv; ++ struct v4l2_ctrl *ctrl; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &ov495_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ priv->exposure = 0x100; ++ priv->gain = 0x100; ++ priv->autogain = 1; ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 9); ++ if (ctrl) ++ ctrl->flags &= ~V4L2_CTRL_FLAG_READ_ONLY; ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = ov495_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = ov495_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = priv->max_width; ++ priv->rect.height = priv->max_height; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ov495) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_OV495_OV2775 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int ov495_remove(struct i2c_client *client) ++{ ++ struct ov495_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ov495); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_OV495_OV2775 ++static const struct i2c_device_id ov495_id[] = { ++ { "ov495-ov2775", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ov495_id); ++ ++static const struct of_device_id ov495_of_ids[] = { ++ { .compatible = "ovti,ov495-ov2775", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ov495_of_ids); ++ ++static struct i2c_driver ov495_i2c_driver = { ++ .driver = { ++ .name = "ov495-ov2775", ++ .of_match_table = ov495_of_ids, ++ }, ++ .probe = ov495_probe, ++ .remove = ov495_remove, ++ .id_table = ov495_id, ++}; ++ ++module_i2c_driver(ov495_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for OV495-OV2775"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/ov495_ov2775.h b/drivers/media/i2c/soc_camera/ov495_ov2775.h +new file mode 100644 +index 0000000..17c94ae +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov495_ov2775.h +@@ -0,0 +1,23 @@ ++/* ++ * OmniVision ov495-ov2775 sensor camera wizard 1920x1080@30/UYVY/MIPI ++ * ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++struct ov495_reg { ++ u16 reg; ++ u8 val; ++}; ++ ++static struct ov495_reg ov495_regs_wizard[] = { ++{0x3516, 0x00}, /* unlock write */ ++{0xFFFD, 0x80}, ++{0xFFFE, 0x20}, ++{0x8017, 0x1e | (0 << 6)}, ++{0x7c10, 0x01}, /* UYVY */ ++}; +diff --git a/drivers/media/i2c/soc_camera/ti9x4.c b/drivers/media/i2c/soc_camera/ti9x4.c +new file mode 100644 +index 0000000..2ce98b4 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ti9x4.c +@@ -0,0 +1,520 @@ ++ /* ++ * TI DS90UB954/960/964 FPDLinkIII driver ++ * ++ * Copyright (C) 2017-2018 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "ti9x4.h" ++ ++struct ti9x4_priv { ++ struct v4l2_subdev sd[4]; ++ struct fwnode_handle *sd_fwnode[4]; ++ int des_addr; ++ int links; ++ int lanes; ++ int csi_rate; ++ const char *forwarding_mode; ++ int is_coax; ++ int dvp_bus; ++ int hsync; ++ int vsync; ++ int poc_delay; ++ atomic_t use_count; ++ struct i2c_client *client; ++ int ti9x3_addr_map[4]; ++ char chip_id[6]; ++ int ser_id; ++ struct gpio_desc *poc_gpio[4]; /* PoC power supply */ ++}; ++ ++static int ser_id; ++module_param(ser_id, int, 0644); ++MODULE_PARM_DESC(ser_id, " Serializer ID (default: TI913)"); ++ ++static int is_stp; ++module_param(is_stp, int, 0644); ++MODULE_PARM_DESC(is_stp, " STP cable (default: Coax cable)"); ++ ++static int dvp_bus = 8; ++module_param(dvp_bus, int, 0644); ++MODULE_PARM_DESC(dvp_bus, " DVP/CSI over FPDLink (default: DVP 8-bit)"); ++ ++static int hsync; ++module_param(hsync, int, 0644); ++MODULE_PARM_DESC(hsync, " HSYNC invertion (default: 0 - not inverted)"); ++ ++static int vsync = 1; ++module_param(vsync, int, 0644); ++MODULE_PARM_DESC(vsync, " VSYNC invertion (default: 1 - inverted)"); ++ ++static int poc_delay; ++module_param(poc_delay, int, 0644); ++MODULE_PARM_DESC(poc_delay, " Delay in ms after POC enable (default: 0 ms)"); ++ ++#ifdef TI954_SILICON_ERRATA ++static int indirect_write(struct i2c_client *client, unsigned int page, u8 reg, u8 val) ++{ ++ if (page > 7) ++ return -EINVAL; ++ ++ reg8_write(client, 0xb0, page << 2); ++ reg8_write(client, 0xb1, reg); ++ reg8_write(client, 0xb2, val); ++ ++ return 0; ++} ++ ++static int indirect_read(struct i2c_client *client, unsigned int page, u8 reg, u8 *val) ++{ ++ if (page > 7) ++ return -EINVAL; ++ ++ reg8_write(client, 0xb0, page << 2); ++ reg8_write(client, 0xb1, reg); ++ reg8_read(client, 0xb2, val); ++ ++ return 0; ++} ++#endif ++ ++static void ti9x4_read_chipid(struct i2c_client *client) ++{ ++ struct ti9x4_priv *priv = i2c_get_clientdata(client); ++ ++ /* Chip ID */ ++ reg8_read(client, 0xf1, &priv->chip_id[0]); ++ reg8_read(client, 0xf2, &priv->chip_id[1]); ++ reg8_read(client, 0xf3, &priv->chip_id[2]); ++ reg8_read(client, 0xf4, &priv->chip_id[3]); ++ reg8_read(client, 0xf5, &priv->chip_id[4]); ++ priv->chip_id[5] = '\0'; ++} ++ ++static void ti9x4_initial_setup(struct i2c_client *client) ++{ ++ struct ti9x4_priv *priv = i2c_get_clientdata(client); ++ ++ /* Initial setup */ ++ client->addr = priv->des_addr; /* TI9x4 I2C */ ++ reg8_write(client, 0x08, 0x1c); /* I2C glitch filter depth */ ++ reg8_write(client, 0x0a, 0x79); /* I2C high pulse width */ ++ reg8_write(client, 0x0b, 0x79); /* I2C low pulse width */ ++ reg8_write(client, 0x0d, 0xb9); /* VDDIO 3.3V */ ++ switch (priv->csi_rate) { ++ case 1600: /* REFCLK = 25MHZ */ ++ case 1450: /* REFCLK = 22.5MHZ */ ++ reg8_write(client, 0x1f, 0x00); /* CSI rate 1.5/1.6Gbps */ ++ break; ++ case 800: /* REFCLK = 25MHZ */ ++ case 700: /* REFCLK = 22.5MHZ */ ++ reg8_write(client, 0x1f, 0x02); /* CSI rate 700/800Mbps */ ++ break; ++ case 400: /* REFCLK = 25MHZ */ ++ reg8_write(client, 0x1f, 0x03); /* CSI rate 400Mbps */ ++ break; ++ default: ++ dev_err(&client->dev, "unsupported CSI rate %d\n", priv->csi_rate); ++ } ++ ++ if (strcmp(priv->forwarding_mode, "round-robin") == 0) { ++ reg8_write(client, 0x21, 0x01); /* Round Robin forwarding enable */ ++ } else if (strcmp(priv->forwarding_mode, "synchronized") == 0) { ++ reg8_write(client, 0x21, 0x44); /* Basic Syncronized forwarding enable (FrameSync must be enabled!!) */ ++ } ++ ++ reg8_write(client, 0x32, 0x01); /* Select TX (CSI) port 0 */ ++ reg8_write(client, 0x33, ((priv->lanes - 1) ^ 0x3) << 4); /* disable CSI output, set CSI lane count, non-continuous CSI mode */ ++ reg8_write(client, 0x20, 0xf0); /* disable port forwarding */ ++#if 0 ++ /* FrameSync setup for REFCLK=25MHz, FPS=30: period_counts=1/2/FPS*25MHz =1/2/30*25Mhz =416666 -> FS_TIME=416666 */ ++ /* FrameSync setup for REFCLK=22.5MHz, FPS=30: period_counts=1/2/FPS*22.5Mhz=1/2/30*22.5Mhz=375000 -> FS_TIME=375000 */ ++// #define FS_TIME (priv->csi_rate == 1450 ? 376000 : 417666) ++ #define FS_TIME (priv->csi_rate == 1450 ? 385000 : 428000) // FPS=29.2 (new vendor's firmware AWB restriction?) ++ reg8_write(client, 0x1a, FS_TIME >> 16); /* FrameSync time 24bit */ ++ reg8_write(client, 0x1b, (FS_TIME >> 8) & 0xff); ++ reg8_write(client, 0x1c, FS_TIME & 0xff); ++ reg8_write(client, 0x18, 0x43); /* Enable FrameSync, 50/50 mode, Frame clock from 25MHz */ ++#else ++ /* FrameSync setup for REFCLK=25MHz, FPS=30: period_counts=1/FPS/12mks=1/30/12e-6=2777 -> HI=2, LO=2775 */ ++ /* FrameSync setup for REFCLK=22.5MHz, FPS=30: period_counts=1/FPS/13.333mks=1/30/13.333e-6=2500 -> HI=2, LO=2498 */ ++ #define FS_TIME (priv->csi_rate == 1450 ? (2498+15) : (2775+15)) ++ reg8_write(client, 0x19, 2 >> 8); /* FrameSync high time MSB */ ++ reg8_write(client, 0x1a, 2 & 0xff); /* FrameSync high time LSB */ ++ reg8_write(client, 0x1b, FS_TIME >> 8); /* FrameSync low time MSB */ ++ reg8_write(client, 0x1c, FS_TIME & 0xff); /* FrameSync low time LSB */ ++ reg8_write(client, 0x18, 0x01); /* Enable FrameSync, HI/LO mode, Frame clock from port0 */ ++#endif ++} ++ ++//#define SENSOR_ID 0x30 // ov10635 ++//#define SENSOR_ID 0x24 // ov490 ++ ++static void ti9x4_fpdlink3_setup(struct i2c_client *client, int idx) ++{ ++ struct ti9x4_priv *priv = i2c_get_clientdata(client); ++ u8 port_config = 0x78; ++ u8 port_config2 = 0; ++ ++ /* FPDLinkIII setup */ ++ client->addr = priv->des_addr; /* TI9x4 I2C */ ++ reg8_write(client, 0x4c, (idx << 4) | (1 << idx)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ ++ switch (priv->ser_id) { ++ case TI913_ID: ++ reg8_write(client, 0x58, 0x58); /* Back channel: Freq=2.5Mbps */ ++ break; ++ case TI953_ID: ++ reg8_write(client, 0x58, 0x5e); /* Back channel: Freq=50Mbps */ ++ break; ++ default: ++ break; ++ } ++ ++ reg8_write(client, 0x5c, priv->ti9x3_addr_map[idx] << 1); /* TI9X3 I2C addr */ ++// reg8_write(client, 0x5d, SENSOR_ID << 1); /* SENSOR I2C native - must be set by sensor driver */ ++// reg8_write(client, 0x65, (0x60 + idx) << 1); /* SENSOR I2C translated - must be set by sensor driver */ ++ ++ if (priv->is_coax) ++ port_config |= 0x04; /* Coax */ ++ else ++ port_config |= 0x00; /* STP */ ++ ++ switch (priv->dvp_bus) { ++ case 8: ++ port_config2 |= 0x80; /* RAW10 as 8-bit prosessing using upper bits */ ++ /* fall through */ ++ case 10: ++ port_config |= 0x03; /* DVP over FPDLink (TI913 compatible) RAW10/RAW8 */ ++ break; ++ case 12: ++ port_config |= 0x02; /* DVP over FPDLink (TI913 compatible) RAW12 */ ++ break; ++ default: ++ port_config |= 0x00; /* CSI over FPDLink (TI953 compatible) */ ++ } ++ ++ if (priv->vsync) ++ port_config2 |= 0x01; /* VSYNC acive low */ ++ if (priv->hsync) ++ port_config2 |= 0x02; /* HSYNC acive low */ ++ ++ reg8_write(client, 0x6d, port_config); ++ reg8_write(client, 0x7c, port_config2); ++ reg8_write(client, 0x70, (idx << 6) | 0x1e); /* CSI data type: yuv422 8-bit, assign VC */ ++ reg8_write(client, 0x71, (idx << 6) | 0x2a); /* CSI data type: RAW8, assign VC */ ++ reg8_write(client, 0xbc, 0x00); /* Setup minimal time between FV and LV to 3 PCLKs */ ++ reg8_write(client, 0x6e, 0x88); /* Sensor reset: backchannel GPIO0/GPIO1 set low */ ++} ++ ++static int ti9x4_initialize(struct i2c_client *client) ++{ ++ struct ti9x4_priv *priv = i2c_get_clientdata(client); ++ int idx; ++ ++ dev_info(&client->dev, "LINKs=%d, LANES=%d, FORWARDING=%s, CABLE=%s, ID=%s\n", ++ priv->links, priv->lanes, priv->forwarding_mode, priv->is_coax ? "coax" : "stp", priv->chip_id); ++ ++ ti9x4_initial_setup(client); ++ ++ for (idx = 0; idx < priv->links; idx++) { ++ if (!IS_ERR(priv->poc_gpio[idx])) { ++ gpiod_direction_output(priv->poc_gpio[idx], 1); /* POC power on */ ++ mdelay(priv->poc_delay); ++ } ++ ++ ti9x4_fpdlink3_setup(client, idx); ++ } ++ ++ client->addr = priv->des_addr; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int ti9x4_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct ti9x4_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ int ret; ++ u8 val = 0; ++ ++ ret = reg8_read(client, (u8)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u8); ++ ++ return 0; ++} ++ ++static int ti9x4_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct ti9x4_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ ++ return reg8_write(client, (u8)reg->reg, (u8)reg->val); ++} ++#endif ++ ++static int ti9x4_s_power(struct v4l2_subdev *sd, int on) ++{ ++ struct ti9x4_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ ++ if (on) { ++ if (atomic_inc_return(&priv->use_count) == 1) ++ reg8_write(client, 0x20, 0x00); /* enable port forwarding to CSI */ ++ } else { ++ if (atomic_dec_return(&priv->use_count) == 0) ++ reg8_write(client, 0x20, 0xf0); /* disable port forwarding to CSI */ ++ } ++ ++ return 0; ++} ++ ++static int ti9x4_registered_async(struct v4l2_subdev *sd) ++{ ++ struct ti9x4_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ ++ reg8_write(client, 0x33, ((priv->lanes - 1) ^ 0x3) << 4 | 0x1); /* enable CSI output, set CSI lane count, non-continuous CSI mode */ ++ ++ return 0; ++} ++ ++static struct v4l2_subdev_core_ops ti9x4_subdev_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ti9x4_g_register, ++ .s_register = ti9x4_s_register, ++#endif ++ .s_power = ti9x4_s_power, ++ .registered_async = ti9x4_registered_async, ++}; ++ ++static struct v4l2_subdev_ops ti9x4_subdev_ops = { ++ .core = &ti9x4_subdev_core_ops, ++}; ++ ++static int ti9x4_parse_dt(struct i2c_client *client) ++{ ++ struct ti9x4_priv *priv = i2c_get_clientdata(client); ++ struct device_node *np = client->dev.of_node; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ struct property *prop; ++ int err, pwen, i; ++ int sensor_delay; ++ char forwarding_mode_default[20] = "round-robin"; /* round-robin, synchronized */ ++ struct property *csi_rate_prop, *dvp_order_prop; ++ u8 val = 0; ++ char poc_name[10]; ++ ++ if (of_property_read_u32(np, "ti,links", &priv->links)) ++ priv->links = 4; ++ ++ if (of_property_read_u32(np, "ti,lanes", &priv->lanes)) ++ priv->lanes = 4; ++ ++ pwen = of_get_gpio(np, 0); ++ if (pwen > 0) { ++ err = devm_gpio_request_one(&client->dev, pwen, GPIOF_OUT_INIT_LOW, dev_name(&client->dev)); ++ if (err) ++ dev_err(&client->dev, "cannot request PWEN gpio %d: %d\n", pwen, err); ++ else ++ mdelay(250); ++ } ++ ++ for (i = 0; i < 4; i++) { ++ sprintf(poc_name, "POC%d", i); ++ priv->poc_gpio[i] = devm_gpiod_get_optional(&client->dev, poc_name, 0); ++ } ++ ++ reg8_read(client, 0x00, &val); /* read TI9x4 I2C address */ ++ if (val != (priv->des_addr << 1)) { ++ prop = of_find_property(np, "reg", NULL); ++ if (prop) ++ of_remove_property(np, prop); ++ return -ENODEV; ++ } ++ ++ ti9x4_read_chipid(client); ++ ++#ifdef TI954_SILICON_ERRATA ++ indirect_write(client, 7, 0x15, 0x30); ++ if (pwen > 0) ++ gpio_set_value(pwen, 1); ++ usleep_range(5000, 5500); /* wait 5ms */ ++ indirect_write(client, 7, 0x15, 0); ++#endif ++ if (!of_property_read_u32(np, "ti,sensor_delay", &sensor_delay)) ++ mdelay(sensor_delay); ++ if (of_property_read_string(np, "ti,forwarding-mode", &priv->forwarding_mode)) ++ priv->forwarding_mode = forwarding_mode_default; ++ if (of_property_read_bool(np, "ti,stp")) ++ priv->is_coax = 0; ++ else ++ priv->is_coax = 1; ++ if (of_property_read_u32(np, "ti,dvp_bus", &priv->dvp_bus)) ++ priv->dvp_bus = 8; ++ if (of_property_read_u32(np, "ti,hsync", &priv->hsync)) ++ priv->vsync = 0; ++ if (of_property_read_u32(np, "ti,vsync", &priv->vsync)) ++ priv->vsync = 1; ++ if (of_property_read_u32(np, "ti,ser_id", &priv->ser_id)) ++ priv->ser_id = TI913_ID; ++ if (of_property_read_u32(np, "ti,poc-delay", &priv->poc_delay)) ++ priv->poc_delay = 50; ++ ++ /* module params override dts */ ++ if (is_stp) ++ priv->is_coax = 0; ++ if (dvp_bus != 8) ++ priv->dvp_bus = dvp_bus; ++ if (hsync) ++ priv->hsync = hsync; ++ if (!vsync) ++ priv->vsync = vsync; ++ if (ser_id) ++ priv->ser_id = ser_id; ++ if (poc_delay) ++ priv->poc_delay = poc_delay; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ if (i < priv->links) { ++ if (of_property_read_u32(endpoint, "ti9x3-addr", &priv->ti9x3_addr_map[i])) { ++ dev_err(&client->dev, "ti9x3-addr not set\n"); ++ return -EINVAL; ++ } ++ priv->sd_fwnode[i] = of_fwnode_handle(endpoint); ++ } ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ csi_rate_prop = of_find_property(endpoint, "csi-rate", NULL); ++ if (csi_rate_prop) { ++ of_property_read_u32(endpoint, "csi-rate", &priv->csi_rate); ++ of_update_property(rendpoint, csi_rate_prop); ++ } ++ ++ dvp_order_prop = of_find_property(endpoint, "dvp-order", NULL); ++ if (dvp_order_prop) ++ of_update_property(rendpoint, dvp_order_prop); ++ } ++ ++ return 0; ++} ++ ++static int ti9x4_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ti9x4_priv *priv; ++ int err, i; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ i2c_set_clientdata(client, priv); ++ priv->des_addr = client->addr; ++ priv->client = client; ++ atomic_set(&priv->use_count, 0); ++ ++ err = ti9x4_parse_dt(client); ++ if (err) ++ goto out; ++ ++ err = ti9x4_initialize(client); ++ if (err < 0) ++ goto out; ++ ++ for (i = 0; i < priv->links; i++) { ++ v4l2_subdev_init(&priv->sd[i], &ti9x4_subdev_ops); ++ priv->sd[i].owner = client->dev.driver->owner; ++ priv->sd[i].dev = &client->dev; ++ priv->sd[i].grp_id = i; ++ v4l2_set_subdevdata(&priv->sd[i], priv); ++ priv->sd[i].fwnode = priv->sd_fwnode[i]; ++ ++ snprintf(priv->sd[i].name, V4L2_SUBDEV_NAME_SIZE, "%s %d-%04x", ++ client->dev.driver->name, i2c_adapter_id(client->adapter), ++ client->addr); ++ ++ err = v4l2_async_register_subdev(&priv->sd[i]); ++ if (err < 0) ++ goto out; ++ } ++ ++out: ++ return err; ++} ++ ++static int ti9x4_remove(struct i2c_client *client) ++{ ++ struct ti9x4_priv *priv = i2c_get_clientdata(client); ++ int i; ++ ++ for (i = 0; i < priv->links; i++) { ++ v4l2_async_unregister_subdev(&priv->sd[i]); ++ v4l2_device_unregister_subdev(&priv->sd[i]); ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id ti9x4_dt_ids[] = { ++ { .compatible = "ti,ti9x4" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, ti9x4_dt_ids); ++ ++static const struct i2c_device_id ti9x4_id[] = { ++ { "ti9x4", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ti9x4_id); ++ ++static struct i2c_driver ti9x4_i2c_driver = { ++ .driver = { ++ .name = "ti9x4", ++ .of_match_table = of_match_ptr(ti9x4_dt_ids), ++ }, ++ .probe = ti9x4_probe, ++ .remove = ti9x4_remove, ++ .id_table = ti9x4_id, ++}; ++ ++module_i2c_driver(ti9x4_i2c_driver); ++ ++MODULE_DESCRIPTION("FPDLinkIII driver for DS90UB9x4"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/i2c/soc_camera/ti9x4.h b/drivers/media/i2c/soc_camera/ti9x4.h +new file mode 100644 +index 0000000..b53b4c6 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ti9x4.h +@@ -0,0 +1,156 @@ ++/* ++ * TI FPDLinkIII driver include file ++ * ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++#ifndef _TI9X4_H ++#define _TI9X4_H ++ ++//#define DEBUG ++#ifdef DEBUG ++#undef dev_dbg ++#define dev_dbg dev_info ++#endif ++ ++#define MAXIM_NUM_RETRIES 1 /* number of read/write retries */ ++#define TI913_ID 0x58 ++#define TI953_ID 0x30 /* or starapped to 0x32 */ ++#define TI9X4_ID 0x00 /* strapped */ ++#define BROADCAST 0x6f ++ ++static inline int reg8_read(struct i2c_client *client, u8 reg, u8 *val) ++{ ++ int ret, retries; ++ ++ for (retries = MAXIM_NUM_RETRIES; retries; retries--) { ++ ret = i2c_smbus_read_byte_data(client, reg); ++ if (!(ret < 0)) ++ break; ++ } ++ ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "read fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } else { ++ *val = ret; ++ } ++ ++ return ret < 0 ? ret : 0; ++} ++ ++static inline int reg8_write(struct i2c_client *client, u8 reg, u8 val) ++{ ++ int ret, retries; ++ ++ for (retries = MAXIM_NUM_RETRIES; retries; retries--) { ++ ret = i2c_smbus_write_byte_data(client, reg, val); ++ if (!(ret < 0)) ++ break; ++ } ++ ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "write fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } ++ ++ return ret < 0 ? ret : 0; ++} ++ ++static inline int reg16_read(struct i2c_client *client, u16 reg, u8 *val) ++{ ++ int ret, retries; ++ u8 buf[2] = {reg >> 8, reg & 0xff}; ++ ++ for (retries = MAXIM_NUM_RETRIES; retries; retries--) { ++ ret = i2c_master_send(client, buf, 2); ++ if (ret == 2) { ++ ret = i2c_master_recv(client, buf, 1); ++ if (ret == 1) ++ break; ++ } ++ } ++ ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "read fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } else { ++ *val = buf[0]; ++ } ++ ++ return ret < 0 ? ret : 0; ++} ++ ++static inline int reg16_write(struct i2c_client *client, u16 reg, u8 val) ++{ ++ int ret, retries; ++ u8 buf[3] = {reg >> 8, reg & 0xff, val}; ++ ++ for (retries = MAXIM_NUM_RETRIES; retries; retries--) { ++ ret = i2c_master_send(client, buf, 3); ++ if (ret == 3) ++ break; ++ } ++ ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "write fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } ++ ++ return ret < 0 ? ret : 0; ++} ++ ++static inline int reg16_read16(struct i2c_client *client, u16 reg, u16 *val) ++{ ++ int ret, retries; ++ u8 buf[2] = {reg >> 8, reg & 0xff}; ++ ++ for (retries = MAXIM_NUM_RETRIES; retries; retries--) { ++ ret = i2c_master_send(client, buf, 2); ++ if (ret == 2) { ++ ret = i2c_master_recv(client, buf, 2); ++ if (ret == 2) ++ break; ++ } ++ } ++ ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "read fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } else { ++ *val = ((u16)buf[0] << 8) | buf[1]; ++ } ++ ++ return ret < 0 ? ret : 0; ++} ++ ++static inline int reg16_write16(struct i2c_client *client, u16 reg, u16 val) ++{ ++ int ret, retries; ++ u8 buf[4] = {reg >> 8, reg & 0xff, val >> 8, val & 0xff}; ++ ++ for (retries = MAXIM_NUM_RETRIES; retries; retries--) { ++ ret = i2c_master_send(client, buf, 4); ++ if (ret == 4) ++ break; ++ } ++ ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "write fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } ++ ++ return ret < 0 ? ret : 0; ++} ++#endif /* _TI9X4_H */ +diff --git a/drivers/media/platform/soc_camera/rcar_csi2.c b/drivers/media/platform/soc_camera/rcar_csi2.c +index 05f623468..2e710e3 100644 +--- a/drivers/media/platform/soc_camera/rcar_csi2.c ++++ b/drivers/media/platform/soc_camera/rcar_csi2.c +@@ -20,24 +20,29 @@ + #include + #include + #include ++#include + #include + #include + #include + #include + #include ++#include + + #include + #include ++#include ++#include + #include + #include + #include + #include + #include + +-#include ++#include ++ ++//#define RCAR_CSI2_DUMP + + #define DRV_NAME "rcar_csi2" +-#define CONNECT_SLAVE_NAME "adv7482" + #define VC_MAX_CHANNEL 4 + + #define RCAR_CSI2_TREF 0x00 +@@ -62,6 +67,7 @@ + + #define RCAR_CSI2_LINKCNT 0x48 + #define RCAR_CSI2_LSWAP 0x4C ++#define RCAR_CSI2_PHTW 0x50 + #define RCAR_CSI2_PHTC 0x58 + #define RCAR_CSI2_PHYPLL 0x68 + +@@ -69,6 +75,10 @@ + #define RCAR_CSI2_PHCLM 0x78 + #define RCAR_CSI2_PHDLM 0x7C + ++#define RCAR_CSI2_CSI0CLKFCPR 0x254 /* CSI0CLK Frequency Configuration Preset */ ++/* CSI0CLK frequency configuration bit */ ++#define CSI0CLKFREQRANGE(n) ((n & 0x3f) << 16) ++ + #define RCAR_CSI2_PHYCNT_SHUTDOWNZ (1 << 17) + #define RCAR_CSI2_PHYCNT_RSTZ (1 << 16) + #define RCAR_CSI2_PHYCNT_ENABLECLK (1 << 4) +@@ -105,6 +115,9 @@ + #define RCAR_CSI2_LSWAP_L0SEL_PLANE2 (2 << 0) + #define RCAR_CSI2_LSWAP_L0SEL_PLANE3 (3 << 0) + ++#define RCAR_CSI2_PHTW_DWEN (1 << 24) ++#define RCAR_CSI2_PHTW_CWEN (1 << 8) ++ + #define RCAR_CSI2_PHTC_TESTCLR (1 << 0) + + /* interrupt status registers */ +@@ -153,6 +166,16 @@ + #define RCAR_CSI2_INTSTATE_ERRSYNCESC (1 << 1) + #define RCAR_CSI2_INTSTATE_ERRCONTROL (1 << 0) + ++static const struct soc_device_attribute r8a7797[] = { ++ { .soc_id = "r8a7797" }, ++ { } ++}; ++ ++static const struct soc_device_attribute r8a7795[] = { ++ { .soc_id = "r8a7795", .revision = "ES2.0" }, ++ { } ++}; ++ + enum chip_id { + RCAR_GEN3, + RCAR_GEN2, +@@ -173,6 +196,7 @@ struct rcar_csi2_link_config { + unsigned char lanes; + unsigned long vcdt; + unsigned long vcdt2; ++ unsigned int csi_rate; + }; + + #define INIT_RCAR_CSI2_LINK_CONFIG(m) \ +@@ -186,8 +210,7 @@ struct rcar_csi_irq_counter_log { + }; + + struct rcar_csi2 { +- struct v4l2_subdev subdev; +- struct v4l2_mbus_framefmt *mf; ++ struct v4l2_subdev subdev[4]; + unsigned int irq; + unsigned long mipi_flags; + void __iomem *base; +@@ -199,7 +222,9 @@ struct rcar_csi2 { + unsigned int field; + unsigned int code; + unsigned int lanes; ++ unsigned int csi_rate; + spinlock_t lock; ++ atomic_t use_count; + }; + + #define RCAR_CSI_80MBPS 0 +@@ -245,10 +270,104 @@ struct rcar_csi2 { + #define RCAR_CSI_1400MBPS 40 + #define RCAR_CSI_1450MBPS 41 + #define RCAR_CSI_1500MBPS 42 ++#define RCAR_CSI_NUMRATES 43 ++ ++#define RCAR_CSI2_PHxM0(i) (0xf0 + i * 0x08) ++#define RCAR_CSI2_PHxM1(i) (0xf4 + i * 0x08) ++#define RCAR_CSI2_PHRM(i) (0x110 + i * 0x04) ++#define RCAR_CSI2_PHCM(i) (0x120 + i * 0x04) ++#define RCAR_CSI2_SERCCNT 0x140 ++#define RCAR_CSI2_SSERCCNT 0x144 ++#define RCAR_CSI2_ECCCM 0x148 ++#define RCAR_CSI2_ECECM 0x14c ++#define RCAR_CSI2_CRCECM 0x150 ++#define RCAR_CSI2_LCNT(i) (0x160 + i * 0x04) ++#define RCAR_CSI2_LCNTM(i) (0x168 + i * 0x04) ++#define RCAR_CSI2_FCNTM 0x170 ++#define RCAR_CSI2_FCNTM2 0x174 ++#define RCAR_CSI2_VINSM(i) (0x190 + i * 0x04) ++#define RCAR_CSI2_PHM(i) (0x1C0 + i * 0x04) ++ ++#define RCAR_CSI2_INTSTATE_ALL 0x3FFFFCDD ++ ++#ifdef RCAR_CSI2_DUMP ++static void rcar_sci2_debug_show(struct rcar_csi2 *priv) ++{ ++ int i; ++ u32 reg0, reg1; ++ ++ printk("Debug registers:\n"); ++ printk("FCNTM : 0x%08x\n", ioread32(priv->base + RCAR_CSI2_FCNTM)); ++ printk("FCNTM2: 0x%08x\n", ioread32(priv->base + RCAR_CSI2_FCNTM2)); ++ ++ for (i = 0; i < 4; i++) { ++ reg0 = ioread32(priv->base + RCAR_CSI2_PHxM0(i)); ++ reg1 = ioread32(priv->base + RCAR_CSI2_PHxM1(i)); ++ ++ printk("Packet header %d: dt: 0x%02x, vc: %d, wc: %d, cnt: %d\n", ++ i, ++ reg0 & 0x3F, (reg0 >> 6) & 0x03, (reg0 >> 8) & 0xffff, ++ reg1 & 0xffff); ++ } ++ for (i = 0; i < 3; i++) { ++ reg0 = ioread32(priv->base + RCAR_CSI2_PHRM(i)); ++ ++ printk("Packet header R %d dt: 0x%02x, vc: %d, wc: %d, ecc: 0x%02x\n", ++ i, ++ reg0 & 0x3F, (reg0 >> 6) & 0x03, (reg0 >> 8) & 0xffff, ++ (reg0 >> 24) & 0xff); ++ } ++ for (i = 0; i < 2; i++) { ++ reg0 = ioread32(priv->base + RCAR_CSI2_PHCM(i)); ++ ++ printk("Packet header C %d: dt: 0x%02x, vc: %d, wc: %d, cal_parity: 0x%02x\n", ++ i, ++ reg0 & 0x3F, (reg0 >> 6) & 0x03, (reg0 >> 8) & 0xffff, ++ (reg0 >> 24) & 0xff); ++ } ++ for (i = 0; i < 8; i++) { ++ reg0 = ioread32(priv->base + RCAR_CSI2_PHM(i)); ++ ++ printk("Packet header Monitor %d: dt: 0x%02x, vc: %d, wc: %d, ecc: 0x%02x\n", ++ i + 1, ++ reg0 & 0x3F, (reg0 >> 6) & 0x03, (reg0 >> 8) & 0xffff, ++ (reg0 >> 24) & 0xff); ++ } ++ for (i = 0; i < 3; i++) ++ printk("VINSM%d: 0x%08x\n", i, ioread32(priv->base + RCAR_CSI2_VINSM(i))); ++ printk("SERCCNT: %d\n", ++ ioread32(priv->base + RCAR_CSI2_SERCCNT)); ++ printk("SSERCCNT: %d\n", ++ ioread32(priv->base + RCAR_CSI2_SSERCCNT)); ++ printk("ECCCM: %d\n", ++ ioread32(priv->base + RCAR_CSI2_ECCCM)); ++ printk("ECECM: %d\n", ++ ioread32(priv->base + RCAR_CSI2_ECECM)); ++ printk("CRCECM: %d\n", ++ ioread32(priv->base + RCAR_CSI2_CRCECM)); ++ for (i = 0; i < 2; i++) ++ printk("LCNT%d: 0x%08x\n", i, ioread32(priv->base + RCAR_CSI2_LCNT(i))); ++ for (i = 0; i < 2; i++) ++ printk("LCNTM%d: 0x%08x\n", i, ioread32(priv->base + RCAR_CSI2_LCNTM(i))); ++} ++#else ++#define rcar_sci2_debug_show(args) ++#endif /* RCAR_CSI2_DUMP */ + + static int rcar_csi2_set_phy_freq(struct rcar_csi2 *priv) + { +- const uint32_t const hs_freq_range[43] = { ++ const uint32_t hs_freq_range_v3m[43] = { ++ 0x00, 0x00, 0x20, 0x40, 0x02, /* 80M, 90M, 100M, 110M, 120M */ ++ 0x02, 0x22, 0x42, 0x04, 0x04, /* 130M, 140M, 150M, 160M, 170M */ ++ 0x24, 0x44, 0x44, 0x06, 0x26, /* 180M, 190M, 205M, 220M, 235M */ ++ 0x46, 0x08, 0x28, 0x0a, 0x2a, /* 250M, 270M, 300M, 325M, 350M */ ++ 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, /* 400M, 450M, 500M, 550M, 600M */ ++ 0x10, 0x30, 0x12, 0x32, 0x52, /* 650M, 700M, 750M, 800M, 950M */ ++ 0x72, 0x14, 0x34, 0x52, 0x74, /* 900M, 950M, 1000M, 1050M, 1100M */ ++ 0x16, 0x36, 0x56, 0x76, 0x18, /* 1150M, 1200M, 1250M, 1300M, 1350M */ ++ 0x38, 0x58, 0x78 /* 1400M, 1450M, 1500M */ ++ }; ++ const uint32_t hs_freq_range_m3[43] = { + 0x00, 0x10, 0x20, 0x30, 0x01, /* 0-4 */ + 0x11, 0x21, 0x31, 0x02, 0x12, /* 5-9 */ + 0x22, 0x32, 0x03, 0x13, 0x23, /* 10-14 */ +@@ -259,60 +378,49 @@ static int rcar_csi2_set_phy_freq(struct rcar_csi2 *priv) + 0x0B, 0x1B, 0x2B, 0x3B, 0x0C, /* 35-39 */ + 0x1C, 0x2C, 0x3C /* 40-42 */ + }; ++ const uint32_t hs_freq_range_h3[43] = { ++ 0x00, 0x10, 0x20, 0x30, 0x01, /* 0-4 */ ++ 0x11, 0x21, 0x31, 0x02, 0x12, /* 5-9 */ ++ 0x22, 0x32, 0x03, 0x13, 0x23, /* 10-14 */ ++ 0x33, 0x04, 0x14, 0x25, 0x35, /* 15-19 */ ++ 0x05, 0x26, 0x36, 0x37, 0x07, /* 20-24 */ ++ 0x18, 0x28, 0x39, 0x09, 0x19, /* 25-29 */ ++ 0x29, 0x3A, 0x0A, 0x1A, 0x2A, /* 30-34 */ ++ 0x3B, 0x0B, 0x1B, 0x2B, 0x3C, /* 35-39 */ ++ 0x0C, 0x1C, 0x2C /* 40-42 */ ++ }; ++ const uint32_t csi2_rate_range[43] = { ++ 80, 90, 100, 110, 120, /* 0-4 */ ++ 130, 140, 150, 160, 170, /* 5-9 */ ++ 180, 190, 205, 220, 235, /* 10-14 */ ++ 250, 275, 300, 325, 350, /* 15-19 */ ++ 400, 450, 500, 550, 600, /* 20-24 */ ++ 650, 700, 750, 800, 850, /* 25-29 */ ++ 900, 950, 1000, 1050, 1100, /* 30-34 */ ++ 1150, 1200, 1250, 1300, 1350, /* 35-39 */ ++ 1400, 1450, 1500 /* 40-42 */ ++ }; + uint32_t bps_per_lane = RCAR_CSI_190MBPS; + +- dev_dbg(&priv->pdev->dev, "Input size (%dx%d%c)\n", +- priv->mf->width, priv->mf->height, +- (priv->mf->field == V4L2_FIELD_NONE) ? 'p' : 'i'); +- +- switch (priv->lanes) { +- case 1: +- bps_per_lane = RCAR_CSI_400MBPS; +- break; +- case 4: +- if (priv->mf->field == V4L2_FIELD_NONE) { +- if ((priv->mf->width == 1920) && +- (priv->mf->height == 1080)) +- bps_per_lane = RCAR_CSI_900MBPS; +- else if ((priv->mf->width == 1280) && +- (priv->mf->height == 720)) +- bps_per_lane = RCAR_CSI_450MBPS; +- else if ((priv->mf->width == 720) && +- (priv->mf->height == 480)) +- bps_per_lane = RCAR_CSI_190MBPS; +- else if ((priv->mf->width == 720) && +- (priv->mf->height == 576)) +- bps_per_lane = RCAR_CSI_190MBPS; +- else if ((priv->mf->width == 640) && +- (priv->mf->height == 480)) +- bps_per_lane = RCAR_CSI_100MBPS; +- else +- goto error; +- } else { +- if ((priv->mf->width == 1920) && +- (priv->mf->height == 1080)) +- bps_per_lane = RCAR_CSI_450MBPS; +- else +- goto error; +- } +- break; +- default: +- dev_err(&priv->pdev->dev, "ERROR: lanes is invalid (%d)\n", +- priv->lanes); +- return -EINVAL; ++ for (bps_per_lane = 0; bps_per_lane < RCAR_CSI_NUMRATES; bps_per_lane++) { ++ if (priv->csi_rate <= csi2_rate_range[bps_per_lane]) ++ break; + } + + dev_dbg(&priv->pdev->dev, "bps_per_lane (%d)\n", bps_per_lane); + +- iowrite32((hs_freq_range[bps_per_lane] << 16), ++ if (soc_device_match(r8a7797)) ++ iowrite32((hs_freq_range_v3m[bps_per_lane] << 16) | ++ RCAR_CSI2_PHTW_DWEN | RCAR_CSI2_PHTW_CWEN | 0x44, ++ priv->base + RCAR_CSI2_PHTW); ++ else if (soc_device_match(r8a7795)) ++ iowrite32(hs_freq_range_h3[bps_per_lane] << 16, ++ priv->base + RCAR_CSI2_PHYPLL); ++ else ++ /* h3 ws1.x is similar to m3 */ ++ iowrite32(hs_freq_range_m3[bps_per_lane] << 16, + priv->base + RCAR_CSI2_PHYPLL); + return 0; +- +-error: +- dev_err(&priv->pdev->dev, "Not support resolution (%dx%d%c)\n", +- priv->mf->width, priv->mf->height, +- (priv->mf->field == V4L2_FIELD_NONE) ? 'p' : 'i'); +- return -EINVAL; + } + + static irqreturn_t rcar_csi2_irq(int irq, void *data) +@@ -370,6 +478,16 @@ static int rcar_csi2_hwinit(struct rcar_csi2 *priv) + iowrite32(0x0001000f, priv->base + RCAR_CSI2_FLD); + tmp |= 0x1; + break; ++ case 2: ++ /* First field number setting */ ++ iowrite32(0x0001000f, priv->base + RCAR_CSI2_FLD); ++ tmp |= 0x3; ++ break; ++ case 3: ++ /* First field number setting */ ++ iowrite32(0x0001000f, priv->base + RCAR_CSI2_FLD); ++ tmp |= 0x7; ++ break; + case 4: + /* First field number setting */ + iowrite32(0x0002000f, priv->base + RCAR_CSI2_FLD); +@@ -382,11 +500,27 @@ static int rcar_csi2_hwinit(struct rcar_csi2 *priv) + return -EINVAL; + } + ++ if (soc_device_match(r8a7795)) { ++ /* Set PHY Test Interface Write Register in R-Car H3(ES2.0) */ ++ iowrite32(0x01cc01e2, priv->base + RCAR_CSI2_PHTW); ++ iowrite32(0x010101e3, priv->base + RCAR_CSI2_PHTW); ++ iowrite32(0x010101e4, priv->base + RCAR_CSI2_PHTW); ++ iowrite32(0x01100104, priv->base + RCAR_CSI2_PHTW); ++ iowrite32(0x01030100, priv->base + RCAR_CSI2_PHTW); ++ iowrite32(0x01800107, priv->base + RCAR_CSI2_PHTW); ++ } ++ + /* set PHY frequency */ + ret = rcar_csi2_set_phy_freq(priv); + if (ret < 0) + return ret; + ++ /* Set CSI0CLK Frequency Configuration Preset Register ++ * in R-Car H3(ES2.0) ++ */ ++ if (soc_device_match(r8a7795)) ++ iowrite32(CSI0CLKFREQRANGE(32), priv->base + RCAR_CSI2_CSI0CLKFCPR); ++ + /* Enable lanes */ + iowrite32(tmp, priv->base + RCAR_CSI2_PHYCNT); + +@@ -447,32 +581,22 @@ static int rcar_csi2_hwinit(struct rcar_csi2 *priv) + + static int rcar_csi2_s_power(struct v4l2_subdev *sd, int on) + { +- struct rcar_csi2 *priv = container_of(sd, struct rcar_csi2, subdev); +- struct v4l2_subdev *tmp_sd; +- struct v4l2_subdev_format fmt = { +- .which = V4L2_SUBDEV_FORMAT_ACTIVE, +- }; +- struct v4l2_mbus_framefmt *mf = &fmt.format; ++ struct rcar_csi2 *priv = v4l2_get_subdevdata(sd); + int ret = 0; + + if (on) { +- v4l2_device_for_each_subdev(tmp_sd, sd->v4l2_dev) { +- if (strncmp(tmp_sd->name, CONNECT_SLAVE_NAME, +- sizeof(CONNECT_SLAVE_NAME) - 1) == 0) { +- v4l2_subdev_call(tmp_sd, pad, get_fmt, +- NULL, &fmt); +- if (ret < 0) +- return ret; +- } ++ if (atomic_inc_return(&priv->use_count) == 1) { ++ pm_runtime_get_sync(&priv->pdev->dev); ++ ret = rcar_csi2_hwinit(priv); ++ if (ret < 0) ++ return ret; + } +- priv->mf = mf; +- pm_runtime_get_sync(&priv->pdev->dev); +- ret = rcar_csi2_hwinit(priv); +- if (ret < 0) +- return ret; + } else { +- rcar_csi2_hwdeinit(priv); +- pm_runtime_put_sync(&priv->pdev->dev); ++ if (atomic_dec_return(&priv->use_count) == 0) { ++ rcar_sci2_debug_show(priv); ++ rcar_csi2_hwdeinit(priv); ++ pm_runtime_put_sync(&priv->pdev->dev); ++ } + } + + return ret; +@@ -488,6 +612,7 @@ static struct v4l2_subdev_ops rcar_csi2_subdev_ops = { + + #ifdef CONFIG_OF + static const struct of_device_id rcar_csi2_of_table[] = { ++ { .compatible = "renesas,r8a7797-csi2", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,r8a7796-csi2", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,r8a7795-csi2", .data = (void *)RCAR_GEN3 }, + { }, +@@ -496,6 +621,7 @@ MODULE_DEVICE_TABLE(of, rcar_csi2_of_table); + #endif + + static struct platform_device_id rcar_csi2_id_table[] = { ++ { "r8a7797-csi2", RCAR_GEN3 }, + { "r8a7796-csi2", RCAR_GEN3 }, + { "r8a7795-csi2", RCAR_GEN3 }, + {}, +@@ -505,7 +631,7 @@ MODULE_DEVICE_TABLE(platform, rcar_csi2_id_table); + static int rcar_csi2_parse_dt(struct device_node *np, + struct rcar_csi2_link_config *config) + { +- struct v4l2_of_endpoint bus_cfg; ++ struct v4l2_fwnode_endpoint bus_cfg; + struct device_node *endpoint; + struct device_node *vc_np, *vc_ch; + const char *str; +@@ -518,19 +644,20 @@ static int rcar_csi2_parse_dt(struct device_node *np, + if (!endpoint) + return -EINVAL; + +- v4l2_of_parse_endpoint(endpoint, &bus_cfg); ++ v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint), &bus_cfg); ++ ret = of_property_read_u32(endpoint, "csi-rate", &config->csi_rate); ++ if (ret < 0) { ++ printk(KERN_ERR "csi-rate not set\n"); ++ return ret; ++ } + of_node_put(endpoint); + + config->lanes = bus_cfg.bus.mipi_csi2.num_data_lanes; + +- ret = of_property_read_string(np, "adi,input-interface", &str); +- if (ret < 0) +- return ret; +- + vc_np = of_get_child_by_name(np, "virtual,channel"); + +- config->vcdt = 0; +- config->vcdt2 = 0; ++ config->vcdt = 0x81008000; ++ config->vcdt2 = 0x83008200; + for (i = 0; i < VC_MAX_CHANNEL; i++) { + sprintf(csi_name, "csi2_vc%d", i); + +@@ -549,6 +676,8 @@ static int rcar_csi2_parse_dt(struct device_node *np, + config->vcdt |= (0x24 << (i * 16)); + else if (!strcmp(str, "ycbcr422")) + config->vcdt |= (0x1e << (i * 16)); ++ else if (!strcmp(str, "raw8")) ++ config->vcdt |= (0x2a << (i * 16)); + else + config->vcdt |= 0; + +@@ -563,6 +692,8 @@ static int rcar_csi2_parse_dt(struct device_node *np, + config->vcdt2 |= (0x24 << (j * 16)); + else if (!strcmp(str, "ycbcr422")) + config->vcdt2 |= (0x1e << (j * 16)); ++ else if (!strcmp(str, "raw8")) ++ config->vcdt2 |= (0x2a << (j * 16)); + else + config->vcdt2 |= 0; + +@@ -584,6 +715,7 @@ static int rcar_csi2_probe(struct platform_device *pdev) + /* Platform data specify the PHY, lanes, ECC, CRC */ + struct rcar_csi2_pdata *pdata; + struct rcar_csi2_link_config link_config; ++ int i; + + dev_dbg(&pdev->dev, "CSI2 probed.\n"); + +@@ -594,12 +726,7 @@ static int rcar_csi2_probe(struct platform_device *pdev) + if (ret) + return ret; + +- if (link_config.lanes == 4) +- dev_info(&pdev->dev, +- "Detected rgb888 in rcar_csi2_parse_dt\n"); +- else +- dev_info(&pdev->dev, +- "Detected YCbCr422 in rcar_csi2_parse_dt\n"); ++ dev_info(&pdev->dev, "Data lanes %d, link freq %d\n", link_config.lanes, link_config.csi_rate); + } else { + pdata = pdev->dev.platform_data; + if (!pdata) +@@ -631,23 +758,27 @@ static int rcar_csi2_probe(struct platform_device *pdev) + return ret; + + priv->pdev = pdev; +- priv->subdev.owner = THIS_MODULE; +- priv->subdev.dev = &pdev->dev; + priv->lanes = link_config.lanes; + priv->vcdt = link_config.vcdt; + priv->vcdt2 = link_config.vcdt2; ++ priv->csi_rate = link_config.csi_rate; ++ atomic_set(&priv->use_count, 0); + +- platform_set_drvdata(pdev, &priv->subdev); ++ platform_set_drvdata(pdev, priv); + +- v4l2_subdev_init(&priv->subdev, &rcar_csi2_subdev_ops); +- v4l2_set_subdevdata(&priv->subdev, &pdev->dev); ++ for (i= 0; i < 4; i++) { ++ priv->subdev[i].owner = THIS_MODULE; ++ priv->subdev[i].dev = &pdev->dev; ++ v4l2_subdev_init(&priv->subdev[i], &rcar_csi2_subdev_ops); ++ v4l2_set_subdevdata(&priv->subdev[i], priv); + +- snprintf(priv->subdev.name, V4L2_SUBDEV_NAME_SIZE, "rcar_csi2.%s", +- dev_name(&pdev->dev)); ++ snprintf(priv->subdev[i].name, V4L2_SUBDEV_NAME_SIZE, "rcar_csi2.%s", ++ dev_name(&pdev->dev)); + +- ret = v4l2_async_register_subdev(&priv->subdev); +- if (ret < 0) +- return ret; ++ ret = v4l2_async_register_subdev(&priv->subdev[i]); ++ if (ret < 0) ++ return ret; ++ } + + spin_lock_init(&priv->lock); + +@@ -660,10 +791,11 @@ static int rcar_csi2_probe(struct platform_device *pdev) + + static int rcar_csi2_remove(struct platform_device *pdev) + { +- struct v4l2_subdev *subdev = platform_get_drvdata(pdev); +- struct rcar_csi2 *priv = container_of(subdev, struct rcar_csi2, subdev); ++ struct rcar_csi2 *priv = platform_get_drvdata(pdev); ++ int i; + +- v4l2_async_unregister_subdev(&priv->subdev); ++ for (i= 0; i < 4; i++) ++ v4l2_async_unregister_subdev(&priv->subdev[i]); + pm_runtime_disable(&pdev->dev); + + return 0; +diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c +index 400958b..9733555 100644 +--- a/drivers/media/platform/soc_camera/rcar_vin.c ++++ b/drivers/media/platform/soc_camera/rcar_vin.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -34,11 +35,12 @@ + + #include + #include ++#include + #include + #include + #include ++#include + #include +-#include + #include + #include + +@@ -95,17 +97,21 @@ + #define VNC8A_REG 0xF0 /* Video n Coefficient Set C8A Register */ + #define VNC8B_REG 0xF4 /* Video n Coefficient Set C8B Register */ + #define VNC8C_REG 0xF8 /* Video n Coefficient Set C8C Register */ ++#define VNLUTP_REG 0x100 /* Video n Lookup table pointer */ ++#define VNLUTD_REG 0x104 /* Video n Lookup table data register */ + + /* Register bit fields for R-Car VIN */ + /* Video n Main Control Register bits */ + #define VNMC_DPINE (1 << 27) + #define VNMC_SCLE (1 << 26) + #define VNMC_FOC (1 << 21) ++#define VNMC_LUTE (1 << 20) + #define VNMC_YCAL (1 << 19) + #define VNMC_INF_YUV8_BT656 (0 << 16) + #define VNMC_INF_YUV8_BT601 (1 << 16) + #define VNMC_INF_YUV10_BT656 (2 << 16) + #define VNMC_INF_YUV10_BT601 (3 << 16) ++#define VNMC_INF_RAW8 (4 << 16) + #define VNMC_INF_YUV16 (5 << 16) + #define VNMC_INF_RGB888 (6 << 16) + #define VNMC_INF_MASK (7 << 16) +@@ -138,6 +144,7 @@ + #define VNINTS_FOS (1 << 0) + + /* Video n Data Mode Register bits */ ++#define VNDMR_YMODE_Y8 (1 << 12) + #define VNDMR_EXRGB (1 << 8) + #define VNDMR_BPSM (1 << 4) + #define VNDMR_DTMD_YCSEP (1 << 1) +@@ -154,7 +161,7 @@ + #define VNCSI_IFMD_REG 0x20 /* Video n CSI2 Interface Mode Register */ + + #define VNCSI_IFMD_DES1 (1 << 26) /* CSI20 */ +-#define VNCSI_IFMD_DES0 (1 << 25) /* H3:CSI40/41, M3:CSI40 */ ++#define VNCSI_IFMD_DES0 (1 << 25) /* H3:CSI40/41, M3:CSI40, V3M:CSI40 */ + + #define VNCSI_IFMD_CSI_CHSEL(n) (n << 0) + #define VNCSI_IFMD_SEL_NUMBER 5 +@@ -178,6 +185,10 @@ + #define RCAR_VIN_BT656 (1 << 3) + #define RCAR_VIN_CSI2 (1 << 4) + ++static int lut_reverse; ++module_param(lut_reverse, int, 0644); ++MODULE_PARM_DESC(lut_reverse, " Use LUT for data order reverse (only 8-bit data allowed)*/"); ++ + static int ifmd0_reg_match[VNCSI_IFMD_SEL_NUMBER]; + static int ifmd4_reg_match[VNCSI_IFMD_SEL_NUMBER]; + static int ifmd0_init = true; +@@ -185,6 +196,7 @@ static int ifmd4_init = true; + + enum chip_id { + RCAR_GEN3, ++ RCAR_V3M, + RCAR_M3, + RCAR_H3, + RCAR_GEN2, +@@ -360,10 +372,54 @@ static const struct vin_gen3_ifmd vin_m3_vc_ifmd[] = { + }, + }; + ++static const struct vin_gen3_ifmd vin_v3_vc_ifmd[] = { ++ { 0x0000, ++ { ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ } ++ }, ++ { 0x0001, ++ { ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ } ++ }, ++ { 0x0002, ++ { ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ } ++ }, ++ { 0x0003, ++ { ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH3}, ++ } ++ }, ++ { 0x0004, ++ { ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ } ++ }, ++}; ++ + enum csi2_fmt { + RCAR_CSI_FMT_NONE = -1, + RCAR_CSI_RGB888, + RCAR_CSI_YCBCR422, ++ RCAR_CSI_RAW8, + }; + + struct vin_coeff { +@@ -729,10 +785,14 @@ struct rcar_vin_priv { + enum csi2_fmt csi_fmt; + enum virtual_ch vc; + bool csi_sync; ++ bool deser_sync; ++ int lut_updated; + + struct rcar_vin_async_client *async_client; + /* Asynchronous CSI2 linking */ + struct v4l2_subdev *csi2_sd; ++ /* Asynchronous Deserializer linking */ ++ struct v4l2_subdev *deser_sd; + /* Synchronous probing compatibility */ + struct platform_device *csi2_pdev; + +@@ -849,7 +909,8 @@ static int rcar_vin_videobuf_setup(struct vb2_queue *vq, + struct rcar_vin_priv *priv = ici->priv; + struct rcar_vin_cam *cam = icd->host_priv; + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { + if ((priv->ratio_h > 0x10000) || (priv->ratio_v > 0x10000)) { + dev_err(icd->parent, "Scaling rate parameter error\n"); + return -EINVAL; +@@ -894,6 +955,8 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + struct rcar_vin_cam *cam = icd->host_priv; + u32 vnmc, dmr, interrupts; + bool progressive = false, output_is_yuv = false, input_is_yuv = false; ++ int i; ++ u32 lutd; + + switch (priv->field) { + case V4L2_FIELD_TOP: +@@ -944,6 +1007,10 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601; + input_is_yuv = true; + break; ++ case MEDIA_BUS_FMT_SBGGR8_1X8: ++ case MEDIA_BUS_FMT_SBGGR12_1X12: ++ vnmc |= VNMC_INF_RAW8 | VNMC_BPS; ++ break; + default: + break; + } +@@ -951,7 +1018,8 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + /* output format */ + switch (icd->current_fmt->host_fmt->fourcc) { + case V4L2_PIX_FMT_NV12: +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { + iowrite32(ALIGN((cam->out_width * cam->out_height), + 0x80), priv->base + VNUVAOF_REG); + dmr = VNDMR_DTMD_YCSEP_YCBCR420; +@@ -975,6 +1043,10 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + dmr = 0; + output_is_yuv = true; + break; ++ case V4L2_PIX_FMT_GREY: ++ dmr = VNDMR_DTMD_YCSEP | VNDMR_YMODE_Y8; ++ output_is_yuv = true; ++ break; + case V4L2_PIX_FMT_ARGB555: + dmr = VNDMR_DTMD_ARGB; + break; +@@ -983,6 +1055,7 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + break; + case V4L2_PIX_FMT_XBGR32: + if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3 && ++ priv->chip != RCAR_V3M && + priv->chip != RCAR_GEN2 && priv->chip != RCAR_H1 && + priv->chip != RCAR_E1) + goto e_format; +@@ -990,11 +1063,16 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + dmr = VNDMR_EXRGB; + break; + case V4L2_PIX_FMT_ABGR32: +- if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3) ++ if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3 && ++ priv->chip != RCAR_V3M) + goto e_format; + + dmr = VNDMR_EXRGB | VNDMR_DTMD_ARGB; + break; ++ case V4L2_PIX_FMT_SBGGR8: ++ case V4L2_PIX_FMT_SBGGR12: ++ dmr = 0; ++ break; + default: + goto e_format; + } +@@ -1006,13 +1084,16 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + if (input_is_yuv == output_is_yuv) + vnmc |= VNMC_BPS; + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { + if (priv->pdata_flags & RCAR_VIN_CSI2) + vnmc &= ~VNMC_DPINE; + else + vnmc |= VNMC_DPINE; + +- if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12) ++ if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12) && ++ (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR8) && ++ (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR12) + && is_scaling(cam)) + vnmc |= VNMC_SCLE; + } +@@ -1024,6 +1105,33 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + if (vin_debug) + interrupts |= VNIE_FOE; + ++ if (lut_reverse && !priv->lut_updated) { ++ iowrite32(0, priv->base + VNLUTP_REG); ++ ++ for (i = 0; i < 1024; i++) { ++ /* reverse MSB 8bits image at 10bit LUT address */ ++ lutd = ((i >> 2) & BIT(0) ? BIT(7) : 0); ++ lutd |= ((i >> 2) & BIT(1) ? BIT(6) : 0); ++ lutd |= ((i >> 2) & BIT(2) ? BIT(5) : 0); ++ lutd |= ((i >> 2) & BIT(3) ? BIT(4) : 0); ++ lutd |= ((i >> 2) & BIT(4) ? BIT(3) : 0); ++ lutd |= ((i >> 2) & BIT(5) ? BIT(2) : 0); ++ lutd |= ((i >> 2) & BIT(6) ? BIT(1) : 0); ++ lutd |= ((i >> 2) & BIT(7) ? BIT(0) : 0); ++#if 0 ++ /* strait (no any density convertion, used for testing) */ ++ lutd = i >> 2; ++#endif ++ lutd = (lutd << 16) | (lutd << 8) | lutd; ++ iowrite32(lutd, priv->base + VNLUTD_REG); ++ } ++ /* update LUT table once */ ++ priv->lut_updated = 1; ++ } ++ ++ if (lut_reverse) ++ vnmc |= VNMC_LUTE; ++ + /* ack interrupts */ + iowrite32(interrupts, priv->base + VNINTS_REG); + /* enable interrupts */ +@@ -1162,6 +1270,10 @@ static void rcar_vin_videobuf_queue(struct vb2_buffer *vb) + */ + static void rcar_vin_wait_stop_streaming(struct rcar_vin_priv *priv) + { ++ /* update the status if hardware is not stopped */ ++ if (ioread32(priv->base + VNMS_REG) & VNMS_CA) ++ priv->state = RUNNING; ++ + while (priv->state != STOPPED) { + /* issue stop if running */ + if (priv->state == RUNNING) +@@ -1312,6 +1424,26 @@ static struct v4l2_subdev *find_csi2(struct rcar_vin_priv *pcdev) + return NULL; + } + ++static struct v4l2_subdev *find_deser(struct rcar_vin_priv *pcdev) ++{ ++ struct v4l2_subdev *sd; ++ char name[] = "max9286"; ++ char name2[] = "ti9x4"; ++ ++ v4l2_device_for_each_subdev(sd, &pcdev->ici.v4l2_dev) { ++ if (!strncmp(name, sd->name, sizeof(name) - 1)) { ++ pcdev->deser_sd = sd; ++ return sd; ++ } ++ if (!strncmp(name2, sd->name, sizeof(name2) - 1)) { ++ pcdev->deser_sd = sd; ++ return sd; ++ } ++ } ++ ++ return NULL; ++} ++ + static int rcar_vin_add_device(struct soc_camera_device *icd) + { + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); +@@ -1323,9 +1455,11 @@ static int rcar_vin_add_device(struct soc_camera_device *icd) + + pm_runtime_get_sync(ici->v4l2_dev.dev); + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { + struct v4l2_subdev *csi2_sd = find_csi2(priv); +- int ret; ++ struct v4l2_subdev *deser_sd = find_deser(priv); ++ int ret = 0; + + if (csi2_sd) { + csi2_sd->grp_id = soc_camera_grp_id(icd); +@@ -1340,6 +1474,18 @@ static int rcar_vin_add_device(struct soc_camera_device *icd) + if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) + return ret; + } ++ if (deser_sd) { ++ v4l2_set_subdev_hostdata(deser_sd, icd); ++ ++ ret = v4l2_subdev_call(deser_sd, core, s_power, 1); ++ priv->deser_sync = true; ++ ++ if (ret < 0 && ret != -EINVAL) ++ priv->deser_sync = false; ++ ++ if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) ++ return ret; ++ } + /* + * -ENODEV is special: + * either csi2_sd == NULL or the CSI-2 driver +@@ -1367,6 +1513,7 @@ static void rcar_vin_remove_device(struct soc_camera_device *icd) + struct rcar_vin_priv *priv = ici->priv; + struct vb2_v4l2_buffer *vbuf; + struct v4l2_subdev *csi2_sd = find_csi2(priv); ++ struct v4l2_subdev *deser_sd = find_deser(priv); + int i; + + /* disable capture, disable interrupts */ +@@ -1393,6 +1540,8 @@ static void rcar_vin_remove_device(struct soc_camera_device *icd) + + if ((csi2_sd) && (priv->csi_sync)) + v4l2_subdev_call(csi2_sd, core, s_power, 0); ++ if ((deser_sd) && (priv->deser_sync)) ++ v4l2_subdev_call(deser_sd, core, s_power, 0); + + dev_dbg(icd->parent, "R-Car VIN driver detached from camera %d\n", + icd->devnum); +@@ -1569,14 +1718,21 @@ static int rcar_vin_set_rect(struct soc_camera_device *icd) + break; + } + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { +- if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12) ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { ++ if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12) && ++ (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR8) && ++ (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR12) + && is_scaling(cam)) { + ret = rcar_vin_uds_set(priv, cam); + if (ret < 0) + return ret; + } +- if (is_scaling(cam) || ++ if ((icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_SBGGR8) || ++ (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_SBGGR12)) ++ iowrite32(ALIGN(cam->out_width / 2, 0x10), ++ priv->base + VNIS_REG); ++ else if (is_scaling(cam) || + (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_NV16) || + (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_NV12)) + iowrite32(ALIGN(cam->out_width, 0x20), +@@ -1720,14 +1876,16 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd) + if (ret < 0 && ret != -ENOIOCTLCMD) + return ret; + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { + if (cfg.type == V4L2_MBUS_CSI2) + vnmc &= ~VNMC_DPINE; + else + vnmc |= VNMC_DPINE; + } + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) + val = VNDMR2_FTEV; + else + val = VNDMR2_FTEV | VNDMR2_VLV(1); +@@ -1815,6 +1973,14 @@ static const struct soc_mbus_pixelfmt rcar_vin_formats[] = { + .layout = SOC_MBUS_LAYOUT_PACKED, + }, + { ++ .fourcc = V4L2_PIX_FMT_GREY, ++ .name = "GREY8", ++ .bits_per_sample = 8, ++ .packing = SOC_MBUS_PACKING_NONE, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, ++ { + .fourcc = V4L2_PIX_FMT_RGB565, + .name = "RGB565", + .bits_per_sample = 16, +@@ -1846,6 +2012,22 @@ static const struct soc_mbus_pixelfmt rcar_vin_formats[] = { + .order = SOC_MBUS_ORDER_LE, + .layout = SOC_MBUS_LAYOUT_PACKED, + }, ++ { ++ .fourcc = V4L2_PIX_FMT_SBGGR8, ++ .name = "Bayer 8 BGGR", ++ .bits_per_sample = 8, ++ .packing = SOC_MBUS_PACKING_NONE, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SBGGR12, ++ .name = "Bayer 12 BGGR", ++ .bits_per_sample = 8, ++ .packing = SOC_MBUS_PACKING_NONE, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, + }; + + static int rcar_vin_get_formats(struct soc_camera_device *icd, unsigned int idx, +@@ -1959,6 +2141,8 @@ static int rcar_vin_get_formats(struct soc_camera_device *icd, unsigned int idx, + case MEDIA_BUS_FMT_YUYV8_2X8: + case MEDIA_BUS_FMT_YUYV10_2X10: + case MEDIA_BUS_FMT_RGB888_1X24: ++ case MEDIA_BUS_FMT_SBGGR8_1X8: ++ case MEDIA_BUS_FMT_SBGGR12_1X12: + if (cam->extra_fmt) + break; + +@@ -2165,12 +2349,15 @@ static int rcar_vin_set_fmt(struct soc_camera_device *icd, + case V4L2_PIX_FMT_ABGR32: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_YUYV: ++ case V4L2_PIX_FMT_GREY: + case V4L2_PIX_FMT_RGB565: + case V4L2_PIX_FMT_ARGB555: + case V4L2_PIX_FMT_NV16: + can_scale = true; + break; + case V4L2_PIX_FMT_NV12: ++ case V4L2_PIX_FMT_SBGGR8: ++ case V4L2_PIX_FMT_SBGGR12: + default: + can_scale = false; + break; +@@ -2263,7 +2450,8 @@ static int rcar_vin_try_fmt(struct soc_camera_device *icd, + /* odd number clipping by pixel post clip processing, */ + /* it is outputted to a memory per even pixels. */ + if ((pixfmt == V4L2_PIX_FMT_NV16) || (pixfmt == V4L2_PIX_FMT_NV12) || +- (pixfmt == V4L2_PIX_FMT_YUYV) || (pixfmt == V4L2_PIX_FMT_UYVY)) ++ (pixfmt == V4L2_PIX_FMT_YUYV) || (pixfmt == V4L2_PIX_FMT_UYVY) || ++ (pixfmt == V4L2_PIX_FMT_GREY)) + v4l_bound_align_image(&pix->width, 5, priv->max_width, 1, + &pix->height, 2, priv->max_height, 0, 0); + else +@@ -2289,7 +2477,8 @@ static int rcar_vin_try_fmt(struct soc_camera_device *icd, + if (ret < 0) + return ret; + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { + /* Adjust max scaling size for Gen3 */ + if (pix->width > 4096) + pix->width = priv->max_width; +@@ -2432,6 +2621,19 @@ static int rcar_vin_cropcap(struct soc_camera_device *icd, + } + #endif + ++static int rcar_vin_get_edid(struct soc_camera_device *icd, ++ struct v4l2_edid *edid) ++{ ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ int ret; ++ ++ ret = v4l2_subdev_call(sd, pad, get_edid, edid); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ + static struct soc_camera_host_ops rcar_vin_host_ops = { + .owner = THIS_MODULE, + .add = rcar_vin_add_device, +@@ -2450,10 +2652,12 @@ static struct soc_camera_host_ops rcar_vin_host_ops = { + .get_selection = rcar_vin_get_selection, + .cropcap = rcar_vin_cropcap, + #endif ++ .get_edid = rcar_vin_get_edid, + }; + + #ifdef CONFIG_OF + static const struct of_device_id rcar_vin_of_table[] = { ++ { .compatible = "renesas,vin-r8a7797", .data = (void *)RCAR_V3M }, + { .compatible = "renesas,vin-r8a7796", .data = (void *)RCAR_M3 }, + { .compatible = "renesas,vin-r8a7795", .data = (void *)RCAR_H3 }, + { .compatible = "renesas,vin-r8a7794", .data = (void *)RCAR_GEN2 }, +@@ -2469,7 +2673,7 @@ static const struct of_device_id rcar_vin_of_table[] = { + MODULE_DEVICE_TABLE(of, rcar_vin_of_table); + #endif + +-#define MAP_MAX_NUM 32 ++#define MAP_MAX_NUM 128 + static DECLARE_BITMAP(device_map, MAP_MAX_NUM); + static DEFINE_MUTEX(list_lock); + +@@ -2578,6 +2782,12 @@ static struct soc_camera_device *rcar_vin_add_pdev( + return platform_get_drvdata(pdev); + } + ++static const struct v4l2_async_notifier_operations rcar_vin_sensor_ops = { ++ .bound = rcar_vin_async_bound, ++ .unbind = rcar_vin_async_unbind, ++ .complete = rcar_vin_async_complete, ++}; ++ + static int rcar_vin_soc_of_bind(struct rcar_vin_priv *priv, + struct soc_camera_host *ici, + struct device_node *ep, +@@ -2597,8 +2807,8 @@ static int rcar_vin_soc_of_bind(struct rcar_vin_priv *priv, + if (!info) + return -ENOMEM; + +- info->sasd.asd.match.of.node = remote; +- info->sasd.asd.match_type = V4L2_ASYNC_MATCH_OF; ++ info->sasd.asd.match.fwnode.fwnode = of_fwnode_handle(remote); ++ info->sasd.asd.match_type = V4L2_ASYNC_MATCH_FWNODE; + info->subdev = &info->sasd.asd; + + /* Or shall this be managed by the soc-camera device? */ +@@ -2618,9 +2828,7 @@ static int rcar_vin_soc_of_bind(struct rcar_vin_priv *priv, + + sasc->notifier.subdevs = &info->subdev; + sasc->notifier.num_subdevs = 1; +- sasc->notifier.bound = rcar_vin_async_bound; +- sasc->notifier.unbind = rcar_vin_async_unbind; +- sasc->notifier.complete = rcar_vin_async_complete; ++ sasc->notifier.ops = &rcar_vin_sensor_ops; + + priv->async_client = sasc; + +@@ -2651,7 +2859,7 @@ static int rcar_vin_probe(struct platform_device *pdev) + { + const struct of_device_id *match = NULL; + struct rcar_vin_priv *priv; +- struct v4l2_of_endpoint ep; ++ struct v4l2_fwnode_endpoint ep; + struct device_node *np; + struct resource *mem; + unsigned int pdata_flags; +@@ -2659,7 +2867,10 @@ static int rcar_vin_probe(struct platform_device *pdev) + const char *str; + unsigned int i; + struct device_node *epn = NULL, *ren = NULL; ++ struct device_node *csi2_ren = NULL, *max9286_ren = NULL, *ti9x4_ren = NULL; + bool csi_use = false; ++ bool max9286_use = false; ++ bool ti9x4_use = false; + + match = of_match_device(of_match_ptr(rcar_vin_of_table), &pdev->dev); + +@@ -2686,16 +2897,25 @@ static int rcar_vin_probe(struct platform_device *pdev) + dev_dbg(&pdev->dev, "node name:%s\n", + of_node_full_name(ren->parent)); + +- if (strcmp(ren->parent->name, "csi2") == 0) ++ if (strcmp(ren->parent->name, "csi2") == 0) { ++ csi2_ren = ren; + csi_use = true; ++ } + +- of_node_put(ren); ++ if (strcmp(ren->parent->name, "max9286") == 0) { ++ max9286_ren = of_parse_phandle(epn, "remote-endpoint", 0); ++ max9286_use = true; ++ } + +- if (i) +- break; ++ if (strcmp(ren->parent->name, "ti9x4") == 0) { ++ ti9x4_ren = of_parse_phandle(epn, "remote-endpoint", 0); ++ ti9x4_use = true; ++ } ++ ++ of_node_put(ren); + } + +- ret = v4l2_of_parse_endpoint(np, &ep); ++ ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(np), &ep); + if (ret) { + dev_err(&pdev->dev, "could not parse endpoint\n"); + return ret; +@@ -2744,17 +2964,24 @@ static int rcar_vin_probe(struct platform_device *pdev) + priv->ici.drv_name = dev_name(&pdev->dev); + priv->ici.ops = &rcar_vin_host_ops; + priv->csi_sync = false; ++ priv->deser_sync = false; + + priv->pdata_flags = pdata_flags; + if (!match) { + priv->ici.nr = pdev->id; + priv->chip = pdev->id_entry->driver_data; + } else { +- priv->ici.nr = of_alias_get_id(pdev->dev.of_node, "vin"); ++ if (of_property_read_u32(pdev->dev.of_node, "renesas,id", &i)) { ++ dev_err(&pdev->dev, "%s: No renesas,id property found\n", ++ of_node_full_name(pdev->dev.of_node)); ++ return -EINVAL; ++ } ++ priv->ici.nr = i; + priv->chip = (enum chip_id)match->data; + } + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { + priv->max_width = 4096; + priv->max_height = 4096; + } else { +@@ -2762,7 +2989,8 @@ static int rcar_vin_probe(struct platform_device *pdev) + priv->max_height = 2048; + } + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { + u32 ifmd = 0; + bool match_flag = false; + const struct vin_gen3_ifmd *gen3_ifmd_table = NULL; +@@ -2841,6 +3069,8 @@ static int rcar_vin_probe(struct platform_device *pdev) + gen3_ifmd_table = vin_h3_vc_ifmd; + else if (priv->chip == RCAR_M3) + gen3_ifmd_table = vin_m3_vc_ifmd; ++ else if (priv->chip == RCAR_V3M) ++ gen3_ifmd_table = vin_v3_vc_ifmd; + + for (i = 0; i < num; i++) { + if ((gen3_ifmd_table[i].v_sel[priv->index].csi2_ch +@@ -2924,7 +3154,19 @@ static int rcar_vin_probe(struct platform_device *pdev) + goto cleanup; + + if (csi_use) { +- ret = rcar_vin_soc_of_bind(priv, &priv->ici, epn, ren->parent); ++ ret = rcar_vin_soc_of_bind(priv, &priv->ici, epn, csi2_ren->parent); ++ if (ret) ++ goto cleanup; ++ } ++ ++ if (max9286_use) { ++ ret = rcar_vin_soc_of_bind(priv, &priv->ici, epn, max9286_ren); ++ if (ret) ++ goto cleanup; ++ } ++ ++ if (ti9x4_use) { ++ ret = rcar_vin_soc_of_bind(priv, &priv->ici, epn, ti9x4_ren); + if (ret) + goto cleanup; + } +@@ -2983,6 +3225,9 @@ static int rcar_vin_resume(struct device *dev) + } else if (priv->chip == RCAR_M3) { + ifmd = VNCSI_IFMD_DES1; + gen3_ifmd_table = vin_m3_vc_ifmd; ++ } else if (priv->chip == RCAR_V3M) { ++ ifmd = VNCSI_IFMD_DES1; ++ gen3_ifmd_table = vin_v3_vc_ifmd; + } + + for (i = 0; i < num; i++) { +diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c +index 916ff68..1f840cf 100644 +--- a/drivers/media/platform/soc_camera/soc_camera.c ++++ b/drivers/media/platform/soc_camera/soc_camera.c +@@ -44,7 +44,7 @@ + #define DEFAULT_WIDTH 640 + #define DEFAULT_HEIGHT 480 + +-#define MAP_MAX_NUM 32 ++#define MAP_MAX_NUM 128 + static DECLARE_BITMAP(device_map, MAP_MAX_NUM); + static LIST_HEAD(hosts); + static LIST_HEAD(devices); +@@ -1044,6 +1044,18 @@ static int soc_camera_s_parm(struct file *file, void *fh, + return -ENOIOCTLCMD; + } + ++static int soc_camera_g_edid(struct file *file, void *fh, ++ struct v4l2_edid *edid) ++{ ++ struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ ++ if (ici->ops->get_edid) ++ return ici->ops->get_edid(icd, edid); ++ ++ return -ENOIOCTLCMD; ++} ++ + static int soc_camera_probe(struct soc_camera_host *ici, + struct soc_camera_device *icd); + +@@ -1602,7 +1614,7 @@ static void scan_of_host(struct soc_camera_host *ici) + of_node_put(ren); + + if (i) { +- dev_err(dev, "multiple subdevices aren't supported yet!\n"); ++ dev_dbg(dev, "multiple subdevices aren't supported yet!\n"); + break; + } + } +@@ -2013,6 +2025,7 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = { + .vidioc_s_selection = soc_camera_s_selection, + .vidioc_g_parm = soc_camera_g_parm, + .vidioc_s_parm = soc_camera_s_parm, ++ .vidioc_g_edid = soc_camera_g_edid, + }; + + static int video_dev_create(struct soc_camera_device *icd) +diff --git a/drivers/media/platform/soc_camera/soc_mediabus.c b/drivers/media/platform/soc_camera/soc_mediabus.c +index 0ad4b28..d4e5c1e 100644 +--- a/drivers/media/platform/soc_camera/soc_mediabus.c ++++ b/drivers/media/platform/soc_camera/soc_mediabus.c +@@ -57,6 +57,16 @@ static const struct soc_mbus_lookup mbus_fmt[] = { + .layout = SOC_MBUS_LAYOUT_PACKED, + }, + }, { ++ .code = MEDIA_BUS_FMT_YUYV10_2X10, ++ .fmt = { ++ .fourcc = V4L2_PIX_FMT_YUYV, ++ .name = "YUYV", ++ .bits_per_sample = 10, ++ .packing = SOC_MBUS_PACKING_2X10_PADHI, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, ++}, { + .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE, + .fmt = { + .fourcc = V4L2_PIX_FMT_RGB555, +@@ -403,6 +413,10 @@ int soc_mbus_samples_per_pixel(const struct soc_mbus_pixelfmt *mf, + *numerator = 2; + *denominator = 1; + return 0; ++ case SOC_MBUS_PACKING_2X10_PADHI: ++ *numerator = 3; ++ *denominator = 1; ++ return 0; + case SOC_MBUS_PACKING_1_5X8: + *numerator = 3; + *denominator = 2; +@@ -428,6 +442,8 @@ s32 soc_mbus_bytes_per_line(u32 width, const struct soc_mbus_pixelfmt *mf) + case SOC_MBUS_PACKING_2X8_PADLO: + case SOC_MBUS_PACKING_EXTEND16: + return width * 2; ++ case SOC_MBUS_PACKING_2X10_PADHI: ++ return width * 3; + case SOC_MBUS_PACKING_1_5X8: + return width * 3 / 2; + case SOC_MBUS_PACKING_VARIABLE: +diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c +index 7b6c556..1fed0f8 100644 +--- a/drivers/media/v4l2-core/v4l2-async.c ++++ b/drivers/media/v4l2-core/v4l2-async.c +@@ -398,6 +398,7 @@ static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier) + case V4L2_ASYNC_MATCH_I2C: + break; + case V4L2_ASYNC_MATCH_FWNODE: ++#if 0 + if (v4l2_async_notifier_fwnode_has_async_subdev( + notifier, asd->match.fwnode.fwnode, i)) { + dev_err(dev, +@@ -405,6 +406,7 @@ static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier) + ret = -EEXIST; + goto err_unlock; + } ++#endif + break; + default: + dev_err(dev, "Invalid match type %u on %p\n", +diff --git a/include/media/drv-intf/soc_mediabus.h b/include/media/drv-intf/soc_mediabus.h +index 2ff7737..e5f3f53 100644 +--- a/include/media/drv-intf/soc_mediabus.h ++++ b/include/media/drv-intf/soc_mediabus.h +@@ -21,6 +21,8 @@ + * @SOC_MBUS_PACKING_2X8_PADHI: 16 bits transferred in 2 8-bit samples, in the + * possibly incomplete byte high bits are padding + * @SOC_MBUS_PACKING_2X8_PADLO: as above, but low bits are padding ++ * @SOC_MBUS_PACKING_2X10_PADHI:20 bits transferred in 2 10-bit samples. The ++ * high bits are padding + * @SOC_MBUS_PACKING_EXTEND16: sample width (e.g., 10 bits) has to be extended + * to 16 bits + * @SOC_MBUS_PACKING_VARIABLE: compressed formats with variable packing +@@ -33,6 +35,7 @@ enum soc_mbus_packing { + SOC_MBUS_PACKING_NONE, + SOC_MBUS_PACKING_2X8_PADHI, + SOC_MBUS_PACKING_2X8_PADLO, ++ SOC_MBUS_PACKING_2X10_PADHI, + SOC_MBUS_PACKING_EXTEND16, + SOC_MBUS_PACKING_VARIABLE, + SOC_MBUS_PACKING_1_5X8, +diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h +index 4d8cb07..4381be0 100644 +--- a/include/media/soc_camera.h ++++ b/include/media/soc_camera.h +@@ -118,6 +118,7 @@ struct soc_camera_host_ops { + int (*set_parm)(struct soc_camera_device *, struct v4l2_streamparm *); + int (*enum_framesizes)(struct soc_camera_device *, struct v4l2_frmsizeenum *); + unsigned int (*poll)(struct file *, poll_table *); ++ int (*get_edid)(struct soc_camera_device *, struct v4l2_edid *); + }; + + #define SOCAM_SENSOR_INVERT_PCLK (1 << 0) +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0031-media-i2c-Add-ov5647-sensor.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0031-media-i2c-Add-ov5647-sensor.patch new file mode 100644 index 00000000..6a530f19 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0031-media-i2c-Add-ov5647-sensor.patch @@ -0,0 +1,951 @@ +From 649acea146fb60eff7a7d924f2affcf76b13a3a8 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Thu, 1 Jun 2017 19:59:56 +0300 +Subject: [PATCH 023/122] media: i2c: Add ov5647 sensor + +Add ov5647 camera sensor driver + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/Kconfig | 6 + + drivers/media/i2c/soc_camera/Makefile | 1 + + drivers/media/i2c/soc_camera/ov5647.c | 648 ++++++++++++++++++++++++++++++++++ + drivers/media/i2c/soc_camera/ov5647.h | 242 +++++++++++++ + 4 files changed, 897 insertions(+) + create mode 100644 drivers/media/i2c/soc_camera/ov5647.c + create mode 100644 drivers/media/i2c/soc_camera/ov5647.h + +diff --git a/drivers/media/i2c/soc_camera/Kconfig b/drivers/media/i2c/soc_camera/Kconfig +index d30a3f9..1db3c6b 100644 +--- a/drivers/media/i2c/soc_camera/Kconfig ++++ b/drivers/media/i2c/soc_camera/Kconfig +@@ -47,6 +47,12 @@ config SOC_CAMERA_OV5642 + help + This is a V4L2 camera driver for the OmniVision OV5642 sensor + ++config SOC_CAMERA_OV5647 ++ tristate "ov5647 camera support" ++ depends on SOC_CAMERA && I2C ++ help ++ This is a V4L2 camera driver for the OmniVision OV5647 sensor ++ + config SOC_CAMERA_OV772X + tristate "ov772x camera support" + depends on SOC_CAMERA && I2C +diff --git a/drivers/media/i2c/soc_camera/Makefile b/drivers/media/i2c/soc_camera/Makefile +index 1134c03..0d4242e 100644 +--- a/drivers/media/i2c/soc_camera/Makefile ++++ b/drivers/media/i2c/soc_camera/Makefile +@@ -5,6 +5,7 @@ obj-$(CONFIG_SOC_CAMERA_MT9T031) += mt9t031.o + obj-$(CONFIG_SOC_CAMERA_MT9T112) += mt9t112.o + obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o + obj-$(CONFIG_SOC_CAMERA_OV5642) += ov5642.o ++obj-$(CONFIG_SOC_CAMERA_OV5647) += ov5647.o + obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o + obj-$(CONFIG_SOC_CAMERA_OV9640) += ov9640.o + obj-$(CONFIG_SOC_CAMERA_OV9740) += ov9740.o +diff --git a/drivers/media/i2c/soc_camera/ov5647.c b/drivers/media/i2c/soc_camera/ov5647.c +new file mode 100644 +index 0000000..d8b87c1 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov5647.c +@@ -0,0 +1,648 @@ ++/* ++ * V4L2 driver for OmniVision OV5647 cameras. ++ * ++ * Based on Samsung S5K6AAFX SXGA 1/6" 1.3M CMOS Image Sensor driver ++ * Copyright (C) 2011 Sylwester Nawrocki ++ * ++ * Based on Omnivision OV7670 Camera Driver ++ * Copyright (C) 2006-7 Jonathan Corbet ++ * ++ * Copyright (C) 2016, Synopsys, Inc. ++ * ++ * Copyright (C) 2017 Cogent Embedded, Inc ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "ov5647.h" ++ ++static bool debug = true; ++module_param(debug, bool, 0644); ++MODULE_PARM_DESC(debug, "Debug level (0-1)"); ++ ++#define OV5647_I2C_ADDR 0x6c ++#define SENSOR_NAME "ov5647" ++ ++#define OV5647_REG_CHIPID_H 0x300A ++#define OV5647_REG_CHIPID_L 0x300B ++ ++#define REG_TERM 0xfffe ++#define VAL_TERM 0xfe ++#define REG_DLY 0xffff ++ ++/*define the voltage level of control signal*/ ++#define CSI_STBY_ON 1 ++#define CSI_STBY_OFF 0 ++#define CSI_RST_ON 0 ++#define CSI_RST_OFF 1 ++#define CSI_PWR_ON 1 ++#define CSI_PWR_OFF 0 ++#define CSI_AF_PWR_ON 1 ++#define CSI_AF_PWR_OFF 0 ++ ++#define OV5647_ROW_START 0x01 ++#define OV5647_ROW_START_MIN 0 ++#define OV5647_ROW_START_MAX 2004 ++#define OV5647_ROW_START_DEF 54 ++ ++#define OV5647_COLUMN_START 0x02 ++#define OV5647_COLUMN_START_MIN 0 ++#define OV5647_COLUMN_START_MAX 2750 ++#define OV5647_COLUMN_START_DEF 16 ++ ++#define OV5647_WINDOW_HEIGHT 0x03 ++#define OV5647_WINDOW_HEIGHT_MIN 2 ++#define OV5647_WINDOW_HEIGHT_MAX 2006 ++#define OV5647_WINDOW_HEIGHT_DEF 1944 ++ ++#define OV5647_WINDOW_WIDTH 0x04 ++#define OV5647_WINDOW_WIDTH_MIN 2 ++#define OV5647_WINDOW_WIDTH_MAX 2752 ++#define OV5647_WINDOW_WIDTH_DEF 2592 ++ ++enum power_seq_cmd { ++ CSI_SUBDEV_PWR_OFF = 0x00, ++ CSI_SUBDEV_PWR_ON = 0x01, ++}; ++ ++struct sensor_format_struct { ++ __u8 *desc; ++ u32 mbus_code; ++ enum v4l2_colorspace colorspace; ++ struct regval_list *regs; ++ int regs_size; ++ int bpp; ++}; ++ ++struct cfg_array { ++ struct regval_list *regs; ++ int size; ++}; ++ ++struct sensor_win_size { ++ int width; ++ int height; ++ unsigned int hoffset; ++ unsigned int voffset; ++ unsigned int hts; ++ unsigned int vts; ++ unsigned int pclk; ++ unsigned int mipi_bps; ++ unsigned int fps_fixed; ++ unsigned int bin_factor; ++ unsigned int intg_min; ++ unsigned int intg_max; ++ void *regs; ++ int regs_size; ++ int (*set_size)(struct v4l2_subdev *subdev); ++}; ++ ++struct ov5647 { ++ struct device *dev; ++ struct v4l2_subdev subdev; ++ struct media_pad pad; ++ struct mutex lock; ++ struct v4l2_mbus_framefmt format; ++ struct sensor_format_struct *fmt; ++ unsigned int width; ++ unsigned int height; ++ unsigned int capture_mode; ++ int hue; ++ struct v4l2_fract tpf; ++ struct sensor_win_size *current_wins; ++}; ++ ++static inline struct ov5647 *to_state(struct v4l2_subdev *subdev) ++{ ++ return container_of(subdev, struct ov5647, subdev); ++} ++ ++static struct sensor_format_struct sensor_formats[] = { ++ { ++ .mbus_code = OV5647_CODE, ++ .colorspace = V4L2_COLORSPACE_JPEG, ++ }, ++}; ++#define N_FMTS ARRAY_SIZE(sensor_formats) ++ ++static int ov5647_write(struct v4l2_subdev *sd, uint16_t reg, uint8_t val) ++{ ++ int ret; ++ unsigned char data[3] = { reg >> 8, reg & 0xff, val}; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ ret = i2c_master_send(client, data, 3); ++ if (ret < 3) { ++ printk( "%s: i2c write error, reg: %x, %d\n", ++ __func__, reg, ret); ++ return ret < 0 ? ret : -EIO; ++ } ++ ++ return 0; ++} ++ ++static int ov5647_read(struct v4l2_subdev *sd, uint16_t reg, uint8_t *val) ++{ ++ int ret; ++ unsigned char data_w[2] = { reg >> 8, reg & 0xff }; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ ++ ret = i2c_master_send(client, data_w, 2); ++ ++ if (ret < 2) { ++ printk("%s: i2c read error, reg: %x\n", ++ __func__, reg); ++ return ret < 0 ? ret : -EIO; ++ } ++ ++ ret = i2c_master_recv(client, val, 1); ++ ++ if (ret < 1) { ++ printk("%s: i2c read error, reg: %x\n", ++ __func__, reg); ++ return ret < 0 ? ret : -EIO; ++ } ++ ++ return 0; ++} ++ ++static int ov5647_write_array(struct v4l2_subdev *subdev, ++ struct regval_list *regs, int array_size) ++{ ++ int i = 0; ++ int ret = 0; ++ ++ if (!regs) ++ return -EINVAL; ++ ++ while (i < array_size) { ++ if (regs->addr == REG_DLY) ++ mdelay(regs->data); ++ else ++ ret = ov5647_write(subdev, regs->addr, regs->data); ++ ++ if (ret == -EIO) ++ return ret; ++ ++ i++; ++ regs++; ++ } ++ return 0; ++} ++ ++static void ov5647_set_virtual_channel(struct v4l2_subdev *subdev, int channel) ++{ ++#if 0 ++ u8 channel_id; ++ ++ ov5647_read(subdev, 0x4814, &channel_id); ++// channel_id = 0x1e; //override ++ ++ channel_id &= ~(3 << 6); ++ channel_id |= (channel << 6); ++ printk("0x4814 = 0x%02x\n", channel_id); ++ ov5647_write(subdev, 0x4814, channel_id); ++ ov5647_write(subdev, 0x4801, 0x8f); ++#endif ++} ++ ++void ov5647_stream_on(struct v4l2_subdev *subdev) ++{ ++ ov5647_write(subdev, 0x4202, 0x00); ++ ov5647_write(subdev, 0x300D, 0x00); ++} ++ ++void ov5647_stream_off(struct v4l2_subdev *subdev) ++{ ++ ov5647_write(subdev, 0x4202, 0x0f); ++ ov5647_write(subdev, 0x300D, 0x01); ++} ++ ++static int sensor_s_sw_stby(struct v4l2_subdev *subdev, int on_off) ++{ ++ int ret; ++ unsigned char rdval; ++ ++ ret = ov5647_read(subdev, 0x0100, &rdval); ++ if (ret != 0) ++ return ret; ++ ++ if (on_off == CSI_STBY_ON) ++ ret = ov5647_write(subdev, 0x0100, rdval&0xfe); ++ else ++ ret = ov5647_write(subdev, 0x0100, rdval|0x01); ++ ++ return ret; ++} ++ ++static int __sensor_init(struct v4l2_subdev *subdev) ++{ ++ int ret; ++ unsigned char rdval; ++ ++ ret = ov5647_read(subdev, 0x0100, &rdval); ++ if (ret != 0) ++ return ret; ++ ++ ov5647_write(subdev, 0x4800, 0x25); ++ ov5647_stream_off(subdev); ++ ++ ov5647_write(subdev, 0x100, 0); ++ /* reset */ ++ ov5647_write(subdev, 0x103, 1); ++ ov5647_write(subdev, 0x103, 1); ++ ov5647_write(subdev, 0x103, 1); ++ mdelay(10); ++ ++ ret = ov5647_write_array(subdev, ov5647_recommend_settings, ++ ARRAY_SIZE(ov5647_recommend_settings)); ++#if 1 ++ ret = ov5647_write_array(subdev, ov5647_snap_settings, ++ ARRAY_SIZE(ov5647_snap_settings)); ++#else ++ ret = ov5647_write_array(subdev, ov5647_prev_settings, ++ ARRAY_SIZE(ov5647_prev_settings)); ++#endif ++ ov5647_set_virtual_channel(subdev, 0); ++ ++ ov5647_write(subdev, 0x0100, 0x01); ++ ++ ov5647_write(subdev, 0x04800, 0x04); ++ ov5647_stream_on(subdev); ++ msleep(30); ++ ++ return 0; ++} ++ ++static int sensor_power(struct v4l2_subdev *subdev, int on) ++{ ++ int ret = 0; ++ struct ov5647 *ov5647 = to_state(subdev); ++ ++ mutex_lock(&ov5647->lock); ++ ++ switch (on) { ++ case CSI_SUBDEV_PWR_OFF: ++ ret = sensor_s_sw_stby(subdev, CSI_STBY_ON); ++ if (ret < 0) ++ printk("soft stby failed!\n"); ++ break; ++ case CSI_SUBDEV_PWR_ON: ++ ret = __sensor_init(subdev); ++ if (ret < 0) { ++ v4l2_err(subdev, "Camera not available, check power\n"); ++ break; ++ } ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ mutex_unlock(&ov5647->lock); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int sensor_get_register(struct v4l2_subdev *subdev, ++ struct v4l2_dbg_register *reg) ++{ ++ u8 val = 0; ++ int ret; ++ ++ ret = ov5647_read(subdev, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u8); ++ ++ return ret; ++} ++ ++static int sensor_set_register(struct v4l2_subdev *subdev, ++ const struct v4l2_dbg_register *reg) ++{ ++ ov5647_write(subdev, (u16)reg->reg, (u8)reg->val); ++ ++ return 0; ++} ++#endif ++ ++static const struct v4l2_subdev_core_ops sensor_core_ops = { ++ .s_power = sensor_power, ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = sensor_get_register, ++ .s_register = sensor_set_register, ++#endif ++}; ++ ++static int sensor_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ if (enable) ++ ov5647_stream_on(sd); ++ else ++ ov5647_stream_off(sd); ++ ++ return 0; ++} ++ ++static int sensor_enum_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index >= N_FMTS) ++ return -EINVAL; ++ ++ code->code = OV5647_CODE; ++ ++ return 0; ++} ++ ++static int sensor_try_fmt_internal(struct v4l2_subdev *subdev, ++ struct v4l2_mbus_framefmt *fmt, ++ struct sensor_format_struct **ret_fmt, ++ struct sensor_win_size **ret_wsize) ++{ ++ int index; ++ ++ for (index = 0; index < N_FMTS; index++) ++ if (sensor_formats[index].mbus_code == fmt->code) ++ break; ++ ++ if (index >= N_FMTS) ++ return -EINVAL; ++ ++ if (ret_fmt != NULL) ++ *ret_fmt = sensor_formats + index; ++ ++ fmt->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int sensor_s_fmt(struct v4l2_subdev *subdev, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *fmt) ++{ ++ int ret; ++ struct sensor_format_struct *sensor_fmt; ++ struct sensor_win_size *wsize = NULL; ++ struct ov5647 *info = to_state(subdev); ++ ++ ret = sensor_try_fmt_internal(subdev, &fmt->format, ++ &sensor_fmt, &wsize); ++ if (ret) ++ return ret; ++ ++ info->fmt = sensor_fmt; ++ info->width = OV5647_WIDTH; ++ info->height = OV5647_HEIGHT; ++ ++ return 0; ++} ++ ++static int sensor_g_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct ov5647 *info = to_state(sd); ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ if (format->pad != 0) ++ return -EINVAL; ++ ++ mf->width = OV5647_WIDTH; ++ mf->height = OV5647_HEIGHT; ++ mf->code = OV5647_CODE; ++ mf->colorspace = info->fmt->colorspace; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int sensor_s_parm(struct v4l2_subdev *subdev, ++ struct v4l2_streamparm *parms) ++{ ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ struct ov5647 *info = to_state(subdev); ++ ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ ++ if (info->tpf.numerator == 0) ++ return -EINVAL; ++ ++ info->capture_mode = cp->capturemode; ++ ++ return 0; ++} ++ ++static int sensor_g_parm(struct v4l2_subdev *subdev, ++ struct v4l2_streamparm *parms) ++{ ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ struct ov5647 *info = to_state(subdev); ++ ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ ++ memset(cp, 0, sizeof(struct v4l2_captureparm)); ++ cp->capability = V4L2_CAP_TIMEPERFRAME; ++ cp->capturemode = info->capture_mode; ++ ++ return 0; ++} ++ ++static int sensor_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++static const struct v4l2_subdev_pad_ops sensor_pad_ops = { ++ .enum_mbus_code = sensor_enum_fmt, ++ .set_fmt = sensor_s_fmt, ++ .get_fmt = sensor_g_fmt, ++}; ++ ++static const struct v4l2_subdev_video_ops sensor_video_ops = { ++ .s_stream = sensor_s_stream, ++ .s_parm = sensor_s_parm, ++ .g_parm = sensor_g_parm, ++ .g_mbus_config = sensor_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_ops subdev_ops = { ++ .core = &sensor_core_ops, ++ .video = &sensor_video_ops, ++ .pad = &sensor_pad_ops, ++}; ++ ++static int ov5647_detect(struct v4l2_subdev *sd) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ unsigned char id_h, id_l; ++ int ret; ++ ++ ret = sensor_power(sd, 1); ++ if (ret < 0) ++ return ret; ++ ++ ret = ov5647_read(sd, OV5647_REG_CHIPID_H, &id_h); ++ if (ret < 0) ++ return ret; ++ ret = ov5647_read(sd, OV5647_REG_CHIPID_L, &id_l); ++ if (ret < 0) ++ return ret; ++ ++ if ((id_h != 0x56) || (id_l != 0x47)) { ++ v4l2_info(sd, "Invalid device ID: %02x%02x\n", id_h, id_l); ++ return -ENODEV; ++ } ++ ++ v4l2_info(sd, "OV5647 detected at address 0x%02x\n", client->addr); ++ ++ ret = sensor_power(sd, 0); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int ov5647_registered(struct v4l2_subdev *subdev) ++{ ++ return 0; ++} ++ ++static int ov5647_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh) ++{ ++ struct v4l2_mbus_framefmt *format = ++ v4l2_subdev_get_try_format(subdev, fh->pad, 0); ++ struct v4l2_rect *crop = ++ v4l2_subdev_get_try_crop(subdev, fh->pad, 0); ++ ++ crop->left = 0; ++ crop->top = 0; ++ crop->width = OV5647_WIDTH; ++ crop->height = OV5647_HEIGHT; ++ ++ format->code = OV5647_CODE; ++ ++ format->width = OV5647_WIDTH; ++ format->height = OV5647_HEIGHT; ++ format->field = V4L2_FIELD_NONE; ++ format->colorspace = sensor_formats[0].colorspace; ++ ++ return sensor_power(subdev, 1); ++} ++ ++static int ov5647_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh) ++{ ++ return sensor_power(subdev, 0); ++} ++ ++static const struct v4l2_subdev_internal_ops ov5647_subdev_internal_ops = { ++ .registered = ov5647_registered, ++ .open = ov5647_open, ++ .close = ov5647_close, ++}; ++ ++static int ov5647_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct device *dev = &client->dev; ++ struct ov5647 *sensor; ++ int ret = 0; ++ struct v4l2_subdev *sd; ++ ++ sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL); ++ if (sensor == NULL) ++ return -ENOMEM; ++ ++ mutex_init(&sensor->lock); ++ sensor->dev = dev; ++ sensor->fmt = &sensor_formats[0]; ++ sensor->width = OV5647_WIDTH; ++ sensor->height = OV5647_HEIGHT; ++ ++ sd = &sensor->subdev; ++ v4l2_i2c_subdev_init(sd, client, &subdev_ops); ++ sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ ret = ov5647_detect(sd); ++ if (ret < 0) { ++ v4l2_err(sd, "OV5647 not found!\n"); ++ goto out; ++ } ++ ++ sensor->pad.flags = MEDIA_PAD_FL_SOURCE; ++ sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&sd->entity, 1, &sensor->pad); ++ if (ret < 0) ++ return ret; ++ ++ ret = v4l2_async_register_subdev(sd); ++ if (ret < 0) ++ media_entity_cleanup(&sd->entity); ++ ++out: ++ return ret; ++} ++ ++static int ov5647_remove(struct i2c_client *client) ++{ ++ struct v4l2_subdev *subdev = i2c_get_clientdata(client); ++ struct ov5647 *ov5647 = to_state(subdev); ++ ++ v4l2_async_unregister_subdev(&ov5647->subdev); ++ media_entity_cleanup(&ov5647->subdev.entity); ++ v4l2_device_unregister_subdev(subdev); ++ ++ return 0; ++} ++ ++static const struct i2c_device_id ov5647_id[] = { ++ { "ov5647", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ov5647_id); ++ ++#if IS_ENABLED(CONFIG_OF) ++static const struct of_device_id ov5647_of_match[] = { ++ { .compatible = "ovti,ov5647" }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, ov5647_of_match); ++#endif ++ ++static struct i2c_driver ov5647_driver = { ++ .driver = { ++ .of_match_table = of_match_ptr(ov5647_of_match), ++ .owner = THIS_MODULE, ++ .name = "ov5647", ++ }, ++ .probe = ov5647_probe, ++ .remove = ov5647_remove, ++ .id_table = ov5647_id, ++}; ++module_i2c_driver(ov5647_driver); ++ ++MODULE_AUTHOR("Ramiro Oliveira "); ++MODULE_DESCRIPTION("A low-level driver for OmniVision ov5647 sensors"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/i2c/soc_camera/ov5647.h b/drivers/media/i2c/soc_camera/ov5647.h +new file mode 100644 +index 0000000..f854da8 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov5647.h +@@ -0,0 +1,242 @@ ++/* ++ * Copyright (c) 2012, The Linux Foundation. All rights reserved. ++ * Copyright (C) 2017 Cogent Embedded, 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 and ++ * only 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. ++ */ ++ ++//#define TEST_PATTERN ++ ++#define OV5647_WIDTH 2592 ++#define OV5647_HEIGHT 1944 ++ ++#define OV5647_CODE MEDIA_BUS_FMT_SBGGR8_1X8 ++//#define OV5647_CODE MEDIA_BUS_FMT_YUYV8_2X8 ++ ++struct regval_list { ++ uint16_t addr; ++ uint8_t data; ++}; ++ ++enum ov5647_test_mode_t { ++ TEST_OFF, ++ TEST_1, ++ TEST_2, ++ TEST_3 ++}; ++ ++struct regval_list ov5647_prev_settings[] = { ++ /*1280*960 Reference Setting 24M MCLK 2lane 280Mbps/lane 30fps ++ for back to preview*/ ++ {0x3035, 0x21}, ++ {0x3036, 0x37}, ++ {0x3821, 0x07}, ++ {0x3820, 0x41}, ++ {0x3612, 0x09}, ++ {0x3618, 0x00}, ++ {0x380c, 0x07}, ++ {0x380d, 0x68}, ++ {0x380e, 0x03}, ++ {0x380f, 0xd8}, ++ {0x3814, 0x31}, ++ {0x3815, 0x31}, ++ {0x3709, 0x52}, ++ {0x3808, 0x05}, // 1280 ++ {0x3809, 0x00}, ++ {0x380a, 0x03}, // 960 ++ {0x380b, 0xc0}, ++ {0x3800, 0x00}, ++ {0x3801, 0x18}, ++ {0x3802, 0x00}, ++ {0x3803, 0x0e}, ++ {0x3804, 0x0a}, ++ {0x3805, 0x27}, ++ {0x3806, 0x07}, ++ {0x3807, 0x95}, ++ {0x4004, 0x02}, ++}; ++struct regval_list ov5647_snap_settings[] = { ++ /*2608*1952 Reference Setting 24M MCLK 2lane 280Mbps/lane 30fps*/ ++ {0x3035, 0x21}, ++ {0x3036, 0x4f}, ++ {0x3821, 0x06}, ++ {0x3820, 0x00}, ++ {0x3612, 0x0b}, ++ {0x3618, 0x04}, ++ {0x380c, 0x0a}, ++ {0x380d, 0x8c}, ++ {0x380e, 0x07}, ++ {0x380f, 0xb0}, ++ {0x3814, 0x11}, ++ {0x3815, 0x11}, ++ {0x3709, 0x12}, ++#if 0 ++ {0x3808, 0x0a}, ++ {0x3809, 0x30}, ++ {0x380a, 0x07}, ++ {0x380b, 0xa0}, ++#else ++ {0x3808, OV5647_WIDTH >> 8}, ++ {0x3809, OV5647_WIDTH & 0xff}, ++ {0x380a, OV5647_HEIGHT >> 8}, ++ {0x380b, OV5647_HEIGHT & 0xff}, ++#endif ++ {0x3800, 0x00}, ++ {0x3801, 0x04}, ++ {0x3802, 0x00}, ++ {0x3803, 0x00}, ++ {0x3804, 0x0a}, ++ {0x3805, 0x3b}, ++ {0x3806, 0x07}, ++ {0x3807, 0xa3}, ++ {0x4004, 0x04}, ++}; ++struct regval_list ov5647_recommend_settings[] = { ++#ifdef TEST_PATTERN ++ {0x503d, 0x80}, ++#endif ++#if 0 ++ {0x4814, 0x1e}, ++ {0x4801, 0x8f}, ++#endif ++ {0x3035, 0x11}, ++ {0x303c, 0x11}, ++ {0x370c, 0x03}, ++ {0x5000, 0x06}, ++ {0x5003, 0x08}, ++ {0x5a00, 0x08}, ++ {0x3000, 0xff}, ++ {0x3001, 0xff}, ++ {0x3002, 0xff}, ++ {0x301d, 0xf0}, ++ {0x3a18, 0x00}, ++ {0x3a19, 0xf8}, ++ {0x3c01, 0x80}, ++ {0x3b07, 0x0c}, ++ {0x3708, 0x64}, ++ {0x3630, 0x2e}, ++ {0x3632, 0xe2}, ++ {0x3633, 0x23}, ++ {0x3634, 0x44}, ++ {0x3620, 0x64}, ++ {0x3621, 0xe0}, ++ {0x3600, 0x37}, ++ {0x3704, 0xa0}, ++ {0x3703, 0x5a}, ++ {0x3715, 0x78}, ++ {0x3717, 0x01}, ++ {0x3731, 0x02}, ++ {0x370b, 0x60}, ++ {0x3705, 0x1a}, ++ {0x3f05, 0x02}, ++ {0x3f06, 0x10}, ++ {0x3f01, 0x0a}, ++ {0x3a08, 0x01}, ++ {0x3a0f, 0x58}, ++ {0x3a10, 0x50}, ++ {0x3a1b, 0x58}, ++ {0x3a1e, 0x50}, ++ {0x3a11, 0x60}, ++ {0x3a1f, 0x28}, ++ {0x4001, 0x02}, ++ {0x4000, 0x09}, ++ {0x3000, 0x00}, ++ {0x3001, 0x00}, ++ {0x3002, 0x00}, ++ {0x3017, 0xe0}, ++ {0x301c, 0xfc}, ++ {0x3636, 0x06}, ++ {0x3016, 0x08}, ++ {0x3827, 0xec}, ++ {0x3018, 0x44}, ++ {0x3035, 0x21}, ++ {0x3106, 0xf5}, ++ {0x3034, 0x18}, ++ {0x301c, 0xf8}, ++ /*lens setting*/ ++ {0x5000, 0x86}, ++ {0x5800, 0x11}, ++ {0x5801, 0x0c}, ++ {0x5802, 0x0a}, ++ {0x5803, 0x0b}, ++ {0x5804, 0x0d}, ++ {0x5805, 0x13}, ++ {0x5806, 0x09}, ++ {0x5807, 0x05}, ++ {0x5808, 0x03}, ++ {0x5809, 0x03}, ++ {0x580a, 0x06}, ++ {0x580b, 0x08}, ++ {0x580c, 0x05}, ++ {0x580d, 0x01}, ++ {0x580e, 0x00}, ++ {0x580f, 0x00}, ++ {0x5810, 0x02}, ++ {0x5811, 0x06}, ++ {0x5812, 0x05}, ++ {0x5813, 0x01}, ++ {0x5814, 0x00}, ++ {0x5815, 0x00}, ++ {0x5816, 0x02}, ++ {0x5817, 0x06}, ++ {0x5818, 0x09}, ++ {0x5819, 0x05}, ++ {0x581a, 0x04}, ++ {0x581b, 0x04}, ++ {0x581c, 0x06}, ++ {0x581d, 0x09}, ++ {0x581e, 0x11}, ++ {0x581f, 0x0c}, ++ {0x5820, 0x0b}, ++ {0x5821, 0x0b}, ++ {0x5822, 0x0d}, ++ {0x5823, 0x13}, ++ {0x5824, 0x22}, ++ {0x5825, 0x26}, ++ {0x5826, 0x26}, ++ {0x5827, 0x24}, ++ {0x5828, 0x24}, ++ {0x5829, 0x24}, ++ {0x582a, 0x22}, ++ {0x582b, 0x20}, ++ {0x582c, 0x22}, ++ {0x582d, 0x26}, ++ {0x582e, 0x22}, ++ {0x582f, 0x22}, ++ {0x5830, 0x42}, ++ {0x5831, 0x22}, ++ {0x5832, 0x02}, ++ {0x5833, 0x24}, ++ {0x5834, 0x22}, ++ {0x5835, 0x22}, ++ {0x5836, 0x22}, ++ {0x5837, 0x26}, ++ {0x5838, 0x42}, ++ {0x5839, 0x26}, ++ {0x583a, 0x06}, ++ {0x583b, 0x26}, ++ {0x583c, 0x24}, ++ {0x583d, 0xce}, ++ /* manual AWB,manual AE,close Lenc,open WBC*/ ++ {0x3503, 0x03}, /*manual AE*/ ++ {0x3501, 0x10}, ++ {0x3502, 0x80}, ++ {0x350a, 0x00}, ++ {0x350b, 0x7f}, ++ {0x5001, 0x01}, /*manual AWB*/ ++ {0x5180, 0x08}, ++ {0x5186, 0x04}, ++ {0x5187, 0x00}, ++ {0x5188, 0x04}, ++ {0x5189, 0x00}, ++ {0x518a, 0x04}, ++ {0x518b, 0x00}, ++ {0x5000, 0x06}, /*No lenc,WBC on*/ ++}; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0032-media-i2c-Add-ov5642-sensor.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0032-media-i2c-Add-ov5642-sensor.patch new file mode 100644 index 00000000..8a1b53f7 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0032-media-i2c-Add-ov5642-sensor.patch @@ -0,0 +1,2155 @@ +From 989c2131d4bae27c2866d47206e2825cfd039778 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Sun, 11 Jun 2017 00:50:59 +0300 +Subject: [PATCH 024/122] media: i2c: ov5642 sensor + +Add ov5642 camera sensor driver update + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ov5642.c | 699 +++++----------------------- + drivers/media/i2c/soc_camera/ov5642.h | 592 ++++++++++++++++++++++++ + drivers/media/i2c/soc_camera/ov5642_720p.h | 711 +++++++++++++++++++++++++++++ + 3 files changed, 1409 insertions(+), 593 deletions(-) + create mode 100644 drivers/media/i2c/soc_camera/ov5642.h + create mode 100644 drivers/media/i2c/soc_camera/ov5642_720p.h + +diff --git a/drivers/media/i2c/soc_camera/ov5642.c b/drivers/media/i2c/soc_camera/ov5642.c +index 39f420d..3fa4756 100644 +--- a/drivers/media/i2c/soc_camera/ov5642.c ++++ b/drivers/media/i2c/soc_camera/ov5642.c +@@ -22,584 +22,16 @@ + #include + #include + #include ++#include ++#include ++#include + + #include + #include + #include + +-/* OV5642 registers */ +-#define REG_CHIP_ID_HIGH 0x300a +-#define REG_CHIP_ID_LOW 0x300b +- +-#define REG_WINDOW_START_X_HIGH 0x3800 +-#define REG_WINDOW_START_X_LOW 0x3801 +-#define REG_WINDOW_START_Y_HIGH 0x3802 +-#define REG_WINDOW_START_Y_LOW 0x3803 +-#define REG_WINDOW_WIDTH_HIGH 0x3804 +-#define REG_WINDOW_WIDTH_LOW 0x3805 +-#define REG_WINDOW_HEIGHT_HIGH 0x3806 +-#define REG_WINDOW_HEIGHT_LOW 0x3807 +-#define REG_OUT_WIDTH_HIGH 0x3808 +-#define REG_OUT_WIDTH_LOW 0x3809 +-#define REG_OUT_HEIGHT_HIGH 0x380a +-#define REG_OUT_HEIGHT_LOW 0x380b +-#define REG_OUT_TOTAL_WIDTH_HIGH 0x380c +-#define REG_OUT_TOTAL_WIDTH_LOW 0x380d +-#define REG_OUT_TOTAL_HEIGHT_HIGH 0x380e +-#define REG_OUT_TOTAL_HEIGHT_LOW 0x380f +-#define REG_OUTPUT_FORMAT 0x4300 +-#define REG_ISP_CTRL_01 0x5001 +-#define REG_AVG_WINDOW_END_X_HIGH 0x5682 +-#define REG_AVG_WINDOW_END_X_LOW 0x5683 +-#define REG_AVG_WINDOW_END_Y_HIGH 0x5686 +-#define REG_AVG_WINDOW_END_Y_LOW 0x5687 +- +-/* active pixel array size */ +-#define OV5642_SENSOR_SIZE_X 2592 +-#define OV5642_SENSOR_SIZE_Y 1944 +- +-/* +- * About OV5642 resolution, cropping and binning: +- * This sensor supports it all, at least in the feature description. +- * Unfortunately, no combination of appropriate registers settings could make +- * the chip work the intended way. As it works with predefined register lists, +- * some undocumented registers are presumably changed there to achieve their +- * goals. +- * This driver currently only works for resolutions up to 720 lines with a +- * 1:1 scale. Hopefully these restrictions will be removed in the future. +- */ +-#define OV5642_MAX_WIDTH OV5642_SENSOR_SIZE_X +-#define OV5642_MAX_HEIGHT 720 +- +-/* default sizes */ +-#define OV5642_DEFAULT_WIDTH 1280 +-#define OV5642_DEFAULT_HEIGHT OV5642_MAX_HEIGHT +- +-/* minimum extra blanking */ +-#define BLANKING_EXTRA_WIDTH 500 +-#define BLANKING_EXTRA_HEIGHT 20 +- +-/* +- * the sensor's autoexposure is buggy when setting total_height low. +- * It tries to expose longer than 1 frame period without taking care of it +- * and this leads to weird output. So we set 1000 lines as minimum. +- */ +-#define BLANKING_MIN_HEIGHT 1000 +- +-struct regval_list { +- u16 reg_num; +- u8 value; +-}; +- +-static struct regval_list ov5642_default_regs_init[] = { +- { 0x3103, 0x93 }, +- { 0x3008, 0x82 }, +- { 0x3017, 0x7f }, +- { 0x3018, 0xfc }, +- { 0x3810, 0xc2 }, +- { 0x3615, 0xf0 }, +- { 0x3000, 0x0 }, +- { 0x3001, 0x0 }, +- { 0x3002, 0x0 }, +- { 0x3003, 0x0 }, +- { 0x3004, 0xff }, +- { 0x3030, 0x2b }, +- { 0x3011, 0x8 }, +- { 0x3010, 0x10 }, +- { 0x3604, 0x60 }, +- { 0x3622, 0x60 }, +- { 0x3621, 0x9 }, +- { 0x3709, 0x0 }, +- { 0x4000, 0x21 }, +- { 0x401d, 0x22 }, +- { 0x3600, 0x54 }, +- { 0x3605, 0x4 }, +- { 0x3606, 0x3f }, +- { 0x3c01, 0x80 }, +- { 0x300d, 0x22 }, +- { 0x3623, 0x22 }, +- { 0x5000, 0x4f }, +- { 0x5020, 0x4 }, +- { 0x5181, 0x79 }, +- { 0x5182, 0x0 }, +- { 0x5185, 0x22 }, +- { 0x5197, 0x1 }, +- { 0x5500, 0xa }, +- { 0x5504, 0x0 }, +- { 0x5505, 0x7f }, +- { 0x5080, 0x8 }, +- { 0x300e, 0x18 }, +- { 0x4610, 0x0 }, +- { 0x471d, 0x5 }, +- { 0x4708, 0x6 }, +- { 0x370c, 0xa0 }, +- { 0x5687, 0x94 }, +- { 0x501f, 0x0 }, +- { 0x5000, 0x4f }, +- { 0x5001, 0xcf }, +- { 0x4300, 0x30 }, +- { 0x4300, 0x30 }, +- { 0x460b, 0x35 }, +- { 0x471d, 0x0 }, +- { 0x3002, 0xc }, +- { 0x3002, 0x0 }, +- { 0x4713, 0x3 }, +- { 0x471c, 0x50 }, +- { 0x4721, 0x2 }, +- { 0x4402, 0x90 }, +- { 0x460c, 0x22 }, +- { 0x3815, 0x44 }, +- { 0x3503, 0x7 }, +- { 0x3501, 0x73 }, +- { 0x3502, 0x80 }, +- { 0x350b, 0x0 }, +- { 0x3818, 0xc8 }, +- { 0x3824, 0x11 }, +- { 0x3a00, 0x78 }, +- { 0x3a1a, 0x4 }, +- { 0x3a13, 0x30 }, +- { 0x3a18, 0x0 }, +- { 0x3a19, 0x7c }, +- { 0x3a08, 0x12 }, +- { 0x3a09, 0xc0 }, +- { 0x3a0a, 0xf }, +- { 0x3a0b, 0xa0 }, +- { 0x350c, 0x7 }, +- { 0x350d, 0xd0 }, +- { 0x3a0d, 0x8 }, +- { 0x3a0e, 0x6 }, +- { 0x3500, 0x0 }, +- { 0x3501, 0x0 }, +- { 0x3502, 0x0 }, +- { 0x350a, 0x0 }, +- { 0x350b, 0x0 }, +- { 0x3503, 0x0 }, +- { 0x3a0f, 0x3c }, +- { 0x3a10, 0x32 }, +- { 0x3a1b, 0x3c }, +- { 0x3a1e, 0x32 }, +- { 0x3a11, 0x80 }, +- { 0x3a1f, 0x20 }, +- { 0x3030, 0x2b }, +- { 0x3a02, 0x0 }, +- { 0x3a03, 0x7d }, +- { 0x3a04, 0x0 }, +- { 0x3a14, 0x0 }, +- { 0x3a15, 0x7d }, +- { 0x3a16, 0x0 }, +- { 0x3a00, 0x78 }, +- { 0x3a08, 0x9 }, +- { 0x3a09, 0x60 }, +- { 0x3a0a, 0x7 }, +- { 0x3a0b, 0xd0 }, +- { 0x3a0d, 0x10 }, +- { 0x3a0e, 0xd }, +- { 0x4407, 0x4 }, +- { 0x5193, 0x70 }, +- { 0x589b, 0x0 }, +- { 0x589a, 0xc0 }, +- { 0x401e, 0x20 }, +- { 0x4001, 0x42 }, +- { 0x401c, 0x6 }, +- { 0x3825, 0xac }, +- { 0x3827, 0xc }, +- { 0x528a, 0x1 }, +- { 0x528b, 0x4 }, +- { 0x528c, 0x8 }, +- { 0x528d, 0x10 }, +- { 0x528e, 0x20 }, +- { 0x528f, 0x28 }, +- { 0x5290, 0x30 }, +- { 0x5292, 0x0 }, +- { 0x5293, 0x1 }, +- { 0x5294, 0x0 }, +- { 0x5295, 0x4 }, +- { 0x5296, 0x0 }, +- { 0x5297, 0x8 }, +- { 0x5298, 0x0 }, +- { 0x5299, 0x10 }, +- { 0x529a, 0x0 }, +- { 0x529b, 0x20 }, +- { 0x529c, 0x0 }, +- { 0x529d, 0x28 }, +- { 0x529e, 0x0 }, +- { 0x529f, 0x30 }, +- { 0x5282, 0x0 }, +- { 0x5300, 0x0 }, +- { 0x5301, 0x20 }, +- { 0x5302, 0x0 }, +- { 0x5303, 0x7c }, +- { 0x530c, 0x0 }, +- { 0x530d, 0xc }, +- { 0x530e, 0x20 }, +- { 0x530f, 0x80 }, +- { 0x5310, 0x20 }, +- { 0x5311, 0x80 }, +- { 0x5308, 0x20 }, +- { 0x5309, 0x40 }, +- { 0x5304, 0x0 }, +- { 0x5305, 0x30 }, +- { 0x5306, 0x0 }, +- { 0x5307, 0x80 }, +- { 0x5314, 0x8 }, +- { 0x5315, 0x20 }, +- { 0x5319, 0x30 }, +- { 0x5316, 0x10 }, +- { 0x5317, 0x0 }, +- { 0x5318, 0x2 }, +- { 0x5380, 0x1 }, +- { 0x5381, 0x0 }, +- { 0x5382, 0x0 }, +- { 0x5383, 0x4e }, +- { 0x5384, 0x0 }, +- { 0x5385, 0xf }, +- { 0x5386, 0x0 }, +- { 0x5387, 0x0 }, +- { 0x5388, 0x1 }, +- { 0x5389, 0x15 }, +- { 0x538a, 0x0 }, +- { 0x538b, 0x31 }, +- { 0x538c, 0x0 }, +- { 0x538d, 0x0 }, +- { 0x538e, 0x0 }, +- { 0x538f, 0xf }, +- { 0x5390, 0x0 }, +- { 0x5391, 0xab }, +- { 0x5392, 0x0 }, +- { 0x5393, 0xa2 }, +- { 0x5394, 0x8 }, +- { 0x5480, 0x14 }, +- { 0x5481, 0x21 }, +- { 0x5482, 0x36 }, +- { 0x5483, 0x57 }, +- { 0x5484, 0x65 }, +- { 0x5485, 0x71 }, +- { 0x5486, 0x7d }, +- { 0x5487, 0x87 }, +- { 0x5488, 0x91 }, +- { 0x5489, 0x9a }, +- { 0x548a, 0xaa }, +- { 0x548b, 0xb8 }, +- { 0x548c, 0xcd }, +- { 0x548d, 0xdd }, +- { 0x548e, 0xea }, +- { 0x548f, 0x1d }, +- { 0x5490, 0x5 }, +- { 0x5491, 0x0 }, +- { 0x5492, 0x4 }, +- { 0x5493, 0x20 }, +- { 0x5494, 0x3 }, +- { 0x5495, 0x60 }, +- { 0x5496, 0x2 }, +- { 0x5497, 0xb8 }, +- { 0x5498, 0x2 }, +- { 0x5499, 0x86 }, +- { 0x549a, 0x2 }, +- { 0x549b, 0x5b }, +- { 0x549c, 0x2 }, +- { 0x549d, 0x3b }, +- { 0x549e, 0x2 }, +- { 0x549f, 0x1c }, +- { 0x54a0, 0x2 }, +- { 0x54a1, 0x4 }, +- { 0x54a2, 0x1 }, +- { 0x54a3, 0xed }, +- { 0x54a4, 0x1 }, +- { 0x54a5, 0xc5 }, +- { 0x54a6, 0x1 }, +- { 0x54a7, 0xa5 }, +- { 0x54a8, 0x1 }, +- { 0x54a9, 0x6c }, +- { 0x54aa, 0x1 }, +- { 0x54ab, 0x41 }, +- { 0x54ac, 0x1 }, +- { 0x54ad, 0x20 }, +- { 0x54ae, 0x0 }, +- { 0x54af, 0x16 }, +- { 0x54b0, 0x1 }, +- { 0x54b1, 0x20 }, +- { 0x54b2, 0x0 }, +- { 0x54b3, 0x10 }, +- { 0x54b4, 0x0 }, +- { 0x54b5, 0xf0 }, +- { 0x54b6, 0x0 }, +- { 0x54b7, 0xdf }, +- { 0x5402, 0x3f }, +- { 0x5403, 0x0 }, +- { 0x3406, 0x0 }, +- { 0x5180, 0xff }, +- { 0x5181, 0x52 }, +- { 0x5182, 0x11 }, +- { 0x5183, 0x14 }, +- { 0x5184, 0x25 }, +- { 0x5185, 0x24 }, +- { 0x5186, 0x6 }, +- { 0x5187, 0x8 }, +- { 0x5188, 0x8 }, +- { 0x5189, 0x7c }, +- { 0x518a, 0x60 }, +- { 0x518b, 0xb2 }, +- { 0x518c, 0xb2 }, +- { 0x518d, 0x44 }, +- { 0x518e, 0x3d }, +- { 0x518f, 0x58 }, +- { 0x5190, 0x46 }, +- { 0x5191, 0xf8 }, +- { 0x5192, 0x4 }, +- { 0x5193, 0x70 }, +- { 0x5194, 0xf0 }, +- { 0x5195, 0xf0 }, +- { 0x5196, 0x3 }, +- { 0x5197, 0x1 }, +- { 0x5198, 0x4 }, +- { 0x5199, 0x12 }, +- { 0x519a, 0x4 }, +- { 0x519b, 0x0 }, +- { 0x519c, 0x6 }, +- { 0x519d, 0x82 }, +- { 0x519e, 0x0 }, +- { 0x5025, 0x80 }, +- { 0x3a0f, 0x38 }, +- { 0x3a10, 0x30 }, +- { 0x3a1b, 0x3a }, +- { 0x3a1e, 0x2e }, +- { 0x3a11, 0x60 }, +- { 0x3a1f, 0x10 }, +- { 0x5688, 0xa6 }, +- { 0x5689, 0x6a }, +- { 0x568a, 0xea }, +- { 0x568b, 0xae }, +- { 0x568c, 0xa6 }, +- { 0x568d, 0x6a }, +- { 0x568e, 0x62 }, +- { 0x568f, 0x26 }, +- { 0x5583, 0x40 }, +- { 0x5584, 0x40 }, +- { 0x5580, 0x2 }, +- { 0x5000, 0xcf }, +- { 0x5800, 0x27 }, +- { 0x5801, 0x19 }, +- { 0x5802, 0x12 }, +- { 0x5803, 0xf }, +- { 0x5804, 0x10 }, +- { 0x5805, 0x15 }, +- { 0x5806, 0x1e }, +- { 0x5807, 0x2f }, +- { 0x5808, 0x15 }, +- { 0x5809, 0xd }, +- { 0x580a, 0xa }, +- { 0x580b, 0x9 }, +- { 0x580c, 0xa }, +- { 0x580d, 0xc }, +- { 0x580e, 0x12 }, +- { 0x580f, 0x19 }, +- { 0x5810, 0xb }, +- { 0x5811, 0x7 }, +- { 0x5812, 0x4 }, +- { 0x5813, 0x3 }, +- { 0x5814, 0x3 }, +- { 0x5815, 0x6 }, +- { 0x5816, 0xa }, +- { 0x5817, 0xf }, +- { 0x5818, 0xa }, +- { 0x5819, 0x5 }, +- { 0x581a, 0x1 }, +- { 0x581b, 0x0 }, +- { 0x581c, 0x0 }, +- { 0x581d, 0x3 }, +- { 0x581e, 0x8 }, +- { 0x581f, 0xc }, +- { 0x5820, 0xa }, +- { 0x5821, 0x5 }, +- { 0x5822, 0x1 }, +- { 0x5823, 0x0 }, +- { 0x5824, 0x0 }, +- { 0x5825, 0x3 }, +- { 0x5826, 0x8 }, +- { 0x5827, 0xc }, +- { 0x5828, 0xe }, +- { 0x5829, 0x8 }, +- { 0x582a, 0x6 }, +- { 0x582b, 0x4 }, +- { 0x582c, 0x5 }, +- { 0x582d, 0x7 }, +- { 0x582e, 0xb }, +- { 0x582f, 0x12 }, +- { 0x5830, 0x18 }, +- { 0x5831, 0x10 }, +- { 0x5832, 0xc }, +- { 0x5833, 0xa }, +- { 0x5834, 0xb }, +- { 0x5835, 0xe }, +- { 0x5836, 0x15 }, +- { 0x5837, 0x19 }, +- { 0x5838, 0x32 }, +- { 0x5839, 0x1f }, +- { 0x583a, 0x18 }, +- { 0x583b, 0x16 }, +- { 0x583c, 0x17 }, +- { 0x583d, 0x1e }, +- { 0x583e, 0x26 }, +- { 0x583f, 0x53 }, +- { 0x5840, 0x10 }, +- { 0x5841, 0xf }, +- { 0x5842, 0xd }, +- { 0x5843, 0xc }, +- { 0x5844, 0xe }, +- { 0x5845, 0x9 }, +- { 0x5846, 0x11 }, +- { 0x5847, 0x10 }, +- { 0x5848, 0x10 }, +- { 0x5849, 0x10 }, +- { 0x584a, 0x10 }, +- { 0x584b, 0xe }, +- { 0x584c, 0x10 }, +- { 0x584d, 0x10 }, +- { 0x584e, 0x11 }, +- { 0x584f, 0x10 }, +- { 0x5850, 0xf }, +- { 0x5851, 0xc }, +- { 0x5852, 0xf }, +- { 0x5853, 0x10 }, +- { 0x5854, 0x10 }, +- { 0x5855, 0xf }, +- { 0x5856, 0xe }, +- { 0x5857, 0xb }, +- { 0x5858, 0x10 }, +- { 0x5859, 0xd }, +- { 0x585a, 0xd }, +- { 0x585b, 0xc }, +- { 0x585c, 0xc }, +- { 0x585d, 0xc }, +- { 0x585e, 0xb }, +- { 0x585f, 0xc }, +- { 0x5860, 0xc }, +- { 0x5861, 0xc }, +- { 0x5862, 0xd }, +- { 0x5863, 0x8 }, +- { 0x5864, 0x11 }, +- { 0x5865, 0x18 }, +- { 0x5866, 0x18 }, +- { 0x5867, 0x19 }, +- { 0x5868, 0x17 }, +- { 0x5869, 0x19 }, +- { 0x586a, 0x16 }, +- { 0x586b, 0x13 }, +- { 0x586c, 0x13 }, +- { 0x586d, 0x12 }, +- { 0x586e, 0x13 }, +- { 0x586f, 0x16 }, +- { 0x5870, 0x14 }, +- { 0x5871, 0x12 }, +- { 0x5872, 0x10 }, +- { 0x5873, 0x11 }, +- { 0x5874, 0x11 }, +- { 0x5875, 0x16 }, +- { 0x5876, 0x14 }, +- { 0x5877, 0x11 }, +- { 0x5878, 0x10 }, +- { 0x5879, 0xf }, +- { 0x587a, 0x10 }, +- { 0x587b, 0x14 }, +- { 0x587c, 0x13 }, +- { 0x587d, 0x12 }, +- { 0x587e, 0x11 }, +- { 0x587f, 0x11 }, +- { 0x5880, 0x12 }, +- { 0x5881, 0x15 }, +- { 0x5882, 0x14 }, +- { 0x5883, 0x15 }, +- { 0x5884, 0x15 }, +- { 0x5885, 0x15 }, +- { 0x5886, 0x13 }, +- { 0x5887, 0x17 }, +- { 0x3710, 0x10 }, +- { 0x3632, 0x51 }, +- { 0x3702, 0x10 }, +- { 0x3703, 0xb2 }, +- { 0x3704, 0x18 }, +- { 0x370b, 0x40 }, +- { 0x370d, 0x3 }, +- { 0x3631, 0x1 }, +- { 0x3632, 0x52 }, +- { 0x3606, 0x24 }, +- { 0x3620, 0x96 }, +- { 0x5785, 0x7 }, +- { 0x3a13, 0x30 }, +- { 0x3600, 0x52 }, +- { 0x3604, 0x48 }, +- { 0x3606, 0x1b }, +- { 0x370d, 0xb }, +- { 0x370f, 0xc0 }, +- { 0x3709, 0x1 }, +- { 0x3823, 0x0 }, +- { 0x5007, 0x0 }, +- { 0x5009, 0x0 }, +- { 0x5011, 0x0 }, +- { 0x5013, 0x0 }, +- { 0x519e, 0x0 }, +- { 0x5086, 0x0 }, +- { 0x5087, 0x0 }, +- { 0x5088, 0x0 }, +- { 0x5089, 0x0 }, +- { 0x302b, 0x0 }, +- { 0x3503, 0x7 }, +- { 0x3011, 0x8 }, +- { 0x350c, 0x2 }, +- { 0x350d, 0xe4 }, +- { 0x3621, 0xc9 }, +- { 0x370a, 0x81 }, +- { 0xffff, 0xff }, +-}; +- +-static struct regval_list ov5642_default_regs_finalise[] = { +- { 0x3810, 0xc2 }, +- { 0x3818, 0xc9 }, +- { 0x381c, 0x10 }, +- { 0x381d, 0xa0 }, +- { 0x381e, 0x5 }, +- { 0x381f, 0xb0 }, +- { 0x3820, 0x0 }, +- { 0x3821, 0x0 }, +- { 0x3824, 0x11 }, +- { 0x3a08, 0x1b }, +- { 0x3a09, 0xc0 }, +- { 0x3a0a, 0x17 }, +- { 0x3a0b, 0x20 }, +- { 0x3a0d, 0x2 }, +- { 0x3a0e, 0x1 }, +- { 0x401c, 0x4 }, +- { 0x5682, 0x5 }, +- { 0x5683, 0x0 }, +- { 0x5686, 0x2 }, +- { 0x5687, 0xcc }, +- { 0x5001, 0x4f }, +- { 0x589b, 0x6 }, +- { 0x589a, 0xc5 }, +- { 0x3503, 0x0 }, +- { 0x460c, 0x20 }, +- { 0x460b, 0x37 }, +- { 0x471c, 0xd0 }, +- { 0x471d, 0x5 }, +- { 0x3815, 0x1 }, +- { 0x3818, 0xc1 }, +- { 0x501f, 0x0 }, +- { 0x5002, 0xe0 }, +- { 0x4300, 0x32 }, /* UYVY */ +- { 0x3002, 0x1c }, +- { 0x4800, 0x14 }, +- { 0x4801, 0xf }, +- { 0x3007, 0x3b }, +- { 0x300e, 0x4 }, +- { 0x4803, 0x50 }, +- { 0x3815, 0x1 }, +- { 0x4713, 0x2 }, +- { 0x4842, 0x1 }, +- { 0x300f, 0xe }, +- { 0x3003, 0x3 }, +- { 0x3003, 0x1 }, +- { 0xffff, 0xff }, +-}; ++#define USE_PREDEF ++#include "ov5642.h" + + struct ov5642_datafmt { + u32 code; +@@ -608,6 +40,7 @@ struct ov5642_datafmt { + + struct ov5642 { + struct v4l2_subdev subdev; ++ struct media_pad pad; + const struct ov5642_datafmt *fmt; + struct v4l2_rect crop_rect; + struct v4l2_clk *clk; +@@ -615,10 +48,14 @@ struct ov5642 { + /* blanking information */ + int total_width; + int total_height; ++ ++ struct soc_camera_subdev_desc ssdd_dt; ++ struct gpio_desc *resetb_gpio; ++ struct gpio_desc *pwdn_gpio; + }; + + static const struct ov5642_datafmt ov5642_colour_fmts[] = { +- {MEDIA_BUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG}, ++ {MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG}, + }; + + static struct ov5642 *to_ov5642(const struct i2c_client *client) +@@ -676,10 +113,7 @@ static int reg_write(struct i2c_client *client, u16 reg, u8 val) + return 0; + } + +-/* +- * convenience function to write 16 bit register values that are split up +- * into two consecutive high and low parts +- */ ++#if 0 + static int reg_write16(struct i2c_client *client, u16 reg, u16 val16) + { + int ret; +@@ -689,6 +123,7 @@ static int reg_write16(struct i2c_client *client, u16 reg, u16 val16) + return ret; + return reg_write(client, reg + 1, val16 & 0x00ff); + } ++#endif + + #ifdef CONFIG_VIDEO_ADV_DEBUG + static int ov5642_get_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) +@@ -733,6 +168,7 @@ static int ov5642_write_array(struct i2c_client *client, + return 0; + } + ++#ifndef USE_PREDEF + static int ov5642_set_resolution(struct v4l2_subdev *sd) + { + struct i2c_client *client = v4l2_get_subdevdata(sd); +@@ -785,6 +221,7 @@ static int ov5642_set_resolution(struct v4l2_subdev *sd) + + return ret; + } ++#endif + + static int ov5642_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, +@@ -872,15 +309,15 @@ static int ov5642_set_selection(struct v4l2_subdev *sd, + priv->total_height = max_t(int, rect.height + + BLANKING_EXTRA_HEIGHT, + BLANKING_MIN_HEIGHT); +- priv->crop_rect.width = rect.width; +- priv->crop_rect.height = rect.height; +- ++#ifdef USE_PREDEF ++ ret = ov5642_write_array(client, OV5642_720P_30FPS); ++#else + ret = ov5642_write_array(client, ov5642_default_regs_init); + if (!ret) + ret = ov5642_set_resolution(sd); + if (!ret) + ret = ov5642_write_array(client, ov5642_default_regs_finalise); +- ++#endif + return ret; + } + +@@ -913,10 +350,10 @@ static int ov5642_get_selection(struct v4l2_subdev *sd, + static int ov5642_g_mbus_config(struct v4l2_subdev *sd, + struct v4l2_mbus_config *cfg) + { +- cfg->type = V4L2_MBUS_CSI2; +- cfg->flags = V4L2_MBUS_CSI2_2_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | +- V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; +- ++ cfg->type = V4L2_MBUS_PARALLEL; ++ cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING | ++ V4L2_MBUS_HSYNC_ACTIVE_LOW | V4L2_MBUS_VSYNC_ACTIVE_HIGH | ++ V4L2_MBUS_DATA_ACTIVE_HIGH; + return 0; + } + +@@ -934,12 +371,15 @@ static int ov5642_s_power(struct v4l2_subdev *sd, int on) + if (ret < 0) + return ret; + ++#ifdef USE_PREDEF ++ ret = ov5642_write_array(client, OV5642_720P_30FPS); ++#else + ret = ov5642_write_array(client, ov5642_default_regs_init); + if (!ret) + ret = ov5642_set_resolution(sd); + if (!ret) + ret = ov5642_write_array(client, ov5642_default_regs_finalise); +- ++#endif + return ret; + } + +@@ -969,6 +409,63 @@ static const struct v4l2_subdev_ops ov5642_subdev_ops = { + .pad = &ov5642_subdev_pad_ops, + }; + ++/* OF probe functions */ ++static int ov5642_hw_power(struct device *dev, int on) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct ov5642 *priv = to_ov5642(client); ++ ++ dev_dbg(&client->dev, "%s: %s the camera\n", ++ __func__, on ? "ENABLE" : "DISABLE"); ++ ++ if (priv->pwdn_gpio) ++ gpiod_direction_output(priv->pwdn_gpio, !on); ++ ++ return 0; ++} ++ ++static int ov5642_hw_reset(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct ov5642 *priv = to_ov5642(client); ++ ++ if (priv->resetb_gpio) { ++ /* Active the resetb pin to perform a reset pulse */ ++ gpiod_direction_output(priv->resetb_gpio, 1); ++ usleep_range(3000, 5000); ++ gpiod_direction_output(priv->resetb_gpio, 0); ++ } ++ ++ return 0; ++} ++ ++static int ov5642_probe_dt(struct i2c_client *client, ++ struct ov5642 *priv) ++{ ++ /* Request the reset GPIO deasserted */ ++ priv->resetb_gpio = devm_gpiod_get_optional(&client->dev, "resetb", ++ GPIOD_OUT_LOW); ++ if (!priv->resetb_gpio) ++ dev_dbg(&client->dev, "resetb gpio is not assigned!\n"); ++ else if (IS_ERR(priv->resetb_gpio)) ++ return PTR_ERR(priv->resetb_gpio); ++ ++ /* Request the power down GPIO asserted */ ++ priv->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "pwdn", ++ GPIOD_OUT_HIGH); ++ if (!priv->pwdn_gpio) ++ dev_dbg(&client->dev, "pwdn gpio is not assigned!\n"); ++ else if (IS_ERR(priv->pwdn_gpio)) ++ return PTR_ERR(priv->pwdn_gpio); ++ ++ /* Initialize the soc_camera_subdev_desc */ ++ priv->ssdd_dt.power = ov5642_hw_power; ++ priv->ssdd_dt.reset = ov5642_hw_reset; ++ client->dev.platform_data = &priv->ssdd_dt; ++ ++ return 0; ++} ++ + static int ov5642_video_probe(struct i2c_client *client) + { + struct v4l2_subdev *subdev = i2c_get_clientdata(client); +@@ -1011,19 +508,23 @@ static int ov5642_probe(struct i2c_client *client, + const struct i2c_device_id *did) + { + struct ov5642 *priv; ++ struct v4l2_subdev *sd; + struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + int ret; + +- if (!ssdd) { +- dev_err(&client->dev, "OV5642: missing platform data!\n"); +- return -EINVAL; +- } +- + priv = devm_kzalloc(&client->dev, sizeof(struct ov5642), GFP_KERNEL); + if (!priv) + return -ENOMEM; + ++ if (!ssdd) { ++ ret = ov5642_probe_dt(client, priv); ++ if (ret) ++ return ret; ++ } ++ ++ sd = &priv->subdev; + v4l2_i2c_subdev_init(&priv->subdev, client, &ov5642_subdev_ops); ++ priv->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + + priv->fmt = &ov5642_colour_fmts[0]; + +@@ -1039,8 +540,20 @@ static int ov5642_probe(struct i2c_client *client, + return PTR_ERR(priv->clk); + + ret = ov5642_video_probe(client); +- if (ret < 0) ++ if (ret < 0) { + v4l2_clk_put(priv->clk); ++ return ret; ++ } ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&sd->entity, 1, &priv->pad); ++ if (ret < 0) ++ return ret; ++ ++ ret = v4l2_async_register_subdev(sd); ++ if (ret < 0) ++ media_entity_cleanup(&sd->entity); + + return ret; + } +diff --git a/drivers/media/i2c/soc_camera/ov5642.h b/drivers/media/i2c/soc_camera/ov5642.h +new file mode 100644 +index 0000000..ac47a16 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov5642.h +@@ -0,0 +1,592 @@ ++#ifndef _OV5642_H_ ++#define _OV5642_H_ ++ ++ ++/* OV5642 registers */ ++#define REG_CHIP_ID_HIGH 0x300a ++#define REG_CHIP_ID_LOW 0x300b ++ ++#define REG_WINDOW_START_X_HIGH 0x3800 ++#define REG_WINDOW_START_X_LOW 0x3801 ++#define REG_WINDOW_START_Y_HIGH 0x3802 ++#define REG_WINDOW_START_Y_LOW 0x3803 ++#define REG_WINDOW_WIDTH_HIGH 0x3804 ++#define REG_WINDOW_WIDTH_LOW 0x3805 ++#define REG_WINDOW_HEIGHT_HIGH 0x3806 ++#define REG_WINDOW_HEIGHT_LOW 0x3807 ++#define REG_OUT_WIDTH_HIGH 0x3808 ++#define REG_OUT_WIDTH_LOW 0x3809 ++#define REG_OUT_HEIGHT_HIGH 0x380a ++#define REG_OUT_HEIGHT_LOW 0x380b ++#define REG_OUT_TOTAL_WIDTH_HIGH 0x380c ++#define REG_OUT_TOTAL_WIDTH_LOW 0x380d ++#define REG_OUT_TOTAL_HEIGHT_HIGH 0x380e ++#define REG_OUT_TOTAL_HEIGHT_LOW 0x380f ++#define REG_OUTPUT_FORMAT 0x4300 ++#define REG_ISP_CTRL_00 0x5000 ++#define REG_ISP_CTRL_01 0x5001 ++#define REG_AVG_WINDOW_START_X_HIGH 0x5680 ++#define REG_AVG_WINDOW_START_X_LOW 0x5681 ++#define REG_AVG_WINDOW_END_X_HIGH 0x5682 ++#define REG_AVG_WINDOW_END_X_LOW 0x5683 ++#define REG_AVG_WINDOW_START_Y_HIGH 0x5684 ++#define REG_AVG_WINDOW_START_Y_LOW 0x5685 ++#define REG_AVG_WINDOW_END_Y_HIGH 0x5686 ++#define REG_AVG_WINDOW_END_Y_LOW 0x5687 ++ ++/* active pixel array size */ ++#define OV5642_SENSOR_SIZE_X 2592 ++#define OV5642_SENSOR_SIZE_Y 1944 ++ ++/* ++ * About OV5642 resolution, cropping and binning: ++ * This sensor supports it all, at least in the feature description. ++ * Unfortunately, no combination of appropriate registers settings could make ++ * the chip work the intended way. As it works with predefined register lists, ++ * some undocumented registers are presumably changed there to achieve their ++ * goals. ++ * This driver currently only works for resolutions up to 720 lines with a ++ * 1:1 scale. Hopefully these restrictions will be removed in the future. ++ */ ++#define OV5642_MAX_WIDTH OV5642_SENSOR_SIZE_X ++#define OV5642_MAX_HEIGHT 720 ++ ++/* default sizes */ ++#define OV5642_DEFAULT_WIDTH 1280 ++#define OV5642_DEFAULT_HEIGHT OV5642_MAX_HEIGHT ++ ++/* minimum extra blanking */ ++#define BLANKING_EXTRA_WIDTH 500 ++#define BLANKING_EXTRA_HEIGHT 20 ++ ++/* ++ * the sensor's autoexposure is buggy when setting total_height low. ++ * It tries to expose longer than 1 frame period without taking care of it ++ * and this leads to weird output. So we set 1000 lines as minimum. ++ */ ++#define BLANKING_MIN_HEIGHT 1000 ++ ++struct regval_list { ++ u16 reg_num; ++ u8 value; ++}; ++ ++#ifdef USE_PREDEF ++ #include "ov5642_720p.h" ++#endif ++ ++#ifndef USE_PREDEF ++ ++static struct regval_list ov5642_default_regs_init[] = { ++ { 0x3103, 0x93 }, ++ { 0x3008, 0x82 }, ++ { 0x3017, 0x7f }, ++ { 0x3018, 0xfc }, ++ { 0x3810, 0xc2 }, ++ { 0x3615, 0xf0 }, ++ { 0x3000, 0x0 }, ++ { 0x3001, 0x0 }, ++ { 0x3002, 0x0 }, ++ { 0x3003, 0x0 }, ++ { 0x3004, 0xff }, ++ { 0x3030, 0x2b }, ++ { 0x3011, 0x8 }, ++ { 0x3010, 0x10 }, ++ { 0x3604, 0x60 }, ++ { 0x3622, 0x60 }, ++ { 0x3621, 0x9 }, ++ { 0x3709, 0x0 }, ++ { 0x4000, 0x21 }, ++ { 0x401d, 0x22 }, ++ { 0x3600, 0x54 }, ++ { 0x3605, 0x4 }, ++ { 0x3606, 0x3f }, ++ { 0x3c01, 0x80 }, ++ { 0x300d, 0x22 }, ++ { 0x3623, 0x22 }, ++ { 0x5000, 0x4f }, ++ { 0x5020, 0x4 }, ++ { 0x5181, 0x79 }, ++ { 0x5182, 0x0 }, ++ { 0x5185, 0x22 }, ++ { 0x5197, 0x1 }, ++ { 0x5500, 0xa }, ++ { 0x5504, 0x0 }, ++ { 0x5505, 0x7f }, ++ { 0x5080, 0x8 }, ++ { 0x300e, 0x18 }, ++ { 0x4610, 0x0 }, ++ { 0x471d, 0x5 }, ++ { 0x4708, 0x6 }, ++ { 0x370c, 0xa0 }, ++ { 0x5687, 0x94 }, ++ { 0x501f, 0x0 }, ++ { 0x5000, 0x4f }, ++ { 0x5001, 0xcf }, ++ { 0x4300, 0x30 }, ++ { 0x4300, 0x30 }, ++ { 0x460b, 0x35 }, ++ { 0x471d, 0x0 }, ++ { 0x3002, 0xc }, ++ { 0x3002, 0x0 }, ++ { 0x4713, 0x3 }, ++ { 0x471c, 0x50 }, ++ { 0x4721, 0x2 }, ++ { 0x4402, 0x90 }, ++ { 0x460c, 0x22 }, ++ { 0x3815, 0x44 }, ++ { 0x3503, 0x7 }, ++ { 0x3501, 0x73 }, ++ { 0x3502, 0x80 }, ++ { 0x350b, 0x0 }, ++ { 0x3818, 0xc8 }, ++ { 0x3824, 0x11 }, ++ { 0x3a00, 0x78 }, ++ { 0x3a1a, 0x4 }, ++ { 0x3a13, 0x30 }, ++ { 0x3a18, 0x0 }, ++ { 0x3a19, 0x7c }, ++ { 0x3a08, 0x12 }, ++ { 0x3a09, 0xc0 }, ++ { 0x3a0a, 0xf }, ++ { 0x3a0b, 0xa0 }, ++ { 0x350c, 0x7 }, ++ { 0x350d, 0xd0 }, ++ { 0x3a0d, 0x8 }, ++ { 0x3a0e, 0x6 }, ++ { 0x3500, 0x0 }, ++ { 0x3501, 0x0 }, ++ { 0x3502, 0x0 }, ++ { 0x350a, 0x0 }, ++ { 0x350b, 0x0 }, ++ { 0x3503, 0x0 }, ++ { 0x3a0f, 0x3c }, ++ { 0x3a10, 0x32 }, ++ { 0x3a1b, 0x3c }, ++ { 0x3a1e, 0x32 }, ++ { 0x3a11, 0x80 }, ++ { 0x3a1f, 0x20 }, ++ { 0x3030, 0x2b }, ++ { 0x3a02, 0x0 }, ++ { 0x3a03, 0x7d }, ++ { 0x3a04, 0x0 }, ++ { 0x3a14, 0x0 }, ++ { 0x3a15, 0x7d }, ++ { 0x3a16, 0x0 }, ++ { 0x3a00, 0x78 }, ++ { 0x3a08, 0x9 }, ++ { 0x3a09, 0x60 }, ++ { 0x3a0a, 0x7 }, ++ { 0x3a0b, 0xd0 }, ++ { 0x3a0d, 0x10 }, ++ { 0x3a0e, 0xd }, ++ { 0x4407, 0x4 }, ++ { 0x5193, 0x70 }, ++ { 0x589b, 0x0 }, ++ { 0x589a, 0xc0 }, ++ { 0x401e, 0x20 }, ++ { 0x4001, 0x42 }, ++ { 0x401c, 0x6 }, ++ { 0x3825, 0xac }, ++ { 0x3827, 0xc }, ++ { 0x528a, 0x1 }, ++ { 0x528b, 0x4 }, ++ { 0x528c, 0x8 }, ++ { 0x528d, 0x10 }, ++ { 0x528e, 0x20 }, ++ { 0x528f, 0x28 }, ++ { 0x5290, 0x30 }, ++ { 0x5292, 0x0 }, ++ { 0x5293, 0x1 }, ++ { 0x5294, 0x0 }, ++ { 0x5295, 0x4 }, ++ { 0x5296, 0x0 }, ++ { 0x5297, 0x8 }, ++ { 0x5298, 0x0 }, ++ { 0x5299, 0x10 }, ++ { 0x529a, 0x0 }, ++ { 0x529b, 0x20 }, ++ { 0x529c, 0x0 }, ++ { 0x529d, 0x28 }, ++ { 0x529e, 0x0 }, ++ { 0x529f, 0x30 }, ++ { 0x5282, 0x0 }, ++ { 0x5300, 0x0 }, ++ { 0x5301, 0x20 }, ++ { 0x5302, 0x0 }, ++ { 0x5303, 0x7c }, ++ { 0x530c, 0x0 }, ++ { 0x530d, 0xc }, ++ { 0x530e, 0x20 }, ++ { 0x530f, 0x80 }, ++ { 0x5310, 0x20 }, ++ { 0x5311, 0x80 }, ++ { 0x5308, 0x20 }, ++ { 0x5309, 0x40 }, ++ { 0x5304, 0x0 }, ++ { 0x5305, 0x30 }, ++ { 0x5306, 0x0 }, ++ { 0x5307, 0x80 }, ++ { 0x5314, 0x8 }, ++ { 0x5315, 0x20 }, ++ { 0x5319, 0x30 }, ++ { 0x5316, 0x10 }, ++ { 0x5317, 0x0 }, ++ { 0x5318, 0x2 }, ++ { 0x5380, 0x1 }, ++ { 0x5381, 0x0 }, ++ { 0x5382, 0x0 }, ++ { 0x5383, 0x4e }, ++ { 0x5384, 0x0 }, ++ { 0x5385, 0xf }, ++ { 0x5386, 0x0 }, ++ { 0x5387, 0x0 }, ++ { 0x5388, 0x1 }, ++ { 0x5389, 0x15 }, ++ { 0x538a, 0x0 }, ++ { 0x538b, 0x31 }, ++ { 0x538c, 0x0 }, ++ { 0x538d, 0x0 }, ++ { 0x538e, 0x0 }, ++ { 0x538f, 0xf }, ++ { 0x5390, 0x0 }, ++ { 0x5391, 0xab }, ++ { 0x5392, 0x0 }, ++ { 0x5393, 0xa2 }, ++ { 0x5394, 0x8 }, ++ { 0x5480, 0x14 }, ++ { 0x5481, 0x21 }, ++ { 0x5482, 0x36 }, ++ { 0x5483, 0x57 }, ++ { 0x5484, 0x65 }, ++ { 0x5485, 0x71 }, ++ { 0x5486, 0x7d }, ++ { 0x5487, 0x87 }, ++ { 0x5488, 0x91 }, ++ { 0x5489, 0x9a }, ++ { 0x548a, 0xaa }, ++ { 0x548b, 0xb8 }, ++ { 0x548c, 0xcd }, ++ { 0x548d, 0xdd }, ++ { 0x548e, 0xea }, ++ { 0x548f, 0x1d }, ++ { 0x5490, 0x5 }, ++ { 0x5491, 0x0 }, ++ { 0x5492, 0x4 }, ++ { 0x5493, 0x20 }, ++ { 0x5494, 0x3 }, ++ { 0x5495, 0x60 }, ++ { 0x5496, 0x2 }, ++ { 0x5497, 0xb8 }, ++ { 0x5498, 0x2 }, ++ { 0x5499, 0x86 }, ++ { 0x549a, 0x2 }, ++ { 0x549b, 0x5b }, ++ { 0x549c, 0x2 }, ++ { 0x549d, 0x3b }, ++ { 0x549e, 0x2 }, ++ { 0x549f, 0x1c }, ++ { 0x54a0, 0x2 }, ++ { 0x54a1, 0x4 }, ++ { 0x54a2, 0x1 }, ++ { 0x54a3, 0xed }, ++ { 0x54a4, 0x1 }, ++ { 0x54a5, 0xc5 }, ++ { 0x54a6, 0x1 }, ++ { 0x54a7, 0xa5 }, ++ { 0x54a8, 0x1 }, ++ { 0x54a9, 0x6c }, ++ { 0x54aa, 0x1 }, ++ { 0x54ab, 0x41 }, ++ { 0x54ac, 0x1 }, ++ { 0x54ad, 0x20 }, ++ { 0x54ae, 0x0 }, ++ { 0x54af, 0x16 }, ++ { 0x54b0, 0x1 }, ++ { 0x54b1, 0x20 }, ++ { 0x54b2, 0x0 }, ++ { 0x54b3, 0x10 }, ++ { 0x54b4, 0x0 }, ++ { 0x54b5, 0xf0 }, ++ { 0x54b6, 0x0 }, ++ { 0x54b7, 0xdf }, ++ { 0x5402, 0x3f }, ++ { 0x5403, 0x0 }, ++ { 0x3406, 0x0 }, ++ { 0x5180, 0xff }, ++ { 0x5181, 0x52 }, ++ { 0x5182, 0x11 }, ++ { 0x5183, 0x14 }, ++ { 0x5184, 0x25 }, ++ { 0x5185, 0x24 }, ++ { 0x5186, 0x6 }, ++ { 0x5187, 0x8 }, ++ { 0x5188, 0x8 }, ++ { 0x5189, 0x7c }, ++ { 0x518a, 0x60 }, ++ { 0x518b, 0xb2 }, ++ { 0x518c, 0xb2 }, ++ { 0x518d, 0x44 }, ++ { 0x518e, 0x3d }, ++ { 0x518f, 0x58 }, ++ { 0x5190, 0x46 }, ++ { 0x5191, 0xf8 }, ++ { 0x5192, 0x4 }, ++ { 0x5193, 0x70 }, ++ { 0x5194, 0xf0 }, ++ { 0x5195, 0xf0 }, ++ { 0x5196, 0x3 }, ++ { 0x5197, 0x1 }, ++ { 0x5198, 0x4 }, ++ { 0x5199, 0x12 }, ++ { 0x519a, 0x4 }, ++ { 0x519b, 0x0 }, ++ { 0x519c, 0x6 }, ++ { 0x519d, 0x82 }, ++ { 0x519e, 0x0 }, ++ { 0x5025, 0x80 }, ++ { 0x3a0f, 0x38 }, ++ { 0x3a10, 0x30 }, ++ { 0x3a1b, 0x3a }, ++ { 0x3a1e, 0x2e }, ++ { 0x3a11, 0x60 }, ++ { 0x3a1f, 0x10 }, ++ { 0x5688, 0xa6 }, ++ { 0x5689, 0x6a }, ++ { 0x568a, 0xea }, ++ { 0x568b, 0xae }, ++ { 0x568c, 0xa6 }, ++ { 0x568d, 0x6a }, ++ { 0x568e, 0x62 }, ++ { 0x568f, 0x26 }, ++ { 0x5583, 0x40 }, ++ { 0x5584, 0x40 }, ++ { 0x5580, 0x2 }, ++ { 0x5000, 0xcf }, ++ { 0x5800, 0x27 }, ++ { 0x5801, 0x19 }, ++ { 0x5802, 0x12 }, ++ { 0x5803, 0xf }, ++ { 0x5804, 0x10 }, ++ { 0x5805, 0x15 }, ++ { 0x5806, 0x1e }, ++ { 0x5807, 0x2f }, ++ { 0x5808, 0x15 }, ++ { 0x5809, 0xd }, ++ { 0x580a, 0xa }, ++ { 0x580b, 0x9 }, ++ { 0x580c, 0xa }, ++ { 0x580d, 0xc }, ++ { 0x580e, 0x12 }, ++ { 0x580f, 0x19 }, ++ { 0x5810, 0xb }, ++ { 0x5811, 0x7 }, ++ { 0x5812, 0x4 }, ++ { 0x5813, 0x3 }, ++ { 0x5814, 0x3 }, ++ { 0x5815, 0x6 }, ++ { 0x5816, 0xa }, ++ { 0x5817, 0xf }, ++ { 0x5818, 0xa }, ++ { 0x5819, 0x5 }, ++ { 0x581a, 0x1 }, ++ { 0x581b, 0x0 }, ++ { 0x581c, 0x0 }, ++ { 0x581d, 0x3 }, ++ { 0x581e, 0x8 }, ++ { 0x581f, 0xc }, ++ { 0x5820, 0xa }, ++ { 0x5821, 0x5 }, ++ { 0x5822, 0x1 }, ++ { 0x5823, 0x0 }, ++ { 0x5824, 0x0 }, ++ { 0x5825, 0x3 }, ++ { 0x5826, 0x8 }, ++ { 0x5827, 0xc }, ++ { 0x5828, 0xe }, ++ { 0x5829, 0x8 }, ++ { 0x582a, 0x6 }, ++ { 0x582b, 0x4 }, ++ { 0x582c, 0x5 }, ++ { 0x582d, 0x7 }, ++ { 0x582e, 0xb }, ++ { 0x582f, 0x12 }, ++ { 0x5830, 0x18 }, ++ { 0x5831, 0x10 }, ++ { 0x5832, 0xc }, ++ { 0x5833, 0xa }, ++ { 0x5834, 0xb }, ++ { 0x5835, 0xe }, ++ { 0x5836, 0x15 }, ++ { 0x5837, 0x19 }, ++ { 0x5838, 0x32 }, ++ { 0x5839, 0x1f }, ++ { 0x583a, 0x18 }, ++ { 0x583b, 0x16 }, ++ { 0x583c, 0x17 }, ++ { 0x583d, 0x1e }, ++ { 0x583e, 0x26 }, ++ { 0x583f, 0x53 }, ++ { 0x5840, 0x10 }, ++ { 0x5841, 0xf }, ++ { 0x5842, 0xd }, ++ { 0x5843, 0xc }, ++ { 0x5844, 0xe }, ++ { 0x5845, 0x9 }, ++ { 0x5846, 0x11 }, ++ { 0x5847, 0x10 }, ++ { 0x5848, 0x10 }, ++ { 0x5849, 0x10 }, ++ { 0x584a, 0x10 }, ++ { 0x584b, 0xe }, ++ { 0x584c, 0x10 }, ++ { 0x584d, 0x10 }, ++ { 0x584e, 0x11 }, ++ { 0x584f, 0x10 }, ++ { 0x5850, 0xf }, ++ { 0x5851, 0xc }, ++ { 0x5852, 0xf }, ++ { 0x5853, 0x10 }, ++ { 0x5854, 0x10 }, ++ { 0x5855, 0xf }, ++ { 0x5856, 0xe }, ++ { 0x5857, 0xb }, ++ { 0x5858, 0x10 }, ++ { 0x5859, 0xd }, ++ { 0x585a, 0xd }, ++ { 0x585b, 0xc }, ++ { 0x585c, 0xc }, ++ { 0x585d, 0xc }, ++ { 0x585e, 0xb }, ++ { 0x585f, 0xc }, ++ { 0x5860, 0xc }, ++ { 0x5861, 0xc }, ++ { 0x5862, 0xd }, ++ { 0x5863, 0x8 }, ++ { 0x5864, 0x11 }, ++ { 0x5865, 0x18 }, ++ { 0x5866, 0x18 }, ++ { 0x5867, 0x19 }, ++ { 0x5868, 0x17 }, ++ { 0x5869, 0x19 }, ++ { 0x586a, 0x16 }, ++ { 0x586b, 0x13 }, ++ { 0x586c, 0x13 }, ++ { 0x586d, 0x12 }, ++ { 0x586e, 0x13 }, ++ { 0x586f, 0x16 }, ++ { 0x5870, 0x14 }, ++ { 0x5871, 0x12 }, ++ { 0x5872, 0x10 }, ++ { 0x5873, 0x11 }, ++ { 0x5874, 0x11 }, ++ { 0x5875, 0x16 }, ++ { 0x5876, 0x14 }, ++ { 0x5877, 0x11 }, ++ { 0x5878, 0x10 }, ++ { 0x5879, 0xf }, ++ { 0x587a, 0x10 }, ++ { 0x587b, 0x14 }, ++ { 0x587c, 0x13 }, ++ { 0x587d, 0x12 }, ++ { 0x587e, 0x11 }, ++ { 0x587f, 0x11 }, ++ { 0x5880, 0x12 }, ++ { 0x5881, 0x15 }, ++ { 0x5882, 0x14 }, ++ { 0x5883, 0x15 }, ++ { 0x5884, 0x15 }, ++ { 0x5885, 0x15 }, ++ { 0x5886, 0x13 }, ++ { 0x5887, 0x17 }, ++ { 0x3710, 0x10 }, ++ { 0x3632, 0x51 }, ++ { 0x3702, 0x10 }, ++ { 0x3703, 0xb2 }, ++ { 0x3704, 0x18 }, ++ { 0x370b, 0x40 }, ++ { 0x370d, 0x3 }, ++ { 0x3631, 0x1 }, ++ { 0x3632, 0x52 }, ++ { 0x3606, 0x24 }, ++ { 0x3620, 0x96 }, ++ { 0x5785, 0x7 }, ++ { 0x3a13, 0x30 }, ++ { 0x3600, 0x52 }, ++ { 0x3604, 0x48 }, ++ { 0x3606, 0x1b }, ++ { 0x370d, 0xb }, ++ { 0x370f, 0xc0 }, ++ { 0x3709, 0x1 }, ++ { 0x3823, 0x0 }, ++ { 0x5007, 0x0 }, ++ { 0x5009, 0x0 }, ++ { 0x5011, 0x0 }, ++ { 0x5013, 0x0 }, ++ { 0x519e, 0x0 }, ++ { 0x5086, 0x0 }, ++ { 0x5087, 0x0 }, ++ { 0x5088, 0x0 }, ++ { 0x5089, 0x0 }, ++ { 0x302b, 0x0 }, ++ { 0x3503, 0x7 }, ++ { 0x3011, 0x8 }, ++ { 0x350c, 0x2 }, ++ { 0x350d, 0xe4 }, ++ { 0x3621, 0xc9 }, ++ { 0x370a, 0x81 }, ++ { 0xffff, 0xff }, ++}; ++ ++static struct regval_list ov5642_default_regs_finalise[] = { ++ { 0x3810, 0xc2 }, ++ { 0x3818, 0xc9 }, ++ { 0x381c, 0x10 }, ++ { 0x381d, 0xa0 }, ++ { 0x381e, 0x5 }, ++ { 0x381f, 0xb0 }, ++ { 0x3820, 0x0 }, ++ { 0x3821, 0x0 }, ++ { 0x3824, 0x11 }, ++ { 0x3a08, 0x1b }, ++ { 0x3a09, 0xc0 }, ++ { 0x3a0a, 0x17 }, ++ { 0x3a0b, 0x20 }, ++ { 0x3a0d, 0x2 }, ++ { 0x3a0e, 0x1 }, ++ { 0x401c, 0x4 }, ++ { 0x5682, 0x5 }, ++ { 0x5683, 0x0 }, ++ { 0x5686, 0x2 }, ++ { 0x5687, 0xcc }, ++ { 0x5001, 0x4f }, ++ { 0x589b, 0x6 }, ++ { 0x589a, 0xc5 }, ++ { 0x3503, 0x0 }, ++ { 0x460c, 0x20 }, ++ { 0x460b, 0x37 }, ++ { 0x471c, 0xd0 }, ++ { 0x471d, 0x5 }, ++ { 0x3815, 0x1 }, ++ { 0x3818, 0xc1 }, ++ { 0x501f, 0x0 }, ++ { 0x5002, 0xe0 }, ++ { 0x4300, 0x32 }, /* UYVY */ ++ { 0x3002, 0x1c }, ++ { 0x4800, 0x14 }, ++ { 0x4801, 0xf }, ++ { 0x3007, 0x3b }, ++ { 0x300e, 0x4 }, ++ { 0x4803, 0x50 }, ++ { 0x3815, 0x1 }, ++ { 0x4713, 0x2 }, ++ { 0x4842, 0x1 }, ++ { 0x300f, 0xe }, ++ { 0x3003, 0x3 }, ++ { 0x3003, 0x1 }, ++ { 0xffff, 0xff }, ++}; ++ ++#endif ++ ++#endif /* _OV5642_H_ */ +diff --git a/drivers/media/i2c/soc_camera/ov5642_720p.h b/drivers/media/i2c/soc_camera/ov5642_720p.h +new file mode 100644 +index 0000000..d5a52e3 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov5642_720p.h +@@ -0,0 +1,711 @@ ++/* Settings array from ++ * From 5e8e49e226b29c144ddf482afe7d3ad659c9897f Mon Sep 17 00:00:00 2001 ++ * From: Kazuya Nishimura ++ * Date: Mon, 20 Oct 2014 15:12:56 +0900 ++ * Subject: [PATCH] Enabled VIN driver for MMB ++ */ ++ ++/* 720p 30fps @ 1280x720 */ ++/* for the setting , 24MHz Mlck input and 90MHz Plck output */ ++/* refer to OV5642.c */ ++ ++static struct regval_list OV5642_720P_30FPS[] = ++{ ++ {0x3103, 0x93}, ++ {0x3008, 0x82}, ++ {0x3017, 0x7f}, ++ {0x3018, 0xfc}, ++ /* drive capability 4x */ ++ { 0x302c, (3 << 5) | 0x02 }, ++ {0x3810, 0xc2}, ++ {0x3615, 0xf0}, ++ {0x3000, 0x00}, ++ {0x3001, 0x00}, ++ {0x3002, 0x00}, ++ {0x3003, 0x00}, ++ {0x3000, 0xf8}, ++ {0x3001, 0x48}, ++ {0x3002, 0x5c}, ++ {0x3003, 0x02}, ++ {0x3004, 0x07}, ++ {0x3005, 0xb7}, ++ {0x3006, 0x43}, ++ {0x3007, 0x37}, ++ {0x3011, 0x0f}, //PLL CONTROL 02 : Bit[5:0] PLL DIVP divider ++ {0x3010, 0x10}, //PLL CONTROL 01 : Bit[7:4] PLL DIVS, Bit[3:0] PLL DIVM (MIPI divider ratio) ++ //29-30fps ++ {0x460c, 0x22}, ++ {0x3815, 0x04}, ++ {0x370d, 0x06}, ++ {0x370c, 0xa0}, ++ {0x3602, 0xfc}, ++ {0x3612, 0xff}, ++ {0x3634, 0xc0}, ++ {0x3613, 0x00}, ++ {0x3605, 0x7c}, ++ {0x3621, 0x09}, ++ {0x3622, 0x00}, ++ {0x3604, 0x40}, ++ {0x3603, 0xa7}, ++ {0x3603, 0x27}, ++ {0x4000, 0x21}, ++ {0x401d, 0x02}, ++ {0x3600, 0x54}, ++ {0x3605, 0x04}, ++ {0x3606, 0x3f}, ++ {0x3c01, 0x80}, ++ {REG_ISP_CTRL_00, 0x4f}, ++ {0x4300, 0x32}, /* YUV422: UYVY... */ ++ {0x5020, 0x04}, ++ {0x5181, 0x79}, ++ {0x5182, 0x00}, ++ {0x5185, 0x22}, ++ {0x5197, 0x01}, ++ {REG_ISP_CTRL_01, 0xff}, ++ {0x5500, 0x0a}, ++ {0x5504, 0x00}, ++ {0x5505, 0x7f}, ++ {0x5080, 0x08}, ++ {0x300e, 0x18}, ++ {0x4610, 0x00}, ++ {0x471d, 0x05}, ++ {0x4708, 0x06}, ++ /* POLARITY CTRL 00 ++ * [0] VSYNC - act low ++ * [1] HREF - act low ++ * [2] gate PCLK under HREF - no ++ * [3] gate PCLK under VSYNK - no ++ * [5] PCLK - falling edge ++ */ ++ {0x4740, 0x20}, ++ {0x3710, 0x10}, ++ {0x3632, 0x41}, ++ {0x3702, 0x40}, ++ {0x3620, 0x37}, ++ {0x3631, 0x01}, ++ {REG_OUT_WIDTH_HIGH, 0x02}, // TIMING DVPHO Bit[3:0] DVP output horizontal width high byte ++ {REG_OUT_WIDTH_LOW, 0x80}, // TIMING DVPHO Bit[7:0] DVP output horizontal width low byte ++ // 0x280 => 640 ++ {REG_OUT_HEIGHT_HIGH, 0x01}, // TIMING DVPVO Bit[3:0] DVP output vertical height high byte ++ {REG_OUT_HEIGHT_LOW, 0xe0}, // TIMING DVPVO Bit[7:0] DVP output vertical height low byte ++ // 0x1e0 => 480 ++ {REG_OUT_TOTAL_HEIGHT_HIGH, 0x07}, // TIMING VTS Bit[3:0] Total vertical size high byte [11:8] ++ {REG_OUT_TOTAL_HEIGHT_LOW, 0xd0}, // TIMING VTS Bit[7:0] Total vertical size low byte [7:0] ++ // 0x7d0 => 2000 ++ {0x501f, 0x00}, ++ {REG_ISP_CTRL_00, 0x4f}, ++ {REG_OUTPUT_FORMAT, 0x32}, //UYVY ++ {0x3503, 0x07}, ++ {0x3501, 0x73}, ++ {0x3502, 0x80}, ++ {0x350b, 0x00}, ++ {0x3503, 0x07}, ++ {0x3824, 0x11}, ++ {0x3501, 0x1e}, ++ {0x3502, 0x80}, ++ {0x350b, 0x7f}, ++ {REG_OUT_TOTAL_WIDTH_HIGH, 0x0c}, ++ {REG_OUT_TOTAL_WIDTH_LOW, 0x80}, ++ {REG_OUT_TOTAL_HEIGHT_HIGH, 0x03}, // TIMING VTS Bit[3:0] Total vertical size high byte [11:8] ++ {REG_OUT_TOTAL_HEIGHT_LOW, 0xe8}, // TIMING VTS Bit[7:0] Total vertical size low byte [7:0] ++ // 0x3e8 => 1000 ++ {0x3a0d, 0x04}, ++ {0x3a0e, 0x03}, ++ {0x3818, 0xc1}, ++ {0x3705, 0xdb}, ++ {0x370a, 0x81}, ++ {REG_WINDOW_START_X_LOW, 0x80}, ++ {0x3621, 0xc7}, ++ {REG_WINDOW_START_X_LOW, 0x50}, ++ {REG_WINDOW_START_Y_LOW, 0x08}, ++ {0x3827, 0x08}, ++ {0x3810, 0xc0}, ++ {REG_WINDOW_WIDTH_HIGH, 0x05}, ++ {REG_WINDOW_WIDTH_LOW, 0x00}, ++ {REG_AVG_WINDOW_END_X_HIGH, 0x05}, ++ {REG_AVG_WINDOW_END_X_LOW, 0x00}, ++ {REG_WINDOW_HEIGHT_HIGH, 0x03}, ++ {REG_WINDOW_HEIGHT_LOW, 0xc0}, ++ {REG_AVG_WINDOW_END_Y_HIGH, 0x03}, ++ {REG_AVG_WINDOW_END_Y_LOW, 0xc0}, ++ {0x3a00, 0x78}, ++ {0x3a1a, 0x04}, ++ {0x3a13, 0x30}, ++ {0x3a18, 0x00}, ++ {0x3a19, 0x7c}, ++ {0x3a08, 0x12}, ++ {0x3a09, 0xc0}, ++ {0x3a0a, 0x0f}, ++ {0x3a0b, 0xa0}, ++ {0x3004, 0xff}, ++ {0x350c, 0x07}, ++ {0x350d, 0xd0}, ++ {0x3500, 0x00}, ++ {0x3501, 0x00}, ++ {0x3502, 0x00}, ++ {0x350a, 0x00}, ++ {0x350b, 0x00}, ++ {0x3503, 0x00}, ++ {0x528a, 0x02}, ++ {0x528b, 0x04}, ++ {0x528c, 0x08}, ++ {0x528d, 0x08}, ++ {0x528e, 0x08}, ++ {0x528f, 0x10}, ++ {0x5290, 0x10}, ++ {0x5292, 0x00}, ++ {0x5293, 0x02}, ++ {0x5294, 0x00}, ++ {0x5295, 0x02}, ++ {0x5296, 0x00}, ++ {0x5297, 0x02}, ++ {0x5298, 0x00}, ++ {0x5299, 0x02}, ++ {0x529a, 0x00}, ++ {0x529b, 0x02}, ++ {0x529c, 0x00}, ++ {0x529d, 0x02}, ++ {0x529e, 0x00}, ++ {0x529f, 0x02}, ++ {0x3a0f, 0x3c}, ++ {0x3a10, 0x30}, ++ {0x3a1b, 0x3c}, ++ {0x3a1e, 0x30}, ++ {0x3a11, 0x70}, ++ {0x3a1f, 0x10}, ++ {0x3030, 0x0b}, ++ {0x3a02, 0x00}, ++ {0x3a03, 0x7d}, ++ {0x3a04, 0x00}, ++ {0x3a14, 0x00}, ++ {0x3a15, 0x7d}, ++ {0x3a16, 0x00}, ++ {0x3a00, 0x78}, ++ {0x3a08, 0x09}, ++ {0x3a09, 0x60}, ++ {0x3a0a, 0x07}, ++ {0x3a0b, 0xd0}, ++ {0x3a0d, 0x08}, ++ {0x3a0e, 0x06}, ++ {0x5193, 0x70}, ++ {0x3620, 0x57}, ++ {0x3703, 0x98}, ++ {0x3704, 0x1c}, ++ {0x589b, 0x04}, ++ {0x589a, 0xc5}, ++ {0x528a, 0x00}, ++ {0x528b, 0x02}, ++ {0x528c, 0x08}, ++ {0x528d, 0x10}, ++ {0x528e, 0x20}, ++ {0x528f, 0x28}, ++ {0x5290, 0x30}, ++ {0x5292, 0x00}, ++ {0x5293, 0x00}, ++ {0x5294, 0x00}, ++ {0x5295, 0x02}, ++ {0x5296, 0x00}, ++ {0x5297, 0x08}, ++ {0x5298, 0x00}, ++ {0x5299, 0x10}, ++ {0x529a, 0x00}, ++ {0x529b, 0x20}, ++ {0x529c, 0x00}, ++ {0x529d, 0x28}, ++ {0x529e, 0x00}, ++ {0x529f, 0x30}, ++ {0x5282, 0x00}, ++ {0x5300, 0x00}, ++ {0x5301, 0x20}, ++ {0x5302, 0x00}, ++ {0x5303, 0x7c}, ++ {0x530c, 0x00}, ++ {0x530d, 0x0c}, ++ {0x530e, 0x20}, ++ {0x530f, 0x80}, ++ {0x5310, 0x20}, ++ {0x5311, 0x80}, ++ {0x5308, 0x20}, ++ {0x5309, 0x40}, ++ {0x5304, 0x00}, ++ {0x5305, 0x30}, ++ {0x5306, 0x00}, ++ {0x5307, 0x80}, ++ {0x5314, 0x08}, ++ {0x5315, 0x20}, ++ {0x5319, 0x30}, ++ {0x5316, 0x10}, ++ {0x5317, 0x08}, ++ {0x5318, 0x02}, ++ {0x5380, 0x01}, ++ {0x5381, 0x00}, ++ {0x5382, 0x00}, ++ {0x5383, 0x4e}, ++ {0x5384, 0x00}, ++ {0x5385, 0x0f}, ++ {0x5386, 0x00}, ++ {0x5387, 0x00}, ++ {0x5388, 0x01}, ++ {0x5389, 0x15}, ++ {0x538a, 0x00}, ++ {0x538b, 0x31}, ++ {0x538c, 0x00}, ++ {0x538d, 0x00}, ++ {0x538e, 0x00}, ++ {0x538f, 0x0f}, ++ {0x5390, 0x00}, ++ {0x5391, 0xab}, ++ {0x5392, 0x00}, ++ {0x5393, 0xa2}, ++ {0x5394, 0x08}, ++ {0x5480, 0x14}, ++ {0x5481, 0x21}, ++ {0x5482, 0x36}, ++ {0x5483, 0x57}, ++ {0x5484, 0x65}, ++ {0x5485, 0x71}, ++ {0x5486, 0x7d}, ++ {0x5487, 0x87}, ++ {0x5488, 0x91}, ++ {0x5489, 0x9a}, ++ {0x548a, 0xaa}, ++ {0x548b, 0xb8}, ++ {0x548c, 0xcd}, ++ {0x548d, 0xdd}, ++ {0x548e, 0xea}, ++ {0x548f, 0x10}, ++ {0x5490, 0x05}, ++ {0x5491, 0x00}, ++ {0x5492, 0x04}, ++ {0x5493, 0x20}, ++ {0x5494, 0x03}, ++ {0x5495, 0x60}, ++ {0x5496, 0x02}, ++ {0x5497, 0xb8}, ++ {0x5498, 0x02}, ++ {0x5499, 0x86}, ++ {0x549a, 0x02}, ++ {0x549b, 0x5b}, ++ {0x549c, 0x02}, ++ {0x549d, 0x3b}, ++ {0x549e, 0x02}, ++ {0x549f, 0x1c}, ++ {0x54a0, 0x02}, ++ {0x54a1, 0x04}, ++ {0x54a2, 0x01}, ++ {0x54a3, 0xed}, ++ {0x54a4, 0x01}, ++ {0x54a5, 0xc5}, ++ {0x54a6, 0x01}, ++ {0x54a7, 0xa5}, ++ {0x54a8, 0x01}, ++ {0x54a9, 0x6c}, ++ {0x54aa, 0x01}, ++ {0x54ab, 0x41}, ++ {0x54ac, 0x01}, ++ {0x54ad, 0x20}, ++ {0x54ae, 0x00}, ++ {0x54af, 0x16}, ++ {0x3406, 0x00}, ++ {0x5192, 0x04}, ++ {0x5191, 0xf8}, ++ {0x5193, 0x70}, ++ {0x5194, 0xf0}, ++ {0x5195, 0xf0}, ++ {0x518d, 0x3d}, ++ {0x518f, 0x54}, ++ {0x518e, 0x3d}, ++ {0x5190, 0x54}, ++ {0x518b, 0xc0}, ++ {0x518c, 0xbd}, ++ {0x5187, 0x18}, ++ {0x5188, 0x18}, ++ {0x5189, 0x6e}, ++ {0x518a, 0x68}, ++ {0x5186, 0x1c}, ++ {0x5181, 0x50}, ++ {0x5184, 0x25}, ++ {0x5182, 0x11}, ++ {0x5183, 0x14}, ++ {0x5184, 0x25}, ++ {0x5185, 0x24}, ++ {0x5025, 0x82}, ++ {0x3a0f, 0x7e}, ++ {0x3a10, 0x72}, ++ {0x3a1b, 0x80}, ++ {0x3a1e, 0x70}, ++ {0x3a11, 0xd0}, ++ {0x3a1f, 0x40}, ++ {0x5583, 0x40}, ++ {0x5584, 0x40}, ++ {0x5580, 0x02}, ++ {0x3633, 0x07}, ++ {0x3702, 0x10}, ++ {0x3703, 0xb2}, ++ {0x3704, 0x18}, ++ {0x370b, 0x40}, ++ {0x370d, 0x02}, ++ {0x3620, 0x52}, ++ {0x3c00, 0x04}, ++ ++ {REG_ISP_CTRL_01, 0xFF}, ++ {0x5583, 0x50}, ++ {0x5584, 0x50}, ++ {0x5580, 0x02}, ++ {0x3c01, 0x80}, ++ {0x3c00, 0x04}, ++ {0x5800, 0x27}, ++ {0x5801, 0x22}, ++ {0x5802, 0x1b}, ++ {0x5803, 0x17}, ++ {0x5804, 0x16}, ++ {0x5805, 0x18}, ++ {0x5806, 0x20}, ++ {0x5807, 0x20}, ++ {0x5808, 0x1b}, ++ {0x5809, 0x15}, ++ {0x580a, 0x0f}, ++ {0x580b, 0x0d}, ++ {0x580c, 0x0d}, ++ {0x580d, 0x0e}, ++ {0x580e, 0x11}, ++ {0x580f, 0x18}, ++ {0x5810, 0x10}, ++ {0x5811, 0x0d}, ++ {0x5812, 0x08}, ++ {0x5813, 0x05}, ++ {0x5814, 0x04}, ++ {0x5815, 0x06}, ++ {0x5816, 0x09}, ++ {0x5817, 0x0e}, ++ {0x5818, 0x0d}, ++ {0x5819, 0x09}, ++ {0x581a, 0x03}, ++ {0x581b, 0x00}, ++ {0x581c, 0x00}, ++ {0x581d, 0x01}, ++ {0x581e, 0x05}, ++ {0x581f, 0x0b}, ++ {0x5820, 0x0d}, ++ {0x5821, 0x09}, ++ {0x5822, 0x03}, ++ {0x5823, 0x00}, ++ {0x5824, 0x00}, ++ {0x5825, 0x01}, ++ {0x5826, 0x05}, ++ {0x5827, 0x0b}, ++ {0x5828, 0x10}, ++ {0x5829, 0x0c}, ++ {0x582a, 0x08}, ++ {0x582b, 0x04}, ++ {0x582c, 0x03}, ++ {0x582d, 0x05}, ++ {0x582e, 0x09}, ++ {0x582f, 0x0e}, ++ {0x5830, 0x1b}, ++ {0x5831, 0x14}, ++ {0x5832, 0x0f}, ++ {0x5833, 0x0c}, ++ {0x5834, 0x0c}, ++ {0x5835, 0x0d}, ++ {0x5836, 0x10}, ++ {0x5837, 0x19}, ++ {0x5838, 0x25}, ++ {0x5839, 0x23}, ++ {0x583a, 0x1a}, ++ {0x583b, 0x16}, ++ {0x583c, 0x15}, ++ {0x583d, 0x18}, ++ {0x583e, 0x1f}, ++ {0x583f, 0x25}, ++ {0x5840, 0x10}, ++ {0x5841, 0x0e}, ++ {0x5842, 0x0e}, ++ {0x5843, 0x0e}, ++ {0x5844, 0x0f}, ++ {0x5845, 0x0a}, ++ {0x5846, 0x08}, ++ {0x5847, 0x0f}, ++ {0x5848, 0x0f}, ++ {0x5849, 0x0f}, ++ {0x584a, 0x0c}, ++ {0x584b, 0x0f}, ++ {0x584c, 0x09}, ++ {0x584d, 0x10}, ++ {0x584e, 0x11}, ++ {0x584f, 0x10}, ++ {0x5850, 0x0f}, ++ {0x5851, 0x0e}, ++ {0x5852, 0x08}, ++ {0x5853, 0x10}, ++ {0x5854, 0x10}, ++ {0x5855, 0x10}, ++ {0x5856, 0x0e}, ++ {0x5857, 0x0e}, ++ {0x5858, 0x0a}, ++ {0x5859, 0x0e}, ++ {0x585a, 0x0e}, ++ {0x585b, 0x0e}, ++ {0x585c, 0x0e}, ++ {0x585d, 0x0d}, ++ {0x585e, 0x08}, ++ {0x585f, 0x0b}, ++ {0x5860, 0x0a}, ++ {0x5861, 0x0a}, ++ {0x5862, 0x09}, ++ {0x5863, 0x0d}, ++ {0x5864, 0x13}, ++ {0x5865, 0x0e}, ++ {0x5866, 0x10}, ++ {0x5867, 0x10}, ++ {0x5868, 0x0e}, ++ {0x5869, 0x11}, ++ {0x586a, 0x12}, ++ {0x586b, 0x10}, ++ {0x586c, 0x10}, ++ {0x586d, 0x10}, ++ {0x586e, 0x10}, ++ {0x586f, 0x11}, ++ {0x5870, 0x15}, ++ {0x5871, 0x10}, ++ {0x5872, 0x10}, ++ {0x5873, 0x10}, ++ {0x5874, 0x11}, ++ {0x5875, 0x11}, ++ {0x5876, 0x14}, ++ {0x5877, 0x0f}, ++ {0x5878, 0x10}, ++ {0x5879, 0x10}, ++ {0x587a, 0x10}, ++ {0x587b, 0x11}, ++ {0x587c, 0x12}, ++ {0x587d, 0x0f}, ++ {0x587e, 0x0f}, ++ {0x587f, 0x10}, ++ {0x5880, 0x10}, ++ {0x5881, 0x0f}, ++ {0x5882, 0x12}, ++ {0x5883, 0x0e}, ++ {0x5884, 0x10}, ++ {0x5885, 0x10}, ++ {0x5886, 0x0e}, ++ {0x5887, 0x0e}, ++ {0x5180, 0xff}, ++ {0x5181, 0x52}, ++ {0x5182, 0x11}, ++ {0x5183, 0x14}, ++ {0x5184, 0x25}, ++ {0x5185, 0x24}, ++ {0x5186, 0x14}, ++ {0x5187, 0x14}, ++ {0x5188, 0x14}, ++ {0x5189, 0x6c}, ++ {0x518a, 0x60}, ++ {0x518b, 0xbd}, ++ {0x518c, 0x9c}, ++ {0x518d, 0x3d}, ++ {0x518e, 0x34}, ++ {0x518f, 0x57}, ++ {0x5190, 0x4a}, ++ {0x5191, 0xf8}, ++ {0x5192, 0x04}, ++ {0x5193, 0x70}, ++ {0x5194, 0xf0}, ++ {0x5195, 0xf0}, ++ {0x5196, 0x03}, ++ {0x5197, 0x01}, ++ {0x5198, 0x04}, ++ {0x5199, 0x00}, ++ {0x519a, 0x04}, ++ {0x519b, 0x35}, ++ {0x519c, 0x08}, ++ {0x519d, 0xb8}, ++ {0x519e, 0xa0}, ++ {0x528a, 0x00}, ++ {0x528b, 0x01}, ++ {0x528c, 0x04}, ++ {0x528d, 0x08}, ++ {0x528e, 0x10}, ++ {0x528f, 0x20}, ++ {0x5290, 0x30}, ++ {0x5292, 0x00}, ++ {0x5293, 0x00}, ++ {0x5294, 0x00}, ++ {0x5295, 0x01}, ++ {0x5296, 0x00}, ++ {0x5297, 0x04}, ++ {0x5298, 0x00}, ++ {0x5299, 0x08}, ++ {0x529a, 0x00}, ++ {0x529b, 0x10}, ++ {0x529c, 0x00}, ++ {0x529d, 0x20}, ++ {0x529e, 0x00}, ++ {0x529f, 0x30}, ++ {0x5282, 0x00}, ++ {0x5300, 0x00}, ++ {0x5301, 0x20}, ++ {0x5302, 0x00}, ++ {0x5303, 0x7c}, ++ {0x530c, 0x00}, ++ {0x530d, 0x10}, ++ {0x530e, 0x20}, ++ {0x530f, 0x80}, ++ {0x5310, 0x20}, ++ {0x5311, 0x80}, ++ {0x5308, 0x20}, ++ {0x5309, 0x40}, ++ {0x5304, 0x00}, ++ {0x5305, 0x30}, ++ {0x5306, 0x00}, ++ {0x5307, 0x80}, ++ {0x5314, 0x08}, ++ {0x5315, 0x20}, ++ {0x5319, 0x30}, ++ {0x5316, 0x10}, ++ {0x5317, 0x00}, ++ {0x5318, 0x02}, ++ {0x5380, 0x01}, ++ {0x5381, 0x00}, ++ {0x5382, 0x00}, ++ {0x5383, 0x1f}, ++ {0x5384, 0x00}, ++ {0x5385, 0x06}, ++ {0x5386, 0x00}, ++ {0x5387, 0x00}, ++ {0x5388, 0x00}, ++ {0x5389, 0xE1}, ++ {0x538A, 0x00}, ++ {0x538B, 0x2B}, ++ {0x538C, 0x00}, ++ {0x538D, 0x00}, ++ {0x538E, 0x00}, ++ {0x538F, 0x10}, ++ {0x5390, 0x00}, ++ {0x5391, 0xB3}, ++ {0x5392, 0x00}, ++ {0x5393, 0xA6}, ++ {0x5394, 0x08}, ++ {0x5480, 0x14}, ++ {0x5481, 0x21}, ++ {0x5482, 0x36}, ++ {0x5483, 0x57}, ++ {0x5484, 0x65}, ++ {0x5485, 0x71}, ++ {0x5486, 0x7D}, ++ {0x5487, 0x87}, ++ {0x5488, 0x91}, ++ {0x5489, 0x9A}, ++ {0x548A, 0xAA}, ++ {0x548B, 0xB8}, ++ {0x548C, 0xCD}, ++ {0x548D, 0xDD}, ++ {0x548E, 0xEA}, ++ {0x548F, 0x1d}, ++ {0x5490, 0x05}, ++ {0x5491, 0x00}, ++ {0x5492, 0x04}, ++ {0x5493, 0x20}, ++ {0x5494, 0x03}, ++ {0x5495, 0x60}, ++ {0x5496, 0x02}, ++ {0x5497, 0xB8}, ++ {0x5498, 0x02}, ++ {0x5499, 0x86}, ++ {0x549A, 0x02}, ++ {0x549B, 0x5B}, ++ {0x549C, 0x02}, ++ {0x549D, 0x3B}, ++ {0x549E, 0x02}, ++ {0x549F, 0x1C}, ++ {0x54A0, 0x02}, ++ {0x54A1, 0x04}, ++ {0x54A2, 0x01}, ++ {0x54A3, 0xED}, ++ {0x54A4, 0x01}, ++ {0x54A5, 0xC5}, ++ {0x54A6, 0x01}, ++ {0x54A7, 0xA5}, ++ {0x54A8, 0x01}, ++ {0x54A9, 0x6C}, ++ {0x54AA, 0x01}, ++ {0x54AB, 0x41}, ++ {0x54AC, 0x01}, ++ {0x54AD, 0x20}, ++ {0x54AE, 0x00}, ++ {0x54AF, 0x16}, ++ {0x54B0, 0x01}, ++ {0x54B1, 0x20}, ++ {0x54B2, 0x00}, ++ {0x54B3, 0x10}, ++ {0x54B4, 0x00}, ++ {0x54B5, 0xf0}, ++ {0x54B6, 0x00}, ++ {0x54B7, 0xDF}, ++ {0x5402, 0x3f}, ++ {0x5403, 0x00}, ++ {0x5500, 0x10}, ++ {0x5502, 0x00}, ++ {0x5503, 0x06}, ++ {0x5504, 0x00}, ++ {0x5505, 0x7f}, ++ {0x5025, 0x80}, ++ {0x3a0f, 0x48}, //0x30 ++ {0x3a10, 0x38}, //0x28 ++ {0x3a1b, 0x50}, //0x30 ++ {0x3a1e, 0x30}, //0x28 ++ {0x3a11, 0x71}, //0x61 ++ {0x3a1f, 0x10}, ++ {0x5688, 0xfd}, ++ {0x5689, 0xdf}, ++ {0x568a, 0xfe}, ++ {0x568b, 0xef}, ++ {0x568c, 0xfe}, ++ {0x568d, 0xef}, ++ {0x568e, 0xaa}, ++ {0x568f, 0xaa}, ++ ++ {REG_WINDOW_START_X_HIGH, 0x1 }, ++ {REG_WINDOW_START_X_LOW, 0x50}, ++ //0x150 = 336 ++ {REG_WINDOW_START_Y_HIGH, 0x0 }, ++ {REG_WINDOW_START_Y_LOW, 0x8 }, ++ //0x8 = 8 ++ {REG_WINDOW_WIDTH_HIGH, 0x5 }, ++ {REG_WINDOW_WIDTH_LOW, 0x0 }, ++ //0x500 = 1280 ++ {REG_WINDOW_HEIGHT_HIGH, 0x3 }, ++ {REG_WINDOW_HEIGHT_LOW, 0xc0}, ++ //0x3c0 = 960 ++ {REG_OUT_WIDTH_HIGH, 0x5 }, // TIMING DVPHO Bit[3:0] DVP output horizontal width high byte ++ {REG_OUT_WIDTH_LOW, 0x00}, // TIMING DVPHO Bit[7:0] DVP output horizontal width low byte ++ // 0x500 => 1280 ++ {REG_OUT_HEIGHT_HIGH, 0x2 }, // TIMING DVPVO Bit[3:0] DVP output vertical height high byte ++// {REG_OUT_HEIGHT_LOW, 0xd0}, // TIMING DVPVO Bit[7:0] DVP output vertical height low byte ++ // 0x2d0 => 720 ++ {REG_OUT_HEIGHT_LOW, 0xd5}, // TIMING DVPVO Bit[7:0] DVP output vertical height low byte ++ // 0x2d5 => 725 ++ {REG_OUT_TOTAL_WIDTH_HIGH, 0xc }, // TIMING HTS Bit[3:0] Total horizontal size high byte [11:8] ++ {REG_OUT_TOTAL_WIDTH_LOW, 0x80}, // TIMING HTS Bit[7:0] Total horizontal size low byte [7:0] ++ // 0xc80 => 3200 ++ {REG_OUT_TOTAL_HEIGHT_HIGH, 0x3 }, // TIMING VTS Bit[3:0] Total vertical size high byte [11:8] ++ {REG_OUT_TOTAL_HEIGHT_LOW, 0xe8}, // TIMING VTS Bit[7:0] Total vertical size low byte [7:0] ++ // 0x3e8 => 1000 ++ {REG_ISP_CTRL_01, 0x7f}, ++ {REG_AVG_WINDOW_START_X_HIGH, 0x0 }, ++ {REG_AVG_WINDOW_START_X_LOW, 0x0 }, ++ {REG_AVG_WINDOW_END_X_HIGH, 0x5 }, ++ {REG_AVG_WINDOW_END_X_LOW, 0x0 }, ++ {REG_AVG_WINDOW_START_Y_HIGH, 0x0 }, ++ {REG_AVG_WINDOW_START_Y_LOW, 0x0 }, ++ {REG_AVG_WINDOW_END_Y_HIGH, 0x3 }, ++ //{REG_AVG_WINDOW_END_Y_LOW, 0xc0}, ++ {REG_AVG_WINDOW_END_Y_LOW, 0xc0}, ++ {0x3815, 0x02}, ++ {0x3503, 0x00}, ++ //{0x4730, 0x01}, ++ {0x4730, 0x00}, ++ {REG_OUTPUT_FORMAT, 0x32}, ++ ++ {0xffff, 0xff}, ++}; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0033-media-soc-camera-fix-parallel-i-f-in-VIN.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0033-media-soc-camera-fix-parallel-i-f-in-VIN.patch new file mode 100644 index 00000000..be22dc35 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0033-media-soc-camera-fix-parallel-i-f-in-VIN.patch @@ -0,0 +1,69 @@ +From cbe8bbb04c7cff0d4c7cca6ca6b6f28f4998fb2a Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Fri, 14 Jul 2017 21:55:20 +0300 +Subject: [PATCH 025/122] media: soc_camera: fix parallel i/f in VIN + +This fixes parallel interface in VIN + +Signed-off-by: Vladimir Barinov +--- + drivers/media/platform/soc_camera/rcar_vin.c | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c +index 9733555..ded9288 100644 +--- a/drivers/media/platform/soc_camera/rcar_vin.c ++++ b/drivers/media/platform/soc_camera/rcar_vin.c +@@ -154,6 +154,9 @@ + /* Video n Data Mode Register 2 bits */ + #define VNDMR2_VPS (1 << 30) + #define VNDMR2_HPS (1 << 29) ++#define VNDMR2_CES (1 << 28) ++#define VNDMR2_DES (1 << 27) ++#define VNDMR2_CHS (1 << 23) + #define VNDMR2_FTEV (1 << 17) + #define VNDMR2_VLV(n) ((n & 0xf) << 12) + +@@ -1889,10 +1892,15 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd) + val = VNDMR2_FTEV; + else + val = VNDMR2_FTEV | VNDMR2_VLV(1); ++ + if (!(common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) + val |= VNDMR2_VPS; + if (!(common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) + val |= VNDMR2_HPS; ++ ++ val |= VNDMR2_CES; ++ dev_dbg(icd->parent, "VNDMR2=0x%x\n", val); ++ + iowrite32(val, priv->base + VNDMR2_REG); + + ret = rcar_vin_set_rect(icd); +@@ -2989,8 +2997,8 @@ static int rcar_vin_probe(struct platform_device *pdev) + priv->max_height = 2048; + } + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) { ++ if ((priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) && !of_property_read_string(np, "csi,select", &str)) { + u32 ifmd = 0; + bool match_flag = false; + const struct vin_gen3_ifmd *gen3_ifmd_table = NULL; +@@ -3025,12 +3033,6 @@ static int rcar_vin_probe(struct platform_device *pdev) + else + priv->index = RCAR_VIN_CH_NONE; + +- ret = of_property_read_string(np, "csi,select", &str); +- if (ret) { +- dev_err(&pdev->dev, "could not parse csi,select\n"); +- return ret; +- } +- + if (strcmp(str, "csi40") == 0) + priv->csi_ch = RCAR_CSI40; + else if (strcmp(str, "csi20") == 0) +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0034-media-soc_camera-Fix-VIDIOC_S_SELECTION-ioctl-miscal.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0034-media-soc_camera-Fix-VIDIOC_S_SELECTION-ioctl-miscal.patch new file mode 100644 index 00000000..ade2361a --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0034-media-soc_camera-Fix-VIDIOC_S_SELECTION-ioctl-miscal.patch @@ -0,0 +1,50 @@ +From e9d22a6f30941cad86b22258fd0a467a7b69ede4 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Mon, 31 Jul 2017 19:26:05 +0300 +Subject: [PATCH 026/122] media: soc_camera: Fix VIDIOC_S_SELECTION ioctl + miscalculation + +This patch corrects the miscalculation of the capture buffer +size and clipping data update in VIDIOC_S_SELECTION sequence. + +Patch isbased on work by: Koji Matsuoka + +Signed-off-by: Vladimir Barinov +--- + drivers/media/platform/soc_camera/soc_scale_crop.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/media/platform/soc_camera/soc_scale_crop.c b/drivers/media/platform/soc_camera/soc_scale_crop.c +index 092c73f..6050f52 100644 +--- a/drivers/media/platform/soc_camera/soc_scale_crop.c ++++ b/drivers/media/platform/soc_camera/soc_scale_crop.c +@@ -126,6 +126,7 @@ int soc_camera_client_s_selection(struct v4l2_subdev *sd, + dev_dbg(dev, "Camera S_SELECTION successful for %dx%d@%d:%d\n", + rect->width, rect->height, rect->left, rect->top); + *target_rect = *cam_rect; ++ *subrect = *rect; + return 0; + } + +@@ -217,6 +218,7 @@ int soc_camera_client_s_selection(struct v4l2_subdev *sd, + + if (!ret) { + *target_rect = *cam_rect; ++ *subrect = *rect; + move_and_crop_subrect(target_rect, subrect); + } + +@@ -297,9 +299,7 @@ static int client_set_fmt(struct soc_camera_device *icd, + if (ret < 0) + return ret; + +- if (host_1to1) +- *subrect = *rect; +- else ++ if (!host_1to1) + move_and_crop_subrect(rect, subrect); + + return 0; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0036-Add-MOST-support-for-r8a77965.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0036-Add-MOST-support-for-r8a77965.patch new file mode 100644 index 00000000..0ff54d35 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0036-Add-MOST-support-for-r8a77965.patch @@ -0,0 +1,100 @@ +From 084e65dfa693df84189b907ab06ec0bac92abc92 Mon Sep 17 00:00:00 2001 +From: Yusuke Goda +Date: Fri, 26 Oct 2018 15:42:38 +0900 +Subject: [PATCH 027/122] Add MOST support for r8a77965 + +This adds MOST support to R-Car M3N. + +Signed-off-by: Yusuke Goda +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77965.dtsi | 13 +++++++++++++ + drivers/clk/renesas/r8a77965-cpg-mssr.c | 1 + + drivers/pinctrl/sh-pfc/pfc-r8a77965.c | 14 ++++++++++++++ + 3 files changed, 28 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77965.dtsi b/arch/arm64/boot/dts/renesas/r8a77965.dtsi +index e682d10..b5926ff 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77965.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77965.dtsi +@@ -1188,6 +1188,19 @@ + status = "disabled"; + }; + ++ mlp: mlp@ec520000 { ++ compatible = "rcar,medialb-dim2"; ++ reg = <0 0xec520000 0 0x800>; ++ interrupts = , ++ , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 802>; ++ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ + msiof0: spi@e6e90000 { + compatible = "renesas,msiof-r8a77965", + "renesas,rcar-gen3-msiof"; +diff --git a/drivers/clk/renesas/r8a77965-cpg-mssr.c b/drivers/clk/renesas/r8a77965-cpg-mssr.c +index b3b637f..3d4fe53 100644 +--- a/drivers/clk/renesas/r8a77965-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a77965-cpg-mssr.c +@@ -190,6 +190,7 @@ static const struct mssr_mod_clk r8a77965_mod_clks[] __initconst = { + DEF_MOD("lvds", 727, R8A77965_CLK_S2D1), + DEF_MOD("hdmi0", 729, R8A77965_CLK_HDMI), + ++ DEF_MOD("mlp", 802, R8A77965_CLK_S2D1), + DEF_MOD("vin7", 804, R8A77965_CLK_S0D2), + DEF_MOD("vin6", 805, R8A77965_CLK_S0D2), + DEF_MOD("vin5", 806, R8A77965_CLK_S0D2), +diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a77965.c b/drivers/pinctrl/sh-pfc/pfc-r8a77965.c +index 8f4b73c..91aa6c0 100644 +--- a/drivers/pinctrl/sh-pfc/pfc-r8a77965.c ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a77965.c +@@ -2627,6 +2627,14 @@ static const unsigned int intc_ex_irq5_mux[] = { + IRQ5_MARK, + }; + ++/* - MLB+ ------------------------------------------------------------------- */ ++static const unsigned int mlb_3pin_pins[] = { ++ RCAR_GP_PIN(5, 23), RCAR_GP_PIN(5, 24), RCAR_GP_PIN(5, 25), ++}; ++static const unsigned int mlb_3pin_mux[] = { ++ MLB_CLK_MARK, MLB_SIG_MARK, MLB_DAT_MARK, ++}; ++ + /* - MSIOF0 ----------------------------------------------------------------- */ + static const unsigned int msiof0_clk_pins[] = { + /* SCK */ +@@ -4562,6 +4570,7 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { + SH_PFC_PIN_GROUP(intc_ex_irq3), + SH_PFC_PIN_GROUP(intc_ex_irq4), + SH_PFC_PIN_GROUP(intc_ex_irq5), ++ SH_PFC_PIN_GROUP(mlb_3pin), + SH_PFC_PIN_GROUP(msiof0_clk), + SH_PFC_PIN_GROUP(msiof0_sync), + SH_PFC_PIN_GROUP(msiof0_ss1), +@@ -4982,6 +4991,10 @@ static const char * const intc_ex_groups[] = { + "intc_ex_irq5", + }; + ++static const char * const mlb_3pin_groups[] = { ++ "mlb_3pin", ++}; ++ + static const char * const msiof0_groups[] = { + "msiof0_clk", + "msiof0_sync", +@@ -5325,6 +5338,7 @@ static const struct sh_pfc_function pinmux_functions[] = { + SH_PFC_FUNCTION(i2c5), + SH_PFC_FUNCTION(i2c6), + SH_PFC_FUNCTION(intc_ex), ++ SH_PFC_FUNCTION(mlb_3pin), + SH_PFC_FUNCTION(msiof0), + SH_PFC_FUNCTION(msiof1), + SH_PFC_FUNCTION(msiof2), +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0037-media-soc_camera-rcar_vin-Fix-VnCSI_IFMD-settings.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0037-media-soc_camera-rcar_vin-Fix-VnCSI_IFMD-settings.patch new file mode 100644 index 00000000..d3afbcf3 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0037-media-soc_camera-rcar_vin-Fix-VnCSI_IFMD-settings.patch @@ -0,0 +1,98 @@ +From c6c33a6088a78955da739ceac223843f66052745 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Tue, 6 Nov 2018 15:51:09 +0300 +Subject: [PATCH 028/122] media: soc_camera: rcar_vin: Fix VnCSI_IFMD settings + +This makes VnCSI_IFMD DES[01] bit settings identical in both +probe and resume callbacks. The DES0 bit is set for all SoCs, +while DES1 bit is reserved on V3M, V3H, and E3. + +While at it, also handle the situations when priv->chip +is not found among supported SoCs. + +Signed-off-by: Valentine Barshak +--- + drivers/media/platform/soc_camera/rcar_vin.c | 37 ++++++++++++++++++++-------- + 1 file changed, 27 insertions(+), 10 deletions(-) + +diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c +index ded9288..77c8d6b 100644 +--- a/drivers/media/platform/soc_camera/rcar_vin.c ++++ b/drivers/media/platform/soc_camera/rcar_vin.c +@@ -2999,7 +2999,7 @@ static int rcar_vin_probe(struct platform_device *pdev) + + if ((priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || + priv->chip == RCAR_V3M) && !of_property_read_string(np, "csi,select", &str)) { +- u32 ifmd = 0; ++ u32 ifmd; + bool match_flag = false; + const struct vin_gen3_ifmd *gen3_ifmd_table = NULL; + int vc, num; +@@ -3065,14 +3065,24 @@ static int rcar_vin_probe(struct platform_device *pdev) + dev_dbg(&pdev->dev, "csi_ch:%d, vc:%d\n", + priv->csi_ch, priv->vc); + +- ifmd = VNCSI_IFMD_DES1 | VNCSI_IFMD_DES0; ++ ifmd = VNCSI_IFMD_DES0; + +- if (priv->chip == RCAR_H3) ++ switch (priv->chip) { ++ case RCAR_H3: + gen3_ifmd_table = vin_h3_vc_ifmd; +- else if (priv->chip == RCAR_M3) ++ ifmd = VNCSI_IFMD_DES1; ++ break; ++ case RCAR_M3: + gen3_ifmd_table = vin_m3_vc_ifmd; +- else if (priv->chip == RCAR_V3M) ++ ifmd = VNCSI_IFMD_DES1; ++ break; ++ case RCAR_V3M: + gen3_ifmd_table = vin_v3_vc_ifmd; ++ break; ++ default: ++ BUG(); ++ break; ++ } + + for (i = 0; i < num; i++) { + if ((gen3_ifmd_table[i].v_sel[priv->index].csi2_ch +@@ -3209,7 +3219,7 @@ static int rcar_vin_suspend(struct device *dev) + + static int rcar_vin_resume(struct device *dev) + { +- u32 ifmd = 0; ++ u32 ifmd; + bool match_flag = false; + const struct vin_gen3_ifmd *gen3_ifmd_table = NULL; + int num; +@@ -3221,15 +3231,22 @@ static int rcar_vin_resume(struct device *dev) + ifmd0_init = true; + ifmd4_init = true; + +- if (priv->chip == RCAR_H3) { +- ifmd = VNCSI_IFMD_DES1 | VNCSI_IFMD_DES0; ++ ifmd = VNCSI_IFMD_DES0; ++ ++ switch (priv->chip) { ++ case RCAR_H3: + gen3_ifmd_table = vin_h3_vc_ifmd; +- } else if (priv->chip == RCAR_M3) { + ifmd = VNCSI_IFMD_DES1; ++ break; ++ case RCAR_M3: + gen3_ifmd_table = vin_m3_vc_ifmd; +- } else if (priv->chip == RCAR_V3M) { + ifmd = VNCSI_IFMD_DES1; ++ break; ++ case RCAR_V3M: + gen3_ifmd_table = vin_v3_vc_ifmd; ++ break; ++ default: ++ return 0; + } + + for (i = 0; i < num; i++) { +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0038-media-soc_camera-rcar_vin-Add-R-Car-M3N-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0038-media-soc_camera-rcar_vin-Add-R-Car-M3N-support.patch new file mode 100644 index 00000000..1c35fead --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0038-media-soc_camera-rcar_vin-Add-R-Car-M3N-support.patch @@ -0,0 +1,236 @@ +From d6c2b71e753a46bc72743d09000ca4589da51251 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Tue, 6 Nov 2018 16:02:21 +0300 +Subject: [PATCH 029/122] media: soc_camera: rcar_vin: Add R-Car M3N support + +This adds R8A77965 SoC support. + +Signed-off-by: Valentine Barshak +--- + drivers/media/platform/soc_camera/rcar_vin.c | 98 ++++++++++++++++++++++++---- + 1 file changed, 86 insertions(+), 12 deletions(-) + +diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c +index 77c8d6b..228bbf3 100644 +--- a/drivers/media/platform/soc_camera/rcar_vin.c ++++ b/drivers/media/platform/soc_camera/rcar_vin.c +@@ -200,6 +200,7 @@ static int ifmd4_init = true; + enum chip_id { + RCAR_GEN3, + RCAR_V3M, ++ RCAR_M3N, + RCAR_M3, + RCAR_H3, + RCAR_GEN2, +@@ -375,6 +376,69 @@ static const struct vin_gen3_ifmd vin_m3_vc_ifmd[] = { + }, + }; + ++static const struct vin_gen3_ifmd vin_m3n_vc_ifmd[] = { ++ { 0x0000, ++ { ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ } ++ }, ++ { 0x0001, ++ { ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ } ++ }, ++ { 0x0002, ++ { ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ } ++ }, ++ { 0x0003, ++ { ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH3}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH3}, ++ } ++ }, ++ { 0x0004, ++ { ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH3}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH3}, ++ } ++ }, ++}; ++ + static const struct vin_gen3_ifmd vin_v3_vc_ifmd[] = { + { 0x0000, + { +@@ -913,7 +977,7 @@ static int rcar_vin_videobuf_setup(struct vb2_queue *vq, + struct rcar_vin_cam *cam = icd->host_priv; + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) { + if ((priv->ratio_h > 0x10000) || (priv->ratio_v > 0x10000)) { + dev_err(icd->parent, "Scaling rate parameter error\n"); + return -EINVAL; +@@ -1022,7 +1086,7 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + switch (icd->current_fmt->host_fmt->fourcc) { + case V4L2_PIX_FMT_NV12: + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) { + iowrite32(ALIGN((cam->out_width * cam->out_height), + 0x80), priv->base + VNUVAOF_REG); + dmr = VNDMR_DTMD_YCSEP_YCBCR420; +@@ -1058,7 +1122,7 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + break; + case V4L2_PIX_FMT_XBGR32: + if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3 && +- priv->chip != RCAR_V3M && ++ priv->chip != RCAR_M3N && priv->chip != RCAR_V3M && + priv->chip != RCAR_GEN2 && priv->chip != RCAR_H1 && + priv->chip != RCAR_E1) + goto e_format; +@@ -1067,7 +1131,7 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + break; + case V4L2_PIX_FMT_ABGR32: + if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3 && +- priv->chip != RCAR_V3M) ++ priv->chip != RCAR_M3N && priv->chip != RCAR_V3M) + goto e_format; + + dmr = VNDMR_EXRGB | VNDMR_DTMD_ARGB; +@@ -1088,7 +1152,7 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + vnmc |= VNMC_BPS; + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) { + if (priv->pdata_flags & RCAR_VIN_CSI2) + vnmc &= ~VNMC_DPINE; + else +@@ -1459,7 +1523,7 @@ static int rcar_vin_add_device(struct soc_camera_device *icd) + pm_runtime_get_sync(ici->v4l2_dev.dev); + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) { + struct v4l2_subdev *csi2_sd = find_csi2(priv); + struct v4l2_subdev *deser_sd = find_deser(priv); + int ret = 0; +@@ -1722,7 +1786,7 @@ static int rcar_vin_set_rect(struct soc_camera_device *icd) + } + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) { + if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12) && + (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR8) && + (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR12) +@@ -1880,7 +1944,7 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd) + return ret; + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) { + if (cfg.type == V4L2_MBUS_CSI2) + vnmc &= ~VNMC_DPINE; + else +@@ -1888,7 +1952,7 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd) + } + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) ++ priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) + val = VNDMR2_FTEV; + else + val = VNDMR2_FTEV | VNDMR2_VLV(1); +@@ -2486,7 +2550,7 @@ static int rcar_vin_try_fmt(struct soc_camera_device *icd, + return ret; + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) { + /* Adjust max scaling size for Gen3 */ + if (pix->width > 4096) + pix->width = priv->max_width; +@@ -2666,6 +2730,7 @@ static struct soc_camera_host_ops rcar_vin_host_ops = { + #ifdef CONFIG_OF + static const struct of_device_id rcar_vin_of_table[] = { + { .compatible = "renesas,vin-r8a7797", .data = (void *)RCAR_V3M }, ++ { .compatible = "renesas,vin-r8a77965", .data = (void *)RCAR_M3N }, + { .compatible = "renesas,vin-r8a7796", .data = (void *)RCAR_M3 }, + { .compatible = "renesas,vin-r8a7795", .data = (void *)RCAR_H3 }, + { .compatible = "renesas,vin-r8a7794", .data = (void *)RCAR_GEN2 }, +@@ -2989,7 +3054,7 @@ static int rcar_vin_probe(struct platform_device *pdev) + } + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) { + priv->max_width = 4096; + priv->max_height = 4096; + } else { +@@ -2998,7 +3063,8 @@ static int rcar_vin_probe(struct platform_device *pdev) + } + + if ((priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) && !of_property_read_string(np, "csi,select", &str)) { ++ priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) && ++ !of_property_read_string(np, "csi,select", &str)) { + u32 ifmd; + bool match_flag = false; + const struct vin_gen3_ifmd *gen3_ifmd_table = NULL; +@@ -3076,6 +3142,10 @@ static int rcar_vin_probe(struct platform_device *pdev) + gen3_ifmd_table = vin_m3_vc_ifmd; + ifmd = VNCSI_IFMD_DES1; + break; ++ case RCAR_M3N: ++ gen3_ifmd_table = vin_m3n_vc_ifmd; ++ ifmd = VNCSI_IFMD_DES1; ++ break; + case RCAR_V3M: + gen3_ifmd_table = vin_v3_vc_ifmd; + break; +@@ -3242,6 +3312,10 @@ static int rcar_vin_resume(struct device *dev) + gen3_ifmd_table = vin_m3_vc_ifmd; + ifmd = VNCSI_IFMD_DES1; + break; ++ case RCAR_M3N: ++ gen3_ifmd_table = vin_m3n_vc_ifmd; ++ ifmd = VNCSI_IFMD_DES1; ++ break; + case RCAR_V3M: + gen3_ifmd_table = vin_v3_vc_ifmd; + break; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0039-media-soc_camera-rcar_csi2-Add-R-Car-M3N-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0039-media-soc_camera-rcar_csi2-Add-R-Car-M3N-support.patch new file mode 100644 index 00000000..262517fa --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0039-media-soc_camera-rcar_csi2-Add-R-Car-M3N-support.patch @@ -0,0 +1,49 @@ +From 94708fd89d1dc5a22177e30a15752d25287157eb Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Tue, 6 Nov 2018 16:03:30 +0300 +Subject: [PATCH 030/122] media: soc_camera: rcar_csi2: Add R-Car M3N support + +This adds R8A77965 SoC support. + +Signed-off-by: Valentine Barshak +--- + drivers/media/platform/soc_camera/Kconfig | 2 +- + drivers/media/platform/soc_camera/rcar_csi2.c | 2 ++ + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig +index a3bf60d..6616d59 100644 +--- a/drivers/media/platform/soc_camera/Kconfig ++++ b/drivers/media/platform/soc_camera/Kconfig +@@ -39,7 +39,7 @@ config VIDEO_RCAR_VIN_LEGACY_DEBUG + config VIDEO_RCAR_CSI2_LEGACY + tristate "R-Car MIPI CSI-2 Interface driver" + depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK +- depends on ARCH_R8A7795 || ARCH_R8A7796 || COMPILE_TEST ++ depends on ARCH_R8A7795 || ARCH_R8A7796 || ARCH_R8A77965 || COMPILE_TEST + select V4L2_FWNODE + ---help--- + This is a v4l2 driver for the R-Car CSI-2 Interface +diff --git a/drivers/media/platform/soc_camera/rcar_csi2.c b/drivers/media/platform/soc_camera/rcar_csi2.c +index 2e710e3..384d7e9 100644 +--- a/drivers/media/platform/soc_camera/rcar_csi2.c ++++ b/drivers/media/platform/soc_camera/rcar_csi2.c +@@ -613,6 +613,7 @@ static struct v4l2_subdev_ops rcar_csi2_subdev_ops = { + #ifdef CONFIG_OF + static const struct of_device_id rcar_csi2_of_table[] = { + { .compatible = "renesas,r8a7797-csi2", .data = (void *)RCAR_GEN3 }, ++ { .compatible = "renesas,r8a77965-csi2", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,r8a7796-csi2", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,r8a7795-csi2", .data = (void *)RCAR_GEN3 }, + { }, +@@ -622,6 +623,7 @@ MODULE_DEVICE_TABLE(of, rcar_csi2_of_table); + + static struct platform_device_id rcar_csi2_id_table[] = { + { "r8a7797-csi2", RCAR_GEN3 }, ++ { "r8a77965-csi2", RCAR_GEN3 }, + { "r8a7796-csi2", RCAR_GEN3 }, + { "r8a7795-csi2", RCAR_GEN3 }, + {}, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch new file mode 100644 index 00000000..08922ed1 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -0,0 +1,13885 @@ +From dc3cc58aeac5bb30a7e8ebd50dd81a7249756a01 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Fri, 14 Jul 2017 15:05:42 +0300 +Subject: [PATCH 031/122] arm64: dts: renesas: add ADAS boards + +Salvator-X.View board on R8A7795 ES1.x SoC +Salvator-X.View board on R8A7795 SoC +Salvator-X.View board on R8A7796 SoC +H3ULCB.View board on R8A7795 ES1.x SoC +H3ULCB.View board on R8A7795 SoC +M3ULCB.View board on R8A7796 SoC +H3ULCB.HAD board on R8A7795 ES1.x SoC +H3ULCB.HAD board on R8A7795 SoC +Kingfisher board on R8A7795 ES1.x SoC +Kingfisher board on R8A7795 SoC +Kingfisher board on R8A7796 SoC +Kingfisher board on R8A77965 SoC +Kingfisher board on R8A77970 ES1.0/2.0 SoC +Videobox board on R8A7795 ES1.x SoC +Videobox board on R8A7795 SoC +Eagle board on R8A77970 ES1.0/2.0 SoC +Eagle Function board on R8A77970 ES1.0/2.0 SoC +V3MSK board on R8A77970 ES1.0/2.0 SoC +V3MSK.View board on R8A77970 ES1.0/2.0 SoC +V3MZF board on R8A77970 SoC +Videobox Mini board on R8A7795 ES1.x SoC +Videobox Mini board on R8A7795 SoC +Videobox Mini board on R8A77970 ES1.0/2.0 SoC +Videobox Mini V2 board on R8A77970 ES1.0/2.0 SoC +Videobox2 board on R8A7795 ES1.x SoC +Videobox2 board on R8A7795 SoC +Condor board on R8A77980 SoC +V3HSK board on R8A77980 SoC +Videobox Mini board on R8A77980 SoC +Videobox Mini V2 board on R8A77980 SoC + +Signed-off-by: Vladimir Barinov +--- + arch/arm64/boot/dts/renesas/Makefile | 23 + + .../dts/renesas/r8a7795-es1-h3ulcb-had-alfa.dts | 22 + + .../dts/renesas/r8a7795-es1-h3ulcb-had-beta.dts | 23 + + .../boot/dts/renesas/r8a7795-es1-h3ulcb-had.dtsi | 202 +++ + .../boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts | 25 + + .../boot/dts/renesas/r8a7795-es1-h3ulcb-vb.dts | 69 + + .../boot/dts/renesas/r8a7795-es1-h3ulcb-vb2.dts | 77 + + .../boot/dts/renesas/r8a7795-es1-h3ulcb-vbm.dts | 26 + + .../boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts | 544 +++++++ + .../dts/renesas/r8a7795-es1-salvator-x-view.dts | 550 +++++++ + .../boot/dts/renesas/r8a7795-h3ulcb-4x2g-kf.dts | 44 + + .../boot/dts/renesas/r8a7795-h3ulcb-4x2g-vb.dts | 68 + + .../boot/dts/renesas/r8a7795-h3ulcb-4x2g-vb2.dts | 68 + + .../boot/dts/renesas/r8a7795-h3ulcb-4x2g-vbm.dts | 26 + + .../boot/dts/renesas/r8a7795-h3ulcb-had-alfa.dts | 22 + + .../boot/dts/renesas/r8a7795-h3ulcb-had-beta.dts | 23 + + .../arm64/boot/dts/renesas/r8a7795-h3ulcb-had.dtsi | 196 +++ + arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts | 25 + + arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb.dts | 68 + + arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb2.dts | 68 + + arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vbm.dts | 26 + + .../arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts | 544 +++++++ + .../boot/dts/renesas/r8a7795-salvator-x-view.dts | 550 +++++++ + arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts | 26 + + .../arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts | 286 ++++ + .../boot/dts/renesas/r8a7796-salvator-x-view.dts | 317 ++++ + .../arm64/boot/dts/renesas/r8a77965-m3nulcb-kf.dts | 41 + + .../boot/dts/renesas/r8a77970-eagle-function.dts | 62 + + arch/arm64/boot/dts/renesas/r8a77970-eagle.dts | 356 +++++ + .../dts/renesas/r8a77970-es1-eagle-function.dts | 17 + + arch/arm64/boot/dts/renesas/r8a77970-es1-eagle.dts | 17 + + .../boot/dts/renesas/r8a77970-es1-v3msk-kf.dts | 17 + + .../boot/dts/renesas/r8a77970-es1-v3msk-vbm-v2.dts | 17 + + .../boot/dts/renesas/r8a77970-es1-v3msk-vbm.dts | 17 + + .../boot/dts/renesas/r8a77970-es1-v3msk-view.dts | 17 + + arch/arm64/boot/dts/renesas/r8a77970-es1-v3msk.dts | 17 + + arch/arm64/boot/dts/renesas/r8a77970-es1.dtsi | 116 ++ + arch/arm64/boot/dts/renesas/r8a77970-v3msk-kf.dts | 519 +++++++ + .../boot/dts/renesas/r8a77970-v3msk-vbm-v2.dts | 82 + + arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm.dts | 507 ++++++ + .../arm64/boot/dts/renesas/r8a77970-v3msk-view.dts | 297 ++++ + arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts | 71 + + arch/arm64/boot/dts/renesas/r8a77970-v3mzf.dts | 442 ++++++ + arch/arm64/boot/dts/renesas/r8a77980-condor.dts | 40 + + .../boot/dts/renesas/r8a77980-v3hsk-vbm-v2.dts | 73 + + arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm.dts | 505 ++++++ + arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts | 41 + + arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi | 462 ++++++ + arch/arm64/boot/dts/renesas/ulcb-kf-most.dtsi | 30 + + arch/arm64/boot/dts/renesas/ulcb-kf-sd3.dtsi | 46 + + arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 1272 ++++++++++++++- + arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi | 459 ++++++ + arch/arm64/boot/dts/renesas/ulcb-vb.dtsi | 1591 +++++++++++++++++++ + arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1641 ++++++++++++++++++++ + arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi | 523 +++++++ + 55 files changed, 13210 insertions(+), 3 deletions(-) + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had-alfa.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had-beta.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had.dtsi + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-vb.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-vb2.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-vbm.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-4x2g-kf.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-4x2g-vb.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-4x2g-vb2.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-4x2g-vbm.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had-alfa.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had-beta.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had.dtsi + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb2.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vbm.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a77965-m3nulcb-kf.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a77970-eagle-function.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a77970-es1-eagle-function.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a77970-es1-eagle.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a77970-es1-v3msk-kf.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a77970-es1-v3msk-vbm-v2.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a77970-es1-v3msk-vbm.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a77970-es1-v3msk-view.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a77970-es1-v3msk.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a77970-es1.dtsi + create mode 100644 arch/arm64/boot/dts/renesas/r8a77970-v3msk-kf.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm-v2.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a77970-v3msk-view.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a77970-v3mzf.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm-v2.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm.dts + create mode 100644 arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi + create mode 100644 arch/arm64/boot/dts/renesas/ulcb-kf-most.dtsi + create mode 100644 arch/arm64/boot/dts/renesas/ulcb-kf-sd3.dtsi + create mode 100644 arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi + create mode 100644 arch/arm64/boot/dts/renesas/ulcb-vb.dtsi + create mode 100644 arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi + create mode 100644 arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi + +diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile +index b9f6bf0..e7fc36e 100644 +--- a/arch/arm64/boot/dts/renesas/Makefile ++++ b/arch/arm64/boot/dts/renesas/Makefile +@@ -20,4 +20,27 @@ dtb-$(CONFIG_ARCH_R8A77990) += r8a77990-ebisu-4d.dtb + dtb-$(CONFIG_ARCH_R8A77990) += r8a77990-es10-ebisu.dtb r8a77990-es10-ebisu-4d.dtb + dtb-$(CONFIG_ARCH_R8A77995) += r8a77995-draak.dtb + ++# ADAS boards ++dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-x-view.dtb ++dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-m3ulcb-view.dtb ++dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-m3ulcb-kf.dtb ++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-salvator-x-view.dtb r8a7795-es1-salvator-x-view.dtb ++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-view.dtb r8a7795-es1-h3ulcb-view.dtb ++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-had-alfa.dtb r8a7795-h3ulcb-had-beta.dtb r8a7795-es1-h3ulcb-had-alfa.dtb r8a7795-es1-h3ulcb-had-beta.dtb ++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-kf.dtb r8a7795-es1-h3ulcb-kf.dtb r8a7795-h3ulcb-4x2g-kf.dtb ++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-vb.dtb r8a7795-es1-h3ulcb-vb.dtb r8a7795-h3ulcb-4x2g-vb.dtb ++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-vb2.dtb r8a7795-es1-h3ulcb-vb2.dtb r8a7795-h3ulcb-4x2g-vb2.dtb ++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-vbm.dtb r8a7795-es1-h3ulcb-vbm.dtb r8a7795-h3ulcb-4x2g-vbm.dtb ++dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-m3nulcb-kf.dtb ++#dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-eagle-function.dtb ++#dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-es1-eagle.dtb r8a77970-es1-eagle-function.dtb ++#dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-es1-v3msk.dtb ++#dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-view.dtb r8a77970-es1-v3msk-view.dtb ++#dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-kf.dtb r8a77970-es1-v3msk-kf.dtb ++#dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-vbm.dtb r8a77970-es1-v3msk-vbm.dtb ++#dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-vbm-v2.dtb r8a77970-es1-v3msk-vbm-v2.dtb ++#dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3mzf.dtb ++#dtb-$(CONFIG_ARCH_R8A77980) += r8a77980-v3hsk-vbm.dtb ++#dtb-$(CONFIG_ARCH_R8A77980) += r8a77980-v3hsk-vbm-v2.dtb ++ + always := $(dtb-y) +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had-alfa.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had-alfa.dts +new file mode 100644 +index 0000000..6b13f07 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had-alfa.dts +@@ -0,0 +1,22 @@ ++/* ++ * Device Tree Source for the H3ULCB.HAD board Alfa side on r8a7795 ES1.x ++ * ++ * Copyright (C) 2017 Renesas Electronics Corp. ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-es1-h3ulcb-had.dtsi" ++ ++/ { ++ model = "Renesas H3ULCB.HAD board Alfa side based on r8a7795"; ++}; ++ ++&pciec0 { ++ status = "okay"; ++ ++ /* Root complex */ ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had-beta.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had-beta.dts +new file mode 100644 +index 0000000..2f8b274 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had-beta.dts +@@ -0,0 +1,23 @@ ++/* ++ * Device Tree Source for the H3ULCB.HAD board Beta side on r8a7795 ES1.x ++ * ++ * Copyright (C) 2017 Renesas Electronics Corp. ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-es1-h3ulcb-had.dtsi" ++ ++/ { ++ model = "Renesas H3ULCB.HAD board Beta side based on r8a7795"; ++}; ++ ++&pciec0 { ++ status = "okay"; ++ ++ /* Endpoint */ ++ endpoint; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had.dtsi b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had.dtsi +new file mode 100644 +index 0000000..484d97a +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had.dtsi +@@ -0,0 +1,202 @@ ++/* ++ * Device Tree Source for the H3ULCB.HAD board on r8a7795 ES1.x ++ * ++ * Copyright (C) 2016-2017 Renesas Electronics Corp. ++ * Copyright (C) 2016-2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++/* ++ * MSIOF0 - /dev/spidev1.0 connected to FPGA ethernet switch (both sides) ++ * MSIOF1 - /dev/spidev2.0 connected to RH850 (sideA to CSIH1, sideB to CSIH0) ++ */ ++ ++#include "r8a7795-es1-h3ulcb-view.dts" ++ ++/ { ++ model = "Renesas H3ULCB.HAD board based on r8a7795"; ++ ++ aliases { ++ serial0 = &scif1; ++ spi1 = &spi0_gpio; ++ spi2 = &spi1_gpio; ++ }; ++ ++ spi0_gpio: spi_gpio@0 { ++ compatible = "spi-gpio"; ++ num-chipselects = <1>; ++ gpio-sck = <&gpio5 17 0>; ++ gpio-mosi = <&gpio5 20 0>; ++ gpio-miso = <&gpio5 22 0>; ++ cs-gpios = <&gpio5 19 0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ spidev@0 { ++ compatible = "spi-gpio"; ++ reg = <0>; ++ spi-max-frequency = <2000000>; ++ spi-cpha; ++ spi-cpol; ++ }; ++ }; ++ ++ spi1_gpio: spi_gpio@1 { ++ compatible = "spi-gpio"; ++ num-chipselects = <1>; ++ gpio-sck = <&gpio6 8 0>; ++ gpio-mosi = <&gpio6 7 0>; ++ gpio-miso = <&gpio6 10 0>; ++ cs-gpios = <&gpio6 5 0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ spidev@0 { ++ compatible = "spi-gpio"; ++ reg = <0>; ++ spi-max-frequency = <2000000>; ++ spi-cpha; ++ spi-cpol; ++ }; ++ }; ++ ++ hdmi1-out { ++ compatible = "hdmi-connector"; ++ label = "HDMI1 OUT"; ++ type = "a"; ++ ++ port { ++ hdmi1_con: endpoint { ++ }; ++ }; ++ }; ++}; ++ ++&hdmi1 { ++ status = "okay"; ++ ++ ports { ++ port@1 { ++ reg = <1>; ++ rcar_dw_hdmi1_out: endpoint { ++ remote-endpoint = <&hdmi1_con>; ++ }; ++ }; ++ }; ++}; ++ ++&hdmi1_con { ++ remote-endpoint = <&rcar_dw_hdmi1_out>; ++}; ++ ++&pfc { ++ scif1_pins: scif1 { ++ groups = "scif1_data_a"; ++ function = "scif1"; ++ }; ++ ++ msiof0_pins: spi1 { ++ groups = "msiof0_clk", "msiof0_rxd", "msiof0_txd", ++ "msiof0_ss1"; ++ function = "msiof0"; ++ }; ++ ++ msiof1_pins: spi2 { ++ groups = "msiof1_clk_a", "msiof1_rxd_a", "msiof1_txd_a", ++ "msiof1_ss1_a"; ++ function = "msiof1"; ++ }; ++ ++ sound_clk_pins: sound-clk { ++ groups = "audio_clk_a_a", "audio_clk_b_a", "audio_clk_c_a", ++ "audio_clkout_a" /*, "audio_clkout3_a"*/; ++ function = "audio_clk"; ++ }; ++ ++ usb31_pins: usb31 { ++ groups = "usb31"; ++ function = "usb31"; ++ }; ++ ++ can0_pins: can0 { ++ groups = "can0_data_a"; ++ function = "can0"; ++ }; ++ ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_a"; ++ function = "canfd0"; ++ }; ++}; ++ ++&scif1 { ++ pinctrl-0 = <&scif1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&avb { ++ /delete-property/phy-handle; ++ /delete-property/phy-gpios; ++ /delete-node/ethernet-phy@0; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++}; ++ ++&msiof0 { ++ pinctrl-0 = <&msiof0_pins>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ cs-gpios = <&gpio5 19 0>; ++ ++ spidev@0 { ++ compatible = "renesas,sh-msiof"; ++ reg = <0>; ++ spi-max-frequency = <66666666>; ++ spi-cpha; ++ spi-cpol; ++ }; ++}; ++ ++&msiof1 { ++ status = "disabled"; ++ cs-gpios = <&gpio6 5 0>; ++}; ++ ++&can0 { ++ pinctrl-0 = <&can0_pins>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ ++ renesas,can-clock-select = <0x0>; ++ gpios = <&gpio2 6 GPIO_ACTIVE_HIGH /* enable - shared with camera board */ ++ &gpio2 7 GPIO_ACTIVE_LOW /* standby */ ++ >; ++}; ++ ++&canfd { ++ pinctrl-0 = <&canfd0_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ renesas,can-clock-select = <0x0>; ++ gpios = <&gpio2 6 GPIO_ACTIVE_HIGH /* enable - shared with camera board */ ++ &gpio2 7 GPIO_ACTIVE_LOW /* standby */ ++ >; ++ ++ channel0 { ++ status = "okay"; ++ }; ++}; ++ ++&xhci1 { ++ status = "okay"; ++ pinctrl-0 = <&usb31_pins>; ++ pinctrl-names = "default"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts +index 2f24dfc..88fee1f 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts +@@ -14,3 +14,28 @@ + compatible = "shimafuji,kingfisher", "renesas,h3ulcb", + "renesas,r8a7795"; + }; ++ ++&du { ++ ports { ++ port@0 { ++ endpoint { ++ remote-endpoint = <&adv7513_in>; ++ }; ++ }; ++ }; ++}; ++ ++&lvds0 { ++ status = "okay"; ++ ++ ports { ++ port@1 { ++ lvds0_out: endpoint { ++ remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++}; ++ ++/* use CN11 instead default CN29/CN48 (H3 only) */ ++//#include "ulcb-kf-cn11.dtsi" +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-vb.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-vb.dts +new file mode 100644 +index 0000000..db9f80f +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-vb.dts +@@ -0,0 +1,69 @@ ++/* ++ * Device Tree Source for the H3ULCB Videobox board on r8a7795 ES1.x ++ * ++ * Copyright (C) 2017 Renesas Electronics Corp. ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-es1-h3ulcb.dts" ++#include "ulcb-vb.dtsi" ++ ++/ { ++ model = "Renesas H3ULCB Videobox board based on r8a7795"; ++ ++ hdmi1-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi1_con: endpoint { ++ remote-endpoint = <&rcar_dw_hdmi1_out>; ++ }; ++ }; ++ }; ++}; ++ ++&du { ++ ports { ++ port@2 { ++ endpoint { ++ remote-endpoint = <&rcar_dw_hdmi1_in>; ++ }; ++ }; ++ port@3 { ++ endpoint { ++ remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++}; ++ ++&hdmi1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ rcar_dw_hdmi1_in: endpoint { ++ remote-endpoint = <&du_out_hdmi1>; ++ }; ++ }; ++ port@1 { ++ reg = <1>; ++ rcar_dw_hdmi1_out: endpoint { ++ remote-endpoint = <&hdmi1_con>; ++ }; ++ }; ++ }; ++}; ++ ++&hsusb { ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-vb2.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-vb2.dts +new file mode 100644 +index 0000000..6d51ffd +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-vb2.dts +@@ -0,0 +1,77 @@ ++/* ++ * Device Tree Source for the H3ULCB Videobox board V2 on r8a7795 ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-es1-h3ulcb.dts" ++#include "ulcb-vb2.dtsi" ++ ++/ { ++ model = "Renesas H3ULCB Videobox board based on r8a7795"; ++ ++ hdmi1-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi1_con: endpoint { ++ remote-endpoint = <&rcar_dw_hdmi1_out>; ++ }; ++ }; ++ }; ++}; ++ ++&pfc { ++ usb31_pins: usb31 { ++ groups = "usb31"; ++ function = "usb31"; ++ }; ++}; ++ ++&du { ++ ports { ++ port@2 { ++ endpoint { ++ remote-endpoint = <&rcar_dw_hdmi1_in>; ++ }; ++ }; ++ port@3 { ++ endpoint { ++ remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++}; ++ ++&hdmi1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ rcar_dw_hdmi1_in: endpoint { ++ remote-endpoint = <&du_out_hdmi1>; ++ }; ++ }; ++ port@1 { ++ reg = <1>; ++ rcar_dw_hdmi1_out: endpoint { ++ remote-endpoint = <&hdmi1_con>; ++ }; ++ }; ++ }; ++}; ++ ++&xhci1 { ++ status = "okay"; ++ pinctrl-0 = <&usb31_pins>; ++ pinctrl-names = "default"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-vbm.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-vbm.dts +new file mode 100644 +index 0000000..64815d4 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-vbm.dts +@@ -0,0 +1,26 @@ ++/* ++ * Device Tree Source for the H3ULCB Videobox Mini board on r8a7795 ES1.x ++ * ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-es1-h3ulcb.dts" ++#include "ulcb-vbm.dtsi" ++ ++/ { ++ model = "Renesas H3ULCB Videobox Mini board based on r8a7795"; ++}; ++ ++&du { ++ ports { ++ port@3 { ++ endpoint { ++ remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts +new file mode 100644 +index 0000000..1ce261d +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts +@@ -0,0 +1,544 @@ ++/* ++ * Device Tree Source for the H3ULCB.View board on r8a7795 ES1.x ++ * ++ * Copyright (C) 2016-2017 Renesas Electronics Corp. ++ * Copyright (C) 2016-2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-es1-h3ulcb.dts" ++ ++/ { ++ model = "Renesas H3ULCB.View board based on r8a7795"; ++}; ++ ++&i2c4 { ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_des0ep3: endpoint { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++ ++ ov106xx@4 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x64>; ++ ++ port@0 { ++ ov106xx_in4: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@5 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x65>; ++ ++ port@0 { ++ ov106xx_in5: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin5ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@6 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x66>; ++ ++ port@0 { ++ ov106xx_in6: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin6ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@7 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x67>; ++ ++ port@0 { ++ ov106xx_in7: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin7ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_des1ep3: endpoint { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ }; ++ }; ++ ++ max9286@0 { ++ compatible = "maxim,max9286"; ++ reg = <0x4c>; ++ gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ maxim,i2c-quirk = <0x6c>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ }; ++ ++ max9286@1 { ++ compatible = "maxim,max9286"; ++ reg = <0x6c>; ++ gpios = <&gpio5 25 GPIO_ACTIVE_HIGH>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ port@0 { ++ max9286_des1ep0: endpoint@0 { ++ max9271-addr = <0x54>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in4>; ++ }; ++ max9286_des1ep1: endpoint@1 { ++ max9271-addr = <0x55>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ }; ++ max9286_des1ep2: endpoint@2 { ++ max9271-addr = <0x56>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in6>; ++ }; ++ max9286_des1ep3: endpoint@3 { ++ max9271-addr = <0x57>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in7>; ++ }; ++ }; ++ port@1 { ++ max9286_csi2ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ }; ++}; ++ ++&pcie_bus_clk { ++ clock-frequency = <100000000>; ++ status = "okay"; ++}; ++ ++&pciec1 { ++ status = "okay"; ++}; ++ ++&vin0 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin2_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin3_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&vin4 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin4ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <0>; ++ remote-endpoint = <&ov106xx_in4>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep0: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin4_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin5 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin5ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep1: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin5_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin6 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin6ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <2>; ++ remote-endpoint = <&ov106xx_in6>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep2: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin6_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin7 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin7ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <3>; ++ remote-endpoint = <&ov106xx_in7>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep3: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin7_max9286_des1ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&csi40 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&csi41 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi41_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts +new file mode 100644 +index 0000000..9a7487c +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts +@@ -0,0 +1,550 @@ ++/* ++ * Device Tree Source for the Salvator-X.View board on r8a7795 ES1.x ++ * ++ * Copyright (C) 2016-2017 Renesas Electronics Corp. ++ * Copyright (C) 2015-2017 Cogent Embedded, Inc ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-es1-salvator-x.dts" ++ ++/ { ++ model = "Renesas Salvator-X.View board based on r8a7795"; ++}; ++ ++&pfc { ++ can0_pins: can0 { ++ groups = "can0_data_a"; ++ function = "can0"; ++ }; ++ ++ can1_pins: can1 { ++ groups = "can1_data"; ++ function = "can1"; ++ }; ++}; ++ ++&i2c4 { ++ /delete-node/hdmi-in@34; ++ /delete-node/composite-in@70; ++ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_des0ep3: endpoint { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++ ++ ov106xx@4 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x64>; ++ ++ port@0 { ++ ov106xx_in4: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@5 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x65>; ++ ++ port@0 { ++ ov106xx_in5: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin5ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@6 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x66>; ++ ++ port@0 { ++ ov106xx_in6: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin6ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@7 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x67>; ++ ++ port@0 { ++ ov106xx_in7: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin7ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_des1ep3: endpoint { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ }; ++ }; ++ ++ max9286@0 { ++ compatible = "maxim,max9286"; ++ reg = <0x4c>; ++ gpios = <&gpio6 30 GPIO_ACTIVE_LOW>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ maxim,i2c-quirk = <0x6c>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ }; ++ ++ max9286@1 { ++ compatible = "maxim,max9286"; ++ reg = <0x6c>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ port@0 { ++ max9286_des1ep0: endpoint@0 { ++ max9271-addr = <0x54>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in4>; ++ }; ++ max9286_des1ep1: endpoint@1 { ++ max9271-addr = <0x55>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ }; ++ max9286_des1ep2: endpoint@2 { ++ max9271-addr = <0x56>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in6>; ++ }; ++ max9286_des1ep3: endpoint@3 { ++ max9271-addr = <0x57>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in7>; ++ }; ++ }; ++ port@1 { ++ max9286_csi2ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ }; ++}; ++ ++&vin0 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin2_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin3_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&vin4 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin4ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <0>; ++ remote-endpoint = <&ov106xx_in4>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep0: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin4_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin5 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin5ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep1: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin5_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin6 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin6ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <2>; ++ remote-endpoint = <&ov106xx_in6>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep2: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin6_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin7 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin7ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <3>; ++ remote-endpoint = <&ov106xx_in7>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep3: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin7_max9286_des1ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&csi20 { ++ status = "disabled"; ++ /delete-node/ports; ++}; ++ ++&csi40 { ++ /delete-node/ports; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&csi41 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi41_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&can0 { ++ pinctrl-0 = <&can0_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&can1 { ++ pinctrl-0 = <&can1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-4x2g-kf.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-4x2g-kf.dts +new file mode 100644 +index 0000000..5e391ae +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-4x2g-kf.dts +@@ -0,0 +1,44 @@ ++/* ++ * Device Tree Source for the H3ULCB Kingfisher board ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-h3ulcb-4x2g.dts" ++#include "ulcb-kf.dtsi" ++ ++/ { ++ model = "Renesas H3ULCB Kingfisher board based on r8a7795 ES2.0+"; ++ compatible = "shimafuji,kingfisher", "renesas,h3ulcb", ++ "renesas,r8a7795"; ++}; ++ ++&du { ++ ports { ++ port@0 { ++ endpoint { ++ remote-endpoint = <&adv7513_in>; ++ }; ++ }; ++ }; ++}; ++ ++&lvds0 { ++ status = "okay"; ++ ++ ports { ++ port@1 { ++ lvds0_out: endpoint { ++ remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++}; ++ ++/* use CN11 instead default CN29/CN48 (H3 only) */ ++//#include "ulcb-kf-cn11.dtsi" +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-4x2g-vb.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-4x2g-vb.dts +new file mode 100644 +index 0000000..ce16cab +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-4x2g-vb.dts +@@ -0,0 +1,68 @@ ++/* ++ * Device Tree Source for the H3ULCB Videobox board on r8a7795 ++ * ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-h3ulcb-4x2g.dts" ++#include "ulcb-vb.dtsi" ++ ++/ { ++ model = "Renesas H3ULCB with 8GiB (4 x 2 GiB) Videobox board based on r8a7795"; ++ ++ hdmi1-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi1_con: endpoint { ++ remote-endpoint = <&rcar_dw_hdmi1_out>; ++ }; ++ }; ++ }; ++}; ++ ++&du { ++ ports { ++ port@2 { ++ endpoint { ++ remote-endpoint = <&rcar_dw_hdmi1_in>; ++ }; ++ }; ++ port@3 { ++ endpoint { ++ remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++}; ++ ++&hdmi1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ rcar_dw_hdmi1_in: endpoint { ++ remote-endpoint = <&du_out_hdmi1>; ++ }; ++ }; ++ port@1 { ++ reg = <1>; ++ rcar_dw_hdmi1_out: endpoint { ++ remote-endpoint = <&hdmi1_con>; ++ }; ++ }; ++ }; ++}; ++ ++&hsusb { ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-4x2g-vb2.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-4x2g-vb2.dts +new file mode 100644 +index 0000000..1351c6f +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-4x2g-vb2.dts +@@ -0,0 +1,68 @@ ++/* ++ * Device Tree Source for the H3ULCB Videobox board V2 on r8a7795 ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-h3ulcb-4x2g.dts" ++#include "ulcb-vb2.dtsi" ++ ++/ { ++ model = "Renesas H3ULCB with 8GiB (4 x 2 GiB) Videobox board based on r8a7795"; ++ ++ hdmi1-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi1_con: endpoint { ++ remote-endpoint = <&rcar_dw_hdmi1_out>; ++ }; ++ }; ++ }; ++}; ++ ++&du { ++ ports { ++ port@2 { ++ endpoint { ++ remote-endpoint = <&rcar_dw_hdmi1_in>; ++ }; ++ }; ++ port@3 { ++ endpoint { ++ remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++}; ++ ++&hdmi1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ rcar_dw_hdmi1_in: endpoint { ++ remote-endpoint = <&du_out_hdmi1>; ++ }; ++ }; ++ port@1 { ++ reg = <1>; ++ rcar_dw_hdmi1_out: endpoint { ++ remote-endpoint = <&hdmi1_con>; ++ }; ++ }; ++ }; ++}; ++ ++&hsusb { ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-4x2g-vbm.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-4x2g-vbm.dts +new file mode 100644 +index 0000000..352cc0d +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-4x2g-vbm.dts +@@ -0,0 +1,26 @@ ++/* ++ * Device Tree Source for the H3ULCB Videobox Mini board on r8a7795 ES1.x ++ * ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-h3ulcb-4x2g.dts" ++#include "ulcb-vbm.dtsi" ++ ++/ { ++ model = "Renesas H3ULCB with 8GiB (4 x 2 GiB) Videobox Mini board based on r8a7795"; ++}; ++ ++&du { ++ ports { ++ port@3 { ++ endpoint { ++ remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had-alfa.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had-alfa.dts +new file mode 100644 +index 0000000..ae115bd +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had-alfa.dts +@@ -0,0 +1,22 @@ ++/* ++ * Device Tree Source for the H3ULCB.HAD board Alfa side ++ * ++ * Copyright (C) 2017 Renesas Electronics Corp. ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-h3ulcb-had.dtsi" ++ ++/ { ++ model = "Renesas H3ULCB.HAD board Alfa side based on r8a7795"; ++}; ++ ++&pciec0 { ++ status = "okay"; ++ ++ /* Root complex */ ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had-beta.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had-beta.dts +new file mode 100644 +index 0000000..805067e +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had-beta.dts +@@ -0,0 +1,23 @@ ++/* ++ * Device Tree Source for the H3ULCB.HAD board Beta side ++ * ++ * Copyright (C) 2017 Renesas Electronics Corp. ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-h3ulcb-had.dtsi" ++ ++/ { ++ model = "Renesas H3ULCB.HAD board Beta side based on r8a7795"; ++}; ++ ++&pciec0 { ++ status = "okay"; ++ ++ /* Endpoint */ ++ endpoint; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had.dtsi b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had.dtsi +new file mode 100644 +index 0000000..2571de6 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had.dtsi +@@ -0,0 +1,196 @@ ++/* ++ * Device Tree Source for the H3ULCB.HAD board on r8a7795 ++ * ++ * Copyright (C) 2016-2017 Renesas Electronics Corp. ++ * Copyright (C) 2016-2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++/* ++ * MSIOF0 - /dev/spidev1.0 connected to FPGA ethernet switch (both sides) ++ * MSIOF1 - /dev/spidev2.0 connected to RH850 (sideA to CSIH1, sideB to CSIH0) ++ */ ++ ++#include "r8a7795-h3ulcb-view.dts" ++ ++/ { ++ model = "Renesas H3ULCB.HAD board based on r8a7795"; ++ ++ aliases { ++ serial0 = &scif1; ++ spi1 = &spi0_gpio; ++ spi2 = &spi1_gpio; ++ }; ++ ++ spi0_gpio: spi_gpio@0 { ++ compatible = "spi-gpio"; ++ num-chipselects = <1>; ++ gpio-sck = <&gpio5 17 0>; ++ gpio-mosi = <&gpio5 20 0>; ++ gpio-miso = <&gpio5 22 0>; ++ cs-gpios = <&gpio5 19 0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ spidev@0 { ++ compatible = "spi-gpio"; ++ reg = <0>; ++ spi-max-frequency = <2000000>; ++ spi-cpha; ++ spi-cpol; ++ }; ++ }; ++ ++ spi1_gpio: spi_gpio@1 { ++ compatible = "spi-gpio"; ++ num-chipselects = <1>; ++ gpio-sck = <&gpio6 8 0>; ++ gpio-mosi = <&gpio6 7 0>; ++ gpio-miso = <&gpio6 10 0>; ++ cs-gpios = <&gpio6 5 0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ spidev@0 { ++ compatible = "spi-gpio"; ++ reg = <0>; ++ spi-max-frequency = <2000000>; ++ spi-cpha; ++ spi-cpol; ++ }; ++ }; ++ ++ hdmi1-out { ++ compatible = "hdmi-connector"; ++ label = "HDMI1 OUT"; ++ type = "a"; ++ ++ port { ++ hdmi1_con: endpoint { ++ }; ++ }; ++ }; ++}; ++ ++&hdmi1 { ++ status = "okay"; ++ ++ ports { ++ port@1 { ++ reg = <1>; ++ rcar_dw_hdmi1_out: endpoint { ++ remote-endpoint = <&hdmi1_con>; ++ }; ++ }; ++ }; ++}; ++ ++&hdmi1_con { ++ remote-endpoint = <&rcar_dw_hdmi1_out>; ++}; ++ ++&pfc { ++ scif1_pins: scif1 { ++ groups = "scif1_data_a"; ++ function = "scif1"; ++ }; ++ ++ msiof0_pins: spi1 { ++ groups = "msiof0_clk", "msiof0_rxd", "msiof0_txd", ++ "msiof0_ss1"; ++ function = "msiof0"; ++ }; ++ ++ msiof1_pins: spi2 { ++ groups = "msiof1_clk_a", "msiof1_rxd_a", "msiof1_txd_a", ++ "msiof1_ss1_a"; ++ function = "msiof1"; ++ }; ++ ++ sound_clk_pins: sound-clk { ++ groups = "audio_clk_a_a", "audio_clk_b_a", "audio_clk_c_a", ++ "audio_clkout_a" /*, "audio_clkout3_a"*/; ++ function = "audio_clk"; ++ }; ++ ++ usb31_pins: usb31 { ++ groups = "usb31"; ++ function = "usb31"; ++ }; ++ ++ can0_pins: can0 { ++ groups = "can0_data_a"; ++ function = "can0"; ++ }; ++ ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_a"; ++ function = "canfd0"; ++ }; ++}; ++ ++&scif1 { ++ pinctrl-0 = <&scif1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&avb { ++ /delete-property/phy-handle; ++ /delete-property/phy-gpios; ++ /delete-node/ethernet-phy@0; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++}; ++ ++&msiof0 { ++ pinctrl-0 = <&msiof0_pins>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ cs-gpios = <&gpio5 19 0>; ++ ++ spidev@0 { ++ compatible = "renesas,sh-msiof"; ++ reg = <0>; ++ spi-max-frequency = <66666666>; ++ spi-cpha; ++ spi-cpol; ++ }; ++}; ++ ++&msiof1 { ++ status = "disabled"; ++ cs-gpios = <&gpio6 5 0>; ++}; ++ ++&can0 { ++ pinctrl-0 = <&can0_pins>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ ++ renesas,can-clock-select = <0x0>; ++ gpios = <&gpio2 6 GPIO_ACTIVE_HIGH /* enable - shared with camera board */ ++ &gpio2 7 GPIO_ACTIVE_LOW /* standby */ ++ >; ++}; ++ ++&canfd { ++ pinctrl-0 = <&canfd0_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ renesas,can-clock-select = <0x0>; ++ gpios = <&gpio2 6 GPIO_ACTIVE_HIGH /* enable - shared with camera board */ ++ &gpio2 7 GPIO_ACTIVE_LOW /* standby */ ++ >; ++ ++ channel0 { ++ status = "okay"; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts +index 80791ed..c848c0e 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts +@@ -14,3 +14,28 @@ + compatible = "shimafuji,kingfisher", "renesas,h3ulcb", + "renesas,r8a7795"; + }; ++ ++&du { ++ ports { ++ port@0 { ++ endpoint { ++ remote-endpoint = <&adv7513_in>; ++ }; ++ }; ++ }; ++}; ++ ++&lvds0 { ++ status = "okay"; ++ ++ ports { ++ port@1 { ++ lvds0_out: endpoint { ++ remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++}; ++ ++/* use CN11 instead default CN29/CN48 (H3 only) */ ++//#include "ulcb-kf-cn11.dtsi" +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb.dts +new file mode 100644 +index 0000000..26c15f4 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb.dts +@@ -0,0 +1,68 @@ ++/* ++ * Device Tree Source for the H3ULCB Videobox board on r8a7795 ++ * ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-h3ulcb.dts" ++#include "ulcb-vb.dtsi" ++ ++/ { ++ model = "Renesas H3ULCB Videobox board based on r8a7795"; ++ ++ hdmi1-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi1_con: endpoint { ++ remote-endpoint = <&rcar_dw_hdmi1_out>; ++ }; ++ }; ++ }; ++}; ++ ++&du { ++ ports { ++ port@2 { ++ endpoint { ++ remote-endpoint = <&rcar_dw_hdmi1_in>; ++ }; ++ }; ++ port@3 { ++ endpoint { ++ remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++}; ++ ++&hdmi1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ rcar_dw_hdmi1_in: endpoint { ++ remote-endpoint = <&du_out_hdmi1>; ++ }; ++ }; ++ port@1 { ++ reg = <1>; ++ rcar_dw_hdmi1_out: endpoint { ++ remote-endpoint = <&hdmi1_con>; ++ }; ++ }; ++ }; ++}; ++ ++&hsusb { ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb2.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb2.dts +new file mode 100644 +index 0000000..816c7da +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb2.dts +@@ -0,0 +1,68 @@ ++/* ++ * Device Tree Source for the H3ULCB Videobox board V2 on r8a7795 ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-h3ulcb.dts" ++#include "ulcb-vb2.dtsi" ++ ++/ { ++ model = "Renesas H3ULCB Videobox board based on r8a7795"; ++ ++ hdmi1-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi1_con: endpoint { ++ remote-endpoint = <&rcar_dw_hdmi1_out>; ++ }; ++ }; ++ }; ++}; ++ ++&du { ++ ports { ++ port@2 { ++ endpoint { ++ remote-endpoint = <&rcar_dw_hdmi1_in>; ++ }; ++ }; ++ port@3 { ++ endpoint { ++ remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++}; ++ ++&hdmi1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ rcar_dw_hdmi1_in: endpoint { ++ remote-endpoint = <&du_out_hdmi1>; ++ }; ++ }; ++ port@1 { ++ reg = <1>; ++ rcar_dw_hdmi1_out: endpoint { ++ remote-endpoint = <&hdmi1_con>; ++ }; ++ }; ++ }; ++}; ++ ++&hsusb { ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vbm.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vbm.dts +new file mode 100644 +index 0000000..053a60e +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vbm.dts +@@ -0,0 +1,26 @@ ++/* ++ * Device Tree Source for the H3ULCB Videobox Mini board on r8a7795 ES1.x ++ * ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-h3ulcb.dts" ++#include "ulcb-vbm.dtsi" ++ ++/ { ++ model = "Renesas H3ULCB Videobox Mini board based on r8a7795"; ++}; ++ ++&du { ++ ports { ++ port@3 { ++ endpoint { ++ remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts +new file mode 100644 +index 0000000..ae90fb89 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts +@@ -0,0 +1,544 @@ ++/* ++ * Device Tree Source for the H3ULCB.View board ++ * ++ * Copyright (C) 2016-2017 Renesas Electronics Corp. ++ * Copyright (C) 2016-2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-h3ulcb.dts" ++ ++/ { ++ model = "Renesas H3ULCB.View board based on r8a7795"; ++}; ++ ++&i2c4 { ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_des0ep3: endpoint { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++ ++ ov106xx@4 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x64>; ++ ++ port@0 { ++ ov106xx_in4: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@5 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x65>; ++ ++ port@0 { ++ ov106xx_in5: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin5ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@6 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x66>; ++ ++ port@0 { ++ ov106xx_in6: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin6ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@7 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x67>; ++ ++ port@0 { ++ ov106xx_in7: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin7ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_des1ep3: endpoint { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ }; ++ }; ++ ++ max9286@0 { ++ compatible = "maxim,max9286"; ++ reg = <0x4c>; ++ gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ maxim,i2c-quirk = <0x6c>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ }; ++ ++ max9286@1 { ++ compatible = "maxim,max9286"; ++ reg = <0x6c>; ++ gpios = <&gpio5 25 GPIO_ACTIVE_HIGH>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ port@0 { ++ max9286_des1ep0: endpoint@0 { ++ max9271-addr = <0x54>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in4>; ++ }; ++ max9286_des1ep1: endpoint@1 { ++ max9271-addr = <0x55>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ }; ++ max9286_des1ep2: endpoint@2 { ++ max9271-addr = <0x56>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in6>; ++ }; ++ max9286_des1ep3: endpoint@3 { ++ max9271-addr = <0x57>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in7>; ++ }; ++ }; ++ port@1 { ++ max9286_csi2ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ }; ++}; ++ ++&pcie_bus_clk { ++ clock-frequency = <100000000>; ++ status = "okay"; ++}; ++ ++&pciec1 { ++ status = "okay"; ++}; ++ ++&vin0 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin2_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin3_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&vin4 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin4ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <0>; ++ remote-endpoint = <&ov106xx_in4>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep0: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin4_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin5 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin5ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep1: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin5_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin6 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin6ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <2>; ++ remote-endpoint = <&ov106xx_in6>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep2: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin6_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin7 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin7ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <3>; ++ remote-endpoint = <&ov106xx_in7>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep3: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin7_max9286_des1ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&csi40 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&csi41 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi41_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts +new file mode 100644 +index 0000000..d4d5557 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts +@@ -0,0 +1,550 @@ ++/* ++ * Device Tree Source for the Salvator-X.View board ++ * ++ * Copyright (C) 2016-2017 Renesas Electronics Corp. ++ * Copyright (C) 2015-2017 Cogent Embedded, Inc ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-salvator-x.dts" ++ ++/ { ++ model = "Renesas Salvator-X.View board based on r8a7795"; ++}; ++ ++&pfc { ++ can0_pins: can0 { ++ groups = "can0_data_a"; ++ function = "can0"; ++ }; ++ ++ can1_pins: can1 { ++ groups = "can1_data"; ++ function = "can1"; ++ }; ++}; ++ ++&i2c4 { ++ /delete-node/hdmi-in@34; ++ /delete-node/composite-in@70; ++ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_des0ep3: endpoint { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++ ++ ov106xx@4 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x64>; ++ ++ port@0 { ++ ov106xx_in4: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@5 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x65>; ++ ++ port@0 { ++ ov106xx_in5: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin5ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@6 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x66>; ++ ++ port@0 { ++ ov106xx_in6: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin6ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@7 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x67>; ++ ++ port@0 { ++ ov106xx_in7: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin7ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_des1ep3: endpoint { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ }; ++ }; ++ ++ max9286@0 { ++ compatible = "maxim,max9286"; ++ reg = <0x4c>; ++ gpios = <&gpio6 30 GPIO_ACTIVE_LOW>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ maxim,i2c-quirk = <0x6c>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ }; ++ ++ max9286@1 { ++ compatible = "maxim,max9286"; ++ reg = <0x6c>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ port@0 { ++ max9286_des1ep0: endpoint@0 { ++ max9271-addr = <0x54>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in4>; ++ }; ++ max9286_des1ep1: endpoint@1 { ++ max9271-addr = <0x55>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ }; ++ max9286_des1ep2: endpoint@2 { ++ max9271-addr = <0x56>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in6>; ++ }; ++ max9286_des1ep3: endpoint@3 { ++ max9271-addr = <0x57>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in7>; ++ }; ++ }; ++ port@1 { ++ max9286_csi2ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ }; ++}; ++ ++&vin0 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin2_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin3_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&vin4 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin4ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <0>; ++ remote-endpoint = <&ov106xx_in4>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep0: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin4_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin5 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin5ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep1: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin5_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin6 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin6ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <2>; ++ remote-endpoint = <&ov106xx_in6>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep2: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin6_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin7 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin7ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <3>; ++ remote-endpoint = <&ov106xx_in7>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep3: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin7_max9286_des1ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&csi20 { ++ status = "disabled"; ++ /delete-node/ports; ++}; ++ ++&csi40 { ++ /delete-node/ports; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&csi41 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi41_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&can0 { ++ pinctrl-0 = <&can0_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&can1 { ++ pinctrl-0 = <&can1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts +index 2df50eb..803d3e1 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts +@@ -14,3 +14,29 @@ + compatible = "shimafuji,kingfisher", "renesas,m3ulcb", + "renesas,r8a7796"; + }; ++ ++&du { ++ ports { ++ port@0 { ++ endpoint { ++ remote-endpoint = <&adv7513_in>; ++ }; ++ }; ++ }; ++}; ++ ++&lvds0 { ++ status = "okay"; ++ ++ ports { ++ port@1 { ++ lvds0_out: endpoint { ++ remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++}; ++ ++&xhci0 { ++ status = "disabled"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts +new file mode 100644 +index 0000000..9e764c5 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts +@@ -0,0 +1,286 @@ ++/* ++ * Device Tree Source for the M3ULCB.View board on r8a7796 ++ * ++ * Copyright (C) 2016-2017 Renesas Electronics Corp. ++ * Copyright (C) 2016-2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7796-m3ulcb.dts" ++ ++/ { ++ model = "Renesas M3ULCB.View board based on r8a7796"; ++}; ++ ++&i2c4 { ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_des0ep3: endpoint { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++ ++ max9286@0 { ++ compatible = "maxim,max9286"; ++ reg = <0x4c>; ++ gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ maxim,i2c-quirk = <0x6c>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ }; ++}; ++ ++&pcie_bus_clk { ++ clock-frequency = <100000000>; ++ status = "okay"; ++}; ++ ++&pciec1 { ++ status = "okay"; ++}; ++ ++&vin0 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin2_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin3_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&csi40 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts +new file mode 100644 +index 0000000..f734437 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts +@@ -0,0 +1,317 @@ ++/* ++ * Device Tree Source for the Salvator-X.View board ++ * ++ * Copyright (C) 2016-2017 Renesas Electronics Corp. ++ * Copyright (C) 2016-2017 Cogent Embedded, Inc ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7796-salvator-x.dts" ++ ++/ { ++ model = "Renesas Salvator-X.View board based on r8a7796"; ++}; ++ ++&pfc { ++ can0_pins: can0 { ++ groups = "can0_data_a"; ++ function = "can0"; ++ }; ++ ++ can1_pins: can1 { ++ groups = "can1_data"; ++ function = "can1"; ++ }; ++}; ++ ++&i2c4 { ++ /delete-node/hdmi-in@34; ++ /delete-node/composite-in@70; ++ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_des0ep3: endpoint { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++ ++ max9286@0 { ++ compatible = "maxim,max9286"; ++ reg = <0x4c>; ++ gpios = <&gpio6 30 GPIO_ACTIVE_LOW>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ maxim,i2c-quirk = <0x6c>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ }; ++}; ++ ++&vin0 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin2_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin3_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&vin4 { ++ status = "disabled"; ++}; ++ ++&vin5 { ++ status = "disabled"; ++}; ++ ++&vin6 { ++ status = "disabled"; ++}; ++ ++&vin7 { ++ status = "disabled"; ++}; ++ ++&csi20 { ++ status = "disabled"; ++ /delete-node/ports; ++}; ++ ++&csi40 { ++ /delete-node/ports; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&can0 { ++ pinctrl-0 = <&can0_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&can1 { ++ pinctrl-0 = <&can1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a77965-m3nulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a77965-m3nulcb-kf.dts +new file mode 100644 +index 0000000..806c873 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a77965-m3nulcb-kf.dts +@@ -0,0 +1,41 @@ ++/* ++ * Device Tree Source for the M3NULCB Kingfisher board ++ * ++ * Copyright (C) 2017 Renesas Electronics Corp. ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a77965-m3nulcb.dts" ++#include "ulcb-kf.dtsi" ++ ++/ { ++ model = "Renesas M3NULCB Kingfisher board based on r8a77965 ES1.1"; ++ compatible = "shimafuji,kingfisher", "renesas,m3nulcb", ++ "renesas,r8a77965"; ++}; ++ ++&du { ++ ports { ++ port@0 { ++ endpoint { ++ remote-endpoint = <&adv7513_in>; ++ }; ++ }; ++ }; ++}; ++ ++&lvds0 { ++ status = "okay"; ++ ++ ports { ++ port@1 { ++ lvds0_out: endpoint { ++ remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-eagle-function.dts b/arch/arm64/boot/dts/renesas/r8a77970-eagle-function.dts +new file mode 100644 +index 0000000..9043a07 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a77970-eagle-function.dts +@@ -0,0 +1,62 @@ ++/* ++ * Device Tree Source for the Eagle Function board on r8a7797 ++ * ++ * Copyright (C) 2017 Renesas Electronics Corp. ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a77970-eagle.dts" ++ ++/ { ++ model = "Renesas Eagle Function board based on r8a7797"; ++ ++ vcc_3v3: regulator0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-VCC3V3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ vcc_vddq_vin0: regulator1 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VCC-VDDQ-VIN0"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++}; ++ ++&pfc { ++ sdhi2_pins_1v8: sdhi2_1v8 { ++ groups = "mmc_data8", "mmc_ctrl"; ++ function = "mmc"; ++ power-source = <1800>; ++ }; ++ ++ sdhi2_pins_3v3: sdhi2_3v3 { ++ groups = "mmc_data8", "mmc_ctrl"; ++ function = "mmc"; ++ power-source = <3300>; ++ }; ++}; ++ ++&sdhi2 { ++ /* used for on-board eMMC */ ++ pinctrl-0 = <&sdhi2_pins_3v3>; ++ pinctrl-1 = <&sdhi2_pins_1v8>; ++ pinctrl-names = "default", "state_uhs"; ++ ++ vmmc-supply = <&vcc_3v3>; ++ vqmmc-supply = <&vcc_vddq_vin0>; ++ mmc-hs200-1_8v; ++ bus-width = <8>; ++ non-removable; ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +index b6d5332..6338ab3 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +@@ -8,6 +8,7 @@ + + /dts-v1/; + #include "r8a77970.dtsi" ++#include + + / { + model = "Renesas Eagle board based on r8a77970"; +@@ -29,6 +30,58 @@ + reg = <0x0 0x48000000 0x0 0x38000000>; + }; + ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ /* device specific region for Lossy Decompression */ ++ lossy_decompress: linux,lossy_decompress { ++ no-map; ++ reg = <0x00000000 0x6c000000 0x0 0x03000000>; ++ }; ++ ++ /* global autoconfigured region for contiguous allocations */ ++ linux,cma { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x6f000000 0x0 0x10000000>; ++ linux,cma-default; ++ }; ++ ++ /* device specific region for contiguous allocations */ ++ linux,multimedia { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x7f000000 0x0 0x01000000>; ++ }; ++ }; ++ ++ mmngr { ++ compatible = "renesas,mmngr"; ++ memory-region = <&lossy_decompress>; ++ }; ++ ++ mmngrbuf { ++ compatible = "renesas,mmngrbuf"; ++ }; ++ ++ vspm_if { ++ compatible = "renesas,vspm_if"; ++ }; ++ ++ dclkin_p0: clock-out0 { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <148500000>; ++ }; ++ ++ msiof_ref_clk: msiof-ref-clock { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <66666666>; ++ }; ++ + hdmi-out { + compatible = "hdmi-connector"; + type = "a"; +@@ -102,6 +155,40 @@ + }; + }; + ++&csi40 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ + &extal_clk { + clock-frequency = <16666666>; + }; +@@ -155,6 +242,158 @@ + }; + }; + }; ++ ++ pmic@5A { ++ compatible = "dlg,da9063"; ++ reg = <0x5A>; ++ interrupt-parent = <&intc_ex>; ++ interrupts = <0 IRQ_TYPE_LEVEL_LOW>; ++ interrupt-controller; ++ ++ rtc { ++ compatible = "dlg,da9063-rtc"; ++ }; ++ ++ wdt { ++ compatible = "dlg,da9063-watchdog"; ++ }; ++ ++ regulators { ++ DA9063_LDO11: bmem { ++ regulator-name = "bmem"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ }; ++ ++ onkey { ++ compatible = "dlg,da9063-onkey"; ++ }; ++ }; ++}; ++ ++&i2c3 { ++ pinctrl-0 = <&i2c3_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ clock-frequency = <400000>; ++ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_des0ep3: endpoint { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++ ++ max9286@0 { ++ compatible = "maxim,max9286"; ++ reg = <0x48>; ++ gpios = <&io_expander 0 GPIO_ACTIVE_LOW>; /* CSI0 DE_PDn */ ++ maxim,gpio0 = <0>; ++ maxim,sensor_delay = <100>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ }; + }; + + &pfc { +@@ -173,6 +412,11 @@ + function = "i2c0"; + }; + ++ i2c3_pins: i2c3 { ++ groups = "i2c3"; ++ function = "i2c3"; ++ }; ++ + scif0_pins: scif0 { + groups = "scif0_data"; + function = "scif0"; +@@ -191,6 +435,118 @@ + status = "okay"; + }; + ++&vin0 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin2_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin3_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++}; ++ + &du { + status = "okay"; + }; +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-es1-eagle-function.dts b/arch/arm64/boot/dts/renesas/r8a77970-es1-eagle-function.dts +new file mode 100644 +index 0000000..b7e74f3 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a77970-es1-eagle-function.dts +@@ -0,0 +1,17 @@ ++/* ++ * Device Tree Source for the Eagle Function board on r8a7797 ES1.0 ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a77970-eagle-function.dts" ++#include "r8a77970-es1.dtsi" ++ ++/ { ++ model = "Renesas Eagle Function board based on r8a7797 ES1.0"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-es1-eagle.dts b/arch/arm64/boot/dts/renesas/r8a77970-es1-eagle.dts +new file mode 100644 +index 0000000..13e0a19 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a77970-es1-eagle.dts +@@ -0,0 +1,17 @@ ++/* ++ * Device Tree Source for the Eagle board on r8a7797 ES1.0 ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a77970-eagle.dts" ++#include "r8a77970-es1.dtsi" ++ ++/ { ++ model = "Renesas Eagle board based on r8a7797 ES1.0"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-es1-v3msk-kf.dts b/arch/arm64/boot/dts/renesas/r8a77970-es1-v3msk-kf.dts +new file mode 100644 +index 0000000..8266db1 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a77970-es1-v3msk-kf.dts +@@ -0,0 +1,17 @@ ++/* ++ * Device Tree Source for the V3MSK Kingfisher board on r8a7797 ES1.0 ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a77970-v3msk-kf.dts" ++#include "r8a77970-es1.dtsi" ++ ++/ { ++ model = "Renesas V3MSK Kingfisher board based on r8a7797 ES1.0"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-es1-v3msk-vbm-v2.dts b/arch/arm64/boot/dts/renesas/r8a77970-es1-v3msk-vbm-v2.dts +new file mode 100644 +index 0000000..3b6f1ae +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a77970-es1-v3msk-vbm-v2.dts +@@ -0,0 +1,17 @@ ++/* ++ * Device Tree Source for the V3MSK Videobox Mini V2 board on r8a7797 ES1.0 ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a77970-v3msk-vbm-v2.dts" ++#include "r8a77970-es1.dtsi" ++ ++/ { ++ model = "Renesas V3MSK Videobox Mini V2 board based on r8a7797 ES1.0"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-es1-v3msk-vbm.dts b/arch/arm64/boot/dts/renesas/r8a77970-es1-v3msk-vbm.dts +new file mode 100644 +index 0000000..7c1c554 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a77970-es1-v3msk-vbm.dts +@@ -0,0 +1,17 @@ ++/* ++ * Device Tree Source for the V3MSK Videobox Mini board on r8a7797 ES1.0 ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a77970-v3msk-vbm.dts" ++#include "r8a77970-es1.dtsi" ++ ++/ { ++ model = "Renesas V3MSK Videobox Mini board based on r8a7797 ES1.0"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-es1-v3msk-view.dts b/arch/arm64/boot/dts/renesas/r8a77970-es1-v3msk-view.dts +new file mode 100644 +index 0000000..8f93e31 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a77970-es1-v3msk-view.dts +@@ -0,0 +1,17 @@ ++/* ++ * Device Tree Source for the V3MSK View board on r8a7797 ES1.0 ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a77970-v3msk-view.dts" ++#include "r8a77970-es1.dtsi" ++ ++/ { ++ model = "Renesas V3MSK View board based on r8a7797 ES1.0"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-es1-v3msk.dts b/arch/arm64/boot/dts/renesas/r8a77970-es1-v3msk.dts +new file mode 100644 +index 0000000..1d955f3 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a77970-es1-v3msk.dts +@@ -0,0 +1,17 @@ ++/* ++ * Device Tree Source for the V3M Starter Kit board on r8a7797 ES1.0 ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a77970-v3msk.dts" ++#include "r8a77970-es1.dtsi" ++ ++/ { ++ model = "Renesas V3M Starter Kit board based on r8a7797 ES1.0"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-es1.dtsi b/arch/arm64/boot/dts/renesas/r8a77970-es1.dtsi +new file mode 100644 +index 0000000..dab9adc +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a77970-es1.dtsi +@@ -0,0 +1,116 @@ ++/* ++ * Device Tree Source for the r8a7797 SoC ES1.0 SoC ++ * (append to r8a7797 SoC ES2.0 SoC) ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++/ { ++ soc { ++ imp_distributer: impdes0 { ++ compatible = "renesas,impx4-distributer"; ++ reg = <0 0xffa00000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 830>; ++ power-domains = <&sysc R8A7797_PD_A3IR>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ imp0 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff900000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <0>; ++ clocks = <&cpg CPG_MOD 827>; ++ power-domains = <&sysc R8A7797_PD_A2IR0>; ++ }; ++ ++ imp1 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff920000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <1>; ++ clocks = <&cpg CPG_MOD 826>; ++ power-domains = <&sysc R8A7797_PD_A2IR1>; ++ }; ++ ++ imp2 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff940000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <2>; ++ clocks = <&cpg CPG_MOD 825>; ++ power-domains = <&sysc R8A7797_PD_A2IR2>; ++ }; ++ ++ imp3 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff960000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <3>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7797_PD_A2IR3>; ++ }; ++ ++ impsc0 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff980000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <4>; ++ clocks = <&cpg CPG_MOD 829>; ++ power-domains = <&sysc R8A7797_PD_A2SC0>; ++ }; ++ ++ impsc1 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff990000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <5>; ++ clocks = <&cpg CPG_MOD 828>; ++ power-domains = <&sysc R8A7797_PD_A2SC1>; ++ }; ++ ++ impdm0 { ++ compatible = "renesas,impx5-dmac"; ++ reg = <0 0xffa10000 0 0x1000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <16>; ++ clocks = <&cpg CPG_MOD 830>; ++ power-domains = <&sysc R8A7797_PD_A3IR>; ++ }; ++ ++ impdm1 { ++ compatible = "renesas,impx5-dmac"; ++ reg = <0 0xffa10000 0 0x1000>, ++ <0 0xffa10800 0 0x0800>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <17>; ++ clocks = <&cpg CPG_MOD 830>; ++ power-domains = <&sysc R8A7797_PD_A3IR>; ++ }; ++ ++ imppsc0 { ++ compatible = "renesas,impx5+-psc"; ++ reg = <0 0xffa20000 0 0x4000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <12>; ++ clocks = <&cpg CPG_MOD 830>; ++ power-domains = <&sysc R8A7797_PD_A3IR>; ++ }; ++ ++ /delete-node/impcnn0; ++ ++ impc0 { ++ compatible = "renesas,impx4-memory"; ++ reg = <0 0xed000000 0 0xe0000>; ++ clocks = <&cpg CPG_MOD 830>; ++ power-domains = <&sysc R8A7797_PD_A3IR>; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk-kf.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk-kf.dts +new file mode 100644 +index 0000000..29ae871 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk-kf.dts +@@ -0,0 +1,519 @@ ++/* ++ * Device Tree Source for the V3MSK Kingfisher board on r8a7797 ++ * ++ * Copyright (C) 2017 Renesas Electronics Corp. ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a77970-v3msk.dts" ++ ++/ { ++ model = "Renesas V3MSK Kingfisher board based on r8a7797"; ++}; ++ ++&canfd { ++ pinctrl-0 = <&canfd0_pins &canfd1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ channel0 { ++ status = "okay"; ++ }; ++ ++ channel1 { ++ status = "okay"; ++ }; ++}; ++ ++&csi40 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&i2c0 { ++ /* i2c0 might conflict with pc9548 reset pin on Kingfisher (uncomment if h/w not patched) */ ++// status = "disabled"; ++}; ++ ++&i2c3 { ++ pinctrl-0 = <&i2c3_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ clock-frequency = <400000>; ++ ++ i2cswitch4: pca9548@71 { ++ compatible = "nxp,pca9548"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x71>; ++// reset-gpios= <&gpio3 15 GPIO_ACTIVE_LOW>; ++ ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ /* Slot B (CN11) */ ++ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ ov106xx_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ ov106xx_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ ov106xx_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ ov106xx_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; ++ }; ++ }; ++ }; ++ ++ /* DS90UB9x4 @ 0x3a */ ++ ti9x4@0 { ++ compatible = "ti,ti9x4"; ++ reg = <0x3a>; ++ ti,links = <4>; ++ ti,lanes = <4>; ++ ti,forwarding-mode = "round-robin"; ++ ++ POC0-gpios = <&gpio_exp_a_5c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_a_5c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_a_5c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_a_5c 11 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ ti9x4_des0ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ ti9x4_des0ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ ti9x4_des0ep2: endpoint@2 { ++ ti9x3-addr = <0x0e>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ ti9x4_des0ep3: endpoint@3 { ++ ti9x3-addr = <0x0f>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ ti9x4_csi0ep0: endpoint { ++ csi-rate = <800>; ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ }; ++ ++ /* MAX9286 @ 0x2c */ ++ max9286@0 { ++ compatible = "maxim,max9286"; ++ reg = <0x2c>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ POC0-gpios = <&gpio_exp_a_5c 9 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_a_5c 8 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_a_5c 11 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_a_5c 10 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ /* Slot B (CN11) */ ++ ++ /* PCA9535 is a redundant/deprecated card */ ++ gpio_exp_a_26: gpio@26 { ++ compatible = "nxp,pca9535"; ++ reg = <0x26>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_a_des_cfg1 { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A cfg1"; ++ }; ++ video_a_des_cfg0 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A cfg0"; ++ }; ++ video_a_pwr_shdn { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR_SHDN"; ++ }; ++ video_a_cam_pwr0 { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR0"; ++ }; ++ video_a_cam_pwr1 { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR1"; ++ }; ++ video_a_cam_pwr2 { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR2"; ++ }; ++ video_a_cam_pwr3 { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR3"; ++ }; ++ video_a_des_shdn { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A DES_SHDN"; ++ }; ++ video_a_des_led { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A led"; ++ }; ++ }; ++ ++ gpio_exp_a_5c: gpio@5c { ++ compatible = "maxim,max7325"; ++ reg = <0x5c>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_a_des_cfg2 { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A cfg2"; ++ }; ++ video_a_des_cfg1 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A cfg1"; ++ }; ++ video_a_des_cfg0 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A cfg0"; ++ }; ++ video_a_pwr_shdn { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR_SHDN"; ++ }; ++ video_a_des_shdn { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A DES_SHDN"; ++ }; ++ video_a_led { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A LED"; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&pfc { ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_a"; ++ function = "canfd0"; ++ }; ++ ++ canfd1_pins: canfd1 { ++ groups = "canfd1_data"; ++ function = "canfd1"; ++ }; ++ ++ i2c3_pins: i2c3 { ++ groups = "i2c3"; ++ function = "i2c3"; ++ }; ++}; ++ ++&vin0 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ vin0_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ vin1_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin2_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ vin2_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin3_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ vin3_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm-v2.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm-v2.dts +new file mode 100644 +index 0000000..e20f4a6 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm-v2.dts +@@ -0,0 +1,82 @@ ++/* ++ * Device Tree Source for the V3MSK Videobox Mini board V2 on r8a7797 ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a77970-v3msk-vbm.dts" ++ ++/ { ++ model = "Renesas V3MSK Videobox Mini board V2 based on r8a7797"; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led5 { ++ label = "board:status"; ++ gpios = <&gpio3 16 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "heartbeat"; ++ }; ++ }; ++}; ++ ++&gpio0 { ++ /delete-node/can0stby; ++ ++ can0_stby { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "CAN0STBY"; ++ }; ++ ++ can1_stby { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "CAN1STBY"; ++ }; ++}; ++ ++&pfc { ++ msiof1_pins: msiof1 { ++ groups = "msiof1_clk", "msiof1_txd", "msiof1_rxd"; ++ function = "msiof1"; ++ }; ++ ++ msiof2_pins: msiof2 { ++ groups = "msiof2_clk", "msiof2_sync", "msiof2_txd", "msiof2_rxd"; ++ function = "msiof2"; ++ }; ++}; ++ ++&scif3 { ++ /* pin conflict with msiof2 */ ++ /* set R240 and remove R241 before enabling */ ++ status = "disabled"; ++}; ++ ++&msiof1 { ++ pinctrl-0 = <&msiof1_pins>; ++ pinctrl-names = "default"; ++ cs-gpios = <&gpio3 3 0>; ++ ++ status = "okay"; ++ spidev@0 { ++ compatible = "renesas,sh-msiof"; ++ reg = <0>; ++ spi-max-frequency = <66666666>; ++ }; ++}; ++ ++&msiof2 { ++ pinctrl-0 = <&msiof2_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ slave; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm.dts +new file mode 100644 +index 0000000..a37ccaa +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm.dts +@@ -0,0 +1,507 @@ ++/* ++ * Device Tree Source for the V3MSK Videobox Mini board on r8a7797 ++ * ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a77970-v3msk.dts" ++ ++/ { ++ model = "Renesas V3MSK Videobox Mini board based on r8a7797"; ++ ++ aliases { ++ serial1 = &scif3; ++ }; ++}; ++ ++&canfd { ++ pinctrl-0 = <&canfd0_pins &canfd1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ channel0 { ++ status = "okay"; ++ }; ++ ++ channel1 { ++ status = "okay"; ++ }; ++}; ++ ++&csi40 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&i2c1 { ++ pinctrl-0 = <&i2c1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ clock-frequency = <400000>; ++ ++ i2cswitch1: i2c-switch@74 { ++ compatible = "nxp,pca9548"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x74>; ++ reset-gpios = <&gpio0 9 GPIO_ACTIVE_LOW>; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ ov106xx_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ ov106xx_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ ov106xx_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ ov106xx_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; ++ }; ++ }; ++ }; ++ ++ max9286@0 { ++ compatible = "maxim,max9286"; ++ reg = <0x2c>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ POC0-gpios = <&gpio_exp_6c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_6c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_6c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_6c 11 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ }; ++ ++ ti9x4@0 { ++ compatible = "ti,ti9x4"; ++ reg = <0x3a>; ++ ti,links = <4>; ++ ti,lanes = <4>; ++ ti,forwarding-mode = "round-robin"; ++ ++ POC0-gpios = <&gpio_exp_6c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_6c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_6c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_6c 11 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ ti9x4_des0ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ ti9x4_des0ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ ti9x4_des0ep2: endpoint@2 { ++ ti9x3-addr = <0x0e>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ ti9x4_des0ep3: endpoint@3 { ++ ti9x3-addr = <0x0f>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ ti9x4_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ ++ gpio_exp_6c: gpio@6c { ++ compatible = "maxim,max7325"; ++ reg = <0x6c>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ virq { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "VIRQ"; ++ }; ++ des_cfg { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "CNFG0"; ++ }; ++ pwr_shdn { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "PWR_SHDN"; ++ }; ++ des_shdn { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Des_SHDN"; ++ }; ++ fpdl_shdn { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "FPDL_SHDN"; ++ }; ++ }; ++ }; ++ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ ++ /* fan node - lm96063 */ ++ fan_ctrl: lm96063@4c { ++ compatible = "lm96163"; ++ reg = <0x4c>; ++ }; ++ }; ++ }; ++}; ++ ++&gpio0 { ++ can0stby { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "CAN0STBY"; ++ }; ++ ++ can1_load { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can1_120R_load"; ++ }; ++}; ++ ++&gpio2 { ++ can0_load { ++ gpio-hog; ++ gpios = <16 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can0_120R_load"; ++ }; ++ ++ wake_pin_7 { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "WAKE INPUT PIN 7"; ++ }; ++ ++ wake_pin_8 { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "WAKE INPUT PIN 8"; ++ }; ++}; ++ ++&pfc { ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_a"; ++ function = "canfd0"; ++ }; ++ ++ canfd1_pins: canfd1 { ++ groups = "canfd1_data"; ++ function = "canfd1"; ++ }; ++ ++ i2c1_pins: i2c1 { ++ groups = "i2c1"; ++ function = "i2c1"; ++ }; ++ ++ scif3_pins: scif3 { ++ groups = "scif3_data"; ++ function = "scif3"; ++ }; ++}; ++ ++&scif3 { ++ pinctrl-0 = <&scif3_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&vin0 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ vin0_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ vin1_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin2_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ vin2_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin3_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ vin3_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk-view.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk-view.dts +new file mode 100644 +index 0000000..75631fb +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk-view.dts +@@ -0,0 +1,297 @@ ++/* ++ * Device Tree Source for the V3MSK View board on r8a7797 ++ * ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a77970-v3msk.dts" ++ ++/ { ++ model = "Renesas V3MSK View board based on r8a7797"; ++}; ++ ++&csi40 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&i2c3 { ++ pinctrl-0 = <&i2c3_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ clock-frequency = <400000>; ++ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++ ++ max9286@0 { ++ compatible = "maxim,max9286"; ++ reg = <0x6c>; ++ gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ }; ++}; ++ ++&gpio2 { ++ gpio_pwdn1 { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "GPIO_PWDN1#"; ++ }; ++}; ++ ++&pfc { ++ i2c3_pins: i2c3 { ++ groups = "i2c3"; ++ function = "i2c3"; ++ }; ++}; ++ ++&vin0 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin2_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin3_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +index 8eac8ca..2b614e4 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +@@ -27,6 +27,46 @@ + reg = <0x0 0x48000000 0x0 0x38000000>; + }; + ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ /* device specific region for Lossy Decompression */ ++ lossy_decompress: linux,lossy_decompress { ++ no-map; ++ reg = <0x00000000 0x6c000000 0x0 0x03000000>; ++ }; ++ ++ /* global autoconfigured region for contiguous allocations */ ++ linux,cma { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x6f000000 0x0 0x10000000>; ++ linux,cma-default; ++ }; ++ ++ /* device specific region for contiguous allocations */ ++ linux,multimedia { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x7f000000 0x0 0x01000000>; ++ }; ++ }; ++ ++ mmngr { ++ compatible = "renesas,mmngr"; ++ memory-region = <&lossy_decompress>; ++ }; ++ ++ mmngrbuf { ++ compatible = "renesas,mmngrbuf"; ++ }; ++ ++ vspm_if { ++ compatible = "renesas,vspm_if"; ++ }; ++ + osc5_clk: osc5-clock { + compatible = "fixed-clock"; + #clock-cells = <0>; +@@ -178,6 +218,37 @@ + }; + }; + }; ++ ++ pmic@5A { ++ compatible = "dlg,da9063"; ++ reg = <0x5A>; ++ interrupt-parent = <&intc_ex>; ++ interrupts = <0 IRQ_TYPE_LEVEL_LOW>; ++ interrupt-controller; ++ ++ rtc { ++ compatible = "dlg,da9063-rtc"; ++ }; ++ ++ wdt { ++ compatible = "dlg,da9063-watchdog"; ++ }; ++ ++ regulators { ++ DA9063_LDO11: bmem { ++ regulator-name = "bmem"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ }; ++ ++ onkey { ++ compatible = "dlg,da9063-onkey"; ++ }; ++ }; ++ + }; + + &lvds0 { +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3mzf.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3mzf.dts +new file mode 100644 +index 0000000..2087364 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a77970-v3mzf.dts +@@ -0,0 +1,442 @@ ++/* ++ * Device Tree Source for the V3MZF board ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++/dts-v1/; ++#include "r8a77970.dtsi" ++#include ++ ++/ { ++ model = "Renesas V3MZF board based on r8a7797"; ++ compatible = "renesas,v3mzf", "renesas,r8a7797"; ++ ++ aliases { ++ serial0 = &scif0; ++ ethernet0 = &avb; ++ }; ++ ++ chosen { ++ bootargs = "ignore_loglevel rw root=/dev/nfs ip=dhcp"; ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ memory@48000000 { ++ device_type = "memory"; ++ /* first 128MB is reserved for secure area. */ ++ reg = <0x0 0x48000000 0x0 0x38000000>; ++ }; ++ ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ /* device specific region for Lossy Decompression */ ++ lossy_decompress: linux,lossy_decompress { ++ no-map; ++ reg = <0x00000000 0x6c000000 0x0 0x03000000>; ++ }; ++ ++ /* global autoconfigured region for contiguous allocations */ ++ linux,cma { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x6f000000 0x0 0x11000000>; ++ linux,cma-default; ++ }; ++ }; ++ ++ mmngr { ++ compatible = "renesas,mmngr"; ++ memory-region = <&lossy_decompress>; ++ }; ++ ++ mmngrbuf { ++ compatible = "renesas,mmngrbuf"; ++ }; ++ ++ vspm_if { ++ compatible = "renesas,vspm_if"; ++ }; ++ ++ lvds { ++ compatible = "panel-lvds"; ++ ++ width-mm = <210>; ++ height-mm = <158>; ++ ++ data-mapping = "jeida-24"; ++ ++ panel-timing { ++ clock-frequency = <65000000>; ++ hactive = <1280>; ++ vactive = <800>; ++ hsync-len = <40>; ++ hfront-porch = <80>; ++ hback-porch = <40>; ++ vfront-porch = <14>; ++ vback-porch = <14>; ++ vsync-len = <4>; ++ }; ++ ++ port { ++ lvds_in: endpoint { ++ remote-endpoint = <&du_out_lvds0>; ++ }; ++ }; ++ }; ++ ++ dclkin_p0: clock-out0 { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <148500000>; ++ }; ++ ++ msiof_ref_clk: msiof-ref-clock { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <66666666>; ++ }; ++ ++ vcc_3v3: regulator0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-VCC3V3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ vcc_vddq_vin0: regulator1 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VCC-VDDQ-VIN0"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++}; ++ ++&avb { ++ pinctrl-0 = <&avb_pins>; ++ pinctrl-names = "default"; ++ renesas,no-ether-link; ++ phy-handle = <&phy0>; ++ status = "okay"; ++ phy-int-gpio = <&gpio1 17 GPIO_ACTIVE_LOW>; ++ ++ phy0: ethernet-phy@0 { ++ rxc-skew-ps = <1500>; ++ rxdv-skew-ps = <420>; /* default */ ++ rxd0-skew-ps = <420>; /* default */ ++ rxd1-skew-ps = <420>; /* default */ ++ rxd2-skew-ps = <420>; /* default */ ++ rxd3-skew-ps = <420>; /* default */ ++ txc-skew-ps = <900>; /* default */ ++ txen-skew-ps = <420>; /* default */ ++ txd0-skew-ps = <420>; /* default */ ++ txd1-skew-ps = <420>; /* default */ ++ txd2-skew-ps = <420>; /* default */ ++ txd3-skew-ps = <420>; /* default */ ++ reg = <0>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <17 IRQ_TYPE_LEVEL_LOW>; ++ max-speed = <1000>; ++ }; ++}; ++ ++&canfd { ++ pinctrl-0 = <&canfd0_pins &canfd1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ channel0 { ++ status = "okay"; ++ }; ++ ++ channel1 { ++ status = "okay"; ++ }; ++}; ++ ++&csi40 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "raw8"; ++ receive,vc = <0>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&du { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ endpoint { ++ remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++}; ++ ++&extal_clk { ++ clock-frequency = <16666666>; ++}; ++ ++&extalr_clk { ++ clock-frequency = <32768>; ++}; ++ ++&gpio1 { ++ pdb_ser_enable { ++ gpio-hog; ++ gpios = <26 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "PDB_SER_Enable"; ++ }; ++ ++ lvds_sw_sel { ++ gpio-hog; ++ gpios = <27 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "LVDS_SW_SEL"; ++ }; ++}; ++ ++&gpio2 { ++ can0_inh_v3m { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "CAN0_INH_V3M"; ++ }; ++ ++ can1_inh_v3m { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "CAN1_INH_V3M"; ++ }; ++}; ++ ++&gpio3 { ++ pdb_des_enable { ++ gpio-hog; ++ gpios = <0 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "PDB_DES_Enable"; ++ }; ++}; ++ ++&i2c0 { ++ pinctrl-0 = <&i2c0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ clock-frequency = <400000>; ++}; ++ ++&i2c3 { ++ pinctrl-0 = <&i2c3_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ clock-frequency = <400000>; ++ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_ti9x4_des0ep0: endpoint@0 { ++ remote-endpoint = <&ti9x4_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ti9x4@30 { ++ compatible = "ti,ti9x4"; ++ reg = <0x30>; ++ ti,links = <1>; ++ ti,lanes = <4>; ++ ti,forwarding-mode = "round-robin"; ++ ti,dvp_bus = <0>; ++ ti,ser_id = <0x30>; ++ ++ port@0 { ++ ti9x4_des0ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ ti9x4_csi0ep0: endpoint { ++ csi-rate = <800>; ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ }; ++}; ++ ++&msiof2 { ++ pinctrl-0 = <&msiof2_pins>; ++ pinctrl-names = "default"; ++ cs-gpios = <&gpio2 4 0>; ++ ++ status = "okay"; ++ spidev@0 { ++ compatible = "renesas,sh-msiof"; ++ reg = <0>; ++ spi-max-frequency = <66666666>; ++ }; ++}; ++ ++&msiof3 { ++ pinctrl-0 = <&msiof3_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ slave; ++}; ++ ++&pfc { ++ pinctrl-0 = <&scif_clk_pins>; ++ pinctrl-names = "default"; ++ ++ avb_pins: avb { ++ groups = "avb0_mdc"; ++ function = "avb0"; ++ }; ++ ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_a"; ++ function = "canfd0"; ++ }; ++ ++ canfd1_pins: canfd1 { ++ groups = "canfd1_data"; ++ function = "canfd1"; ++ }; ++ ++ i2c0_pins: i2c0 { ++ groups = "i2c0"; ++ function = "i2c0"; ++ }; ++ ++ i2c3_pins: i2c3 { ++ groups = "i2c3"; ++ function = "i2c3"; ++ }; ++ ++ msiof2_pins: msiof2 { ++ groups = "msiof2_clk", "msiof2_txd", "msiof2_rxd"; ++ function = "msiof2"; ++ }; ++ ++ msiof3_pins: msiof3 { ++ groups = "msiof3_clk", "msiof3_txd", "msiof3_rxd", "msiof3_sync"; ++ function = "msiof3"; ++ }; ++ ++ scif0_pins: scif0 { ++ groups = "scif0_data"; ++ function = "scif0"; ++ }; ++ ++ scif_clk_pins: scif_clk { ++ groups = "scif_clk_b"; ++ function = "scif_clk"; ++ }; ++ ++ sdhi2_pins_3v3: sdhi2_3v3 { ++ groups = "mmc_data8", "mmc_ctrl"; ++ function = "mmc"; ++ power-source = <3300>; ++ }; ++}; ++ ++&scif0 { ++ pinctrl-0 = <&scif0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&scif_clk { ++ clock-frequency = <14745600>; ++ status = "okay"; ++}; ++ ++&sdhi2 { ++ /* used for on-board eMMC */ ++ pinctrl-0 = <&sdhi2_pins_3v3>; ++ pinctrl-names = "default"; ++ ++ vmmc-supply = <&vcc_3v3>; ++ vqmmc-supply = <&vcc_vddq_vin0>; ++ no-1-8-v; ++ cap-mmc-highspeed; ++ bus-width = <8>; ++ non-removable; ++ status = "okay"; ++}; ++ ++&vin0 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_ti9x4_des0ep0: endpoint@0 { ++ remote-endpoint = <&ti9x4_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&wdt0 { ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +index 0b93a7d..e270cc0 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +@@ -28,6 +28,46 @@ + reg = <0 0x48000000 0 0x78000000>; + }; + ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ /* device specific region for Lossy Decompression */ ++ lossy_decompress: linux,lossy_decompress { ++ no-map; ++ reg = <0x00000000 0x6c000000 0x0 0x03000000>; ++ }; ++ ++ /* global autoconfigured region for contiguous allocations */ ++ linux,cma { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x6f000000 0x0 0x10000000>; ++ linux,cma-default; ++ }; ++ ++ /* device specific region for contiguous allocations */ ++ linux,multimedia { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x7f000000 0x0 0x01000000>; ++ }; ++ }; ++ ++ mmngr { ++ compatible = "renesas,mmngr"; ++ memory-region = <&lossy_decompress>; ++ }; ++ ++ mmngrbuf { ++ compatible = "renesas,mmngrbuf"; ++ }; ++ ++ vspm_if { ++ compatible = "renesas,vspm_if"; ++ }; ++ + d3_3v: regulator-0 { + compatible = "regulator-fixed"; + regulator-name = "D3.3V"; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm-v2.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm-v2.dts +new file mode 100644 +index 0000000..56d4253 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm-v2.dts +@@ -0,0 +1,73 @@ ++/* ++ * Device Tree Source for the V3HSK Videobox Mini board V2 on r8a7798 ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7798-v3hsk-vbm.dts" ++ ++/ { ++ model = "Renesas V3HSK Videobox Mini board V2 based on r8a7798"; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led5 { ++ label = "board:status"; ++ gpios = <&gpio2 26 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "heartbeat"; ++ }; ++ }; ++}; ++ ++&gpio0 { ++ can1_stby { ++ gpio-hog; ++ gpios = <21 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "CAN1STBY"; ++ }; ++}; ++ ++&pfc { ++ msiof1_pins: msiof1 { ++ groups = "msiof1_clk", "msiof1_txd", "msiof1_rxd"; ++ function = "msiof1"; ++ }; ++ ++ msiof2_pins: msiof2 { ++ groups = "msiof2_clk", "msiof2_sync", "msiof2_txd", "msiof2_rxd"; ++ function = "msiof2"; ++ }; ++}; ++ ++&scif3 { ++ /* pin conflict with msiof2 */ ++ /* set R240 and remove R241 before enabling */ ++ status = "disabled"; ++}; ++ ++&msiof1 { ++ pinctrl-0 = <&msiof1_pins>; ++ pinctrl-names = "default"; ++ cs-gpios = <&gpio3 3 0>; ++ ++ status = "okay"; ++ spidev@0 { ++ compatible = "renesas,sh-msiof"; ++ reg = <0>; ++ spi-max-frequency = <66666666>; ++ }; ++}; ++ ++&msiof2 { ++ pinctrl-0 = <&msiof2_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ slave; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm.dts +new file mode 100644 +index 0000000..9a54554 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm.dts +@@ -0,0 +1,505 @@ ++/* ++ * Device Tree Source for the V3HSK Videobox Mini board on r8a7798 ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7798-v3hsk.dts" ++ ++/ { ++ model = "Renesas V3HSK Videobox Mini board based on r8a7798"; ++ ++ aliases { ++ serial1 = &scif3; ++ }; ++}; ++ ++&canfd { ++ pinctrl-0 = <&canfd0_pins &canfd1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ channel0 { ++ status = "okay"; ++ }; ++ ++ channel1 { ++ status = "okay"; ++ }; ++}; ++ ++&csi41 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi41_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&i2c1 { ++ pinctrl-0 = <&i2c1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ clock-frequency = <400000>; ++ ++ i2cswitch1: i2c-switch@74 { ++ compatible = "nxp,pca9548"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x74>; ++ reset-gpios = <&gpio2 28 GPIO_ACTIVE_LOW>; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ ov106xx_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin5ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ ov106xx_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin6ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ ov106xx_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin7ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ ov106xx_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; ++ }; ++ }; ++ }; ++ ++ max9286@0 { ++ compatible = "maxim,max9286"; ++ reg = <0x2c>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ POC0-gpios = <&gpio_exp_6c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_6c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_6c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_6c 11 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi1ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ }; ++ ++ ti9x4@0 { ++ compatible = "ti,ti9x4"; ++ reg = <0x3a>; ++ ti,links = <4>; ++ ti,lanes = <4>; ++ ti,forwarding-mode = "round-robin"; ++ ++ POC0-gpios = <&gpio_exp_6c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_6c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_6c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_6c 11 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ ti9x4_des0ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ ti9x4_des0ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ ti9x4_des0ep2: endpoint@2 { ++ ti9x3-addr = <0x0e>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ ti9x4_des0ep3: endpoint@3 { ++ ti9x3-addr = <0x0f>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ ti9x4_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ ++ gpio_exp_6c: gpio@6c { ++ compatible = "maxim,max7325"; ++ reg = <0x6c>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ virq { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "VIRQ"; ++ }; ++ des_cfg { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "CNFG0"; ++ }; ++ pwr_shdn { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "PWR_SHDN"; ++ }; ++ des_shdn { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Des_SHDN"; ++ }; ++ fpdl_shdn { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "FPDL_SHDN"; ++ }; ++ }; ++ }; ++ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ ++ /* fan node - lm96063 */ ++ fan_ctrl: lm96063@4c { ++ compatible = "lm96163"; ++ reg = <0x4c>; ++ }; ++ }; ++ }; ++}; ++ ++&gpio2 { ++ can0_load { ++ gpio-hog; ++ gpios = <16 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can0_120R_load"; ++ }; ++ ++ can0stby { ++ gpio-hog; ++ gpios = <27 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "CAN0STBY"; ++ }; ++ ++ can1_load { ++ gpio-hog; ++ gpios = <29 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can1_120R_load"; ++ }; ++ ++ wake_pin_7 { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "WAKE INPUT PIN 7"; ++ }; ++ ++ wake_pin_8 { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "WAKE INPUT PIN 8"; ++ }; ++}; ++ ++&pfc { ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_a"; ++ function = "canfd0"; ++ }; ++ ++ canfd1_pins: canfd1 { ++ groups = "canfd1_data"; ++ function = "canfd1"; ++ }; ++ ++ i2c1_pins: i2c1 { ++ groups = "i2c1"; ++ function = "i2c1"; ++ }; ++ ++ scif3_pins: scif3 { ++ groups = "scif3_data"; ++ function = "scif3"; ++ }; ++}; ++ ++&scif3 { ++ pinctrl-0 = <&scif3_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&vin4 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin4ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi1ep0: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin4_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ vin4_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin5 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin5ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi1ep1: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin5_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ vin5_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin6 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin6ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi1ep2: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin6_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ vin6_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin7 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin7ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi1ep3: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin7_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ vin7_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +index c968099..dff7d02 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +@@ -26,6 +26,47 @@ + /* first 128MB is reserved for secure area. */ + reg = <0 0x48000000 0 0x78000000>; + }; ++ ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ /* device specific region for Lossy Decompression */ ++ lossy_decompress: linux,lossy_decompress { ++ no-map; ++ reg = <0x00000000 0x6c000000 0x0 0x03000000>; ++ }; ++ ++ /* global autoconfigured region for contiguous allocations */ ++ linux,cma { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x6f000000 0x0 0x10000000>; ++ linux,cma-default; ++ }; ++ ++ /* device specific region for contiguous allocations */ ++ linux,multimedia { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x7f000000 0x0 0x01000000>; ++ }; ++ }; ++ ++ mmngr { ++ compatible = "renesas,mmngr"; ++ memory-region = <&lossy_decompress>; ++ }; ++ ++ mmngrbuf { ++ compatible = "renesas,mmngrbuf"; ++ }; ++ ++ vspm_if { ++ compatible = "renesas,vspm_if"; ++ }; ++ + }; + + &extal_clk { +diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi +new file mode 100644 +index 0000000..c5384ca +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi +@@ -0,0 +1,462 @@ ++/* ++ * Device Tree Source for the H3ULCB Kingfisher board: ++ * this adding conflicting resource on VIN4/VIN5/VIN6/VIN7 for CN11 ++ * use CN11 instead default CN29/CN48 ++ * ++ * Copyright (C) 2017 Renesas Electronics Corp. ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++&i2cswitch4 { ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ /* Slot B (CN11) */ ++ ++ ov106xx@4 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x64>; ++ ++ port@0 { ++ ov106xx_in4: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ ov106xx_ti9x4_des1ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@5 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x65>; ++ ++ port@0 { ++ ov106xx_in5: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin5ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ ov106xx_ti9x4_des1ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@6 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x66>; ++ port@0 { ++ ov106xx_in6: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin6ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ ov106xx_ti9x4_des1ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@7 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x67>; ++ port@0 { ++ ov106xx_in7: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin7ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ ov106xx_ti9x4_des1ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep3>; ++ }; ++ }; ++ }; ++ ++ /* DS90UB9x4 @ 0x3a */ ++ ti9x4@1 { ++ compatible = "ti,ti9x4"; ++ reg = <0x3a>; ++ ti,sensor_delay = <350>; ++ ti,links = <4>; ++ ti,lanes = <4>; ++ ti,forwarding-mode = "round-robin"; ++ ti,cable-mode = "coax"; ++ ++ POC0-gpios = <&gpio_exp_b_5c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_b_5c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_b_5c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_b_5c 11 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ ti9x4_des1ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in4>; ++ }; ++ ti9x4_des1ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in5>; ++ }; ++ ti9x4_des1ep2: endpoint@2 { ++ ti9x3-addr = <0x0e>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in6>; ++ }; ++ ti9x4_des1ep3: endpoint@3 { ++ ti9x3-addr = <0x0f>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in7>; ++ }; ++ }; ++ port@1 { ++ ti9x4_csi2ep0: endpoint { ++ csi-rate = <1450>; ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ }; ++ ++ /* MAX9286 @ 0x2c */ ++ max9286@1 { ++ compatible = "maxim,max9286"; ++ reg = <0x2c>; ++ maxim,sensor_delay = <350>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ POC0-gpios = <&gpio_exp_b_5c 9 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_b_5c 8 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_b_5c 11 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_b_5c 10 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ max9286_des1ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in4>; ++ }; ++ max9286_des1ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ }; ++ max9286_des1ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in6>; ++ }; ++ max9286_des1ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in7>; ++ }; ++ }; ++ port@1 { ++ max9286_csi2ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ /* Slot B (CN11) */ ++ ++ /* PCA9535 is a redundand/deprecated card */ ++ gpio_exp_b_27: gpio@27 { ++ compatible = "nxp,pca9535"; ++ reg = <0x27>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_b_des_cfg1 { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B cfg1"; ++ }; ++ video_b_des_cfg0 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B cfg0"; ++ }; ++ video_b_pwr_shdn { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR_SHDN"; ++ }; ++ video_b_cam_pwr0 { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR0"; ++ }; ++ video_b_cam_pwr1 { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR1"; ++ }; ++ video_b_cam_pwr2 { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR2"; ++ }; ++ video_b_cam_pwr3 { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR3"; ++ }; ++ video_b_des_shdn { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B DES_SHDN"; ++ }; ++ video_b_des_led { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-B led"; ++ }; ++ }; ++ ++ gpio_exp_b_5c: gpio@5c { ++ compatible = "maxim,max7325"; ++ reg = <0x5c>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_b_des_cfg2 { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B cfg2"; ++ }; ++ video_b_des_cfg1 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B cfg1"; ++ }; ++ video_b_des_cfg0 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B cfg0"; ++ }; ++ video_b_pwr_shdn { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR_SHDN"; ++ }; ++ video_b_des_shdn { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B DES_SHDN"; ++ }; ++ video_b_led { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-B LED"; ++ }; ++ }; ++ }; ++}; ++ ++&vin4 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin4ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <0>; ++ remote-endpoint = <&ov106xx_in4>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep0: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin4_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ vin4_ti9x4_des1ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin5 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin5ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep1: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin5_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ vin5_ti9x4_des1ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin6 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin6ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <2>; ++ remote-endpoint = <&ov106xx_in6>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep2: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin6_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ vin6_ti9x4_des1ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin7 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin7ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <3>; ++ remote-endpoint = <&ov106xx_in7>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep3: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin7_max9286_des1ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ vin7_ti9x4_des1ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&csi41 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi41_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf-most.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf-most.dtsi +new file mode 100644 +index 0000000..4af5ca0 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/ulcb-kf-most.dtsi +@@ -0,0 +1,30 @@ ++/* ++ * Device Tree Source for the H3/M3ULCB Kingfisher board: ++ * this overrides GPS in favour MOST on GP5_24/GP5_25 R-CAR pins ++ * ++ * Copyright (C) 2017 Renesas Electronics Corp. ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++&pfc { ++ mlp_pins: mlp { ++ groups = "mlb_3pin"; ++ function = "mlb_3pin"; ++ }; ++}; ++ ++&scif1 { ++ status = "disabled"; ++}; ++ ++&mlp { ++ pinctrl-0 = <&mlp_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ clock-speed = "1024fs"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf-sd3.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf-sd3.dtsi +new file mode 100644 +index 0000000..b854216 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/ulcb-kf-sd3.dtsi +@@ -0,0 +1,46 @@ ++/* ++ * Device Tree Source for the H3/M3ULCB Kingfisher board: ++ * this overrides WIFI in favour SD on SDHI3 ++ * ++ * Copyright (C) 2017 Renesas Electronics Corp. ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++&sdio_switch { ++ regulator-name = "sd_on"; ++ enable-active-high; ++}; ++ ++&vccq_sdhi3 { ++ compatible = "regulator-gpio"; ++ ++ regulator-min-microvolt = <1800000>; ++ ++ gpios = <&gpio3 14 GPIO_ACTIVE_HIGH>; ++ gpios-states = <1>; ++ states = <3300000 1 ++ 1800000 0>; ++}; ++ ++&sdhi3 { ++ /delete-property/non-removable; ++ /delete-property/cap-power-off-card; ++ /delete-property/keep-power-in-suspend; ++ /delete-property/enable-sdio-wakeup; ++ /delete-property/max-frequency; ++ /delete-property/no-1-8-v; ++ ++ vmmc-supply = <&vcc_sdhi3>; ++ cd-gpios = <&gpio4 15 GPIO_ACTIVE_LOW>; ++ wp-gpios = <&gpio4 16 GPIO_ACTIVE_HIGH>; ++// sd-uhs-sdr50; ++// sd-uhs-sdr104; ++}; ++ ++&wlcore { ++ status = "disabled"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +index 1b316d79..a70636e 100644 +--- a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi ++++ b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +@@ -10,7 +10,239 @@ + aliases { + serial1 = &hscif0; + serial2 = &scif1; ++ serial3 = &hscif1; + }; ++ ++ snd_clk: snd_clk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <24576000>; ++ clock-output-names = "scki"; ++ }; ++ ++ wlan_en: regulator@4 { ++ compatible = "regulator-fixed"; ++ regulator-name = "wlan-en-regulator"; ++ ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpio = <&gpio_exp_74 4 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ vcc_sdhi3: regulator@41 { ++ compatible = "regulator-fixed"; ++ ++ regulator-name = "SDHI3 Vcc"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpio = <&gpio4 17 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ vccq_sdhi3: regulator@5 { ++ compatible = "regulator-fixed"; ++ ++ regulator-name = "SDHI3 VccQ"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ++ codec_en_reg: regulator@6 { ++ compatible = "regulator-fixed"; ++ regulator-name = "codec-en-regulator"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpio = <&gpio_exp_74 15 0>; ++ ++ /* delay - CHECK */ ++ startup-delay-us = <70000>; ++ enable-active-high; ++ }; ++ ++ amp_en_reg: regulator@7 { ++ compatible = "regulator-fixed"; ++ regulator-name = "amp-en-regulator"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpio = <&gpio_exp_74 0 0>; ++ ++ startup-delay-us = <0>; ++ enable-active-high; ++ }; ++ ++ sdio_switch: regulator@9 { ++ compatible = "regulator-fixed"; ++ regulator-name = "wifi_on"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio_exp_74 5 0>; ++ enable-active-low; ++ regulator-always-on; ++ }; ++ ++ radio_switch: regulator@11 { ++ compatible = "regulator-fixed"; ++ regulator-name = "radio_on"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio_exp_74 13 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ regulator-always-on; ++ }; ++ ++ mpcie_3v3: regulator@12 { ++ compatible = "regulator-fixed"; ++ regulator-name = "mPCIe 3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio_exp_77 14 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ mpcie_1v8: regulator@13 { ++ compatible = "regulator-fixed"; ++ regulator-name = "mPCIe 1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ gpio = <&gpio_exp_77 15 GPIO_ACTIVE_HIGH>; ++ startup-delay-us = <200000>; ++ enable-active-high; ++ }; ++ ++ kim { ++ compatible = "kim"; ++ shutdown-gpios = <&gpio_exp_74 3 GPIO_ACTIVE_HIGH>; ++ /* serial1 */ ++ dev_name = "/dev/ttySC1"; ++ flow_cntrl = <1>; ++ /* int div 8 hscif@26.6666656MHz */ ++ baud_rate = <3333332>; ++ }; ++ ++ btwilink { ++ compatible = "btwilink"; ++ }; ++ ++ sound_ext: sound@0 { ++ pinctrl-0 = <&sound_0_pins>; ++ pinctrl-names = "default"; ++ ++ compatible = "audio-graph-card"; ++ ++ label = "pcm3168a"; ++ ++ dais = <&rsnd_port0>; ++ }; ++ ++ /delete-node/sound; ++ ++ rsnd_ak4613: sound@1 { ++ compatible = "audio-graph-card"; ++ ++ label = "ak4613"; ++ ++ dais = <&rsnd_port1>; ++ }; ++ ++ sound_radio: sound@2 { ++ pinctrl-0 = <&sound_2_pins>; ++ pinctrl-names = "default"; ++ ++ compatible = "audio-graph-card"; ++ ++ label = "radio"; ++ ++ dais = <&rsnd_port2>; ++ }; ++ ++ sound_wl18xx: sound@3 { ++ pinctrl-0 = <&sound_3_pins>; ++ pinctrl-names = "default"; ++ ++ compatible = "audio-graph-card"; ++ ++ label = "wl18xx"; ++ ++ dais = <&rsnd_port3>; ++ }; ++ ++ lvds { ++ compatible = "panel-lvds"; ++ ++ width-mm = <210>; ++ height-mm = <158>; ++ ++ data-mapping = "jeida-24"; ++ ++ panel-timing { ++ /* 1280x800 @60Hz */ ++ clock-frequency = <65000000>; ++ hactive = <1280>; ++ vactive = <800>; ++ hsync-len = <40>; ++ hfront-porch = <80>; ++ hback-porch = <40>; ++ vfront-porch = <14>; ++ vback-porch = <14>; ++ vsync-len = <4>; ++ }; ++ ++ port { ++ lvds_in: endpoint { ++ remote-endpoint = <&lvds0_out>; ++ }; ++ }; ++ }; ++ ++ hdmi-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_con: endpoint { ++ remote-endpoint = <&adv7513_out>; ++ }; ++ }; ++ }; ++ ++ radio: si468x@0 { ++ compatible = "si,si468x-pcm"; ++ status = "okay"; ++ ++ port { ++ radio_endpoint: endpoint { ++ remote-endpoint = <&rsnd_endpoint2>; ++ system-clock-frequency = <12288000>; ++ }; ++ }; ++ }; ++ ++ wl18xx_pcm: wl18xx_pcm@0 { ++ compatible = "ti,wl18xx-pcm"; ++ status = "okay"; ++ ++ port { ++ wl18xx_pcm_endpoint: endpoint { ++ remote-endpoint = <&rsnd_endpoint3>; ++ }; ++ }; ++ }; ++ ++ camera_clk: camera_clk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <24000000>; ++ clock-output-names = "mclk"; ++ }; ++}; ++ ++&ak4613_endpoint { ++ remote-endpoint = <&rsnd_endpoint1>; + }; + + &can0 { +@@ -25,11 +257,113 @@ + status = "okay"; + }; + ++&canfd { ++ pinctrl-0 = <&canfd0_pins &canfd1_pins>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ ++ channel0 { ++ status = "okay"; ++ }; ++ ++ channel1 { ++ status = "okay"; ++ }; ++}; ++ ++&csi40 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&csi20 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "raw8"; ++ receive,vc = <0>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi20_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ csi-rate = <280>; ++ }; ++ }; ++}; ++ ++&du { ++ pinctrl-0 = <&du_pins>; ++ pinctrl-names = "default"; ++}; ++ + &ehci0 { + dr_mode = "otg"; + status = "okay"; + }; + ++&gpio2 { ++ bl_pwm { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "BL PWM 100%"; ++ }; ++}; ++ ++&gpio4 { ++ most_rst { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "MOST RST"; ++ }; ++}; ++ ++&gpio6 { ++ audio_sw { ++ gpio-hog; ++ gpios = <21 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Onboard MCh Audio"; ++ }; ++}; ++ + &hscif0 { + pinctrl-0 = <&hscif0_pins>; + pinctrl-names = "default"; +@@ -38,21 +372,31 @@ + status = "okay"; + }; + ++&hscif1 { ++ pinctrl-0 = <&hscif1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ + &hsusb { + dr_mode = "otg"; + status = "okay"; + }; + + &i2c2 { ++ clock-frequency = <100000>; ++ + gpio_exp_74: gpio@74 { + compatible = "ti,tca9539"; + reg = <0x74>; + gpio-controller; + #gpio-cells = <2>; ++/* + interrupt-controller; + interrupt-parent = <&gpio6>; + interrupts = <8 IRQ_TYPE_EDGE_FALLING>; +- ++*/ + hub_pwen { + gpio-hog; + gpios = <6 GPIO_ACTIVE_HIGH>; +@@ -90,6 +434,19 @@ + interrupt-controller; + interrupt-parent = <&gpio6>; + interrupts = <4 IRQ_TYPE_EDGE_FALLING>; ++ ++ gps_rst { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "GPS rst"; ++ }; ++ fpdl_shdn { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "FPDLink shdn"; ++ }; + }; + + i2cswitch2: i2c-switch@71 { +@@ -98,6 +455,142 @@ + #size-cells = <0>; + reg = <0x71>; + reset-gpios = <&gpio5 3 GPIO_ACTIVE_LOW>; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ /* BCM node(s) */ ++ }; ++ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ /* USB3.0 HUB node(s) */ ++ }; ++ ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ /* Power amp node(s) */ ++ }; ++ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ /* Radio node(s) */ ++ }; ++ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ ++ hdmi@3d { ++ compatible = "adi,adv7513"; ++ reg = <0x3d>; ++// interrupt-parent = <&gpio2>; ++// interrupts = <0 IRQ_TYPE_EDGE_BOTH>; ++ pd-gpios = <&gpio_exp_75 5 GPIO_ACTIVE_LOW>; ++ ++ interlace-allowed; ++ adi,input-depth = <8>; ++ adi,input-colorspace = "rgb"; ++ adi,input-clock = "1x"; ++ adi,input-style = <1>; ++ adi,input-justification = "evenly"; ++ adi,clock-delay = <1200>; ++ ++ limit-frequency = <100000000>; ++// lower-refresh = <50>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ adv7513_in: endpoint { ++ remote-endpoint = <&du_out_rgb>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ adv7513_out: endpoint { ++ remote-endpoint = <&hdmi_con>; ++ }; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ /* PCIe node(s) */ ++ }; ++ ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ /* LVDS display node(s) */ ++ ++ polytouch: edt-ft5x06@38 { ++ compatible = "edt,edt-ft5x06"; ++ reg = <0x38>; ++ interrupt-parent = <&gpio5>; ++ interrupts = <6 IRQ_TYPE_EDGE_FALLING>; ++ }; ++ }; ++ ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ /* Audio, GPS and Gyro node(s) */ ++ ++ pcm3168a: audio-codec@44 { ++ #sound-dai-cells = <0>; ++ compatible = "ti,pcm3168a"; ++ reg = <0x44>; ++ clocks = <&snd_clk>; ++ clock-names = "scki"; ++ tdm; ++ VDD1-supply = <&codec_en_reg>; ++ VDD2-supply = <&codec_en_reg>; ++ VCCAD1-supply = <&codec_en_reg>; ++ VCCAD2-supply = <&codec_en_reg>; ++ VCCDA1-supply = <&_en_reg>; ++ VCCDA2-supply = <&_en_reg>; ++ ++ port { ++ pcm3168a_endpoint: endpoint { ++ remote-endpoint = <&rsnd_endpoint0>; ++ dai-tdm-slot-num = <8>; ++ dai-tdm-slot-width = <32>; ++ system-clock-frequency = <24576000>; ++ }; ++ }; ++ }; ++ ++ lsm9ds0_acc_mag@1d { ++ compatible = "st,lsm9ds0_accel_magn"; ++ reg = <0x1d>; ++ }; ++ ++ lsm9ds0_gyr@6b { ++ compatible = "st,lsm9ds0_gyro"; ++ reg = <0x6b>; ++ }; ++ ++ /* GPS@ 0x42 */ ++ }; + }; + }; + +@@ -110,6 +603,76 @@ + interrupt-controller; + interrupt-parent = <&gpio7>; + interrupts = <3 IRQ_TYPE_EDGE_FALLING>; ++ ++ port_b_a0 { ++ gpio-hog; ++ gpios = <0 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-B A0"; ++ }; ++ port_b_a1 { ++ gpio-hog; ++ gpios = <1 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B A1"; ++ }; ++ port_a_a0 { ++ gpio-hog; ++ gpios = <2 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A A0"; ++ }; ++ port_a_a1 { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A A1"; ++ }; ++ cmos_pwdn { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CMOS PWDN"; ++ }; ++ cmos_rst { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CMOS RST"; ++ }; ++ /* pin 12 - CAM_CLK */ ++ rpi_cam_io_1 { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "RaspB_IO1"; ++ }; ++ /* pin 11 - CAM_GPIO - assume pwdn */ ++ rpi_cam_io_0 { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "RaspB_IO0"; ++ }; ++ sam_rst { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "SAM RST"; ++ }; ++ sam_pwr { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "SAM PWR"; ++ }; ++ /* 0 - FPDLink output, 1 - LVDS output */ ++ lvds_vs_fpdl { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "LVDS switch"; ++ }; + }; + + gpio_exp_77: gpio@77 { +@@ -120,6 +683,31 @@ + interrupt-controller; + interrupt-parent = <&gpio5>; + interrupts = <9 IRQ_TYPE_EDGE_FALLING>; ++ ++ mpcie_wake { ++ gpio-hog; ++ gpios = <0 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "mPCIe WAKE#"; ++ }; ++ mpcie_wdisable { ++ gpio-hog; ++ gpios = <1 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "mPCIe W_DISABLE"; ++ }; ++ mpcie_clreq { ++ gpio-hog; ++ gpios = <2 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "mPCIe CLKREQ#"; ++ }; ++ mpcie_ovc { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "mPCIe OVC"; ++ }; + }; + + i2cswitch4: i2c-switch@71 { +@@ -128,9 +716,359 @@ + #size-cells = <0>; + reg = <0x71>; + reset-gpios = <&gpio3 15 GPIO_ACTIVE_LOW>; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ /* SAM node(s) */ ++ }; ++ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ /* Slot A (CN10) */ ++ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ ov106xx_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ ov106xx_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ ov106xx_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ ov106xx_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; ++ }; ++ }; ++ }; ++ ++ /* DS90UB9x4 @ 0x3a */ ++ ti9x4@0 { ++ compatible = "ti,ti9x4"; ++ reg = <0x3a>; ++ ti,links = <4>; ++ ti,lanes = <4>; ++ ti,forwarding-mode = "round-robin"; ++ ti,cable-mode = "coax"; ++ ++ POC0-gpios = <&gpio_exp_a_5c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_a_5c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_a_5c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_a_5c 11 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ ti9x4_des0ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ ti9x4_des0ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ ti9x4_des0ep2: endpoint@2 { ++ ti9x3-addr = <0x0e>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ ti9x4_des0ep3: endpoint@3 { ++ ti9x3-addr = <0x0f>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ ti9x4_csi0ep0: endpoint { ++ csi-rate = <1450>; ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ }; ++ ++ /* MAX9286 @ 0x2c */ ++ max9286@0 { ++ compatible = "maxim,max9286"; ++ reg = <0x2c>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ POC0-gpios = <&gpio_exp_a_5c 9 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_a_5c 8 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_a_5c 11 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_a_5c 10 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ /* MOST node(s) */ ++ }; ++ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ ++ rpi_camera: ov5647@36 { ++ compatible = "ovti,ov5647"; ++ reg = <0x36>; ++ ++ port@0 { ++ rpi_camera_in: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ ++ cmos_camera: ov5642@3c { ++ compatible = "ovti,ov5642"; ++ reg = <0x3c>; ++ clocks = <&camera_clk>; ++ clock-names = "mclk"; ++ ++ port@0 { ++ cmos_camera_in: endpoint { ++ remote-endpoint = <&vin5ep0>; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ /* Slot A (CN10) */ ++ ++ /* PCA9535 is a redundant/deprecated card */ ++ gpio_exp_a_26: gpio@26 { ++ compatible = "nxp,pca9535"; ++ reg = <0x26>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_a_des_cfg1 { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A cfg1"; ++ }; ++ video_a_des_cfg0 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A cfg0"; ++ }; ++ video_a_pwr_shdn { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR_SHDN"; ++ }; ++ video_a_cam_pwr0 { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR0"; ++ }; ++ video_a_cam_pwr1 { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR1"; ++ }; ++ video_a_cam_pwr2 { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR2"; ++ }; ++ video_a_cam_pwr3 { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR3"; ++ }; ++ video_a_des_shdn { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A DES_SHDN"; ++ }; ++ video_a_des_led { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A led"; ++ }; ++ }; ++ ++ gpio_exp_a_5c: gpio@5c { ++ compatible = "maxim,max7325"; ++ reg = <0x5c>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_a_des_cfg2 { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A cfg2"; ++ }; ++ video_a_des_cfg1 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A cfg1"; ++ }; ++ video_a_des_cfg0 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A cfg0"; ++ }; ++ video_a_pwr_shdn { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR_SHDN"; ++ }; ++ video_a_des_shdn { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A DES_SHDN"; ++ }; ++ video_a_led { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A LED"; ++ }; ++ }; ++ }; + }; + }; + ++&msiof1 { ++ status = "disabled"; ++}; ++ + &ohci0 { + dr_mode = "otg"; + status = "okay"; +@@ -138,6 +1076,7 @@ + + &pcie_bus_clk { + clock-frequency = <100000000>; ++ status = "okay"; + }; + + &pciec0 { +@@ -146,6 +1085,9 @@ + + &pciec1 { + status = "okay"; ++ ++ pcie3v3-supply = <&mpcie_3v3>; ++ pcie1v8-supply = <&mpcie_1v8>; + }; + + &pfc { +@@ -159,30 +1101,183 @@ + function = "can1"; + }; + ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_a"; ++ function = "canfd0"; ++ }; ++ ++ canfd1_pins: canfd1 { ++ groups = "canfd1_data"; ++ function = "canfd1"; ++ }; ++ ++ du_pins: du { ++ groups = "du_rgb888", "du_sync", "du_clk_out_0", "du_disp"; ++ function = "du"; ++ }; ++ + hscif0_pins: hscif0 { + groups = "hscif0_data", "hscif0_ctrl"; + function = "hscif0"; + }; + ++ hscif1_pins: hscif1 { ++ groups = "hscif1_data_a", "hscif1_ctrl_a"; ++ function = "hscif1"; ++ }; ++ + scif1_pins: scif1 { +- groups = "scif1_data_b", "scif1_ctrl"; ++ groups = "scif1_data_b"; + function = "scif1"; + }; + ++ sdhi3_pins_3v3: sd3_3v3 { ++ groups = "sdhi3_data4", "sdhi3_ctrl"; ++ function = "sdhi3"; ++ power-source = <3300>; ++ }; ++ ++ sdhi3_pins_1v8: sd3_1v8 { ++ groups = "sdhi3_data4", "sdhi3_ctrl"; ++ function = "sdhi3"; ++ power-source = <1800>; ++ }; ++ ++ sound_0_pins: sound0 { ++ groups = "ssi349_ctrl", "ssi3_data", "ssi4_data"; ++ function = "ssi"; ++ }; ++ ++ /* sound_pins defined in H3 or M3 ulsb file */ ++ ++ sound_2_pins: sound2 { ++ groups = "ssi6_ctrl", "ssi6_data"; ++ function = "ssi"; ++ }; ++ ++ sound_3_pins: sound3 { ++ groups = "ssi78_ctrl", "ssi7_data", "ssi8_data"; ++ function = "ssi"; ++ }; ++ + usb0_pins: usb0 { + groups = "usb0"; + function = "usb0"; + }; ++ ++ vin5_pins: vin5 { ++ groups = "vin5_data8", "vin5_sync", "vin5_clk"; ++ function = "vin5"; ++ }; ++}; ++ ++&rcar_sound { ++ pinctrl-0 = <&sound_clk_pins>; ++ pinctrl-names = "default"; ++ ++ /* Multi DAI */ ++ #sound-dai-cells = <1>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ rsnd_port0: port@0 { ++ reg = <0>; ++ rsnd_endpoint0: endpoint { ++ remote-endpoint = <&pcm3168a_endpoint>; ++ ++ dai-format = "left_j"; ++ bitclock-master = <&pcm3168a_endpoint>; ++ frame-master = <&pcm3168a_endpoint>; ++ dai-tdm-slot-num = <8>; ++ dai-tdm-slot-width = <32>; ++ ++ playback = <&ssi3>; ++ capture = <&ssi4>; ++ }; ++ }; ++ rsnd_port1: port@1 { ++ reg = <1>; ++ rsnd_endpoint1: endpoint { ++ remote-endpoint = <&ak4613_endpoint>; ++ ++ dai-format = "left_j"; ++ bitclock-master = <&rsnd_endpoint1>; ++ frame-master = <&rsnd_endpoint1>; ++ ++ playback = <&ssi0 &src0 &dvc0>; ++ capture = <&ssi1 &src1 &dvc1>; ++ }; ++ }; ++ rsnd_port2: port@2 { ++ reg = <2>; ++ rsnd_endpoint2: endpoint { ++ remote-endpoint = <&radio_endpoint>; ++ ++ dai-format = "i2s"; ++ bitclock-master = <&radio_endpoint>; ++ frame-master = <&radio_endpoint>; ++ ++ capture = <&ssi6>; ++ }; ++ }; ++ rsnd_port3: port@3 { ++ reg = <3>; ++ rsnd_endpoint3: enpoint { ++ remote-endpoint = <&wl18xx_pcm_endpoint>; ++ ++ simple-audio-card,format = "i2s"; ++ bitclock-master = <&wl18xx_pcm_endpoint>; ++ frame-master = <&wl18xx_pcm_endpoint>; ++ ++ playback = <&ssi7>; ++ capture = <&ssi8>; ++ }; ++ }; ++ }; + }; + + &scif1 { + pinctrl-0 = <&scif1_pins>; + pinctrl-names = "default"; +- uart-has-rtscts; + + status = "okay"; + }; + ++&sdhi3 { ++ pinctrl-0 = <&sdhi3_pins_3v3>; ++ pinctrl-1 = <&sdhi3_pins_1v8>; ++ pinctrl-names = "default", "state_uhs"; ++ ++ vmmc-supply = <&wlan_en>; ++ vqmmc-supply = <&vccq_sdhi3>; ++ keep-power-in-suspend; ++ enable-sdio-wakeup; ++ bus-width = <4>; ++ no-1-8-v; ++ non-removable; ++ cap-power-off-card; ++ max-frequency = <26000000>; ++ status = "okay"; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ wlcore: wlcore@2 { ++ compatible = "ti,wl1837"; ++ reg = <2>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <25 IRQ_TYPE_EDGE_FALLING>; ++ }; ++}; ++ ++&ssi4 { ++ shared-pin; ++}; ++ ++&ssi8 { ++ shared-pin; ++}; ++ + &usb2_phy0 { + pinctrl-0 = <&usb0_pins>; + pinctrl-names = "default"; +@@ -190,6 +1285,177 @@ + status = "okay"; + }; + ++&vin0 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ vin0_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ vin1_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin2_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ vin2_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin3_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ vin3_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&vin4 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin4ep0: endpoint { ++ csi,select = "csi20"; ++ virtual,channel = <0>; ++ remote-endpoint = <&rpi_camera_in>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ port@1 { ++ csi2ep0: endpoint { ++ remote-endpoint = <&csi20_ep>; ++ }; ++ }; ++ }; ++}; ++ ++&vin5 { ++ pinctrl-0 = <&vin5_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin5ep0: endpoint@0 { ++ bus-width = <8>; ++ /* #HSYNC, #VSYNC */ ++ vsync-active = <1>; ++ hsync-active = <0>; ++ remote-endpoint = <&cmos_camera_in>; ++ }; ++ }; ++ }; ++}; ++ + &xhci0 { + status = "okay"; + }; ++ ++ ++ +diff --git a/arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi +new file mode 100644 +index 0000000..abf4669 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi +@@ -0,0 +1,459 @@ ++/* ++ * Device Tree Source for the H3ULCB Videobox board: ++ * this adding conflicting resource on VIN4/VIN5/VIN6/VIN7 for CN12 ++ * ++ * Copyright (C) 2017 Renesas Electronics Corp. ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++&i2cswitch2 { ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ /* Slot C (CN12) */ ++ ++ ov106xx@8 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x68>; ++ ++ port@0 { ++ ov106xx_in8: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des2ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des2ep0>; ++ }; ++ ov106xx_ti9x4_des2ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des2ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@9 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x69>; ++ ++ port@0 { ++ ov106xx_in9: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ remote-endpoint = <&vin5ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des2ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des2ep1>; ++ }; ++ ov106xx_ti9x4_des2ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des2ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@10 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x6a>; ++ ++ port@0 { ++ ov106xx_in10: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ remote-endpoint = <&vin6ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des2ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des2ep2>; ++ }; ++ ov106xx_ti9x4_des2ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des2ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@11 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x6b>; ++ ++ port@0 { ++ ov106xx_in11: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ remote-endpoint = <&vin7ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des2ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des2ep3>; ++ }; ++ ov106xx_ti9x4_des2ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des2ep3>; ++ }; ++ }; ++ }; ++ ++ /* DS90UB9x4 @ 0x3a */ ++ ti9x4@2 { ++ compatible = "ti,ti9x4"; ++ reg = <0x3a>; ++ ti,sensor_delay = <350>; ++ ti,links = <4>; ++ ti,lanes = <2>; ++ ti,forwarding-mode = "round-robin"; ++ ti,cable-mode = "coax"; ++ ++ POC0-gpios = <&gpio_exp_c_5c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_c_5c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_c_5c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_c_5c 11 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ ti9x4_des2ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in8>; ++ }; ++ ti9x4_des2ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in9>; ++ }; ++ ti9x4_des2ep2: endpoint@2 { ++ ti9x3-addr = <0x0e>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in10>; ++ }; ++ ti9x4_des2ep3: endpoint@3 { ++ ti9x3-addr = <0x0f>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in11>; ++ }; ++ }; ++ port@1 { ++ ti9x4_csi1ep0: endpoint { ++ csi-rate = <1450>; ++ remote-endpoint = <&csi20_ep>; ++ }; ++ }; ++ }; ++ ++ /* MAX9286 @ 0x2c */ ++ max9286@2 { ++ compatible = "maxim,max9286"; ++ reg = <0x2c>; ++ maxim,sensor_delay = <350>; ++ maxim,links = <4>; ++ maxim,lanes = <2>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ POC0-gpios = <&gpio_exp_c_5c 9 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_c_5c 8 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_c_5c 11 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_c_5c 10 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ max9286_des2ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in8>; ++ }; ++ max9286_des2ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in9>; ++ }; ++ max9286_des2ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in10>; ++ }; ++ max9286_des2ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in11>; ++ }; ++ }; ++ port@1 { ++ max9286_csi1ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi20_ep>; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ /* Slot C (CN12) */ ++ ++ /* PCA9535 is a redundand/deprecated card */ ++ gpio_exp_c_27: gpio@27 { ++ compatible = "nxp,pca9535"; ++ reg = <0x26>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_c_des_cfg1 { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-C cfg1"; ++ }; ++ video_c_des_cfg0 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-C cfg0"; ++ }; ++ video_c_pwr_shdn { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-C PWR_SHDN"; ++ }; ++ video_c_cam_pwr0 { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-C PWR0"; ++ }; ++ video_c_cam_pwr1 { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-C PWR1"; ++ }; ++ video_c_cam_pwr2 { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-C PWR2"; ++ }; ++ video_c_cam_pwr3 { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-C PWR3"; ++ }; ++ video_c_des_shdn { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-C DES_SHDN"; ++ }; ++ video_c_des_led { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-C led"; ++ }; ++ }; ++ ++ gpio_exp_c_5c: gpio@5c { ++ compatible = "maxim,max7325"; ++ reg = <0x5c>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_c_des_cfg2 { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-C cfg2"; ++ }; ++ video_c_des_cfg1 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-C cfg1"; ++ }; ++ video_c_des_cfg0 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-C cfg0"; ++ }; ++ video_c_pwr_shdn { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-C PWR_SHDN"; ++ }; ++ video_c_des_shdn { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-C DES_SHDN"; ++ }; ++ video_c_led { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-C LED"; ++ }; ++ }; ++ }; ++}; ++ ++&vin4 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin4ep0: endpoint { ++ csi,select = "csi20"; ++ virtual,channel = <0>; ++ remote-endpoint = <&ov106xx_in8>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ port@1 { ++ csi2ep0: endpoint { ++ remote-endpoint = <&csi20_ep>; ++ }; ++ }; ++ port@2 { ++ vin4_max9286_des2ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des2ep0>; ++ }; ++ vin4_ti9x4_des2ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des2ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin5 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin5ep0: endpoint@0 { ++ csi,select = "csi20"; ++ virtual,channel = <1>; ++ remote-endpoint = <&ov106xx_in9>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ port@1 { ++ csi2ep1: endpoint { ++ remote-endpoint = <&csi20_ep>; ++ }; ++ }; ++ port@2 { ++ vin5_max9286_des2ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des2ep1>; ++ }; ++ vin5_ti9x4_des2ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des2ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin6 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin6ep0: endpoint@0 { ++ csi,select = "csi20"; ++ virtual,channel = <2>; ++ remote-endpoint = <&ov106xx_in10>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ port@1 { ++ csi2ep2: endpoint { ++ remote-endpoint = <&csi20_ep>; ++ }; ++ }; ++ port@2 { ++ vin6_max9286_des2ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des2ep2>; ++ }; ++ vin6_ti9x4_des2ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des2ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin7 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin7ep0: endpoint@0 { ++ csi,select = "csi20"; ++ virtual,channel = <3>; ++ remote-endpoint = <&ov106xx_in11>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ port@1 { ++ csi2ep3: endpoint { ++ remote-endpoint = <&csi20_ep>; ++ }; ++ }; ++ port@2 { ++ vin7_max9286_des2ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des2ep3>; ++ }; ++ vin7_ti9x4_des2ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des2ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&csi20 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi20_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ csi-rate = <300>; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/ulcb-vb.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vb.dtsi +new file mode 100644 +index 0000000..67903db +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/ulcb-vb.dtsi +@@ -0,0 +1,1591 @@ ++/* ++ * Device Tree Source for the ULCB Videobox board ++ * ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++/ { ++ leds { ++ compatible = "gpio-leds"; ++ ++ led5 { ++ gpios = <&gpio6 12 GPIO_ACTIVE_HIGH>; ++ }; ++ led6 { ++ gpios = <&gpio6 13 GPIO_ACTIVE_HIGH>; ++ }; ++ /* D13 - status 0 */ ++ led_ext00 { ++ gpios = <&gpio_ext_led 0 GPIO_ACTIVE_LOW>; ++ /* linux,default-trigger = "heartbeat"; */ ++ }; ++ /* D14 - status 1 */ ++ led_ext01 { ++ gpios = <&gpio_ext_led 1 GPIO_ACTIVE_LOW>; ++ /* linux,default-trigger = "mmc1"; */ ++ }; ++ /* D16 - HDMI1 */ ++ led_ext02 { ++ gpios = <&gpio_ext_led 2 GPIO_ACTIVE_LOW>; ++ }; ++ /* D18 - HDMI0 */ ++ led_ext03 { ++ gpios = <&gpio_ext_led 3 GPIO_ACTIVE_LOW>; ++ }; ++ /* D20 - USB3.0 - 0.1 */ ++ led_ext04 { ++ gpios = <&gpio_ext_led 4 GPIO_ACTIVE_LOW>; ++ }; ++ /* D21 - USB3.0 - 0.2 */ ++ led_ext05 { ++ gpios = <&gpio_ext_led 5 GPIO_ACTIVE_LOW>; ++ }; ++ /* D24 - USB3.0 - 1.1 */ ++ led6_ext06 { ++ gpios = <&gpio_ext_led 6 GPIO_ACTIVE_LOW>; ++ }; ++ /* D25 - USB3.0 - 1.2 */ ++ led_ext07 { ++ gpios = <&gpio_ext_led 7 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++ ++ snd_clk: snd_clk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <24576000>; ++ clock-output-names = "scki"; ++ }; ++ ++ vccq_sdhi3: regulator@5 { ++ compatible = "regulator-fixed"; ++ ++ regulator-name = "SDHI3 VccQ"; ++ /* external voltage translator to 1.8V */ ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ++ fpdlink_switch: regulator@8 { ++ compatible = "regulator-fixed"; ++ regulator-name = "fpdlink_on"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio1 20 0>; ++ enable-active-high; ++ regulator-always-on; ++ }; ++ ++ hub_reset: regulator@9 { ++ compatible = "regulator-fixed"; ++ regulator-name = "hub_reset"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio5 5 0>; ++ enable-active-high; ++ regulator-always-on; ++ }; ++ ++ hub_power: regulator@10 { ++ compatible = "regulator-fixed"; ++ regulator-name = "hub_power"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ gpio = <&gpio6 28 0>; ++ enable-active-high; ++ regulator-always-on; ++ }; ++ ++ /delete-node/sound; ++ ++ rsnd_ak4613: sound@0 { ++ pinctrl-0 = <&sound_0_pins>; ++ pinctrl-names = "default"; ++ compatible = "simple-audio-card"; ++ ++ simple-audio-card,format = "left_j"; ++ simple-audio-card,name = "ak4613"; ++ ++ simple-audio-card,bitclock-master = <&sndcpu>; ++ simple-audio-card,frame-master = <&sndcpu>; ++ ++ sndcpu: simple-audio-card,cpu@1 { ++ sound-dai = <&rcar_sound>; ++ }; ++ ++ sndcodec: simple-audio-card,codec@1 { ++ sound-dai = <&ak4613>; ++ }; ++ }; ++ ++ lvds { ++ compatible = "panel-lvds"; ++ ++ width-mm = <210>; ++ height-mm = <158>; ++ ++ data-mapping = "jeida-24"; ++ ++ panel-timing { ++ /* 1280x800 @60Hz */ ++ clock-frequency = <65000000>; ++ hactive = <1280>; ++ vactive = <800>; ++ hsync-len = <40>; ++ hfront-porch = <80>; ++ hback-porch = <40>; ++ vfront-porch = <14>; ++ vback-porch = <14>; ++ vsync-len = <4>; ++ }; ++ ++ port { ++ lvds_in: endpoint { ++ remote-endpoint = <&du_out_lvds0>; ++ }; ++ }; ++ }; ++ ++ excan_ref_clk: excan-ref-clock { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <16000000>; ++ }; ++ ++ radio: si468x@0 { ++ compatible = "si,si468x-pcm"; ++ status = "okay"; ++ ++ #sound-dai-cells = <0>; ++ }; ++ ++ spi_gpio_sw { ++ compatible = "spi-gpio"; ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ gpio-sck = <&gpio0 8 GPIO_ACTIVE_HIGH>; ++ gpio-miso = <&gpio0 10 GPIO_ACTIVE_HIGH>; ++ gpio-mosi = <&gpio0 11 GPIO_ACTIVE_HIGH>; ++ cs-gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>; ++ num-chipselects = <1>; ++ ++ spidev: spidev@0 { ++ compatible = "spidev", "spi-gpio"; ++ reg = <0>; ++ spi-max-frequency = <25000000>; ++ spi-cpha; ++ spi-cpol; ++ }; ++ }; ++ ++ spi_gpio_can { ++ compatible = "spi-gpio"; ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ gpio-sck = <&gpio1 2 GPIO_ACTIVE_HIGH>; ++ gpio-miso = <&gpio1 3 GPIO_ACTIVE_HIGH>; ++ gpio-mosi = <&gpio1 1 GPIO_ACTIVE_HIGH>; ++ cs-gpios = <&gpio1 0 GPIO_ACTIVE_HIGH ++ &gpio1 4 GPIO_ACTIVE_HIGH>; ++ num-chipselects = <2>; ++ ++ spican0: spidev@0 { ++ compatible = "microchip,mcp2515"; ++ reg = <0>; ++ clocks = <&excan_ref_clk>; ++ interrupt-parent = <&gpio0>; ++ interrupts = <15 GPIO_ACTIVE_LOW>; ++ spi-max-frequency = <10000000>; ++ }; ++ spican1: spidev@1 { ++ compatible = "microchip,mcp2515"; ++ reg = <1>; ++ clocks = <&excan_ref_clk>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <5 GPIO_ACTIVE_LOW>; ++ spi-max-frequency = <10000000>; ++ }; ++ }; ++}; ++ ++&pfc { ++ hscif4_pins: hscif4 { ++ groups = "hscif4_data_a", "hscif4_ctrl"; ++ function = "hscif4"; ++ }; ++ ++ sdhi3_pins_3v3: sd3_3v3 { ++ groups = "sdhi3_data4", "sdhi3_ctrl"; ++ function = "sdhi3"; ++ power-source = <3300>; ++ }; ++ ++ /delete-node/sound; ++ ++ sound_0_pins: sound1 { ++ groups = "ssi01239_ctrl", "ssi0_data", "ssi1_data_a"; ++ function = "ssi"; ++ }; ++ ++ usb0_pins: usb0 { ++ groups = "usb0"; ++ function = "usb0"; ++ }; ++ ++ can0_pins: can0 { ++ groups = "can0_data_a"; ++ function = "can0"; ++ }; ++ ++ can1_pins: can1 { ++ groups = "can1_data"; ++ function = "can1"; ++ }; ++ ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_a"; ++ function = "canfd0"; ++ }; ++ ++ canfd1_pins: canfd1 { ++ groups = "canfd1_data"; ++ function = "canfd1"; ++ }; ++}; ++ ++&gpio0 { ++ video_a_irq { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A irq"; ++ }; ++ ++ video_b_irq { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B irq"; ++ }; ++ ++ video_c_irq { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-C irq"; ++ }; ++}; ++ ++&gpio1 { ++ gpioext_4_22_irq { ++ gpio-hog; ++ gpios = <25 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "0x22@i2c4 irq"; ++ }; ++ pcie_disable { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "mPCIe W_DISABLE"; ++ }; ++ m2_sleep { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "M.2 SLEEP#"; ++ }; ++ m2_pres { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "M.2 Present"; ++ }; ++ m2_pcie_det { ++ gpio-hog; ++ gpios = <18 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "M.2 PCIe detected"; ++ }; ++ m2_usb_det { ++ gpio-hog; ++ gpios = <19 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "M.2 USB30 detected"; ++ }; ++ m2_usb_det { ++ gpio-hog; ++ gpios = <27 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "M.2 SSD detected"; ++ }; ++ eth_phy_reset { ++ gpio-hog; ++ gpios = <16 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "BR phy reset"; ++ }; ++ eth_sw_reset { ++ gpio-hog; ++ gpios = <17 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "BR switch reset"; ++ }; ++}; ++ ++&gpio2 { ++ m2_wake { ++ gpio-hog; ++ gpios = <1 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "M.2 WAKE#"; ++ }; ++ m2_pcie_en { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "M.2 PCIe enable"; ++ }; ++}; ++ ++&gpio3 { ++ m2_power_off { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "M.2 FULL_CARD_POWER_OFF#"; ++ }; ++}; ++ ++&gpio6 { ++ pcie_wake { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "mPCIe WAKE#"; ++ }; ++ pcie_clkreq { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "mPCIe CLKREQ#"; ++ }; ++ m2_rst { ++ gpio-hog; ++ gpios = <21 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "M.2 RESET#"; ++ }; ++}; ++ ++&hscif4 { ++ pinctrl-0 = <&hscif4_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ status = "okay"; ++}; ++ ++&i2c2 { ++ clock-frequency = <400000>; ++ ++ i2cswitch2: pca9548@74 { ++ compatible = "nxp,pca9548"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x74>; ++ reset-gpios = <&gpio6 5 GPIO_ACTIVE_LOW>; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ /* USB3.0 HUB node(s) */ ++ }; ++ ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ /* PCIe node(s) */ ++ }; ++ ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ /* Slot A (CN10) */ ++ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ ov106xx_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ ov106xx_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ ov106xx_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ ov106xx_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; ++ }; ++ }; ++ }; ++ ++ /* DS90UB9x4 @ 0x3a */ ++ ti9x4@0 { ++ compatible = "ti,ti9x4"; ++ reg = <0x3a>; ++ ti,links = <4>; ++ ti,lanes = <4>; ++ ti,forwarding-mode = "round-robin"; ++ ti,cable-mode = "stp"; ++ ++ POC0-gpios = <&gpio_exp_a_5c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_a_5c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_a_5c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_a_5c 11 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ ti9x4_des0ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ ti9x4_des0ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ ti9x4_des0ep2: endpoint@2 { ++ ti9x3-addr = <0x0e>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ ti9x4_des0ep3: endpoint@3 { ++ ti9x3-addr = <0x0f>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ ti9x4_csi0ep0: endpoint { ++ csi-rate = <1450>; ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ }; ++ ++ /* MAX9286 @ 0x2c */ ++ max9286@0 { ++ compatible = "maxim,max9286"; ++ reg = <0x2c>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ POC0-gpios = <&gpio_exp_a_5c 9 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_a_5c 8 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_a_5c 11 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_a_5c 10 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ /* Slot B (CN11) */ ++ ++ ov106xx@4 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x64>; ++ ++ port@0 { ++ ov106xx_in4: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ ov106xx_ti9x4_des1ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@5 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x65>; ++ ++ port@0 { ++ ov106xx_in5: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin5ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ ov106xx_ti9x4_des1ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@6 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x66>; ++ ++ port@0 { ++ ov106xx_in6: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin6ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ ov106xx_ti9x4_des1ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@7 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x67>; ++ ++ port@0 { ++ ov106xx_in7: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin7ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ ov106xx_ti9x4_des1ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep3>; ++ }; ++ }; ++ }; ++ ++ /* DS90UB9x4 @ 0x3a */ ++ ti9x4@1 { ++ compatible = "ti,ti9x4"; ++ reg = <0x3a>; ++ ti,links = <4>; ++ ti,lanes = <4>; ++ ti,forwarding-mode = "round-robin"; ++ ti,cable-mode = "stp"; ++ ++ POC0-gpios = <&gpio_exp_b_5c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_b_5c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_b_5c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_b_5c 11 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ ti9x4_des1ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in4>; ++ }; ++ ti9x4_des1ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in5>; ++ }; ++ ti9x4_des1ep2: endpoint@2 { ++ ti9x3-addr = <0x0e>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in6>; ++ }; ++ ti9x4_des1ep3: endpoint@3 { ++ ti9x3-addr = <0x0f>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in7>; ++ }; ++ }; ++ port@1 { ++ ti9x4_csi2ep0: endpoint { ++ csi-rate = <1450>; ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ }; ++ ++ /* MAX9286 @ 0x2c */ ++ max9286@1 { ++ compatible = "maxim,max9286"; ++ reg = <0x2c>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ POC0-gpios = <&gpio_exp_b_5c 9 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_b_5c 8 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_b_5c 11 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_b_5c 10 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ max9286_des1ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in4>; ++ }; ++ max9286_des1ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ }; ++ max9286_des1ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in6>; ++ }; ++ max9286_des1ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in7>; ++ }; ++ }; ++ port@1 { ++ max9286_csi2ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ /* Slot C (CN12) */ ++ }; ++ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ /* Slot A (CN10) */ ++ ++ /* PCA9535 is a redundant/deprecated card */ ++ gpio_exp_a_26: gpio@26 { ++ compatible = "nxp,pca9535"; ++ reg = <0x26>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_a_des_cfg1 { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A cfg1"; ++ }; ++ video_a_des_cfg0 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A cfg0"; ++ }; ++ video_a_pwr_shdn { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR_SHDN"; ++ }; ++ video_a_cam_pwr0 { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR0"; ++ }; ++ video_a_cam_pwr1 { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR1"; ++ }; ++ video_a_cam_pwr2 { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR2"; ++ }; ++ video_a_cam_pwr3 { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR3"; ++ }; ++ video_a_des_shdn { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A DES_SHDN"; ++ }; ++ video_a_des_led { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A led"; ++ }; ++ }; ++ ++ gpio_exp_a_5c: gpio@5c { ++ compatible = "maxim,max7325"; ++ reg = <0x5c>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_a_des_cfg2 { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A cfg2"; ++ }; ++ video_a_des_cfg1 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A cfg1"; ++ }; ++ video_a_des_cfg0 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A cfg0"; ++ }; ++ video_a_pwr_shdn { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR_SHDN"; ++ }; ++ video_a_des_shdn { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A DES_SHDN"; ++ }; ++ video_a_led { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A LED"; ++ }; ++ }; ++ }; ++ ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ /* Slot B (CN11) */ ++ ++ /* PCA9535 is a redundant/deprecated card */ ++ gpio_exp_b_26: gpio@26 { ++ compatible = "nxp,pca9535"; ++ reg = <0x26>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_b_des_cfg1 { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B cfg1"; ++ }; ++ video_b_des_cfg0 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B cfg0"; ++ }; ++ video_b_pwr_shdn { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR_SHDN"; ++ }; ++ video_b_cam_pwr0 { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR0"; ++ }; ++ video_b_cam_pwr1 { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR1"; ++ }; ++ video_b_cam_pwr2 { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR2"; ++ }; ++ video_b_cam_pwr3 { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR3"; ++ }; ++ video_b_des_shdn { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B DES_SHDN"; ++ }; ++ video_b_des_led { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-B led"; ++ }; ++ }; ++ ++ gpio_exp_b_5c: gpio@5c { ++ compatible = "maxim,max7325"; ++ reg = <0x5c>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_b_des_cfg2 { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B cfg2"; ++ }; ++ video_b_des_cfg1 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B cfg1"; ++ }; ++ video_b_des_cfg0 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B cfg0"; ++ }; ++ video_b_pwr_shdn { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR_SHDN"; ++ }; ++ video_b_des_shdn { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B DES_SHDN"; ++ }; ++ video_b_led { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-B LED"; ++ }; ++ }; ++ }; ++ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ /* Slot C (CN12) */ ++ }; ++ }; ++}; ++ ++&i2c4 { ++ i2cswitch4: pca9548@74 { ++ compatible = "nxp,pca9548"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x74>; ++ reset-gpios= <&gpio5 15 GPIO_ACTIVE_LOW>; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ /* FAN node - EMC2103 */ ++ fan_ctrl:ecm2103@2e { ++ compatible = "emc2103"; ++ reg = <0x2e>; ++ }; ++ }; ++ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ /* Power nodes - 2 x TPS544x20 */ ++ }; ++ ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ /* CAN and power board nodes */ ++ ++ gpio_ext_pwr: pca9535@22 { ++ compatible = "nxp,pca9535"; ++ reg = <0x22>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio1>; ++ interrupts = <25 IRQ_TYPE_EDGE_FALLING>; ++ ++ /* enable input DCDC after wake-up signal released */ ++ pwr_hold { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "pwr_hold"; ++ }; ++ ++ /* CAN0 */ ++ can0_stby { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can0_stby"; ++ }; ++ can0_load { ++ gpio-hog; ++ gpios = <0 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can0_120R_load"; ++ }; ++ /* CAN1 */ ++ can1_stby { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can1_stby"; ++ }; ++ can1_load { ++ gpio-hog; ++ gpios = <1 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can1_120R_load"; ++ }; ++ /* CAN2 */ ++ can2_stby { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can2_stby"; ++ }; ++ can2_load { ++ gpio-hog; ++ gpios = <2 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can2_120R_load"; ++ }; ++ can2_rst { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "can2_rst"; ++ }; ++ /* CAN3 */ ++ can3_stby { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can3_stby"; ++ }; ++ can3_load { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can3_120R_load"; ++ }; ++ can3_rst { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "can3_rst"; ++ }; ++ }; ++ }; ++ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ /* FPDLink output node - DS90UH947 */ ++ }; ++ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ /* BCM switch node */ ++ }; ++ ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ /* LED board node(s) */ ++ ++ gpio_ext_led: pca9535@22 { ++ compatible = "nxp,pca9535"; ++ reg = <0x22>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ /* gpios 0..7 are used for indication LEDs, low-active */ ++ }; ++ }; ++ ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ /* M2 connector i2c node(s) */ ++ }; ++ ++ /* port 7 is not used */ ++ }; ++}; ++ ++&pcie_bus_clk { ++ clock-frequency = <100000000>; ++ status = "okay"; ++}; ++ ++&pciec0 { ++ status = "okay"; ++}; ++ ++&pciec1 { ++ status = "okay"; ++}; ++ ++&vin0 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ vin0_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ vin1_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin2_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ vin2_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin3_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ vin3_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&vin4 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin4ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <0>; ++ remote-endpoint = <&ov106xx_in4>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep0: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin4_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ vin4_ti9x4_des1ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin5 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin5ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep1: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin5_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ vin5_ti9x4_des1ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin6 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin6ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <2>; ++ remote-endpoint = <&ov106xx_in6>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep2: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin6_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ vin6_ti9x4_des1ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin7 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin7ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <3>; ++ remote-endpoint = <&ov106xx_in7>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep3: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin7_max9286_des1ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ vin7_ti9x4_des1ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&csi40 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&csi41 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi41_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&rcar_sound { ++ pinctrl-0 = <&sound_clk_pins>; ++ ++ /* Multi DAI */ ++ #sound-dai-cells = <1>; ++}; ++ ++&sata { ++ status = "okay"; ++}; ++ ++&ssi1 { ++ /delete-property/shared-pin; ++}; ++ ++&avb { ++ /delete-property/phy-handle; ++ /delete-property/phy-gpios; ++ phy-mode = "rgmii"; ++ ++ /delete-node/ethernet-phy@0; ++ ++ fixed-link { ++ speed = <100>; ++ full-duplex; ++ }; ++}; ++ ++&msiof1 { ++ status = "disabled"; ++}; ++ ++&usb2_phy0 { ++ pinctrl-0 = <&usb0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&xhci0 { ++ status = "okay"; ++}; ++ ++&ehci0 { ++ status = "okay"; ++}; ++ ++&ohci0 { ++ status = "okay"; ++}; ++ ++&can0 { ++ pinctrl-0 = <&can0_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ renesas,can-clock-select = <0x0>; ++}; ++ ++&can1 { ++ pinctrl-0 = <&can1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ renesas,can-clock-select = <0x0>; ++}; ++ ++&canfd { ++ pinctrl-0 = <&canfd0_pins &canfd1_pins>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ ++ renesas,can-clock-select = <0x0>; ++ ++ channel0 { ++ status = "okay"; ++ }; ++ ++ channel1 { ++ status = "okay"; ++ }; ++}; ++ ++/* uncomment to enable CN12 on VIN4-7 */ ++//#include "ulcb-vb-cn12.dtsi" +diff --git a/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi +new file mode 100644 +index 0000000..0f49b44 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi +@@ -0,0 +1,1641 @@ ++/* ++ * Device Tree Source for the ULCB Videobox V2 board ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++/ { ++ leds { ++ compatible = "gpio-leds"; ++ ++ led5 { ++ gpios = <&gpio6 12 GPIO_ACTIVE_HIGH>; ++ }; ++ led6 { ++ gpios = <&gpio6 13 GPIO_ACTIVE_HIGH>; ++ }; ++ /* D13 - status 0 */ ++ led_ext00 { ++ gpios = <&gpio_ext_led 0 GPIO_ACTIVE_LOW>; ++ /* linux,default-trigger = "heartbeat"; */ ++ }; ++ /* D14 - status 1 */ ++ led_ext01 { ++ gpios = <&gpio_ext_led 1 GPIO_ACTIVE_LOW>; ++ /* linux,default-trigger = "mmc1"; */ ++ }; ++ /* D16 - HDMI0 */ ++ led_ext02 { ++ gpios = <&gpio_ext_led 2 GPIO_ACTIVE_LOW>; ++ }; ++ /* D18 - HDMI1 */ ++ led_ext03 { ++ gpios = <&gpio_ext_led 3 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++ ++ snd_clk: snd_clk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <24576000>; ++ clock-output-names = "scki"; ++ }; ++ ++ vcc_sdhi3: regulator-vcc-sdhi3 { ++ compatible = "regulator-fixed"; ++ ++ regulator-name = "SDHI3 Vcc"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpio = <&gpio4 17 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ vccq_sdhi3: regulator-vccq-sdhi3 { ++ compatible = "regulator-fixed"; ++ ++ regulator-name = "SDHI3 VccQ"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ++ fpdlink_switch: regulator@8 { ++ compatible = "regulator-fixed"; ++ regulator-name = "fpdlink_on"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio1 20 0>; ++ enable-active-high; ++ regulator-always-on; ++ }; ++ ++ hub_reset: regulator@9 { ++ compatible = "regulator-fixed"; ++ regulator-name = "hub_reset"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio5 5 0>; ++ enable-active-high; ++ regulator-always-on; ++ }; ++ ++ hub_power: regulator@10 { ++ compatible = "regulator-fixed"; ++ regulator-name = "hub_power"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ gpio = <&gpio6 28 0>; ++ enable-active-high; ++ regulator-always-on; ++ }; ++ ++ /delete-node/sound; ++ ++ rsnd_ak4613: sound@0 { ++ pinctrl-0 = <&sound_0_pins>; ++ pinctrl-names = "default"; ++ compatible = "simple-audio-card"; ++ ++ simple-audio-card,format = "left_j"; ++ simple-audio-card,name = "ak4613"; ++ ++ simple-audio-card,bitclock-master = <&sndcpu>; ++ simple-audio-card,frame-master = <&sndcpu>; ++ ++ sndcpu: simple-audio-card,cpu@1 { ++ sound-dai = <&rcar_sound>; ++ }; ++ ++ sndcodec: simple-audio-card,codec@1 { ++ sound-dai = <&ak4613>; ++ }; ++ }; ++ ++ lvds { ++ compatible = "panel-lvds"; ++ ++ width-mm = <210>; ++ height-mm = <158>; ++ ++ data-mapping = "jeida-24"; ++ ++ panel-timing { ++ /* 1280x800 @60Hz */ ++ clock-frequency = <65000000>; ++ hactive = <1280>; ++ vactive = <800>; ++ hsync-len = <40>; ++ hfront-porch = <80>; ++ hback-porch = <40>; ++ vfront-porch = <14>; ++ vback-porch = <14>; ++ vsync-len = <4>; ++ }; ++ ++ port { ++ lvds_in: endpoint { ++ remote-endpoint = <&du_out_lvds0>; ++ }; ++ }; ++ }; ++ ++ excan_ref_clk: excan-ref-clock { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <16000000>; ++ }; ++ ++ spi_gpio_sw { ++ compatible = "spi-gpio"; ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ gpio-sck = <&gpio0 8 GPIO_ACTIVE_HIGH>; ++ gpio-miso = <&gpio0 10 GPIO_ACTIVE_HIGH>; ++ gpio-mosi = <&gpio0 11 GPIO_ACTIVE_HIGH>; ++ cs-gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>; ++ num-chipselects = <1>; ++ ++ spidev: spidev@0 { ++ compatible = "spidev", "spi-gpio"; ++ reg = <0>; ++ spi-max-frequency = <25000000>; ++ spi-cpha; ++ spi-cpol; ++ }; ++ }; ++ ++ spi_gpio_can { ++ compatible = "spi-gpio"; ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ gpio-sck = <&gpio1 2 GPIO_ACTIVE_HIGH>; ++ gpio-miso = <&gpio1 3 GPIO_ACTIVE_HIGH>; ++ gpio-mosi = <&gpio1 1 GPIO_ACTIVE_HIGH>; ++ cs-gpios = <&gpio1 0 GPIO_ACTIVE_HIGH ++ &gpio1 4 GPIO_ACTIVE_HIGH>; ++ num-chipselects = <2>; ++ ++ spican0: spidev@0 { ++ compatible = "microchip,mcp2515"; ++ reg = <0>; ++ clocks = <&excan_ref_clk>; ++ interrupt-parent = <&gpio0>; ++ interrupts = <15 GPIO_ACTIVE_LOW>; ++ spi-max-frequency = <10000000>; ++ }; ++ spican1: spidev@1 { ++ compatible = "microchip,mcp2515"; ++ reg = <1>; ++ clocks = <&excan_ref_clk>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <5 GPIO_ACTIVE_LOW>; ++ spi-max-frequency = <10000000>; ++ }; ++ }; ++}; ++ ++&pfc { ++ hscif4_pins: hscif4 { ++ groups = "hscif4_data_a", "hscif4_ctrl"; ++ function = "hscif4"; ++ }; ++ ++ /delete-node/sound; ++ ++ sound_0_pins: sound1 { ++ groups = "ssi01239_ctrl", "ssi0_data", "ssi1_data_a"; ++ function = "ssi"; ++ }; ++ ++ usb0_pins: usb0 { ++ groups = "usb0"; ++ function = "usb0"; ++ }; ++ ++ usb2_pins: usb2 { ++ groups = "usb2"; ++ function = "usb2"; ++ }; ++ ++ can0_pins: can0 { ++ groups = "can0_data_a"; ++ function = "can0"; ++ }; ++ ++ can1_pins: can1 { ++ groups = "can1_data"; ++ function = "can1"; ++ }; ++ ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_a"; ++ function = "canfd0"; ++ }; ++ ++ canfd1_pins: canfd1 { ++ groups = "canfd1_data"; ++ function = "canfd1"; ++ }; ++ ++ sdhi3_pins: sd3 { ++ groups = "sdhi3_data4", "sdhi3_ctrl"; ++ function = "sdhi3"; ++ power-source = <3300>; ++ }; ++ ++ sdhi3_pins_uhs: sd3_uhs { ++ groups = "sdhi3_data4", "sdhi3_ctrl"; ++ function = "sdhi3"; ++ power-source = <1800>; ++ }; ++}; ++ ++&gpio0 { ++ video_a_irq { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A irq"; ++ }; ++ ++ video_b_irq { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B irq"; ++ }; ++ ++ video_c_irq { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-C irq"; ++ }; ++ can2_irq { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "CAN2 irq"; ++ }; ++}; ++ ++&gpio1 { ++ can3_irq { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "CAN3 irq"; ++ }; ++ gpioext_4_22_irq { ++ gpio-hog; ++ gpios = <25 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "0x22@i2c4 irq"; ++ }; ++ m2_0_sleep { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "M2 0 SLEEP#"; ++ }; ++ m2_1_sleep { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "M2 1 SLEEP#"; ++ }; ++ m2_0_pcie_det { ++ gpio-hog; ++ gpios = <18 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "M.2 0 PCIe/SATA"; ++ }; ++ m2_1_pcie_det { ++ gpio-hog; ++ gpios = <19 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "M.2 1 PCIe/SATA"; ++ }; ++ m2_1_rst { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "M.2 1 RST#"; ++ }; ++ switch_ext_phy_reset { ++ gpio-hog; ++ gpios = <16 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "BR ext phy reset"; ++ }; ++ switch_sw_reset { ++ gpio-hog; ++ gpios = <17 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "BR switch reset"; ++ }; ++ switch_1v2_en { ++ gpio-hog; ++ gpios = <27 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "BR 1.2V en"; ++ }; ++}; ++ ++&gpio2 { ++ m2_0_wake { ++ gpio-hog; ++ gpios = <1 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "M.2 0 WAKE#"; ++ }; ++ m2_0_clkreq { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "M.2 0 CLKREQ#"; ++ }; ++ switch_3v3_en { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "BR 3.3V en"; ++ }; ++}; ++ ++&gpio3 { ++ switch_int_phy_reset { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "BR int phy reset"; ++ }; ++}; ++ ++&gpio5 { ++ switch_2v5_en { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "BR 2.5V en"; ++ }; ++ switch_25mhz_en { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "BR 25MHz clk en"; ++ }; ++}; ++ ++&gpio6 { ++ m2_1_wake { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "M.2 1 WAKE#"; ++ }; ++ m2_1_clkreq { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "M.2 1 CLKREQ#"; ++ }; ++ ++ m2_0_rst { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "M.2 0 RST#"; ++ }; ++}; ++ ++&i2c2 { ++ clock-frequency = <400000>; ++ ++ i2cswitch2: pca9548@74 { ++ compatible = "nxp,pca9548"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x74>; ++ reset-gpios = <&gpio6 5 GPIO_ACTIVE_LOW>; ++ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ /* USB3.0 HUB node(s) */ ++ /* addr of TUSB8041 is 100.0100 = 0x44 */ ++ }; ++ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ /* Slot A (CN10) */ ++ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ ov106xx_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ ov106xx_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ ov106xx_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ ov106xx_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; ++ }; ++ }; ++ }; ++ ++ /* DS90UB9x4 @ 0x3a */ ++ ti9x4@0 { ++ compatible = "ti,ti9x4"; ++ reg = <0x3a>; ++ ti,links = <4>; ++ ti,lanes = <4>; ++ ti,forwarding-mode = "round-robin"; ++ ti,cable-mode = "stp"; ++ ++ POC0-gpios = <&gpio_exp_a_5c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_a_5c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_a_5c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_a_5c 11 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ ti9x4_des0ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ ti9x4_des0ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ ti9x4_des0ep2: endpoint@2 { ++ ti9x3-addr = <0x0e>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ ti9x4_des0ep3: endpoint@3 { ++ ti9x3-addr = <0x0f>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ ti9x4_csi0ep0: endpoint { ++ csi-rate = <1450>; ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ }; ++ ++ /* MAX9286 @ 0x2c */ ++ max9286@0 { ++ compatible = "maxim,max9286"; ++ reg = <0x2c>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ POC0-gpios = <&gpio_exp_a_5c 9 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_a_5c 8 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_a_5c 11 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_a_5c 10 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ /* Slot B (CN11) */ ++ ++ ov106xx@4 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x64>; ++ ++ port@0 { ++ ov106xx_in4: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ ov106xx_ti9x4_des1ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@5 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x65>; ++ ++ port@0 { ++ ov106xx_in5: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin5ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ ov106xx_ti9x4_des1ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@6 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x66>; ++ ++ port@0 { ++ ov106xx_in6: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin6ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ ov106xx_ti9x4_des1ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@7 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x67>; ++ ++ port@0 { ++ ov106xx_in7: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin7ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ ov106xx_ti9x4_des1ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep3>; ++ }; ++ }; ++ }; ++ ++ /* DS90UB9x4 @ 0x3a */ ++ ti9x4@1 { ++ compatible = "ti,ti9x4"; ++ reg = <0x3a>; ++ ti,links = <4>; ++ ti,lanes = <4>; ++ ti,forwarding-mode = "round-robin"; ++ ti,cable-mode = "stp"; ++ ++ POC0-gpios = <&gpio_exp_b_5c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_b_5c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_b_5c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_b_5c 11 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ ti9x4_des1ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in4>; ++ }; ++ ti9x4_des1ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in5>; ++ }; ++ ti9x4_des1ep2: endpoint@2 { ++ ti9x3-addr = <0x0e>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in6>; ++ }; ++ ti9x4_des1ep3: endpoint@3 { ++ ti9x3-addr = <0x0f>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in7>; ++ }; ++ }; ++ port@1 { ++ ti9x4_csi2ep0: endpoint { ++ csi-rate = <1450>; ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ }; ++ ++ /* MAX9286 @ 0x2c */ ++ max9286@1 { ++ compatible = "maxim,max9286"; ++ reg = <0x2c>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ POC0-gpios = <&gpio_exp_b_5c 9 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_b_5c 8 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_b_5c 11 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_b_5c 10 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ max9286_des1ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in4>; ++ }; ++ max9286_des1ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ }; ++ max9286_des1ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in6>; ++ }; ++ max9286_des1ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in7>; ++ }; ++ }; ++ port@1 { ++ max9286_csi2ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ /* Slot C (CN12) */ ++ }; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ /* Slot A (CN10) */ ++ ++ /* PCA9535 is a redundant/deprecated card */ ++ gpio_exp_a_26: gpio@26 { ++ compatible = "nxp,pca9535"; ++ reg = <0x26>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_a_pwr_shdn { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR_SHDN"; ++ }; ++ video_a_cam_pwr0 { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR0"; ++ }; ++ video_a_cam_pwr1 { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR1"; ++ }; ++ video_a_cam_pwr2 { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR2"; ++ }; ++ video_a_cam_pwr3 { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR3"; ++ }; ++ video_a_des_shdn { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A DES_SHDN"; ++ }; ++ video_a_des_led { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A led"; ++ }; ++ }; ++ ++ gpio_exp_a_5c: gpio@5c { ++ compatible = "maxim,max7325"; ++ reg = <0x5c>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_a_des_cfg0 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A cfg0"; ++ }; ++ video_a_pwr_shdn { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR_SHDN"; ++ }; ++ video_a_des_shdn { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A DES_SHDN"; ++ }; ++ video_a_led { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A LED"; ++ }; ++ }; ++ }; ++ ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ /* Slot B (CN11) */ ++ ++ /* PCA9535 is a redundant/deprecated card */ ++ gpio_exp_b_26: gpio@26 { ++ compatible = "nxp,pca9535"; ++ reg = <0x26>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_b_des_cfg1 { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B cfg1"; ++ }; ++ video_b_des_cfg0 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B cfg0"; ++ }; ++ video_b_pwr_shdn { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR_SHDN"; ++ }; ++ video_b_cam_pwr0 { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR0"; ++ }; ++ video_b_cam_pwr1 { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR1"; ++ }; ++ video_b_cam_pwr2 { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR2"; ++ }; ++ video_b_cam_pwr3 { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR3"; ++ }; ++ video_b_des_shdn { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B DES_SHDN"; ++ }; ++ video_b_des_led { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-B led"; ++ }; ++ }; ++ ++ gpio_exp_b_5c: gpio@5c { ++ compatible = "maxim,max7325"; ++ reg = <0x5c>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_b_des_cfg2 { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B cfg2"; ++ }; ++ video_b_des_cfg1 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B cfg1"; ++ }; ++ video_b_des_cfg0 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B cfg0"; ++ }; ++ video_b_pwr_shdn { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR_SHDN"; ++ }; ++ video_b_des_shdn { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B DES_SHDN"; ++ }; ++ video_b_led { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-B LED"; ++ }; ++ }; ++ }; ++ ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ /* Slot C (CN12) */ ++ }; ++ }; ++}; ++ ++&i2c4 { ++ i2cswitch4: pca9548@74 { ++ compatible = "nxp,pca9548"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x74>; ++ reset-gpios= <&gpio5 15 GPIO_ACTIVE_LOW>; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ /* FAN1 node - lm96063 */ ++ fan_ctrl_1:lm96063-1@4c { ++ compatible = "lm96163"; ++ reg = <0x4c>; ++ }; ++ }; ++ ++ i2c@6 { ++ /* FAN2 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ /* FAN2 node - lm96063 */ ++ fan_ctrl_2:lm96063-2@4c { ++ compatible = "lm96163"; ++ reg = <0x4c>; ++ }; ++ }; ++ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ ++ /* Power nodes - 2 x TPS544x20 */ ++ tps_5v: tps544c20@0x2a { ++ compatible = "tps544c20"; ++ reg = <0x2c>; ++ status = "disabled"; ++ }; ++ tps_3v3: tps544c20@0x22 { ++ compatible = "tps544c20"; ++ reg = <0x24>; ++ status = "disabled"; ++ }; ++ }; ++ ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ /* CAN and power board nodes */ ++ ++ gpio_ext_pwr: pca9535@22 { ++ compatible = "nxp,pca9535"; ++ reg = <0x22>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio1>; ++ interrupts = <25 IRQ_TYPE_EDGE_FALLING>; ++ ++ /* enable input DCDC after wake-up signal released */ ++ pwr_hold { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "pwr_hold"; ++ }; ++ pwr_5v_out { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "pwr_5v_out"; ++ }; ++ pwr_5v_oc { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "pwr_5v_oc"; ++ }; ++ pwr_wake8 { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "wake8"; ++ }; ++ pwr_wake7 { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "wake7"; ++ }; ++ ++ /* CAN0 */ ++ can0_stby { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can0_stby"; ++ }; ++ can0_load { ++ gpio-hog; ++ gpios = <0 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "can0_120R_load"; ++ }; ++ /* CAN1 */ ++ can1_stby { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can1_stby"; ++ }; ++ can1_load { ++ gpio-hog; ++ gpios = <1 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "can1_120R_load"; ++ }; ++ /* CAN2 */ ++ can2_stby { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can2_stby"; ++ }; ++ can2_load { ++ gpio-hog; ++ gpios = <2 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "can2_120R_load"; ++ }; ++ can2_rst { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "can2_rst"; ++ }; ++ /* CAN3 */ ++ can3_stby { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can3_stby"; ++ }; ++ can3_load { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "can3_120R_load"; ++ }; ++ can3_rst { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "can3_rst"; ++ }; ++ }; ++ }; ++ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ /* FPDLink output node - DS90UH947 */ ++ }; ++ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ /* BCM switch node */ ++ }; ++ ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ /* LED board node(s) */ ++ ++ gpio_ext_led: pca9535@22 { ++ compatible = "nxp,pca9535"; ++ reg = <0x22>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ /* gpios 0..7 are used for indication LEDs, low-active */ ++ }; ++ rtc: mcp79411@6f { ++ compatible = "microchip,mcp7941x"; ++ reg = <0x6f>; ++ }; ++ }; ++ ++ /* port 7 is not used */ ++ }; ++}; ++ ++&pcie_bus_clk { ++ clock-frequency = <100000000>; ++ status = "okay"; ++}; ++ ++&pciec0 { ++ status = "okay"; ++}; ++ ++&pciec1 { ++ status = "okay"; ++}; ++ ++&vin0 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ vin0_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ vin1_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin2_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ vin2_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin3_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ vin3_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&vin4 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin4ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <0>; ++ remote-endpoint = <&ov106xx_in4>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep0: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin4_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ vin4_ti9x4_des1ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin5 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin5ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep1: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin5_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ vin5_ti9x4_des1ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin6 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin6ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <2>; ++ remote-endpoint = <&ov106xx_in6>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep2: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin6_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ vin6_ti9x4_des1ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin7 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin7ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <3>; ++ remote-endpoint = <&ov106xx_in7>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep3: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin7_max9286_des1ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ vin7_ti9x4_des1ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&csi40 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&csi41 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi41_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&rcar_sound { ++ pinctrl-0 = <&sound_clk_pins>; ++ ++ /* Multi DAI */ ++ #sound-dai-cells = <1>; ++}; ++ ++&ssi1 { ++ /delete-property/shared-pin; ++}; ++ ++&sdhi3 { ++ pinctrl-0 = <&sdhi3_pins>; ++ pinctrl-1 = <&sdhi3_pins_uhs>; ++ pinctrl-names = "default", "state_uhs"; ++ ++ vmmc-supply = <&vcc_sdhi3>; ++ vqmmc-supply = <&vccq_sdhi3>; ++ cd-gpios = <&gpio4 15 GPIO_ACTIVE_LOW>; ++ wp-gpios = <&gpio4 16 GPIO_ACTIVE_HIGH>; ++ bus-width = <4>; ++ sd-uhs-sdr50; ++ status = "okay"; ++}; ++ ++&msiof1 { ++ status = "disabled"; ++}; ++ ++&usb2_phy0 { ++ pinctrl-0 = <&usb0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&usb2_phy2 { ++ pinctrl-0 = <&usb2_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&xhci0 { ++ status = "okay"; ++}; ++ ++&ehci0 { ++ status = "okay"; ++}; ++ ++&ehci2 { ++ status = "okay"; ++}; ++ ++&ohci0 { ++ status = "okay"; ++}; ++ ++&ohci2 { ++ status = "okay"; ++}; ++ ++&can0 { ++ pinctrl-0 = <&can0_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ renesas,can-clock-select = <0x0>; ++}; ++ ++&can1 { ++ pinctrl-0 = <&can1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ renesas,can-clock-select = <0x0>; ++}; ++ ++&canfd { ++ pinctrl-0 = <&canfd0_pins &canfd1_pins>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ ++ renesas,can-clock-select = <0x0>; ++ ++ channel0 { ++ status = "okay"; ++ }; ++ ++ channel1 { ++ status = "okay"; ++ }; ++}; ++ ++/* uncomment to enable CN12 on VIN4-7 */ ++//#include "ulcb-vb2-cn12.dtsi" +diff --git a/arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi +new file mode 100644 +index 0000000..067607a +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi +@@ -0,0 +1,523 @@ ++/* ++ * Device Tree Source for the ULCB Videobox Mini board ++ * ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++/ { ++ aliases { ++ serial1 = &scif1; ++ }; ++ ++ lvds { ++ compatible = "panel-lvds"; ++ ++ width-mm = <210>; ++ height-mm = <158>; ++ ++ data-mapping = "jeida-24"; ++ ++ panel-timing { ++ /* 1280x800 @60Hz */ ++ clock-frequency = <65000000>; ++ hactive = <1280>; ++ vactive = <800>; ++ hsync-len = <40>; ++ hfront-porch = <80>; ++ hback-porch = <40>; ++ vfront-porch = <14>; ++ vback-porch = <14>; ++ vsync-len = <4>; ++ }; ++ ++ port { ++ lvds_in: endpoint { ++ remote-endpoint = <&du_out_lvds0>; ++ }; ++ }; ++ }; ++}; ++ ++&can0 { ++ pinctrl-0 = <&can0_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&can1 { ++ pinctrl-0 = <&can1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&canfd { ++ pinctrl-0 = <&canfd0_pins &canfd1_pins>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ ++ channel0 { ++ status = "okay"; ++ }; ++ ++ channel1 { ++ status = "okay"; ++ }; ++}; ++ ++&csi41 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi41_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&i2c1 { ++ pinctrl-0 = <&i2c1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ clock-frequency = <400000>; ++ ++ i2cswitch1: i2c-switch@74 { ++ compatible = "nxp,pca9548"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x74>; ++ reset-gpios = <&gpio5 25 GPIO_ACTIVE_LOW>; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ ov106xx_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin5ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ ov106xx_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin6ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ ov106xx_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin7ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ ov106xx_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; ++ }; ++ }; ++ }; ++ ++ max9286@0 { ++ compatible = "maxim,max9286"; ++ reg = <0x2c>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ POC0-gpios = <&gpio_exp_6c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_6c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_6c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_6c 11 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ }; ++ ++ ti9x4@0 { ++ compatible = "ti,ti9x4"; ++ reg = <0x3a>; ++ ti,sensor_delay = <350>; ++ ti,links = <4>; ++ ti,lanes = <4>; ++ ti,forwarding-mode = "round-robin"; ++ ti,cable-mode = "coax"; ++ ++ POC0-gpios = <&gpio_exp_6c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_6c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_6c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_6c 11 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ ti9x4_des0ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ ti9x4_des0ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ ti9x4_des0ep2: endpoint@2 { ++ ti9x3-addr = <0x0e>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ ti9x4_des0ep3: endpoint@3 { ++ ti9x3-addr = <0x0f>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ ti9x4_csi0ep0: endpoint { ++ csi-rate = <1450>; ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ ++ gpio_exp_6c: gpio@6c { ++ compatible = "maxim,max7325"; ++ reg = <0x6c>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ virq { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "VIRQ"; ++ }; ++ des_cfg { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "CNFG0"; ++ }; ++ pwr_shdn { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "PWR_SHDN"; ++ }; ++ des_shdn { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Des_SHDN"; ++ }; ++ fpdl_shdn { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "FPDL_SHDN"; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&gpio1 { ++ can0stby { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "CAN0STBY"; ++ }; ++}; ++ ++&gpio2 { ++ can0_load { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "CAN0Loff"; ++ }; ++}; ++ ++&pfc { ++ can0_pins: can0 { ++ groups = "can0_data_a"; ++ function = "can0"; ++ }; ++ ++ can1_pins: can1 { ++ groups = "can1_data"; ++ function = "can1"; ++ }; ++ ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_a"; ++ function = "canfd0"; ++ }; ++ ++ canfd1_pins: canfd1 { ++ groups = "canfd1_data"; ++ function = "canfd1"; ++ }; ++ ++ i2c1_pins: i2c1 { ++ groups = "i2c1_b"; ++ function = "i2c1"; ++ }; ++ ++ scif1_pins: scif1 { ++ groups = "scif1_data_a"; ++ function = "scif1"; ++ }; ++}; ++ ++&scif1 { ++ pinctrl-0 = <&scif1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&vin4 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin4ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin4_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ vin4_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin5 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin5ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin5_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ vin5_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin6 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin6ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin6_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ vin6_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin7 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin7ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin7_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ vin7_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; ++ }; ++ }; ++ }; ++}; ++ +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0041-arm64-dts-renesas-ulcb-kf-Move-panel-configuration-t.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0041-arm64-dts-renesas-ulcb-kf-Move-panel-configuration-t.patch new file mode 100644 index 00000000..d640d26e --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0041-arm64-dts-renesas-ulcb-kf-Move-panel-configuration-t.patch @@ -0,0 +1,125 @@ +From 4345b900761a169590891eb1946aae7d55b0c749 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Mon, 17 Dec 2018 16:47:51 +0300 +Subject: [PATCH 032/122] arm64: dts: renesas: ulcb-kf: Move panel + configuration to ulcb-kf-panel.dtsi + +This moves LVDS panel configuration from ulcb-kf.dtsi +to ulcb-kf-panel.dtsi. This various LVDS panel setup +a bit easier. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/ulcb-kf-panel.dtsi | 41 ++++++++++++++++++++++++++ + arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 34 +++------------------ + 2 files changed, 45 insertions(+), 30 deletions(-) + create mode 100644 arch/arm64/boot/dts/renesas/ulcb-kf-panel.dtsi + +diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf-panel.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf-panel.dtsi +new file mode 100644 +index 0000000..b54c935 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/ulcb-kf-panel.dtsi +@@ -0,0 +1,41 @@ ++/* ++ * Device Tree Source for the Kingfisher (ULCB extension) LVDS panel ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++&lvds { ++ compatible = "panel-lvds"; ++ ++ width-mm = <210>; ++ height-mm = <158>; ++ ++ data-mapping = "jeida-24"; ++ ++ panel-timing { ++ /* 1280x800 @60Hz Boundary Devices BD101LCC1 compatible panel */ ++ clock-frequency = <65000000>; ++ hactive = <1280>; ++ vactive = <800>; ++ hsync-len = <40>; ++ hfront-porch = <80>; ++ hback-porch = <40>; ++ vfront-porch = <14>; ++ vback-porch = <14>; ++ vsync-len = <4>; ++ }; ++}; ++ ++&gpio2 { ++ bl_pwm { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "BL PWM 100%"; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +index a70636e..4ab8d60 100644 +--- a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi ++++ b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +@@ -171,27 +171,7 @@ + dais = <&rsnd_port3>; + }; + +- lvds { +- compatible = "panel-lvds"; +- +- width-mm = <210>; +- height-mm = <158>; +- +- data-mapping = "jeida-24"; +- +- panel-timing { +- /* 1280x800 @60Hz */ +- clock-frequency = <65000000>; +- hactive = <1280>; +- vactive = <800>; +- hsync-len = <40>; +- hfront-porch = <80>; +- hback-porch = <40>; +- vfront-porch = <14>; +- vback-porch = <14>; +- vsync-len = <4>; +- }; +- ++ lvds: lvds { + port { + lvds_in: endpoint { + remote-endpoint = <&lvds0_out>; +@@ -337,15 +317,6 @@ + status = "okay"; + }; + +-&gpio2 { +- bl_pwm { +- gpio-hog; +- gpios = <3 GPIO_ACTIVE_HIGH>; +- output-high; +- line-name = "BL PWM 100%"; +- }; +-}; +- + &gpio4 { + most_rst { + gpio-hog; +@@ -1457,5 +1428,8 @@ + status = "okay"; + }; + ++/* set LVDS panel timings and pins */ ++#include "ulcb-kf-panel.dtsi" ++ + + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0042-arm64-dts-renesas-r8a7795-es1-h3ulcb-disable-eMMC.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0042-arm64-dts-renesas-r8a7795-es1-h3ulcb-disable-eMMC.patch new file mode 100644 index 00000000..8811c9f6 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0042-arm64-dts-renesas-r8a7795-es1-h3ulcb-disable-eMMC.patch @@ -0,0 +1,27 @@ +From cee42d4e680e0d4f3485eb772371d26b769a5cec Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Sat, 15 Jul 2017 00:44:12 +0300 +Subject: [PATCH 033/122] arm64: dts: renesas: r8a7795-es1-h3ulcb: disable eMMC + +Disable eMMC due to ES1.x silicon bug + +Signed-off-by: Vladimir Barinov +--- + arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb.dts | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb.dts +index 119f06c..658cc0f 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb.dts +@@ -78,6 +78,7 @@ + + &sdhi2 { + /delete-property/ mmc-hs400-1_8v; ++ status = "disabled"; + }; + + &vspbc { +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0043-pinctrl-sh-pfc-pfc-r8a77965-Add-missing-avb_mii-pin-.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0043-pinctrl-sh-pfc-pfc-r8a77965-Add-missing-avb_mii-pin-.patch new file mode 100644 index 00000000..adea08fe --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0043-pinctrl-sh-pfc-pfc-r8a77965-Add-missing-avb_mii-pin-.patch @@ -0,0 +1,154 @@ +From dda649f6888394cfdd469167c2976eee2c4f64e7 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Fri, 7 Jul 2017 16:22:40 +0300 +Subject: [PATCH 034/122] pinctrl: r8a779x: add mlb pinmux + +Signed-off-by: Andrey Gusakov +Signed-off-by: Vladimir Barinov +--- + drivers/pinctrl/sh-pfc/pfc-r8a7795-es1.c | 14 ++++++++++++++ + drivers/pinctrl/sh-pfc/pfc-r8a7795.c | 14 ++++++++++++++ + drivers/pinctrl/sh-pfc/pfc-r8a7796.c | 14 ++++++++++++++ + 3 files changed, 42 insertions(+) + +diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7795-es1.c b/drivers/pinctrl/sh-pfc/pfc-r8a7795-es1.c +index 9f302f6..827155c1 100644 +--- a/drivers/pinctrl/sh-pfc/pfc-r8a7795-es1.c ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a7795-es1.c +@@ -2387,6 +2387,14 @@ static const unsigned int intc_ex_irq5_mux[] = { + IRQ5_MARK, + }; + ++/* - MLB+ ------------------------------------------------------------------- */ ++static const unsigned int mlb_3pin_pins[] = { ++ RCAR_GP_PIN(5, 23), RCAR_GP_PIN(5, 24), RCAR_GP_PIN(5, 25), ++}; ++static const unsigned int mlb_3pin_mux[] = { ++ MLB_CLK_MARK, MLB_SIG_MARK, MLB_DAT_MARK, ++}; ++ + /* - MSIOF0 ----------------------------------------------------------------- */ + static const unsigned int msiof0_clk_pins[] = { + /* SCK */ +@@ -4289,6 +4297,7 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { + SH_PFC_PIN_GROUP(intc_ex_irq3), + SH_PFC_PIN_GROUP(intc_ex_irq4), + SH_PFC_PIN_GROUP(intc_ex_irq5), ++ SH_PFC_PIN_GROUP(mlb_3pin), + SH_PFC_PIN_GROUP(msiof0_clk), + SH_PFC_PIN_GROUP(msiof0_sync), + SH_PFC_PIN_GROUP(msiof0_ss1), +@@ -4698,6 +4707,10 @@ static const char * const intc_ex_groups[] = { + "intc_ex_irq5", + }; + ++static const char * const mlb_3pin_groups[] = { ++ "mlb_3pin", ++}; ++ + static const char * const msiof0_groups[] = { + "msiof0_clk", + "msiof0_sync", +@@ -5046,6 +5059,7 @@ static const struct sh_pfc_function pinmux_functions[] = { + SH_PFC_FUNCTION(i2c5), + SH_PFC_FUNCTION(i2c6), + SH_PFC_FUNCTION(intc_ex), ++ SH_PFC_FUNCTION(mlb_3pin), + SH_PFC_FUNCTION(msiof0), + SH_PFC_FUNCTION(msiof1), + SH_PFC_FUNCTION(msiof2), +diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c +index 3ebe8de..b0fde0d 100644 +--- a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c +@@ -2469,6 +2469,14 @@ static const unsigned int intc_ex_irq5_mux[] = { + IRQ5_MARK, + }; + ++/* - MLB+ ------------------------------------------------------------------- */ ++static const unsigned int mlb_3pin_pins[] = { ++ RCAR_GP_PIN(5, 23), RCAR_GP_PIN(5, 24), RCAR_GP_PIN(5, 25), ++}; ++static const unsigned int mlb_3pin_mux[] = { ++ MLB_CLK_MARK, MLB_SIG_MARK, MLB_DAT_MARK, ++}; ++ + /* - MSIOF0 ----------------------------------------------------------------- */ + static const unsigned int msiof0_clk_pins[] = { + /* SCK */ +@@ -4329,6 +4337,7 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { + SH_PFC_PIN_GROUP(intc_ex_irq3), + SH_PFC_PIN_GROUP(intc_ex_irq4), + SH_PFC_PIN_GROUP(intc_ex_irq5), ++ SH_PFC_PIN_GROUP(mlb_3pin), + SH_PFC_PIN_GROUP(msiof0_clk), + SH_PFC_PIN_GROUP(msiof0_sync), + SH_PFC_PIN_GROUP(msiof0_ss1), +@@ -4751,6 +4760,10 @@ static const char * const intc_ex_groups[] = { + "intc_ex_irq5", + }; + ++static const char * const mlb_3pin_groups[] = { ++ "mlb_3pin", ++}; ++ + static const char * const msiof0_groups[] = { + "msiof0_clk", + "msiof0_sync", +@@ -5103,6 +5116,7 @@ static const struct sh_pfc_function pinmux_functions[] = { + SH_PFC_FUNCTION(i2c5), + SH_PFC_FUNCTION(i2c6), + SH_PFC_FUNCTION(intc_ex), ++ SH_PFC_FUNCTION(mlb_3pin), + SH_PFC_FUNCTION(msiof0), + SH_PFC_FUNCTION(msiof1), + SH_PFC_FUNCTION(msiof2), +diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c +index 1617559..43cb931 100644 +--- a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c +@@ -2478,6 +2478,14 @@ static const unsigned int intc_ex_irq5_mux[] = { + IRQ5_MARK, + }; + ++/* - MLB+ ------------------------------------------------------------------- */ ++static const unsigned int mlb_3pin_pins[] = { ++ RCAR_GP_PIN(5, 23), RCAR_GP_PIN(5, 24), RCAR_GP_PIN(5, 25), ++}; ++static const unsigned int mlb_3pin_mux[] = { ++ MLB_CLK_MARK, MLB_SIG_MARK, MLB_DAT_MARK, ++}; ++ + /* - MSIOF0 ----------------------------------------------------------------- */ + static const unsigned int msiof0_clk_pins[] = { + /* SCK */ +@@ -4307,6 +4315,7 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { + SH_PFC_PIN_GROUP(intc_ex_irq3), + SH_PFC_PIN_GROUP(intc_ex_irq4), + SH_PFC_PIN_GROUP(intc_ex_irq5), ++ SH_PFC_PIN_GROUP(mlb_3pin), + SH_PFC_PIN_GROUP(msiof0_clk), + SH_PFC_PIN_GROUP(msiof0_sync), + SH_PFC_PIN_GROUP(msiof0_ss1), +@@ -4725,6 +4734,10 @@ static const char * const intc_ex_groups[] = { + "intc_ex_irq5", + }; + ++static const char * const mlb_3pin_groups[] = { ++ "mlb_3pin", ++}; ++ + static const char * const msiof0_groups[] = { + "msiof0_clk", + "msiof0_sync", +@@ -5064,6 +5077,7 @@ static const struct sh_pfc_function pinmux_functions[] = { + SH_PFC_FUNCTION(i2c5), + SH_PFC_FUNCTION(i2c6), + SH_PFC_FUNCTION(intc_ex), ++ SH_PFC_FUNCTION(mlb_3pin), + SH_PFC_FUNCTION(msiof0), + SH_PFC_FUNCTION(msiof1), + SH_PFC_FUNCTION(msiof2), +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0045-clk-r8a779x-add-mlp-clock.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0045-clk-r8a779x-add-mlp-clock.patch new file mode 100644 index 00000000..6a5b9082 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0045-clk-r8a779x-add-mlp-clock.patch @@ -0,0 +1,38 @@ +From 9bb19c618df3b036672f9abb0261960ba0c4966b Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Fri, 7 Jul 2017 16:23:44 +0300 +Subject: [PATCH 035/122] clk: r8a779x: add mlp clock + +Signed-off-by: Andrey Gusakov +--- + drivers/clk/renesas/r8a7795-cpg-mssr.c | 1 + + drivers/clk/renesas/r8a7796-cpg-mssr.c | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c +index 5b09453..fc033cc 100644 +--- a/drivers/clk/renesas/r8a7795-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c +@@ -218,6 +218,7 @@ static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = { + DEF_MOD("lvds", 727, R8A7795_CLK_S0D4), + DEF_MOD("hdmi1", 728, R8A7795_CLK_HDMI), + DEF_MOD("hdmi0", 729, R8A7795_CLK_HDMI), ++ DEF_MOD("mlp", 802, R8A7795_CLK_S2D1), + DEF_MOD("vin7", 804, R8A7795_CLK_S0D2), + DEF_MOD("vin6", 805, R8A7795_CLK_S0D2), + DEF_MOD("vin5", 806, R8A7795_CLK_S0D2), +diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c +index ad1e3f8..aeb435f 100644 +--- a/drivers/clk/renesas/r8a7796-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c +@@ -194,6 +194,7 @@ static struct mssr_mod_clk r8a7796_mod_clks[] __initdata = { + DEF_MOD("du0", 724, R8A7796_CLK_S2D1), + DEF_MOD("lvds", 727, R8A7796_CLK_S2D1), + DEF_MOD("hdmi0", 729, R8A7796_CLK_HDMI), ++ DEF_MOD("mlp", 802, R8A7796_CLK_S2D1), + DEF_MOD("vin7", 804, R8A7796_CLK_S0D2), + DEF_MOD("vin6", 805, R8A7796_CLK_S0D2), + DEF_MOD("vin5", 806, R8A7796_CLK_S0D2), +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0046-arm64-dts-renesas-r8a779x-add-mlp-nodes.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0046-arm64-dts-renesas-r8a779x-add-mlp-nodes.patch new file mode 100644 index 00000000..672afefa --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0046-arm64-dts-renesas-r8a779x-add-mlp-nodes.patch @@ -0,0 +1,62 @@ +From decad395fffdd4b5426434696596c908dbb6ca3a Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Fri, 7 Jul 2017 16:25:06 +0300 +Subject: [PATCH 036/122] arm64: dts: renesas: r8a779x: add mlp nodes + +Signed-off-by: Andrey Gusakov +--- + arch/arm64/boot/dts/renesas/r8a7795.dtsi | 13 +++++++++++++ + arch/arm64/boot/dts/renesas/r8a7796.dtsi | 13 +++++++++++++ + 2 files changed, 26 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi +index f15d587..b9c4a39 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi +@@ -1868,6 +1868,19 @@ + status = "disabled"; + }; + ++ mlp: mlp@ec520000 { ++ compatible = "rcar,medialb-dim2"; ++ reg = <0 0xec520000 0 0x800>; ++ interrupts = , ++ , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 802>; ++ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ + msiof0: spi@e6e90000 { + compatible = "renesas,msiof-r8a7795", + "renesas,rcar-gen3-msiof"; +diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi +index 00433dc..c41d1c2 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7796.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi +@@ -1791,6 +1791,19 @@ + status = "disabled"; + }; + ++ mlp: mlp@ec520000 { ++ compatible = "rcar,medialb-dim2"; ++ reg = <0 0xec520000 0 0x800>; ++ interrupts = , ++ , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 802>; ++ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ + msiof1: spi@e6ea0000 { + compatible = "renesas,msiof-r8a7796", + "renesas,rcar-gen3-msiof"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0047-arm64-dts-renesas-ulcb-kf-enable-sd3.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0047-arm64-dts-renesas-ulcb-kf-enable-sd3.patch new file mode 100644 index 00000000..cf309759 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0047-arm64-dts-renesas-ulcb-kf-enable-sd3.patch @@ -0,0 +1,28 @@ +From 92895c4d38f2a9e03217ffc4fa3fc7d143205d93 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Fri, 27 Oct 2017 20:54:47 +0300 +Subject: [PATCH 037/122] arm64: dts: renesas: ulcb-kf: enable sd3 + +This enables SD3 on CN47 instead wifi + +Signed-off-by: Vladimir Barinov +--- + arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +index 4ab8d60..da522a2 100644 +--- a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi ++++ b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +@@ -1433,3 +1433,8 @@ + + + ++/* enable CN47: SD on SDHI3 */ ++#include "ulcb-kf-sd3.dtsi" ++ ++ ++ +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0048-arm64-dts-renesas-ulcb-kf-enable-most.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0048-arm64-dts-renesas-ulcb-kf-enable-most.patch new file mode 100644 index 00000000..d26cfc68 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0048-arm64-dts-renesas-ulcb-kf-enable-most.patch @@ -0,0 +1,28 @@ +From 93c3ef73d1b9fdab33a2e875b50a94840ff6cd31 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Fri, 27 Oct 2017 20:58:21 +0300 +Subject: [PATCH 038/122] arm64: dts: renesas: ulcb-kf: enable most + +This enables MOST on CN22 instead GPS + +Signed-off-by: Vladimir Barinov +--- + arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +index da522a2..61b7851 100644 +--- a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi ++++ b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +@@ -1438,3 +1438,8 @@ + + + ++/* enable CN22: enable MOST and disable GPS (move R661->R660, R663->R662) */ ++#include "ulcb-kf-most.dtsi" ++ ++ ++ +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0049-clk-r8a779x-add-IMP-clock.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0049-clk-r8a779x-add-IMP-clock.patch new file mode 100644 index 00000000..28737061 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0049-clk-r8a779x-add-IMP-clock.patch @@ -0,0 +1,40 @@ +From 2ba0b0a944c433438730c3dd78985dd43abb51c4 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Mon, 27 Nov 2017 16:53:06 +0300 +Subject: [PATCH 039/122] clk: r8a779x: add IMP clock + +This adds IMP clock sources for Gen3 SoCs + +Signed-off-by: Vladimir Barinov +--- + drivers/clk/renesas/r8a7795-cpg-mssr.c | 1 + + drivers/clk/renesas/r8a7796-cpg-mssr.c | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c +index fc033cc..bd5a73f 100644 +--- a/drivers/clk/renesas/r8a7795-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c +@@ -233,6 +233,7 @@ static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = { + DEF_MOD("imr2", 821, R8A7795_CLK_S0D2), + DEF_MOD("imr1", 822, R8A7795_CLK_S0D2), + DEF_MOD("imr0", 823, R8A7795_CLK_S0D2), ++ DEF_MOD("imp", 824, R8A7795_CLK_S1D1), + DEF_MOD("gpio7", 905, R8A7795_CLK_S3D4), + DEF_MOD("gpio6", 906, R8A7795_CLK_S3D4), + DEF_MOD("gpio5", 907, R8A7795_CLK_S3D4), +diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c +index aeb435f..f4f1350 100644 +--- a/drivers/clk/renesas/r8a7796-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c +@@ -206,6 +206,7 @@ static struct mssr_mod_clk r8a7796_mod_clks[] __initdata = { + DEF_MOD("etheravb", 812, R8A7796_CLK_S0D6), + DEF_MOD("imr1", 822, R8A7796_CLK_S0D2), + DEF_MOD("imr0", 823, R8A7796_CLK_S0D2), ++ DEF_MOD("imp", 824, R8A7796_CLK_S1D1), + DEF_MOD("gpio7", 905, R8A7796_CLK_S3D4), + DEF_MOD("gpio6", 906, R8A7796_CLK_S3D4), + DEF_MOD("gpio5", 907, R8A7796_CLK_S3D4), +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0050-arm64-dts-renesas-r8a779x-add-IMP-nodes.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0050-arm64-dts-renesas-r8a779x-add-IMP-nodes.patch new file mode 100644 index 00000000..f0f8ff8b --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0050-arm64-dts-renesas-r8a779x-add-IMP-nodes.patch @@ -0,0 +1,198 @@ +From 853eb0ced4522f2d93f4b26abf656f358fd7a80e Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Tue, 28 Nov 2017 14:47:12 +0300 +Subject: [PATCH 040/122] arm64: dts: renesas: r8a779x: add IMP nodes + +This adds IMP resource nodes for Gen3 SoCs + +Signed-off-by: Vladimir Barinov +--- + arch/arm64/boot/dts/renesas/r8a7795.dtsi | 98 ++++++++++++++++++++++++++++++++ + arch/arm64/boot/dts/renesas/r8a7796.dtsi | 62 ++++++++++++++++++++ + 2 files changed, 160 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi +index b9c4a39..536deef 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi +@@ -3265,6 +3265,104 @@ + }; + }; + ++ imp_distributer: impdes0 { ++ compatible = "renesas,impx4-distributer"; ++ reg = <0 0xffa00000 0 0x4000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ imp0 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff900000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <0>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ imp1 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff920000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <1>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ imp2 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff940000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <2>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ imp3 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff960000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <3>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ impsc0 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff980000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <4>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ impsc1 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff990000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <5>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ impsl0 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff9c0000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <12>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ impdm0 { ++ compatible = "renesas,impx5-dmac"; ++ reg = <0 0xffa10000 0 0x4000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <16>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ impc0 { ++ compatible = "renesas,impx4-memory"; ++ reg = <0 0xffa40000 0 0x20000>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ imprtt { ++ compatible = "renesas,impx5-rtt"; ++ reg = <0 0xff8d0000 0 0x1000>, ++ <0 0xe6150000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ + thermal-zones { + emergency { + polling-delay = <1000>; +diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi +index c41d1c2..383639b 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7796.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi +@@ -2638,6 +2638,68 @@ + resets = <&cpg 822>; + }; + ++ imp_distributer: impdes0 { ++ compatible = "renesas,impx4-distributer"; ++ reg = <0 0xffa00000 0 0x4000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7796_PD_A3IR>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ imp0 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff900000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <0>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7796_PD_A3IR>; ++ }; ++ ++ imp1 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff920000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <1>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7796_PD_A3IR>; ++ }; ++ ++ impsc0 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff980000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <4>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7796_PD_A3IR>; ++ }; ++ ++ impdm0 { ++ compatible = "renesas,impx5-dmac"; ++ reg = <0 0xffa10000 0 0x4000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <16>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7796_PD_A3IR>; ++ }; ++ ++ impc0 { ++ compatible = "renesas,impx4-memory"; ++ reg = <0 0xffa40000 0 0x20000>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7796_PD_A3IR>; ++ }; ++ ++ imprtt { ++ compatible = "renesas,impx5-rtt"; ++ reg = <0 0xff8d0000 0 0x1000>, ++ <0 0xe6150000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7796_PD_A3IR>; ++ }; ++ + fcpcs: vcp4@fe90f000 { + compatible = "renesas,vcp4-fcpcs"; + reg = <0 0xfe90f000 0 0x200>; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch new file mode 100644 index 00000000..7d57c38d --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch @@ -0,0 +1,6490 @@ +From e8fd03e53c50c67a2aebf19f39a9f14b583f0e2d Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Sun, 14 May 2017 14:48:08 +0300 +Subject: [PATCH] arm64: renesas: r8a7798: Add Renesas R8A7798 SoC support + +This adds Renesas R8A7798 SoC support + +Signed-off-by: Vladimir Barinov +Signed-off-by: Mikhail Ulyanov +--- + arch/arm64/Kconfig.platforms | 8 + + arch/arm64/boot/dts/renesas/r8a7798.dtsi | 1700 +++++++++++++ + drivers/clk/renesas/Kconfig | 1 + + drivers/clk/renesas/Makefile | 1 + + drivers/clk/renesas/r8a7798-cpg-mssr.c | 292 +++ + drivers/clk/renesas/rcar-gen3-cpg.c | 19 +- + drivers/clk/renesas/renesas-cpg-mssr.c | 6 + + drivers/clk/renesas/renesas-cpg-mssr.h | 1 + + drivers/cpufreq/cpufreq-dt-platdev.c | 1 + + drivers/gpio/gpio-rcar.c | 4 + + drivers/gpu/drm/rcar-du/rcar_du_drv.c | 1 + + drivers/gpu/drm/rcar-du/rcar_du_group.c | 5 +- + drivers/i2c/busses/i2c-rcar.c | 1 + + drivers/iommu/ipmmu-vmsa.c | 3 + + drivers/media/platform/soc_camera/Kconfig | 2 +- + drivers/media/platform/soc_camera/rcar_csi2.c | 15 +- + drivers/media/platform/soc_camera/rcar_vin.c | 97 +- + drivers/media/platform/vsp1/vsp1_lif.c | 8 +- + drivers/mmc/host/sh_mobile_sdhi.c | 1 + + drivers/net/ethernet/renesas/ravb_main.c | 1 + + drivers/net/ethernet/renesas/sh_eth.c | 53 +- + drivers/net/ethernet/renesas/sh_eth.h | 5 +- + drivers/pci/host/pcie-rcar.c | 59 +- + drivers/pinctrl/sh-pfc/Kconfig | 5 + + drivers/pinctrl/sh-pfc/Makefile | 1 + + drivers/pinctrl/sh-pfc/core.c | 6 + + drivers/pinctrl/sh-pfc/pfc-r8a7798.c | 3151 +++++++++++++++++++++++++ + drivers/pinctrl/sh-pfc/sh_pfc.h | 9 +- + drivers/soc/renesas/Makefile | 4 + + drivers/soc/renesas/r8a7798-sysc.c | 57 + + drivers/soc/renesas/rcar-rst.c | 1 + + drivers/soc/renesas/rcar-sysc.c | 3 + + drivers/soc/renesas/rcar-sysc.h | 1 + + drivers/soc/renesas/rcar_ems_ctrl.c | 5 +- + drivers/soc/renesas/renesas-soc.c | 8 + + drivers/spi/spi-sh-msiof.c | 4 +- + drivers/thermal/rcar_gen3_thermal.c | 10 + + include/dt-bindings/clock/r8a7798-cpg-mssr.h | 56 + + include/dt-bindings/power/r8a7798-sysc.h | 46 + + 39 files changed, 5618 insertions(+), 33 deletions(-) + create mode 100644 arch/arm64/boot/dts/renesas/r8a7798.dtsi + create mode 100644 drivers/clk/renesas/r8a7798-cpg-mssr.c + create mode 100644 drivers/pinctrl/sh-pfc/pfc-r8a7798.c + create mode 100644 drivers/soc/renesas/r8a7798-sysc.c + create mode 100644 include/dt-bindings/clock/r8a7798-cpg-mssr.h + create mode 100644 include/dt-bindings/power/r8a7798-sysc.h + +diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms +index 9cebaad..3646b6e 100644 +--- a/arch/arm64/Kconfig.platforms ++++ b/arch/arm64/Kconfig.platforms +@@ -174,6 +174,14 @@ config ARCH_R8A7797 + help + This enables support for the Renesas R-Car V3M SoC. + ++config ARCH_R8A7798 ++ bool "Renesas R-Car V3H SoC Platform" ++ select SYS_SUPPORTS_SH_TMU ++ select SYS_SUPPORTS_SH_CMT ++ depends on ARCH_RENESAS ++ help ++ This enables support for the Renesas R-Car V3H SoC. ++ + config ARCH_STRATIX10 + bool "Altera's Stratix 10 SoCFPGA Family" + help +diff --git a/arch/arm64/boot/dts/renesas/r8a7798.dtsi b/arch/arm64/boot/dts/renesas/r8a7798.dtsi +new file mode 100644 +index 0000000..6412a24 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7798.dtsi +@@ -0,0 +1,1700 @@ ++/* ++ * Device Tree Source for the r8a7798 SoC ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include ++#include ++#include ++ ++/ { ++ compatible = "renesas,r8a7798"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ++ aliases { ++ csi2_40 = &csi2_40; ++ csi2_41 = &csi2_41; ++ i2c0 = &i2c0; ++ i2c1 = &i2c1; ++ i2c2 = &i2c2; ++ i2c3 = &i2c3; ++ i2c4 = &i2c4; ++ i2c5 = &i2c5; ++ spi1 = &msiof0; ++ spi2 = &msiof1; ++ spi3 = &msiof2; ++ spi4 = &msiof3; ++ vin0 = &vin0; ++ vin1 = &vin1; ++ vin2 = &vin2; ++ vin3 = &vin3; ++ vin4 = &vin4; ++ vin5 = &vin5; ++ vin6 = &vin6; ++ vin7 = &vin7; ++ vin8 = &vin8; ++ vin9 = &vin9; ++ vin10 = &vin10; ++ vin11 = &vin11; ++ vin12 = &vin12; ++ vin13 = &vin13; ++ vin14 = &vin14; ++ vin15 = &vin15; ++ tsc0 = &tsc1; ++ tsc1 = &tsc2; ++ }; ++ ++ psci { ++ compatible = "arm,psci-1.0"; ++ method = "smc"; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ a53_0: cpu@0 { ++ compatible = "arm,cortex-a53", "arm,armv8"; ++ reg = <0x0>; ++ device_type = "cpu"; ++ power-domains = <&sysc R8A7798_PD_CA53_CPU0>; ++ next-level-cache = <&L2_CA53>; ++ enable-method = "psci"; ++ cpu-idle-states = <&CPU_SLEEP_0>; ++ #cooling-cells = <2>; ++ dynamic-power-coefficient = <277>; ++ cooling-min-level = <0>; ++ cooling-max-level = <2>; ++ clocks =<&cpg CPG_CORE R8A7798_CLK_Z2>; ++ operating-points-v2 = <&cluster0_opp_tb0>; ++ /*cpu-supply = <&vdd_dvfs>;*/ ++ }; ++ ++ a53_1: cpu@1 { ++ compatible = "arm,cortex-a53","arm,armv8"; ++ reg = <0x1>; ++ device_type = "cpu"; ++ power-domains = <&sysc R8A7798_PD_CA53_CPU1>; ++ next-level-cache = <&L2_CA53>; ++ enable-method = "psci"; ++ cpu-idle-states = <&CPU_SLEEP_0>; ++ operating-points-v2 = <&cluster0_opp_tb0>; ++ }; ++ ++ a53_2: cpu@2 { ++ compatible = "arm,cortex-a53","arm,armv8"; ++ reg = <0x2>; ++ device_type = "cpu"; ++ power-domains = <&sysc R8A7798_PD_CA53_CPU2>; ++ next-level-cache = <&L2_CA53>; ++ enable-method = "psci"; ++ cpu-idle-states = <&CPU_SLEEP_0>; ++ operating-points-v2 = <&cluster0_opp_tb0>; ++ }; ++ ++ a53_3: cpu@3 { ++ compatible = "arm,cortex-a53","arm,armv8"; ++ reg = <0x3>; ++ device_type = "cpu"; ++ power-domains = <&sysc R8A7798_PD_CA53_CPU3>; ++ next-level-cache = <&L2_CA53>; ++ enable-method = "psci"; ++ cpu-idle-states = <&CPU_SLEEP_0>; ++ operating-points-v2 = <&cluster0_opp_tb0>; ++ }; ++ ++ idle-states { ++ entry-method = "psci"; ++ ++ CPU_SLEEP_0: cpu-sleep-0 { ++ compatible = "arm,idle-state"; ++ arm,psci-suspend-param = <0x0010000>; ++ local-timer-stop; ++ entry-latency-us = <639>; ++ exit-latency-us = <680>; ++ min-residency-us = <1088>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ L2_CA53: cache-controller@1 { ++ compatible = "cache"; ++ power-domains = <&sysc R8A7798_PD_CA53_SCU>; ++ cache-unified; ++ cache-level = <2>; ++ }; ++ ++ cluster0_opp_tb0: opp_table0 { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp@1000000000 { ++ opp-hz = /bits/ 64 <1000000000>; ++ opp-microvolt = <850000>; /* TBD; section 87.2 */ ++ clock-latency-ns = <300000>; ++ }; ++ }; ++ ++ extal_clk: extal { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ /* This value must be overridden by the board */ ++ clock-frequency = <0>; ++ }; ++ ++ extalr_clk: extalr { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ /* This value must be overridden by the board */ ++ clock-frequency = <0>; ++ }; ++ ++ can_clk: can { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <0>; ++ }; ++ ++ /* MSIOF reference clock - to be overridden by boards that provide it */ ++ msiof_ref_clk: msiof-ref-clock { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <0>; ++ }; ++ ++ /* External PCIe clock - can be overridden by the board */ ++ pcie_bus_clk: pcie_bus { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <0>; ++ }; ++ ++ /* External SCIF clock - to be overridden by boards that provide it */ ++ scif_clk: scif { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <0>; ++ }; ++ ++ /* DU input dot clock - tob be overriden by boards that provide it */ ++ du_dotclkin0: dclkin-0 { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <148500000>; ++ }; ++ ++ soc { ++ compatible = "simple-bus"; ++ interrupt-parent = <&gic>; ++ ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ gic: interrupt-controller@0xf1010000 { ++ compatible = "arm,gic-400"; ++ #interrupt-cells = <3>; ++ #address-cells = <0>; ++ interrupt-controller; ++ reg = <0x0 0xf1010000 0 0x1000>, ++ <0x0 0xf1020000 0 0x20000>, ++ <0x0 0xf1040000 0 0x20000>, ++ <0x0 0xf1060000 0 0x20000>; ++ interrupts = ; ++ }; ++ ++ gpio0: gpio@e6050000 { ++ compatible = "renesas,gpio-r8a7798", ++ "renesas,gpio-rcar"; ++ reg = <0 0xe6050000 0 0x50>; ++ interrupts = ; ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 0 22>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 912>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; ++ ++ gpio1: gpio@e6051000 { ++ compatible = "renesas,gpio-r8a7798", ++ "renesas,gpio-rcar"; ++ reg = <0 0xe6051000 0 0x50>; ++ interrupts = ; ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 32 28>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 911>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; ++ ++ gpio2: gpio@e6052000 { ++ compatible = "renesas,gpio-r8a7798", ++ "renesas,gpio-rcar"; ++ reg = <0 0xe6052000 0 0x50>; ++ interrupts = ; ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 64 29>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 910>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; ++ ++ gpio3: gpio@e6053000 { ++ compatible = "renesas,gpio-r8a7798", ++ "renesas,gpio-rcar"; ++ reg = <0 0xe6053000 0 0x50>; ++ interrupts = ; ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 96 17>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 909>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; ++ ++ gpio4: gpio@e6054000 { ++ compatible = "renesas,gpio-r8a7798", ++ "renesas,gpio-rcar"; ++ reg = <0 0xe6054000 0 0x50>; ++ interrupts = ; ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 128 25>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 908>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; ++ ++ gpio5: gpio@e6055000 { ++ compatible = "renesas,gpio-r8a7798", ++ "renesas,gpio-rcar"; ++ reg = <0 0xe6055000 0 0x50>; ++ interrupts = ; ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 160 15>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 907>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; ++ ++ pmu_a53 { ++ compatible = "arm,cortex-a53-pmu"; ++ interrupts = , ++ , ++ , ++ ; ++ interrupt-affinity = <&a53_0>, ++ <&a53_1>, ++ <&a53_2>, ++ <&a53_3>; ++ }; ++ ++ timer { ++ compatible = "arm,armv8-timer"; ++ interrupts = , ++ , ++ , ++ ; ++ }; ++ ++ wdt0: wdt@e6020000 { ++ compatible = "renesas,r8a7798-wdt", "renesas,rcar-gen3-wdt"; ++ reg = <0 0xe6020000 0 0x0c>; ++ clocks = <&cpg CPG_MOD 402>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ cpg: clock-controller@e6150000 { ++ compatible = "renesas,r8a7798-cpg-mssr"; ++ reg = <0 0xe6150000 0 0x1000>; ++ clocks = <&extal_clk>, <&extalr_clk>; ++ clock-names = "extal", "extalr"; ++ #clock-cells = <2>; ++ #power-domain-cells = <0>; ++ }; ++ ++ csi2_40: csi2@feaa0000 { ++ compatible = "renesas,r8a7798-csi2"; ++ reg = <0 0xfeaa0000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 716>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ csi2_41: csi2@feab0000 { ++ compatible = "renesas,r8a7798-csi2"; ++ reg = <0 0xfeab0000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 715>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ prr: chipid@fff00044 { ++ compatible = "renesas,prr"; ++ reg = <0 0xfff00044 0 4>; ++ }; ++ ++ rst: reset-controller@e6160000 { ++ compatible = "renesas,r8a7798-rst"; ++ reg = <0 0xe6160000 0 0x0200>; ++ }; ++ ++ sysc: system-controller@e6180000 { ++ compatible = "renesas,r8a7798-sysc"; ++ reg = <0 0xe6180000 0 0x0440>; ++ #power-domain-cells = <1>; ++ }; ++ ++ pfc: pfc@e6060000 { ++ compatible = "renesas,pfc-r8a7798"; ++ reg = <0 0xe6060000 0 0x50c>; ++ }; ++ ++ intc_ex: interrupt-controller@e61c0000 { ++ compatible = "renesas,intc-ex-r8a7798", "renesas,irqc"; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ reg = <0 0xe61c0000 0 0x200>; ++ interrupts = ; /* SPI1:IRQ1, SPI2:IRQ2, SPI3:IRQ3, SPI18:IRQ4, SPI161:IRQ5 */ ++ clocks = <&cpg CPG_MOD 407>; /* RMSTPCR4/bit7:INTC-EX */ ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; ++ ++ ipmmu_vi: mmu@febd0000 { ++ compatible = "renesas,ipmmu-r8a7798"; ++ reg = <0 0xfebd0000 0 0x1000>; /* IPMMU-VI */ ++ renesas,ipmmu-main = <&ipmmu_mm 14>; ++ #iommu-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ ipmmu_vc: mmu@fe6b0000 { ++ compatible = "renesas,ipmmu-r8a7798"; ++ reg = <0 0xfe6b0000 0 0x1000>; /* IPMMU-VC */ ++ renesas,ipmmu-main = <&ipmmu_mm 12>; ++ #iommu-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ ipmmu_ir: mmu@ff8b0000 { ++ compatible = "renesas,ipmmu-r8a7798"; ++ reg = <0 0xff8b0000 0 0x1000>; /* IPMMU-IR */ ++ renesas,ipmmu-main = <&ipmmu_mm 3>; ++ #iommu-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ ipmmu_rt: mmu@ffc80000 { ++ compatible = "renesas,ipmmu-r8a7798"; ++ reg = <0 0xffc80000 0 0x1000>; /* IPMMU-RT */ ++ renesas,ipmmu-main = <&ipmmu_mm 10>; ++ #iommu-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ ipmmu_ds0: mmu@e6740000 { ++ compatible = "renesas,ipmmu-r8a7798"; ++ reg = <0 0xe6740000 0 0x1000>; /* IPMMU-DS1 */ ++ renesas,ipmmu-main = <&ipmmu_mm 0>; ++ #iommu-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ ipmmu_vip0: mmu@e7b00000 { ++ compatible = "renesas,ipmmu-r8a7798"; ++ reg = <0 0xe7b00000 0 0x1000>; /* IPMMU-VIP0 */ ++ renesas,ipmmu-main = <&ipmmu_mm 0>; /* FIXME missing in datasheet */ ++ #iommu-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ ipmmu_vip1: mmu@e7960000 { ++ compatible = "renesas,ipmmu-r8a7798"; ++ reg = <0 0xe7960000 0 0x1000>; /* IPMMU-VIP1 */ ++ renesas,ipmmu-main = <&ipmmu_mm 0>; /* FIXME missing in datasheet */ ++ #iommu-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ ipmmu_mm: mmu@e67b0000 { ++ compatible = "renesas,ipmmu-r8a7798"; ++ reg = <0 0xe67b0000 0 0x1000>; /* IPMMU-MM */ ++ interrupts = , ++ ; ++ #iommu-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ dmac1: dma-controller@e7300000 { ++ compatible = "renesas,dmac-r8a7798", ++ "renesas,rcar-dmac"; ++ reg = <0 0xe7300000 0 0x10000>; ++ interrupts = ; ++ ++ interrupt-names = "error", ++ "ch0", "ch1", "ch2", "ch3", ++ "ch4", "ch5", "ch6", "ch7", ++ "ch8", "ch9", "ch10", "ch11", ++ "ch12", "ch13", "ch14", "ch15"; ++ clocks = <&cpg CPG_MOD 218>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ #dma-cells = <1>; ++ dma-channels = <16>; ++ iommus = <&ipmmu_ds0 0>, <&ipmmu_ds0 1>, ++ <&ipmmu_ds0 2>, <&ipmmu_ds0 3>, ++ <&ipmmu_ds0 4>, <&ipmmu_ds0 5>, ++ <&ipmmu_ds0 6>, <&ipmmu_ds0 7>, ++ <&ipmmu_ds0 8>, <&ipmmu_ds0 9>, ++ <&ipmmu_ds0 10>, <&ipmmu_ds0 11>, ++ <&ipmmu_ds0 12>, <&ipmmu_ds0 13>, ++ <&ipmmu_ds0 14>, <&ipmmu_ds0 15>; ++ }; ++ ++ dmac2: dma-controller@e7310000 { ++ compatible = "renesas,dmac-r8a7798", ++ "renesas,rcar-dmac"; ++ reg = <0 0xe7310000 0 0x10000>; ++ interrupts = ; /* SPI307::SYS-DMAC2 err, ++ SPI312~319:SYS-DMAC2.ch0~SYS-DMAC1.ch7 */ ++ interrupt-names = "error", ++ "ch0", "ch1", "ch2", "ch3", ++ "ch4", "ch5", "ch6", "ch7", ++ "ch8", "ch9", "ch10", "ch11", ++ "ch12", "ch13", "ch14", "ch15"; ++ clocks = <&cpg CPG_MOD 217>; /* RMSTPCR2/bit17:SYS-DMAC2 */ ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ #dma-cells = <1>; ++ dma-channels = <16>; ++ iommus = <&ipmmu_ds0 16>, <&ipmmu_ds0 17>, ++ <&ipmmu_ds0 18>, <&ipmmu_ds0 19>, ++ <&ipmmu_ds0 20>, <&ipmmu_ds0 21>, ++ <&ipmmu_ds0 22>, <&ipmmu_ds0 23>, ++ <&ipmmu_ds0 24>, <&ipmmu_ds0 25>, ++ <&ipmmu_ds0 26>, <&ipmmu_ds0 27>, ++ <&ipmmu_ds0 28>, <&ipmmu_ds0 29>, ++ <&ipmmu_ds0 30>, <&ipmmu_ds0 31>; ++ }; ++ ++ avb: ethernet@e6800000 { ++ compatible = "renesas,etheravb-r8a7798", ++ "renesas,etheravb-rcar-gen3"; ++ reg = <0 0xe6800000 0 0x800>, <0 0xe6a00000 0 0x10000>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; /* SPI39~63:Ethernet AVB.ch0~24 */ ++ /* @@ errreq_avb_p[0]~[3] add (T.B.D) */ ++ interrupt-names = "ch0", "ch1", "ch2", "ch3", ++ "ch4", "ch5", "ch6", "ch7", ++ "ch8", "ch9", "ch10", "ch11", ++ "ch12", "ch13", "ch14", "ch15", ++ "ch16", "ch17", "ch18", "ch19", ++ "ch20", "ch21", "ch22", "ch23", ++ "ch24"; ++ clocks = <&cpg CPG_MOD 812>; /* RMSTPCR8/bit12:EAVB-IF */ ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ phy-mode = "rgmii-id"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ gether: ethernet@e7400000 { ++ compatible = "renesas,gether-r8a7798"; ++ reg = <0 0xe7400000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 813>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ phy-mode = "rgmii"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ canfd: canfd@e66c0000 { ++ compatible = "renesas,r8a7798-canfd", ++ "renesas,rcar-gen3-canfd"; ++ reg = <0 0xe66c0000 0 0x8000>; ++ interrupts = , ++ ; ++ clocks = <&cpg CPG_MOD 914>, ++ <&cpg CPG_CORE R8A7798_CLK_CANFD>, ++ <&can_clk>; ++ clock-names = "fck", "canfd", "can_clk"; ++ assigned-clocks = <&cpg CPG_CORE R8A7798_CLK_CANFD>; ++ assigned-clock-rates = <40000000>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ ++ channel0 { ++ status = "disabled"; ++ }; ++ ++ channel1 { ++ status = "disabled"; ++ }; ++ }; ++ ++ ++ cmt0: timer@e60f0000 { ++ compatible = "renesas,cmt-48-r8a7798", "renesas,cmt-48-gen2"; ++ reg = <0 0xe60f0000 0 0x1004>; ++ interrupts = , ++ ; ++ clocks = <&cpg CPG_MOD 303>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ ++ renesas,channels-mask = <0x60>; ++ ++ status = "disabled"; ++ }; ++ ++ cmt1: timer@e6130000 { ++ compatible = "renesas,cmt-48-r8a7798", "renesas,cmt-48-gen2"; ++ reg = <0 0xe6130000 0 0x1004>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 302>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ ++ renesas,channels-mask = <0xff>; ++ ++ status = "disabled"; ++ }; ++ ++ cmt2: timer@e6140000 { ++ compatible = "renesas,cmt-48-r8a7798", "renesas,cmt-48-gen2"; ++ reg = <0 0xe6140000 0 0x1004>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 301>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ ++ renesas,channels-mask = <0xff>; ++ ++ status = "disabled"; ++ }; ++ ++ cmt3: timer@e6148000 { ++ compatible = "renesas,cmt-48-r8a7798", "renesas,cmt-48-gen2"; ++ reg = <0 0xe6148000 0 0x1004>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 300>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ ++ renesas,channels-mask = <0xff>; ++ ++ status = "disabled"; ++ }; ++ ++ tpu: pwm@e6e80000 { ++ compatible = "renesas,tpu-r8a7798", "renesas,tpu"; ++ reg = <0 0xe6e80000 0 0x100>; ++ clocks = <&cpg CPG_MOD 304>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ #pwm-cells = <4>; ++ }; ++ ++ tmu0: timer@e61e0000 { ++ compatible = "renesas,tmu-r8a7798", "renesas,tmu"; ++ reg = <0 0xe61e0000 0 0x30>; ++ interrupts = , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 125>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ #renesas,channels = <3>; ++ status = "disabled"; ++ }; ++ ++ tmu1: timer@e6fc0000 { ++ compatible = "renesas,tmu-r8a7798", "renesas,tmu"; ++ reg = <0 0xe6fc0000 0 0x30>; ++ interrupts = , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 124>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ #renesas,channels = <3>; ++ status = "disabled"; ++ }; ++ ++ tmu2: timer@e6fd0000 { ++ compatible = "renesas,tmu-r8a7798", "renesas,tmu"; ++ reg = <0 0xe6fd0000 0 0x30>; ++ interrupts = , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 123>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ #renesas,channels = <3>; ++ status = "disabled"; ++ }; ++ ++ tmu3: timer@e6fe0000 { ++ compatible = "renesas,tmu-r8a7798", "renesas,tmu"; ++ reg = <0 0xe6fe0000 0 0x30>; ++ interrupts = , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 122>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ #renesas,channels = <3>; ++ status = "disabled"; ++ }; ++ ++ tmu4: timer@ffc00000 { ++ compatible = "renesas,tmu-r8a7798", "renesas,tmu"; ++ reg = <0 0xffc00000 0 0x30>; ++ interrupts = , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 121>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ #renesas,channels = <3>; ++ status = "disabled"; ++ }; ++ ++ pwm0: pwm@e6e30000 { ++ compatible = "renesas,pwm-r8a7798", "renesas,pwm-rcar"; ++ reg = <0 0xe6e30000 0 0x10>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; /* RMSTPCR5/bit23:PWM */ ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ pwm1: pwm@e6e31000 { ++ compatible = "renesas,pwm-r8a7798", "renesas,pwm-rcar"; ++ reg = <0 0xe6e31000 0 0x10>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; /* RMSTPCR5/bit23:PWM */ ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ pwm2: pwm@e6e32000 { ++ compatible = "renesas,pwm-r8a7798", "renesas,pwm-rcar"; ++ reg = <0 0xe6e32000 0 0x10>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; /* RMSTPCR5/bit23:PWM */ ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ pwm3: pwm@e6e33000 { ++ compatible = "renesas,pwm-r8a7798", "renesas,pwm-rcar"; ++ reg = <0 0xe6e33000 0 0x10>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; /* RMSTPCR5/bit23:PWM */ ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ pwm4: pwm@e6e34000 { ++ compatible = "renesas,pwm-r8a7798", "renesas,pwm-rcar"; ++ reg = <0 0xe6e34000 0 0x10>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; /* RMSTPCR5/bit23:PWM */ ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ hscif0: serial@e6540000 { ++ compatible = "renesas,hscif-r8a7798", ++ "renesas,rcar-gen3-hscif", ++ "renesas,hscif"; ++ reg = <0 0xe6540000 0 96>; ++ interrupts = ; /* SPI154:HSCIF.ch0 */ ++ clocks = <&cpg CPG_MOD 520>, ++ <&cpg CPG_CORE R8A7798_CLK_S2D1>, ++ <&scif_clk>; /* RMSTPCR5/bit20:HSCIF0 */ ++ clock-names = "fck", "brg_int", "scif_clk"; ++ dmas = <&dmac1 0x31>, <&dmac1 0x30>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ hscif1: serial@e6550000 { ++ compatible = "renesas,hscif-r8a7798", ++ "renesas,rcar-gen3-hscif", ++ "renesas,hscif"; ++ reg = <0 0xe6550000 0 96>; ++ interrupts = ; /* SPI155:HSCIF.ch1 */ ++ clocks = <&cpg CPG_MOD 519>, ++ <&cpg CPG_CORE R8A7798_CLK_S2D1>, ++ <&scif_clk>; /* RMSTPCR5/bit19:HSCIF1 */ ++ clock-names = "fck", "brg_int", "scif_clk"; ++ dmas = <&dmac1 0x33>, <&dmac1 0x32>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ hscif2: serial@e6560000 { ++ compatible = "renesas,hscif-r8a7798", ++ "renesas,rcar-gen3-hscif", ++ "renesas,hscif"; ++ reg = <0 0xe6560000 0 96>; ++ interrupts = ; /* SPI144:HSCIF.ch2 */ ++ clocks = <&cpg CPG_MOD 518>, ++ <&cpg CPG_CORE R8A7798_CLK_S2D1>, ++ <&scif_clk>; /* RMSTPCR5/bit18:HSCIF2 */ ++ clock-names = "fck", "brg_int", "scif_clk"; ++ dmas = <&dmac1 0x35>, <&dmac1 0x34>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ hscif3: serial@e66a0000 { ++ compatible = "renesas,hscif-r8a7798", ++ "renesas,rcar-gen3-hscif", ++ "renesas,hscif"; ++ reg = <0 0xe66a0000 0 96>; ++ //interrupts = ; /* SPI145:HSCIF.ch3 */ ++ clocks = <&cpg CPG_MOD 517>, ++ <&cpg CPG_CORE R8A7798_CLK_S2D1>, ++ <&scif_clk>; /* RMSTPCR5/bit17:HSCIF3 */ ++ clock-names = "fck", "brg_int", "scif_clk"; ++ dmas = <&dmac1 0x37>, <&dmac1 0x36>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ scif0: serial@e6e60000 { ++ compatible = "renesas,scif-r8a7798", ++ "renesas,rcar-gen3-scif", "renesas,scif"; ++ reg = <0 0xe6e60000 0 64>; ++ interrupts = ; /* SPI152:SCIF.ch0 */ ++ clocks = <&cpg CPG_MOD 207>, ++ <&cpg CPG_CORE R8A7798_CLK_S2D1>, ++ <&scif_clk>; /* RMSTPCR2/bit7:SCIF0 */ ++ /*clock-names = "fck", "sck", "brg_int", "scif_clk"; */ ++ clock-names = "fck"; ++ dmas = <&dmac1 0x51>, <&dmac1 0x50>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ scif1: serial@e6e68000 { ++ compatible = "renesas,scif-r8a7798", ++ "renesas,rcar-gen3-scif", "renesas,scif"; ++ reg = <0 0xe6e68000 0 64>; ++ interrupts = ; /* SPI153:SCIF.ch1 */ ++ clocks = <&cpg CPG_MOD 206>, ++ <&cpg CPG_CORE R8A7798_CLK_S2D1>, ++ <&scif_clk>; /* RMSTPCR2/bit6:SCIF1 */ ++ clock-names = "fck", "brg_int", "scif_clk"; ++ dmas = <&dmac1 0x53>, <&dmac1 0x52>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ scif3: serial@e6c50000 { ++ compatible = "renesas,scif-r8a7798", ++ "renesas,rcar-gen3-scif", "renesas,scif"; ++ reg = <0 0xe6c50000 0 64>; ++ interrupts = ; /* SPI23:SCIF.ch3 */ ++ clocks = <&cpg CPG_MOD 204>, ++ <&cpg CPG_CORE R8A7798_CLK_S2D1>, ++ <&scif_clk>; /* RMSTPCR2/bit4:SCIF3 */ ++ clock-names = "fck", "brg_int", "scif_clk"; ++ dmas = <&dmac1 0x57>, <&dmac1 0x56>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ scif4: serial@e6c40000 { ++ compatible = "renesas,scif-r8a7798", ++ "renesas,rcar-gen3-scif", "renesas,scif"; ++ reg = <0 0xe6c40000 0 64>; ++ interrupts = ; /* SPI16:SCIF.ch4 */ ++ clocks = <&cpg CPG_MOD 203>, ++ <&cpg CPG_CORE R8A7798_CLK_S2D1>, ++ <&scif_clk>; /* RMSTPCR2/bit3:SCIF4 */ ++ clock-names = "fck", "brg_int", "scif_clk"; ++ dmas = <&dmac1 0x59>, <&dmac1 0x58>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ i2c0: i2c@e6500000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,i2c-r8a7798"; ++ reg = <0 0xe6500000 0 0x40>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 931>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ dmas = <&dmac1 0x91>, <&dmac1 0x90>; ++ dma-names = "tx", "rx"; ++ i2c-scl-internal-delay-ns = <6>; ++ status = "disabled"; ++ }; ++ ++ i2c1: i2c@e6508000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,i2c-r8a7798"; ++ reg = <0 0xe6508000 0 0x40>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 930>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ dmas = <&dmac1 0x93>, <&dmac1 0x92>; ++ dma-names = "tx", "rx"; ++ i2c-scl-internal-delay-ns = <6>; ++ status = "disabled"; ++ }; ++ ++ i2c2: i2c@e6510000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,i2c-r8a7798"; ++ reg = <0 0xe6510000 0 0x40>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 929>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ dmas = <&dmac1 0x95>, <&dmac1 0x94>; ++ dma-names = "tx", "rx"; ++ i2c-scl-internal-delay-ns = <6>; ++ status = "disabled"; ++ }; ++ ++ i2c3: i2c@e66d0000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,i2c-r8a7798"; ++ reg = <0 0xe66d0000 0 0x40>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 928>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ dmas = <&dmac1 0x97>, <&dmac1 0x96>; ++ dma-names = "tx", "rx"; ++ i2c-scl-internal-delay-ns = <6>; ++ status = "disabled"; ++ }; ++ ++ i2c4: i2c@e66d8000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,i2c-r8a7798"; ++ reg = <0 0xe66d8000 0 0x40>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 927>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ dmas = <&dmac1 0x99>, <&dmac1 0x98>; ++ dma-names = "tx", "rx"; ++ i2c-scl-internal-delay-ns = <6>; ++ status = "disabled"; ++ }; ++ ++ i2c5: i2c@e66e0000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,i2c-r8a7798"; ++ reg = <0 0xe66e0000 0 0x40>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 00>; /* FIXME missing entry in MSSR */ ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ dmas = <&dmac1 0x99>, <&dmac1 0x98>; ++ dma-names = "tx", "rx"; ++ i2c-scl-internal-delay-ns = <6>; ++ status = "disabled"; ++ }; ++ ++ msiof0: spi@e6e90000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,msiof-r8a7798"; ++ reg = <0 0xe6e90000 0 0x64>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 211>, <&msiof_ref_clk>; ++ clock-names = "msiof_clk", "msiof_ref_clk"; ++ dmas = <&dmac1 0x41>, <&dmac1 0x40>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ msiof1: spi@e6ea0000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,msiof-r8a7798"; ++ reg = <0 0xe6ea0000 0 0x0064>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 210>, <&msiof_ref_clk>; ++ clock-names = "msiof_clk", "msiof_ref_clk"; ++ dmas = <&dmac1 0x43>, <&dmac1 0x42>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ msiof2: spi@e6c00000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,msiof-r8a7798"; ++ reg = <0 0xe6c00000 0 0x0064>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 209>, <&msiof_ref_clk>; ++ clock-names = "msiof_clk", "msiof_ref_clk"; ++ dmas = <&dmac1 0x45>, <&dmac1 0x44>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ msiof3: spi@e6c10000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,msiof-r8a7798"; ++ reg = <0 0xe6c10000 0 0x0064>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 208>, <&msiof_ref_clk>; ++ clock-names = "msiof_clk", "msiof_ref_clk"; ++ dmas = <&dmac1 0x47>, <&dmac1 0x46>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ ++ pciec: pcie@fe000000 { ++ compatible = "renesas,pcie-r8a7798", ++ "renesas,pcie-rcar-gen3"; ++ reg = <0 0xfe000000 0 0x80000>, ++ <0 0xe65d0000 0 0x8000>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ bus-range = <0x00 0xff>; ++ device_type = "pci"; ++ ranges = <0x01000000 0 0x00000000 0 0xfe100000 0 0x00100000 ++ 0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000 ++ 0x02000000 0 0x30000000 0 0x30000000 0 0x08000000 ++ 0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>; ++ dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000>; ++ interrupts = , ++ , ++ ; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 0>; ++ interrupt-map = <0 0 0 0 &gic GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&cpg CPG_MOD 319>, <&pcie_bus_clk>; ++ clock-names = "pcie", "pcie_bus"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin0: video@e6ef0000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6ef0000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 811>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin1: video@e6ef1000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6ef1000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 810>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin2: video@e6ef2000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6ef2000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 809>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin3: video@e6ef3000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6ef3000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 808>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin4: video@e6ef4000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6ef4000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 807>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin5: video@e6ef5000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6ef5000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 806>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin6: video@e6ef6000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6ef6000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 805>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin7: video@e6ef7000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6ef7000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 804>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin8: video@e6ef8000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6ef8000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 628>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin9: video@e6ef9000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6ef9000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 627>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin10: video@e6efa000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6efa000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 625>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin11: video@e6efb000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6efb000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 618>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin12: video@e6efc000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6efc000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 612>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin13: video@e6efd000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6efd000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 608>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin14: video@e6efe000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6efe000 0 0x1000>; ++ interrupts = ; /* FIXME no info in datasheet */ ++ clocks = <&cpg CPG_MOD 605>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin15: video@e6eff000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6eff000 0 0x1000>; ++ interrupts = ; /* FIXME no info in datasheet */ ++ clocks = <&cpg CPG_MOD 604>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ sdhi2: sd@ee140000 { ++ compatible = "renesas,sdhi-r8a7798"; ++ reg = <0 0xee140000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 314>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ renesas,clk-rate = <200000000>; ++ status = "disabled"; ++ }; ++ ++ qos@e67e0000 { ++ compatible = "renesas,qos"; ++ }; ++ ++ vspd0: vsp@fea20000 { ++ compatible = "renesas,vsp2"; ++ reg = <0 0xfea20000 0 0x4000>; ++ ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 623>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ ++ renesas,fcp = <&fcpvd0>; ++ }; ++ ++ fcpvd0: fcp@fea27000 { ++ compatible = "renesas,r8a7798-fcpv", "renesas,fcpv"; ++ reg = <0 0xfea27000 0 0x200>; ++ clocks = <&cpg CPG_MOD 603>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; ++ ++ du: display@feb00000 { ++ compatible = "renesas,du-r8a7798"; ++ reg = <0 0xfeb00000 0 0x80000>, ++ <0 0xfeb90000 0 0x14>; ++ reg-names = "du", "lvds.0"; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 724>, ++ <&cpg CPG_MOD 727>, ++ <&dclkin_p0>; ++ clock-names = "du.0", "lvds.0", "dclkin.0"; ++ status = "disabled"; ++ ++ vsps = <&vspd0>; ++ ++ interlaced = <1>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ du_out_lvds0: endpoint { ++ }; ++ }; ++ }; ++ }; ++ ++ tsc1: thermal@0xe6198000 { ++ compatible = "renesas,thermal-r8a7798"; ++ reg = <0 0xe6198000 0 0x5c>; ++ interrupts = , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 522>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ #thermal-sensor-cells = <0>; ++ status = "okay"; ++ }; ++ ++ tsc2: thermal@0xe61a0000 { ++ compatible = "renesas,thermal-r8a7798"; ++ reg = <0 0xe61a0000 0 0x5c>; ++ interrupts = , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 522>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ #thermal-sensor-cells = <0>; ++ status = "okay"; ++ }; ++ ++ thermal-zones { ++ emergency { ++ polling-delay = <1000>; ++ on-temperature = <110000>; ++ off-temperature = <95000>; ++ target_cpus = <&a53_1>, ++ <&a53_2>, ++ <&a53_3>; ++ status = "disabled"; ++ }; ++ ++ sensor_thermal1: sensor-thermal1 { ++ polling-delay-passive = <250>; ++ polling-delay = <0>; ++ sustainable-power = <0>; /* TBD; HWM 87.4 */ ++ ++ thermal-sensors = <&tsc1>; ++ ++ trips { ++ sensor1_crit: sensor1-crit { ++ temperature = <120000>; ++ hysteresis = <2000>; ++ type = "critical"; ++ }; ++ }; ++ }; ++ ++ sensor_thermal2: sensor-thermal2 { ++ polling-delay-passive = <250>; ++ polling-delay = <0>; ++ sustainable-power = <0>; /* TBD; HWM 87.4 */ ++ ++ thermal-sensors = <&tsc2>; ++ ++ trips { ++ sensor2_crit: sensor2-crit { ++ temperature = <120000>; ++ hysteresis = <2000>; ++ type = "critical"; ++ }; ++ }; ++ }; ++ }; ++ ++ mfis: mfis@e6260000 { ++ compatible = "renesas,mfis-r8a7798", "renesas,mfis"; ++ reg = <0 0xe6260000 0 0x0200>; ++ clocks = <&cpg CPG_MOD 213>; ++ clock-names = "mfis"; ++ interrupts = ; ++ interrupt-names = "eicr0"; ++ status = "okay"; ++ }; ++ ++ mfis_lock: mfis-lock@e62600c0 { ++ compatible = "renesas,mfis-lock-r8a7798", ++ "renesas,mfis-lock"; ++ reg = <0 0xe62600c0 0 0x0020>; ++ status = "okay"; ++ }; ++ ++ imp_distributer: impdes0 { ++ compatible = "renesas,impx5+-distributer"; ++ reg = <0 0xffa00000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 830>; ++ power-domains = <&sysc R8A7798_PD_A3IR>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ imp0 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff900000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <0>; ++ clocks = <&cpg CPG_MOD 827>; ++ power-domains = <&sysc R8A7798_PD_A2IR0>; ++ }; ++ ++ imp1 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff920000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <1>; ++ clocks = <&cpg CPG_MOD 826>; ++ power-domains = <&sysc R8A7798_PD_A2IR1>; ++ }; ++ ++ imp2 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff940000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <2>; ++ clocks = <&cpg CPG_MOD 825>; ++ power-domains = <&sysc R8A7798_PD_A2IR2>; ++ }; ++ ++ imp3 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff960000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <3>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7798_PD_A2IR3>; ++ }; ++ ++ imp4 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xffa80000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <4>; ++ clocks = <&cpg CPG_MOD 521>; ++ power-domains = <&sysc R8A7798_PD_A2IR4>; ++ }; ++ ++ impslc0 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff9c0000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <5>; ++ clocks = <&cpg CPG_MOD 500>; ++ power-domains = <&sysc R8A7798_PD_A2IR5>; ++ }; ++ ++ impsc0 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff980000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <6>; ++ clocks = <&cpg CPG_MOD 829>; ++ power-domains = <&sysc R8A7798_PD_A2SC0>; ++ }; ++ ++ impsc1 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff990000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <7>; ++ clocks = <&cpg CPG_MOD 828>; ++ power-domains = <&sysc R8A7798_PD_A2SC1>; ++ }; ++ ++ impsc2 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff9a0000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <8>; ++ clocks = <&cpg CPG_MOD 531>; ++ power-domains = <&sysc R8A7798_PD_A2SC2>; ++ }; ++ ++ impsc3 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff9b0000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <9>; ++ clocks = <&cpg CPG_MOD 529>; ++ power-domains = <&sysc R8A7798_PD_A2SC3>; ++ }; ++ ++ impsc4 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xffa40000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <10>; ++ clocks = <&cpg CPG_MOD 528>; ++ power-domains = <&sysc R8A7798_PD_A2SC4>; ++ }; ++ ++ impdm0 { ++ compatible = "renesas,impx5-dmac"; ++ reg = <0 0xffa10000 0 0x1000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <11>; ++ clocks = <&cpg CPG_MOD 527>; ++ power-domains = <&sysc R8A7798_PD_A2PD0>; ++ }; ++ ++ impdm1 { ++ compatible = "renesas,impx5-dmac"; ++ reg = <0 0xffa11000 0 0x1000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <12>; ++ clocks = <&cpg CPG_MOD 527>; ++ power-domains = <&sysc R8A7798_PD_A2PD0>; ++ }; ++ ++ impdm2 { ++ compatible = "renesas,impx5-dmac"; ++ reg = <0 0xffa14000 0 0x1000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <13>; ++ clocks = <&cpg CPG_MOD 526>; ++ power-domains = <&sysc R8A7798_PD_A2PD1>; ++ }; ++ ++ impdm3 { ++ compatible = "renesas,impx5-dmac"; ++ reg = <0 0xffa15000 0 0x1000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <14>; ++ clocks = <&cpg CPG_MOD 526>; ++ power-domains = <&sysc R8A7798_PD_A2PD1>; ++ }; ++ ++ imppsc0 { ++ compatible = "renesas,impx5+-psc"; ++ reg = <0 0xffa20000 0 0x4000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <15>; ++ clocks = <&cpg CPG_MOD 525>; ++ power-domains = <&sysc R8A7798_PD_A2PD0>; ++ }; ++ ++ imppsc1 { ++ compatible = "renesas,impx5+-psc"; ++ reg = <0 0xffa24000 0 0x4000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <16>; ++ clocks = <&cpg CPG_MOD 524>; ++ power-domains = <&sysc R8A7798_PD_A2PD1>; ++ }; ++ ++ impcnn0 { ++ compatible = "renesas,impx5+-cnn"; ++ reg = <0 0xff9e0000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <17>; ++ clocks = <&cpg CPG_MOD 831>; ++ power-domains = <&sysc R8A7798_PD_A2CN>; ++ }; ++ ++ impc0 { ++ compatible = "renesas,impx4-memory"; ++ reg = <0 0xed000000 0 0x200000>; ++ clocks = <&cpg CPG_MOD 830>; ++ power-domains = <&sysc R8A7798_PD_A3IR>; ++ }; ++ ++ imrlx4_ch0: imr-lx4@fe860000 { ++ compatible = "renesas,imr-lx4"; ++ reg = <0 0xfe860000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 823>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; ++ ++ imrlx4_ch1: imr-lx4@fe870000 { ++ compatible = "renesas,imr-lx4"; ++ reg = <0 0xfe870000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 822>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; ++ ++ imrlx4_ch2: imr-lx4@fe880000 { ++ compatible = "renesas,imr-lx4"; ++ reg = <0 0xfe880000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 821>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; ++ ++ imrlx4_ch3: imr-lx4@fe890000 { ++ compatible = "renesas,imr-lx4"; ++ reg = <0 0xfe890000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 820>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; ++ ++ imrlx4_ch4: imr-lx4@fe8a0000 { ++ compatible = "renesas,imr-lx4"; ++ reg = <0 0xfe8a0000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 707>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ rse; ++ }; ++ ++ imrlx4_ch5: imr-lx4@fe8b0000 { ++ compatible = "renesas,imr-lx4"; ++ reg = <0 0xfe8b0000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 706>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ rse; ++ }; ++ ++ disp { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a00000 0 0x10000>; ++ clocks = <&cpg CPG_MOD 101>; ++ power-domains = <&sysc R8A7798_PD_A3VIP>; ++ }; ++ ++ umf { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a10000 0 0x10000>; ++ clocks = <&cpg CPG_MOD 102>; ++ power-domains = <&sysc R8A7798_PD_A3VIP1>; ++ }; ++ ++ smd_ps { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a20000 0 0x10000>; ++ clocks = <&cpg CPG_MOD 1102>; ++ power-domains = <&sysc R8A7798_PD_A3VIP1>; ++ }; ++ ++ smd_est { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a30000 0 0x10000>; ++ clocks = <&cpg CPG_MOD 1101>; ++ power-domains = <&sysc R8A7798_PD_A3VIP1>; ++ }; ++ ++ smd_post { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a40000 0 0x10000>; ++ clocks = <&cpg CPG_MOD 1100>; ++ power-domains = <&sysc R8A7798_PD_A3VIP1>; ++ }; ++ ++ cle0 { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a50000 0 0x10000>; ++ clocks = <&cpg CPG_MOD 1004>; ++ power-domains = <&sysc R8A7798_PD_A3VIP2>; ++ }; ++ ++ cle1 { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a60000 0 0x10000>; ++ clocks = <&cpg CPG_MOD 1003>; ++ power-domains = <&sysc R8A7798_PD_A3VIP2>; ++ }; ++ ++ cle2 { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a70000 0 0x10000>; ++ clocks = <&cpg CPG_MOD 1002>; ++ power-domains = <&sysc R8A7798_PD_A3VIP2>; ++ }; ++ ++ cle3 { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a80000 0 0x10000>; ++ clocks = <&cpg CPG_MOD 1001>; ++ power-domains = <&sysc R8A7798_PD_A3VIP2>; ++ }; ++ ++ cle4 { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a90000 0 0x10000>; ++ clocks = <&cpg CPG_MOD 1000>; ++ power-domains = <&sysc R8A7798_PD_A3VIP2>; ++ }; ++ }; ++}; +diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig +index b52e907..4e6d24d 100644 +--- a/drivers/clk/renesas/Kconfig ++++ b/drivers/clk/renesas/Kconfig +@@ -6,6 +6,7 @@ config CLK_RENESAS_CPG_MSSR + default y if ARCH_R8A7796 + default y if ARCH_R8A77965 + default y if ARCH_R8A7797 ++ default y if ARCH_R8A7798 + + config CLK_RENESAS_CPG_MSTP + bool +diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile +index c2ef11e..9f659d5 100644 +--- a/drivers/clk/renesas/Makefile ++++ b/drivers/clk/renesas/Makefile +@@ -15,6 +15,7 @@ obj-$(CONFIG_ARCH_R8A7795) += r8a7795-cpg-mssr.o rcar-gen3-cpg.o + obj-$(CONFIG_ARCH_R8A7796) += r8a7796-cpg-mssr.o rcar-gen3-cpg.o + obj-$(CONFIG_ARCH_R8A77965) += r8a77965-cpg-mssr.o rcar-gen3-cpg.o + obj-$(CONFIG_ARCH_R8A7797) += r8a7797-cpg-mssr.o rcar-gen3-cpg.o ++obj-$(CONFIG_ARCH_R8A7798) += r8a7798-cpg-mssr.o rcar-gen3-cpg.o + obj-$(CONFIG_ARCH_SH73A0) += clk-sh73a0.o clk-div6.o + + obj-$(CONFIG_CLK_RENESAS_CPG_MSSR) += renesas-cpg-mssr.o clk-div6.o +diff --git a/drivers/clk/renesas/r8a7798-cpg-mssr.c b/drivers/clk/renesas/r8a7798-cpg-mssr.c +new file mode 100644 +index 0000000..40ad314 +--- /dev/null ++++ b/drivers/clk/renesas/r8a7798-cpg-mssr.c +@@ -0,0 +1,292 @@ ++/* ++ * r8a7798 Clock Pulse Generator / Module Standby and Software Reset ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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; version 2 of the License. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "renesas-cpg-mssr.h" ++#include "rcar-gen3-cpg.h" ++ ++enum clk_ids { ++ /* Core Clock Outputs exported to DT */ ++ LAST_DT_CORE_CLK = R8A7798_CLK_OSC, ++ ++ /* External Input Clocks */ ++ CLK_EXTAL, ++ CLK_EXTALR, ++ ++ /* Internal Core Clocks */ ++ CLK_MAIN, ++ CLK_PLL1, ++ CLK_PLL2, ++ CLK_PLL3, ++ CLK_PLL1_DIV2, ++ CLK_PLL1_DIV4, ++ CLK_S0, ++ CLK_S1, ++ CLK_S2, ++ CLK_S3, ++ CLK_SDSRC, ++ CLK_RINT, ++ ++ /* Module Clocks */ ++ MOD_CLK_BASE ++}; ++ ++static const struct cpg_core_clk r8a7798_core_clks[] __initconst = { ++ /* External Clock Inputs */ ++ DEF_INPUT("extal", CLK_EXTAL), ++ DEF_INPUT("extalr", CLK_EXTALR), ++ ++ /* Internal Core Clocks */ ++ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL), ++ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN), ++ DEF_BASE(".pll2", CLK_PLL2, CLK_TYPE_GEN3_PLL2, CLK_MAIN), ++ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN), ++ ++ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1), ++ DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4, CLK_PLL1_DIV2, 2, 1), ++ DEF_FIXED(".s0", CLK_S0, CLK_PLL1_DIV2, 2, 1), ++ DEF_FIXED(".s1", CLK_S1, CLK_PLL1_DIV2, 3, 1), ++ DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1), ++ DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1), ++ DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1), ++ ++ /* Core Clock Outputs */ ++ DEF_BASE("z2", R8A7798_CLK_Z2, CLK_TYPE_GEN3_Z2, CLK_PLL2), ++ DEF_FIXED("ztr", R8A7798_CLK_ZTR, CLK_PLL1_DIV2, 6, 1), ++ DEF_FIXED("ztrd2", R8A7798_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1), ++ DEF_FIXED("zt", R8A7798_CLK_ZT, CLK_PLL1_DIV2, 4, 1), ++ DEF_FIXED("zx", R8A7798_CLK_ZX, CLK_PLL1_DIV2, 3, 1), ++ DEF_FIXED("s0d1", R8A7798_CLK_S0D1, CLK_S0, 1, 1), ++ DEF_FIXED("s0d2", R8A7798_CLK_S0D2, CLK_S0, 2, 1), ++ DEF_FIXED("s0d3", R8A7798_CLK_S0D3, CLK_S0, 3, 1), ++ DEF_FIXED("s0d4", R8A7798_CLK_S0D4, CLK_S0, 4, 1), ++ DEF_FIXED("s0d6", R8A7798_CLK_S0D6, CLK_S0, 6, 1), ++ DEF_FIXED("s0d12", R8A7798_CLK_S0D12, CLK_S0, 12, 1), ++ DEF_FIXED("s0d24", R8A7798_CLK_S0D24, CLK_S0, 24, 1), ++ DEF_FIXED("s1d1", R8A7798_CLK_S1D1, CLK_S1, 1, 1), ++ DEF_FIXED("s1d2", R8A7798_CLK_S1D2, CLK_S1, 2, 1), ++ DEF_FIXED("s1d4", R8A7798_CLK_S1D4, CLK_S1, 4, 1), ++ DEF_FIXED("s2d1", R8A7798_CLK_S2D1, CLK_S2, 1, 1), ++ DEF_FIXED("s2d2", R8A7798_CLK_S2D2, CLK_S2, 2, 1), ++ DEF_FIXED("s2d4", R8A7798_CLK_S2D4, CLK_S2, 4, 1), ++ DEF_FIXED("s3d1", R8A7798_CLK_S3D1, CLK_S3, 1, 1), ++ DEF_FIXED("s3d2", R8A7798_CLK_S3D2, CLK_S3, 2, 1), ++ DEF_FIXED("s3d4", R8A7798_CLK_S3D4, CLK_S3, 4, 1), ++ ++ DEF_GEN3_SD("sd0", R8A7798_CLK_SD0, CLK_SDSRC, 0x0074), /* OK? */ ++ ++ DEF_FIXED("cl", R8A7798_CLK_CL, CLK_PLL1_DIV2, 48, 1), ++ DEF_FIXED("cp", R8A7798_CLK_CP, CLK_EXTAL, 2, 1), ++ ++ DEF_DIV6P1("canfd", R8A7798_CLK_CANFD, CLK_PLL1_DIV4, 0x244), ++ DEF_DIV6P1("csi0", R8A7798_CLK_CSI0, CLK_PLL1_DIV4, 0x00c), ++ DEF_DIV6P1("mso", R8A7798_CLK_MSO, CLK_PLL1_DIV4, 0x014), ++ ++ DEF_BASE("osc", R8A7798_CLK_OSC, CLK_TYPE_GEN3_OSC, CLK_EXTAL), ++ DEF_BASE("r_int", CLK_RINT, CLK_TYPE_GEN3_RINT, CLK_EXTAL), ++ ++ DEF_BASE("r", R8A7798_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT), ++}; ++ ++static const struct mssr_mod_clk r8a7798_mod_clks[] __initconst = { ++ /*... skip crc, umf, disp, rt-sram, cle, smd_ */ ++ DEF_MOD("disp", 101, R8A7798_CLK_S1D1), ++ DEF_MOD("umf", 102, R8A7798_CLK_S1D1), ++ DEF_MOD("tmu4", 121, R8A7798_CLK_S0D6), ++ DEF_MOD("tmu3", 122, R8A7798_CLK_S0D6), ++ DEF_MOD("tmu2", 123, R8A7798_CLK_S0D6), ++ DEF_MOD("tmu1", 124, R8A7798_CLK_S0D6), ++ DEF_MOD("tmu0", 125, R8A7798_CLK_CP), ++ DEF_MOD("ivcp1e", 127, R8A7798_CLK_S3D1), /* FIXME parent clk? */ ++ DEF_MOD("scif4", 203, R8A7798_CLK_S3D4), ++ DEF_MOD("scif3", 204, R8A7798_CLK_S3D4), ++ DEF_MOD("scif1", 206, R8A7798_CLK_S3D4), ++ DEF_MOD("scif0", 207, R8A7798_CLK_S3D4), ++ DEF_MOD("msiof3", 208, R8A7798_CLK_MSO), ++ DEF_MOD("msiof2", 209, R8A7798_CLK_MSO), ++ DEF_MOD("msiof1", 210, R8A7798_CLK_MSO), ++ DEF_MOD("msiof0", 211, R8A7798_CLK_MSO), ++ DEF_MOD("mfis", 213, R8A7798_CLK_S2D2), /* FIXME parent clk? */ ++ DEF_MOD("sys-dmac2", 217, R8A7798_CLK_S0D3), /* OK? */ ++ DEF_MOD("sys-dmac1", 218, R8A7798_CLK_S0D3), /* OK? */ ++ DEF_MOD("cmt3", 300, R8A7798_CLK_R), ++ DEF_MOD("cmt2", 301, R8A7798_CLK_R), ++ DEF_MOD("cmt1", 302, R8A7798_CLK_R), ++ DEF_MOD("cmt0", 303, R8A7798_CLK_R), ++ DEF_MOD("tpu", 304, R8A7798_CLK_S3D4), ++ DEF_MOD("sdif", 314, R8A7798_CLK_SD0), /* OK */ ++ DEF_MOD("pciec", 319, R8A7798_CLK_S3D1), ++ DEF_MOD("rwdt0", 402, R8A7798_CLK_R), ++ DEF_MOD("intc-ex", 407, R8A7798_CLK_CP), /* OK */ ++ DEF_MOD("intc-ap", 408, R8A7798_CLK_S0D3), ++ DEF_MOD("simp", 500, R8A7798_CLK_S1D1), ++ DEF_MOD("hscif3", 517, R8A7798_CLK_S3D1), ++ DEF_MOD("hscif2", 518, R8A7798_CLK_S3D1), ++ DEF_MOD("hscif1", 519, R8A7798_CLK_S3D1), ++ DEF_MOD("hscif0", 520, R8A7798_CLK_S3D1), ++ DEF_MOD("imp4", 521, R8A7798_CLK_S1D1), /* OK? */ ++ DEF_MOD("thermal", 522, R8A7798_CLK_CP), ++ DEF_MOD("pwm", 523, R8A7798_CLK_S0D12), ++ DEF_MOD("imppsc1", 524, R8A7798_CLK_S1D1), ++ DEF_MOD("imppsc0", 525, R8A7798_CLK_S1D1), ++ DEF_MOD("impdma1", 526, R8A7798_CLK_S1D1), /* OK? */ ++ DEF_MOD("impdma0", 527, R8A7798_CLK_S1D1), /* OK? */ ++ DEF_MOD("imp-ocv4", 528, R8A7798_CLK_S1D1), /* OK? */ ++ DEF_MOD("imp-ocv3", 529, R8A7798_CLK_S1D1), /* OK? */ ++ DEF_MOD("imp-ocv2", 531, R8A7798_CLK_S1D1), /* OK? */ ++ DEF_MOD("fcpvd0", 603, R8A7798_CLK_S3D1), ++ DEF_MOD("vin15", 604, R8A7798_CLK_S2D1), /* FIXME parent clk? */ ++ DEF_MOD("vin14", 605, R8A7798_CLK_S2D1), /* FIXME parent clk? */ ++ DEF_MOD("vin13", 608, R8A7798_CLK_S2D1), /* FIXME parent clk? */ ++ DEF_MOD("vin12", 612, R8A7798_CLK_S2D1), /* FIXME parent clk? */ ++ DEF_MOD("vin11", 618, R8A7798_CLK_S2D1), /* FIXME parent clk? */ ++ DEF_MOD("vspd0", 623, R8A7798_CLK_S3D1), ++ DEF_MOD("vin10", 625, R8A7798_CLK_S2D1), /* FIXME parent clk? */ ++ DEF_MOD("vin9", 627, R8A7798_CLK_S2D1), /* FIXME parent clk? */ ++ DEF_MOD("vin8", 628, R8A7798_CLK_S2D1), /* FIXME parent clk? */ ++ DEF_MOD("imr5", 706, R8A7798_CLK_S2D1), /* FIXME parent clk? */ ++ DEF_MOD("imr4", 707, R8A7798_CLK_S2D1), /* FIXME parent clk? */ ++ DEF_MOD("csi41", 715, R8A7798_CLK_CSI0), ++ DEF_MOD("csi40", 716, R8A7798_CLK_CSI0), ++ DEF_MOD("du0", 724, R8A7798_CLK_S2D1), ++ DEF_MOD("lvds", 727, R8A7798_CLK_S2D1), ++ DEF_MOD("vin7", 804, R8A7798_CLK_S0D2), /* FIXME parent clk? */ ++ DEF_MOD("vin6", 805, R8A7798_CLK_S0D2), /* FIXME parent clk? */ ++ DEF_MOD("vin5", 806, R8A7798_CLK_S0D2), /* FIXME parent clk? */ ++ DEF_MOD("vin4", 807, R8A7798_CLK_S0D2), /* FIXME parent clk? */ ++ DEF_MOD("vin3", 808, R8A7798_CLK_S0D2), /* FIXME parent clk? */ ++ DEF_MOD("vin2", 809, R8A7798_CLK_S0D2), /* FIXME parent clk? */ ++ DEF_MOD("vin1", 810, R8A7798_CLK_S0D2), /* FIXME parent clk? */ ++ DEF_MOD("vin0", 811, R8A7798_CLK_S0D2), /* FIXME parent clk? */ ++ DEF_MOD("etheravb", 812, R8A7798_CLK_S3D2), /* OK */ ++ DEF_MOD("gether", 813, R8A7798_CLK_S3D2), /* OK */ ++ DEF_MOD("isp1", 814, R8A7798_CLK_S3D1), /* FIXME parent clk? */ ++ DEF_MOD("isp0", 817, R8A7798_CLK_S3D1), /* FIXME parent clk? */ ++ DEF_MOD("imr3", 820, R8A7798_CLK_S2D1), /* FIXME check clk? */ ++ DEF_MOD("imr2", 821, R8A7798_CLK_S2D1), /* FIXME check clk? */ ++ DEF_MOD("imr1", 822, R8A7798_CLK_S2D1), /* FIXME check clk? */ ++ DEF_MOD("imr0", 823, R8A7798_CLK_S2D1), /* FIXME check clk? */ ++ DEF_MOD("imp3", 824, R8A7798_CLK_S1D1), /* OK? figure 8.1e CPG block diag */ ++ DEF_MOD("imp2", 825, R8A7798_CLK_S1D1), /* OK? */ ++ DEF_MOD("imp1", 826, R8A7798_CLK_S1D1), /* OK? */ ++ DEF_MOD("imp0", 827, R8A7798_CLK_S1D1), /* OK? */ ++ DEF_MOD("imp-ocv1", 828, R8A7798_CLK_S1D1), /* OK? */ ++ DEF_MOD("imp-ocv0", 829, R8A7798_CLK_S1D1), /* OK? */ ++ DEF_MOD("impram", 830, R8A7798_CLK_S1D1), /* OK? */ ++ DEF_MOD("impcnn", 831, R8A7798_CLK_S1D1), /* OK? */ ++ DEF_MOD("gpio5", 907, R8A7798_CLK_CP), ++ DEF_MOD("gpio4", 908, R8A7798_CLK_CP), ++ DEF_MOD("gpio3", 909, R8A7798_CLK_CP), ++ DEF_MOD("gpio2", 910, R8A7798_CLK_CP), ++ DEF_MOD("gpio1", 911, R8A7798_CLK_CP), ++ DEF_MOD("gpio0", 912, R8A7798_CLK_CP), ++ DEF_MOD("can-fd", 914, R8A7798_CLK_S3D2), ++ /* FIXME missing MSSR for i2c5; should it be 919 as in H3/M3? */ ++ /* DEF_MOD("i2c4", 919, R8A7798_CLK_S3D2), */ ++ DEF_MOD("i2c4", 927, R8A7798_CLK_S0D6), ++ DEF_MOD("i2c3", 928, R8A7798_CLK_S0D6), ++ DEF_MOD("i2c2", 929, R8A7798_CLK_S3D2), ++ DEF_MOD("i2c1", 930, R8A7798_CLK_S3D2), ++ DEF_MOD("i2c0", 931, R8A7798_CLK_S3D2), ++ DEF_MOD("cle4", 1000, R8A7798_CLK_S1D1), ++ DEF_MOD("cle3", 1001, R8A7798_CLK_S1D1), ++ DEF_MOD("cle2", 1002, R8A7798_CLK_S1D1), ++ DEF_MOD("cle1", 1003, R8A7798_CLK_S1D1), ++ DEF_MOD("cle0", 1004, R8A7798_CLK_S1D1), ++ DEF_MOD("smd_post", 1100, R8A7798_CLK_S0D3), ++ DEF_MOD("smd_est", 1101, R8A7798_CLK_S0D3), ++ DEF_MOD("smd_ps", 1102, R8A7798_CLK_S0D3), ++}; ++ ++static const unsigned int r8a7798_crit_mod_clks[] __initconst = { ++ MOD_CLK_ID(408), /* INTC-AP (GIC) */ ++}; ++ ++ ++/* ++ * CPG Clock Data ++ */ ++ ++/* ++ * MD EXTAL PLL2 PLL1 PLL3 ++ * 14 13 19 (MHz) ++ *------------------------------------------------- ++ * 0 0 0 16.66 x 1 x240 x192 x192 ++ * 0 0 1 16.66 x 1 x240 x192 x192 ++ * 0 1 0 20 x 1 x200 x160 x160 ++ * 0 1 1 20 x 1 x200 x160 x160 ++ * 1 0 0 27 x 1 x148 x118 x118 ++ * 1 0 1 27 x 1 x148 x118 x118 ++ * 1 1 0 33.33 / 2 x240 x192 x192 ++ * 1 1 1 33.33 / 2 x240 x192 x192 ++ */ ++#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \ ++ (((md) & BIT(13)) >> 12) | \ ++ (((md) & BIT(19)) >> 19)) ++ ++static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[8] __initconst = { ++ /* EXTAL div PLL1 mult PLL3 mult */ ++ { 1, 192, 192,}, ++ { 1, 192, 192,}, ++ { 1, 160, 160,}, ++ { 1, 160, 160,}, ++ { 1, 118, 118,}, ++ { 1, 118, 118,}, ++ { 2, 192, 192,}, ++ { 2, 192, 192,}, ++}; ++ ++static int __init r8a7798_cpg_mssr_init(struct device *dev) ++{ ++ const struct rcar_gen3_cpg_pll_config *cpg_pll_config; ++ u32 cpg_mode; ++ int error; ++ ++ error = rcar_rst_read_mode_pins(&cpg_mode); ++ if (error) ++ return error; ++ ++ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)]; ++ if (!cpg_pll_config->extal_div) { ++ dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode); ++ return -EINVAL; ++ } ++ ++ return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode); ++} ++ ++const struct cpg_mssr_info r8a7798_cpg_mssr_info __initconst = { ++ /* Core Clocks */ ++ .core_clks = r8a7798_core_clks, ++ .num_core_clks = ARRAY_SIZE(r8a7798_core_clks), ++ .last_dt_core_clk = LAST_DT_CORE_CLK, ++ .num_total_core_clks = MOD_CLK_BASE, ++ ++ /* Module Clocks */ ++ .mod_clks = r8a7798_mod_clks, ++ .num_mod_clks = ARRAY_SIZE(r8a7798_mod_clks), ++ .num_hw_mod_clks = 12 * 32, ++ ++ /* Critical Module Clocks */ ++ .crit_mod_clks = r8a7798_crit_mod_clks, ++ .num_crit_mod_clks = ARRAY_SIZE(r8a7798_crit_mod_clks), ++ ++ /* Callbacks */ ++ .init = r8a7798_cpg_mssr_init, ++ .cpg_clk_register = rcar_gen3_cpg_clk_register, ++}; +diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c +index b145f14..930fa3d 100644 +--- a/drivers/clk/renesas/rcar-gen3-cpg.c ++++ b/drivers/clk/renesas/rcar-gen3-cpg.c +@@ -33,6 +33,11 @@ + { /* sentinel */ } + }; + ++static const struct soc_device_attribute r8a7798[] = { ++ { .soc_id = "r8a7798" }, ++ { } ++}; ++ + #define CPG_PLL0CR 0x00d8 + #define CPG_PLL2CR 0x002c + #define CPG_PLL4CR 0x01f4 +@@ -242,6 +247,10 @@ static unsigned long cpg_z2_clk_recalc_rate(struct clk_hw *hw, + mult = 32 - val; + + rate = div_u64((u64)parent_rate * mult + 16, 32); ++ ++ if (soc_device_match(r8a7798)) ++ rate /= 2; ++ + /* Round to closest value at 100MHz unit */ + rate = 100000000*DIV_ROUND_CLOSEST(rate, 100000000); + return rate; +@@ -303,6 +312,9 @@ static long cpg_z2_clk_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long prate = *parent_rate; + unsigned int mult; + ++ if (soc_device_match(r8a7798)) ++ prate /= 2; ++ + mult = div_u64((u64)rate * 32 + prate/2, prate); + mult = clamp(mult, 1U, 32U); + +@@ -382,7 +394,7 @@ static int cpg_z2_clk_set_rate(struct clk_hw *hw, unsigned long rate, + u32 val, kick; + unsigned int i; + +- if (soc_device_match(r8a7797)){ ++ if (soc_device_match(r8a7797) || soc_device_match(r8a7798)){ + pr_info("Do not support V3M's Z2 clock changing\n"); + return 0; + } +@@ -916,6 +928,11 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, + if (cpg_quirks & RCLK_CKSEL_RESEVED) + break; + ++ if (soc_device_match(r8a7798) && (cpg_mode ^ BIT(29))) { ++ parent = clks[cpg_clk_extalr]; ++ break; ++ } ++ + /* Select parent clock of RCLK by MD28 */ + if (cpg_mode & BIT(28)) + parent = clks[cpg_clk_extalr]; +diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c +index bd901a6..f1a81ed 100644 +--- a/drivers/clk/renesas/renesas-cpg-mssr.c ++++ b/drivers/clk/renesas/renesas-cpg-mssr.c +@@ -600,6 +600,12 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev, + .data = &r8a7797_cpg_mssr_info, + }, + #endif ++#ifdef CONFIG_ARCH_R8A7798 ++ { ++ .compatible = "renesas,r8a7798-cpg-mssr", ++ .data = &r8a7798_cpg_mssr_info, ++ }, ++#endif + { /* sentinel */ } + }; + +diff --git a/drivers/clk/renesas/renesas-cpg-mssr.h b/drivers/clk/renesas/renesas-cpg-mssr.h +index ce3546a..70cb4cb 100644 +--- a/drivers/clk/renesas/renesas-cpg-mssr.h ++++ b/drivers/clk/renesas/renesas-cpg-mssr.h +@@ -136,6 +136,7 @@ struct cpg_mssr_info { + extern const struct cpg_mssr_info r8a7796_cpg_mssr_info; + extern const struct cpg_mssr_info r8a77965_cpg_mssr_info; + extern const struct cpg_mssr_info r8a7797_cpg_mssr_info; ++extern const struct cpg_mssr_info r8a7798_cpg_mssr_info; + + + /* +diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c +index 5a2ec23..2d7d41c 100644 +--- a/drivers/cpufreq/cpufreq-dt-platdev.c ++++ b/drivers/cpufreq/cpufreq-dt-platdev.c +@@ -61,6 +61,7 @@ + { .compatible = "renesas,r8a7796", }, + { .compatible = "renesas,r8a77965", }, + { .compatible = "renesas,r8a7797", }, ++ { .compatible = "renesas,r8a7798", }, + { .compatible = "renesas,sh73a0", }, + + { .compatible = "rockchip,rk2928", }, +diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c +index fd15649..11044cd 100644 +--- a/drivers/gpio/gpio-rcar.c ++++ b/drivers/gpio/gpio-rcar.c +@@ -371,6 +371,10 @@ struct gpio_rcar_info { + /* Gen3 GPIO is identical to Gen2. */ + .data = &gpio_rcar_info_gen2, + }, { ++ .compatible = "renesas,gpio-r8a7798", ++ /* Gen3 GPIO is identical to Gen2. */ ++ .data = &gpio_rcar_info_gen2, ++ }, { + .compatible = "renesas,gpio-rcar", + .data = &gpio_rcar_info_gen1, + }, { +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c +index f74f264..6fea1e2 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c +@@ -360,6 +360,7 @@ + { .compatible = "renesas,du-r8a7796", .data = &rcar_du_r8a7796_info }, + { .compatible = "renesas,du-r8a77965", .data = &rcar_du_r8a77965_info }, + { .compatible = "renesas,du-r8a7797", .data = &rcar_du_r8a7797_info }, ++ { .compatible = "renesas,du-r8a7798", .data = &rcar_du_r8a7797_info }, + { } + }; + +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c +index 3916b63..22c7713 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c +@@ -35,8 +35,9 @@ + #include "rcar_du_group.h" + #include "rcar_du_regs.h" + +-static const struct soc_device_attribute r8a7797[] = { ++static const struct soc_device_attribute r8a7797_8[] = { + { .soc_id = "r8a7797" }, ++ { .soc_id = "r8a7798" }, + { } + }; + +@@ -161,7 +162,7 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp) + + /* Apply planes to CRTCs association. */ + mutex_lock(&rgrp->lock); +- if (!soc_device_match(r8a7797)) ++ if (!soc_device_match(r8a7797_8)) + rcar_du_group_write(rgrp, DPTSR, (rgrp->dptsr_planes << 16) | + rgrp->dptsr_planes); + +diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c +index 149c107..0ad583a 100644 +--- a/drivers/i2c/busses/i2c-rcar.c ++++ b/drivers/i2c/busses/i2c-rcar.c +@@ -808,6 +808,7 @@ static u32 rcar_i2c_func(struct i2c_adapter *adap) + { .compatible = "renesas,i2c-r8a7796", .data = (void *)I2C_RCAR_GEN3 }, + { .compatible = "renesas,i2c-r8a77965", .data = (void *)I2C_RCAR_GEN3 }, + { .compatible = "renesas,i2c-r8a7797", .data = (void *)I2C_RCAR_GEN3 }, ++ { .compatible = "renesas,i2c-r8a7798", .data = (void *)I2C_RCAR_GEN3 }, + {}, + }; + MODULE_DEVICE_TABLE(of, rcar_i2c_dt_ids); +diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c +index 1ae9174..41e14fa 100644 +--- a/drivers/iommu/ipmmu-vmsa.c ++++ b/drivers/iommu/ipmmu-vmsa.c +@@ -1280,6 +1280,9 @@ static void ipmmu_device_reset(struct ipmmu_vmsa_device *mmu) + .compatible = "renesas,ipmmu-r8a7797", + .data = &ipmmu_features_rcar_gen3, + }, { ++ .compatible = "renesas,ipmmu-r8a7798", ++ .data = &ipmmu_features_rcar_gen3, ++ }, { + /* Terminator */ + }, + }; +diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig +index 5539c5d..fc7d829 100644 +--- a/drivers/media/platform/soc_camera/Kconfig ++++ b/drivers/media/platform/soc_camera/Kconfig +@@ -39,7 +39,7 @@ config VIDEO_RCAR_VIN_LEGACY_DEBUG + config VIDEO_RCAR_CSI2_LEGACY + tristate "R-Car MIPI CSI-2 Interface driver" + depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK +- depends on ARCH_R8A7795 || ARCH_R8A7796 || ARCH_R8A7797 || COMPILE_TEST ++ depends on ARCH_R8A7795 || ARCH_R8A7796 || ARCH_R8A7797 || ARCH_R8A7798 || COMPILE_TEST + ---help--- + This is a v4l2 driver for the R-Car CSI-2 Interface + +diff --git a/drivers/media/platform/soc_camera/rcar_csi2.c b/drivers/media/platform/soc_camera/rcar_csi2.c +index 2ef27e8..98f271f 100644 +--- a/drivers/media/platform/soc_camera/rcar_csi2.c ++++ b/drivers/media/platform/soc_camera/rcar_csi2.c +@@ -163,6 +163,11 @@ + #define RCAR_CSI2_INTSTATE_ERRSYNCESC (1 << 1) + #define RCAR_CSI2_INTSTATE_ERRCONTROL (1 << 0) + ++static const struct soc_device_attribute r8a7798[] = { ++ { .soc_id = "r8a7798" }, ++ { } ++}; ++ + static const struct soc_device_attribute r8a7797[] = { + { .soc_id = "r8a7797" }, + { } +@@ -410,7 +415,7 @@ static int rcar_csi2_set_phy_freq(struct rcar_csi2 *priv) + iowrite32((hs_freq_range_v3m[bps_per_lane] << 16) | + RCAR_CSI2_PHTW_DWEN | RCAR_CSI2_PHTW_CWEN | 0x44, + priv->base + RCAR_CSI2_PHTW); +- else if (soc_device_match(r8a7795)) ++ else if (soc_device_match(r8a7795) || soc_device_match(r8a7798)) + iowrite32(hs_freq_range_h3[bps_per_lane] << 16, + priv->base + RCAR_CSI2_PHYPLL); + else +@@ -497,8 +502,8 @@ static int rcar_csi2_hwinit(struct rcar_csi2 *priv) + return -EINVAL; + } + +- if (soc_device_match(r8a7795)) { +- /* Set PHY Test Interface Write Register in R-Car H3(ES2.0) */ ++ if (soc_device_match(r8a7795) || soc_device_match(r8a7798)) { ++ /* Set PHY Test Interface Write Register in R-Car H3(ES2.0)/V3H */ + iowrite32(0x01cc01e2, priv->base + RCAR_CSI2_PHTW); + iowrite32(0x010101e3, priv->base + RCAR_CSI2_PHTW); + iowrite32(0x010101e4, priv->base + RCAR_CSI2_PHTW); +@@ -515,7 +520,7 @@ static int rcar_csi2_hwinit(struct rcar_csi2 *priv) + /* Set CSI0CLK Frequency Configuration Preset Register + * in R-Car H3(ES2.0) + */ +- if (soc_device_match(r8a7795)) ++ if (soc_device_match(r8a7795) || soc_device_match(r8a7798)) + iowrite32(CSI0CLKFREQRANGE(32), priv->base + RCAR_CSI2_CSI0CLKFCPR); + + /* Enable lanes */ +@@ -609,6 +614,7 @@ static int rcar_csi2_s_power(struct v4l2_subdev *sd, int on) + + #ifdef CONFIG_OF + static const struct of_device_id rcar_csi2_of_table[] = { ++ { .compatible = "renesas,r8a7798-csi2", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,r8a7797-csi2", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,r8a7796-csi2", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,r8a7795-csi2", .data = (void *)RCAR_GEN3 }, +@@ -618,6 +624,7 @@ static int rcar_csi2_s_power(struct v4l2_subdev *sd, int on) + #endif + + static struct platform_device_id rcar_csi2_id_table[] = { ++ { "r8a7798-csi2", RCAR_GEN3 }, + { "r8a7797-csi2", RCAR_GEN3 }, + { "r8a7796-csi2", RCAR_GEN3 }, + { "r8a7795-csi2", RCAR_GEN3 }, +diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c +index b7ec03c..37f1a11 100644 +--- a/drivers/media/platform/soc_camera/rcar_vin.c ++++ b/drivers/media/platform/soc_camera/rcar_vin.c +@@ -162,7 +162,7 @@ + #define VNCSI_IFMD_REG 0x20 /* Video n CSI2 Interface Mode Register */ + + #define VNCSI_IFMD_DES1 (1 << 26) /* CSI20 */ +-#define VNCSI_IFMD_DES0 (1 << 25) /* H3:CSI40/41, M3:CSI40, V3M:CSI40 */ ++#define VNCSI_IFMD_DES0 (1 << 25) /* H3,V3H:CSI40/41, M3:CSI40, V3M:CSI40 */ + + #define VNCSI_IFMD_CSI_CHSEL(n) (n << 0) + #define VNCSI_IFMD_SEL_NUMBER 5 +@@ -197,6 +197,7 @@ + + enum chip_id { + RCAR_GEN3, ++ RCAR_V3H, + RCAR_V3M, + RCAR_M3, + RCAR_H3, +@@ -416,6 +417,69 @@ struct vin_gen3_ifmd { + }, + }; + ++static const struct vin_gen3_ifmd vin_v3h_vc_ifmd[] = { ++ { 0x0000, ++ { ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH1}, ++ } ++ }, ++ { 0x0001, ++ { ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ } ++ }, ++ { 0x0002, ++ { ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ } ++ }, ++ { 0x0003, ++ { ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH3}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH3}, ++ } ++ }, ++ { 0x0004, ++ { ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ } ++ }, ++}; ++ + enum csi2_fmt { + RCAR_CSI_FMT_NONE = -1, + RCAR_CSI_RGB888, +@@ -911,7 +975,7 @@ static int rcar_vin_videobuf_setup(struct vb2_queue *vq, + struct rcar_vin_cam *cam = icd->host_priv; + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_V3M || priv->chip == RCAR_V3H) { + if ((priv->ratio_h > 0x10000) || (priv->ratio_v > 0x10000)) { + dev_err(icd->parent, "Scaling rate parameter error\n"); + return -EINVAL; +@@ -1020,7 +1084,7 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + switch (icd->current_fmt->host_fmt->fourcc) { + case V4L2_PIX_FMT_NV12: + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_V3M || priv->chip == RCAR_V3H) { + iowrite32(ALIGN((cam->out_width * cam->out_height), + 0x80), priv->base + VNUVAOF_REG); + dmr = VNDMR_DTMD_YCSEP_YCBCR420; +@@ -1056,7 +1120,7 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + break; + case V4L2_PIX_FMT_XBGR32: + if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3 && +- priv->chip != RCAR_V3M && ++ priv->chip != RCAR_V3M && priv->chip != RCAR_V3H && + priv->chip != RCAR_GEN2 && priv->chip != RCAR_H1 && + priv->chip != RCAR_E1) + goto e_format; +@@ -1065,7 +1129,7 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + break; + case V4L2_PIX_FMT_ABGR32: + if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3 && +- priv->chip != RCAR_V3M) ++ priv->chip != RCAR_V3M && priv->chip != RCAR_V3H) + goto e_format; + + dmr = VNDMR_EXRGB | VNDMR_DTMD_ARGB; +@@ -1086,7 +1150,7 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + vnmc |= VNMC_BPS; + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_V3M || priv->chip == RCAR_V3H) { + if (priv->pdata_flags & RCAR_VIN_CSI2) + vnmc &= ~VNMC_DPINE; + else +@@ -1457,7 +1521,7 @@ static int rcar_vin_add_device(struct soc_camera_device *icd) + pm_runtime_get_sync(ici->v4l2_dev.dev); + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_V3M || priv->chip == RCAR_V3H) { + struct v4l2_subdev *csi2_sd = find_csi2(priv); + struct v4l2_subdev *deser_sd = find_deser(priv); + int ret = 0; +@@ -1720,7 +1784,7 @@ static int rcar_vin_set_rect(struct soc_camera_device *icd) + } + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_V3M || priv->chip == RCAR_V3H) { + if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12) && + (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR8) && + (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR12) +@@ -1878,7 +1942,7 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd) + return ret; + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_V3M || priv->chip == RCAR_V3H) { + if (cfg.type == V4L2_MBUS_CSI2) + vnmc &= ~VNMC_DPINE; + else +@@ -1886,7 +1950,7 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd) + } + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) ++ priv->chip == RCAR_V3M || priv->chip == RCAR_V3H) + val = VNDMR2_FTEV; + else + val = VNDMR2_FTEV | VNDMR2_VLV(1); +@@ -2484,7 +2548,7 @@ static int rcar_vin_try_fmt(struct soc_camera_device *icd, + return ret; + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_V3M || priv->chip == RCAR_V3H) { + /* Adjust max scaling size for Gen3 */ + if (pix->width > 4096) + pix->width = priv->max_width; +@@ -2663,6 +2727,7 @@ static int rcar_vin_get_edid(struct soc_camera_device *icd, + + #ifdef CONFIG_OF + static const struct of_device_id rcar_vin_of_table[] = { ++ { .compatible = "renesas,vin-r8a7798", .data = (void *)RCAR_V3H }, + { .compatible = "renesas,vin-r8a7797", .data = (void *)RCAR_V3M }, + { .compatible = "renesas,vin-r8a7796", .data = (void *)RCAR_M3 }, + { .compatible = "renesas,vin-r8a7795", .data = (void *)RCAR_H3 }, +@@ -2978,7 +3043,7 @@ static int rcar_vin_probe(struct platform_device *pdev) + } + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_V3M || priv->chip == RCAR_V3H) { + priv->max_width = 4096; + priv->max_height = 4096; + } else { +@@ -2987,7 +3052,8 @@ static int rcar_vin_probe(struct platform_device *pdev) + } + + if ((priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) && !of_property_read_string(np, "csi,select", &str)) { ++ priv->chip == RCAR_V3M || priv->chip == RCAR_V3H) && ++ !of_property_read_string(np, "csi,select", &str)) { + u32 ifmd = 0; + bool match_flag = false; + const struct vin_gen3_ifmd *gen3_ifmd_table = NULL; +@@ -3062,6 +3128,8 @@ static int rcar_vin_probe(struct platform_device *pdev) + gen3_ifmd_table = vin_m3_vc_ifmd; + else if (priv->chip == RCAR_V3M) + gen3_ifmd_table = vin_v3_vc_ifmd; ++ else if (priv->chip == RCAR_V3H) ++ gen3_ifmd_table = vin_v3h_vc_ifmd; + + for (i = 0; i < num; i++) { + if ((gen3_ifmd_table[i].v_sel[priv->index].csi2_ch +@@ -3219,6 +3287,9 @@ static int rcar_vin_resume(struct device *dev) + } else if (priv->chip == RCAR_V3M) { + ifmd = VNCSI_IFMD_DES1; + gen3_ifmd_table = vin_v3_vc_ifmd; ++ } else if (priv->chip == RCAR_V3H) { ++ ifmd = VNCSI_IFMD_DES0; ++ gen3_ifmd_table = vin_v3h_vc_ifmd; + } + + for (i = 0; i < num; i++) { +diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c +index e79f9e6..22fb76a 100644 +--- a/drivers/media/platform/vsp1/vsp1_lif.c ++++ b/drivers/media/platform/vsp1/vsp1_lif.c +@@ -29,6 +29,11 @@ + { } + }; + ++static const struct soc_device_attribute r8a7798[] = { ++ { .soc_id = "r8a7798" }, ++ { } ++}; ++ + /* ----------------------------------------------------------------------------- + * Device Access + */ +@@ -151,7 +156,8 @@ static void lif_configure(struct vsp1_entity *entity, + format = vsp1_entity_get_pad_format(&lif->entity, lif->entity.config, + LIF_PAD_SOURCE); + +- if (vsp1_gen3_vspdl_check(vsp1) || soc_device_match(r8a7797)) ++ if (vsp1_gen3_vspdl_check(vsp1) || ++ soc_device_match(r8a7797) || soc_device_match(r8a7798)) + obth = 1500; + else + obth = 3000; +diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c +index 040f474..72b46bb 100644 +--- a/drivers/mmc/host/sh_mobile_sdhi.c ++++ b/drivers/mmc/host/sh_mobile_sdhi.c +@@ -141,6 +141,7 @@ struct sh_mobile_sdhi_of_data { + { .compatible = "renesas,sdhi-r8a77965", + .data = &of_rcar_gen3_compatible, }, + { .compatible = "renesas,sdhi-r8a7797", .data = &of_rcar_gen3_compatible, }, ++ { .compatible = "renesas,sdhi-r8a7798", .data = &of_rcar_gen3_compatible, }, + {}, + }; + MODULE_DEVICE_TABLE(of, sh_mobile_sdhi_of_match); +diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c +index 73fa286..c539234 100644 +--- a/drivers/net/ethernet/renesas/ravb_main.c ++++ b/drivers/net/ethernet/renesas/ravb_main.c +@@ -1921,6 +1921,7 @@ static int ravb_mdio_release(struct ravb_private *priv) + { .compatible = "renesas,etheravb-r8a7796", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,etheravb-r8a77965", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,etheravb-r8a7797", .data = (void *)RCAR_GEN3 }, ++ { .compatible = "renesas,etheravb-r8a7798", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,etheravb-rcar-gen3", .data = (void *)RCAR_GEN3 }, + { } + }; +diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c +index d18b452..f87cae6 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.c ++++ b/drivers/net/ethernet/renesas/sh_eth.c +@@ -456,6 +456,9 @@ static void sh_eth_select_mii(struct net_device *ndev) + u32 value; + + switch (mdp->phy_interface) { ++ case PHY_INTERFACE_MODE_RGMII: ++ value = 0x3; ++ break; + case PHY_INTERFACE_MODE_GMII: + value = 0x2; + break; +@@ -645,6 +648,36 @@ static void sh_eth_set_rate_r8a777x(struct net_device *ndev) + .rmiimode = 1, + .magic = 1, + }; ++ ++/* R8A7798 */ ++static struct sh_eth_cpu_data r8a7798_data = { ++ .set_duplex = sh_eth_set_duplex, ++ .set_rate = sh_eth_set_rate_gether, ++ ++ .register_type = SH_ETH_REG_GIGABIT, ++ ++ .ecsr_value = ECSR_PSRTO | ECSR_LCHNG | ECSR_ICD | ECSR_MPD, ++ .ecsipr_value = ECSIPR_PSRTOIP | ECSIPR_LCHNGIP | ECSIPR_ICDIP | ++ ECSIPR_MPDIP, ++ .eesipr_value = 0x01ff009f, ++ ++ .tx_check = EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO, ++ .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | ++ EESR_RFE | EESR_RDE | EESR_RFRMER | EESR_TFE | ++ EESR_TDE | EESR_ECI, ++ .fdr_value = 0x0000070f, ++ ++ .apr = 1, ++ .mpr = 1, ++ .tpauser = 1, ++ .nbst = 1, ++ .hw_swap = 1, ++ .no_trimd = 1, ++ .no_ade = 1, ++ .select_mii = 1, ++ .shift_rd0 = 1, ++ .magic = 1, ++}; + #endif /* CONFIG_OF */ + + static void sh_eth_set_rate_sh7724(struct net_device *ndev) +@@ -1088,14 +1121,14 @@ static void sh_eth_ring_free(struct net_device *ndev) + + if (mdp->rx_ring) { + ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring; +- dma_free_coherent(NULL, ringsize, mdp->rx_ring, ++ dma_free_coherent(&ndev->dev, ringsize, mdp->rx_ring, + mdp->rx_desc_dma); + mdp->rx_ring = NULL; + } + + if (mdp->tx_ring) { + ringsize = sizeof(struct sh_eth_txdesc) * mdp->num_tx_ring; +- dma_free_coherent(NULL, ringsize, mdp->tx_ring, ++ dma_free_coherent(&ndev->dev, ringsize, mdp->tx_ring, + mdp->tx_desc_dma); + mdp->tx_ring = NULL; + } +@@ -1209,9 +1242,16 @@ static int sh_eth_ring_init(struct net_device *ndev) + if (!mdp->tx_skbuff) + goto ring_free; + ++#ifdef CONFIG_ARM64 ++ { ++ struct device_node *np; ++ np = of_find_compatible_node(NULL, NULL, "shared-dma-pool"); ++ of_dma_configure(&ndev->dev, np); ++ } ++#endif + /* Allocate all Rx descriptors. */ + rx_ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring; +- mdp->rx_ring = dma_alloc_coherent(NULL, rx_ringsize, &mdp->rx_desc_dma, ++ mdp->rx_ring = dma_alloc_coherent(&ndev->dev, rx_ringsize, &mdp->rx_desc_dma, + GFP_KERNEL); + if (!mdp->rx_ring) + goto ring_free; +@@ -1220,7 +1260,7 @@ static int sh_eth_ring_init(struct net_device *ndev) + + /* Allocate all Tx descriptors. */ + tx_ringsize = sizeof(struct sh_eth_txdesc) * mdp->num_tx_ring; +- mdp->tx_ring = dma_alloc_coherent(NULL, tx_ringsize, &mdp->tx_desc_dma, ++ mdp->tx_ring = dma_alloc_coherent(&ndev->dev, tx_ringsize, &mdp->tx_desc_dma, + GFP_KERNEL); + if (!mdp->tx_ring) + goto ring_free; +@@ -1261,6 +1301,10 @@ static int sh_eth_dev_init(struct net_device *ndev) + #endif + sh_eth_write(ndev, 0, EDMR); + ++ /* DMA transfer burst mode */ ++ if (mdp->cd->nbst) ++ sh_eth_modify(ndev, EDMR, EDMR_NBST, EDMR_NBST); ++ + /* FIFO size set */ + sh_eth_write(ndev, mdp->cd->fdr_value, FDR); + sh_eth_write(ndev, 0, TFTR); +@@ -3001,6 +3045,7 @@ static struct sh_eth_plat_data *sh_eth_parse_dt(struct device *dev) + { .compatible = "renesas,ether-r8a7791", .data = &r8a779x_data }, + { .compatible = "renesas,ether-r8a7793", .data = &r8a779x_data }, + { .compatible = "renesas,ether-r8a7794", .data = &r8a779x_data }, ++ { .compatible = "renesas,gether-r8a7798", .data = &r8a7798_data }, + { .compatible = "renesas,ether-r7s72100", .data = &r7s72100_data }, + { } + }; +diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h +index 4ceed00..2c4ddd6 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.h ++++ b/drivers/net/ethernet/renesas/sh_eth.h +@@ -163,7 +163,8 @@ enum { + }; + + /* Driver's parameters */ +-#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE) ++#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE) || \ ++ defined(CONFIG_ARCH_R8A7798) + #define SH_ETH_RX_ALIGN 32 + #else + #define SH_ETH_RX_ALIGN 2 +@@ -184,6 +185,7 @@ enum GECMR_BIT { + + /* EDMR */ + enum DMAC_M_BIT { ++ EDMR_NBST = 0x80, + EDMR_EL = 0x40, /* Litte endian */ + EDMR_DL1 = 0x20, EDMR_DL0 = 0x10, + EDMR_SRST_GETHER = 0x03, +@@ -484,6 +486,7 @@ struct sh_eth_cpu_data { + unsigned tpauser:1; /* EtherC have TPAUSER */ + unsigned bculr:1; /* EtherC have BCULR */ + unsigned tsu:1; /* EtherC have TSU */ ++ unsigned nbst:1; /* E-DMAC have NBST bit in EDMR */ + unsigned hw_swap:1; /* E-DMAC have DE bit in EDMR */ + unsigned rpadir:1; /* E-DMAC have RPADIR */ + unsigned no_trimd:1; /* E-DMAC DO NOT have TRIMD */ +diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c +index ccc29b3..ebe7e92 100644 +--- a/drivers/pci/host/pcie-rcar.c ++++ b/drivers/pci/host/pcie-rcar.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + + #define PCIECAR 0x000010 + #define PCIECCTLR 0x000018 +@@ -41,6 +42,8 @@ + #define PCIEINTXR 0x000400 + #define PCIEMSITXR 0x000840 + ++#define GEN3_PCIEPHYSR 0x07f0 ++ + /* Transfer control */ + #define PCIETCTLR 0x02000 + #define DL_DOWN (1 << 3) +@@ -118,6 +121,9 @@ + #define GEN2_PCIEPHYDATA 0x784 + #define GEN2_PCIEPHYCTRL 0x78c + ++/* R-Car Gen3 R8A7798 */ ++#define R8A7798_PCIEPHYCTL 0x4000 ++ + #define INT_PCI_MSI_NR 32 + + #define RCONF(x) (PCICONF(0)+(x)) +@@ -132,6 +138,11 @@ + #define RCAR_PCI_MAX_RESOURCES 4 + #define MAX_NR_INBOUND_MAPS 6 + ++static const struct soc_device_attribute r8a7798[] = { ++ { .soc_id = "r8a7798" }, ++ { } ++}; ++ + struct rcar_msi { + DECLARE_BITMAP(used, INT_PCI_MSI_NR); + struct irq_domain *domain; +@@ -151,6 +162,7 @@ static inline struct rcar_msi *to_rcar_msi(struct msi_controller *chip) + struct rcar_pcie { + struct device *dev; + void __iomem *base; ++ void __iomem *phy_base; + struct list_head resources; + int root_bus_nr; + struct clk *clk; +@@ -160,6 +172,18 @@ struct rcar_pcie { + + static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie); + ++static void rcar_pci_phy_write_reg(struct rcar_pcie *pcie, unsigned long val, ++ unsigned long reg) ++{ ++ writel(val, pcie->phy_base + reg); ++} ++ ++static unsigned long rcar_pci_phy_read_reg(struct rcar_pcie *pcie, ++ unsigned long reg) ++{ ++ return readl(pcie->phy_base + reg); ++} ++ + static void rcar_pci_write_reg(struct rcar_pcie *pcie, unsigned long val, + unsigned long reg) + { +@@ -672,6 +696,22 @@ static int rcar_pcie_hw_init(struct rcar_pcie *pcie) + return 0; + } + ++static int rcar_pcie_hw_init_r8a7798(struct rcar_pcie *pcie) ++{ ++ unsigned int timeout = 10; ++ ++ rcar_pci_phy_write_reg(pcie, 0, R8A7798_PCIEPHYCTL); ++ ++ while (timeout--) { ++ if (rcar_pci_read_reg(pcie, GEN3_PCIEPHYSR)) ++ return rcar_pcie_hw_init(pcie); ++ ++ msleep(5); ++ } ++ ++ return -ETIMEDOUT; ++} ++ + static int rcar_pcie_hw_init_h1(struct rcar_pcie *pcie) + { + unsigned int timeout = 10; +@@ -998,6 +1038,16 @@ static int rcar_pcie_get_resources(struct rcar_pcie *pcie) + if (IS_ERR(pcie->base)) + return PTR_ERR(pcie->base); + ++ if (soc_device_match(r8a7798)) { ++ err = of_address_to_resource(dev->of_node, 1, &res); ++ if (err) ++ return err; ++ ++ pcie->phy_base = devm_ioremap_resource(dev, &res); ++ if (IS_ERR(pcie->phy_base)) ++ return PTR_ERR(pcie->base); ++ } ++ + pcie->bus_clk = devm_clk_get(dev, "pcie_bus"); + if (IS_ERR(pcie->bus_clk)) { + dev_err(dev, "cannot get pcie bus clock\n"); +@@ -1153,6 +1203,7 @@ static int rcar_pcie_parse_map_dma_ranges(struct rcar_pcie *pcie, + { .compatible = "renesas,pcie-r8a7795", .data = rcar_pcie_hw_init }, + { .compatible = "renesas,pcie-r8a7796", .data = rcar_pcie_hw_init }, + { .compatible = "renesas,pcie-r8a77965", .data = rcar_pcie_hw_init }, ++ { .compatible = "renesas,pcie-r8a7798", .data = rcar_pcie_hw_init_r8a7798 }, + {}, + }; + +@@ -1347,7 +1398,13 @@ static SIMPLE_DEV_PM_OPS(rcar_pcie_pm_ops, + }, + .probe = rcar_pcie_probe, + }; +-builtin_platform_driver(rcar_pcie_driver); ++/* builtin_platform_driver(rcar_pcie_driver); */ ++ ++static int __init rcar_pcie_init(void) ++{ ++ return platform_driver_register(&rcar_pcie_driver); ++} ++late_initcall(rcar_pcie_init); + + static int rcar_pcie_pci_notifier(struct notifier_block *nb, + unsigned long action, void *data) +diff --git a/drivers/pinctrl/sh-pfc/Kconfig b/drivers/pinctrl/sh-pfc/Kconfig +index 4aaf0be..6ae17af 100644 +--- a/drivers/pinctrl/sh-pfc/Kconfig ++++ b/drivers/pinctrl/sh-pfc/Kconfig +@@ -89,6 +89,11 @@ config PINCTRL_PFC_R8A7797 + depends on ARCH_R8A7797 + select PINCTRL_SH_PFC + ++config PINCTRL_PFC_R8A7798 ++ def_bool y ++ depends on ARCH_R8A7798 ++ select PINCTRL_SH_PFC ++ + config PINCTRL_PFC_SH7203 + def_bool y + depends on CPU_SUBTYPE_SH7203 +diff --git a/drivers/pinctrl/sh-pfc/Makefile b/drivers/pinctrl/sh-pfc/Makefile +index e263c14..5f2f619 100644 +--- a/drivers/pinctrl/sh-pfc/Makefile ++++ b/drivers/pinctrl/sh-pfc/Makefile +@@ -15,6 +15,7 @@ obj-$(CONFIG_PINCTRL_PFC_R8A7795) += pfc-r8a7795-es1.o + obj-$(CONFIG_PINCTRL_PFC_R8A7796) += pfc-r8a7796.o + obj-$(CONFIG_PINCTRL_PFC_R8A77965) += pfc-r8a77965.o + obj-$(CONFIG_PINCTRL_PFC_R8A7797) += pfc-r8a7797.o ++obj-$(CONFIG_PINCTRL_PFC_R8A7798) += pfc-r8a7798.o + obj-$(CONFIG_PINCTRL_PFC_SH7203) += pfc-sh7203.o + obj-$(CONFIG_PINCTRL_PFC_SH7264) += pfc-sh7264.o + obj-$(CONFIG_PINCTRL_PFC_SH7269) += pfc-sh7269.o +diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c +index 9aba933..d685090 100644 +--- a/drivers/pinctrl/sh-pfc/core.c ++++ b/drivers/pinctrl/sh-pfc/core.c +@@ -552,6 +552,12 @@ static int sh_pfc_init_ranges(struct sh_pfc *pfc) + .data = &r8a7797_pinmux_info, + }, + #endif ++#ifdef CONFIG_PINCTRL_PFC_R8A7798 ++ { ++ .compatible = "renesas,pfc-r8a7798", ++ .data = &r8a7798_pinmux_info, ++ }, ++#endif + #ifdef CONFIG_PINCTRL_PFC_SH73A0 + { + .compatible = "renesas,pfc-sh73a0", +diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7798.c b/drivers/pinctrl/sh-pfc/pfc-r8a7798.c +new file mode 100644 +index 0000000..39aba74 +--- /dev/null ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a7798.c +@@ -0,0 +1,3151 @@ ++/* ++ * R8A7798 processor support - PFC hardware block. ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is based on the drivers/pinctrl/sh-pfc/pfc-r8a7795.c ++ * ++ * R-Car Gen3 processor support - PFC hardware block. ++ * ++ * Copyright (C) 2015 Renesas Electronics Corporation ++ * ++ * 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; version 2 of the License. ++ */ ++ ++#include ++#include ++#include ++ ++#include "core.h" ++#include "sh_pfc.h" ++ ++/* mmc in gpsr3, so do POC; check if any other reg needs it */ ++#define CPU_ALL_PORT(fn, sfx) \ ++ PORT_GP_CFG_22(0, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \ ++ PORT_GP_CFG_28(1, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \ ++ PORT_GP_CFG_30(2, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \ ++ PORT_GP_CFG_17(3, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH | \ ++ SH_PFC_PIN_CFG_IO_VOLTAGE), \ ++ PORT_GP_CFG_25(4, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \ ++ PORT_GP_CFG_15(5, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH) ++/* ++ * F_() : just information ++ * FM() : macro for FN_xxx / xxx_MARK ++ */ ++ ++/* GPSR0 */ ++#define GPSR0_21 F_(DU_EXODDF_DU_ODDF_DISP_CDE, IP2_23_20) ++#define GPSR0_20 F_(DU_EXVSYNC_DU_VSYNC, IP2_19_16) ++#define GPSR0_19 F_(DU_EXHSYNC_DU_HSYNC, IP2_15_12) ++#define GPSR0_18 F_(DU_DOTCLKOUT, IP2_11_8) ++#define GPSR0_17 F_(DU_DB7, IP2_7_4) ++#define GPSR0_16 F_(DU_DB6, IP2_3_0) ++#define GPSR0_15 F_(DU_DB5, IP1_31_28) ++#define GPSR0_14 F_(DU_DB4, IP1_27_24) ++#define GPSR0_13 F_(DU_DB3, IP1_23_20) ++#define GPSR0_12 F_(DU_DB2, IP1_19_16) ++#define GPSR0_11 F_(DU_DG7, IP1_15_12) ++#define GPSR0_10 F_(DU_DG6, IP1_11_8) ++#define GPSR0_9 F_(DU_DG5, IP1_7_4) ++#define GPSR0_8 F_(DU_DG4, IP1_3_0) ++#define GPSR0_7 F_(DU_DG3, IP0_31_28) ++#define GPSR0_6 F_(DU_DG2, IP0_27_24) ++#define GPSR0_5 F_(DU_DR7, IP0_23_20) ++#define GPSR0_4 F_(DU_DR6, IP0_19_16) ++#define GPSR0_3 F_(DU_DR5, IP0_15_12) ++#define GPSR0_2 F_(DU_DR4, IP0_11_8) ++#define GPSR0_1 F_(DU_DR3, IP0_7_4) ++#define GPSR0_0 F_(DU_DR2, IP0_3_0) ++ ++/* GPSR1 */ ++#define GPSR1_27 F_(DIGRF_CLKOUT, IP8_31_28) ++#define GPSR1_26 F_(DIGRF_CLKIN, IP8_27_24) ++#define GPSR1_25 F_(CANFD_CLK_A, IP8_23_20) /* OK? */ ++#define GPSR1_24 F_(CANFD1_RX, IP8_19_16) ++#define GPSR1_23 F_(CANFD1_TX, IP8_15_12) ++#define GPSR1_22 F_(CANFD0_RX_A, IP8_11_8) ++#define GPSR1_21 F_(CANFD0_TX_A, IP8_7_4) ++#define GPSR1_20 F_(AVB_AVTP_CAPTURE, IP8_3_0) ++#define GPSR1_19 F_(AVB_AVTP_MATCH, IP7_31_28) ++#define GPSR1_18 FM(AVB_LINK) ++#define GPSR1_17 FM(AVB_PHY_INT) ++#define GPSR1_16 FM(AVB_MAGIC) ++#define GPSR1_15 FM(AVB_MDC) ++#define GPSR1_14 FM(AVB_MDIO) ++#define GPSR1_13 FM(AVB_TXCREFCLK) ++#define GPSR1_12 FM(AVB_TD3) ++#define GPSR1_11 FM(AVB_TD2) ++#define GPSR1_10 FM(AVB_TD1) ++#define GPSR1_9 FM(AVB_TD0) ++#define GPSR1_8 FM(AVB_TXC) ++#define GPSR1_7 FM(AVB_TX_CTL) ++#define GPSR1_6 FM(AVB_RD3) ++#define GPSR1_5 FM(AVB_RD2) ++#define GPSR1_4 FM(AVB_RD1) ++#define GPSR1_3 FM(AVB_RD0) ++#define GPSR1_2 FM(AVB_RXC) ++#define GPSR1_1 FM(AVB_RX_CTL) ++#define GPSR1_0 F_(IRQ0, IP2_27_24) ++ ++/* GPSR2 */ ++#define GPSR2_29 F_(FSO_TOE_N, IP10_19_16) ++#define GPSR2_28 F_(FSO_CFE_1_N, IP10_15_12) ++#define GPSR2_27 F_(FSO_CFE_0_N, IP10_11_8) ++#define GPSR2_26 F_(SDA3, IP10_7_4) ++#define GPSR2_25 F_(SCL3, IP10_3_0) ++#define GPSR2_24 F_(MSIOF0_SS2, IP9_31_28) ++#define GPSR2_23 F_(MSIOF0_SS1, IP9_27_24) ++#define GPSR2_22 F_(MSIOF0_SYNC, IP9_23_20) ++#define GPSR2_21 F_(MSIOF0_SCK, IP9_19_16) ++#define GPSR2_20 F_(MSIOF0_TXD, IP9_15_12) ++#define GPSR2_19 F_(MSIOF0_RXD, IP9_11_8) ++#define GPSR2_18 F_(IRQ5, IP9_7_4) ++#define GPSR2_17 F_(IRQ4, IP9_3_0) ++#define GPSR2_16 F_(VI0_FIELD, IP4_31_28) ++#define GPSR2_15 F_(VI0_DATA11, IP4_27_24) ++#define GPSR2_14 F_(VI0_DATA10, IP4_23_20) ++#define GPSR2_13 F_(VI0_DATA9, IP4_19_16) ++#define GPSR2_12 F_(VI0_DATA8, IP4_15_12) ++#define GPSR2_11 F_(VI0_DATA7, IP4_11_8) ++#define GPSR2_10 F_(VI0_DATA6, IP4_7_4) ++#define GPSR2_9 F_(VI0_DATA5, IP4_3_0) ++#define GPSR2_8 F_(VI0_DATA4, IP3_31_28) ++#define GPSR2_7 F_(VI0_DATA3, IP3_27_24) ++#define GPSR2_6 F_(VI0_DATA2, IP3_23_20) ++#define GPSR2_5 F_(VI0_DATA1, IP3_19_16) ++#define GPSR2_4 F_(VI0_DATA0, IP3_15_12) ++#define GPSR2_3 F_(VI0_VSYNC_N, IP3_11_8) ++#define GPSR2_2 F_(VI0_HSYNC_N, IP3_7_4) ++#define GPSR2_1 F_(VI0_CLKENB, IP3_3_0) ++#define GPSR2_0 F_(VI0_CLK, IP2_31_28) ++ ++/* GPSR3 */ ++#define GPSR3_16 F_(VI1_FIELD, IP7_3_0) ++#define GPSR3_15 F_(VI1_DATA11, IP6_31_28) ++#define GPSR3_14 F_(VI1_DATA10, IP6_27_24) ++#define GPSR3_13 F_(VI1_DATA9, IP6_23_20) ++#define GPSR3_12 F_(VI1_DATA8, IP6_19_16) ++#define GPSR3_11 F_(VI1_DATA7, IP6_15_12) ++#define GPSR3_10 F_(VI1_DATA6, IP6_11_8) ++#define GPSR3_9 F_(VI1_DATA5, IP6_7_4) ++#define GPSR3_8 F_(VI1_DATA4, IP6_3_0) ++#define GPSR3_7 F_(VI1_DATA3, IP5_31_28) ++#define GPSR3_6 F_(VI1_DATA2, IP5_27_24) ++#define GPSR3_5 F_(VI1_DATA1, IP5_23_20) ++#define GPSR3_4 F_(VI1_DATA0, IP5_19_16) ++#define GPSR3_3 F_(VI1_VSYNC_N, IP5_15_12) ++#define GPSR3_2 F_(VI1_HSYNC_N, IP5_11_8) ++#define GPSR3_1 F_(VI1_CLKENB, IP5_7_4) ++#define GPSR3_0 F_(VI1_CLK, IP5_3_0) ++ ++/* GPSR4 */ ++#define GPSR4_24 FM(GETHER_LINK_A) ++#define GPSR4_23 FM(GETHER_PHY_INT_A) ++#define GPSR4_22 FM(GETHER_MAGIC) ++#define GPSR4_21 FM(GETHER_MDC_A) ++#define GPSR4_20 FM(GETHER_MDIO_A) ++#define GPSR4_19 FM(GETHER_TXCREFCLK_MEGA) ++#define GPSR4_18 FM(GETHER_TXCREFCLK) ++#define GPSR4_17 FM(GETHER_TD3) ++#define GPSR4_16 FM(GETHER_TD2) ++#define GPSR4_15 FM(GETHER_TD1) ++#define GPSR4_14 FM(GETHER_TD0) ++#define GPSR4_13 FM(GETHER_TXC) ++#define GPSR4_12 FM(GETHER_TX_CTL) ++#define GPSR4_11 FM(GETHER_RD3) ++#define GPSR4_10 FM(GETHER_RD2) ++#define GPSR4_9 FM(GETHER_RD1) ++#define GPSR4_8 FM(GETHER_RD0) ++#define GPSR4_7 FM(GETHER_RXC) ++#define GPSR4_6 FM(GETHER_RX_CTL) ++#define GPSR4_5 F_(SDA2, IP7_27_24) ++#define GPSR4_4 F_(SCL2, IP7_23_20) ++#define GPSR4_3 F_(SDA1, IP7_19_16) ++#define GPSR4_2 F_(SCL1, IP7_15_12) ++#define GPSR4_1 F_(SDA0, IP7_11_8) ++#define GPSR4_0 F_(SCL0, IP7_7_4) ++ ++/* GPSR5 */ ++#define GPSR5_14 FM(RPC_INT_N) ++#define GPSR5_13 FM(RPC_WP_N) ++#define GPSR5_12 FM(RPC_RESET_N) ++#define GPSR5_11 FM(QSPI1_SSL) ++#define GPSR5_10 FM(QSPI1_IO3) ++#define GPSR5_9 FM(QSPI1_IO2) ++#define GPSR5_8 FM(QSPI1_MISO_IO1) ++#define GPSR5_7 FM(QSPI1_MOSI_IO0) ++#define GPSR5_6 FM(QSPI1_SPCLK) ++#define GPSR5_5 FM(QSPI0_SSL) ++#define GPSR5_4 FM(QSPI0_IO3) ++#define GPSR5_3 FM(QSPI0_IO2) ++#define GPSR5_2 FM(QSPI0_MISO_IO1) ++#define GPSR5_1 FM(QSPI0_MOSI_IO0) ++#define GPSR5_0 FM(QSPI0_SPCLK) ++ ++ ++/* IPSRx */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 */ /* 8 */ /* 9 */ /* A */ /* B */ /* C */ /* D */ /* E */ /* F */ ++#define IP0_3_0 FM(DU_DR2) FM(SCK4) FM(GETHER_RMII_CRS_DV) FM(A0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP0_7_4 FM(DU_DR3) FM(RX4) FM(GETHER_RMII_RX_ER) FM(A1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP0_11_8 FM(DU_DR4) FM(TX4) FM(GETHER_RMII_RXD0) FM(A2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP0_15_12 FM(DU_DR5) FM(CTS4_N) FM(GETHER_RMII_RXD1) FM(A3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP0_19_16 FM(DU_DR6) FM(RTS4_N_TANS) FM(GETHER_RMII_TXD_EN) FM(A4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP0_23_20 FM(DU_DR7) F_(0, 0) FM(GETHER_RMII_TXD0) FM(A5) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP0_27_24 FM(DU_DG2) F_(0, 0) FM(GETHER_RMII_TXD1) FM(A6) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP0_31_28 FM(DU_DG3) FM(CPG_CPCKOUT) FM(GETHER_RMII_REFCLK) FM(A7) FM(PWMFSW0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP1_3_0 FM(DU_DG4) FM(SCL5) F_(0, 0) FM(A8) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP1_7_4 FM(DU_DG5) FM(SDA5) FM(GETHER_MDC_B) FM(A9) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP1_11_8 FM(DU_DG6) FM(SCIF_CLK_A) FM(GETHER_MDIO_B) FM(A10) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP1_15_12 FM(DU_DG7) FM(HRX0_A) F_(0, 0) FM(A11) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP1_19_16 FM(DU_DB2) FM(HSCK0_A) F_(0, 0) FM(A12) FM(IRQ1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP1_23_20 FM(DU_DB3) FM(HRTS0_N_A) F_(0, 0) FM(A13) FM(IRQ2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP1_27_24 FM(DU_DB4) FM(HCTS0_N_A) F_(0, 0) FM(A14) FM(IRQ3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP1_31_28 FM(DU_DB5) FM(HTX0_A) FM(PWM0_A) FM(A15) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP2_3_0 FM(DU_DB6) FM(MSIOF3_RXD) F_(0, 0) FM(A16) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP2_7_4 FM(DU_DB7) FM(MSIOF3_TXD) F_(0, 0) FM(A17) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP2_11_8 FM(DU_DOTCLKOUT) FM(MSIOF3_SS1) FM(GETHER_LINK_B) FM(A18) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP2_15_12 FM(DU_EXHSYNC_DU_HSYNC) FM(MSIOF3_SS2) FM(GETHER_PHY_INT_B) FM(A19) FM(FXR_TXENA_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP2_19_16 FM(DU_EXVSYNC_DU_VSYNC) FM(MSIOF3_SCK) F_(0, 0) F_(0, 0) FM(FXR_TXENB_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP2_23_20 FM(DU_EXODDF_DU_ODDF_DISP_CDE) FM(MSIOF3_SYNC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP2_27_24 FM(IRQ0) FM(CC5_OSCOUT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP2_31_28 FM(VI0_CLK) FM(MSIOF2_SCK) FM(SCK3) F_(0, 0) FM(HSCK3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP3_3_0 FM(VI0_CLKENB) FM(MSIOF2_RXD) FM(RX3) FM(RD_WR_N) FM(HCTS3_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP3_7_4 FM(VI0_HSYNC_N) FM(MSIOF2_TXD) FM(TX3) F_(0, 0) FM(HRTS3_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP3_11_8 FM(VI0_VSYNC_N) FM(MSIOF2_SYNC) FM(CTS3_N) F_(0, 0) FM(HTX3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP3_15_12 FM(VI0_DATA0) FM(MSIOF2_SS1) FM(RTS3_N_TANS) F_(0, 0) FM(HRX3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP3_19_16 FM(VI0_DATA1) FM(MSIOF2_SS2) FM(SCK1) F_(0, 0) FM(SPEEDIN_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP3_23_20 FM(VI0_DATA2) FM(AVB_AVTP_PPS) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP3_27_24 FM(VI0_DATA3) FM(HSCK1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP3_31_28 FM(VI0_DATA4) FM(HRTS1_N) FM(RX1_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP4_3_0 FM(VI0_DATA5) FM(HCTS1_N) FM(TX1_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP4_7_4 FM(VI0_DATA6) FM(HTX1) FM(CTS1_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP4_11_8 FM(VI0_DATA7) FM(HRX1) FM(RTS1_N_TANS) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP4_15_12 FM(VI0_DATA8) FM(HSCK2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP4_19_16 FM(VI0_DATA9) FM(HCTS2_N) FM(PWM1_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP4_23_20 FM(VI0_DATA10) FM(HRTS2_N) FM(PWM2_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP4_27_24 FM(VI0_DATA11) FM(HTX2) FM(PWM3_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP4_31_28 FM(VI0_FIELD) FM(HRX2) FM(PWM4_A) FM(CS1_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP5_3_0 FM(VI1_CLK) FM(MSIOF1_RXD) F_(0, 0) FM(CS0_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP5_7_4 FM(VI1_CLKENB) FM(MSIOF1_TXD) F_(0, 0) FM(D0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP5_11_8 FM(VI1_HSYNC_N) FM(MSIOF1_SCK) F_(0, 0) FM(D1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP5_15_12 FM(VI1_VSYNC_N) FM(MSIOF1_SYNC) F_(0, 0) FM(D2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP5_19_16 FM(VI1_DATA0) FM(MSIOF1_SS1) F_(0, 0) FM(D3) FM(MMC_WP) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP5_23_20 FM(VI1_DATA1) FM(MSIOF1_SS2) F_(0, 0) FM(D4) FM(MMC_CD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP5_27_24 FM(VI1_DATA2) FM(CANFD0_TX_B) F_(0, 0) FM(D5) FM(MMC_DS) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP5_31_28 FM(VI1_DATA3) FM(CANFD0_RX_B) F_(0, 0) FM(D6) FM(MMC_CMD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP6_3_0 FM(VI1_DATA4) FM(CANFD_CLK_B) F_(0, 0) FM(D7) FM(MMC_D0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP6_7_4 FM(VI1_DATA5) F_(0, 0) F_(0, 0) FM(D8) FM(MMC_D1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP6_11_8 FM(VI1_DATA6) F_(0, 0) F_(0, 0) FM(D9) FM(MMC_D2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP6_15_12 FM(VI1_DATA7) F_(0, 0) F_(0, 0) FM(D10) FM(MMC_D3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP6_19_16 FM(VI1_DATA8) F_(0, 0) F_(0, 0) FM(D11) FM(MMC_CLK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP6_23_20 FM(VI1_DATA9) FM(TCLK1_A) F_(0, 0) FM(D12) FM(MMC_D4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP6_27_24 FM(VI1_DATA10) FM(TCLK2_A) F_(0, 0) FM(D13) FM(MMC_D5) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP6_31_28 FM(VI1_DATA11) FM(SCL4) F_(0, 0) FM(D14) FM(MMC_D6) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP7_3_0 FM(VI1_FIELD) FM(SDA4) F_(0, 0) FM(D15) FM(MMC_D7) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP7_7_4 FM(SCL0) F_(0, 0) F_(0, 0) FM(CLKOUT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP7_11_8 FM(SDA0) F_(0, 0) F_(0, 0) FM(BS_N) FM(SCK0) FM(HSCK0_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP7_15_12 FM(SCL1) F_(0, 0) FM(TPU0TO2) FM(RD_N) FM(CTS0_N) FM(HCTS0_N_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP7_19_16 FM(SDA1) F_(0, 0) FM(TPU0TO3) FM(WE0_N) FM(RTS0_N_TANS) FM(HRTS0_N_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP7_23_20 FM(SCL2) F_(0, 0) F_(0, 0) FM(WE1_N) FM(RX0) FM(HRX0_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP7_27_24 FM(SDA2) F_(0, 0) F_(0, 0) FM(EX_WAIT0) FM(TX0) FM(HTX0_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP7_31_28 FM(AVB_AVTP_MATCH) FM(TPU0TO0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP8_3_0 FM(AVB_AVTP_CAPTURE) FM(TPU0TO1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP8_7_4 FM(CANFD0_TX_A) FM(FXR_TXDA) FM(PWM0_B) FM(DU_DISP) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP8_11_8 FM(CANFD0_RX_A) FM(RXDA_EXTFXR) FM(PWM1_B) FM(DU_CDE) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP8_15_12 FM(CANFD1_TX) FM(FXR_TXDB) FM(PWM2_B) FM(TCLK1_B) FM(TX1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP8_19_16 FM(CANFD1_RX) FM(RXDB_EXTFXR) FM(PWM3_B) FM(TCLK2_B) FM(RX1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP8_23_20 FM(CANFD_CLK_A) FM(CLK_EXTFXR) FM(PWM4_B) FM(SPEEDIN_B) FM(SCIF_CLK_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP8_27_24 FM(DIGRF_CLKIN) FM(DIGRF_CLKEN_IN) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP8_31_28 FM(DIGRF_CLKOUT) FM(DIGRF_CLKEN_OUT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP9_3_0 FM(IRQ4) F_(0, 0) F_(0, 0) FM(VI0_DATA12) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP9_7_4 FM(IRQ5) F_(0, 0) F_(0, 0) FM(VI0_DATA13) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP9_11_8 FM(MSIOF0_RXD) FM(DU_DR0) F_(0, 0) FM(VI0_DATA14) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP9_15_12 FM(MSIOF0_TXD) FM(DU_DR1) F_(0, 0) FM(VI0_DATA15) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP9_19_16 FM(MSIOF0_SCK) FM(DU_DG0) F_(0, 0) FM(VI0_DATA16) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP9_23_20 FM(MSIOF0_SYNC) FM(DU_DG1) F_(0, 0) FM(VI0_DATA17) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP9_27_24 FM(MSIOF0_SS1) FM(DU_DB0) FM(TCLK3) FM(VI0_DATA18) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP9_31_28 FM(MSIOF0_SS2) FM(DU_DB1) FM(TCLK4) FM(VI0_DATA19) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP10_3_0 FM(SCL3) F_(0, 0) F_(0, 0) FM(VI0_DATA20) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP10_7_4 FM(SDA3) F_(0, 0) F_(0, 0) FM(VI0_DATA21) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP10_11_8 FM(FSO_CFE_0_N) F_(0, 0) F_(0, 0) FM(VI0_DATA22) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP10_15_12 FM(FSO_CFE_1_N) F_(0, 0) F_(0, 0) FM(VI0_DATA23) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP10_19_16 FM(FSO_TOE_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP10_23_20 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP10_27_24 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP10_31_28 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++ ++#define PINMUX_GPSR \ ++\ ++ GPSR2_29 \ ++ GPSR2_28 \ ++ GPSR1_27 GPSR2_27 \ ++ GPSR1_26 GPSR2_26 \ ++ GPSR1_25 GPSR2_25 \ ++ GPSR1_24 GPSR2_24 GPSR4_24 \ ++ GPSR1_23 GPSR2_23 GPSR4_23 \ ++ GPSR1_22 GPSR2_22 GPSR4_22 \ ++GPSR0_21 GPSR1_21 GPSR2_21 GPSR4_21 \ ++GPSR0_20 GPSR1_20 GPSR2_20 GPSR4_20 \ ++GPSR0_19 GPSR1_19 GPSR2_19 GPSR4_19 \ ++GPSR0_18 GPSR1_18 GPSR2_18 GPSR4_18 \ ++GPSR0_17 GPSR1_17 GPSR2_17 GPSR4_17 \ ++GPSR0_16 GPSR1_16 GPSR2_16 GPSR3_16 GPSR4_16 \ ++GPSR0_15 GPSR1_15 GPSR2_15 GPSR3_15 GPSR4_15 \ ++GPSR0_14 GPSR1_14 GPSR2_14 GPSR3_14 GPSR4_14 GPSR5_14 \ ++GPSR0_13 GPSR1_13 GPSR2_13 GPSR3_13 GPSR4_13 GPSR5_13 \ ++GPSR0_12 GPSR1_12 GPSR2_12 GPSR3_12 GPSR4_12 GPSR5_12 \ ++GPSR0_11 GPSR1_11 GPSR2_11 GPSR3_11 GPSR4_11 GPSR5_11 \ ++GPSR0_10 GPSR1_10 GPSR2_10 GPSR3_10 GPSR4_10 GPSR5_10 \ ++GPSR0_9 GPSR1_9 GPSR2_9 GPSR3_9 GPSR4_9 GPSR5_9 \ ++GPSR0_8 GPSR1_8 GPSR2_8 GPSR3_8 GPSR4_8 GPSR5_8 \ ++GPSR0_7 GPSR1_7 GPSR2_7 GPSR3_7 GPSR4_7 GPSR5_7 \ ++GPSR0_6 GPSR1_6 GPSR2_6 GPSR3_6 GPSR4_6 GPSR5_6 \ ++GPSR0_5 GPSR1_5 GPSR2_5 GPSR3_5 GPSR4_5 GPSR5_5 \ ++GPSR0_4 GPSR1_4 GPSR2_4 GPSR3_4 GPSR4_4 GPSR5_4 \ ++GPSR0_3 GPSR1_3 GPSR2_3 GPSR3_3 GPSR4_3 GPSR5_3 \ ++GPSR0_2 GPSR1_2 GPSR2_2 GPSR3_2 GPSR4_2 GPSR5_2 \ ++GPSR0_1 GPSR1_1 GPSR2_1 GPSR3_1 GPSR4_1 GPSR5_1 \ ++GPSR0_0 GPSR1_0 GPSR2_0 GPSR3_0 GPSR4_0 GPSR5_0 ++ ++#define PINMUX_IPSR \ ++\ ++FM(IP0_3_0) IP0_3_0 FM(IP1_3_0) IP1_3_0 FM(IP2_3_0) IP2_3_0 FM(IP3_3_0) IP3_3_0 \ ++FM(IP0_7_4) IP0_7_4 FM(IP1_7_4) IP1_7_4 FM(IP2_7_4) IP2_7_4 FM(IP3_7_4) IP3_7_4 \ ++FM(IP0_11_8) IP0_11_8 FM(IP1_11_8) IP1_11_8 FM(IP2_11_8) IP2_11_8 FM(IP3_11_8) IP3_11_8 \ ++FM(IP0_15_12) IP0_15_12 FM(IP1_15_12) IP1_15_12 FM(IP2_15_12) IP2_15_12 FM(IP3_15_12) IP3_15_12 \ ++FM(IP0_19_16) IP0_19_16 FM(IP1_19_16) IP1_19_16 FM(IP2_19_16) IP2_19_16 FM(IP3_19_16) IP3_19_16 \ ++FM(IP0_23_20) IP0_23_20 FM(IP1_23_20) IP1_23_20 FM(IP2_23_20) IP2_23_20 FM(IP3_23_20) IP3_23_20 \ ++FM(IP0_27_24) IP0_27_24 FM(IP1_27_24) IP1_27_24 FM(IP2_27_24) IP2_27_24 FM(IP3_27_24) IP3_27_24 \ ++FM(IP0_31_28) IP0_31_28 FM(IP1_31_28) IP1_31_28 FM(IP2_31_28) IP2_31_28 FM(IP3_31_28) IP3_31_28 \ ++\ ++FM(IP4_3_0) IP4_3_0 FM(IP5_3_0) IP5_3_0 FM(IP6_3_0) IP6_3_0 FM(IP7_3_0) IP7_3_0 \ ++FM(IP4_7_4) IP4_7_4 FM(IP5_7_4) IP5_7_4 FM(IP6_7_4) IP6_7_4 FM(IP7_7_4) IP7_7_4 \ ++FM(IP4_11_8) IP4_11_8 FM(IP5_11_8) IP5_11_8 FM(IP6_11_8) IP6_11_8 FM(IP7_11_8) IP7_11_8 \ ++FM(IP4_15_12) IP4_15_12 FM(IP5_15_12) IP5_15_12 FM(IP6_15_12) IP6_15_12 FM(IP7_15_12) IP7_15_12 \ ++FM(IP4_19_16) IP4_19_16 FM(IP5_19_16) IP5_19_16 FM(IP6_19_16) IP6_19_16 FM(IP7_19_16) IP7_19_16 \ ++FM(IP4_23_20) IP4_23_20 FM(IP5_23_20) IP5_23_20 FM(IP6_23_20) IP6_23_20 FM(IP7_23_20) IP7_23_20 \ ++FM(IP4_27_24) IP4_27_24 FM(IP5_27_24) IP5_27_24 FM(IP6_27_24) IP6_27_24 FM(IP7_27_24) IP7_27_24 \ ++FM(IP4_31_28) IP4_31_28 FM(IP5_31_28) IP5_31_28 FM(IP6_31_28) IP6_31_28 FM(IP7_31_28) IP7_31_28 \ ++\ ++FM(IP8_3_0) IP8_3_0 FM(IP9_3_0) IP9_3_0 FM(IP10_3_0) IP10_3_0 \ ++FM(IP8_7_4) IP8_7_4 FM(IP9_7_4) IP9_7_4 FM(IP10_7_4) IP10_7_4 \ ++FM(IP8_11_8) IP8_11_8 FM(IP9_11_8) IP9_11_8 FM(IP10_11_8) IP10_11_8 \ ++FM(IP8_15_12) IP8_15_12 FM(IP9_15_12) IP9_15_12 FM(IP10_15_12) IP10_15_12 \ ++FM(IP8_19_16) IP8_19_16 FM(IP9_19_16) IP9_19_16 FM(IP10_19_16) IP10_19_16 \ ++FM(IP8_23_20) IP8_23_20 FM(IP9_23_20) IP9_23_20 FM(IP10_23_20) IP10_23_20 \ ++FM(IP8_27_24) IP8_27_24 FM(IP9_27_24) IP9_27_24 FM(IP10_27_24) IP10_27_24 \ ++FM(IP8_31_28) IP8_31_28 FM(IP9_31_28) IP9_31_28 FM(IP10_31_28) IP10_31_28 ++ ++/* ++ Set Value = H'0 Set Value = H'1 ++Register Function Pin Function Pin ++------------------------------------------------------------ ++sel_canfd0 CANFD0_TX_A CANFD0_TX_A CANFD0_TX_B VI1_DATA2 ++ CANFD0_RX_A CANFD0_RX_A CANFD0_TX_B VI1_DATA3 ++ CANFD_CLK_A CANFD_CLK_A CANFD_CLK_B VI1_DATA4 ++sel_gether GETHER_MDC_A GETHER_MDC_A GETHER_MDC_B DU_DG5 ++ GETHER_MDIO_A GETHER_MDIO_A GETHER_MDIO_B DU_DG6 ++ GETHER_LINK_A GETHER_LINK_A GETHER_LINK_B DU_DOTCLKOUT ++ GETHER_PHY_INT_A GETHER_PHY_INT_A GETHER_PHY_INT_B DU_EXHSYNC_DU_HSYNC ++sel_hscif0 HSCK0_A DU_DB2 HSCK0_B SDA0 ++ HCTS0_N_A DU_DB4 HCTS_N_B SCL1 ++ HRTS0_N_A DU_DB3 HRTS_N_B SDA1 ++ HRX0_A DU_DG7 HRX0_B SCL2 ++ HTX0_A DU_DB5 HTX0_B SDA2 ++ SCIF_CLK_A DU_DG6 SCIF_CLK_B CANFD_CLK_A ++sel_pwm0 PWM0_A DU_DB5 PWM0_B CANFD0_TX_A ++sel_pwm1 PWM1_A VI0_DATA9 PWM1_B CANFD0_RX_A ++sel_pwm2 PWM2_A VI0_DATA10 PWM2_B CANFD1_TX ++sel_pwm3 PWM3_A VI0_DATA11 PWM3_B CANFD1_RX ++sel_pwm4 PWM4_A VI0_FIELD PWM4_B CANFD_CLK_A ++sel_rsp SPEEDIN_A VI0_DATA1 SPEEDIN_B CANFD_CLK_A ++sel_scif1 RX1_A VI0_DATA4 RX1_B CANFD1_RX ++ TX1_A VI0_DATA5 TX1_B CANFD1_TX ++sel_tmu TCLK1_A VI1_DATA9 TCLK1_B CANFD1_TX ++ TCLK2_A VI1_DATA10 TCLK2_B CANFD1_RX ++*/ ++/* MOD_SEL0 */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 */ ++#define MOD_SEL0_11 FM(SEL_CANFD0_0) FM(SEL_CANFD0_1) ++#define MOD_SEL0_10 FM(SEL_GETHER_0) FM(SEL_GETHER_1) ++#define MOD_SEL0_9 FM(SEL_HSCIF0_0) FM(SEL_HSCIF0_1) ++#define MOD_SEL0_8 FM(SEL_PWM0_0) FM(SEL_PWM0_1) ++#define MOD_SEL0_7 FM(SEL_PWM1_0) FM(SEL_PWM1_1) ++#define MOD_SEL0_6 FM(SEL_PWM2_0) FM(SEL_PWM2_1) ++#define MOD_SEL0_5 FM(SEL_PWM3_0) FM(SEL_PWM3_1) ++#define MOD_SEL0_4 FM(SEL_PWM4_0) FM(SEL_PWM4_1) ++#define MOD_SEL0_2 FM(SEL_RSP_0) FM(SEL_RSP_1) ++#define MOD_SEL0_1 FM(SEL_SCIF1_0) FM(SEL_SCIF1_1) ++#define MOD_SEL0_0 FM(SEL_TMU1_0) FM(SEL_TMU1_1) ++ ++#define PINMUX_MOD_SELS \ ++\ ++MOD_SEL0_11 \ ++MOD_SEL0_10 \ ++MOD_SEL0_9 \ ++MOD_SEL0_8 \ ++MOD_SEL0_7 \ ++MOD_SEL0_6 \ ++MOD_SEL0_5 \ ++MOD_SEL0_4 \ ++MOD_SEL0_2 \ ++MOD_SEL0_1 \ ++MOD_SEL0_0 ++ ++enum { ++ PINMUX_RESERVED = 0, ++ ++ PINMUX_DATA_BEGIN, ++ GP_ALL(DATA), ++ PINMUX_DATA_END, ++ ++#define F_(x, y) ++#define FM(x) FN_##x, ++ PINMUX_FUNCTION_BEGIN, ++ GP_ALL(FN), ++ PINMUX_GPSR ++ PINMUX_IPSR ++ PINMUX_MOD_SELS ++ PINMUX_FUNCTION_END, ++#undef F_ ++#undef FM ++ ++#define F_(x, y) ++#define FM(x) x##_MARK, ++ PINMUX_MARK_BEGIN, ++ PINMUX_GPSR ++ PINMUX_IPSR ++ PINMUX_MOD_SELS ++ PINMUX_MARK_END, ++#undef F_ ++#undef FM ++}; ++ ++static const u16 pinmux_data[] = { ++ PINMUX_DATA_GP_ALL(), ++ ++ PINMUX_SINGLE(AVB_RX_CTL), ++ PINMUX_SINGLE(AVB_RXC), ++ PINMUX_SINGLE(AVB_RD0), ++ PINMUX_SINGLE(AVB_RD1), ++ PINMUX_SINGLE(AVB_RD2), ++ PINMUX_SINGLE(AVB_RD3), ++ PINMUX_SINGLE(AVB_TX_CTL), ++ PINMUX_SINGLE(AVB_TXC), ++ PINMUX_SINGLE(AVB_TD0), ++ PINMUX_SINGLE(AVB_TD1), ++ PINMUX_SINGLE(AVB_TD2), ++ PINMUX_SINGLE(AVB_TD3), ++ PINMUX_SINGLE(AVB_TXCREFCLK), ++ PINMUX_SINGLE(AVB_MDIO), ++ PINMUX_SINGLE(AVB_MDC), ++ PINMUX_SINGLE(AVB_MAGIC), ++ PINMUX_SINGLE(AVB_PHY_INT), ++ PINMUX_SINGLE(AVB_LINK), ++ ++ PINMUX_SINGLE(GETHER_RX_CTL), ++ PINMUX_SINGLE(GETHER_RXC), ++ PINMUX_SINGLE(GETHER_RD0), ++ PINMUX_SINGLE(GETHER_RD1), ++ PINMUX_SINGLE(GETHER_RD2), ++ PINMUX_SINGLE(GETHER_RD3), ++ PINMUX_SINGLE(GETHER_TX_CTL), ++ PINMUX_SINGLE(GETHER_TXC), ++ PINMUX_SINGLE(GETHER_TD0), ++ PINMUX_SINGLE(GETHER_TD1), ++ PINMUX_SINGLE(GETHER_TD2), ++ PINMUX_SINGLE(GETHER_TD3), ++ PINMUX_SINGLE(GETHER_TXCREFCLK), ++ PINMUX_SINGLE(GETHER_TXCREFCLK_MEGA), ++ PINMUX_SINGLE(GETHER_MDIO_A), ++ PINMUX_SINGLE(GETHER_MDC_A), ++ PINMUX_SINGLE(GETHER_MAGIC), ++ PINMUX_SINGLE(GETHER_PHY_INT_A), ++ PINMUX_SINGLE(GETHER_LINK_A), ++ ++ PINMUX_SINGLE(QSPI0_SPCLK), ++ PINMUX_SINGLE(QSPI0_MOSI_IO0), ++ PINMUX_SINGLE(QSPI0_MISO_IO1), ++ PINMUX_SINGLE(QSPI0_IO2), ++ PINMUX_SINGLE(QSPI0_IO3), ++ PINMUX_SINGLE(QSPI0_SSL), ++ PINMUX_SINGLE(QSPI1_SPCLK), ++ PINMUX_SINGLE(QSPI1_MOSI_IO0), ++ PINMUX_SINGLE(QSPI1_MISO_IO1), ++ PINMUX_SINGLE(QSPI1_IO2), ++ PINMUX_SINGLE(QSPI1_IO3), ++ PINMUX_SINGLE(QSPI1_SSL), ++ PINMUX_SINGLE(RPC_RESET_N), ++ PINMUX_SINGLE(RPC_WP_N), ++ PINMUX_SINGLE(RPC_INT_N), ++ ++ /* IPSR0 */ ++ PINMUX_IPSR_GPSR(IP0_3_0, DU_DR2), ++ PINMUX_IPSR_GPSR(IP0_3_0, SCK4), ++ PINMUX_IPSR_GPSR(IP0_3_0, GETHER_RMII_CRS_DV), ++ PINMUX_IPSR_GPSR(IP0_3_0, A0), ++ ++ PINMUX_IPSR_GPSR(IP0_7_4, DU_DR3), ++ PINMUX_IPSR_GPSR(IP0_7_4, RX4), ++ PINMUX_IPSR_GPSR(IP0_7_4, GETHER_RMII_RX_ER), ++ PINMUX_IPSR_GPSR(IP0_7_4, A1), ++ ++ PINMUX_IPSR_GPSR(IP0_11_8, DU_DR4), ++ PINMUX_IPSR_GPSR(IP0_11_8, TX4), ++ PINMUX_IPSR_GPSR(IP0_11_8, GETHER_RMII_RXD0), ++ PINMUX_IPSR_GPSR(IP0_11_8, A2), ++ ++ PINMUX_IPSR_GPSR(IP0_15_12, DU_DR5), ++ PINMUX_IPSR_GPSR(IP0_15_12, CTS4_N), ++ PINMUX_IPSR_GPSR(IP0_15_12, GETHER_RMII_RXD1), ++ PINMUX_IPSR_GPSR(IP0_15_12, A3), ++ ++ PINMUX_IPSR_GPSR(IP0_19_16, DU_DR6), ++ PINMUX_IPSR_GPSR(IP0_19_16, RTS4_N_TANS), ++ PINMUX_IPSR_GPSR(IP0_19_16, GETHER_RMII_TXD_EN), ++ PINMUX_IPSR_GPSR(IP0_19_16, A4), ++ ++ PINMUX_IPSR_GPSR(IP0_23_20, DU_DR7), ++ PINMUX_IPSR_GPSR(IP0_23_20, GETHER_RMII_TXD0), ++ PINMUX_IPSR_GPSR(IP0_23_20, A5), ++ ++ PINMUX_IPSR_GPSR(IP0_27_24, DU_DG2), ++ PINMUX_IPSR_GPSR(IP0_27_24, GETHER_RMII_TXD1), ++ PINMUX_IPSR_GPSR(IP0_27_24, A6), ++ ++ PINMUX_IPSR_GPSR(IP0_31_28, DU_DG3), ++ PINMUX_IPSR_GPSR(IP0_31_28, CPG_CPCKOUT), ++ PINMUX_IPSR_GPSR(IP0_31_28, GETHER_RMII_REFCLK), ++ PINMUX_IPSR_GPSR(IP0_31_28, A7), ++ PINMUX_IPSR_GPSR(IP0_31_28, PWMFSW0), ++ ++ /* IPSR1 */ ++ PINMUX_IPSR_GPSR(IP1_3_0, DU_DG4), ++ PINMUX_IPSR_GPSR(IP1_3_0, SCL5), ++ PINMUX_IPSR_GPSR(IP1_3_0, A8), ++ ++ PINMUX_IPSR_GPSR(IP1_7_4, DU_DG5), ++ PINMUX_IPSR_GPSR(IP1_7_4, SDA5), ++ PINMUX_IPSR_MSEL(IP1_7_4, GETHER_MDC_B, SEL_GETHER_1), ++ PINMUX_IPSR_GPSR(IP1_7_4, A9), ++ ++ PINMUX_IPSR_GPSR(IP1_11_8, DU_DG6), ++ PINMUX_IPSR_MSEL(IP1_11_8, SCIF_CLK_A, SEL_HSCIF0_0), ++ PINMUX_IPSR_MSEL(IP1_11_8, GETHER_MDIO_B, SEL_GETHER_1), ++ PINMUX_IPSR_GPSR(IP1_11_8, A10), ++ ++ PINMUX_IPSR_GPSR(IP1_15_12, DU_DG7), ++ PINMUX_IPSR_MSEL(IP1_15_12, HRX0_A, SEL_HSCIF0_0), ++ PINMUX_IPSR_GPSR(IP1_15_12, A11), ++ ++ PINMUX_IPSR_GPSR(IP1_19_16, DU_DB2), ++ PINMUX_IPSR_MSEL(IP1_19_16, HSCK0_A, SEL_HSCIF0_0), ++ PINMUX_IPSR_GPSR(IP1_19_16, A12), ++ PINMUX_IPSR_GPSR(IP1_19_16, IRQ1), ++ ++ PINMUX_IPSR_GPSR(IP1_23_20, DU_DB3), ++ PINMUX_IPSR_MSEL(IP1_23_20, HRTS0_N_A, SEL_HSCIF0_0), ++ PINMUX_IPSR_GPSR(IP1_23_20, A13), ++ PINMUX_IPSR_GPSR(IP1_23_20, IRQ2), ++ ++ PINMUX_IPSR_GPSR(IP1_27_24, DU_DB4), ++ PINMUX_IPSR_MSEL(IP1_27_24, HCTS0_N_A, SEL_HSCIF0_0), ++ PINMUX_IPSR_GPSR(IP1_27_24, A14), ++ PINMUX_IPSR_GPSR(IP1_27_24, IRQ3), ++ ++ PINMUX_IPSR_GPSR(IP1_31_28, DU_DB5), ++ PINMUX_IPSR_MSEL(IP1_31_28, HTX0_A, SEL_HSCIF0_0), ++ PINMUX_IPSR_MSEL(IP1_31_28, PWM0_A, SEL_PWM0_0), ++ PINMUX_IPSR_GPSR(IP1_31_28, A15), ++ ++ /* IPSR2 */ ++ PINMUX_IPSR_GPSR(IP2_3_0, DU_DB6), ++ PINMUX_IPSR_GPSR(IP2_3_0, MSIOF3_RXD), ++ PINMUX_IPSR_GPSR(IP2_3_0, A16), ++ ++ PINMUX_IPSR_GPSR(IP2_7_4, DU_DB7), ++ PINMUX_IPSR_GPSR(IP2_7_4, MSIOF3_TXD), ++ PINMUX_IPSR_GPSR(IP2_7_4, A17), ++ ++ PINMUX_IPSR_GPSR(IP2_11_8, DU_DOTCLKOUT), ++ PINMUX_IPSR_GPSR(IP2_11_8, MSIOF3_SS1), ++ PINMUX_IPSR_MSEL(IP2_11_8, GETHER_LINK_B, SEL_GETHER_1), ++ PINMUX_IPSR_GPSR(IP2_11_8, A18), ++ ++ PINMUX_IPSR_GPSR(IP2_15_12, DU_EXHSYNC_DU_HSYNC), ++ PINMUX_IPSR_GPSR(IP2_15_12, MSIOF3_SS2), ++ PINMUX_IPSR_MSEL(IP2_15_12, GETHER_PHY_INT_B, SEL_GETHER_1), ++ PINMUX_IPSR_GPSR(IP2_15_12, A19), ++ PINMUX_IPSR_GPSR(IP2_15_12, FXR_TXENA_N), ++ ++ PINMUX_IPSR_GPSR(IP2_19_16, DU_EXVSYNC_DU_VSYNC), ++ PINMUX_IPSR_GPSR(IP2_19_16, MSIOF3_SCK), ++ PINMUX_IPSR_GPSR(IP2_19_16, FXR_TXENB_N), ++ ++ PINMUX_IPSR_GPSR(IP2_23_20, DU_EXODDF_DU_ODDF_DISP_CDE), ++ PINMUX_IPSR_GPSR(IP2_23_20, MSIOF3_SYNC), ++ ++ PINMUX_IPSR_GPSR(IP2_27_24, IRQ0), ++ PINMUX_IPSR_GPSR(IP2_27_24, CC5_OSCOUT), ++ ++ PINMUX_IPSR_GPSR(IP2_31_28, VI0_CLK), ++ PINMUX_IPSR_GPSR(IP2_31_28, MSIOF2_SCK), ++ PINMUX_IPSR_GPSR(IP2_31_28, SCK3), ++ PINMUX_IPSR_GPSR(IP2_31_28, HSCK3), ++ ++ /* IPSR3 */ ++ PINMUX_IPSR_GPSR(IP3_3_0, VI0_CLKENB), ++ PINMUX_IPSR_GPSR(IP3_3_0, MSIOF2_RXD), ++ PINMUX_IPSR_GPSR(IP3_3_0, RX3), ++ PINMUX_IPSR_GPSR(IP3_3_0, RD_WR_N), ++ PINMUX_IPSR_GPSR(IP3_3_0, HCTS3_N), ++ ++ PINMUX_IPSR_GPSR(IP3_7_4, VI0_HSYNC_N), ++ PINMUX_IPSR_GPSR(IP3_7_4, MSIOF2_TXD), ++ PINMUX_IPSR_GPSR(IP3_7_4, TX3), ++ PINMUX_IPSR_GPSR(IP3_7_4, HRTS3_N), ++ ++ PINMUX_IPSR_GPSR(IP3_11_8, VI0_VSYNC_N), ++ PINMUX_IPSR_GPSR(IP3_11_8, MSIOF2_SYNC), ++ PINMUX_IPSR_GPSR(IP3_11_8, CTS3_N), ++ PINMUX_IPSR_GPSR(IP3_11_8, HTX3), ++ ++ PINMUX_IPSR_GPSR(IP3_15_12, VI0_DATA0), ++ PINMUX_IPSR_GPSR(IP3_15_12, MSIOF2_SS1), ++ PINMUX_IPSR_GPSR(IP3_15_12, RTS3_N_TANS), ++ PINMUX_IPSR_GPSR(IP3_15_12, HRX3), ++ ++ PINMUX_IPSR_GPSR(IP3_19_16, VI0_DATA1), ++ PINMUX_IPSR_GPSR(IP3_19_16, MSIOF2_SS2), ++ PINMUX_IPSR_GPSR(IP3_19_16, SCK1), ++ PINMUX_IPSR_MSEL(IP3_19_16, SPEEDIN_A, SEL_RSP_0), ++ ++ PINMUX_IPSR_GPSR(IP3_23_20, VI0_DATA2), ++ PINMUX_IPSR_GPSR(IP3_23_20, AVB_AVTP_PPS), ++ ++ PINMUX_IPSR_GPSR(IP3_27_24, VI0_DATA3), ++ PINMUX_IPSR_GPSR(IP3_27_24, HSCK1), ++ ++ PINMUX_IPSR_GPSR(IP3_31_28, VI0_DATA4), ++ PINMUX_IPSR_GPSR(IP3_31_28, HRTS1_N), ++ PINMUX_IPSR_MSEL(IP3_31_28, RX1_A, SEL_SCIF1_0), ++ ++ /* IPSR4 */ ++ PINMUX_IPSR_GPSR(IP4_3_0, VI0_DATA5), ++ PINMUX_IPSR_GPSR(IP4_3_0, HCTS1_N), ++ PINMUX_IPSR_MSEL(IP4_3_0, TX1_A, SEL_SCIF1_0), ++ ++ PINMUX_IPSR_GPSR(IP4_7_4, VI0_DATA6), ++ PINMUX_IPSR_GPSR(IP4_7_4, HTX1), ++ PINMUX_IPSR_GPSR(IP4_7_4, CTS1_N), ++ ++ PINMUX_IPSR_GPSR(IP4_11_8, VI0_DATA7), ++ PINMUX_IPSR_GPSR(IP4_11_8, HRX1), ++ PINMUX_IPSR_GPSR(IP4_11_8, RTS1_N_TANS), ++ ++ PINMUX_IPSR_GPSR(IP4_15_12, VI0_DATA8), ++ PINMUX_IPSR_GPSR(IP4_15_12, HSCK2), ++ ++ PINMUX_IPSR_GPSR(IP4_19_16, VI0_DATA9), ++ PINMUX_IPSR_GPSR(IP4_19_16, HCTS2_N), ++ PINMUX_IPSR_MSEL(IP4_19_16, PWM1_A, SEL_PWM1_0), ++ ++ PINMUX_IPSR_GPSR(IP4_23_20, VI0_DATA10), ++ PINMUX_IPSR_GPSR(IP4_23_20, HRTS2_N), ++ PINMUX_IPSR_MSEL(IP4_23_20, PWM2_A, SEL_PWM2_0), ++ ++ PINMUX_IPSR_GPSR(IP4_27_24, VI0_DATA11), ++ PINMUX_IPSR_GPSR(IP4_27_24, HTX2), ++ PINMUX_IPSR_MSEL(IP4_27_24, PWM3_A, SEL_PWM3_0), ++ ++ PINMUX_IPSR_GPSR(IP4_31_28, VI0_FIELD), ++ PINMUX_IPSR_GPSR(IP4_31_28, HRX2), ++ PINMUX_IPSR_MSEL(IP4_31_28, PWM4_A, SEL_PWM4_0), ++ PINMUX_IPSR_GPSR(IP4_31_28, CS1_N), ++ ++ /* IPSR5 */ ++ PINMUX_IPSR_GPSR(IP5_3_0, VI1_CLK), ++ PINMUX_IPSR_GPSR(IP5_3_0, MSIOF1_RXD), ++ PINMUX_IPSR_GPSR(IP5_3_0, CS0_N), ++ ++ PINMUX_IPSR_GPSR(IP5_7_4, VI1_CLKENB), ++ PINMUX_IPSR_GPSR(IP5_7_4, MSIOF1_TXD), ++ PINMUX_IPSR_GPSR(IP5_7_4, D0), ++ ++ PINMUX_IPSR_GPSR(IP5_11_8, VI1_HSYNC_N), ++ PINMUX_IPSR_GPSR(IP5_11_8, MSIOF1_SCK), ++ PINMUX_IPSR_GPSR(IP5_11_8, D1), ++ ++ PINMUX_IPSR_GPSR(IP5_15_12, VI1_VSYNC_N), ++ PINMUX_IPSR_GPSR(IP5_15_12, MSIOF1_SYNC), ++ PINMUX_IPSR_GPSR(IP5_15_12, D2), ++ ++ PINMUX_IPSR_GPSR(IP5_19_16, VI1_DATA0), ++ PINMUX_IPSR_GPSR(IP5_19_16, MSIOF1_SS1), ++ PINMUX_IPSR_GPSR(IP5_19_16, D3), ++ PINMUX_IPSR_GPSR(IP5_19_16, MMC_WP), ++ ++ PINMUX_IPSR_GPSR(IP5_23_20, VI1_DATA1), ++ PINMUX_IPSR_GPSR(IP5_23_20, MSIOF1_SS2), ++ PINMUX_IPSR_GPSR(IP5_23_20, D4), ++ PINMUX_IPSR_GPSR(IP5_23_20, MMC_CD), ++ ++ PINMUX_IPSR_GPSR(IP5_27_24, VI1_DATA2), ++ PINMUX_IPSR_MSEL(IP5_27_24, CANFD0_TX_B, SEL_CANFD0_1), ++ PINMUX_IPSR_GPSR(IP5_27_24, D5), ++ PINMUX_IPSR_GPSR(IP5_27_24, MMC_DS), ++ ++ PINMUX_IPSR_GPSR(IP5_31_28, VI1_DATA3), ++ PINMUX_IPSR_MSEL(IP5_31_28, CANFD0_RX_B, SEL_CANFD0_1), ++ PINMUX_IPSR_GPSR(IP5_31_28, D6), ++ PINMUX_IPSR_GPSR(IP5_31_28, MMC_CMD), ++ ++ /* IPSR6 */ ++ PINMUX_IPSR_GPSR(IP6_3_0, VI1_DATA4), ++ PINMUX_IPSR_MSEL(IP6_3_0, CANFD_CLK_B, SEL_CANFD0_1), ++ PINMUX_IPSR_GPSR(IP6_3_0, D7), ++ PINMUX_IPSR_GPSR(IP6_3_0, MMC_D0), ++ ++ PINMUX_IPSR_GPSR(IP6_7_4, VI1_DATA5), ++ PINMUX_IPSR_GPSR(IP6_7_4, D8), ++ PINMUX_IPSR_GPSR(IP6_7_4, MMC_D1), ++ ++ PINMUX_IPSR_GPSR(IP6_11_8, VI1_DATA6), ++ PINMUX_IPSR_GPSR(IP6_11_8, D9), ++ PINMUX_IPSR_GPSR(IP6_11_8, MMC_D2), ++ ++ PINMUX_IPSR_GPSR(IP6_15_12, VI1_DATA7), ++ PINMUX_IPSR_GPSR(IP6_15_12, D10), ++ PINMUX_IPSR_GPSR(IP6_15_12, MMC_D3), ++ ++ PINMUX_IPSR_GPSR(IP6_19_16, VI1_DATA8), ++ PINMUX_IPSR_GPSR(IP6_19_16, D11), ++ PINMUX_IPSR_GPSR(IP6_19_16, MMC_CLK), ++ ++ PINMUX_IPSR_GPSR(IP6_23_20, VI1_DATA9), ++ PINMUX_IPSR_MSEL(IP6_23_20, TCLK1_A, SEL_TMU1_0), ++ PINMUX_IPSR_GPSR(IP6_23_20, D12), ++ PINMUX_IPSR_GPSR(IP6_23_20, MMC_D4), ++ ++ PINMUX_IPSR_GPSR(IP6_27_24, VI1_DATA10), ++ PINMUX_IPSR_MSEL(IP6_27_24, TCLK2_A, SEL_TMU1_0), ++ PINMUX_IPSR_GPSR(IP6_27_24, D13), ++ PINMUX_IPSR_GPSR(IP6_27_24, MMC_D5), ++ ++ PINMUX_IPSR_GPSR(IP6_31_28, VI1_DATA11), ++ PINMUX_IPSR_GPSR(IP6_31_28, SCL4), ++ PINMUX_IPSR_GPSR(IP6_31_28, D14), ++ PINMUX_IPSR_GPSR(IP6_31_28, MMC_D6), ++ ++ /* IPSR7 */ ++ PINMUX_IPSR_GPSR(IP7_3_0, VI1_FIELD), ++ PINMUX_IPSR_GPSR(IP7_3_0, SDA4), ++ PINMUX_IPSR_GPSR(IP7_3_0, D15), ++ PINMUX_IPSR_GPSR(IP7_3_0, MMC_D7), ++ ++ PINMUX_IPSR_GPSR(IP7_7_4, SCL0), ++ PINMUX_IPSR_GPSR(IP7_7_4, CLKOUT), ++ ++ PINMUX_IPSR_GPSR(IP7_11_8, SDA0), ++ PINMUX_IPSR_GPSR(IP7_11_8, BS_N), ++ PINMUX_IPSR_GPSR(IP7_11_8, SCK0), ++ PINMUX_IPSR_MSEL(IP7_11_8, HSCK0_B, SEL_HSCIF0_1), ++ ++ PINMUX_IPSR_GPSR(IP7_15_12, SCL1), ++ PINMUX_IPSR_GPSR(IP7_15_12, TPU0TO2), ++ PINMUX_IPSR_GPSR(IP7_15_12, RD_N), ++ PINMUX_IPSR_GPSR(IP7_15_12, CTS0_N), ++ PINMUX_IPSR_GPSR(IP7_15_12, HCTS0_N_B), ++ ++ PINMUX_IPSR_GPSR(IP7_19_16, SDA1), ++ PINMUX_IPSR_GPSR(IP7_19_16, TPU0TO3), ++ PINMUX_IPSR_GPSR(IP7_19_16, WE0_N), ++ PINMUX_IPSR_GPSR(IP7_19_16, RTS0_N_TANS), ++ PINMUX_IPSR_GPSR(IP7_19_16, HRTS0_N_B), ++ ++ PINMUX_IPSR_GPSR(IP7_23_20, SCL2), ++ PINMUX_IPSR_GPSR(IP7_23_20, WE1_N), ++ PINMUX_IPSR_GPSR(IP7_23_20, RX0), ++ PINMUX_IPSR_MSEL(IP7_23_20, HRX0_B, SEL_HSCIF0_1), ++ ++ PINMUX_IPSR_GPSR(IP7_27_24, SDA2), ++ PINMUX_IPSR_GPSR(IP7_27_24, EX_WAIT0), ++ PINMUX_IPSR_GPSR(IP7_27_24, TX0), ++ PINMUX_IPSR_MSEL(IP7_27_24, HTX0_B, SEL_HSCIF0_1), ++ ++ PINMUX_IPSR_GPSR(IP7_31_28, AVB_AVTP_MATCH), ++ PINMUX_IPSR_GPSR(IP7_31_28, TPU0TO0), ++ ++ /* IPSR8 */ ++ PINMUX_IPSR_GPSR(IP8_3_0, AVB_AVTP_CAPTURE), ++ PINMUX_IPSR_GPSR(IP8_3_0, TPU0TO1), ++ ++ PINMUX_IPSR_MSEL(IP8_7_4, CANFD0_TX_A, SEL_CANFD0_0), ++ PINMUX_IPSR_GPSR(IP8_7_4, FXR_TXDA), ++ PINMUX_IPSR_MSEL(IP8_7_4, PWM0_B, SEL_PWM0_1), ++ PINMUX_IPSR_GPSR(IP8_7_4, DU_DISP), ++ ++ PINMUX_IPSR_MSEL(IP8_11_8, CANFD0_RX_A, SEL_CANFD0_0), ++ PINMUX_IPSR_GPSR(IP8_11_8, RXDA_EXTFXR), ++ PINMUX_IPSR_MSEL(IP8_11_8, PWM1_B, SEL_PWM1_1), ++ PINMUX_IPSR_GPSR(IP8_11_8, DU_CDE), ++ ++ PINMUX_IPSR_GPSR(IP8_15_12, CANFD1_TX), ++ PINMUX_IPSR_GPSR(IP8_15_12, FXR_TXDB), ++ PINMUX_IPSR_MSEL(IP8_15_12, PWM2_B, SEL_PWM2_1), ++ PINMUX_IPSR_MSEL(IP8_15_12, TCLK1_B, SEL_TMU1_1), ++ PINMUX_IPSR_MSEL(IP8_15_12, TX1_B, SEL_SCIF1_1), ++ ++ PINMUX_IPSR_GPSR(IP8_19_16, CANFD1_RX), ++ PINMUX_IPSR_GPSR(IP8_19_16, RXDB_EXTFXR), ++ PINMUX_IPSR_MSEL(IP8_19_16, PWM3_B, SEL_PWM3_1), ++ PINMUX_IPSR_MSEL(IP8_19_16, TCLK2_B, SEL_TMU1_1), ++ PINMUX_IPSR_MSEL(IP8_19_16, RX1_B, SEL_SCIF1_1), ++ ++ PINMUX_IPSR_MSEL(IP8_23_20, CANFD_CLK_A, SEL_CANFD0_0), ++ PINMUX_IPSR_GPSR(IP8_23_20, CLK_EXTFXR), ++ PINMUX_IPSR_MSEL(IP8_23_20, PWM4_B, SEL_PWM4_1), ++ PINMUX_IPSR_MSEL(IP8_23_20, SPEEDIN_B, SEL_RSP_1), ++ PINMUX_IPSR_MSEL(IP8_23_20, SCIF_CLK_B, SEL_HSCIF0_1), ++ ++ PINMUX_IPSR_GPSR(IP8_27_24, DIGRF_CLKIN), ++ PINMUX_IPSR_GPSR(IP8_27_24, DIGRF_CLKEN_IN), ++ ++ PINMUX_IPSR_GPSR(IP8_31_28, DIGRF_CLKOUT), ++ PINMUX_IPSR_GPSR(IP8_31_28, DIGRF_CLKEN_OUT), ++ ++ /* IPSR9 */ ++ PINMUX_IPSR_GPSR(IP9_3_0, IRQ4), ++ PINMUX_IPSR_GPSR(IP9_3_0, VI0_DATA12), ++ ++ PINMUX_IPSR_GPSR(IP9_7_4, IRQ5), ++ PINMUX_IPSR_GPSR(IP9_7_4, VI0_DATA13), ++ ++ PINMUX_IPSR_GPSR(IP9_11_8, MSIOF0_RXD), ++ PINMUX_IPSR_GPSR(IP9_11_8, DU_DR0), ++ PINMUX_IPSR_GPSR(IP9_11_8, VI0_DATA14), ++ ++ PINMUX_IPSR_GPSR(IP9_15_12, MSIOF0_TXD), ++ PINMUX_IPSR_GPSR(IP9_15_12, DU_DR1), ++ PINMUX_IPSR_GPSR(IP9_15_12, VI0_DATA15), ++ ++ PINMUX_IPSR_GPSR(IP9_19_16, MSIOF0_SCK), ++ PINMUX_IPSR_GPSR(IP9_19_16, DU_DG0), ++ PINMUX_IPSR_GPSR(IP9_19_16, VI0_DATA16), ++ ++ PINMUX_IPSR_GPSR(IP9_23_20, MSIOF0_SYNC), ++ PINMUX_IPSR_GPSR(IP9_23_20, DU_DG1), ++ PINMUX_IPSR_GPSR(IP9_23_20, VI0_DATA17), ++ ++ PINMUX_IPSR_GPSR(IP9_27_24, MSIOF0_SS1), ++ PINMUX_IPSR_GPSR(IP9_27_24, DU_DB0), ++ PINMUX_IPSR_GPSR(IP9_27_24, TCLK3), ++ PINMUX_IPSR_GPSR(IP9_27_24, VI0_DATA18), ++ ++ PINMUX_IPSR_GPSR(IP9_31_28, MSIOF0_SS2), ++ PINMUX_IPSR_GPSR(IP9_31_28, DU_DB1), ++ PINMUX_IPSR_GPSR(IP9_31_28, TCLK4), ++ PINMUX_IPSR_GPSR(IP9_31_28, VI0_DATA19), ++ ++ /* IPSR10 */ ++ PINMUX_IPSR_GPSR(IP10_3_0, SCL3), ++ PINMUX_IPSR_GPSR(IP10_3_0, VI0_DATA20), ++ ++ PINMUX_IPSR_GPSR(IP10_7_4, SDA3), ++ PINMUX_IPSR_GPSR(IP10_7_4, VI0_DATA21), ++ ++ PINMUX_IPSR_GPSR(IP10_11_8, FSO_CFE_0_N), ++ PINMUX_IPSR_GPSR(IP10_11_8, VI0_DATA22), ++ ++ PINMUX_IPSR_GPSR(IP10_15_12, FSO_CFE_1_N), ++ PINMUX_IPSR_GPSR(IP10_15_12, VI0_DATA23), ++ ++ PINMUX_IPSR_GPSR(IP10_19_16, FSO_TOE_N), ++}; ++ ++static const struct sh_pfc_pin pinmux_pins[] = { ++ PINMUX_GPIO_GP_ALL(), ++}; ++ ++/* - EtherAVB --------------------------------------------------------------- */ ++static const unsigned int avb_rx_ctrl_pins[] = { ++ /* AVB_RX_CTL */ ++ RCAR_GP_PIN(1, 1), ++}; ++static const unsigned int avb_rx_ctrl_mux[] = { ++ AVB_RX_CTL_MARK, ++}; ++static const unsigned int avb_rxc_pins[] = { ++ /* AVB_RXC */ ++ RCAR_GP_PIN(1, 2), ++}; ++static const unsigned int avb_rxc_mux[] = { ++ AVB_RXC_MARK, ++}; ++static const unsigned int avb_rd0_pins[] = { ++ /* AVB_RD[0] */ ++ RCAR_GP_PIN(1, 3), ++}; ++static const unsigned int avb_rd0_mux[] = { ++ AVB_RD0_MARK, ++}; ++static const unsigned int avb_rd1_pins[] = { ++ /* AVB_RD[1] */ ++ RCAR_GP_PIN(1, 4), ++}; ++static const unsigned int avb_rd1_mux[] = { ++ AVB_RD1_MARK, ++}; ++static const unsigned int avb_rd2_pins[] = { ++ /* AVB_RD[2] */ ++ RCAR_GP_PIN(1, 5), ++}; ++static const unsigned int avb_rd2_mux[] = { ++ AVB_RD2_MARK, ++}; ++static const unsigned int avb_rd3_pins[] = { ++ /* AVB_RD[3] */ ++ RCAR_GP_PIN(1, 6), ++}; ++static const unsigned int avb_rd3_mux[] = { ++ AVB_RD3_MARK, ++}; ++static const unsigned int avb_rd4_pins[] = { ++ /* AVB_RD[3:0] */ ++ RCAR_GP_PIN(1, 3), RCAR_GP_PIN(1, 4), ++ RCAR_GP_PIN(1, 5), RCAR_GP_PIN(1, 6), ++}; ++static const unsigned int avb_rd4_mux[] = { ++ AVB_RD0_MARK, AVB_RD1_MARK, ++ AVB_RD2_MARK, AVB_RD3_MARK, ++}; ++static const unsigned int avb_tx_ctrl_pins[] = { ++ /* AVB_TX_CTL */ ++ RCAR_GP_PIN(1, 7), ++}; ++static const unsigned int avb_tx_ctrl_mux[] = { ++ AVB_TX_CTL_MARK, ++}; ++static const unsigned int avb_txc_pins[] = { ++ /* AVB_TXC */ ++ RCAR_GP_PIN(1, 8), ++}; ++static const unsigned int avb_txc_mux[] = { ++ AVB_TXC_MARK, ++}; ++static const unsigned int avb_td0_pins[] = { ++ /* AVB_TD[0] */ ++ RCAR_GP_PIN(1, 9), ++}; ++static const unsigned int avb_td0_mux[] = { ++ AVB_TD0_MARK, ++}; ++static const unsigned int avb_td1_pins[] = { ++ /* AVB_TD[1] */ ++ RCAR_GP_PIN(1, 10), ++}; ++static const unsigned int avb_td1_mux[] = { ++ AVB_TD1_MARK, ++}; ++static const unsigned int avb_td2_pins[] = { ++ /* AVB_TD[2] */ ++ RCAR_GP_PIN(1, 11), ++}; ++static const unsigned int avb_td2_mux[] = { ++ AVB_TD2_MARK, ++}; ++static const unsigned int avb_td3_pins[] = { ++ /* AVB_TD[3] */ ++ RCAR_GP_PIN(1, 12), ++}; ++static const unsigned int avb_td3_mux[] = { ++ AVB_TD3_MARK, ++}; ++static const unsigned int avb_td4_pins[] = { ++ /* AVB_TD[3:0] */ ++ RCAR_GP_PIN(1, 9), RCAR_GP_PIN(1, 10), ++ RCAR_GP_PIN(1, 11), RCAR_GP_PIN(1, 12), ++}; ++static const unsigned int avb_td4_mux[] = { ++ AVB_TD0_MARK, AVB_TD1_MARK, ++ AVB_TD2_MARK, AVB_TD3_MARK, ++}; ++static const unsigned int avb_txcrefclk_pins[] = { ++ /* AVB_TXCREFCLK */ ++ RCAR_GP_PIN(1, 13), ++}; ++static const unsigned int avb_txcrefclk_mux[] = { ++ AVB_TXCREFCLK_MARK, ++}; ++static const unsigned int avb_mdio_pins[] = { ++ /* AVB_MDIO */ ++ RCAR_GP_PIN(1, 14), ++}; ++static const unsigned int avb_mdio_mux[] = { ++ AVB_MDIO_MARK, ++}; ++static const unsigned int avb_mdc_pins[] = { ++ /* AVB_MDC */ ++ RCAR_GP_PIN(1, 15), ++}; ++static const unsigned int avb_mdc_mux[] = { ++ AVB_MDC_MARK, ++}; ++static const unsigned int avb_magic_pins[] = { ++ /* AVB_MAGIC */ ++ RCAR_GP_PIN(1, 16), ++}; ++static const unsigned int avb_magic_mux[] = { ++ AVB_MAGIC_MARK, ++}; ++static const unsigned int avb_phy_int_pins[] = { ++ /* AVB_PHY_INT */ ++ RCAR_GP_PIN(1, 17), ++}; ++static const unsigned int avb_phy_int_mux[] = { ++ AVB_PHY_INT_MARK, ++}; ++static const unsigned int avb_link_pins[] = { ++ /* AVB_LINK */ ++ RCAR_GP_PIN(1, 18), ++}; ++static const unsigned int avb_link_mux[] = { ++ AVB_LINK_MARK, ++}; ++static const unsigned int avb_avtp_match_pins[] = { ++ /* AVB_AVTP_MATCH */ ++ RCAR_GP_PIN(1, 19), ++}; ++static const unsigned int avb_avtp_match_mux[] = { ++ AVB_AVTP_MATCH_MARK, ++}; ++static const unsigned int avb_avtp_capture_pins[] = { ++ /* AVB_AVTP_CAPTURE */ ++ RCAR_GP_PIN(1, 20), ++}; ++static const unsigned int avb_avtp_capture_mux[] = { ++ AVB_AVTP_CAPTURE_MARK, ++}; ++static const unsigned int avb_avtp_pps_pins[] = { ++ /* AVB_AVTP_PPS */ ++ RCAR_GP_PIN(2, 6), ++}; ++static const unsigned int avb_avtp_pps_mux[] = { ++ AVB_AVTP_PPS_MARK, ++}; ++ ++/* - GETHER ----------------------------------------------------------------- */ ++static const unsigned int gether_rx_ctrl_pins[] = { ++ /* GETHER_RX_CTL */ ++ RCAR_GP_PIN(4, 6), ++}; ++static const unsigned int gether_rx_ctrl_mux[] = { ++ GETHER_RX_CTL_MARK, ++}; ++static const unsigned int gether_rxc_pins[] = { ++ /* GETHER_RXC */ ++ RCAR_GP_PIN(4, 7), ++}; ++static const unsigned int gether_rxc_mux[] = { ++ GETHER_RXC_MARK, ++}; ++static const unsigned int gether_rd0_pins[] = { ++ /* GETHER_RD[0] */ ++ RCAR_GP_PIN(4, 8), ++}; ++static const unsigned int gether_rd0_mux[] = { ++ GETHER_RD0_MARK, ++}; ++static const unsigned int gether_rd1_pins[] = { ++ /* GETHER_RD[1] */ ++ RCAR_GP_PIN(4, 9), ++}; ++static const unsigned int gether_rd1_mux[] = { ++ GETHER_RD1_MARK, ++}; ++static const unsigned int gether_rd2_pins[] = { ++ /* GETHER_RD[2] */ ++ RCAR_GP_PIN(4, 10), ++}; ++static const unsigned int gether_rd2_mux[] = { ++ GETHER_RD2_MARK, ++}; ++static const unsigned int gether_rd3_pins[] = { ++ /* GETHER_RD[3] */ ++ RCAR_GP_PIN(4, 11), ++}; ++static const unsigned int gether_rd3_mux[] = { ++ GETHER_RD3_MARK, ++}; ++static const unsigned int gether_rd4_pins[] = { ++ /* GETHER_RD[3:0] */ ++ RCAR_GP_PIN(4, 8), RCAR_GP_PIN(4, 9), ++ RCAR_GP_PIN(4, 10), RCAR_GP_PIN(4, 11), ++}; ++static const unsigned int gether_rd4_mux[] = { ++ GETHER_RD0_MARK, AVB_RD1_MARK, ++ GETHER_RD2_MARK, AVB_RD3_MARK, ++}; ++static const unsigned int gether_tx_ctrl_pins[] = { ++ /* GETHER_TX_CTL */ ++ RCAR_GP_PIN(4, 12), ++}; ++static const unsigned int gether_tx_ctrl_mux[] = { ++ GETHER_TX_CTL_MARK, ++}; ++static const unsigned int gether_txc_pins[] = { ++ /* GETHER_TXC */ ++ RCAR_GP_PIN(4, 13), ++}; ++static const unsigned int gether_txc_mux[] = { ++ GETHER_TXC_MARK, ++}; ++static const unsigned int gether_td0_pins[] = { ++ /* GETHER_TD[0] */ ++ RCAR_GP_PIN(4, 14), ++}; ++static const unsigned int gether_td0_mux[] = { ++ GETHER_TD0_MARK, ++}; ++static const unsigned int gether_td1_pins[] = { ++ /* GETHER_TD[1] */ ++ RCAR_GP_PIN(4, 15), ++}; ++static const unsigned int gether_td1_mux[] = { ++ GETHER_TD1_MARK, ++}; ++static const unsigned int gether_td2_pins[] = { ++ /* GETHER_TD[2] */ ++ RCAR_GP_PIN(4, 16), ++}; ++static const unsigned int gether_td2_mux[] = { ++ GETHER_TD2_MARK, ++}; ++static const unsigned int gether_td3_pins[] = { ++ /* GETHER_TD[3] */ ++ RCAR_GP_PIN(4, 17), ++}; ++static const unsigned int gether_td3_mux[] = { ++ GETHER_TD3_MARK, ++}; ++static const unsigned int gether_td4_pins[] = { ++ /* GETHER_TD[3:0] */ ++ RCAR_GP_PIN(4, 14), RCAR_GP_PIN(4, 15), ++ RCAR_GP_PIN(4, 16), RCAR_GP_PIN(1, 17), ++}; ++static const unsigned int gether_td4_mux[] = { ++ GETHER_TD0_MARK, GETHER_TD1_MARK, ++ GETHER_TD2_MARK, GETHER_TD3_MARK, ++}; ++static const unsigned int gether_txcrefclk_pins[] = { ++ /* GETHER_TXCREFCLK */ ++ RCAR_GP_PIN(4, 18), ++}; ++static const unsigned int gether_txcrefclk_mux[] = { ++ GETHER_TXCREFCLK_MARK, ++}; ++static const unsigned int gether_txcrefclk_mega_pins[] = { ++ /* GETHER_TXCREFCLK_MEGA */ ++ RCAR_GP_PIN(4, 19), ++}; ++static const unsigned int gether_txcrefclk_mega_mux[] = { ++ GETHER_TXCREFCLK_MEGA_MARK, ++}; ++static const unsigned int gether_mdio_a_pins[] = { ++ /* GETHER_MDIO_A */ ++ RCAR_GP_PIN(4, 20), ++}; ++static const unsigned int gether_mdio_a_mux[] = { ++ GETHER_MDIO_A_MARK, ++}; ++static const unsigned int gether_mdc_a_pins[] = { ++ /* GETHER_MDC_A */ ++ RCAR_GP_PIN(4, 21), ++}; ++static const unsigned int gether_mdc_a_mux[] = { ++ GETHER_MDC_A_MARK, ++}; ++static const unsigned int gether_magic_pins[] = { ++ /* GETHER_MAGIC */ ++ RCAR_GP_PIN(4, 22), ++}; ++static const unsigned int gether_magic_mux[] = { ++ GETHER_MAGIC_MARK, ++}; ++static const unsigned int gether_phy_int_a_pins[] = { ++ /* GETHER_PHY_INT_A */ ++ RCAR_GP_PIN(4, 23), ++}; ++static const unsigned int gether_phy_int_a_mux[] = { ++ GETHER_PHY_INT_A_MARK, ++}; ++static const unsigned int gether_link_a_pins[] = { ++ /* GETHER_LINK_A */ ++ RCAR_GP_PIN(4, 24), ++}; ++static const unsigned int gether_link_a_mux[] = { ++ GETHER_LINK_A_MARK, ++}; ++ ++static const unsigned int gether_mdio_b_pins[] = { ++ /* GETHER_MDIO_B */ ++ RCAR_GP_PIN(0, 10), ++}; ++static const unsigned int gether_mdio_b_mux[] = { ++ GETHER_MDIO_B_MARK, ++}; ++static const unsigned int gether_mdc_b_pins[] = { ++ /* GETHER_MDC_B */ ++ RCAR_GP_PIN(0, 9), ++}; ++static const unsigned int gether_mdc_b_mux[] = { ++ GETHER_MDC_B_MARK, ++}; ++static const unsigned int gether_phy_int_b_pins[] = { ++ /* GETHER_PHY_INT_B */ ++ RCAR_GP_PIN(0, 19), ++}; ++static const unsigned int gether_phy_int_b_mux[] = { ++ GETHER_PHY_INT_B_MARK, ++}; ++static const unsigned int gether_link_b_pins[] = { ++ /* GETHER_LINK_B */ ++ RCAR_GP_PIN(0, 18), ++}; ++static const unsigned int gether_link_b_mux[] = { ++ GETHER_LINK_B_MARK, ++}; ++ ++/* OK? */ ++static const unsigned int gether_rmii_pins[] = { ++ /* GETHER_RMII_CRS_DV GETHER_RMII_RX_ER GETHER_RMII_RXD0 GETHER_RMII_RXD1 */ ++ /* GETHER_RMII_TXD_EN GETHER_RMII_TXD0 GETHER_RMII_TXD1 GETHER_RMII_REFCLK */ ++ RCAR_GP_PIN(0, 0), RCAR_GP_PIN(0, 1), ++ RCAR_GP_PIN(0, 2), RCAR_GP_PIN(0, 3), ++ RCAR_GP_PIN(0, 4), RCAR_GP_PIN(0, 5), ++ RCAR_GP_PIN(0, 6), RCAR_GP_PIN(0, 7), ++}; ++static const unsigned int gether_rmii_mux[] = { ++ GETHER_RMII_CRS_DV_MARK, GETHER_RMII_RX_ER_MARK, ++ GETHER_RMII_RXD0_MARK, GETHER_RMII_RXD1_MARK, ++ GETHER_RMII_TXD_EN_MARK, GETHER_RMII_TXD0_MARK, ++ GETHER_RMII_TXD1_MARK, GETHER_RMII_REFCLK_MARK, ++}; ++ ++/* - CANFD0 ----------------------------------------------------------------- */ ++static const unsigned int canfd0_data_a_pins[] = { ++ /* TX, RX */ ++ RCAR_GP_PIN(1, 21), RCAR_GP_PIN(1, 22), ++}; ++static const unsigned int canfd0_data_a_mux[] = { ++ CANFD0_TX_A_MARK, CANFD0_RX_A_MARK, ++}; ++static const unsigned int canfd_clk_a_pins[] = { ++ /* CLK */ ++ RCAR_GP_PIN(1, 25), ++}; ++static const unsigned int canfd_clk_a_mux[] = { ++ CANFD_CLK_A_MARK, ++}; ++static const unsigned int canfd0_data_b_pins[] = { ++ /* TX, RX */ ++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), ++}; ++static const unsigned int canfd0_data_b_mux[] = { ++ CANFD0_TX_B_MARK, CANFD0_RX_B_MARK, ++}; ++static const unsigned int canfd_clk_b_pins[] = { ++ /* CLK */ ++ RCAR_GP_PIN(3, 8), ++}; ++static const unsigned int canfd_clk_b_mux[] = { ++ CANFD_CLK_B_MARK, ++}; ++ ++/* - CANFD1 ----------------------------------------------------------------- */ ++static const unsigned int canfd1_data_pins[] = { ++ /* TX, RX */ ++ RCAR_GP_PIN(1, 23), RCAR_GP_PIN(1, 24), ++}; ++static const unsigned int canfd1_data_mux[] = { ++ CANFD1_TX_MARK, CANFD1_RX_MARK, ++}; ++ ++/* - DU --------------------------------------------------------------------- */ ++/* D_[1:0] ??? */ ++static const unsigned int du_rgb666_pins[] = { ++ /* R[7:0] */ ++ RCAR_GP_PIN(0, 5), RCAR_GP_PIN(0, 4), ++ RCAR_GP_PIN(0, 3), RCAR_GP_PIN(0, 2), ++ RCAR_GP_PIN(0, 1), RCAR_GP_PIN(0, 0), ++ /* G[7:0] */ ++ RCAR_GP_PIN(0, 11), RCAR_GP_PIN(0, 10), ++ RCAR_GP_PIN(0, 9), RCAR_GP_PIN(0, 8), ++ RCAR_GP_PIN(0, 7), RCAR_GP_PIN(0, 6), ++ /* B[7:0] */ ++ RCAR_GP_PIN(0, 17), RCAR_GP_PIN(0, 16), ++ RCAR_GP_PIN(0, 15), RCAR_GP_PIN(0, 14), ++ RCAR_GP_PIN(0, 13), RCAR_GP_PIN(0, 12), ++}; ++static const unsigned int du_rgb666_mux[] = { ++ DU_DR7_MARK, DU_DR6_MARK, ++ DU_DR5_MARK, DU_DR4_MARK, ++ DU_DR3_MARK, DU_DR2_MARK, ++ DU_DG7_MARK, DU_DG6_MARK, ++ DU_DG5_MARK, DU_DG4_MARK, ++ DU_DG3_MARK, DU_DG2_MARK, ++ DU_DB7_MARK, DU_DB6_MARK, ++ DU_DB5_MARK, DU_DB4_MARK, ++ DU_DB3_MARK, DU_DB2_MARK, ++}; ++static const unsigned int du_clk_out_0_pins[] = { ++ /* CLKOUT0 */ ++ RCAR_GP_PIN(0, 18), ++}; ++static const unsigned int du_clk_out_0_mux[] = { ++ DU_DOTCLKOUT_MARK, ++}; ++static const unsigned int du_clk_out_1_pins[] = { ++ /* CLKOUT1 */ ++ RCAR_GP_PIN(0, 18), /* @@ */ ++}; ++static const unsigned int du_clk_out_1_mux[] = { ++ DU_DOTCLKOUT_MARK, ++}; ++static const unsigned int du_sync_pins[] = { ++ /* EXVSYNC/VSYNC, EXHSYNC/HSYNC */ ++ RCAR_GP_PIN(0, 20), RCAR_GP_PIN(0, 19), ++}; ++static const unsigned int du_sync_mux[] = { ++ DU_EXVSYNC_DU_VSYNC_MARK, DU_EXHSYNC_DU_HSYNC_MARK, ++}; ++static const unsigned int du_oddf_pins[] = { ++ /* EXDISP/EXODDF/EXCDE */ ++ RCAR_GP_PIN(0, 21), ++}; ++static const unsigned int du_oddf_mux[] = { ++ DU_EXODDF_DU_ODDF_DISP_CDE_MARK, ++}; ++static const unsigned int du_cde_pins[] = { ++ /* CDE */ ++ RCAR_GP_PIN(1, 22), ++}; ++static const unsigned int du_cde_mux[] = { ++ DU_CDE_MARK, ++}; ++static const unsigned int du_disp_pins[] = { ++ /* DISP */ ++ RCAR_GP_PIN(1, 21), ++}; ++static const unsigned int du_disp_mux[] = { ++ DU_DISP_MARK, ++}; ++ ++/* - HSCIF0 ----------------------------------------------------------------- */ ++static const unsigned int hscif0_data_a_pins[] = { ++ /* HRX0_A, HTX0_A */ ++ RCAR_GP_PIN(0, 11), RCAR_GP_PIN(0, 15), ++}; ++static const unsigned int hscif0_data_a_mux[] = { ++ HRX0_A_MARK, HTX0_A_MARK, ++}; ++static const unsigned int hscif0_clk_a_pins[] = { ++ /* HSCK0_A */ ++ RCAR_GP_PIN(0, 12), ++}; ++static const unsigned int hscif0_clk_a_mux[] = { ++ HSCK0_A_MARK, ++}; ++static const unsigned int hscif0_ctrl_a_pins[] = { ++ /* HRTS0#_A, HCTS0#_A */ ++ RCAR_GP_PIN(0, 13), RCAR_GP_PIN(0, 14), ++}; ++static const unsigned int hscif0_ctrl_a_mux[] = { ++ HRTS0_N_A_MARK, HCTS0_N_A_MARK, ++}; ++ ++static const unsigned int hscif0_data_b_pins[] = { ++ /* HRX0_B, HTX0_B */ ++ RCAR_GP_PIN(0, 11), RCAR_GP_PIN(0, 15), ++}; ++static const unsigned int hscif0_data_b_mux[] = { ++ HRX0_B_MARK, HTX0_B_MARK, ++}; ++static const unsigned int hscif0_clk_b_pins[] = { ++ /* HSCK0_B */ ++ RCAR_GP_PIN(0, 12), ++}; ++static const unsigned int hscif0_clk_b_mux[] = { ++ HSCK0_B_MARK, ++}; ++static const unsigned int hscif0_ctrl_b_pins[] = { ++ /* HRTS0#_B, HCTS0#_B */ ++ RCAR_GP_PIN(0, 13), RCAR_GP_PIN(0, 14), ++}; ++static const unsigned int hscif0_ctrl_b_mux[] = { ++ HRTS0_N_B_MARK, HCTS0_N_B_MARK, ++}; ++ ++/* - HSCIF1 ----------------------------------------------------------------- */ ++static const unsigned int hscif1_data_pins[] = { ++ /* HRX1, HTX1 */ ++ RCAR_GP_PIN(2, 11), RCAR_GP_PIN(2, 10), ++}; ++static const unsigned int hscif1_data_mux[] = { ++ HRX1_MARK, HTX1_MARK, ++}; ++static const unsigned int hscif1_clk_pins[] = { ++ /* HSCK1 */ ++ RCAR_GP_PIN(2, 7), ++}; ++static const unsigned int hscif1_clk_mux[] = { ++ HSCK1_MARK, ++}; ++static const unsigned int hscif1_ctrl_pins[] = { ++ /* HRTS1#, HCTS1# */ ++ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9), ++}; ++static const unsigned int hscif1_ctrl_mux[] = { ++ HRTS1_N_MARK, HCTS1_N_MARK, ++}; ++ ++/* - HSCIF2 ----------------------------------------------------------------- */ ++static const unsigned int hscif2_data_pins[] = { ++ /* HRX2, HTX2 */ ++ RCAR_GP_PIN(2, 16), RCAR_GP_PIN(2, 15), ++}; ++static const unsigned int hscif2_data_mux[] = { ++ HRX2_MARK, HTX2_MARK, ++}; ++static const unsigned int hscif2_clk_pins[] = { ++ /* HSCK2 */ ++ RCAR_GP_PIN(2, 12), ++}; ++static const unsigned int hscif2_clk_mux[] = { ++ HSCK2_MARK, ++}; ++static const unsigned int hscif2_ctrl_pins[] = { ++ /* HRTS2#, HCTS2# */ ++ RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 13), ++}; ++static const unsigned int hscif2_ctrl_mux[] = { ++ HRTS2_N_MARK, HCTS2_N_MARK, ++}; ++ ++/* - HSCIF3 ----------------------------------------------------------------- */ ++static const unsigned int hscif3_data_pins[] = { ++ /* HRX3, HTX3 */ ++ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 3), ++}; ++static const unsigned int hscif3_data_mux[] = { ++ HRX3_MARK, HTX3_MARK, ++}; ++static const unsigned int hscif3_clk_pins[] = { ++ /* HSCK3 */ ++ RCAR_GP_PIN(2, 0), ++}; ++static const unsigned int hscif3_clk_mux[] = { ++ HSCK3_MARK, ++}; ++static const unsigned int hscif3_ctrl_pins[] = { ++ /* HRTS3#, HCTS3# */ ++ RCAR_GP_PIN(2, 2), RCAR_GP_PIN(2, 1), ++}; ++static const unsigned int hscif3_ctrl_mux[] = { ++ HRTS3_N_MARK, HCTS3_N_MARK, ++}; ++ ++/* - SCIF Clock ------------------------------------------------------------- */ ++static const unsigned int scif_clk_a_pins[] = { ++ /* SCIF_CLK */ ++ RCAR_GP_PIN(0, 10), ++}; ++static const unsigned int scif_clk_a_mux[] = { ++ SCIF_CLK_A_MARK, ++}; ++static const unsigned int scif_clk_b_pins[] = { ++ /* SCIF_CLK */ ++ RCAR_GP_PIN(1, 25), ++}; ++static const unsigned int scif_clk_b_mux[] = { ++ SCIF_CLK_B_MARK, ++}; ++ ++/* - I2C -------------------------------------------------------------------- */ ++static const unsigned int i2c0_pins[] = { ++ /* SDA0, SCL0 */ ++ RCAR_GP_PIN(4, 1), RCAR_GP_PIN(4, 0), ++}; ++static const unsigned int i2c0_mux[] = { ++ SDA0_MARK, SCL0_MARK, ++}; ++static const unsigned int i2c1_pins[] = { ++ /* SDA1, SCL1 */ ++ RCAR_GP_PIN(4, 3), RCAR_GP_PIN(4, 2), ++}; ++static const unsigned int i2c1_mux[] = { ++ SDA1_MARK, SCL1_MARK, ++}; ++static const unsigned int i2c2_pins[] = { ++ /* SDA2, SCL2 */ ++ RCAR_GP_PIN(4, 5), RCAR_GP_PIN(4, 4), ++}; ++static const unsigned int i2c2_mux[] = { ++ SDA2_MARK, SCL2_MARK, ++}; ++static const unsigned int i2c3_pins[] = { ++ /* SDA3, SCL3 */ ++ RCAR_GP_PIN(2, 26), RCAR_GP_PIN(2, 25), ++}; ++static const unsigned int i2c3_mux[] = { ++ SDA3_MARK, SCL3_MARK, ++}; ++static const unsigned int i2c4_pins[] = { ++ /* SDA4, SCL4 */ ++ RCAR_GP_PIN(3, 16), RCAR_GP_PIN(3, 15), ++}; ++static const unsigned int i2c4_mux[] = { ++ SDA4_MARK, SCL4_MARK, ++}; ++static const unsigned int i2c5_pins[] = { ++ /* SDA5, SCL5 */ ++ RCAR_GP_PIN(0, 9), RCAR_GP_PIN(0, 8), ++}; ++static const unsigned int i2c5_mux[] = { ++ SDA5_MARK, SCL5_MARK, ++}; ++ ++/* - INTC-EX ---------------------------------------------------------------- */ ++static const unsigned int intc_ex_irq0_pins[] = { ++ /* IRQ0 */ ++ RCAR_GP_PIN(1, 0), ++}; ++static const unsigned int intc_ex_irq0_mux[] = { ++ IRQ0_MARK, ++}; ++static const unsigned int intc_ex_irq1_pins[] = { ++ /* IRQ1 */ ++ RCAR_GP_PIN(0, 12), ++}; ++static const unsigned int intc_ex_irq1_mux[] = { ++ IRQ1_MARK, ++}; ++static const unsigned int intc_ex_irq2_pins[] = { ++ /* IRQ2 */ ++ RCAR_GP_PIN(0, 13), ++}; ++static const unsigned int intc_ex_irq2_mux[] = { ++ IRQ2_MARK, ++}; ++static const unsigned int intc_ex_irq3_pins[] = { ++ /* IRQ3 */ ++ RCAR_GP_PIN(0, 14), ++}; ++static const unsigned int intc_ex_irq3_mux[] = { ++ IRQ3_MARK, ++}; ++static const unsigned int intc_ex_irq4_pins[] = { ++ /* IRQ4 */ ++ RCAR_GP_PIN(2, 17), ++}; ++static const unsigned int intc_ex_irq4_mux[] = { ++ IRQ4_MARK, ++}; ++static const unsigned int intc_ex_irq5_pins[] = { ++ /* IRQ5 */ ++ RCAR_GP_PIN(2, 18), ++}; ++static const unsigned int intc_ex_irq5_mux[] = { ++ IRQ5_MARK, ++}; ++ ++/* - MSIOF0 ----------------------------------------------------------------- */ ++static const unsigned int msiof0_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(2, 21), ++}; ++static const unsigned int msiof0_clk_mux[] = { ++ MSIOF0_SCK_MARK, ++}; ++static const unsigned int msiof0_sync_pins[] = { ++ /* SYNC */ ++ RCAR_GP_PIN(2, 22), ++}; ++static const unsigned int msiof0_sync_mux[] = { ++ MSIOF0_SYNC_MARK, ++}; ++static const unsigned int msiof0_ss1_pins[] = { ++ /* SS1 */ ++ RCAR_GP_PIN(2, 23), ++}; ++static const unsigned int msiof0_ss1_mux[] = { ++ MSIOF0_SS1_MARK, ++}; ++static const unsigned int msiof0_ss2_pins[] = { ++ /* SS2 */ ++ RCAR_GP_PIN(2, 24), ++}; ++static const unsigned int msiof0_ss2_mux[] = { ++ MSIOF0_SS2_MARK, ++}; ++static const unsigned int msiof0_txd_pins[] = { ++ /* TXD */ ++ RCAR_GP_PIN(2, 20), ++}; ++static const unsigned int msiof0_txd_mux[] = { ++ MSIOF0_TXD_MARK, ++}; ++static const unsigned int msiof0_rxd_pins[] = { ++ /* RXD */ ++ RCAR_GP_PIN(2, 19), ++}; ++static const unsigned int msiof0_rxd_mux[] = { ++ MSIOF0_RXD_MARK, ++}; ++ ++/* - MSIOF1 ----------------------------------------------------------------- */ ++static const unsigned int msiof1_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(3, 2), ++}; ++static const unsigned int msiof1_clk_mux[] = { ++ MSIOF1_SCK_MARK, ++}; ++static const unsigned int msiof1_sync_pins[] = { ++ /* SYNC */ ++ RCAR_GP_PIN(3, 3), ++}; ++static const unsigned int msiof1_sync_mux[] = { ++ MSIOF1_SYNC_MARK, ++}; ++static const unsigned int msiof1_ss1_pins[] = { ++ /* SS1 */ ++ RCAR_GP_PIN(3, 4), ++}; ++static const unsigned int msiof1_ss1_mux[] = { ++ MSIOF1_SS1_MARK, ++}; ++static const unsigned int msiof1_ss2_pins[] = { ++ /* SS2 */ ++ RCAR_GP_PIN(3, 5), ++}; ++static const unsigned int msiof1_ss2_mux[] = { ++ MSIOF1_SS2_MARK, ++}; ++static const unsigned int msiof1_txd_pins[] = { ++ /* TXD */ ++ RCAR_GP_PIN(3, 1), ++}; ++static const unsigned int msiof1_txd_mux[] = { ++ MSIOF1_TXD_MARK, ++}; ++static const unsigned int msiof1_rxd_pins[] = { ++ /* RXD */ ++ RCAR_GP_PIN(3, 0), ++}; ++static const unsigned int msiof1_rxd_mux[] = { ++ MSIOF1_RXD_MARK, ++}; ++ ++/* - MSIOF2 ----------------------------------------------------------------- */ ++static const unsigned int msiof2_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(2, 0), ++}; ++static const unsigned int msiof2_clk_mux[] = { ++ MSIOF2_SCK_MARK, ++}; ++static const unsigned int msiof2_sync_pins[] = { ++ /* SYNC */ ++ RCAR_GP_PIN(2, 3), ++}; ++static const unsigned int msiof2_sync_mux[] = { ++ MSIOF2_SYNC_MARK, ++}; ++static const unsigned int msiof2_ss1_pins[] = { ++ /* SS1 */ ++ RCAR_GP_PIN(2, 4), ++}; ++static const unsigned int msiof2_ss1_mux[] = { ++ MSIOF2_SS1_MARK, ++}; ++static const unsigned int msiof2_ss2_pins[] = { ++ /* SS2 */ ++ RCAR_GP_PIN(2, 5), ++}; ++static const unsigned int msiof2_ss2_mux[] = { ++ MSIOF2_SS2_MARK, ++}; ++static const unsigned int msiof2_txd_pins[] = { ++ /* TXD */ ++ RCAR_GP_PIN(2, 2), ++}; ++static const unsigned int msiof2_txd_mux[] = { ++ MSIOF2_TXD_MARK, ++}; ++static const unsigned int msiof2_rxd_pins[] = { ++ /* RXD */ ++ RCAR_GP_PIN(2, 1), ++}; ++static const unsigned int msiof2_rxd_mux[] = { ++ MSIOF2_RXD_MARK, ++}; ++ ++/* - MSIOF3 ----------------------------------------------------------------- */ ++static const unsigned int msiof3_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(0, 20), ++}; ++static const unsigned int msiof3_clk_mux[] = { ++ MSIOF3_SCK_MARK, ++}; ++static const unsigned int msiof3_sync_pins[] = { ++ /* SYNC */ ++ RCAR_GP_PIN(0, 21), ++}; ++static const unsigned int msiof3_sync_mux[] = { ++ MSIOF3_SYNC_MARK, ++}; ++static const unsigned int msiof3_ss1_pins[] = { ++ /* SS1 */ ++ RCAR_GP_PIN(0, 18), ++}; ++static const unsigned int msiof3_ss1_mux[] = { ++ MSIOF3_SS1_MARK, ++}; ++static const unsigned int msiof3_ss2_pins[] = { ++ /* SS2 */ ++ RCAR_GP_PIN(0, 19), ++}; ++static const unsigned int msiof3_ss2_mux[] = { ++ MSIOF3_SS2_MARK, ++}; ++static const unsigned int msiof3_txd_pins[] = { ++ /* TXD */ ++ RCAR_GP_PIN(0, 17), ++}; ++static const unsigned int msiof3_txd_mux[] = { ++ MSIOF3_TXD_MARK, ++}; ++static const unsigned int msiof3_rxd_pins[] = { ++ /* RXD */ ++ RCAR_GP_PIN(0, 16), ++}; ++static const unsigned int msiof3_rxd_mux[] = { ++ MSIOF3_RXD_MARK, ++}; ++ ++/* - TPU ------------------------------------------------------------------- */ ++static const unsigned int tpu_to0_pins[] = { ++ /* TPU0TO0 */ ++ RCAR_GP_PIN(1, 19), ++}; ++static const unsigned int tpu_to0_mux[] = { ++ TPU0TO0_MARK, ++}; ++static const unsigned int tpu_to1_pins[] = { ++ /* TPU0TO1 */ ++ RCAR_GP_PIN(1, 20), ++}; ++static const unsigned int tpu_to1_mux[] = { ++ TPU0TO1_MARK, ++}; ++static const unsigned int tpu_to2_pins[] = { ++ /* TPU0TO2 */ ++ RCAR_GP_PIN(4, 2), ++}; ++static const unsigned int tpu_to2_mux[] = { ++ TPU0TO2_MARK, ++}; ++static const unsigned int tpu_to3_pins[] = { ++ /* TPU0TO3 */ ++ RCAR_GP_PIN(4, 3), ++}; ++static const unsigned int tpu_to3_mux[] = { ++ TPU0TO3_MARK, ++}; ++ ++/* - PWM0 ------------------------------------------------------------------- */ ++static const unsigned int pwm0_a_pins[] = { ++ /* PWM0 */ ++ RCAR_GP_PIN(0, 15), ++}; ++static const unsigned int pwm0_a_mux[] = { ++ PWM0_A_MARK, ++}; ++static const unsigned int pwm0_b_pins[] = { ++ /* PWM0 */ ++ RCAR_GP_PIN(1, 21), ++}; ++static const unsigned int pwm0_b_mux[] = { ++ PWM0_B_MARK, ++}; ++ ++/* - PWM1 ------------------------------------------------------------------- */ ++static const unsigned int pwm1_a_pins[] = { ++ /* PWM1 */ ++ RCAR_GP_PIN(2, 13), ++}; ++static const unsigned int pwm1_a_mux[] = { ++ PWM1_A_MARK, ++}; ++static const unsigned int pwm1_b_pins[] = { ++ /* PWM1 */ ++ RCAR_GP_PIN(1, 22), ++}; ++static const unsigned int pwm1_b_mux[] = { ++ PWM1_B_MARK, ++}; ++ ++/* - PWM2 ------------------------------------------------------------------- */ ++static const unsigned int pwm2_a_pins[] = { ++ /* PWM2 */ ++ RCAR_GP_PIN(2, 14), ++}; ++static const unsigned int pwm2_a_mux[] = { ++ PWM2_A_MARK, ++}; ++static const unsigned int pwm2_b_pins[] = { ++ /* PWM2 */ ++ RCAR_GP_PIN(1, 23), ++}; ++static const unsigned int pwm2_b_mux[] = { ++ PWM2_B_MARK, ++}; ++ ++/* - PWM3 ------------------------------------------------------------------- */ ++static const unsigned int pwm3_a_pins[] = { ++ /* PWM3 */ ++ RCAR_GP_PIN(2, 15), ++}; ++static const unsigned int pwm3_a_mux[] = { ++ PWM3_A_MARK, ++}; ++static const unsigned int pwm3_b_pins[] = { ++ /* PWM3 */ ++ RCAR_GP_PIN(1, 24), ++}; ++static const unsigned int pwm3_b_mux[] = { ++ PWM3_B_MARK, ++}; ++ ++/* - PWM4 ------------------------------------------------------------------- */ ++static const unsigned int pwm4_a_pins[] = { ++ /* PWM4 */ ++ RCAR_GP_PIN(2, 16), ++}; ++static const unsigned int pwm4_a_mux[] = { ++ PWM4_A_MARK, ++}; ++static const unsigned int pwm4_b_pins[] = { ++ /* PWM4 */ ++ RCAR_GP_PIN(1, 25), ++}; ++static const unsigned int pwm4_b_mux[] = { ++ PWM4_B_MARK, ++}; ++ ++/* - SCIF0 ------------------------------------------------------------------ */ ++static const unsigned int scif0_data_pins[] = { ++ /* RX, TX */ ++ RCAR_GP_PIN(4, 4), RCAR_GP_PIN(4, 5), ++}; ++static const unsigned int scif0_data_mux[] = { ++ RX0_MARK, TX0_MARK, ++}; ++static const unsigned int scif0_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(4, 1), ++}; ++static const unsigned int scif0_clk_mux[] = { ++ SCK0_MARK, ++}; ++static const unsigned int scif0_ctrl_pins[] = { ++ /* RTS, CTS */ ++ RCAR_GP_PIN(4, 3), RCAR_GP_PIN(4, 2), ++}; ++static const unsigned int scif0_ctrl_mux[] = { ++ RTS0_N_TANS_MARK, CTS0_N_MARK, ++}; ++ ++/* - SCIF1 ------------------------------------------------------------------ */ ++static const unsigned int scif1_data_a_pins[] = { ++ /* RX, TX */ ++ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9), ++}; ++static const unsigned int scif1_data_a_mux[] = { ++ RX1_A_MARK, TX1_A_MARK, ++}; ++static const unsigned int scif1_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(2, 5), ++}; ++static const unsigned int scif1_clk_mux[] = { ++ SCK1_MARK, ++}; ++static const unsigned int scif1_ctrl_pins[] = { ++ /* RTS, CTS */ ++ RCAR_GP_PIN(2, 11), RCAR_GP_PIN(2, 10), ++}; ++static const unsigned int scif1_ctrl_mux[] = { ++ RTS1_N_TANS_MARK, CTS1_N_MARK, ++}; ++static const unsigned int scif1_data_b_pins[] = { ++ /* RX, TX */ ++ RCAR_GP_PIN(1, 24), RCAR_GP_PIN(1, 23), ++}; ++static const unsigned int scif1_data_b_mux[] = { ++ RX1_B_MARK, TX1_B_MARK, ++}; ++ ++/* - SCIF3 ------------------------------------------------------------------ */ ++static const unsigned int scif3_data_pins[] = { ++ /* RX, TX */ ++ RCAR_GP_PIN(2, 1), RCAR_GP_PIN(2, 2), ++}; ++static const unsigned int scif3_data_mux[] = { ++ RX3_MARK, TX3_MARK, ++}; ++static const unsigned int scif3_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(2, 0), ++}; ++static const unsigned int scif3_clk_mux[] = { ++ SCK3_MARK, ++}; ++static const unsigned int scif3_ctrl_pins[] = { ++ /* RTS, CTS */ ++ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 3), ++}; ++static const unsigned int scif3_ctrl_mux[] = { ++ RTS3_N_TANS_MARK, CTS3_N_MARK, ++}; ++ ++/* - SCIF4 ------------------------------------------------------------------ */ ++static const unsigned int scif4_data_pins[] = { ++ /* RX, TX */ ++ RCAR_GP_PIN(0, 1), RCAR_GP_PIN(0, 2), ++}; ++static const unsigned int scif4_data_mux[] = { ++ RX4_MARK, TX4_MARK, ++}; ++static const unsigned int scif4_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(0, 0), ++}; ++static const unsigned int scif4_clk_mux[] = { ++ SCK4_MARK, ++}; ++static const unsigned int scif4_ctrl_pins[] = { ++ /* RTS, CTS */ ++ RCAR_GP_PIN(0, 4), RCAR_GP_PIN(0, 3), ++}; ++static const unsigned int scif4_ctrl_mux[] = { ++ RTS4_N_TANS_MARK, CTS4_N_MARK, ++}; ++ ++/* - MMC -------------------------------------------------------------------- */ ++static const unsigned int mmc_data1_pins[] = { ++ /* D0 */ ++ RCAR_GP_PIN(3, 8), ++}; ++static const unsigned int mmc_data1_mux[] = { ++ MMC_D0_MARK, ++}; ++static const unsigned int mmc_data4_pins[] = { ++ /* D[0:3] */ ++ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), ++ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11), ++}; ++static const unsigned int mmc_data4_mux[] = { ++ MMC_D0_MARK, MMC_D1_MARK, ++ MMC_D2_MARK, MMC_D3_MARK, ++}; ++static const unsigned int mmc_data8_pins[] = { ++ /* D[0:7] */ ++ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), ++ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11), ++ RCAR_GP_PIN(3, 13), RCAR_GP_PIN(3, 14), ++ RCAR_GP_PIN(3, 15), RCAR_GP_PIN(3, 16), ++}; ++static const unsigned int mmc_data8_mux[] = { ++ MMC_D0_MARK, MMC_D1_MARK, ++ MMC_D2_MARK, MMC_D3_MARK, ++ MMC_D4_MARK, MMC_D5_MARK, ++ MMC_D6_MARK, MMC_D7_MARK, ++}; ++static const unsigned int mmc_ctrl_pins[] = { ++ /* CLK, CMD */ ++ RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 7), ++}; ++static const unsigned int mmc_ctrl_mux[] = { ++ MMC_CLK_MARK, MMC_CMD_MARK, ++}; ++static const unsigned int mmc_cd_pins[] = { ++ /* CD */ ++ RCAR_GP_PIN(3, 5), ++}; ++static const unsigned int mmc_cd_mux[] = { ++ MMC_CD_MARK, ++}; ++static const unsigned int mmc_wp_pins[] = { ++ /* WP */ ++ RCAR_GP_PIN(3, 4), ++}; ++static const unsigned int mmc_wp_mux[] = { ++ MMC_WP_MARK, ++}; ++static const unsigned int mmc_ds_pins[] = { ++ /* DS */ ++ RCAR_GP_PIN(3, 6), ++}; ++static const unsigned int mmc_ds_mux[] = { ++ MMC_DS_MARK, ++}; ++ ++/* - TMU -------------------------------------------------------------------- */ ++static const unsigned int tmu_tclk1_a_pins[] = { ++ /* TCLK1 */ ++ RCAR_GP_PIN(3, 13), ++}; ++static const unsigned int tmu_tclk1_a_mux[] = { ++ TCLK1_A_MARK, ++}; ++static const unsigned int tmu_tclk1_b_pins[] = { ++ /* TCLK1 */ ++ RCAR_GP_PIN(1, 23), ++}; ++static const unsigned int tmu_tclk1_b_mux[] = { ++ TCLK1_B_MARK, ++}; ++static const unsigned int tmu_tclk2_a_pins[] = { ++ /* TCLK2 */ ++ RCAR_GP_PIN(3, 14), ++}; ++static const unsigned int tmu_tclk2_a_mux[] = { ++ TCLK2_A_MARK, ++}; ++static const unsigned int tmu_tclk2_b_pins[] = { ++ /* TCLK2 */ ++ RCAR_GP_PIN(1, 24), ++}; ++static const unsigned int tmu_tclk2_b_mux[] = { ++ TCLK2_B_MARK, ++}; ++ ++/* - VIN0 ------------------------------------------------------------------- */ ++static const unsigned int vin0_data8_pins[] = { ++ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 5), ++ RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 7), ++ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9), ++ RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11), ++}; ++static const unsigned int vin0_data8_mux[] = { ++ VI0_DATA0_MARK, VI0_DATA1_MARK, ++ VI0_DATA2_MARK, VI0_DATA3_MARK, ++ VI0_DATA4_MARK, VI0_DATA5_MARK, ++ VI0_DATA6_MARK, VI0_DATA7_MARK, ++}; ++static const unsigned int vin0_data10_pins[] = { ++ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 5), ++ RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 7), ++ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9), ++ RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11), ++ RCAR_GP_PIN(2, 12), RCAR_GP_PIN(2, 13), ++}; ++static const unsigned int vin0_data10_mux[] = { ++ VI0_DATA0_MARK, VI0_DATA1_MARK, ++ VI0_DATA2_MARK, VI0_DATA3_MARK, ++ VI0_DATA4_MARK, VI0_DATA5_MARK, ++ VI0_DATA6_MARK, VI0_DATA7_MARK, ++ VI0_DATA8_MARK, VI0_DATA9_MARK, ++}; ++static const unsigned int vin0_data12_pins[] = { ++ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 5), ++ RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 7), ++ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9), ++ RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11), ++ RCAR_GP_PIN(2, 12), RCAR_GP_PIN(2, 13), ++ RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 15), ++}; ++static const unsigned int vin0_data12_mux[] = { ++ VI0_DATA0_MARK, VI0_DATA1_MARK, ++ VI0_DATA2_MARK, VI0_DATA3_MARK, ++ VI0_DATA4_MARK, VI0_DATA5_MARK, ++ VI0_DATA6_MARK, VI0_DATA7_MARK, ++ VI0_DATA8_MARK, VI0_DATA9_MARK, ++ VI0_DATA10_MARK, VI0_DATA11_MARK, ++}; ++static const unsigned int vin0_data16_pins[] = { ++ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 5), ++ RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 7), ++ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9), ++ RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11), ++ RCAR_GP_PIN(2, 12), RCAR_GP_PIN(2, 13), ++ RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 15), ++ RCAR_GP_PIN(2, 17), RCAR_GP_PIN(2, 18), ++ RCAR_GP_PIN(2, 19), RCAR_GP_PIN(2, 20), ++}; ++static const unsigned int vin0_data16_mux[] = { ++ VI0_DATA0_MARK, VI0_DATA1_MARK, ++ VI0_DATA2_MARK, VI0_DATA3_MARK, ++ VI0_DATA4_MARK, VI0_DATA5_MARK, ++ VI0_DATA6_MARK, VI0_DATA7_MARK, ++ VI0_DATA8_MARK, VI0_DATA9_MARK, ++ VI0_DATA10_MARK, VI0_DATA11_MARK, ++ VI0_DATA12_MARK, VI0_DATA13_MARK, ++ VI0_DATA14_MARK, VI0_DATA15_MARK, ++}; ++static const unsigned int vin0_data20_pins[] = { ++ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 5), ++ RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 7), ++ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9), ++ RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11), ++ RCAR_GP_PIN(2, 12), RCAR_GP_PIN(2, 13), ++ RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 15), ++ RCAR_GP_PIN(2, 17), RCAR_GP_PIN(2, 18), ++ RCAR_GP_PIN(2, 19), RCAR_GP_PIN(2, 20), ++ RCAR_GP_PIN(2, 21), RCAR_GP_PIN(2, 22), ++ RCAR_GP_PIN(2, 23), RCAR_GP_PIN(2, 24), ++}; ++static const unsigned int vin0_data20_mux[] = { ++ VI0_DATA0_MARK, VI0_DATA1_MARK, ++ VI0_DATA2_MARK, VI0_DATA3_MARK, ++ VI0_DATA4_MARK, VI0_DATA5_MARK, ++ VI0_DATA6_MARK, VI0_DATA7_MARK, ++ VI0_DATA8_MARK, VI0_DATA9_MARK, ++ VI0_DATA10_MARK, VI0_DATA11_MARK, ++ VI0_DATA12_MARK, VI0_DATA13_MARK, ++ VI0_DATA14_MARK, VI0_DATA15_MARK, ++ VI0_DATA16_MARK, VI0_DATA17_MARK, ++ VI0_DATA18_MARK, VI0_DATA19_MARK, ++}; ++static const unsigned int vin0_data24_pins[] = { ++ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 5), ++ RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 7), ++ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9), ++ RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11), ++ RCAR_GP_PIN(2, 12), RCAR_GP_PIN(2, 13), ++ RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 15), ++ RCAR_GP_PIN(2, 17), RCAR_GP_PIN(2, 18), ++ RCAR_GP_PIN(2, 19), RCAR_GP_PIN(2, 20), ++ RCAR_GP_PIN(2, 21), RCAR_GP_PIN(2, 22), ++ RCAR_GP_PIN(2, 23), RCAR_GP_PIN(2, 24), ++ RCAR_GP_PIN(2, 25), RCAR_GP_PIN(2, 26), ++ RCAR_GP_PIN(2, 27), RCAR_GP_PIN(2, 28), ++}; ++static const unsigned int vin0_data24_mux[] = { ++ VI0_DATA0_MARK, VI0_DATA1_MARK, ++ VI0_DATA2_MARK, VI0_DATA3_MARK, ++ VI0_DATA4_MARK, VI0_DATA5_MARK, ++ VI0_DATA6_MARK, VI0_DATA7_MARK, ++ VI0_DATA8_MARK, VI0_DATA9_MARK, ++ VI0_DATA10_MARK, VI0_DATA11_MARK, ++ VI0_DATA12_MARK, VI0_DATA13_MARK, ++ VI0_DATA14_MARK, VI0_DATA15_MARK, ++ VI0_DATA16_MARK, VI0_DATA17_MARK, ++ VI0_DATA18_MARK, VI0_DATA19_MARK, ++ VI0_DATA20_MARK, VI0_DATA21_MARK, ++ VI0_DATA22_MARK, VI0_DATA23_MARK, ++}; ++static const unsigned int vin0_sync_pins[] = { ++ /* VSYNC_N, HSYNC_N */ ++ RCAR_GP_PIN(2, 3), RCAR_GP_PIN(2, 2), ++}; ++static const unsigned int vin0_sync_mux[] = { ++ VI0_HSYNC_N_MARK, VI0_VSYNC_N_MARK, ++}; ++static const unsigned int vin0_field_pins[] = { ++ /* FIELD */ ++ RCAR_GP_PIN(2, 16), ++}; ++static const unsigned int vin0_field_mux[] = { ++ VI0_FIELD_MARK, ++}; ++static const unsigned int vin0_clkenb_pins[] = { ++ /* CLKENB */ ++ RCAR_GP_PIN(2, 1), ++}; ++static const unsigned int vin0_clkenb_mux[] = { ++ VI0_CLKENB_MARK, ++}; ++static const unsigned int vin0_clk_pins[] = { ++ /* CLK */ ++ RCAR_GP_PIN(2, 0), ++}; ++static const unsigned int vin0_clk_mux[] = { ++ VI0_CLK_MARK, ++}; ++/* - VIN1 ------------------------------------------------------------------- */ ++static const unsigned int vin1_data8_pins[] = { ++ RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5), ++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), ++ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), ++ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11), ++}; ++static const unsigned int vin1_data8_mux[] = { ++ VI1_DATA0_MARK, VI1_DATA1_MARK, ++ VI1_DATA2_MARK, VI1_DATA3_MARK, ++ VI1_DATA4_MARK, VI1_DATA5_MARK, ++ VI1_DATA6_MARK, VI1_DATA7_MARK, ++}; ++static const unsigned int vin1_data10_pins[] = { ++ RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5), ++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), ++ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), ++ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11), ++ RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 13), ++}; ++static const unsigned int vin1_data10_mux[] = { ++ VI1_DATA0_MARK, VI1_DATA1_MARK, ++ VI1_DATA2_MARK, VI1_DATA3_MARK, ++ VI1_DATA4_MARK, VI1_DATA5_MARK, ++ VI1_DATA6_MARK, VI1_DATA7_MARK, ++ VI1_DATA8_MARK, VI1_DATA9_MARK, ++}; ++static const unsigned int vin1_data12_pins[] = { ++ RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5), ++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), ++ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), ++ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11), ++ RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 13), ++ RCAR_GP_PIN(3, 14), RCAR_GP_PIN(3, 15), ++}; ++static const unsigned int vin1_data12_mux[] = { ++ VI1_DATA0_MARK, VI1_DATA1_MARK, ++ VI1_DATA2_MARK, VI1_DATA3_MARK, ++ VI1_DATA4_MARK, VI1_DATA5_MARK, ++ VI1_DATA6_MARK, VI1_DATA7_MARK, ++ VI1_DATA8_MARK, VI1_DATA9_MARK, ++ VI1_DATA10_MARK, VI1_DATA11_MARK, ++}; ++static const unsigned int vin1_sync_pins[] = { ++ /* VSYNC_N, HSYNC_N */ ++ RCAR_GP_PIN(3, 3), RCAR_GP_PIN(3, 2), ++}; ++static const unsigned int vin1_sync_mux[] = { ++ VI1_HSYNC_N_MARK, VI1_VSYNC_N_MARK, ++}; ++static const unsigned int vin1_field_pins[] = { ++ /* FIELD */ ++ RCAR_GP_PIN(3, 16), ++}; ++static const unsigned int vin1_field_mux[] = { ++ VI1_FIELD_MARK, ++}; ++static const unsigned int vin1_clkenb_pins[] = { ++ /* CLKENB */ ++ RCAR_GP_PIN(3, 1), ++}; ++static const unsigned int vin1_clkenb_mux[] = { ++ VI1_CLKENB_MARK, ++}; ++static const unsigned int vin1_clk_pins[] = { ++ /* CLK */ ++ RCAR_GP_PIN(3, 0), ++}; ++static const unsigned int vin1_clk_mux[] = { ++ VI1_CLK_MARK, ++}; ++ ++static const struct sh_pfc_pin_group pinmux_groups[] = { ++ SH_PFC_PIN_GROUP(avb_rx_ctrl), ++ SH_PFC_PIN_GROUP(avb_rxc), ++ SH_PFC_PIN_GROUP(avb_rd0), ++ SH_PFC_PIN_GROUP(avb_rd1), ++ SH_PFC_PIN_GROUP(avb_rd2), ++ SH_PFC_PIN_GROUP(avb_rd3), ++ SH_PFC_PIN_GROUP(avb_rd4), ++ SH_PFC_PIN_GROUP(avb_tx_ctrl), ++ SH_PFC_PIN_GROUP(avb_txc), ++ SH_PFC_PIN_GROUP(avb_td0), ++ SH_PFC_PIN_GROUP(avb_td1), ++ SH_PFC_PIN_GROUP(avb_td2), ++ SH_PFC_PIN_GROUP(avb_td3), ++ SH_PFC_PIN_GROUP(avb_td4), ++ SH_PFC_PIN_GROUP(avb_txcrefclk), ++ SH_PFC_PIN_GROUP(avb_mdio), ++ SH_PFC_PIN_GROUP(avb_mdc), ++ SH_PFC_PIN_GROUP(avb_magic), ++ SH_PFC_PIN_GROUP(avb_phy_int), ++ SH_PFC_PIN_GROUP(avb_link), ++ SH_PFC_PIN_GROUP(avb_avtp_match), ++ SH_PFC_PIN_GROUP(avb_avtp_capture), ++ SH_PFC_PIN_GROUP(avb_avtp_pps), ++ SH_PFC_PIN_GROUP(gether_rx_ctrl), ++ SH_PFC_PIN_GROUP(gether_rxc), ++ SH_PFC_PIN_GROUP(gether_rd0), ++ SH_PFC_PIN_GROUP(gether_rd1), ++ SH_PFC_PIN_GROUP(gether_rd2), ++ SH_PFC_PIN_GROUP(gether_rd3), ++ SH_PFC_PIN_GROUP(gether_rd4), ++ SH_PFC_PIN_GROUP(gether_tx_ctrl), ++ SH_PFC_PIN_GROUP(gether_txc), ++ SH_PFC_PIN_GROUP(gether_td0), ++ SH_PFC_PIN_GROUP(gether_td1), ++ SH_PFC_PIN_GROUP(gether_td2), ++ SH_PFC_PIN_GROUP(gether_td3), ++ SH_PFC_PIN_GROUP(gether_td4), ++ SH_PFC_PIN_GROUP(gether_txcrefclk), ++ SH_PFC_PIN_GROUP(gether_txcrefclk_mega), ++ SH_PFC_PIN_GROUP(gether_mdio_a), ++ SH_PFC_PIN_GROUP(gether_mdio_b), ++ SH_PFC_PIN_GROUP(gether_mdc_a), ++ SH_PFC_PIN_GROUP(gether_mdc_b), ++ SH_PFC_PIN_GROUP(gether_magic), ++ SH_PFC_PIN_GROUP(gether_phy_int_a), ++ SH_PFC_PIN_GROUP(gether_phy_int_b), ++ SH_PFC_PIN_GROUP(gether_link_a), ++ SH_PFC_PIN_GROUP(gether_link_b), ++ SH_PFC_PIN_GROUP(gether_rmii), ++ SH_PFC_PIN_GROUP(canfd0_data_a), ++ SH_PFC_PIN_GROUP(canfd_clk_a), ++ SH_PFC_PIN_GROUP(canfd0_data_b), ++ SH_PFC_PIN_GROUP(canfd_clk_b), ++ SH_PFC_PIN_GROUP(canfd1_data), ++ SH_PFC_PIN_GROUP(du_rgb666), ++ SH_PFC_PIN_GROUP(du_clk_out_0), ++ SH_PFC_PIN_GROUP(du_clk_out_1), ++ SH_PFC_PIN_GROUP(du_sync), ++ SH_PFC_PIN_GROUP(du_oddf), ++ SH_PFC_PIN_GROUP(du_cde), ++ SH_PFC_PIN_GROUP(du_disp), ++ SH_PFC_PIN_GROUP(hscif0_data_a), ++ SH_PFC_PIN_GROUP(hscif0_clk_a), ++ SH_PFC_PIN_GROUP(hscif0_ctrl_a), ++ SH_PFC_PIN_GROUP(hscif0_data_b), ++ SH_PFC_PIN_GROUP(hscif0_clk_b), ++ SH_PFC_PIN_GROUP(hscif0_ctrl_b), ++ SH_PFC_PIN_GROUP(hscif1_data), ++ SH_PFC_PIN_GROUP(hscif1_clk), ++ SH_PFC_PIN_GROUP(hscif1_ctrl), ++ SH_PFC_PIN_GROUP(hscif2_data), ++ SH_PFC_PIN_GROUP(hscif2_clk), ++ SH_PFC_PIN_GROUP(hscif2_ctrl), ++ SH_PFC_PIN_GROUP(hscif3_data), ++ SH_PFC_PIN_GROUP(hscif3_clk), ++ SH_PFC_PIN_GROUP(hscif3_ctrl), ++ SH_PFC_PIN_GROUP(scif_clk_a), ++ SH_PFC_PIN_GROUP(scif_clk_b), ++ SH_PFC_PIN_GROUP(i2c0), ++ SH_PFC_PIN_GROUP(i2c1), ++ SH_PFC_PIN_GROUP(i2c2), ++ SH_PFC_PIN_GROUP(i2c3), ++ SH_PFC_PIN_GROUP(i2c4), ++ SH_PFC_PIN_GROUP(i2c5), ++ SH_PFC_PIN_GROUP(intc_ex_irq0), ++ SH_PFC_PIN_GROUP(intc_ex_irq1), ++ SH_PFC_PIN_GROUP(intc_ex_irq2), ++ SH_PFC_PIN_GROUP(intc_ex_irq3), ++ SH_PFC_PIN_GROUP(intc_ex_irq4), ++ SH_PFC_PIN_GROUP(intc_ex_irq5), ++ SH_PFC_PIN_GROUP(msiof0_clk), ++ SH_PFC_PIN_GROUP(msiof0_sync), ++ SH_PFC_PIN_GROUP(msiof0_ss1), ++ SH_PFC_PIN_GROUP(msiof0_ss2), ++ SH_PFC_PIN_GROUP(msiof0_txd), ++ SH_PFC_PIN_GROUP(msiof0_rxd), ++ SH_PFC_PIN_GROUP(msiof1_clk), ++ SH_PFC_PIN_GROUP(msiof1_sync), ++ SH_PFC_PIN_GROUP(msiof1_ss1), ++ SH_PFC_PIN_GROUP(msiof1_ss2), ++ SH_PFC_PIN_GROUP(msiof1_txd), ++ SH_PFC_PIN_GROUP(msiof1_rxd), ++ SH_PFC_PIN_GROUP(msiof2_clk), ++ SH_PFC_PIN_GROUP(msiof2_sync), ++ SH_PFC_PIN_GROUP(msiof2_ss1), ++ SH_PFC_PIN_GROUP(msiof2_ss2), ++ SH_PFC_PIN_GROUP(msiof2_txd), ++ SH_PFC_PIN_GROUP(msiof2_rxd), ++ SH_PFC_PIN_GROUP(msiof3_clk), ++ SH_PFC_PIN_GROUP(msiof3_sync), ++ SH_PFC_PIN_GROUP(msiof3_ss1), ++ SH_PFC_PIN_GROUP(msiof3_ss2), ++ SH_PFC_PIN_GROUP(msiof3_txd), ++ SH_PFC_PIN_GROUP(msiof3_rxd), ++ SH_PFC_PIN_GROUP(tpu_to0), ++ SH_PFC_PIN_GROUP(tpu_to1), ++ SH_PFC_PIN_GROUP(tpu_to2), ++ SH_PFC_PIN_GROUP(tpu_to3), ++ SH_PFC_PIN_GROUP(pwm0_a), ++ SH_PFC_PIN_GROUP(pwm0_b), ++ SH_PFC_PIN_GROUP(pwm1_a), ++ SH_PFC_PIN_GROUP(pwm1_b), ++ SH_PFC_PIN_GROUP(pwm2_a), ++ SH_PFC_PIN_GROUP(pwm2_b), ++ SH_PFC_PIN_GROUP(pwm3_a), ++ SH_PFC_PIN_GROUP(pwm3_b), ++ SH_PFC_PIN_GROUP(pwm4_a), ++ SH_PFC_PIN_GROUP(pwm4_b), ++ SH_PFC_PIN_GROUP(scif0_data), ++ SH_PFC_PIN_GROUP(scif0_clk), ++ SH_PFC_PIN_GROUP(scif0_ctrl), ++ SH_PFC_PIN_GROUP(scif1_data_a), ++ SH_PFC_PIN_GROUP(scif1_clk), ++ SH_PFC_PIN_GROUP(scif1_ctrl), ++ SH_PFC_PIN_GROUP(scif1_data_b), ++ SH_PFC_PIN_GROUP(scif3_data), ++ SH_PFC_PIN_GROUP(scif3_clk), ++ SH_PFC_PIN_GROUP(scif3_ctrl), ++ SH_PFC_PIN_GROUP(scif4_data), ++ SH_PFC_PIN_GROUP(scif4_clk), ++ SH_PFC_PIN_GROUP(scif4_ctrl), ++ SH_PFC_PIN_GROUP(mmc_data1), ++ SH_PFC_PIN_GROUP(mmc_data4), ++ SH_PFC_PIN_GROUP(mmc_data8), ++ SH_PFC_PIN_GROUP(mmc_ctrl), ++ SH_PFC_PIN_GROUP(mmc_cd), ++ SH_PFC_PIN_GROUP(mmc_wp), ++ SH_PFC_PIN_GROUP(mmc_ds), ++ SH_PFC_PIN_GROUP(tmu_tclk1_a), ++ SH_PFC_PIN_GROUP(tmu_tclk1_b), ++ SH_PFC_PIN_GROUP(tmu_tclk2_a), ++ SH_PFC_PIN_GROUP(tmu_tclk2_b), ++ SH_PFC_PIN_GROUP(vin0_data8), ++ SH_PFC_PIN_GROUP(vin0_data10), ++ SH_PFC_PIN_GROUP(vin0_data12), ++ SH_PFC_PIN_GROUP(vin0_data16), ++ SH_PFC_PIN_GROUP(vin0_data20), ++ SH_PFC_PIN_GROUP(vin0_data24), ++ SH_PFC_PIN_GROUP(vin0_sync), ++ SH_PFC_PIN_GROUP(vin0_field), ++ SH_PFC_PIN_GROUP(vin0_clkenb), ++ SH_PFC_PIN_GROUP(vin0_clk), ++ SH_PFC_PIN_GROUP(vin1_data8), ++ SH_PFC_PIN_GROUP(vin1_data10), ++ SH_PFC_PIN_GROUP(vin1_data12), ++ SH_PFC_PIN_GROUP(vin1_sync), ++ SH_PFC_PIN_GROUP(vin1_field), ++ SH_PFC_PIN_GROUP(vin1_clkenb), ++ SH_PFC_PIN_GROUP(vin1_clk), ++}; ++ ++static const char * const avb_groups[] = { ++ "avb_rx_ctrl", ++ "avb_rxc", ++ "avb_rd1", ++ "avb_rd4", ++ "avb_tx_ctrl", ++ "avb_txc", ++ "avb_td1", ++ "avb_td4", ++ "avb_txcrefclk", ++ "avb_mdio", ++ "avb_mdc", ++ "avb_magic", ++ "avb_phy_int", ++ "avb_link", ++ "avb_avtp_match", ++ "avb_avtp_capture", ++ "avb_avtp_pps", ++}; ++ ++static const char * const gether_groups[] = { ++ "gether_rx_ctrl", ++ "gether_rxc", ++ "gether_rd1", ++ "gether_rd4", ++ "gether_tx_ctrl", ++ "gether_txc", ++ "gether_td1", ++ "gether_td4", ++ "gether_txcrefclk", ++ "gether_txcrefclk_mega", ++ "gether_mdio_a", ++ "gether_mdc_a", ++ "gether_mdio_b", ++ "gether_mdc_b", ++ "gether_magic", ++ "gether_phy_int_a", ++ "gether_link_a", ++ "gether_phy_int_b", ++ "gether_link_b", ++ "gether_rmii", ++}; ++ ++static const char * const canfd0_groups[] = { ++ "canfd0_data_a", ++ "canfd_clk_a", ++ "canfd0_data_b", ++ "canfd_clk_b", ++}; ++ ++static const char * const canfd1_groups[] = { ++ "canfd1_data", ++}; ++ ++static const char * const du_groups[] = { ++ "du_rgb666", ++ "du_clk_out_0", ++ "du_clk_out_1", ++ "du_sync", ++ "du_oddf", ++ "du_cde", ++ "du_disp", ++}; ++ ++static const char * const hscif0_groups[] = { ++ "hscif0_data_a", ++ "hscif0_clk_a", ++ "hscif0_ctrl_a", ++ "hscif0_data_b", ++ "hscif0_clk_b", ++ "hscif0_ctrl_b", ++}; ++ ++static const char * const hscif1_groups[] = { ++ "hscif1_data", ++ "hscif1_clk", ++ "hscif1_ctrl", ++}; ++ ++static const char * const hscif2_groups[] = { ++ "hscif2_data", ++ "hscif2_clk", ++ "hscif2_ctrl", ++}; ++ ++static const char * const hscif3_groups[] = { ++ "hscif3_data", ++ "hscif3_clk", ++ "hscif3_ctrl", ++}; ++ ++static const char * const scif_clk_groups[] = { ++ "scif_clk_a", ++ "scif_clk_b", ++}; ++ ++static const char * const i2c0_groups[] = { ++ "i2c0", ++}; ++ ++static const char * const i2c1_groups[] = { ++ "i2c1", ++}; ++ ++static const char * const i2c2_groups[] = { ++ "i2c2", ++}; ++ ++static const char * const i2c3_groups[] = { ++ "i2c3", ++}; ++ ++static const char * const i2c4_groups[] = { ++ "i2c4", ++}; ++ ++static const char * const i2c5_groups[] = { ++ "i2c5", ++}; ++ ++static const char * const intc_ex_groups[] = { ++ "intc_ex_irq0", ++ "intc_ex_irq1", ++ "intc_ex_irq2", ++ "intc_ex_irq3", ++ "intc_ex_irq4", ++ "intc_ex_irq5", ++}; ++ ++static const char * const msiof0_groups[] = { ++ "msiof0_clk", ++ "msiof0_sync", ++ "msiof0_ss1", ++ "msiof0_ss2", ++ "msiof0_txd", ++ "msiof0_rxd", ++}; ++ ++static const char * const msiof1_groups[] = { ++ "msiof1_clk", ++ "msiof1_sync", ++ "msiof1_ss1", ++ "msiof1_ss2", ++ "msiof1_txd", ++ "msiof1_rxd", ++}; ++ ++static const char * const msiof2_groups[] = { ++ "msiof2_clk", ++ "msiof2_sync", ++ "msiof2_ss1", ++ "msiof2_ss2", ++ "msiof2_txd", ++ "msiof2_rxd", ++}; ++ ++static const char * const msiof3_groups[] = { ++ "msiof3_clk", ++ "msiof3_sync", ++ "msiof3_ss1", ++ "msiof3_ss2", ++ "msiof3_txd", ++ "msiof3_rxd", ++}; ++ ++static const char * const tpu_groups[] = { ++ "tpu_to0", ++ "tpu_to1", ++ "tpu_to2", ++ "tpu_to3", ++}; ++ ++static const char * const pwm0_groups[] = { ++ "pwm0_a", ++ "pwm0_b", ++}; ++ ++static const char * const pwm1_groups[] = { ++ "pwm1_a", ++ "pwm1_b", ++}; ++ ++static const char * const pwm2_groups[] = { ++ "pwm2_a", ++ "pwm2_b", ++}; ++ ++static const char * const pwm3_groups[] = { ++ "pwm3_a", ++ "pwm3_b", ++}; ++ ++static const char * const pwm4_groups[] = { ++ "pwm4_a", ++ "pwm4_b", ++}; ++ ++static const char * const scif0_groups[] = { ++ "scif0_data", ++// "scif0_clk", ++// "scif0_ctrl", ++}; ++ ++static const char * const scif1_groups[] = { ++ "scif1_data_a", ++ "scif1_clk", ++ "scif1_ctrl", ++ "scif1_data_b", ++}; ++ ++static const char * const scif3_groups[] = { ++ "scif3_data", ++ "scif3_clk", ++ "scif3_ctrl", ++}; ++ ++static const char * const scif4_groups[] = { ++ "scif4_data", ++ "scif4_clk", ++ "scif4_ctrl", ++}; ++ ++static const char * const mmc_groups[] = { ++ "mmc_data1", ++ "mmc_data4", ++ "mmc_data8", ++ "mmc_ctrl", ++ "mmc_cd", ++ "mmc_wp", ++ "mmc_ds", ++}; ++ ++static const char * const tmu_groups[] = { ++ "tmu_tclk1_a", ++ "tmu_tclk1_b", ++ "tmu_tclk2_a", ++ "tmu_tclk2_b", ++}; ++ ++static const char * const vin0_groups[] = { ++ "vin0_data8", ++ "vin0_data10", ++ "vin0_data12", ++ "vin0_data16", ++ "vin0_data20", ++ "vin0_data24", ++ "vin0_sync", ++ "vin0_field", ++ "vin0_clkenb", ++ "vin0_clk", ++}; ++ ++static const char * const vin1_groups[] = { ++ "vin1_data8", ++ "vin1_data10", ++ "vin1_data12", ++ "vin1_sync", ++ "vin1_field", ++ "vin1_clkenb", ++ "vin1_clk", ++}; ++ ++static const struct sh_pfc_function pinmux_functions[] = { ++ SH_PFC_FUNCTION(avb), ++ SH_PFC_FUNCTION(gether), ++ SH_PFC_FUNCTION(canfd0), ++ SH_PFC_FUNCTION(canfd1), ++ SH_PFC_FUNCTION(du), ++ SH_PFC_FUNCTION(hscif0), ++ SH_PFC_FUNCTION(hscif1), ++ SH_PFC_FUNCTION(hscif2), ++ SH_PFC_FUNCTION(hscif3), ++ SH_PFC_FUNCTION(scif_clk), ++ SH_PFC_FUNCTION(i2c0), ++ SH_PFC_FUNCTION(i2c1), ++ SH_PFC_FUNCTION(i2c2), ++ SH_PFC_FUNCTION(i2c3), ++ SH_PFC_FUNCTION(i2c4), ++ SH_PFC_FUNCTION(i2c5), ++ SH_PFC_FUNCTION(intc_ex), ++ SH_PFC_FUNCTION(msiof0), ++ SH_PFC_FUNCTION(msiof1), ++ SH_PFC_FUNCTION(msiof2), ++ SH_PFC_FUNCTION(msiof3), ++ SH_PFC_FUNCTION(tpu), ++ SH_PFC_FUNCTION(pwm0), ++ SH_PFC_FUNCTION(pwm1), ++ SH_PFC_FUNCTION(pwm2), ++ SH_PFC_FUNCTION(pwm3), ++ SH_PFC_FUNCTION(pwm4), ++ SH_PFC_FUNCTION(scif0), ++ SH_PFC_FUNCTION(scif1), ++ SH_PFC_FUNCTION(scif3), ++ SH_PFC_FUNCTION(scif4), ++ SH_PFC_FUNCTION(mmc), ++ SH_PFC_FUNCTION(tmu), ++ SH_PFC_FUNCTION(vin0), ++ SH_PFC_FUNCTION(vin1), ++}; ++ ++static const struct pinmux_cfg_reg pinmux_config_regs[] = { ++#define F_(x, y) FN_##y ++#define FM(x) FN_##x ++ { PINMUX_CFG_REG("GPSR0", 0xe6060100, 32, 1) { ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ GP_0_21_FN, GPSR0_21, ++ GP_0_20_FN, GPSR0_20, ++ GP_0_19_FN, GPSR0_19, ++ GP_0_18_FN, GPSR0_18, ++ GP_0_17_FN, GPSR0_17, ++ GP_0_16_FN, GPSR0_16, ++ GP_0_15_FN, GPSR0_15, ++ GP_0_14_FN, GPSR0_14, ++ GP_0_13_FN, GPSR0_13, ++ GP_0_12_FN, GPSR0_12, ++ GP_0_11_FN, GPSR0_11, ++ GP_0_10_FN, GPSR0_10, ++ GP_0_9_FN, GPSR0_9, ++ GP_0_8_FN, GPSR0_8, ++ GP_0_7_FN, GPSR0_7, ++ GP_0_6_FN, GPSR0_6, ++ GP_0_5_FN, GPSR0_5, ++ GP_0_4_FN, GPSR0_4, ++ GP_0_3_FN, GPSR0_3, ++ GP_0_2_FN, GPSR0_2, ++ GP_0_1_FN, GPSR0_1, ++ GP_0_0_FN, GPSR0_0, } ++ }, ++ { PINMUX_CFG_REG("GPSR1", 0xe6060104, 32, 1) { ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ GP_1_27_FN, GPSR1_27, ++ GP_1_26_FN, GPSR1_26, ++ GP_1_25_FN, GPSR1_25, ++ GP_1_24_FN, GPSR1_24, ++ GP_1_23_FN, GPSR1_23, ++ GP_1_22_FN, GPSR1_22, ++ GP_1_21_FN, GPSR1_21, ++ GP_1_20_FN, GPSR1_20, ++ GP_1_19_FN, GPSR1_19, ++ GP_1_18_FN, GPSR1_18, ++ GP_1_17_FN, GPSR1_17, ++ GP_1_16_FN, GPSR1_16, ++ GP_1_15_FN, GPSR1_15, ++ GP_1_14_FN, GPSR1_14, ++ GP_1_13_FN, GPSR1_13, ++ GP_1_12_FN, GPSR1_12, ++ GP_1_11_FN, GPSR1_11, ++ GP_1_10_FN, GPSR1_10, ++ GP_1_9_FN, GPSR1_9, ++ GP_1_8_FN, GPSR1_8, ++ GP_1_7_FN, GPSR1_7, ++ GP_1_6_FN, GPSR1_6, ++ GP_1_5_FN, GPSR1_5, ++ GP_1_4_FN, GPSR1_4, ++ GP_1_3_FN, GPSR1_3, ++ GP_1_2_FN, GPSR1_2, ++ GP_1_1_FN, GPSR1_1, ++ GP_1_0_FN, GPSR1_0, } ++ }, ++ { PINMUX_CFG_REG("GPSR2", 0xe6060108, 32, 1) { ++ 0, 0, ++ 0, 0, ++ GP_2_29_FN, GPSR2_29, ++ GP_2_28_FN, GPSR2_28, ++ GP_2_27_FN, GPSR2_27, ++ GP_2_26_FN, GPSR2_26, ++ GP_2_25_FN, GPSR2_25, ++ GP_2_24_FN, GPSR2_24, ++ GP_2_23_FN, GPSR2_23, ++ GP_2_22_FN, GPSR2_22, ++ GP_2_21_FN, GPSR2_21, ++ GP_2_20_FN, GPSR2_20, ++ GP_2_19_FN, GPSR2_19, ++ GP_2_18_FN, GPSR2_18, ++ GP_2_17_FN, GPSR2_17, ++ GP_2_16_FN, GPSR2_16, ++ GP_2_15_FN, GPSR2_15, ++ GP_2_14_FN, GPSR2_14, ++ GP_2_13_FN, GPSR2_13, ++ GP_2_12_FN, GPSR2_12, ++ GP_2_11_FN, GPSR2_11, ++ GP_2_10_FN, GPSR2_10, ++ GP_2_9_FN, GPSR2_9, ++ GP_2_8_FN, GPSR2_8, ++ GP_2_7_FN, GPSR2_7, ++ GP_2_6_FN, GPSR2_6, ++ GP_2_5_FN, GPSR2_5, ++ GP_2_4_FN, GPSR2_4, ++ GP_2_3_FN, GPSR2_3, ++ GP_2_2_FN, GPSR2_2, ++ GP_2_1_FN, GPSR2_1, ++ GP_2_0_FN, GPSR2_0, } ++ }, ++ { PINMUX_CFG_REG("GPSR3", 0xe606010c, 32, 1) { ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ GP_3_16_FN, GPSR3_16, ++ GP_3_15_FN, GPSR3_15, ++ GP_3_14_FN, GPSR3_14, ++ GP_3_13_FN, GPSR3_13, ++ GP_3_12_FN, GPSR3_12, ++ GP_3_11_FN, GPSR3_11, ++ GP_3_10_FN, GPSR3_10, ++ GP_3_9_FN, GPSR3_9, ++ GP_3_8_FN, GPSR3_8, ++ GP_3_7_FN, GPSR3_7, ++ GP_3_6_FN, GPSR3_6, ++ GP_3_5_FN, GPSR3_5, ++ GP_3_4_FN, GPSR3_4, ++ GP_3_3_FN, GPSR3_3, ++ GP_3_2_FN, GPSR3_2, ++ GP_3_1_FN, GPSR3_1, ++ GP_3_0_FN, GPSR3_0, } ++ }, ++ { PINMUX_CFG_REG("GPSR4", 0xe6060110, 32, 1) { ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ GP_4_24_FN, GPSR4_24, ++ GP_4_23_FN, GPSR4_23, ++ GP_4_22_FN, GPSR4_22, ++ GP_4_21_FN, GPSR4_21, ++ GP_4_20_FN, GPSR4_20, ++ GP_4_19_FN, GPSR4_19, ++ GP_4_18_FN, GPSR4_18, ++ GP_4_17_FN, GPSR4_17, ++ GP_4_16_FN, GPSR4_16, ++ GP_4_15_FN, GPSR4_15, ++ GP_4_14_FN, GPSR4_14, ++ GP_4_13_FN, GPSR4_13, ++ GP_4_12_FN, GPSR4_12, ++ GP_4_11_FN, GPSR4_11, ++ GP_4_10_FN, GPSR4_10, ++ GP_4_9_FN, GPSR4_9, ++ GP_4_8_FN, GPSR4_8, ++ GP_4_7_FN, GPSR4_7, ++ GP_4_6_FN, GPSR4_6, ++ GP_4_5_FN, GPSR4_5, ++ GP_4_4_FN, GPSR4_4, ++ GP_4_3_FN, GPSR4_3, ++ GP_4_2_FN, GPSR4_2, ++ GP_4_1_FN, GPSR4_1, ++ GP_4_0_FN, GPSR4_0, } ++ }, ++ { PINMUX_CFG_REG("GPSR5", 0xe6060114, 32, 1) { ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ GP_5_14_FN, GPSR5_14, ++ GP_5_13_FN, GPSR5_13, ++ GP_5_12_FN, GPSR5_12, ++ GP_5_11_FN, GPSR5_11, ++ GP_5_10_FN, GPSR5_10, ++ GP_5_9_FN, GPSR5_9, ++ GP_5_8_FN, GPSR5_8, ++ GP_5_7_FN, GPSR5_7, ++ GP_5_6_FN, GPSR5_6, ++ GP_5_5_FN, GPSR5_5, ++ GP_5_4_FN, GPSR5_4, ++ GP_5_3_FN, GPSR5_3, ++ GP_5_2_FN, GPSR5_2, ++ GP_5_1_FN, GPSR5_1, ++ GP_5_0_FN, GPSR5_0, } ++ }, ++#undef F_ ++#undef FM ++ ++#define F_(x, y) x, ++#define FM(x) FN_##x, ++ { PINMUX_CFG_REG("IPSR0", 0xe6060200, 32, 4) { ++ IP0_31_28 ++ IP0_27_24 ++ IP0_23_20 ++ IP0_19_16 ++ IP0_15_12 ++ IP0_11_8 ++ IP0_7_4 ++ IP0_3_0 } ++ }, ++ { PINMUX_CFG_REG("IPSR1", 0xe6060204, 32, 4) { ++ IP1_31_28 ++ IP1_27_24 ++ IP1_23_20 ++ IP1_19_16 ++ IP1_15_12 ++ IP1_11_8 ++ IP1_7_4 ++ IP1_3_0 } ++ }, ++ { PINMUX_CFG_REG("IPSR2", 0xe6060208, 32, 4) { ++ IP2_31_28 ++ IP2_27_24 ++ IP2_23_20 ++ IP2_19_16 ++ IP2_15_12 ++ IP2_11_8 ++ IP2_7_4 ++ IP2_3_0 } ++ }, ++ { PINMUX_CFG_REG("IPSR3", 0xe606020c, 32, 4) { ++ IP3_31_28 ++ IP3_27_24 ++ IP3_23_20 ++ IP3_19_16 ++ IP3_15_12 ++ IP3_11_8 ++ IP3_7_4 ++ IP3_3_0 } ++ }, ++ { PINMUX_CFG_REG("IPSR4", 0xe6060210, 32, 4) { ++ IP4_31_28 ++ IP4_27_24 ++ IP4_23_20 ++ IP4_19_16 ++ IP4_15_12 ++ IP4_11_8 ++ IP4_7_4 ++ IP4_3_0 } ++ }, ++ { PINMUX_CFG_REG("IPSR5", 0xe6060214, 32, 4) { ++ IP5_31_28 ++ IP5_27_24 ++ IP5_23_20 ++ IP5_19_16 ++ IP5_15_12 ++ IP5_11_8 ++ IP5_7_4 ++ IP5_3_0 } ++ }, ++ { PINMUX_CFG_REG("IPSR6", 0xe6060218, 32, 4) { ++ IP6_31_28 ++ IP6_27_24 ++ IP6_23_20 ++ IP6_19_16 ++ IP6_15_12 ++ IP6_11_8 ++ IP6_7_4 ++ IP6_3_0 } ++ }, ++ { PINMUX_CFG_REG("IPSR7", 0xe606021c, 32, 4) { ++ IP7_31_28 ++ IP7_27_24 ++ IP7_23_20 ++ IP7_19_16 ++ IP7_15_12 ++ IP7_11_8 ++ IP7_7_4 ++ IP7_3_0 } ++ }, ++ { PINMUX_CFG_REG("IPSR8", 0xe6060220, 32, 4) { ++ IP8_31_28 ++ IP8_27_24 ++ IP8_23_20 ++ IP8_19_16 ++ IP8_15_12 ++ IP8_11_8 ++ IP8_7_4 ++ IP8_3_0 } ++ }, ++ { PINMUX_CFG_REG("IPSR9", 0xe6060224, 32, 4) { ++ IP8_31_28 ++ IP8_27_24 ++ IP8_23_20 ++ IP8_19_16 ++ IP8_15_12 ++ IP8_11_8 ++ IP8_7_4 ++ IP8_3_0 } ++ }, ++ { PINMUX_CFG_REG("IPSR10", 0xe6060228, 32, 4) { ++ IP8_31_28 ++ IP8_27_24 ++ IP8_23_20 ++ IP8_19_16 ++ IP8_15_12 ++ IP8_11_8 ++ IP8_7_4 ++ IP8_3_0 } ++ }, ++#undef F_ ++#undef FM ++ ++#define F_(x, y) x, ++#define FM(x) FN_##x, ++ { PINMUX_CFG_REG("MOD_SEL0", 0xe6060500, 32, 1) { ++ /* RESERVED 31..12 */ ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ MOD_SEL0_11 ++ MOD_SEL0_10 ++ MOD_SEL0_9 ++ MOD_SEL0_8 ++ MOD_SEL0_7 ++ MOD_SEL0_6 ++ MOD_SEL0_5 ++ MOD_SEL0_4 ++ 0, 0, ++ MOD_SEL0_2 ++ MOD_SEL0_1 ++ MOD_SEL0_0 } ++ }, ++ { }, ++}; ++ ++#define POC0 0xe6060380 ++#define POC1 0xe6060384 ++#define POC2 0xe6060388 ++ ++/* TODO make it nice */ ++static int r8a7798_pin_to_pocctrl(struct sh_pfc *pfc, unsigned int pin, u32 *pocctrl) ++{ ++ int bit = -EINVAL; ++ ++ *pocctrl = POC0; ++ ++ if (pin >= RCAR_GP_PIN(0, 0) && pin <= RCAR_GP_PIN(0, 21)) ++ bit = pin & 0x1f; ++ else if (pin >= RCAR_GP_PIN(2, 0) && pin <= RCAR_GP_PIN(2, 9)) ++ bit = (pin & 0x1f) + 22; ++ ++ if (bit != -EINVAL) ++ goto out; ++ ++ *pocctrl = POC1; ++ ++ if (pin >= RCAR_GP_PIN(2, 10) && pin <= RCAR_GP_PIN(2, 16)) ++ bit = (pin & 0x1f) - 10; ++ else if (pin >= RCAR_GP_PIN(3, 0) && pin <= RCAR_GP_PIN(3, 16)) ++ bit = (pin & 0x1f) + 7; ++ else if (pin >= RCAR_GP_PIN(2, 17) && pin <= RCAR_GP_PIN(2, 24)) ++ bit = (pin & 0x1f) + 7; ++ ++ if (bit != -EINVAL) ++ goto out; ++ ++ *pocctrl = POC2; ++ ++ if (pin >= RCAR_GP_PIN(2, 25) && pin <= RCAR_GP_PIN(2, 29)) ++ bit = (pin & 0x1f) - 25; ++ ++out: ++ return bit; ++} ++ ++static const struct sh_pfc_soc_operations pinmux_ops = { ++ .pin_to_pocctrl = r8a7798_pin_to_pocctrl, ++}; ++ ++const struct sh_pfc_soc_info r8a7798_pinmux_info = { ++ .name = "r8a77980_pfc", ++ .ops = &pinmux_ops, ++ .unlock_reg = 0xe6060000, /* PMMR */ ++ ++ .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END }, ++ ++ .pins = pinmux_pins, ++ .nr_pins = ARRAY_SIZE(pinmux_pins), ++ .groups = pinmux_groups, ++ .nr_groups = ARRAY_SIZE(pinmux_groups), ++ .functions = pinmux_functions, ++ .nr_functions = ARRAY_SIZE(pinmux_functions), ++ ++ .cfg_regs = pinmux_config_regs, ++ ++ .pinmux_data = pinmux_data, ++ .pinmux_data_size = ARRAY_SIZE(pinmux_data), ++}; +diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h +index 062af89..eaf052d 100644 +--- a/drivers/pinctrl/sh-pfc/sh_pfc.h ++++ b/drivers/pinctrl/sh-pfc/sh_pfc.h +@@ -289,6 +289,7 @@ struct sh_pfc_soc_info { + extern const struct sh_pfc_soc_info r8a7796_pinmux_info; + extern const struct sh_pfc_soc_info r8a77965_pinmux_info; + extern const struct sh_pfc_soc_info r8a7797_pinmux_info; ++extern const struct sh_pfc_soc_info r8a7798_pinmux_info; + extern const struct sh_pfc_soc_info sh7203_pinmux_info; + extern const struct sh_pfc_soc_info sh7264_pinmux_info; + extern const struct sh_pfc_soc_info sh7269_pinmux_info; +@@ -465,9 +466,13 @@ struct sh_pfc_soc_info { + PORT_GP_CFG_1(bank, 23, fn, sfx, cfg) + #define PORT_GP_24(bank, fn, sfx) PORT_GP_CFG_24(bank, fn, sfx, 0) + +-#define PORT_GP_CFG_26(bank, fn, sfx, cfg) \ ++#define PORT_GP_CFG_25(bank, fn, sfx, cfg) \ + PORT_GP_CFG_24(bank, fn, sfx, cfg), \ +- PORT_GP_CFG_1(bank, 24, fn, sfx, cfg), \ ++ PORT_GP_CFG_1(bank, 24, fn, sfx, cfg) ++#define PORT_GP_24(bank, fn, sfx) PORT_GP_CFG_24(bank, fn, sfx, 0) ++ ++#define PORT_GP_CFG_26(bank, fn, sfx, cfg) \ ++ PORT_GP_CFG_25(bank, fn, sfx, cfg), \ + PORT_GP_CFG_1(bank, 25, fn, sfx, cfg) + #define PORT_GP_26(bank, fn, sfx) PORT_GP_CFG_26(bank, fn, sfx, 0) + +diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile +index 2ba6a76..164b3e7 100644 +--- a/drivers/soc/renesas/Makefile ++++ b/drivers/soc/renesas/Makefile +@@ -6,6 +6,7 @@ obj-$(CONFIG_ARCH_R8A7795) += rcar-rst.o + obj-$(CONFIG_ARCH_R8A7796) += rcar-rst.o + obj-$(CONFIG_ARCH_R8A77965) += rcar-rst.o + obj-$(CONFIG_ARCH_R8A7797) += rcar-rst.o ++obj-$(CONFIG_ARCH_R8A7798) += rcar-rst.o + + obj-$(CONFIG_ARCH_R8A7743) += rcar-sysc.o r8a7743-sysc.o + obj-$(CONFIG_ARCH_R8A7745) += rcar-sysc.o r8a7745-sysc.o +@@ -20,15 +21,18 @@ obj-$(CONFIG_ARCH_R8A7795) += rcar-sysc.o r8a7795-sysc.o + obj-$(CONFIG_ARCH_R8A7796) += rcar-sysc.o r8a7796-sysc.o + obj-$(CONFIG_ARCH_R8A77965) += rcar-sysc.o r8a77965-sysc.o + obj-$(CONFIG_ARCH_R8A7797) += rcar-sysc.o r8a7797-sysc.o ++obj-$(CONFIG_ARCH_R8A7798) += rcar-sysc.o r8a7798-sysc.o + + obj-$(CONFIG_ARCH_R8A7795) += rcar-avs.o + obj-$(CONFIG_ARCH_R8A7796) += rcar-avs.o + obj-$(CONFIG_ARCH_R8A77965) += rcar-avs.o + obj-$(CONFIG_ARCH_R8A7797) += rcar-avs.o ++obj-$(CONFIG_ARCH_R8A7798) += rcar-avs.o + # EMS for R-Car Gen3 + obj-$(CONFIG_ARCH_R8A7795) += rcar_ems_ctrl.o + obj-$(CONFIG_ARCH_R8A7796) += rcar_ems_ctrl.o + obj-$(CONFIG_ARCH_R8A77965) += rcar_ems_ctrl.o + obj-$(CONFIG_ARCH_R8A7797) += rcar_ems_ctrl.o ++obj-$(CONFIG_ARCH_R8A7798) += rcar_ems_ctrl.o + + obj-$(CONFIG_RCAR_DDR_BACKUP) += s2ram_ddr_backup.o +diff --git a/drivers/soc/renesas/r8a7798-sysc.c b/drivers/soc/renesas/r8a7798-sysc.c +new file mode 100644 +index 0000000..128e79d +--- /dev/null ++++ b/drivers/soc/renesas/r8a7798-sysc.c +@@ -0,0 +1,57 @@ ++/* ++ * Renesas R-Car V3H System Controller ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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; version 2 of the License. ++ */ ++ ++#include ++#include ++ ++#include ++ ++#include "rcar-sysc.h" ++ ++static const struct rcar_sysc_area r8a7798_areas[] __initconst = { ++ { "always-on", 0, 0, R8A7798_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, ++ { "ca53-scu", 0x140, 0, R8A7798_PD_CA53_SCU, R8A7798_PD_ALWAYS_ON, ++ PD_SCU }, ++ { "ca53-cpu0", 0x200, 0, R8A7798_PD_CA53_CPU0, R8A7798_PD_CA53_SCU, ++ PD_CPU_NOCR }, ++ { "ca53-cpu1", 0x200, 1, R8A7798_PD_CA53_CPU1, R8A7798_PD_CA53_SCU, ++ PD_CPU_NOCR }, ++ { "ca53-cpu2", 0x200, 2, R8A7798_PD_CA53_CPU2, R8A7798_PD_CA53_SCU, ++ PD_CPU_NOCR }, ++ { "ca53-cpu3", 0x200, 3, R8A7798_PD_CA53_CPU3, R8A7798_PD_CA53_SCU, ++ PD_CPU_NOCR }, ++ { "cr7", 0x240, 0, R8A7798_PD_CR7, R8A7798_PD_ALWAYS_ON }, ++ ++ { "a3ir", 0x180, 0, R8A7798_PD_A3IR, R8A7798_PD_ALWAYS_ON }, ++ { "a2ir0", 0x400, 0, R8A7798_PD_A2IR0, R8A7798_PD_A3IR }, ++ { "a2ir1", 0x400, 1, R8A7798_PD_A2IR1, R8A7798_PD_A3IR }, ++ { "a2ir2", 0x400, 2, R8A7798_PD_A2IR2, R8A7798_PD_A3IR }, ++ { "a2ir3", 0x400, 3, R8A7798_PD_A2IR3, R8A7798_PD_A3IR }, ++ { "a2ir4", 0x400, 4, R8A7798_PD_A2IR4, R8A7798_PD_A3IR }, ++ { "a2ir5", 0x400, 5, R8A7798_PD_A2IR5, R8A7798_PD_A3IR }, ++ { "a2sc0", 0x400, 6, R8A7798_PD_A2SC0, R8A7798_PD_A3IR }, ++ { "a2sc1", 0x400, 7, R8A7798_PD_A2SC1, R8A7798_PD_A3IR }, ++ { "a2sc2", 0x400, 8, R8A7798_PD_A2SC2, R8A7798_PD_A3IR }, ++ { "a2sc3", 0x400, 9, R8A7798_PD_A2SC3, R8A7798_PD_A3IR }, ++ { "a2sc4", 0x400, 10, R8A7798_PD_A2SC4, R8A7798_PD_A3IR }, ++ { "a2pd0", 0x400, 11, R8A7798_PD_A2PD0, R8A7798_PD_A3IR }, ++ { "a2pd1", 0x400, 12, R8A7798_PD_A2PD1, R8A7798_PD_A3IR }, ++ { "a2cn", 0x400, 13, R8A7798_PD_A2CN, R8A7798_PD_A3IR }, ++ ++ { "a3vip", 0x2c0, 0, R8A7798_PD_A3VIP, R8A7798_PD_ALWAYS_ON }, ++ { "a3vip1", 0x300, 0, R8A7798_PD_A3VIP1, R8A7798_PD_ALWAYS_ON }, ++ { "a3vip2", 0x280, 0, R8A7798_PD_A3VIP2, R8A7798_PD_ALWAYS_ON }, ++}; ++ ++const struct rcar_sysc_info r8a7798_sysc_info __initconst = { ++ .areas = r8a7798_areas, ++ .num_areas = ARRAY_SIZE(r8a7798_areas), ++}; +diff --git a/drivers/soc/renesas/rcar-rst.c b/drivers/soc/renesas/rcar-rst.c +index bc3632b..8906817 100644 +--- a/drivers/soc/renesas/rcar-rst.c ++++ b/drivers/soc/renesas/rcar-rst.c +@@ -43,6 +43,7 @@ struct rst_config { + { .compatible = "renesas,r8a7796-rst", .data = &rcar_rst_gen2 }, + { .compatible = "renesas,r8a77965-rst", .data = &rcar_rst_gen2 }, + { .compatible = "renesas,r8a7797-rst", .data = &rcar_rst_gen2 }, ++ { .compatible = "renesas,r8a7798-rst", .data = &rcar_rst_gen2 }, + { /* sentinel */ } + }; + +diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c +index 1d5d440..bfde184 100644 +--- a/drivers/soc/renesas/rcar-sysc.c ++++ b/drivers/soc/renesas/rcar-sysc.c +@@ -327,6 +327,9 @@ static void __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd) + #ifdef CONFIG_ARCH_R8A7797 + { .compatible = "renesas,r8a7797-sysc", .data = &r8a7797_sysc_info }, + #endif ++#ifdef CONFIG_ARCH_R8A7798 ++ { .compatible = "renesas,r8a7798-sysc", .data = &r8a7798_sysc_info }, ++#endif + { /* sentinel */ } + }; + +diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h +index 1eb4e6d..dc58a58 100644 +--- a/drivers/soc/renesas/rcar-sysc.h ++++ b/drivers/soc/renesas/rcar-sysc.h +@@ -62,4 +62,5 @@ struct rcar_sysc_info { + extern const struct rcar_sysc_info r8a7796_sysc_info; + extern const struct rcar_sysc_info r8a77965_sysc_info; + extern const struct rcar_sysc_info r8a7797_sysc_info; ++extern const struct rcar_sysc_info r8a7798_sysc_info; + #endif /* __SOC_RENESAS_RCAR_SYSC_H__ */ +diff --git a/drivers/soc/renesas/rcar_ems_ctrl.c b/drivers/soc/renesas/rcar_ems_ctrl.c +index 388c570..516858d 100644 +--- a/drivers/soc/renesas/rcar_ems_ctrl.c ++++ b/drivers/soc/renesas/rcar_ems_ctrl.c +@@ -30,8 +30,9 @@ + + #define EMS_THERMAL_ZONE_MAX 10 + +-static const struct soc_device_attribute r8a7797[] = { ++static const struct soc_device_attribute r8a7797_8[] = { + { .soc_id = "r8a7797" }, ++ { .soc_id = "r8a7798" }, + { } + }; + +@@ -274,7 +275,7 @@ static int __init rcar_ems_cpu_shutdown_init(void) + + for_each_online_cpu(cpu) { + tmp_node = of_get_cpu_node(cpu, NULL); +- if (soc_device_match(r8a7797)) { ++ if (soc_device_match(r8a7797_8)) { + if (!of_device_is_compatible(tmp_node, "arm,cortex-a53")) + continue; + } +diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c +index 63f943d..b1fcae1 100644 +--- a/drivers/soc/renesas/renesas-soc.c ++++ b/drivers/soc/renesas/renesas-soc.c +@@ -144,6 +144,11 @@ struct renesas_soc { + .id = 0x54, + }; + ++static const struct renesas_soc soc_rcar_v3h __initconst __maybe_unused = { ++ .family = &fam_rcar_gen3, ++ .id = 0x56, ++}; ++ + static const struct renesas_soc soc_shmobile_ag5 __initconst __maybe_unused = { + .family = &fam_shmobile, + .id = 0x37, +@@ -199,6 +204,9 @@ struct renesas_soc { + #ifdef CONFIG_ARCH_R8A7797 + { .compatible = "renesas,r8a7797", .data = &soc_rcar_v3m }, + #endif ++#ifdef CONFIG_ARCH_R8A7798 ++ { .compatible = "renesas,r8a7798", .data = &soc_rcar_v3h }, ++#endif + #ifdef CONFIG_ARCH_SH73A0 + { .compatible = "renesas,sh73a0", .data = &soc_shmobile_ag5 }, + #endif +diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c +index a2606fe..13fd706 100644 +--- a/drivers/spi/spi-sh-msiof.c ++++ b/drivers/spi/spi-sh-msiof.c +@@ -217,7 +217,8 @@ static int msiof_rcar_is_gen3(struct device *dev) + return of_device_is_compatible(node, "renesas,msiof-r8a7795") || + of_device_is_compatible(node, "renesas,msiof-r8a7796") || + of_device_is_compatible(node, "renesas,msiof-r8a77965") || +- of_device_is_compatible(node, "renesas,msiof-r8a7797"); ++ of_device_is_compatible(node, "renesas,msiof-r8a7797") || ++ of_device_is_compatible(node, "renesas,msiof-r8a7798"); + } + + static u32 sh_msiof_read(struct sh_msiof_spi_priv *p, int reg_offs) +@@ -1192,6 +1193,7 @@ static int sh_msiof_transfer_one(struct spi_master *master, + { .compatible = "renesas,msiof-r8a7796", .data = &r8a779x_data }, + { .compatible = "renesas,msiof-r8a77965", .data = &r8a779x_data }, + { .compatible = "renesas,msiof-r8a7797", .data = &r8a779x_data }, ++ { .compatible = "renesas,msiof-r8a7798", .data = &r8a779x_data }, + {}, + }; + MODULE_DEVICE_TABLE(of, sh_msiof_match); +diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c +index a23dd44..90978c2 100644 +--- a/drivers/thermal/rcar_gen3_thermal.c ++++ b/drivers/thermal/rcar_gen3_thermal.c +@@ -415,6 +415,11 @@ static int rcar_gen3_r8a7797_thermal_init(struct rcar_thermal_priv *priv) + return 0; + } + ++static int rcar_gen3_r8a7798_thermal_init(struct rcar_thermal_priv *priv) ++{ ++ return rcar_gen3_r8a7796_thermal_init(priv); ++} ++ + /* + * Interrupt + */ +@@ -500,11 +505,16 @@ static int rcar_gen3_thermal_remove(struct platform_device *pdev) + .thermal_init = rcar_gen3_r8a7797_thermal_init, + }; + ++static const struct rcar_thermal_data r8a7798_data = { ++ .thermal_init = rcar_gen3_r8a7798_thermal_init, ++}; ++ + static const struct of_device_id rcar_thermal_dt_ids[] = { + { .compatible = "renesas,thermal-r8a7795", .data = &r8a7795_data}, + { .compatible = "renesas,thermal-r8a7796", .data = &r8a7796_data}, + { .compatible = "renesas,thermal-r8a77965", .data = &r8a7796_data}, + { .compatible = "renesas,thermal-r8a7797", .data = &r8a7797_data}, ++ { .compatible = "renesas,thermal-r8a7798", .data = &r8a7798_data}, + {}, + }; + MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids); +diff --git a/include/dt-bindings/clock/r8a7798-cpg-mssr.h b/include/dt-bindings/clock/r8a7798-cpg-mssr.h +new file mode 100644 +index 0000000..3d85730 +--- /dev/null ++++ b/include/dt-bindings/clock/r8a7798-cpg-mssr.h +@@ -0,0 +1,56 @@ ++/* ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++#ifndef __DT_BINDINGS_CLOCK_R8A7798_CPG_MSSR_H__ ++#define __DT_BINDINGS_CLOCK_R8A7798_CPG_MSSR_H__ ++ ++#include ++ ++/* r8a7798 CPG Core Clocks */ ++#define R8A7798_CLK_Z2 0 ++#define R8A7798_CLK_ZR 1 ++#define R8A7798_CLK_ZTR 2 ++#define R8A7798_CLK_ZTRD2 3 ++#define R8A7798_CLK_ZT 4 ++#define R8A7798_CLK_ZX 5 ++#define R8A7798_CLK_S0D1 6 ++#define R8A7798_CLK_S0D2 7 ++#define R8A7798_CLK_S0D3 8 ++#define R8A7798_CLK_S0D4 9 ++#define R8A7798_CLK_S0D6 10 ++#define R8A7798_CLK_S0D12 11 ++#define R8A7798_CLK_S0D24 12 ++#define R8A7798_CLK_S1D1 13 ++#define R8A7798_CLK_S1D2 14 ++#define R8A7798_CLK_S1D4 15 ++#define R8A7798_CLK_S2D1 16 ++#define R8A7798_CLK_S2D2 17 ++#define R8A7798_CLK_S2D4 18 ++#define R8A7798_CLK_S3D1 19 ++#define R8A7798_CLK_S3D2 20 ++#define R8A7798_CLK_S3D4 21 ++#define R8A7798_CLK_LB 22 ++#define R8A7798_CLK_CL 23 ++#define R8A7798_CLK_ZB3 24 ++#define R8A7798_CLK_ZB3D2 25 ++#define R8A7798_CLK_ZB3D4 26 ++#define R8A7798_CLK_SD0H 27 ++#define R8A7798_CLK_SD0 28 ++#define R8A7798_CLK_RPC 29 ++#define R8A7798_CLK_RPCD2 30 ++#define R8A7798_CLK_MSO 31 ++#define R8A7798_CLK_CANFD 32 ++#define R8A7798_CLK_CSI0 33 ++#define R8A7798_CLK_CSIREF 34 ++#define R8A7798_CLK_CP 35 ++#define R8A7798_CLK_CPEX 36 ++#define R8A7798_CLK_R 37 ++#define R8A7798_CLK_OSC 38 ++ ++#endif /* __DT_BINDINGS_CLOCK_R8A7798_CPG_MSSR_H__ */ +diff --git a/include/dt-bindings/power/r8a7798-sysc.h b/include/dt-bindings/power/r8a7798-sysc.h +new file mode 100644 +index 0000000..c10d60e +--- /dev/null ++++ b/include/dt-bindings/power/r8a7798-sysc.h +@@ -0,0 +1,46 @@ ++/* ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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; version 2 of the License. ++ */ ++#ifndef __DT_BINDINGS_POWER_R8A7798_SYSC_H__ ++#define __DT_BINDINGS_POWER_R8A7798_SYSC_H__ ++ ++/* ++ * These power domain indices match the numbers of the interrupt bits ++ * representing the power areas in the various Interrupt Registers ++ * (e.g. SYSCISR, Interrupt Status Register) ++ */ ++ ++#define R8A7798_PD_A2SC2 0 ++#define R8A7798_PD_A2SC3 1 ++#define R8A7798_PD_A2SC4 2 ++#define R8A7798_PD_A2PD0 3 ++#define R8A7798_PD_A2PD1 4 ++#define R8A7798_PD_CA53_CPU0 5 ++#define R8A7798_PD_CA53_CPU1 6 ++#define R8A7798_PD_CA53_CPU2 7 ++#define R8A7798_PD_CA53_CPU3 8 ++#define R8A7798_PD_A2CN 10 ++#define R8A7798_PD_A3VIP 11 ++#define R8A7798_PD_A2IR5 12 ++#define R8A7798_PD_CR7 13 ++#define R8A7798_PD_A2IR4 15 ++#define R8A7798_PD_CA53_SCU 21 ++#define R8A7798_PD_A2IR0 23 ++#define R8A7798_PD_A3IR 24 ++#define R8A7798_PD_A3VIP1 25 ++#define R8A7798_PD_A3VIP2 26 ++#define R8A7798_PD_A2IR1 27 ++#define R8A7798_PD_A2IR2 28 ++#define R8A7798_PD_A2IR3 29 ++#define R8A7798_PD_A2SC0 30 ++#define R8A7798_PD_A2SC1 31 ++ ++/* Always-on power area */ ++#define R8A7798_PD_ALWAYS_ON 32 ++ ++#endif /* __DT_BINDINGS_POWER_R8A7798_SYSC_H__ */ +-- +1.9.1 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0052-soc-renesas-rcar-sysc-Add-workaround-for-A3-PD-issue.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0052-soc-renesas-rcar-sysc-Add-workaround-for-A3-PD-issue.patch new file mode 100644 index 00000000..9cad5002 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0052-soc-renesas-rcar-sysc-Add-workaround-for-A3-PD-issue.patch @@ -0,0 +1,278 @@ +From 01fdcd06bd73807c03a6c8cf077fa53841861b58 Mon Sep 17 00:00:00 2001 +From: Shinyu Ninomiya +Date: Fri, 26 Jan 2018 21:38:58 +0900 +Subject: [PATCH] soc: renesas: rcar-sysc: Add workaround for A3 PD issue + +Before turning ON/OFF power domain of A3VIP0, A3VIP1, A3VIP2 the clock is supplied for BoschIP +by deactivating MSTP assigned for BoschIP before. This issue is also occurred at A3IR. +MSTP for impdes0 and impc0 should be deactivated before turning off A3IR domain. +This implements workaround to implement the sequence above. + +Signed-off-by: Shinyu Ninomiya +--- + drivers/soc/renesas/r8a7797-sysc.c | 3 +- + drivers/soc/renesas/r8a7798-sysc.c | 12 +++-- + drivers/soc/renesas/rcar-sysc.c | 108 ++++++++++++++++++++++++++++++++++++- + drivers/soc/renesas/rcar-sysc.h | 6 +++ + 4 files changed, 123 insertions(+), 6 deletions(-) + +diff --git a/drivers/soc/renesas/r8a7797-sysc.c b/drivers/soc/renesas/r8a7797-sysc.c +index cde7d9e..5725ad0 100644 +--- a/drivers/soc/renesas/r8a7797-sysc.c ++++ b/drivers/soc/renesas/r8a7797-sysc.c +@@ -24,7 +24,8 @@ static const struct rcar_sysc_area r8a7797_areas[] __initconst = { + { "ca53-cpu1", 0x200, 1, R8A7797_PD_CA53_CPU1, R8A7797_PD_CA53_SCU, + PD_CPU_NOCR }, + { "cr7", 0x240, 0, R8A7797_PD_CR7, R8A7797_PD_ALWAYS_ON }, +- { "a3ir", 0x180, 0, R8A7797_PD_A3IR, R8A7797_PD_ALWAYS_ON }, ++ { "a3ir", 0x180, 0, R8A7797_PD_A3IR, R8A7797_PD_ALWAYS_ON, ++ PD_WA_CLK, {"impram"} }, + { "a2ir0", 0x400, 0, R8A7797_PD_A2IR0, R8A7797_PD_A3IR }, + { "a2ir1", 0x400, 1, R8A7797_PD_A2IR1, R8A7797_PD_A3IR }, + { "a2ir2", 0x400, 2, R8A7797_PD_A2IR2, R8A7797_PD_A3IR }, +diff --git a/drivers/soc/renesas/r8a7798-sysc.c b/drivers/soc/renesas/r8a7798-sysc.c +index 128e79d..2affaa2 100644 +--- a/drivers/soc/renesas/r8a7798-sysc.c ++++ b/drivers/soc/renesas/r8a7798-sysc.c +@@ -30,7 +30,8 @@ static const struct rcar_sysc_area r8a7798_areas[] __initconst = { + PD_CPU_NOCR }, + { "cr7", 0x240, 0, R8A7798_PD_CR7, R8A7798_PD_ALWAYS_ON }, + +- { "a3ir", 0x180, 0, R8A7798_PD_A3IR, R8A7798_PD_ALWAYS_ON }, ++ { "a3ir", 0x180, 0, R8A7798_PD_A3IR, R8A7798_PD_ALWAYS_ON, ++ PD_WA_CLK, {"impram"} }, + { "a2ir0", 0x400, 0, R8A7798_PD_A2IR0, R8A7798_PD_A3IR }, + { "a2ir1", 0x400, 1, R8A7798_PD_A2IR1, R8A7798_PD_A3IR }, + { "a2ir2", 0x400, 2, R8A7798_PD_A2IR2, R8A7798_PD_A3IR }, +@@ -46,9 +47,12 @@ static const struct rcar_sysc_area r8a7798_areas[] __initconst = { + { "a2pd1", 0x400, 12, R8A7798_PD_A2PD1, R8A7798_PD_A3IR }, + { "a2cn", 0x400, 13, R8A7798_PD_A2CN, R8A7798_PD_A3IR }, + +- { "a3vip", 0x2c0, 0, R8A7798_PD_A3VIP, R8A7798_PD_ALWAYS_ON }, +- { "a3vip1", 0x300, 0, R8A7798_PD_A3VIP1, R8A7798_PD_ALWAYS_ON }, +- { "a3vip2", 0x280, 0, R8A7798_PD_A3VIP2, R8A7798_PD_ALWAYS_ON }, ++ { "a3vip", 0x2c0, 0, R8A7798_PD_A3VIP, R8A7798_PD_ALWAYS_ON, ++ PD_WA_CLK, {"disp"} }, ++ { "a3vip1", 0x300, 0, R8A7798_PD_A3VIP1, R8A7798_PD_ALWAYS_ON, ++ PD_WA_CLK, {"umf", "smd_post", "smd_est", "smd_ps"} }, ++ { "a3vip2", 0x280, 0, R8A7798_PD_A3VIP2, R8A7798_PD_ALWAYS_ON, ++ PD_WA_CLK, {"cle0", "cle1", "cle2", "cle3", "cle4"} }, + }; + + const struct rcar_sysc_info r8a7798_sysc_info __initconst = { +diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c +index bfde184..f3f18d0 100644 +--- a/drivers/soc/renesas/rcar-sysc.c ++++ b/drivers/soc/renesas/rcar-sysc.c +@@ -20,6 +20,8 @@ + #include + #include + #include ++#include ++#include + + #include "rcar-sysc.h" + +@@ -64,6 +66,7 @@ static DEFINE_SPINLOCK(rcar_sysc_lock); /* SMP CPUs + I/O devices */ + + + static const char *to_pd_name(const struct rcar_sysc_ch *sysc_ch); ++static int rcar_sysc_wa_clk(const struct rcar_sysc_ch *sysc_ch, int en); + + static int rcar_sysc_pwr_on_off(const struct rcar_sysc_ch *sysc_ch, bool on) + { +@@ -110,6 +113,12 @@ static int rcar_sysc_power(const struct rcar_sysc_ch *sysc_ch, bool on) + int ret = 0; + int k; + ++ ret = rcar_sysc_wa_clk(sysc_ch, 1); ++ if (ret) { ++ pr_err("%s: Failed to enable clock for workaround\n", to_pd_name(sysc_ch)); ++ return ret; ++ } ++ + spin_lock_irqsave(&rcar_sysc_lock, flags); + + iowrite32(isr_mask, rcar_sysc_base + SYSCISCR); +@@ -148,6 +157,8 @@ static int rcar_sysc_power(const struct rcar_sysc_ch *sysc_ch, bool on) + out: + spin_unlock_irqrestore(&rcar_sysc_lock, flags); + ++ rcar_sysc_wa_clk(sysc_ch, 0); ++ + pr_debug("sysc power %s domain %d: %08x -> %d\n", on ? "on" : "off", + sysc_ch->isr_bit, ioread32(rcar_sysc_base + SYSCISR), ret); + return ret; +@@ -178,9 +189,35 @@ struct rcar_sysc_pd { + struct generic_pm_domain genpd; + struct rcar_sysc_ch ch; + unsigned int flags; ++ struct clk *wa_clk[RCAR_SYSC_MAX_WA_CLKS]; + char name[0]; + }; + ++static int rcar_sysc_wa_clk(const struct rcar_sysc_ch *sysc_ch, int en) ++{ ++ int i, ret; ++ struct rcar_sysc_pd *pd = container_of(sysc_ch, struct rcar_sysc_pd, ch); ++ ++ if (pd->flags & PD_WA_CLK) { ++ if (!(pd->flags & PD_WA_CLK_RDY)) ++ return -EBUSY; ++ ++ for (i = 0; i < RCAR_SYSC_MAX_WA_CLKS; i++) { ++ if (!pd->wa_clk[i]) ++ break; ++ ++ if (en) { ++ ret = clk_enable(pd->wa_clk[i]); ++ if (ret) ++ return ret; ++ } else ++ clk_disable(pd->wa_clk[i]); ++ } ++ } ++ ++ return 0; ++} ++ + static inline struct rcar_sysc_pd *to_rcar_pd(struct generic_pm_domain *d) + { + return container_of(d, struct rcar_sysc_pd, genpd); +@@ -231,6 +268,7 @@ static void __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd) + struct generic_pm_domain *genpd = &pd->genpd; + const char *name = pd->genpd.name; + struct dev_power_governor *gov = &simple_qos_governor; ++ bool is_off = false; + + if (pd->flags & PD_CPU) { + /* +@@ -278,6 +316,12 @@ static void __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd) + goto finalize; + } + ++ if (pd->flags & PD_NO_INIT_ON) { ++ is_off = rcar_sysc_power_is_off(&pd->ch); ++ pr_debug("%s: %s is initialy %s\n", __func__, genpd->name, is_off ? "off" : "on"); ++ goto finalize; ++ } ++ + if (!rcar_sysc_power_is_off(&pd->ch)) { + pr_debug("%s: %s is already powered\n", __func__, genpd->name); + goto finalize; +@@ -286,7 +330,7 @@ static void __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd) + rcar_sysc_power_up(&pd->ch); + + finalize: +- pm_genpd_init(genpd, gov, false); ++ pm_genpd_init(genpd, gov, is_off); + } + + static const struct of_device_id rcar_sysc_matches[] = { +@@ -442,6 +486,12 @@ static int __init rcar_sysc_pd_init(void) + pd->ch.isr_bit = area->isr_bit; + pd->flags = area->flags; + ++ if ((pd->flags & PD_WA_CLK) || ++ (area->parent >= 0 && (container_of(domains->domains[area->parent], ++ struct rcar_sysc_pd, genpd)->flags & PD_NO_INIT_ON)) ++ ) ++ pd->flags |= PD_NO_INIT_ON; ++ + rcar_sysc_pd_setup(pd); + if (area->parent >= 0) + pm_genpd_add_subdomain(domains->domains[area->parent], +@@ -479,6 +529,62 @@ static int __init rcar_sysc_pd_init2(void) + postcore_initcall(rcar_sysc_pd_init2); + #endif + ++#if IS_ENABLED(CONFIG_ARCH_R8A7797) || \ ++ IS_ENABLED(CONFIG_ARCH_R8A7798) ++static int __init rcar_sysc_pd_init3(void) ++{ ++ const struct rcar_sysc_info *info; ++ const struct of_device_id *match; ++ struct device_node *np; ++ unsigned int i, j; ++ ++ np = of_find_matching_node_and_match(NULL, rcar_sysc_matches, &match); ++ if (!np) ++ return -ENODEV; ++ ++ info = match->data; ++ ++ for (i = 0; i < info->num_areas; i++) { ++ const struct rcar_sysc_area *area = &info->areas[i]; ++ struct rcar_sysc_pd *pd = rcar_domains[i]; ++ ++ if (pd->flags & PD_WA_CLK) { ++ int err = 0; ++ ++ for (j = 0; j < RCAR_SYSC_MAX_WA_CLKS; j++) { ++ struct clk *wa_clk; ++ const char *wa_clk_name = area->wa_clk_names[j]; ++ ++ if (!wa_clk_name) ++ break; ++ ++ wa_clk = __clk_lookup(wa_clk_name); ++ if (!wa_clk) { ++ err = -ENODEV; ++ pr_err("%s: Unable to get clock %s for workaround\n", pd->name, wa_clk_name); ++ break; ++ } ++ ++ err = clk_prepare(wa_clk); ++ if (err) { ++ pr_err("%s: Unable to prepare clock %s for workaround\n", pd->name, wa_clk_name); ++ break; ++ } ++ ++ pd->wa_clk[j] = wa_clk; ++ } ++ ++ if (!err) ++ pd->flags |= PD_WA_CLK_RDY; ++ } ++ } ++ ++ return 0; ++} ++/* Should be called after cpg_mssr_driver is initialized */ ++subsys_initcall_sync(rcar_sysc_pd_init3); ++#endif ++ + void __init rcar_sysc_init(phys_addr_t base, u32 syscier) + { + u32 syscimr; +diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h +index dc58a58..b991103 100644 +--- a/drivers/soc/renesas/rcar-sysc.h ++++ b/drivers/soc/renesas/rcar-sysc.h +@@ -23,10 +23,15 @@ + #define PD_BUSY BIT(3) /* Busy, for internal use only */ + #define PD_ON_ONCE BIT(4) /* Turned on once at boot */ + ++#define PD_WA_CLK BIT(5) /* Use clocks for workaround */ ++#define PD_WA_CLK_RDY BIT(6) /* Clock ready, for internal use only */ ++#define PD_NO_INIT_ON BIT(7) /* Do not power on at initialization, for internal use */ ++ + #define PD_CPU_CR PD_CPU /* CPU area has CR (R-Car H1) */ + #define PD_CPU_NOCR PD_CPU | PD_NO_CR /* CPU area lacks CR (R-Car Gen2/3) */ + #define PD_ALWAYS_ON PD_NO_CR /* Always-on area */ + ++#define RCAR_SYSC_MAX_WA_CLKS 8 + + /* + * Description of a Power Area +@@ -39,6 +44,7 @@ struct rcar_sysc_area { + u8 isr_bit; /* Bit in SYSCI*R */ + int parent; /* -1 if none */ + unsigned int flags; /* See PD_* */ ++ const char* wa_clk_names[RCAR_SYSC_MAX_WA_CLKS]; /* Clocks needed by workaround for A3 PD issue */ + }; + + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0062-IIO-lsm9ds0-add-IMU-driver.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0062-IIO-lsm9ds0-add-IMU-driver.patch new file mode 100644 index 00000000..f108ad74 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0062-IIO-lsm9ds0-add-IMU-driver.patch @@ -0,0 +1,958 @@ +From cc9a9418d5147aba469ff9a69c17e13514021b5e Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Wed, 7 Jun 2017 13:35:52 +0300 +Subject: [PATCH 041/122] IIO: lsm9ds0: add IMU driver + +Taken from: +https://github.com/mpod/kernel-playground + +Signed-off-by: Andrey Gusakov +--- + drivers/iio/imu/Kconfig | 11 + + drivers/iio/imu/Makefile | 2 + + drivers/iio/imu/lsm9ds0.c | 898 ++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 911 insertions(+) + create mode 100644 drivers/iio/imu/lsm9ds0.c + +diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig +index 156630a..6fd8490 100644 +--- a/drivers/iio/imu/Kconfig ++++ b/drivers/iio/imu/Kconfig +@@ -38,6 +38,17 @@ config KMX61 + To compile this driver as module, choose M here: the module will + be called kmx61. + ++config LSM9DS0 ++ tristate "ST LSM9DS0 9-axis IMU" ++ depends on I2C ++ select IIO_BUFFER ++ select IIO_TRIGGERED_BUFFER ++ help ++ Say Y here if you want to build a driver for ST LSM9DS0 ++ system-in-package featuring a 3D digital linear acceleration ++ sensor, a 3D digital angular rate sensor, and a 3D digital magnetic ++ sensor. ++ + source "drivers/iio/imu/inv_mpu6050/Kconfig" + source "drivers/iio/imu/st_lsm6dsx/Kconfig" + +diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile +index 68629c68..5ca2537 100644 +--- a/drivers/iio/imu/Makefile ++++ b/drivers/iio/imu/Makefile +@@ -14,6 +14,8 @@ adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_trigger.o + adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o + obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o + ++obj-$(CONFIG_LSM9DS0) += lsm9ds0.o ++ + obj-y += bmi160/ + obj-y += inv_mpu6050/ + +diff --git a/drivers/iio/imu/lsm9ds0.c b/drivers/iio/imu/lsm9ds0.c +new file mode 100644 +index 0000000..d1c81f6 +--- /dev/null ++++ b/drivers/iio/imu/lsm9ds0.c +@@ -0,0 +1,898 @@ ++/* ++ * lsm9ds0_gyro.c ++ * ++ * Copyright (C) 2016 Matija Podravec ++ * ++ * 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 3 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. ++ ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * ++ * Driver for ST LSM9DS0 gyroscope, accelerometer, and magnetometer sensor. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define LSM9DS0_WHO_AM_I_REG (0x0F) ++#define LSM9DS0_CTRL_REG1_G_REG (0x20) ++#define LSM9DS0_CTRL_REG2_G_REG (0x21) ++#define LSM9DS0_CTRL_REG3_G_REG (0x22) ++#define LSM9DS0_CTRL_REG4_G_REG (0x23) ++#define LSM9DS0_CTRL_REG5_G_REG (0x24) ++#define LSM9DS0_REFERENCE_G_REG (0x25) ++#define LSM9DS0_STATUS_REG_G_REG (0x27) ++#define LSM9DS0_OUT_X_L_G_REG (0x28) ++#define LSM9DS0_OUT_X_H_G_REG (0x29) ++#define LSM9DS0_OUT_Y_L_G_REG (0x2A) ++#define LSM9DS0_OUT_Y_H_G_REG (0x2B) ++#define LSM9DS0_OUT_Z_L_G_REG (0x2C) ++#define LSM9DS0_OUT_Z_H_G_REG (0x2D) ++#define LSM9DS0_FIFO_CTRL_REG_G_REG (0x2E) ++#define LSM9DS0_FIFO_SRC_REG_G_REG (0x2F) ++#define LSM9DS0_INT1_CFG_G_REG (0x30) ++#define LSM9DS0_INT1_SRC_G_REG (0x31) ++#define LSM9DS0_INT1_TSH_XH_G_REG (0x32) ++#define LSM9DS0_INT1_TSH_XL_G_REG (0x33) ++#define LSM9DS0_INT1_TSH_YH_G_REG (0x34) ++#define LSM9DS0_INT1_TSH_YL_G_REG (0x35) ++#define LSM9DS0_INT1_TSH_ZH_G_REG (0x36) ++#define LSM9DS0_INT1_TSH_ZL_G_REG (0x37) ++#define LSM9DS0_INT1_DURATION_G_REG (0x38) ++#define LSM9DS0_OUT_TEMP_L_XM_REG (0x05) ++#define LSM9DS0_OUT_TEMP_H_XM_REG (0x06) ++#define LSM9DS0_STATUS_REG_M_REG (0x07) ++#define LSM9DS0_OUT_X_L_M_REG (0x08) ++#define LSM9DS0_OUT_X_H_M_REG (0x09) ++#define LSM9DS0_OUT_Y_L_M_REG (0x0A) ++#define LSM9DS0_OUT_Y_H_M_REG (0x0B) ++#define LSM9DS0_OUT_Z_L_M_REG (0x0C) ++#define LSM9DS0_OUT_Z_H_M_REG (0x0D) ++#define LSM9DS0_INT_CTRL_REG_M_REG (0x12) ++#define LSM9DS0_INT_SRC_REG_M_REG (0x13) ++#define LSM9DS0_INT_THS_L_M_REG (0x14) ++#define LSM9DS0_INT_THS_H_M_REG (0x15) ++#define LSM9DS0_OFFSET_X_L_M_REG (0x16) ++#define LSM9DS0_OFFSET_X_H_M_REG (0x17) ++#define LSM9DS0_OFFSET_Y_L_M_REG (0x18) ++#define LSM9DS0_OFFSET_Y_H_M_REG (0x19) ++#define LSM9DS0_OFFSET_Z_L_M_REG (0x1A) ++#define LSM9DS0_OFFSET_Z_H_M_REG (0x1B) ++#define LSM9DS0_REFERENCE_X_REG (0x1C) ++#define LSM9DS0_REFERENCE_Y_REG (0x1D) ++#define LSM9DS0_REFERENCE_Z_REG (0x1E) ++#define LSM9DS0_CTRL_REG0_XM_REG (0x1F) ++#define LSM9DS0_CTRL_REG1_XM_REG (0x20) ++#define LSM9DS0_CTRL_REG2_XM_REG (0x21) ++#define LSM9DS0_CTRL_REG3_XM_REG (0x22) ++#define LSM9DS0_CTRL_REG4_XM_REG (0x23) ++#define LSM9DS0_CTRL_REG5_XM_REG (0x24) ++#define LSM9DS0_CTRL_REG6_XM_REG (0x25) ++#define LSM9DS0_CTRL_REG7_XM_REG (0x26) ++#define LSM9DS0_STATUS_REG_A_REG (0x27) ++#define LSM9DS0_OUT_X_L_A_REG (0x28) ++#define LSM9DS0_OUT_X_H_A_REG (0x29) ++#define LSM9DS0_OUT_Y_L_A_REG (0x2A) ++#define LSM9DS0_OUT_Y_H_A_REG (0x2B) ++#define LSM9DS0_OUT_Z_L_A_REG (0x2C) ++#define LSM9DS0_OUT_Z_H_A_REG (0x2D) ++#define LSM9DS0_FIFO_CTRL_REG_REG (0x2E) ++#define LSM9DS0_FIFO_SRC_REG_REG (0x2F) ++#define LSM9DS0_INT_GEN_1_REG_REG (0x30) ++#define LSM9DS0_INT_GEN_1_SRC_REG (0x31) ++#define LSM9DS0_INT_GEN_1_THS_REG (0x32) ++#define LSM9DS0_INT_GEN_1_DURATION_REG (0x33) ++#define LSM9DS0_INT_GEN_2_REG_REG (0x34) ++#define LSM9DS0_INT_GEN_2_SRC_REG (0x35) ++#define LSM9DS0_INT_GEN_2_THS_REG (0x36) ++#define LSM9DS0_INT_GEN_2_DURATION_REG (0x37) ++#define LSM9DS0_CLICK_CFG_REG (0x38) ++#define LSM9DS0_CLICK_SRC_REG (0x39) ++#define LSM9DS0_CLICK_THS_REG (0x3A) ++#define LSM9DS0_TIME_LIMIT_REG (0x3B) ++#define LSM9DS0_TIME_LATENCY_REG (0x3C) ++#define LSM9DS0_TIME_WINDOW_REG (0x3D) ++#define LSM9DS0_ACT_THS_REG (0x3E) ++#define LSM9DS0_ACT_DUR_REG (0x3F) ++ ++#define LSM9DS0_GYRO_ODR_95HZ_VAL (0x00 << 6) ++#define LSM9DS0_GYRO_ODR_190HZ_VAL (0x01 << 6) ++#define LSM9DS0_GYRO_ODR_380HZ_VAL (0x02 << 6) ++#define LSM9DS0_GYRO_ODR_760HZ_VAL (0x03 << 6) ++ ++#define LSM9DS0_ACCEL_POWER_DOWN (0x00 << 4) ++#define LSM9DS0_ACCEL_ODR_3_125HZ_VAL (0x01 << 4) ++#define LSM9DS0_ACCEL_ODR_6_25HZ_VAL (0x02 << 4) ++#define LSM9DS0_ACCEL_ODR_12_5HZ_VAL (0x03 << 4) ++#define LSM9DS0_ACCEL_ODR_25HZ_VAL (0x04 << 4) ++#define LSM9DS0_ACCEL_ODR_50HZ_VAL (0x05 << 4) ++#define LSM9DS0_ACCEL_ODR_100HZ_VAL (0x06 << 4) ++#define LSM9DS0_ACCEL_ODR_200HZ_VAL (0x07 << 4) ++#define LSM9DS0_ACCEL_ODR_400HZ_VAL (0x08 << 4) ++#define LSM9DS0_ACCEL_ODR_800HZ_VAL (0x09 << 4) ++#define LSM9DS0_ACCEL_ODR_1600HZ_VAL (0x0A << 4) ++ ++#define LSM9DS0_ACCEL_FS_MASK (0x03 << 3) ++#define LSM9DS0_ACCEL_FS_2G_VAL (0x00 << 3) ++#define LSM9DS0_ACCEL_FS_4G_VAL (0x01 << 3) ++#define LSM9DS0_ACCEL_FS_6G_VAL (0x02 << 3) ++#define LSM9DS0_ACCEL_FS_8G_VAL (0x03 << 3) ++#define LSM9DS0_ACCEL_FS_16G_VAL (0x04 << 3) ++#define LSM9DS0_ACCEL_FS_2G_GAIN 61 /* ug/LSB */ ++#define LSM9DS0_ACCEL_FS_4G_GAIN 122 /* ug/LSB */ ++#define LSM9DS0_ACCEL_FS_6G_GAIN 183 /* ug/LSB */ ++#define LSM9DS0_ACCEL_FS_8G_GAIN 244 /* ug/LSB */ ++#define LSM9DS0_ACCEL_FS_16G_GAIN 732 /* ug/LSB */ ++ ++#define LSM9DS0_MAGN_ODR_3_125HZ_VAL (0x00 << 2) ++#define LSM9DS0_MAGN_ODR_6_25HZ_VAL (0x01 << 2) ++#define LSM9DS0_MAGN_ODR_12_5HZ_VAL (0x02 << 2) ++#define LSM9DS0_MAGN_ODR_25HZ_VAL (0x03 << 2) ++#define LSM9DS0_MAGN_ODR_50HZ_VAL (0x04 << 2) ++#define LSM9DS0_MAGN_ODR_100HZ_VAL (0x05 << 2) ++ ++#define LSM9DS0_MAGN_FS_MASK (0x03 << 5) ++#define LSM9DS0_MAGN_FS_2GAUSS_VAL (0x00 << 5) ++#define LSM9DS0_MAGN_FS_4GAUSS_VAL (0x01 << 5) ++#define LSM9DS0_MAGN_FS_8GAUSS_VAL (0x02 << 5) ++#define LSM9DS0_MAGN_FS_12GAUSS_VAL (0x03 << 5) ++#define LSM9DS0_MAGN_FS_2GAUSS_GAIN 80 /* ugauss/LSB */ ++#define LSM9DS0_MAGN_FS_4GAUSS_GAIN 160 /* ugauss/LSB */ ++#define LSM9DS0_MAGN_FS_8GAUSS_GAIN 320 /* ugauss/LSB */ ++#define LSM9DS0_MAGN_FS_12GAUSS_GAIN 480 /* ugauss/LSB */ ++ ++#define LSM9DS0_GYRO_FS_MASK (0x03 << 4) ++#define LSM9DS0_GYRO_FS_245DPS_VAL (0x00 << 4) ++#define LSM9DS0_GYRO_FS_500DPS_VAL (0x01 << 4) ++#define LSM9DS0_GYRO_FS_2000DPS_VAL (0x02 << 4) ++#define LSM9DS0_GYRO_FS_245DPS_GAIN 8750 /* udps/LSB */ ++#define LSM9DS0_GYRO_FS_500DPS_GAIN 17500 /* udps/LSB */ ++#define LSM9DS0_GYRO_FS_2000DPS_GAIN 70000 /* udps/LSB */ ++ ++#define LSM9DS0_GYRO_X_EN BIT(1) ++#define LSM9DS0_GYRO_Y_EN BIT(0) ++#define LSM9DS0_GYRO_Z_EN BIT(2) ++#define LSM9DS0_GYRO_POWER_DOWN (0x00 << 3) ++#define LSM9DS0_GYRO_NORMAL_MODE BIT(3) ++#define LSM9DS0_ACCEL_X_EN BIT(0) ++#define LSM9DS0_ACCEL_Y_EN BIT(1) ++#define LSM9DS0_ACCEL_Z_EN BIT(2) ++#define LSM9DS0_TEMP_EN BIT(7) ++#define LSM9DS0_MAGN_LOW_RES_VAL (0x00 << 5) ++#define LSM9DS0_MAGN_HIGH_RES_VAL (0x03 << 5) ++#define LSM9DS0_MAGN_POWER_DOWN (0x02) ++#define LSM9DS0_MAGN_CONT_CONV_MODE (0x00) ++#define LSM9DS0_MAGN_SINGLE_CONV_MODE (0x01) ++ ++#define LSM9DS0_GYRO_ID 0xD4 ++#define LSM9DS0_ACCEL_MAGN_ID 0x49 ++ ++enum { SCAN_INDEX_X, SCAN_INDEX_Y, SCAN_INDEX_Z }; ++enum { ++ SCAN_INDEX_ACCEL_X, SCAN_INDEX_ACCEL_Y, SCAN_INDEX_ACCEL_Z, ++ SCAN_INDEX_MAGN_X, SCAN_INDEX_MAGN_Y, SCAN_INDEX_MAGN_Z ++}; ++enum { GYRO, ACCEL_MAGN }; ++ ++struct lsm9ds0_data { ++ struct i2c_client *client; ++ struct mutex lock; ++ int sensor_type; ++ int gyro_scale; ++ int accel_scale; ++ int magn_scale; ++}; ++ ++struct sensor_fs_avl { ++ unsigned int num; ++ u8 value; ++ unsigned int gain; ++}; ++ ++static const struct sensor_fs_avl lsm9ds0_gyro_fs_avl[3] = { ++ {245, LSM9DS0_GYRO_FS_245DPS_VAL, LSM9DS0_GYRO_FS_245DPS_GAIN}, ++ {500, LSM9DS0_GYRO_FS_500DPS_VAL, LSM9DS0_GYRO_FS_500DPS_GAIN}, ++ {2000, LSM9DS0_GYRO_FS_2000DPS_VAL, LSM9DS0_GYRO_FS_2000DPS_GAIN}, ++}; ++ ++static const struct sensor_fs_avl lsm9ds0_accel_fs_avl[5] = { ++ {2, LSM9DS0_ACCEL_FS_2G_VAL, LSM9DS0_ACCEL_FS_2G_GAIN}, ++ {4, LSM9DS0_ACCEL_FS_4G_VAL, LSM9DS0_ACCEL_FS_4G_GAIN}, ++ {6, LSM9DS0_ACCEL_FS_6G_VAL, LSM9DS0_ACCEL_FS_6G_GAIN}, ++ {8, LSM9DS0_ACCEL_FS_8G_VAL, LSM9DS0_ACCEL_FS_8G_GAIN}, ++ {16, LSM9DS0_ACCEL_FS_16G_VAL, LSM9DS0_ACCEL_FS_16G_GAIN}, ++}; ++ ++static const struct sensor_fs_avl lsm9ds0_magn_fs_avl[4] = { ++ {2, LSM9DS0_MAGN_FS_2GAUSS_VAL, LSM9DS0_MAGN_FS_2GAUSS_GAIN}, ++ {4, LSM9DS0_MAGN_FS_4GAUSS_VAL, LSM9DS0_MAGN_FS_4GAUSS_GAIN}, ++ {8, LSM9DS0_MAGN_FS_8GAUSS_VAL, LSM9DS0_MAGN_FS_8GAUSS_GAIN}, ++ {12, LSM9DS0_MAGN_FS_12GAUSS_VAL, LSM9DS0_MAGN_FS_12GAUSS_GAIN}, ++}; ++ ++static ssize_t lsm9ds0_show_scale_avail(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ //struct iio_dev *indio_dev = dev_to_iio_dev(dev); ++ //struct lsm9ds0_data *data = iio_priv(indio_dev); ++ size_t len = 0; ++ int n; ++ const struct sensor_fs_avl (*avl)[]; ++ ++ if (strcmp(attr->attr.name, "in_gyro_scale_available") == 0) { ++ avl = &lsm9ds0_gyro_fs_avl; ++ n = ARRAY_SIZE(lsm9ds0_gyro_fs_avl); ++ } else if (strcmp(attr->attr.name, "in_accel_scale_available") == 0) { ++ avl = &lsm9ds0_accel_fs_avl; ++ n = ARRAY_SIZE(lsm9ds0_accel_fs_avl); ++ } else if (strcmp(attr->attr.name, "in_magn_scale_available") == 0) { ++ avl = &lsm9ds0_magn_fs_avl; ++ n = ARRAY_SIZE(lsm9ds0_magn_fs_avl); ++ } else { ++ return -EINVAL; ++ } ++ ++ while (n-- > 0) ++ len += scnprintf(buf + len, PAGE_SIZE - len, ++ "0.%06u ", (*avl)[n].gain); ++ buf[len - 1] = '\n'; ++ ++ return len; ++} ++ ++static IIO_DEVICE_ATTR(in_accel_scale_available, S_IRUGO, ++ lsm9ds0_show_scale_avail, NULL, 0); ++static IIO_DEVICE_ATTR(in_magn_scale_available, S_IRUGO, ++ lsm9ds0_show_scale_avail, NULL, 0); ++static IIO_DEVICE_ATTR(in_gyro_scale_available, S_IRUGO, ++ lsm9ds0_show_scale_avail, NULL, 0); ++ ++static struct attribute *lsm9ds0_gyro_attributes[] = { ++ &iio_dev_attr_in_gyro_scale_available.dev_attr.attr, ++ NULL ++}; ++ ++static struct attribute *lsm9ds0_accel_magn_attributes[] = { ++ &iio_dev_attr_in_accel_scale_available.dev_attr.attr, ++ &iio_dev_attr_in_magn_scale_available.dev_attr.attr, ++ NULL ++}; ++ ++static const struct attribute_group lsm9ds0_gyro_group = { ++ .attrs = lsm9ds0_gyro_attributes, ++}; ++ ++static const struct attribute_group lsm9ds0_accel_magn_group = { ++ .attrs = lsm9ds0_accel_magn_attributes, ++}; ++ ++static const struct iio_buffer_setup_ops lsm9ds0_buffer_setup_ops = { ++ .postenable = &iio_triggered_buffer_postenable, ++ .predisable = &iio_triggered_buffer_predisable, ++}; ++ ++static const struct iio_chan_spec lsm9ds0_gyro_channels[] = { ++ { ++ .type = IIO_ANGL_VEL, ++ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), ++ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .modified = 1, ++ .channel2 = IIO_MOD_X, ++ .scan_index = SCAN_INDEX_X, ++ .scan_type = { ++ .sign = 's', ++ .realbits = 16, ++ .storagebits = 16, ++ .shift = 0, ++ .endianness = IIO_LE, ++ }, ++ }, { ++ .type = IIO_ANGL_VEL, ++ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), ++ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .modified = 1, ++ .channel2 = IIO_MOD_Y, ++ .scan_index = SCAN_INDEX_Y, ++ .scan_type = { ++ .sign = 's', ++ .realbits = 16, ++ .storagebits = 16, ++ .shift = 0, ++ .endianness = IIO_LE, ++ }, ++ }, { ++ .type = IIO_ANGL_VEL, ++ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), ++ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .modified = 1, ++ .channel2 = IIO_MOD_Z, ++ .scan_index = SCAN_INDEX_Z, ++ .scan_type = { ++ .sign = 's', ++ .realbits = 16, ++ .storagebits = 16, ++ .shift = 0, ++ .endianness = IIO_LE, ++ }, ++ }, ++ IIO_CHAN_SOFT_TIMESTAMP(3), ++}; ++ ++static const struct iio_chan_spec lsm9ds0_accel_magn_channels[] = { ++ { ++ .type = IIO_ACCEL, ++ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), ++ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .modified = 1, ++ .channel2 = IIO_MOD_X, ++ .scan_index = SCAN_INDEX_ACCEL_X, ++ .scan_type = { ++ .sign = 's', ++ .realbits = 16, ++ .storagebits = 16, ++ .shift = 0, ++ .endianness = IIO_LE, ++ }, ++ }, { ++ .type = IIO_ACCEL, ++ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), ++ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .modified = 1, ++ .channel2 = IIO_MOD_Y, ++ .scan_index = SCAN_INDEX_ACCEL_Y, ++ .scan_type = { ++ .sign = 's', ++ .realbits = 16, ++ .storagebits = 16, ++ .shift = 0, ++ .endianness = IIO_LE, ++ }, ++ }, { ++ .type = IIO_ACCEL, ++ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), ++ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .modified = 1, ++ .channel2 = IIO_MOD_Z, ++ .scan_index = SCAN_INDEX_ACCEL_Z, ++ .scan_type = { ++ .sign = 's', ++ .realbits = 16, ++ .storagebits = 16, ++ .shift = 0, ++ .endianness = IIO_LE, ++ }, ++ }, { ++ .type = IIO_MAGN, ++ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), ++ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .modified = 1, ++ .channel2 = IIO_MOD_X, ++ .scan_index = SCAN_INDEX_MAGN_X, ++ .scan_type = { ++ .sign = 's', ++ .realbits = 16, ++ .storagebits = 16, ++ .shift = 0, ++ .endianness = IIO_LE, ++ }, ++ }, { ++ .type = IIO_MAGN, ++ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), ++ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .modified = 1, ++ .channel2 = IIO_MOD_Y, ++ .scan_index = SCAN_INDEX_MAGN_Y, ++ .scan_type = { ++ .sign = 's', ++ .realbits = 16, ++ .storagebits = 16, ++ .shift = 0, ++ .endianness = IIO_LE, ++ }, ++ }, { ++ .type = IIO_MAGN, ++ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), ++ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .modified = 1, ++ .channel2 = IIO_MOD_Z, ++ .scan_index = SCAN_INDEX_MAGN_Z, ++ .scan_type = { ++ .sign = 's', ++ .realbits = 16, ++ .storagebits = 16, ++ .shift = 0, ++ .endianness = IIO_LE, ++ }, ++ }, ++ IIO_CHAN_SOFT_TIMESTAMP(6), ++}; ++ ++static int lsm9ds0_read_measurements(struct i2c_client *client, ++ u8 reg_address, s16 *x, s16 *y, s16 *z) ++{ ++ int ret; ++ u8 buf[6] = {0}; ++ ++ buf[0] = 0x80 | reg_address; ++ ret = i2c_master_send(client, buf, 1); ++ if (ret < 0) ++ return ret; ++ ++ ret = i2c_master_recv(client, buf, 6); ++ if (ret < 0) ++ return ret; ++ ++ *x = (buf[1] << 8) | buf[0]; ++ *y = (buf[3] << 8) | buf[2]; ++ *z = (buf[5] << 8) | buf[4]; ++ return ret; ++} ++ ++static int lsm9ds0_read_raw(struct iio_dev *iio_dev, ++ struct iio_chan_spec const *channel, ++ int *val, int *val2, long mask) ++{ ++ struct lsm9ds0_data *data = iio_priv(iio_dev); ++ int err = 0; ++ s16 x = 0, y = 0, z = 0; ++ int scale = 0; ++ ++ switch (mask) { ++ case IIO_CHAN_INFO_RAW: ++ mutex_lock(&data->lock); ++ switch (channel->type) { ++ case IIO_ANGL_VEL: ++ err = lsm9ds0_read_measurements(data->client, ++ LSM9DS0_OUT_X_L_G_REG, &x, &y, &z); ++ scale = data->gyro_scale; ++ break; ++ case IIO_ACCEL: ++ err = lsm9ds0_read_measurements(data->client, ++ LSM9DS0_OUT_X_L_A_REG, &x, &y, &z); ++ scale = data->accel_scale; ++ break; ++ case IIO_MAGN: ++ err = lsm9ds0_read_measurements(data->client, ++ LSM9DS0_OUT_X_L_M_REG, &x, &y, &z); ++ scale = data->magn_scale; ++ break; ++ default: ++ return -EINVAL; ++ } ++ mutex_unlock(&data->lock); ++ if (err < 0) ++ goto read_error; ++ ++ switch (channel->channel2) { ++ case IIO_MOD_X: ++ *val = x; ++ break; ++ case IIO_MOD_Y: ++ *val = y; ++ break; ++ case IIO_MOD_Z: ++ *val = z; ++ break; ++ } ++ return IIO_VAL_INT; ++ case IIO_CHAN_INFO_SCALE: ++ *val = 0; ++ switch (channel->type) { ++ case IIO_ANGL_VEL: ++ *val2 = data->gyro_scale; ++ break; ++ case IIO_ACCEL: ++ *val2 = data->accel_scale; ++ break; ++ case IIO_MAGN: ++ *val2 = data->magn_scale; ++ break; ++ default: ++ return -EINVAL; ++ } ++ return IIO_VAL_INT_PLUS_MICRO; ++ default: ++ return -EINVAL; ++ } ++ ++read_error: ++ return err; ++} ++ ++static int lsm9ds0_write_config(struct i2c_client *client, ++ u8 reg_address, u8 mask, u8 value) ++{ ++ u8 reg; ++ s32 ret; ++ ret = i2c_smbus_read_byte_data(client, reg_address); ++ if (ret < 0) ++ return -EINVAL; ++ ++ reg = (u8)ret; ++ reg &= ~mask; ++ reg |= value; ++ ++ ret = i2c_smbus_write_byte_data(client, reg_address, reg); ++ ++ return ret; ++} ++ ++static int lsm9ds0_write_raw(struct iio_dev *indio_dev, ++ struct iio_chan_spec const *channel, ++ int val, int val2, long mask) ++{ ++ struct lsm9ds0_data *data = iio_priv(indio_dev); ++ struct i2c_client *client = data->client; ++ const struct sensor_fs_avl (*avl)[]; ++ int n, i, ret; ++ u8 reg_address, reg_mask, new_value; ++ int *scale_in_data; ++ ++ mutex_lock(&data->lock); ++ switch (mask) { ++ case IIO_CHAN_INFO_SCALE: ++ dev_info(&client->dev, "Vals %d %d\n", val, val2); ++ switch (channel->type) { ++ case IIO_ANGL_VEL: ++ avl = &lsm9ds0_gyro_fs_avl; ++ n = ARRAY_SIZE(lsm9ds0_gyro_fs_avl); ++ reg_address = LSM9DS0_CTRL_REG4_G_REG; ++ reg_mask = LSM9DS0_GYRO_FS_MASK; ++ scale_in_data = &(data->gyro_scale); ++ break; ++ case IIO_ACCEL: ++ avl = &lsm9ds0_accel_fs_avl; ++ n = ARRAY_SIZE(lsm9ds0_accel_fs_avl); ++ reg_address = LSM9DS0_CTRL_REG2_XM_REG; ++ reg_mask = LSM9DS0_ACCEL_FS_MASK; ++ scale_in_data = &(data->accel_scale); ++ break; ++ case IIO_MAGN: ++ avl = &lsm9ds0_magn_fs_avl; ++ n = ARRAY_SIZE(lsm9ds0_magn_fs_avl); ++ reg_address = LSM9DS0_CTRL_REG6_XM_REG; ++ reg_mask = LSM9DS0_MAGN_FS_MASK; ++ scale_in_data = &(data->magn_scale); ++ break; ++ default: ++ ret = -EINVAL; ++ goto done; ++ } ++ ret = -EINVAL; ++ for (i = 0; i < n; i++) { ++ if ((*avl)[i].gain == val2) { ++ ret = 0; ++ new_value = (*avl)[i].value; ++ break; ++ } ++ } ++ if (ret < 0) ++ goto done; ++ ++ ret = lsm9ds0_write_config(client, reg_address, reg_mask, new_value); ++ if (ret < 0) ++ goto done; ++ ++ *scale_in_data = (*avl)[i].gain; ++ break; ++ default: ++ ret = -EINVAL; ++ } ++ ++done: ++ mutex_unlock(&data->lock); ++ return ret; ++} ++ ++static irqreturn_t lsm9ds0_trigger_h(int irq, void *p) ++{ ++ struct iio_poll_func *pf = p; ++ struct iio_dev *indio_dev = pf->indio_dev; ++ struct lsm9ds0_data *data = iio_priv(indio_dev); ++ u32 *buf_data; ++ int i, j; ++ s16 x1, y1, z1, x2, y2, z2; ++ int err; ++ ++ buf_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); ++ if (!buf_data) ++ goto done; ++ ++ mutex_lock(&data->lock); ++ if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) { ++ ++ if (data->sensor_type == GYRO) { ++ err = lsm9ds0_read_measurements(data->client, ++ LSM9DS0_OUT_X_L_G_REG, &x1, &y1, &z1); ++ if (err < 0) ++ goto free_buf; ++ } else if (data->sensor_type == ACCEL_MAGN) { ++ err = lsm9ds0_read_measurements(data->client, ++ LSM9DS0_OUT_X_L_A_REG, &x1, &y1, &z1); ++ if (err < 0) ++ goto free_buf; ++ err = lsm9ds0_read_measurements(data->client, ++ LSM9DS0_OUT_X_L_M_REG, &x2, &y2, &z2); ++ if (err < 0) ++ goto free_buf; ++ } else ++ goto free_buf; ++ ++ for (i = 0, j = 0; ++ i < bitmap_weight(indio_dev->active_scan_mask, indio_dev->masklength); ++ i++, j++) { ++ j = find_next_bit(indio_dev->active_scan_mask, indio_dev->masklength, j); ++ ++ if (data->sensor_type == GYRO) { ++ switch (j) { ++ case SCAN_INDEX_X: ++ buf_data[i] = x1; ++ break; ++ case SCAN_INDEX_Y: ++ buf_data[i] = y1; ++ break; ++ case SCAN_INDEX_Z: ++ buf_data[i] = z1; ++ break; ++ default: ++ break; ++ } ++ } else { ++ switch (j) { ++ case SCAN_INDEX_ACCEL_X: ++ buf_data[i] = x1; ++ break; ++ case SCAN_INDEX_ACCEL_Y: ++ buf_data[i] = y1; ++ break; ++ case SCAN_INDEX_ACCEL_Z: ++ buf_data[i] = z1; ++ break; ++ case SCAN_INDEX_MAGN_X: ++ buf_data[i] = x2; ++ break; ++ case SCAN_INDEX_MAGN_Y: ++ buf_data[i] = y2; ++ break; ++ case SCAN_INDEX_MAGN_Z: ++ buf_data[i] = z2; ++ break; ++ default: ++ break; ++ } ++ } ++ } ++ } ++ ++ iio_push_to_buffers_with_timestamp(indio_dev, buf_data, iio_get_time_ns(indio_dev)); ++ ++free_buf: ++ kfree(buf_data); ++ mutex_unlock(&data->lock); ++ ++done: ++ iio_trigger_notify_done(indio_dev->trig); ++ ++ return IRQ_HANDLED; ++} ++ ++static const struct iio_info lsm9ds0_gyro_info = { ++ .attrs = &lsm9ds0_gyro_group, ++ .read_raw = lsm9ds0_read_raw, ++ .write_raw = lsm9ds0_write_raw, ++ .driver_module = THIS_MODULE, ++}; ++ ++static const struct iio_info lsm9ds0_accel_magn_info = { ++ .attrs = &lsm9ds0_accel_magn_group, ++ .read_raw = lsm9ds0_read_raw, ++ .write_raw = lsm9ds0_write_raw, ++ .driver_module = THIS_MODULE, ++}; ++ ++static int lsm9ds0_gyro_init(struct i2c_client *client) ++{ ++ int ret; ++ struct iio_dev *indio_dev; ++ struct lsm9ds0_data *data; ++ ++ ret = i2c_smbus_write_byte_data(client, LSM9DS0_CTRL_REG1_G_REG, ++ LSM9DS0_GYRO_NORMAL_MODE | LSM9DS0_GYRO_X_EN | ++ LSM9DS0_GYRO_Y_EN | LSM9DS0_GYRO_Z_EN); ++ if (ret < 0) { ++ dev_err(&client->dev, "Failed to write control register 5.\n"); ++ return ret; ++ } ++ ret = i2c_smbus_write_byte_data(client, LSM9DS0_CTRL_REG4_G_REG, ++ LSM9DS0_GYRO_FS_245DPS_VAL); ++ if (ret < 0) { ++ dev_err(&client->dev, "Failed to write control register 4.\n"); ++ return ret; ++ } ++ ++ indio_dev = i2c_get_clientdata(client); ++ data = iio_priv(indio_dev); ++ ++ data->gyro_scale = LSM9DS0_GYRO_FS_245DPS_GAIN; ++ ++ return 0; ++} ++ ++static int lsm9ds0_accel_magn_init(struct i2c_client *client) ++{ ++ int ret; ++ struct iio_dev *indio_dev; ++ struct lsm9ds0_data *data; ++ ++ ret = i2c_smbus_write_byte_data(client, LSM9DS0_CTRL_REG1_XM_REG, ++ LSM9DS0_ACCEL_ODR_100HZ_VAL | LSM9DS0_ACCEL_X_EN | ++ LSM9DS0_ACCEL_Y_EN | LSM9DS0_ACCEL_Z_EN); ++ if (ret < 0) { ++ dev_err(&client->dev, "Failed to write control register 1.\n"); ++ return ret; ++ } ++ ret = i2c_smbus_write_byte_data(client, LSM9DS0_CTRL_REG5_XM_REG, ++ LSM9DS0_TEMP_EN | LSM9DS0_MAGN_HIGH_RES_VAL | LSM9DS0_MAGN_ODR_50HZ_VAL); ++ if (ret < 0) { ++ dev_err(&client->dev, "Failed to write control register 5.\n"); ++ return ret; ++ } ++ ret = i2c_smbus_write_byte_data(client, LSM9DS0_CTRL_REG7_XM_REG, ++ LSM9DS0_MAGN_CONT_CONV_MODE); ++ if (ret < 0) { ++ dev_err(&client->dev, "Failed to write control register 7.\n"); ++ return ret; ++ } ++ ret = i2c_smbus_write_byte_data(client, LSM9DS0_CTRL_REG2_XM_REG, ++ LSM9DS0_ACCEL_FS_2G_VAL); ++ if (ret < 0) { ++ dev_err(&client->dev, "Failed to write control register 2.\n"); ++ return ret; ++ } ++ ret = i2c_smbus_write_byte_data(client, LSM9DS0_CTRL_REG6_XM_REG, ++ LSM9DS0_MAGN_FS_2GAUSS_VAL); ++ if (ret < 0) { ++ dev_err(&client->dev, "Failed to write control register 6.\n"); ++ return ret; ++ } ++ ++ indio_dev = i2c_get_clientdata(client); ++ data = iio_priv(indio_dev); ++ ++ data->accel_scale = LSM9DS0_ACCEL_FS_2G_GAIN; ++ data->magn_scale = LSM9DS0_MAGN_FS_2GAUSS_GAIN; ++ ++ return 0; ++} ++ ++static int lsm9ds0_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct iio_dev *indio_dev; ++ struct lsm9ds0_data *data; ++ int sensor_type; ++ int ret; ++ ++ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) { ++ ret = -ENODEV; ++ goto error_ret; ++ } ++ ++ ret = i2c_smbus_read_byte_data(client, LSM9DS0_WHO_AM_I_REG); ++ if (ret < 0) { ++ ret = -EINVAL; ++ goto error_ret; ++ } ++ if (ret == LSM9DS0_GYRO_ID) { ++ dev_info(&client->dev, "Gyroscope found.\n"); ++ sensor_type = GYRO; ++ } else if (ret == LSM9DS0_ACCEL_MAGN_ID) { ++ dev_info(&client->dev, "Accelerometer and magnetometer found.\n"); ++ sensor_type = ACCEL_MAGN; ++ } else { ++ dev_err(&client->dev, "No LSM9DS0 sensor found.\n"); ++ ret = -ENODEV; ++ goto error_ret; ++ } ++ ++ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); ++ if (!indio_dev) { ++ ret = -ENOMEM; ++ goto error_ret; ++ } ++ ++ data = iio_priv(indio_dev); ++ mutex_init(&data->lock); ++ i2c_set_clientdata(client, indio_dev); ++ data->client = client; ++ data->sensor_type = sensor_type; ++ ++ indio_dev->dev.parent = &client->dev; ++ indio_dev->name = dev_name(&client->dev); ++ indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_TRIGGERED; ++ ++ ++ if (sensor_type == GYRO) { ++ ret = lsm9ds0_gyro_init(client); ++ indio_dev->info = &lsm9ds0_gyro_info; ++ indio_dev->channels = lsm9ds0_gyro_channels; ++ indio_dev->num_channels = ARRAY_SIZE(lsm9ds0_gyro_channels); ++ } else { ++ ret = lsm9ds0_accel_magn_init(client); ++ indio_dev->info = &lsm9ds0_accel_magn_info; ++ indio_dev->channels = lsm9ds0_accel_magn_channels; ++ indio_dev->num_channels = ARRAY_SIZE(lsm9ds0_accel_magn_channels); ++ } ++ if (ret < 0) ++ goto error_free_device; ++ ++ ret = devm_iio_triggered_buffer_setup(&client->dev, ++ indio_dev, ++ NULL, ++ &lsm9ds0_trigger_h, ++ &lsm9ds0_buffer_setup_ops); ++ if (ret < 0) ++ goto error_free_device; ++ ++ ret = iio_device_register(indio_dev); ++ if (ret < 0) ++ goto error_free_device; ++ ++ return 0; ++ ++error_free_device: ++ iio_device_free(indio_dev); ++error_ret: ++ return ret; ++} ++ ++static int lsm9ds0_remove(struct i2c_client *client) ++{ ++ struct iio_dev *indio_dev = i2c_get_clientdata(client); ++ iio_device_unregister(indio_dev); ++ iio_device_free(indio_dev); ++ dev_info(&client->dev, "Driver removed."); ++ return 0; ++} ++ ++static const struct i2c_device_id lsm9ds0_id[] = { ++ { "lsm9ds0_gyro", 0 }, ++ { "lsm9ds0_accel_magn", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, lsm9ds0_id); ++ ++static struct i2c_driver lsm9ds0_driver = { ++ .driver = { ++ .name = "lsm9ds0", ++ .owner = THIS_MODULE, ++ }, ++ .probe = lsm9ds0_probe, ++ .remove = lsm9ds0_remove, ++ .id_table = lsm9ds0_id, ++}; ++module_i2c_driver(lsm9ds0_driver); ++ ++MODULE_AUTHOR("Matija Podravec "); ++MODULE_DESCRIPTION("LSM9DS0 gyroscope, accelerometer, and magnetometer sensor"); ++MODULE_LICENSE("GPL"); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0063-ASoC-PCM3168A-add-TDM-modes-merge-ADC-and-DAC.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0063-ASoC-PCM3168A-add-TDM-modes-merge-ADC-and-DAC.patch new file mode 100644 index 00000000..83b00b71 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0063-ASoC-PCM3168A-add-TDM-modes-merge-ADC-and-DAC.patch @@ -0,0 +1,474 @@ +From a6d896b91938493193cfd0546a14f5c84b73ef8a Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Wed, 13 Apr 2016 15:32:38 +0300 +Subject: [PATCH 042/122] ASoC: PCM3168A: add TDM modes, merge ADC and DAC + +Also disable 16 bit format and enable at start + +Signed-off-by: Andrey Gusakov +--- + sound/soc/codecs/pcm3168a.c | 314 ++++++++++++++++++++++++++++---------------- + sound/soc/codecs/pcm3168a.h | 2 +- + 2 files changed, 202 insertions(+), 114 deletions(-) + +diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c +index b9d1207..28975f1 100644 +--- a/sound/soc/codecs/pcm3168a.c ++++ b/sound/soc/codecs/pcm3168a.c +@@ -22,7 +22,7 @@ + + #include "pcm3168a.h" + +-#define PCM3168A_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ ++#define PCM3168A_FORMATS (/*SNDRV_PCM_FMTBIT_S16_LE | */\ + SNDRV_PCM_FMTBIT_S24_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) +@@ -33,7 +33,11 @@ + #define PCM3168A_FMT_RIGHT_J_16 0x3 + #define PCM3168A_FMT_DSP_A 0x4 + #define PCM3168A_FMT_DSP_B 0x5 +-#define PCM3168A_FMT_DSP_MASK 0x4 ++#define PCM3168A_FMT_I2S_TDM 0x6 ++#define PCM3168A_FMT_LEFT_J_TDM 0x7 ++/* High speed */ ++#define PCM3168A_FMT_I2S_TDMHS 0x8 ++#define PCM3168A_FMT_LEFT_J_TDMHS 0x9 + + #define PCM3168A_NUM_SUPPLIES 6 + static const char *const pcm3168a_supply_names[PCM3168A_NUM_SUPPLIES] = { +@@ -45,12 +49,18 @@ static const char *const pcm3168a_supply_names[PCM3168A_NUM_SUPPLIES] = { + "VCCDA2" + }; + ++#define TDM_MODE_NONE 0 ++#define TDM_MODE_NORM 1 ++#define TDM_MODE_HS 2 ++ + struct pcm3168a_priv { + struct regulator_bulk_data supplies[PCM3168A_NUM_SUPPLIES]; + struct regmap *regmap; + struct clk *scki; +- bool adc_master_mode; +- bool dac_master_mode; ++ bool master_mode; ++ unsigned int tdm; ++ unsigned int slots; ++ unsigned int slot_width; + unsigned long sysclk; + unsigned int adc_fmt; + unsigned int dac_fmt; +@@ -313,32 +323,43 @@ static int pcm3168a_set_dai_sysclk(struct snd_soc_dai *dai, + return 0; + } + +-static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, ++int format_table[3][6] = { ++ [TDM_MODE_NONE] = { ++ [0] = -1, ++ [SND_SOC_DAIFMT_I2S] = PCM3168A_FMT_I2S, ++ [SND_SOC_DAIFMT_LEFT_J] = PCM3168A_FMT_LEFT_J, ++ [SND_SOC_DAIFMT_RIGHT_J] = PCM3168A_FMT_RIGHT_J, ++ [SND_SOC_DAIFMT_DSP_A] = PCM3168A_FMT_DSP_A, ++ [SND_SOC_DAIFMT_DSP_B] = PCM3168A_FMT_DSP_B}, ++ [TDM_MODE_NORM] = { ++ [0] = -1, ++ [SND_SOC_DAIFMT_I2S] = PCM3168A_FMT_I2S_TDM, ++ [SND_SOC_DAIFMT_LEFT_J] = PCM3168A_FMT_LEFT_J_TDM, ++ [SND_SOC_DAIFMT_RIGHT_J] = -1, ++ [SND_SOC_DAIFMT_DSP_A] = -1, ++ [SND_SOC_DAIFMT_DSP_B] = -1}, ++ [TDM_MODE_HS] = { ++ [0] = -1, ++ [SND_SOC_DAIFMT_I2S] = PCM3168A_FMT_I2S_TDMHS, ++ [SND_SOC_DAIFMT_LEFT_J] = PCM3168A_FMT_LEFT_J_TDMHS, ++ [SND_SOC_DAIFMT_RIGHT_J] = -1, ++ [SND_SOC_DAIFMT_DSP_A] = -1, ++ [SND_SOC_DAIFMT_DSP_B] = -1}, ++}; ++ ++static int __pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, + unsigned int format, bool dac) + { + struct snd_soc_codec *codec = dai->codec; + struct pcm3168a_priv *pcm3168a = snd_soc_codec_get_drvdata(codec); +- u32 fmt, reg, mask, shift; ++ u32 reg, mask, shift; ++ int fmt; + bool master_mode; + +- switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { +- case SND_SOC_DAIFMT_LEFT_J: +- fmt = PCM3168A_FMT_LEFT_J; +- break; +- case SND_SOC_DAIFMT_I2S: +- fmt = PCM3168A_FMT_I2S; +- break; +- case SND_SOC_DAIFMT_RIGHT_J: +- fmt = PCM3168A_FMT_RIGHT_J; +- break; +- case SND_SOC_DAIFMT_DSP_A: +- fmt = PCM3168A_FMT_DSP_A; +- break; +- case SND_SOC_DAIFMT_DSP_B: +- fmt = PCM3168A_FMT_DSP_B; +- break; +- default: +- dev_err(codec->dev, "unsupported dai format\n"); ++ fmt = format_table[pcm3168a->tdm][format & SND_SOC_DAIFMT_FORMAT_MASK]; ++ ++ if (fmt < 0) { ++ dev_err(codec->dev, "unsupported dai format of TDM mode\n"); + return -EINVAL; + } + +@@ -354,6 +375,16 @@ static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, + return -EINVAL; + } + ++ if ((pcm3168a->tdm == TDM_MODE_HS) && (master_mode)) { ++ dev_err(codec->dev, "TDM high speed supported only in slave mode\n"); ++ return -EINVAL; ++ } ++ ++ if ((pcm3168a->tdm == TDM_MODE_HS) && (!dac)) { ++ dev_err(codec->dev, "TDM high speed not supported for ADC\n"); ++ return -EINVAL; ++ } ++ + switch (format & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; +@@ -365,31 +396,32 @@ static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, + reg = PCM3168A_DAC_PWR_MST_FMT; + mask = PCM3168A_DAC_FMT_MASK; + shift = PCM3168A_DAC_FMT_SHIFT; +- pcm3168a->dac_master_mode = master_mode; + pcm3168a->dac_fmt = fmt; + } else { + reg = PCM3168A_ADC_MST_FMT; + mask = PCM3168A_ADC_FMTAD_MASK; + shift = PCM3168A_ADC_FMTAD_SHIFT; +- pcm3168a->adc_master_mode = master_mode; + pcm3168a->adc_fmt = fmt; + } + ++ pcm3168a->master_mode = master_mode; ++ + regmap_update_bits(pcm3168a->regmap, reg, mask, fmt << shift); + + return 0; + } + +-static int pcm3168a_set_dai_fmt_dac(struct snd_soc_dai *dai, ++static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, + unsigned int format) + { +- return pcm3168a_set_dai_fmt(dai, format, true); +-} ++ int ret; + +-static int pcm3168a_set_dai_fmt_adc(struct snd_soc_dai *dai, +- unsigned int format) +-{ +- return pcm3168a_set_dai_fmt(dai, format, false); ++ /* dac */ ++ ret = __pcm3168a_set_dai_fmt(dai, format, false); ++ if (ret) ++ return ret; ++ /* adc */ ++ return __pcm3168a_set_dai_fmt(dai, format, true); + } + + static int pcm3168a_hw_params(struct snd_pcm_substream *substream, +@@ -398,125 +430,168 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, + { + struct snd_soc_codec *codec = dai->codec; + struct pcm3168a_priv *pcm3168a = snd_soc_codec_get_drvdata(codec); +- bool tx, master_mode; ++ int bits; ++ bool tx; + u32 val, mask, shift, reg; +- unsigned int rate, fmt, ratio, max_ratio; ++ u32 sample_rate = 0; /* auto */ ++ unsigned int rate, channels, fmt, ratio, max_ratio; + int i, min_frame_size; + + rate = params_rate(params); +- +- ratio = pcm3168a->sysclk / rate; ++ channels = params_channels(params); ++ bits = params->msbits; + + tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; ++ + if (tx) { + max_ratio = PCM3168A_NUM_SCKI_RATIOS_DAC; +- reg = PCM3168A_DAC_PWR_MST_FMT; +- mask = PCM3168A_DAC_MSDA_MASK; +- shift = PCM3168A_DAC_MSDA_SHIFT; +- master_mode = pcm3168a->dac_master_mode; + fmt = pcm3168a->dac_fmt; + } else { + max_ratio = PCM3168A_NUM_SCKI_RATIOS_ADC; +- reg = PCM3168A_ADC_MST_FMT; +- mask = PCM3168A_ADC_MSAD_MASK; +- shift = PCM3168A_ADC_MSAD_SHIFT; +- master_mode = pcm3168a->adc_master_mode; + fmt = pcm3168a->adc_fmt; + } + +- for (i = 0; i < max_ratio; i++) { +- if (pcm3168a_scki_ratios[i] == ratio) +- break; +- } ++ if (pcm3168a->master_mode) { ++ ratio = pcm3168a->sysclk / rate; ++ for (i = 0; i < max_ratio; i++) ++ if (pcm3168a_scki_ratios[i] == ratio) ++ break; + +- if (i == max_ratio) { +- dev_err(codec->dev, "unsupported sysclk ratio\n"); +- return -EINVAL; ++ if (i == max_ratio) { ++ dev_err(codec->dev, "unsupported sysclk ratio: %d\n", ratio); ++ return -EINVAL; ++ } ++ val = i + 1; ++ } else { ++ /* slave mode */ ++ val = 0; + } + +- min_frame_size = params_width(params) * 2; +- switch (min_frame_size) { +- case 32: +- if (master_mode || (fmt != PCM3168A_FMT_RIGHT_J)) { +- dev_err(codec->dev, "32-bit frames are supported only for slave mode using right justified\n"); ++ if (pcm3168a->tdm == TDM_MODE_NONE) { ++ /* one stereo frame size */ ++ min_frame_size = bits * 2; ++ switch (min_frame_size) { ++ case 32: ++ if (pcm3168a->master_mode || ++ (fmt != PCM3168A_FMT_RIGHT_J)) { ++ dev_err(codec->dev, "32-bit frames are supported only for slave mode using right justified\n"); ++ return -EINVAL; ++ } ++ fmt = PCM3168A_FMT_RIGHT_J_16; ++ break; ++ case 48: ++ if (pcm3168a->master_mode || ++ (fmt == PCM3168A_FMT_DSP_A) || ++ (fmt == PCM3168A_FMT_DSP_B)) { ++ dev_err(codec->dev, "48-bit frames not supported in master mode, or slave mode using DSP\n"); ++ return -EINVAL; ++ } ++ break; ++ case 64: ++ break; ++ default: ++ dev_err(codec->dev, "unsupported frame size: %d\n", min_frame_size); + return -EINVAL; + } +- fmt = PCM3168A_FMT_RIGHT_J_16; +- break; +- case 48: +- if (master_mode || (fmt & PCM3168A_FMT_DSP_MASK)) { +- dev_err(codec->dev, "48-bit frames not supported in master mode, or slave mode using DSP\n"); ++ } ++ if ((pcm3168a->tdm == TDM_MODE_NORM) || ++ (pcm3168a->tdm == TDM_MODE_HS)) { ++ /* all channels over one or two line */ ++ min_frame_size = bits * channels; ++ ++ /* single rate */ ++ sample_rate = 1; ++ ++ /* ++ * 256fs for single line DIN0/DOUT0 ++ * 128fs for two lines DIN01/DOU01 ++ */ ++ if ((min_frame_size != 256) && ++ (min_frame_size != 128)) { ++ dev_err(codec->dev, "256/128-bit frames only supported in TDM formats\n"); + return -EINVAL; + } +- break; +- case 64: +- break; +- default: +- dev_err(codec->dev, "unsupported frame size: %d\n", min_frame_size); +- return -EINVAL; + } +- +- if (master_mode) +- val = ((i + 1) << shift); +- else ++ ++ /* Setup ADC in master mode, couse it drives ADC */ ++ if ((pcm3168a->master_mode) || (tx)) { ++ fmt = pcm3168a->dac_fmt; ++ reg = PCM3168A_DAC_PWR_MST_FMT; ++ mask = PCM3168A_DAC_MSDA_MASK | PCM3168A_DAC_FMT_MASK; ++ shift = PCM3168A_DAC_MSDA_SHIFT; ++ /* start DAC */ ++ regmap_update_bits(pcm3168a->regmap, reg, mask, (val << shift) | fmt); ++ } ++ /* Do we need also ADC? */ ++ if (!tx) { ++ fmt = pcm3168a->adc_fmt; ++ reg = PCM3168A_ADC_MST_FMT; ++ mask = PCM3168A_ADC_MSAD_MASK | PCM3168A_ADC_FMTAD_MASK; ++ shift = PCM3168A_ADC_MSAD_SHIFT; ++ /* ADC slave mode only, driven by DAC or CPU DAI */ + val = 0; ++ regmap_update_bits(pcm3168a->regmap, reg, mask, (val << shift) | fmt); ++ } + +- regmap_update_bits(pcm3168a->regmap, reg, mask, val); ++ regmap_update_bits(pcm3168a->regmap, PCM3168A_RST_SMODE, ++ PCM3168A_DAC_SRDA_MASK, ++ sample_rate << PCM3168A_DAC_SRDA_SHIFT); + +- if (tx) { +- mask = PCM3168A_DAC_FMT_MASK; +- shift = PCM3168A_DAC_FMT_SHIFT; +- } else { +- mask = PCM3168A_ADC_FMTAD_MASK; +- shift = PCM3168A_ADC_FMTAD_SHIFT; +- } ++ return 0; ++} + +- regmap_update_bits(pcm3168a->regmap, reg, mask, fmt << shift); ++static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, ++ unsigned int tx_mask, ++ unsigned int rx_mask, ++ int slots, ++ int slot_width) ++{ ++ struct snd_soc_codec *codec = dai->codec; ++ struct pcm3168a_priv *pcm3168a = snd_soc_codec_get_drvdata(codec); ++ ++ if ((slots != 8) && (slots != 4)) ++ return -EINVAL; ++ ++ if ((slot_width != 32) && (slot_width != 24)) ++ return -EINVAL; ++ ++ pcm3168a->slots = slots; ++ pcm3168a->slot_width = slot_width; + + return 0; + } + +-static const struct snd_soc_dai_ops pcm3168a_dac_dai_ops = { +- .set_fmt = pcm3168a_set_dai_fmt_dac, ++static const struct snd_soc_dai_ops pcm3168a_dai_ops = { ++ .set_fmt = pcm3168a_set_dai_fmt, + .set_sysclk = pcm3168a_set_dai_sysclk, ++ .set_tdm_slot = pcm3168a_set_tdm_slot, + .hw_params = pcm3168a_hw_params, + .digital_mute = pcm3168a_digital_mute + }; + +-static const struct snd_soc_dai_ops pcm3168a_adc_dai_ops = { +- .set_fmt = pcm3168a_set_dai_fmt_adc, +- .set_sysclk = pcm3168a_set_dai_sysclk, +- .hw_params = pcm3168a_hw_params +-}; +- +-static struct snd_soc_dai_driver pcm3168a_dais[] = { +- { +- .name = "pcm3168a-dac", +- .playback = { +- .stream_name = "Playback", +- .channels_min = 1, +- .channels_max = 8, +- .rates = SNDRV_PCM_RATE_8000_192000, +- .formats = PCM3168A_FORMATS +- }, +- .ops = &pcm3168a_dac_dai_ops ++static struct snd_soc_dai_driver pcm3168a_dai = { ++ .name = "pcm3168a", ++ .playback = { ++ .stream_name = "Playback", ++ .channels_min = 1, ++ .channels_max = 8, ++ .rates = SNDRV_PCM_RATE_8000_192000, ++ .formats = PCM3168A_FORMATS + }, +- { +- .name = "pcm3168a-adc", +- .capture = { +- .stream_name = "Capture", +- .channels_min = 1, +- .channels_max = 6, +- .rates = SNDRV_PCM_RATE_8000_96000, +- .formats = PCM3168A_FORMATS +- }, +- .ops = &pcm3168a_adc_dai_ops ++ .capture = { ++ .stream_name = "Capture", ++ .channels_min = 1, ++ .channels_max = 8, ++ .rates = SNDRV_PCM_RATE_8000_96000, ++ .formats = PCM3168A_FORMATS + }, ++ .ops = &pcm3168a_dai_ops, ++ .symmetric_rates = 1, + }; + + static const struct reg_default pcm3168a_reg_default[] = { + { PCM3168A_RST_SMODE, PCM3168A_MRST_MASK | PCM3168A_SRST_MASK }, +- { PCM3168A_DAC_PWR_MST_FMT, 0x00 }, ++ { PCM3168A_DAC_PWR_MST_FMT, 0x80 }, + { PCM3168A_DAC_OP_FLT, 0x00 }, + { PCM3168A_DAC_INV, 0x00 }, + { PCM3168A_DAC_MUTE, 0x00 }, +@@ -665,12 +740,25 @@ int pcm3168a_probe(struct device *dev, struct regmap *regmap) + goto err_regulator; + } + ++ /* get TDM mode */ ++ if (dev->of_node) { ++ if (of_get_property(dev->of_node, "tdm", NULL)) ++ pcm3168a->tdm = TDM_MODE_NORM; ++ else if (of_get_property(dev->of_node, "tdmhs", NULL)) ++ pcm3168a->tdm = TDM_MODE_HS; ++ } ++ + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + pm_runtime_idle(dev); + +- ret = snd_soc_register_codec(dev, &pcm3168a_driver, pcm3168a_dais, +- ARRAY_SIZE(pcm3168a_dais)); ++ if (pcm3168a->tdm != TDM_MODE_NONE) { ++ pcm3168a_dai.playback.channels_min = 8; ++ pcm3168a_dai.capture.channels_min = 8; ++ } ++ ++ ret = snd_soc_register_codec(dev, &pcm3168a_driver, ++ &pcm3168a_dai, 1); + if (ret) { + dev_err(dev, "failed to register codec: %d\n", ret); + goto err_regulator; +diff --git a/sound/soc/codecs/pcm3168a.h b/sound/soc/codecs/pcm3168a.h +index 56c8332..658507f 100644 +--- a/sound/soc/codecs/pcm3168a.h ++++ b/sound/soc/codecs/pcm3168a.h +@@ -69,7 +69,7 @@ extern void pcm3168a_remove(struct device *dev); + #define PCM3168A_ADC_MSAD_SHIFT 4 + #define PCM3168A_ADC_MSAD_MASK 0x70 + #define PCM3168A_ADC_FMTAD_SHIFT 0 +-#define PCM3168A_ADC_FMTAD_MASK 0x7 ++#define PCM3168A_ADC_FMTAD_MASK 0xf + + #define PCM3168A_ADC_PWR_HPFB 0x52 + #define PCM3168A_ADC_PSVAD_SHIFT 4 +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0064-drm-bridge-adv7511-Add-frequency-and-vrefresh-limita.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0064-drm-bridge-adv7511-Add-frequency-and-vrefresh-limita.patch new file mode 100644 index 00000000..fffd5c6a --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0064-drm-bridge-adv7511-Add-frequency-and-vrefresh-limita.patch @@ -0,0 +1,96 @@ +From 1b9c44163036d1c28e55d508ffe6d33492e92569 Mon Sep 17 00:00:00 2001 +From: Koji Matsuoka +Date: Thu, 7 Dec 2017 20:10:39 +0900 +Subject: [PATCH 043/122] drm/bridge: adv7511: Add frequency and vrefresh + limitation option + +This patch adds processing of frequency and vrefresh to ADV7511. + +Signed-off-by: Koji Matsuoka +--- + drivers/gpu/drm/bridge/adv7511/adv7511.h | 7 +++++++ + drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 22 ++++++++++++++++++++++ + 2 files changed, 29 insertions(+) + +diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511.h b/drivers/gpu/drm/bridge/adv7511/adv7511.h +index 73d8ccb..8a30267 100644 +--- a/drivers/gpu/drm/bridge/adv7511/adv7511.h ++++ b/drivers/gpu/drm/bridge/adv7511/adv7511.h +@@ -271,6 +271,8 @@ enum adv7511_sync_polarity { + * @sync_pulse: Select the sync pulse + * @vsync_polarity: vsync input signal configuration + * @hsync_polarity: hsync input signal configuration ++ * @limit_vrefresh_option: limit vrefresh option ++ * @limit_freq_option: limit frequency option + */ + struct adv7511_link_config { + unsigned int input_color_depth; +@@ -285,6 +287,9 @@ struct adv7511_link_config { + enum adv7511_input_sync_pulse sync_pulse; + enum adv7511_sync_polarity vsync_polarity; + enum adv7511_sync_polarity hsync_polarity; ++ ++ unsigned int limit_vrefresh_option; ++ unsigned int limit_freq_option; + }; + + /** +@@ -354,6 +359,8 @@ struct adv7511 { + enum adv7511_sync_polarity vsync_polarity; + enum adv7511_sync_polarity hsync_polarity; + bool rgb; ++ unsigned int limit_vref; ++ unsigned int limit_freq; + + struct gpio_desc *gpio_pd; + +diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +index 808021f..470be69 100644 +--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c ++++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +@@ -323,6 +323,8 @@ static void adv7511_set_link_config(struct adv7511 *adv7511, + adv7511->hsync_polarity = config->hsync_polarity; + adv7511->vsync_polarity = config->vsync_polarity; + adv7511->rgb = config->input_colorspace == HDMI_COLORSPACE_RGB; ++ adv7511->limit_vref = config->limit_freq_option; ++ adv7511->limit_freq = config->limit_vrefresh_option; + } + + static void __adv7511_power_on(struct adv7511 *adv7511) +@@ -672,6 +674,16 @@ static enum drm_mode_status adv7511_mode_valid(struct adv7511 *adv7511, + if (mode->clock > 165000) + return MODE_CLOCK_HIGH; + ++ if (adv7511->limit_freq) { ++ if (mode->clock > (adv7511->limit_freq / 1000)) ++ return MODE_CLOCK_HIGH; ++ } ++ ++ if (adv7511->limit_vref) { ++ if (drm_mode_vrefresh(mode) < adv7511->limit_vref) ++ return MODE_BAD; ++ } ++ + return MODE_OK; + } + +@@ -1089,6 +1101,16 @@ static int adv7511_parse_dt(struct device_node *np, + config->vsync_polarity = ADV7511_SYNC_POLARITY_PASSTHROUGH; + config->hsync_polarity = ADV7511_SYNC_POLARITY_PASSTHROUGH; + ++ ret = of_property_read_u32(np, "limit-frequency", ++ &config->limit_vrefresh_option); ++ if (ret < 0) ++ config->limit_vrefresh_option = 0; ++ ++ ret = of_property_read_u32(np, "lower-refresh", ++ &config->limit_freq_option); ++ if (ret < 0) ++ config->limit_freq_option = 0; ++ + return 0; + } + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0066-pci-pcie-rcar-add-regulators-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0066-pci-pcie-rcar-add-regulators-support.patch new file mode 100644 index 00000000..7536dd6a --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0066-pci-pcie-rcar-add-regulators-support.patch @@ -0,0 +1,100 @@ +From 78ade93086080c37638af492c567e049a0ee51e7 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Mon, 24 Jul 2017 20:22:03 +0300 +Subject: [PATCH 044/122] pci: pcie-rcar: add regulators support + +Add PCIE regulators + +Signed-off-by: Andrey Gusakov +--- + drivers/pci/host/pcie-rcar.c | 53 ++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 53 insertions(+) + +diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c +index 46b2622..276d011 100644 +--- a/drivers/pci/host/pcie-rcar.c ++++ b/drivers/pci/host/pcie-rcar.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -158,6 +159,8 @@ struct rcar_pcie { + struct list_head resources; + int root_bus_nr; + struct clk *bus_clk; ++ struct regulator *pcie3v3; /* 3.3V power supply */ ++ struct regulator *pcie1v8; /* 1.8V power supply */ + struct rcar_msi msi; + }; + +@@ -1199,6 +1202,36 @@ static const struct of_device_id rcar_pcie_of_match[] = { + {}, + }; + ++static int rcar_pcie_set_vpcie(struct rcar_pcie *pcie) ++{ ++ struct device *dev = pcie->dev; ++ int err; ++ ++ if (!IS_ERR(pcie->pcie3v3)) { ++ err = regulator_enable(pcie->pcie3v3); ++ if (err) { ++ dev_err(dev, "fail to enable vpcie3v3 regulator\n"); ++ goto err_out; ++ } ++ } ++ ++ if (!IS_ERR(pcie->pcie1v8)) { ++ err = regulator_enable(pcie->pcie1v8); ++ if (err) { ++ dev_err(dev, "fail to enable vpcie1v8 regulator\n"); ++ goto err_disable_3v3; ++ } ++ } ++ ++ return 0; ++ ++err_disable_3v3: ++ if (!IS_ERR(pcie->pcie3v3)) ++ regulator_disable(pcie->pcie3v3); ++err_out: ++ return err; ++} ++ + static int rcar_pcie_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -1217,6 +1250,26 @@ static int rcar_pcie_probe(struct platform_device *pdev) + pcie->dev = dev; + platform_set_drvdata(pdev, pcie); + ++ pcie->pcie3v3 = devm_regulator_get_optional(dev, "pcie3v3"); ++ if (IS_ERR(pcie->pcie3v3)) { ++ if (PTR_ERR(pcie->pcie3v3) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ dev_info(dev, "no pcie3v3 regulator found\n"); ++ } ++ ++ pcie->pcie1v8 = devm_regulator_get_optional(dev, "pcie1v8"); ++ if (IS_ERR(pcie->pcie1v8)) { ++ if (PTR_ERR(pcie->pcie1v8) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ dev_info(dev, "no pcie1v8 regulator found\n"); ++ } ++ ++ err = rcar_pcie_set_vpcie(pcie); ++ if (err) { ++ dev_err(dev, "failed to set pcie regulators\n"); ++ return err; ++ } ++ + err = pci_parse_request_of_pci_ranges(dev, &pcie->resources, NULL); + if (err) + goto err_free_bridge; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0067-ti-st-use-proper-way-to-get-shutdown-gpio.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0067-ti-st-use-proper-way-to-get-shutdown-gpio.patch new file mode 100644 index 00000000..f5c10681 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0067-ti-st-use-proper-way-to-get-shutdown-gpio.patch @@ -0,0 +1,61 @@ +From 1a54ccbce2a39adc024ca62e75d5e2bbefeb8a0f Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Wed, 2 Aug 2017 17:39:56 +0300 +Subject: [PATCH 045/122] ti-st: use proper way to get shutdown gpio + +Signed-off-by: Andrey Gusakov +--- + drivers/misc/ti-st/st_kim.c | 23 ++++++++++++++++++----- + 1 file changed, 18 insertions(+), 5 deletions(-) + +diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c +index 01edf9d..06ebdf5 100644 +--- a/drivers/misc/ti-st/st_kim.c ++++ b/drivers/misc/ti-st/st_kim.c +@@ -32,6 +32,8 @@ + #include + #include + #include ++#include ++#include + + #include + #include +@@ -749,18 +751,29 @@ static struct ti_st_plat_data *get_platform_data(struct device *dev) + + dt_pdata = kzalloc(sizeof(*dt_pdata), GFP_KERNEL); + +- if (!dt_pdata) ++ if (!dt_pdata) { + pr_err("Can't allocate device_tree platform data\n"); ++ return NULL; ++ } + + dt_property = of_get_property(np, "dev_name", &len); +- if (dt_property) +- memcpy(&dt_pdata->dev_name, dt_property, len); +- of_property_read_u32(np, "nshutdown_gpio", +- (u32 *)&dt_pdata->nshutdown_gpio); ++ if (!dt_property) { ++ dev_err(dev, "failed to get tty name\n"); ++ goto err; ++ } ++ memcpy(&dt_pdata->dev_name, dt_property, len); ++ dt_pdata->nshutdown_gpio = of_get_named_gpio(np, "shutdown-gpios", 0); ++ if (!gpio_is_valid(dt_pdata->nshutdown_gpio)) { ++ dev_err(dev, "failed to get shutdown gpio\n"); ++ goto err; ++ } + of_property_read_u32(np, "flow_cntrl", (u32 *)&dt_pdata->flow_cntrl); + of_property_read_u32(np, "baud_rate", (u32 *)&dt_pdata->baud_rate); + + return dt_pdata; ++err: ++ kfree(dt_pdata); ++ return NULL; + } + + static struct dentry *kim_debugfs_dir; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0068-drm-adv7511-use-smbus-to-retrieve-edid.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0068-drm-adv7511-use-smbus-to-retrieve-edid.patch new file mode 100644 index 00000000..56aa71a3 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0068-drm-adv7511-use-smbus-to-retrieve-edid.patch @@ -0,0 +1,53 @@ +From d8e286fd757432df78121151e5174ff64d902add Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Wed, 9 Aug 2017 11:52:22 +0300 +Subject: [PATCH 046/122] drm: adv7511: use smbus to retrieve edid + +Get EDID using smbus protocol instead block i2c transfer +This fixes often checksum errors while retriving EDID at 400kHz bus speed + +Signed-off-by: Vladimir Barinov +--- + drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +index 470be69..06a70f0 100644 +--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c ++++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +@@ -553,18 +553,19 @@ static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block, + * support 64 byte transfers than 256 byte transfers + */ + ++#define CHUNK_SIZE 1 + xfer[0].addr = adv7511->i2c_edid->addr; + xfer[0].flags = 0; + xfer[0].len = 1; + xfer[0].buf = &offset; + xfer[1].addr = adv7511->i2c_edid->addr; + xfer[1].flags = I2C_M_RD; +- xfer[1].len = 64; ++ xfer[1].len = CHUNK_SIZE; + xfer[1].buf = adv7511->edid_buf; + + offset = 0; + +- for (i = 0; i < 4; ++i) { ++ for (i = 0; i < 256/CHUNK_SIZE; ++i) { + ret = i2c_transfer(adv7511->i2c_edid->adapter, xfer, + ARRAY_SIZE(xfer)); + if (ret < 0) +@@ -572,8 +573,8 @@ static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block, + else if (ret != 2) + return -EIO; + +- xfer[1].buf += 64; +- offset += 64; ++ xfer[1].buf += CHUNK_SIZE; ++ offset += CHUNK_SIZE; + } + + adv7511->current_edid_segment = block / 2; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0071-ASoC-add-dummy-device-for-WL18xx-PCM-audio.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0071-ASoC-add-dummy-device-for-WL18xx-PCM-audio.patch new file mode 100644 index 00000000..b9ca6b8e --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0071-ASoC-add-dummy-device-for-WL18xx-PCM-audio.patch @@ -0,0 +1,128 @@ +From 6a414c0d01edc607fee65f5f026011d8d57ffc22 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Thu, 10 Aug 2017 16:29:01 +0300 +Subject: [PATCH 047/122] ASoC: add dummy device for WL18xx PCM audio + +Signed-off-by: Andrey Gusakov +--- + sound/soc/codecs/Kconfig | 3 ++ + sound/soc/codecs/Makefile | 2 ++ + sound/soc/codecs/wl18xx.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 77 insertions(+) + create mode 100644 sound/soc/codecs/wl18xx.c + +diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig +index 8d52af2..bf4f606 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -682,6 +682,9 @@ config SND_SOC_PCM3168A_SPI + config SND_SOC_SI468X + tristate "Dummy sound driver for Si468x radio" + ++config SND_SOC_WL18XX ++ tristate "Dummy sound driver for WL18xx BT" ++ + config SND_SOC_PCM5102A + tristate + +diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile +index 79b4386..57e81a9 100644 +--- a/sound/soc/codecs/Makefile ++++ b/sound/soc/codecs/Makefile +@@ -140,6 +140,7 @@ snd-soc-sigmadsp-i2c-objs := sigmadsp-i2c.o + snd-soc-sigmadsp-regmap-objs := sigmadsp-regmap.o + snd-soc-si476x-objs := si476x.o + snd-soc-si468x-objs := si468x.o ++snd-soc-wl18xx-objs := wl18xx.o + snd-soc-sirf-audio-codec-objs := sirf-audio-codec.o + snd-soc-sn95031-objs := sn95031.o + snd-soc-spdif-tx-objs := spdif_transmitter.o +@@ -379,6 +380,7 @@ obj-$(CONFIG_SND_SOC_SIGMADSP_I2C) += snd-soc-sigmadsp-i2c.o + obj-$(CONFIG_SND_SOC_SIGMADSP_REGMAP) += snd-soc-sigmadsp-regmap.o + obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o + obj-$(CONFIG_SND_SOC_SI468X) += snd-soc-si468x.o ++obj-$(CONFIG_SND_SOC_WL18XX) += snd-soc-wl18xx.o + obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o + obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o + obj-$(CONFIG_SND_SOC_SIRF_AUDIO_CODEC) += sirf-audio-codec.o +diff --git a/sound/soc/codecs/wl18xx.c b/sound/soc/codecs/wl18xx.c +new file mode 100644 +index 0000000..6e52b0f +--- /dev/null ++++ b/sound/soc/codecs/wl18xx.c +@@ -0,0 +1,72 @@ ++/* ++ * Dummy sound driver for wl18xx BT modules ++ * Copyright 2016 Andrey Gusakov ++ * ++ * Based on: Driver for the DFBM-CS320 bluetooth module ++ * Copyright 2011 Lars-Peter Clausen ++ * ++ * 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 ++#include ++#include ++ ++#include ++ ++static struct snd_soc_dai_driver wl18xx_dai = { ++ .name = "wl18xx-pcm", ++ .capture = { ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = SNDRV_PCM_RATE_48000, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE, ++ }, ++ .playback = { ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = SNDRV_PCM_RATE_48000, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE, ++ }, ++}; ++ ++static struct snd_soc_codec_driver soc_codec_dev_wl18xx; ++ ++static int wl18xx_probe(struct platform_device *pdev) ++{ ++ return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wl18xx, ++ &wl18xx_dai, 1); ++} ++ ++static int wl18xx_remove(struct platform_device *pdev) ++{ ++ snd_soc_unregister_codec(&pdev->dev); ++ ++ return 0; ++} ++ ++static const struct of_device_id wl18xx_of_match[] = { ++ { .compatible = "ti,wl18xx-pcm", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, wl18xx_of_match); ++ ++static struct platform_driver wl18xx_driver = { ++ .driver = { ++ .name = "wl18xx-codec", ++ .of_match_table = wl18xx_of_match, ++ .owner = THIS_MODULE, ++ }, ++ .probe = wl18xx_probe, ++ .remove = wl18xx_remove, ++}; ++ ++module_platform_driver(wl18xx_driver); ++ ++MODULE_AUTHOR("Andrey Gusakov "); ++MODULE_DESCRIPTION("ASoC wl18xx driver"); ++MODULE_LICENSE("GPL"); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0072-usb-hub-disable-autosuspend-for-SMSC-hubs.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0072-usb-hub-disable-autosuspend-for-SMSC-hubs.patch new file mode 100644 index 00000000..138c59af --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0072-usb-hub-disable-autosuspend-for-SMSC-hubs.patch @@ -0,0 +1,51 @@ +From 2cba40e9f31caf67fccbec8310a1c9a1e53b2c79 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Fri, 11 Aug 2017 17:30:40 +0300 +Subject: [PATCH 048/122] usb: hub: disable autosuspend for SMSC hubs + +Disable autosuspend for SMSC hubs (USB5534B/USB2134B devices) +This is a workaround for RCar Gen3 XHCI + +Signed-off-by: Vladimir Barinov +--- + drivers/usb/core/hub.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index a9db088..b5e602f 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -36,7 +36,9 @@ + #include "otg_whitelist.h" + + #define USB_VENDOR_GENESYS_LOGIC 0x05e3 ++#define USB_VENDOR_SMSC 0x0424 + #define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND 0x01 ++#define HUB_QUIRK_DISABLE_AUTOSUSPEND 0x02 + + /* Protect struct usb_device->state and ->children members + * Note: Both are also protected by ->dev.sem, except that ->state can +@@ -1797,6 +1799,9 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) + if (id->driver_info & HUB_QUIRK_CHECK_PORT_AUTOSUSPEND) + hub->quirk_check_port_auto_suspend = 1; + ++ if (id->driver_info & HUB_QUIRK_DISABLE_AUTOSUSPEND) ++ pm_runtime_set_autosuspend_delay(&hdev->dev, -1); ++ + if (hub_configure(hub, &desc->endpoint[0].desc) >= 0) + return 0; + +@@ -5269,6 +5274,10 @@ static void hub_event(struct work_struct *work) + } + + static const struct usb_device_id hub_id_table[] = { ++ { .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_CLASS, ++ .idVendor = USB_VENDOR_SMSC, ++ .bInterfaceClass = USB_CLASS_HUB, ++ .driver_info = HUB_QUIRK_DISABLE_AUTOSUSPEND}, + { .match_flags = USB_DEVICE_ID_MATCH_VENDOR + | USB_DEVICE_ID_MATCH_INT_CLASS, + .idVendor = USB_VENDOR_GENESYS_LOGIC, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0073-MOST-dim2-add-device-tree-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0073-MOST-dim2-add-device-tree-support.patch new file mode 100644 index 00000000..18eafcce --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0073-MOST-dim2-add-device-tree-support.patch @@ -0,0 +1,169 @@ +From 951c781c8f921d5e8fc46752fba05f0ffb2f85cd Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Fri, 7 Jul 2017 20:42:36 +0300 +Subject: [PATCH 049/122] MOST: dim2: add device tree support + +Signed-off-by: Andrey Gusakov +--- + drivers/staging/most/hdm-dim2/dim2_hdm.c | 72 ++++++++++++++++++++++---------- + 1 file changed, 50 insertions(+), 22 deletions(-) + +diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c +index df7021c..e3ce23c 100644 +--- a/drivers/staging/most/hdm-dim2/dim2_hdm.c ++++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c +@@ -14,6 +14,7 @@ + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include ++#include + #include + #include + #include +@@ -21,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -98,6 +100,7 @@ struct dim2_hdm { + struct most_interface most_iface; + char name[16 + sizeof "dim2-"]; + void __iomem *io_base; ++ struct clk *clk; + int clk_speed; + struct task_struct *netinfo_task; + wait_queue_head_t netinfo_waitq; +@@ -160,6 +163,27 @@ void dimcb_on_error(u8 error_id, const char *error_message) + error_message); + } + ++static int dim_parce_speed(const char *clock_speed) ++{ ++ if (!strcmp(clock_speed, "256fs")) ++ return CLK_256FS; ++ else if (!strcmp(clock_speed, "512fs")) ++ return CLK_512FS; ++ else if (!strcmp(clock_speed, "1024fs")) ++ return CLK_1024FS; ++ else if (!strcmp(clock_speed, "2048fs")) ++ return CLK_2048FS; ++ else if (!strcmp(clock_speed, "3072fs")) ++ return CLK_3072FS; ++ else if (!strcmp(clock_speed, "4096fs")) ++ return CLK_4096FS; ++ else if (!strcmp(clock_speed, "6144fs")) ++ return CLK_6144FS; ++ else if (!strcmp(clock_speed, "8192fs")) ++ return CLK_8192FS; ++ return -1; ++} ++ + /** + * startup_dim - initialize the dim2 interface + * @pdev: platform device +@@ -173,32 +197,12 @@ static int startup_dim(struct platform_device *pdev) + struct dim2_platform_data *pdata = pdev->dev.platform_data; + u8 hal_ret; + +- dev->clk_speed = -1; +- +- if (clock_speed) { +- if (!strcmp(clock_speed, "256fs")) +- dev->clk_speed = CLK_256FS; +- else if (!strcmp(clock_speed, "512fs")) +- dev->clk_speed = CLK_512FS; +- else if (!strcmp(clock_speed, "1024fs")) +- dev->clk_speed = CLK_1024FS; +- else if (!strcmp(clock_speed, "2048fs")) +- dev->clk_speed = CLK_2048FS; +- else if (!strcmp(clock_speed, "3072fs")) +- dev->clk_speed = CLK_3072FS; +- else if (!strcmp(clock_speed, "4096fs")) +- dev->clk_speed = CLK_4096FS; +- else if (!strcmp(clock_speed, "6144fs")) +- dev->clk_speed = CLK_6144FS; +- else if (!strcmp(clock_speed, "8192fs")) +- dev->clk_speed = CLK_8192FS; +- } ++ if (clock_speed) ++ dev->clk_speed = dim_parce_speed(clock_speed); + + if (dev->clk_speed == -1) { + pr_info("Bad or missing clock speed parameter, using default value: 3072fs\n"); + dev->clk_speed = CLK_3072FS; +- } else { +- pr_info("Selected clock speed: %s\n", clock_speed); + } + if (pdata && pdata->init) { + int ret = pdata->init(pdata, dev->io_base, dev->clk_speed); +@@ -746,6 +750,7 @@ static int dim2_probe(struct platform_device *pdev) + int ret, i; + struct kobject *kobj; + int irq; ++ struct device_node *np = pdev->dev.of_node; + + dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); + if (!dev) +@@ -785,6 +790,14 @@ static int dim2_probe(struct platform_device *pdev) + return ret; + } + ++ dev->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(dev->clk)) { ++ dev_err(&pdev->dev, "cannot get clock\n"); ++ ret = PTR_ERR(dev->clk); ++ return ret; ++ } ++ clk_prepare_enable(dev->clk); ++ + init_waitqueue_head(&dev->netinfo_waitq); + dev->deliver_netinfo = 0; + dev->netinfo_task = kthread_run(&deliver_netinfo_thread, (void *)dev, +@@ -833,6 +846,12 @@ static int dim2_probe(struct platform_device *pdev) + dev->most_iface.poison_channel = poison_channel; + dev->most_iface.request_netinfo = request_netinfo; + ++ if (np) { ++ const char *tmp; ++ if (!of_property_read_string(np, "clock-speed", &tmp)) ++ dev->clk_speed = dim_parce_speed(tmp); ++ } ++ + kobj = most_register_interface(&dev->most_iface); + if (IS_ERR(kobj)) { + ret = PTR_ERR(kobj); +@@ -885,6 +904,8 @@ static int dim2_remove(struct platform_device *pdev) + most_deregister_interface(&dev->most_iface); + kthread_stop(dev->netinfo_task); + ++ clk_disable_unprepare(dev->clk); ++ + /* + * break link to local platform_device_id struct + * to prevent crash by unload platform device module +@@ -901,12 +922,19 @@ static const struct platform_device_id dim2_id[] = { + + MODULE_DEVICE_TABLE(platform, dim2_id); + ++static const struct of_device_id dim2_of_match[] = { ++ { .compatible = "rcar,medialb-dim2", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, dim2_of_match); ++ + static struct platform_driver dim2_driver = { + .probe = dim2_probe, + .remove = dim2_remove, + .id_table = dim2_id, + .driver = { + .name = "hdm_dim2", ++ .of_match_table = dim2_of_match, + }, + }; + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0074-MOST-dim2-add-R-Car3-related-initialization.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0074-MOST-dim2-add-R-Car3-related-initialization.patch new file mode 100644 index 00000000..2e496e03 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0074-MOST-dim2-add-R-Car3-related-initialization.patch @@ -0,0 +1,63 @@ +From acc636a3603d2c541bfc758eea3dfa245a13cc46 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Fri, 7 Jul 2017 20:43:33 +0300 +Subject: [PATCH 050/122] MOST: dim2: add R-Car3 related initialization + +Signed-off-by: Andrey Gusakov +--- + drivers/staging/most/hdm-dim2/dim2_hdm.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c +index e3ce23c..0e5855d 100644 +--- a/drivers/staging/most/hdm-dim2/dim2_hdm.c ++++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + #include + #include "dim2_hal.h" +@@ -184,6 +185,26 @@ static int dim_parce_speed(const char *clock_speed) + return -1; + } + ++static int dim_rcar_init(struct dim2_hdm *dev) ++{ ++ /* PLL */ ++ __raw_writel(0x04, dev->io_base + 0x600); ++ ++ /* 512FS Enable Register */ ++ if (dev->clk_speed == CLK_512FS) ++ __raw_writel(0x01, dev->io_base + 0x604); ++ else ++ __raw_writel(0x00, dev->io_base + 0x604); ++ ++ udelay(200); ++ ++ /* BBCR = 0b11 */ ++ __raw_writel(0x03, dev->io_base + 0x500); ++ __raw_writel(0x0002FF02, dev->io_base + 0x508); ++ ++ return 0; ++} ++ + /** + * startup_dim - initialize the dim2 interface + * @pdev: platform device +@@ -211,6 +232,10 @@ static int startup_dim(struct platform_device *pdev) + return ret; + } + ++ if (1 /* renesas */) { ++ dim_rcar_init(dev); ++ } ++ + pr_info("sync: num of frames per sub-buffer: %u\n", fcnt); + hal_ret = dim_startup(dev->io_base, dev->clk_speed, fcnt); + if (hal_ret != DIM_NO_ERROR) { +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0075-MOST-core-fix-memory-allocation-at-arm64.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0075-MOST-core-fix-memory-allocation-at-arm64.patch new file mode 100644 index 00000000..870754de --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0075-MOST-core-fix-memory-allocation-at-arm64.patch @@ -0,0 +1,54 @@ +From edcebac286e677c3ac5043540bc36fd7c850b9be Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Fri, 7 Jul 2017 20:45:01 +0300 +Subject: [PATCH 051/122] MOST: core: fix memory allocation at arm64 + +Provide valid dev pointer to dma_alloc_coherent + +Signed-off-by: Andrey Gusakov +--- + drivers/staging/most/hdm-dim2/dim2_hdm.c | 1 + + drivers/staging/most/mostcore/core.c | 2 +- + drivers/staging/most/mostcore/mostcore.h | 1 + + 3 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c +index 0e5855d..349eb66 100644 +--- a/drivers/staging/most/hdm-dim2/dim2_hdm.c ++++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c +@@ -870,6 +870,7 @@ static int dim2_probe(struct platform_device *pdev) + dev->most_iface.enqueue = enqueue; + dev->most_iface.poison_channel = poison_channel; + dev->most_iface.request_netinfo = request_netinfo; ++ dev->most_iface.dev = &pdev->dev; + + if (np) { + const char *tmp; +diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c +index 069269d..6952ce6 100644 +--- a/drivers/staging/most/mostcore/core.c ++++ b/drivers/staging/most/mostcore/core.c +@@ -1272,7 +1272,7 @@ static int arm_mbo_chain(struct most_c_obj *c, int dir, + mbo->context = c; + mbo->ifp = c->iface; + mbo->hdm_channel_id = c->channel_id; +- mbo->virt_address = dma_alloc_coherent(NULL, ++ mbo->virt_address = dma_alloc_coherent(c->iface->dev, + coherent_buf_size, + &mbo->bus_address, + GFP_KERNEL); +diff --git a/drivers/staging/most/mostcore/mostcore.h b/drivers/staging/most/mostcore/mostcore.h +index 915e515..19f5d2c 100644 +--- a/drivers/staging/most/mostcore/mostcore.h ++++ b/drivers/staging/most/mostcore/mostcore.h +@@ -252,6 +252,7 @@ struct most_interface { + void (*on_netinfo)(struct most_interface *iface, + unsigned char link_stat, + unsigned char *mac_addr)); ++ struct device *dev; + void *priv; + }; + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0076-MOST-dim2-Renesas-R-Car3-variant.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0076-MOST-dim2-Renesas-R-Car3-variant.patch new file mode 100644 index 00000000..43cabb36 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0076-MOST-dim2-Renesas-R-Car3-variant.patch @@ -0,0 +1,120 @@ +From 77503a746d91ad4bb637c907640d3576e1943e1c Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Mon, 25 Sep 2017 07:16:25 +0300 +Subject: [PATCH 052/122] MOST: dim2: Renesas R-Car3 variant + +- R-Car H3 has 8 FPSB +- remove not existing registers access + +Signed-off-by: Andrey Gusakov +Signed-off-by: Vladimir Barinov +--- + drivers/staging/most/hdm-dim2/dim2_hal.c | 8 ++++---- + drivers/staging/most/hdm-dim2/dim2_hdm.c | 2 +- + drivers/staging/most/hdm-dim2/dim2_reg.h | 18 +++++++++--------- + 3 files changed, 14 insertions(+), 14 deletions(-) + +diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c +index 9148464..a685c5a 100644 +--- a/drivers/staging/most/hdm-dim2/dim2_hal.c ++++ b/drivers/staging/most/hdm-dim2/dim2_hal.c +@@ -532,11 +532,11 @@ static void dim2_cleanup(void) + + /* clear status for all dma channels */ + dimcb_io_write(&g.dim2->ACSR0, 0xFFFFFFFF); +- dimcb_io_write(&g.dim2->ACSR1, 0xFFFFFFFF); ++// dimcb_io_write(&g.dim2->ACSR1, 0xFFFFFFFF); + + /* mask interrupts for all channels */ + dimcb_io_write(&g.dim2->ACMR0, 0); +- dimcb_io_write(&g.dim2->ACMR1, 0); ++// dimcb_io_write(&g.dim2->ACMR1, 0); + } + + static void dim2_initialize(bool enable_6pin, u8 mlb_clock) +@@ -552,7 +552,7 @@ static void dim2_initialize(bool enable_6pin, u8 mlb_clock) + + /* activate all HBI channels */ + dimcb_io_write(&g.dim2->HCMR0, 0xFFFFFFFF); +- dimcb_io_write(&g.dim2->HCMR1, 0xFFFFFFFF); ++// dimcb_io_write(&g.dim2->HCMR1, 0xFFFFFFFF); + + /* enable HBI */ + dimcb_io_write(&g.dim2->HCTL, bit_mask(HCTL_EN_BIT)); +@@ -782,7 +782,7 @@ static u8 init_ctrl_async(struct dim_channel *ch, u8 type, u8 is_tx, + void dim_service_mlb_int_irq(void) + { + dimcb_io_write(&g.dim2->MS0, 0); +- dimcb_io_write(&g.dim2->MS1, 0); ++// dimcb_io_write(&g.dim2->MS1, 0); + } + + u16 dim_norm_ctrl_async_buffer_size(u16 buf_size) +diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c +index 349eb66..2731398 100644 +--- a/drivers/staging/most/hdm-dim2/dim2_hdm.c ++++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c +@@ -53,7 +53,7 @@ MODULE_PARM_DESC(clock_speed, "MediaLB Clock Speed"); + * The values 0, 1, 2, 3, 4, 5, 6 represent corresponding number of frames per + * sub-buffer 1, 2, 4, 8, 16, 32, 64. + */ +-static u8 fcnt = 4; /* (1 << fcnt) frames per subbuffer */ ++static u8 fcnt = 3; /* (1 << fcnt) frames per subbuffer */ + module_param(fcnt, byte, 0000); + MODULE_PARM_DESC(fcnt, "Num of frames per sub-buffer for sync channels as a power of 2"); + +diff --git a/drivers/staging/most/hdm-dim2/dim2_reg.h b/drivers/staging/most/hdm-dim2/dim2_reg.h +index f7d9fbc..30a0f27 100644 +--- a/drivers/staging/most/hdm-dim2/dim2_reg.h ++++ b/drivers/staging/most/hdm-dim2/dim2_reg.h +@@ -20,28 +20,28 @@ + struct dim2_regs { + /* 0x00 */ u32 MLBC0; + /* 0x01 */ u32 rsvd0[1]; +- /* 0x02 */ u32 MLBPC0; ++ /* 0x02 */ u32 MLBPC0; /* no at R-Car3 */ + /* 0x03 */ u32 MS0; + /* 0x04 */ u32 rsvd1[1]; +- /* 0x05 */ u32 MS1; ++ /* 0x05 */ u32 MS1; /* no at R-Car3 */ + /* 0x06 */ u32 rsvd2[2]; + /* 0x08 */ u32 MSS; + /* 0x09 */ u32 MSD; + /* 0x0A */ u32 rsvd3[1]; + /* 0x0B */ u32 MIEN; + /* 0x0C */ u32 rsvd4[1]; +- /* 0x0D */ u32 MLBPC2; +- /* 0x0E */ u32 MLBPC1; ++ /* 0x0D */ u32 MLBPC2; /* no at R-Car3 */ ++ /* 0x0E */ u32 MLBPC1; /* no at R-Car3 */ + /* 0x0F */ u32 MLBC1; + /* 0x10 */ u32 rsvd5[0x10]; + /* 0x20 */ u32 HCTL; + /* 0x21 */ u32 rsvd6[1]; + /* 0x22 */ u32 HCMR0; +- /* 0x23 */ u32 HCMR1; ++ /* 0x23 */ u32 HCMR1; /* no at R-Car3 */ + /* 0x24 */ u32 HCER0; +- /* 0x25 */ u32 HCER1; ++ /* 0x25 */ u32 HCER1; /* no at R-Car3 */ + /* 0x26 */ u32 HCBR0; +- /* 0x27 */ u32 HCBR1; ++ /* 0x27 */ u32 HCBR1; /* no at R-Car3 */ + /* 0x28 */ u32 rsvd7[8]; + /* 0x30 */ u32 MDAT0; + /* 0x31 */ u32 MDAT1; +@@ -57,9 +57,9 @@ struct dim2_regs { + /* 0xF0 */ u32 ACTL; + /* 0xF1 */ u32 rsvd9[3]; + /* 0xF4 */ u32 ACSR0; +- /* 0xF5 */ u32 ACSR1; ++ /* 0xF5 */ u32 ACSR1; /* no at R-Car3 */ + /* 0xF6 */ u32 ACMR0; +- /* 0xF7 */ u32 ACMR1; ++ /* 0xF7 */ u32 ACMR1; /* no at R-Car3 */ + }; + + #define DIM2_MASK(n) (~((~(u32)0) << (n))) +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0077-MOST-dim2-add-timeouts.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0077-MOST-dim2-add-timeouts.patch new file mode 100644 index 00000000..6939d0e9 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0077-MOST-dim2-add-timeouts.patch @@ -0,0 +1,46 @@ +From 19b051580b0d5665ff2ac66cd753b2e7b6bd05b9 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Mon, 25 Sep 2017 07:13:29 +0300 +Subject: [PATCH 053/122] MOST: dim2: add timeouts + +Get rid from loop hang if device not functional + +Signed-off-by: Andrey Gusakov +Signed-off-by: Vladimir Barinov +--- + drivers/staging/most/hdm-dim2/dim2_hal.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c +index a685c5a..d0f78ac 100644 +--- a/drivers/staging/most/hdm-dim2/dim2_hal.c ++++ b/drivers/staging/most/hdm-dim2/dim2_hal.c +@@ -19,6 +19,7 @@ + #include "dim2_reg.h" + #include + #include ++#include + + /* + * Size factor for isochronous DBR buffer. +@@ -149,11 +150,16 @@ static void free_dbr(int offs, int size) + + static void dim2_transfer_madr(u32 val) + { ++ int timeout = 1000; + dimcb_io_write(&g.dim2->MADR, val); + + /* wait for transfer completion */ +- while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1) ++ while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1) { ++ if (--timeout == 0) ++ break; ++ udelay(1); + continue; ++ } + + dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ + } +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0078-MOST-aim-fix-null-pointer-crash.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0078-MOST-aim-fix-null-pointer-crash.patch new file mode 100644 index 00000000..790be166 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0078-MOST-aim-fix-null-pointer-crash.patch @@ -0,0 +1,29 @@ +From a68299f4a29874aee83938274100b323a72d4c3f Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Fri, 27 Oct 2017 17:34:05 +0300 +Subject: [PATCH 054/122] MOST: aim: fix null pointer crash + +The snd_card_new now crashes if first argument NULL + +Signed-off-by: Andrey Gusakov +Signed-off-by: Vladimir Barinov +--- + drivers/staging/most/aim-sound/sound.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/staging/most/aim-sound/sound.c b/drivers/staging/most/aim-sound/sound.c +index ea1366a..71f5a15 100644 +--- a/drivers/staging/most/aim-sound/sound.c ++++ b/drivers/staging/most/aim-sound/sound.c +@@ -595,7 +595,7 @@ static int audio_probe_channel(struct most_interface *iface, int channel_id, + return ret; + } + +- ret = snd_card_new(NULL, -1, card_name, THIS_MODULE, ++ ret = snd_card_new(iface->dev, -1, card_name, THIS_MODULE, + sizeof(*channel), &card); + if (ret < 0) + return ret; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0079-Revert-dmaengine-rcar-dmac-use-TCRB-instead-of-TCR-f.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0079-Revert-dmaengine-rcar-dmac-use-TCRB-instead-of-TCR-f.patch new file mode 100644 index 00000000..ccddaa8f --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0079-Revert-dmaengine-rcar-dmac-use-TCRB-instead-of-TCR-f.patch @@ -0,0 +1,31 @@ +From 462132b2edb18653be39b96fa6168c503d87fa6e Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Thu, 22 Nov 2018 18:19:30 +0300 +Subject: [PATCH 52/61] Revert "dmaengine: rcar-dmac: use TCRB instead of TCR + for "residue" + +The patch breaks SCIF DMA support. + +This partially reverts commit f5927ca87de38ab81a19cbb03e774b57c0e46fed. + +Signed-off-by: Valentine Barshak +--- + drivers/dma/sh/rcar-dmac.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c +index 218c5b0e..f487ceb 100644 +--- a/drivers/dma/sh/rcar-dmac.c ++++ b/drivers/dma/sh/rcar-dmac.c +@@ -1364,7 +1364,7 @@ static unsigned int rcar_dmac_chan_get_residue(struct rcar_dmac_chan *chan, + } + + /* Add the residue for the current chunk. */ +- residue += rcar_dmac_chan_read(chan, RCAR_DMATCRB) << desc->xfer_shift; ++ residue += rcar_dmac_chan_read(chan, RCAR_DMATCR) << desc->xfer_shift; + + return residue; + } +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0082-gpio-pca953x-fix-interrupt-trigger.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0082-gpio-pca953x-fix-interrupt-trigger.patch new file mode 100644 index 00000000..f5767590 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0082-gpio-pca953x-fix-interrupt-trigger.patch @@ -0,0 +1,28 @@ +From 03708e8a6c537752528d865964fd37be56453995 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Fri, 15 Dec 2017 02:23:49 +0300 +Subject: [PATCH] gpio: pca953x: fix interrupt trigger + +The PCA9539 chip has edge sensitive interrupt + +Signed-off-by: Vladimir Barinov +--- + drivers/gpio/gpio-pca953x.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c +index fe731f0..0b3f0d8 100644 +--- a/drivers/gpio/gpio-pca953x.c ++++ b/drivers/gpio/gpio-pca953x.c +@@ -626,7 +626,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, + client->irq, + NULL, + pca953x_irq_handler, +- IRQF_TRIGGER_LOW | IRQF_ONESHOT | ++ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT | + IRQF_SHARED, + dev_name(&client->dev), chip); + if (ret) { +-- +1.9.1 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0090-ASoC-rsnd-fixup-rsnd_ssi_master_clk_start-user-count.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0090-ASoC-rsnd-fixup-rsnd_ssi_master_clk_start-user-count.patch new file mode 100644 index 00000000..eab7b2f9 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0090-ASoC-rsnd-fixup-rsnd_ssi_master_clk_start-user-count.patch @@ -0,0 +1,41 @@ +From 5c621fb5ee767836a56fb1f1f73087d494c2e196 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto +Date: Wed, 30 Jan 2019 14:11:21 +0300 +Subject: [PATCH] ASoC: rsnd: fixup rsnd_ssi_master_clk_start() user count + check + +commit 4d230d1271064 ("ASoC: rsnd: fixup not to call clk_get/set +under non-atomic") added new rsnd_ssi_prepare() and moved +rsnd_ssi_master_clk_start() to .prepare. +But, ssi user count (= ssi->usrcnt) is incremented at .init +(= rsnd_ssi_init()). +Because of these timing exchange, ssi->usrcnt check at +rsnd_ssi_master_clk_start() should be adjusted. +Otherwise, 2nd master clock setup will be no check. +This patch fixup this issue. + +Fixes: commit 4d230d1271064 ("ASoC: rsnd: fixup not to call clk_get/set under non-atomic") +Reported-by: Yusuke Goda +Reported-by: Valentine Barshak +Signed-off-by: Kuninori Morimoto +Tested-by: Yusuke Goda +--- + sound/soc/sh/rcar/ssi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c +index a9d0692..d9f02b0 100644 +--- a/sound/soc/sh/rcar/ssi.c ++++ b/sound/soc/sh/rcar/ssi.c +@@ -287,7 +287,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod, + if (rsnd_ssi_is_multi_slave(mod, io)) + return 0; + +- if (ssi->usrcnt > 1) { ++ if (ssi->usrcnt > 0) { + if (ssi->rate != rate) { + dev_err(dev, "SSI parent/child should use same rate\n"); + return -EINVAL; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0100-LVDS-ar0132-use-raw12.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0100-LVDS-ar0132-use-raw12.patch new file mode 100644 index 00000000..7822b359 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0100-LVDS-ar0132-use-raw12.patch @@ -0,0 +1,152 @@ +From 2869ff3002560ee637f905ed684aaccfac53372e Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Mon, 28 Aug 2017 03:16:21 +0300 +Subject: [PATCH] LVDS: ar0132: use raw12 + +Set CSI2 type raw8 in RCAR CSI2 and set raw12 in ti960 + +Signed-off-by: Vladimir Barinov +--- + arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts | 8 ++++---- + arch/arm64/boot/dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts | 8 ++++---- + arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts | 8 ++++---- + arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 8 ++++---- + drivers/media/i2c/soc_camera/ti964_ti9x3.c | 5 +++-- + 5 files changed, 19 insertions(+), 18 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts b/arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts +index cd23797..5dc5144 100644 +--- a/arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts ++++ b/arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts +@@ -1571,19 +1571,19 @@ + + virtual,channel { + csi2_vc0 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <0>; + }; + csi2_vc1 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <1>; + }; + csi2_vc2 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <2>; + }; + csi2_vc3 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <3>; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts b/arch/arm64/boot/dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts +index f640350..b26ca3a 100644 +--- a/arch/arm64/boot/dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts ++++ b/arch/arm64/boot/dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts +@@ -1578,19 +1578,19 @@ + + virtual,channel { + csi2_vc0 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <0>; + }; + csi2_vc1 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <1>; + }; + csi2_vc2 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <2>; + }; + csi2_vc3 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <3>; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts +index 9837e17..402e894 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts +@@ -511,19 +511,19 @@ + + virtual,channel { + csi2_vc0 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <0>; + }; + csi2_vc1 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <1>; + }; + csi2_vc2 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <2>; + }; + csi2_vc3 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <3>; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +index 4ead97a..6dbcf7f 100644 +--- a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi ++++ b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +@@ -1346,19 +1346,19 @@ + + virtual,channel { + csi2_vc0 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <0>; + }; + csi2_vc1 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <1>; + }; + csi2_vc2 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <2>; + }; + csi2_vc3 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <3>; + }; + }; +diff --git a/drivers/media/i2c/soc_camera/ti964_ti9x3.c b/drivers/media/i2c/soc_camera/ti964_ti9x3.c +index 8dd0f99..caa3f74 100644 +--- a/drivers/media/i2c/soc_camera/ti964_ti9x3.c ++++ b/drivers/media/i2c/soc_camera/ti964_ti9x3.c +@@ -122,12 +122,14 @@ static void ti964_ti9x3_fpdlink3_setup(struct i2c_client *client, int idx) + // reg8_write(client, 0x5d, SENSOR_ID << 1); /* SENSOR I2C native - must be set by sensor driver */ + // reg8_write(client, 0x65, (0x60 + idx) << 1); /* SENSOR I2C translated - must be set by sensor driver */ + if (strcmp(priv->cable_mode, "coax") == 0) { +- reg8_write(client, 0x6d, 0x7f); /* Coax, RAW10 */ ++ reg8_write(client, 0x6d, 0x7e); /* Coax, RAW12 */ + } else if (strcmp(priv->cable_mode, "stp") == 0) { + reg8_write(client, 0x6d, 0x78); /* STP, CSI */ + } + reg8_write(client, 0x70, (idx << 6) | 0x1e); /* CSI data type: yuv422 8-bit, assign VC */ +- reg8_write(client, 0x7c, 0x81); /* BIT(7) - magic to Use RAW10 as 8-bit mode */ ++ reg8_write(client, 0x71, (idx << 6) | 0x2a); /* CSI data type: RAW8 (for RAW12 and bits reodering), assign VC */ ++ reg8_write(client, 0x7c, 0x00); /* RAW12 mode */ ++ reg8_write(client, 0xbc, 0x00); /* Setup minimal time between FV and LV to 3 PCLKs */ + reg8_write(client, 0x6e, 0x88); /* Sensor reset: backchannel GPIO0/GPIO1 set low */ + } + +-- +1.9.1 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0101-LVDS-ar0132-use-context-swwitch.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0101-LVDS-ar0132-use-context-swwitch.patch new file mode 100644 index 00000000..00b62e8c --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0101-LVDS-ar0132-use-context-swwitch.patch @@ -0,0 +1,119 @@ +From d9b811e183d9cae753929cb55e627a29c6a971a8 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Wed, 30 Aug 2017 14:44:29 +0300 +Subject: [PATCH] LVDS: ar0132 use context swwitch + +This enabled context-A-B switch on every frame + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ar0132.c | 19 +++++++++++++++++++ + drivers/media/platform/soc_camera/rcar_vin.c | 23 ++++++++++++++++++----- + 2 files changed, 37 insertions(+), 5 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ar0132.c b/drivers/media/i2c/soc_camera/ar0132.c +index 284c522..2c21fa9 100644 +--- a/drivers/media/i2c/soc_camera/ar0132.c ++++ b/drivers/media/i2c/soc_camera/ar0132.c +@@ -238,11 +238,30 @@ static int ar0132_s_register(struct v4l2_subdev *sd, + } + #endif + ++static int ar0132_isr(struct v4l2_subdev *sd, u32 status, bool *handled) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++#if 1 ++ u16 frame_count = 0; ++ /* read frame counter from sensor */ ++ reg16_read16(client, 0x303a, &frame_count); ++#else ++ static int frame_count = 0; ++ /* get cached frame counter */ ++ frame_count++; ++#endif ++ /* odd frame -> Mode A, even frame -> Mode B */ ++ reg16_write16(client, 0x30b0, frame_count & 1 ? 0x2 : 0x2002); ++ ++ return 0; ++}; ++ + static struct v4l2_subdev_core_ops ar0132_core_ops = { + #ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = ar0132_g_register, + .s_register = ar0132_s_register, + #endif ++ .interrupt_service_routine = ar0132_isr, + }; + + static int ar0132_s_ctrl(struct v4l2_ctrl *ctrl) +diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c +index c39fe63..9ab6f00 100644 +--- a/drivers/media/platform/soc_camera/rcar_vin.c ++++ b/drivers/media/platform/soc_camera/rcar_vin.c +@@ -1292,13 +1292,24 @@ static void rcar_vin_stop_streaming(struct vb2_queue *vq) + .wait_finish = vb2_ops_wait_finish, + }; + ++static irqreturn_t rcar_vin_threaded_irq(int irq, void *data) ++{ ++ struct rcar_vin_priv *priv = data; ++ struct soc_camera_device *icd = priv->ici.icd; ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ ++ v4l2_subdev_call(sd, core, interrupt_service_routine, 0, NULL); ++ ++ return IRQ_HANDLED; ++}; ++ + static irqreturn_t rcar_vin_irq(int irq, void *data) + { + struct rcar_vin_priv *priv = data; + u32 int_status; + bool can_run = false, hw_stopped; + int slot; +- unsigned int handled = 0; ++ unsigned int handled = IRQ_NONE; + int vin_ovr_cnt = 0; + + spin_lock(&priv->lock); +@@ -1309,7 +1320,7 @@ static irqreturn_t rcar_vin_irq(int irq, void *data) + + /* ack interrupts */ + iowrite32(int_status, priv->base + VNINTS_REG); +- handled = 1; ++ handled = IRQ_HANDLED; + + /* overflow occurs */ + if (vin_debug && (int_status & VNINTS_FOS)) { +@@ -1342,6 +1353,8 @@ static irqreturn_t rcar_vin_irq(int irq, void *data) + priv->queue_buf[slot] = NULL; + + can_run = rcar_vin_fill_hw_slot(priv); ++ ++ handled = IRQ_WAKE_THREAD; + } + + if (is_continuous_transfer(priv)) { +@@ -1370,7 +1383,7 @@ static irqreturn_t rcar_vin_irq(int irq, void *data) + done: + spin_unlock(&priv->lock); + +- return IRQ_RETVAL(handled); ++ return handled; + } + + static struct v4l2_subdev *find_csi2(struct rcar_vin_priv *pcdev) +@@ -2930,8 +2943,8 @@ static int rcar_vin_probe(struct platform_device *pdev) + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + +- ret = devm_request_irq(&pdev->dev, irq, rcar_vin_irq, IRQF_SHARED, +- dev_name(&pdev->dev), priv); ++ ret = devm_request_threaded_irq(&pdev->dev, irq, rcar_vin_irq, rcar_vin_threaded_irq, ++ IRQF_SHARED, dev_name(&pdev->dev), priv); + if (ret) + return ret; + +-- +1.9.1 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0103-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0103-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch new file mode 100644 index 00000000..e3f24a67 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0103-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch @@ -0,0 +1,546 @@ +From b6176e313aea415b83d5762db275b2f364f08820 Mon Sep 17 00:00:00 2001 +From: Konstantin Kozhevnikov +Date: Tue, 14 Nov 2017 01:38:51 -0800 +Subject: [PATCH] gpu: drm: rcar-du: Extend VSP1-DRM interface + +Extend VSP1-DRM interface + +Signed-off-by: Konstantin Kozhevnikov +--- + drivers/gpu/drm/drm_framebuffer.c | 1 + + drivers/gpu/drm/rcar-du/rcar_du_drv.h | 5 + + drivers/gpu/drm/rcar-du/rcar_du_kms.c | 42 ++++++- + drivers/gpu/drm/rcar-du/rcar_du_plane.c | 3 +- + drivers/gpu/drm/rcar-du/rcar_du_plane.h | 5 + + drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 209 ++++++++++++++++++++++++++------ + drivers/gpu/drm/rcar-du/rcar_du_vsp.h | 7 +- + 7 files changed, 232 insertions(+), 40 deletions(-) + +diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c +index 398efd6..4a43e15 100644 +--- a/drivers/gpu/drm/drm_framebuffer.c ++++ b/drivers/gpu/drm/drm_framebuffer.c +@@ -192,6 +192,7 @@ static int format_check(const struct drm_mode_fb_cmd2 *r) + case DRM_FORMAT_YVU422: + case DRM_FORMAT_YUV444: + case DRM_FORMAT_YVU444: ++ case DRM_FORMAT_R8: + return 0; + default: + format_name = drm_get_format_name(r->pixel_format); +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h +index 45d6e7e..bdf2612 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h ++++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h +@@ -104,6 +104,11 @@ struct rcar_du_device { + struct { + struct drm_property *alpha; + struct drm_property *colorkey; ++ struct drm_property *alphaplane; ++ struct drm_property *blend; ++ struct drm_property *ckey; ++ struct drm_property *ckey_set0; ++ struct drm_property *ckey_set1; + } props; + + unsigned int dpad0_source; +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c +index e955e92..31b48bc 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c +@@ -10,7 +10,7 @@ + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +- ++//#define DEBUG + #include + #include + #include +@@ -101,6 +101,12 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = { + .planes = 2, + .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC, + .edf = PnDDCR4_EDF_NONE, ++ }, { ++ .fourcc = DRM_FORMAT_R8, ++ .bpp = 8, ++ .planes = 1, ++ .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_8BPP, ++ .edf = PnDDCR4_EDF_NONE, + }, + }; + +@@ -169,6 +175,10 @@ static const struct rcar_du_format_info rcar_vsp_format_infos[] = { + .fourcc = DRM_FORMAT_YVU444, + .bpp = 24, + .planes = 3, ++ }, { ++ .fourcc = DRM_FORMAT_R8, ++ .bpp = 8, ++ .planes = 1, + }, + }; + +@@ -565,6 +575,36 @@ static int rcar_du_properties_init(struct rcar_du_device *rcdu) + if (rcdu->props.colorkey == NULL) + return -ENOMEM; + ++ rcdu->props.alphaplane = ++ drm_property_create(rcdu->ddev, DRM_MODE_PROP_OBJECT, "alphaplane", 1); ++ if (rcdu->props.alphaplane == NULL) ++ return -ENOMEM; ++ rcdu->props.alphaplane->values[0] = DRM_MODE_OBJECT_FB; ++ ++ rcdu->props.blend = ++ drm_property_create_range(rcdu->ddev, 0, "blend", ++ 0, 0xffffffff); ++ if (rcdu->props.blend == NULL) ++ return -ENOMEM; ++ ++ rcdu->props.ckey = ++ drm_property_create_range(rcdu->ddev, 0, "ckey", ++ 0, 0xffffffff); ++ if (rcdu->props.ckey == NULL) ++ return -ENOMEM; ++ ++ rcdu->props.ckey_set0 = ++ drm_property_create_range(rcdu->ddev, 0, "ckey_set0", ++ 0, 0xffffffff); ++ if (rcdu->props.ckey_set0 == NULL) ++ return -ENOMEM; ++ ++ rcdu->props.ckey_set1 = ++ drm_property_create_range(rcdu->ddev, 0, "ckey_set1", ++ 0, 0xffffffff); ++ if (rcdu->props.ckey_set1 == NULL) ++ return -ENOMEM; ++ + return 0; + } + +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c +index e408aa3..2b57f09 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c +@@ -10,7 +10,7 @@ + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +- ++//#define DEBUG + #include + #include + #include +@@ -719,6 +719,7 @@ static const uint32_t formats[] = { + DRM_FORMAT_NV12, + DRM_FORMAT_NV21, + DRM_FORMAT_NV16, ++ DRM_FORMAT_R8, + }; + + int rcar_du_planes_init(struct rcar_du_group *rgrp) +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h +index c1de338..a6065ef 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h ++++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h +@@ -66,6 +66,11 @@ struct rcar_du_plane_state { + + unsigned int alpha; + unsigned int colorkey; ++ struct drm_framebuffer *alphaplane; ++ unsigned int blend; ++ unsigned int ckey; ++ unsigned int ckey_set0; ++ unsigned int ckey_set1; + }; + + static inline struct rcar_du_plane_state * +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +index 770238a..910e0f0 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +@@ -10,7 +10,7 @@ + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +- ++//#define DEBUG + #include + #include + #include +@@ -91,6 +91,16 @@ void rcar_du_vsp_enable(struct rcar_du_crtc *crtc) + + void rcar_du_vsp_disable(struct rcar_du_crtc *crtc) + { ++ struct rcar_du_vsp *vsp = crtc->vsp; ++ struct rcar_du_vsp_plane *primary = &vsp->planes[0]; ++ struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(primary->plane.state); ++ ++ /* ...drop alpha-plane associated with primary plane (why only primary? - tbd) */ ++ if (rstate->alphaplane) { ++ drm_framebuffer_unreference(rstate->alphaplane); ++ rstate->alphaplane = NULL; ++ } ++ + vsp1_du_setup_lif(crtc->vsp->vsp, NULL, crtc->lif_index, + crtc->suspend); + } +@@ -133,6 +143,7 @@ static const u32 formats_kms[] = { + DRM_FORMAT_YVU422, + DRM_FORMAT_YUV444, + DRM_FORMAT_YVU444, ++ DRM_FORMAT_R8, + }; + + static const u32 formats_v4l2[] = { +@@ -162,6 +173,7 @@ static const u32 formats_v4l2[] = { + V4L2_PIX_FMT_YVU422M, + V4L2_PIX_FMT_YUV444M, + V4L2_PIX_FMT_YVU444M, ++ V4L2_PIX_FMT_GREY, + }; + + static const u32 formats_xlate[][2] = { +@@ -184,6 +196,7 @@ static const u32 formats_xlate[][2] = { + { DRM_FORMAT_NV21, V4L2_PIX_FMT_NV21M }, + { DRM_FORMAT_NV16, V4L2_PIX_FMT_NV16M }, + { DRM_FORMAT_NV61, V4L2_PIX_FMT_NV61M }, ++ { DRM_FORMAT_R8, V4L2_PIX_FMT_GREY }, + }; + + static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane) +@@ -226,6 +239,27 @@ static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane) + } + } + ++ /* ...add alpha-plane as needed */ ++ if (state->alphaplane) { ++ i = state->format->planes; ++ cfg.alpha_mem = sg_dma_address(state->sg_tables[i].sgl); ++ cfg.alpha_pitch = state->alphaplane->pitches[0]; ++ pr_debug("alpha-%d: set alpha-mem address: %llx, pitch=%d\n", i, (unsigned long long)cfg.alpha_mem, cfg.alpha_pitch); ++ } ++ ++ /* ...add blending formula as needed */ ++ if (state->blend) { ++ cfg.blend = state->blend; ++ pr_debug("set blending formula: %X\n", cfg.blend); ++ } ++ ++ /* ...add color key property as needed */ ++ if (state->ckey) { ++ cfg.ckey = state->ckey; ++ cfg.ckey_set0 = state->ckey_set0; ++ cfg.ckey_set1 = state->ckey_set1; ++ } ++ + vsp1_du_atomic_update(plane->vsp->vsp, plane->index, &cfg); + } + +@@ -259,6 +293,23 @@ static int rcar_du_vsp_plane_prepare_fb(struct drm_plane *plane, + } + } + ++ /* ...check if we have alpha-plane attached */ ++ if (rstate->alphaplane) { ++ struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(rstate->alphaplane, 0); ++ struct sg_table *sgt = &rstate->sg_tables[i++]; ++ ++ ret = dma_get_sgtable(rcdu->dev, sgt, gem->vaddr, gem->paddr, gem->base.size); ++ if (ret) ++ goto fail; ++ ++ ret = vsp1_du_map_sg(vsp->vsp, sgt); ++ if (!ret) { ++ sg_free_table(sgt); ++ ret = -ENOMEM; ++ goto fail; ++ } ++ } ++ + return 0; + + fail: +@@ -288,6 +339,14 @@ static void rcar_du_vsp_plane_cleanup_fb(struct drm_plane *plane, + vsp1_du_unmap_sg(vsp->vsp, sgt); + sg_free_table(sgt); + } ++ ++ if (rstate->alphaplane) { ++ struct sg_table *sgt = &rstate->sg_tables[i]; ++ ++ vsp1_du_unmap_sg(vsp->vsp, sgt); ++ sg_free_table(sgt); ++ pr_debug("unmap alpha-plane\n"); ++ } + } + + static int rcar_du_vsp_plane_atomic_check(struct drm_plane *plane, +@@ -369,6 +428,11 @@ rcar_du_vsp_plane_atomic_duplicate_state(struct drm_plane *plane) + if (copy == NULL) + return NULL; + ++ if (copy->alphaplane) { ++ drm_framebuffer_reference(copy->alphaplane); ++ pr_debug("duplicate alpha-plane '%p' (refcount=%d)\n", copy->alphaplane, drm_framebuffer_read_refcount(copy->alphaplane)); ++ } ++ + __drm_atomic_helper_plane_duplicate_state(plane, ©->state); + + return ©->state; +@@ -377,8 +441,15 @@ rcar_du_vsp_plane_atomic_duplicate_state(struct drm_plane *plane) + static void rcar_du_vsp_plane_atomic_destroy_state(struct drm_plane *plane, + struct drm_plane_state *state) + { ++ struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(state); ++ ++ if (rstate->alphaplane) { ++ pr_debug("unref alpha-plane '%p' (refcount=%d)\n", rstate->alphaplane, drm_framebuffer_read_refcount(rstate->alphaplane)); ++ drm_framebuffer_unreference(rstate->alphaplane); ++ } ++ + __drm_atomic_helper_plane_destroy_state(state); +- kfree(to_rcar_vsp_plane_state(state)); ++ kfree(rstate); + } + + static void rcar_du_vsp_plane_reset(struct drm_plane *plane) +@@ -386,6 +457,7 @@ static void rcar_du_vsp_plane_reset(struct drm_plane *plane) + struct rcar_du_vsp_plane_state *state; + + if (plane->state) { ++ pr_debug("reset plane '%p'\n", to_rcar_vsp_plane_state(plane->state)->alphaplane); + rcar_du_vsp_plane_atomic_destroy_state(plane, plane->state); + plane->state = NULL; + } +@@ -410,7 +482,30 @@ static int rcar_du_vsp_plane_atomic_set_property(struct drm_plane *plane, + + if (property == rcdu->props.alpha) + rstate->alpha = val; +- else ++ else if (property == rcdu->props.blend) ++ rstate->blend = val; ++ else if (property == rcdu->props.ckey) ++ rstate->ckey = val; ++ else if (property == rcdu->props.ckey_set0) ++ rstate->ckey_set0 = val; ++ else if (property == rcdu->props.ckey_set1) ++ rstate->ckey_set1 = val; ++ else if (property == rcdu->props.alphaplane) { ++ if (rstate->alphaplane) { ++ pr_debug("unref alpha-plane '%p' (refcount=%d)\n", rstate->alphaplane, drm_framebuffer_read_refcount(rstate->alphaplane)); ++ drm_framebuffer_unreference(rstate->alphaplane); ++ } ++ rstate->alphaplane = drm_framebuffer_lookup(plane->dev, val); ++ if (rstate->alphaplane) { ++ pr_debug("use alpha-plane '%p' (refcount=%d)\n", rstate->alphaplane, drm_framebuffer_read_refcount(rstate->alphaplane)); ++ /* ...the way how we handle this leads to a "loss" of plane reference (it is acquired ++ * within "drm_property_change_valid_get" but not returned in symmetric "drm_property_change_valid_put") ++ * Whether it is a bug or was done intentionally, I don't know. For a moment just drop that ++ * extra reference right here ++ */ ++ if (0) drm_framebuffer_unreference(rstate->alphaplane); ++ } ++ } else + return -EINVAL; + + return 0; +@@ -426,6 +521,16 @@ static int rcar_du_vsp_plane_atomic_get_property(struct drm_plane *plane, + + if (property == rcdu->props.alpha) + *val = rstate->alpha; ++ else if (property == rcdu->props.alphaplane) ++ *val = (rstate->alphaplane ? rstate->alphaplane->base.id : 0); ++ else if (property == rcdu->props.blend) ++ *val = rstate->blend; ++ else if (property == rcdu->props.ckey) ++ *val = rstate->ckey; ++ else if (property == rcdu->props.ckey_set0) ++ *val = rstate->ckey_set0; ++ else if (property == rcdu->props.ckey_set1) ++ *val = rstate->ckey_set1; + else + return -EINVAL; + +@@ -442,9 +547,10 @@ int rcar_du_vsp_write_back(struct drm_device *dev, void *data, + struct rcar_du_crtc *rcrtc; + struct rcar_du_device *rcdu; + const struct drm_display_mode *mode; +- u32 pixelformat, bpp; +- unsigned int pitch; ++ struct drm_framebuffer *fb; + dma_addr_t mem[3]; ++ struct sg_table sg_tables[3]; ++ int i = 0; + + obj = drm_mode_object_find(dev, sh->crtc_id, DRM_MODE_OBJECT_CRTC); + if (!obj) +@@ -455,62 +561,79 @@ int rcar_du_vsp_write_back(struct drm_device *dev, void *data, + rcdu = rcrtc->group->dev; + mode = &rcrtc->crtc.state->adjusted_mode; + +- switch (sh->fmt) { +- case DRM_FORMAT_RGB565: +- bpp = 16; +- pixelformat = V4L2_PIX_FMT_RGB565; +- break; +- case DRM_FORMAT_ARGB1555: +- bpp = 16; +- pixelformat = V4L2_PIX_FMT_ARGB555; +- break; +- case DRM_FORMAT_ARGB8888: +- bpp = 32; +- pixelformat = V4L2_PIX_FMT_ABGR32; +- break; +- default: +- dev_err(rcdu->dev, "specified format is not supported.\n"); ++ fb = drm_framebuffer_lookup(dev, sh->buff); ++ if (!fb) { ++ dev_err(dev->dev, "failed to lookup destination framebuffer '%lu'\n", sh->buff); + return -EINVAL; + } + +- pitch = mode->hdisplay * bpp / 8; ++ /* ...check framebuffer is okay */ ++ if ((fb->width != (mode->hdisplay)) || ++ (fb->height != (mode->vdisplay))) { ++ dev_err(dev->dev, "wrong fb mode: %d*%d vs %d*%d\n", fb->width, fb->height, mode->hdisplay, mode->vdisplay); ++ ret = -EINVAL; ++ goto done; ++ } + +- mem[0] = sh->buff; +- mem[1] = 0; +- mem[2] = 0; ++ /* ...need to verify compatibility of output format, I guess - tbd */ + +- if ((sh->width != (mode->hdisplay)) || +- (sh->height != (mode->vdisplay))) +- return -EINVAL; ++ /* ...fill memory planes addresses */ ++ for (i = 0; i < 3; i++) { ++ struct drm_gem_cma_object *gem; ++ struct sg_table *sgt = &sg_tables[i]; ++ gem = drm_fb_cma_get_gem_obj(fb, i); ++ if (!gem) ++ break; ++ ret = dma_get_sgtable(rcdu->dev, sgt, gem->vaddr, gem->paddr, ++ gem->base.size); ++ if (ret) ++ goto done; + +- if ((pitch * mode->vdisplay) > sh->buff_len) +- return -EINVAL; ++ ret = vsp1_du_map_sg(rcrtc->vsp->vsp, sgt); ++ if (!ret) { ++ sg_free_table(sgt); ++ ret = -ENOMEM; ++ goto done; ++ } ++ mem[i] = sg_dma_address(sg_tables[i].sgl) + fb->offsets[i]; ++ } ++ ++ dev_info(dev->dev, "setup write-back (pixfmt=%X, %u*%u, planes: %d)\n", fb->pixel_format, fb->width, fb->height, i); ++ ++ vsp1_du_setup_wb(rcrtc->vsp->vsp, fb->pixel_format, fb->pitches[0], mem, rcrtc->lif_index); + +- vsp1_du_setup_wb(rcrtc->vsp->vsp, pixelformat, pitch, mem, +- rcrtc->lif_index); + ret = vsp1_du_wait_wb(rcrtc->vsp->vsp, WB_STAT_CATP_SET, + rcrtc->lif_index); + if (ret != 0) +- return ret; ++ goto done; + + ret = rcar_du_async_commit(dev, crtc); + if (ret != 0) +- return ret; ++ goto done; + + ret = vsp1_du_wait_wb(rcrtc->vsp->vsp, WB_STAT_CATP_START, + rcrtc->lif_index); + if (ret != 0) +- return ret; ++ goto done; + + ret = rcar_du_async_commit(dev, crtc); + if (ret != 0) +- return ret; ++ goto done; + + ret = vsp1_du_wait_wb(rcrtc->vsp->vsp, WB_STAT_CATP_DONE, + rcrtc->lif_index); + if (ret != 0) +- return ret; ++ goto done; ++ ++done: ++ /* ...unmap all tables */ ++ while (i--) { ++ struct sg_table *sgt = &sg_tables[i]; ++ vsp1_du_unmap_sg(rcrtc->vsp->vsp, sgt); ++ sg_free_table(sgt); ++ } + ++ drm_framebuffer_unreference(fb); + return ret; + } + +@@ -574,6 +697,7 @@ static const uint32_t formats[] = { + DRM_FORMAT_NV21, + DRM_FORMAT_NV16, + DRM_FORMAT_NV61, ++ DRM_FORMAT_R8, + }; + + int rcar_du_vsp_init(struct rcar_du_vsp *vsp) +@@ -653,13 +777,24 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp) + drm_plane_helper_add(&plane->plane, + &rcar_du_vsp_plane_helper_funcs); + ++#if 0 // ...use same set of properties for all planes + if (type == DRM_PLANE_TYPE_PRIMARY) + continue; +- ++#endif + drm_object_attach_property(&plane->plane.base, + rcdu->props.alpha, 255); + drm_plane_create_zpos_property(&plane->plane, 1, 1, + vsp->num_planes - 1); ++ drm_object_attach_property(&plane->plane.base, ++ rcdu->props.alphaplane, 0); ++ drm_object_attach_property(&plane->plane.base, ++ rcdu->props.blend, 0); ++ drm_object_attach_property(&plane->plane.base, ++ rcdu->props.ckey, 0); ++ drm_object_attach_property(&plane->plane.base, ++ rcdu->props.ckey_set0, 0); ++ drm_object_attach_property(&plane->plane.base, ++ rcdu->props.ckey_set1, 0); + } + + return 0; +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.h b/drivers/gpu/drm/rcar-du/rcar_du_vsp.h +index 3fd9cef..2f4aa41 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.h ++++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.h +@@ -52,10 +52,15 @@ struct rcar_du_vsp_plane_state { + struct drm_plane_state state; + + const struct rcar_du_format_info *format; +- struct sg_table sg_tables[3]; ++ struct sg_table sg_tables[4]; + + unsigned int alpha; + unsigned int zpos; ++ struct drm_framebuffer *alphaplane; ++ unsigned int blend; ++ unsigned int ckey; ++ unsigned int ckey_set0; ++ unsigned int ckey_set1; + }; + + static inline struct rcar_du_vsp_plane_state * +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0104-media-vsp1-extend-DRM-VSP1-interface.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0104-media-vsp1-extend-DRM-VSP1-interface.patch new file mode 100644 index 00000000..2f6fa35f --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0104-media-vsp1-extend-DRM-VSP1-interface.patch @@ -0,0 +1,367 @@ +From 0cbfce87c1a16b80111cdcecdd703ad5f75cc6e7 Mon Sep 17 00:00:00 2001 +From: Konstantin Kozhevnikov +Date: Tue, 14 Nov 2017 01:41:06 -0800 +Subject: [PATCH] media: platform: vsp1: extend DRM-VSP1 interface + +- Extend DRM-VSP1 interface +- Add alpha-plane support for VSP1 + +Signed-off-by: Konstantin Kozhevnikov +--- + drivers/media/platform/vsp1/vsp1_bru.c | 13 ++++++++++++- + drivers/media/platform/vsp1/vsp1_dl.c | 5 +++++ + drivers/media/platform/vsp1/vsp1_drm.c | 34 ++++++++++++++++++++++++++------- + drivers/media/platform/vsp1/vsp1_lif.c | 2 +- + drivers/media/platform/vsp1/vsp1_pipe.c | 4 ++++ + drivers/media/platform/vsp1/vsp1_rpf.c | 24 ++++++++++++++++++++--- + drivers/media/platform/vsp1/vsp1_rwpf.c | 2 +- + drivers/media/platform/vsp1/vsp1_rwpf.h | 6 ++++++ + drivers/media/platform/vsp1/vsp1_wpf.c | 4 +++- + include/media/vsp1.h | 6 ++++++ + 10 files changed, 86 insertions(+), 14 deletions(-) + +diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c +index 8b3164a..2c131be 100644 +--- a/drivers/media/platform/vsp1/vsp1_bru.c ++++ b/drivers/media/platform/vsp1/vsp1_bru.c +@@ -387,6 +387,16 @@ static void bru_configure(struct vsp1_entity *entity, + ctrl |= VI6_BRU_CTRL_SRCSEL_BRUIN(i); + + vsp1_bru_write(bru, dl, VI6_BRU_CTRL(i), ctrl); ++ dev_dbg(entity->vsp1->dev, "bru#%d: ctrl=%X\n", i, ctrl); ++ ++ /* ...set blending formula as defined by the input RPF */ ++ if (bru->inputs[i].rpf) { ++ if (bru->inputs[i].rpf->blend) { ++ vsp1_bru_write(bru, dl, VI6_BRU_BLD(i), bru->inputs[i].rpf->blend); ++ dev_dbg(entity->vsp1->dev, "bru#%d(#%d): setup blending formula: %X\n", i, bru->inputs[i].rpf->entity.index, bru->inputs[i].rpf->blend); ++ continue; ++ } ++ } + + /* Harcode the blending formula to + * +@@ -441,7 +451,8 @@ struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1) + v4l2_ctrl_new_std(&bru->ctrls, &bru_ctrl_ops, V4L2_CID_BG_COLOR, + 0, 0xffffff, 1, 0); + +- bru->bgcolor = 0; ++ /* ...for YUV, set black background */ ++ bru->bgcolor = 0x00800080; + + bru->entity.subdev.ctrl_handler = &bru->ctrls; + +diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c +index 478e093..f9c6d09 100644 +--- a/drivers/media/platform/vsp1/vsp1_dl.c ++++ b/drivers/media/platform/vsp1/vsp1_dl.c +@@ -272,6 +272,7 @@ void vsp1_dl_set_addr_auto_fld(struct vsp1_dl_list *dl, struct vsp1_rwpf *rpf) + u32 y_top_index, y_bot_index; + u32 u_top_index, u_bot_index; + u32 v_top_index, v_bot_index; ++ u32 alpha_index; + dma_addr_t y_top_addr, y_bot_addr; + dma_addr_t u_top_addr, u_bot_addr; + dma_addr_t v_top_addr, v_bot_addr; +@@ -287,6 +288,7 @@ void vsp1_dl_set_addr_auto_fld(struct vsp1_dl_list *dl, struct vsp1_rwpf *rpf) + u_bot_index = rpf->entity.index * 8 + 3; + v_top_index = rpf->entity.index * 8 + 4; + v_bot_index = rpf->entity.index * 8 + 5; ++ alpha_index = rpf->entity.index * 8 + 6; + + switch (rpf->fmtinfo->fourcc) { + case V4L2_PIX_FMT_YUV420M: +@@ -359,6 +361,9 @@ void vsp1_dl_set_addr_auto_fld(struct vsp1_dl_list *dl, struct vsp1_rwpf *rpf) + dl->src_dst_addr[u_bot_index].addr = u_bot_addr; + dl->src_dst_addr[v_top_index].addr = v_top_addr; + dl->src_dst_addr[v_bot_index].addr = v_bot_addr; ++ ++ /* ...set alpha-plane address as needed */ ++ dl->src_dst_addr[alpha_index].addr = rpf->mem.alpha; + } + + static struct vsp1_dl_list *vsp1_dl_list_alloc(struct vsp1_dl_manager *dlm) +diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c +index 2681c8a..542ca5a 100644 +--- a/drivers/media/platform/vsp1/vsp1_drm.c ++++ b/drivers/media/platform/vsp1/vsp1_drm.c +@@ -10,7 +10,7 @@ + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +- ++//#define DEBUG + #include + #include + #include +@@ -201,7 +201,9 @@ int vsp1_du_setup_lif(struct device *dev, const struct vsp1_du_lif_config *cfg, + + format.format.width = cfg->width; + format.format.height = cfg->height; +- format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; ++ //format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; ++ /* ...always blend in YUV colorspace; apply conversion as needed */ ++ format.format.code = MEDIA_BUS_FMT_AYUV8_1X32; + format.format.field = V4L2_FIELD_NONE; + + ret = v4l2_subdev_call(&brs->entity.subdev, pad, +@@ -222,7 +224,9 @@ int vsp1_du_setup_lif(struct device *dev, const struct vsp1_du_lif_config *cfg, + + format.format.width = cfg->width; + format.format.height = cfg->height; +- format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; ++ //format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; ++ /* ...always blend in YUV colorspace; apply conversion as needed */ ++ format.format.code = MEDIA_BUS_FMT_AYUV8_1X32; + format.format.field = V4L2_FIELD_NONE; + + ret = v4l2_subdev_call(&bru->entity.subdev, pad, +@@ -241,7 +245,8 @@ int vsp1_du_setup_lif(struct device *dev, const struct vsp1_du_lif_config *cfg, + + format.format.width = cfg->width; + format.format.height = cfg->height; +- format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; ++ //format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; ++ format.format.code = MEDIA_BUS_FMT_AYUV8_1X32; + format.format.field = V4L2_FIELD_NONE; + + if (lif_index == 1) { +@@ -275,6 +280,13 @@ int vsp1_du_setup_lif(struct device *dev, const struct vsp1_du_lif_config *cfg, + format.format.code, lif_index); + + format.pad = RWPF_PAD_SOURCE; ++ /* ...force conversion back to ARGB at the output */ ++ format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; ++ ret = v4l2_subdev_call(&vsp1->wpf[0]->entity.subdev, pad, set_fmt, NULL, ++ &format); ++ if (ret < 0) ++ return ret; ++ + ret = v4l2_subdev_call(&vsp1->wpf[lif_index]->entity.subdev, + pad, get_fmt, NULL, &format); + if (ret < 0) +@@ -402,12 +414,12 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index, + } + + dev_dbg(vsp1->dev, +- "%s: RPF%u: (%u,%u)/%ux%u -> (%u,%u)/%ux%u (%08x), pitch %u dma { %pad, %pad, %pad } zpos %u\n", ++ "%s: RPF%u: (%u,%u)/%ux%u -> (%u,%u)/%ux%u (%08x), pitch %u dma { %pad, %pad, %pad } zpos %u, alpha %pad, ckey %x/%x/%x\n", + __func__, rpf_index, + cfg->src.left, cfg->src.top, cfg->src.width, cfg->src.height, + cfg->dst.left, cfg->dst.top, cfg->dst.width, cfg->dst.height, + cfg->pixelformat, cfg->pitch, &cfg->mem[0], &cfg->mem[1], +- &cfg->mem[2], cfg->zpos); ++ &cfg->mem[2], cfg->zpos, &cfg->alpha_mem, cfg->ckey, cfg->ckey_set0, cfg->ckey_set1); + + /* + * Store the format, stride, memory buffer address, crop and compose +@@ -432,6 +444,11 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index, + rpf->format.plane_fmt[1].bytesperline = cfg->pitch; + rpf->alpha = cfg->alpha; + rpf->interlaced = cfg->interlaced; ++ rpf->alpha_pitch = cfg->alpha_pitch; ++ rpf->ckey = cfg->ckey; ++ rpf->ckey_set0 = cfg->ckey_set0; ++ rpf->ckey_set1 = cfg->ckey_set1; ++ rpf->blend = cfg->blend; + + if ((vsp1->ths_quirks & VSP1_AUTO_FLD_NOT_SUPPORT) && + rpf->interlaced) { +@@ -443,6 +460,7 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index, + rpf->mem.addr[0] = cfg->mem[0]; + rpf->mem.addr[1] = cfg->mem[1]; + rpf->mem.addr[2] = cfg->mem[2]; ++ rpf->mem.alpha = cfg->alpha_mem; + + vsp1->drm->inputs[rpf_index].crop = cfg->src; + vsp1->drm->inputs[rpf_index].compose = cfg->dst; +@@ -517,7 +535,9 @@ static int vsp1_du_setup_rpf_pipe(struct vsp1_device *vsp1, + __func__, format.format.width, format.format.height, + format.format.code, rpf->entity.index); + +- format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; ++ //format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; ++ /* ...do blending in YUV color-space; apply conversion as needed */ ++ format.format.code = MEDIA_BUS_FMT_AYUV8_1X32; + + ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_fmt, NULL, + &format); +diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c +index e79f9e6..753763d 100644 +--- a/drivers/media/platform/vsp1/vsp1_lif.c ++++ b/drivers/media/platform/vsp1/vsp1_lif.c +@@ -162,7 +162,7 @@ static void lif_configure(struct vsp1_entity *entity, + + vsp1_lif_write(lif, dl, VI6_LIF_CTRL(lif->entity.index), + (obth << VI6_LIF_CTRL_OBTH_SHIFT) | +- (format->code == 0 ? VI6_LIF_CTRL_CFMT : 0) | ++ (format->code != MEDIA_BUS_FMT_ARGB8888_1X32 ? VI6_LIF_CTRL_CFMT : 0) | + VI6_LIF_CTRL_REQSEL | VI6_LIF_CTRL_LIF_EN); + + if (soc_device_match(r8a7797)) +diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c +index 8379962..86d4a85 100644 +--- a/drivers/media/platform/vsp1/vsp1_pipe.c ++++ b/drivers/media/platform/vsp1/vsp1_pipe.c +@@ -137,6 +137,10 @@ static const struct vsp1_format_info vsp1_video_formats[] = { + VI6_FMT_Y_U_V_444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 3, { 8, 8, 8 }, false, false, 1, 1, false }, ++ { V4L2_PIX_FMT_GREY, MEDIA_BUS_FMT_Y8_1X8, ++ /*VI6_FMT_Y_U_V_444*/0xDEAD, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | ++ VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, ++ 1, { 8, 0, 0 }, false, false, 0, 0, false }, + }; + + /** +diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c +index ff25470..2cce294 100644 +--- a/drivers/media/platform/vsp1/vsp1_rpf.c ++++ b/drivers/media/platform/vsp1/vsp1_rpf.c +@@ -10,7 +10,7 @@ + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +- ++//#define DEBUG + #include + + #include +@@ -253,8 +253,10 @@ static void rpf_configure(struct vsp1_entity *entity, + if (sink_format->code != source_format->code) + infmt |= VI6_RPF_INFMT_CSC; + ++ dev_dbg(vsp1->dev, "rpf#%d: infmt=%x (csc=%d)\n", rpf->entity.index, infmt, !!(infmt & VI6_RPF_INFMT_CSC)); ++ + vsp1_rpf_write(rpf, dl, VI6_RPF_INFMT, infmt); +- vsp1_rpf_write(rpf, dl, VI6_RPF_DSWAP, fmtinfo->swap); ++ vsp1_rpf_write(rpf, dl, VI6_RPF_DSWAP, fmtinfo->swap | 0xF00); + + /* Output location */ + if (pipe->bru) { +@@ -288,6 +290,15 @@ static void rpf_configure(struct vsp1_entity *entity, + (left << VI6_RPF_LOC_HCOORD_SHIFT) | + (top << VI6_RPF_LOC_VCOORD_SHIFT)); + ++ // ...setup alpha-plane as required ++ if (rpf->mem.alpha) { ++ vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_AI, rpf->mem.alpha); ++ vsp1_rpf_write(rpf, dl, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_ASEL_8B_PLANE); ++ vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ASTRIDE, rpf->alpha_pitch); ++ dev_dbg(vsp1->dev, "rpf#%d: setup alpha-plane: buffer=%pad, stride=%u\n", rpf->entity.index, &rpf->mem.alpha, rpf->alpha_pitch); ++ goto out; ++ } ++ + /* On Gen2 use the alpha channel (extended to 8 bits) when available or + * a fixed alpha value set through the V4L2_CID_ALPHA_COMPONENT control + * otherwise. +@@ -342,7 +353,9 @@ static void rpf_configure(struct vsp1_entity *entity, + if (entity->vsp1->info->gen == 3) { + u32 mult; + +- if ((fmtinfo->alpha) && ++ dev_dbg(vsp1->dev, "rpf#%d: alpha=%x, fourcc=%x\n", rpf->entity.index, fmtinfo->alpha, fmtinfo->fourcc); ++ ++ if (0 && (fmtinfo->alpha) && + (fmtinfo->fourcc != V4L2_PIX_FMT_ARGB555)) { + /* When the input contains an alpha channel enable the + * alpha multiplier. If the input is premultiplied we +@@ -371,9 +384,14 @@ static void rpf_configure(struct vsp1_entity *entity, + rpf->mult_alpha = mult; + } + ++out: + vsp1_rpf_write(rpf, dl, VI6_RPF_MSK_CTRL, 0); + vsp1_rpf_write(rpf, dl, VI6_RPF_CKEY_CTRL, 0); + ++ /* ...set up color keying */ ++ vsp1_rpf_write(rpf, dl, VI6_RPF_CKEY_CTRL, rpf->ckey); ++ vsp1_rpf_write(rpf, dl, VI6_RPF_CKEY_SET0, rpf->ckey_set0); ++ vsp1_rpf_write(rpf, dl, VI6_RPF_CKEY_SET1, rpf->ckey_set1); + } + + static const struct vsp1_entity_operations rpf_entity_ops = { +diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.c b/drivers/media/platform/vsp1/vsp1_rwpf.c +index 66e4d7e..d7e730f 100644 +--- a/drivers/media/platform/vsp1/vsp1_rwpf.c ++++ b/drivers/media/platform/vsp1/vsp1_rwpf.c +@@ -10,7 +10,7 @@ + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +- ++//#define DEBUG + #include + + #include "vsp1.h" +diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h +index fbe6aa6..7553f2b 100644 +--- a/drivers/media/platform/vsp1/vsp1_rwpf.h ++++ b/drivers/media/platform/vsp1/vsp1_rwpf.h +@@ -33,6 +33,7 @@ struct vsp1_video; + + struct vsp1_rwpf_memory { + dma_addr_t addr[3]; ++ dma_addr_t alpha; + }; + + struct vsp1_rwpf { +@@ -72,6 +73,11 @@ struct vsp1_rwpf { + + int write_back; + dma_addr_t buf_addr[3]; ++ unsigned int alpha_pitch; ++ unsigned int ckey; ++ unsigned int ckey_set0; ++ unsigned int ckey_set1; ++ unsigned int blend; + }; + + static inline struct vsp1_rwpf *to_rwpf(struct v4l2_subdev *subdev) +diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c +index e8b3cfb..cb81848 100644 +--- a/drivers/media/platform/vsp1/vsp1_wpf.c ++++ b/drivers/media/platform/vsp1/vsp1_wpf.c +@@ -10,7 +10,7 @@ + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +- ++//#define DEBUG + #include + + #include +@@ -358,6 +358,8 @@ static void wpf_configure(struct vsp1_entity *entity, + + wpf->outfmt = outfmt; + ++ dev_dbg(vsp1->dev, "wpf#%d: outfmt=%x (csc=%d)\n", wpf->entity.index, outfmt, !!(outfmt & VI6_WPF_OUTFMT_CSC)); ++ + vsp1_dl_list_write(dl, VI6_DPR_WPF_FPORCH(wpf->entity.index), + VI6_DPR_WPF_FPORCH_FP_WPFN); + +diff --git a/include/media/vsp1.h b/include/media/vsp1.h +index d5d93ed..c1c3201 100644 +--- a/include/media/vsp1.h ++++ b/include/media/vsp1.h +@@ -53,11 +53,17 @@ struct vsp1_du_atomic_config { + u32 pixelformat; + unsigned int pitch; + dma_addr_t mem[3]; ++ dma_addr_t alpha_mem; ++ unsigned int alpha_pitch; ++ unsigned int ckey; ++ unsigned int ckey_set0; ++ unsigned int ckey_set1; + struct v4l2_rect src; + struct v4l2_rect dst; + unsigned int alpha; + unsigned int zpos; + bool interlaced; ++ unsigned int blend; + }; + + void vsp1_du_atomic_begin(struct device *dev, unsigned int lif_index); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0105-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0105-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch new file mode 100644 index 00000000..42d2e32b --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0105-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch @@ -0,0 +1,538 @@ +From a687bfb7343b33992f92e86c234718c3e21144a0 Mon Sep 17 00:00:00 2001 +From: Konstantin Kozhevnikov +Date: Tue, 14 Nov 2017 01:47:11 -0800 +Subject: [PATCH] media: rcar-imr: IMR driver updates for raw DL + +IMR driver updates for raw DL + +Signed-off-by: Konstantin Kozhevnikov +--- + drivers/media/platform/rcar_imr.c | 209 ++++++++++++++++++++++++++++++-------- + include/uapi/linux/rcar-imr.h | 16 +-- + 2 files changed, 175 insertions(+), 50 deletions(-) + +diff --git a/drivers/media/platform/rcar_imr.c b/drivers/media/platform/rcar_imr.c +index 30c6742..9b601da 100644 +--- a/drivers/media/platform/rcar_imr.c ++++ b/drivers/media/platform/rcar_imr.c +@@ -94,6 +94,7 @@ struct imr_device { + struct v4l2_device v4l2_dev; + struct video_device video_dev; + struct v4l2_m2m_dev *m2m_dev; ++ struct device *alloc_dev; + + /* ...do we need that counter really? framework counts fh structures for us - tbd */ + int refcount; +@@ -117,6 +118,9 @@ struct imr_ctx { + /* ...cropping parameters (in pixels) */ + u16 crop[4]; + ++ /* ...solid color code */ ++ u32 color; ++ + /* ...number of active configurations (debugging) */ + u32 cfg_num; + }; +@@ -192,6 +196,7 @@ struct imr_ctx { + + #define IMR_TRICR 0x6C + #define IMR_TRIC_YCFORM (1 << 31) ++#define IMR_TRICR2 0xA0 + + #define IMR_UVDPOR 0x70 + #define IMR_SUSR 0x74 +@@ -212,6 +217,8 @@ struct imr_ctx { + #define IMR_CPDP_UBDPO_SHIFT 4 + #define IMR_CPDP_VRDPO_SHIFT 0 + ++#define IMR_TPOR 0xF0 ++ + /******************************************************************************* + * Auxiliary helpers + ******************************************************************************/ +@@ -404,11 +411,16 @@ static int imr_queue_setup(struct vb2_queue *vq, + return -EINVAL; + } + ++ /* ...specify default allocator */ ++ alloc_devs[0] = ctx->imr->alloc_dev; ++ + return 0; + } + + static int imr_buf_prepare(struct vb2_buffer *vb) + { ++ struct imr_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); ++ + /* ...unclear yet if we want to prepare a buffer somehow (cache invalidation? - tbd) */ + return 0; + } +@@ -441,9 +453,10 @@ static void imr_buf_finish(struct vb2_buffer *vb) + WARN_ON(!mutex_is_locked(&ctx->imr->mutex)); + + /* ...any special processing of completed buffer? - tbd */ +- v4l2_dbg(3, debug, &ctx->imr->v4l2_dev, "%sput buffer <0x%08llx> done\n", ++ v4l2_dbg(3, debug, &ctx->imr->v4l2_dev, "%sput buffer <0x%08llx> done (err: %d) (ctx=%p)\n", + q->is_output ? "in" : "out", +- vb2_dma_contig_plane_dma_addr(vb, 0)); ++ vb2_dma_contig_plane_dma_addr(vb, 0), ++ vb->state, ctx); + + /* ...unref configuration pointer as needed */ + if (q->is_output) +@@ -568,6 +581,11 @@ static inline u16 __imr_auto_sg_dg_tcm(u32 type) + (type & IMR_MAP_TCM ? IMR_TRIM_TCM : 0); + } + ++static inline u16 __imr_bfe_tme(u32 type) ++{ ++ return (type & IMR_MAP_TME ? IMR_TRIM_TME : 0) | (type & IMR_MAP_BFE ? IMR_TRIM_BFE : 0); ++} ++ + static inline u16 __imr_uvdp(u32 type) + { + return __IMR_MAP_UVDPOR(type) | (type & IMR_MAP_DDP ? (1 << 8) : 0); +@@ -674,15 +692,14 @@ static inline u32 * imr_tri_set_type_b(u32 *dl, void *map, struct imr_mesh *mesh + ******************************************************************************/ + + /* ...calculate length of a type "c" mapping */ +-static inline u32 imr_tri_type_c_get_length(struct imr_vbo *vbo, int item_size) ++static inline u32 imr_tri_type_c_get_length(int num, int item_size) + { +- return ((4 + 3 * item_size) * vbo->num + 4); ++ return ((4 + 3 * item_size) * num + 4); + } + + /* ...set a VBO mapping using absolute coordinates */ +-static inline u32 * imr_tri_set_type_c(u32 *dl, void *map, struct imr_vbo *vbo, int item_size) ++static inline u32 * imr_tri_set_type_c(u32 *dl, void *map, int num, int item_size) + { +- int num = vbo->num; + int i; + + /* ...prepare list of triangles to draw */ +@@ -732,6 +749,7 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg + int h = ctx->queue[0].fmt.height; + int W = ctx->queue[1].fmt.width; + int H = ctx->queue[1].fmt.height; ++ u32 tricr = ctx->color & 0xFFFFFF; + + v4l2_dbg(2, debug, &ctx->imr->v4l2_dev, "setup %u*%u -> %u*%u mapping (type=%x)\n", w, h, W, H, type); + +@@ -739,11 +757,17 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg + *dl++ = IMR_OP_WTS(IMR_TRIMCR, 0xFFFF); + + /* ...set automatic source / destination coordinates generation flags */ +- *dl++ = IMR_OP_WTS(IMR_TRIMSR, __imr_auto_sg_dg_tcm(type) | IMR_TRIM_BFE | IMR_TRIM_TME); ++ *dl++ = IMR_OP_WTS(IMR_TRIMSR, __imr_auto_sg_dg_tcm(type) | __imr_bfe_tme(type)); ++ ++ /* ...that's probably not needed? - tbd */ ++ *dl++ = IMR_OP_SYNCM; + + /* ...set source / destination coordinate precision */ + *dl++ = IMR_OP_WTS(IMR_UVDPOR, __imr_uvdp(type)); + ++ /* ...that's probably not needed? - tbd */ ++ *dl++ = IMR_OP_SYNCM; ++ + /* ...set luminance/chromacity correction parameters precision */ + *dl++ = IMR_OP_WTS(IMR_CPDPOR, __imr_cpdp(type)); + +@@ -776,14 +800,12 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg + } + } else { + u16 src_fmt = (iflags & IMR_F_UV_SWAP ? IMR_CMR2_UVFORM : 0) | (iflags & IMR_F_YUV_SWAP ? IMR_CMR2_YUV422FORM : 0); +- u32 dst_fmt = (oflags & IMR_F_YUV_SWAP ? IMR_TRIC_YCFORM : 0); + + /* ...interleaved input; output is either interleaved or planar */ + *dl++ = IMR_OP_WTS(IMR_CMRCSR2, IMR_CMR2_YUV422E | src_fmt); + + /* ...destination is always YUYV or UYVY */ +- *dl++ = IMR_OP_WTL(IMR_TRICR, 1); +- *dl++ = dst_fmt; ++ tricr |= (oflags & IMR_F_YUV_SWAP ? IMR_TRIC_YCFORM : 0); + + /* ...set precision of Y/UV planes and required correction */ + *dl++ = IMR_OP_WTS(IMR_CMRCSR, src_y_fmt | src_uv_fmt | dst_y_fmt | dst_uv_fmt | __imr_clce(type) | __imr_luce(type)); +@@ -810,6 +832,10 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg + *dl++ = ((w - 2) << 16) | (w - 1); + *dl++ = h - 1; + ++ /* ...set triangle single color */ ++ *dl++ = IMR_OP_WTL(IMR_TRICR, 1); ++ *dl++ = tricr; ++ + /* ...invoke subroutine for triangles drawing */ + *dl++ = IMR_OP_GOSUB; + *dl++ = subaddr; +@@ -852,7 +878,7 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc) + { + struct imr_device *imr = ctx->imr; + struct imr_mesh *mesh; +- struct imr_vbo *vbo; ++ int vbo_num; + struct imr_cfg *cfg; + void *buf, *map; + u32 type; +@@ -925,13 +951,6 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc) + tri_length = imr_tri_type_a_get_length(mesh, item_size); + } + } else { +- /* ...assure we have proper VBO descriptor */ +- if (length < sizeof(struct imr_vbo)) { +- v4l2_err(&imr->v4l2_dev, "invalid vbo specification size: %u\n", length); +- ret = -EINVAL; +- goto out; +- } +- + /* ...make sure there is no automatic-generation flags */ + if (type & (IMR_MAP_AUTODG | IMR_MAP_AUTOSG)) { + v4l2_err(&imr->v4l2_dev, "invalid auto-dg/sg flags: 0x%x\n", type); +@@ -939,22 +958,23 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc) + goto out; + } + +- vbo = (struct imr_vbo *)buf; +- length -= sizeof(struct imr_vbo); +- map = buf + sizeof(struct imr_vbo); ++ map = buf; + + /* ...vertex is given with absolute coordinates */ + item_size += 8; + ++ /* ...calculate total number of triangles */ ++ vbo_num = length / (3 * item_size); ++ + /* ...check the length is sane */ +- if (length != vbo->num * 3 * item_size) { +- v4l2_err(&imr->v4l2_dev, "invalid vbo size: %u*%u*3 != %u\n", vbo->num, item_size, length); ++ if (length != vbo_num * 3 * item_size) { ++ v4l2_err(&imr->v4l2_dev, "invalid vbo size: %u*%u*3 != %u\n", vbo_num, item_size, length); + ret = -EINVAL; + goto out; + } + + /* ...calculate size of trangles drawing subroutine */ +- tri_length = imr_tri_type_c_get_length(vbo, item_size); ++ tri_length = imr_tri_type_c_get_length(vbo_num, item_size); + } + + /* ...DL main program shall start with 8-byte aligned address */ +@@ -975,13 +995,16 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc) + imr_cfg_unref(ctx, ctx->cfg); + + /* ...create new configuration */ +- ctx->cfg = cfg = imr_cfg_create(ctx, dl_size, dl_start_offset); ++ cfg = imr_cfg_create(ctx, dl_size, dl_start_offset); + if (IS_ERR(cfg)) { + ret = PTR_ERR(cfg); ++ ctx->cfg = NULL; + v4l2_err(&imr->v4l2_dev, "failed to create configuration: %d\n", ret); + goto out; + } + ++ ctx->cfg = cfg; ++ + /* ...get pointer to the new display list */ + dl_vaddr = cfg->dl_vaddr; + dl_dma_addr = cfg->dl_dma_addr; +@@ -994,7 +1017,7 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc) + imr_tri_set_type_a(dl_vaddr, map, mesh, item_size); + } + } else { +- imr_tri_set_type_c(dl_vaddr, map, vbo, item_size); ++ imr_tri_set_type_c(dl_vaddr, map, vbo_num, item_size); + } + + /* ...prepare main DL-program */ +@@ -1020,6 +1043,66 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc) + return ret; + } + ++/* ...set mapping data (function called with video device lock held) */ ++static int imr_ioctl_map_raw(struct imr_ctx *ctx, struct imr_map_desc *desc) ++{ ++ struct imr_device *imr = ctx->imr; ++ u32 type = desc->type; ++ u32 length = desc->size; ++ struct imr_cfg *cfg; ++ void *dl_vaddr; ++ u32 dl_size; ++ u32 dl_start_offset; ++ dma_addr_t dl_dma_addr; ++ ++ /* ...calculate main routine length */ ++ dl_size = imr_dl_program_length(ctx); ++ if (!dl_size) { ++ v4l2_err(&imr->v4l2_dev, "format configuration error\n"); ++ return -EINVAL; ++ } ++ ++ /* ...unref current configuration (will not be used by subsequent jobs) */ ++ imr_cfg_unref(ctx, ctx->cfg); ++ ++ /* ...create new configuration (starts with zero offset) */ ++ cfg = imr_cfg_create(ctx, dl_size, 0); ++ if (IS_ERR(cfg)) { ++ ctx->cfg = NULL; ++ v4l2_err(&imr->v4l2_dev, "failed to create configuration: %ld\n", PTR_ERR(cfg)); ++ return PTR_ERR(cfg); ++ } ++ ++ ctx->cfg = cfg; ++ ++ /* ...get pointer to the new display list */ ++ dl_vaddr = cfg->dl_vaddr; ++ ++ /* ...prepare main DL-program */ ++ imr_dl_program_setup(ctx, cfg, type, dl_vaddr, (u32)(uintptr_t)desc->data); ++ ++ /* ...update cropping parameters */ ++ cfg->dst_subpixel = (type & IMR_MAP_DDP ? 2 : 0); ++ ++ /* ...display list updated successfully */ ++ v4l2_dbg(2, debug, &ctx->imr->v4l2_dev, "display-list created: #%u[%08X]:%u[%u]\n", ++ cfg->id, (u32)dl_dma_addr, dl_size, 0); ++ ++ if (debug >= 4) ++ print_hex_dump_bytes("DL-", DUMP_PREFIX_OFFSET, dl_vaddr + dl_start_offset, dl_size - dl_start_offset); ++ ++ /* ...success */ ++ return 0; ++} ++ ++/* ...set mapping data (function called with video device lock held) */ ++static int imr_ioctl_color(struct imr_ctx *ctx, u32 color) ++{ ++ ctx->color = color; ++ ++ return 0; ++} ++ + /******************************************************************************* + * V4L2 I/O controls + ******************************************************************************/ +@@ -1183,7 +1266,7 @@ static int imr_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) + WARN_ON(!mutex_is_locked(&ctx->imr->mutex)); + + /* ...verify the configuration is complete */ +- if (!V4L2_TYPE_IS_OUTPUT(buf->type) && !ctx->cfg) { ++ if (!ctx->cfg) { + v4l2_err(&ctx->imr->v4l2_dev, "stream configuration is not complete\n"); + return -EINVAL; + } +@@ -1265,6 +1348,14 @@ static long imr_default(struct file *file, void *fh, bool valid_prio, unsigned i + /* ...set mesh data */ + return imr_ioctl_map(ctx, (struct imr_map_desc *)arg); + ++ case VIDIOC_IMR_MESH_RAW: ++ /* ...set mesh data */ ++ return imr_ioctl_map_raw(ctx, (struct imr_map_desc *)arg); ++ ++ case VIDIOC_IMR_COLOR: ++ /* ...set solid color code */ ++ return imr_ioctl_color(ctx, *(u32 *)arg); ++ + default: + return -ENOIOCTLCMD; + } +@@ -1326,6 +1417,9 @@ static int imr_open(struct file *file) + /* ...set default cropping parameters */ + ctx->crop[1] = ctx->crop[3] = 0x3FF; + ++ /* ...set default color */ ++ ctx->color = 0x808080; ++ + /* ...initialize M2M processing context */ + ctx->m2m_ctx = v4l2_m2m_ctx_init(imr->m2m_dev, ctx, imr_queue_init); + if (IS_ERR(ctx->m2m_ctx)) { +@@ -1418,8 +1512,11 @@ static unsigned int imr_poll(struct file *file, struct poll_table_struct *wait) + return -ERESTARTSYS; + + res = v4l2_m2m_poll(file, ctx->m2m_ctx, wait); ++ + mutex_unlock(&imr->mutex); + ++ v4l2_dbg(3, debug, &imr->v4l2_dev, "poll result: %X (ctx=%p)\n", res, ctx); ++ + return res; + } + +@@ -1453,7 +1550,6 @@ static const struct v4l2_file_operations imr_fops = { + * M2M device interface + ******************************************************************************/ + +-#if 0 + /* ...job cleanup function */ + static void imr_cleanup(struct imr_ctx *ctx) + { +@@ -1473,17 +1569,16 @@ static void imr_cleanup(struct imr_ctx *ctx) + /* ...release lock before we mark current job as finished */ + spin_unlock_irqrestore(&imr->lock, flags); + } +-#endif + + /* ...job execution function */ + static void imr_device_run(void *priv) + { +- struct imr_ctx *ctx = priv; +- struct imr_device *imr = ctx->imr; +- struct imr_cfg *cfg; +- struct vb2_buffer *src_buf, *dst_buf; +- u32 src_addr, dst_addr; +- unsigned long flags; ++ struct imr_ctx *ctx = priv; ++ struct imr_device *imr = ctx->imr; ++ struct imr_cfg *cfg; ++ struct vb2_v4l2_buffer *src_buf, *dst_buf; ++ u32 src_addr, dst_addr; ++ unsigned long flags; + + v4l2_dbg(3, debug, &imr->v4l2_dev, "run next job...\n"); + +@@ -1494,8 +1589,11 @@ static void imr_device_run(void *priv) + src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); + dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); + ++ /* ...put source/destination buffers sequence numbers */ ++ dst_buf->sequence = src_buf->sequence = ctx->sequence++; ++ + /* ...take configuration pointer associated with input buffer */ +- cfg = to_imr_buffer(to_vb2_v4l2_buffer(src_buf))->cfg; ++ cfg = to_imr_buffer(src_buf)->cfg; + + /* ...cancel software reset state as needed */ + iowrite32(0, imr->mmio + IMR_CR); +@@ -1507,8 +1605,8 @@ static void imr_device_run(void *priv) + iowrite32(ctx->crop[3] << cfg->dst_subpixel, imr->mmio + IMR_YMAXR); + + /* ...adjust source/destination parameters of the program (interleaved / semiplanar) */ +- *cfg->src_pa_ptr[0] = src_addr = (u32)vb2_dma_contig_plane_dma_addr(src_buf, 0); +- *cfg->dst_pa_ptr[0] = dst_addr = (u32)vb2_dma_contig_plane_dma_addr(dst_buf, 0); ++ *cfg->src_pa_ptr[0] = src_addr = (u32)vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); ++ *cfg->dst_pa_ptr[0] = dst_addr = (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); + + /* ...adjust source/destination parameters of the UV-plane as needed */ + if (cfg->src_pa_ptr[1] && cfg->dst_pa_ptr[1]) { +@@ -1529,6 +1627,9 @@ static void imr_device_run(void *priv) + /* ...set display list address */ + iowrite32(cfg->dl_dma_addr + cfg->dl_start_offset, imr->mmio + IMR_DLSAR); + ++ /* ...enable texture prefetching */ ++ iowrite32(0xACCE5501, imr->mmio + IMR_TPOR); ++ + /* ...explicitly flush any pending write operations (don't need that, I guess) */ + wmb(); + +@@ -1536,7 +1637,7 @@ static void imr_device_run(void *priv) + iowrite32(IMR_CR_RS, imr->mmio + IMR_CR); + + /* ...timestamp input buffer */ +- src_buf->timestamp = ktime_get_ns(); ++ src_buf->vb2_buf.timestamp = ktime_get_ns(); + + /* ...unlock device access */ + spin_unlock_irqrestore(&imr->lock, flags); +@@ -1633,13 +1734,14 @@ static irqreturn_t imr_irq_handler(int irq, void *data) + dst_buf->timecode = src_buf->timecode; + dst_buf->flags = src_buf->flags & (V4L2_BUF_FLAG_TIMECODE | V4L2_BUF_FLAG_KEYFRAME | + V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | V4L2_BUF_FLAG_TSTAMP_SRC_MASK); +- dst_buf->sequence = src_buf->sequence = ctx->sequence++; ++ //dst_buf->sequence = src_buf->sequence = ctx->sequence++; ++ + v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); + v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); + +- v4l2_dbg(3, debug, &imr->v4l2_dev, "buffers <0x%08x,0x%08x> done\n", ++ v4l2_dbg(3, debug, &imr->v4l2_dev, "buffers <0x%08x,0x%08x> done (ctx=%p)\n", + (u32)vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0), +- (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0)); ++ (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0), ctx); + } else { + /* ...operation completed in error; no way to understand what exactly went wrong */ + v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); +@@ -1668,6 +1770,8 @@ static irqreturn_t imr_irq_handler(int irq, void *data) + * Device probing / removal interface + ******************************************************************************/ + ++static struct class *imr_alloc_class; ++ + static int imr_probe(struct platform_device *pdev) + { + struct imr_device *imr; +@@ -1727,6 +1831,26 @@ static int imr_probe(struct platform_device *pdev) + goto device_register_rollback; + } + ++ if (!imr_alloc_class) { ++ imr_alloc_class = class_create(THIS_MODULE, "imr-alloc"); ++ if (IS_ERR(imr_alloc_class)) { ++ v4l2_err(&imr->v4l2_dev, "Failed to create alloc-device class\n"); ++ ret = PTR_ERR(imr_alloc_class); ++ goto m2m_init_rollback; ++ } ++ } ++ ++ struct device *adev = device_create(imr_alloc_class, imr->dev, MKDEV(0, 0), NULL, "%s_alloc", dev_name(&pdev->dev)); ++ if (IS_ERR(adev)) { ++ v4l2_err(&imr->v4l2_dev, "Failed to create alloc-device\n"); ++ ret = PTR_ERR(adev); ++ goto m2m_init_rollback; ++ } ++ adev->dma_mask = &adev->coherent_dma_mask; ++ adev->coherent_dma_mask = DMA_BIT_MASK(32); ++ arch_setup_dma_ops(adev, 0, DMA_BIT_MASK(32) + 1, NULL, true); ++ imr->alloc_dev = adev; ++ + strlcpy(imr->video_dev.name, dev_name(&pdev->dev), sizeof(imr->video_dev.name)); + imr->video_dev.fops = &imr_fops; + imr->video_dev.ioctl_ops = &imr_ioctl_ops; +@@ -1765,6 +1889,7 @@ static int imr_remove(struct platform_device *pdev) + + //pm_runtime_disable(imr->v4l2_dev.dev); + video_unregister_device(&imr->video_dev); ++ //device_destroy(imr->alloc_dev, MKDEV(0, 0)); + v4l2_m2m_release(imr->m2m_dev); + v4l2_device_unregister(&imr->v4l2_dev); + +diff --git a/include/uapi/linux/rcar-imr.h b/include/uapi/linux/rcar-imr.h +index d02082f..7b8ed0c 100644 +--- a/include/uapi/linux/rcar-imr.h ++++ b/include/uapi/linux/rcar-imr.h +@@ -48,6 +48,12 @@ struct imr_map_desc { + /* ...vertex clockwise-mode order */ + #define IMR_MAP_TCM (1 << 5) + ++/* ...texture mapping enable flag */ ++#define IMR_MAP_TME (1 << 6) ++ ++/* ...bilinear filtration enable flag */ ++#define IMR_MAP_BFE (1 << 7) ++ + /* ...source coordinate decimal point position bit index */ + #define __IMR_MAP_UVDPOR_SHIFT 8 + #define __IMR_MAP_UVDPOR(v) (((v) >> __IMR_MAP_UVDPOR_SHIFT) & 0x7) +@@ -81,18 +87,12 @@ struct imr_mesh { + + } __attribute__((packed)); + +-/* ...VBO descriptor */ +-struct imr_vbo { +- /* ...number of triangles */ +- u16 num; +- +-} __attribute__((packed)); +- +- + /******************************************************************************* + * Private IOCTL codes + ******************************************************************************/ + + #define VIDIOC_IMR_MESH _IOW('V', BASE_VIDIOC_PRIVATE + 0, struct imr_map_desc) ++#define VIDIOC_IMR_MESH_RAW _IOW('V', BASE_VIDIOC_PRIVATE + 1, struct imr_map_desc) ++#define VIDIOC_IMR_COLOR _IOW('V', BASE_VIDIOC_PRIVATE + 2, u32) + + #endif /* RCAR_IMR_USER_H */ +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0106-media-rcar-imr-Add-RSE-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0106-media-rcar-imr-Add-RSE-support.patch new file mode 100644 index 00000000..1c8d800f --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0106-media-rcar-imr-Add-RSE-support.patch @@ -0,0 +1,327 @@ +From a6fd88487f2dda6f8c5ec28230129478711206fb Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Tue, 6 Feb 2018 13:38:34 +0300 +Subject: [PATCH] media: rcar-imr: Add RSE support + +This adds RSE support for V3H IMR + +Signed-off-by: Andrey Dolnikov +--- + drivers/media/platform/rcar_imr.c | 143 +++++++++++++++++++++++++++++++ + include/uapi/linux/rcar-imr.h | 22 ++++- + 2 files changed, 165 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/platform/rcar_imr.c b/drivers/media/platform/rcar_imr.c +index 9b601da..7b16765 100644 +--- a/drivers/media/platform/rcar_imr.c ++++ b/drivers/media/platform/rcar_imr.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -38,6 +39,9 @@ MODULE_PARM_DESC(debug, "Debug level (0-4)"); + * Local types definitions + ******************************************************************************/ + ++/* Number of RSE planes on V3H (non scaled, 1/2, 1/4, 1/8) */ ++#define RSE_PLANES_NUM 4 ++ + /* ...configuration data */ + struct imr_cfg { + /* ...display-list main program data */ +@@ -49,6 +53,21 @@ struct imr_cfg { + /* ...pointers to the source/destination planes */ + u32 *src_pa_ptr[2]; + u32 *dst_pa_ptr[2]; ++ /* ...pointers to the RSE destination planes */ ++ u32 *dstn_pa_ptr[RSE_PLANES_NUM]; ++ u32 *dstr_pa_ptr[RSE_PLANES_NUM]; ++ ++ /* ...offsets to RSE destination planes */ ++ u32 dstnr_offsets[IMR_EXTDST_NUM]; ++ ++ /* ...RSE logical right shift data */ ++ u32 *rscr_ptr; ++ u8 rscr_sc8, rscr_sc4, rscr_sc2; ++ ++ /* ...RSE destination stride values */ ++ u32 dstnr_strides[IMR_EXTDST_NUM]; ++ u32 *striden_ptr[RSE_PLANES_NUM]; ++ u32 *strider_ptr[RSE_PLANES_NUM]; + + /* ...subpixel destination coordinates space */ + int dst_subpixel; +@@ -96,6 +115,8 @@ struct imr_device { + struct v4l2_m2m_dev *m2m_dev; + struct device *alloc_dev; + ++ bool rse; ++ + /* ...do we need that counter really? framework counts fh structures for us - tbd */ + int refcount; + +@@ -219,6 +240,18 @@ struct imr_ctx { + + #define IMR_TPOR 0xF0 + ++#define IMR_RSCSR 0x204 ++#define IMR_RSCCR 0x208 ++#define IMR_RSCR_RSE 31 ++#define IMR_RSCR_SC8 25 ++#define IMR_RSCR_SC4 21 ++#define IMR_RSCR_SC2 17 ++ ++#define IMR_DSANRR0 0x210 ++#define IMR_DSTNRR0 0x214 ++#define IMR_DSARR0 0x218 ++#define IMR_DSTRR0 0x21C ++ + /******************************************************************************* + * Auxiliary helpers + ******************************************************************************/ +@@ -398,6 +431,7 @@ static int imr_queue_setup(struct vb2_queue *vq, + case V4L2_PIX_FMT_YVYU: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_Y10: ++ case V4L2_PIX_FMT_Y12: + case V4L2_PIX_FMT_Y16: + sizes[0] = w * h * 2; + break; +@@ -750,6 +784,7 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg + int W = ctx->queue[1].fmt.width; + int H = ctx->queue[1].fmt.height; + u32 tricr = ctx->color & 0xFFFFFF; ++ int i; + + v4l2_dbg(2, debug, &ctx->imr->v4l2_dev, "setup %u*%u -> %u*%u mapping (type=%x)\n", w, h, W, H, type); + +@@ -775,6 +810,38 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg + *dl++ = IMR_OP_WTS(IMR_CMRCCR, 0xFFFF); + *dl++ = IMR_OP_WTS(IMR_CMRCCR2, 0xFFFF); + ++ if (type & IMR_MAP_RSE) { ++ /* ...enable RSE */ ++ *dl++ = IMR_OP_WTL(IMR_RSCCR, 1); ++ *dl++ = 0xffffffff; ++ *dl++ = IMR_OP_WTL(IMR_RSCSR, 1); ++ cfg->rscr_ptr = dl++; ++ ++ for (i = 0; i < RSE_PLANES_NUM; i++) { ++ /* ...set destination planes base address and strides */ ++ *dl++ = IMR_OP_WTL(IMR_DSANRR0 + i * 0x10, 4); ++ cfg->dstn_pa_ptr[i] = dl++; ++ cfg->striden_ptr[i] = dl++; ++ cfg->dstr_pa_ptr[i] = dl++; ++ cfg->strider_ptr[i] = dl++; ++ } ++ ++ cfg->rscr_sc8 = cfg->rscr_sc4 = cfg->rscr_sc2 = 0; ++ memset(cfg->dstnr_offsets, 0, sizeof(cfg->dstnr_offsets)); ++ memset(cfg->dstnr_strides, 0, sizeof(cfg->dstnr_strides)); ++ } else { ++ /* ...disable RSE */ ++ *dl++ = IMR_OP_WTL(IMR_RSCCR, 1); ++ *dl++ = 0xffffffff; ++ ++ for (i = 0; i < RSE_PLANES_NUM; i++) { ++ cfg->dstn_pa_ptr[i] = NULL; ++ cfg->striden_ptr[i] = NULL; ++ cfg->dstr_pa_ptr[i] = NULL; ++ cfg->strider_ptr[i] = NULL; ++ } ++ cfg->rscr_ptr = NULL; ++ } + /* ...set source/destination addresses of Y/UV plane */ + *dl++ = IMR_OP_WTL(IMR_DSAR, 2); + cfg->dst_pa_ptr[0] = dl++; +@@ -907,6 +974,12 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc) + + type = desc->type; + ++ /* ...check for RSE */ ++ if ((type & IMR_MAP_RSE) && !imr->rse) { ++ v4l2_err(&imr->v4l2_dev, "Rotator & Scaler extension not supported\n"); ++ return -EINVAL; ++ } ++ + /* ...mesh item size calculation */ + item_size = (type & IMR_MAP_LUCE ? 4 : 0) + (type & IMR_MAP_CLCE ? 4 : 0); + +@@ -1055,6 +1128,12 @@ static int imr_ioctl_map_raw(struct imr_ctx *ctx, struct imr_map_desc *desc) + u32 dl_start_offset; + dma_addr_t dl_dma_addr; + ++ /* ...check RSE */ ++ if ((type & IMR_MAP_RSE) && !imr->rse) { ++ v4l2_err(&imr->v4l2_dev, "Rotator & Scaler extension not supported\n"); ++ return -EINVAL; ++ } ++ + /* ...calculate main routine length */ + dl_size = imr_dl_program_length(ctx); + if (!dl_size) { +@@ -1103,6 +1182,46 @@ static int imr_ioctl_color(struct imr_ctx *ctx, u32 color) + return 0; + } + ++static int imr_extdst_set(struct imr_ctx *ctx, u32 *extdst) ++{ ++ struct imr_device *imr = ctx->imr; ++ struct imr_cfg *cfg = ctx->cfg; ++ ++ if (!cfg) { ++ v4l2_err(&imr->v4l2_dev, "failed to set V3H extension dst buffers: No active confguration.\n"); ++ return -EINVAL; ++ } ++ ++ if (copy_from_user((void *) cfg->dstnr_offsets, (void __user *) extdst, sizeof(cfg->dstnr_offsets))) { ++ v4l2_err(&imr->v4l2_dev, "failed to read V3H extension dst buffers\n"); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++static int imr_extstride_set(struct imr_ctx *ctx, struct imr_rse_param *param) ++{ ++ struct imr_device *imr = ctx->imr; ++ struct imr_cfg *cfg = ctx->cfg; ++ ++ if (!cfg) { ++ v4l2_err(&imr->v4l2_dev, "failed to set V3H extension buffers params: No active confguration.\n"); ++ return -EINVAL; ++ } ++ ++ cfg->rscr_sc8 = param->sc8; ++ cfg->rscr_sc4 = param->sc4; ++ cfg->rscr_sc2 = param->sc2; ++ ++ if (copy_from_user((void *) cfg->dstnr_strides, (void __user *) param->strides, sizeof(cfg->dstnr_strides))) { ++ v4l2_err(&imr->v4l2_dev, "failed to read V3H extension buffers strides\n"); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ + /******************************************************************************* + * V4L2 I/O controls + ******************************************************************************/ +@@ -1356,6 +1475,14 @@ static long imr_default(struct file *file, void *fh, bool valid_prio, unsigned i + /* ...set solid color code */ + return imr_ioctl_color(ctx, *(u32 *)arg); + ++ case VIDIOC_IMR_EXTDST: ++ /* ...set V3H extension dst buffers */ ++ return imr_extdst_set(ctx, *(u32 **)arg); ++ ++ case VIDIOC_IMR_EXTSTRIDE: ++ /* ...set V3H extension dst strides */ ++ return imr_extstride_set(ctx, (struct imr_rse_param *)arg); ++ + default: + return -ENOIOCTLCMD; + } +@@ -1579,6 +1706,7 @@ static void imr_device_run(void *priv) + struct vb2_v4l2_buffer *src_buf, *dst_buf; + u32 src_addr, dst_addr; + unsigned long flags; ++ int i; + + v4l2_dbg(3, debug, &imr->v4l2_dev, "run next job...\n"); + +@@ -1608,6 +1736,17 @@ static void imr_device_run(void *priv) + *cfg->src_pa_ptr[0] = src_addr = (u32)vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); + *cfg->dst_pa_ptr[0] = dst_addr = (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); + ++ for (i = 0; i < RSE_PLANES_NUM; i++) { ++ if (cfg->rscr_ptr) *cfg->rscr_ptr = (1 << IMR_RSCR_RSE) | (cfg->rscr_sc8 << IMR_RSCR_SC8) | ++ (cfg->rscr_sc4 << IMR_RSCR_SC4) |(cfg->rscr_sc2 << IMR_RSCR_SC2); ++ ++ if (cfg->dstn_pa_ptr[i]) *cfg->dstn_pa_ptr[i] = dst_addr + cfg->dstnr_offsets[i]; ++ if (cfg->dstr_pa_ptr[i]) *cfg->dstr_pa_ptr[i] = dst_addr + cfg->dstnr_offsets[i + RSE_PLANES_NUM]; ++ ++ if (cfg->striden_ptr[i]) *cfg->striden_ptr[i] = cfg->dstnr_strides[i]; ++ if (cfg->strider_ptr[i]) *cfg->strider_ptr[i] = cfg->dstnr_strides[i + RSE_PLANES_NUM]; ++ } ++ + /* ...adjust source/destination parameters of the UV-plane as needed */ + if (cfg->src_pa_ptr[1] && cfg->dst_pa_ptr[1]) { + *cfg->src_pa_ptr[1] = src_addr + ctx->queue[0].fmt.width * ctx->queue[0].fmt.height; +@@ -1776,6 +1915,7 @@ static int imr_probe(struct platform_device *pdev) + { + struct imr_device *imr; + struct resource *res; ++ struct device_node *np = pdev->dev.of_node; + int ret; + + imr = devm_kzalloc(&pdev->dev, sizeof(*imr), GFP_KERNEL); +@@ -1786,6 +1926,9 @@ static int imr_probe(struct platform_device *pdev) + spin_lock_init(&imr->lock); + imr->dev = &pdev->dev; + ++ /* Check RSE support */ ++ imr->rse = of_property_read_bool(np, "rse"); ++ + /* ...memory-mapped registers */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { +diff --git a/include/uapi/linux/rcar-imr.h b/include/uapi/linux/rcar-imr.h +index 7b8ed0c..19fdbae 100644 +--- a/include/uapi/linux/rcar-imr.h ++++ b/include/uapi/linux/rcar-imr.h +@@ -25,8 +25,8 @@ struct imr_map_desc { + /* ...total size of the mesh structure */ + u32 size; + +- /* ...map-specific user-pointer */ +- void *data; ++ /* ...map-specific user-pointer */ ++ void *data; + + } __attribute__((packed)); + +@@ -54,6 +54,9 @@ struct imr_map_desc { + /* ...bilinear filtration enable flag */ + #define IMR_MAP_BFE (1 << 7) + ++/* ...extended functionality (rotation/scaling) enable flag */ ++#define IMR_MAP_RSE (1 << 21) ++ + /* ...source coordinate decimal point position bit index */ + #define __IMR_MAP_UVDPOR_SHIFT 8 + #define __IMR_MAP_UVDPOR(v) (((v) >> __IMR_MAP_UVDPOR_SHIFT) & 0x7) +@@ -88,11 +91,26 @@ struct imr_mesh { + } __attribute__((packed)); + + /******************************************************************************* ++ * V3H Extension destination data ++ ******************************************************************************/ ++/* ...number of V3H extension destination buffers (rotated/non-rotated, scaled 1/1, 1/2, 1/4, 1/8) */ ++#define IMR_EXTDST_NUM 8 ++ ++struct imr_rse_param { ++ /* ...logical right shift data */ ++ u8 sc8, sc4, sc2; ++ /* ...destination buffers stride */ ++ u32 *strides; ++}; ++ ++/******************************************************************************* + * Private IOCTL codes + ******************************************************************************/ + + #define VIDIOC_IMR_MESH _IOW('V', BASE_VIDIOC_PRIVATE + 0, struct imr_map_desc) + #define VIDIOC_IMR_MESH_RAW _IOW('V', BASE_VIDIOC_PRIVATE + 1, struct imr_map_desc) + #define VIDIOC_IMR_COLOR _IOW('V', BASE_VIDIOC_PRIVATE + 2, u32) ++#define VIDIOC_IMR_EXTDST _IOW('V', BASE_VIDIOC_PRIVATE + 3, u32 *) ++#define VIDIOC_IMR_EXTSTRIDE _IOW('V', BASE_VIDIOC_PRIVATE + 4, struct imr_rse_param) + + #endif /* RCAR_IMR_USER_H */ +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0109-serial-sh-sci-Fix-minimal-rx_timeout-value.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0109-serial-sh-sci-Fix-minimal-rx_timeout-value.patch new file mode 100644 index 00000000..5358670b --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0109-serial-sh-sci-Fix-minimal-rx_timeout-value.patch @@ -0,0 +1,34 @@ +From 8b5bbc523cf41fbb8e657f9c81d7821b04ac1b89 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Mon, 26 Nov 2018 05:55:03 +0300 +Subject: [PATCH 055/122] serial: sh-sci: Fix minimal rx_timeout value + +Commit "serial: sh-sci: use hrtimer for receive timeout" +breaks rx_timeout limit check. It used to be calculated +in jiffies and the minimal value was msecs_to_jiffies(20). +Since rx_timeout is now measured in uS, the minimal value +should be 20000 instead of 20. + +Signed-off-by: Valentine Barshak +--- + drivers/tty/serial/sh-sci.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c +index eba08cd..7ab614f 100644 +--- a/drivers/tty/serial/sh-sci.c ++++ b/drivers/tty/serial/sh-sci.c +@@ -2523,8 +2523,8 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, + s->rx_frame = (10000 * bits) / (baud / 100); + #ifdef CONFIG_SERIAL_SH_SCI_DMA + s->rx_timeout = s->buf_len_rx * 2 * s->rx_frame; +- if (s->rx_timeout < 20) +- s->rx_timeout = 20; ++ if (s->rx_timeout < 20000) ++ s->rx_timeout = 20000; + #endif + + if ((termios->c_cflag & CREAD) != 0) +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0110-mmc-tmio-Add-SDHI-SEQUENCER-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0110-mmc-tmio-Add-SDHI-SEQUENCER-support.patch new file mode 100644 index 00000000..e6964f87 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0110-mmc-tmio-Add-SDHI-SEQUENCER-support.patch @@ -0,0 +1,295 @@ +From 39a2bccf80d801eb225b191f1e6ed7cd9ef872b4 Mon Sep 17 00:00:00 2001 +From: Masaharu Hayakawa +Date: Mon, 11 Dec 2017 20:51:50 +0900 +Subject: [PATCH 53/61] mmc: tmio: Add SDHI-SEQUENCER support + +This is Workaround for SDHI-DMAC restriction of R-Car H3(WS1.x)/M3(WS1.0). + +Restriction: + Mismatch of the transfer completion interrupt time and data transfer + completion time. + +Overview: + It does not take into account the bus response, the transfer completion + interrupt IP outputs is in the early out. Therefore, when carrying out + the data verification data read from the SD card, there is a possibility + that the data of the last sector might be missing. + (MMC Interface is also the same.) + +S/W Workaround: + The last sector data is preserved by reading data for 2 sectors extra + in the SDHI Driver of Linux kernel. + +SDHI Driver achieves a dummy read for 2 sectors by the SDHI-SEQ function. +In case of CMD18(MMC_READ_MULTIPLE_BLOCK) were requested, +1024 bytes are read additionally by CMD18. +In other cases commands, CMD17 and CMD53(SD_IO_RW_EXTENDED) is +carried out additionally twice. + +Signed-off-by: Masaharu Hayakawa +--- + drivers/mmc/host/tmio_mmc.h | 8 ++ + drivers/mmc/host/tmio_mmc_core.c | 157 +++++++++++++++++++++++++++++++++++++-- + 2 files changed, 159 insertions(+), 6 deletions(-) + +diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h +index 815f650..a5d30b2 100644 +--- a/drivers/mmc/host/tmio_mmc.h ++++ b/drivers/mmc/host/tmio_mmc.h +@@ -122,6 +122,7 @@ + #define HS400_USE_4TAP BIT(1) + #define FORCE_HS200 BIT(2) + #define HS400_USE_MANUAL_CALIB BIT(3) ++#define USE_SEQUENCER BIT(4) + /* bit[31:16] reserved for HS400 manual calibration */ + #define HS400_CALIB_MASK GENMASK_ULL(23, 16) + #define HS400_OFFSET_MASK GENMASK_ULL(31, 24) +@@ -144,6 +145,8 @@ struct tmio_mmc_dma_ops { + void (*abort)(struct tmio_mmc_host *host); + void (*dataend)(struct tmio_mmc_host *host); + bool (*dma_irq)(struct tmio_mmc_host *host); ++ void (*seq_start)(struct tmio_mmc_host *host); ++ void (*seq_irq)(struct tmio_mmc_host *host, int status); + }; + + struct tmio_mmc_host { +@@ -175,10 +178,15 @@ struct tmio_mmc_host { + struct dma_chan *chan_rx; + struct dma_chan *chan_tx; + struct tasklet_struct dma_issue; ++ struct tasklet_struct seq_complete; ++ bool bounce_sg_mapped; + struct scatterlist bounce_sg; + u8 *bounce_buf; + u32 dma_tranend1; + ++ /* Sequencer support */ ++ bool seq_enabled; ++ + /* Track lost interrupts */ + struct delayed_work delayed_reset_work; + struct work_struct done; +diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c +index 2320183..5d3a12c 100644 +--- a/drivers/mmc/host/tmio_mmc_core.c ++++ b/drivers/mmc/host/tmio_mmc_core.c +@@ -194,6 +194,13 @@ static int tmio_mmc_next_sg(struct tmio_mmc_host *host) + static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) + { + struct tmio_mmc_host *host = mmc_priv(mmc); ++ unsigned int timeout = 1000; ++ unsigned long flags = 0; ++ ++ if (host->seq_enabled) ++ spin_lock_irqsave(&host->lock, flags); ++ else ++ __acquire(&host->lock); + + if (enable && !host->sdio_irq_enabled) { + u16 sdio_status; +@@ -210,15 +217,52 @@ static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) + sdio_status |= TMIO_SDIO_SETBITS_MASK; + sd_ctrl_write16(host, CTL_SDIO_STATUS, sdio_status); + +- sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, host->sdio_irq_mask); ++ if (host->seq_enabled) { ++ while (timeout) { ++ sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, ++ host->sdio_irq_mask); ++ if (sd_ctrl_read16(host, CTL_SDIO_IRQ_MASK) == ++ host->sdio_irq_mask) ++ break; ++ ++ udelay(1); ++ timeout--; ++ } ++ if (!timeout) ++ dev_warn(&host->pdev->dev, ++ "failed to write CTL_SDIO_IRQ_MASK\n"); ++ } else { ++ sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, ++ host->sdio_irq_mask); ++ } + } else if (!enable && host->sdio_irq_enabled) { + host->sdio_irq_mask = TMIO_SDIO_MASK_ALL; +- sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, host->sdio_irq_mask); +- ++ if (host->seq_enabled) { ++ while (timeout) { ++ sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, ++ host->sdio_irq_mask); ++ if (sd_ctrl_read16(host, CTL_SDIO_IRQ_MASK) == ++ host->sdio_irq_mask) ++ break; ++ ++ udelay(1); ++ timeout--; ++ } ++ if (!timeout) ++ dev_warn(&host->pdev->dev, ++ "failed to write CTL_SDIO_IRQ_MASK\n"); ++ } else { ++ sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, ++ host->sdio_irq_mask); ++ } + host->sdio_irq_enabled = false; + pm_runtime_mark_last_busy(mmc_dev(mmc)); + pm_runtime_put_autosuspend(mmc_dev(mmc)); + } ++ if (host->seq_enabled) ++ spin_unlock_irqrestore(&host->lock, flags); ++ else ++ __release(&host->lock); + } + + static void tmio_mmc_clk_start(struct tmio_mmc_host *host) +@@ -791,6 +835,11 @@ static void __tmio_mmc_sdio_irq(struct tmio_mmc_host *host) + if (!(pdata->flags & TMIO_MMC_SDIO_IRQ)) + return; + ++ if (host->seq_enabled) ++ spin_lock(&host->lock); ++ else ++ __acquire(&host->lock); ++ + status = sd_ctrl_read16(host, CTL_SDIO_STATUS); + ireg = status & TMIO_SDIO_MASK_ALL & ~host->sdio_irq_mask; + +@@ -800,6 +849,11 @@ static void __tmio_mmc_sdio_irq(struct tmio_mmc_host *host) + + sd_ctrl_write16(host, CTL_SDIO_STATUS, sdio_status); + ++ if (host->seq_enabled) ++ spin_unlock(&host->lock); ++ else ++ __release(&host->lock); ++ + if (mmc->caps & MMC_CAP_SDIO_IRQ && ireg & TMIO_SDIO_STAT_IOIRQ) + mmc_signal_sdio_irq(mmc); + } +@@ -818,6 +872,17 @@ irqreturn_t tmio_mmc_irq(int irq, void *devid) + + if (__tmio_mmc_card_detect_irq(host, ireg, status)) + return IRQ_HANDLED; ++ /* Sequencer Operation End */ ++ if (host->seq_enabled) { ++ if (host->dma_ops) ++ if (host->dma_ops->dma_irq(host)) { ++ tmio_mmc_ack_mmc_irqs(host, TMIO_MASK_IRQ & ++ ~(TMIO_STAT_CARD_REMOVE | ++ TMIO_STAT_CARD_INSERT)); ++ host->dma_ops->seq_irq(host, status); ++ return IRQ_HANDLED; ++ } ++ } + if (__tmio_mmc_sdcard_irq(host, ireg, status)) + return IRQ_HANDLED; + if (host->dma_ops) +@@ -830,6 +895,60 @@ irqreturn_t tmio_mmc_irq(int irq, void *devid) + } + EXPORT_SYMBOL_GPL(tmio_mmc_irq); + ++static int tmio_mmc_start_seq(struct tmio_mmc_host *host, ++ struct mmc_request *mrq) ++{ ++ struct tmio_mmc_data *pdata = host->pdata; ++ struct mmc_data *data = mrq->data; ++ ++ pr_debug("setup data transfer: blocksize %08x nr_blocks %d\n", ++ data->blksz, data->blocks); ++ ++ if (!host->chan_rx || !host->chan_tx) { ++ host->force_pio = true; ++ return 0; ++ } ++ ++ /* Some hardware cannot perform 2 byte requests in 4 bit mode */ ++ if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4) { ++ int blksz_2bytes = pdata->flags & TMIO_MMC_BLKSZ_2BYTES; ++ ++ if (data->blksz < 2 || (data->blksz < 4 && !blksz_2bytes)) { ++ pr_err("%s: %d byte block unsupported in 4 bit mode\n", ++ mmc_hostname(host->mmc), data->blksz); ++ return -EINVAL; ++ } ++ } ++ ++ tmio_mmc_init_sg(host, data); ++ host->cmd = mrq->cmd; ++ host->data = data; ++ ++ sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0); ++ ++ if (host->dma_ops) ++ host->dma_ops->seq_start(host); ++ ++ if (host->force_pio) { ++ host->cmd = NULL; ++ host->data = NULL; ++ } ++ ++ return 0; ++} ++ ++static void tmio_mmc_set_blklen_and_blkcnt(struct tmio_mmc_host *host, ++ struct mmc_data *data) ++{ ++ host->force_pio = true; ++ tmio_mmc_init_sg(host, data); ++ host->data = data; ++ ++ /* Set transfer length / blocksize */ ++ sd_ctrl_write16(host, CTL_SD_XFER_LEN, data->blksz); ++ sd_ctrl_write16(host, CTL_XFER_BLK_COUNT, data->blocks); ++} ++ + static int tmio_mmc_start_data(struct tmio_mmc_host *host, + struct mmc_data *data) + { +@@ -958,14 +1077,40 @@ static void tmio_process_mrq(struct tmio_mmc_host *host, + struct mmc_command *cmd; + int ret; + ++ if (host->seq_enabled) { ++ if (mrq->data) { ++ /* Start SEQ */ ++ ret = tmio_mmc_start_seq(host, mrq); ++ if (ret) { ++ goto fail; ++ } else if (!host->force_pio) { ++ /* ++ * Succeeded to start SEQ ++ * Wait SEQ interrupt ++ */ ++ schedule_delayed_work( ++ &host->delayed_reset_work, ++ msecs_to_jiffies(CMDREQ_TIMEOUT)); ++ return; ++ } ++ } ++ } + if (mrq->sbc && host->cmd != mrq->sbc) { + cmd = mrq->sbc; + } else { + cmd = mrq->cmd; + if (mrq->data) { +- ret = tmio_mmc_start_data(host, mrq->data); +- if (ret) +- goto fail; ++ if (host->seq_enabled) { ++ /* ++ * Failed to start SEQ ++ * Set blklen and blkcnt to transfer in PIO mode ++ */ ++ tmio_mmc_set_blklen_and_blkcnt(host, mrq->data); ++ } else { ++ ret = tmio_mmc_start_data(host, mrq->data); ++ if (ret) ++ goto fail; ++ } + } + } + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0111-mmc-renesas_sdhi-Add-SDHI-SEQUENCER-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0111-mmc-renesas_sdhi-Add-SDHI-SEQUENCER-support.patch new file mode 100644 index 00000000..814e58f5 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0111-mmc-renesas_sdhi-Add-SDHI-SEQUENCER-support.patch @@ -0,0 +1,747 @@ +From e7e0800e6b1c083355cbd0d5dccd3f6ad56a80a3 Mon Sep 17 00:00:00 2001 +From: Masaharu Hayakawa +Date: Mon, 11 Dec 2017 20:53:39 +0900 +Subject: [PATCH 54/61] mmc: renesas_sdhi: Add SDHI-SEQUENCER support + +This is Workaround for SDHI-DMAC restriction of R-Car H3(WS1.x)/M3(WS1.0). + +Restriction: + Mismatch of the transfer completion interrupt time and data transfer + completion time. + +Overview: + It does not take into account the bus response, the transfer completion + interrupt IP outputs is in the early out. Therefore, when carrying out + the data verification data read from the SD card, there is a possibility + that the data of the last sector might be missing. + (MMC Interface is also the same.) + +S/W Workaround: + The last sector data is preserved by reading data for 2 sectors extra + in the SDHI Driver of Linux kernel. + +SDHI Driver achieves a dummy read for 2 sectors by the SDHI-SEQ function. +In case of CMD18(MMC_READ_MULTIPLE_BLOCK) were requested, +1024 bytes are read additionally by CMD18. +In other cases commands, CMD17 and CMD53(SD_IO_RW_EXTENDED) is +carried out additionally twice. + +Signed-off-by: Masaharu Hayakawa +--- + drivers/mmc/host/renesas_sdhi_core.c | 17 +- + drivers/mmc/host/renesas_sdhi_internal_dmac.c | 556 +++++++++++++++++++++++++- + 2 files changed, 570 insertions(+), 3 deletions(-) + +diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c +index e4d9dd1..6964161 100644 +--- a/drivers/mmc/host/renesas_sdhi_core.c ++++ b/drivers/mmc/host/renesas_sdhi_core.c +@@ -259,12 +259,12 @@ static int renesas_sdhi_start_signal_voltage_switch(struct mmc_host *mmc, + static const struct soc_device_attribute sdhi_quirks_match[] = { + { .soc_id = "r8a7795", .revision = "ES1.*", + .data = (void *)(DTRAEND1_SET_BIT17 | HS400_USE_4TAP | +- FORCE_HS200), }, ++ FORCE_HS200 | USE_SEQUENCER), }, + { .soc_id = "r8a7795", .revision = "ES2.0", + .data = (void *)HS400_USE_4TAP, }, + { .soc_id = "r8a7796", .revision = "ES1.0", + .data = (void *)(DTRAEND1_SET_BIT17 | HS400_USE_4TAP | +- FORCE_HS200), }, ++ FORCE_HS200 | USE_SEQUENCER), }, + { .soc_id = "r8a7796", .revision = "ES1.1", + .data = (void *)(HS400_USE_4TAP | FORCE_HS200), }, + { .soc_id = "r8a77965", +@@ -835,6 +835,9 @@ int renesas_sdhi_probe(struct platform_device *pdev, + host->hs400_use_4tap = (host->sdhi_quirks & HS400_USE_4TAP) ? + true : false; + ++ host->seq_enabled = (host->sdhi_quirks & USE_SEQUENCER) ? ++ true : false; ++ + if (of_data) { + mmc_data->flags |= of_data->tmio_flags; + mmc_data->ocr_mask = of_data->tmio_ocr_mask; +@@ -848,6 +851,16 @@ int renesas_sdhi_probe(struct platform_device *pdev, + priv->scc_offset = of_data->scc_offset; + } + ++ if (host->seq_enabled) { ++ mmc_data->max_blk_count = 0xffffffff / 512; ++#ifdef CONFIG_MMC_BLOCK_BOUNCE ++ /* (CMD23+CMD18)*1 + (dummy read command) */ ++ mmc_data->max_segs = 1; ++#else ++ /* (CMD23+CMD18)*3 + (dummy read command) */ ++ mmc_data->max_segs = 3; ++#endif ++ } + host->write16_hook = renesas_sdhi_write16_hook; + host->clk_enable = renesas_sdhi_clk_enable; + host->clk_update = renesas_sdhi_clk_update; +diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c +index a563cea..069b3dc 100644 +--- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c ++++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c +@@ -15,6 +15,9 @@ + #include + #include + #include ++#include ++#include ++#include + #include + #include + #include +@@ -24,6 +27,9 @@ + #include "renesas_sdhi.h" + #include "tmio_mmc.h" + ++#define DM_CM_SEQ_REGSET 0x800 ++#define DM_CM_SEQ_MODE 0x808 ++#define DM_CM_SEQ_CTRL 0x810 + #define DM_CM_DTRAN_MODE 0x820 + #define DM_CM_DTRAN_CTRL 0x828 + #define DM_CM_RST 0x830 +@@ -31,7 +37,16 @@ + #define DM_CM_INFO1_MASK 0x848 + #define DM_CM_INFO2 0x850 + #define DM_CM_INFO2_MASK 0x858 ++#define DM_CM_TUNING_STAT 0x860 ++#define DM_CM_SEQ_STAT 0x868 + #define DM_DTRAN_ADDR 0x880 ++#define DM_SEQ_CMD 0x8a0 ++#define DM_SEQ_ARG 0x8a8 ++#define DM_SEQ_SIZE 0x8b0 ++#define DM_SEQ_SECCNT 0x8b8 ++#define DM_SEQ_RSP 0x8c0 ++#define DM_SEQ_RSP_CHK 0x8c8 ++#define DM_SEQ_ADDR 0x8d0 + + /* DM_CM_DTRAN_MODE */ + #define DTRAN_MODE_CH_NUM_CH0 0 /* "downstream" = for write commands */ +@@ -45,6 +60,7 @@ + /* DM_CM_RST */ + #define RST_DTRANRST1 BIT(9) + #define RST_DTRANRST0 BIT(8) ++#define RST_SEQRST BIT(0) + #define RST_RESERVED_BITS GENMASK_ULL(31, 0) + + /* DM_CM_INFO1 and DM_CM_INFO1_MASK */ +@@ -52,6 +68,8 @@ + #define INFO1_DTRANEND1_BIT20 BIT(20) + #define INFO1_DTRANEND1_BIT17 BIT(17) + #define INFO1_DTRANEND0 BIT(16) ++#define INFO1_SEQSUSPEND BIT(8) ++#define INFO1_SEQEND BIT(0) + + /* DM_CM_INFO2 and DM_CM_INFO2_MASK */ + #define INFO2_DTRANERR1 BIT(17) +@@ -133,7 +151,8 @@ renesas_sdhi_internal_dmac_enable_dma(struct tmio_mmc_host *host, bool enable) + INFO1_CLEAR); + + if (priv->dma_priv.enable) { +- host->dma_irq_mask = ~(host->dma_tranend1 | INFO1_DTRANEND0); ++ host->dma_irq_mask = host->seq_enabled ? ++ 0xffffffff : ~(host->dma_tranend1 | INFO1_DTRANEND0); + priv->dma_priv.enable(host, enable); + renesas_sdhi_internal_dmac_dm_write(host, DM_CM_INFO1_MASK, + host->dma_irq_mask); +@@ -146,6 +165,9 @@ renesas_sdhi_internal_dmac_abort_dma(struct tmio_mmc_host *host) { + + renesas_sdhi_internal_dmac_enable_dma(host, false); + ++ if (host->seq_enabled) ++ val |= RST_SEQRST; ++ + renesas_sdhi_internal_dmac_dm_write(host, DM_CM_RST, + RST_RESERVED_BITS & ~val); + renesas_sdhi_internal_dmac_dm_write(host, DM_CM_RST, +@@ -154,6 +176,12 @@ renesas_sdhi_internal_dmac_abort_dma(struct tmio_mmc_host *host) { + clear_bit(SDHI_INTERNAL_DMAC_RX_IN_USE, &global_flags); + + renesas_sdhi_internal_dmac_enable_dma(host, true); ++ ++ if (host->bounce_sg_mapped) { ++ dma_unmap_sg(&host->pdev->dev, &host->bounce_sg, 1, ++ DMA_FROM_DEVICE); ++ host->bounce_sg_mapped = false; ++ } + } + + static void +@@ -229,6 +257,12 @@ static void renesas_sdhi_internal_dmac_complete_tasklet_fn(unsigned long arg) + host->data->host_cookie = COOKIE_UNMAPPED; + } + ++ if (host->bounce_sg_mapped) { ++ dma_unmap_sg(&host->pdev->dev, &host->bounce_sg, 1, ++ DMA_FROM_DEVICE); ++ host->bounce_sg_mapped = false; ++ } ++ + if (host->data->flags & MMC_DATA_READ) + clear_bit(SDHI_INTERNAL_DMAC_RX_IN_USE, &global_flags); + +@@ -237,11 +271,435 @@ static void renesas_sdhi_internal_dmac_complete_tasklet_fn(unsigned long arg) + spin_unlock_irq(&host->lock); + } + ++static void ++renesas_sdhi_internal_dmac_seq_complete_tasklet_fn(unsigned long arg) ++{ ++ renesas_sdhi_internal_dmac_complete_tasklet_fn(arg); ++} ++ ++/* DM_CM_SEQ_REGSET bits */ ++#define DM_CM_SEQ_REGSET_TABLE_NUM BIT(8) ++ ++/* DM_CM_SEQ_CTRL bits */ ++#define DM_CM_SEQ_CTRL_SEQ_TABLE BIT(28) ++#define DM_CM_SEQ_CTRL_T_NUM BIT(24) ++#define DM_CM_SEQ_CTRL_SEQ_TYPE_SD BIT(16) ++#define DM_CM_SEQ_CTRL_START_NUM(x) ((x) << 12) ++#define DM_CM_SEQ_CTRL_END_NUM(x) ((x) << 8) ++#define DM_CM_SEQ_CTRL_SEQ_START BIT(0) ++ ++/* DM_SEQ_CMD bits */ ++#define DM_SEQ_CMD_MULTI BIT(13) ++#define DM_SEQ_CMD_DIO BIT(12) ++#define DM_SEQ_CMD_CMDTYP BIT(11) ++#define DM_SEQ_CMD_RSP_NONE (BIT(9) | BIT(8)) ++#define DM_SEQ_CMD_RSP_R1 BIT(10) ++#define DM_SEQ_CMD_RSP_R1B (BIT(10) | BIT(8)) ++#define DM_SEQ_CMD_RSP_R2 (BIT(10) | BIT(9)) ++#define DM_SEQ_CMD_RSP_R3 (BIT(10) | BIT(9) | BIT(8)) ++#define DM_SEQ_CMD_NONAUTOSTP BIT(7) ++#define DM_SEQ_CMD_APP BIT(6) ++ ++#define MAX_CONTEXT_NUM 8 ++ ++struct tmio_mmc_context { ++ u64 seq_cmd; ++ u64 seq_arg; ++ u64 seq_size; ++ u64 seq_seccnt; ++ u64 seq_rsp; ++ u64 seq_rsp_chk; ++ u64 seq_addr; ++}; ++ ++static void ++renesas_sdhi_internal_dmac_set_seq_context(struct tmio_mmc_host *host, ++ int ctxt_num, ++ struct tmio_mmc_context *ctxt) ++{ ++ u64 val; ++ ++ WARN_ON(ctxt_num >= MAX_CONTEXT_NUM); ++ ++ /* set sequencer table/context number */ ++ if (ctxt_num < 4) ++ val = ctxt_num; ++ else ++ val = DM_CM_SEQ_REGSET_TABLE_NUM | (ctxt_num - 4); ++ renesas_sdhi_internal_dmac_dm_write(host, DM_CM_SEQ_REGSET, val); ++ ++ /* set command parameter */ ++ renesas_sdhi_internal_dmac_dm_write(host, DM_SEQ_CMD, ctxt->seq_cmd); ++ renesas_sdhi_internal_dmac_dm_write(host, DM_SEQ_ARG, ctxt->seq_arg); ++ renesas_sdhi_internal_dmac_dm_write(host, DM_SEQ_SIZE, ctxt->seq_size); ++ renesas_sdhi_internal_dmac_dm_write(host, DM_SEQ_SECCNT, ++ ctxt->seq_seccnt); ++ renesas_sdhi_internal_dmac_dm_write(host, DM_SEQ_RSP, ctxt->seq_rsp); ++ renesas_sdhi_internal_dmac_dm_write(host, DM_SEQ_RSP_CHK, ++ ctxt->seq_rsp_chk); ++ renesas_sdhi_internal_dmac_dm_write(host, DM_SEQ_ADDR, ctxt->seq_addr); ++} ++ ++static int renesas_sdhi_internal_dmac_set_seq_table(struct tmio_mmc_host *host, ++ struct mmc_request *mrq, ++ struct scatterlist *sg, ++ bool ipmmu_on) ++{ ++ struct mmc_card *card = host->mmc->card; ++ struct mmc_data *data = mrq->data; ++ struct scatterlist *sg_tmp; ++ struct tmio_mmc_context ctxt; ++ unsigned int blksz, blocks; ++ u32 cmd_opcode, cmd_flag, cmd_arg; ++ u32 sbc_opcode = 0, sbc_arg = 0; ++ int i, ctxt_cnt = 0; ++ ++ /* SD_COMBO media not tested */ ++ cmd_opcode = (mrq->cmd->opcode & 0x3f); ++ cmd_flag = DM_SEQ_CMD_CMDTYP; ++ if (data->flags & MMC_DATA_READ) ++ cmd_flag |= DM_SEQ_CMD_DIO; ++ if (mmc_op_multi(mrq->cmd->opcode) || ++ (cmd_opcode == SD_IO_RW_EXTENDED && mrq->cmd->arg & 0x08000000)) ++ cmd_flag |= DM_SEQ_CMD_MULTI; ++ if (mrq->sbc || cmd_opcode == SD_IO_RW_EXTENDED) ++ cmd_flag |= DM_SEQ_CMD_NONAUTOSTP; ++ ++ switch (mmc_resp_type(mrq->cmd)) { ++ case MMC_RSP_NONE: ++ cmd_flag |= DM_SEQ_CMD_RSP_NONE; ++ break; ++ case MMC_RSP_R1: ++ case MMC_RSP_R1 & ~MMC_RSP_CRC: ++ cmd_flag |= DM_SEQ_CMD_RSP_R1; ++ break; ++ case MMC_RSP_R1B: ++ cmd_flag |= DM_SEQ_CMD_RSP_R1B; ++ break; ++ case MMC_RSP_R2: ++ cmd_flag |= DM_SEQ_CMD_RSP_R2; ++ break; ++ case MMC_RSP_R3: ++ cmd_flag |= DM_SEQ_CMD_RSP_R3; ++ break; ++ default: ++ pr_debug("Unknown response type %d\n", mmc_resp_type(mrq->cmd)); ++ return -EINVAL; ++ } ++ ++ cmd_arg = mrq->cmd->arg; ++ if (cmd_opcode == SD_IO_RW_EXTENDED && cmd_arg & 0x08000000) { ++ /* SDIO CMD53 block mode */ ++ cmd_arg &= ~0x1ff; ++ } ++ ++ if (mrq->sbc) { ++ sbc_opcode = (mrq->sbc->opcode & 0x3f) | DM_SEQ_CMD_RSP_R1; ++ sbc_arg = mrq->sbc->arg & (MMC_CMD23_ARG_REL_WR | ++ MMC_CMD23_ARG_PACKED | MMC_CMD23_ARG_TAG_REQ); ++ } ++ ++ blksz = data->blksz; ++ if (ipmmu_on) { ++ blocks = data->blocks; ++ memset(&ctxt, 0, sizeof(ctxt)); ++ ++ if (sbc_opcode) { ++ /* set CMD23 */ ++ ctxt.seq_cmd = sbc_opcode; ++ ctxt.seq_arg = sbc_arg | blocks; ++ renesas_sdhi_internal_dmac_set_seq_context ++ (host, ctxt_cnt, &ctxt); ++ ctxt_cnt++; ++ } ++ ++ /* set CMD */ ++ ctxt.seq_cmd = cmd_opcode | cmd_flag; ++ ctxt.seq_arg = cmd_arg; ++ if (cmd_opcode == SD_IO_RW_EXTENDED && cmd_arg & 0x08000000) { ++ /* SDIO CMD53 block mode */ ++ ctxt.seq_arg |= blocks; ++ } ++ ctxt.seq_size = blksz; ++ ctxt.seq_seccnt = blocks; ++ ctxt.seq_addr = sg_dma_address(sg); ++ renesas_sdhi_internal_dmac_set_seq_context ++ (host, ctxt_cnt, &ctxt); ++ } else { ++ for_each_sg(sg, sg_tmp, host->sg_len, i) { ++ blocks = sg_tmp->length / blksz; ++ memset(&ctxt, 0, sizeof(ctxt)); ++ ++ if (sbc_opcode) { ++ /* set CMD23 */ ++ ctxt.seq_cmd = sbc_opcode; ++ ctxt.seq_arg = sbc_arg | blocks; ++ if (sbc_arg & MMC_CMD23_ARG_TAG_REQ && card && ++ card->ext_csd.data_tag_unit_size && ++ blksz * blocks < ++ card->ext_csd.data_tag_unit_size) ++ ctxt.seq_arg &= ~MMC_CMD23_ARG_TAG_REQ; ++ renesas_sdhi_internal_dmac_set_seq_context ++ (host, ctxt_cnt, &ctxt); ++ ctxt_cnt++; ++ } ++ ++ /* set CMD */ ++ ctxt.seq_cmd = cmd_opcode | cmd_flag; ++ ctxt.seq_arg = cmd_arg; ++ if (cmd_opcode == SD_IO_RW_EXTENDED && ++ cmd_arg & 0x08000000) { ++ /* SDIO CMD53 block mode */ ++ ctxt.seq_arg |= blocks; ++ } ++ ctxt.seq_size = blksz; ++ ctxt.seq_seccnt = blocks; ++ ctxt.seq_addr = sg_dma_address(sg_tmp); ++ renesas_sdhi_internal_dmac_set_seq_context ++ (host, ctxt_cnt, &ctxt); ++ ++ if (i < (host->sg_len - 1)) { ++ /* increment address */ ++ if (cmd_opcode == SD_IO_RW_EXTENDED) { ++ /* ++ * sg_len should be 1 in SDIO CMD53 ++ * byte mode ++ */ ++ WARN_ON(!(cmd_arg & 0x08000000)); ++ if (cmd_arg & 0x04000000) { ++ /* ++ * SDIO CMD53 address ++ * increment mode ++ */ ++ cmd_arg += ++ (blocks * blksz) << 9; ++ } ++ } else { ++ /* card uses block-addressing */ ++ if (card && !(card->state & 0x4)) ++ cmd_arg += blocks * blksz; ++ else ++ cmd_arg += blocks; ++ } ++ ctxt_cnt++; ++ } ++ } ++ } ++ ++ if (data->flags & MMC_DATA_READ) { ++ /* dummy read */ ++ if (cmd_opcode == MMC_READ_MULTIPLE_BLOCK && card && ++ blksz == 512 && data->blocks > 1) { ++ memset(&ctxt, 0, sizeof(ctxt)); ++ if (sbc_opcode) { ++ /* set CMD23 */ ++ ctxt.seq_cmd = sbc_opcode; ++ ctxt.seq_arg = sbc_arg | 2; ++ if (sbc_arg & MMC_CMD23_ARG_TAG_REQ && ++ card->ext_csd.data_tag_unit_size && ++ blksz * 2 < ++ card->ext_csd.data_tag_unit_size) ++ ctxt.seq_arg &= ~MMC_CMD23_ARG_TAG_REQ; ++ ctxt_cnt++; ++ renesas_sdhi_internal_dmac_set_seq_context ++ (host, ctxt_cnt, &ctxt); ++ } ++ ++ /* set CMD18 */ ++ ctxt.seq_cmd = cmd_opcode | cmd_flag; ++ ctxt.seq_arg = mrq->cmd->arg; ++ /* card uses block-addressing */ ++ if (!(card->state & 0x4)) ++ ctxt.seq_arg += (data->blocks - 2) * 512; ++ else ++ ctxt.seq_arg += data->blocks - 2; ++ ctxt.seq_size = 512; ++ ctxt.seq_seccnt = 2; ++ ctxt.seq_addr = sg_dma_address(&host->bounce_sg); ++ ctxt_cnt++; ++ renesas_sdhi_internal_dmac_set_seq_context ++ (host, ctxt_cnt, &ctxt); ++ } else { ++ if (cmd_opcode == SD_SWITCH) { ++ /* set SD CMD6 twice */ ++ ctxt.seq_addr = ++ sg_dma_address(&host->bounce_sg); ++ } else if ((card && (mmc_card_sdio(card) || ++ card->type == MMC_TYPE_SD_COMBO)) || ++ cmd_opcode == SD_IO_RW_EXTENDED) { ++ /* ++ * In case of SDIO/SD_COMBO, ++ * read Common I/O Area 0x0-0x1FF twice. ++ */ ++ memset(&ctxt, 0, sizeof(ctxt)); ++ ctxt.seq_cmd = SD_IO_RW_EXTENDED | ++ DM_SEQ_CMD_CMDTYP | ++ DM_SEQ_CMD_DIO | ++ DM_SEQ_CMD_NONAUTOSTP | ++ DM_SEQ_CMD_RSP_R1; ++ /* ++ * SD_IO_RW_EXTENDED argument format: ++ * [31] R/W flag -> 0 ++ * [30:28] Function number -> 0x0 selects ++ * Common I/O Area ++ * [27] Block mode -> 0 ++ * [26] Increment address -> 1 ++ * [25:9] Regiser address -> 0x0 ++ * [8:0] Byte/block count -> 0x0 -> 512Bytes ++ */ ++ ctxt.seq_arg = 0x04000000; ++ ctxt.seq_size = 512; ++ ctxt.seq_seccnt = 1; ++ ctxt.seq_addr = ++ sg_dma_address(&host->bounce_sg); ++ } else { ++ /* set CMD17 twice */ ++ memset(&ctxt, 0, sizeof(ctxt)); ++ ctxt.seq_cmd = MMC_READ_SINGLE_BLOCK | ++ DM_SEQ_CMD_CMDTYP | ++ DM_SEQ_CMD_DIO | ++ DM_SEQ_CMD_RSP_R1; ++ if ((cmd_opcode == MMC_READ_SINGLE_BLOCK || ++ cmd_opcode == MMC_READ_MULTIPLE_BLOCK) && ++ blksz == 512) ++ ctxt.seq_arg = mrq->cmd->arg; ++ else ++ ctxt.seq_arg = 0; ++ ctxt.seq_size = 512; ++ ctxt.seq_seccnt = 1; ++ ctxt.seq_addr = ++ sg_dma_address(&host->bounce_sg); ++ } ++ ++ for (i = 0; i < 2; i++) { ++ ctxt_cnt++; ++ renesas_sdhi_internal_dmac_set_seq_context ++ (host, ctxt_cnt, &ctxt); ++ } ++ } ++ } ++ ++ return ctxt_cnt; ++} ++ ++void renesas_sdhi_internal_dmac_start_sequencer(struct tmio_mmc_host *host) ++{ ++ struct mmc_card *card = host->mmc->card; ++ struct scatterlist *sg = host->sg_ptr; ++ struct mmc_host *mmc = host->mmc; ++ struct mmc_request *mrq = host->mrq; ++ struct mmc_data *data = mrq->data; ++ int ret, ctxt_num; ++ u64 val; ++ bool ipmmu_on = false; ++ ++ /* This DMAC cannot handle if sg_len larger than max_segs */ ++ if (mmc->max_segs == 1 || mmc->max_segs == 3) ++ WARN_ON(host->sg_len > mmc->max_segs); ++ else ++ ipmmu_on = true; ++ ++ dev_dbg(&host->pdev->dev, "%s: %d, %x\n", __func__, host->sg_len, ++ data->flags); ++ ++ if (!card && host->mrq->cmd->opcode == MMC_SEND_TUNING_BLOCK) { ++ /* ++ * workaround: if card is NULL, ++ * we can not decide a dummy read command to be added ++ * to the CMD19. ++ */ ++ goto force_pio; ++ } ++ ++ ret = tmio_mmc_pre_dma_transfer(host, data, COOKIE_MAPPED); ++ if (ret == 0) ++ goto force_pio; ++ ++ if (ipmmu_on) { ++ /* ++ * workaround: if we use IPMMU, sometimes unhandled error ++ * happened ++ */ ++ switch (host->mrq->cmd->opcode) { ++ case MMC_SEND_TUNING_BLOCK_HS200: ++ case MMC_SEND_TUNING_BLOCK: ++ goto force_pio; ++ default: ++ break; ++ } ++ } ++ ++ if (data->flags & MMC_DATA_READ && !host->bounce_sg_mapped) { ++ if (dma_map_sg(&host->pdev->dev, &host->bounce_sg, 1, ++ DMA_FROM_DEVICE) <= 0) { ++ dev_err(&host->pdev->dev, "%s: bounce_sg map failed\n", ++ __func__); ++ goto force_pio; ++ } ++ host->bounce_sg_mapped = true; ++ } ++ ++ renesas_sdhi_internal_dmac_enable_dma(host, true); ++ /* set context */ ++ ctxt_num = renesas_sdhi_internal_dmac_set_seq_table(host, mrq, sg, ++ ipmmu_on); ++ if (ctxt_num < 0) ++ goto unmap_sg; ++ /* set dma mode */ ++ renesas_sdhi_internal_dmac_dm_write(host, DM_CM_DTRAN_MODE, ++ DTRAN_MODE_BUS_WID_TH); ++ /* enable SEQEND irq */ ++ renesas_sdhi_internal_dmac_dm_write(host, DM_CM_INFO1_MASK, ++ GENMASK_ULL(31, 0) & ~INFO1_SEQEND); ++ ++ if (ctxt_num < 4) { ++ /* issue table0 commands */ ++ val = DM_CM_SEQ_CTRL_SEQ_TYPE_SD | ++ DM_CM_SEQ_CTRL_START_NUM(0) | ++ DM_CM_SEQ_CTRL_END_NUM(ctxt_num) | ++ DM_CM_SEQ_CTRL_SEQ_START; ++ renesas_sdhi_internal_dmac_dm_write(host, DM_CM_SEQ_CTRL, val); ++ } else { ++ /* issue table0 commands */ ++ val = DM_CM_SEQ_CTRL_SEQ_TYPE_SD | ++ DM_CM_SEQ_CTRL_T_NUM | ++ DM_CM_SEQ_CTRL_START_NUM(0) | ++ DM_CM_SEQ_CTRL_END_NUM(3) | ++ DM_CM_SEQ_CTRL_SEQ_START; ++ renesas_sdhi_internal_dmac_dm_write(host, DM_CM_SEQ_CTRL, val); ++ /* issue table1 commands */ ++ val = DM_CM_SEQ_CTRL_SEQ_TABLE | ++ DM_CM_SEQ_CTRL_SEQ_TYPE_SD | ++ DM_CM_SEQ_CTRL_T_NUM | ++ DM_CM_SEQ_CTRL_START_NUM(0) | ++ DM_CM_SEQ_CTRL_END_NUM(ctxt_num - 4) | ++ DM_CM_SEQ_CTRL_SEQ_START; ++ renesas_sdhi_internal_dmac_dm_write(host, DM_CM_SEQ_CTRL, val); ++ } ++ ++ return; ++ ++unmap_sg: ++ if (host->bounce_sg_mapped) { ++ dma_unmap_sg(&host->pdev->dev, &host->bounce_sg, 1, ++ DMA_FROM_DEVICE); ++ host->bounce_sg_mapped = false; ++ } ++force_pio: ++ host->force_pio = true; ++ renesas_sdhi_internal_dmac_enable_dma(host, false); ++ ++ return; /* return for PIO */ ++} ++ + static bool renesas_sdhi_internal_dmac_dma_irq(struct tmio_mmc_host *host) + { + unsigned int ireg, status; + + status = renesas_sdhi_internal_dmac_dm_read(host, DM_CM_INFO1); ++ if (host->seq_enabled && status & INFO1_SEQEND) ++ return true; ++ + ireg = status & ~host->dma_irq_mask; + + if (ireg & INFO1_DTRANEND0) { +@@ -260,6 +718,76 @@ static bool renesas_sdhi_internal_dmac_dma_irq(struct tmio_mmc_host *host) + return false; + } + ++static void renesas_sdhi_internal_dmac_seq_irq(struct tmio_mmc_host *host, ++ int status) ++{ ++ struct mmc_data *data; ++ struct mmc_command *cmd, *sbc; ++ u64 dm_cm_info2; ++ ++ spin_lock(&host->lock); ++ data = host->data; ++ cmd = host->mrq->cmd; ++ sbc = host->mrq->sbc; ++ ++ dm_cm_info2 = renesas_sdhi_internal_dmac_dm_read(host, DM_CM_INFO2); ++ renesas_sdhi_internal_dmac_dm_write(host, DM_CM_INFO1, 0x0); ++ renesas_sdhi_internal_dmac_dm_write(host, DM_CM_INFO2, 0x0); ++ ++ if (dm_cm_info2) { ++ pr_debug("sequencer error, CMD%d SD_INFO2=0x%x\n", ++ cmd->opcode, status >> 16); ++ if (status & TMIO_STAT_CMDTIMEOUT) { ++ cmd->error = -ETIMEDOUT; ++ if (sbc) ++ sbc->error = -ETIMEDOUT; ++ } else if ((status & TMIO_STAT_CRCFAIL && ++ cmd->flags & MMC_RSP_CRC) || ++ status & TMIO_STAT_STOPBIT_ERR || ++ status & TMIO_STAT_CMD_IDX_ERR) { ++ cmd->error = -EILSEQ; ++ if (sbc) ++ sbc->error = -EILSEQ; ++ } ++ ++ if (status & TMIO_STAT_DATATIMEOUT) ++ data->error = -ETIMEDOUT; ++ else if (status & TMIO_STAT_CRCFAIL || ++ status & TMIO_STAT_STOPBIT_ERR || ++ status & TMIO_STAT_TXUNDERRUN) ++ data->error = -EILSEQ; ++ } ++ ++ if (host->chan_tx && (data->flags & MMC_DATA_WRITE)) { ++ u32 status = sd_ctrl_read16_and_16_as_32(host, CTL_STATUS); ++ bool done = false; ++ ++ /* ++ * Has all data been written out yet? Testing on SuperH showed, ++ * that in most cases the first interrupt comes already with the ++ * BUSY status bit clear, but on some operations, like mount or ++ * in the beginning of a write / sync / umount, there is one ++ * DATAEND interrupt with the BUSY bit set, in this cases ++ * waiting for one more interrupt fixes the problem. ++ */ ++ if (host->pdata->flags & TMIO_MMC_HAS_IDLE_WAIT) { ++ if (status & TMIO_STAT_SCLKDIVEN) ++ done = true; ++ } else { ++ if (!(status & TMIO_STAT_CMD_BUSY)) ++ done = true; ++ } ++ if (!done) ++ goto out; ++ } ++ /* mask sequencer irq */ ++ renesas_sdhi_internal_dmac_dm_write(host, DM_CM_INFO1_MASK, 0xffffffff); ++ tasklet_schedule(&host->seq_complete); ++ ++out: ++ spin_unlock(&host->lock); ++} ++ + static void + renesas_sdhi_internal_dmac_request_dma(struct tmio_mmc_host *host, + struct tmio_mmc_data *pdata) +@@ -278,6 +806,19 @@ renesas_sdhi_internal_dmac_request_dma(struct tmio_mmc_host *host, + tasklet_init(&host->dma_issue, + renesas_sdhi_internal_dmac_issue_tasklet_fn, + (unsigned long)host); ++ tasklet_init(&host->seq_complete, ++ renesas_sdhi_internal_dmac_seq_complete_tasklet_fn, ++ (unsigned long)host); ++ /* alloc bounce_buf for dummy read */ ++ host->bounce_buf = (u8 *)__get_free_page(GFP_KERNEL | GFP_DMA); ++ if (!host->bounce_buf) { ++ host->chan_rx = NULL; ++ host->chan_tx = NULL; ++ return; ++ } ++ /* setup bounce_sg for dummy read */ ++ sg_init_one(&host->bounce_sg, host->bounce_buf, 1024); ++ host->bounce_sg_mapped = false; + } + + static void +@@ -285,6 +826,17 @@ renesas_sdhi_internal_dmac_release_dma(struct tmio_mmc_host *host) + { + /* Each value is set to zero to assume "disabling" each DMA */ + host->chan_rx = host->chan_tx = NULL; ++ ++ /* free bounce_buf for dummy read */ ++ if (host->bounce_buf) { ++ if (host->bounce_sg_mapped) { ++ dma_unmap_sg(&host->pdev->dev, &host->bounce_sg, 1, ++ DMA_FROM_DEVICE); ++ host->bounce_sg_mapped = false; ++ } ++ free_pages((unsigned long)host->bounce_buf, 0); ++ host->bounce_buf = NULL; ++ } + } + + static const struct tmio_mmc_dma_ops renesas_sdhi_internal_dmac_dma_ops = { +@@ -295,6 +847,8 @@ static const struct tmio_mmc_dma_ops renesas_sdhi_internal_dmac_dma_ops = { + .abort = renesas_sdhi_internal_dmac_abort_dma, + .dataend = renesas_sdhi_internal_dmac_dataend_dma, + .dma_irq = renesas_sdhi_internal_dmac_dma_irq, ++ .seq_start = renesas_sdhi_internal_dmac_start_sequencer, ++ .seq_irq = renesas_sdhi_internal_dmac_seq_irq, + }; + + /* +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0112-ARM64-dts-renesas-ulcb-Make-AK4613-sound-device-name.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0112-ARM64-dts-renesas-ulcb-Make-AK4613-sound-device-name.patch new file mode 100644 index 00000000..aa56e172 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0112-ARM64-dts-renesas-ulcb-Make-AK4613-sound-device-name.patch @@ -0,0 +1,34 @@ +From 3d10977e9e9811efe110d90b725f3132f80112ae Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Fri, 18 Jan 2019 23:24:15 +0300 +Subject: [PATCH 056/122] ARM64: dts: renesas: ulcb: Make AK4613 sound device + name consistent + +This makes AK4613 sound device name consistent throughout all +ULCB boards. This helps to avoid naming issues when pulseaudio +fails to start because the device has different names on +infotainment and starter boards. For example, "ak4613" +on Kingfisher vs "rsnd-sound" on Starter Kit. +Pulseaudio is expecting "ak4613" name. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/ulcb.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/renesas/ulcb.dtsi b/arch/arm64/boot/dts/renesas/ulcb.dtsi +index b60fd45..7e546d3 100644 +--- a/arch/arm64/boot/dts/renesas/ulcb.dtsi ++++ b/arch/arm64/boot/dts/renesas/ulcb.dtsi +@@ -97,7 +97,7 @@ + sound_card: sound { + compatible = "audio-graph-card"; + +- label = "rcar-sound"; ++ label = "ak4613"; + + dais = <&rsnd_port0>; + }; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0113-arm64-dts-ulcb-kf-increase-SDIO-frequency-for-WLAN-c.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0113-arm64-dts-ulcb-kf-increase-SDIO-frequency-for-WLAN-c.patch new file mode 100644 index 00000000..b3b4a745 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0113-arm64-dts-ulcb-kf-increase-SDIO-frequency-for-WLAN-c.patch @@ -0,0 +1,32 @@ +From 1729cb28cb311bd326cb4495a51c86813270540e Mon Sep 17 00:00:00 2001 +From: Nikita Yushchenko +Date: Tue, 2 Oct 2018 10:01:06 +0300 +Subject: [PATCH 057/122] arm64: dts: ulcb-kf: increase SDIO frequency for WLAN + chip + +WL1837MOD supports up to 50 MHz on SDIO interface, increase max-frequency +value up to that. + +This increases WLAN throughput. + +Signed-off-by: Nikita Yushchenko +--- + arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +index 61b7851..ccc84cb 100644 +--- a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi ++++ b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +@@ -1228,7 +1228,7 @@ + no-1-8-v; + non-removable; + cap-power-off-card; +- max-frequency = <26000000>; ++ max-frequency = <50000000>; + status = "okay"; + + #address-cells = <1>; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0114-Sony-IMX219-driver.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0114-Sony-IMX219-driver.patch new file mode 100644 index 00000000..ee21c701 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0114-Sony-IMX219-driver.patch @@ -0,0 +1,1115 @@ +From 1a0e23a15528eb2715c13706fe6d74a32640cbb2 Mon Sep 17 00:00:00 2001 +From: Sergey Lapin +Date: Wed, 26 Sep 2018 03:48:08 +0200 +Subject: [PATCH 058/122] Sony IMX219 driver + +Signed-off-by: Sergey Lapin +--- + .../devicetree/bindings/media/i2c/imx219.txt | 35 + + drivers/media/i2c/soc_camera/Kconfig | 6 + + drivers/media/i2c/soc_camera/Makefile | 1 + + drivers/media/i2c/soc_camera/imx219.c | 1026 ++++++++++++++++++++ + 4 files changed, 1068 insertions(+) + create mode 100644 Documentation/devicetree/bindings/media/i2c/imx219.txt + create mode 100644 drivers/media/i2c/soc_camera/imx219.c + +diff --git a/Documentation/devicetree/bindings/media/i2c/imx219.txt b/Documentation/devicetree/bindings/media/i2c/imx219.txt +new file mode 100644 +index 0000000..bc2ccf3 +--- /dev/null ++++ b/Documentation/devicetree/bindings/media/i2c/imx219.txt +@@ -0,0 +1,35 @@ ++Sony IMX219 raw image sensor ++---------------------------- ++ ++IMX219 is a raw image sensor with MIPI CSI-2 image data interface ++and CCI (I2C compatible) control bus. ++ ++Required properties: ++ ++- compatible : "sony,imx219". ++- reg : I2C slave address of the sensor. ++ ++The common video interfaces bindings (see video-interfaces.txt) should be ++used to specify link to the image data receiver. The IMX219 device node ++should contain one 'port' child node with an 'endpoint' subnode. ++ ++Endpoint node mandatory properties: ++ ++- remote-endpoint: A phandle to the bus receiver's endpoint node. ++ ++Example: ++ ++ ... ++ imx219_cam: imx219@10 { ++ compatible = "sony,imx219"; ++ reg = <0x10>; ++ ++ port@0 { ++ rpi_camera_in: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ }; ++ }; +diff --git a/drivers/media/i2c/soc_camera/Kconfig b/drivers/media/i2c/soc_camera/Kconfig +index 1db3c6b..627d8d9 100644 +--- a/drivers/media/i2c/soc_camera/Kconfig ++++ b/drivers/media/i2c/soc_camera/Kconfig +@@ -100,3 +100,9 @@ config SOC_CAMERA_OV106XX + depends on SOC_CAMERA && I2C + help + This is a runtime detected GMSL/FPDLink3 sensors driver ++ ++config SOC_CAMERA_IMX219 ++ tristate "imx219 camera support" ++ depends on SOC_CAMERA && I2C ++ help ++ This is Sony IMX219 driver +diff --git a/drivers/media/i2c/soc_camera/Makefile b/drivers/media/i2c/soc_camera/Makefile +index 0d4242e..eed6e24 100644 +--- a/drivers/media/i2c/soc_camera/Makefile ++++ b/drivers/media/i2c/soc_camera/Makefile +@@ -14,4 +14,5 @@ obj-$(CONFIG_SOC_CAMERA_TW9910) += tw9910.o + obj-$(CONFIG_SOC_CAMERA_MAX9286) += max9286.o + obj-$(CONFIG_SOC_CAMERA_TI9X4) += ti9x4.o + obj-$(CONFIG_SOC_CAMERA_OV106XX) += ov106xx.o ++obj-$(CONFIG_SOC_CAMERA_IMX219) += imx219.o + +diff --git a/drivers/media/i2c/soc_camera/imx219.c b/drivers/media/i2c/soc_camera/imx219.c +new file mode 100644 +index 0000000..f0ce3f7 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/imx219.c +@@ -0,0 +1,1026 @@ ++/* ++ * V4L2 driver for Sony IMX219 cameras. ++ * ++ * Based on Samsung S5K6AAFX SXGA 1/6" 1.3M CMOS Image Sensor driver ++ * Copyright (C) 2011 Sylwester Nawrocki ++ * ++ * Based on Omnivision OV7670 Camera Driver ++ * Copyright (C) 2006-7 Jonathan Corbet ++ * ++ * Based on Omnivision OV5647 image sensor driver ++ * Copyright (C) 2016, Synopsys, Inc. ++ * ++ * Copyright (C) 2017-2018 Cogent Embedded, Inc ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define IMX219_REG_CHIPID_H 0x0 ++#define IMX219_REG_CHIPID_L 0x1 ++ ++#define REG_DLY 0xffff ++ ++#define CSI_STBY_ON 1 ++#define CSI_STBY_OFF 0 ++ ++/* #define TEST_PATTERN */ ++ ++struct regval_list { ++ u16 addr; ++ u8 data; ++}; ++ ++enum power_seq_cmd { ++ CSI_SUBDEV_PWR_OFF = 0x00, ++ CSI_SUBDEV_PWR_ON = 0x01, ++}; ++ ++struct sensor_format_struct { ++ __u8 *desc; ++ u32 mbus_code; ++ enum v4l2_colorspace colorspace; ++}; ++ ++struct cfg_array { ++ struct regval_list *regs; ++ int size; ++}; ++ ++struct sensor_win_size { ++ int width; ++ int height; ++ void *regs; ++ int regs_size; ++}; ++ ++struct imx219 { ++ struct device *dev; ++ struct v4l2_subdev subdev; ++ struct media_pad pad; ++ struct mutex lock; ++ struct v4l2_mbus_framefmt format; ++ struct sensor_format_struct *fmt; ++ unsigned int width; ++ unsigned int height; ++ unsigned int capture_mode; ++ struct v4l2_fract tpf; ++ struct sensor_win_size *current_wins; ++}; ++ ++static inline struct imx219 *to_state(struct v4l2_subdev *subdev) ++{ ++ return container_of(subdev, struct imx219, subdev); ++} ++ ++static struct sensor_format_struct sensor_formats[] = { ++ { ++ .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8, ++ .colorspace = V4L2_COLORSPACE_SRGB, ++ }, ++}; ++ ++/* ++Used the following sources for register data: ++Copyright (C) 2014, Andrew Chew ++https://chromium.googlesource.com/chromiumos/third_party/kernel/+/factory-ryu-6486.14.B-chromeos-3.14/drivers/media/i2c/soc_camera/imx219.c ++ ++Copyright (C) 2013 Broadcom Corporation ++https://android.googlesource.com/kernel/bcm/+/android-bcm-tetra-3.10-lollipop-wear-release/drivers/media/video/imx219.c ++ ++Chomoly (looks like Allwinner corporation made this one) ++https://github.com/allwinner-zh/linux-3.4-sunxi/blob/master/drivers/media/video/sunxi-vfe/device/imx219.c ++ ++https://github.com/rellimmot/Sony-IMX219-Raspberry-Pi-V2-CMOS ++ ++Copyright (c) 2017, Raspberry Pi Foundation ++Copyright (c) 2017, Dave Stevenson ++https//github.com/6by9/raspiraw ++ ++Register data was manually tuned and tweaked for use with Renesas ++RCar CSI driver. ++*/ ++ ++/* unlock vendor registers */ ++static struct regval_list sensor_unlock_regs[] = { ++ {0x30EB, 0x05}, ++ {0x30EB, 0x0C}, ++ {0x300A, 0xFF}, ++ {0x300B, 0xFF}, ++ {0x30EB, 0x05}, ++ {0x30EB, 0x09}, ++ {REG_DLY, 30}, ++}; ++ ++/* CIS tuning */ ++static struct regval_list cis_tuning_regs[] = { ++ /* magic */ ++ {0x455E, 0x00}, ++ {0x471E, 0x4B}, ++ {0x4767, 0x0F}, ++ {0x4750, 0x14}, ++ {0x4540, 0x00}, ++ {0x47B4, 0x14}, ++ {0x4713, 0x30}, ++ {0x478B, 0x10}, ++ {0x478F, 0x10}, ++ {0x4793, 0x10}, ++ {0x4797, 0x0E}, ++ {0x479B, 0x0E}, ++}; ++ ++static struct regval_list sensor_hxga_regs[] = { ++ /* 0x114: 03 = 4 lanes, 01 = 2 lanes */ ++ {0x0114, 0x01}, ++ /* manual phy control */ ++ {0x0128, 0x01}, ++ /* EXCK_FREQ */ ++ {0x012A, 0x18}, ++ {0x012B, 0x00}, ++ /* gain */ ++ {0x0157, 0xe8}, ++ {0x0158, 0x01}, ++ {0x0159, 0x00}, ++ /* integration time */ ++ {0x015a, 0x02}, ++ {0x015b, 0x31}, ++ /* frame length */ ++ {0x0160, 0x0f}, ++ {0x0161, 0xe0}, ++ /* line length */ ++ {0x0162, 0x0f}, ++ {0x0163, 0xE8}, ++ /* x addr start */ ++ {0x0164, 0x00}, ++ {0x0165, 0x00}, ++ /* x addr end */ ++ {0x0166, 0x0C}, ++ {0x0167, 0xCF}, ++ /* y addr start */ ++ {0x0168, 0x00}, ++ {0x0169, 0x00}, ++ /* y addr end */ ++ {0x016A, 0x09}, ++ {0x016B, 0x9F}, ++ /* Output X size */ ++ {0x016C, 0x0C}, ++ {0x016D, 0xD0}, ++ /* Output Y size */ ++ {0x016E, 0x09}, ++ {0x016F, 0xA0}, ++ /* pixel increment */ ++ {0x0170, 0x01}, ++ {0x0171, 0x01}, ++ {0x0174, 0x00}, ++ {0x0175, 0x00}, ++ /* pixell data format */ ++ {0x018C, 0x08}, ++ {0x018D, 0x08}, ++ /* pix clk div, */ ++ {0x0301, 0x05}, ++ {0x0303, 0x01}, ++ {0x0304, 0x03}, ++ {0x0305, 0x03}, ++ /* PLL1 */ ++ {0x0306, 0x00}, ++ {0x0307, 0x39}, ++ {0x0309, 0x08}, ++ {0x030B, 0x01}, ++ /* PLL2 */ ++ {0x030C, 0x00}, ++ {0x030D, 0x72}, ++}; ++ ++static struct regval_list sensor_1080p_regs[] = { ++ /* 0x114: 03 = 4 lanes, 01 = 2 lanes */ ++ {0x0114, 0x01}, ++ /* manual phy control */ ++ {0x0128, 0x01}, ++ /* EXCK_FREQ */ ++ {0x012A, 0x18}, ++ {0x012B, 0x00}, ++ /* gain */ ++ {0x0157, 0xe8}, ++ {0x0158, 0x01}, ++ {0x0159, 0x00}, ++ /* coarse integration time */ ++ {0x015a, 0x05}, ++ {0x015b, 0x3f}, ++ {0x0160, 0x0A}, ++ {0x0161, 0x2F}, ++ {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}, ++ /* pixell data format */ ++ {0x018C, 0x08}, ++ {0x018D, 0x08}, ++ /* pix clk div, */ ++ {0x0301, 0x05}, ++ {0x0303, 0x01}, ++ {0x0304, 0x03}, ++ {0x0305, 0x03}, ++ /* PLL1 */ ++ {0x0306, 0x00}, ++ {0x0307, 0x39}, ++ {0x0309, 0x08}, ++ {0x030B, 0x01}, ++ /* PLL2 */ ++ {0x030C, 0x00}, ++ {0x030D, 0x72}, ++}; ++ ++static struct regval_list sensor_720p_regs[] = { ++ /* 0x114: 03 = 4 lanes, 01 = 2 lanes */ ++ {0x0114, 0x01}, ++ {0x0128, 0x01}, ++ /* EXCK_FREQ */ ++ {0x012A, 0x18}, ++ {0x012B, 0x00}, ++ /* gain */ ++ {0x0157, 0xc8}, ++ {0x0158, 0x01}, ++ {0x0159, 0x00}, ++ /* coarse integration time */ ++ {0x015a, 0x01}, ++ {0x015b, 0x7f}, ++ {0x0160, 0x02}, ++ {0x0161, 0x39}, ++ {0x0162, 0x0d}, ++ {0x0163, 0xe7}, ++ {0x0164, 0x01}, ++ {0x0165, 0x68}, ++ {0x0166, 0x0b}, ++ {0x0167, 0x67}, ++ {0x0168, 0x02}, ++ {0x0169, 0x00}, ++ {0x016A, 0x07}, ++ {0x016B, 0x9f}, ++ {0x016C, 0x05}, ++ {0x016D, 0x00}, ++ {0x016E, 0x02}, ++ {0x016F, 0xd0}, ++ {0x0170, 0x01}, ++ {0x0171, 0x01}, ++ {0x0172, 0x03}, ++ {0x0174, 0x03}, ++ {0x0175, 0x03}, ++ /* pixell data format */ ++ {0x018C, 0x08}, ++ {0x018D, 0x08}, ++ /* pix clk div, */ ++ {0x0301, 0x05}, ++ {0x0303, 0x01}, ++ {0x0304, 0x03}, ++ {0x0305, 0x03}, ++ /* PLL1 */ ++ {0x0306, 0x00}, ++ {0x0307, 0x39}, ++ /* div2 */ ++ {0x0309, 0x08}, ++ {0x030B, 0x01}, ++ /* PLL2 */ ++ {0x030C, 0x00}, ++ {0x030D, 0x72}, ++}; ++ ++static struct regval_list sensor_480p_regs[] = { ++ /* 0x114: 03 = 4 lanes, 01 = 2 lanes */ ++ {0x0114, 0x01}, ++ {0x0128, 0x01}, ++ /* EXCK_FREQ */ ++ {0x012A, 0x18}, ++ {0x012B, 0x00}, ++ /* gain */ ++ {0x0157, 0xe8}, ++ {0x0158, 0x01}, ++ {0x0159, 0x00}, ++ /* coarse integration time */ ++ {0x015a, 0x01}, ++ {0x015b, 0x2f}, ++ {0x0160, 0x02}, ++ {0x0161, 0x39}, ++ {0x0162, 0x0d}, ++ {0x0163, 0xe7}, ++ /* x start */ ++ {0x0164, 0x03}, ++ {0x0165, 0xe8}, ++ /* x end */ ++ {0x0166, 0x08}, ++ {0x0167, 0xe7}, ++ /* y start */ ++ {0x0168, 0x02}, ++ {0x0169, 0xf0}, ++ /* y end */ ++ {0x016A, 0x06}, ++ {0x016B, 0xaf}, ++ {0x016C, 0x02}, ++ {0x016D, 0x80}, ++ {0x016E, 0x01}, ++ {0x016F, 0xe0}, ++ {0x0170, 0x01}, ++ {0x0171, 0x01}, ++ {0x0172, 0x03}, ++ {0x0174, 0x03}, ++ {0x0175, 0x03}, ++ /* pixell data format */ ++ {0x018C, 0x08}, ++ {0x018D, 0x08}, ++ /* pix clk div, */ ++ {0x0301, 0x05}, ++ {0x0303, 0x01}, ++ {0x0304, 0x03}, ++ {0x0305, 0x03}, ++ /* PLL1 */ ++ {0x0306, 0x00}, ++ {0x0307, 0x39}, ++ /* div2 */ ++ {0x0309, 0x08}, ++ {0x030B, 0x01}, ++ /* PLL2 */ ++ {0x030C, 0x00}, ++ {0x030D, 0x72}, ++}; ++ ++static struct regval_list sensor_240p_regs[] = { ++ /* 0x114: 03 = 4 lanes, 01 = 2 lanes */ ++ {0x0114, 0x01}, ++ {0x0128, 0x01}, ++ /* EXCK_FREQ */ ++ {0x012A, 0x18}, ++ {0x012B, 0x00}, ++ /* gain */ ++ {0x0157, 0xd4}, ++ {0x0158, 0x01}, ++ {0x0159, 0x00}, ++ /* coarse integration time */ ++ {0x015a, 0x01}, ++ {0x015b, 0x30}, ++ /* frame time size */ ++ {0x0160, 0x02}, ++ {0x0161, 0x39}, ++ /* line time size */ ++ {0x0162, 0x0d}, ++ {0x0163, 0xE7}, ++ /* x start */ ++ {0x0164, 0x03}, ++ {0x0165, 0xe8}, ++ /* x end */ ++ {0x0166, 0x06}, ++ {0x0167, 0x67}, ++ /* y start */ ++ {0x0168, 0x03}, ++ {0x0169, 0xde}, ++ /* y end */ ++ {0x016A, 0x05}, ++ {0x016B, 0xbe}, ++ /* x width */ ++ {0x016C, 0x01}, ++ {0x016D, 0x40}, ++ /* x height */ ++ {0x016E, 0x00}, ++ {0x016F, 0xf0}, ++ {0x0170, 0x01}, ++ {0x0171, 0x01}, ++ {0x0172, 0x03}, ++ {0x0174, 0x03}, ++ {0x0175, 0x03}, ++ /* pixell data format */ ++ {0x018C, 0x08}, ++ {0x018D, 0x08}, ++ /* pix clk div, */ ++ {0x0301, 0x05}, ++ {0x0303, 0x01}, ++ {0x0304, 0x03}, ++ {0x0305, 0x03}, ++ /* PLL1 */ ++ {0x0306, 0x00}, ++ {0x0307, 0x39}, ++ /* div2 */ ++ {0x0309, 0x08}, ++ {0x030B, 0x01}, ++ /* PLL2 */ ++ {0x030C, 0x00}, ++ {0x030D, 0x72}, ++}; ++ ++#define IMX219_DEFAULT_WIDTH 3296 ++#define IMX219_DEFAULT_HEIGHT 2464 ++ ++static struct sensor_win_size sensor_win_sizes[] = { ++ { ++ /* 3296x2464 */ ++ .width = 3296, ++ .height = 2464, ++ .regs = sensor_hxga_regs, ++ .regs_size = ARRAY_SIZE(sensor_hxga_regs), ++ }, ++ /* 1920x1080 */ ++ { ++ .width = 1920, ++ .height = 1080, ++ .regs = sensor_1080p_regs, ++ .regs_size = ARRAY_SIZE(sensor_1080p_regs), ++ }, ++ /* 1280x720 */ ++ { ++ .width = 1280, ++ .height = 720, ++ .regs = sensor_720p_regs, ++ .regs_size = ARRAY_SIZE(sensor_720p_regs), ++ }, ++ /* 640x480 */ ++ { ++ .width = 640, ++ .height = 480, ++ .regs = sensor_480p_regs, ++ .regs_size = ARRAY_SIZE(sensor_480p_regs), ++ }, ++ /* 320x240 */ ++ { ++ .width = 320, ++ .height = 240, ++ .regs = sensor_240p_regs, ++ .regs_size = ARRAY_SIZE(sensor_240p_regs), ++ }, ++}; ++ ++#define N_FMTS ARRAY_SIZE(sensor_formats) ++#define N_WIN_SIZES ARRAY_SIZE(sensor_win_sizes) ++ ++static int imx219_write(struct v4l2_subdev *sd, uint16_t reg, uint8_t val) ++{ ++ int ret; ++ unsigned char data[3] = {reg >> 8, reg & 0xff, val}; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ ret = i2c_master_send(client, data, 3); ++ if (ret < 3) { ++ v4l2_err(sd, "%s: i2c write error, reg: %x, %d\n", ++ __func__, reg, ret); ++ return ret < 0 ? ret : -EIO; ++ } ++ return 0; ++} ++ ++static int imx219_read(struct v4l2_subdev *sd, uint16_t reg, uint8_t *val) ++{ ++ int ret; ++ unsigned char data_w[2] = { reg >> 8, reg & 0xff }; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ ret = i2c_master_send(client, data_w, 2); ++ ++ if (ret < 2) { ++ v4l2_err(sd, "%s: i2c read error, reg: %x\n", ++ __func__, reg); ++ return ret < 0 ? ret : -EIO; ++ } ++ ++ ret = i2c_master_recv(client, val, 1); ++ ++ if (ret < 1) { ++ v4l2_err(sd, "%s: i2c read error, reg: %x\n", ++ __func__, reg); ++ return ret < 0 ? ret : -EIO; ++ } ++ ++ return 0; ++} ++ ++static int imx219_write_array(struct v4l2_subdev *subdev, ++ struct regval_list *regs, int array_size) ++{ ++ int i = 0; ++ int ret = 0; ++ ++ if (!regs) ++ return -EINVAL; ++ ++ while (i < array_size) { ++ if (regs->addr == REG_DLY) ++ mdelay(regs->data); ++ else ++ ret = imx219_write(subdev, regs->addr, regs->data); ++ ++ if (ret == -EIO) { ++ v4l2_err(subdev, "register write error at %d, %04x\n", ++ i, regs->addr); ++ return ret; ++ } ++ ++ i++; ++ regs++; ++ } ++ return 0; ++} ++ ++static int sensor_s_sw_stby(struct v4l2_subdev *subdev, int on_off) ++{ ++ int ret; ++ unsigned char rdval; ++ ++ ret = imx219_read(subdev, 0x0100, &rdval); ++ if (ret != 0) ++ return ret; ++ ++ if (on_off == CSI_STBY_ON) ++ ret = imx219_write(subdev, 0x0100, rdval & 0xfe); ++ else ++ ret = imx219_write(subdev, 0x0100, rdval | 0x01); ++ ++ msleep(30); ++ return ret; ++} ++ ++static int sensor_power(struct v4l2_subdev *subdev, int on) ++{ ++ int ret = 0; ++ struct imx219 *imx219 = to_state(subdev); ++ ++ mutex_lock(&imx219->lock); ++ ++ switch (on) { ++ case CSI_SUBDEV_PWR_OFF: ++ ret = sensor_s_sw_stby(subdev, CSI_STBY_ON); ++ if (ret < 0) ++ v4l2_err(subdev, "soft stby failed!\n"); ++ break; ++ case CSI_SUBDEV_PWR_ON: ++ ret = sensor_s_sw_stby(subdev, CSI_STBY_OFF); ++ if (ret) { ++ /* soft reset */ ++ imx219_write(subdev, 0x103, 1); ++ msleep(120); ++ ret = sensor_s_sw_stby(subdev, CSI_STBY_OFF); ++ } ++ if (ret < 0) { ++ v4l2_err(subdev, ++ "Camera not available, check power\n"); ++ break; ++ } ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ mutex_unlock(&imx219->lock); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int sensor_get_register(struct v4l2_subdev *subdev, ++ struct v4l2_dbg_register *reg) ++{ ++ u8 val = 0; ++ int ret; ++ ++ ret = imx219_read(subdev, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u8); ++ ++ return ret; ++} ++ ++static int sensor_set_register(struct v4l2_subdev *subdev, ++ const struct v4l2_dbg_register *reg) ++{ ++ imx219_write(subdev, (u16)reg->reg, (u8)reg->val); ++ ++ return 0; ++} ++#endif ++ ++static const struct v4l2_subdev_core_ops sensor_core_ops = { ++ .s_power = sensor_power, ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = sensor_get_register, ++ .s_register = sensor_set_register, ++#endif ++}; ++ ++#ifdef DUMP_REGS ++static void sensor_dump_regs(struct v4l2_subdev *subdev) ++{ ++ u8 val; ++ ++ imx219_read(subdev, 0x18, &val); ++ pr_info("FRM_CNT %02x\n", val); ++ imx219_read(subdev, 0x19, &val); ++ pr_info("PX_ORDER %02x\n", val); ++ imx219_read(subdev, 0x1a, &val); ++ pr_info("DT_PEDESTAL1 %02x\n", val); ++ imx219_read(subdev, 0x1b, &val); ++ pr_info("DT_PEDESTAL0 %02x\n", val); ++ imx219_read(subdev, 0x104, &val); ++ pr_info("corrupted frame status %02x\n", val); ++ imx219_read(subdev, 0x111, &val); ++ pr_info("CSI_SIG_MODE %02x\n", val); ++ imx219_read(subdev, 0x114, &val); ++ pr_info("CSI_LANE_MODE %02x\n", val); ++ imx219_read(subdev, 0x140, &val); ++ pr_info("TEMPERATURE_VAL %02x\n", val); ++ imx219_read(subdev, 0x142, &val); ++ pr_info("READOUT_V_CNT1 %02x\n", val); ++ imx219_read(subdev, 0x143, &val); ++ pr_info("READOUT_V_CNT0 %02x\n", val); ++ imx219_read(subdev, 0x150, &val); ++ pr_info("FRAME_BANK_STATUS %02x\n", val); ++ imx219_read(subdev, 0x151, &val); ++ pr_info("FRAME_BANK_FRM_COUNT %02x\n", val); ++} ++#else ++#define sensor_dump_regs(x) ++#endif ++static int sensor_enum_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index >= N_FMTS) ++ return -EINVAL; ++ ++ code->code = sensor_formats[code->index].mbus_code; ++ return 0; ++} ++ ++static int sensor_try_fmt_internal(struct v4l2_subdev *subdev, ++ struct v4l2_mbus_framefmt *fmt, ++ struct sensor_format_struct **ret_fmt, ++ struct sensor_win_size **ret_wsize) ++{ ++ int index; ++ struct sensor_win_size *wsize; ++ struct imx219 *imx219 = to_state(subdev); ++ ++ for (index = 0; index < N_FMTS; index++) ++ if (sensor_formats[index].mbus_code == fmt->code) ++ break; ++ ++ if (index >= N_FMTS) ++ return -EINVAL; ++ ++ if (ret_fmt) ++ *ret_fmt = sensor_formats + index; ++ ++ fmt->field = V4L2_FIELD_NONE; ++ for (wsize = sensor_win_sizes; ++ wsize < sensor_win_sizes + N_WIN_SIZES; ++ wsize++) ++ if (fmt->width >= wsize->width && fmt->height >= wsize->height) ++ break; ++ if (wsize >= sensor_win_sizes + N_WIN_SIZES) ++ wsize--; ++ if (ret_wsize) ++ *ret_wsize = wsize; ++ fmt->width = wsize->width; ++ fmt->height = wsize->height; ++ imx219->current_wins = wsize; ++ ++ return 0; ++} ++ ++static int sensor_s_fmt(struct v4l2_subdev *subdev, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *fmt) ++{ ++ int ret; ++ struct sensor_format_struct *sensor_fmt; ++ struct sensor_win_size *wsize = NULL; ++ struct imx219 *info = to_state(subdev); ++ ++ ret = sensor_try_fmt_internal(subdev, &fmt->format, ++ &sensor_fmt, &wsize); ++ if (ret) ++ return ret; ++ ++ info->fmt = sensor_fmt; ++ if (wsize->regs) { ++ /* putting sensor to sleep */ ++ imx219_write(subdev, 0x100, 0); ++ msleep(30); ++ ret = imx219_write_array(subdev, sensor_unlock_regs, ++ ARRAY_SIZE(sensor_hxga_regs)); ++ if (ret < 0) ++ return ret; ++ ret = imx219_write_array(subdev, ++ wsize->regs, ++ wsize->regs_size); ++ if (ret) ++ return ret; ++ ret = imx219_write_array(subdev, cis_tuning_regs, ++ ARRAY_SIZE(cis_tuning_regs)); ++ if (ret) ++ return ret; ++#ifdef TEST_PATTERN ++ ret = imx219_write(subdev, 0x0600, 0x00); ++ ret |= imx219_write(subdev, 0x0601, 0x02); ++ ret |= imx219_write(subdev, 0x0620, 0x00); ++ ret |= imx219_write(subdev, 0x0621, 0x00); ++ ret |= imx219_write(subdev, 0x0622, 0x00); ++ ret |= imx219_write(subdev, 0x0623, 0x00); ++ ret |= imx219_write(subdev, 0x0624, ++ (wsize->width >> 8) & 0xff); ++ ret |= imx219_write(subdev, 0x0625, ++ wsize->width & 0xff); ++ ret |= imx219_write(subdev, 0x0626, ++ (wsize->height >> 8) & 0xff); ++ ret |= imx219_write(subdev, 0x0627, ++ wsize->height & 0xff); ++ if (ret) { ++ v4l2_err(subdev, "%s: i2c write error\n", ++ __func__); ++ return -EIO; ++ } ++#endif ++ /* putting sensor out of sleep */ ++ imx219_write(subdev, 0x100, 1); ++ msleep(30); ++ sensor_dump_regs(sd); ++ } ++ ++ return 0; ++} ++ ++static int sensor_g_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct imx219 *info = to_state(sd); ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ if (format->pad != 0) ++ return -EINVAL; ++ ++ mf->width = info->current_wins->width; ++ mf->height = info->current_wins->height; ++ mf->code = info->fmt->mbus_code; ++ mf->colorspace = info->fmt->colorspace; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int sensor_s_parm(struct v4l2_subdev *subdev, ++ struct v4l2_streamparm *parms) ++{ ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ struct imx219 *info = to_state(subdev); ++ ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ ++ if (info->tpf.numerator == 0) ++ return -EINVAL; ++ ++ info->capture_mode = cp->capturemode; ++ ++ return 0; ++} ++ ++static int sensor_g_parm(struct v4l2_subdev *subdev, ++ struct v4l2_streamparm *parms) ++{ ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ struct imx219 *info = to_state(subdev); ++ ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ ++ memset(cp, 0, sizeof(struct v4l2_captureparm)); ++ cp->capability = V4L2_CAP_TIMEPERFRAME; ++ cp->capturemode = info->capture_mode; ++ ++ return 0; ++} ++ ++static int sensor_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_2_LANE; ++ cfg->flags |= V4L2_MBUS_CSI2_CHANNEL_0; ++ cfg->flags |= V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->flags |= V4L2_MBUS_MASTER; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++static const struct v4l2_subdev_pad_ops sensor_pad_ops = { ++ .enum_mbus_code = sensor_enum_fmt, ++ .set_fmt = sensor_s_fmt, ++ .get_fmt = sensor_g_fmt, ++}; ++ ++static const struct v4l2_subdev_video_ops sensor_video_ops = { ++ .s_parm = sensor_s_parm, ++ .g_parm = sensor_g_parm, ++ .g_mbus_config = sensor_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_ops subdev_ops = { ++ .core = &sensor_core_ops, ++ .video = &sensor_video_ops, ++ .pad = &sensor_pad_ops, ++}; ++ ++static int imx219_detect(struct v4l2_subdev *sd) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ unsigned char id_h, id_l; ++ int ret; ++ ++ ret = sensor_power(sd, 1); ++ if (ret < 0) ++ return ret; ++ msleep(30); ++ ++ ret = imx219_read(sd, IMX219_REG_CHIPID_H, &id_h); ++ if (ret < 0) ++ return ret; ++ ret = imx219_read(sd, IMX219_REG_CHIPID_L, &id_l); ++ if (ret < 0) ++ return ret; ++ ++ if (id_h != 0x02 || id_l != 0x19) { ++ v4l2_info(sd, "Invalid device ID: %02x%02x\n", id_h, id_l); ++ return -ENODEV; ++ } ++ ++ v4l2_info(sd, "IMX219 detected at address 0x%02x\n", client->addr); ++ ++ ret = sensor_power(sd, 0); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int imx219_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh) ++{ ++ struct v4l2_mbus_framefmt *format = ++ v4l2_subdev_get_try_format(subdev, fh->pad, 0); ++ struct v4l2_rect *crop = ++ v4l2_subdev_get_try_crop(subdev, fh->pad, 0); ++ ++ crop->left = 0; ++ crop->top = 0; ++ crop->width = IMX219_DEFAULT_WIDTH; ++ crop->height = IMX219_DEFAULT_HEIGHT; ++ ++ format->code = MEDIA_BUS_FMT_SBGGR8_1X8; ++ ++ format->width = IMX219_DEFAULT_WIDTH; ++ format->height = IMX219_DEFAULT_HEIGHT; ++ format->field = V4L2_FIELD_NONE; ++ format->colorspace = sensor_formats[0].colorspace; ++ ++ return sensor_power(subdev, 1); ++} ++ ++static int imx219_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh) ++{ ++ return sensor_power(subdev, 0); ++} ++ ++static const struct v4l2_subdev_internal_ops imx219_subdev_internal_ops = { ++ .open = imx219_open, ++ .close = imx219_close, ++}; ++ ++static int imx219_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct device *dev = &client->dev; ++ struct imx219 *sensor; ++ int ret = 0, i; ++ struct v4l2_subdev *sd; ++ ++ sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL); ++ if (!sensor) ++ return -ENOMEM; ++ ++ mutex_init(&sensor->lock); ++ sensor->dev = dev; ++ sensor->fmt = &sensor_formats[0]; ++ sensor->width = sensor_win_sizes[0].width; ++ sensor->height = sensor_win_sizes[0].height; ++ sensor->current_wins = &sensor_win_sizes[0]; ++ ++ sd = &sensor->subdev; ++ v4l2_i2c_subdev_init(sd, client, &subdev_ops); ++ sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ ret = imx219_detect(sd); ++ if (ret < 0) { ++ v4l2_err(sd, "IMX219 not found!\n"); ++ goto out; ++ } ++ /* soft reset sequence */ ++ for (i = 0; i < 3; i++) { ++ imx219_write(sd, 0x103, 1); ++ mdelay(30); ++ } ++ msleep(60); ++ ++ /* putting sensor to sleep */ ++ imx219_write(sd, 0x100, 0); ++ msleep(30); ++ ret = imx219_write_array(sd, sensor_unlock_regs, ++ ARRAY_SIZE(sensor_hxga_regs)); ++ if (ret < 0) ++ return ret; ++ ret = imx219_write_array(sd, sensor_win_sizes[0].regs, ++ sensor_win_sizes[0].regs_size); ++ if (ret < 0) ++ return ret; ++ ret = imx219_write_array(sd, cis_tuning_regs, ++ ARRAY_SIZE(cis_tuning_regs)); ++ if (ret < 0) ++ return ret; ++ /* getting sensor out of sleep */ ++ imx219_write(sd, 0x100, 1); ++ msleep(30); ++ sensor->pad.flags = MEDIA_PAD_FL_SOURCE; ++ sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&sd->entity, 1, &sensor->pad); ++ if (ret < 0) ++ return ret; ++ ++ ret = v4l2_async_register_subdev(sd); ++ if (ret < 0) ++ media_entity_cleanup(&sd->entity); ++ ++ /* putting sensor back to sleep to save power */ ++ imx219_write(sd, 0x100, 0); ++out: ++ return ret; ++} ++ ++static int imx219_remove(struct i2c_client *client) ++{ ++ struct v4l2_subdev *subdev = i2c_get_clientdata(client); ++ struct imx219 *imx219 = to_state(subdev); ++ ++ v4l2_async_unregister_subdev(&imx219->subdev); ++ media_entity_cleanup(&imx219->subdev.entity); ++ v4l2_device_unregister_subdev(subdev); ++ ++ return 0; ++} ++ ++static const struct i2c_device_id imx219_id[] = { ++ { "imx219", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, imx219_id); ++ ++#if IS_ENABLED(CONFIG_OF) ++static const struct of_device_id imx219_of_match[] = { ++ { .compatible = "sony,imx219" }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, imx219_of_match); ++#endif ++ ++static struct i2c_driver imx219_driver = { ++ .driver = { ++ .of_match_table = of_match_ptr(imx219_of_match), ++ .owner = THIS_MODULE, ++ .name = "imx219", ++ }, ++ .probe = imx219_probe, ++ .remove = imx219_remove, ++ .id_table = imx219_id, ++}; ++module_i2c_driver(imx219_driver); ++ ++MODULE_AUTHOR("Sergey Lapin "); ++MODULE_DESCRIPTION("A low-level driver for Sony imx219 sensors"); ++MODULE_LICENSE("GPL"); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0115-arm64-dts-renesas-ulcb-kf-enable-enable-IMX219.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0115-arm64-dts-renesas-ulcb-kf-enable-enable-IMX219.patch new file mode 100644 index 00000000..18ae14e0 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0115-arm64-dts-renesas-ulcb-kf-enable-enable-IMX219.patch @@ -0,0 +1,95 @@ +From f24ff97f1aad1bd121ef691d1b3294613e1646ea Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Wed, 3 Oct 2018 14:06:33 +0300 +Subject: [PATCH 059/122] arm64: dts: renesas: ulcb-kf: enable enable IMX219 + +This enables IMX219 instead OV5647 + +Signed-off-by: Sergey Lapin +Signed-off-by: Vladimir Barinov +--- + arch/arm64/boot/dts/renesas/ulcb-kf-imx219.dtsi | 58 +++++++++++++++++++++++++ + arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 5 +++ + 2 files changed, 63 insertions(+) + create mode 100644 arch/arm64/boot/dts/renesas/ulcb-kf-imx219.dtsi + +diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf-imx219.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf-imx219.dtsi +new file mode 100644 +index 0000000..1779a2b +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/ulcb-kf-imx219.dtsi +@@ -0,0 +1,58 @@ ++/* ++ * Device Tree Source for the Kingfisher (ULCB extension) board: ++ * this overrides OV5647 RPI cameras with IMX219 ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++/delete-node/ &rpi_camera_in; ++/delete-node/ &rpi_camera; ++ ++&csi20_ep { ++ csi-rate = <860>; ++}; ++ ++&gpio_exp_76 { ++ /* pin 11 - CAM_GPIO - assume pwdn */ ++ rpi_cam_io_0 { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "RaspB_IO0"; ++ }; ++ ++ /* pin 12 - CAM_CLK */ ++ /* pin12 is output from camera to CPU, so it should be input */ ++ rpi_cam_io_1 { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "RaspB_IO1"; ++ }; ++}; ++ ++&i2cswitch4 { ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ ++ rpi_camera: imx219@10 { ++ compatible = "sony,imx219"; ++ reg = <0x10>; ++ ++ port@0 { ++ rpi_camera_in: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +index ccc84cb..731300e 100644 +--- a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi ++++ b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +@@ -1443,3 +1443,8 @@ + + + ++/* enable IMX219 camera */ ++#include "ulcb-kf-imx219.dtsi" ++ ++ ++ +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0116-media-i2c-soc_camera-Fix-Bad-of_node_put-error.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0116-media-i2c-soc_camera-Fix-Bad-of_node_put-error.patch new file mode 100644 index 00000000..6730d60c --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0116-media-i2c-soc_camera-Fix-Bad-of_node_put-error.patch @@ -0,0 +1,250 @@ +From e23740bbebec60b8f8076491745f0e30dfb80cf3 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Mon, 13 Aug 2018 15:13:52 +0300 +Subject: [PATCH 060/122] media: i2c: soc_camera: Fix Bad of_node_put error + +This fixes "OF: ERROR: Bad of_node_put()" error and possible kernel +crash when probing soc_camera sensor devices. When CONFIG_OF_DYNAMIC +is not enabled, bad of_node_put error is not displayed and everything +seems to work fine. However, there's an error in sensors' parse_dt +callbacks which causes inconsistent node reference counter management. + +Move of_node_put() out of a loop scope to prevent bad of_node_put error. +We don't need to call of_node_put() for every node since subsequent +calls to of_graph_get_next_endpoint() decrement reference counter of +the previous node. We only need to call of_node_put() for the last node. + +Signed-off-by: Valentine Barshak +--- + drivers/media/i2c/soc_camera/ap0101_ar014x.c | 4 ++-- + drivers/media/i2c/soc_camera/ar0132.c | 4 ++-- + drivers/media/i2c/soc_camera/ar0220.c | 3 ++- + drivers/media/i2c/soc_camera/max9286.c | 8 ++++---- + drivers/media/i2c/soc_camera/ov10635.c | 4 ++-- + drivers/media/i2c/soc_camera/ov2775.c | 4 ++-- + drivers/media/i2c/soc_camera/ov490_ov10640.c | 4 ++-- + drivers/media/i2c/soc_camera/ov495_ov2775.c | 4 ++-- + drivers/media/i2c/soc_camera/ti9x4.c | 4 ++-- + 9 files changed, 20 insertions(+), 19 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ap0101_ar014x.c b/drivers/media/i2c/soc_camera/ap0101_ar014x.c +index cae0b19..d8025a4 100644 +--- a/drivers/media/i2c/soc_camera/ap0101_ar014x.c ++++ b/drivers/media/i2c/soc_camera/ap0101_ar014x.c +@@ -420,8 +420,6 @@ static int ap0101_parse_dt(struct device_node *np, struct ap0101_priv *priv) + if (!endpoint) + break; + +- of_node_put(endpoint); +- + rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); + if (!rendpoint) + continue; +@@ -432,6 +430,8 @@ static int ap0101_parse_dt(struct device_node *np, struct ap0101_priv *priv) + break; + } + ++ of_node_put(endpoint); ++ + if (!priv->max9286_addr) { + dev_err(&client->dev, "deserializer does not present for AP0101\n"); + return -EINVAL; +diff --git a/drivers/media/i2c/soc_camera/ar0132.c b/drivers/media/i2c/soc_camera/ar0132.c +index a7ee868..2865902 100644 +--- a/drivers/media/i2c/soc_camera/ar0132.c ++++ b/drivers/media/i2c/soc_camera/ar0132.c +@@ -379,8 +379,6 @@ static int ar0132_parse_dt(struct device_node *np, struct ar0132_priv *priv) + if (!endpoint) + break; + +- of_node_put(endpoint); +- + of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order); + + rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); +@@ -399,6 +397,8 @@ static int ar0132_parse_dt(struct device_node *np, struct ar0132_priv *priv) + break; + } + ++ of_node_put(endpoint); ++ + if (!priv->max9286_addr && !priv->ti9x4_addr) { + dev_err(&client->dev, "deserializer does not present for AR0132\n"); + return -EINVAL; +diff --git a/drivers/media/i2c/soc_camera/ar0220.c b/drivers/media/i2c/soc_camera/ar0220.c +index e00fe4a..8813522 100644 +--- a/drivers/media/i2c/soc_camera/ar0220.c ++++ b/drivers/media/i2c/soc_camera/ar0220.c +@@ -358,7 +358,6 @@ static int ar0220_parse_dt(struct device_node *np, struct ar0220_priv *priv) + if (!endpoint) + break; + +- of_node_put(endpoint); + + rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); + if (!rendpoint) +@@ -371,6 +370,8 @@ static int ar0220_parse_dt(struct device_node *np, struct ar0220_priv *priv) + break; + } + ++ of_node_put(endpoint); ++ + if (!priv->ti9x4_addr) { + dev_err(&client->dev, "deserializer does not present\n"); + return -EINVAL; +diff --git a/drivers/media/i2c/soc_camera/max9286.c b/drivers/media/i2c/soc_camera/max9286.c +index 6a5d0889..d01acdc 100644 +--- a/drivers/media/i2c/soc_camera/max9286.c ++++ b/drivers/media/i2c/soc_camera/max9286.c +@@ -560,9 +560,8 @@ static int max9286_parse_dt(struct i2c_client *client) + if (!endpoint) + break; + +- of_node_put(endpoint); +- + if (of_property_read_u32(endpoint, "max9271-addr", &priv->max9271_addr_map[i])) { ++ of_node_put(endpoint); + dev_err(&client->dev, "max9271-addr not set\n"); + return -EINVAL; + } +@@ -570,6 +569,7 @@ static int max9286_parse_dt(struct i2c_client *client) + priv->sd_fwnode[i] = of_fwnode_handle(endpoint); + } + ++ of_node_put(endpoint); + return 0; + } + +@@ -586,8 +586,6 @@ static void max9286_setup_remote_endpoint(struct i2c_client *client) + if (!endpoint) + break; + +- of_node_put(endpoint); +- + rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); + if (!rendpoint) + continue; +@@ -604,6 +602,8 @@ static void max9286_setup_remote_endpoint(struct i2c_client *client) + if (dvp_order_prop) + of_update_property(rendpoint, dvp_order_prop); + } ++ ++ of_node_put(endpoint); + } + + static int max9286_probe(struct i2c_client *client, +diff --git a/drivers/media/i2c/soc_camera/ov10635.c b/drivers/media/i2c/soc_camera/ov10635.c +index eacf015..8289b76 100644 +--- a/drivers/media/i2c/soc_camera/ov10635.c ++++ b/drivers/media/i2c/soc_camera/ov10635.c +@@ -555,8 +555,6 @@ static int ov10635_parse_dt(struct device_node *np, struct ov10635_priv *priv) + if (!endpoint) + break; + +- of_node_put(endpoint); +- + of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order); + + rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); +@@ -581,6 +579,8 @@ static int ov10635_parse_dt(struct device_node *np, struct ov10635_priv *priv) + break; + } + ++ of_node_put(endpoint); ++ + if (!priv->max9286_addr && !priv->ti964_addr && !priv->ti954_addr) { + dev_err(&client->dev, "deserializer does not present for OV10635\n"); + return -EINVAL; +diff --git a/drivers/media/i2c/soc_camera/ov2775.c b/drivers/media/i2c/soc_camera/ov2775.c +index feb547f..cb41764 100644 +--- a/drivers/media/i2c/soc_camera/ov2775.c ++++ b/drivers/media/i2c/soc_camera/ov2775.c +@@ -355,8 +355,6 @@ static int ov2775_parse_dt(struct device_node *np, struct ov2775_priv *priv) + if (!endpoint) + break; + +- of_node_put(endpoint); +- + rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); + if (!rendpoint) + continue; +@@ -368,6 +366,8 @@ static int ov2775_parse_dt(struct device_node *np, struct ov2775_priv *priv) + break; + } + ++ of_node_put(endpoint); ++ + if (!priv->ti9x4_addr) { + dev_err(&client->dev, "deserializer does not present\n"); + return -EINVAL; +diff --git a/drivers/media/i2c/soc_camera/ov490_ov10640.c b/drivers/media/i2c/soc_camera/ov490_ov10640.c +index e698f59..4b51a92 100644 +--- a/drivers/media/i2c/soc_camera/ov490_ov10640.c ++++ b/drivers/media/i2c/soc_camera/ov490_ov10640.c +@@ -904,8 +904,6 @@ static int ov490_parse_dt(struct device_node *np, struct ov490_priv *priv) + if (!endpoint) + break; + +- of_node_put(endpoint); +- + of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order); + + rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); +@@ -933,6 +931,8 @@ static int ov490_parse_dt(struct device_node *np, struct ov490_priv *priv) + break; + } + ++ of_node_put(endpoint); ++ + if (!priv->max9286_addr && !priv->ti9x4_addr) { + dev_err(&client->dev, "deserializer does not present for OV490\n"); + return -EINVAL; +diff --git a/drivers/media/i2c/soc_camera/ov495_ov2775.c b/drivers/media/i2c/soc_camera/ov495_ov2775.c +index bb5991c..32b5078 100644 +--- a/drivers/media/i2c/soc_camera/ov495_ov2775.c ++++ b/drivers/media/i2c/soc_camera/ov495_ov2775.c +@@ -464,8 +464,6 @@ static int ov495_parse_dt(struct device_node *np, struct ov495_priv *priv) + if (!endpoint) + break; + +- of_node_put(endpoint); +- + rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); + if (!rendpoint) + continue; +@@ -477,6 +475,8 @@ static int ov495_parse_dt(struct device_node *np, struct ov495_priv *priv) + break; + } + ++ of_node_put(endpoint); ++ + if (!priv->ti9x4_addr) { + dev_err(&client->dev, "deserializer does not present for OV495\n"); + return -EINVAL; +diff --git a/drivers/media/i2c/soc_camera/ti9x4.c b/drivers/media/i2c/soc_camera/ti9x4.c +index 2ce98b4..7704bfa 100644 +--- a/drivers/media/i2c/soc_camera/ti9x4.c ++++ b/drivers/media/i2c/soc_camera/ti9x4.c +@@ -406,10 +406,9 @@ static int ti9x4_parse_dt(struct i2c_client *client) + if (!endpoint) + break; + +- of_node_put(endpoint); +- + if (i < priv->links) { + if (of_property_read_u32(endpoint, "ti9x3-addr", &priv->ti9x3_addr_map[i])) { ++ of_node_put(endpoint); + dev_err(&client->dev, "ti9x3-addr not set\n"); + return -EINVAL; + } +@@ -431,6 +430,7 @@ static int ti9x4_parse_dt(struct i2c_client *client) + of_update_property(rendpoint, dvp_order_prop); + } + ++ of_node_put(endpoint); + return 0; + } + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0117-rcar-vin-fix-get_selection-use.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0117-rcar-vin-fix-get_selection-use.patch new file mode 100644 index 00000000..5a063c59 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0117-rcar-vin-fix-get_selection-use.patch @@ -0,0 +1,48 @@ +From e0a3dbada217b98610a00f6878bdf111c41b5475 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Wed, 12 Sep 2018 22:06:53 +0300 +Subject: [PATCH 061/122] rcar-vin: fix get_selection use + +Get crop bounds from glue driver (imager) + +Signed-off-by: Vladimir Barinov +--- + drivers/media/platform/soc_camera/rcar_vin.c | 20 ++++++++++++++++++-- + 1 file changed, 18 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c +index 228bbf3..50d393b 100644 +--- a/drivers/media/platform/soc_camera/rcar_vin.c ++++ b/drivers/media/platform/soc_camera/rcar_vin.c +@@ -2334,10 +2334,26 @@ static int rcar_vin_get_selection(struct soc_camera_device *icd, + struct v4l2_selection *sel) + { + struct rcar_vin_cam *cam = icd->host_priv; ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ struct v4l2_subdev_selection sdsel; ++ int ret; + +- sel->r = cam->subrect; ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sdsel.which = V4L2_SUBDEV_FORMAT_ACTIVE; ++ sdsel.target = sel->target; + +- return 0; ++ ret = v4l2_subdev_call(sd, pad, get_selection, NULL, &sdsel); ++ if (!ret) ++ sel->r = sdsel.r; ++ return ret; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ case V4L2_SEL_TGT_CROP: ++ sel->r = cam->subrect; ++ return 0; ++ default: ++ return -EINVAL; ++ } + } + + /* Similar to set_crop multistage iterative algorithm */ +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0118-clk-clk-gpio-Allow-GPIO-to-sleep-in-set-get_parent.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0118-clk-clk-gpio-Allow-GPIO-to-sleep-in-set-get_parent.patch new file mode 100644 index 00000000..2aece053 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0118-clk-clk-gpio-Allow-GPIO-to-sleep-in-set-get_parent.patch @@ -0,0 +1,43 @@ +From 3ed86f45efc154e3a8e5ebd60beea30929b1c30c Mon Sep 17 00:00:00 2001 +From: Mike Looijmans +Date: Tue, 13 Mar 2018 09:54:03 +0100 +Subject: [PATCH 062/122] clk: clk-gpio: Allow GPIO to sleep in set/get_parent + +When changing or retrieving clock parents, the caller is in a sleepable +state (like prepare) so the GPIO operation need not be atomic. Replace +gpiod_{g|s}et_value with gpiod_{g|s}et_value_cansleep in the {g|s}et_parent +calls for the GPIO based clock mux. + +This fixes a "slowpath" warning when the GPIO controller is an I2C expander +or something similar. + +Signed-off-by: Mike Looijmans +Signed-off-by: Andrey Gusakov +--- + drivers/clk/clk-gpio.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c +index 86b2457..3441e9c 100644 +--- a/drivers/clk/clk-gpio.c ++++ b/drivers/clk/clk-gpio.c +@@ -75,14 +75,14 @@ static u8 clk_gpio_mux_get_parent(struct clk_hw *hw) + { + struct clk_gpio *clk = to_clk_gpio(hw); + +- return gpiod_get_value(clk->gpiod); ++ return gpiod_get_value_cansleep(clk->gpiod); + } + + static int clk_gpio_mux_set_parent(struct clk_hw *hw, u8 index) + { + struct clk_gpio *clk = to_clk_gpio(hw); + +- gpiod_set_value(clk->gpiod, index); ++ gpiod_set_value_cansleep(clk->gpiod, index); + + return 0; + } +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0119-i2c-mix-pca954x-reset-mux-in-case-of-error-during-bu.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0119-i2c-mix-pca954x-reset-mux-in-case-of-error-during-bu.patch new file mode 100644 index 00000000..1c817728 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0119-i2c-mix-pca954x-reset-mux-in-case-of-error-during-bu.patch @@ -0,0 +1,102 @@ +From d166aec2c769ae0ebc6bf54366d794469cec5122 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Wed, 13 Jun 2018 14:06:59 +0300 +Subject: [PATCH 063/122] i2c: mix: pca954x: reset mux in case of error during + bus (de)select + +Signed-off-by: Andrey Gusakov +--- + drivers/i2c/muxes/i2c-mux-pca954x.c | 36 ++++++++++++++++++++++++++++++------ + 1 file changed, 30 insertions(+), 6 deletions(-) + +diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c +index 7b992db..0c8c965 100644 +--- a/drivers/i2c/muxes/i2c-mux-pca954x.c ++++ b/drivers/i2c/muxes/i2c-mux-pca954x.c +@@ -35,6 +35,7 @@ + * warranty of any kind, whether express or implied. + */ + ++#include + #include + #include + #include +@@ -78,6 +79,7 @@ struct chip_desc { + struct pca954x { + const struct chip_desc *chip; + ++ struct gpio_desc *gpio; /* reset gpio */ + u8 last_chan; /* last register value */ + u8 deselect; + struct i2c_client *client; +@@ -207,6 +209,15 @@ static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan) + /* Only select the channel if its different from the last channel */ + if (data->last_chan != regval) { + ret = pca954x_reg_write(muxc->parent, client, regval); ++ if (ret < 0) { ++ dev_err(&data->client->dev, "error selecting channed %d (was 0x%02x), reseting mux\n", ++ chan, data->last_chan); ++ gpiod_set_value(data->gpio, 1); ++ usleep_range(1, 10); ++ gpiod_set_value(data->gpio, 0); ++ /* retry */ ++ ret = pca954x_reg_write(muxc->parent, client, regval); ++ } + data->last_chan = ret < 0 ? 0 : regval; + } + +@@ -217,13 +228,23 @@ static int pca954x_deselect_mux(struct i2c_mux_core *muxc, u32 chan) + { + struct pca954x *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; ++ int ret; + + if (!(data->deselect & (1 << chan))) + return 0; + + /* Deselect active channel */ + data->last_chan = 0; +- return pca954x_reg_write(muxc->parent, client, data->last_chan); ++ ret = pca954x_reg_write(muxc->parent, client, data->last_chan); ++ if (ret < 0) { ++ dev_err(&data->client->dev, "error deselecting channed %d, reseting mux\n", chan); ++ gpiod_set_value(data->gpio, 1); ++ usleep_range(1, 10); ++ gpiod_set_value(data->gpio, 0); ++ /* retry */ ++ ret = pca954x_reg_write(muxc->parent, client, data->last_chan); ++ } ++ return ret; + } + + static irqreturn_t pca954x_irq_handler(int irq, void *dev_id) +@@ -344,7 +365,6 @@ static int pca954x_probe(struct i2c_client *client, + struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev); + struct device_node *of_node = client->dev.of_node; + bool idle_disconnect_dt; +- struct gpio_desc *gpio; + int num, force, class; + struct i2c_mux_core *muxc; + struct pca954x *data; +@@ -364,10 +384,14 @@ static int pca954x_probe(struct i2c_client *client, + i2c_set_clientdata(client, muxc); + data->client = client; + +- /* Get the mux out of reset if a reset GPIO is specified. */ +- gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_LOW); +- if (IS_ERR(gpio)) +- return PTR_ERR(gpio); ++ /* Perform reset if a reset GPIO is specified. */ ++ data->gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_HIGH); ++ if (IS_ERR(data->gpio)) { ++ return PTR_ERR(data->gpio); ++ } else { ++ usleep_range(1, 10); ++ gpiod_set_value(data->gpio, 0); ++ } + + /* Write the mux register at addr to verify + * that the mux is in fact present. This also +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0120-arm64-dts-ulcb-kf-pcm3168a-reset-earlier-i2c-mux-dis.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0120-arm64-dts-ulcb-kf-pcm3168a-reset-earlier-i2c-mux-dis.patch new file mode 100644 index 00000000..6aef8956 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0120-arm64-dts-ulcb-kf-pcm3168a-reset-earlier-i2c-mux-dis.patch @@ -0,0 +1,82 @@ +From ea5e8199be27ecd2271485294084513fa72d78ae Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Fri, 9 Nov 2018 17:40:06 +0300 +Subject: [PATCH 064/122] arm64: dts: ulcb-kf: pcm3168a reset earlier, i2c-mux + disconnect on idle + +Signed-off-by: Andrey Gusakov +--- + arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 26 ++++++++++++++------------ + 1 file changed, 14 insertions(+), 12 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +index 731300e..d4e17a2 100644 +--- a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi ++++ b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +@@ -13,11 +13,11 @@ + serial3 = &hscif1; + }; + +- snd_clk: snd_clk { +- compatible = "fixed-clock"; ++ pcm3168a_clk: pcm3168a_clk { ++ compatible = "gpio-mux-clock"; ++ clocks = <&cs2000>, <&audio_clk_a>; + #clock-cells = <0>; +- clock-frequency = <24576000>; +- clock-output-names = "scki"; ++ select-gpios = <&gpio_exp_75 13 GPIO_ACTIVE_HIGH>; + }; + + wlan_en: regulator@4 { +@@ -52,15 +52,10 @@ + + codec_en_reg: regulator@6 { + compatible = "regulator-fixed"; +- regulator-name = "codec-en-regulator"; ++ ++ regulator-name = "PCM3168A Vcc Vdd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; +- +- gpio = <&gpio_exp_74 15 0>; +- +- /* delay - CHECK */ +- startup-delay-us = <70000>; +- enable-active-high; + }; + + amp_en_reg: regulator@7 { +@@ -395,6 +390,12 @@ + output-high; + line-name = "OTG EXTLPn"; + }; ++ snd_rst { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "pcm3168a reset"; ++ }; + }; + + gpio_exp_75: gpio@75 { +@@ -426,6 +427,7 @@ + #size-cells = <0>; + reg = <0x71>; + reset-gpios = <&gpio5 3 GPIO_ACTIVE_LOW>; ++ i2c-mux-idle-disconnect; + + i2c@0 { + #address-cells = <1>; +@@ -530,7 +532,7 @@ + #sound-dai-cells = <0>; + compatible = "ti,pcm3168a"; + reg = <0x44>; +- clocks = <&snd_clk>; ++ clocks = <&pcm3168a_clk>; + clock-names = "scki"; + tdm; + VDD1-supply = <&codec_en_reg>; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0121-arm64-dts-renesas-ulcb-kf-Set-KOE-TX31D200VM0BAA-128.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0121-arm64-dts-renesas-ulcb-kf-Set-KOE-TX31D200VM0BAA-128.patch new file mode 100644 index 00000000..390ca584 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0121-arm64-dts-renesas-ulcb-kf-Set-KOE-TX31D200VM0BAA-128.patch @@ -0,0 +1,64 @@ +From 2a9c52ee2c53be87c62c841d5c4485cec4f35a60 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Mon, 17 Dec 2018 17:48:17 +0300 +Subject: [PATCH 065/122] arm64: dts: renesas: ulcb-kf: Set KOE TX31D200VM0BAA + 1280x480 panel + +This sets LVDS LCD parameters for KOE TX31D200VM0BAA 1280x480 panel. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/ulcb-kf-panel.dtsi | 27 ++++++++++++++++---------- + 1 file changed, 17 insertions(+), 10 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf-panel.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf-panel.dtsi +index b54c935..5b8748c 100644 +--- a/arch/arm64/boot/dts/renesas/ulcb-kf-panel.dtsi ++++ b/arch/arm64/boot/dts/renesas/ulcb-kf-panel.dtsi +@@ -12,26 +12,33 @@ + &lvds { + compatible = "panel-lvds"; + +- width-mm = <210>; +- height-mm = <158>; ++ width-mm = <291>; ++ height-mm = <109>; + + data-mapping = "jeida-24"; + + panel-timing { +- /* 1280x800 @60Hz Boundary Devices BD101LCC1 compatible panel */ +- clock-frequency = <65000000>; ++ /* 1280x480 @60Hz KOE TX31D200VM0BAA compatible panel */ ++ clock-frequency = <43200000>; + hactive = <1280>; +- vactive = <800>; +- hsync-len = <40>; +- hfront-porch = <80>; ++ vactive = <480>; ++ hsync-len = <20>; ++ hfront-porch = <20>; + hback-porch = <40>; +- vfront-porch = <14>; +- vback-porch = <14>; +- vsync-len = <4>; ++ vsync-len = <15>; ++ vfront-porch = <15>; ++ vback-porch = <20>; + }; + }; + + &gpio2 { ++ sd { ++ gpio-hog; ++ gpios = <2 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Scan Direction Normal"; ++ }; ++ + bl_pwm { + gpio-hog; + gpios = <3 GPIO_ACTIVE_HIGH>; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0121-arm64-dts-renesas-ulcb-kf-Set-Mitsubishi-AA104XD12-1.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0121-arm64-dts-renesas-ulcb-kf-Set-Mitsubishi-AA104XD12-1.patch new file mode 100644 index 00000000..46a92a17 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0121-arm64-dts-renesas-ulcb-kf-Set-Mitsubishi-AA104XD12-1.patch @@ -0,0 +1,64 @@ +From a345757975a1cbb6910d97b98976cc54f102888e Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Mon, 17 Dec 2018 17:56:40 +0300 +Subject: [PATCH 067/122] arm64: dts: renesas: ulcb-kf: Set Mitsubishi + AA104XD12 1024x768 panel + +This sets LVDS LCD parameters for Mitsubishi AA104XD12 1024x768 panel. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/ulcb-kf-panel.dtsi | 31 ++++++++++++++++---------- + 1 file changed, 19 insertions(+), 12 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf-panel.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf-panel.dtsi +index b54c935..73c2378 100644 +--- a/arch/arm64/boot/dts/renesas/ulcb-kf-panel.dtsi ++++ b/arch/arm64/boot/dts/renesas/ulcb-kf-panel.dtsi +@@ -18,24 +18,31 @@ + data-mapping = "jeida-24"; + + panel-timing { +- /* 1280x800 @60Hz Boundary Devices BD101LCC1 compatible panel */ ++ /* 1024x768 @60Hz Mitsubishi AA104XD12 compatible panel */ + clock-frequency = <65000000>; +- hactive = <1280>; +- vactive = <800>; +- hsync-len = <40>; +- hfront-porch = <80>; +- hback-porch = <40>; +- vfront-porch = <14>; +- vback-porch = <14>; +- vsync-len = <4>; ++ hactive = <1024>; ++ vactive = <768>; ++ hsync-len = <136>; ++ hfront-porch = <20>; ++ hback-porch = <160>; ++ vfront-porch = <3>; ++ vback-porch = <29>; ++ vsync-len = <6>; + }; + }; + + &gpio2 { +- bl_pwm { ++ mode { ++ gpio-hog; ++ gpios = <2 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "LVDS ISP 6-Bit Compatibility Mode"; ++ }; ++ ++ sd { + gpio-hog; + gpios = <3 GPIO_ACTIVE_HIGH>; +- output-high; +- line-name = "BL PWM 100%"; ++ output-low; ++ line-name = "LVDS Scan Direction Normal"; + }; + }; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0121-arm64-dts-renesas-ulcb-kf-Set-Mitsubishi-AA121TD01-1.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0121-arm64-dts-renesas-ulcb-kf-Set-Mitsubishi-AA121TD01-1.patch new file mode 100644 index 00000000..26521b58 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0121-arm64-dts-renesas-ulcb-kf-Set-Mitsubishi-AA121TD01-1.patch @@ -0,0 +1,71 @@ +From 10517a5740e7b6f24fd5a45d8f9635ed13e94ddd Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Mon, 17 Dec 2018 17:56:40 +0300 +Subject: [PATCH 069/122] arm64: dts: renesas: ulcb-kf: Set Mitsubishi + AA121TD01 1280x800 panel + +This sets LVDS LCD parameters for Mitsubishi AA121TD01 1280x800 panel. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/ulcb-kf-panel.dtsi | 33 ++++++++++++++++---------- + 1 file changed, 20 insertions(+), 13 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf-panel.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf-panel.dtsi +index b54c935..2fe2b6c 100644 +--- a/arch/arm64/boot/dts/renesas/ulcb-kf-panel.dtsi ++++ b/arch/arm64/boot/dts/renesas/ulcb-kf-panel.dtsi +@@ -12,30 +12,37 @@ + &lvds { + compatible = "panel-lvds"; + +- width-mm = <210>; +- height-mm = <158>; ++ width-mm = <261>; ++ height-mm = <163>; + + data-mapping = "jeida-24"; + + panel-timing { +- /* 1280x800 @60Hz Boundary Devices BD101LCC1 compatible panel */ +- clock-frequency = <65000000>; ++ /* 1280x800 @60Hz Mitsubishi AA121TD01 compatible panel */ ++ clock-frequency = <71000000>; + hactive = <1280>; + vactive = <800>; +- hsync-len = <40>; +- hfront-porch = <80>; +- hback-porch = <40>; +- vfront-porch = <14>; +- vback-porch = <14>; +- vsync-len = <4>; ++ hsync-len = <70>; ++ hfront-porch = <20>; ++ hback-porch = <70>; ++ vsync-len = <5>; ++ vfront-porch = <3>; ++ vback-porch = <15>; + }; + }; + + &gpio2 { +- bl_pwm { ++ mode { ++ gpio-hog; ++ gpios = <2 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "LVDS ISP 6-Bit Compatibility Mode"; ++ }; ++ ++ sd { + gpio-hog; + gpios = <3 GPIO_ACTIVE_HIGH>; +- output-high; +- line-name = "BL PWM 100%"; ++ output-low; ++ line-name = "LVDS Scan Direction Normal"; + }; + }; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0122-block-blk-mq-Fix-IO-hang.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0122-block-blk-mq-Fix-IO-hang.patch new file mode 100644 index 00000000..6edbc24f --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0122-block-blk-mq-Fix-IO-hang.patch @@ -0,0 +1,78 @@ +From 67845bd98cd08aa18a07c884263aea0110273e51 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Fri, 1 Mar 2019 22:22:04 +0300 +Subject: [PATCH 071/122] block: blk-mq: Fix IO hang + +Sometimes IO hangs are observed on Samsung Pro 960 NVME device. +If driver returns BLK_STS_RESOURCE and SCHED_RESTART is set, +rerun queue after a delay (BLK_MQ_DELAY_QUEUE) to avoid IO stalls. +BLK_MQ_DELAY_QUEUE is 3 ms because both scsi-mq and nvmefc are using +that magic value. + +This is part of the commit 86ff7c2a80cd357f6156a53b354f6a0b357dc0c9 +"blk-mq: introduce BLK_STS_DEV_RESOURCE" found in +https://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git. + +Signed-off-by: Valentine Barshak +--- + block/blk-mq.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/block/blk-mq.c b/block/blk-mq.c +index 49979c0..0d923ea 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -1037,11 +1037,14 @@ static bool blk_mq_dispatch_wait_add(struct blk_mq_hw_ctx *hctx) + return true; + } + ++#define BLK_MQ_RESOURCE_DELAY 3 /* ms units */ ++ + bool blk_mq_dispatch_rq_list(struct request_queue *q, struct list_head *list) + { + struct blk_mq_hw_ctx *hctx; + struct request *rq; + int errors, queued; ++ blk_status_t ret = BLK_STS_OK; + + if (list_empty(list)) + return false; +@@ -1052,7 +1055,6 @@ bool blk_mq_dispatch_rq_list(struct request_queue *q, struct list_head *list) + errors = queued = 0; + do { + struct blk_mq_queue_data bd; +- blk_status_t ret; + + rq = list_first_entry(list, struct request, queuelist); + if (!blk_mq_get_driver_tag(rq, &hctx, false)) { +@@ -1116,6 +1118,8 @@ bool blk_mq_dispatch_rq_list(struct request_queue *q, struct list_head *list) + * that is where we will continue on next queue run. + */ + if (!list_empty(list)) { ++ bool needs_restart; ++ + /* + * If an I/O scheduler has been configured and we got a driver + * tag for the next request already, free it again. +@@ -1146,10 +1150,17 @@ bool blk_mq_dispatch_rq_list(struct request_queue *q, struct list_head *list) + * - Some but not all block drivers stop a queue before + * returning BLK_STS_RESOURCE. Two exceptions are scsi-mq + * and dm-rq. ++ * ++ * If driver returns BLK_STS_RESOURCE and SCHED_RESTART ++ * bit is set, run queue after a delay to avoid IO stalls ++ * that could otherwise occur if the queue is idle. + */ +- if (!blk_mq_sched_needs_restart(hctx) && ++ needs_restart = blk_mq_sched_needs_restart(hctx); ++ if (!needs_restart && + !test_bit(BLK_MQ_S_TAG_WAITING, &hctx->state)) + blk_mq_run_hw_queue(hctx, true); ++ else if (needs_restart && (ret == BLK_STS_RESOURCE)) ++ blk_mq_delay_run_hw_queue(hctx, BLK_MQ_RESOURCE_DELAY); + } + + return (queued + errors) != 0; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0123-nvme-Workaround-Samsung-970-Pro-power-state-issues.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0123-nvme-Workaround-Samsung-970-Pro-power-state-issues.patch new file mode 100644 index 00000000..86dcdf62 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0123-nvme-Workaround-Samsung-970-Pro-power-state-issues.patch @@ -0,0 +1,33 @@ +From 49e089f9173aaf001ed82a250f8ff0ce6f585ac4 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Fri, 22 Feb 2019 02:55:02 +0300 +Subject: [PATCH 072/122] nvme: Workaround Samsung 970 Pro power state issues + +Sometimes Samsung 970 Pro NVME device just disappears. +Looks like it drops into deep sleep mode during I/O. +This behaviour has been observed at least on R-Car +Gen3 H3ULCB and M3ULC Kingfisher boards. + +Add a quirk that disables deep sleep mode for the device. + +Signed-off-by: Valentine Barshak +--- + drivers/nvme/host/pci.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c +index afb9987..a6c0789 100644 +--- a/drivers/nvme/host/pci.c ++++ b/drivers/nvme/host/pci.c +@@ -2557,6 +2557,8 @@ static const struct pci_device_id nvme_id_table[] = { + .driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY, }, + { PCI_DEVICE(0x1c5f, 0x0540), /* Memblaze Pblaze4 adapter */ + .driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY, }, ++ { PCI_DEVICE(0x144d, 0xa808), /* Samsung 970 Pro */ ++ .driver_data = NVME_QUIRK_NO_DEEPEST_PS }, + { PCI_DEVICE(0x144d, 0xa821), /* Samsung PM1725 */ + .driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY, }, + { PCI_DEVICE(0x144d, 0xa822), /* Samsung PM1725a */ +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0124-nvme-pci-add-SGL-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0124-nvme-pci-add-SGL-support.patch new file mode 100644 index 00000000..08e53b76 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0124-nvme-pci-add-SGL-support.patch @@ -0,0 +1,393 @@ +From 8e7e1db3e1807fe910d14bdfcd22794ce8d4fb68 Mon Sep 17 00:00:00 2001 +From: Chaitanya Kulkarni +Date: Mon, 16 Oct 2017 18:24:20 -0700 +Subject: [PATCH 073/122] nvme-pci: add SGL support + +This adds SGL support for NVMe PCIe driver, based on an earlier patch +from Rajiv Shanmugam Madeswaran . This patch +refactors the original code and adds new module parameter sgl_threshold +to determine whether to use SGL or PRP for IOs. + +The usage of SGLs is controlled by the sgl_threshold module parameter, +which allows to conditionally use SGLs if average request segment +size (avg_seg_size) is greater than sgl_threshold. In the original patch, +the decision of using SGLs was dependent only on the IO size, +with the new approach we consider not only IO size but also the +number of physical segments present in the IO. + +We calculate avg_seg_size based on request payload bytes and number +of physical segments present in the request. + +For e.g.:- + +1. blk_rq_nr_phys_segments = 2 blk_rq_payload_bytes = 8k +avg_seg_size = 4K use sgl if avg_seg_size >= sgl_threshold. + +2. blk_rq_nr_phys_segments = 2 blk_rq_payload_bytes = 64k +avg_seg_size = 32K use sgl if avg_seg_size >= sgl_threshold. + +3. blk_rq_nr_phys_segments = 16 blk_rq_payload_bytes = 64k +avg_seg_size = 4K use sgl if avg_seg_size >= sgl_threshold. + +Signed-off-by: Chaitanya Kulkarni +Reviewed-by: Keith Busch +Reviewed-by: Sagi Grimberg +Signed-off-by: Christoph Hellwig + +(cherry picked from commit a7a7cbe353a52665b8463e1822ce6ba46b0609d6 +https://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git) + +Signed-off-by: Valentine Barshak +--- + drivers/nvme/host/pci.c | 214 ++++++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 187 insertions(+), 27 deletions(-) + +diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c +index a6c0789..433c6dc 100644 +--- a/drivers/nvme/host/pci.c ++++ b/drivers/nvme/host/pci.c +@@ -45,6 +45,8 @@ + */ + #define NVME_AQ_BLKMQ_DEPTH (NVME_AQ_DEPTH - NVME_NR_AERS) + ++#define SGES_PER_PAGE (PAGE_SIZE / sizeof(struct nvme_sgl_desc)) ++ + static int use_threaded_interrupts; + module_param(use_threaded_interrupts, int, 0); + +@@ -57,6 +59,12 @@ module_param(max_host_mem_size_mb, uint, 0444); + MODULE_PARM_DESC(max_host_mem_size_mb, + "Maximum Host Memory Buffer (HMB) size per controller (in MiB)"); + ++static unsigned int sgl_threshold = SZ_32K; ++module_param(sgl_threshold, uint, 0644); ++MODULE_PARM_DESC(sgl_threshold, ++ "Use SGLs when average request segment size is larger or equal to " ++ "this size. Use 0 to disable SGLs."); ++ + static int io_queue_depth_set(const char *val, const struct kernel_param *kp); + static const struct kernel_param_ops io_queue_depth_ops = { + .set = io_queue_depth_set, +@@ -178,6 +186,7 @@ struct nvme_queue { + struct nvme_iod { + struct nvme_request req; + struct nvme_queue *nvmeq; ++ bool use_sgl; + int aborted; + int npages; /* In the PRP list. 0 means small pool in use */ + int nents; /* Used in scatterlist */ +@@ -339,17 +348,35 @@ static int nvme_npages(unsigned size, struct nvme_dev *dev) + return DIV_ROUND_UP(8 * nprps, PAGE_SIZE - 8); + } + +-static unsigned int nvme_iod_alloc_size(struct nvme_dev *dev, +- unsigned int size, unsigned int nseg) ++/* ++ * Calculates the number of pages needed for the SGL segments. For example a 4k ++ * page can accommodate 256 SGL descriptors. ++ */ ++static int nvme_pci_npages_sgl(unsigned int num_seg) ++{ ++ return DIV_ROUND_UP(num_seg * sizeof(struct nvme_sgl_desc), PAGE_SIZE); ++} ++ ++static unsigned int nvme_pci_iod_alloc_size(struct nvme_dev *dev, ++ unsigned int size, unsigned int nseg, bool use_sgl) + { +- return sizeof(__le64 *) * nvme_npages(size, dev) + +- sizeof(struct scatterlist) * nseg; ++ size_t alloc_size; ++ ++ if (use_sgl) ++ alloc_size = sizeof(__le64 *) * nvme_pci_npages_sgl(nseg); ++ else ++ alloc_size = sizeof(__le64 *) * nvme_npages(size, dev); ++ ++ return alloc_size + sizeof(struct scatterlist) * nseg; + } + +-static unsigned int nvme_cmd_size(struct nvme_dev *dev) ++static unsigned int nvme_pci_cmd_size(struct nvme_dev *dev, bool use_sgl) + { +- return sizeof(struct nvme_iod) + +- nvme_iod_alloc_size(dev, NVME_INT_BYTES(dev), NVME_INT_PAGES); ++ unsigned int alloc_size = nvme_pci_iod_alloc_size(dev, ++ NVME_INT_BYTES(dev), NVME_INT_PAGES, ++ use_sgl); ++ ++ return sizeof(struct nvme_iod) + alloc_size; + } + + static int nvme_admin_init_hctx(struct blk_mq_hw_ctx *hctx, void *data, +@@ -433,10 +460,10 @@ static void __nvme_submit_cmd(struct nvme_queue *nvmeq, + nvmeq->sq_tail = tail; + } + +-static __le64 **iod_list(struct request *req) ++static void **nvme_pci_iod_list(struct request *req) + { + struct nvme_iod *iod = blk_mq_rq_to_pdu(req); +- return (__le64 **)(iod->sg + blk_rq_nr_phys_segments(req)); ++ return (void **)(iod->sg + blk_rq_nr_phys_segments(req)); + } + + static blk_status_t nvme_init_iod(struct request *rq, struct nvme_dev *dev) +@@ -446,7 +473,10 @@ static blk_status_t nvme_init_iod(struct request *rq, struct nvme_dev *dev) + unsigned int size = blk_rq_payload_bytes(rq); + + if (nseg > NVME_INT_PAGES || size > NVME_INT_BYTES(dev)) { +- iod->sg = kmalloc(nvme_iod_alloc_size(dev, size, nseg), GFP_ATOMIC); ++ size_t alloc_size = nvme_pci_iod_alloc_size(dev, size, nseg, ++ iod->use_sgl); ++ ++ iod->sg = kmalloc(alloc_size, GFP_ATOMIC); + if (!iod->sg) + return BLK_STS_RESOURCE; + } else { +@@ -464,18 +494,31 @@ static blk_status_t nvme_init_iod(struct request *rq, struct nvme_dev *dev) + static void nvme_free_iod(struct nvme_dev *dev, struct request *req) + { + struct nvme_iod *iod = blk_mq_rq_to_pdu(req); +- const int last_prp = dev->ctrl.page_size / 8 - 1; ++ const int last_prp = dev->ctrl.page_size / sizeof(__le64) - 1; ++ dma_addr_t dma_addr = iod->first_dma, next_dma_addr; ++ + int i; +- __le64 **list = iod_list(req); +- dma_addr_t prp_dma = iod->first_dma; + + if (iod->npages == 0) +- dma_pool_free(dev->prp_small_pool, list[0], prp_dma); ++ dma_pool_free(dev->prp_small_pool, nvme_pci_iod_list(req)[0], ++ dma_addr); ++ + for (i = 0; i < iod->npages; i++) { +- __le64 *prp_list = list[i]; +- dma_addr_t next_prp_dma = le64_to_cpu(prp_list[last_prp]); +- dma_pool_free(dev->prp_page_pool, prp_list, prp_dma); +- prp_dma = next_prp_dma; ++ void *addr = nvme_pci_iod_list(req)[i]; ++ ++ if (iod->use_sgl) { ++ struct nvme_sgl_desc *sg_list = addr; ++ ++ next_dma_addr = ++ le64_to_cpu((sg_list[SGES_PER_PAGE - 1]).addr); ++ } else { ++ __le64 *prp_list = addr; ++ ++ next_dma_addr = le64_to_cpu(prp_list[last_prp]); ++ } ++ ++ dma_pool_free(dev->prp_page_pool, addr, dma_addr); ++ dma_addr = next_dma_addr; + } + + if (iod->sg != iod->inline_sg) +@@ -563,7 +606,8 @@ static void nvme_print_sgl(struct scatterlist *sgl, int nents) + } + } + +-static blk_status_t nvme_setup_prps(struct nvme_dev *dev, struct request *req) ++static blk_status_t nvme_pci_setup_prps(struct nvme_dev *dev, ++ struct request *req, struct nvme_rw_command *cmnd) + { + struct nvme_iod *iod = blk_mq_rq_to_pdu(req); + struct dma_pool *pool; +@@ -574,14 +618,16 @@ static blk_status_t nvme_setup_prps(struct nvme_dev *dev, struct request *req) + u32 page_size = dev->ctrl.page_size; + int offset = dma_addr & (page_size - 1); + __le64 *prp_list; +- __le64 **list = iod_list(req); ++ void **list = nvme_pci_iod_list(req); + dma_addr_t prp_dma; + int nprps, i; + ++ iod->use_sgl = false; ++ + length -= (page_size - offset); + if (length <= 0) { + iod->first_dma = 0; +- return BLK_STS_OK; ++ goto done; + } + + dma_len -= (page_size - offset); +@@ -595,7 +641,7 @@ static blk_status_t nvme_setup_prps(struct nvme_dev *dev, struct request *req) + + if (length <= page_size) { + iod->first_dma = dma_addr; +- return BLK_STS_OK; ++ goto done; + } + + nprps = DIV_ROUND_UP(length, page_size); +@@ -642,6 +688,10 @@ static blk_status_t nvme_setup_prps(struct nvme_dev *dev, struct request *req) + dma_len = sg_dma_len(sg); + } + ++done: ++ cmnd->dptr.prp1 = cpu_to_le64(sg_dma_address(iod->sg)); ++ cmnd->dptr.prp2 = cpu_to_le64(iod->first_dma); ++ + return BLK_STS_OK; + + bad_sgl: +@@ -651,6 +701,110 @@ static blk_status_t nvme_setup_prps(struct nvme_dev *dev, struct request *req) + return BLK_STS_IOERR; + } + ++static void nvme_pci_sgl_set_data(struct nvme_sgl_desc *sge, ++ struct scatterlist *sg) ++{ ++ sge->addr = cpu_to_le64(sg_dma_address(sg)); ++ sge->length = cpu_to_le32(sg_dma_len(sg)); ++ sge->type = NVME_SGL_FMT_DATA_DESC << 4; ++} ++ ++static void nvme_pci_sgl_set_seg(struct nvme_sgl_desc *sge, ++ dma_addr_t dma_addr, int entries) ++{ ++ sge->addr = cpu_to_le64(dma_addr); ++ if (entries < SGES_PER_PAGE) { ++ sge->length = cpu_to_le32(entries * sizeof(*sge)); ++ sge->type = NVME_SGL_FMT_LAST_SEG_DESC << 4; ++ } else { ++ sge->length = cpu_to_le32(PAGE_SIZE); ++ sge->type = NVME_SGL_FMT_SEG_DESC << 4; ++ } ++} ++ ++static blk_status_t nvme_pci_setup_sgls(struct nvme_dev *dev, ++ struct request *req, struct nvme_rw_command *cmd) ++{ ++ struct nvme_iod *iod = blk_mq_rq_to_pdu(req); ++ int length = blk_rq_payload_bytes(req); ++ struct dma_pool *pool; ++ struct nvme_sgl_desc *sg_list; ++ struct scatterlist *sg = iod->sg; ++ int entries = iod->nents, i = 0; ++ dma_addr_t sgl_dma; ++ ++ iod->use_sgl = true; ++ ++ /* setting the transfer type as SGL */ ++ cmd->flags = NVME_CMD_SGL_METABUF; ++ ++ if (length == sg_dma_len(sg)) { ++ nvme_pci_sgl_set_data(&cmd->dptr.sgl, sg); ++ return BLK_STS_OK; ++ } ++ ++ if (entries <= (256 / sizeof(struct nvme_sgl_desc))) { ++ pool = dev->prp_small_pool; ++ iod->npages = 0; ++ } else { ++ pool = dev->prp_page_pool; ++ iod->npages = 1; ++ } ++ ++ sg_list = dma_pool_alloc(pool, GFP_ATOMIC, &sgl_dma); ++ if (!sg_list) { ++ iod->npages = -1; ++ return BLK_STS_RESOURCE; ++ } ++ ++ nvme_pci_iod_list(req)[0] = sg_list; ++ iod->first_dma = sgl_dma; ++ ++ nvme_pci_sgl_set_seg(&cmd->dptr.sgl, sgl_dma, entries); ++ ++ do { ++ if (i == SGES_PER_PAGE) { ++ struct nvme_sgl_desc *old_sg_desc = sg_list; ++ struct nvme_sgl_desc *link = &old_sg_desc[i - 1]; ++ ++ sg_list = dma_pool_alloc(pool, GFP_ATOMIC, &sgl_dma); ++ if (!sg_list) ++ return BLK_STS_RESOURCE; ++ ++ i = 0; ++ nvme_pci_iod_list(req)[iod->npages++] = sg_list; ++ sg_list[i++] = *link; ++ nvme_pci_sgl_set_seg(link, sgl_dma, entries); ++ } ++ ++ nvme_pci_sgl_set_data(&sg_list[i++], sg); ++ ++ length -= sg_dma_len(sg); ++ sg = sg_next(sg); ++ entries--; ++ } while (length > 0); ++ ++ WARN_ON(entries > 0); ++ return BLK_STS_OK; ++} ++ ++static inline bool nvme_pci_use_sgls(struct nvme_dev *dev, struct request *req) ++{ ++ struct nvme_iod *iod = blk_mq_rq_to_pdu(req); ++ unsigned int avg_seg_size; ++ ++ avg_seg_size = DIV_ROUND_UP(blk_rq_payload_bytes(req), ++ blk_rq_nr_phys_segments(req)); ++ ++ if (!(dev->ctrl.sgls & ((1 << 0) | (1 << 1)))) ++ return false; ++ if (!iod->nvmeq->qid) ++ return false; ++ if (!sgl_threshold || avg_seg_size < sgl_threshold) ++ return false; ++ return true; ++} ++ + static blk_status_t nvme_map_data(struct nvme_dev *dev, struct request *req, + struct nvme_command *cmnd) + { +@@ -670,7 +824,11 @@ static blk_status_t nvme_map_data(struct nvme_dev *dev, struct request *req, + DMA_ATTR_NO_WARN)) + goto out; + +- ret = nvme_setup_prps(dev, req); ++ if (nvme_pci_use_sgls(dev, req)) ++ ret = nvme_pci_setup_sgls(dev, req, &cmnd->rw); ++ else ++ ret = nvme_pci_setup_prps(dev, req, &cmnd->rw); ++ + if (ret != BLK_STS_OK) + goto out_unmap; + +@@ -690,8 +848,6 @@ static blk_status_t nvme_map_data(struct nvme_dev *dev, struct request *req, + goto out_unmap; + } + +- cmnd->rw.dptr.prp1 = cpu_to_le64(sg_dma_address(iod->sg)); +- cmnd->rw.dptr.prp2 = cpu_to_le64(iod->first_dma); + if (blk_integrity_rq(req)) + cmnd->rw.metadata = cpu_to_le64(sg_dma_address(&iod->meta_sg)); + return BLK_STS_OK; +@@ -1398,7 +1554,7 @@ static int nvme_alloc_admin_tags(struct nvme_dev *dev) + dev->admin_tagset.queue_depth = NVME_AQ_BLKMQ_DEPTH - 1; + dev->admin_tagset.timeout = ADMIN_TIMEOUT; + dev->admin_tagset.numa_node = dev_to_node(dev->dev); +- dev->admin_tagset.cmd_size = nvme_cmd_size(dev); ++ dev->admin_tagset.cmd_size = nvme_pci_cmd_size(dev, false); + dev->admin_tagset.flags = BLK_MQ_F_NO_SCHED; + dev->admin_tagset.driver_data = dev; + +@@ -1924,7 +2080,11 @@ static int nvme_dev_add(struct nvme_dev *dev) + dev->tagset.numa_node = dev_to_node(dev->dev); + dev->tagset.queue_depth = + min_t(int, dev->q_depth, BLK_MQ_MAX_DEPTH) - 1; +- dev->tagset.cmd_size = nvme_cmd_size(dev); ++ dev->tagset.cmd_size = nvme_pci_cmd_size(dev, false); ++ if ((dev->ctrl.sgls & ((1 << 0) | (1 << 1))) && sgl_threshold) { ++ dev->tagset.cmd_size = max(dev->tagset.cmd_size, ++ nvme_pci_cmd_size(dev, true)); ++ } + dev->tagset.flags = BLK_MQ_F_SHOULD_MERGE; + dev->tagset.driver_data = dev; + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0125-nvme-pci-don-t-open-code-nvme_reset_ctrl.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0125-nvme-pci-don-t-open-code-nvme_reset_ctrl.patch new file mode 100644 index 00000000..406d0f75 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0125-nvme-pci-don-t-open-code-nvme_reset_ctrl.patch @@ -0,0 +1,36 @@ +From 5814a8b9881d3280577d7ccf640b63bfee9822ae Mon Sep 17 00:00:00 2001 +From: Sagi Grimberg +Date: Sun, 31 Dec 2017 14:01:19 +0200 +Subject: [PATCH 074/122] nvme-pci: don't open-code nvme_reset_ctrl + +Signed-off-by: Sagi Grimberg +Signed-off-by: Christoph Hellwig + +(cherry picked from commit 4caff8fc19f10ffb06f095a9cf5a9e755377112e +https://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git) + +Signed-off-by: Valentine Barshak +--- + drivers/nvme/host/pci.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c +index 433c6dc..8f234b5 100644 +--- a/drivers/nvme/host/pci.c ++++ b/drivers/nvme/host/pci.c +@@ -2533,10 +2533,10 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) + if (result) + goto release_pools; + +- nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_RESETTING); + dev_info(dev->ctrl.device, "pci function %s\n", dev_name(&pdev->dev)); + +- queue_work(nvme_wq, &dev->ctrl.reset_work); ++ nvme_reset_ctrl(&dev->ctrl); ++ + return 0; + + release_pools: +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0126-nvme-pci-limit-max-IO-size-and-segments-to-avoid-hig.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0126-nvme-pci-limit-max-IO-size-and-segments-to-avoid-hig.patch new file mode 100644 index 00000000..b56c0510 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0126-nvme-pci-limit-max-IO-size-and-segments-to-avoid-hig.patch @@ -0,0 +1,164 @@ +From 226592cd140ed5f1b08d2ceb51f1a1b2e629b506 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Sun, 24 Feb 2019 01:05:24 +0300 +Subject: [PATCH 075/122] nvme-pci: limit max IO size and segments to avoid + high order allocations + +nvme requires an sg table allocation for each request. If the request +is large, then the allocation can become quite large. For instance, +with our default software settings of 1280KB IO size, we'll need +10248 bytes of sg table. That turns into a 2nd order allocation, +which we can't always guarantee. If we fail the allocation, blk-mq +will retry it later. But there's no guarantee that we'll EVER be +able to allocate that much contigious memory. + +Limit the IO size such that we never need more than a single page +of memory. That's a lot faster and more reliable. Then back that +allocation with a mempool, so that we know we'll always be able +to succeed the allocation at some point. + +Signed-off-by: Jens Axboe +Acked-by: Keith Busch +Signed-off-by: Christoph Hellwig + +(cherry picked from commit 943e942e6266f22babee5efeb00f8f672fbff5bd +https://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git) + +Slightly modified the original commit to make it apply with no fuzz. + +Signed-off-by: Valentine Barshak +--- + drivers/nvme/host/core.c | 1 + + drivers/nvme/host/nvme.h | 1 + + drivers/nvme/host/pci.c | 42 +++++++++++++++++++++++++++++++++++++----- + 3 files changed, 39 insertions(+), 5 deletions(-) + +diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c +index 3a63d58..adb9196 100644 +--- a/drivers/nvme/host/core.c ++++ b/drivers/nvme/host/core.c +@@ -1513,6 +1513,7 @@ static void nvme_set_queue_limits(struct nvme_ctrl *ctrl, + u32 max_segments = + (ctrl->max_hw_sectors / (ctrl->page_size >> 9)) + 1; + ++ max_segments = min_not_zero(max_segments, ctrl->max_segments); + blk_queue_max_hw_sectors(q, ctrl->max_hw_sectors); + blk_queue_max_segments(q, min_t(u32, max_segments, USHRT_MAX)); + } +diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h +index 7ef0a8e..d207ff1 100644 +--- a/drivers/nvme/host/nvme.h ++++ b/drivers/nvme/host/nvme.h +@@ -159,6 +159,7 @@ struct nvme_ctrl { + u64 cap; + u32 page_size; + u32 max_hw_sectors; ++ u32 max_segments; + u16 oncs; + u16 vid; + u16 oacs; +diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c +index 8f234b5..4c585e7 100644 +--- a/drivers/nvme/host/pci.c ++++ b/drivers/nvme/host/pci.c +@@ -47,6 +47,13 @@ + + #define SGES_PER_PAGE (PAGE_SIZE / sizeof(struct nvme_sgl_desc)) + ++/* ++ * These can be higher, but we need to ensure that any command doesn't ++ * require an sg allocation that needs more than a page of data. ++ */ ++#define NVME_MAX_KB_SZ 4096 ++#define NVME_MAX_SEGS 127 ++ + static int use_threaded_interrupts; + module_param(use_threaded_interrupts, int, 0); + +@@ -109,6 +116,8 @@ struct nvme_dev { + struct nvme_ctrl ctrl; + struct completion ioq_wait; + ++ mempool_t *iod_mempool; ++ + /* shadow doorbell buffer support: */ + u32 *dbbuf_dbs; + dma_addr_t dbbuf_dbs_dma_addr; +@@ -473,10 +482,7 @@ static blk_status_t nvme_init_iod(struct request *rq, struct nvme_dev *dev) + unsigned int size = blk_rq_payload_bytes(rq); + + if (nseg > NVME_INT_PAGES || size > NVME_INT_BYTES(dev)) { +- size_t alloc_size = nvme_pci_iod_alloc_size(dev, size, nseg, +- iod->use_sgl); +- +- iod->sg = kmalloc(alloc_size, GFP_ATOMIC); ++ iod->sg = mempool_alloc(dev->iod_mempool, GFP_ATOMIC); + if (!iod->sg) + return BLK_STS_RESOURCE; + } else { +@@ -522,7 +528,7 @@ static void nvme_free_iod(struct nvme_dev *dev, struct request *req) + } + + if (iod->sg != iod->inline_sg) +- kfree(iod->sg); ++ mempool_free(iod->sg, dev->iod_mempool); + } + + #ifdef CONFIG_BLK_DEV_INTEGRITY +@@ -2303,6 +2309,7 @@ static void nvme_pci_free_ctrl(struct nvme_ctrl *ctrl) + blk_put_queue(dev->ctrl.admin_q); + kfree(dev->queues); + free_opal_dev(dev->ctrl.opal_dev); ++ mempool_destroy(dev->iod_mempool); + kfree(dev); + } + +@@ -2345,6 +2352,13 @@ static void nvme_reset_work(struct work_struct *work) + if (result) + goto out; + ++ /* ++ * Limit the max command size to prevent iod->sg allocations going ++ * over a single page. ++ */ ++ dev->ctrl.max_hw_sectors = NVME_MAX_KB_SZ << 1; ++ dev->ctrl.max_segments = NVME_MAX_SEGS; ++ + result = nvme_init_identify(&dev->ctrl); + if (result) + goto out; +@@ -2496,6 +2510,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) + int node, result = -ENOMEM; + struct nvme_dev *dev; + unsigned long quirks = id->driver_data; ++ size_t alloc_size; + + node = dev_to_node(&pdev->dev); + if (node == NUMA_NO_NODE) +@@ -2533,6 +2548,23 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) + if (result) + goto release_pools; + ++ /* ++ * Double check that our mempool alloc size will cover the biggest ++ * command we support. ++ */ ++ alloc_size = nvme_pci_iod_alloc_size(dev, NVME_MAX_KB_SZ, ++ NVME_MAX_SEGS, true); ++ WARN_ON_ONCE(alloc_size > PAGE_SIZE); ++ ++ dev->iod_mempool = mempool_create_node(1, mempool_kmalloc, ++ mempool_kfree, ++ (void *) alloc_size, ++ GFP_KERNEL, node); ++ if (!dev->iod_mempool) { ++ result = -ENOMEM; ++ goto release_pools; ++ } ++ + dev_info(dev->ctrl.device, "pci function %s\n", dev_name(&pdev->dev)); + + nvme_reset_ctrl(&dev->ctrl); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0127-swiotlb-Respect-DMA_ATTR_NO_WARN-in-swiotlb_map_sg_a.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0127-swiotlb-Respect-DMA_ATTR_NO_WARN-in-swiotlb_map_sg_a.patch new file mode 100644 index 00000000..c829fea1 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0127-swiotlb-Respect-DMA_ATTR_NO_WARN-in-swiotlb_map_sg_a.patch @@ -0,0 +1,33 @@ +From 33342c77defd9f19b91269521f6eda34fdf0410b Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Sat, 2 Mar 2019 01:18:25 +0300 +Subject: [PATCH 076/122] swiotlb: Respect DMA_ATTR_NO_WARN in + swiotlb_map_sg_attrs + +If DMA_ATTR_NO_WARN attribute is set, do not call swiotlb_full() +to print a "swiotlb full" warning. The function is actually removed +altogether in the later kernels since all properly written drivers +have error handling in the dma_map_single / dma_map_page callers. + +Signed-off-by: Valentine Barshak +--- + lib/swiotlb.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/lib/swiotlb.c b/lib/swiotlb.c +index 20df2fd..7b5666d 100644 +--- a/lib/swiotlb.c ++++ b/lib/swiotlb.c +@@ -995,7 +995,8 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems, + if (map == SWIOTLB_MAP_ERROR) { + /* Don't panic here, we expect map_sg users + to do proper error handling. */ +- swiotlb_full(hwdev, sg->length, dir, 0); ++ if (!(attrs & DMA_ATTR_NO_WARN)) ++ swiotlb_full(hwdev, sg->length, dir, 0); + attrs |= DMA_ATTR_SKIP_CPU_SYNC; + swiotlb_unmap_sg_attrs(hwdev, sgl, i, dir, + attrs); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0128-arm64-dts-Add-H3ULCB-VideoBox-2.1-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0128-arm64-dts-Add-H3ULCB-VideoBox-2.1-support.patch new file mode 100644 index 00000000..93d88621 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0128-arm64-dts-Add-H3ULCB-VideoBox-2.1-support.patch @@ -0,0 +1,292 @@ +From 79d76546341424d3b712bfb65c96f5150386da72 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Fri, 22 Feb 2019 19:45:04 +0300 +Subject: [PATCH 077/122] arm64: dts: Add H3ULCB VideoBox 2.1 support. + +This adds VideoBox 2.1 support for H3ULCB and H3ULCB 4x2G boards. + +Signed-off-by: Andrey Gusakov +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/Makefile | 1 + + .../boot/dts/renesas/r8a7795-h3ulcb-4x2g-vb2.1.dts | 68 ++++++++++++++++ + .../boot/dts/renesas/r8a7795-h3ulcb-vb2.1.dts | 68 ++++++++++++++++ + arch/arm64/boot/dts/renesas/ulcb-vb2.1.dtsi | 90 ++++++++++++++++++++++ + arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 2 +- + 5 files changed, 228 insertions(+), 1 deletion(-) + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-4x2g-vb2.1.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb2.1.dts + create mode 100644 arch/arm64/boot/dts/renesas/ulcb-vb2.1.dtsi + +diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile +index e7fc36e..f7f8638 100644 +--- a/arch/arm64/boot/dts/renesas/Makefile ++++ b/arch/arm64/boot/dts/renesas/Makefile +@@ -30,6 +30,7 @@ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-had-alfa.dtb r8a7795-h3ulcb-had-bet + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-kf.dtb r8a7795-es1-h3ulcb-kf.dtb r8a7795-h3ulcb-4x2g-kf.dtb + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-vb.dtb r8a7795-es1-h3ulcb-vb.dtb r8a7795-h3ulcb-4x2g-vb.dtb + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-vb2.dtb r8a7795-es1-h3ulcb-vb2.dtb r8a7795-h3ulcb-4x2g-vb2.dtb ++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-vb2.1.dtb r8a7795-h3ulcb-4x2g-vb2.1.dtb + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-vbm.dtb r8a7795-es1-h3ulcb-vbm.dtb r8a7795-h3ulcb-4x2g-vbm.dtb + dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-m3nulcb-kf.dtb + #dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-eagle-function.dtb +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-4x2g-vb2.1.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-4x2g-vb2.1.dts +new file mode 100644 +index 0000000..1a9d0be +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-4x2g-vb2.1.dts +@@ -0,0 +1,68 @@ ++/* ++ * Device Tree Source for the H3ULCB Videobox board V2.1 on r8a7795 ++ * ++ * Copyright (C) 2019 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-h3ulcb-4x2g.dts" ++#include "ulcb-vb2.1.dtsi" ++ ++/ { ++ model = "Renesas H3ULCB with 8GiB (4 x 2 GiB) Videobox V2.1 board based on r8a7795"; ++ ++ hdmi1-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi1_con: endpoint { ++ remote-endpoint = <&rcar_dw_hdmi1_out>; ++ }; ++ }; ++ }; ++}; ++ ++&du { ++ ports { ++ port@2 { ++ endpoint { ++ remote-endpoint = <&rcar_dw_hdmi1_in>; ++ }; ++ }; ++ port@3 { ++ endpoint { ++ remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++}; ++ ++&hdmi1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ rcar_dw_hdmi1_in: endpoint { ++ remote-endpoint = <&du_out_hdmi1>; ++ }; ++ }; ++ port@1 { ++ reg = <1>; ++ rcar_dw_hdmi1_out: endpoint { ++ remote-endpoint = <&hdmi1_con>; ++ }; ++ }; ++ }; ++}; ++ ++&hsusb { ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb2.1.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb2.1.dts +new file mode 100644 +index 0000000..43c20b0 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb2.1.dts +@@ -0,0 +1,68 @@ ++/* ++ * Device Tree Source for the H3ULCB Videobox board V2.1 on r8a7795 ++ * ++ * Copyright (C) 2019 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-h3ulcb.dts" ++#include "ulcb-vb2.1.dtsi" ++ ++/ { ++ model = "Renesas H3ULCB Videobox V2.1 board based on r8a7795"; ++ ++ hdmi1-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi1_con: endpoint { ++ remote-endpoint = <&rcar_dw_hdmi1_out>; ++ }; ++ }; ++ }; ++}; ++ ++&du { ++ ports { ++ port@2 { ++ endpoint { ++ remote-endpoint = <&rcar_dw_hdmi1_in>; ++ }; ++ }; ++ port@3 { ++ endpoint { ++ remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++}; ++ ++&hdmi1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ rcar_dw_hdmi1_in: endpoint { ++ remote-endpoint = <&du_out_hdmi1>; ++ }; ++ }; ++ port@1 { ++ reg = <1>; ++ rcar_dw_hdmi1_out: endpoint { ++ remote-endpoint = <&hdmi1_con>; ++ }; ++ }; ++ }; ++}; ++ ++&hsusb { ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/ulcb-vb2.1.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vb2.1.dtsi +new file mode 100644 +index 0000000..0df720d +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/ulcb-vb2.1.dtsi +@@ -0,0 +1,90 @@ ++/* ++ * Device Tree Source for the ULCB Videobox V2.1 board ++ * ++ * Copyright (C) 2019 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "ulcb-vb2.dtsi" ++ ++/{ ++ leds { ++ led_button { ++ gpios = <&gpio_ext_led 9 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "cpu"; ++ }; ++ }; ++ ++ gpio_keys_polled { ++ compatible = "gpio-keys-polled"; ++ poll-interval = <100>; ++ autorepeat; ++ ++ button_pwr { ++ label = "GPIO Key POWER"; ++ linux,code = <116>; ++ gpios = <&gpio_ext_led 8 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&i2c_power { ++ adc@48 { ++ reg = <0x48>; ++ compatible = "ti,ads1115"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ wake7_voltage: channel@4 { ++ /* single endded AIN0 */ ++ reg = <4>; ++ }; ++ wake8_voltage: channel@5 { ++ /* single endded AIN1 */ ++ reg = <5>; ++ }; ++ dc_prot_voltage: channel@6 { ++ /* single endded AIN2 */ ++ reg = <6>; ++ }; ++ dcdc_voltage: channel@7 { ++ /* single endded AIN3 */ ++ reg = <7>; ++ }; ++ }; ++}; ++ ++&gpio6 { ++ /delete-node/m2_0_rst; ++ ++ m2_0_rst { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "M.2 0 RST#"; ++ }; ++}; ++ ++&pfc { ++ usb1_pins: usb1 { ++ groups = "usb1"; ++ function = "usb1"; ++ }; ++}; ++ ++&usb2_phy1 { ++ pinctrl-0 = <&usb1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&ehci1 { ++ status = "okay"; ++}; ++ ++&ohci1 { ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi +index 0f49b44..1610949 100644 +--- a/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi ++++ b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi +@@ -1061,7 +1061,7 @@ + }; + }; + +- i2c@2 { ++ i2c_power: i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0129-can-rcar_canfd-fix-possible-IRQ-storm-on-high-load.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0129-can-rcar_canfd-fix-possible-IRQ-storm-on-high-load.patch new file mode 100644 index 00000000..4de49573 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0129-can-rcar_canfd-fix-possible-IRQ-storm-on-high-load.patch @@ -0,0 +1,63 @@ +From 0c0b56e36d1b3479f5e3f6c2b8bf52b89caa3b78 Mon Sep 17 00:00:00 2001 +From: Nikita Yushchenko +Date: Wed, 13 Mar 2019 18:49:28 +0300 +Subject: [PATCH 078/122] can: rcar_canfd: fix possible IRQ storm on high load + +We have observed rcar_canfd driver entering IRQ storm under high load, +with following scenario: +- rcar_canfd_global_interrupt() in entered due to Rx available, +- napi_schedule_prep() is called, and sets NAPIF_STATE_SCHED in state +- Rx fifo interrupts are masked, +- rcar_canfd_global_interrupt() is entered again, this time due to + error interrupt (e.g. due to overflow), +- since scheduled napi poller has not yet executed, condition for calling + napi_schedule_prep() from rcar_canfd_global_interrupt() remains true, + thus napi_schedule_prep() gets called and sets NAPIF_STATE_MISSED flag + in state, +- later, napi poller function rcar_canfd_rx_poll() gets executed, and + calls napi_complete_done(), +- due to NAPIF_STATE_MISSED flag in state, this call does not clear + NAPIF_STATE_SCHED flag from state, +- on return from napi_complete_done(), rcar_canfd_rx_poll() unmasks Rx + interrutps, +- Rx interrupt happens, rcar_canfd_global_interrupt() gets called + and calls napi_schedule_prep(), +- since NAPIF_STATE_SCHED is set in state at this time, this call + returns false, +- due to that false return, rcar_canfd_global_interrupt() returns + without masking Rx interrupt +- and this results into IRQ storm: unmasked Rx interrupt happens again + and again is misprocessed in the same way. + +This patch fixes that scenario by unmasking Rx interrupts only when +napi_complete_done() returns true, which means it has cleared +NAPIF_STATE_SCHED in state. + +Signed-off-by: Nikita Yushchenko +--- + drivers/net/can/rcar/rcar_canfd.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c +index 5b98f8c..0017ab9 100644 +--- a/drivers/net/can/rcar/rcar_canfd.c ++++ b/drivers/net/can/rcar/rcar_canfd.c +@@ -1522,10 +1522,11 @@ static int rcar_canfd_rx_poll(struct napi_struct *napi, int quota) + + /* All packets processed */ + if (num_pkts < quota) { +- napi_complete_done(napi, num_pkts); +- /* Enable Rx FIFO interrupts */ +- rcar_canfd_set_bit(priv->base, RCANFD_RFCC(ridx), +- RCANFD_RFCC_RFIE); ++ if (napi_complete_done(napi, num_pkts)) { ++ /* Enable Rx FIFO interrupts */ ++ rcar_canfd_set_bit(priv->base, RCANFD_RFCC(ridx), ++ RCANFD_RFCC_RFIE); ++ } + } + return num_pkts; + } +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0130-LVDS-ar0132-use-context-swwitch.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0130-LVDS-ar0132-use-context-swwitch.patch new file mode 100644 index 00000000..bde202ed --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0130-LVDS-ar0132-use-context-swwitch.patch @@ -0,0 +1,119 @@ +From 4bf93979202bec78f922fa39728e0f00f8650b21 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Wed, 30 Aug 2017 14:44:29 +0300 +Subject: [PATCH 079/122] LVDS: ar0132 use context swwitch + +This enabled context-A-B switch on every frame + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ar0132.c | 19 +++++++++++++++++++ + drivers/media/platform/soc_camera/rcar_vin.c | 23 ++++++++++++++++++----- + 2 files changed, 37 insertions(+), 5 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ar0132.c b/drivers/media/i2c/soc_camera/ar0132.c +index 2865902..72dfbb4 100644 +--- a/drivers/media/i2c/soc_camera/ar0132.c ++++ b/drivers/media/i2c/soc_camera/ar0132.c +@@ -254,11 +254,30 @@ static int ar0132_s_register(struct v4l2_subdev *sd, + } + #endif + ++static int ar0132_isr(struct v4l2_subdev *sd, u32 status, bool *handled) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++#if 1 ++ u16 frame_count = 0; ++ /* read frame counter from sensor */ ++ reg16_read16(client, 0x303a, &frame_count); ++#else ++ static int frame_count = 0; ++ /* get cached frame counter */ ++ frame_count++; ++#endif ++ /* odd frame -> Mode A, even frame -> Mode B */ ++ reg16_write16(client, 0x30b0, frame_count & 1 ? 0x2 : 0x2002); ++ ++ return 0; ++}; ++ + static struct v4l2_subdev_core_ops ar0132_core_ops = { + #ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = ar0132_g_register, + .s_register = ar0132_s_register, + #endif ++ .interrupt_service_routine = ar0132_isr, + }; + + static int ar0132_s_ctrl(struct v4l2_ctrl *ctrl) +diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c +index 50d393b..5239938 100644 +--- a/drivers/media/platform/soc_camera/rcar_vin.c ++++ b/drivers/media/platform/soc_camera/rcar_vin.c +@@ -1395,13 +1395,24 @@ static const struct vb2_ops rcar_vin_vb2_ops = { + .wait_finish = vb2_ops_wait_finish, + }; + ++static irqreturn_t rcar_vin_threaded_irq(int irq, void *data) ++{ ++ struct rcar_vin_priv *priv = data; ++ struct soc_camera_device *icd = priv->ici.icd; ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ ++ v4l2_subdev_call(sd, core, interrupt_service_routine, 0, NULL); ++ ++ return IRQ_HANDLED; ++}; ++ + static irqreturn_t rcar_vin_irq(int irq, void *data) + { + struct rcar_vin_priv *priv = data; + u32 int_status; + bool can_run = false, hw_stopped; + int slot; +- unsigned int handled = 0; ++ unsigned int handled = IRQ_NONE; + int vin_ovr_cnt = 0; + + spin_lock(&priv->lock); +@@ -1412,7 +1423,7 @@ static irqreturn_t rcar_vin_irq(int irq, void *data) + + /* ack interrupts */ + iowrite32(int_status, priv->base + VNINTS_REG); +- handled = 1; ++ handled = IRQ_HANDLED; + + /* overflow occurs */ + if (vin_debug && (int_status & VNINTS_FOS)) { +@@ -1445,6 +1456,8 @@ static irqreturn_t rcar_vin_irq(int irq, void *data) + priv->queue_buf[slot] = NULL; + + can_run = rcar_vin_fill_hw_slot(priv); ++ ++ handled = IRQ_WAKE_THREAD; + } + + if (is_continuous_transfer(priv)) { +@@ -1473,7 +1486,7 @@ static irqreturn_t rcar_vin_irq(int irq, void *data) + done: + spin_unlock(&priv->lock); + +- return IRQ_RETVAL(handled); ++ return handled; + } + + static struct v4l2_subdev *find_csi2(struct rcar_vin_priv *pcdev) +@@ -3043,8 +3056,8 @@ static int rcar_vin_probe(struct platform_device *pdev) + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + +- ret = devm_request_irq(&pdev->dev, irq, rcar_vin_irq, IRQF_SHARED, +- dev_name(&pdev->dev), priv); ++ ret = devm_request_threaded_irq(&pdev->dev, irq, rcar_vin_irq, rcar_vin_threaded_irq, ++ IRQF_SHARED, dev_name(&pdev->dev), priv); + if (ret) + return ret; + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0131-media-i2c-soc_camera-Bunch-update-from-2.23.1.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0131-media-i2c-soc_camera-Bunch-update-from-2.23.1.patch new file mode 100644 index 00000000..881079bf --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0131-media-i2c-soc_camera-Bunch-update-from-2.23.1.patch @@ -0,0 +1,13431 @@ +From 6509268d16bf6136907337a5101705449d4b844f Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Wed, 7 Nov 2018 22:42:50 +0300 +Subject: [PATCH 080/122] media: i2c: soc_camera: Bunch update from 2.23.1 + +--- + drivers/media/i2c/soc_camera/ap0101_ar014x.c | 78 +- + drivers/media/i2c/soc_camera/ar0132.c | 3 +- + drivers/media/i2c/soc_camera/ar0132.h | 9 +- + drivers/media/i2c/soc_camera/ar0140.c | 648 +++++ + drivers/media/i2c/soc_camera/ar0140.h | 475 ++++ + drivers/media/i2c/soc_camera/ar0143.c | 678 +++++ + drivers/media/i2c/soc_camera/ar0143.h | 549 ++++ + drivers/media/i2c/soc_camera/ar0220.c | 20 +- + drivers/media/i2c/soc_camera/ar0220.h | 18 +- + drivers/media/i2c/soc_camera/ar0231.c | 580 ++++ + drivers/media/i2c/soc_camera/ar0231.h | 34 + + drivers/media/i2c/soc_camera/ar0231_rev4.h | 348 +++ + drivers/media/i2c/soc_camera/ar0233.c | 579 ++++ + drivers/media/i2c/soc_camera/ar0233.h | 409 +++ + drivers/media/i2c/soc_camera/gw4200_ar014x.c | 592 ++++ + drivers/media/i2c/soc_camera/gw4200_ar014x.h | 28 + + drivers/media/i2c/soc_camera/imx390.c | 574 ++++ + drivers/media/i2c/soc_camera/imx390.h | 3818 ++++++++++++++++++++++++++ + drivers/media/i2c/soc_camera/max9286.c | 406 ++- + drivers/media/i2c/soc_camera/max9286.h | 1 + + drivers/media/i2c/soc_camera/ov10635.c | 38 +- + drivers/media/i2c/soc_camera/ov10635.h | 10 +- + drivers/media/i2c/soc_camera/ov106xx.c | 79 +- + drivers/media/i2c/soc_camera/ov2775.c | 14 +- + drivers/media/i2c/soc_camera/ov2775.h | 32 +- + drivers/media/i2c/soc_camera/ov490_ov10640.c | 1 - + drivers/media/i2c/soc_camera/ov495_ov2775.c | 16 +- + drivers/media/i2c/soc_camera/ox03a.c | 589 ++++ + drivers/media/i2c/soc_camera/ox03a.h | 1766 ++++++++++++ + drivers/media/i2c/soc_camera/ti9x4.c | 94 +- + 30 files changed, 12305 insertions(+), 181 deletions(-) + create mode 100644 drivers/media/i2c/soc_camera/ar0140.c + create mode 100644 drivers/media/i2c/soc_camera/ar0140.h + create mode 100644 drivers/media/i2c/soc_camera/ar0143.c + create mode 100644 drivers/media/i2c/soc_camera/ar0143.h + create mode 100644 drivers/media/i2c/soc_camera/ar0231.c + create mode 100644 drivers/media/i2c/soc_camera/ar0231.h + create mode 100644 drivers/media/i2c/soc_camera/ar0231_rev4.h + create mode 100644 drivers/media/i2c/soc_camera/ar0233.c + create mode 100644 drivers/media/i2c/soc_camera/ar0233.h + create mode 100644 drivers/media/i2c/soc_camera/gw4200_ar014x.c + create mode 100644 drivers/media/i2c/soc_camera/gw4200_ar014x.h + create mode 100644 drivers/media/i2c/soc_camera/imx390.c + create mode 100644 drivers/media/i2c/soc_camera/imx390.h + create mode 100644 drivers/media/i2c/soc_camera/ox03a.c + create mode 100644 drivers/media/i2c/soc_camera/ox03a.h + +diff --git a/drivers/media/i2c/soc_camera/ap0101_ar014x.c b/drivers/media/i2c/soc_camera/ap0101_ar014x.c +index d8025a4..142942d 100644 +--- a/drivers/media/i2c/soc_camera/ap0101_ar014x.c ++++ b/drivers/media/i2c/soc_camera/ap0101_ar014x.c +@@ -19,11 +19,10 @@ + #include + #include + #include +-#include + + #include "ap0101_ar014x.h" + +-#define AP0101_I2C_ADDR 0x5d ++static const int ap0101_i2c_addr[] = {0x5d, 0x48}; + + #define AP0101_PID 0x0000 + #define AP0101_VERSION_REG 0x0160 +@@ -37,6 +36,8 @@ struct ap0101_priv { + struct v4l2_ctrl_handler hdl; + struct media_pad pad; + struct v4l2_rect rect; ++ int max_width; ++ int max_height; + int init_complete; + u8 id[6]; + int exposure; +@@ -48,6 +49,9 @@ struct ap0101_priv { + int port; + int gpio_resetb; + int gpio_fsin; ++ int hts; ++ int vts; ++ int frame_preamble; + }; + + static inline struct ap0101_priv *to_ap0101(const struct i2c_client *client) +@@ -207,8 +211,8 @@ static int ap0101_set_selection(struct v4l2_subdev *sd, + rect->width = ALIGN(rect->width, 2); + rect->height = ALIGN(rect->height, 2); + +- if ((rect->left + rect->width > AP0101_MAX_WIDTH) || +- (rect->top + rect->height > AP0101_MAX_HEIGHT)) ++ if ((rect->left + rect->width > priv->max_width) || ++ (rect->top + rect->height > priv->max_height)) + *rect = priv->rect; + + priv->rect.left = rect->left; +@@ -233,14 +237,14 @@ static int ap0101_get_selection(struct v4l2_subdev *sd, + case V4L2_SEL_TGT_CROP_BOUNDS: + sel->r.left = 0; + sel->r.top = 0; +- sel->r.width = AP0101_MAX_WIDTH; +- sel->r.height = AP0101_MAX_HEIGHT; ++ sel->r.width = priv->max_width; ++ sel->r.height = priv->max_height; + return 0; + case V4L2_SEL_TGT_CROP_DEFAULT: + sel->r.left = 0; + sel->r.top = 0; +- sel->r.width = AP0101_MAX_WIDTH; +- sel->r.height = AP0101_MAX_HEIGHT; ++ sel->r.width = priv->max_width; ++ sel->r.height = priv->max_height; + return 0; + case V4L2_SEL_TGT_CROP: + sel->r = priv->rect; +@@ -381,11 +385,29 @@ static DEVICE_ATTR(otp_id_ap0101, S_IRUGO, ap0101_otp_id_show, NULL); + static int ap0101_initialize(struct i2c_client *client) + { + struct ap0101_priv *priv = to_ap0101(client); +- u16 pid = 0; ++ u16 pid = 0, val = 0; + int ret = 0; ++ int tmp_addr; ++ int i; + + ap0101_s_port(client, 1); + ++ for (i = 0; i < ARRAY_SIZE(ap0101_i2c_addr); i++) { ++ tmp_addr = client->addr; ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x0A, ap0101_i2c_addr[i] << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ client->addr = tmp_addr; ++ ++ /* check model ID */ ++ reg16_read16(client, AP0101_PID, &pid); ++ ++ if (pid == AP0101_VERSION_REG) ++ break; ++ } ++ + /* check and show model ID */ + reg16_read16(client, AP0101_PID, &pid); + +@@ -394,14 +416,42 @@ static int ap0101_initialize(struct i2c_client *client) + ret = -ENODEV; + goto err; + } +- ++#if 1 ++ /* read resolution used by current firmware */ ++ reg16_read16(client, 0xca90, &val); ++ priv->max_width = val; ++ reg16_read16(client, 0xca92, &val); ++ priv->max_height = val; ++#else ++ priv->max_width = AP0101_MAX_WIDTH; ++ priv->max_height = AP0101_MAX_HEIGHT; ++#endif + /* Program wizard registers */ + ap0101_set_regs(client, ap0101_regs_wizard, ARRAY_SIZE(ap0101_regs_wizard)); + /* Read OTP IDs */ + ap0101_otp_id_read(client); + ++ tmp_addr = client->addr; ++ if (priv->max9271_addr) { ++ /* setup serializer HS generator */ ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ priv->frame_preamble = 5; ++ priv->hts = 1280 * 2 + 548; ++ priv->vts = 960; ++ reg8_write(client, 0x4e, priv->frame_preamble >> 16); /* HS delay */ ++ reg8_write(client, 0x4f, (priv->frame_preamble >> 8) & 0xff); ++ reg8_write(client, 0x50, priv->frame_preamble & 0xff); ++ reg8_write(client, 0x54, (priv->max_width * 2) >> 8); /* HS high period */ ++ reg8_write(client, 0x55, (priv->max_width * 2) & 0xff); ++ reg8_write(client, 0x56, (priv->hts - priv->max_width * 2) >> 8); /* HS low period */ ++ reg8_write(client, 0x57, (priv->hts - priv->max_width * 2) & 0xff); ++ reg8_write(client, 0x58, priv->vts >> 8); /* HS count */ ++ reg8_write(client, 0x59, priv->vts & 0xff); ++ } ++ client->addr = tmp_addr; ++ + dev_info(&client->dev, "ap0101 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", +- pid, AP0101_MAX_WIDTH, AP0101_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++ pid, priv->max_width, priv->max_height, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); + err: + ap0101_s_port(client, 0); + +@@ -443,9 +493,7 @@ static int ap0101_parse_dt(struct device_node *np, struct ap0101_priv *priv) + tmp_addr = client->addr; + if (priv->max9286_addr) { + client->addr = priv->max9271_addr; /* Serializer I2C address */ +- + reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */ +- reg8_write(client, 0x0A, AP0101_I2C_ADDR << 1); /* Sensor native I2C address */ + usleep_range(2000, 2500); /* wait 2ms */ + }; + client->addr = tmp_addr; +@@ -518,8 +566,8 @@ static int ap0101_probe(struct i2c_client *client, + + priv->rect.left = 0; + priv->rect.top = 0; +- priv->rect.width = AP0101_MAX_WIDTH; +- priv->rect.height = AP0101_MAX_HEIGHT; ++ priv->rect.width = priv->max_width; ++ priv->rect.height = priv->max_height; + + ret = v4l2_async_register_subdev(&priv->sd); + if (ret) +diff --git a/drivers/media/i2c/soc_camera/ar0132.c b/drivers/media/i2c/soc_camera/ar0132.c +index 72dfbb4..18bc5dc 100644 +--- a/drivers/media/i2c/soc_camera/ar0132.c ++++ b/drivers/media/i2c/soc_camera/ar0132.c +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + + #include "ar0132.h" + +@@ -29,7 +28,7 @@ + #define AR0132_PID 0x3000 + #define AR0132_VERSION_REG 0x2400 + +-#define AR0132_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR12_1X12 ++#define AR0132_MEDIA_BUS_FMT MEDIA_BUS_FMT_SGRBG12_1X12 + + struct ar0132_priv { + struct v4l2_subdev sd; +diff --git a/drivers/media/i2c/soc_camera/ar0132.h b/drivers/media/i2c/soc_camera/ar0132.h +index bafa193..7dfc4e3 100644 +--- a/drivers/media/i2c/soc_camera/ar0132.h ++++ b/drivers/media/i2c/soc_camera/ar0132.h +@@ -14,16 +14,15 @@ + + #define AR0132_EMBEDDED_LINE + +-#define AR0132_MAX_WIDTH 1665 // (1110*3/2) ++#define AR0132_MAX_WIDTH 1104 + #define AR0132_MAX_HEIGHT 624 + + #define AR0132_DELAY 0xffff + + #define AR0132_MAX_ROI_DIM_X 1288 + #define AR0132_MAX_ROI_DIM_Y 968 +-#define AR0132_InfoLines 4 + +-#define AR0132_ROI_DIM_X 1110 // 1104 ++#define AR0132_ROI_DIM_X 1104 + #define AR0132_ROI_DIM_Y 620 // AR0132_MAX_HEIGHT + + #define AR0132_ROI_Y_START 0x00AE +@@ -57,11 +56,11 @@ static const struct ar0132_reg ar0132_regs_wizard[] = { + //256: Walking 1 test pattern (12 bit) + #ifdef AR0132_DISPLAY_PATTERN_FIXED + {0x3070, 0x0001}, ++#endif + {0x3072, 0x0123}, // R + {0x3074, 0x0456}, // G(GR row) + {0x3076, 0x0abc}, // B + {0x3078, 0x0def}, // G(GB row) +-#endif + #ifdef AR0132_DISPLAY_PATTERN_COLOR_BAR + {0x3070, 0x0002}, + #endif +@@ -150,7 +149,7 @@ static const struct ar0132_reg ar0132_regs_wizard[] = { + {0x302E, AR0132_PLL_Pre_Clk_Div}, + {0x3030, AR0132_PLL_Multiplier}, + {0x3032, 0x0000}, // SCALING_MODE = 0 +-{0x3040, 0xC000}, // READ_MODE = read_mode_vert_flip | read_mode_horiz_mirror ++{0x3040, 0x0000}, // READ_MODE = read_mode_vert_flip | read_mode_horiz_mirror + {0x3044, 0x0404}, // Dark Control = 1028 + {0x30A6, 0x0001}, // Y Odd Inc. (A) = 1 + {0x30A8, 0x0001}, // Y Odd Inc. (B) = 1 +diff --git a/drivers/media/i2c/soc_camera/ar0140.c b/drivers/media/i2c/soc_camera/ar0140.c +new file mode 100644 +index 0000000..807b6f8 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0140.c +@@ -0,0 +1,648 @@ ++/* ++ * ON Semiconductor AR0140 sensor camera driver ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "ar0140.h" ++ ++#define AR0140_I2C_ADDR 0x10 ++ ++#define AR0140_PID 0x3000 ++#define AR0140_VERSION_REG 0x0051 ++ ++#define AR0140_MEDIA_BUS_FMT MEDIA_BUS_FMT_SGRBG12_1X12 ++ ++struct ar0140_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int init_complete; ++ u8 id[6]; ++ /* serializers */ ++ int max9286_addr; ++ int max9271_addr; ++ int ti9x4_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++ int hts; ++ int vts; ++ int frame_preamble; ++}; ++ ++static inline struct ar0140_priv *to_ar0140(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct ar0140_priv, sd); ++} ++ ++static void ar0140_s_port(struct i2c_client *client, int fwd_en) ++{ ++ struct ar0140_priv *priv = to_ar0140(client); ++ int tmp_addr; ++ ++ if (priv->max9286_addr) { ++ tmp_addr = client->addr; ++ client->addr = priv->max9286_addr; /* Deserializer I2C address */ ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ client->addr = tmp_addr; ++ }; ++} ++ ++static int ar0140_set_regs(struct i2c_client *client, ++ const struct ar0140_reg *regs, int nr_regs) ++{ ++ struct ar0140_priv *priv = to_ar0140(client); ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (regs[i].reg == AR0140_DELAY) { ++ mdelay(regs[i].val); ++ continue; ++ } ++ /* cache timings */ ++ if (regs[i].reg == 0x300a) ++ priv->vts = regs[i].val; ++ if (regs[i].reg == 0x300c) ++ priv->hts = regs[i].val; ++ if (regs[i].reg == 0x31b0) ++ priv->frame_preamble = regs[i].val - 1; ++ ++ reg16_write16(client, regs[i].reg, regs[i].val); ++ } ++ ++ return 0; ++} ++ ++static int ar0140_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int ar0140_set_window(struct v4l2_subdev *sd) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0140_priv *priv = to_ar0140(client); ++ ++ dev_dbg(&client->dev, "L=%d T=%d %dx%d\n", priv->rect.left, priv->rect.top, priv->rect.width, priv->rect.height); ++ ++ /* horiz crop start */ ++ reg16_write16(client, 0x3004, priv->rect.left); ++ /* horiz crop end */ ++ reg16_write16(client, 0x3008, priv->rect.left + priv->rect.width - 1); ++ /* vert crop start */ ++ reg16_write16(client, 0x3002, priv->rect.top); ++ /* vert crop end */ ++ reg16_write16(client, 0x3006, priv->rect.top + priv->rect.height + 1); ++ ++ return 0; ++}; ++ ++static int ar0140_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0140_priv *priv = to_ar0140(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = AR0140_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int ar0140_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = AR0140_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int ar0140_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = AR0140_MEDIA_BUS_FMT; ++ ++ return 0; ++} ++ ++static int ar0140_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0140_priv *priv = to_ar0140(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = AR0140_VERSION_REG >> 8; ++ edid->edid[9] = AR0140_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int ar0140_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0140_priv *priv = to_ar0140(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > AR0140_MAX_WIDTH) || ++ (rect->top + rect->height > AR0140_MAX_HEIGHT)) ++ *rect = priv->rect; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ ar0140_set_window(sd); ++ ++ return 0; ++} ++ ++static int ar0140_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0140_priv *priv = to_ar0140(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = AR0140_MAX_WIDTH; ++ sel->r.height = AR0140_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = AR0140_MAX_WIDTH; ++ sel->r.height = AR0140_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ar0140_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int ar0140_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u16 val = 0; ++ ++ ret = reg16_read16(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int ar0140_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return reg16_write16(client, (u16)reg->reg, (u16)reg->val); ++} ++#endif ++ ++static struct v4l2_subdev_core_ops ar0140_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ar0140_g_register, ++ .s_register = ar0140_s_register, ++#endif ++}; ++ ++static int ar0140_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0140_priv *priv = to_ar0140(client); ++ int ret = -EINVAL; ++ u16 val = 0; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ case V4L2_CID_CONTRAST: ++ case V4L2_CID_SATURATION: ++ case V4L2_CID_HUE: ++ case V4L2_CID_GAMMA: ++ case V4L2_CID_SHARPNESS: ++ case V4L2_CID_AUTOGAIN: ++ break; ++ case V4L2_CID_GAIN: ++ /* Digital gain */ ++ ret = reg16_write16(client, 0x305e, ctrl->val); ++ break; ++ case V4L2_CID_ANALOGUE_GAIN: ++ /* Analog gain */ ++ ret = reg16_write16(client, 0x3060, ctrl->val); ++ break; ++ case V4L2_CID_EXPOSURE: ++ /* T1 exposure */ ++ ret = reg16_write16(client, 0x3012, ctrl->val); ++ break; ++ case V4L2_CID_HFLIP: ++ ret = reg16_read16(client, 0x3040, &val); ++ if (ctrl->val) ++ val |= 0x4000; ++ else ++ val &= ~0x4000; ++ ret |= reg16_write16(client, 0x3040, val); ++ break; ++ case V4L2_CID_VFLIP: ++ ret = reg16_read16(client, 0x3040, &val); ++ if (ctrl->val) ++ val |= 0x8000; ++ else ++ val &= ~0x8000; ++ ret |= reg16_write16(client, 0x3040, val); ++ break; ++ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: ++ ret = 0; ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ar0140_ctrl_ops = { ++ .s_ctrl = ar0140_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops ar0140_video_ops = { ++ .s_stream = ar0140_s_stream, ++ .g_mbus_config = ar0140_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops ar0140_subdev_pad_ops = { ++ .get_edid = ar0140_get_edid, ++ .enum_mbus_code = ar0140_enum_mbus_code, ++ .get_selection = ar0140_get_selection, ++ .set_selection = ar0140_set_selection, ++ .get_fmt = ar0140_get_fmt, ++ .set_fmt = ar0140_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops ar0140_subdev_ops = { ++ .core = &ar0140_core_ops, ++ .video = &ar0140_video_ops, ++ .pad = &ar0140_subdev_pad_ops, ++}; ++ ++static void ar0140_otp_id_read(struct i2c_client *client) ++{ ++ struct ar0140_priv *priv = to_ar0140(client); ++ int i; ++ u16 val = 0; ++ ++ /* read camera id from ar014x OTP memory */ ++ reg16_write16(client, 0x3054, 0x400); ++ reg16_write16(client, 0x304a, 0x110); ++ usleep_range(25000, 25500); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i += 2) { ++ /* first 4 bytes are equal on all ar014x */ ++ reg16_read16(client, 0x3800 + i + 4, &val); ++ priv->id[i] = val >> 8; ++ priv->id[i + 1] = val & 0xff; ++ } ++} ++ ++static ssize_t ar0140_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0140_priv *priv = to_ar0140(client); ++ ++ ar0140_otp_id_read(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_ar0140, S_IRUGO, ar0140_otp_id_show, NULL); ++ ++static int ar0140_initialize(struct i2c_client *client) ++{ ++ struct ar0140_priv *priv = to_ar0140(client); ++ u16 val = 0; ++ u16 pid = 0; ++ int ret = 0; ++ int tmp_addr; ++ ++ ar0140_s_port(client, 1); ++ ++ /* check and show model ID */ ++ reg16_read16(client, AR0140_PID, &pid); ++ ++ if (pid != AR0140_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x\n", pid); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ tmp_addr = client->addr; ++ if (priv->max9271_addr) { ++ /* setup serializer HS generator */ ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x4e, priv->frame_preamble >> 16); /* HS delay */ ++ reg8_write(client, 0x4f, (priv->frame_preamble >> 8) & 0xff); ++ reg8_write(client, 0x50, priv->frame_preamble & 0xff); ++ reg8_write(client, 0x54, AR0140_MAX_WIDTH >> 8); /* HS high period */ ++ reg8_write(client, 0x55, AR0140_MAX_WIDTH & 0xff); ++ reg8_write(client, 0x56, (priv->hts - AR0140_MAX_WIDTH) >> 8); /* HS low period */ ++ reg8_write(client, 0x57, (priv->hts - AR0140_MAX_WIDTH) & 0xff); ++ reg8_write(client, 0x58, priv->vts >> 8); /* HS count */ ++ reg8_write(client, 0x59, priv->vts & 0xff); ++ } ++ client->addr = tmp_addr; ++ ++ /* Read OTP IDs */ ++ ar0140_otp_id_read(client); ++ /* Program wizard registers */ ++ ar0140_set_regs(client, ar0140_regs_wizard, ARRAY_SIZE(ar0140_regs_wizard)); ++ /* Enable stream */ ++ reg16_read16(client, 0x301a, &val); // read inital reset_register value ++ val |= (1 << 2); // Set streamOn bit ++ reg16_write16(client, 0x301a, val); // Start Streaming ++ ++ dev_info(&client->dev, "ar0140 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, AR0140_MAX_WIDTH, AR0140_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ ar0140_s_port(client, 0); ++ ++ return ret; ++} ++ ++static int ar0140_parse_dt(struct device_node *np, struct ar0140_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ of_node_put(endpoint); ++ ++ if (!priv->max9286_addr && !priv->ti9x4_addr) { ++ dev_err(&client->dev, "deserializer does not present for AR0140\n"); ++ return -EINVAL; ++ } ++ ++ ar0140_s_port(client, 1); ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ ++ reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x0A, AR0140_I2C_ADDR << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, AR0140_I2C_ADDR << 1); /* Sensor native I2C address */ ++ ++ reg8_write(client, 0x6e, 0x9a); /* GPIO0 - fsin, GPIO1 - reset */ ++ } ++ client->addr = tmp_addr; ++ ++ mdelay(10); ++ ++ return 0; ++} ++ ++static int ar0140_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ar0140_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &ar0140_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0140_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0140_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0140_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0140_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0140_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0140_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0140_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0140_ctrl_ops, ++ V4L2_CID_GAIN, 1, 0x7ff, 1, 0x80); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0140_ctrl_ops, ++ V4L2_CID_ANALOGUE_GAIN, 1, 0x7ff, 1, 0x1); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0140_ctrl_ops, ++ V4L2_CID_EXPOSURE, 1, 0x400, 1, 0x206); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0140_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0140_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = ar0140_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = ar0140_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = AR0140_MAX_WIDTH; ++ priv->rect.height = AR0140_MAX_HEIGHT; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ar0140) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_AR0140 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int ar0140_remove(struct i2c_client *client) ++{ ++ struct ar0140_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ar0140); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_AR0140 ++static const struct i2c_device_id ar0140_id[] = { ++ { "ar0140", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ar0140_id); ++ ++static const struct of_device_id ar0140_of_ids[] = { ++ { .compatible = "aptina,ar0140", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ar0140_of_ids); ++ ++static struct i2c_driver ar0140_i2c_driver = { ++ .driver = { ++ .name = "ar0140", ++ .of_match_table = ar0140_of_ids, ++ }, ++ .probe = ar0140_probe, ++ .remove = ar0140_remove, ++ .id_table = ar0140_id, ++}; ++ ++module_i2c_driver(ar0140_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for AR0140"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/ar0140.h b/drivers/media/i2c/soc_camera/ar0140.h +new file mode 100644 +index 0000000..f90762c +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0140.h +@@ -0,0 +1,475 @@ ++/* ++ * ON Semiconductor AR0140 sensor camera wizard 1344x968@30/BGGR/BT601/RAW12 ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++//#define AR0140_DISPLAY_PATTERN_FIXED ++//#define AR0140_DISPLAY_PATTERN_COLOR_BAR ++ ++//#define AR0140_EMBEDDED_LINE ++ ++#define AR0140_MAX_WIDTH 1280 ++#define AR0140_MAX_HEIGHT 800 ++ ++#define AR0140_DELAY 0xffff ++ ++#define AR0140_SENSOR_WIDTH 1280 ++#define AR0140_SENSOR_HEIGHT 800 ++ ++#define AR0140_X_START ((AR0140_SENSOR_WIDTH - AR0140_MAX_WIDTH) / 2) ++#define AR0140_Y_START ((AR0140_SENSOR_HEIGHT - AR0140_MAX_HEIGHT) / 2) ++#define AR0140_X_END (AR0140_X_START + AR0140_MAX_WIDTH - 1) ++#define AR0140_Y_END (AR0140_Y_START + AR0140_MAX_HEIGHT + 1) /* must be +1 and not -1 or 2 lines missed - bug in imager? */ ++ ++struct ar0140_reg { ++ u16 reg; ++ u16 val; ++}; ++ ++static const struct ar0140_reg ar0140_regs_wizard[] = { ++{0x301A, 0x0001}, // reset ++{AR0140_DELAY, 100}, ++{0x301A, 0x10D8}, // Stream off and setup parallel ++{0x3070, 0x0001}, ++{0x3070, 0x0000}, // 1: Solid color test pattern, ++ // 2: Full color bar test pattern, ++ // 3: Fade to grey color bar test pattern, ++ //256: Walking 1 test pattern (12 bit) ++#ifdef AR0140_DISPLAY_PATTERN_FIXED ++{0x3070, 0x0001}, ++#endif ++{0x3072, 0x0fff}, // R ++{0x3074, 0x0fff}, // G(GR row) ++{0x3076, 0x0fff}, // B ++{0x3078, 0x0fff}, // G(GB row) ++#ifdef AR0140_DISPLAY_PATTERN_COLOR_BAR ++{0x3070, 0x0002}, ++#endif ++{AR0140_DELAY, 250}, ++/* SEQ_CTRL_PORT */ ++{0x3088, 0x8000}, ++/* SEQ_DATA_PORT */ ++{0x3086, 0x4558}, ++{0x3086, 0x6E9B}, ++{0x3086, 0x4A31}, ++{0x3086, 0x4342}, ++{0x3086, 0x8E03}, ++{0x3086, 0x2714}, ++{0x3086, 0x4578}, ++{0x3086, 0x7B3D}, ++{0x3086, 0xFF3D}, ++{0x3086, 0xFF3D}, ++{0x3086, 0xEA27}, ++{0x3086, 0x043D}, ++{0x3086, 0x1027}, ++{0x3086, 0x0527}, ++{0x3086, 0x1535}, ++{0x3086, 0x2705}, ++{0x3086, 0x3D10}, ++{0x3086, 0x4558}, ++{0x3086, 0x2704}, ++{0x3086, 0x2714}, ++{0x3086, 0x3DFF}, ++{0x3086, 0x3DFF}, ++{0x3086, 0x3DEA}, ++{0x3086, 0x2704}, ++{0x3086, 0x6227}, ++{0x3086, 0x288E}, ++{0x3086, 0x0036}, ++{0x3086, 0x2708}, ++{0x3086, 0x3D64}, ++{0x3086, 0x7A3D}, ++{0x3086, 0x0444}, ++{0x3086, 0x2C4B}, ++{0x3086, 0x8F00}, ++{0x3086, 0x4372}, ++{0x3086, 0x719F}, ++{0x3086, 0x6343}, ++{0x3086, 0x166F}, ++{0x3086, 0x9F92}, ++{0x3086, 0x1244}, ++{0x3086, 0x1663}, ++{0x3086, 0x4316}, ++{0x3086, 0x9326}, ++{0x3086, 0x0426}, ++{0x3086, 0x848E}, ++{0x3086, 0x0327}, ++{0x3086, 0xFC5C}, ++{0x3086, 0x0D57}, ++{0x3086, 0x5417}, ++{0x3086, 0x0955}, ++{0x3086, 0x5649}, ++{0x3086, 0x5F53}, ++{0x3086, 0x0553}, ++{0x3086, 0x0728}, ++{0x3086, 0x6C4C}, ++{0x3086, 0x0928}, ++{0x3086, 0x2C72}, ++{0x3086, 0xAD7C}, ++{0x3086, 0xA928}, ++{0x3086, 0xA879}, ++{0x3086, 0x6026}, ++{0x3086, 0x9C5C}, ++{0x3086, 0x1B45}, ++{0x3086, 0x4845}, ++{0x3086, 0x0845}, ++{0x3086, 0x8826}, ++{0x3086, 0xBE8E}, ++{0x3086, 0x0127}, ++{0x3086, 0xF817}, ++{0x3086, 0x0227}, ++{0x3086, 0xFA17}, ++{0x3086, 0x095C}, ++{0x3086, 0x0B17}, ++{0x3086, 0x1026}, ++{0x3086, 0xBA5C}, ++{0x3086, 0x0317}, ++{0x3086, 0x1026}, ++{0x3086, 0xB217}, ++{0x3086, 0x065F}, ++{0x3086, 0x2888}, ++{0x3086, 0x9060}, ++{0x3086, 0x27F2}, ++{0x3086, 0x1710}, ++{0x3086, 0x26A2}, ++{0x3086, 0x26A3}, ++{0x3086, 0x5F4D}, ++{0x3086, 0x2808}, ++{0x3086, 0x1927}, ++{0x3086, 0xFA84}, ++{0x3086, 0x69A0}, ++{0x3086, 0x785D}, ++{0x3086, 0x2888}, ++{0x3086, 0x8710}, ++{0x3086, 0x8C82}, ++{0x3086, 0x8926}, ++{0x3086, 0xB217}, ++{0x3086, 0x036B}, ++{0x3086, 0x9C60}, ++{0x3086, 0x9417}, ++{0x3086, 0x2926}, ++{0x3086, 0x8345}, ++{0x3086, 0xA817}, ++{0x3086, 0x0727}, ++{0x3086, 0xFB17}, ++{0x3086, 0x2945}, ++{0x3086, 0x881F}, ++{0x3086, 0x1708}, ++{0x3086, 0x27FA}, ++{0x3086, 0x5D87}, ++{0x3086, 0x108C}, ++{0x3086, 0x8289}, ++{0x3086, 0x170E}, ++{0x3086, 0x4826}, ++{0x3086, 0x9A28}, ++{0x3086, 0x884C}, ++{0x3086, 0x0B79}, ++{0x3086, 0x1730}, ++{0x3086, 0x2692}, ++{0x3086, 0x1709}, ++{0x3086, 0x9160}, ++{0x3086, 0x27F2}, ++{0x3086, 0x1710}, ++{0x3086, 0x2682}, ++{0x3086, 0x2683}, ++{0x3086, 0x5F4D}, ++{0x3086, 0x2808}, ++{0x3086, 0x1927}, ++{0x3086, 0xFA84}, ++{0x3086, 0x69A1}, ++{0x3086, 0x785D}, ++{0x3086, 0x2888}, ++{0x3086, 0x8710}, ++{0x3086, 0x8C80}, ++{0x3086, 0x8A26}, ++{0x3086, 0x9217}, ++{0x3086, 0x036B}, ++{0x3086, 0x9D95}, ++{0x3086, 0x2603}, ++{0x3086, 0x5C01}, ++{0x3086, 0x4558}, ++{0x3086, 0x8E00}, ++{0x3086, 0x2798}, ++{0x3086, 0x170A}, ++{0x3086, 0x4A65}, ++{0x3086, 0x4316}, ++{0x3086, 0x6643}, ++{0x3086, 0x165B}, ++{0x3086, 0x4316}, ++{0x3086, 0x5943}, ++{0x3086, 0x168E}, ++{0x3086, 0x0327}, ++{0x3086, 0x9C45}, ++{0x3086, 0x7817}, ++{0x3086, 0x0727}, ++{0x3086, 0x9D17}, ++{0x3086, 0x225D}, ++{0x3086, 0x8710}, ++{0x3086, 0x2808}, ++{0x3086, 0x530D}, ++{0x3086, 0x8C80}, ++{0x3086, 0x8A45}, ++{0x3086, 0x5823}, ++{0x3086, 0x1708}, ++{0x3086, 0x8E01}, ++{0x3086, 0x2798}, ++{0x3086, 0x8E00}, ++{0x3086, 0x2644}, ++{0x3086, 0x5C05}, ++{0x3086, 0x1244}, ++{0x3086, 0x4B71}, ++{0x3086, 0x759E}, ++{0x3086, 0x8B85}, ++{0x3086, 0x0143}, ++{0x3086, 0x7271}, ++{0x3086, 0xA346}, ++{0x3086, 0x4316}, ++{0x3086, 0x6FA3}, ++{0x3086, 0x9612}, ++{0x3086, 0x4416}, ++{0x3086, 0x4643}, ++{0x3086, 0x1697}, ++{0x3086, 0x2604}, ++{0x3086, 0x2684}, ++{0x3086, 0x8E03}, ++{0x3086, 0x27FC}, ++{0x3086, 0x5C0D}, ++{0x3086, 0x5754}, ++{0x3086, 0x1709}, ++{0x3086, 0x5556}, ++{0x3086, 0x495F}, ++{0x3086, 0x5305}, ++{0x3086, 0x5307}, ++{0x3086, 0x286C}, ++{0x3086, 0x4C09}, ++{0x3086, 0x282C}, ++{0x3086, 0x72AE}, ++{0x3086, 0x7CAA}, ++{0x3086, 0x28A8}, ++{0x3086, 0x7960}, ++{0x3086, 0x269C}, ++{0x3086, 0x5C1B}, ++{0x3086, 0x4548}, ++{0x3086, 0x4508}, ++{0x3086, 0x4588}, ++{0x3086, 0x26BE}, ++{0x3086, 0x8E01}, ++{0x3086, 0x27F8}, ++{0x3086, 0x1702}, ++{0x3086, 0x27FA}, ++{0x3086, 0x1709}, ++{0x3086, 0x5C0B}, ++{0x3086, 0x1710}, ++{0x3086, 0x26BA}, ++{0x3086, 0x5C03}, ++{0x3086, 0x1710}, ++{0x3086, 0x26B2}, ++{0x3086, 0x1706}, ++{0x3086, 0x5F28}, ++{0x3086, 0x8898}, ++{0x3086, 0x6027}, ++{0x3086, 0xF217}, ++{0x3086, 0x1026}, ++{0x3086, 0xA226}, ++{0x3086, 0xA35F}, ++{0x3086, 0x4D28}, ++{0x3086, 0x081A}, ++{0x3086, 0x27FA}, ++{0x3086, 0x8469}, ++{0x3086, 0xA578}, ++{0x3086, 0x5D28}, ++{0x3086, 0x8887}, ++{0x3086, 0x108C}, ++{0x3086, 0x8289}, ++{0x3086, 0x26B2}, ++{0x3086, 0x1703}, ++{0x3086, 0x6BA4}, ++{0x3086, 0x6099}, ++{0x3086, 0x1729}, ++{0x3086, 0x2683}, ++{0x3086, 0x45A8}, ++{0x3086, 0x1707}, ++{0x3086, 0x27FB}, ++{0x3086, 0x1729}, ++{0x3086, 0x4588}, ++{0x3086, 0x2017}, ++{0x3086, 0x0827}, ++{0x3086, 0xFA5D}, ++{0x3086, 0x8710}, ++{0x3086, 0x8C82}, ++{0x3086, 0x8917}, ++{0x3086, 0x0E48}, ++{0x3086, 0x269A}, ++{0x3086, 0x2888}, ++{0x3086, 0x4C0B}, ++{0x3086, 0x7917}, ++{0x3086, 0x3026}, ++{0x3086, 0x9217}, ++{0x3086, 0x099A}, ++{0x3086, 0x6027}, ++{0x3086, 0xF217}, ++{0x3086, 0x1026}, ++{0x3086, 0x8226}, ++{0x3086, 0x835F}, ++{0x3086, 0x4D28}, ++{0x3086, 0x081A}, ++{0x3086, 0x27FA}, ++{0x3086, 0x8469}, ++{0x3086, 0xAB78}, ++{0x3086, 0x5D28}, ++{0x3086, 0x8887}, ++{0x3086, 0x108C}, ++{0x3086, 0x808A}, ++{0x3086, 0x2692}, ++{0x3086, 0x1703}, ++{0x3086, 0x6BA6}, ++{0x3086, 0xA726}, ++{0x3086, 0x035C}, ++{0x3086, 0x0145}, ++{0x3086, 0x588E}, ++{0x3086, 0x0027}, ++{0x3086, 0x9817}, ++{0x3086, 0x0A4A}, ++{0x3086, 0x0A43}, ++{0x3086, 0x160B}, ++{0x3086, 0x438E}, ++{0x3086, 0x0327}, ++{0x3086, 0x9C45}, ++{0x3086, 0x7817}, ++{0x3086, 0x0727}, ++{0x3086, 0x9D17}, ++{0x3086, 0x225D}, ++{0x3086, 0x8710}, ++{0x3086, 0x2808}, ++{0x3086, 0x530D}, ++{0x3086, 0x8C80}, ++{0x3086, 0x8A45}, ++{0x3086, 0x5817}, ++{0x3086, 0x088E}, ++{0x3086, 0x0127}, ++{0x3086, 0x988E}, ++{0x3086, 0x0076}, ++{0x3086, 0xAC77}, ++{0x3086, 0xAC46}, ++{0x3086, 0x4416}, ++{0x3086, 0x16A8}, ++{0x3086, 0x7A26}, ++{0x3086, 0x445C}, ++{0x3086, 0x0512}, ++{0x3086, 0x444B}, ++{0x3086, 0x7175}, ++{0x3086, 0xA24A}, ++{0x3086, 0x0343}, ++{0x3086, 0x1604}, ++{0x3086, 0x4316}, ++{0x3086, 0x5843}, ++{0x3086, 0x165A}, ++{0x3086, 0x4316}, ++{0x3086, 0x0643}, ++{0x3086, 0x1607}, ++{0x3086, 0x4316}, ++{0x3086, 0x8E03}, ++{0x3086, 0x279C}, ++{0x3086, 0x4578}, ++{0x3086, 0x7B17}, ++{0x3086, 0x078B}, ++{0x3086, 0x8627}, ++{0x3086, 0x9D17}, ++{0x3086, 0x2345}, ++{0x3086, 0x5822}, ++{0x3086, 0x1708}, ++{0x3086, 0x8E01}, ++{0x3086, 0x2798}, ++{0x3086, 0x8E00}, ++{0x3086, 0x2644}, ++{0x3086, 0x5C05}, ++{0x3086, 0x1244}, ++{0x3086, 0x4B8D}, ++{0x3086, 0x602C}, ++{0x3086, 0x2C2C}, ++{0x3086, 0x2C00}, ++/* End Sequencer */ ++#ifdef AR0140_EMBEDDED_LINE ++{0x3064, 0x1982}, // SMIA_TEST ++#else ++{0x3064, 0x1802}, // SMIA_TEST ++#endif ++/* PCLK=27Mhz/0x2 *0x30 /1/0x10 - TI serializers */ ++{0x302A, 0x0010}, // vt_pix_clk_div ++{0x302E, 0x0002}, // pre_pll_clk_div ++{0x3030, 0x0030}, // pll_multiplier ++#if 0 ++/* Resolution: 1284x804x29.98p */ ++{0x3002, 0x001A}, // y_addr_start ++{0x3004, 0x0014}, // x_addr_start ++{0x3006, 0x033D}, // y_addr_end}, 804 lines ++{0x3008, 0x0517}, // x_addr_end}, 1284px ++{0x300A, 0x0344}, // frame_length_lines}, 840 lines ++{0x300C, 0x0648}, // line_length_pck}, 1608px ++#else ++{0x31B0, 0x0056}, // FRAME_PREAMBLE ++{0x31B2, 0x0045}, // LINE_PREAMBLE ++{0x3004, AR0140_X_START}, // X_ADDR_START_ ++{0x3008, AR0140_X_END}, // X_ADDR_END_ ++{0x3002, AR0140_Y_START}, // Y_ADDR_START_ ++{0x3006, AR0140_Y_END}, // Y_ADDR_END_ ++{0x3402, 0x0000 | AR0140_MAX_WIDTH}, // X_OUTPUT_CONTROL ++{0x3404, 0x0000 | AR0140_MAX_HEIGHT}, // Y_OUTPUT_CONTROL ++{0x300A, AR0140_SENSOR_HEIGHT + 36}, // FRAME_LENGTH_LINES_ ++{0x300C, AR0140_SENSOR_WIDTH + 328}, // LINE_LENGTH_PCK_ ++#endif ++/* Rev3 Optimized Settings */ ++{0x3044, 0x0400}, ++{0x3052, 0xA134}, ++{0x3092, 0x010F}, ++{0x30FE, 0x0080}, ++{0x3ECE, 0x40FF}, ++{0x3ED0, 0xFF40}, ++{0x3ED2, 0xA906}, ++{0x3ED4, 0x001F}, ++{0x3ED6, 0x638F}, ++{0x3ED8, 0xCC99}, ++{0x3EDA, 0x0888}, ++{0x3EDE, 0x8878}, ++{0x3EE0, 0x7744}, ++{0x3EE2, 0x5563}, ++{0x3EE4, 0xAAE0}, ++{0x3EE6, 0x3400}, ++{0x3EEA, 0xA4FF}, ++{0x3EEC, 0x80F0}, ++{0x3EEE, 0x0000}, ++{0x31E0, 0x1701}, ++/* HDR mode */ ++/* 2D Motion Compensation */ ++{0x318A, 0x0E74}, // hdr_mc_ctrl1 ++{0x318C, 0xC000}, // hdr_mc_ctrl2 ++{0x318E, 0x0800}, // hdr_mc_ctrl3: Gain before DLO set to 1 ++{0x3190, 0x0000}, // hdr_mc_ctrl4: if DLO enabled overrides 2D MC ++{0x3192, 0x0400}, // hdr_mc_ctrl5 ++{0x3194, 0x0BB8}, // hdr_mc_ctrl6: T1 barrier set to 3000 ++{0x3196, 0x0E74}, // hdr_mc_ctrl7: T2 barrier set to 3700 ++{0x3198, 0x183C}, // hdr_mc_ctrl8: Motion detect Q1 set to 60}, Q2 set to 24 ++{0x3200, 0x0002}, // adacd_control ++{0x3202, 0x00A0}, // adacd_noise_model1 ++{0x3206, 0x0A06}, // adacd_noise_floor1 ++{0x3208, 0x1A12}, // adacd_noise_floor2 ++{0x320A, 0x0080}, // adacd_pedestal ++{0x306E, 0x9010}, // datapath select - LV noncontinuous ++{0x31AC, 0x100C}, // DATA_FORMAT_BITS: RAW12 ++{0x31AE, 0x0301}, // SERIAL_FORMAT ++{0x301A, 0x11D8}, // RESET_REGISTER ++// patch start ++{0x3012, 0x0206}, // COARSE_INTEGRATION_TIME_: T1 exposure - max=0x400 ++// patch end ++// enable trigger ++{0x340A, 0x0070}, // GPIO_CONTROL1: GPIO3 is trigger ++{0x340C, 0x0080}, // GPIO_CONTROL2: GPIO3 is trigger ++{0x30CE, 0x0120}, // TRIGGER_MODE ++//{0x30DC, 0x0120}, // TRIGGER_DELAY ++}; +diff --git a/drivers/media/i2c/soc_camera/ar0143.c b/drivers/media/i2c/soc_camera/ar0143.c +new file mode 100644 +index 0000000..b51dcfc +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0143.c +@@ -0,0 +1,678 @@ ++/* ++ * ON Semiconductor AR0143 sensor camera driver ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "ar0143.h" ++ ++#define AR0143_I2C_ADDR 0x10 ++ ++#define AR0143_PID 0x3000 ++#define AR0143_VERSION_REG 0x0D54 ++ ++#define AR0143_MEDIA_BUS_FMT MEDIA_BUS_FMT_SGRBG12_1X12 ++ ++struct ar0143_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int init_complete; ++ u8 id[6]; ++ /* serializers */ ++ int max9286_addr; ++ int max9271_addr; ++ int ti9x4_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++ int hts; ++ int vts; ++ int frame_preamble; ++}; ++ ++static inline struct ar0143_priv *to_ar0143(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct ar0143_priv, sd); ++} ++ ++static void ar0143_s_port(struct i2c_client *client, int fwd_en) ++{ ++ struct ar0143_priv *priv = to_ar0143(client); ++ int tmp_addr; ++ ++ if (priv->max9286_addr) { ++ tmp_addr = client->addr; ++ client->addr = priv->max9286_addr; /* Deserializer I2C address */ ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ client->addr = tmp_addr; ++ }; ++} ++ ++static int ar0143_set_regs(struct i2c_client *client, ++ const struct ar0143_reg *regs, int nr_regs) ++{ ++ struct ar0143_priv *priv = to_ar0143(client); ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (regs[i].reg == AR0143_DELAY) { ++ mdelay(regs[i].val); ++ continue; ++ } ++ /* cache timings */ ++ if (regs[i].reg == 0x300a) ++ priv->vts = regs[i].val; ++ if (regs[i].reg == 0x300c) ++ priv->hts = regs[i].val; ++ if (regs[i].reg == 0x31b0) ++ priv->frame_preamble = regs[i].val - 1; ++ ++ if (priv->ti9x4_addr) { ++ /* Override default (MAXIM serializer) table */ ++ /* PCLK=16Mhz/2 *48/1/8= 48Mhz - TI serializers */ ++ switch (regs[i].reg) { ++ case 0x302A: ++ reg16_write16(client, regs[i].reg, 8); // VT_PIX_CLK_DIV ++ continue; ++ case 0x302C: ++ reg16_write16(client, regs[i].reg, 1); // VT_SYS_CLK_DIV ++ continue; ++ case 0x302E: ++ reg16_write16(client, regs[i].reg, 2); // PRE_PLL_CLK_DIV ++ continue; ++ case 0x3030: ++ reg16_write16(client, regs[i].reg, 48); // PLL_MULTIPLIER ++ continue; ++ case 0x3036: ++ reg16_write16(client, regs[i].reg, 8); // OP_WORD_CLK_DIV ++ continue; ++ case 0x3038: ++ reg16_write16(client, regs[i].reg, 1); // OP_SYS_CLK_DIV ++ continue; ++ case 0x300A: ++ reg16_write16(client, regs[i].reg, AR0143_SENSOR_HEIGHT + 142); // FRAME_LENGTH_LINES_ ++ continue; ++ } ++ } ++ ++ reg16_write16(client, regs[i].reg, regs[i].val); ++ } ++ ++ return 0; ++} ++ ++static int ar0143_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int ar0143_set_window(struct v4l2_subdev *sd) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0143_priv *priv = to_ar0143(client); ++ ++ dev_dbg(&client->dev, "L=%d T=%d %dx%d\n", priv->rect.left, priv->rect.top, priv->rect.width, priv->rect.height); ++ ++ /* horiz crop start */ ++ reg16_write16(client, 0x3004, priv->rect.left); ++ /* horiz crop end */ ++ reg16_write16(client, 0x3008, priv->rect.left + priv->rect.width - 1); ++ /* vert crop start */ ++ reg16_write16(client, 0x3002, priv->rect.top); ++ /* vert crop end */ ++ reg16_write16(client, 0x3006, priv->rect.top + priv->rect.height + 1); ++ ++ return 0; ++}; ++ ++static int ar0143_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0143_priv *priv = to_ar0143(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = AR0143_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int ar0143_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = AR0143_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int ar0143_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = AR0143_MEDIA_BUS_FMT; ++ ++ return 0; ++} ++ ++static int ar0143_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0143_priv *priv = to_ar0143(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = AR0143_VERSION_REG >> 8; ++ edid->edid[9] = AR0143_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int ar0143_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0143_priv *priv = to_ar0143(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > AR0143_MAX_WIDTH) || ++ (rect->top + rect->height > AR0143_MAX_HEIGHT)) ++ *rect = priv->rect; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ ar0143_set_window(sd); ++ ++ return 0; ++} ++ ++static int ar0143_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0143_priv *priv = to_ar0143(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = AR0143_MAX_WIDTH; ++ sel->r.height = AR0143_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = AR0143_MAX_WIDTH; ++ sel->r.height = AR0143_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ar0143_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int ar0143_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u16 val = 0; ++ ++ ret = reg16_read16(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int ar0143_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return reg16_write16(client, (u16)reg->reg, (u16)reg->val); ++} ++#endif ++ ++static struct v4l2_subdev_core_ops ar0143_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ar0143_g_register, ++ .s_register = ar0143_s_register, ++#endif ++}; ++ ++static int ar0143_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0143_priv *priv = to_ar0143(client); ++ int ret = -EINVAL; ++ u16 val = 0; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ case V4L2_CID_CONTRAST: ++ case V4L2_CID_SATURATION: ++ case V4L2_CID_HUE: ++ case V4L2_CID_GAMMA: ++ case V4L2_CID_SHARPNESS: ++ case V4L2_CID_AUTOGAIN: ++ break; ++ case V4L2_CID_GAIN: ++ /* Digital gain */ ++ ret = reg16_write16(client, 0x3308, ctrl->val); ++ break; ++ case V4L2_CID_ANALOGUE_GAIN: ++ /* Analog gain */ ++ ret = reg16_write16(client, 0x3366, ctrl->val); ++ break; ++ case V4L2_CID_EXPOSURE: ++ /* T1 exposure */ ++ ret = reg16_write16(client, 0x3012, ctrl->val); ++ break; ++ case V4L2_CID_HFLIP: ++ ret = reg16_read16(client, 0x3040, &val); ++ if (ctrl->val) ++ val |= 0x4000; ++ else ++ val &= ~0x4000; ++ ret |= reg16_write16(client, 0x3040, val); ++ break; ++ case V4L2_CID_VFLIP: ++ ret = reg16_read16(client, 0x3040, &val); ++ if (ctrl->val) ++ val |= 0x8000; ++ else ++ val &= ~0x8000; ++ ret |= reg16_write16(client, 0x3040, val); ++ break; ++ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: ++ ret = 0; ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ar0143_ctrl_ops = { ++ .s_ctrl = ar0143_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops ar0143_video_ops = { ++ .s_stream = ar0143_s_stream, ++ .g_mbus_config = ar0143_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops ar0143_subdev_pad_ops = { ++ .get_edid = ar0143_get_edid, ++ .enum_mbus_code = ar0143_enum_mbus_code, ++ .get_selection = ar0143_get_selection, ++ .set_selection = ar0143_set_selection, ++ .get_fmt = ar0143_get_fmt, ++ .set_fmt = ar0143_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops ar0143_subdev_ops = { ++ .core = &ar0143_core_ops, ++ .video = &ar0143_video_ops, ++ .pad = &ar0143_subdev_pad_ops, ++}; ++ ++static void ar0143_otp_id_read(struct i2c_client *client) ++{ ++ struct ar0143_priv *priv = to_ar0143(client); ++ int i; ++ u16 val = 0; ++ ++ /* read camera id from ar014x OTP memory */ ++ reg16_write16(client, 0x3054, 0x400); ++ reg16_write16(client, 0x304a, 0x110); ++ usleep_range(25000, 25500); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i += 2) { ++ /* first 4 bytes are equal on all ar014x */ ++ reg16_read16(client, 0x3800 + i + 4, &val); ++ priv->id[i] = val >> 8; ++ priv->id[i + 1] = val & 0xff; ++ } ++} ++ ++static ssize_t ar0143_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0143_priv *priv = to_ar0143(client); ++ ++ ar0143_otp_id_read(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_ar0143, S_IRUGO, ar0143_otp_id_show, NULL); ++ ++static int ar0143_initialize(struct i2c_client *client) ++{ ++ struct ar0143_priv *priv = to_ar0143(client); ++ u16 val = 0; ++ u16 pid = 0; ++ int ret = 0; ++ int tmp_addr; ++ ++ ar0143_s_port(client, 1); ++ ++ /* check and show model ID */ ++ reg16_read16(client, AR0143_PID, &pid); ++ ++ if (pid != AR0143_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x\n", pid); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ /* Program wizard registers */ ++ ar0143_set_regs(client, ar0143_regs_wizard, ARRAY_SIZE(ar0143_regs_wizard)); ++ ++ tmp_addr = client->addr; ++ if (priv->max9271_addr) { ++ /* setup serializer HS generator */ ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x4e, priv->frame_preamble >> 16); /* HS delay */ ++ reg8_write(client, 0x4f, (priv->frame_preamble >> 8) & 0xff); ++ reg8_write(client, 0x50, priv->frame_preamble & 0xff); ++ reg8_write(client, 0x54, AR0143_MAX_WIDTH >> 8); /* HS high period */ ++ reg8_write(client, 0x55, AR0143_MAX_WIDTH & 0xff); ++ reg8_write(client, 0x56, (priv->hts - AR0143_MAX_WIDTH) >> 8); /* HS low period */ ++ reg8_write(client, 0x57, (priv->hts - AR0143_MAX_WIDTH) & 0xff); ++ reg8_write(client, 0x58, priv->vts >> 8); /* HS count */ ++ reg8_write(client, 0x59, priv->vts & 0xff); ++ } ++ client->addr = tmp_addr; ++ ++ /* Enable stream */ ++ reg16_read16(client, 0x301a, &val); // read inital reset_register value ++ val |= (1 << 2); // Set streamOn bit ++ reg16_write16(client, 0x301a, val); // Start Streaming ++ ++ /* Read OTP IDs */ ++ ar0143_otp_id_read(client); ++ ++ dev_info(&client->dev, "ar0143 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, AR0143_MAX_WIDTH, AR0143_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ ar0143_s_port(client, 0); ++ ++ return ret; ++} ++ ++static int ar0143_parse_dt(struct device_node *np, struct ar0143_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ of_node_put(endpoint); ++ ++ if (!priv->max9286_addr && !priv->ti9x4_addr) { ++ dev_err(&client->dev, "deserializer does not present for AR0143\n"); ++ return -EINVAL; ++ } ++ ++ ar0143_s_port(client, 1); ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ ++ reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x0A, AR0143_I2C_ADDR << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, AR0143_I2C_ADDR << 1); /* Sensor native I2C address */ ++ ++ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - reset, GPIO1 - fsin */ ++ } ++ client->addr = tmp_addr; ++ ++ mdelay(10); ++ ++ return 0; ++} ++ ++static int ar0143_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ar0143_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &ar0143_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops, ++ V4L2_CID_GAIN, 1, 0x7ff, 1, 0x200); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops, ++ V4L2_CID_ANALOGUE_GAIN, 1, 0xe, 1, 0x7); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops, ++ V4L2_CID_EXPOSURE, 1, 0x400, 1, 0x300); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0143_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = ar0143_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = ar0143_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = AR0143_MAX_WIDTH; ++ priv->rect.height = AR0143_MAX_HEIGHT; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ar0143) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_AR0143 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int ar0143_remove(struct i2c_client *client) ++{ ++ struct ar0143_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ar0143); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_AR0143 ++static const struct i2c_device_id ar0143_id[] = { ++ { "ar0143", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ar0143_id); ++ ++static const struct of_device_id ar0143_of_ids[] = { ++ { .compatible = "aptina,ar0143", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ar0143_of_ids); ++ ++static struct i2c_driver ar0143_i2c_driver = { ++ .driver = { ++ .name = "ar0143", ++ .of_match_table = ar0143_of_ids, ++ }, ++ .probe = ar0143_probe, ++ .remove = ar0143_remove, ++ .id_table = ar0143_id, ++}; ++ ++module_i2c_driver(ar0143_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for AR0143"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/ar0143.h b/drivers/media/i2c/soc_camera/ar0143.h +new file mode 100644 +index 0000000..774a438 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0143.h +@@ -0,0 +1,549 @@ ++/* ++ * ON Semiconductor AR0143 sensor camera wizard 1344x968@30/BGGR/BT601/RAW12 ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++//#define AR0143_DISPLAY_PATTERN_FIXED ++//#define AR0143_DISPLAY_PATTERN_COLOR_BAR ++ ++//#define AR0143_EMBEDDED_LINE ++ ++#define AR0143_MAX_WIDTH 1344 ++#define AR0143_MAX_HEIGHT 968 ++ ++#define AR0143_DELAY 0xffff ++ ++#define AR0143_SENSOR_WIDTH 1344 ++#define AR0143_SENSOR_HEIGHT 968 ++ ++#define AR0143_X_START ((AR0143_SENSOR_WIDTH - AR0143_MAX_WIDTH) / 2) ++#define AR0143_Y_START ((AR0143_SENSOR_HEIGHT - AR0143_MAX_HEIGHT) / 2) ++#define AR0143_X_END (AR0143_X_START + AR0143_MAX_WIDTH - 1) ++#define AR0143_Y_END (AR0143_Y_START + AR0143_MAX_HEIGHT + 1) /* must be +1 and not -1 or 2 lines missed - bug in imager? */ ++ ++struct ar0143_reg { ++ u16 reg; ++ u16 val; ++}; ++ ++static const struct ar0143_reg ar0143_regs_wizard[] = { ++{0x301A, 0x0001}, // reset ++{AR0143_DELAY, 100}, ++{0x301A, 0x10D8}, // Stream off and setup parallel ++{0x3070, 0x0001}, ++{0x3070, 0x0000}, // 1: Solid color test pattern, ++ // 2: Full color bar test pattern, ++ // 3: Fade to grey color bar test pattern, ++ //256: Walking 1 test pattern (12 bit) ++#ifdef AR0143_DISPLAY_PATTERN_FIXED ++{0x3070, 0x0001}, ++#endif ++{0x3072, 0x0fff}, // R ++{0x3074, 0x0fff}, // G(GR row) ++{0x3076, 0x0fff}, // B ++{0x3078, 0x0fff}, // G(GB row) ++#ifdef AR0143_DISPLAY_PATTERN_COLOR_BAR ++{0x3070, 0x0002}, ++#endif ++{AR0143_DELAY, 250}, ++// start demo init ++{0x3100, 0x4000}, // DLO_CONTROL0 ++{0x3102, 0x6060}, // RESERVED_MFR_3102 ++{0x3104, 0x6060}, // RESERVED_MFR_3104 ++{0x3106, 0x6060}, // RESERVED_MFR_3106 ++{0x3108, 0x0F9F}, // RESERVED_MFR_3108 ++{0x3280, 0x0FA0}, // T1_BARRIER_C0 ++{0x3282, 0x0FA0}, // T1_BARRIER_C1 ++{0x3284, 0x0FA0}, // T1_BARRIER_C2 ++{0x3286, 0x0FA0}, // T1_BARRIER_C3 ++{0x3288, 0x0FA0}, // T2_BARRIER_C0 ++{0x328A, 0x0FA0}, // T2_BARRIER_C1 ++{0x328C, 0x0FA0}, // T2_BARRIER_C2 ++{0x328E, 0x0FA0}, // T2_BARRIER_C3 ++{0x3290, 0x0FA0}, // T3_BARRIER_C0 ++{0x3292, 0x0FA0}, // T3_BARRIER_C1 ++{0x3294, 0x0FA0}, // T3_BARRIER_C2 ++{0x3296, 0x0FA0}, // T3_BARRIER_C3 ++{0x3298, 0x0FA0}, // T4_BARRIER_C0 ++{0x329A, 0x0FA0}, // T4_BARRIER_C1 ++{0x329C, 0x0FA0}, // T4_BARRIER_C2 ++{0x329E, 0x0FA0}, // T4_BARRIER_C3 ++{0x3110, 0x0011}, // HDR_CONTROL0 ++{0x3112, 0x7FE7}, // RESERVED_MFR_3112 ++{0x3114, 0x0000}, // RESERVED_MFR_3114 ++{0x3116, 0xC000}, // HDR_CONTROL3 ++{0x3120, 0x0BA0}, // HDR_SC_CONTROL0 ++{0x3122, 0x0FA0}, // HDR_SC_CONTROL1 ++{0x3124, 0x00B4}, // HDR_MD_CONTROL0 ++{0x3126, 0x0030}, // HDR_MD_CONTROL1 ++{0x3128, 0x6100}, // RESERVED_MFR_3128 ++{0x3506, 0x3333}, // RESERVED_MFR_3506 ++{0x3508, 0x3333}, // RESERVED_MFR_3508 ++{0x350A, 0x3333}, // RESERVED_MFR_350A ++{0x350C, 0x035F}, // RESERVED_MFR_350C ++{0x350E, 0xEF14}, // RESERVED_MFR_350E ++{0x3086, 0x0600}, // RESERVED_MFR_3086 ++{0x3C00, 0xDD67}, // RESERVED_MFR_3C00 ++{0x3092, 0x1C24}, // RESERVED_MFR_3092 ++{0x3096, 0x147E}, // RESERVED_MFR_3096 ++{0x3750, 0x147E}, // RESERVED_MFR_3750 ++{0x30B0, 0x0800}, // DIGITAL_TEST ++{0x30FE, 0x0000}, // NOISE_PEDESTAL ++{0x32D0, 0x3A02}, // RESERVED_MFR_32D0 ++{0x32D6, 0x3C04}, // RESERVED_MFR_32D6 ++{0x3C0C, 0x0516}, // DELAY_BUFFER_LLPCK_RD_WR_OVERLAP ++{0x3F94, 0x483e}, // TEMPVSENS0_FLAG_CTRL ++{0x3F96, 0xFFFE}, // TEMPVSENS1_FLAG_CTRL ++{0x3088, 0x6680}, // LFM_CTRL ++{0x33E2, 0x0000}, // SAMPLE_CTRL ++{0x3366, 0x7777}, // ANALOG_GAIN ++{0x3056, 0x0080}, // GREEN1_GAIN ++{0x305C, 0x0080}, // GREEN2_GAIN ++{0x3058, 0x0080}, // BLUE_GAIN ++{0x305A, 0x0080}, // RED_GAIN ++{0x306E, 0x9010}, // DATAPATH_SELECT ++{0x3044, 0x0400}, // DARK_CONTROL ++{0x30BA, 0x01E2}, // DIGITAL_CTRL ++{0x32EA, 0x3C0E}, // RESERVED_MFR_32EA ++{0x3362, 0x0000}, // DC_GAIN ++{0x3364, 0x005B}, // RESERVED_MFR_3364 ++{0x3370, 0x0131}, // DBLC_CONTROL ++{0x3372, 0x700F}, // DBLC_FS0_CONTROL ++{0x3386, 0x0000}, // DBLC_PEDESTAL ++{0x3C04, 0x0E80}, // RESERVED_MFR_3C04 ++{0x30B4, 0x01C7}, // TEMPSENS0_CTRL_REG ++{0x30B8, 0x0007}, // TEMPSENS1_CTRL_REG ++{0x3F90, 0x8D03}, // TEMPVSENS0_TMG_CTRL ++{0x3F92, 0x0D03}, // TEMPVSENS1_TMG_CTRL ++{0x3502, 0x0808}, // RESERVED_MFR_3502 ++{0x3566, 0x1D28}, // RESERVED_MFR_3566 ++{0x3518, 0x1FFE}, // RESERVED_MFR_3518 ++{0x3526, 0x0F00}, // RESERVED_MFR_3526 ++{0x3528, 0xDDDD}, // RESERVED_MFR_3528 ++{0x352A, 0x089F}, // RESERVED_MFR_352A ++{0x352E, 0x0011}, // RESERVED_MFR_352E ++{0x3530, 0x4400}, // RESERVED_MFR_3530 ++{0x3536, 0xFF07}, // RESERVED_MFR_3536 ++{0x3538, 0xFFFF}, // RESERVED_MFR_3538 ++{0x353A, 0x9000}, // RESERVED_MFR_353A ++{0x353C, 0x3F00}, // RESERVED_MFR_353C ++{0x32EC, 0x72A1}, // RESERVED_MFR_32EC ++{0x3540, 0xC637}, // RESERVED_MFR_3540 ++{0x3542, 0x464B}, // RESERVED_MFR_3542 ++{0x3544, 0x4B50}, // RESERVED_MFR_3544 ++{0x3546, 0x545A}, // RESERVED_MFR_3546 ++{0x3548, 0x5A00}, // RESERVED_MFR_3548 ++{0x354A, 0x007F}, // RESERVED_MFR_354A ++{0x3556, 0x101F}, // RESERVED_MFR_3556 ++{0x3566, 0x3328}, // RESERVED_MFR_3566 ++{0x337A, 0x0CA3}, // DBLC_SCALE0 ++{0x3372, 0x710F}, // DBLC_FS0_CONTROL ++{0x3520, 0x4688}, // RESERVED_MFR_3520 ++{0x3522, 0x8840}, // RESERVED_MFR_3522 ++{0x3524, 0x4046}, // RESERVED_MFR_3524 ++{0x352C, 0x4646}, // RESERVED_MFR_352C ++{0x2512, 0x8000}, // SEQ_CTRL_PORT ++{0x2510, 0x0903}, // SEQ_DATA_PORT ++{0x2510, 0x3350}, // SEQ_DATA_PORT ++{0x2510, 0x2004}, // SEQ_DATA_PORT ++{0x2510, 0x1420}, // SEQ_DATA_PORT ++{0x2510, 0x1578}, // SEQ_DATA_PORT ++{0x2510, 0x087B}, // SEQ_DATA_PORT ++{0x2510, 0x24FF}, // SEQ_DATA_PORT ++{0x2510, 0x24FF}, // SEQ_DATA_PORT ++{0x2510, 0x24EA}, // SEQ_DATA_PORT ++{0x2510, 0x2410}, // SEQ_DATA_PORT ++{0x2510, 0x2224}, // SEQ_DATA_PORT ++{0x2510, 0x1015}, // SEQ_DATA_PORT ++{0x2510, 0x5813}, // SEQ_DATA_PORT ++{0x2510, 0x0214}, // SEQ_DATA_PORT ++{0x2510, 0x0024}, // SEQ_DATA_PORT ++{0x2510, 0xFF24}, // SEQ_DATA_PORT ++{0x2510, 0xFF24}, // SEQ_DATA_PORT ++{0x2510, 0xEA23}, // SEQ_DATA_PORT ++{0x2510, 0x2464}, // SEQ_DATA_PORT ++{0x2510, 0x7A24}, // SEQ_DATA_PORT ++{0x2510, 0x0405}, // SEQ_DATA_PORT ++{0x2510, 0x2C40}, // SEQ_DATA_PORT ++{0x2510, 0x0AFF}, // SEQ_DATA_PORT ++{0x2510, 0x0ACC}, // SEQ_DATA_PORT ++{0x2510, 0x0A07}, // SEQ_DATA_PORT ++{0x2510, 0x3851}, // SEQ_DATA_PORT ++{0x2510, 0x1440}, // SEQ_DATA_PORT ++{0x2510, 0x0004}, // SEQ_DATA_PORT ++{0x2510, 0x0801}, // SEQ_DATA_PORT ++{0x2510, 0x0408}, // SEQ_DATA_PORT ++{0x2510, 0x1180}, // SEQ_DATA_PORT ++{0x2510, 0x2652}, // SEQ_DATA_PORT ++{0x2510, 0x0815}, // SEQ_DATA_PORT ++{0x2510, 0x1813}, // SEQ_DATA_PORT ++{0x2510, 0xC810}, // SEQ_DATA_PORT ++{0x2510, 0x0210}, // SEQ_DATA_PORT ++{0x2510, 0x1611}, // SEQ_DATA_PORT ++{0x2510, 0x8111}, // SEQ_DATA_PORT ++{0x2510, 0x8910}, // SEQ_DATA_PORT ++{0x2510, 0x5612}, // SEQ_DATA_PORT ++{0x2510, 0x1009}, // SEQ_DATA_PORT ++{0x2510, 0x020D}, // SEQ_DATA_PORT ++{0x2510, 0x0905}, // SEQ_DATA_PORT ++{0x2510, 0x1588}, // SEQ_DATA_PORT ++{0x2510, 0x1388}, // SEQ_DATA_PORT ++{0x2510, 0x0938}, // SEQ_DATA_PORT ++{0x2510, 0x1199}, // SEQ_DATA_PORT ++{0x2510, 0x11D9}, // SEQ_DATA_PORT ++{0x2510, 0x091E}, // SEQ_DATA_PORT ++{0x2510, 0x1214}, // SEQ_DATA_PORT ++{0x2510, 0x10D6}, // SEQ_DATA_PORT ++{0x2510, 0x0901}, // SEQ_DATA_PORT ++{0x2510, 0x1210}, // SEQ_DATA_PORT ++{0x2510, 0x1212}, // SEQ_DATA_PORT ++{0x2510, 0x1210}, // SEQ_DATA_PORT ++{0x2510, 0x11DD}, // SEQ_DATA_PORT ++{0x2510, 0x11D9}, // SEQ_DATA_PORT ++{0x2510, 0x0901}, // SEQ_DATA_PORT ++{0x2510, 0x1441}, // SEQ_DATA_PORT ++{0x2510, 0x0904}, // SEQ_DATA_PORT ++{0x2510, 0x1056}, // SEQ_DATA_PORT ++{0x2510, 0x0811}, // SEQ_DATA_PORT ++{0x2510, 0xDB09}, // SEQ_DATA_PORT ++{0x2510, 0x0311}, // SEQ_DATA_PORT ++{0x2510, 0xFB11}, // SEQ_DATA_PORT ++{0x2510, 0xBB12}, // SEQ_DATA_PORT ++{0x2510, 0x1A12}, // SEQ_DATA_PORT ++{0x2510, 0x1008}, // SEQ_DATA_PORT ++{0x2510, 0x1250}, // SEQ_DATA_PORT ++{0x2510, 0x1076}, // SEQ_DATA_PORT ++{0x2510, 0x10E6}, // SEQ_DATA_PORT ++{0x2510, 0x1461}, // SEQ_DATA_PORT ++{0x2510, 0x0906}, // SEQ_DATA_PORT ++{0x2510, 0x1240}, // SEQ_DATA_PORT ++{0x2510, 0x1260}, // SEQ_DATA_PORT ++{0x2510, 0x091C}, // SEQ_DATA_PORT ++{0x2510, 0x1460}, // SEQ_DATA_PORT ++{0x2510, 0x090C}, // SEQ_DATA_PORT ++{0x2510, 0x0B09}, // SEQ_DATA_PORT ++{0x2510, 0x0515}, // SEQ_DATA_PORT ++{0x2510, 0xC813}, // SEQ_DATA_PORT ++{0x2510, 0xC808}, // SEQ_DATA_PORT ++{0x2510, 0x1066}, // SEQ_DATA_PORT ++{0x2510, 0x090B}, // SEQ_DATA_PORT ++{0x2510, 0x1588}, // SEQ_DATA_PORT ++{0x2510, 0x1388}, // SEQ_DATA_PORT ++{0x2510, 0x0913}, // SEQ_DATA_PORT ++{0x2510, 0x0C14}, // SEQ_DATA_PORT ++{0x2510, 0x4009}, // SEQ_DATA_PORT ++{0x2510, 0x0310}, // SEQ_DATA_PORT ++{0x2510, 0xE611}, // SEQ_DATA_PORT ++{0x2510, 0xFB12}, // SEQ_DATA_PORT ++{0x2510, 0x6212}, // SEQ_DATA_PORT ++{0x2510, 0x6011}, // SEQ_DATA_PORT ++{0x2510, 0xFF11}, // SEQ_DATA_PORT ++{0x2510, 0xFB14}, // SEQ_DATA_PORT ++{0x2510, 0x4109}, // SEQ_DATA_PORT ++{0x2510, 0x0210}, // SEQ_DATA_PORT ++{0x2510, 0x6609}, // SEQ_DATA_PORT ++{0x2510, 0x1211}, // SEQ_DATA_PORT ++{0x2510, 0xBB12}, // SEQ_DATA_PORT ++{0x2510, 0x6312}, // SEQ_DATA_PORT ++{0x2510, 0x6014}, // SEQ_DATA_PORT ++{0x2510, 0x0015}, // SEQ_DATA_PORT ++{0x2510, 0x1811}, // SEQ_DATA_PORT ++{0x2510, 0xB812}, // SEQ_DATA_PORT ++{0x2510, 0xA012}, // SEQ_DATA_PORT ++{0x2510, 0x0010}, // SEQ_DATA_PORT ++{0x2510, 0x2610}, // SEQ_DATA_PORT ++{0x2510, 0x0013}, // SEQ_DATA_PORT ++{0x2510, 0x0011}, // SEQ_DATA_PORT ++{0x2510, 0x8030}, // SEQ_DATA_PORT ++{0x2510, 0x5342}, // SEQ_DATA_PORT ++{0x2510, 0x1100}, // SEQ_DATA_PORT ++{0x2510, 0x1002}, // SEQ_DATA_PORT ++{0x2510, 0x1016}, // SEQ_DATA_PORT ++{0x2510, 0x1101}, // SEQ_DATA_PORT ++{0x2510, 0x1109}, // SEQ_DATA_PORT ++{0x2510, 0x1056}, // SEQ_DATA_PORT ++{0x2510, 0x1210}, // SEQ_DATA_PORT ++{0x2510, 0x0D09}, // SEQ_DATA_PORT ++{0x2510, 0x0614}, // SEQ_DATA_PORT ++{0x2510, 0x4009}, // SEQ_DATA_PORT ++{0x2510, 0x0214}, // SEQ_DATA_PORT ++{0x2510, 0x6009}, // SEQ_DATA_PORT ++{0x2510, 0x0615}, // SEQ_DATA_PORT ++{0x2510, 0x4C13}, // SEQ_DATA_PORT ++{0x2510, 0x0C09}, // SEQ_DATA_PORT ++{0x2510, 0x0713}, // SEQ_DATA_PORT ++{0x2510, 0x4C09}, // SEQ_DATA_PORT ++{0x2510, 0x0715}, // SEQ_DATA_PORT ++{0x2510, 0xCC09}, // SEQ_DATA_PORT ++{0x2510, 0x0211}, // SEQ_DATA_PORT ++{0x2510, 0x4908}, // SEQ_DATA_PORT ++{0x2510, 0x1461}, // SEQ_DATA_PORT ++{0x2510, 0x1460}, // SEQ_DATA_PORT ++{0x2510, 0x0903}, // SEQ_DATA_PORT ++{0x2510, 0x1588}, // SEQ_DATA_PORT ++{0x2510, 0x1308}, // SEQ_DATA_PORT ++{0x2510, 0x0905}, // SEQ_DATA_PORT ++{0x2510, 0x1388}, // SEQ_DATA_PORT ++{0x2510, 0x0913}, // SEQ_DATA_PORT ++{0x2510, 0x1159}, // SEQ_DATA_PORT ++{0x2510, 0x090B}, // SEQ_DATA_PORT ++{0x2510, 0x1214}, // SEQ_DATA_PORT ++{0x2510, 0x0901}, // SEQ_DATA_PORT ++{0x2510, 0x1210}, // SEQ_DATA_PORT ++{0x2510, 0x10D6}, // SEQ_DATA_PORT ++{0x2510, 0x1212}, // SEQ_DATA_PORT ++{0x2510, 0x1210}, // SEQ_DATA_PORT ++{0x2510, 0x115D}, // SEQ_DATA_PORT ++{0x2510, 0x1159}, // SEQ_DATA_PORT ++{0x2510, 0x1056}, // SEQ_DATA_PORT ++{0x2510, 0x0903}, // SEQ_DATA_PORT ++{0x2510, 0x115B}, // SEQ_DATA_PORT ++{0x2510, 0x0913}, // SEQ_DATA_PORT ++{0x2510, 0x111B}, // SEQ_DATA_PORT ++{0x2510, 0x113B}, // SEQ_DATA_PORT ++{0x2510, 0x121A}, // SEQ_DATA_PORT ++{0x2510, 0x1210}, // SEQ_DATA_PORT ++{0x2510, 0x0901}, // SEQ_DATA_PORT ++{0x2510, 0x1250}, // SEQ_DATA_PORT ++{0x2510, 0x10F6}, // SEQ_DATA_PORT ++{0x2510, 0x10E6}, // SEQ_DATA_PORT ++{0x2510, 0x0903}, // SEQ_DATA_PORT ++{0x2510, 0x15AB}, // SEQ_DATA_PORT ++{0x2510, 0x13AB}, // SEQ_DATA_PORT ++{0x2510, 0x1240}, // SEQ_DATA_PORT ++{0x2510, 0x1260}, // SEQ_DATA_PORT ++{0x2510, 0x0964}, // SEQ_DATA_PORT ++{0x2510, 0x1588}, // SEQ_DATA_PORT ++{0x2510, 0x0903}, // SEQ_DATA_PORT ++{0x2510, 0x0B08}, // SEQ_DATA_PORT ++{0x2510, 0x0813}, // SEQ_DATA_PORT ++{0x2510, 0x8809}, // SEQ_DATA_PORT ++{0x2510, 0x0715}, // SEQ_DATA_PORT ++{0x2510, 0x8D13}, // SEQ_DATA_PORT ++{0x2510, 0x8D09}, // SEQ_DATA_PORT ++{0x2510, 0x0D15}, // SEQ_DATA_PORT ++{0x2510, 0x8813}, // SEQ_DATA_PORT ++{0x2510, 0x8809}, // SEQ_DATA_PORT ++{0x2510, 0x0310}, // SEQ_DATA_PORT ++{0x2510, 0x6609}, // SEQ_DATA_PORT ++{0x2510, 0x030C}, // SEQ_DATA_PORT ++{0x2510, 0x0914}, // SEQ_DATA_PORT ++{0x2510, 0x10E6}, // SEQ_DATA_PORT ++{0x2510, 0x1262}, // SEQ_DATA_PORT ++{0x2510, 0x1260}, // SEQ_DATA_PORT ++{0x2510, 0x113F}, // SEQ_DATA_PORT ++{0x2510, 0x113B}, // SEQ_DATA_PORT ++{0x2510, 0x1066}, // SEQ_DATA_PORT ++{0x2510, 0x117B}, // SEQ_DATA_PORT ++{0x2510, 0x0927}, // SEQ_DATA_PORT ++{0x2510, 0x113B}, // SEQ_DATA_PORT ++{0x2510, 0x1263}, // SEQ_DATA_PORT ++{0x2510, 0x1260}, // SEQ_DATA_PORT ++{0x2510, 0x1400}, // SEQ_DATA_PORT ++{0x2510, 0x155A}, // SEQ_DATA_PORT ++{0x2510, 0x1138}, // SEQ_DATA_PORT ++{0x2510, 0x12A0}, // SEQ_DATA_PORT ++{0x2510, 0x1200}, // SEQ_DATA_PORT ++{0x2510, 0x1026}, // SEQ_DATA_PORT ++{0x2510, 0x1000}, // SEQ_DATA_PORT ++{0x2510, 0x1342}, // SEQ_DATA_PORT ++{0x2510, 0x1100}, // SEQ_DATA_PORT ++{0x2510, 0x437A}, // SEQ_DATA_PORT ++{0x2510, 0x0605}, // SEQ_DATA_PORT ++{0x2510, 0x0807}, // SEQ_DATA_PORT ++{0x2510, 0x4137}, // SEQ_DATA_PORT ++{0x2510, 0x502C}, // SEQ_DATA_PORT ++{0x2510, 0x2CFE}, // SEQ_DATA_PORT ++{0x2510, 0x16FE}, // SEQ_DATA_PORT ++{0x2510, 0x0C2C}, // SEQ_DATA_PORT ++{0x1008, 0x0338}, // FINE_INTEGRATION_TIME_MIN ++{0x100C, 0x051B}, // FINE_INTEGRATION_TIME2_MIN ++{0x100E, 0x06FE}, // FINE_INTEGRATION_TIME3_MIN ++{0x1010, 0x0155}, // FINE_INTEGRATION_TIME4_MIN ++{0x3230, 0x02D6}, // FINE_CORRECTION ++{0x3232, 0x04B9}, // FINE_CORRECTION2 ++{0x3234, 0x069C}, // FINE_CORRECTION3 ++{0x3236, 0x00F3}, // FINE_CORRECTION4 ++{0x32E6, 0x00DA}, // RESERVED_MFR_32E6 ++{0x350C, 0x035F}, // RESERVED_MFR_350C ++{0x32D0, 0x3A02}, // RESERVED_MFR_32D0 ++{0x32D2, 0x3508}, // RESERVED_MFR_32D2 ++{0x32D4, 0x3702}, // RESERVED_MFR_32D4 ++{0x32D6, 0x3C04}, // RESERVED_MFR_32D6 ++{0x32DC, 0x370A}, // RESERVED_MFR_32DC ++{0x302A, 0x0008}, // VT_PIX_CLK_DIV ++{0x302C, 0x0001}, // VT_SYS_CLK_DIV ++{0x302E, 0x0002}, // PRE_PLL_CLK_DIV ++{0x3030, 0x0034}, // PLL_MULTIPLIER ++{0x3036, 0x0008}, // OP_WORD_CLK_DIV ++{0x3038, 0x0001}, // OP_SYS_CLK_DIV ++{0x31DC, 0x0030}, // RESERVED_MFR_31DC ++{0x30A2, 0x0001}, // X_ODD_INC_ ++{0x30A6, 0x0001}, // Y_ODD_INC_ ++{0x3040, 0x0000}, // READ_MODE ++{0x3044, 0x0400}, // DARK_CONTROL ++{0x3180, 0x0080}, // RESERVED_MFR_3180 ++{0x33E4, 0x0080}, // RESERVED_MFR_33E4 ++{0x33E0, 0x0880}, // TEST_ASIL_ROWS ++#ifdef AR0143_EMBEDDED_LINE ++{0x3064, 0x1982}, // SMIA_TEST ++#else ++{0x3064, 0x1802}, // SMIA_TEST ++#endif ++{0x3004, 0x0000}, // X_ADDR_START_ ++{0x3008, 0x053F}, // X_ADDR_END_ ++{0x3002, 0x0000}, // Y_ADDR_START_ ++{0x3006, 0x03C7}, // Y_ADDR_END_ ++{0x3400, 0x0010}, // RESERVED_MFR_3400 ++{0x3402, 0x0A80}, // X_OUTPUT_CONTROL ++{0x3404, 0x0790}, // Y_OUTPUT_CONTROL ++{0x3082, 0x0008}, // OPERATION_MODE_CTRL ++{0x30BA, 0x01E2}, // DIGITAL_CTRL ++{0x300C, 0x09A0}, // LINE_LENGTH_PCK_ ++{0x300A, 0x041E}, // FRAME_LENGTH_LINES_ ++{0x3042, 0x0000}, // EXTRA_DELAY ++{0x3238, 0x0333}, // EXPOSURE_RATIO ++{0x3012, 0x036E}, // COARSE_INTEGRATION_TIME_ ++{0x3014, 0x0A7A}, // FINE_INTEGRATION_TIME_ ++{0x321E, 0x0A7A}, // FINE_INTEGRATION_TIME2 ++{0x3222, 0x0A7A}, // FINE_INTEGRATION_TIME3 ++{0x32EA, 0x3C0E}, // RESERVED_MFR_32EA ++{0x32EA, 0x3C0E}, // RESERVED_MFR_32EA ++{0x32EA, 0x3C0E}, // RESERVED_MFR_32EA ++{0x32EC, 0x72A1}, // RESERVED_MFR_32EC ++{0x32EC, 0x72A1}, // RESERVED_MFR_32EC ++{0x32EC, 0x72A1}, // RESERVED_MFR_32EC ++{0x32EC, 0x72A1}, // RESERVED_MFR_32EC ++{0x32EC, 0x72A1}, // RESERVED_MFR_32EC ++{0x32EC, 0x72A1}, // RESERVED_MFR_32EC ++{0x3C06, 0x083C}, // RESERVED_MFR_3C06 ++{0x3C08, 0x0100}, // RESERVED_MFR_3C08 ++{0x31D0, 0x0001}, // COMPANDING ++{0x31AC, 0x1410}, // DATA_FORMAT_BITS: 2xRAW8 ++{0x301A, 0x1098}, // RESET_REGISTER ++{0x301A, 0x1018}, // RESET_REGISTER ++{0x301A, 0x0018}, // RESET_REGISTER ++{0x31AE, 0x0204}, // SERIAL_FORMAT ++{0x3342, 0x122A}, // MIPI_F1_PDT_EDT ++{0x3346, 0x122A}, // MIPI_F2_PDT_EDT ++{0x334A, 0x122A}, // MIPI_F3_PDT_EDT ++{0x334E, 0x122A}, // MIPI_F4_PDT_EDT ++{0x3344, 0x0011}, // MIPI_F1_VDT_VC ++{0x3348, 0x0111}, // MIPI_F2_VDT_VC ++{0x334C, 0x0211}, // MIPI_F3_VDT_VC ++{0x3350, 0x0311}, // MIPI_F4_VDT_VC ++{0x31B0, 0x0061}, // FRAME_PREAMBLE ++{0x31B2, 0x004C}, // LINE_PREAMBLE ++{0x31B4, 0x51C8}, // RESERVED_MFR_31B4 ++{0x31B6, 0x424B}, // RESERVED_MFR_31B6 ++{0x31B8, 0x40CF}, // RESERVED_MFR_31B8 ++{0x31BA, 0x028B}, // RESERVED_MFR_31BA ++{0x31BC, 0x0D09}, // RESERVED_MFR_31BC ++// end demo init ++// start reg wizard WIDTHxHEIGHT@30fps ++#define NEW_TBL ++#ifdef NEW_TBL ++/* PCLK=27Mhz/0x5 *0x5d /1/0xa - MAXIM serializers */ ++{0x302A, 0x000A}, // VT_PIX_CLK_DIV ++{0x302C, 0x0001}, // VT_SYS_CLK_DIV ++{0x302E, 0x0005}, // PRE_PLL_CLK_DIV ++{0x3030, 0x005d}, // PLL_MULTIPLIER ++{0x3036, 0x000A}, // OP_WORD_CLK_DIV ++{0x3038, 0x0001}, // OP_SYS_CLK_DIV ++#else ++/* PCLK=27Mhz/0x9 *134 /1/8 - MAXIM serializers */ ++{0x302A, 0x0008}, // VT_PIX_CLK_DIV ++{0x302C, 0x0001}, // VT_SYS_CLK_DIV ++{0x302E, 0x0009}, // PRE_PLL_CLK_DIV ++{0x3030, 134}, // PLL_MULTIPLIER ++{0x3036, 0x0008}, // OP_WORD_CLK_DIV ++{0x3038, 0x0001}, // OP_SYS_CLK_DIV ++#endif ++{0x31B0, 0x0056}, // FRAME_PREAMBLE ++{0x31B2, 0x0045}, // LINE_PREAMBLE ++{0x3004, AR0143_X_START}, // X_ADDR_START_ ++{0x3008, AR0143_X_END}, // X_ADDR_END_ ++{0x3002, AR0143_Y_START}, // Y_ADDR_START_ ++{0x3006, AR0143_Y_END}, // Y_ADDR_END_ ++{0x3402, 0x0000 | AR0143_MAX_WIDTH}, // X_OUTPUT_CONTROL ++{0x3404, 0x0000 | AR0143_MAX_HEIGHT}, // Y_OUTPUT_CONTROL ++{0x31B4, 0x2207}, // RESERVED_MFR_31B4 ++{0x31B6, 0x220B}, // RESERVED_MFR_31B6 ++{0x31B8, 0x404B}, // RESERVED_MFR_31B8 ++{0x31BA, 0x020A}, // RESERVED_MFR_31BA ++{0x31BC, 0x0C08}, // RESERVED_MFR_31BC ++{0x3040, 0x0000}, // READ_MODE ++{0x30BA, 0x01E2}, // DIGITAL_CTRL ++{0x3082, 0x0008}, // OPERATION_MODE_CTRL ++{0x3044, 0x0400}, // DARK_CONTROL ++{0x33E0, 0x0880}, // TEST_ASIL_ROWS ++{0x3180, 0x0080}, // RESERVED_MFR_3180 ++{0x33E4, 0x0080}, // RESERVED_MFR_33E4 ++{0x3032, 0x0000}, // RESERVED_MFR_3032 ++{0x3400, 0x0010}, // RESERVED_MFR_3400 ++{0x31D0, 0x0001}, // COMPANDING ++//{0x31AC, 0x1410}, // DATA_FORMAT_BITS: 2xRAW8 ++{0x31AC, 0x140C}, // DATA_FORMAT_BITS: RAW12 ++{0x3C08, 0x0100}, // RESERVED_MFR_3C08 ++{0x3C0C, 0x0518}, // DELAY_BUFFER_LLPCK_RD_WR_OVERLAP ++#ifdef NEW_TBL ++//{0x300A, 0x0438}, // FRAME_LENGTH_LINES_ ++//{0x300C, 0x060e}, // LINE_LENGTH_PCK_ ++{0x300A, AR0143_SENSOR_HEIGHT + 157}, // FRAME_LENGTH_LINES_ ++{0x300C, AR0143_SENSOR_WIDTH + 144}, // LINE_LENGTH_PCK_ ++#else ++{0x300A, 0x048A}, // FRAME_LENGTH_LINES_ ++{0x300C, 0x05BA}, // LINE_LENGTH_PCK_ ++#endif ++{0x3018, 0x0000}, // FINE_INTEGRATION_TIME_CB ++{0x1008, 0x0338}, // FINE_INTEGRATION_TIME_MIN ++{0x100C, 0x051B}, // FINE_INTEGRATION_TIME2_MIN ++{0x100E, 0x06FE}, // FINE_INTEGRATION_TIME3_MIN ++{0x1010, 0x0155}, // FINE_INTEGRATION_TIME4_MIN ++#ifdef NEW_TBL ++{0x3012, 0x0206}, // COARSE_INTEGRATION_TIME_ ++{0x3014, 0x06e8}, // FINE_INTEGRATION_TIME_ ++{0x321E, 0x06E8}, // FINE_INTEGRATION_TIME2 ++{0x3222, 0x06E8}, // FINE_INTEGRATION_TIME3 ++#else ++{0x3012, 0x0332}, // COARSE_INTEGRATION_TIME_ ++{0x3014, 0x0694}, // FINE_INTEGRATION_TIME_ ++{0x321E, 0x0694}, // FINE_INTEGRATION_TIME2 ++{0x3222, 0x0694}, // FINE_INTEGRATION_TIME3 ++#endif ++{0x32EC, 0x72A0}, // RESERVED_MFR_32EC ++{0x31C6, 0x0000}, // HISPI_CONTROL ++#ifdef NEW_TBL ++{0x3082, 0x0000}, // OPERATION_MODE_CTRL: 1 exposure ++{0x3238, 0x0222}, // auto exposure time ratio - Fixed! ++#else ++// patch start ++//{0x30BA, 0x01E2}, // DIGITAL_CTRL: 3 exposures ++//{0x3082, 0x0008}, // OPERATION_MODE_CTRL: 3 exposures ++{0x3082, 0x0000}, // OPERATION_MODE_CTRL: 1 exposure ++//{0x30fe, 0x07ff}, // NOISE PEDESTAL ++//{0x305e, 0x3333}, // DIGITAL COLOR GLOBAL GAIN ++{0x3308, 0x200}, // DIGITAL GLOBAL GAIN: max=0x7ff ++//{0x3060, 0x7777}, // ANALOG COLOR GAIN ++{0x3366, 0x0666}, // ANALOG_GAIN - Fixed! ++//{0x3238, 0x8000}, // manual exposure time ++{0x3238, 0x0222}, // auto exposure time ratio - Fixed! ++{0x3012, 0x0300}, // T1 exposure - max=0x400 ++//{0x3212, 0x0004}, // T2 exposure - not used in auto ++//{0x3216, 0x0001}, // T3 exposure - not used in auto ++#endif ++// patch eof ++{0x301A, 0x01d8}, // RESET_REGISTER ++// enable trigger ++{0x340A, 0x0070}, // GPIO_CONTROL1: GPIO3 is trigger ++{0x340C, 0x0080}, // GPIO_CONTROL2: GPIO3 is trigger ++{0x30CE, 0x0120}, // TRIGGER_MODE ++//{0x30DC, 0x0120}, // TRIGGER_DELAY ++// end reg wizard WIDTHxHEIGHT@30fps ++}; +diff --git a/drivers/media/i2c/soc_camera/ar0220.c b/drivers/media/i2c/soc_camera/ar0220.c +index 8813522..b1ca101 100644 +--- a/drivers/media/i2c/soc_camera/ar0220.c ++++ b/drivers/media/i2c/soc_camera/ar0220.c +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + + #include "ar0220.h" + +@@ -29,7 +28,7 @@ + #define AR0220_PID 0x3000 + #define AR0220_VERSION_REG 0x0C54 + +-#define AR0220_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR8_1X8 ++#define AR0220_MEDIA_BUS_FMT MEDIA_BUS_FMT_SGRBG14_1X14 + + struct ar0220_priv { + struct v4l2_subdev sd; +@@ -47,7 +46,6 @@ struct ar0220_priv { + int port; + int gpio_resetb; + int gpio_fsin; +- + }; + + static inline struct ar0220_priv *to_ar0220(const struct i2c_client *client) +@@ -319,6 +317,7 @@ static int ar0220_initialize(struct i2c_client *client) + u16 val = 0; + u16 pid = 0; + int ret = 0; ++ int tmp_addr; + + /* check and show model ID */ + reg16_read16(client, AR0220_PID, &pid); +@@ -329,6 +328,16 @@ static int ar0220_initialize(struct i2c_client *client) + goto err; + } + ++ /* setup XCLK */ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ /* CLK_OUT=22.5792*160*M/N/CLKDIV -> CLK_OUT=27MHz: CLKDIV=2, M=15, N=251: 22.5792*160/8*15/251=26.987MHz=CLK_OUT */ ++ client->addr = priv->ti9x3_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x06, 0x6f); /* Set CLKDIV and M */ ++ reg8_write(client, 0x07, 0xfb); /* Set N */ ++ } ++ client->addr = tmp_addr; ++ + /* Program wizard registers */ + ar0220_set_regs(client, ar0220_regs_wizard, ARRAY_SIZE(ar0220_regs_wizard)); + +@@ -386,11 +395,8 @@ static int ar0220_parse_dt(struct device_node *np, struct ar0220_priv *priv) + usleep_range(2000, 2500); /* wait 2ms */ + reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ + reg8_write(client, 0x5d, AR0220_I2C_ADDR << 1); /* Sensor native I2C address */ +-// reg8_write(client, 0x6e, 0xa9); /* GPIO0 - reset, GPIO1 - fsin */ + +- client->addr = priv->ti9x3_addr; /* Serializer I2C address */ +- reg8_write(client, 0x06, 0x41); /* Set clock divider M */ +- reg8_write(client, 0x07, 0x25); /* Set clock divider N = 27MHz */ ++// reg8_write(client, 0x6e, 0xa9); /* GPIO0 - reset, GPIO1 - fsin */ + } + client->addr = tmp_addr; + +diff --git a/drivers/media/i2c/soc_camera/ar0220.h b/drivers/media/i2c/soc_camera/ar0220.h +index 8ef557d..205c351 100644 +--- a/drivers/media/i2c/soc_camera/ar0220.h ++++ b/drivers/media/i2c/soc_camera/ar0220.h +@@ -12,7 +12,7 @@ + //#define AR0220_DISPLAY_PATTERN_FIXED + //#define AR0220_DISPLAY_PATTERN_COLOR_BAR + +-#define AR0220_MAX_WIDTH 3648 // (1820*2=3640) <- must be multiple of 16 - requred by R-CAR VIN ++#define AR0220_MAX_WIDTH 1820 + #define AR0220_MAX_HEIGHT 944 + + #define AR0220_DELAY 0xffff +@@ -25,14 +25,14 @@ struct ar0220_reg { + static const struct ar0220_reg ar0220_regs_wizard[] = { + {0x301A, 0x0018}, // RESET_REGISTER + {AR0220_DELAY, 500}, // Wait 500ms +-{0x3070, 0x0000}, // 1: Solid color test pattern, +- // 2: Full color bar test pattern, +- // 3: Fade to grey color bar test pattern, +- //256: Walking 1 test pattern (12 bit) +-{0x3072, 0x0123}, // R +-{0x3074, 0x0456}, // G(GR row) +-{0x3076, 0x0abc}, // B +-{0x3078, 0x0def}, // G(GB row) ++{0x3070, 0x0000}, // 1: Solid color test pattern, ++ // 2: Full color bar test pattern, ++ // 3: Fade to grey color bar test pattern, ++ //256: Walking 1 test pattern (12 bit) ++{0x3072, 0x0123}, // R ++{0x3074, 0x0456}, // G(GR row) ++{0x3076, 0x0abc}, // B ++{0x3078, 0x0def}, // G(GB row) + #ifdef AR0220_DISPLAY_PATTERN_FIXED + {0x3070, 0x0001}, + #endif +diff --git a/drivers/media/i2c/soc_camera/ar0231.c b/drivers/media/i2c/soc_camera/ar0231.c +new file mode 100644 +index 0000000..176e1bf +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0231.c +@@ -0,0 +1,580 @@ ++/* ++ * ON Semiconductor AR0231 sensor camera driver ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "ar0231.h" ++ ++#define AR0231_I2C_ADDR 0x10 ++ ++#define AR0231_PID 0x3000 ++#define AR0231_VERSION_REG 0x0354 ++ ++#define AR0231_MEDIA_BUS_FMT MEDIA_BUS_FMT_SGRBG12_1X12 ++ ++struct ar0231_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int init_complete; ++ u8 id[6]; ++ /* serializers */ ++ int max9286_addr; ++ int max9271_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++}; ++ ++static inline struct ar0231_priv *to_ar0231(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct ar0231_priv, sd); ++} ++ ++static void ar0231_s_port(struct i2c_client *client, int fwd_en) ++{ ++ struct ar0231_priv *priv = to_ar0231(client); ++ int tmp_addr; ++ ++ if (priv->max9286_addr) { ++ tmp_addr = client->addr; ++ client->addr = priv->max9286_addr; /* Deserializer I2C address */ ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ client->addr = tmp_addr; ++ }; ++} ++ ++static int ar0231_set_regs(struct i2c_client *client, ++ const struct ar0231_reg *regs, int nr_regs) ++{ ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (regs[i].reg == AR0231_DELAY) { ++ mdelay(regs[i].val); ++ continue; ++ } ++ ++ reg16_write16(client, regs[i].reg, regs[i].val); ++ } ++ ++ return 0; ++} ++ ++static int ar0231_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int ar0231_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0231_priv *priv = to_ar0231(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = AR0231_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int ar0231_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = AR0231_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int ar0231_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = AR0231_MEDIA_BUS_FMT; ++ ++ return 0; ++} ++ ++static int ar0231_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0231_priv *priv = to_ar0231(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = AR0231_VERSION_REG >> 8; ++ edid->edid[9] = AR0231_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int ar0231_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0231_priv *priv = to_ar0231(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > AR0231_MAX_WIDTH) || ++ (rect->top + rect->height > AR0231_MAX_HEIGHT)) ++ *rect = priv->rect; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ return 0; ++} ++ ++static int ar0231_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0231_priv *priv = to_ar0231(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = AR0231_MAX_WIDTH; ++ sel->r.height = AR0231_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = AR0231_MAX_WIDTH; ++ sel->r.height = AR0231_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ar0231_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int ar0231_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u16 val = 0; ++ ++ ret = reg16_read16(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int ar0231_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return reg16_write16(client, (u16)reg->reg, (u16)reg->val); ++} ++#endif ++ ++static struct v4l2_subdev_core_ops ar0231_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ar0231_g_register, ++ .s_register = ar0231_s_register, ++#endif ++}; ++ ++static int ar0231_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0231_priv *priv = to_ar0231(client); ++ int ret = -EINVAL; ++ u16 val = 0; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ case V4L2_CID_CONTRAST: ++ case V4L2_CID_SATURATION: ++ case V4L2_CID_HUE: ++ case V4L2_CID_GAMMA: ++ case V4L2_CID_SHARPNESS: ++ case V4L2_CID_AUTOGAIN: ++ break; ++ case V4L2_CID_GAIN: ++ /* Digital gain */ ++ ret = reg16_write16(client, 0x3308, ctrl->val); ++ break; ++ case V4L2_CID_ANALOGUE_GAIN: ++ /* Analog gain */ ++ ret = reg16_write16(client, 0x3366, (ctrl->val << 8) | (ctrl->val << 4) | ctrl->val); ++ break; ++ case V4L2_CID_EXPOSURE: ++ /* T1 exposure */ ++ ret = reg16_write16(client, 0x3012, ctrl->val); ++ break; ++ case V4L2_CID_HFLIP: ++ ret = reg16_read16(client, 0x3040, &val); ++ if (ctrl->val) ++ val |= (1 << 14); ++ else ++ val &= ~(1 << 14); ++ ret |= reg16_write16(client, 0x3040, val); ++ break; ++ case V4L2_CID_VFLIP: ++ ret = reg16_read16(client, 0x3040, &val); ++ if (ctrl->val) ++ val |= (1 << 15); ++ else ++ val &= ~(1 << 15); ++ ret |= reg16_write16(client, 0x3040, val); ++ break; ++ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: ++ ret = 0; ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ar0231_ctrl_ops = { ++ .s_ctrl = ar0231_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops ar0231_video_ops = { ++ .s_stream = ar0231_s_stream, ++ .g_mbus_config = ar0231_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops ar0231_subdev_pad_ops = { ++ .get_edid = ar0231_get_edid, ++ .enum_mbus_code = ar0231_enum_mbus_code, ++ .get_selection = ar0231_get_selection, ++ .set_selection = ar0231_set_selection, ++ .get_fmt = ar0231_get_fmt, ++ .set_fmt = ar0231_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops ar0231_subdev_ops = { ++ .core = &ar0231_core_ops, ++ .video = &ar0231_video_ops, ++ .pad = &ar0231_subdev_pad_ops, ++}; ++ ++static void ar0231_otp_id_read(struct i2c_client *client) ++{ ++ struct ar0231_priv *priv = to_ar0231(client); ++ int i; ++ u16 val = 0; ++ ++ /* read camera id from ar014x OTP memory */ ++ reg16_write16(client, 0x3054, 0x400); ++ reg16_write16(client, 0x304a, 0x110); ++ usleep_range(25000, 25500); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i += 2) { ++ /* first 4 bytes are equal on all ar014x */ ++ reg16_read16(client, 0x3800 + i + 4, &val); ++ priv->id[i] = val >> 8; ++ priv->id[i + 1] = val & 0xff; ++ } ++} ++ ++static ssize_t ar0231_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0231_priv *priv = to_ar0231(client); ++ ++ ar0231_otp_id_read(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_ar0231, S_IRUGO, ar0231_otp_id_show, NULL); ++ ++static int ar0231_initialize(struct i2c_client *client) ++{ ++ struct ar0231_priv *priv = to_ar0231(client); ++ u16 val = 0; ++ u16 pid = 0; ++ int ret = 0; ++ ++ /* check and show model ID */ ++ reg16_read16(client, AR0231_PID, &pid); ++ ++ if (pid != AR0231_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x\n", pid); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ /* Program wizard registers */ ++ ar0231_set_regs(client, ar0231_regs_wizard_rev4, ARRAY_SIZE(ar0231_regs_wizard_rev4)); ++ ++ /* Enable stream */ ++ reg16_read16(client, 0x301a, &val); // read inital reset_register value ++ val |= (1 << 2); // Set streamOn bit ++ reg16_write16(client, 0x301a, val); // Start Streaming ++ ++ /* Read OTP IDs */ ++ ar0231_otp_id_read(client); ++ ++ dev_info(&client->dev, "ar0231 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, AR0231_MAX_WIDTH, AR0231_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ ar0231_s_port(client, 0); ++ return ret; ++} ++ ++static int ar0231_parse_dt(struct device_node *np, struct ar0231_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ of_node_put(endpoint); ++ ++ if (!priv->max9286_addr) { ++ dev_err(&client->dev, "deserializer does not present\n"); ++ return -EINVAL; ++ } ++ ++ ar0231_s_port(client, 1); ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ ++ reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x0A, AR0231_I2C_ADDR << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ client->addr = tmp_addr; ++ ++ mdelay(10); ++ ++ return 0; ++} ++ ++static int ar0231_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ar0231_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &ar0231_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0231_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0231_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0231_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0231_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0231_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0231_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0231_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0231_ctrl_ops, ++ V4L2_CID_GAIN, 1, 0x7ff, 1, 0x200); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0231_ctrl_ops, ++ V4L2_CID_ANALOGUE_GAIN, 1, 0xe, 1, 0xa); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0231_ctrl_ops, ++ V4L2_CID_EXPOSURE, 1, 0x600, 1, 0x144); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0231_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0231_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = ar0231_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = ar0231_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = AR0231_MAX_WIDTH; ++ priv->rect.height = AR0231_MAX_HEIGHT; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ar0231) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_AR0231 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int ar0231_remove(struct i2c_client *client) ++{ ++ struct ar0231_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ar0231); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_AR0231 ++static const struct i2c_device_id ar0231_id[] = { ++ { "ar0231", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ar0231_id); ++ ++static const struct of_device_id ar0231_of_ids[] = { ++ { .compatible = "aptina,ar0231", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ar0231_of_ids); ++ ++static struct i2c_driver ar0231_i2c_driver = { ++ .driver = { ++ .name = "ar0231", ++ .of_match_table = ar0231_of_ids, ++ }, ++ .probe = ar0231_probe, ++ .remove = ar0231_remove, ++ .id_table = ar0231_id, ++}; ++ ++module_i2c_driver(ar0231_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for AR0231"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/ar0231.h b/drivers/media/i2c/soc_camera/ar0231.h +new file mode 100644 +index 0000000..b63dc91 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0231.h +@@ -0,0 +1,34 @@ ++/* ++ * ON Semiconductor AR0231 sensor camera wizard 1928x1208@30/BGGR/BT601 ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++//#define AR0231_DISPLAY_PATTERN_FIXED ++//#define AR0231_DISPLAY_PATTERN_COLOR_BAR ++ ++#define AR0231_MAX_WIDTH 1928 ++#define AR0231_MAX_HEIGHT 1208 ++ ++#define AR0231_DELAY 0xffff ++ ++#define AR0231_SENSOR_WIDTH 1928 ++#define AR0231_SENSOR_HEIGHT 1208 ++ ++#define AR0231_X_START ((AR0231_SENSOR_WIDTH - AR0231_MAX_WIDTH) / 2) ++#define AR0231_Y_START ((AR0231_SENSOR_HEIGHT - AR0231_MAX_HEIGHT) / 2) ++#define AR0231_X_END (AR0231_X_START + AR0231_MAX_WIDTH - 1) ++#define AR0231_Y_END (AR0231_Y_START + AR0231_MAX_HEIGHT - 1) ++ ++struct ar0231_reg { ++ u16 reg; ++ u16 val; ++}; ++ ++#include "ar0231_rev4.h" ++//#include "ar0231_rev6.h" +diff --git a/drivers/media/i2c/soc_camera/ar0231_rev4.h b/drivers/media/i2c/soc_camera/ar0231_rev4.h +new file mode 100644 +index 0000000..d4614ec +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0231_rev4.h +@@ -0,0 +1,348 @@ ++/* ++ * ON Semiconductor AR0231 sensor camera wizard 1920x1080@30/BGGR/MIPI ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++static const struct ar0231_reg ar0231_regs_wizard_rev4[] = { ++{0x301A, 0x0001}, // reset ++{0x301A, 0x10D8}, // Stream off and setup parallel ++{0x3070, 0x0000}, // 1: Solid color test pattern, ++ // 2: Full color bar test pattern, ++ // 3: Fade to grey color bar test pattern, ++ //256: Walking 1 test pattern (12 bit) ++{0x3072, 0x0123}, // R ++{0x3074, 0x0456}, // G(GR row) ++{0x3076, 0x0abc}, // B ++{0x3078, 0x0def}, // G(GB row) ++#ifdef AR0231_DISPLAY_PATTERN_FIXED ++{0x3070, 0x0001}, ++#endif ++#ifdef AR0231_DISPLAY_PATTERN_COLOR_BAR ++{0x3070, 0x0002}, ++#endif ++//Recommended Settings ++{0x3366, 0x6666}, // ANALOG_GAIN ++{0x3056, 0x0080}, // GREEN1_GAIN ++{0x305C, 0x0080}, // GREEN2_GAIN ++{0x3058, 0x0080}, // BLUE_GAIN ++{0x305A, 0x0080}, // RED_GAIN ++{0x3044, 0x0400}, // DARK_CONTROL ++{0x30BA, 0x1021}, // DIGITAL_CTRL ++{0x318E, 0x0200}, // DLO_CONTROL0 ++{0x32EA, 0x3C0A}, // RESERVED_MFR_32EA ++{0x32EA, 0x3C0E}, // RESERVED_MFR_32EA ++{0x3362, 0x0000}, // DC_GAIN ++{0x3364, 0x0060}, // RESERVED_MFR_3364 ++{0x3370, 0x0231}, // DBLC_CONTROL ++{0x3372, 0x700F}, // RESERVED_MFR_3372 ++{0x3386, 0x0000}, // RESERVED_MFR_3386 ++{0x3C04, 0x0E80}, // RESERVED_MFR_3C04 ++{0x3F90, 0x06E1}, // TEMPVSENS0_TMG_CTRL ++{0x3F92, 0x06E1}, // TEMPVSENS1_TMG_CTRL ++{0x3502, 0x0808}, // RESERVED_MFR_3502 ++{0x3502, 0x0808}, // RESERVED_MFR_3502 ++{0x350E, 0xFF10}, // RESERVED_MFR_350E ++{0x3506, 0x4444}, // RESERVED_MFR_3506 ++{0x3508, 0x4444}, // RESERVED_MFR_3508 ++{0x350A, 0x4465}, // RESERVED_MFR_350A ++{0x350C, 0x055F}, // RESERVED_MFR_350C ++{0x3230, 0x0317}, // FINE_CORRECTION ++{0x3232, 0x0552}, // FINE_CORRECTION2 ++{0x3234, 0x078D}, // FINE_CORRECTION3 ++{0x3566, 0x9D38}, // RESERVED_MFR_3566 ++{0x3518, 0x1FFE}, // RESERVED_MFR_3518 ++{0x3520, 0xC688}, // RESERVED_MFR_3520 ++{0x3522, 0x88C0}, // RESERVED_MFR_3522 ++{0x3524, 0xC0C6}, // RESERVED_MFR_3524 ++{0x352C, 0xC6C6}, // RESERVED_MFR_352C ++{0x3528, 0x0900}, // RESERVED_MFR_3528 ++{0x3528, 0x9900}, // RESERVED_MFR_3528 ++{0x3528, 0x9909}, // RESERVED_MFR_3528 ++{0x3528, 0x9999}, // RESERVED_MFR_3528 ++{0x352A, 0x081F}, // RESERVED_MFR_352A ++{0x352E, 0x0001}, // RESERVED_MFR_352E ++{0x352E, 0x0011}, // RESERVED_MFR_352E ++{0x3530, 0x0400}, // RESERVED_MFR_3530 ++{0x3530, 0x4400}, // RESERVED_MFR_3530 ++{0x3536, 0xFF00}, // RESERVED_MFR_3536 ++{0x3536, 0xFF00}, // RESERVED_MFR_3536 ++{0x3536, 0xFF00}, // RESERVED_MFR_3536 ++{0x3536, 0xFF00}, // RESERVED_MFR_3536 ++{0x3536, 0xFF00}, // RESERVED_MFR_3536 ++{0x3536, 0xFF00}, // RESERVED_MFR_3536 ++{0x3536, 0xFF00}, // RESERVED_MFR_3536 ++{0x3536, 0xFF00}, // RESERVED_MFR_3536 ++{0x3536, 0xFF02}, // RESERVED_MFR_3536 ++{0x3536, 0xFF06}, // RESERVED_MFR_3536 ++{0x3536, 0xFF06}, // RESERVED_MFR_3536 ++{0x3538, 0xFFFF}, // RESERVED_MFR_3538 ++{0x3538, 0xFFFF}, // RESERVED_MFR_3538 ++{0x3538, 0xFFFF}, // RESERVED_MFR_3538 ++{0x3538, 0xFFFF}, // RESERVED_MFR_3538 ++{0x3538, 0xFFFF}, // RESERVED_MFR_3538 ++{0x3538, 0xFFFF}, // RESERVED_MFR_3538 ++{0x3538, 0xFFFF}, // RESERVED_MFR_3538 ++{0x3538, 0xFFFF}, // RESERVED_MFR_3538 ++{0x3538, 0xFFFF}, // RESERVED_MFR_3538 ++{0x3538, 0xFFFF}, // RESERVED_MFR_3538 ++{0x353A, 0x9000}, // RESERVED_MFR_353A ++{0x353C, 0x3F00}, // RESERVED_MFR_353C ++{0x353C, 0x3F00}, // RESERVED_MFR_353C ++{0x353C, 0x3F00}, // RESERVED_MFR_353C ++{0x353C, 0x3F00}, // RESERVED_MFR_353C ++{0x353C, 0x3F00}, // RESERVED_MFR_353C ++{0x353C, 0x3F00}, // RESERVED_MFR_353C ++{0x32EC, 0x72A1}, // RESERVED_MFR_32EC ++{0x3540, 0xC637}, // RESERVED_MFR_3540 ++{0x3540, 0xC637}, // RESERVED_MFR_3540 ++{0x3540, 0xC637}, // RESERVED_MFR_3540 ++{0x3542, 0x584B}, // RESERVED_MFR_3542 ++{0x3542, 0x464B}, // RESERVED_MFR_3542 ++{0x3544, 0x565A}, // RESERVED_MFR_3544 ++{0x3544, 0x4B5A}, // RESERVED_MFR_3544 ++{0x3546, 0x545A}, // RESERVED_MFR_3546 ++{0x3546, 0x5A5A}, // RESERVED_MFR_3546 ++{0x3548, 0x6430}, // RESERVED_MFR_3548 ++{0x3556, 0x101F}, // RESERVED_MFR_3556 ++{0x3566, 0x9D38}, // RESERVED_MFR_3566 ++{0x3566, 0x1D38}, // RESERVED_MFR_3566 ++{0x3566, 0x1D28}, // RESERVED_MFR_3566 ++{0x3566, 0x1128}, // RESERVED_MFR_3566 ++{0x3566, 0x1328}, // RESERVED_MFR_3566 ++{0x3566, 0x3328}, // RESERVED_MFR_3566 ++//Sequencer Update ++{0x2512, 0x8000}, // SEQ_CTRL_PORT ++{0x2510, 0x0905}, // SEQ_DATA_PORT ++{0x2510, 0x3350}, // SEQ_DATA_PORT ++{0x2510, 0x2004}, // SEQ_DATA_PORT ++{0x2510, 0x1460}, // SEQ_DATA_PORT ++{0x2510, 0x1578}, // SEQ_DATA_PORT ++{0x2510, 0x1360}, // SEQ_DATA_PORT ++{0x2510, 0x7B24}, // SEQ_DATA_PORT ++{0x2510, 0xFF24}, // SEQ_DATA_PORT ++{0x2510, 0xFF24}, // SEQ_DATA_PORT ++{0x2510, 0xEA24}, // SEQ_DATA_PORT ++{0x2510, 0x1022}, // SEQ_DATA_PORT ++{0x2510, 0x2410}, // SEQ_DATA_PORT ++{0x2510, 0x155A}, // SEQ_DATA_PORT ++{0x2510, 0x1342}, // SEQ_DATA_PORT ++{0x2510, 0x1400}, // SEQ_DATA_PORT ++{0x2510, 0x24FF}, // SEQ_DATA_PORT ++{0x2510, 0x24FF}, // SEQ_DATA_PORT ++{0x2510, 0x24EA}, // SEQ_DATA_PORT ++{0x2510, 0x2324}, // SEQ_DATA_PORT ++{0x2510, 0x647A}, // SEQ_DATA_PORT ++{0x2510, 0x2404}, // SEQ_DATA_PORT ++{0x2510, 0x052C}, // SEQ_DATA_PORT ++{0x2510, 0x400A}, // SEQ_DATA_PORT ++{0x2510, 0xFF0A}, // SEQ_DATA_PORT ++{0x2510, 0xFF0A}, // SEQ_DATA_PORT ++{0x2510, 0x0408}, // SEQ_DATA_PORT ++{0x2510, 0x3851}, // SEQ_DATA_PORT ++{0x2510, 0x1440}, // SEQ_DATA_PORT ++{0x2510, 0x0004}, // SEQ_DATA_PORT ++{0x2510, 0x0801}, // SEQ_DATA_PORT ++{0x2510, 0x0408}, // SEQ_DATA_PORT ++{0x2510, 0x1180}, // SEQ_DATA_PORT ++{0x2510, 0x15DC}, // SEQ_DATA_PORT ++{0x2510, 0x134C}, // SEQ_DATA_PORT ++{0x2510, 0x1002}, // SEQ_DATA_PORT ++{0x2510, 0x1016}, // SEQ_DATA_PORT ++{0x2510, 0x1181}, // SEQ_DATA_PORT ++{0x2510, 0x1189}, // SEQ_DATA_PORT ++{0x2510, 0x1056}, // SEQ_DATA_PORT ++{0x2510, 0x1210}, // SEQ_DATA_PORT ++{0x2510, 0x0901}, // SEQ_DATA_PORT ++{0x2510, 0x0D08}, // SEQ_DATA_PORT ++{0x2510, 0x0913}, // SEQ_DATA_PORT ++{0x2510, 0x13C8}, // SEQ_DATA_PORT ++{0x2510, 0x092B}, // SEQ_DATA_PORT ++{0x2510, 0x1588}, // SEQ_DATA_PORT ++{0x2510, 0x1388}, // SEQ_DATA_PORT ++{0x2510, 0x090B}, // SEQ_DATA_PORT ++{0x2510, 0x11D9}, // SEQ_DATA_PORT ++{0x2510, 0x091D}, // SEQ_DATA_PORT ++{0x2510, 0x1441}, // SEQ_DATA_PORT ++{0x2510, 0x0903}, // SEQ_DATA_PORT ++{0x2510, 0x1214}, // SEQ_DATA_PORT ++{0x2510, 0x0901}, // SEQ_DATA_PORT ++{0x2510, 0x10D6}, // SEQ_DATA_PORT ++{0x2510, 0x1210}, // SEQ_DATA_PORT ++{0x2510, 0x1212}, // SEQ_DATA_PORT ++{0x2510, 0x1210}, // SEQ_DATA_PORT ++{0x2510, 0x11DD}, // SEQ_DATA_PORT ++{0x2510, 0x11D9}, // SEQ_DATA_PORT ++{0x2510, 0x1056}, // SEQ_DATA_PORT ++{0x2510, 0x090B}, // SEQ_DATA_PORT ++{0x2510, 0x11DB}, // SEQ_DATA_PORT ++{0x2510, 0x0915}, // SEQ_DATA_PORT ++{0x2510, 0x119B}, // SEQ_DATA_PORT ++{0x2510, 0x090F}, // SEQ_DATA_PORT ++{0x2510, 0x11BB}, // SEQ_DATA_PORT ++{0x2510, 0x121A}, // SEQ_DATA_PORT ++{0x2510, 0x1210}, // SEQ_DATA_PORT ++{0x2510, 0x1460}, // SEQ_DATA_PORT ++{0x2510, 0x1250}, // SEQ_DATA_PORT ++{0x2510, 0x1076}, // SEQ_DATA_PORT ++{0x2510, 0x10E6}, // SEQ_DATA_PORT ++{0x2510, 0x0901}, // SEQ_DATA_PORT ++{0x2510, 0x15AB}, // SEQ_DATA_PORT ++{0x2510, 0x0901}, // SEQ_DATA_PORT ++{0x2510, 0x13A8}, // SEQ_DATA_PORT ++{0x2510, 0x1240}, // SEQ_DATA_PORT ++{0x2510, 0x1260}, // SEQ_DATA_PORT ++{0x2510, 0x0923}, // SEQ_DATA_PORT ++{0x2510, 0x158D}, // SEQ_DATA_PORT ++{0x2510, 0x138D}, // SEQ_DATA_PORT ++{0x2510, 0x0901}, // SEQ_DATA_PORT ++{0x2510, 0x0B09}, // SEQ_DATA_PORT ++{0x2510, 0x0108}, // SEQ_DATA_PORT ++{0x2510, 0x0901}, // SEQ_DATA_PORT ++{0x2510, 0x1440}, // SEQ_DATA_PORT ++{0x2510, 0x091D}, // SEQ_DATA_PORT ++{0x2510, 0x1588}, // SEQ_DATA_PORT ++{0x2510, 0x1388}, // SEQ_DATA_PORT ++{0x2510, 0x092D}, // SEQ_DATA_PORT ++{0x2510, 0x1066}, // SEQ_DATA_PORT ++{0x2510, 0x0905}, // SEQ_DATA_PORT ++{0x2510, 0x0C08}, // SEQ_DATA_PORT ++{0x2510, 0x090B}, // SEQ_DATA_PORT ++{0x2510, 0x1441}, // SEQ_DATA_PORT ++{0x2510, 0x090D}, // SEQ_DATA_PORT ++{0x2510, 0x10E6}, // SEQ_DATA_PORT ++{0x2510, 0x0901}, // SEQ_DATA_PORT ++{0x2510, 0x1262}, // SEQ_DATA_PORT ++{0x2510, 0x1260}, // SEQ_DATA_PORT ++{0x2510, 0x11BF}, // SEQ_DATA_PORT ++{0x2510, 0x11BB}, // SEQ_DATA_PORT ++{0x2510, 0x1066}, // SEQ_DATA_PORT ++{0x2510, 0x11FB}, // SEQ_DATA_PORT ++{0x2510, 0x0935}, // SEQ_DATA_PORT ++{0x2510, 0x11BB}, // SEQ_DATA_PORT ++{0x2510, 0x1263}, // SEQ_DATA_PORT ++{0x2510, 0x1260}, // SEQ_DATA_PORT ++{0x2510, 0x1400}, // SEQ_DATA_PORT ++{0x2510, 0x1510}, // SEQ_DATA_PORT ++{0x2510, 0x11B8}, // SEQ_DATA_PORT ++{0x2510, 0x12A0}, // SEQ_DATA_PORT ++{0x2510, 0x1200}, // SEQ_DATA_PORT ++{0x2510, 0x1026}, // SEQ_DATA_PORT ++{0x2510, 0x1000}, // SEQ_DATA_PORT ++{0x2510, 0x1342}, // SEQ_DATA_PORT ++{0x2510, 0x1100}, // SEQ_DATA_PORT ++{0x2510, 0x7A06}, // SEQ_DATA_PORT ++{0x2510, 0x0926}, // SEQ_DATA_PORT ++{0x2510, 0x0507}, // SEQ_DATA_PORT ++{0x2510, 0x0841}, // SEQ_DATA_PORT ++{0x2510, 0x3750}, // SEQ_DATA_PORT ++{0x2510, 0x2C2C}, // SEQ_DATA_PORT ++{0x2510, 0xFE02}, // SEQ_DATA_PORT ++{0x2510, 0xFE14}, // SEQ_DATA_PORT ++{0x3566, 0x3328}, // RESERVED_MFR_3566 ++{0x350C, 0x055F}, // RESERVED_MFR_350C ++{0x32D0, 0x3A02}, // RESERVED_MFR_32D0 ++{0x32D2, 0x3508}, // RESERVED_MFR_32D2 ++{0x32D4, 0x3702}, // RESERVED_MFR_32D4 ++{0x32D6, 0x3C04}, // RESERVED_MFR_32D6 ++{0x32DC, 0x370A}, // RESERVED_MFR_32DC ++//Parallel Timing Setup ++{0x302A, 0x0009}, // VT_PIX_CLK_DIV ++{0x302C, 0x0001}, // VT_SYS_CLK_DIV ++{0x302E, 0x0003}, // PRE_PLL_CLK_DIV ++{0x3030, 0x0058}, // PLL_MULTIPLIER ++{0x3036, 0x0008}, // OP_WORD_CLK_DIV ++{0x3038, 0x0001}, // OP_SYS_CLK_DIV ++{0x30B0, 0x0A00}, // DIGITAL_TEST ++//Readout Mode Configuration ++{0x30A2, 0x0001}, // X_ODD_INC_ ++{0x30A6, 0x0001}, // Y_ODD_INC_ ++{0x3040, 0x0000}, // READ_MODE ++{0x3044, 0x0400}, // DARK_CONTROL ++{0x33E0, 0x0880}, // RESERVED_MFR_33E0 ++{0x3180, 0x0080}, // RESERVED_MFR_3180 ++{0x33E4, 0x0080}, // RESERVED_MFR_33E4 ++ ++//HDR Readout Mode Configuration ++#ifdef AR0231_EMBEDDED_LINE ++{0x3064, 0x1982}, // SMIA_TEST ++#else ++{0x3064, 0x1802}, // SMIA_TEST ++#endif ++ ++#if 1 ++{0x3004, AR0231_X_START}, // X_ADDR_START_ ++{0x3008, AR0231_X_END}, // X_ADDR_END_ ++{0x3002, AR0231_Y_START}, // Y_ADDR_START_ ++{0x3006, AR0231_Y_END}, // Y_ADDR_END_ ++{0x3402, 0x0000 | AR0231_MAX_WIDTH}, // X_OUTPUT_CONTROL ++{0x3404, 0x0000 | AR0231_MAX_HEIGHT}, // Y_OUTPUT_CONTROL ++#else ++{0x3004, 0}, // X_ADDR_START_ ++{0x3008, 0x0787}, // X_ADDR_END_ ++{0x3002, 0x0000}, // Y_ADDR_START_ ++{0x3006, 0x04B7}, // Y_ADDR_END_ ++{0x3402, 0x0788}, // RESERVED_MFR_3402 ++{0x3402, 0x0F10}, // RESERVED_MFR_3402 ++{0x3404, 0x0440}, // RESERVED_MFR_3404 ++{0x3404, 0x0970}, // RESERVED_MFR_3404 ++#endif ++{0x3032, 0x0000}, // SCALING_MODE ++{0x3400, 0x0010}, // RESERVED_MFR_3400 ++ ++//3exp Timing and Exposure ++{0x3082, 0x0008}, // OPERATION_MODE_CTRL ++{0x30BA, 0x11E2}, // DIGITAL_CTRL ++ ++//Row and Pixel Timing ++{0x300A, 0x5af}, ++{0x300C, 0x7ba}, ++ ++//Exposure Settings ++{0x3042, 0x0000}, // EXTRA_DELAY ++{0x3238, 0x0222}, // EXPOSURE_RATIO ++{0x1008, 0x0374}, // FINE_INTEGRATION_TIME_MIN ++{0x100C, 0x05AF}, // FINE_INTEGRATION_TIME2_MIN ++{0x100E, 0x07EA}, // FINE_INTEGRATION_TIME3_MIN ++{0x1010, 0x0139}, // FINE_INTEGRATION_TIME4_MIN ++{0x3012, 0x0163}, // COARSE_INTEGRATION_TIME_ ++{0x3014, 0x06A6}, // FINE_INTEGRATION_TIME_ ++{0x321E, 0x06A6}, // FINE_INTEGRATION_TIME2 ++{0x3222, 0x06A6}, // FINE_INTEGRATION_TIME3 ++{0x30B0, 0x0B02}, // DIGITAL_TEST ++ ++{0x32EA, 0x3C0E}, // RESERVED_MFR_32EA ++{0x32EC, 0x72A1}, // RESERVED_MFR_32EC ++//Parallel HDR 12 bit Output ++{0x31D0, 0x0001}, // COMPANDING ++{0x31AC, 0x140C}, // DATA_FORMAT_BITS ++ ++//{0x301A, 0x01d8}, // RESET_REGISTER ++{0x301A, 0x01dc}, // RESET_REGISTER - stream on ++ ++//{AR0231_DELAY, 100}, // Wait 100ms ++ ++#if 0 // no need for front only camera ++/* Enable trigger input */ ++{0x340A, 0x00E0}, // GPIO_CONTROL1: GPIO1 is trigger ++{0x340C, 0x0002}, // GPIO_CONTROL2: GPIO1 is trigger ++{0x30CE, 0x0120}, // TRIGGER_MODE ++//{0x30DC, 0x0120}, // TRIGGER_DELAY ++#endif ++ ++#define NEW_TIMINGS ++#ifdef NEW_TIMINGS ++/* the sequence must be updated to use following timings, now it is a hack */ ++{0x300A, AR0231_SENSOR_HEIGHT + 225}, // FRAME_LENGTH_LINES_ ++{0x300C, AR0231_SENSOR_WIDTH + 120}, // LINE_LENGTH_PCK_ ++{0x1008, 0x0fff}, // FINE_INTEGRATION_TIME_MIN ++{0x100C, 0x0fff}, // FINE_INTEGRATION_TIME2_MIN ++{0x100E, 0x0fff}, // FINE_INTEGRATION_TIME3_MIN ++{0x1010, 0x0fff}, // FINE_INTEGRATION_TIME4_MIN ++#endif ++}; +diff --git a/drivers/media/i2c/soc_camera/ar0233.c b/drivers/media/i2c/soc_camera/ar0233.c +new file mode 100644 +index 0000000..6d034e2 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0233.c +@@ -0,0 +1,579 @@ ++/* ++ * ON Semiconductor AR0233 sensor camera driver ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "ar0233.h" ++ ++#define AR0233_I2C_ADDR 0x10 ++ ++#define AR0233_PID 0x3000 ++#define AR0233_VERSION_REG 0x0354 ++ ++#define AR0233_MEDIA_BUS_FMT MEDIA_BUS_FMT_SGRBG12_1X12 ++ ++struct ar0233_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int init_complete; ++ u8 id[6]; ++ /* serializers */ ++ int ti9x4_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++}; ++ ++static inline struct ar0233_priv *to_ar0233(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct ar0233_priv, sd); ++} ++ ++static int ar0233_set_regs(struct i2c_client *client, ++ const struct ar0233_reg *regs, int nr_regs) ++{ ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (regs[i].reg == AR0233_DELAY) { ++ mdelay(regs[i].val); ++ continue; ++ } ++ ++ reg16_write16(client, regs[i].reg, regs[i].val); ++ } ++ ++ return 0; ++} ++ ++static int ar0233_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int ar0233_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0233_priv *priv = to_ar0233(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = AR0233_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int ar0233_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = AR0233_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int ar0233_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = AR0233_MEDIA_BUS_FMT; ++ ++ return 0; ++} ++ ++static int ar0233_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0233_priv *priv = to_ar0233(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = AR0233_VERSION_REG >> 8; ++ edid->edid[9] = AR0233_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int ar0233_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0233_priv *priv = to_ar0233(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > AR0233_MAX_WIDTH) || ++ (rect->top + rect->height > AR0233_MAX_HEIGHT)) ++ *rect = priv->rect; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ return 0; ++} ++ ++static int ar0233_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0233_priv *priv = to_ar0233(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = AR0233_MAX_WIDTH; ++ sel->r.height = AR0233_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = AR0233_MAX_WIDTH; ++ sel->r.height = AR0233_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ar0233_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int ar0233_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u16 val = 0; ++ ++ ret = reg16_read16(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int ar0233_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return reg16_write16(client, (u16)reg->reg, (u16)reg->val); ++} ++#endif ++ ++static struct v4l2_subdev_core_ops ar0233_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ar0233_g_register, ++ .s_register = ar0233_s_register, ++#endif ++}; ++ ++static int ar0233_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0233_priv *priv = to_ar0233(client); ++ int ret = -EINVAL; ++ u16 val = 0; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ case V4L2_CID_CONTRAST: ++ case V4L2_CID_SATURATION: ++ case V4L2_CID_HUE: ++ case V4L2_CID_GAMMA: ++ case V4L2_CID_SHARPNESS: ++ case V4L2_CID_AUTOGAIN: ++ break; ++ case V4L2_CID_GAIN: ++ /* Digital gain */ ++ ret = reg16_write16(client, 0x3308, ctrl->val); ++ break; ++ case V4L2_CID_ANALOGUE_GAIN: ++ /* Analog gain */ ++ ret = reg16_write16(client, 0x3366, (ctrl->val << 8) | (ctrl->val << 4) | ctrl->val); ++ break; ++ case V4L2_CID_EXPOSURE: ++ /* T1 exposure */ ++ ret = reg16_write16(client, 0x3012, ctrl->val); ++ break; ++ case V4L2_CID_HFLIP: ++ ret = reg16_read16(client, 0x3040, &val); ++ if (ctrl->val) ++ val |= (1 << 14); ++ else ++ val &= ~(1 << 14); ++ ret |= reg16_write16(client, 0x3040, val); ++ break; ++ case V4L2_CID_VFLIP: ++ ret = reg16_read16(client, 0x3040, &val); ++ if (ctrl->val) ++ val |= (1 << 15); ++ else ++ val &= ~(1 << 15); ++ ret |= reg16_write16(client, 0x3040, val); ++ break; ++ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: ++ ret = 0; ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ar0233_ctrl_ops = { ++ .s_ctrl = ar0233_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops ar0233_video_ops = { ++ .s_stream = ar0233_s_stream, ++ .g_mbus_config = ar0233_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops ar0233_subdev_pad_ops = { ++ .get_edid = ar0233_get_edid, ++ .enum_mbus_code = ar0233_enum_mbus_code, ++ .get_selection = ar0233_get_selection, ++ .set_selection = ar0233_set_selection, ++ .get_fmt = ar0233_get_fmt, ++ .set_fmt = ar0233_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops ar0233_subdev_ops = { ++ .core = &ar0233_core_ops, ++ .video = &ar0233_video_ops, ++ .pad = &ar0233_subdev_pad_ops, ++}; ++ ++static void ar0233_otp_id_read(struct i2c_client *client) ++{ ++ struct ar0233_priv *priv = to_ar0233(client); ++ int i; ++ u16 val = 0; ++ ++ /* read camera id from ar014x OTP memory */ ++ reg16_write16(client, 0x3054, 0x400); ++ reg16_write16(client, 0x304a, 0x110); ++ usleep_range(25000, 25500); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i += 2) { ++ /* first 4 bytes are equal on all ar014x */ ++ reg16_read16(client, 0x3800 + i + 4, &val); ++ priv->id[i] = val >> 8; ++ priv->id[i + 1] = val & 0xff; ++ } ++} ++ ++static ssize_t ar0233_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0233_priv *priv = to_ar0233(client); ++ ++ ar0233_otp_id_read(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_ar0233, S_IRUGO, ar0233_otp_id_show, NULL); ++ ++static int ar0233_initialize(struct i2c_client *client) ++{ ++ struct ar0233_priv *priv = to_ar0233(client); ++ u16 val = 0; ++ u16 pid = 0; ++ int ret = 0; ++ int tmp_addr; ++ ++ /* check and show model ID */ ++ reg16_read16(client, AR0233_PID, &pid); ++ ++ if (pid != AR0233_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x\n", pid); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ /* setup XCLK */ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ /* CLK_OUT=22.5792*160*M/N/CLKDIV -> CLK_OUT=27MHz: CLKDIV=2, M=15, N=251: 22.5792*160/8*15/251=26.987MHz=CLK_OUT */ ++ client->addr = priv->ti9x3_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x06, 0x6f); /* Set CLKDIV and M */ ++ reg8_write(client, 0x07, 0xfb); /* Set N */ ++ reg8_write(client, 0x0e, 0x1f); /* Set FSIN GPIO to output */ ++ } ++ client->addr = tmp_addr; ++ ++ /* Program wizard registers */ ++ ar0233_set_regs(client, ar0233_regs_wizard, ARRAY_SIZE(ar0233_regs_wizard)); ++ ++ /* Enable stream */ ++ reg16_read16(client, 0x301a, &val); // read inital reset_register value ++ val |= (1 << 2); // Set streamOn bit ++ reg16_write16(client, 0x301a, val); // Start Streaming ++ ++ /* Read OTP IDs */ ++ ar0233_otp_id_read(client); ++ ++ dev_info(&client->dev, "ar0233 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, AR0233_MAX_WIDTH, AR0233_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ return ret; ++} ++ ++static int ar0233_parse_dt(struct device_node *np, struct ar0233_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ of_node_put(endpoint); ++ ++ if (!priv->ti9x4_addr) { ++ dev_err(&client->dev, "deserializer does not present\n"); ++ return -EINVAL; ++ } ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, AR0233_I2C_ADDR << 1); /* Sensor native I2C address */ ++ ++ reg8_write(client, 0x6e, 0x8a); /* GPIO0 - fsin, GPIO1 - NC */ ++ } ++ client->addr = tmp_addr; ++ ++ mdelay(10); ++ ++ return 0; ++} ++ ++static int ar0233_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ar0233_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &ar0233_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0233_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0233_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0233_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0233_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0233_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0233_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0233_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0233_ctrl_ops, ++ V4L2_CID_GAIN, 1, 0x7ff, 1, 0x200); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0233_ctrl_ops, ++ V4L2_CID_ANALOGUE_GAIN, 1, 0xe, 1, 0xa); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0233_ctrl_ops, ++ V4L2_CID_EXPOSURE, 1, 0x600, 1, 0x144); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0233_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0233_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = ar0233_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = ar0233_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = AR0233_MAX_WIDTH; ++ priv->rect.height = AR0233_MAX_HEIGHT; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ar0233) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_AR0233 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int ar0233_remove(struct i2c_client *client) ++{ ++ struct ar0233_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ar0233); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_AR0233 ++static const struct i2c_device_id ar0233_id[] = { ++ { "ar0233", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ar0233_id); ++ ++static const struct of_device_id ar0233_of_ids[] = { ++ { .compatible = "aptina,ar0233", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ar0233_of_ids); ++ ++static struct i2c_driver ar0233_i2c_driver = { ++ .driver = { ++ .name = "ar0233", ++ .of_match_table = ar0233_of_ids, ++ }, ++ .probe = ar0233_probe, ++ .remove = ar0233_remove, ++ .id_table = ar0233_id, ++}; ++ ++module_i2c_driver(ar0233_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for AR0233"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/ar0233.h b/drivers/media/i2c/soc_camera/ar0233.h +new file mode 100644 +index 0000000..f88e5a3 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0233.h +@@ -0,0 +1,409 @@ ++/* ++ * ON Semiconductor AR0233 sensor camera wizard 1920x1080@30/BGGR/MIPI ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++//#define AR0233_DISPLAY_PATTERN_FIXED ++//#define AR0233_DISPLAY_PATTERN_COLOR_BAR ++ ++#define AR0233_MAX_WIDTH 1792 //1920 ++#define AR0233_MAX_HEIGHT 1080 ++ ++#define AR0233_DELAY 0xffff ++ ++#define AR0233_SENSOR_WIDTH 1920 ++#define AR0233_SENSOR_HEIGHT 1280 ++ ++#define AR0233_X_START ((AR0233_SENSOR_WIDTH - AR0233_MAX_WIDTH) / 2) ++#define AR0233_Y_START ((AR0233_SENSOR_HEIGHT - AR0233_MAX_HEIGHT) / 2) ++#define AR0233_X_END (AR0233_X_START + AR0233_MAX_WIDTH - 1) ++#define AR0233_Y_END (AR0233_Y_START + AR0233_MAX_HEIGHT - 1) ++ ++struct ar0233_reg { ++ u16 reg; ++ u16 val; ++}; ++ ++static const struct ar0233_reg ar0233_regs_wizard[] = { ++{0x301A, 0x0018}, // RESET_REGISTER ++{AR0233_DELAY, 500}, // Wait 500ms ++{0x3070, 0x0000}, // 1: Solid color test pattern, ++ // 2: Full color bar test pattern, ++ // 3: Fade to grey color bar test pattern, ++ //256: Walking 1 test pattern (12 bit) ++{0x3072, 0x0123}, // R ++{0x3074, 0x0456}, // G(GR row) ++{0x3076, 0x0abc}, // B ++{0x3078, 0x0def}, // G(GB row) ++#ifdef AR0233_DISPLAY_PATTERN_FIXED ++{0x3070, 0x0001}, ++#endif ++#ifdef AR0233_DISPLAY_PATTERN_COLOR_BAR ++{0x3070, 0x0002}, ++#endif ++{AR0233_DELAY, 100}, // Wait 100ms ++ ++{0x3092, 0x0C24}, ++{0x337A, 0x0C80}, ++{0x3520, 0x1288}, ++{0x3522, 0x880C}, ++{0x3524, 0x0C12}, ++{0x352C, 0x1212}, ++{0x354A, 0x007F}, ++{0x350C, 0x0568}, ++{0x3506, 0x3333}, ++{0x3508, 0x3333}, ++{0x3100, 0x4000}, ++{0x3280, 0x0FA0}, ++{0x3282, 0x0FA0}, ++{0x3284, 0x0FA0}, ++{0x3286, 0x0FA0}, ++{0x3288, 0x0FA0}, ++{0x328A, 0x0FA0}, ++{0x328C, 0x0FA0}, ++{0x328E, 0x0FA0}, ++{0x3290, 0x0FA0}, ++{0x3292, 0x0FA0}, ++{0x3294, 0x0FA0}, ++{0x3296, 0x0FA0}, ++{0x3298, 0x0FA0}, ++{0x329A, 0x0FA0}, ++{0x329C, 0x0FA0}, ++{0x329E, 0x0FA0}, ++ ++{AR0233_DELAY, 200}, // Wait 200ms ++ ++{0x2512, 0x8000}, ++{0x2510, 0x0905}, ++{0x2510, 0x3350}, ++{0x2510, 0x2004}, ++{0x2510, 0x1460}, ++{0x2510, 0x1578}, ++{0x2510, 0x0901}, ++{0x2510, 0x7B24}, ++{0x2510, 0xFF24}, ++{0x2510, 0xFF24}, ++{0x2510, 0xEA24}, ++{0x2510, 0x1022}, ++{0x2510, 0x2410}, ++{0x2510, 0x155A}, ++{0x2510, 0x0901}, ++{0x2510, 0x1400}, ++{0x2510, 0x24FF}, ++{0x2510, 0x24FF}, ++{0x2510, 0x24EA}, ++{0x2510, 0x2324}, ++{0x2510, 0x647A}, ++{0x2510, 0x2404}, ++{0x2510, 0x052C}, ++{0x2510, 0x400A}, ++{0x2510, 0xFF0A}, ++{0x2510, 0xFF0A}, ++{0x2510, 0x1008}, ++{0x2510, 0x3851}, ++{0x2510, 0x1440}, ++{0x2510, 0x0004}, ++{0x2510, 0x0801}, ++{0x2510, 0x0408}, ++{0x2510, 0x1180}, ++{0x2510, 0x2652}, ++{0x2510, 0x1518}, ++{0x2510, 0x0906}, ++{0x2510, 0x1348}, ++{0x2510, 0x1002}, ++{0x2510, 0x1016}, ++{0x2510, 0x1181}, ++{0x2510, 0x1189}, ++{0x2510, 0x1056}, ++{0x2510, 0x1210}, ++{0x2510, 0x0901}, ++{0x2510, 0x0D09}, ++{0x2510, 0x1413}, ++{0x2510, 0x8809}, ++{0x2510, 0x2B15}, ++{0x2510, 0x8809}, ++{0x2510, 0x0311}, ++{0x2510, 0xD909}, ++{0x2510, 0x1214}, ++{0x2510, 0x4109}, ++{0x2510, 0x0312}, ++{0x2510, 0x1409}, ++{0x2510, 0x0110}, ++{0x2510, 0xD612}, ++{0x2510, 0x1012}, ++{0x2510, 0x1212}, ++{0x2510, 0x1011}, ++{0x2510, 0xDD11}, ++{0x2510, 0xD910}, ++{0x2510, 0x5609}, ++{0x2510, 0x1511}, ++{0x2510, 0xDB09}, ++{0x2510, 0x1511}, ++{0x2510, 0x9B09}, ++{0x2510, 0x0F11}, ++{0x2510, 0xBB12}, ++{0x2510, 0x1A12}, ++{0x2510, 0x1014}, ++{0x2510, 0x6012}, ++{0x2510, 0x5010}, ++{0x2510, 0x7610}, ++{0x2510, 0xE609}, ++{0x2510, 0x0812}, ++{0x2510, 0x4012}, ++{0x2510, 0x6009}, ++{0x2510, 0x290B}, ++{0x2510, 0x0904}, ++{0x2510, 0x1440}, ++{0x2510, 0x0923}, ++{0x2510, 0x15C8}, ++{0x2510, 0x13C8}, ++{0x2510, 0x092C}, ++{0x2510, 0x1588}, ++{0x2510, 0x1388}, ++{0x2510, 0x0C09}, ++{0x2510, 0x0C14}, ++{0x2510, 0x4109}, ++{0x2510, 0x1112}, ++{0x2510, 0x6212}, ++{0x2510, 0x6011}, ++{0x2510, 0xBF11}, ++{0x2510, 0xBB10}, ++{0x2510, 0x6611}, ++{0x2510, 0xFB09}, ++{0x2510, 0x3511}, ++{0x2510, 0xBB12}, ++{0x2510, 0x6312}, ++{0x2510, 0x6014}, ++{0x2510, 0x0015}, ++{0x2510, 0x0011}, ++{0x2510, 0xB812}, ++{0x2510, 0xA012}, ++{0x2510, 0x0010}, ++{0x2510, 0x2610}, ++{0x2510, 0x0013}, ++{0x2510, 0x0011}, ++{0x2510, 0x0008}, ++{0x2510, 0x3053}, ++{0x2510, 0x4215}, ++{0x2510, 0x4013}, ++{0x2510, 0x4010}, ++{0x2510, 0x0210}, ++{0x2510, 0x1611}, ++{0x2510, 0x8111}, ++{0x2510, 0x8910}, ++{0x2510, 0x5612}, ++{0x2510, 0x1009}, ++{0x2510, 0x010D}, ++{0x2510, 0x0815}, ++{0x2510, 0xC015}, ++{0x2510, 0xD013}, ++{0x2510, 0x5009}, ++{0x2510, 0x1313}, ++{0x2510, 0xD009}, ++{0x2510, 0x0215}, ++{0x2510, 0xC015}, ++{0x2510, 0xC813}, ++{0x2510, 0xC009}, ++{0x2510, 0x0515}, ++{0x2510, 0x8813}, ++{0x2510, 0x8009}, ++{0x2510, 0x0213}, ++{0x2510, 0x8809}, ++{0x2510, 0x0411}, ++{0x2510, 0xC909}, ++{0x2510, 0x0814}, ++{0x2510, 0x0109}, ++{0x2510, 0x0B11}, ++{0x2510, 0xD908}, ++{0x2510, 0x1400}, ++{0x2510, 0x091A}, ++{0x2510, 0x1440}, ++{0x2510, 0x0903}, ++{0x2510, 0x1214}, ++{0x2510, 0x0901}, ++{0x2510, 0x10D6}, ++{0x2510, 0x1210}, ++{0x2510, 0x1212}, ++{0x2510, 0x1210}, ++{0x2510, 0x11DD}, ++{0x2510, 0x11D9}, ++{0x2510, 0x1056}, ++{0x2510, 0x0917}, ++{0x2510, 0x11DB}, ++{0x2510, 0x0913}, ++{0x2510, 0x11FB}, ++{0x2510, 0x0905}, ++{0x2510, 0x11BB}, ++{0x2510, 0x121A}, ++{0x2510, 0x1210}, ++{0x2510, 0x1460}, ++{0x2510, 0x1250}, ++{0x2510, 0x1076}, ++{0x2510, 0x10E6}, ++{0x2510, 0x0901}, ++{0x2510, 0x15A8}, ++{0x2510, 0x0901}, ++{0x2510, 0x13A8}, ++{0x2510, 0x1240}, ++{0x2510, 0x1260}, ++{0x2510, 0x0925}, ++{0x2510, 0x13AD}, ++{0x2510, 0x0902}, ++{0x2510, 0x0907}, ++{0x2510, 0x1588}, ++{0x2510, 0x0901}, ++{0x2510, 0x138D}, ++{0x2510, 0x0B09}, ++{0x2510, 0x0914}, ++{0x2510, 0x4009}, ++{0x2510, 0x0B13}, ++{0x2510, 0x8809}, ++{0x2510, 0x1C0C}, ++{0x2510, 0x0920}, ++{0x2510, 0x1262}, ++{0x2510, 0x1260}, ++{0x2510, 0x11BF}, ++{0x2510, 0x11BB}, ++{0x2510, 0x1066}, ++{0x2510, 0x090A}, ++{0x2510, 0x11FB}, ++{0x2510, 0x093B}, ++{0x2510, 0x11BB}, ++{0x2510, 0x1263}, ++{0x2510, 0x1260}, ++{0x2510, 0x1400}, ++{0x2510, 0x1508}, ++{0x2510, 0x11B8}, ++{0x2510, 0x12A0}, ++{0x2510, 0x1200}, ++{0x2510, 0x1026}, ++{0x2510, 0x1000}, ++{0x2510, 0x1300}, ++{0x2510, 0x1100}, ++{0x2510, 0x437A}, ++{0x2510, 0x0609}, ++{0x2510, 0x0B05}, ++{0x2510, 0x0708}, ++{0x2510, 0x4137}, ++{0x2510, 0x502C}, ++{0x2510, 0x2CFE}, ++{0x2510, 0x15FE}, ++{0x2510, 0x0C2C}, ++{0x32E6, 0x00E0}, ++{0x1008, 0x036F}, ++{0x100C, 0x058F}, ++{0x100E, 0x07AF}, ++{0x1010, 0x014F}, ++{0x3230, 0x0312}, ++{0x3232, 0x0532}, ++{0x3234, 0x0752}, ++{0x3236, 0x00F2}, ++{0x3566, 0x3328}, ++{0x32D0, 0x3A02}, ++{0x32D2, 0x3508}, ++{0x32D4, 0x3702}, ++{0x32D6, 0x3C04}, ++{0x32DC, 0x370A}, ++{0x30B0, 0x0800}, ++{0x302A, 0x0006}, ++{0x302C, 0x0001}, ++{0x302E, 0x0002}, ++{0x3030, 0x002C}, ++{0x3036, 0x000C}, ++{0x3038, 0x0001}, ++{0x30B0, 0x0A00}, ++{0x30A2, 0x0001}, ++{0x30A6, 0x0001}, ++{0x3040, 0x0000}, ++{0x3040, 0x0000}, ++{0x3044, 0x0400}, ++{0x3044, 0x0400}, ++{0x3044, 0x0400}, ++{0x3044, 0x0400}, ++{0x3064, 0x1882}, ++{0x3064, 0x1802}, ++{0x3064, 0x1802}, ++{0x3064, 0x1802}, ++{0x33E0, 0x0C80}, ++{0x33E0, 0x0C80}, ++{0x3180, 0x0080}, ++{0x33E4, 0x0080}, ++{0x33E0, 0x0C80}, ++{0x33E0, 0x0C80}, ++{0x3004, AR0233_X_START}, // X_ADDR_START_ ++{0x3008, AR0233_X_END}, // X_ADDR_END_ ++{0x3002, AR0233_Y_START}, // Y_ADDR_START_ ++{0x3006, AR0233_Y_END}, // Y_ADDR_END_ ++{0x3402, 0x0000 | AR0233_MAX_WIDTH}, // X_OUTPUT_CONTROL ++{0x3404, 0x0000 | AR0233_MAX_HEIGHT}, // Y_OUTPUT_CONTROL ++{0x3032, 0x0000}, ++{0x3400, 0x0010}, ++#if 1 ++/* disable HDR */ ++{0x3082, 0x0000}, ++{0x30BA, 0x11F2}, ++#endif ++{AR0233_DELAY, 100}, // Wait 100ms ++ ++#if 0 ++{0x300A, AR0233_SENSOR_HEIGHT + 356}, // FRAME_LENGTH_LINES_ ++{0x300C, AR0233_SENSOR_WIDTH + 100}, // LINE_LENGTH_PCK_ ++#else ++{0x300A, AR0233_SENSOR_HEIGHT + 208}, // FRAME_LENGTH_LINES_ ++{0x300C, AR0233_SENSOR_WIDTH + 300}, // LINE_LENGTH_PCK_ ++#endif ++{0x3042, 0x0000}, ++{0x3238, 0x0222}, ++{0x3012, 0x0144}, ++{0x3014, AR0233_SENSOR_WIDTH + 100}, ++{0x321E, AR0233_SENSOR_WIDTH + 100}, ++{0x3222, AR0233_SENSOR_WIDTH + 100}, ++{0x30B0, 0x0B00}, ++{0x32EA, 0x3C0E}, ++{0x32EA, 0x3C0E}, ++{0x32EA, 0x3C0E}, ++{0x32EC, 0x72A1}, ++{0x32EC, 0x72A1}, ++{0x32EC, 0x72A1}, ++{0x32EC, 0x72A1}, ++{0x32EC, 0x72A1}, ++{0x32EC, 0x72A1}, ++{0x31D0, 0x0001}, // COMPANDING ++{0x31AE, 0x0004}, ++{0x31AE, 0x0304}, ++{0x31AC, 0x140C}, // DATA_FORMAT_BITS: RAW12 ++{0x301A, 0x1098}, ++{0x301A, 0x1018}, ++{0x301A, 0x1018}, ++{0x31AE, 0x0204}, ++{0x3342, 0x122C}, ++{0x3346, 0x122C}, ++{0x334A, 0x122C}, ++{0x334E, 0x122C}, ++{0x3344, 0x0011}, ++{0x3348, 0x0111}, ++{0x334C, 0x0211}, ++{0x3350, 0x0311}, ++{0x31B0, 0x0049}, ++{0x31B2, 0x0033}, ++{0x31B4, 0x2185}, ++{0x31B6, 0x1146}, ++{0x31B8, 0x3047}, ++{0x31BA, 0x0186}, ++{0x31BC, 0x0805}, ++#if 1 ++/* Enable trigger input */ ++{0x340A, 0x00E0}, // GPIO_CONTROL1: GPIO1 is trigger ++{0x340C, 0x0002}, // GPIO_CONTROL2: GPIO1 is trigger ++{0x30CE, 0x0120}, // TRIGGER_MODE ++//{0x30DC, 0x0120}, // TRIGGER_DELAY ++#endif ++{0x3366, 0x0aaa}, // ANALOG_GAIN ++{0x301A, 0x011C}, ++}; +diff --git a/drivers/media/i2c/soc_camera/gw4200_ar014x.c b/drivers/media/i2c/soc_camera/gw4200_ar014x.c +new file mode 100644 +index 0000000..2de6fe7 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/gw4200_ar014x.c +@@ -0,0 +1,592 @@ ++/* ++ * ON Semiconductor GW4200-AR014X sensor camera driver ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "gw4200_ar014x.h" ++ ++#define GW4200_I2C_ADDR 0x6d ++ ++#define GW4200_PID 0x00 ++#define GW4200_VERSION_REG 0xda ++ ++#define GW4200_MEDIA_BUS_FMT MEDIA_BUS_FMT_YUYV8_2X8 ++ ++static void gw4200_otp_id_read(struct i2c_client *client); ++ ++struct gw4200_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int init_complete; ++ u8 id[6]; ++ int exposure; ++ int gain; ++ int autogain; ++ /* serializers */ ++ int max9286_addr; ++ int max9271_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++}; ++ ++static inline struct gw4200_priv *to_gw4200(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct gw4200_priv, sd); ++} ++ ++static void gw4200_s_port(struct i2c_client *client, int fwd_en) ++{ ++ struct gw4200_priv *priv = to_gw4200(client); ++ int tmp_addr; ++ ++ if (priv->max9286_addr) { ++ tmp_addr = client->addr; ++ client->addr = priv->max9286_addr; /* Deserializer I2C address */ ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ client->addr = tmp_addr; ++ }; ++} ++ ++#if 0 ++static int gw4200_set_regs(struct i2c_client *client, ++ const struct gw4200_reg *regs, int nr_regs) ++{ ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (regs[i].reg == GW4200_DELAY) { ++ mdelay(regs[i].val); ++ continue; ++ } ++ ++ reg16_write16(client, regs[i].reg, regs[i].val); ++ } ++ ++ return 0; ++} ++#endif ++ ++static u16 gw4200_ar014x_read(struct i2c_client *client, u16 addr) ++{ ++ u16 reg_val = 0; ++ ++ reg16_write16(client, 0x0040, 0x8d00); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write16(client, 0xfc00, addr); ++ reg16_write16(client, 0xfc02, 0x0200); /* 2 bytes */ ++ reg16_write16(client, 0x0040, 0x8d05); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write16(client, 0x0040, 0x8d08); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_read16(client, 0xfc00, ®_val); ++ reg16_write16(client, 0x0040, 0x8d02); ++ usleep_range(100, 150); /* wait 100 us */ ++ ++ return reg_val; ++} ++ ++static void gw4200_ar014x_write(struct i2c_client *client, u16 addr, u16 val) ++{ ++ reg16_write16(client, 0x0040, 0x8d00); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write16(client, 0xfc00, addr); ++ reg16_write16(client, 0xfc02, 0x0200 | (val >> 8)); /* 2 bytes */ ++ reg16_write16(client, 0xfc04, (val & 0xff) << 8); ++ reg16_write16(client, 0x0040, 0x8d06); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write16(client, 0x0040, 0x8d08); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write16(client, 0x0040, 0x8d02); ++ usleep_range(100, 150); /* wait 100 us */ ++} ++ ++static int gw4200_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int gw4200_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct gw4200_priv *priv = to_gw4200(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = GW4200_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int gw4200_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = GW4200_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int gw4200_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = GW4200_MEDIA_BUS_FMT; ++ ++ return 0; ++} ++ ++static int gw4200_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct gw4200_priv *priv = to_gw4200(client); ++ ++ gw4200_otp_id_read(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = GW4200_VERSION_REG >> 8; ++ edid->edid[9] = GW4200_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int gw4200_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct gw4200_priv *priv = to_gw4200(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > GW4200_MAX_WIDTH) || ++ (rect->top + rect->height > GW4200_MAX_HEIGHT)) ++ *rect = priv->rect; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ return 0; ++} ++ ++static int gw4200_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct gw4200_priv *priv = to_gw4200(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = GW4200_MAX_WIDTH; ++ sel->r.height = GW4200_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = GW4200_MAX_WIDTH; ++ sel->r.height = GW4200_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int gw4200_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int gw4200_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u16 val = 0; ++ ++ ret = reg16_read16(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int gw4200_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return reg16_write16(client, (u16)reg->reg, (u16)reg->val); ++} ++#endif ++ ++static struct v4l2_subdev_core_ops gw4200_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = gw4200_g_register, ++ .s_register = gw4200_s_register, ++#endif ++}; ++ ++static int gw4200_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct gw4200_priv *priv = to_gw4200(client); ++ int ret = -EINVAL; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ case V4L2_CID_CONTRAST: ++ case V4L2_CID_SATURATION: ++ case V4L2_CID_HUE: ++ case V4L2_CID_GAMMA: ++ case V4L2_CID_SHARPNESS: ++ case V4L2_CID_AUTOGAIN: ++ case V4L2_CID_GAIN: ++ case V4L2_CID_EXPOSURE: ++ case V4L2_CID_HFLIP: ++ case V4L2_CID_VFLIP: ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops gw4200_ctrl_ops = { ++ .s_ctrl = gw4200_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops gw4200_video_ops = { ++ .s_stream = gw4200_s_stream, ++ .g_mbus_config = gw4200_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops gw4200_subdev_pad_ops = { ++ .get_edid = gw4200_get_edid, ++ .enum_mbus_code = gw4200_enum_mbus_code, ++ .get_selection = gw4200_get_selection, ++ .set_selection = gw4200_set_selection, ++ .get_fmt = gw4200_get_fmt, ++ .set_fmt = gw4200_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops gw4200_subdev_ops = { ++ .core = &gw4200_core_ops, ++ .video = &gw4200_video_ops, ++ .pad = &gw4200_subdev_pad_ops, ++}; ++ ++static void gw4200_otp_id_read(struct i2c_client *client) ++{ ++ struct gw4200_priv *priv = to_gw4200(client); ++ int i; ++ ++ /* read camera id from ar014x OTP memory */ ++ gw4200_ar014x_write(client, 0x3054, 0x400); ++ gw4200_ar014x_write(client, 0x304a, 0x110); ++ usleep_range(25000, 25500); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i += 2) { ++ /* first 4 bytes are equal on all ar014x */ ++ priv->id[i] = gw4200_ar014x_read(client, 0x3800 + i + 4) >> 8; ++ priv->id[i + 1] = gw4200_ar014x_read(client, 0x3800 + i + 4) & 0xff; ++ } ++} ++ ++static ssize_t gw4200_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct gw4200_priv *priv = to_gw4200(client); ++ ++ gw4200_otp_id_read(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_gw4200, S_IRUGO, gw4200_otp_id_show, NULL); ++ ++static int gw4200_initialize(struct i2c_client *client) ++{ ++ struct gw4200_priv *priv = to_gw4200(client); ++ u8 pid = 0; ++ int ret = 0; ++ ++ gw4200_s_port(client, 1); ++ ++ /* check and show model ID */ ++ reg8_read(client, GW4200_PID, &pid); ++ ++ if (pid != GW4200_VERSION_REG) { ++ dev_err(&client->dev, "Product ID error %x\n", pid); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++#if 0 ++ /* Program wizard registers */ ++ gw4200_set_regs(client, gw4200_regs_wizard, ARRAY_SIZE(gw4200_regs_wizard)); ++ /* Read OTP IDs */ ++ gw4200_otp_id_read(client); ++#endif ++ ++ dev_info(&client->dev, "gw4200 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, GW4200_MAX_WIDTH, GW4200_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ gw4200_s_port(client, 0); ++ ++ return ret; ++} ++ ++static int gw4200_parse_dt(struct device_node *np, struct gw4200_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ of_node_put(endpoint); ++ ++ if (!priv->max9286_addr) { ++ dev_err(&client->dev, "deserializer does not present for GW4200\n"); ++ return -EINVAL; ++ } ++ ++ gw4200_s_port(client, 1); ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ ++ reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x0A, GW4200_I2C_ADDR << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ client->addr = tmp_addr; ++ ++ mdelay(10); ++ ++ return 0; ++} ++ ++static int gw4200_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct gw4200_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &gw4200_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ priv->exposure = 0x100; ++ priv->gain = 0x100; ++ priv->autogain = 1; ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &gw4200_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &gw4200_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &gw4200_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &gw4200_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &gw4200_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &gw4200_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &gw4200_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); ++ v4l2_ctrl_new_std(&priv->hdl, &gw4200_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); ++ v4l2_ctrl_new_std(&priv->hdl, &gw4200_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure); ++ v4l2_ctrl_new_std(&priv->hdl, &gw4200_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &gw4200_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = gw4200_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = gw4200_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = GW4200_MAX_WIDTH; ++ priv->rect.height = GW4200_MAX_HEIGHT; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_gw4200) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_GW4200 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int gw4200_remove(struct i2c_client *client) ++{ ++ struct gw4200_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_gw4200); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_GW4200 ++static const struct i2c_device_id gw4200_id[] = { ++ { "gw4200", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, gw4200_id); ++ ++static const struct of_device_id gw4200_of_ids[] = { ++ { .compatible = "aptina,gw4200", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, gw4200_of_ids); ++ ++static struct i2c_driver gw4200_i2c_driver = { ++ .driver = { ++ .name = "gw4200", ++ .of_match_table = gw4200_of_ids, ++ }, ++ .probe = gw4200_probe, ++ .remove = gw4200_remove, ++ .id_table = gw4200_id, ++}; ++ ++module_i2c_driver(gw4200_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for GW4200"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/gw4200_ar014x.h b/drivers/media/i2c/soc_camera/gw4200_ar014x.h +new file mode 100644 +index 0000000..003f2a6 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/gw4200_ar014x.h +@@ -0,0 +1,28 @@ ++/* ++ * ON Semiconductor gw4200-ar014x sensor camera wizard 1280x720@30/UYVY/BT601/8bit ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++#define GW4200_MAX_WIDTH 1280 ++#define GW4200_MAX_HEIGHT 960 ++ ++#define GW4200_DELAY 0xffff ++ ++struct gw4200_reg { ++ u16 reg; ++ u16 val; ++}; ++ ++static const struct gw4200_reg gw4200_regs_wizard[] = { ++/* enable FSIN */ ++{0xc88c, 0x0303}, ++{0xfc00, 0x2800}, ++{0x0040, 0x8100}, ++{GW4200_DELAY, 100}, ++}; +diff --git a/drivers/media/i2c/soc_camera/imx390.c b/drivers/media/i2c/soc_camera/imx390.c +new file mode 100644 +index 0000000..fc73b4b +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/imx390.c +@@ -0,0 +1,574 @@ ++/* ++ * OmniVision IMX390 sensor camera driver ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "imx390.h" ++ ++static const int imx390_i2c_addr[] = {0x21, 0x1a}; ++ ++#define IMX390_PID 0x0330 ++#define IMX390_VER 0x0330 ++#define IMX390_VERSION_REG 0x1515 ++ ++#define IMX390_MEDIA_BUS_FMT MEDIA_BUS_FMT_SRGGB12_1X12 ++ ++struct imx390_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int init_complete; ++ u8 id[6]; ++ int exposure; ++ int gain; ++ int autogain; ++ /* serializers */ ++ int ti9x4_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++}; ++ ++static inline struct imx390_priv *to_imx390(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct imx390_priv, sd); ++} ++ ++static int imx390_set_regs(struct i2c_client *client, ++ const struct imx390_reg *regs, int nr_regs) ++{ ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (regs[i].reg == IMX390_DELAY) { ++ mdelay(regs[i].val); ++ continue; ++ } ++ ++ reg16_write(client, regs[i].reg, regs[i].val); ++ } ++ ++ return 0; ++} ++ ++static int imx390_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int imx390_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct imx390_priv *priv = to_imx390(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = IMX390_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int imx390_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = IMX390_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int imx390_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = IMX390_MEDIA_BUS_FMT; ++ ++ return 0; ++} ++ ++static int imx390_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct imx390_priv *priv = to_imx390(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = IMX390_VERSION_REG >> 8; ++ edid->edid[9] = IMX390_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int imx390_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct imx390_priv *priv = to_imx390(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > IMX390_MAX_WIDTH) || ++ (rect->top + rect->height > IMX390_MAX_HEIGHT)) ++ *rect = priv->rect; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ return 0; ++} ++ ++static int imx390_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct imx390_priv *priv = to_imx390(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = IMX390_MAX_WIDTH; ++ sel->r.height = IMX390_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = IMX390_MAX_WIDTH; ++ sel->r.height = IMX390_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int imx390_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int imx390_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u8 val = 0; ++ ++ ret = reg16_read(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u8); ++ ++ return 0; ++} ++ ++static int imx390_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return reg16_write(client, (u16)reg->reg, (u8)reg->val); ++} ++#endif ++ ++static struct v4l2_subdev_core_ops imx390_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = imx390_g_register, ++ .s_register = imx390_s_register, ++#endif ++}; ++ ++static int imx390_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct imx390_priv *priv = to_imx390(client); ++ int ret = -EINVAL; ++ int val; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ case V4L2_CID_CONTRAST: ++ case V4L2_CID_SATURATION: ++ case V4L2_CID_HUE: ++ case V4L2_CID_GAMMA: ++ case V4L2_CID_SHARPNESS: ++ case V4L2_CID_AUTOGAIN: ++ break; ++ case V4L2_CID_GAIN: ++ /* Digital gain */ ++ ret = 0; ++ break; ++ case V4L2_CID_ANALOGUE_GAIN: ++ /* Analog gain */ ++ ret = 0; ++ break; ++ case V4L2_CID_EXPOSURE: ++ val = 0xfff - ctrl->val; ++ ret = reg16_write(client, 0x0c, val); /* LSB */ ++ ret |= reg16_write(client, 0x0d, val >> 8); ++// ret |= reg16_write(client, 0x0e, ctrl->val >> 16); /* MSB */ ++ break; ++ case V4L2_CID_HFLIP: ++ case V4L2_CID_VFLIP: ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops imx390_ctrl_ops = { ++ .s_ctrl = imx390_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops imx390_video_ops = { ++ .s_stream = imx390_s_stream, ++ .g_mbus_config = imx390_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops imx390_subdev_pad_ops = { ++ .get_edid = imx390_get_edid, ++ .enum_mbus_code = imx390_enum_mbus_code, ++ .get_selection = imx390_get_selection, ++ .set_selection = imx390_set_selection, ++ .get_fmt = imx390_get_fmt, ++ .set_fmt = imx390_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops imx390_subdev_ops = { ++ .core = &imx390_core_ops, ++ .video = &imx390_video_ops, ++ .pad = &imx390_subdev_pad_ops, ++}; ++ ++static void imx390_otp_id_read(struct i2c_client *client) ++{ ++ struct imx390_priv *priv = to_imx390(client); ++ int i; ++ u8 val = 0; ++ ++ /* read camera id from imx390 OTP memory */ ++ for (i = 0; i < 6; i++) { ++ reg16_read(client, 0x3050 + i, &val); ++ priv->id[i] = val; ++ } ++} ++ ++static ssize_t imx390_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct imx390_priv *priv = to_imx390(client); ++ ++ imx390_otp_id_read(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_imx390, S_IRUGO, imx390_otp_id_show, NULL); ++ ++static int imx390_initialize(struct i2c_client *client) ++{ ++ struct imx390_priv *priv = to_imx390(client); ++ u8 val = 0; ++ u16 pid; ++ int ret = 0; ++ int tmp_addr; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(imx390_i2c_addr); i++) { ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ ++ reg8_write(client, 0x5d, imx390_i2c_addr[i] << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ } ++ client->addr = tmp_addr; ++ ++ /* check model ID */ ++ reg16_read(client, IMX390_PID, &val); ++ pid = val; ++ reg16_read(client, IMX390_VER, &val); ++ pid = (pid << 8) | val; ++ ++ if (pid == IMX390_VERSION_REG) ++ break; ++ } ++ ++ if (pid != IMX390_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x\n", pid); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++#if 0 ++ /* setup XCLK */ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ /* CLK_OUT=22.5792*160*M/N/CLKDIV -> CLK_OUT=25MHz: CLKDIV=4, M=7, N=253: 22.5792*160/4*7/253=24.989MHz=CLK_OUT */ ++ client->addr = priv->ti9x3_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x06, 0x47); /* Set CLKDIV and M */ ++ reg8_write(client, 0x07, 0xfd); /* Set N */ ++ } ++ client->addr = tmp_addr; ++#endif ++ ++ /* Read OTP IDs */ ++ imx390_otp_id_read(client); ++ /* Program wizard registers */ ++ imx390_set_regs(client, imx390_regs_wizard, ARRAY_SIZE(imx390_regs_wizard)); ++ ++ dev_info(&client->dev, "imx390 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, IMX390_MAX_WIDTH, IMX390_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++ ++err: ++ return ret; ++} ++ ++static int imx390_parse_dt(struct device_node *np, struct imx390_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ of_node_put(endpoint); ++ ++ if (!priv->ti9x4_addr) { ++ dev_err(&client->dev, "deserializer does not present\n"); ++ return -EINVAL; ++ } ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++// reg8_write(client, 0x6e, 0xa9); /* GPIO0 - reset, GPIO1 - fsin */ ++ } ++ client->addr = tmp_addr; ++ ++ return 0; ++} ++ ++static int imx390_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct imx390_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &imx390_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ priv->exposure = 0x100; ++ priv->gain = 0x100; ++ priv->autogain = 1; ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_ANALOGUE_GAIN, 1, 0xe, 1, 0x7); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0xff0, 1, 0xfff - 0x2f2); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = imx390_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = imx390_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = IMX390_MAX_WIDTH; ++ priv->rect.height = IMX390_MAX_HEIGHT; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_imx390) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_IMX390 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int imx390_remove(struct i2c_client *client) ++{ ++ struct imx390_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_imx390); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_IMX390 ++static const struct i2c_device_id imx390_id[] = { ++ { "imx390", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, imx390_id); ++ ++static const struct of_device_id imx390_of_ids[] = { ++ { .compatible = "sony,imx390", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, imx390_of_ids); ++ ++static struct i2c_driver imx390_i2c_driver = { ++ .driver = { ++ .name = "imx390", ++ .of_match_table = imx390_of_ids, ++ }, ++ .probe = imx390_probe, ++ .remove = imx390_remove, ++ .id_table = imx390_id, ++}; ++ ++module_i2c_driver(imx390_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for IMX390"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/imx390.h b/drivers/media/i2c/soc_camera/imx390.h +new file mode 100644 +index 0000000..a7189e8 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/imx390.h +@@ -0,0 +1,3818 @@ ++/* ++ * OmniVision IMX390 sensor camera wizard 1920x1080@30/BGGR/MIPI ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++//#define IMX390_DISPLAY_PATTERN_COLOR_BAR ++ ++#define IMX390_MAX_WIDTH 1920 ++#define IMX390_MAX_HEIGHT 1080 ++ ++#define IMX390_DELAY 0xffff ++#define IMX390_DT 0x2c /* MIPI Data Type RAW12 */ ++ ++struct imx390_reg { ++ u16 reg; ++ u8 val; ++}; ++ ++/* wizard: MIPI 1920x1080 RAW12 Linear 30fps 700Mbps */ ++static const struct imx390_reg imx390_regs_wizard[] = { ++{0x000C, 0xF2}, ++{0x000D, 0x02}, ++{0x000E, 0x00}, ++{0x0010, 0xF2}, ++{0x0011, 0x02}, ++{0x0012, 0x00}, ++{0x0018, 0x15}, ++{0x0019, 0x00}, ++{0x001A, 0x0C}, ++{0x001B, 0x00}, ++{0x0038, 0x00}, ++{0x003C, 0x00}, ++{0x003D, 0x00}, ++{0x003E, 0x00}, ++{0x0040, 0x00}, ++{0x0041, 0x00}, ++{0x0042, 0x00}, ++{0x0044, 0x00}, ++{0x0045, 0x00}, ++{0x0046, 0x00}, ++{0x0048, 0x00}, ++{0x0049, 0x00}, ++{0x004A, 0x00}, ++{0x004C, 0x00}, ++{0x004D, 0x00}, ++{0x004E, 0x00}, ++{0x0050, 0x00}, ++{0x0051, 0x00}, ++{0x0052, 0x00}, ++{0x0054, 0x00}, ++{0x0055, 0x00}, ++{0x0056, 0x00}, ++{0x0058, 0x00}, ++{0x0059, 0x00}, ++{0x005A, 0x00}, ++{0x005C, 0x00}, ++{0x005D, 0x00}, ++{0x005E, 0x00}, ++{0x0060, 0x00}, ++{0x0061, 0x00}, ++{0x0062, 0x00}, ++{0x0064, 0x00}, ++{0x0065, 0x00}, ++{0x0066, 0x00}, ++{0x0068, 0x00}, ++{0x0069, 0x00}, ++{0x006A, 0x00}, ++{0x0078, 0x00}, ++{0x007C, 0x00}, ++{0x007D, 0x00}, ++{0x0080, 0x00}, ++{0x0081, 0x00}, ++{0x00F4, 0x1C}, ++{0x00F5, 0xF8}, ++{0x00F6, 0x01}, ++{0x00F8, 0x03}, ++{0x00F9, 0x00}, // non-HDR ++//{0x00F9, 0x01}, // HDR ++{0x00FA, 0x00}, ++{0x00FB, 0x00}, ++{0x0114, 0x00}, ++{0x0115, 0x01}, ++{0x0118, 0x20}, ++{0x0119, 0x03}, ++{0x011A, 0x00}, ++{0x011B, 0x41}, ++{0x011C, 0x80}, ++{0x011D, 0x00}, ++{0x0120, 0x20}, ++{0x0121, 0x00}, ++{0x0122, 0x00}, ++{0x0123, 0x44}, ++{0x0124, 0x00}, ++{0x0125, 0x01}, ++{0x0128, 0xAC}, ++{0x0129, 0x0D}, ++{0x012A, 0x00}, ++{0x012B, 0xA4}, ++{0x012C, 0x00}, ++{0x012D, 0x01}, ++{0x0130, 0xC4}, ++{0x0131, 0x09}, ++{0x0132, 0x00}, ++{0x0133, 0xDA}, ++//{0x013A, ,3}, ++{0x013B, 0x01}, ++//{0x013C, ,3}, ++//{0x013D, ,3}, ++//{0x013E, ,3}, ++//{0x0140, ,3}, ++//{0x0141, ,3}, ++//{0x0142, ,3}, ++//{0x0144, ,3}, ++//{0x0145, ,3}, ++//{0x0146, ,3}, ++//{0x0148, ,3}, ++//{0x0149, ,3}, ++//{0x014A, ,3}, ++//{0x014C, ,3}, ++//{0x014D, ,3}, ++//{0x014E, ,3}, ++//{0x0150, ,3}, ++//{0x0151, ,3}, ++//{0x0152, ,3}, ++//{0x0154, ,3}, ++//{0x0155, ,3}, ++//{0x0156, ,3}, ++//{0x0158, ,3}, ++//{0x0159, ,3}, ++//{0x015A, ,3}, ++//{0x015C, ,3}, ++//{0x015D, ,3}, ++//{0x015E, ,3}, ++//{0x0160, ,3}, ++//{0x0161, ,3}, ++//{0x0162, ,3}, ++//{0x0164, ,3}, ++//{0x0165, ,3}, ++//{0x0166, ,3}, ++//{0x0168, ,3}, ++//{0x0169, ,3}, ++//{0x016A, ,3}, ++//{0x016C, ,3}, ++//{0x016D, ,3}, ++//{0x016E, ,3}, ++//{0x0170, ,3}, ++//{0x0171, ,3}, ++//{0x0172, ,3}, ++//{0x0174, ,3}, ++//{0x0175, ,3}, ++//{0x0176, ,3}, ++//{0x0178, ,3}, ++//{0x0179, ,3}, ++//{0x017A, ,3}, ++//{0x017C, ,3}, ++//{0x017D, ,3}, ++//{0x017E, ,3}, ++//{0x0180, ,3}, ++//{0x0181, ,3}, ++//{0x0182, ,3}, ++//{0x0184, ,3}, ++//{0x0185, ,3}, ++//{0x0186, ,3}, ++//{0x0188, ,3}, ++//{0x0189, ,3}, ++//{0x018A, ,3}, ++//{0x018C, ,3}, ++//{0x018D, ,3}, ++//{0x018E, ,3}, ++//{0x0190, ,3}, ++//{0x0191, ,3}, ++//{0x0192, ,3}, ++//{0x0194, ,3}, ++//{0x0195, ,3}, ++//{0x0196, ,3}, ++//{0x0198, ,3}, ++//{0x0199, ,3}, ++//{0x019A, ,3}, ++//{0x019B, ,3}, ++//{0x019C, ,3}, ++//{0x019D, ,3}, ++//{0x019E, ,3}, ++//{0x019F, ,3}, ++//{0x01A0, ,3}, ++//{0x01A1, ,3}, ++//{0x01A2, ,3}, ++//{0x01A3, ,3}, ++//{0x01A4, ,3}, ++//{0x01A5, ,3}, ++//{0x01A6, ,3}, ++//{0x01A7, ,3}, ++//{0x01A8, ,3}, ++//{0x01A9, ,3}, ++//{0x01AA, ,3}, ++//{0x01AB, ,3}, ++//{0x01AC, ,3}, ++//{0x01AD, ,3}, ++//{0x01AE, ,3}, ++//{0x01AF, ,3}, ++//{0x01B0, ,3}, ++//{0x01B1, ,3}, ++//{0x01B2, ,3}, ++//{0x01B3, ,3}, ++//{0x01B4, ,3}, ++//{0x01B5, ,3}, ++//{0x01B6, ,3}, ++//{0x01B7, ,3}, ++//{0x01B8, ,3}, ++//{0x01B9, ,3}, ++//{0x01BA, ,3}, ++//{0x01BB, ,3}, ++//{0x01BC, ,3}, ++//{0x01BD, ,3}, ++//{0x01BE, ,3}, ++//{0x01BF, ,3}, ++//{0x01C0, ,3}, ++//{0x01C1, ,3}, ++//{0x01C2, ,3}, ++//{0x01C3, ,3}, ++{0x01C4, 0x00}, ++{0x01C5, 0x00}, ++{0x01CC, 0x01}, ++{0x01D0, 0x09}, ++{0x01D4, 0x01}, ++{0x0232, 0x7E}, ++{0x0233, 0x00}, ++{0x0390, 0x00}, ++{0x0391, 0x00}, ++{0x0392, 0x00}, ++#ifdef IMX390_DISPLAY_PATTERN_COLOR_BAR ++{0x01DB, 0x32}, ++{0x03C0, 0x02}, ++#else ++{0x03C0, 0x00}, ++#endif ++{0x2000, 0x55}, ++{0x2001, 0x55}, ++{0x2002, 0x55}, ++{0x2003, 0x05}, ++{0x2004, 0x02}, ++{0x2008, 0x65}, ++{0x2009, 0x04}, ++{0x200A, 0x00}, ++{0x200C, 0x30}, ++{0x200D, 0x11}, ++{0x2010, 0x04}, ++{0x2014, 0x01}, ++{0x2018, 0x02}, ++{0x2019, 0x04}, ++{0x201A, 0x00}, ++{0x201C, 0x21}, ++{0x201D, 0x11}, ++{0x201E, 0x00}, ++{0x201F, 0x00}, ++{0x2020, 0xBC}, ++{0x2021, 0x00}, ++{0x2022, 0x7F}, ++{0x2023, 0x00}, ++{0x2024, 0xBA}, ++{0x2025, 0x00}, ++{0x2026, 0x81}, ++{0x2027, 0x00}, ++{0x2028, 0x7D}, ++{0x2029, 0x90}, ++{0x202A, 0x05}, ++{0x202C, 0xFC}, ++{0x202D, 0x02}, ++{0x202E, 0x25}, ++{0x202F, 0x03}, ++{0x2030, 0x05}, ++{0x2031, 0x02}, ++{0x2032, 0xCA}, ++{0x2033, 0x02}, ++{0x2034, 0xFC}, ++{0x2035, 0x02}, ++{0x2036, 0x25}, ++{0x2037, 0x03}, ++{0x2038, 0x25}, ++{0x2039, 0x97}, ++{0x203A, 0xEC}, ++{0x203B, 0x01}, ++{0x203C, 0xF5}, ++{0x203D, 0x8E}, ++{0x203E, 0x0C}, ++{0x203F, 0x2D}, ++{0x2040, 0x69}, ++{0x2041, 0x01}, ++{0x2042, 0x8E}, ++{0x2043, 0x01}, ++{0x2044, 0x0C}, ++{0x2045, 0x02}, ++{0x2046, 0x31}, ++{0x2047, 0x02}, ++{0x2048, 0x6A}, ++{0x2049, 0x01}, ++{0x204A, 0x8E}, ++{0x204B, 0x01}, ++{0x204C, 0x0D}, ++{0x204D, 0x02}, ++{0x204E, 0x31}, ++{0x204F, 0x02}, ++{0x2050, 0x7B}, ++{0x2051, 0x00}, ++{0x2052, 0x7D}, ++{0x2053, 0x00}, ++{0x2054, 0x95}, ++{0x2055, 0x00}, ++{0x2056, 0x97}, ++{0x2057, 0x00}, ++{0x2058, 0xAD}, ++{0x2059, 0x00}, ++{0x205A, 0xAF}, ++{0x205B, 0x00}, ++{0x205C, 0x92}, ++{0x205D, 0x00}, ++{0x205E, 0x94}, ++{0x205F, 0x00}, ++{0x2060, 0x8E}, ++{0x2061, 0x00}, ++{0x2062, 0x90}, ++{0x2063, 0x00}, ++{0x2064, 0xB1}, ++{0x2065, 0x00}, ++{0x2066, 0xB3}, ++{0x2067, 0x00}, ++{0x2068, 0x08}, ++{0x2069, 0x00}, ++{0x206A, 0x04}, ++{0x206B, 0x00}, ++{0x206C, 0x84}, ++{0x206D, 0x00}, ++{0x206E, 0x80}, ++{0x206F, 0x00}, ++{0x2070, 0x04}, ++{0x2071, 0x00}, ++{0x2072, 0x46}, ++{0x2073, 0x00}, ++{0x2074, 0xE9}, ++{0x2075, 0x01}, ++{0x2076, 0x74}, ++{0x2077, 0x02}, ++{0x2078, 0x80}, ++{0x2079, 0x00}, ++{0x207A, 0xC1}, ++{0x207B, 0x00}, ++{0x207C, 0xFF}, ++{0x207D, 0x03}, ++{0x207E, 0xFF}, ++{0x207F, 0x03}, ++{0x2080, 0x78}, ++{0x2081, 0x00}, ++{0x2082, 0x6A}, ++{0x2083, 0x01}, ++{0x2084, 0xE4}, ++{0x2085, 0x01}, ++{0x2086, 0x2B}, ++{0x2087, 0x03}, ++{0x2088, 0x00}, ++{0x2089, 0x00}, ++{0x208A, 0xFF}, ++{0x208B, 0x03}, ++{0x208C, 0xFF}, ++{0x208D, 0x03}, ++{0x208E, 0xFF}, ++{0x208F, 0x03}, ++{0x2090, 0x7D}, ++{0x2091, 0x00}, ++{0x2092, 0x62}, ++{0x2093, 0x01}, ++{0x2094, 0xE9}, ++{0x2095, 0x01}, ++{0x2096, 0x00}, ++{0x2097, 0x00}, ++{0x2098, 0x7C}, ++{0x2099, 0x00}, ++{0x209A, 0x21}, ++{0x209B, 0x03}, ++{0x209C, 0xE9}, ++{0x209D, 0x01}, ++{0x209E, 0x21}, ++{0x209F, 0x03}, ++{0x20A0, 0xFF}, ++{0x20A1, 0x03}, ++{0x20A2, 0xFF}, ++{0x20A3, 0x03}, ++{0x20A4, 0xFF}, ++{0x20A5, 0x03}, ++{0x20A6, 0xFF}, ++{0x20A7, 0x03}, ++{0x20A8, 0xFF}, ++{0x20A9, 0x03}, ++{0x20AA, 0xFF}, ++{0x20AB, 0x03}, ++{0x20AC, 0xFF}, ++{0x20AD, 0x03}, ++{0x20AE, 0xFF}, ++{0x20AF, 0x03}, ++{0x20B0, 0xFF}, ++{0x20B1, 0x03}, ++{0x20B2, 0xFF}, ++{0x20B3, 0x03}, ++{0x20B4, 0x87}, ++{0x20B5, 0xCC}, ++{0x20B6, 0x87}, ++{0x20B7, 0x08}, ++{0x20B8, 0xF4}, ++{0x20B9, 0xA5}, ++{0x20BA, 0x07}, ++{0x20BC, 0x1F}, ++{0x20BD, 0x01}, ++{0x20BE, 0xF6}, ++{0x20BF, 0x00}, ++{0x20C0, 0x90}, ++{0x20C1, 0x01}, ++{0x20C2, 0x67}, ++{0x20C3, 0x01}, ++{0x20C4, 0xFF}, ++{0x20C5, 0x03}, ++{0x20C6, 0xFF}, ++{0x20C7, 0x03}, ++{0x20C8, 0x33}, ++{0x20C9, 0x02}, ++{0x20CA, 0x0A}, ++{0x20CB, 0x02}, ++{0x20CC, 0x7F}, ++{0x20CD, 0x00}, ++{0x20CE, 0xD2}, ++{0x20CF, 0x00}, ++{0x20D0, 0x81}, ++{0x20D1, 0x00}, ++{0x20D2, 0x87}, ++{0x20D3, 0x00}, ++{0x20D4, 0x09}, ++{0x20D5, 0x00}, ++{0x20D8, 0x7F}, ++{0x20D9, 0x00}, ++{0x20DA, 0x62}, ++{0x20DB, 0x01}, ++{0x20DC, 0x7F}, ++{0x20DD, 0x00}, ++{0x20DE, 0x62}, ++{0x20DF, 0x01}, ++{0x20E0, 0x65}, ++{0x20E1, 0x00}, ++{0x20E2, 0x75}, ++{0x20E3, 0x00}, ++{0x20E4, 0xE0}, ++{0x20E5, 0x00}, ++{0x20E6, 0xF0}, ++{0x20E7, 0x00}, ++{0x20E8, 0x4C}, ++{0x20E9, 0x01}, ++{0x20EA, 0x5C}, ++{0x20EB, 0x01}, ++{0x20EC, 0xD1}, ++{0x20ED, 0x01}, ++{0x20EE, 0xE1}, ++{0x20EF, 0x01}, ++{0x20F0, 0x93}, ++{0x20F1, 0x02}, ++{0x20F2, 0xA3}, ++{0x20F3, 0x02}, ++{0x20F4, 0x0D}, ++{0x20F5, 0x03}, ++{0x20F6, 0x1D}, ++{0x20F7, 0x03}, ++{0x20F8, 0x57}, ++{0x20F9, 0x00}, ++{0x20FA, 0x7B}, ++{0x20FB, 0x00}, ++{0x20FC, 0xD2}, ++{0x20FD, 0x00}, ++{0x20FE, 0xF6}, ++{0x20FF, 0x00}, ++{0x2100, 0x3E}, ++{0x2101, 0x01}, ++{0x2102, 0x60}, ++{0x2103, 0x01}, ++{0x2104, 0xC3}, ++{0x2105, 0x01}, ++{0x2106, 0xE5}, ++{0x2107, 0x01}, ++{0x2108, 0x85}, ++{0x2109, 0x02}, ++{0x210A, 0xA9}, ++{0x210B, 0x02}, ++{0x210C, 0xFF}, ++{0x210D, 0x02}, ++{0x210E, 0x21}, ++{0x210F, 0x03}, ++{0x2110, 0xFF}, ++{0x2111, 0x03}, ++{0x2112, 0x00}, ++{0x2113, 0x00}, ++{0x2114, 0xFF}, ++{0x2115, 0x03}, ++{0x2116, 0xFF}, ++{0x2117, 0x03}, ++{0x2118, 0xFF}, ++{0x2119, 0x03}, ++{0x211A, 0xFF}, ++{0x211B, 0x03}, ++{0x211C, 0xFF}, ++{0x211D, 0x03}, ++{0x211E, 0xFF}, ++{0x211F, 0x03}, ++{0x2120, 0xFF}, ++{0x2121, 0x03}, ++{0x2122, 0xFF}, ++{0x2123, 0x03}, ++{0x2124, 0xFF}, ++{0x2125, 0x03}, ++{0x2126, 0xFF}, ++{0x2127, 0x03}, ++{0x2128, 0x7D}, ++{0x2129, 0x90}, ++{0x212A, 0xD5}, ++{0x212B, 0x07}, ++{0x212C, 0x64}, ++{0x212D, 0x01}, ++{0x2130, 0x5F}, ++{0x2131, 0x7D}, ++{0x2132, 0x05}, ++{0x2134, 0x78}, ++{0x2135, 0x00}, ++{0x2136, 0x76}, ++{0x2137, 0x00}, ++{0x2138, 0xF3}, ++{0x2139, 0x00}, ++{0x213A, 0xF1}, ++{0x213B, 0x00}, ++{0x213C, 0xA6}, ++{0x213D, 0x02}, ++{0x213E, 0xA4}, ++{0x213F, 0x02}, ++{0x2140, 0x7D}, ++{0x2141, 0x00}, ++{0x2142, 0x8D}, ++{0x2143, 0x00}, ++{0x2144, 0xA1}, ++{0x2145, 0x01}, ++{0x2146, 0xB1}, ++{0x2147, 0x01}, ++{0x2148, 0xAB}, ++{0x2149, 0x02}, ++{0x214A, 0xBB}, ++{0x214B, 0x02}, ++{0x214C, 0x17}, ++{0x214D, 0x5C}, ++{0x214E, 0x00}, ++{0x2150, 0x00}, ++{0x2151, 0x00}, ++{0x2152, 0xF8}, ++{0x2153, 0x00}, ++{0x2154, 0xBE}, ++{0x2155, 0x00}, ++{0x2156, 0x7D}, ++{0x2157, 0x00}, ++{0x2158, 0x25}, ++{0x2159, 0x00}, ++{0x215A, 0x7D}, ++{0x215B, 0x00}, ++{0x215C, 0x62}, ++{0x215D, 0x01}, ++{0x215E, 0xFF}, ++{0x215F, 0x03}, ++{0x2160, 0x26}, ++{0x2161, 0x00}, ++{0x2162, 0x7D}, ++{0x2163, 0x00}, ++{0x2164, 0x63}, ++{0x2165, 0x01}, ++{0x2166, 0xFF}, ++{0x2167, 0x03}, ++{0x2168, 0xCB}, ++{0x2169, 0x02}, ++{0x216A, 0xCF}, ++{0x216B, 0x02}, ++{0x216C, 0xFF}, ++{0x216D, 0x03}, ++{0x216E, 0xFF}, ++{0x216F, 0x03}, ++{0x2170, 0xFF}, ++{0x2171, 0x03}, ++{0x2172, 0xFF}, ++{0x2173, 0x03}, ++{0x2174, 0xFF}, ++{0x2175, 0x03}, ++{0x2176, 0xFF}, ++{0x2177, 0x03}, ++{0x2178, 0x7E}, ++{0x2179, 0x00}, ++{0x217A, 0xBD}, ++{0x217B, 0x00}, ++{0x217C, 0xEC}, ++{0x217D, 0x01}, ++{0x217E, 0x7B}, ++{0x217F, 0x02}, ++{0x2180, 0xD1}, ++{0x2181, 0x02}, ++{0x2182, 0x25}, ++{0x2183, 0x03}, ++{0x2184, 0x7F}, ++{0x2185, 0x00}, ++{0x2186, 0xBD}, ++{0x2187, 0x00}, ++{0x2188, 0xED}, ++{0x2189, 0x01}, ++{0x218A, 0x7B}, ++{0x218B, 0x02}, ++{0x218C, 0xD2}, ++{0x218D, 0x02}, ++{0x218E, 0x25}, ++{0x218F, 0x03}, ++{0x2190, 0xFF}, ++{0x2191, 0x03}, ++{0x2192, 0xFF}, ++{0x2193, 0x03}, ++{0x2194, 0xE9}, ++{0x2195, 0x01}, ++{0x2196, 0x21}, ++{0x2197, 0x03}, ++{0x2198, 0x17}, ++{0x2199, 0xFC}, ++{0x219A, 0x7F}, ++{0x219B, 0x01}, ++{0x219C, 0xFF}, ++{0x219D, 0x03}, ++{0x21A0, 0x1B}, ++{0x21A1, 0x1B}, ++{0x21A2, 0x1B}, ++{0x21A3, 0x1B}, ++{0x21A4, 0x2E}, ++{0x21A5, 0x80}, ++{0x21A6, 0x00}, ++{0x21A8, 0x04}, ++{0x21A9, 0x98}, ++{0x21AA, 0x60}, ++{0x21AB, 0x03}, ++{0x21AC, 0x7F}, ++{0x21AD, 0x80}, ++{0x21AE, 0x09}, ++{0x21B0, 0x1C}, ++{0x21B1, 0x00}, ++{0x21B2, 0xA0}, ++{0x21B3, 0x00}, ++{0x21B4, 0x0C}, ++{0x21B5, 0x00}, ++{0x21B6, 0x2D}, ++{0x21B7, 0x00}, ++{0x21B8, 0x20}, ++{0x21B9, 0x00}, ++{0x21BA, 0x02}, ++{0x21BB, 0x00}, ++{0x21BC, 0xCC}, ++{0x21BD, 0x00}, ++{0x21BE, 0x4A}, ++{0x21BF, 0x00}, ++{0x21C0, 0xD0}, ++{0x21C1, 0x00}, ++{0x21C2, 0x44}, ++{0x21C3, 0x00}, ++{0x21C4, 0x00}, ++{0x21C5, 0xE0}, ++{0x21C6, 0x00}, ++{0x21C8, 0x11}, ++{0x21C9, 0x00}, ++{0x21CA, 0x02}, ++{0x21CC, 0x08}, ++{0x21CD, 0xC0}, ++{0x21CE, 0x0C}, ++{0x21D0, 0x44}, ++{0x21D1, 0x00}, ++{0x21D2, 0x02}, ++{0x21D4, 0x02}, ++{0x21D5, 0x20}, ++{0x21D6, 0x2C}, ++{0x21D8, 0xFE}, ++{0x21D9, 0x9D}, ++{0x21DA, 0xDF}, ++{0x21DB, 0x03}, ++{0x21DC, 0x62}, ++{0x21DD, 0x01}, ++{0x21DE, 0x7F}, ++{0x21DF, 0x00}, ++{0x21E0, 0xB7}, ++{0x21E1, 0x01}, ++{0x21E2, 0xB5}, ++{0x21E3, 0x01}, ++{0x21E4, 0xC1}, ++{0x21E5, 0x02}, ++{0x21E6, 0xBF}, ++{0x21E7, 0x02}, ++{0x21E8, 0xB3}, ++{0x21E9, 0x0D}, ++{0x21EA, 0x00}, ++{0x21EB, 0x04}, ++#if 1 ++{0x21EC, 0x90}, ++{0x21ED, 0x07}, ++{0x21EE, 0x58}, ++{0x21EF, 0x04}, ++#else ++{0x21EC, 0x80}, ++{0x21ED, 0x07}, ++{0x21EE, 0x38}, ++{0x21EF, 0x04}, ++#endif ++{0x21F0, 0x54}, ++{0x21F1, 0x04}, ++{0x21F4, 0x02}, ++{0x21F5, 0x00}, ++{0x21F6, 0x00}, ++{0x21F8, 0x3C}, ++{0x21F9, 0x00}, ++{0x21FC, 0x28}, ++{0x21FD, 0x00}, ++{0x21FE, 0x3C}, ++{0x21FF, 0x00}, ++{0x2200, 0x00}, ++{0x2204, 0x4C}, ++{0x2205, 0x04}, ++{0x2206, 0x65}, ++{0x2207, 0x04}, ++{0x2208, 0x0A}, ++{0x2209, 0x00}, ++{0x220C, 0x47}, ++{0x220D, 0x00}, ++{0x220E, 0x1F}, ++{0x220F, 0x00}, ++{0x2210, 0x17}, ++{0x2211, 0x00}, ++{0x2212, 0x0F}, ++{0x2213, 0x00}, ++{0x2214, 0x17}, ++{0x2215, 0x00}, ++{0x2216, 0x47}, ++{0x2217, 0x00}, ++{0x2218, 0x0F}, ++{0x2219, 0x00}, ++{0x221A, 0x0F}, ++{0x221B, 0x00}, ++{0x221C, 0x03}, ++{0x2220, 0x20}, ++{0x2221, 0x20}, ++{0x2222, 0x22}, ++{0x2223, 0x02}, ++{0x2224, 0xA7}, ++{0x2225, 0xAA}, ++{0x2226, 0x80}, ++{0x2227, 0x08}, ++{0x2228, 0x01}, ++{0x22B2, 0x92}, ++{0x22B4, 0x20}, ++{0x22B5, 0x00}, ++{0x22B6, 0x20}, ++{0x22B7, 0x00}, ++{0x22B8, 0x20}, ++{0x22B9, 0x00}, ++{0x22BA, 0x20}, ++{0x22BB, 0x00}, ++{0x22BC, 0x20}, ++{0x22BD, 0x00}, ++{0x22BE, 0x20}, ++{0x22BF, 0x00}, ++{0x22C0, 0x20}, ++{0x22C1, 0x00}, ++{0x22C2, 0x20}, ++{0x22C3, 0x00}, ++{0x22C4, 0x20}, ++{0x22C5, 0x00}, ++{0x22C6, 0x20}, ++{0x22C7, 0x00}, ++{0x22C8, 0x20}, ++{0x22C9, 0x00}, ++{0x22CA, 0x20}, ++{0x22CB, 0x00}, ++{0x22CC, 0x20}, ++{0x22CD, 0x00}, ++{0x22CE, 0x20}, ++{0x22CF, 0x00}, ++{0x22DA, 0x00}, ++{0x2308, 0x01}, ++{0x2311, 0x09}, ++{0x2318, 0x40}, ++{0x2319, 0xCD}, ++{0x231A, 0x54}, ++{0x2324, 0x20}, ++{0x2325, 0x00}, ++{0x2328, 0x00}, ++{0x2354, 0x0C}, ++{0x23C0, 0x5D}, ++{0x244C, 0x00}, ++{0x244D, 0x02}, ++{0x244E, 0x54}, ++{0x244F, 0x02}, ++{0x24A0, 0x00}, ++{0x24DA, 0x6F}, ++{0x24DB, 0x00}, ++{0x24DC, 0x62}, ++{0x24DD, 0x01}, ++{0x24EA, 0x32}, ++{0x24EB, 0x00}, ++{0x24EC, 0xDC}, ++{0x24ED, 0x00}, ++{0x24FA, 0x32}, ++{0x24FB, 0x00}, ++{0x24FC, 0xDD}, ++{0x24FD, 0x00}, ++{0x254A, 0x15}, ++{0x254B, 0x01}, ++{0x255A, 0x15}, ++{0x255B, 0x01}, ++{0x2560, 0x01}, ++{0x2561, 0x00}, ++{0x2562, 0x2A}, ++{0x2563, 0x00}, ++{0x2564, 0xF8}, ++{0x2565, 0x00}, ++{0x2566, 0x15}, ++{0x2567, 0x01}, ++{0x2568, 0x0C}, ++{0x2569, 0x02}, ++{0x256A, 0x31}, ++{0x256B, 0x02}, ++{0x2578, 0x90}, ++{0x2579, 0x01}, ++{0x257A, 0x92}, ++{0x257B, 0x01}, ++{0x257C, 0xB8}, ++{0x257D, 0x02}, ++{0x257E, 0xBA}, ++{0x257F, 0x02}, ++{0x2584, 0x90}, ++{0x2585, 0x01}, ++{0x2586, 0x92}, ++{0x2587, 0x01}, ++{0x2588, 0xB8}, ++{0x2589, 0x02}, ++{0x258A, 0xBA}, ++{0x258B, 0x02}, ++{0x26B8, 0x10}, ++{0x26B9, 0x00}, ++{0x26BA, 0x33}, ++{0x26BB, 0x00}, ++{0x26BC, 0x89}, ++{0x26BD, 0x00}, ++{0x26BE, 0xB0}, ++{0x26BF, 0x00}, ++{0x26C4, 0x4E}, ++{0x26C5, 0x00}, ++{0x26C8, 0xC9}, ++{0x26C9, 0x00}, ++{0x26CC, 0x35}, ++{0x26CD, 0x01}, ++{0x26D0, 0xBA}, ++{0x26D1, 0x01}, ++{0x26D4, 0x7C}, ++{0x26D5, 0x02}, ++{0x26D8, 0xF6}, ++{0x26D9, 0x02}, ++{0x26DE, 0x51}, ++{0x26DF, 0x00}, ++{0x26E0, 0x7F}, ++{0x26E1, 0x00}, ++{0x26E2, 0xCC}, ++{0x26E3, 0x00}, ++{0x26E4, 0xF8}, ++{0x26E5, 0x00}, ++{0x26E6, 0x38}, ++{0x26E7, 0x01}, ++{0x26E8, 0x65}, ++{0x26E9, 0x01}, ++{0x26EA, 0xBD}, ++{0x26EB, 0x01}, ++{0x26EE, 0x7F}, ++{0x26EF, 0x02}, ++{0x26F0, 0xAB}, ++{0x26F1, 0x02}, ++{0x26F2, 0xF9}, ++{0x26F3, 0x02}, ++{0x2722, 0x59}, ++{0x2723, 0x02}, ++{0x2938, 0x55}, ++{0x2939, 0x00}, ++{0x293A, 0x17}, ++{0x293B, 0x00}, ++{0x293C, 0xD0}, ++{0x293D, 0x00}, ++{0x293E, 0x91}, ++{0x293F, 0x00}, ++{0x2940, 0x3C}, ++{0x2941, 0x01}, ++{0x2942, 0x0C}, ++{0x2943, 0x01}, ++{0x2944, 0xC1}, ++{0x2945, 0x01}, ++{0x2946, 0x76}, ++{0x2947, 0x01}, ++{0x2948, 0x83}, ++{0x2949, 0x02}, ++{0x294A, 0xFB}, ++{0x294B, 0x01}, ++{0x294C, 0xFD}, ++{0x294D, 0x02}, ++{0x294E, 0xBF}, ++{0x294F, 0x02}, ++{0x2A06, 0xFF}, ++{0x2A07, 0x03}, ++{0x2A20, 0x00}, ++{0x2A21, 0x00}, ++{0x2A22, 0x7D}, ++{0x2A23, 0x00}, ++{0x2B11, 0x19}, ++{0x2B13, 0x15}, ++{0x2B14, 0x14}, ++{0x2B15, 0x13}, ++{0x2B16, 0x12}, ++{0x2B17, 0x11}, ++{0x2B18, 0x10}, ++{0x2B19, 0x0F}, ++{0x2B1A, 0x0E}, ++{0x2B1B, 0x0D}, ++{0x2B1C, 0x0C}, ++{0x2B1D, 0x0B}, ++{0x2B1E, 0x0A}, ++{0x2B1F, 0x09}, ++{0x2B20, 0x08}, ++{0x2B21, 0x07}, ++{0x2B22, 0x06}, ++{0x2B23, 0x05}, ++{0x2B24, 0x04}, ++{0x2B25, 0x03}, ++{0x2B26, 0x03}, ++{0x2B38, 0x01}, ++{0x2B45, 0xE3}, ++{0x2B50, 0x01}, ++{0x2B51, 0x00}, ++//{0x2B62, ,3}, ++{0x2B6D, 0x47}, ++{0x2B70, 0x02}, ++{0x2B71, 0x02}, ++{0x2B72, 0x02}, ++{0x2B7F, 0x7F}, ++{0x2B80, 0x94}, ++{0x2B81, 0x06}, ++{0x2B87, 0x1B}, ++{0x2B88, 0x1B}, ++{0x2B89, 0x17}, ++{0x2B8A, 0x12}, ++{0x2B8B, 0x12}, ++{0x2B8D, 0x2B}, ++{0x2B8E, 0x2B}, ++{0x2B8F, 0x2B}, ++{0x2B90, 0x7F}, ++{0x2B91, 0x1F}, ++{0x2B94, 0x7F}, ++{0x2B95, 0x27}, ++{0x2B98, 0x7F}, ++{0x2B99, 0x57}, ++{0x2BA8, 0xBC}, ++{0x2BA9, 0x62}, ++{0x2BC1, 0x70}, ++{0x2BC5, 0x80}, ++{0x2BD5, 0x30}, ++{0x2BD6, 0xF0}, ++{0x2BD8, 0xDB}, ++{0x2BD9, 0xF6}, ++{0x2BDA, 0x63}, ++{0x2BDB, 0x0C}, ++{0x2BDC, 0x5C}, ++{0x2C98, 0xE1}, ++{0x2C99, 0x2E}, ++{0x2C9B, 0x86}, ++{0x2CA9, 0x80}, ++{0x2CAA, 0x01}, ++{0x2D39, 0x0E}, ++{0x2D54, 0x00}, ++{0x2D5B, 0x58}, ++{0x3000, 0x00}, ++{0x3001, 0x40}, ++{0x3002, 0x23}, ++{0x3003, 0xA1}, ++{0x3004, 0x00}, ++{0x3005, 0x20}, ++{0x3006, 0x94}, ++{0x3007, 0x00}, ++{0x3008, 0x06}, ++{0x3009, 0xB4}, ++{0x300A, 0x1F}, ++{0x300B, 0x28}, ++{0x300C, 0x00}, ++{0x300D, 0x18}, ++{0x300E, 0x90}, ++{0x300F, 0x97}, ++{0x3010, 0x00}, ++{0x3011, 0x40}, ++{0x3012, 0x21}, ++{0x3013, 0x21}, ++{0x3014, 0x00}, ++{0x3015, 0x20}, ++{0x3016, 0x94}, ++{0x3017, 0x00}, ++{0x3018, 0x00}, ++{0x3019, 0x09}, ++{0x301A, 0x46}, ++{0x301B, 0x28}, ++//{0x3053, ,3}, ++{0x3070, 0xC1}, ++{0x3071, 0x81}, ++{0x3072, 0x29}, ++{0x3073, 0x81}, ++//{0x3370, ,3}, ++//{0x3374, ,3}, ++//{0x3375, ,3}, ++//{0x3376, ,3}, ++//{0x3377, ,3}, ++#if 1 ++{0x3410, 0x90}, ++{0x3411, 0x07}, ++{0x3418, 0x48}, ++{0x3419, 0x04}, ++#else ++{0x3410, 0x80}, ++{0x3411, 0x07}, ++{0x3418, 0x38}, ++{0x3419, 0x04}, ++#endif ++//{0x34C0, ,3}, ++//{0x34C1, ,3}, ++//{0x34C2, ,3}, ++//{0x34C3, ,3}, ++//{0x34C4, ,3}, ++//{0x34C5, ,3}, ++//{0x34C6, ,3}, ++//{0x34C7, ,3}, ++//{0x34C8, ,3}, ++//{0x34C9, ,3}, ++//{0x34CA, ,3}, ++//{0x34CB, ,3}, ++//{0x34CC, ,3}, ++//{0x34CD, ,3}, ++//{0x34CE, ,3}, ++//{0x34CF, ,3}, ++{0x3584, 0x00}, ++{0x3586, 0x00}, ++{0x3587, 0x01}, ++{0x3588, 0xE6}, ++{0x3589, 0x00}, ++{0x3590, 0x00}, ++{0x3591, 0x00}, ++{0x3594, 0x40}, ++{0x3598, 0x03}, ++{0x3599, 0x00}, ++{0x359A, 0x80}, ++{0x359B, 0x00}, ++{0x359C, 0x00}, ++{0x359D, 0x01}, ++{0x359E, 0x00}, ++{0x359F, 0x02}, ++{0x35A0, 0x00}, ++{0x35A1, 0x04}, ++{0x35A2, 0x20}, ++{0x35A3, 0x00}, ++{0x35A4, 0x40}, ++{0x35A5, 0x00}, ++{0x35A6, 0x80}, ++{0x35A7, 0x00}, ++{0x35A8, 0x00}, ++{0x35A9, 0x01}, ++{0x35AA, 0x3A}, ++{0x35AB, 0x00}, ++{0x35AC, 0x80}, ++{0x35AD, 0x00}, ++{0x35AE, 0x00}, ++{0x35AF, 0x01}, ++{0x35B0, 0x00}, ++{0x35B1, 0x02}, ++{0x35B2, 0x00}, ++{0x35B3, 0x04}, ++{0x35B4, 0x02}, ++{0x35B5, 0x00}, ++{0x35B6, 0x04}, ++{0x35B7, 0x00}, ++{0x35B8, 0x08}, ++{0x35B9, 0x00}, ++{0x35BA, 0x10}, ++{0x35BB, 0x00}, ++{0x35BC, 0x03}, ++{0x35BD, 0x00}, ++{0x35C8, 0x00}, ++{0x35C9, 0x01}, ++{0x35CA, 0x00}, ++{0x35CB, 0x04}, ++{0x35CC, 0x00}, ++{0x35CD, 0x10}, ++{0x35CE, 0x00}, ++{0x35CF, 0x40}, ++{0x35D0, 0x00}, ++{0x35D1, 0x0C}, ++{0x35D2, 0x00}, ++{0x35D3, 0x0C}, ++{0x35D4, 0x00}, ++{0x35D5, 0x0C}, ++{0x35D6, 0x00}, ++{0x35D7, 0x0C}, ++{0x35D8, 0x00}, ++{0x35D9, 0x00}, ++{0x35DA, 0x08}, ++{0x35DB, 0x00}, ++{0x35DC, 0xD8}, ++{0x35DD, 0x0E}, ++{0x35F0, 0x00}, ++{0x35F1, 0x10}, ++{0x35F2, 0x00}, ++{0x35F3, 0x10}, ++{0x35F4, 0x00}, ++{0x35F5, 0x10}, ++{0x35F6, 0x00}, ++{0x35F7, 0x03}, ++{0x35F8, 0x00}, ++{0x35F9, 0x01}, ++{0x35FA, 0x38}, ++{0x35FB, 0x00}, ++{0x35FC, 0xB3}, ++{0x35FD, 0x01}, ++{0x35FE, 0x00}, ++{0x35FF, 0x00}, ++{0x3600, 0x04}, ++{0x3601, 0x06}, ++{0x3604, 0x03}, ++{0x3605, 0x00}, ++{0x3608, 0x03}, ++{0x3609, 0x00}, ++{0x360C, 0x00}, ++{0x360D, 0x00}, ++{0x3610, 0x10}, ++{0x3611, 0x01}, ++{0x3612, 0x00}, ++{0x3613, 0x00}, ++{0x3614, 0x00}, ++{0x3615, 0x00}, ++{0x361C, 0x00}, ++{0x361D, 0x01}, ++{0x361E, 0x00}, ++{0x361F, 0x01}, ++{0x3620, 0x01}, ++{0x3621, 0x00}, ++{0x3622, 0xB0}, ++{0x3623, 0x04}, ++{0x3624, 0xDC}, ++{0x3625, 0x05}, ++{0x3626, 0x00}, ++{0x3627, 0x01}, ++{0x3628, 0xFF}, ++{0x3629, 0x0F}, ++{0x362A, 0x00}, ++{0x362B, 0x10}, ++{0x362C, 0x00}, ++{0x362D, 0x01}, ++//{0x3630, ,3}, ++//{0x3631, ,3}, ++//{0x3632, ,3}, ++//{0x3633, ,3}, ++//{0x3634, ,3}, ++//{0x3635, ,3}, ++//{0x3636, ,3}, ++//{0x3637, ,3}, ++//{0x3638, ,3}, ++//{0x3639, ,3}, ++//{0x363A, ,3}, ++//{0x363B, ,3}, ++//{0x363C, ,3}, ++//{0x363D, ,3}, ++//{0x363E, ,3}, ++//{0x363F, ,3}, ++{0x36C4, 0x99}, ++{0x36C5, 0x09}, ++{0x36C6, 0x18}, ++{0x36C7, 0x07}, ++{0x36C8, 0x65}, ++{0x36C9, 0x0E}, ++{0x36CC, 0x99}, ++{0x36CD, 0x01}, ++{0x36CE, 0x47}, ++{0x36CF, 0x00}, ++{0x36D0, 0x04}, ++{0x36D1, 0x00}, ++{0x36D4, 0x65}, ++{0x36D5, 0x0E}, ++{0x36D6, 0xA4}, ++{0x36D7, 0x0A}, ++{0x36D8, 0x65}, ++{0x36D9, 0x0E}, ++{0x36DC, 0x65}, ++{0x36DD, 0x0E}, ++{0x36DE, 0xA4}, ++{0x36DF, 0x0A}, ++{0x36E0, 0x65}, ++{0x36E1, 0x0E}, ++{0x36E4, 0x65}, ++{0x36E5, 0x0E}, ++{0x36E6, 0xA4}, ++{0x36E7, 0x0A}, ++{0x36E8, 0x65}, ++{0x36E9, 0x0E}, ++{0x36EE, 0x00}, ++{0x36EF, 0x00}, ++{0x36F0, 0x00}, ++{0x36F1, 0x80}, ++{0x36F8, 0x00}, ++{0x3702, 0x03}, ++{0x3703, 0x04}, ++{0x3704, 0x08}, ++{0x370E, 0x0E}, ++{0x3718, 0x62}, ++{0x3719, 0x4A}, ++{0x371A, 0x38}, ++{0x371B, 0x20}, ++{0x371C, 0x64}, ++{0x371D, 0x42}, ++{0x371E, 0x32}, ++{0x371F, 0x1B}, ++{0x3720, 0x98}, ++{0x3721, 0xA0}, ++{0x3722, 0xA8}, ++{0x3723, 0xB0}, ++{0x3748, 0xA5}, ++{0x3749, 0x9B}, ++{0x374A, 0x91}, ++{0x374B, 0x7D}, ++{0x37C0, 0x00}, ++{0x37C1, 0x00}, ++{0x37C2, 0x00}, ++{0x37C4, 0x00}, ++{0x37C5, 0x00}, ++{0x37C6, 0x00}, ++{0x37C8, 0x00}, ++{0x37C9, 0x00}, ++{0x37CA, 0x00}, ++{0x37CC, 0x00}, ++{0x37CD, 0x00}, ++{0x37CE, 0x00}, ++{0x37D0, 0x00}, ++{0x37D1, 0x00}, ++{0x37D2, 0x00}, ++{0x37D4, 0x00}, ++{0x37D5, 0x00}, ++{0x37D6, 0x00}, ++{0x37D8, 0x00}, ++{0x37D9, 0x00}, ++{0x37DA, 0x00}, ++{0x37DC, 0x00}, ++{0x37DD, 0x00}, ++{0x37DE, 0x00}, ++{0x37E0, 0x00}, ++{0x37E1, 0x00}, ++{0x37E2, 0x00}, ++{0x37E4, 0x00}, ++{0x37E5, 0x00}, ++{0x37E6, 0x00}, ++{0x37E8, 0x00}, ++{0x37E9, 0x00}, ++{0x37EA, 0x00}, ++{0x37EC, 0x00}, ++{0x37ED, 0x00}, ++{0x37EE, 0x00}, ++{0x37F0, 0x00}, ++{0x37F4, 0x00}, ++{0x37F5, 0x1E}, ++{0x37F6, 0x34}, ++{0x37F7, 0x00}, ++{0x37F8, 0xFF}, ++{0x37F9, 0xFF}, ++{0x37FA, 0x03}, ++{0x37FC, 0x00}, ++{0x37FD, 0x00}, ++{0x37FE, 0x04}, ++{0x3800, 0xFF}, ++{0x3801, 0xFF}, ++{0x3802, 0x03}, ++{0x3804, 0x00}, ++{0x3805, 0x00}, ++{0x3806, 0x04}, ++{0x3808, 0x00}, ++{0x3809, 0x00}, ++{0x380A, 0x00}, ++{0x380C, 0x00}, ++{0x380D, 0x00}, ++{0x380E, 0x00}, ++{0x3810, 0x00}, ++{0x3811, 0x00}, ++{0x3812, 0x00}, ++{0x3814, 0x00}, ++{0x3815, 0x00}, ++{0x3816, 0x00}, ++{0x3818, 0x00}, ++{0x3819, 0x00}, ++{0x381A, 0x00}, ++{0x381C, 0x00}, ++{0x381D, 0x00}, ++{0x381E, 0x00}, ++{0x3820, 0x00}, ++{0x3821, 0x00}, ++{0x3822, 0x00}, ++{0x3824, 0x00}, ++{0x3825, 0x00}, ++{0x3826, 0x00}, ++{0x3828, 0x00}, ++{0x3829, 0x00}, ++{0x382A, 0x00}, ++{0x382C, 0x00}, ++{0x382D, 0x00}, ++{0x382E, 0x00}, ++{0x3830, 0x00}, ++{0x3831, 0x00}, ++{0x3832, 0x00}, ++{0x3834, 0x00}, ++{0x3835, 0x00}, ++{0x3836, 0x00}, ++{0x3838, 0x22}, ++{0x3839, 0x00}, ++{0x383A, 0x25}, ++{0x383B, 0x00}, ++{0x383C, 0x1A}, ++{0x383D, 0x00}, ++{0x383E, 0x26}, ++{0x383F, 0x00}, ++{0x3840, 0x07}, ++{0x3841, 0x00}, ++{0x3842, 0x06}, ++{0x3843, 0x00}, ++{0x3844, 0x03}, ++{0x3845, 0x00}, ++{0x3846, 0x02}, ++{0x3847, 0x00}, ++{0x3848, 0xFB}, ++{0x3849, 0xFF}, ++{0x384A, 0xFF}, ++{0x384B, 0xFF}, ++{0x384C, 0xF3}, ++{0x384D, 0xFF}, ++{0x384E, 0xF2}, ++{0x384F, 0xFF}, ++{0x3850, 0xFF}, ++{0x3851, 0x0F}, ++{0x3852, 0x00}, ++{0x3853, 0x10}, ++{0x3854, 0xFF}, ++{0x3855, 0x0F}, ++{0x3856, 0x00}, ++{0x3857, 0x10}, ++{0x3858, 0xFF}, ++{0x3859, 0x0F}, ++{0x385A, 0x00}, ++{0x385B, 0x10}, ++{0x385C, 0x02}, ++{0x385D, 0x00}, ++{0x385E, 0x06}, ++{0x385F, 0x00}, ++{0x3860, 0x06}, ++{0x3861, 0x00}, ++{0x3862, 0x08}, ++{0x3863, 0x00}, ++{0x3864, 0x02}, ++{0x3865, 0x00}, ++{0x38A0, 0x01}, ++{0x38A1, 0x01}, ++{0x38A2, 0x00}, ++{0x38A3, 0x01}, ++{0x38A4, 0x07}, ++{0x38A5, 0x00}, ++{0x38A6, 0x04}, ++{0x38A7, 0x05}, ++{0x38A8, 0x00}, ++{0x38A9, 0x00}, ++{0x38AC, 0x00}, ++{0x38AD, 0x00}, ++{0x38AE, 0x01}, ++{0x38B0, 0x02}, ++{0x38B2, 0x22}, ++{0x38B3, 0x00}, ++{0x38B4, 0x17}, ++{0x38B5, 0x00}, ++{0x38B6, 0x11}, ++{0x38B7, 0x00}, ++{0x38B8, 0x0E}, ++{0x38B9, 0x00}, ++{0x38BA, 0x2A}, ++{0x38BB, 0x00}, ++{0x38BC, 0x1C}, ++{0x38BD, 0x00}, ++{0x38BE, 0x14}, ++{0x38BF, 0x00}, ++{0x38C0, 0x10}, ++{0x38C1, 0x00}, ++{0x38C2, 0x31}, ++{0x38C3, 0x00}, ++{0x38C4, 0x21}, ++{0x38C5, 0x00}, ++{0x38C6, 0x18}, ++{0x38C7, 0x00}, ++{0x38C8, 0x12}, ++{0x38C9, 0x00}, ++{0x38CA, 0x3C}, ++{0x38CB, 0x00}, ++{0x38CC, 0x29}, ++{0x38CD, 0x00}, ++{0x38CE, 0x1D}, ++{0x38CF, 0x00}, ++{0x38D0, 0x15}, ++{0x38D1, 0x00}, ++{0x38D2, 0x4E}, ++{0x38D3, 0x00}, ++{0x38D4, 0x35}, ++{0x38D5, 0x00}, ++{0x38D6, 0x26}, ++{0x38D7, 0x00}, ++{0x38D8, 0x1A}, ++{0x38D9, 0x00}, ++{0x38DA, 0x69}, ++{0x38DB, 0x00}, ++{0x38DC, 0x48}, ++{0x38DD, 0x00}, ++{0x38DE, 0x33}, ++{0x38DF, 0x00}, ++{0x38E0, 0x22}, ++{0x38E1, 0x00}, ++{0x38E2, 0x93}, ++{0x38E3, 0x00}, ++{0x38E4, 0x64}, ++{0x38E5, 0x00}, ++{0x38E6, 0x48}, ++{0x38E7, 0x00}, ++{0x38E8, 0x30}, ++{0x38E9, 0x00}, ++{0x38EA, 0xD3}, ++{0x38EB, 0x00}, ++{0x38EC, 0x90}, ++{0x38ED, 0x00}, ++{0x38EE, 0x69}, ++{0x38EF, 0x00}, ++{0x38F0, 0x49}, ++{0x38F1, 0x00}, ++{0x38F2, 0x39}, ++{0x38F3, 0x01}, ++{0x38F4, 0xD5}, ++{0x38F5, 0x00}, ++{0x38F6, 0x9F}, ++{0x38F7, 0x00}, ++{0x38F8, 0x75}, ++{0x38F9, 0x00}, ++{0x38FA, 0x00}, ++{0x38FB, 0x01}, ++{0x38FC, 0x00}, ++{0x38FD, 0x01}, ++{0x38FE, 0x00}, ++{0x38FF, 0x01}, ++{0x3900, 0x00}, ++{0x3901, 0x01}, ++{0x3902, 0x60}, ++{0x3903, 0x00}, ++{0x3904, 0x25}, ++{0x3905, 0x00}, ++{0x3906, 0x18}, ++{0x3907, 0x00}, ++{0x3908, 0x10}, ++{0x3909, 0x00}, ++{0x390A, 0xFF}, ++{0x390B, 0x00}, ++{0x390C, 0xD5}, ++{0x390D, 0x00}, ++{0x390E, 0xAA}, ++{0x390F, 0x00}, ++{0x3910, 0x85}, ++{0x3911, 0x00}, ++{0x3912, 0xFF}, ++{0x3913, 0x00}, ++{0x3914, 0xD5}, ++{0x3915, 0x00}, ++{0x3916, 0xAA}, ++{0x3917, 0x00}, ++{0x3918, 0x85}, ++{0x3919, 0x00}, ++{0x391A, 0xFF}, ++{0x391B, 0x00}, ++{0x391C, 0xD5}, ++{0x391D, 0x00}, ++{0x391E, 0xAA}, ++{0x391F, 0x00}, ++{0x3920, 0x85}, ++{0x3921, 0x00}, ++{0x3922, 0x40}, ++{0x3923, 0x00}, ++{0x3924, 0x40}, ++{0x3925, 0x00}, ++{0x3926, 0x40}, ++{0x3927, 0x00}, ++{0x3928, 0x40}, ++{0x3929, 0x00}, ++{0x392A, 0x80}, ++{0x392B, 0x00}, ++{0x392C, 0x80}, ++{0x392D, 0x00}, ++{0x392E, 0x80}, ++{0x392F, 0x00}, ++{0x3930, 0x80}, ++{0x3931, 0x00}, ++{0x3932, 0x4C}, ++{0x3933, 0x4C}, ++{0x3934, 0x4C}, ++{0x3940, 0x01}, ++{0x3941, 0x01}, ++{0x3942, 0x00}, ++{0x3943, 0x01}, ++{0x3944, 0x07}, ++{0x3945, 0x00}, ++{0x3946, 0x04}, ++{0x3947, 0x05}, ++{0x3948, 0x00}, ++{0x3949, 0x00}, ++{0x394C, 0x00}, ++{0x394D, 0x00}, ++{0x394E, 0x01}, ++{0x3950, 0x03}, ++{0x3952, 0x14}, ++{0x3953, 0x00}, ++{0x3954, 0x0F}, ++{0x3955, 0x00}, ++{0x3956, 0x0E}, ++{0x3957, 0x00}, ++{0x3958, 0x0E}, ++{0x3959, 0x00}, ++{0x395A, 0x19}, ++{0x395B, 0x00}, ++{0x395C, 0x11}, ++{0x395D, 0x00}, ++{0x395E, 0x0F}, ++{0x395F, 0x00}, ++{0x3960, 0x0E}, ++{0x3961, 0x00}, ++{0x3962, 0x1C}, ++{0x3963, 0x00}, ++{0x3964, 0x13}, ++{0x3965, 0x00}, ++{0x3966, 0x0F}, ++{0x3967, 0x00}, ++{0x3968, 0x0E}, ++{0x3969, 0x00}, ++{0x396A, 0x23}, ++{0x396B, 0x00}, ++{0x396C, 0x15}, ++{0x396D, 0x00}, ++{0x396E, 0x11}, ++{0x396F, 0x00}, ++{0x3970, 0x0E}, ++{0x3971, 0x00}, ++{0x3972, 0x2E}, ++{0x3973, 0x00}, ++{0x3974, 0x1A}, ++{0x3975, 0x00}, ++{0x3976, 0x14}, ++{0x3977, 0x00}, ++{0x3978, 0x0F}, ++{0x3979, 0x00}, ++{0x397A, 0x3E}, ++{0x397B, 0x00}, ++{0x397C, 0x23}, ++{0x397D, 0x00}, ++{0x397E, 0x1A}, ++{0x397F, 0x00}, ++{0x3980, 0x12}, ++{0x3981, 0x00}, ++{0x3982, 0x56}, ++{0x3983, 0x00}, ++{0x3984, 0x31}, ++{0x3985, 0x00}, ++{0x3986, 0x25}, ++{0x3987, 0x00}, ++{0x3988, 0x1A}, ++{0x3989, 0x00}, ++{0x398A, 0x7B}, ++{0x398B, 0x00}, ++{0x398C, 0x49}, ++{0x398D, 0x00}, ++{0x398E, 0x39}, ++{0x398F, 0x00}, ++{0x3990, 0x2C}, ++{0x3991, 0x00}, ++{0x3992, 0xB4}, ++{0x3993, 0x00}, ++{0x3994, 0x75}, ++{0x3995, 0x00}, ++{0x3996, 0x61}, ++{0x3997, 0x00}, ++{0x3998, 0x53}, ++{0x3999, 0x00}, ++{0x399A, 0x00}, ++{0x399B, 0x01}, ++{0x399C, 0x00}, ++{0x399D, 0x01}, ++{0x399E, 0x00}, ++{0x399F, 0x01}, ++{0x39A0, 0x00}, ++{0x39A1, 0x01}, ++{0x39A2, 0x60}, ++{0x39A3, 0x00}, ++{0x39A4, 0x20}, ++{0x39A5, 0x00}, ++{0x39A6, 0x15}, ++{0x39A7, 0x00}, ++{0x39A8, 0x10}, ++{0x39A9, 0x00}, ++{0x39AA, 0xFF}, ++{0x39AB, 0x00}, ++{0x39AC, 0xD5}, ++{0x39AD, 0x00}, ++{0x39AE, 0xAA}, ++{0x39AF, 0x00}, ++{0x39B0, 0x85}, ++{0x39B1, 0x00}, ++{0x39B2, 0xFF}, ++{0x39B3, 0x00}, ++{0x39B4, 0xD5}, ++{0x39B5, 0x00}, ++{0x39B6, 0xAA}, ++{0x39B7, 0x00}, ++{0x39B8, 0x85}, ++{0x39B9, 0x00}, ++{0x39BA, 0xFF}, ++{0x39BB, 0x00}, ++{0x39BC, 0xD5}, ++{0x39BD, 0x00}, ++{0x39BE, 0xAA}, ++{0x39BF, 0x00}, ++{0x39C0, 0x85}, ++{0x39C1, 0x00}, ++{0x39C2, 0x40}, ++{0x39C3, 0x00}, ++{0x39C4, 0x40}, ++{0x39C5, 0x00}, ++{0x39C6, 0x40}, ++{0x39C7, 0x00}, ++{0x39C8, 0x40}, ++{0x39C9, 0x00}, ++{0x39CA, 0x80}, ++{0x39CB, 0x00}, ++{0x39CC, 0x80}, ++{0x39CD, 0x00}, ++{0x39CE, 0x80}, ++{0x39CF, 0x00}, ++{0x39D0, 0x80}, ++{0x39D1, 0x00}, ++{0x39D2, 0x4C}, ++{0x39D3, 0x4C}, ++{0x39D4, 0x4C}, ++{0x39E0, 0x01}, ++{0x39E1, 0x00}, ++{0x39E4, 0x40}, ++{0x39E5, 0x01}, ++{0x39E6, 0x01}, ++{0x39E8, 0x00}, ++{0x39E9, 0x01}, ++{0x39EA, 0x00}, ++{0x39EB, 0x00}, ++{0x39EC, 0x01}, ++{0x39ED, 0x00}, ++{0x39EE, 0x01}, ++{0x39F0, 0x03}, ++{0x39F1, 0x04}, ++{0x39F2, 0x0E}, ++{0x39F4, 0x1C}, ++{0x39F5, 0x00}, ++{0x39F6, 0x13}, ++{0x39F7, 0x00}, ++{0x39F8, 0x0D}, ++{0x39F9, 0x00}, ++{0x39FA, 0x07}, ++{0x39FB, 0x00}, ++{0x39FC, 0x38}, ++{0x39FD, 0x00}, ++{0x39FE, 0x1C}, ++{0x39FF, 0x00}, ++{0x3A00, 0x11}, ++{0x3A01, 0x00}, ++{0x3A02, 0x08}, ++{0x3A03, 0x00}, ++{0x3A04, 0x4A}, ++{0x3A05, 0x00}, ++{0x3A06, 0x23}, ++{0x3A07, 0x00}, ++{0x3A08, 0x15}, ++{0x3A09, 0x00}, ++{0x3A0A, 0x09}, ++{0x3A0B, 0x00}, ++{0x3A0C, 0x65}, ++{0x3A0D, 0x00}, ++{0x3A0E, 0x2D}, ++{0x3A0F, 0x00}, ++{0x3A10, 0x1A}, ++{0x3A11, 0x00}, ++{0x3A12, 0x0B}, ++{0x3A13, 0x00}, ++{0x3A14, 0x8D}, ++{0x3A15, 0x00}, ++{0x3A16, 0x3D}, ++{0x3A17, 0x00}, ++{0x3A18, 0x23}, ++{0x3A19, 0x00}, ++{0x3A1A, 0x0E}, ++{0x3A1B, 0x00}, ++{0x3A1C, 0xC5}, ++{0x3A1D, 0x00}, ++{0x3A1E, 0x55}, ++{0x3A1F, 0x00}, ++{0x3A20, 0x30}, ++{0x3A21, 0x00}, ++{0x3A22, 0x13}, ++{0x3A23, 0x00}, ++{0x3A24, 0x16}, ++{0x3A25, 0x01}, ++{0x3A26, 0x76}, ++{0x3A27, 0x00}, ++{0x3A28, 0x42}, ++{0x3A29, 0x00}, ++{0x3A2A, 0x1A}, ++{0x3A2B, 0x00}, ++{0x3A2C, 0x88}, ++{0x3A2D, 0x01}, ++{0x3A2E, 0xA7}, ++{0x3A2F, 0x00}, ++{0x3A30, 0x5D}, ++{0x3A31, 0x00}, ++{0x3A32, 0x24}, ++{0x3A33, 0x00}, ++{0x3A34, 0x2A}, ++{0x3A35, 0x02}, ++{0x3A36, 0xEB}, ++{0x3A37, 0x00}, ++{0x3A38, 0x83}, ++{0x3A39, 0x00}, ++{0x3A3A, 0x32}, ++{0x3A3B, 0x00}, ++{0x3A3C, 0x00}, ++{0x3A3D, 0x01}, ++{0x3A3E, 0x00}, ++{0x3A3F, 0x01}, ++{0x3A40, 0x00}, ++{0x3A41, 0x01}, ++{0x3A42, 0x00}, ++{0x3A43, 0x01}, ++{0x3A44, 0x70}, ++{0x3A45, 0x00}, ++{0x3A46, 0x25}, ++{0x3A47, 0x00}, ++{0x3A48, 0x18}, ++{0x3A49, 0x00}, ++{0x3A4A, 0x10}, ++{0x3A4B, 0x00}, ++{0x3A4C, 0xFF}, ++{0x3A4D, 0x00}, ++{0x3A4E, 0xD5}, ++{0x3A4F, 0x00}, ++{0x3A50, 0xAA}, ++{0x3A51, 0x00}, ++{0x3A52, 0x85}, ++{0x3A53, 0x00}, ++{0x3A54, 0xFF}, ++{0x3A55, 0x00}, ++{0x3A56, 0xD5}, ++{0x3A57, 0x00}, ++{0x3A58, 0xAA}, ++{0x3A59, 0x00}, ++{0x3A5A, 0x85}, ++{0x3A5B, 0x00}, ++{0x3A5C, 0xFF}, ++{0x3A5D, 0x00}, ++{0x3A5E, 0xD5}, ++{0x3A5F, 0x00}, ++{0x3A60, 0xAA}, ++{0x3A61, 0x00}, ++{0x3A62, 0x85}, ++{0x3A63, 0x00}, ++{0x3A64, 0x1C}, ++{0x3A65, 0x00}, ++{0x3A66, 0x13}, ++{0x3A67, 0x00}, ++{0x3A68, 0x0D}, ++{0x3A69, 0x00}, ++{0x3A6A, 0x07}, ++{0x3A6B, 0x00}, ++{0x3A6C, 0x0D}, ++{0x3A6D, 0x00}, ++{0x3A6E, 0x0B}, ++{0x3A6F, 0x00}, ++{0x3A70, 0x06}, ++{0x3A71, 0x00}, ++{0x3A72, 0x05}, ++{0x3A73, 0x00}, ++{0x3A74, 0x19}, ++{0x3A75, 0x00}, ++{0x3A76, 0x14}, ++{0x3A77, 0x00}, ++{0x3A78, 0x0F}, ++{0x3A79, 0x00}, ++{0x3A7A, 0x0A}, ++{0x3A7B, 0x00}, ++{0x3A7C, 0x80}, ++{0x3A7D, 0x00}, ++{0x3A7E, 0x80}, ++{0x3A7F, 0x00}, ++{0x3A80, 0x80}, ++{0x3A81, 0x00}, ++{0x3A82, 0x80}, ++{0x3A83, 0x00}, ++{0x3A84, 0x08}, ++{0x3A85, 0x00}, ++{0x3A86, 0x05}, ++{0x3A87, 0x00}, ++{0x3A88, 0x04}, ++{0x3A89, 0x00}, ++{0x3A8A, 0x03}, ++{0x3A8B, 0x00}, ++{0x3A8C, 0xCD}, ++{0x3A8D, 0x00}, ++{0x3A8E, 0xAA}, ++{0x3A8F, 0x00}, ++{0x3A90, 0x8C}, ++{0x3A91, 0x00}, ++{0x3A92, 0x64}, ++{0x3A93, 0x00}, ++{0x3A94, 0xCD}, ++{0x3A95, 0x00}, ++{0x3A96, 0xAA}, ++{0x3A97, 0x00}, ++{0x3A98, 0x8C}, ++{0x3A99, 0x00}, ++{0x3A9A, 0x64}, ++{0x3A9B, 0x00}, ++{0x3A9C, 0x08}, ++{0x3A9D, 0x10}, ++{0x3A9E, 0x4C}, ++{0x3A9F, 0x4C}, ++{0x3AA0, 0x4C}, ++{0x3AA1, 0x04}, ++{0x3AA2, 0x05}, ++{0x3AC0, 0x01}, ++{0x3AC4, 0x81}, ++{0x3AC5, 0x00}, ++{0x3AC6, 0x00}, ++{0x3AC7, 0x00}, ++{0x3AC8, 0x00}, ++{0x3AC9, 0x00}, ++{0x3ACA, 0x00}, ++{0x3ACB, 0x00}, ++{0x3ACC, 0x02}, ++{0x3ACD, 0x00}, ++{0x3ACE, 0x81}, ++{0x3ACF, 0x00}, ++{0x3AD0, 0x00}, ++{0x3AD1, 0x00}, ++{0x3AD2, 0xFD}, ++{0x3AD3, 0x03}, ++{0x3AD4, 0x02}, ++{0x3AD5, 0x00}, ++{0x3AD6, 0x00}, ++{0x3AD7, 0x00}, ++{0x3AD8, 0x81}, ++{0x3AD9, 0x00}, ++{0x3ADA, 0xFD}, ++{0x3ADB, 0x03}, ++{0x3ADC, 0xFF}, ++{0x3ADD, 0x03}, ++{0x3ADE, 0x01}, ++{0x3ADF, 0x00}, ++{0x3AE0, 0x01}, ++{0x3AE1, 0x00}, ++{0x3AE2, 0x7E}, ++{0x3AE3, 0x00}, ++{0x3AF4, 0x00}, ++{0x3AF6, 0x40}, ++{0x3AF7, 0x1E}, ++{0x3AF8, 0x01}, ++{0x3AFA, 0x63}, ++{0x3AFB, 0x09}, ++{0x3AFC, 0x11}, ++{0x3AFD, 0x09}, ++{0x3AFE, 0x00}, ++{0x3AFF, 0x00}, ++{0x3B00, 0x00}, ++{0x3B01, 0x00}, ++{0x3B02, 0x84}, ++{0x3B03, 0x06}, ++{0x3B04, 0x30}, ++{0x3B05, 0x06}, ++{0x3B06, 0x00}, ++{0x3B07, 0x00}, ++{0x3B08, 0x00}, ++{0x3B09, 0x00}, ++{0x3B0A, 0x00}, ++{0x3B0B, 0x00}, ++{0x3B0C, 0x00}, ++{0x3B0D, 0x00}, ++{0x3B0E, 0x00}, ++{0x3B0F, 0x00}, ++{0x3B10, 0x00}, ++{0x3B11, 0x00}, ++{0x3B12, 0x00}, ++{0x3B13, 0x00}, ++{0x3B14, 0x00}, ++{0x3B15, 0x00}, ++{0x3B16, 0x00}, ++{0x3B17, 0x00}, ++{0x3B18, 0x00}, ++{0x3B19, 0x00}, ++{0x3B1A, 0x00}, ++{0x3B1B, 0x00}, ++{0x3B1C, 0x00}, ++{0x3B1D, 0x00}, ++{0x3B1E, 0x00}, ++{0x3B1F, 0x00}, ++{0x3B20, 0x00}, ++{0x3B21, 0x00}, ++{0x3B22, 0x00}, ++{0x3B23, 0x00}, ++{0x3B24, 0x00}, ++{0x3B25, 0x00}, ++{0x3B26, 0x00}, ++{0x3B27, 0x00}, ++{0x3B28, 0x00}, ++{0x3B29, 0x00}, ++{0x3B2A, 0x00}, ++{0x3B2C, 0x00}, ++{0x3B2E, 0x00}, ++{0x3B30, 0x00}, ++{0x3B32, 0x0C}, ++{0x4000, 0xD1}, ++{0x4001, 0xC0}, ++{0x4002, 0xC0}, ++{0x4003, 0xB8}, ++{0x4004, 0xC0}, ++{0x4005, 0xB8}, ++{0x4006, 0xB9}, ++{0x4007, 0xB7}, ++{0x4008, 0xB0}, ++{0x4009, 0xAB}, ++{0x400A, 0xAC}, ++{0x400B, 0xAB}, ++{0x400C, 0xA8}, ++{0x400D, 0xA6}, ++{0x400E, 0xA6}, ++{0x400F, 0xA5}, ++{0x4010, 0xA2}, ++{0x4011, 0xA0}, ++{0x4012, 0xA0}, ++{0x4013, 0x9F}, ++{0x4014, 0xA4}, ++{0x4015, 0xA2}, ++{0x4016, 0xA2}, ++{0x4017, 0x9C}, ++{0x4018, 0xA8}, ++{0x4019, 0xA6}, ++{0x401A, 0xA8}, ++{0x401B, 0xAA}, ++{0x401C, 0xB0}, ++{0x401D, 0xAE}, ++{0x401E, 0xAE}, ++{0x401F, 0xAE}, ++{0x4020, 0xBA}, ++{0x4021, 0xAE}, ++{0x4022, 0xAF}, ++{0x4023, 0xAE}, ++{0x4024, 0xC6}, ++{0x4025, 0xBD}, ++{0x4026, 0xBD}, ++{0x4027, 0xBA}, ++{0x4028, 0xB0}, ++{0x4029, 0xA9}, ++{0x402A, 0xAA}, ++{0x402B, 0xA8}, ++{0x402C, 0x9F}, ++{0x402D, 0x9C}, ++{0x402E, 0x9C}, ++{0x402F, 0x9B}, ++{0x4030, 0x93}, ++{0x4031, 0x91}, ++{0x4032, 0x92}, ++{0x4033, 0x91}, ++{0x4034, 0x8D}, ++{0x4035, 0x8C}, ++{0x4036, 0x8C}, ++{0x4037, 0x8C}, ++{0x4038, 0x8F}, ++{0x4039, 0x8E}, ++{0x403A, 0x8E}, ++{0x403B, 0x8E}, ++{0x403C, 0x98}, ++{0x403D, 0x96}, ++{0x403E, 0x96}, ++{0x403F, 0x95}, ++{0x4040, 0xA4}, ++{0x4041, 0xA0}, ++{0x4042, 0xA0}, ++{0x4043, 0x9E}, ++{0x4044, 0xB3}, ++{0x4045, 0xAE}, ++{0x4046, 0xAF}, ++{0x4047, 0xAB}, ++{0x4048, 0xC2}, ++{0x4049, 0xB7}, ++{0x404A, 0xB8}, ++{0x404B, 0xB5}, ++{0x404C, 0xAB}, ++{0x404D, 0xA4}, ++{0x404E, 0xA5}, ++{0x404F, 0xA3}, ++{0x4050, 0x99}, ++{0x4051, 0x96}, ++{0x4052, 0x96}, ++{0x4053, 0x96}, ++{0x4054, 0x8B}, ++{0x4055, 0x8A}, ++{0x4056, 0x8A}, ++{0x4057, 0x8A}, ++{0x4058, 0x82}, ++{0x4059, 0x81}, ++{0x405A, 0x81}, ++{0x405B, 0x81}, ++{0x405C, 0x85}, ++{0x405D, 0x86}, ++{0x405E, 0x85}, ++{0x405F, 0x85}, ++{0x4060, 0x90}, ++{0x4061, 0x90}, ++{0x4062, 0x8F}, ++{0x4063, 0x8F}, ++{0x4064, 0x9D}, ++{0x4065, 0x9B}, ++{0x4066, 0x9B}, ++{0x4067, 0x9A}, ++{0x4068, 0xAF}, ++{0x4069, 0xAA}, ++{0x406A, 0xAC}, ++{0x406B, 0xAA}, ++{0x406C, 0xC2}, ++{0x406D, 0xB7}, ++{0x406E, 0xB8}, ++{0x406F, 0xB5}, ++{0x4070, 0xAB}, ++{0x4071, 0xA4}, ++{0x4072, 0xA4}, ++{0x4073, 0xA3}, ++{0x4074, 0x99}, ++{0x4075, 0x96}, ++{0x4076, 0x96}, ++{0x4077, 0x96}, ++{0x4078, 0x8B}, ++{0x4079, 0x8A}, ++{0x407A, 0x8A}, ++{0x407B, 0x8A}, ++{0x407C, 0x82}, ++{0x407D, 0x82}, ++{0x407E, 0x82}, ++{0x407F, 0x82}, ++{0x4080, 0x85}, ++{0x4081, 0x86}, ++{0x4082, 0x86}, ++{0x4083, 0x86}, ++{0x4084, 0x90}, ++{0x4085, 0x90}, ++{0x4086, 0x8F}, ++{0x4087, 0x8F}, ++{0x4088, 0x9D}, ++{0x4089, 0x9B}, ++{0x408A, 0x9B}, ++{0x408B, 0x99}, ++{0x408C, 0xAE}, ++{0x408D, 0xAA}, ++{0x408E, 0xAA}, ++{0x408F, 0xA7}, ++{0x4090, 0xC7}, ++{0x4091, 0xBA}, ++{0x4092, 0xBC}, ++{0x4093, 0xB9}, ++{0x4094, 0xB1}, ++{0x4095, 0xA8}, ++{0x4096, 0xA8}, ++{0x4097, 0xA7}, ++{0x4098, 0x9F}, ++{0x4099, 0x9B}, ++{0x409A, 0x9B}, ++{0x409B, 0x9B}, ++{0x409C, 0x93}, ++{0x409D, 0x91}, ++{0x409E, 0x91}, ++{0x409F, 0x91}, ++{0x40A0, 0x8D}, ++{0x40A1, 0x8C}, ++{0x40A2, 0x8C}, ++{0x40A3, 0x8C}, ++{0x40A4, 0x8E}, ++{0x40A5, 0x8E}, ++{0x40A6, 0x8D}, ++{0x40A7, 0x8D}, ++{0x40A8, 0x96}, ++{0x40A9, 0x95}, ++{0x40AA, 0x95}, ++{0x40AB, 0x94}, ++{0x40AC, 0xA2}, ++{0x40AD, 0x9F}, ++{0x40AE, 0x9F}, ++{0x40AF, 0x9D}, ++{0x40B0, 0xB1}, ++{0x40B1, 0xAC}, ++{0x40B2, 0xAB}, ++{0x40B3, 0xAA}, ++{0x40B4, 0xD3}, ++{0x40B5, 0xBC}, ++{0x40B6, 0xBD}, ++{0x40B7, 0xBC}, ++{0x40B8, 0xC1}, ++{0x40B9, 0xB7}, ++{0x40BA, 0xB7}, ++{0x40BB, 0xB5}, ++{0x40BC, 0xB0}, ++{0x40BD, 0xAA}, ++{0x40BE, 0xAA}, ++{0x40BF, 0xAA}, ++{0x40C0, 0xA8}, ++{0x40C1, 0xA4}, ++{0x40C2, 0xA4}, ++{0x40C3, 0xA4}, ++{0x40C4, 0xA2}, ++{0x40C5, 0x9F}, ++{0x40C6, 0x9F}, ++{0x40C7, 0x9F}, ++{0x40C8, 0xA3}, ++{0x40C9, 0xA0}, ++{0x40CA, 0xA0}, ++{0x40CB, 0xA0}, ++{0x40CC, 0xA6}, ++{0x40CD, 0xA3}, ++{0x40CE, 0xA3}, ++{0x40CF, 0xA2}, ++{0x40D0, 0xAF}, ++{0x40D1, 0xAB}, ++{0x40D2, 0xAA}, ++{0x40D3, 0xA8}, ++{0x40D4, 0xBA}, ++{0x40D5, 0xAE}, ++{0x40D6, 0xAE}, ++{0x40D7, 0xAB}, ++{0x4100, 0xBD}, ++{0x4101, 0xBA}, ++{0x4102, 0xBD}, ++{0x4103, 0xB7}, ++{0x4104, 0xB7}, ++{0x4105, 0xB7}, ++{0x4106, 0xB8}, ++{0x4107, 0xB5}, ++{0x4108, 0xAB}, ++{0x4109, 0xAA}, ++{0x410A, 0xAC}, ++{0x410B, 0xAB}, ++{0x410C, 0xA4}, ++{0x410D, 0xA5}, ++{0x410E, 0xA5}, ++{0x410F, 0xA4}, ++{0x4110, 0x9F}, ++{0x4111, 0xA0}, ++{0x4112, 0xA0}, ++{0x4113, 0x9F}, ++{0x4114, 0xA0}, ++{0x4115, 0xA0}, ++{0x4116, 0xA0}, ++{0x4117, 0x9F}, ++{0x4118, 0xA1}, ++{0x4119, 0xA1}, ++{0x411A, 0xA1}, ++{0x411B, 0xA0}, ++{0x411C, 0xA7}, ++{0x411D, 0xA6}, ++{0x411E, 0xA6}, ++{0x411F, 0xA6}, ++{0x4120, 0xA7}, ++{0x4121, 0xA6}, ++{0x4122, 0xA6}, ++{0x4123, 0xA3}, ++{0x4124, 0xB9}, ++{0x4125, 0xB9}, ++{0x4126, 0xBA}, ++{0x4127, 0xB8}, ++{0x4128, 0xA6}, ++{0x4129, 0xA7}, ++{0x412A, 0xA7}, ++{0x412B, 0xA6}, ++{0x412C, 0x9B}, ++{0x412D, 0x9B}, ++{0x412E, 0x9B}, ++{0x412F, 0x9B}, ++{0x4130, 0x91}, ++{0x4131, 0x92}, ++{0x4132, 0x92}, ++{0x4133, 0x91}, ++{0x4134, 0x8C}, ++{0x4135, 0x8C}, ++{0x4136, 0x8C}, ++{0x4137, 0x8C}, ++{0x4138, 0x8D}, ++{0x4139, 0x8D}, ++{0x413A, 0x8D}, ++{0x413B, 0x8D}, ++{0x413C, 0x93}, ++{0x413D, 0x93}, ++{0x413E, 0x93}, ++{0x413F, 0x92}, ++{0x4140, 0x9A}, ++{0x4141, 0x9A}, ++{0x4142, 0x9A}, ++{0x4143, 0x99}, ++{0x4144, 0xA7}, ++{0x4145, 0xA5}, ++{0x4146, 0xA6}, ++{0x4147, 0xA6}, ++{0x4148, 0xB8}, ++{0x4149, 0xB4}, ++{0x414A, 0xB4}, ++{0x414B, 0xB3}, ++{0x414C, 0xA3}, ++{0x414D, 0xA2}, ++{0x414E, 0xA3}, ++{0x414F, 0xA2}, ++{0x4150, 0x96}, ++{0x4151, 0x96}, ++{0x4152, 0x96}, ++{0x4153, 0x96}, ++{0x4154, 0x8A}, ++{0x4155, 0x8A}, ++{0x4156, 0x8A}, ++{0x4157, 0x8A}, ++{0x4158, 0x82}, ++{0x4159, 0x82}, ++{0x415A, 0x82}, ++{0x415B, 0x82}, ++{0x415C, 0x84}, ++{0x415D, 0x85}, ++{0x415E, 0x84}, ++{0x415F, 0x84}, ++{0x4160, 0x8D}, ++{0x4161, 0x8D}, ++{0x4162, 0x8D}, ++{0x4163, 0x8D}, ++{0x4164, 0x96}, ++{0x4165, 0x96}, ++{0x4166, 0x96}, ++{0x4167, 0x95}, ++{0x4168, 0xA5}, ++{0x4169, 0xA2}, ++{0x416A, 0xA3}, ++{0x416B, 0xA2}, ++{0x416C, 0xB7}, ++{0x416D, 0xB3}, ++{0x416E, 0xB5}, ++{0x416F, 0xB4}, ++{0x4170, 0xA4}, ++{0x4171, 0xA2}, ++{0x4172, 0xA3}, ++{0x4173, 0xA2}, ++{0x4174, 0x97}, ++{0x4175, 0x96}, ++{0x4176, 0x96}, ++{0x4177, 0x96}, ++{0x4178, 0x8B}, ++{0x4179, 0x8A}, ++{0x417A, 0x8A}, ++{0x417B, 0x8A}, ++{0x417C, 0x81}, ++{0x417D, 0x81}, ++{0x417E, 0x81}, ++{0x417F, 0x81}, ++{0x4180, 0x84}, ++{0x4181, 0x84}, ++{0x4182, 0x84}, ++{0x4183, 0x84}, ++{0x4184, 0x8C}, ++{0x4185, 0x8D}, ++{0x4186, 0x8D}, ++{0x4187, 0x8D}, ++{0x4188, 0x95}, ++{0x4189, 0x96}, ++{0x418A, 0x96}, ++{0x418B, 0x95}, ++{0x418C, 0xA1}, ++{0x418D, 0xA1}, ++{0x418E, 0xA1}, ++{0x418F, 0xA0}, ++{0x4190, 0xBC}, ++{0x4191, 0xB8}, ++{0x4192, 0xB8}, ++{0x4193, 0xB9}, ++{0x4194, 0xA8}, ++{0x4195, 0xA5}, ++{0x4196, 0xA6}, ++{0x4197, 0xA5}, ++{0x4198, 0x9C}, ++{0x4199, 0x9A}, ++{0x419A, 0x9A}, ++{0x419B, 0x9A}, ++{0x419C, 0x91}, ++{0x419D, 0x91}, ++{0x419E, 0x91}, ++{0x419F, 0x91}, ++{0x41A0, 0x8B}, ++{0x41A1, 0x8B}, ++{0x41A2, 0x8B}, ++{0x41A3, 0x8B}, ++{0x41A4, 0x8C}, ++{0x41A5, 0x8C}, ++{0x41A6, 0x8C}, ++{0x41A7, 0x8C}, ++{0x41A8, 0x91}, ++{0x41A9, 0x92}, ++{0x41AA, 0x91}, ++{0x41AB, 0x91}, ++{0x41AC, 0x98}, ++{0x41AD, 0x99}, ++{0x41AE, 0x99}, ++{0x41AF, 0x98}, ++{0x41B0, 0xA3}, ++{0x41B1, 0xA3}, ++{0x41B2, 0xA3}, ++{0x41B3, 0xA2}, ++{0x41B4, 0xC1}, ++{0x41B5, 0xB8}, ++{0x41B6, 0xB9}, ++{0x41B7, 0xBA}, ++{0x41B8, 0xB8}, ++{0x41B9, 0xB4}, ++{0x41BA, 0xB4}, ++{0x41BB, 0xB4}, ++{0x41BC, 0xAA}, ++{0x41BD, 0xA7}, ++{0x41BE, 0xA7}, ++{0x41BF, 0xA8}, ++{0x41C0, 0xA4}, ++{0x41C1, 0xA2}, ++{0x41C2, 0xA2}, ++{0x41C3, 0xA3}, ++{0x41C4, 0x9E}, ++{0x41C5, 0x9D}, ++{0x41C6, 0x9D}, ++{0x41C7, 0x9D}, ++{0x41C8, 0x9E}, ++{0x41C9, 0x9D}, ++{0x41CA, 0x9D}, ++{0x41CB, 0x9D}, ++{0x41CC, 0x9E}, ++{0x41CD, 0x9E}, ++{0x41CE, 0x9E}, ++{0x41CF, 0x9E}, ++{0x41D0, 0xA3}, ++{0x41D1, 0xA3}, ++{0x41D2, 0xA2}, ++{0x41D3, 0xA1}, ++{0x41D4, 0xA7}, ++{0x41D5, 0xA7}, ++{0x41D6, 0xA7}, ++{0x41D7, 0xA3}, ++{0x4200, 0xCE}, ++{0x4201, 0xC0}, ++{0x4202, 0xC1}, ++{0x4203, 0xB9}, ++{0x4204, 0xC3}, ++{0x4205, 0xB9}, ++{0x4206, 0xBC}, ++{0x4207, 0xBD}, ++{0x4208, 0xB3}, ++{0x4209, 0xAE}, ++{0x420A, 0xAF}, ++{0x420B, 0xAE}, ++{0x420C, 0xAA}, ++{0x420D, 0xA8}, ++{0x420E, 0xA8}, ++{0x420F, 0xA6}, ++{0x4210, 0xA4}, ++{0x4211, 0xA2}, ++{0x4212, 0xA2}, ++{0x4213, 0xA0}, ++{0x4214, 0xA4}, ++{0x4215, 0xA3}, ++{0x4216, 0xA2}, ++{0x4217, 0xA0}, ++{0x4218, 0xA7}, ++{0x4219, 0xA5}, ++{0x421A, 0xA3}, ++{0x421B, 0xA1}, ++{0x421C, 0xB0}, ++{0x421D, 0xA8}, ++{0x421E, 0xA8}, ++{0x421F, 0xA6}, ++{0x4220, 0xB4}, ++{0x4221, 0xAA}, ++{0x4222, 0xA5}, ++{0x4223, 0xA3}, ++{0x4224, 0xC7}, ++{0x4225, 0xBC}, ++{0x4226, 0xBE}, ++{0x4227, 0xBC}, ++{0x4228, 0xB0}, ++{0x4229, 0xA9}, ++{0x422A, 0xA9}, ++{0x422B, 0xA8}, ++{0x422C, 0xA0}, ++{0x422D, 0x9D}, ++{0x422E, 0x9D}, ++{0x422F, 0x9C}, ++{0x4230, 0x94}, ++{0x4231, 0x93}, ++{0x4232, 0x93}, ++{0x4233, 0x92}, ++{0x4234, 0x8E}, ++{0x4235, 0x8D}, ++{0x4236, 0x8D}, ++{0x4237, 0x8C}, ++{0x4238, 0x8F}, ++{0x4239, 0x8E}, ++{0x423A, 0x8E}, ++{0x423B, 0x8D}, ++{0x423C, 0x96}, ++{0x423D, 0x94}, ++{0x423E, 0x94}, ++{0x423F, 0x92}, ++{0x4240, 0xA1}, ++{0x4241, 0x9C}, ++{0x4242, 0x9C}, ++{0x4243, 0x99}, ++{0x4244, 0xB0}, ++{0x4245, 0xA8}, ++{0x4246, 0xAB}, ++{0x4247, 0xA7}, ++{0x4248, 0xC3}, ++{0x4249, 0xB7}, ++{0x424A, 0xB7}, ++{0x424B, 0xBC}, ++{0x424C, 0xAB}, ++{0x424D, 0xA4}, ++{0x424E, 0xA5}, ++{0x424F, 0xA5}, ++{0x4250, 0x9A}, ++{0x4251, 0x97}, ++{0x4252, 0x97}, ++{0x4253, 0x98}, ++{0x4254, 0x8C}, ++{0x4255, 0x8B}, ++{0x4256, 0x8B}, ++{0x4257, 0x8B}, ++{0x4258, 0x82}, ++{0x4259, 0x82}, ++{0x425A, 0x82}, ++{0x425B, 0x82}, ++{0x425C, 0x85}, ++{0x425D, 0x85}, ++{0x425E, 0x85}, ++{0x425F, 0x84}, ++{0x4260, 0x8F}, ++{0x4261, 0x8E}, ++{0x4262, 0x8E}, ++{0x4263, 0x8D}, ++{0x4264, 0x9B}, ++{0x4265, 0x98}, ++{0x4266, 0x98}, ++{0x4267, 0x95}, ++{0x4268, 0xAE}, ++{0x4269, 0xA5}, ++{0x426A, 0xA7}, ++{0x426B, 0xA2}, ++{0x426C, 0xC2}, ++{0x426D, 0xB7}, ++{0x426E, 0xB8}, ++{0x426F, 0xB9}, ++{0x4270, 0xAA}, ++{0x4271, 0xA4}, ++{0x4272, 0xA4}, ++{0x4273, 0xA5}, ++{0x4274, 0x99}, ++{0x4275, 0x96}, ++{0x4276, 0x97}, ++{0x4277, 0x98}, ++{0x4278, 0x8B}, ++{0x4279, 0x8A}, ++{0x427A, 0x8A}, ++{0x427B, 0x8B}, ++{0x427C, 0x81}, ++{0x427D, 0x81}, ++{0x427E, 0x81}, ++{0x427F, 0x82}, ++{0x4280, 0x84}, ++{0x4281, 0x84}, ++{0x4282, 0x84}, ++{0x4283, 0x84}, ++{0x4284, 0x8E}, ++{0x4285, 0x8E}, ++{0x4286, 0x8D}, ++{0x4287, 0x8C}, ++{0x4288, 0x9A}, ++{0x4289, 0x97}, ++{0x428A, 0x97}, ++{0x428B, 0x95}, ++{0x428C, 0xAA}, ++{0x428D, 0xA3}, ++{0x428E, 0xA3}, ++{0x428F, 0xA2}, ++{0x4290, 0xC7}, ++{0x4291, 0xBA}, ++{0x4292, 0xC0}, ++{0x4293, 0xC3}, ++{0x4294, 0xB0}, ++{0x4295, 0xA7}, ++{0x4296, 0xA7}, ++{0x4297, 0xA9}, ++{0x4298, 0x9F}, ++{0x4299, 0x9B}, ++{0x429A, 0x9B}, ++{0x429B, 0x9D}, ++{0x429C, 0x93}, ++{0x429D, 0x91}, ++{0x429E, 0x91}, ++{0x429F, 0x92}, ++{0x42A0, 0x8C}, ++{0x42A1, 0x8B}, ++{0x42A2, 0x8B}, ++{0x42A3, 0x8C}, ++{0x42A4, 0x8D}, ++{0x42A5, 0x8C}, ++{0x42A6, 0x8C}, ++{0x42A7, 0x8C}, ++{0x42A8, 0x94}, ++{0x42A9, 0x93}, ++{0x42AA, 0x92}, ++{0x42AB, 0x91}, ++{0x42AC, 0x9E}, ++{0x42AD, 0x9B}, ++{0x42AE, 0x9B}, ++{0x42AF, 0x98}, ++{0x42B0, 0xAC}, ++{0x42B1, 0xA6}, ++{0x42B2, 0xA6}, ++{0x42B3, 0xA2}, ++{0x42B4, 0xCE}, ++{0x42B5, 0xBA}, ++{0x42B6, 0xBC}, ++{0x42B7, 0xB7}, ++{0x42B8, 0xC5}, ++{0x42B9, 0xB5}, ++{0x42BA, 0xBA}, ++{0x42BB, 0xC0}, ++{0x42BC, 0xB1}, ++{0x42BD, 0xA8}, ++{0x42BE, 0xAE}, ++{0x42BF, 0xAF}, ++{0x42C0, 0xA7}, ++{0x42C1, 0xA3}, ++{0x42C2, 0xA3}, ++{0x42C3, 0xA5}, ++{0x42C4, 0xA0}, ++{0x42C5, 0x9D}, ++{0x42C6, 0x9D}, ++{0x42C7, 0x9F}, ++{0x42C8, 0xA0}, ++{0x42C9, 0x9E}, ++{0x42CA, 0x9E}, ++{0x42CB, 0x9F}, ++{0x42CC, 0xA2}, ++{0x42CD, 0xA0}, ++{0x42CE, 0xA0}, ++{0x42CF, 0xA0}, ++{0x42D0, 0xA8}, ++{0x42D1, 0xA5}, ++{0x42D2, 0xA5}, ++{0x42D3, 0xA2}, ++{0x42D4, 0xB3}, ++{0x42D5, 0xAA}, ++{0x42D6, 0xAB}, ++{0x42D7, 0xA3}, ++{0x42D8, 0x00}, ++{0x42D9, 0x00}, ++{0x4300, 0xA2}, ++{0x4301, 0xAE}, ++{0x4302, 0xAD}, ++{0x4303, 0xB5}, ++{0x4304, 0x95}, ++{0x4305, 0x9A}, ++{0x4306, 0x98}, ++{0x4307, 0x9B}, ++{0x4308, 0x8D}, ++{0x4309, 0x90}, ++{0x430A, 0x8F}, ++{0x430B, 0x91}, ++{0x430C, 0x86}, ++{0x430D, 0x88}, ++{0x430E, 0x87}, ++{0x430F, 0x89}, ++{0x4310, 0x86}, ++{0x4311, 0x87}, ++{0x4312, 0x86}, ++{0x4313, 0x88}, ++{0x4314, 0x89}, ++{0x4315, 0x88}, ++{0x4316, 0x88}, ++{0x4317, 0x8E}, ++{0x4318, 0x90}, ++{0x4319, 0x8F}, ++{0x431A, 0x8C}, ++{0x431B, 0x8C}, ++{0x431C, 0x9C}, ++{0x431D, 0x99}, ++{0x431E, 0x98}, ++{0x431F, 0x99}, ++{0x4320, 0xAB}, ++{0x4321, 0xB0}, ++{0x4322, 0xAD}, ++{0x4323, 0xAF}, ++{0x4324, 0x9B}, ++{0x4325, 0x9F}, ++{0x4326, 0x9E}, ++{0x4327, 0xA1}, ++{0x4328, 0x8E}, ++{0x4329, 0x91}, ++{0x432A, 0x90}, ++{0x432B, 0x93}, ++{0x432C, 0x86}, ++{0x432D, 0x88}, ++{0x432E, 0x87}, ++{0x432F, 0x89}, ++{0x4330, 0x82}, ++{0x4331, 0x84}, ++{0x4332, 0x83}, ++{0x4333, 0x84}, ++{0x4334, 0x82}, ++{0x4335, 0x82}, ++{0x4336, 0x82}, ++{0x4337, 0x83}, ++{0x4338, 0x85}, ++{0x4339, 0x84}, ++{0x433A, 0x84}, ++{0x433B, 0x85}, ++{0x433C, 0x8A}, ++{0x433D, 0x89}, ++{0x433E, 0x88}, ++{0x433F, 0x89}, ++{0x4340, 0x93}, ++{0x4341, 0x91}, ++{0x4342, 0x91}, ++{0x4343, 0x93}, ++{0x4344, 0xA0}, ++{0x4345, 0x9E}, ++{0x4346, 0x9D}, ++{0x4347, 0xA1}, ++{0x4348, 0x95}, ++{0x4349, 0x9B}, ++{0x434A, 0x9A}, ++{0x434B, 0x9C}, ++{0x434C, 0x8A}, ++{0x434D, 0x8D}, ++{0x434E, 0x8C}, ++{0x434F, 0x8D}, ++{0x4350, 0x83}, ++{0x4351, 0x85}, ++{0x4352, 0x84}, ++{0x4353, 0x85}, ++{0x4354, 0x80}, ++{0x4355, 0x81}, ++{0x4356, 0x81}, ++{0x4357, 0x81}, ++{0x4358, 0x80}, ++{0x4359, 0x80}, ++{0x435A, 0x80}, ++{0x435B, 0x80}, ++{0x435C, 0x82}, ++{0x435D, 0x81}, ++{0x435E, 0x81}, ++{0x435F, 0x81}, ++{0x4360, 0x85}, ++{0x4361, 0x84}, ++{0x4362, 0x84}, ++{0x4363, 0x85}, ++{0x4364, 0x8D}, ++{0x4365, 0x8B}, ++{0x4366, 0x8B}, ++{0x4367, 0x8D}, ++{0x4368, 0x98}, ++{0x4369, 0x98}, ++{0x436A, 0x95}, ++{0x436B, 0x98}, ++{0x436C, 0x95}, ++{0x436D, 0x9A}, ++{0x436E, 0x99}, ++{0x436F, 0x9A}, ++{0x4370, 0x8A}, ++{0x4371, 0x8D}, ++{0x4372, 0x8C}, ++{0x4373, 0x8C}, ++{0x4374, 0x83}, ++{0x4375, 0x85}, ++{0x4376, 0x84}, ++{0x4377, 0x84}, ++{0x4378, 0x80}, ++{0x4379, 0x80}, ++{0x437A, 0x80}, ++{0x437B, 0x80}, ++{0x437C, 0x7F}, ++{0x437D, 0x7F}, ++{0x437E, 0x7F}, ++{0x437F, 0x7F}, ++{0x4380, 0x81}, ++{0x4381, 0x80}, ++{0x4382, 0x80}, ++{0x4383, 0x81}, ++{0x4384, 0x84}, ++{0x4385, 0x83}, ++{0x4386, 0x83}, ++{0x4387, 0x84}, ++{0x4388, 0x8B}, ++{0x4389, 0x8A}, ++{0x438A, 0x8A}, ++{0x438B, 0x8C}, ++{0x438C, 0x97}, ++{0x438D, 0x96}, ++{0x438E, 0x96}, ++{0x438F, 0x99}, ++{0x4390, 0x99}, ++{0x4391, 0x9F}, ++{0x4392, 0x9E}, ++{0x4393, 0x9D}, ++{0x4394, 0x8D}, ++{0x4395, 0x90}, ++{0x4396, 0x90}, ++{0x4397, 0x8F}, ++{0x4398, 0x85}, ++{0x4399, 0x87}, ++{0x439A, 0x87}, ++{0x439B, 0x86}, ++{0x439C, 0x81}, ++{0x439D, 0x83}, ++{0x439E, 0x82}, ++{0x439F, 0x82}, ++{0x43A0, 0x80}, ++{0x43A1, 0x81}, ++{0x43A2, 0x81}, ++{0x43A3, 0x81}, ++{0x43A4, 0x82}, ++{0x43A5, 0x82}, ++{0x43A6, 0x82}, ++{0x43A7, 0x82}, ++{0x43A8, 0x86}, ++{0x43A9, 0x85}, ++{0x43AA, 0x85}, ++{0x43AB, 0x87}, ++{0x43AC, 0x8D}, ++{0x43AD, 0x8D}, ++{0x43AE, 0x8D}, ++{0x43AF, 0x90}, ++{0x43B0, 0x9A}, ++{0x43B1, 0x9A}, ++{0x43B2, 0x9B}, ++{0x43B3, 0x9D}, ++{0x43B4, 0xA0}, ++{0x43B5, 0xAD}, ++{0x43B6, 0xAC}, ++{0x43B7, 0xAA}, ++{0x43B8, 0x93}, ++{0x43B9, 0x97}, ++{0x43BA, 0x97}, ++{0x43BB, 0x96}, ++{0x43BC, 0x8B}, ++{0x43BD, 0x8E}, ++{0x43BE, 0x8E}, ++{0x43BF, 0x8C}, ++{0x43C0, 0x83}, ++{0x43C1, 0x85}, ++{0x43C2, 0x85}, ++{0x43C3, 0x84}, ++{0x43C4, 0x82}, ++{0x43C5, 0x84}, ++{0x43C6, 0x83}, ++{0x43C7, 0x83}, ++{0x43C8, 0x83}, ++{0x43C9, 0x84}, ++{0x43CA, 0x84}, ++{0x43CB, 0x85}, ++{0x43CC, 0x8A}, ++{0x43CD, 0x8A}, ++{0x43CE, 0x8A}, ++{0x43CF, 0x8C}, ++{0x43D0, 0x92}, ++{0x43D1, 0x93}, ++{0x43D2, 0x93}, ++{0x43D3, 0x96}, ++{0x43D4, 0x9F}, ++{0x43D5, 0xA6}, ++{0x43D6, 0xA5}, ++{0x43D7, 0xAA}, ++{0x4400, 0xA1}, ++{0x4401, 0xAB}, ++{0x4402, 0xA7}, ++{0x4403, 0xB0}, ++{0x4404, 0x91}, ++{0x4405, 0x96}, ++{0x4406, 0x94}, ++{0x4407, 0x99}, ++{0x4408, 0x8A}, ++{0x4409, 0x8E}, ++{0x440A, 0x8C}, ++{0x440B, 0x8F}, ++{0x440C, 0x85}, ++{0x440D, 0x86}, ++{0x440E, 0x86}, ++{0x440F, 0x88}, ++{0x4410, 0x85}, ++{0x4411, 0x86}, ++{0x4412, 0x85}, ++{0x4413, 0x87}, ++{0x4414, 0x88}, ++{0x4415, 0x87}, ++{0x4416, 0x87}, ++{0x4417, 0x89}, ++{0x4418, 0x91}, ++{0x4419, 0x8F}, ++{0x441A, 0x8F}, ++{0x441B, 0x90}, ++{0x441C, 0x9C}, ++{0x441D, 0x9B}, ++{0x441E, 0x9A}, ++{0x441F, 0x9A}, ++{0x4420, 0xB3}, ++{0x4421, 0xB1}, ++{0x4422, 0xB0}, ++{0x4423, 0xB2}, ++{0x4424, 0x96}, ++{0x4425, 0x9C}, ++{0x4426, 0x9A}, ++{0x4427, 0x9E}, ++{0x4428, 0x8B}, ++{0x4429, 0x8F}, ++{0x442A, 0x8E}, ++{0x442B, 0x91}, ++{0x442C, 0x84}, ++{0x442D, 0x87}, ++{0x442E, 0x86}, ++{0x442F, 0x88}, ++{0x4430, 0x82}, ++{0x4431, 0x83}, ++{0x4432, 0x82}, ++{0x4433, 0x84}, ++{0x4434, 0x82}, ++{0x4435, 0x82}, ++{0x4436, 0x82}, ++{0x4437, 0x83}, ++{0x4438, 0x84}, ++{0x4439, 0x84}, ++{0x443A, 0x84}, ++{0x443B, 0x84}, ++{0x443C, 0x8B}, ++{0x443D, 0x89}, ++{0x443E, 0x89}, ++{0x443F, 0x89}, ++{0x4440, 0x95}, ++{0x4441, 0x93}, ++{0x4442, 0x93}, ++{0x4443, 0x93}, ++{0x4444, 0xA2}, ++{0x4445, 0xA2}, ++{0x4446, 0xA1}, ++{0x4447, 0xA0}, ++{0x4448, 0x8F}, ++{0x4449, 0x97}, ++{0x444A, 0x97}, ++{0x444B, 0x98}, ++{0x444C, 0x87}, ++{0x444D, 0x8B}, ++{0x444E, 0x8A}, ++{0x444F, 0x8B}, ++{0x4450, 0x81}, ++{0x4451, 0x83}, ++{0x4452, 0x83}, ++{0x4453, 0x84}, ++{0x4454, 0x7F}, ++{0x4455, 0x80}, ++{0x4456, 0x80}, ++{0x4457, 0x81}, ++{0x4458, 0x80}, ++{0x4459, 0x80}, ++{0x445A, 0x80}, ++{0x445B, 0x80}, ++{0x445C, 0x82}, ++{0x445D, 0x81}, ++{0x445E, 0x81}, ++{0x445F, 0x81}, ++{0x4460, 0x87}, ++{0x4461, 0x85}, ++{0x4462, 0x85}, ++{0x4463, 0x86}, ++{0x4464, 0x90}, ++{0x4465, 0x8E}, ++{0x4466, 0x8E}, ++{0x4467, 0x8E}, ++{0x4468, 0x9B}, ++{0x4469, 0x9C}, ++{0x446A, 0x9A}, ++{0x446B, 0x9A}, ++{0x446C, 0x91}, ++{0x446D, 0x97}, ++{0x446E, 0x95}, ++{0x446F, 0x95}, ++{0x4470, 0x87}, ++{0x4471, 0x8A}, ++{0x4472, 0x8A}, ++{0x4473, 0x89}, ++{0x4474, 0x81}, ++{0x4475, 0x83}, ++{0x4476, 0x83}, ++{0x4477, 0x83}, ++{0x4478, 0x7F}, ++{0x4479, 0x80}, ++{0x447A, 0x80}, ++{0x447B, 0x80}, ++{0x447C, 0x80}, ++{0x447D, 0x80}, ++{0x447E, 0x80}, ++{0x447F, 0x7F}, ++{0x4480, 0x81}, ++{0x4481, 0x81}, ++{0x4482, 0x81}, ++{0x4483, 0x81}, ++{0x4484, 0x85}, ++{0x4485, 0x85}, ++{0x4486, 0x85}, ++{0x4487, 0x85}, ++{0x4488, 0x8E}, ++{0x4489, 0x8D}, ++{0x448A, 0x8D}, ++{0x448B, 0x8E}, ++{0x448C, 0x9D}, ++{0x448D, 0x9C}, ++{0x448E, 0x9C}, ++{0x448F, 0x9C}, ++{0x4490, 0x94}, ++{0x4491, 0x9B}, ++{0x4492, 0x9A}, ++{0x4493, 0x97}, ++{0x4494, 0x8A}, ++{0x4495, 0x8E}, ++{0x4496, 0x8E}, ++{0x4497, 0x8C}, ++{0x4498, 0x84}, ++{0x4499, 0x86}, ++{0x449A, 0x86}, ++{0x449B, 0x84}, ++{0x449C, 0x81}, ++{0x449D, 0x83}, ++{0x449E, 0x83}, ++{0x449F, 0x81}, ++{0x44A0, 0x81}, ++{0x44A1, 0x82}, ++{0x44A2, 0x82}, ++{0x44A3, 0x81}, ++{0x44A4, 0x83}, ++{0x44A5, 0x83}, ++{0x44A6, 0x83}, ++{0x44A7, 0x83}, ++{0x44A8, 0x88}, ++{0x44A9, 0x88}, ++{0x44AA, 0x88}, ++{0x44AB, 0x88}, ++{0x44AC, 0x91}, ++{0x44AD, 0x91}, ++{0x44AE, 0x91}, ++{0x44AF, 0x92}, ++{0x44B0, 0xA0}, ++{0x44B1, 0xA0}, ++{0x44B2, 0xA0}, ++{0x44B3, 0xA0}, ++{0x44B4, 0x9E}, ++{0x44B5, 0xA9}, ++{0x44B6, 0xA8}, ++{0x44B7, 0xA3}, ++{0x44B8, 0x90}, ++{0x44B9, 0x95}, ++{0x44BA, 0x95}, ++{0x44BB, 0x92}, ++{0x44BC, 0x8A}, ++{0x44BD, 0x8E}, ++{0x44BE, 0x8E}, ++{0x44BF, 0x8B}, ++{0x44C0, 0x84}, ++{0x44C1, 0x86}, ++{0x44C2, 0x86}, ++{0x44C3, 0x84}, ++{0x44C4, 0x84}, ++{0x44C5, 0x85}, ++{0x44C6, 0x85}, ++{0x44C7, 0x84}, ++{0x44C8, 0x86}, ++{0x44C9, 0x87}, ++{0x44CA, 0x87}, ++{0x44CB, 0x86}, ++{0x44CC, 0x8D}, ++{0x44CD, 0x8E}, ++{0x44CE, 0x8E}, ++{0x44CF, 0x8D}, ++{0x44D0, 0x98}, ++{0x44D1, 0x98}, ++{0x44D2, 0x99}, ++{0x44D3, 0x9A}, ++{0x44D4, 0xA9}, ++{0x44D5, 0xAA}, ++{0x44D6, 0xAA}, ++{0x44D7, 0xAD}, ++{0x4500, 0x9F}, ++{0x4501, 0xA8}, ++{0x4502, 0xA5}, ++{0x4503, 0xAF}, ++{0x4504, 0x8F}, ++{0x4505, 0x96}, ++{0x4506, 0x92}, ++{0x4507, 0x94}, ++{0x4508, 0x89}, ++{0x4509, 0x8D}, ++{0x450A, 0x8A}, ++{0x450B, 0x8E}, ++{0x450C, 0x84}, ++{0x450D, 0x85}, ++{0x450E, 0x84}, ++{0x450F, 0x87}, ++{0x4510, 0x84}, ++{0x4511, 0x85}, ++{0x4512, 0x84}, ++{0x4513, 0x86}, ++{0x4514, 0x87}, ++{0x4515, 0x86}, ++{0x4516, 0x86}, ++{0x4517, 0x88}, ++{0x4518, 0x8F}, ++{0x4519, 0x8D}, ++{0x451A, 0x8D}, ++{0x451B, 0x8F}, ++{0x451C, 0x9A}, ++{0x451D, 0x9A}, ++{0x451E, 0x98}, ++{0x451F, 0x9A}, ++{0x4520, 0xAF}, ++{0x4521, 0xAF}, ++{0x4522, 0xB2}, ++{0x4523, 0xB1}, ++{0x4524, 0x95}, ++{0x4525, 0x9B}, ++{0x4526, 0x97}, ++{0x4527, 0x9C}, ++{0x4528, 0x8A}, ++{0x4529, 0x8E}, ++{0x452A, 0x8D}, ++{0x452B, 0x90}, ++{0x452C, 0x84}, ++{0x452D, 0x86}, ++{0x452E, 0x85}, ++{0x452F, 0x87}, ++{0x4530, 0x81}, ++{0x4531, 0x82}, ++{0x4532, 0x82}, ++{0x4533, 0x83}, ++{0x4534, 0x81}, ++{0x4535, 0x81}, ++{0x4536, 0x81}, ++{0x4537, 0x82}, ++{0x4538, 0x84}, ++{0x4539, 0x83}, ++{0x453A, 0x83}, ++{0x453B, 0x84}, ++{0x453C, 0x8A}, ++{0x453D, 0x88}, ++{0x453E, 0x88}, ++{0x453F, 0x89}, ++{0x4540, 0x94}, ++{0x4541, 0x92}, ++{0x4542, 0x91}, ++{0x4543, 0x92}, ++{0x4544, 0xA1}, ++{0x4545, 0xA0}, ++{0x4546, 0x9C}, ++{0x4547, 0x9D}, ++{0x4548, 0x8F}, ++{0x4549, 0x96}, ++{0x454A, 0x95}, ++{0x454B, 0x92}, ++{0x454C, 0x87}, ++{0x454D, 0x8A}, ++{0x454E, 0x89}, ++{0x454F, 0x8A}, ++{0x4550, 0x81}, ++{0x4551, 0x83}, ++{0x4552, 0x82}, ++{0x4553, 0x83}, ++{0x4554, 0x7F}, ++{0x4555, 0x80}, ++{0x4556, 0x80}, ++{0x4557, 0x81}, ++{0x4558, 0x7F}, ++{0x4559, 0x80}, ++{0x455A, 0x7F}, ++{0x455B, 0x80}, ++{0x455C, 0x81}, ++{0x455D, 0x81}, ++{0x455E, 0x81}, ++{0x455F, 0x81}, ++{0x4560, 0x86}, ++{0x4561, 0x85}, ++{0x4562, 0x85}, ++{0x4563, 0x85}, ++{0x4564, 0x8F}, ++{0x4565, 0x8D}, ++{0x4566, 0x8D}, ++{0x4567, 0x8D}, ++{0x4568, 0x99}, ++{0x4569, 0x9A}, ++{0x456A, 0x97}, ++{0x456B, 0x99}, ++{0x456C, 0x90}, ++{0x456D, 0x95}, ++{0x456E, 0x93}, ++{0x456F, 0x92}, ++{0x4570, 0x87}, ++{0x4571, 0x8A}, ++{0x4572, 0x88}, ++{0x4573, 0x87}, ++{0x4574, 0x81}, ++{0x4575, 0x83}, ++{0x4576, 0x82}, ++{0x4577, 0x82}, ++{0x4578, 0x7F}, ++{0x4579, 0x80}, ++{0x457A, 0x80}, ++{0x457B, 0x80}, ++{0x457C, 0x80}, ++{0x457D, 0x80}, ++{0x457E, 0x80}, ++{0x457F, 0x80}, ++{0x4580, 0x81}, ++{0x4581, 0x81}, ++{0x4582, 0x81}, ++{0x4583, 0x81}, ++{0x4584, 0x85}, ++{0x4585, 0x85}, ++{0x4586, 0x84}, ++{0x4587, 0x85}, ++{0x4588, 0x8E}, ++{0x4589, 0x8D}, ++{0x458A, 0x8C}, ++{0x458B, 0x8D}, ++{0x458C, 0x9B}, ++{0x458D, 0x9B}, ++{0x458E, 0x9A}, ++{0x458F, 0x98}, ++{0x4590, 0x94}, ++{0x4591, 0x9A}, ++{0x4592, 0x94}, ++{0x4593, 0x90}, ++{0x4594, 0x8A}, ++{0x4595, 0x8D}, ++{0x4596, 0x8C}, ++{0x4597, 0x89}, ++{0x4598, 0x84}, ++{0x4599, 0x86}, ++{0x459A, 0x85}, ++{0x459B, 0x83}, ++{0x459C, 0x82}, ++{0x459D, 0x83}, ++{0x459E, 0x82}, ++{0x459F, 0x80}, ++{0x45A0, 0x81}, ++{0x45A1, 0x82}, ++{0x45A2, 0x81}, ++{0x45A3, 0x80}, ++{0x45A4, 0x83}, ++{0x45A5, 0x83}, ++{0x45A6, 0x83}, ++{0x45A7, 0x83}, ++{0x45A8, 0x88}, ++{0x45A9, 0x87}, ++{0x45AA, 0x87}, ++{0x45AB, 0x88}, ++{0x45AC, 0x91}, ++{0x45AD, 0x90}, ++{0x45AE, 0x90}, ++{0x45AF, 0x91}, ++{0x45B0, 0x9F}, ++{0x45B1, 0x9F}, ++{0x45B2, 0x9E}, ++{0x45B3, 0x9F}, ++{0x45B4, 0x9F}, ++{0x45B5, 0xA8}, ++{0x45B6, 0xA6}, ++{0x45B7, 0xA7}, ++{0x45B8, 0x8D}, ++{0x45B9, 0x95}, ++{0x45BA, 0x90}, ++{0x45BB, 0x8A}, ++{0x45BC, 0x89}, ++{0x45BD, 0x8D}, ++{0x45BE, 0x88}, ++{0x45BF, 0x86}, ++{0x45C0, 0x84}, ++{0x45C1, 0x86}, ++{0x45C2, 0x85}, ++{0x45C3, 0x82}, ++{0x45C4, 0x84}, ++{0x45C5, 0x85}, ++{0x45C6, 0x85}, ++{0x45C7, 0x83}, ++{0x45C8, 0x86}, ++{0x45C9, 0x86}, ++{0x45CA, 0x86}, ++{0x45CB, 0x85}, ++{0x45CC, 0x8E}, ++{0x45CD, 0x8D}, ++{0x45CE, 0x8D}, ++{0x45CF, 0x8C}, ++{0x45D0, 0x99}, ++{0x45D1, 0x98}, ++{0x45D2, 0x98}, ++{0x45D3, 0x98}, ++{0x45D4, 0xA6}, ++{0x45D5, 0xA9}, ++{0x45D6, 0xA7}, ++{0x45D7, 0xAC}, ++{0x7000, 0xAB}, ++{0x7001, 0xBA}, ++{0x7002, 0x40}, ++{0x7003, 0x02}, ++{0x7004, 0x00}, ++{0x7005, 0x00}, ++{0x7006, 0x00}, ++{0x7007, 0x00}, ++{0x7008, 0x00}, ++{0x7009, 0x00}, ++{0x700A, 0x00}, ++{0x700B, 0x00}, ++{0x700C, 0x00}, ++{0x700D, 0x00}, ++{0x700E, 0x00}, ++{0x700F, 0x00}, ++{0x7010, 0x55}, ++{0x7011, 0x88}, ++{0x7012, 0x40}, ++{0x7013, 0x01}, ++{0x7014, 0x72}, ++{0x7015, 0xF1}, ++{0x7016, 0x02}, ++{0x7017, 0xF8}, ++{0x7018, 0x00}, ++{0x7019, 0x00}, ++{0x701A, 0x00}, ++{0x701B, 0x00}, ++{0x701C, 0x00}, ++{0x701D, 0x00}, ++{0x701E, 0x00}, ++{0x701F, 0x00}, ++{0x7020, 0x00}, ++{0x7021, 0x00}, ++{0x7022, 0x00}, ++{0x7023, 0x00}, ++{0x7024, 0x00}, ++{0x7025, 0x00}, ++{0x7026, 0x00}, ++{0x7027, 0x00}, ++{0x7028, 0x00}, ++{0x7029, 0x00}, ++{0x702A, 0x00}, ++{0x702B, 0x00}, ++{0x702C, 0x00}, ++{0x702D, 0x00}, ++{0x702E, 0x00}, ++{0x702F, 0x00}, ++{0x7030, 0x00}, ++{0x7031, 0x00}, ++{0x7032, 0x00}, ++{0x7033, 0x00}, ++{0x7034, 0x00}, ++{0x7035, 0x00}, ++{0x7036, 0x00}, ++{0x7037, 0x00}, ++{0x7038, 0x00}, ++{0x7039, 0x00}, ++{0x703A, 0x00}, ++{0x703B, 0x00}, ++{0x703C, 0x00}, ++{0x703D, 0x00}, ++{0x703E, 0x00}, ++{0x703F, 0x00}, ++{0x7040, 0x00}, ++{0x7041, 0x00}, ++{0x7042, 0x00}, ++{0x7043, 0x00}, ++{0x7044, 0x00}, ++{0x7045, 0x00}, ++{0x7046, 0x00}, ++{0x7047, 0x00}, ++{0x7048, 0x00}, ++{0x7049, 0x00}, ++{0x704A, 0x00}, ++{0x704B, 0x00}, ++{0x704C, 0x00}, ++{0x704D, 0x00}, ++{0x704E, 0x00}, ++{0x704F, 0x00}, ++{0x7050, 0x00}, ++{0x7051, 0x00}, ++{0x7052, 0x00}, ++{0x7053, 0x00}, ++{0x7054, 0x00}, ++{0x7055, 0x00}, ++{0x7056, 0x00}, ++{0x7057, 0x00}, ++{0x7058, 0x00}, ++{0x7059, 0x00}, ++{0x705A, 0x00}, ++{0x705B, 0x00}, ++{0x705C, 0x00}, ++{0x705D, 0x00}, ++{0x705E, 0x00}, ++{0x705F, 0x00}, ++{0x7060, 0x00}, ++{0x7061, 0x00}, ++{0x7062, 0x00}, ++{0x7063, 0x00}, ++{0x7064, 0x00}, ++{0x7065, 0x00}, ++{0x7066, 0x00}, ++{0x7067, 0x00}, ++{0x7068, 0x00}, ++{0x7069, 0x00}, ++{0x706A, 0x00}, ++{0x706B, 0x00}, ++{0x706C, 0x00}, ++{0x706D, 0x00}, ++{0x706E, 0x00}, ++{0x706F, 0x00}, ++{0x7070, 0x00}, ++{0x7071, 0x00}, ++{0x7072, 0x00}, ++{0x7073, 0x00}, ++{0x7074, 0x00}, ++{0x7075, 0x00}, ++{0x7076, 0x00}, ++{0x7077, 0x00}, ++{0x7078, 0x00}, ++{0x7079, 0x00}, ++{0x707A, 0x00}, ++{0x707B, 0x00}, ++{0x707C, 0x00}, ++{0x707D, 0x00}, ++{0x707E, 0x00}, ++{0x707F, 0x00}, ++{0x7080, 0x00}, ++{0x7081, 0x00}, ++{0x7082, 0x00}, ++{0x7083, 0x00}, ++{0x7084, 0x00}, ++{0x7085, 0x00}, ++{0x7086, 0x00}, ++{0x7087, 0x00}, ++{0x7088, 0x00}, ++{0x7089, 0x00}, ++{0x708A, 0x00}, ++{0x708B, 0x00}, ++{0x708C, 0x00}, ++{0x708D, 0x00}, ++{0x708E, 0x00}, ++{0x708F, 0x00}, ++{0x7090, 0x00}, ++{0x7091, 0xF0}, ++{0x7092, 0x02}, ++{0x7093, 0xF8}, ++{0x7094, 0x8D}, ++{0x7095, 0xF6}, ++{0x7096, 0xFA}, ++{0x7097, 0xFF}, ++{0x7098, 0xF0}, ++{0x7099, 0xB5}, ++{0x709A, 0x04}, ++{0x709B, 0x46}, ++{0x709C, 0x8F}, ++{0x709D, 0xB0}, ++{0x709E, 0x5F}, ++{0x709F, 0x48}, ++{0x70A0, 0x0C}, ++{0x70A1, 0x90}, ++{0x70A2, 0x5F}, ++{0x70A3, 0x48}, ++{0x70A4, 0x06}, ++{0x70A5, 0x90}, ++{0x70A6, 0x20}, ++{0x70A7, 0x46}, ++{0x70A8, 0x34}, ++{0x70A9, 0x30}, ++{0x70AA, 0x0B}, ++{0x70AB, 0x90}, ++{0x70AC, 0x5B}, ++{0x70AD, 0x48}, ++{0x70AE, 0x5A}, ++{0x70AF, 0x49}, ++{0x70B0, 0x26}, ++{0x70B1, 0x46}, ++{0x70B2, 0x66}, ++{0x70B3, 0x30}, ++{0x70B4, 0x3A}, ++{0x70B5, 0x31}, ++{0x70B6, 0x3C}, ++{0x70B7, 0x36}, ++{0x70B8, 0x05}, ++{0x70B9, 0x90}, ++{0x70BA, 0x0A}, ++{0x70BB, 0x30}, ++{0x70BC, 0x04}, ++{0x70BD, 0x90}, ++{0x70BE, 0x59}, ++{0x70BF, 0x48}, ++{0x70C0, 0x55}, ++{0x70C1, 0x4A}, ++{0x70C2, 0x40}, ++{0x70C3, 0x6E}, ++{0x70C4, 0xC0}, ++{0x70C5, 0x07}, ++{0x70C6, 0x7D}, ++{0x70C7, 0xD1}, ++{0x70C8, 0x17}, ++{0x70C9, 0x88}, ++{0x70CA, 0x0A}, ++{0x70CB, 0x5E}, ++{0x70CC, 0x0D}, ++{0x70CD, 0x92}, ++{0x70CE, 0x53}, ++{0x70CF, 0x49}, ++{0x70D0, 0x55}, ++{0x70D1, 0x48}, ++{0x70D2, 0x94}, ++{0x70D3, 0x31}, ++{0x70D4, 0x89}, ++{0x70D5, 0x6B}, ++{0x70D6, 0x80}, ++{0x70D7, 0x68}, ++{0x70D8, 0x09}, ++{0x70D9, 0x02}, ++{0x70DA, 0x00}, ++{0x70DB, 0x03}, ++{0x70DC, 0x09}, ++{0x70DD, 0x0E}, ++{0x70DE, 0x00}, ++{0x70DF, 0x0B}, ++{0x70E0, 0x49}, ++{0x70E1, 0x1C}, ++{0x70E2, 0x48}, ++{0x70E3, 0x43}, ++{0x70E4, 0x4D}, ++{0x70E5, 0x49}, ++{0x70E6, 0x6C}, ++{0x70E7, 0x39}, ++{0x70E8, 0x8A}, ++{0x70E9, 0x6A}, ++{0x70EA, 0x07}, ++{0x70EB, 0x92}, ++{0x70EC, 0xCA}, ++{0x70ED, 0x6A}, ++{0x70EE, 0x00}, ++{0x70EF, 0x21}, ++{0x70F0, 0xC9}, ++{0x70F1, 0x43}, ++{0x70F2, 0x03}, ++{0x70F3, 0x92}, ++{0x70F4, 0x00}, ++{0x70F5, 0x22}, ++{0x70F6, 0x00}, ++{0x70F7, 0x91}, ++{0x70F8, 0x01}, ++{0x70F9, 0x92}, ++{0x70FA, 0x39}, ++{0x70FB, 0x46}, ++{0x70FC, 0x8F}, ++{0x70FD, 0xF6}, ++{0x70FE, 0xCE}, ++{0x70FF, 0xFB}, ++{0x7100, 0x01}, ++{0x7101, 0x22}, ++{0x7102, 0x00}, ++{0x7103, 0x23}, ++{0x7104, 0x8C}, ++{0x7105, 0xF6}, ++{0x7106, 0x02}, ++{0x7107, 0xFA}, ++{0x7108, 0x00}, ++{0x7109, 0x21}, ++{0x710A, 0x05}, ++{0x710B, 0x46}, ++{0x710C, 0x01}, ++{0x710D, 0x91}, ++{0x710E, 0x00}, ++{0x710F, 0x90}, ++{0x7110, 0x39}, ++{0x7111, 0x46}, ++{0x7112, 0x07}, ++{0x7113, 0x98}, ++{0x7114, 0x8F}, ++{0x7115, 0xF6}, ++{0x7116, 0xC2}, ++{0x7117, 0xFB}, ++{0x7118, 0x0D}, ++{0x7119, 0x9A}, ++{0x711A, 0xD3}, ++{0x711B, 0x17}, ++{0x711C, 0x80}, ++{0x711D, 0x18}, ++{0x711E, 0x59}, ++{0x711F, 0x41}, ++{0x7120, 0x01}, ++{0x7121, 0x22}, ++{0x7122, 0x00}, ++{0x7123, 0x23}, ++{0x7124, 0x8C}, ++{0x7125, 0xF6}, ++{0x7126, 0xCD}, ++{0x7127, 0xF9}, ++{0x7128, 0x07}, ++{0x7129, 0x90}, ++{0x712A, 0x00}, ++{0x712B, 0x20}, ++{0x712C, 0x01}, ++{0x712D, 0x90}, ++{0x712E, 0x00}, ++{0x712F, 0x95}, ++{0x7130, 0x39}, ++{0x7131, 0x46}, ++{0x7132, 0x03}, ++{0x7133, 0x98}, ++{0x7134, 0x8F}, ++{0x7135, 0xF6}, ++{0x7136, 0xB2}, ++{0x7137, 0xFB}, ++{0x7138, 0x01}, ++{0x7139, 0x22}, ++{0x713A, 0x00}, ++{0x713B, 0x23}, ++{0x713C, 0x8C}, ++{0x713D, 0xF6}, ++{0x713E, 0xE6}, ++{0x713F, 0xF9}, ++{0x7140, 0x02}, ++{0x7141, 0x46}, ++{0x7142, 0x07}, ++{0x7143, 0x98}, ++{0x7144, 0x00}, ++{0x7145, 0x23}, ++{0x7146, 0x81}, ++{0x7147, 0x0B}, ++{0x7148, 0x80}, ++{0x7149, 0x04}, ++{0x714A, 0x7A}, ++{0x714B, 0xF6}, ++{0x714C, 0x54}, ++{0x714D, 0xF8}, ++{0x714E, 0x37}, ++{0x714F, 0x4A}, ++{0x7150, 0x00}, ++{0x7151, 0x23}, ++{0x7152, 0x00}, ++{0x7153, 0x92}, ++{0x7154, 0x01}, ++{0x7155, 0x93}, ++{0x7156, 0x01}, ++{0x7157, 0x22}, ++{0x7158, 0x8C}, ++{0x7159, 0xF6}, ++{0x715A, 0xD8}, ++{0x715B, 0xF9}, ++{0x715C, 0x05}, ++{0x715D, 0x46}, ++{0x715E, 0x60}, ++{0x715F, 0x68}, ++{0x7160, 0x00}, ++{0x7161, 0x23}, ++{0x7162, 0x01}, ++{0x7163, 0x0C}, ++{0x7164, 0x00}, ++{0x7165, 0x04}, ++{0x7166, 0xE2}, ++{0x7167, 0x68}, ++{0x7168, 0x7A}, ++{0x7169, 0xF6}, ++{0x716A, 0x45}, ++{0x716B, 0xF8}, ++{0x716C, 0x00}, ++{0x716D, 0x22}, ++{0x716E, 0xD2}, ++{0x716F, 0x43}, ++{0x7170, 0x00}, ++{0x7171, 0x23}, ++{0x7172, 0x00}, ++{0x7173, 0x92}, ++{0x7174, 0x01}, ++{0x7175, 0x93}, ++{0x7176, 0x1A}, ++{0x7177, 0x46}, ++{0x7178, 0x8C}, ++{0x7179, 0xF6}, ++{0x717A, 0xC8}, ++{0x717B, 0xF9}, ++{0x717C, 0x29}, ++{0x717D, 0x46}, ++{0x717E, 0x8F}, ++{0x717F, 0xF6}, ++{0x7180, 0x8D}, ++{0x7181, 0xFB}, ++{0x7182, 0x8A}, ++{0x7183, 0x03}, ++{0x7184, 0x80}, ++{0x7185, 0x0C}, ++{0x7186, 0x10}, ++{0x7187, 0x43}, ++{0x7188, 0x00}, ++{0x7189, 0x22}, ++{0x718A, 0xD2}, ++{0x718B, 0x43}, ++{0x718C, 0x00}, ++{0x718D, 0x23}, ++{0x718E, 0x00}, ++{0x718F, 0x92}, ++{0x7190, 0x89}, ++{0x7191, 0x0C}, ++{0x7192, 0x01}, ++{0x7193, 0x93}, ++{0x7194, 0x1A}, ++{0x7195, 0x46}, ++{0x7196, 0x8C}, ++{0x7197, 0xF6}, ++{0x7198, 0xB9}, ++{0x7199, 0xF9}, ++{0x719A, 0x00}, ++{0x719B, 0x24}, ++{0x719C, 0x03}, ++{0x719D, 0x90}, ++{0x719E, 0x0C}, ++{0x719F, 0x98}, ++{0x71A0, 0x61}, ++{0x71A1, 0x00}, ++{0x71A2, 0x45}, ++{0x71A3, 0x5A}, ++{0x71A4, 0x06}, ++{0x71A5, 0x98}, ++{0x71A6, 0x22}, ++{0x71A7, 0x4A}, ++{0x71A8, 0x40}, ++{0x71A9, 0x5A}, ++{0x71AA, 0x00}, ++{0x71AB, 0x21}, ++{0x71AC, 0x8C}, ++{0x71AD, 0xF6}, ++{0x71AE, 0xBE}, ++{0x71AF, 0xF9}, ++{0x71B0, 0x07}, ++{0x71B1, 0x46}, ++{0x71B2, 0x28}, ++{0x71B3, 0x46}, ++{0x71B4, 0x03}, ++{0x71B5, 0x99}, ++{0x71B6, 0x8F}, ++{0x71B7, 0xF6}, ++{0x71B8, 0x71}, ++{0x71B9, 0xFB}, ++{0x71BA, 0x3A}, ++{0x71BB, 0x46}, ++{0x71BC, 0x00}, ++{0x71BD, 0x23}, ++{0x71BE, 0x79}, ++{0x71BF, 0xF6}, ++{0x71C0, 0xCA}, ++{0x71C1, 0xFF}, ++{0x71C2, 0x00}, ++{0x71C3, 0xE0}, ++{0x71C4, 0x0F}, ++{0x71C5, 0xE0}, ++{0x71C6, 0x8A}, ++{0x71C7, 0x02}, ++{0x71C8, 0x80}, ++{0x71C9, 0x0D}, ++{0x71CA, 0x10}, ++{0x71CB, 0x43}, ++{0x71CC, 0x19}, ++{0x71CD, 0x4A}, ++{0x71CE, 0x00}, ++{0x71CF, 0x23}, ++{0x71D0, 0x00}, ++{0x71D1, 0x92}, ++{0x71D2, 0x89}, ++{0x71D3, 0x0D}, ++{0x71D4, 0x01}, ++{0x71D5, 0x93}, ++{0x71D6, 0x40}, ++{0x71D7, 0x22}, ++{0x71D8, 0x8C}, ++{0x71D9, 0xF6}, ++{0x71DA, 0x98}, ++{0x71DB, 0xF9}, ++{0x71DC, 0xA1}, ++{0x71DD, 0x00}, ++{0x71DE, 0x64}, ++{0x71DF, 0x1C}, ++{0x71E0, 0x70}, ++{0x71E1, 0x50}, ++{0x71E2, 0x04}, ++{0x71E3, 0x2C}, ++{0x71E4, 0xDB}, ++{0x71E5, 0xD3}, ++{0x71E6, 0x14}, ++{0x71E7, 0x4D}, ++{0x71E8, 0x00}, ++{0x71E9, 0x24}, ++{0x71EA, 0x0B}, ++{0x71EB, 0x98}, ++{0x71EC, 0x67}, ++{0x71ED, 0x00}, ++{0x71EE, 0xC0}, ++{0x71EF, 0x5B}, ++{0x71F0, 0x2A}, ++{0x71F1, 0x46}, ++{0x71F2, 0x40}, ++{0x71F3, 0x21}, ++{0x71F4, 0x8C}, ++{0x71F5, 0xF6}, ++{0x71F6, 0x9A}, ++{0x71F7, 0xF9}, ++{0x71F8, 0x05}, ++{0x71F9, 0x99}, ++{0x71FA, 0x0E}, ++{0x71FB, 0x4A}, ++{0x71FC, 0xC8}, ++{0x71FD, 0x53}, ++{0x71FE, 0xA7}, ++{0x71FF, 0x00}, ++{0x7200, 0xF0}, ++{0x7201, 0x59}, ++{0x7202, 0x40}, ++{0x7203, 0x21}, ++{0x7204, 0x8C}, ++{0x7205, 0xF6}, ++{0x7206, 0x7B}, ++{0x7207, 0xF9}, ++{0x7208, 0x04}, ++{0x7209, 0x99}, ++{0x720A, 0x64}, ++{0x720B, 0x1C}, ++{0x720C, 0xC8}, ++{0x720D, 0x51}, ++{0x720E, 0x04}, ++{0x720F, 0x2C}, ++{0x7210, 0xEB}, ++{0x7211, 0xD3}, ++{0x7212, 0x0F}, ++{0x7213, 0xB0}, ++{0x7214, 0xF0}, ++{0x7215, 0xBD}, ++{0x7216, 0x00}, ++{0x7217, 0x00}, ++{0x7218, 0x76}, ++{0x7219, 0x69}, ++{0x721A, 0x18}, ++{0x721B, 0x00}, ++{0x721C, 0xEC}, ++{0x721D, 0x58}, ++{0x721E, 0x18}, ++{0x721F, 0x00}, ++{0x7220, 0x38}, ++{0x7221, 0x36}, ++{0x7222, 0x18}, ++{0x7223, 0x00}, ++{0x7224, 0x00}, ++{0x7225, 0x35}, ++{0x7226, 0x18}, ++{0x7227, 0x00}, ++{0x7228, 0x00}, ++{0x7229, 0x20}, ++{0x722A, 0x18}, ++{0x722B, 0x00}, ++{0x722C, 0xFF}, ++{0x722D, 0xFF}, ++{0x722E, 0xFF}, ++{0x722F, 0x3F}, ++{0x7230, 0xFF}, ++{0x7231, 0x07}, ++{0x7232, 0x00}, ++{0x7233, 0x00}, ++{0x7234, 0xFF}, ++{0x7235, 0xFF}, ++{0x7236, 0x07}, ++{0x7237, 0x00}, ++{0x7238, 0xFF}, ++{0x7239, 0x1F}, ++{0x723A, 0x00}, ++{0x723B, 0x00}, ++{0x723C, 0x01}, ++{0x723D, 0xF6}, ++{0x723E, 0x45}, ++{0x723F, 0x12}, ++{0x0000, 0x00}, ++}; +diff --git a/drivers/media/i2c/soc_camera/max9286.c b/drivers/media/i2c/soc_camera/max9286.c +index d01acdc..88eab02 100644 +--- a/drivers/media/i2c/soc_camera/max9286.c ++++ b/drivers/media/i2c/soc_camera/max9286.c +@@ -17,10 +17,8 @@ + #include + #include + +-#include + #include + #include +-#include + #include + + #include "max9286.h" +@@ -45,6 +43,7 @@ struct max9286_priv { + int csi_rate; + const char *fsync_mode; + int fsync_period; ++ int pclk; + char pclk_rising_edge; + int gpio_resetb; + int active_low_resetb; +@@ -53,12 +52,26 @@ struct max9286_priv { + int vsync; + int timeout; + int poc_delay; ++ int bws; ++ int dbl; ++ int dt; ++ int hsgen; ++ int hts; ++ int vts; ++ int hts_delay; ++ int imager_width; + atomic_t use_count; + u32 csi2_outord; ++ u32 switchin; + struct i2c_client *client; + int max9271_addr_map[4]; + int ser_id; + struct gpio_desc *poc_gpio[4]; /* PoC power supply */ ++ ++ /* link statistic */ ++ int prbserr[4]; ++ int deterr[4]; ++ int correrr[4]; + }; + + static char fsync_mode_default[20] = "manual"; /* manual, automatic, semi-automatic, external */ +@@ -95,9 +108,57 @@ static int active_low_resetb; + module_param(active_low_resetb, int, 0644); + MODULE_PARM_DESC(active_low_resetb, " Serializer GPIO reset level (default: 0 - active high)"); + +-static int poc_delay; ++static int poc_delay = 50; + module_param(poc_delay, int, 0644); +-MODULE_PARM_DESC(poc_delay, " Delay in ms after POC enable (default: 0 ms)"); ++MODULE_PARM_DESC(poc_delay, " Delay in ms after POC enable (default: 50 ms)"); ++ ++static int bws; ++module_param(bws, int, 0644); ++MODULE_PARM_DESC(bws, " BWS mode (default: 0 - 24-bit gmsl packets)"); ++ ++static int dbl = 1; ++module_param(dbl, int, 0644); ++MODULE_PARM_DESC(dbl, " DBL mode (default: 1 - DBL mode enabled)"); ++ ++static int dt = 3; ++module_param(dt, int, 0644); ++MODULE_PARM_DESC(dt, " DataType (default: 3 - YUV8), 0 - RGB888, 5 - RAW8, 6 - RAW10, 7 - RAW12, 8 - RAW14"); ++ ++static int hsgen; ++module_param(hsgen, int, 0644); ++MODULE_PARM_DESC(hsgen, " Enable HS embedded generator (default: 0 - disabled)"); ++ ++static int pclk = 100; ++module_param(pclk, int, 0644); ++MODULE_PARM_DESC(pclk, " PCLK rate (default: 100MHz)"); ++ ++static int switchin = 0; ++module_param(switchin, int, 0644); ++MODULE_PARM_DESC(switchin, " COAX SWITCH IN+ and IN- (default: 0 - not switched)"); ++ ++enum { ++ RGB888_DT = 0, ++ RGB565_DT, ++ RGB666_DT, ++ YUV8_DT, /* default */ ++ YUV10_DT, ++ RAW8_DT, ++ RAW10_DT, ++ RAW12_DT, ++ RAW14_DT, ++}; ++ ++static int dt2bpp [9] = { ++ 24, /* RGB888 */ ++ 16, /* RGB565 */ ++ 18, /* RGB666 */ ++ 8, /* YUV8 - default */ ++ 10, /* YUV10 */ ++ 8, /* RAW8/RAW16 */ ++ 10, /* RAW10 */ ++ 12, /* RAW12 */ ++ 14, /* RAW14 */ ++}; + + static char* ser_name(int id) + { +@@ -106,11 +167,42 @@ static char* ser_name(int id) + return "MAX9271"; + case MAX96705_ID: + return "MAX96705"; ++ case MAX96707_ID: ++ return "MAX96707"; + default: + return "unknown"; + } + } + ++static void max9286_write_remote_verify(struct i2c_client *client, int idx, u8 reg, u8 val) ++{ ++ struct max9286_priv *priv = i2c_get_clientdata(client); ++ int timeout; ++ ++ for (timeout = 0; timeout < 10; timeout++) { ++ int tmp_addr; ++ u8 sts = 0; ++ u8 val2 = 0; ++ ++ reg8_write(client, reg, val); ++ ++ tmp_addr = client->addr; ++ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ ++ reg8_read(client, 0x70, &sts); ++ client->addr = tmp_addr; ++ if (sts & BIT(idx)) /* if ACKed */ { ++ reg8_read(client, reg, &val2); ++ if (val2 == val) ++ break; ++ } ++ ++ usleep_range(1000, 1500); ++ } ++ ++ if (timeout >= 10) ++ dev_err(&client->dev, "timeout remote write acked\n"); ++} ++ + static void max9286_preinit(struct i2c_client *client, int addr) + { + struct max9286_priv *priv = i2c_get_clientdata(client); +@@ -118,8 +210,9 @@ static void max9286_preinit(struct i2c_client *client, int addr) + client->addr = addr; /* MAX9286-CAMx I2C */ + reg8_write(client, 0x0a, 0x00); /* disable reverse control for all cams */ + reg8_write(client, 0x00, 0x00); /* disable all GMSL links [0:3] */ +- usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ +- reg8_write(client, 0x1c, priv->him ? 0xf4 : 0x04); /* high-immunity or legacy mode */ ++// usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ reg8_write(client, 0x1b, priv->switchin); /* coax polarity (default - normal) */ ++ reg8_write(client, 0x1c, priv->him ? 0xf4 : 0x04); /* high-immunity/legacy mode, BWS: 24-bit */ + } + + static void max9286_sensor_reset(struct i2c_client *client, int addr, int reset_on) +@@ -142,11 +235,16 @@ static void max9286_postinit(struct i2c_client *client, int addr) + int idx; + + for (idx = 0; idx < priv->links; idx++) { ++ if (priv->ser_id == MAX96705_ID || priv->ser_id == MAX96707_ID) ++ continue; ++ + client->addr = priv->des_addr; /* MAX9286 I2C */ ++ reg8_write(client, 0x00, 0xe0 | BIT(idx)); /* enable GMSL link for CAMx */ + reg8_write(client, 0x0a, 0x11 << idx); /* enable reverse/forward control for CAMx */ ++ usleep_range(5000, 5500); /* wait 2ms after any change of reverse channel settings */ + + client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C */ +- max9286_sensor_reset(client, client->addr, 0); /* sensor unreset */ ++ max9286_sensor_reset(client, client->addr, 0); /* sensor unreset using gpios. TODO: should be in imager driver */ + } + + client->addr = addr; /* MAX9286 I2C */ +@@ -154,7 +252,9 @@ static void max9286_postinit(struct i2c_client *client, int addr) + reg8_write(client, 0x00, 0xe0 | priv->links_mask); /* enable GMSL link for CAMs */ + reg8_write(client, 0x0b, priv->csi2_outord); /* CSI2 output order */ + reg8_write(client, 0x15, 0x9b); /* enable CSI output, VC is set accordingly to Link number, BIT7 magic must be set */ +- reg8_write(client, 0x1b, priv->links_mask); /* enable equalizer for CAMs */ ++ reg8_write(client, 0x1b, priv->switchin | priv->links_mask); /* coax polarity, enable equalizer for CAMs */ ++ reg8_write(client, 0x1c, (priv->him ? 0xf0 : 0x00) | ++ (priv->bws ? 0x05 : 0x04)); /* high-immunity/legacy mode, BWS 24/32-bit */ + usleep_range(5000, 5500); /* wait 2ms after any change of reverse channel settings */ + + if (strcmp(priv->fsync_mode, "manual") == 0) { +@@ -178,7 +278,6 @@ static int max9286_reverse_channel_setup(struct i2c_client *client, int idx) + + /* Reverse channel enable */ + client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ +- reg8_write(client, 0x3f, 0x4f); /* enable custom reverse channel & first pulse length */ + reg8_write(client, 0x34, 0xa2 | MAXIM_I2C_I2C_SPEED); /* enable artificial ACKs, I2C speed set */ + usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ + reg8_write(client, 0x00, 0xe0 | BIT(idx)); /* enable GMSL link for CAMx */ +@@ -186,24 +285,35 @@ static int max9286_reverse_channel_setup(struct i2c_client *client, int idx) + usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ + + for (;;) { +- client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ +- reg8_write(client, 0x3b, 0x1e); /* first pulse length rise time changed from 300ns to 200ns, amplitude 100mV */ +- usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ if (priv->him) { ++ /* HIM mode setup */ ++ client->addr = 0x40; /* MAX9271-CAMx I2C */ ++ reg8_write(client, 0x4d, 0xc0); ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ reg8_write(client, 0x04, 0x43); /* wake-up, enable reverse_control/conf_link */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ } else { ++ /* Legacy mode setup */ ++ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ ++ reg8_write(client, 0x3f, 0x4f); /* enable custom reverse channel & first pulse length */ ++ reg8_write(client, 0x3b, 0x1e); /* first pulse length rise time changed from 300ns to 200ns, amplitude 100mV */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ + +- client->addr = 0x40; /* MAX9271-CAMx I2C */ +- reg8_write(client, 0x04, 0x43); /* wake-up, enable reverse_control/conf_link */ +- usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ +- reg8_write(client, 0x08, 0x01); /* reverse channel receiver high threshold enable */ +- reg8_write(client, 0x97, priv->him ? 0xaf : 0x5f); /* enable reverse control channel programming (MAX96705-MAX96711 only) */ +- usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ client->addr = 0x40; /* MAX9271-CAMx I2C */ ++ reg8_write(client, 0x04, 0x43); /* wake-up, enable reverse_control/conf_link */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ reg8_write(client, 0x08, 0x01); /* reverse channel receiver high threshold enable */ ++ reg8_write(client, 0x97, 0x5f); /* enable reverse control channel programming (MAX96705-MAX96711 only) */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ + +- client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ +- reg8_write(client, 0x3b, 0x19); /* reverse channel increase amplitude 170mV to compensate high threshold enabled */ +- usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ ++ reg8_write(client, 0x3b, 0x19); /* reverse channel increase amplitude 170mV to compensate high threshold enabled */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ } + + client->addr = 0x40; /* MAX9271-CAMx I2C */ + reg8_read(client, 0x1e, &val); /* read max9271 ID */ +- if (val == MAX9271_ID || val == MAX96705_ID || --timeout == 0) { ++ if (val == MAX9271_ID || val == MAX96705_ID || val == MAX96707_ID || --timeout == 0) { + priv->ser_id = val; + break; + } +@@ -211,7 +321,7 @@ static int max9286_reverse_channel_setup(struct i2c_client *client, int idx) + /* Check if already initialized (after reboot/reset ?) */ + client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C */ + reg8_read(client, 0x1e, &val); /* read max9271 ID */ +- if (val == MAX9271_ID || val == MAX96705_ID) { ++ if (val == MAX9271_ID || val == MAX96705_ID || val == MAX96707_ID) { + priv->ser_id = val; + reg8_write(client, 0x04, 0x43); /* enable reverse_control/conf_link */ + usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ +@@ -258,22 +368,9 @@ static void max9286_initial_setup(struct i2c_client *client) + client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ + reg8_write(client, 0x15, 0x13); /* disable CSI output, VC is set accordingly to Link number */ + reg8_write(client, 0x69, 0x0f); /* mask CSI forwarding from all links */ +- switch (priv->lanes) { +- case 1: +- reg8_write(client, 0x12, 0x33); /* enable CSI-2 Lane D0, DBL mode, YUV422 8-bit*/ +- break; +- case 2: +- reg8_write(client, 0x12, 0x73); /* enable CSI-2 Lanes D0,D1, DBL mode, YUV422 8-bit*/ +- break; +- case 3: +- reg8_write(client, 0x12, 0xd3); /* enable CSI-2 Lanes D0-D2, DBL mode, YUV422 8-bit*/ +- break; +- case 4: +- reg8_write(client, 0x12, 0xf3); /* enable CSI-2 Lanes D0-D3, DBL mode, YUV422 8-bit*/ +- break; +- default: +- dev_err(&client->dev, "CSI2 lanes number is invalid (%d)\n", priv->lanes); +- } ++ reg8_write(client, 0x12, ((priv->lanes - 1) << 6) | ++ (priv->dbl ? 0x30 : 0) | ++ (priv->dt & 0xf)); /* setup lanes, DBL mode, DataType */ + + /* Start GMSL initialization with FSYNC disabled. This is required for some odd LVDS cameras */ + reg8_write(client, 0x01, 0xc0); /* ECU (aka MCU) based FrameSync using GPI-to-GPO */ +@@ -294,30 +391,96 @@ static void max9286_gmsl_link_setup(struct i2c_client *client, int idx) + /* GMSL setup */ + client->addr = 0x40; /* MAX9271-CAMx I2C */ + reg8_write(client, 0x0d, 0x22 | MAXIM_I2C_I2C_SPEED); /* disable artificial ACK, I2C speed set */ +- reg8_write(client, 0x07, 0x84 | (priv->pclk_rising_edge ? 0 : 0x10)); /* RAW/YUV, PCLK edge, HS/VS encoding enabled */ ++ reg8_write(client, 0x07, 0x04 | (priv->pclk_rising_edge ? 0 : 0x10) | (priv->dbl ? 0x80 : 0)); /* RAW/YUV, PCLK edge, HS/VS encoding enabled, DBL mode, BWS 24-bit */ + usleep_range(2000, 2500); /* wait 2ms */ + reg8_write(client, 0x02, 0xff); /* spread spectrum +-4%, pclk range automatic, Gbps automatic */ + usleep_range(2000, 2500); /* wait 2ms */ + +- if (priv->ser_id == MAX96705_ID) { +- /* setup crossbar in DBL mode: reverse DVP bus */ +- reg8_write(client, 0x20, 0x07); +- reg8_write(client, 0x21, 0x06); +- reg8_write(client, 0x22, 0x05); +- reg8_write(client, 0x23, 0x04); +- reg8_write(client, 0x24, 0x03); +- reg8_write(client, 0x25, 0x02); +- reg8_write(client, 0x26, 0x01); +- reg8_write(client, 0x27, 0x00); +- +- reg8_write(client, 0x30, 0x17); +- reg8_write(client, 0x31, 0x16); +- reg8_write(client, 0x32, 0x15); +- reg8_write(client, 0x33, 0x14); +- reg8_write(client, 0x34, 0x13); +- reg8_write(client, 0x35, 0x12); +- reg8_write(client, 0x36, 0x11); +- reg8_write(client, 0x37, 0x10); ++ if (priv->ser_id == MAX96705_ID || priv->ser_id == MAX96707_ID) { ++ switch (priv->dt) { ++ case YUV8_DT: ++ /* setup crossbar for YUV8/RAW8: reverse DVP bus */ ++ reg8_write(client, 0x20, 7); ++ reg8_write(client, 0x21, 6); ++ reg8_write(client, 0x22, 5); ++ reg8_write(client, 0x23, 4); ++ reg8_write(client, 0x24, 3); ++ reg8_write(client, 0x25, 2); ++ reg8_write(client, 0x26, 1); ++ reg8_write(client, 0x27, 0); ++ ++ /* this is second byte if DBL=1 */ ++ reg8_write(client, 0x30, 23); ++ reg8_write(client, 0x31, 22); ++ reg8_write(client, 0x32, 21); ++ reg8_write(client, 0x33, 20); ++ reg8_write(client, 0x34, 19); ++ reg8_write(client, 0x35, 18); ++ reg8_write(client, 0x36, 17); ++ reg8_write(client, 0x37, 16); ++ ++ break; ++ case RAW12_DT: ++ /* setup crossbar for RAW12: reverse DVP bus */ ++ reg8_write(client, 0x20, 11); ++ reg8_write(client, 0x21, 10); ++ reg8_write(client, 0x22, 9); ++ reg8_write(client, 0x23, 8); ++ reg8_write(client, 0x24, 7); ++ reg8_write(client, 0x25, 6); ++ reg8_write(client, 0x26, 5); ++ reg8_write(client, 0x27, 4); ++ reg8_write(client, 0x28, 3); ++ reg8_write(client, 0x29, 2); ++ reg8_write(client, 0x2a, 1); ++ reg8_write(client, 0x2b, 0); ++ ++ /* this is second byte if DBL=1 */ ++ reg8_write(client, 0x30, 27); ++ reg8_write(client, 0x31, 26); ++ reg8_write(client, 0x32, 25); ++ reg8_write(client, 0x33, 24); ++ reg8_write(client, 0x34, 23); ++ reg8_write(client, 0x35, 22); ++ reg8_write(client, 0x36, 21); ++ reg8_write(client, 0x37, 20); ++ reg8_write(client, 0x38, 19); ++ reg8_write(client, 0x39, 18); ++ reg8_write(client, 0x3a, 17); ++ reg8_write(client, 0x3b, 16); ++ ++ if (!priv->bws && priv->dbl) ++ dev_err(&client->dev, " BWS must be 27/32-bit for RAW12 in DBL mode\n"); ++ ++ break; ++ } ++ ++ if (priv->hsgen) { ++ /* HS/VS pins map */ ++ reg8_write(client, 0x3f, 0x10); /* HS (NC) */ ++ reg8_write(client, 0x41, 0x10); /* DE (NC) */ ++ if (priv->ser_id == MAX96705_ID) ++ reg8_write(client, 0x40, 15); /* VS (DIN13) */ ++ if (priv->ser_id == MAX96707_ID) ++ reg8_write(client, 0x40, 13); /* VS (DIN13) */ ++#if 0 ++ /* following must come from imager */ ++#define SENSOR_WIDTH (1280*2) ++#define HTS (1288*2) ++#define VTS 960 ++#define HTS_DELAY 0x9 ++ reg8_write(client, 0x4e, HTS_DELAY >> 16); /* HS delay */ ++ reg8_write(client, 0x4f, (HTS_DELAY >> 8) & 0xff); ++ reg8_write(client, 0x50, HTS_DELAY & 0xff); ++ reg8_write(client, 0x54, SENSOR_WIDTH >> 8); /* HS high period */ ++ reg8_write(client, 0x55, SENSOR_WIDTH & 0xff); ++ reg8_write(client, 0x56, (HTS - SENSOR_WIDTH) >> 8); /* HS low period */ ++ reg8_write(client, 0x57, (HTS - SENSOR_WIDTH) & 0xff); ++ reg8_write(client, 0x58, VTS >> 8); /* HS count */ ++ reg8_write(client, 0x59, VTS & 0xff ); ++#endif ++ reg8_write(client, 0x43, 0x15); /* enable HS generator */ ++ } + } + + client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ +@@ -344,6 +507,9 @@ static void max9286_gmsl_link_setup(struct i2c_client *client, int idx) + client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C new */ + maxim_max927x_dump_regs(client); + #endif ++ reg8_write(client, 0x07, 0x04 | (priv->pclk_rising_edge ? 0 : 0x10) | ++ (priv->dbl ? 0x80 : 0) | ++ (priv->bws ? 0x20 : 0)); /* RAW/YUV, PCLK edge, HS/VS encoding enabled, DBL mode, BWS 24/32-bit */ + } + + static int max9286_initialize(struct i2c_client *client) +@@ -439,8 +605,8 @@ static int max9286_registered_async(struct v4l2_subdev *sd) + reg8_write(client, 0x0a, 0x11 << idx); /* enable reverse/forward control for CAMx */ + + client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx */ +- reg8_write(client, 0x04, conf_link ? 0x43 : 0x83); /* enable serial_link */ +- usleep_range(2000, 2500); /* wait 2ms after changing reverse_control */ ++ max9286_write_remote_verify(client, idx, 0x04, conf_link ? 0x43 : 0x83); ++// usleep_range(2000, 2500); /* wait 2ms after changing reverse_control */ + + client->addr = priv->des_addr; /* MAX9286 I2C */ + reg8_write(client, 0x0a, (priv->links_mask << 4) | priv->links_mask); /* enable reverse/forward control for all CAMs */ +@@ -491,7 +657,7 @@ static int max9286_parse_dt(struct i2c_client *client) + + for (i = 0; i < 4; i++) { + sprintf(poc_name, "POC%d", i); +- priv->poc_gpio[i] = devm_gpiod_get_optional(&client->dev, poc_name, 0); ++ priv->poc_gpio[i] = devm_gpiod_get_optional(&client->dev, kstrdup(poc_name, GFP_KERNEL), 0); + } + + reg8_read(client, 0x1e, &val); /* read max9286 ID */ +@@ -536,6 +702,19 @@ static int max9286_parse_dt(struct i2c_client *client) + priv->vsync = 1; + if (of_property_read_u32(np, "maxim,poc-delay", &priv->poc_delay)) + priv->poc_delay = 50; ++ if (of_property_read_u32(np, "maxim,bws", &priv->bws)) ++ priv->bws = 0; ++ if (of_property_read_u32(np, "maxim,dbl", &priv->dbl)) ++ priv->dbl = 1; ++ if (of_property_read_u32(np, "maxim,dt", &priv->dt)) ++ priv->dt = 3; ++ if (of_property_read_u32(np, "maxim,hsgen", &priv->hsgen)) ++ priv->hsgen = 0; ++ if (of_property_read_u32(np, "maxim,pclk", &priv->pclk)) ++ priv->pclk = pclk; ++ if (of_property_read_u32(np, "maxim,switchin", &priv->switchin)) ++ priv->switchin = 0; ++ + + /* module params override dts */ + if (him) +@@ -554,6 +733,18 @@ static int max9286_parse_dt(struct i2c_client *client) + priv->active_low_resetb = active_low_resetb; + if (poc_delay) + priv->poc_delay = poc_delay; ++ if (bws) ++ priv->bws = bws; ++ if (!dbl) ++ priv->dbl = dbl; ++ if (dt != 3) ++ priv->dt = dt; ++ if (hsgen) ++ priv->hsgen = hsgen; ++ if (pclk != 100) ++ priv->pclk = pclk; ++ if (switchin) ++ priv->switchin = switchin; + + for (i = 0; i < priv->links; i++) { + endpoint = of_graph_get_next_endpoint(np, endpoint); +@@ -592,8 +783,8 @@ static void max9286_setup_remote_endpoint(struct i2c_client *client) + + csi_rate_prop = of_find_property(endpoint, "csi-rate", NULL); + if (csi_rate_prop) { +- /* CSI2_RATE = PCLK*sizeof(YUV8)*links/lanes */ +- priv->csi_rate = cpu_to_be32(100 * 8 * hweight8(priv->links_mask) / priv->lanes); ++ /* CSI2_RATE = PCLK*bpp*links/lanes */ ++ priv->csi_rate = cpu_to_be32(priv->pclk * dt2bpp[priv->dt] * hweight8(priv->links_mask) / priv->lanes); + csi_rate_prop->value = &priv->csi_rate; + of_update_property(rendpoint, csi_rate_prop); + } +@@ -606,6 +797,86 @@ static void max9286_setup_remote_endpoint(struct i2c_client *client) + of_node_put(endpoint); + } + ++static const char *line_status[] = ++{ ++ "BAT", ++ "GND", ++ "NORMAL", ++ "OPEN" ++}; ++ ++static ssize_t max9286_link_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ int i = -1; ++ u8 val = 0; ++ bool lenghterr, linebuffof, hlocked, prbsok, vsyncdet, configdet, videodet; ++ int lf; ++ u8 prbserr = 0, deterr = 0, correrr = 0; ++ struct i2c_client *client = to_i2c_client(dev); ++ struct max9286_priv *priv = i2c_get_clientdata(client); ++ ++ if (!sscanf(attr->attr.name, "link_%d", &i)) ++ return -EINVAL; ++ ++ if ((i < 0) || (i > 3)) ++ return -EINVAL; ++ ++ reg8_read(client, 0x20, &val); ++ lf = (val >> (2 * i)) & 0x03; ++ ++ reg8_read(client, 0x21, &val); ++ hlocked = !!(val & (1 << i)); ++ prbsok = !!(val & (1 << (i + 4))); ++ ++ reg8_read(client, 0x22, &val); ++ lenghterr = !!(val & (1 << i)); ++ linebuffof = !!(val & (1 << (i + 4))); ++ ++ reg8_read(client, 0x23 + i, &prbserr); ++ priv->prbserr[i] += prbserr; ++ ++ reg8_read(client, 0x27, &val); ++ vsyncdet = !!(val & (1 << i)); ++ ++ reg8_read(client, 0x28 + i, &deterr); ++ priv->deterr[i] += deterr; ++ ++ reg8_read(client, 0x2c + i, &correrr); ++ priv->correrr[i] += correrr; ++ ++ reg8_read(client, 0x49, &val); ++ configdet = !!(val & (1 << i)); ++ videodet = !!(val & (1 << (i + 4))); ++ ++ return sprintf(buf, "LINK:%d LF:%s HLOCKED:%d PRBSOK:%d LINBUFFOF:%d" ++ " LENGHTERR:%d VSYNCDET:%d CONFIGDET:%d VIDEODET:%d" ++ " PRBSERR:%d(%d) DETEERR:%d(%d) CORRERR:%d(%d)\n", ++ i, line_status[lf], hlocked, prbsok, lenghterr, ++ linebuffof, vsyncdet, configdet, videodet, ++ priv->prbserr[i], prbserr, ++ priv->deterr[i], deterr, ++ priv->correrr[i], correrr); ++ return 0; ++} ++ ++static DEVICE_ATTR(link_0, S_IRUGO, max9286_link_show, NULL); ++static DEVICE_ATTR(link_1, S_IRUGO, max9286_link_show, NULL); ++static DEVICE_ATTR(link_2, S_IRUGO, max9286_link_show, NULL); ++static DEVICE_ATTR(link_3, S_IRUGO, max9286_link_show, NULL); ++ ++static struct attribute *max9286_attributes_links[] = { ++ &dev_attr_link_0.attr, ++ &dev_attr_link_1.attr, ++ &dev_attr_link_2.attr, ++ &dev_attr_link_3.attr, ++ NULL ++}; ++ ++static const struct attribute_group max9286_group = { ++ .attrs = max9286_attributes_links, ++}; ++ + static int max9286_probe(struct i2c_client *client, + const struct i2c_device_id *did) + { +@@ -648,6 +919,11 @@ static int max9286_probe(struct i2c_client *client, + if (err < 0) + goto out; + } ++ ++ err = sysfs_create_group(&client->dev.kobj, ++ &max9286_group); ++ if (err < 0) ++ dev_err(&client->dev, "Sysfs registration failed\n"); + out: + return err; + } +@@ -657,6 +933,8 @@ static int max9286_remove(struct i2c_client *client) + struct max9286_priv *priv = i2c_get_clientdata(client); + int i; + ++ sysfs_remove_group(&client->dev.kobj, &max9286_group); ++ + for (i = 0; i < 4; i++) { + v4l2_async_unregister_subdev(&priv->sd[i]); + v4l2_device_unregister_subdev(&priv->sd[i]); +diff --git a/drivers/media/i2c/soc_camera/max9286.h b/drivers/media/i2c/soc_camera/max9286.h +index 6c2a9e0..2875b3c 100644 +--- a/drivers/media/i2c/soc_camera/max9286.h ++++ b/drivers/media/i2c/soc_camera/max9286.h +@@ -24,6 +24,7 @@ + #define REG16_NUM_RETRIES 10 /* number of read/write retries */ + #define MAX9271_ID 0x9 + #define MAX96705_ID 0x41 ++#define MAX96707_ID 0x45 /* MAX96715: there is no HS pin */ + #define MAX9286_ID 0x40 + #define BROADCAST 0x6f + +diff --git a/drivers/media/i2c/soc_camera/ov10635.c b/drivers/media/i2c/soc_camera/ov10635.c +index 8289b76..916173c 100644 +--- a/drivers/media/i2c/soc_camera/ov10635.c ++++ b/drivers/media/i2c/soc_camera/ov10635.c +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + + #include "max9286.h" + #include "ov10635.h" +@@ -44,8 +43,7 @@ struct ov10635_priv { + /* serializers */ + int max9286_addr; + int max9271_addr; +- int ti964_addr; +- int ti954_addr; ++ int ti9x4_addr; + int ti9x3_addr; + int port; + int gpio_resetb; +@@ -429,13 +427,11 @@ static int ov10635_s_ctrl(struct v4l2_ctrl *ctrl) + break; + case V4L2_CID_HFLIP: + ret = reg16_read(client, 0x381d, &val); +- if (ret < 0) +- goto out; + if (ctrl->val) + val |= 0x3; + else + val &= ~0x3; +- ret = reg16_write(client, 0x381d, val); ++ ret |= reg16_write(client, 0x381d, val); + break; + case V4L2_CID_VFLIP: + ret = reg16_read(client, 0x381c, &val); +@@ -443,14 +439,13 @@ static int ov10635_s_ctrl(struct v4l2_ctrl *ctrl) + val |= 0xc0; + else + val &= ~0xc0; +- ret = reg16_write(client, 0x381c, val); ++ ret |= reg16_write(client, 0x381c, val); + break; + case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: + ret = 0; + break; + } + +-out: + return ret; + } + +@@ -567,21 +562,15 @@ static int ov10635_parse_dt(struct device_node *np, struct ov10635_priv *priv) + break; + + if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && +- !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti964-ti9x3") && +- !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti964_addr) && +- !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) +- break; +- +- if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && +- !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti954-ti9x3") && +- !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti954_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && + !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) + break; + } + + of_node_put(endpoint); + +- if (!priv->max9286_addr && !priv->ti964_addr && !priv->ti954_addr) { ++ if (!priv->max9286_addr && !priv->ti9x4_addr) { + dev_err(&client->dev, "deserializer does not present for OV10635\n"); + return -EINVAL; + } +@@ -598,19 +587,8 @@ static int ov10635_parse_dt(struct device_node *np, struct ov10635_priv *priv) + usleep_range(2000, 2500); /* wait 2ms */ + }; + +- if (priv->ti964_addr) { +- client->addr = priv->ti964_addr; /* Deserializer I2C address */ +- +- reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ +- usleep_range(2000, 2500); /* wait 2ms */ +- reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ +- reg8_write(client, 0x5d, OV10635_I2C_ADDR << 1); /* Sensor native I2C address */ +- +- reg8_write(client, 0x6e, 0xa9); /* GPIO0 - resetb, GPIO1 - fsin */ +- } +- +- if (priv->ti954_addr) { +- client->addr = priv->ti954_addr; /* Deserializer I2C address */ ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ + + reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ + usleep_range(2000, 2500); /* wait 2ms */ +diff --git a/drivers/media/i2c/soc_camera/ov10635.h b/drivers/media/i2c/soc_camera/ov10635.h +index a0e510d..a74f360 100644 +--- a/drivers/media/i2c/soc_camera/ov10635.h ++++ b/drivers/media/i2c/soc_camera/ov10635.h +@@ -17,13 +17,13 @@ + #define OV10635_MAX_WIDTH 1280 + #define OV10635_MAX_HEIGHT 800 + +-//#define OV10635_PCLK_96MHZ +-#define OV10635_PCLK_88MHZ ++#define OV10635_PCLK_96MHZ ++//#define OV10635_PCLK_88MHZ + + #if defined(OV10635_PCLK_96MHZ) +-/* VTS=PCLK/FPS/HTS/2 (=96MHz/30/1600/2) */ +- #define OV10635_HTS 1600 +- #define OV10635_VTS 1000 /* fps=30 */ ++/* VTS=PCLK/FPS/HTS/2 (=96MHz/30/1750/2) */ ++ #define OV10635_HTS 1750 ++ #define OV10635_VTS 914 /* fps=30 */ + #elif defined(OV10635_PCLK_88MHZ) + /* VTS=PCLK/FPS/HTS/2 (=88MHz/1572/30/2) */ + #define OV10635_HTS 1572 +diff --git a/drivers/media/i2c/soc_camera/ov106xx.c b/drivers/media/i2c/soc_camera/ov106xx.c +index fa775ae..c7bd92e 100644 +--- a/drivers/media/i2c/soc_camera/ov106xx.c ++++ b/drivers/media/i2c/soc_camera/ov106xx.c +@@ -13,18 +13,32 @@ + #include "ov490_ov10640.c" + #include "ov495_ov2775.c" + #include "ar0132.c" ++#include "ar0140.c" ++#include "ar0143.c" + #include "ar0220.c" ++#include "ar0231.c" ++#include "ar0233.c" + #include "ap0101_ar014x.c" ++#include "gw4200_ar014x.c" + #include "ov2775.c" ++#include "imx390.c" ++#include "ox03a.c" + + static enum { + ID_OV10635, + ID_OV490_OV10640, + ID_OV495_OV2775, + ID_AR0132, ++ ID_AR0140, ++ ID_AR0143, + ID_AR0220, ++ ID_AR0231, ++ ID_AR0233, + ID_AP0101_AR014X, ++ ID_GW4200_AR014X, + ID_OV2775, ++ ID_IMX390, ++ ID_OX03A, + } chip_id; + + static int ov106xx_probe(struct i2c_client *client, +@@ -57,24 +71,66 @@ static int ov106xx_probe(struct i2c_client *client, + goto out; + } + ++ ret = ar0140_probe(client, did); ++ if (!ret) { ++ chip_id = ID_AR0140; ++ goto out; ++ } ++ ++ ret = ar0143_probe(client, did); ++ if (!ret) { ++ chip_id = ID_AR0143; ++ goto out; ++ } ++ + ret = ar0220_probe(client, did); + if (!ret) { + chip_id = ID_AR0220; + goto out; + } + ++ ret = ar0233_probe(client, did); ++ if (!ret) { ++ chip_id = ID_AR0233; ++ goto out; ++ } ++ ++ ret = ar0231_probe(client, did); ++ if (!ret) { ++ chip_id = ID_AR0231; ++ goto out; ++ } ++ + ret = ap0101_probe(client, did); + if (!ret) { + chip_id = ID_AP0101_AR014X; + goto out; + } + ++ ret = gw4200_probe(client, did); ++ if (!ret) { ++ chip_id = ID_GW4200_AR014X; ++ goto out; ++ } ++ + ret = ov2775_probe(client, did); + if (!ret) { + chip_id = ID_OV2775; + goto out; + } + ++ ret = imx390_probe(client, did); ++ if (!ret) { ++ chip_id = ID_IMX390; ++ goto out; ++ } ++ ++ ret = ox03a_probe(client, did); ++ if (!ret) { ++ chip_id = ID_OX03A; ++ goto out; ++ } ++ + v4l_err(client, "failed to probe @ 0x%02x (%s)\n", + client->addr, client->adapter->name); + out: +@@ -96,15 +152,36 @@ static int ov106xx_remove(struct i2c_client *client) + case ID_AR0132: + ar0132_remove(client); + break; ++ case ID_AR0140: ++ ar0140_remove(client); ++ break; ++ case ID_AR0143: ++ ar0143_remove(client); ++ break; + case ID_AR0220: + ar0220_remove(client); + break; ++ case ID_AR0231: ++ ar0231_remove(client); ++ break; ++ case ID_AR0233: ++ ar0233_remove(client); ++ break; + case ID_AP0101_AR014X: + ap0101_remove(client); + break; ++ case ID_GW4200_AR014X: ++ gw4200_remove(client); ++ break; + case ID_OV2775: + ov2775_remove(client); + break; ++ case ID_IMX390: ++ imx390_remove(client); ++ break; ++ case ID_OX03A: ++ ox03a_remove(client); ++ break; + }; + + return 0; +@@ -134,6 +211,6 @@ static struct i2c_driver ov106xx_i2c_driver = { + + module_i2c_driver(ov106xx_i2c_driver); + +-MODULE_DESCRIPTION("SoC Camera driver for OV10635, OV490/OV10640, OV495/OV2775, AR0132, AR0220, AP0101/AR014X"); ++MODULE_DESCRIPTION("SoC Camera driver for OV10635, OV490+OV10640, OV495+OV2775, AR0132/140/143/220/223, AP0101+AR014X"); + MODULE_AUTHOR("Vladimir Barinov"); + MODULE_LICENSE("GPL"); +diff --git a/drivers/media/i2c/soc_camera/ov2775.c b/drivers/media/i2c/soc_camera/ov2775.c +index cb41764..2022d47 100644 +--- a/drivers/media/i2c/soc_camera/ov2775.c ++++ b/drivers/media/i2c/soc_camera/ov2775.c +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + + #include "ov2775.h" + +@@ -29,7 +28,7 @@ + #define OV2775_VER 0x300b + #define OV2775_VERSION_REG 0x2770 + +-#define OV2775_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR8_1X8 ++#define OV2775_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR12_1X12 + + struct ov2775_priv { + struct v4l2_subdev sd; +@@ -319,6 +318,7 @@ static int ov2775_initialize(struct i2c_client *client) + u8 val = 0; + u16 pid; + int ret = 0; ++ int tmp_addr; + + /* check and show model ID */ + reg16_read(client, OV2775_PID, &val); +@@ -332,6 +332,16 @@ static int ov2775_initialize(struct i2c_client *client) + goto err; + } + ++ /* setup XCLK */ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ /* CLK_OUT=22.5792*160*M/N/CLKDIV -> CLK_OUT=25MHz: CLKDIV=4, M=7, N=253: 22.5792*160/4*7/253=24.989MHz=CLK_OUT */ ++ client->addr = priv->ti9x3_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x06, 0x47); /* Set CLKDIV and M */ ++ reg8_write(client, 0x07, 0xfd); /* Set N */ ++ } ++ client->addr = tmp_addr; ++ + /* Program wizard registers */ + ov2775_set_regs(client, ov2775_regs_wizard, ARRAY_SIZE(ov2775_regs_wizard)); + /* Read OTP IDs */ +diff --git a/drivers/media/i2c/soc_camera/ov2775.h b/drivers/media/i2c/soc_camera/ov2775.h +index 1cdfb50..7e1ee31 100644 +--- a/drivers/media/i2c/soc_camera/ov2775.h ++++ b/drivers/media/i2c/soc_camera/ov2775.h +@@ -1,5 +1,5 @@ + /* +- * OmniVision OV2775 sensor camera wizard 1928x1088@30/RGGB/MIPI ++ * OmniVision OV2775 sensor camera wizard 1920x1080@30/BGGR/MIPI + * + * Copyright (C) 2018 Cogent Embedded, Inc. + * +@@ -9,29 +9,29 @@ + * option) any later version. + */ + +-//#define OV2775_DISPLAY_PATTERN_COLOR_BAR ++#define OV2775_DISPLAY_PATTERN_COLOR_BAR + +-#define OV2775_MAX_WIDTH 2880 // (1928*1.5=2892) <- must be multiple of 16 - requred by R-CAR VIN +-#define OV2775_MAX_HEIGHT 1088 ++#define OV2775_MAX_WIDTH 1920 ++#define OV2775_MAX_HEIGHT 1080 + + #define OV2775_DELAY 0xffff +-#define OV2775_DT 0x2c // MIPI Data Type ++#define OV2775_DT 0x2c /* MIPI Data Type RAW12 */ + + struct ov2775_reg { + u16 reg; + u8 val; + }; + +-/* wizard: MIPI 1928x1088 RAW12 Linear 30fps 960Mbps */ ++/* wizard: MIPI 1920x1080 RAW12 Linear 30fps 600Mbps XCLK=25MHz */ + static const struct ov2775_reg ov2775_regs_wizard[] = { + {0x3013, 0x01}, // s/w reset + {OV2775_DELAY, 10}, // Wait 10ms +-{0x3000, 0x02}, +-{0x3001, 0x28}, +-{0x3002, 0x03}, ++{0x3000, 0x03}, ++{0x3001, 0x18}, ++{0x3002, 0x01}, + {0x3003, 0x01}, +-{0x3004, 0x02}, +-{0x3005, 0x26}, ++{0x3004, 0x03}, ++{0x3005, 0x1c}, + {0x3006, 0x00}, + {0x3007, 0x07}, + {0x3008, 0x01}, +@@ -41,7 +41,7 @@ static const struct ov2775_reg ov2775_regs_wizard[] = { + {0x300f, 0x00}, + {0x3012, 0x00}, + {0x3013, 0x00}, +-{0x3014, 0xc4}, ++{0x3014, 0x44}, + {0x3015, 0x00}, + {0x3017, 0x00}, + {0x3018, 0x00}, +@@ -328,7 +328,7 @@ static const struct ov2775_reg ov2775_regs_wizard[] = { + {0x320d, 0x1e}, + {0x320e, 0x30}, + {0x320f, 0x2d}, +-{0x3210, OV2775_DT}, ++{0x3210, 0x2c}, + {0x3211, 0x2b}, + {0x3212, 0x2a}, + {0x3213, 0x24}, +@@ -358,7 +358,7 @@ static const struct ov2775_reg ov2775_regs_wizard[] = { + {0x3251, 0x00}, + {0x3252, 0x20}, + #ifdef OV2775_DISPLAY_PATTERN_COLOR_BAR +-{0x3253, 0x80}, ++{0x3253, 0xC0}, + #else + {0x3253, 0x00}, + #endif +@@ -1822,9 +1822,9 @@ static const struct ov2775_reg ov2775_regs_wizard[] = { + {0x30a9, 0x04}, + {0x30aa, 0x00}, + {0x30ab, 0x04}, +-{0x30ac, 0x07}, ++{0x30ac, 0x07}, /* OV2775_MAX_WIDTH */ + {0x30ad, 0x88}, +-{0x30ae, 0x04}, ++{0x30ae, 0x04}, /* OV2775_MAX_HEIGHT */ + {0x30af, 0x40}, + {0x30b0, 0x0d}, + {0x30b1, 0xde}, +diff --git a/drivers/media/i2c/soc_camera/ov490_ov10640.c b/drivers/media/i2c/soc_camera/ov490_ov10640.c +index 4b51a92..1c8aac8 100644 +--- a/drivers/media/i2c/soc_camera/ov490_ov10640.c ++++ b/drivers/media/i2c/soc_camera/ov490_ov10640.c +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + + #include "max9286.h" + #include "ov490_ov10640.h" +diff --git a/drivers/media/i2c/soc_camera/ov495_ov2775.c b/drivers/media/i2c/soc_camera/ov495_ov2775.c +index 32b5078..34b2f46 100644 +--- a/drivers/media/i2c/soc_camera/ov495_ov2775.c ++++ b/drivers/media/i2c/soc_camera/ov495_ov2775.c +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + + #include "ov495_ov2775.h" + +@@ -403,6 +402,7 @@ static int ov495_initialize(struct i2c_client *client) + struct ov495_priv *priv = to_ov495(client); + u8 pid = 0, ver = 0; + int ret = 0; ++// int tmp_addr; + + /* check and show product ID and manufacturer ID */ + reg16_write(client, 0xFFFD, 0x80); +@@ -417,6 +417,18 @@ static int ov495_initialize(struct i2c_client *client) + goto err; + } + ++#if 0 ++ /* setup XCLK */ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ /* CLK_OUT=22.5792*160*M/N/CLKDIV -> CLK_OUT=25MHz: CLKDIV=4, M=7, N=253: 22.5792*160/4*7/253=24.989MHz=CLK_OUT */ ++ client->addr = priv->ti9x3_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x06, 0x47); /* Set CLKDIV and M */ ++ reg8_write(client, 0x07, 0xfd); /* Set N */ ++ } ++ client->addr = tmp_addr; ++#endif ++ + if (unlikely(force_conf_link)) + goto out; + +@@ -439,7 +451,7 @@ static int ov495_initialize(struct i2c_client *client) + #endif + + /* set virtual channel */ +- ov495_regs_wizard[3].val = 0x1e | (priv->port << 6); ++// ov495_regs_wizard[3].val = 0x1e | (priv->port << 6); + /* Program wizard registers */ + ov495_set_regs(client, ov495_regs_wizard, ARRAY_SIZE(ov495_regs_wizard)); + /* Read OTP IDs */ +diff --git a/drivers/media/i2c/soc_camera/ox03a.c b/drivers/media/i2c/soc_camera/ox03a.c +new file mode 100644 +index 0000000..162c75b +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ox03a.c +@@ -0,0 +1,589 @@ ++/* ++ * OmniVision OX03A sensor camera driver ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "ox03a.h" ++ ++#define OX03A_I2C_ADDR 0x36 ++ ++#define OX03A_PID 0x300A ++#define OX03A_VER 0x300B ++#define OX03A_VERSION_REG 0x5803 ++ ++#define OX03A_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR16_1X16 ++ ++struct ox03a_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int init_complete; ++ u8 id[6]; ++ int exposure; ++ int gain; ++ int autogain; ++ /* serializers */ ++ int ti9x4_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++}; ++ ++static inline struct ox03a_priv *to_ox03a(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct ox03a_priv, sd); ++} ++ ++static int ox03a_set_regs(struct i2c_client *client, ++ const struct ox03a_reg *regs, int nr_regs) ++{ ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (regs[i].reg == OX03A_DELAY) { ++ mdelay(regs[i].val); ++ continue; ++ } ++ ++ reg16_write(client, regs[i].reg, regs[i].val); ++ } ++ ++ return 0; ++} ++ ++static int ox03a_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int ox03a_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ox03a_priv *priv = to_ox03a(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = OX03A_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int ox03a_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = OX03A_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int ox03a_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = OX03A_MEDIA_BUS_FMT; ++ ++ return 0; ++} ++ ++static int ox03a_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ox03a_priv *priv = to_ox03a(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = OX03A_VERSION_REG >> 8; ++ edid->edid[9] = OX03A_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int ox03a_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ox03a_priv *priv = to_ox03a(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > OX03A_MAX_WIDTH) || ++ (rect->top + rect->height > OX03A_MAX_HEIGHT)) ++ *rect = priv->rect; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ return 0; ++} ++ ++static int ox03a_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ox03a_priv *priv = to_ox03a(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = OX03A_MAX_WIDTH; ++ sel->r.height = OX03A_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = OX03A_MAX_WIDTH; ++ sel->r.height = OX03A_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ox03a_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int ox03a_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u8 val = 0; ++ ++ ret = reg16_read(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u8); ++ ++ return 0; ++} ++ ++static int ox03a_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return reg16_write(client, (u16)reg->reg, (u8)reg->val); ++} ++#endif ++ ++static struct v4l2_subdev_core_ops ox03a_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ox03a_g_register, ++ .s_register = ox03a_s_register, ++#endif ++}; ++ ++static int ox03a_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ox03a_priv *priv = to_ox03a(client); ++ int ret = -EINVAL; ++ u8 val = 0; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ case V4L2_CID_CONTRAST: ++ case V4L2_CID_SATURATION: ++ case V4L2_CID_HUE: ++ case V4L2_CID_GAMMA: ++ case V4L2_CID_SHARPNESS: ++ case V4L2_CID_AUTOGAIN: ++ break; ++ case V4L2_CID_GAIN: ++ /* start recording group3 */ ++ ret = reg16_write(client, 0x3208, 0x03); ++ /* HCG real gain */ ++ ret |= reg16_write(client, 0x3508, ctrl->val >> 8); ++ ret |= reg16_write(client, 0x3509, ctrl->val & 0xff); ++ /* HCG digital gain */ ++ ret |= reg16_write(client, 0x350a, ctrl->val >> 8); ++ ret |= reg16_write(client, 0x350b, ctrl->val & 0xff); ++ /* LCG real gain */ ++ ret |= reg16_write(client, 0x3548, ctrl->val >> 8); ++ ret |= reg16_write(client, 0x3549, ctrl->val & 0xff); ++ /* LCG digital gain */ ++ ret |= reg16_write(client, 0x354a, ctrl->val >> 8); ++ ret |= reg16_write(client, 0x354b, ctrl->val & 0xff); ++ /* VS real gain */ ++ ret |= reg16_write(client, 0x3588, ctrl->val >> 8); ++ ret |= reg16_write(client, 0x3589, ctrl->val & 0xff); ++ /* VS digital gain */ ++ ret |= reg16_write(client, 0x358a, ctrl->val >> 8); ++ ret |= reg16_write(client, 0x358b, ctrl->val & 0xff); ++ /* stop recording and launch group3 */ ++ ret |= reg16_write(client, 0x3208, 0x13); ++ ret |= reg16_write(client, 0x3208, 0xe3); ++ break; ++ case V4L2_CID_EXPOSURE: ++ /* start recording group3 */ ++ ret = reg16_write(client, 0x3208, 0x03); ++ /* HCG (long) exposure time */ ++ ret |= reg16_write(client, 0x3501, ctrl->val >> 8); ++ ret |= reg16_write(client, 0x3502, ctrl->val & 0xff); ++ /* VS exposure time */ ++// ret |= reg16_write(client, 0x3581, ctrl->val >> 8); ++// ret |= reg16_write(client, 0x3582, ctrl->val & 0xff); ++ /* stop recording and launch group3 */ ++ ret |= reg16_write(client, 0x3208, 0x13); ++ ret |= reg16_write(client, 0x3208, 0xe3); ++ break; ++ case V4L2_CID_HFLIP: ++ /* start recording group3 */ ++ ret = reg16_write(client, 0x3208, 0x03); ++ ret = reg16_read(client, 0x3821, &val); ++ if (ctrl->val) ++ val |= 0x04; ++ else ++ val &= ~0x04; ++ ret |= reg16_write(client, 0x3821, val); ++ /* hflip channges CFA, hence compensate it by moving crop window over bayer matrix */ ++ ret |= reg16_read(client, 0x3811, &val); ++ if (ctrl->val) ++ val++; ++ else ++ val--; ++ ret |= reg16_write(client, 0x3811, val); ++ /* stop recording and launch group3 */ ++ ret |= reg16_write(client, 0x3208, 0x13); ++ ret |= reg16_write(client, 0x3208, 0xe3); ++ break; ++ case V4L2_CID_VFLIP: ++ ret = reg16_read(client, 0x3820, &val); ++ if (ctrl->val) ++ val |= 0x44; ++ else ++ val &= ~0x44; ++ ret |= reg16_write(client, 0x3820, val); ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ox03a_ctrl_ops = { ++ .s_ctrl = ox03a_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops ox03a_video_ops = { ++ .s_stream = ox03a_s_stream, ++ .g_mbus_config = ox03a_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops ox03a_subdev_pad_ops = { ++ .get_edid = ox03a_get_edid, ++ .enum_mbus_code = ox03a_enum_mbus_code, ++ .get_selection = ox03a_get_selection, ++ .set_selection = ox03a_set_selection, ++ .get_fmt = ox03a_get_fmt, ++ .set_fmt = ox03a_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops ox03a_subdev_ops = { ++ .core = &ox03a_core_ops, ++ .video = &ox03a_video_ops, ++ .pad = &ox03a_subdev_pad_ops, ++}; ++ ++static void ox03a_otp_id_read(struct i2c_client *client) ++{ ++} ++ ++static ssize_t ox03a_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ox03a_priv *priv = to_ox03a(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_ox03a, S_IRUGO, ox03a_otp_id_show, NULL); ++ ++static int ox03a_initialize(struct i2c_client *client) ++{ ++ struct ox03a_priv *priv = to_ox03a(client); ++ u8 val = 0; ++ u16 pid; ++ int ret = 0; ++ ++ /* check and show model ID */ ++ reg16_read(client, OX03A_PID, &val); ++ pid = val; ++ reg16_read(client, OX03A_VER, &val); ++ pid = (pid << 8) | val; ++ ++ if (pid != OX03A_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x\n", pid); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ /* Program wizard registers */ ++ ox03a_set_regs(client, ox03a_regs_wizard_r1a, ARRAY_SIZE(ox03a_regs_wizard_r1a)); ++ /* Read OTP IDs */ ++ ox03a_otp_id_read(client); ++ ++ dev_info(&client->dev, "ox03a PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, OX03A_MAX_WIDTH, OX03A_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ return ret; ++} ++ ++static int ox03a_parse_dt(struct device_node *np, struct ox03a_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ of_node_put(endpoint); ++ ++ if (!priv->ti9x4_addr) { ++ dev_err(&client->dev, "deserializer does not present\n"); ++ return -EINVAL; ++ } ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, OX03A_I2C_ADDR << 1); /* Sensor native I2C address */ ++// reg8_write(client, 0x6e, 0xa9); /* GPIO0 - reset, GPIO1 - fsin */ ++ ++ client->addr = priv->ti9x3_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x0d, 0x03); /* unreset gpios */ ++ reg8_write(client, 0x0e, 0xf0); /* unreset gpios */ ++ } ++ client->addr = tmp_addr; ++ ++ mdelay(10); ++ ++ return 0; ++} ++ ++static int ox03a_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ox03a_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &ox03a_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ priv->exposure = 0x880; ++ priv->gain = 0x600; ++ priv->autogain = 1; ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, ++ V4L2_CID_GAIN, 1, 0xfff, 1, priv->gain); ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, ++ V4L2_CID_EXPOSURE, 1, 0xffff, 1, priv->exposure); ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 1); ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = ox03a_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = ox03a_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = OX03A_MAX_WIDTH; ++ priv->rect.height = OX03A_MAX_HEIGHT; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ox03a) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_OX03A ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int ox03a_remove(struct i2c_client *client) ++{ ++ struct ox03a_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ox03a); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_OX03A ++static const struct i2c_device_id ox03a_id[] = { ++ { "ox03a", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ox03a_id); ++ ++static const struct of_device_id ox03a_of_ids[] = { ++ { .compatible = "ovti,ox03a", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ox03a_of_ids); ++ ++static struct i2c_driver ox03a_i2c_driver = { ++ .driver = { ++ .name = "ox03a", ++ .of_match_table = ox03a_of_ids, ++ }, ++ .probe = ox03a_probe, ++ .remove = ox03a_remove, ++ .id_table = ox03a_id, ++}; ++ ++module_i2c_driver(ox03a_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for OX03A"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/ox03a.h b/drivers/media/i2c/soc_camera/ox03a.h +new file mode 100644 +index 0000000..4c20374 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ox03a.h +@@ -0,0 +1,1766 @@ ++/* ++ * OmniVision OX03A sensor camera wizard 1920x1080@30/BGGR/MIPI ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++//#define OX03A_DISPLAY_PATTERN_COLOR_BAR ++ ++#define OX03A_MAX_WIDTH 1632 ++#define OX03A_MAX_HEIGHT 1280 ++ ++#define OX03A_DELAY 0xffff ++//#define OX03A_DT 0x2c /* MIPI Data Type RAW12 */ ++//#define DCG16_ONLY ++ ++struct ox03a_reg { ++ u16 reg; ++ u8 val; ++}; ++ ++/* wizard: MIPI 1632x1280 16DCG+12VS 30fps 575MBPS R1A */ ++static const struct ox03a_reg ox03a_regs_wizard_r1a[] = { ++{0x0103, 0x01}, // s/w reset ++{OX03A_DELAY, 10}, // Wait 10ms ++{0x4d09, 0x5f}, ++{0x0100, 0x00}, ++{0x0102, 0x00}, ++{0x0103, 0x00}, ++{0x0104, 0x04}, ++{0x0105, 0x02}, ++{0x0106, 0x00}, ++{0x0107, 0x00}, ++{0x0109, 0x00}, ++{0x0300, 0x00}, ++{0x0301, 0x01}, ++{0x0302, 0x00}, ++{0x0303, 0x02}, ++{0x0304, 0x00}, ++{0x0305, 0x2e}, ++{0x0306, 0x00}, ++{0x0307, 0x00}, ++{0x0308, 0x04}, ++{0x0309, 0x02}, ++{0x030a, 0x00}, ++{0x030c, 0x00}, ++{0x030d, 0x00}, ++{0x0310, 0x00}, ++{0x0311, 0x00}, ++{0x0312, 0x00}, ++{0x0313, 0x00}, ++{0x0314, 0x00}, ++{0x0315, 0x00}, ++{0x0316, 0x00}, ++{0x0317, 0x12}, ++{0x0318, 0x01}, ++{0x0320, 0x00}, ++{0x0321, 0x01}, ++{0x0322, 0x00}, ++{0x0323, 0x02}, ++{0x0324, 0x00}, ++{0x0325, 0x6c}, ++{0x0326, 0x00}, ++{0x0327, 0x05}, ++{0x0328, 0x05}, ++{0x0329, 0x01}, ++{0x032a, 0x02}, ++{0x032b, 0x00}, ++{0x032c, 0x00}, ++{0x0400, 0xe7}, ++{0x0401, 0xff}, ++{0x0404, 0x2b}, ++{0x0405, 0x32}, ++{0x0406, 0x33}, ++{0x0407, 0x8f}, ++{0x0408, 0x0c}, ++{0x040a, 0x00}, ++{0x0410, 0xe7}, ++{0x0411, 0xff}, ++{0x0414, 0x2b}, ++{0x0415, 0x32}, ++{0x0416, 0x33}, ++{0x0417, 0x8f}, ++{0x0418, 0x0c}, ++{0x041a, 0x00}, ++{0x2803, 0x00}, ++{0x3000, 0x00}, ++{0x3001, 0x03}, ++{0x3002, 0x03}, ++{0x3003, 0x00}, ++{0x3004, 0x04}, ++{0x3005, 0x00}, ++{0x3006, 0x00}, ++{0x3007, 0x04}, ++{0x3008, 0x00}, ++{0x3009, 0x06}, ++{0x300d, 0x11}, ++{0x300e, 0x11}, ++{0x300f, 0x11}, ++{0x3012, 0x41}, ++{0x3016, 0xf0}, ++{0x3017, 0xf0}, ++{0x3018, 0xf0}, ++{0x3019, 0xf0}, ++{0x301a, 0xf0}, ++{0x301b, 0xb4}, ++{0x301c, 0x01}, ++{0x301d, 0x02}, ++{0x301e, 0xb8}, ++{0x301f, 0xe1}, ++{0x3020, 0x01}, ++{0x3021, 0x00}, ++{0x3022, 0xf8}, ++{0x3023, 0xf0}, ++{0x3024, 0xf0}, ++{0x3025, 0x02}, ++{0x3026, 0x00}, ++{0x3027, 0x00}, ++{0x3028, 0xf0}, ++{0x3029, 0x80}, ++{0x3035, 0x6c}, ++{0x3036, 0x42}, ++{0x3037, 0x20}, ++{0x3038, 0x00}, ++{0x3700, 0x26}, ++{0x3701, 0x1e}, ++{0x3702, 0x25}, ++{0x3703, 0x28}, ++{0x3704, 0x0f}, ++{0x3705, 0x00}, ++{0x3706, 0x39}, ++{0x3707, 0x0a}, ++{0x3708, 0x36}, ++{0x3709, 0x41}, ++{0x370a, 0x00}, ++{0x370b, 0xa3}, ++{0x370c, 0x0f}, ++{0x370d, 0x00}, ++{0x370e, 0xa6}, ++{0x370f, 0x95}, ++{0x3710, 0x15}, ++{0x3711, 0x72}, ++{0x3712, 0x12}, ++{0x3713, 0x00}, ++{0x3714, 0x22}, ++{0x3715, 0x00}, ++{0x3716, 0x04}, ++{0x3717, 0x02}, ++{0x3718, 0x09}, ++{0x3719, 0x1f}, ++{0x371a, 0x0c}, ++{0x371b, 0x16}, ++{0x371c, 0x00}, ++{0x371d, 0x08}, ++{0x371e, 0x00}, ++{0x371f, 0x02}, ++{0x3720, 0x03}, ++{0x3721, 0x1c}, ++{0x3722, 0x87}, ++{0x3723, 0x08}, ++{0x3724, 0x0d}, ++{0x3725, 0x08}, ++{0x3726, 0x0d}, ++{0x3727, 0x08}, ++{0x3728, 0x04}, ++{0x3729, 0x0c}, ++{0x372a, 0x01}, ++{0x372b, 0x01}, ++{0x372c, 0x17}, ++{0x372d, 0x01}, ++{0x372e, 0x35}, ++{0x372f, 0x43}, ++{0x3730, 0x04}, ++{0x3731, 0x06}, ++{0x3732, 0x01}, ++{0x3733, 0x41}, ++{0x3734, 0x0a}, ++{0x3735, 0x11}, ++{0x3736, 0x11}, ++{0x3737, 0x00}, ++{0x3738, 0x54}, ++{0x3739, 0x54}, ++{0x373a, 0x54}, ++{0x373b, 0x54}, ++{0x373c, 0x11}, ++{0x373d, 0x11}, ++{0x373e, 0x00}, ++{0x373f, 0x4c}, ++{0x3740, 0x4c}, ++{0x3741, 0x44}, ++{0x3742, 0x34}, ++{0x3743, 0x01}, ++{0x3744, 0x16}, ++{0x3745, 0x08}, ++{0x3746, 0x03}, ++{0x3747, 0x01}, ++{0x3748, 0x07}, ++{0x3749, 0x01}, ++{0x374a, 0x07}, ++{0x374b, 0x03}, ++{0x374c, 0xb1}, ++{0x374d, 0x01}, ++{0x374e, 0x01}, ++{0x374f, 0x01}, ++{0x3750, 0x07}, ++{0x3751, 0x02}, ++{0x3752, 0x03}, ++{0x3753, 0xd0}, ++{0x3754, 0x08}, ++{0x3755, 0x00}, ++{0x3758, 0xdd}, ++{0x3759, 0x50}, ++{0x375a, 0x49}, ++{0x375b, 0x02}, ++{0x375c, 0x2f}, ++{0x375d, 0x00}, ++{0x375e, 0x0f}, ++{0x375f, 0x03}, ++{0x3760, 0x13}, ++{0x3761, 0x12}, ++{0x3762, 0x1c}, ++{0x3763, 0x03}, ++{0x3764, 0x0d}, ++{0x3765, 0x25}, ++{0x3766, 0x08}, ++{0x3767, 0x08}, ++{0x3768, 0x21}, ++{0x3769, 0x01}, ++{0x376a, 0x01}, ++{0x376b, 0x00}, ++{0x376c, 0x15}, ++{0x376d, 0x08}, ++{0x376e, 0x08}, ++{0x376f, 0x08}, ++{0x3770, 0x91}, ++{0x3771, 0x00}, ++{0x3772, 0x00}, ++{0x3773, 0x00}, ++{0x3774, 0x82}, ++{0x3775, 0x00}, ++{0x3776, 0x00}, ++{0x3777, 0x00}, ++{0x3778, 0x00}, ++{0x3779, 0x22}, ++{0x377a, 0x00}, ++{0x377b, 0x00}, ++{0x377c, 0x48}, ++{0x377d, 0x00}, ++{0x377e, 0x00}, ++{0x377f, 0x07}, ++{0x3780, 0x00}, ++{0x3781, 0x02}, ++{0x3782, 0x04}, ++{0x3783, 0x02}, ++{0x3784, 0x08}, ++{0x3785, 0x08}, ++{0x3786, 0x00}, ++{0x3787, 0x04}, ++{0x3788, 0x02}, ++{0x3789, 0x02}, ++{0x378a, 0x04}, ++{0x378b, 0x00}, ++{0x378c, 0x00}, ++{0x378d, 0x00}, ++{0x378e, 0x00}, ++{0x378f, 0x00}, ++{0x3790, 0x10}, ++{0x3791, 0x05}, ++{0x3792, 0x31}, ++#ifdef DCG16_ONLY ++{0x3793, 0x04}, /* DCG16 only */ ++#else ++{0x3793, 0x00}, /* DCG16 + VS12*/ ++#endif ++{0x3795, 0x00}, ++{0x3796, 0x00}, ++{0x3797, 0x00}, ++{0x3798, 0x00}, ++{0x3799, 0x00}, ++{0x379a, 0x00}, ++{0x379b, 0x10}, ++{0x379c, 0x01}, ++{0x379d, 0x00}, ++{0x379e, 0x0d}, ++{0x379f, 0x03}, ++{0x37a0, 0x08}, ++{0x37a1, 0x80}, ++{0x37a2, 0x03}, ++{0x37a3, 0x05}, ++{0x37a4, 0x04}, ++{0x37a5, 0x14}, ++{0x37a6, 0x17}, ++{0x37a7, 0x14}, ++{0x37a8, 0x05}, ++{0x37a9, 0x08}, ++{0x37aa, 0x05}, ++{0x37ab, 0x06}, ++{0x37ac, 0x05}, ++{0x37ad, 0x0d}, ++{0x37ae, 0x0d}, ++{0x37af, 0x01}, ++{0x37b0, 0x0c}, ++{0x37b1, 0x05}, ++{0x37b2, 0x08}, ++{0x37b3, 0x0a}, ++{0x37b4, 0x08}, ++{0x37b5, 0x08}, ++{0x37b6, 0x08}, ++{0x37b7, 0x08}, ++{0x37b8, 0xff}, ++{0x37b9, 0x01}, ++{0x37ba, 0x08}, ++{0x37bb, 0x08}, ++{0x37bd, 0x01}, ++{0x37be, 0xe0}, ++{0x37bf, 0x00}, ++{0x37c0, 0x01}, ++{0x37c1, 0x11}, ++{0x37c2, 0x11}, ++{0x37c3, 0x00}, ++{0x37c4, 0x63}, ++{0x37c5, 0x63}, ++{0x37c6, 0x48}, ++{0x37c7, 0x38}, ++{0x37c8, 0x21}, ++{0x37c9, 0x00}, ++{0x37ca, 0x08}, ++{0x37cb, 0x00}, ++{0x37cc, 0x40}, ++{0x37cd, 0x00}, ++{0x37ce, 0x01}, ++{0x37cf, 0x08}, ++{0x37d0, 0x00}, ++{0x37d1, 0x39}, ++{0x37d2, 0x00}, ++{0x37d3, 0xa3}, ++{0x37d4, 0x00}, ++{0x37d5, 0x39}, ++{0x37d6, 0x00}, ++{0x37d7, 0xa3}, ++{0x37da, 0x00}, ++{0x37db, 0x00}, ++{0x37dc, 0x00}, ++{0x37dd, 0x00}, ++{0x37de, 0x00}, ++{0x37df, 0x00}, ++{0x37e0, 0x00}, ++{0x37e1, 0x00}, ++{0x37e2, 0x00}, ++{0x37e3, 0x00}, ++{0x37e4, 0x00}, ++{0x37e5, 0x00}, ++{0x37e6, 0x00}, ++{0x37e7, 0x00}, ++{0x37e8, 0x00}, ++{0x37e9, 0x00}, ++{0x37ea, 0x00}, ++{0x37eb, 0x00}, ++{0x37ec, 0x00}, ++{0x37ed, 0x00}, ++{0x37ee, 0x00}, ++{0x37ef, 0x00}, ++{0x37f0, 0x00}, ++{0x37f1, 0x00}, ++{0x37f2, 0x00}, ++{0x37f3, 0x00}, ++{0x37f4, 0x00}, ++{0x37f5, 0x00}, ++{0x37f6, 0x00}, ++{0x37f7, 0x00}, ++{0x37f8, 0x00}, ++{0x37f9, 0x00}, ++{0x37fa, 0x00}, ++{0x37fb, 0x00}, ++{0x37fc, 0x00}, ++{0x37fd, 0x00}, ++{0x37fe, 0x00}, ++{0x37ff, 0x00}, ++{0x3c00, 0x00}, ++{0x3c01, 0x11}, ++{0x3c02, 0x20}, ++{0x3c03, 0x04}, ++{0x3c04, 0x04}, ++{0x3c05, 0x00}, ++{0x3c06, 0x29}, ++{0x3c07, 0x01}, ++{0x3c08, 0x05}, ++{0x3c09, 0x0c}, ++{0x3c0a, 0x04}, ++{0x3c0b, 0xa8}, ++{0x3c0c, 0x11}, ++{0x3c0d, 0x08}, ++{0x3c0e, 0x03}, ++{0x3c0f, 0x02}, ++{0x3c10, 0x01}, ++{0x3c11, 0x08}, ++{0x3c12, 0x89}, ++{0x3c13, 0x21}, ++{0x3c14, 0x81}, ++{0x3c15, 0x21}, ++{0x3c16, 0x11}, ++{0x3c17, 0x01}, ++{0x3c18, 0x0c}, ++{0x3c19, 0x00}, ++{0x3c1a, 0x16}, ++{0x3c1b, 0x81}, ++{0x3c1c, 0x04}, ++{0x3c1d, 0x16}, ++{0x3c1e, 0x11}, ++{0x3c1f, 0x3a}, ++{0x3c20, 0x20}, ++{0x3c21, 0x00}, ++{0x3c22, 0x17}, ++{0x3c23, 0x07}, ++{0x3c24, 0x1a}, ++{0x3c25, 0x1e}, ++{0x3c26, 0x24}, ++{0x3c27, 0x37}, ++{0x3c28, 0x0a}, ++{0x3c29, 0x14}, ++{0x3c2a, 0xd1}, ++{0x3c2b, 0x27}, ++{0x3c2c, 0x33}, ++{0x3c2d, 0x0c}, ++{0x3c2e, 0x12}, ++{0x3c2f, 0x08}, ++{0x3c30, 0x16}, ++{0x3c31, 0x24}, ++{0x3c32, 0x35}, ++{0x3c33, 0x29}, ++{0x3c34, 0x31}, ++{0x3c35, 0x21}, ++{0x3c36, 0x11}, ++{0x3c37, 0x12}, ++{0x3c38, 0x11}, ++{0x3c39, 0x11}, ++{0x3c3a, 0x08}, ++{0x3c3b, 0x38}, ++{0x3c3c, 0x03}, ++{0x3c3d, 0x23}, ++{0x3c3e, 0x05}, ++{0x3c3f, 0x0a}, ++{0x3c40, 0xc1}, ++{0x3c41, 0x04}, ++{0x3c42, 0x01}, ++{0x3c43, 0x18}, ++{0x3c44, 0x21}, ++{0x3c45, 0x20}, ++{0x3c46, 0x0b}, ++{0x3c47, 0x11}, ++{0x3c48, 0x11}, ++{0x3c4a, 0x02}, ++{0x3c4b, 0x63}, ++{0x3c4c, 0x02}, ++{0x3c4d, 0x63}, ++{0x3c4e, 0x00}, ++{0x3c4f, 0x2a}, ++{0x3c50, 0x2a}, ++{0x3c51, 0x2a}, ++{0x3c52, 0x2a}, ++{0x3c53, 0x08}, ++{0x3c54, 0x1d}, ++{0x3c55, 0xeb}, ++{0x3c56, 0x24}, ++{0x3c57, 0x10}, ++{0x3c58, 0x10}, ++{0x3c59, 0x16}, ++{0x3c5a, 0x55}, ++{0x3c5b, 0x25}, ++{0x3c5c, 0x8e}, ++{0x3ce0, 0x00}, ++{0x3ce1, 0x00}, ++{0x3ce2, 0x00}, ++{0x3ce3, 0x00}, ++{0x3ce4, 0x00}, ++{0x3ce5, 0x00}, ++{0x3ce6, 0x00}, ++{0x3ce7, 0x00}, ++{0x3ce8, 0x00}, ++{0x3ce9, 0x00}, ++{0x3cea, 0x00}, ++{0x3ceb, 0x00}, ++{0x3cec, 0x00}, ++{0x3ced, 0x00}, ++{0x3cee, 0x00}, ++{0x3cef, 0x00}, ++{0x3cf0, 0x00}, ++{0x3cf1, 0x00}, ++{0x3cf2, 0x00}, ++{0x3cf3, 0x00}, ++{0x3cf4, 0x00}, ++{0x3cf5, 0x00}, ++{0x3cf6, 0x00}, ++{0x3cf7, 0x00}, ++{0x3cf8, 0x00}, ++{0x3cf9, 0x00}, ++{0x3cfa, 0x00}, ++{0x3cfb, 0x00}, ++{0x3cfc, 0x00}, ++{0x3cfd, 0x00}, ++{0x3cfe, 0x00}, ++{0x3cff, 0x00}, ++{0x3100, 0x00}, ++{0x3101, 0x32}, ++{0x3102, 0x00}, ++{0x3103, 0x25}, ++{0x3104, 0x01}, ++{0x3105, 0x11}, ++{0x3106, 0x10}, ++{0x3107, 0x01}, ++{0x3108, 0x01}, ++{0x3109, 0x00}, ++{0x3182, 0x10}, ++{0x3183, 0xff}, ++{0x3184, 0xff}, ++{0x3187, 0xff}, ++{0x3189, 0x00}, ++{0x318a, 0x00}, ++{0x318b, 0x00}, ++{0x318c, 0x00}, ++{0x318d, 0x00}, ++{0x318e, 0x00}, ++{0x318f, 0x00}, ++{0x3190, 0x00}, ++{0x3191, 0x00}, ++{0x3192, 0x00}, ++{0x3193, 0x00}, ++{0x3194, 0x00}, ++{0x3200, 0x00}, ++{0x3201, 0x08}, ++{0x3202, 0x10}, ++{0x3203, 0x18}, ++{0x3204, 0x20}, ++{0x3205, 0x30}, ++{0x3206, 0xc0}, ++{0x3209, 0x00}, ++{0x320a, 0x00}, ++{0x320b, 0x00}, ++{0x320c, 0x00}, ++{0x320d, 0x01}, ++{0x3216, 0x02}, ++{0x3217, 0x00}, ++{0x3218, 0xf7}, ++{0x3219, 0x55}, ++{0x321b, 0x00}, ++{0x3220, 0x1c}, ++{0x3221, 0x00}, ++{0x3304, 0x04}, ++{0x3305, 0x00}, ++{0x3306, 0x03}, ++{0x3307, 0x00}, ++{0x3308, 0x00}, ++{0x3309, 0x00}, ++{0x330a, 0x00}, ++{0x330b, 0x00}, ++{0x330c, 0x00}, ++{0x330d, 0x00}, ++{0x330e, 0x00}, ++{0x330f, 0x00}, ++{0x3310, 0x06}, ++{0x3311, 0x05}, ++{0x3312, 0x55}, ++{0x3313, 0x0a}, ++{0x3314, 0xaa}, ++{0x3315, 0x0f}, ++{0x3316, 0xf0}, ++{0x3317, 0x00}, ++{0x3400, 0x08}, ++{0x3401, 0x00}, ++{0x3402, 0x00}, ++{0x3403, 0xb1}, ++{0x3404, 0x00}, ++{0x3405, 0x0f}, ++{0x3406, 0x08}, ++{0x3407, 0x08}, ++{0x3408, 0x01}, ++{0x3409, 0x02}, ++{0x340a, 0x02}, ++{0x340c, 0x10}, ++{0x340d, 0x00}, ++{0x3410, 0x00}, ++{0x3412, 0x00}, ++{0x3413, 0x00}, ++{0x3414, 0x00}, ++{0x3415, 0x00}, ++{0x3416, 0x00}, ++{0x3417, 0x00}, ++{0x3420, 0x00}, ++{0x3421, 0x00}, ++{0x3422, 0x00}, ++{0x3423, 0x00}, ++{0x3424, 0x00}, ++{0x3425, 0x00}, ++{0x3426, 0x00}, ++{0x3427, 0x00}, ++{0x3428, 0x00}, ++{0x3429, 0x00}, ++{0x342a, 0x00}, ++{0x342b, 0x00}, ++{0x3501, 0x00}, ++{0x3502, 0x24}, ++{0x3503, 0xa8}, ++{0x3504, 0x08}, ++{0x3506, 0x00}, ++{0x3507, 0x00}, ++{0x3508, 0x01}, ++{0x3509, 0x00}, ++{0x350a, 0x01}, ++{0x350b, 0x00}, ++{0x350c, 0x00}, ++{0x350d, 0x00}, ++{0x3541, 0x00}, ++{0x3542, 0x40}, ++{0x3543, 0xa8}, ++{0x3544, 0x08}, ++{0x3546, 0x00}, ++{0x3547, 0x00}, ++{0x3548, 0x01}, ++{0x3549, 0x00}, ++{0x354a, 0x01}, ++{0x354b, 0x00}, ++{0x354c, 0x00}, ++{0x354d, 0x00}, ++{0x3581, 0x00}, ++{0x3582, 0x24}, ++{0x3583, 0xa8}, ++{0x3584, 0x08}, ++{0x3586, 0x00}, ++{0x3587, 0x00}, ++{0x3588, 0x01}, ++{0x3589, 0x00}, ++{0x358a, 0x01}, ++{0x358b, 0x00}, ++{0x358c, 0x00}, ++{0x358d, 0x00}, ++{0x3600, 0x00}, ++{0x3601, 0x70}, ++{0x3602, 0x42}, ++{0x3603, 0xe3}, ++{0x3604, 0x93}, ++{0x3605, 0xff}, ++{0x3606, 0x80}, ++{0x3607, 0x4a}, ++{0x3608, 0x98}, ++{0x3609, 0x70}, ++{0x360a, 0x90}, ++{0x360b, 0x0a}, ++{0x360c, 0x40}, ++{0x360d, 0x88}, ++{0x360e, 0x88}, ++{0x360f, 0x88}, ++{0x3610, 0x89}, ++{0x3611, 0x4d}, ++{0x3612, 0x4f}, ++{0x3613, 0xba}, ++{0x3614, 0x99}, ++{0x3615, 0x99}, ++{0x3616, 0x00}, ++{0x3617, 0x00}, ++{0x3618, 0x18}, ++{0x3619, 0x00}, ++{0x3620, 0x02}, ++{0x3621, 0x80}, ++{0x3622, 0x00}, ++{0x3623, 0x00}, ++{0x3624, 0x00}, ++{0x3625, 0x00}, ++{0x3626, 0x0e}, ++{0x3627, 0x0f}, ++{0x3628, 0x0a}, ++{0x3629, 0x0a}, ++{0x362a, 0x0e}, ++{0x362b, 0x0e}, ++{0x362c, 0x0e}, ++{0x362d, 0x12}, ++{0x362e, 0x00}, ++{0x362f, 0x00}, ++{0x3630, 0x00}, ++{0x3631, 0x00}, ++{0x3632, 0x99}, ++{0x3633, 0x99}, ++{0x3634, 0x30}, ++{0x3635, 0x30}, ++{0x3636, 0x30}, ++{0x3637, 0x30}, ++{0x3638, 0x00}, ++{0x3639, 0x00}, ++{0x363a, 0x00}, ++{0x363b, 0x0f}, ++{0x363c, 0x0f}, ++{0x363d, 0x0a}, ++{0x363e, 0x0a}, ++{0x363f, 0x0a}, ++{0x3640, 0x0a}, ++{0x3641, 0x0a}, ++{0x3642, 0x0a}, ++{0x3643, 0x0e}, ++{0x3644, 0x00}, ++{0x3645, 0x10}, ++{0x3646, 0x16}, ++{0x3647, 0x0e}, ++{0x3648, 0x00}, ++{0x3649, 0x13}, ++{0x364a, 0x13}, ++{0x364b, 0x00}, ++{0x364c, 0x0e}, ++{0x364d, 0x0e}, ++{0x364e, 0x0e}, ++{0x364f, 0x0e}, ++{0x3650, 0x00}, ++{0x3651, 0x00}, ++{0x3652, 0xc5}, ++{0x3653, 0x00}, ++{0x3654, 0x40}, ++{0x3655, 0x00}, ++{0x3656, 0xcf}, ++{0x3657, 0x2b}, ++{0x3658, 0x09}, ++{0x3659, 0x00}, ++{0x365a, 0x00}, ++{0x365b, 0x00}, ++{0x365c, 0x00}, ++{0x365d, 0x00}, ++{0x3660, 0x01}, ++{0x3661, 0x07}, ++{0x3662, 0x00}, ++{0x3663, 0x20}, ++{0x3664, 0x00}, ++{0x3665, 0x12}, ++{0x3666, 0x13}, ++{0x3667, 0x54}, ++{0x3668, 0x95}, ++{0x3669, 0x16}, ++{0x366a, 0x00}, ++{0x366b, 0x00}, ++{0x366c, 0x00}, ++{0x366d, 0x00}, ++{0x366e, 0x00}, ++{0x366f, 0xf4}, ++{0x3670, 0x6f}, ++{0x3671, 0x0f}, ++{0x3672, 0x1d}, ++{0x3673, 0x6a}, ++{0x3674, 0x6f}, ++{0x3675, 0x1d}, ++{0x3676, 0x6f}, ++{0x3677, 0x1d}, ++{0x3678, 0x80}, ++{0x3679, 0x04}, ++{0x367a, 0x00}, ++{0x367b, 0x04}, ++{0x367c, 0x00}, ++{0x367d, 0x00}, ++{0x367e, 0x00}, ++{0x367f, 0x00}, ++{0x3680, 0x00}, ++/* window start */ ++{0x3800, 0x00}, ++{0x3801, 0x00}, ++{0x3802, 0x00}, ++{0x3803, 0x04}, ++{0x3804, 0x07}, ++{0x3805, 0x8f}, ++{0x3806, 0x05}, ++{0x3807, 0x0d}, ++{0x3808, OX03A_MAX_WIDTH >> 8}, ++{0x3809, OX03A_MAX_WIDTH & 0xff}, ++{0x380a, OX03A_MAX_HEIGHT >> 8}, ++{0x380b, OX03A_MAX_HEIGHT & 0xff}, ++{0x380c, 0x06}, ++{0x380d, 0xce}, ++{0x380e, 0x05}, ++{0x380f, 0x37}, ++{0x3810, 0x00}, ++{0x3811, 0x9c}, ++{0x3812, 0x00}, ++{0x3813, 0x04}, ++/* window end */ ++{0x3814, 0x01}, ++{0x3815, 0x01}, ++{0x3816, 0x01}, ++{0x3817, 0x01}, ++{0x3818, 0x00}, ++{0x3819, 0x00}, ++{0x381a, 0x00}, ++{0x381b, 0x01}, ++{0x381c, 0x08}, ++{0x381d, 0x00}, ++{0x3820, 0x44}, /* VPLIP on */ ++{0x3821, 0x20}, /* HFLIP off */ ++{0x3822, 0x14}, ++{0x3823, 0x08}, ++{0x3824, 0x00}, ++{0x3825, 0x20}, ++{0x3826, 0x00}, ++{0x3827, 0x08}, ++{0x3828, 0x38}, ++{0x382a, 0x00}, ++{0x382b, 0x00}, ++{0x382c, 0x00}, ++{0x382d, 0x00}, ++{0x3832, 0x00}, ++{0x3833, 0x00}, ++{0x3834, 0x00}, ++{0x3838, 0x00}, ++{0x3839, 0x00}, ++{0x383a, 0x00}, ++{0x383b, 0x00}, ++{0x383c, 0x48}, ++{0x383d, 0x20}, ++{0x383e, 0x00}, ++{0x3842, 0x00}, ++{0x3843, 0x00}, ++{0x3844, 0x00}, ++{0x384c, 0x03}, ++{0x384d, 0xc2}, ++{0x384e, 0x00}, ++{0x384f, 0x40}, ++{0x3850, 0x00}, ++{0x3851, 0x42}, ++{0x3852, 0x00}, ++{0x3853, 0x40}, ++{0x3854, 0x00}, ++{0x3855, 0x05}, ++{0x3856, 0x04}, ++{0x3857, 0x6b}, ++{0x3858, 0x3c}, ++{0x3859, 0x00}, ++{0x385a, 0x03}, ++{0x385b, 0x04}, ++{0x385c, 0x6a}, ++{0x385d, 0x00}, ++{0x385e, 0x12}, ++{0x385f, 0x00}, ++{0x3860, 0x10}, ++{0x3861, 0x00}, ++{0x3862, 0x40}, ++{0x3863, 0x00}, ++{0x3864, 0x40}, ++{0x3865, 0x00}, ++{0x3866, 0x40}, ++{0x3881, 0x02}, ++{0x3882, 0x00}, ++{0x3883, 0x08}, ++{0x3b40, 0x3e}, ++{0x3b41, 0x00}, ++{0x3b42, 0x02}, ++{0x3b43, 0x00}, ++{0x3b44, 0x03}, ++{0x3b45, 0x00}, ++{0x3b46, 0x03}, ++{0x3b47, 0x00}, ++{0x3b80, 0x00}, ++{0x3b81, 0x00}, ++{0x3b82, 0x07}, ++{0x3b83, 0x87}, ++{0x3b84, 0x36}, ++{0x3b85, 0x00}, ++{0x3b86, 0x00}, ++{0x3b87, 0x04}, ++{0x3b88, 0x00}, ++{0x3b89, 0x04}, ++{0x3b8a, 0x00}, ++{0x3b8b, 0x0a}, ++{0x3b8c, 0x00}, ++{0x3b8d, 0x01}, ++{0x3b8e, 0x03}, ++{0x3b8f, 0xe8}, ++{0x3d82, 0xbc}, ++{0x3d83, 0x08}, ++{0x3d84, 0x00}, ++{0x3d85, 0x0b}, ++{0x3d86, 0x02}, ++{0x3d87, 0x0a}, ++{0x3d88, 0x00}, ++{0x3d89, 0x00}, ++{0x3d8a, 0x03}, ++{0x3d8b, 0xff}, ++{0x3d8c, 0x70}, ++{0x3d8d, 0x10}, ++{0x3d90, 0x00}, ++{0x3d91, 0x00}, ++{0x3d92, 0xe2}, ++{0x3d93, 0x46}, ++{0x3d94, 0x14}, ++{0x3d95, 0x06}, ++{0x3d96, 0x01}, ++{0x3d97, 0x00}, ++{0x3d98, 0x00}, ++{0x3d99, 0x00}, ++{0x3d9a, 0x00}, ++{0x3d9b, 0x00}, ++{0x3d9c, 0x00}, ++{0x3d9d, 0x00}, ++{0x3d9e, 0x00}, ++{0x3d9f, 0x00}, ++{0x3da0, 0x00}, ++{0x3da1, 0x00}, ++{0x3da2, 0x00}, ++{0x3da4, 0x00}, ++{0x3e00, 0x00}, ++{0x3e01, 0x00}, ++{0x3e02, 0x0f}, ++{0x3e03, 0xdb}, ++{0x3e04, 0x14}, ++{0x3e05, 0x00}, ++{0x3e06, 0x03}, ++{0x3e07, 0x40}, ++{0x3e08, 0x00}, ++{0x3e09, 0x00}, ++{0x3e0a, 0x00}, ++{0x3e0b, 0x00}, ++{0x3e0c, 0x00}, ++{0x3e0d, 0x00}, ++{0x3e0e, 0x00}, ++{0x3f00, 0x04}, ++{0x3f01, 0x00}, ++{0x3f02, 0x00}, ++{0x3f03, 0x01}, ++{0x4000, 0xf8}, ++{0x4001, 0x2b}, ++{0x4004, 0x00}, ++{0x4005, 0x40}, ++{0x4006, 0x00}, ++{0x4007, 0x10}, ++{0x4008, 0x02}, ++{0x4009, 0x0d}, ++{0x400a, 0x08}, ++{0x400b, 0x00}, ++{0x400c, 0x00}, ++{0x400d, 0x10}, ++{0x400e, 0x00}, ++{0x400f, 0xa0}, ++{0x4010, 0x10}, ++{0x4011, 0xff}, ++{0x4012, 0x08}, ++{0x4013, 0x02}, ++{0x4014, 0x02}, ++{0x4015, 0x02}, ++{0x4016, 0x00}, ++{0x4017, 0x10}, ++{0x4018, 0x18}, ++{0x4019, 0x04}, ++{0x401a, 0x58}, ++{0x4020, 0x00}, ++{0x4021, 0x00}, ++{0x4022, 0x00}, ++{0x4023, 0x00}, ++{0x4024, 0x00}, ++{0x4025, 0x00}, ++{0x4026, 0x00}, ++{0x4027, 0x00}, ++{0x4028, 0x4f}, ++{0x4029, 0x01}, ++{0x402a, 0x00}, ++{0x402b, 0x00}, ++{0x402c, 0x00}, ++{0x402d, 0x00}, ++{0x402e, 0x00}, ++{0x402f, 0x40}, ++{0x4030, 0x00}, ++{0x4031, 0x40}, ++{0x4032, 0x9f}, ++{0x4033, 0x00}, ++{0x4034, 0x00}, ++{0x4035, 0x80}, ++{0x4036, 0x00}, ++{0x4037, 0x80}, ++{0x4038, 0x00}, ++{0x4039, 0x80}, ++{0x403a, 0x00}, ++{0x403b, 0x80}, ++{0x403c, 0x00}, ++{0x403d, 0x00}, ++{0x4040, 0x00}, ++{0x4041, 0x00}, ++{0x4042, 0x00}, ++{0x4043, 0x00}, ++{0x4044, 0x00}, ++{0x4045, 0x00}, ++{0x4046, 0x00}, ++{0x4047, 0x00}, ++{0x4048, 0x00}, ++{0x4049, 0x00}, ++{0x404a, 0x00}, ++{0x404b, 0x00}, ++{0x404c, 0x00}, ++{0x404d, 0x00}, ++{0x404e, 0x00}, ++{0x404f, 0x00}, ++{0x4050, 0x00}, ++{0x4051, 0x05}, ++{0x4052, 0x00}, ++{0x4053, 0x80}, ++{0x4054, 0x00}, ++{0x4055, 0x80}, ++{0x4056, 0x00}, ++{0x4057, 0x80}, ++{0x4058, 0x00}, ++{0x4059, 0x80}, ++{0x405a, 0x30}, ++{0x405b, 0x18}, ++{0x405c, 0x00}, ++{0x405d, 0x00}, ++{0x405e, 0x00}, ++{0x405f, 0x00}, ++{0x4060, 0x00}, ++{0x4065, 0x00}, ++{0x4066, 0x02}, ++{0x406d, 0x00}, ++{0x406e, 0x00}, ++{0x406f, 0x00}, ++{0x40a0, 0x00}, ++{0x40a1, 0x00}, ++{0x40a2, 0x00}, ++{0x40a3, 0x00}, ++{0x40a4, 0x00}, ++{0x40a5, 0x00}, ++{0x40a6, 0x00}, ++{0x40a7, 0x00}, ++{0x40c0, 0x00}, ++{0x40c1, 0x00}, ++{0x40c2, 0x00}, ++{0x40c3, 0x00}, ++{0x40c4, 0x00}, ++{0x40c5, 0x00}, ++{0x40c6, 0x00}, ++{0x40c7, 0x00}, ++{0x40c8, 0x00}, ++{0x40c9, 0x00}, ++{0x40ca, 0x00}, ++{0x40cb, 0x00}, ++{0x40cc, 0x00}, ++{0x40cd, 0x00}, ++{0x40ce, 0x00}, ++{0x40cf, 0x00}, ++{0x4200, 0x00}, ++{0x4201, 0x00}, ++{0x4202, 0x00}, ++{0x4203, 0x00}, ++{0x4204, 0x00}, ++{0x4205, 0x00}, ++{0x4206, 0x00}, ++{0x4207, 0x00}, ++{0x4208, 0x00}, ++{0x4300, 0x00}, ++{0x4301, 0x00}, ++{0x4302, 0x00}, ++{0x4303, 0x00}, ++{0x4304, 0x00}, ++{0x4305, 0x00}, ++{0x4306, 0x00}, ++{0x4307, 0x00}, ++{0x4308, 0x00}, ++{0x4309, 0x00}, ++{0x430a, 0x00}, ++{0x430b, 0xff}, ++{0x430c, 0xff}, ++{0x430d, 0x00}, ++{0x430e, 0x00}, ++{0x430f, 0x02}, ++{0x4500, 0x16}, ++{0x4501, 0x18}, ++{0x4502, 0x00}, ++{0x4503, 0x00}, ++{0x4504, 0x01}, ++{0x4505, 0x00}, ++{0x4506, 0x32}, ++{0x4507, 0x16}, ++{0x4508, 0x1a}, ++{0x4580, 0x68}, ++{0x4581, 0xc7}, ++{0x4582, 0x07}, ++{0x4583, 0x07}, ++{0x4584, 0xec}, ++{0x4585, 0x09}, ++{0x4586, 0xae}, ++{0x4587, 0x04}, ++{0x4588, 0x52}, ++{0x4589, 0x05}, ++{0x458a, 0x47}, ++{0x458b, 0x02}, ++{0x458c, 0xe2}, ++{0x458d, 0x03}, ++{0x458e, 0x85}, ++{0x458f, 0x00}, ++{0x4590, 0x20}, ++{0x4591, 0x09}, ++{0x4592, 0x60}, ++{0x45a6, 0x18}, ++{0x4600, 0x00}, ++{0x4601, 0x30}, ++{0x4602, 0x02}, ++{0x4603, 0x01}, ++{0x4604, 0x00}, ++{0x4605, 0x03}, ++{0x4609, 0x00}, ++{0x460a, 0x36}, ++{0x460b, 0x00}, ++{0x460c, 0x60}, ++{0x460d, 0x01}, ++{0x460e, 0x00}, ++{0x4700, 0x2a}, ++{0x4702, 0x00}, ++{0x4703, 0x80}, ++{0x4704, 0x00}, ++{0x4705, 0x10}, ++{0x4706, 0xaa}, ++{0x4707, 0x55}, ++{0x4708, 0x99}, ++{0x4709, 0x66}, ++{0x470a, 0x08}, ++{0x470b, 0x88}, ++{0x470c, 0x00}, ++{0x470d, 0x02}, ++{0x470e, 0x00}, ++{0x470f, 0x00}, ++{0x4710, 0x00}, ++{0x4711, 0x00}, ++{0x4712, 0x00}, ++{0x4713, 0x00}, ++{0x4800, 0x04}, ++{0x4802, 0x00}, ++{0x4803, 0x00}, ++{0x4804, 0x08}, ++{0x4805, 0x00}, ++{0x4806, 0x00}, ++{0x4807, 0x03}, ++{0x4808, 0x18}, ++{0x480e, 0x04}, ++{0x4810, 0xff}, ++{0x4811, 0xff}, ++{0x4813, 0x12}, // 0xVC ++{0x4814, 0x2a}, ++{0x4815, 0x2b}, ++{0x4816, 0x2b}, ++{0x4818, 0x00}, ++{0x4819, 0x70}, ++{0x481a, 0x00}, ++{0x481b, 0x3c}, ++{0x481c, 0x01}, ++{0x481d, 0x2c}, ++{0x481e, 0x5f}, ++{0x481f, 0x26}, ++{0x4820, 0x00}, ++{0x4821, 0x3c}, ++{0x4822, 0x00}, ++{0x4823, 0x3c}, ++{0x4824, 0x00}, ++{0x4825, 0x32}, ++{0x4826, 0x32}, ++{0x4827, 0x55}, ++{0x4828, 0x00}, ++{0x4829, 0x64}, ++{0x482a, 0x06}, ++{0x482b, 0x04}, ++{0x482c, 0x00}, ++{0x482d, 0x00}, ++{0x482e, 0x34}, ++{0x482f, 0x00}, ++{0x4830, 0x00}, ++{0x4831, 0x64}, ++{0x4832, 0x00}, ++{0x4833, 0x10}, ++{0x4837, 0x18}, ++{0x4838, 0x00}, ++{0x4839, 0x00}, ++{0x483c, 0x10}, ++{0x483d, 0x00}, ++{0x484a, 0x3f}, ++{0x484b, 0x27}, ++{0x484c, 0x00}, ++{0x484e, 0x10}, ++{0x4850, 0x40}, ++{0x4851, 0xaa}, ++{0x4852, 0xff}, ++{0x4853, 0x8a}, ++{0x4854, 0x08}, ++{0x4855, 0x30}, ++{0x4856, 0x01}, ++{0x4860, 0x00}, ++{0x4861, 0xa0}, ++{0x4862, 0x01}, ++{0x4863, 0x01}, ++{0x4864, 0x02}, ++{0x4865, 0x66}, ++{0x4866, 0x99}, ++{0x4867, 0x88}, ++{0x4868, 0xaa}, ++{0x4869, 0xff}, ++{0x486a, 0x3f}, ++{0x486b, 0x84}, ++{0x486c, 0x36}, ++{0x486d, 0x00}, ++{0x486e, 0x84}, ++{0x486f, 0x36}, ++{0x4870, 0x00}, ++{0x4880, 0x00}, ++{0x4881, 0x00}, ++{0x4882, 0x00}, ++{0x4883, 0x00}, ++{0x4884, 0x08}, ++{0x4885, 0x00}, ++{0x4886, 0x00}, ++{0x4900, 0x08}, ++{0x4901, 0x00}, ++{0x4902, 0x00}, ++{0x4903, 0x80}, ++{0x4f00, 0xff}, ++{0x4f01, 0xff}, ++{0x4f04, 0x00}, ++{0x4f05, 0x01}, ++{0x5180, 0x04}, ++{0x5181, 0x00}, ++{0x5182, 0x04}, ++{0x5183, 0x00}, ++{0x5184, 0x04}, ++{0x5185, 0x00}, ++{0x5186, 0x04}, ++{0x5187, 0x00}, ++{0x5188, 0x00}, ++{0x5189, 0x00}, ++{0x518a, 0x00}, ++{0x518b, 0x10}, ++{0x51a0, 0x04}, ++{0x51a1, 0x00}, ++{0x51a2, 0x04}, ++{0x51a3, 0x00}, ++{0x51a4, 0x04}, ++{0x51a5, 0x00}, ++{0x51a6, 0x04}, ++{0x51a7, 0x00}, ++{0x51a8, 0x00}, ++{0x51a9, 0x00}, ++{0x51aa, 0x00}, ++{0x51ab, 0x10}, ++{0x51c0, 0x04}, ++{0x51c1, 0x00}, ++{0x51c2, 0x04}, ++{0x51c3, 0x00}, ++{0x51c4, 0x04}, ++{0x51c5, 0x00}, ++{0x51c6, 0x04}, ++{0x51c7, 0x00}, ++{0x51c8, 0x00}, ++{0x51c9, 0x00}, ++{0x51ca, 0x00}, ++{0x51cb, 0x10}, ++{0x5380, 0x19}, ++{0x5381, 0x94}, ++{0x5382, 0x2e}, ++{0x5383, 0x24}, ++{0x5384, 0x12}, ++{0x5385, 0x41}, ++{0x5386, 0x48}, ++{0x5387, 0x84}, ++{0x5388, 0x40}, ++{0x5389, 0x00}, ++{0x538a, 0x00}, ++{0x538b, 0x03}, ++{0x538c, 0x00}, ++{0x538d, 0x0f}, ++{0x538e, 0x00}, ++{0x538f, 0x3f}, ++{0x5390, 0x0f}, ++{0x5391, 0xfd}, ++{0x5392, 0xf5}, ++{0x5393, 0xf5}, ++{0x5394, 0x02}, ++{0x5395, 0xff}, ++{0x5396, 0x00}, ++{0x5397, 0x00}, ++{0x53a0, 0x41}, ++{0x53a2, 0x04}, ++{0x53a3, 0x00}, ++{0x53a4, 0x04}, ++{0x53a5, 0x00}, ++{0x53a6, 0x04}, ++{0x53a7, 0x00}, ++{0x53ac, 0x04}, ++{0x53ad, 0x00}, ++{0x53ae, 0x04}, ++{0x53af, 0x00}, ++{0x53b0, 0x04}, ++{0x53b1, 0x00}, ++{0x5400, 0x19}, ++{0x5401, 0x94}, ++{0x5402, 0x2e}, ++{0x5403, 0x24}, ++{0x5404, 0x12}, ++{0x5405, 0x41}, ++{0x5406, 0x48}, ++{0x5407, 0x84}, ++{0x5408, 0x40}, ++{0x5409, 0x00}, ++{0x540a, 0x00}, ++{0x540b, 0x03}, ++{0x540c, 0x00}, ++{0x540d, 0x0f}, ++{0x540e, 0x00}, ++{0x540f, 0x3f}, ++{0x5410, 0x0f}, ++{0x5411, 0xfd}, ++{0x5412, 0xf5}, ++{0x5413, 0xf5}, ++{0x5414, 0x02}, ++{0x5415, 0xff}, ++{0x5416, 0x00}, ++{0x5417, 0x00}, ++{0x5420, 0x41}, ++{0x5422, 0x04}, ++{0x5423, 0x00}, ++{0x5424, 0x04}, ++{0x5425, 0x00}, ++{0x5426, 0x04}, ++{0x5427, 0x00}, ++{0x542c, 0x04}, ++{0x542d, 0x00}, ++{0x542e, 0x04}, ++{0x542f, 0x00}, ++{0x5430, 0x04}, ++{0x5431, 0x00}, ++{0x5480, 0x19}, ++{0x5481, 0x94}, ++{0x5482, 0x2e}, ++{0x5483, 0x24}, ++{0x5484, 0x12}, ++{0x5485, 0x41}, ++{0x5486, 0x48}, ++{0x5487, 0x84}, ++{0x5488, 0x40}, ++{0x5489, 0x00}, ++{0x548a, 0x00}, ++{0x548b, 0x03}, ++{0x548c, 0x00}, ++{0x548d, 0x0f}, ++{0x548e, 0x00}, ++{0x548f, 0x3f}, ++{0x5490, 0x0f}, ++{0x5491, 0xfd}, ++{0x5492, 0xf5}, ++{0x5493, 0xf5}, ++{0x5494, 0x02}, ++{0x5495, 0xff}, ++{0x5496, 0x00}, ++{0x5497, 0x00}, ++{0x54a0, 0x41}, ++{0x54a2, 0x04}, ++{0x54a3, 0x00}, ++{0x54a4, 0x04}, ++{0x54a5, 0x00}, ++{0x54a6, 0x04}, ++{0x54a7, 0x00}, ++{0x54ac, 0x04}, ++{0x54ad, 0x00}, ++{0x54ae, 0x04}, ++{0x54af, 0x00}, ++{0x54b0, 0x04}, ++{0x54b1, 0x00}, ++{0x5800, 0x39}, ++{0x5801, 0x03}, ++{0x5802, 0x60}, ++{0x5803, 0xf0}, ++{0x5804, 0x00}, ++{0x5805, 0x40}, ++{0x5806, 0x01}, ++{0x5807, 0x00}, ++{0x5808, 0x60}, ++{0x5809, 0xf0}, ++{0x580a, 0x33}, ++{0x580b, 0x10}, ++{0x580c, 0x04}, ++{0x580d, 0x00}, ++{0x580e, 0x10}, ++{0x580f, 0x10}, ++{0x5810, 0x02}, ++{0x5811, 0x08}, ++{0x5812, 0x38}, ++{0x5813, 0x00}, ++{0x5814, 0x00}, ++{0x5815, 0x00}, ++{0x5816, 0x00}, ++{0x5000, 0x81}, ++{0x5001, 0x42}, ++{0x5002, 0x1b}, ++{0x5003, 0xfe}, ++{0x5004, 0x02}, ++{0x5005, 0x00}, ++{0x5006, 0x01}, ++{0x5007, 0x00}, ++{0x5008, 0x00}, ++{0x5009, 0x40}, ++{0x500a, 0x00}, ++{0x500b, 0x00}, ++{0x500c, 0x00}, ++{0x500d, 0x00}, ++{0x500e, 0x00}, ++{0x500f, 0x00}, ++{0x5010, 0x07}, ++{0x5011, 0x8f}, ++{0x5012, 0x05}, ++{0x5013, 0x0f}, ++{0x5014, 0x01}, ++{0x5015, 0x01}, ++{0x5016, 0x01}, ++{0x5017, 0x01}, ++{0x5018, 0x00}, ++{0x5019, 0x00}, ++{0x501a, 0x00}, ++{0x501b, 0x10}, ++{0x501c, 0x00}, ++{0x501d, 0x10}, ++{0x501e, 0x00}, ++{0x501f, 0x10}, ++{0x5020, 0x04}, ++{0x5021, 0x00}, ++{0x5022, 0x04}, ++{0x5023, 0x00}, ++{0x5024, 0x04}, ++{0x5025, 0x00}, ++{0x5026, 0x00}, ++{0x5027, 0x10}, ++{0x5028, 0x00}, ++{0x5029, 0x10}, ++{0x502a, 0x00}, ++{0x502b, 0x10}, ++{0x502c, 0x00}, ++{0x502d, 0x10}, ++{0x502e, 0x00}, ++{0x502f, 0x10}, ++{0x5030, 0x00}, ++{0x5031, 0x10}, ++{0x5032, 0x04}, ++{0x5033, 0x00}, ++{0x5034, 0x04}, ++{0x5035, 0x00}, ++{0x5036, 0x04}, ++{0x5037, 0x00}, ++{0x5038, 0x00}, ++{0x5039, 0x10}, ++{0x503a, 0x00}, ++{0x503b, 0x10}, ++{0x503c, 0x00}, ++{0x503d, 0x10}, ++{0x503e, 0x00}, ++{0x503f, 0x00}, ++{0x5040, 0x00}, ++{0x5041, 0x01}, ++{0x5042, 0x00}, ++{0x5043, 0x00}, ++{0x5600, 0x0f}, ++{0x5601, 0xab}, ++{0x5602, 0x02}, ++{0x5603, 0x58}, ++{0x5604, 0x03}, ++{0x5605, 0x20}, ++{0x5606, 0x02}, ++{0x5607, 0x58}, ++{0x5608, 0x03}, ++{0x5609, 0x20}, ++{0x560a, 0x02}, ++{0x560b, 0x58}, ++{0x560c, 0x03}, ++{0x560d, 0x20}, ++{0x560e, 0x02}, ++{0x560f, 0x58}, ++{0x5610, 0x03}, ++{0x5611, 0x20}, ++{0x5612, 0x02}, ++{0x5613, 0x58}, ++{0x5614, 0x03}, ++{0x5615, 0x20}, ++{0x5616, 0x02}, ++{0x5617, 0x58}, ++{0x5618, 0x03}, ++{0x5619, 0x20}, ++{0x5640, 0x0f}, ++{0x5641, 0xab}, ++{0x5642, 0x02}, ++{0x5643, 0x58}, ++{0x5644, 0x03}, ++{0x5645, 0x20}, ++{0x5646, 0x02}, ++{0x5647, 0x58}, ++{0x5648, 0x03}, ++{0x5649, 0x20}, ++{0x564a, 0x02}, ++{0x564b, 0x58}, ++{0x564c, 0x03}, ++{0x564d, 0x20}, ++{0x564e, 0x02}, ++{0x564f, 0x58}, ++{0x5650, 0x03}, ++{0x5651, 0x20}, ++{0x5652, 0x02}, ++{0x5653, 0x58}, ++{0x5654, 0x03}, ++{0x5655, 0x20}, ++{0x5656, 0x02}, ++{0x5657, 0x58}, ++{0x5658, 0x03}, ++{0x5659, 0x20}, ++{0x5680, 0x0f}, ++{0x5681, 0xab}, ++{0x5682, 0x02}, ++{0x5683, 0x58}, ++{0x5684, 0x03}, ++{0x5685, 0x20}, ++{0x5686, 0x02}, ++{0x5687, 0x58}, ++{0x5688, 0x03}, ++{0x5689, 0x20}, ++{0x568a, 0x02}, ++{0x568b, 0x58}, ++{0x568c, 0x03}, ++{0x568d, 0x20}, ++{0x568e, 0x02}, ++{0x568f, 0x58}, ++{0x5690, 0x03}, ++{0x5691, 0x20}, ++{0x5692, 0x02}, ++{0x5693, 0x58}, ++{0x5694, 0x03}, ++{0x5695, 0x20}, ++{0x5696, 0x02}, ++{0x5697, 0x58}, ++{0x5698, 0x03}, ++{0x5699, 0x20}, ++{0x5700, 0x00}, ++{0x5701, 0x00}, ++{0x5702, 0x00}, ++{0x5703, 0x00}, ++{0x5704, 0x02}, ++{0x5705, 0x80}, ++{0x5706, 0x01}, ++{0x5707, 0xe0}, ++{0x5708, 0x00}, ++{0x5709, 0x0f}, ++{0x5740, 0x00}, ++{0x5741, 0x00}, ++{0x5742, 0x00}, ++{0x5743, 0x00}, ++{0x5744, 0x02}, ++{0x5745, 0x80}, ++{0x5746, 0x01}, ++{0x5747, 0xe0}, ++{0x5748, 0x00}, ++{0x5749, 0x0f}, ++{0x5780, 0x00}, ++{0x5781, 0x00}, ++{0x5782, 0x00}, ++{0x5783, 0x00}, ++{0x5784, 0x02}, ++{0x5785, 0x80}, ++{0x5786, 0x01}, ++{0x5787, 0xe0}, ++{0x5788, 0x00}, ++{0x5789, 0x0f}, ++{0x5200, 0x70}, ++{0x5201, 0x70}, ++{0x5202, 0x73}, ++{0x5203, 0xff}, ++{0x5204, 0x02}, ++{0x5205, 0x6c}, ++{0x5206, 0x00}, ++{0x5207, 0x00}, ++{0x5209, 0x08}, ++{0x520a, 0x00}, ++{0x520b, 0x07}, ++{0x520c, 0x01}, ++{0x520d, 0x01}, ++{0x520e, 0x01}, ++{0x520f, 0x01}, ++{0x5210, 0x00}, ++{0x5211, 0x00}, ++{0x5212, 0x00}, ++{0x5213, 0x00}, ++{0x5214, 0x00}, ++{0x5215, 0x00}, ++{0x5216, 0x07}, ++{0x5217, 0x8b}, ++{0x5218, 0x00}, ++{0x5219, 0x00}, ++{0x5280, 0x00}, ++{0x5281, 0x00}, ++{0x5282, 0xff}, ++{0x5283, 0xff}, ++{0x5284, 0x02}, ++{0x5285, 0x6c}, ++{0x5286, 0x00}, ++{0x5287, 0x00}, ++{0x5289, 0x08}, ++{0x528a, 0x00}, ++{0x528b, 0x07}, ++{0x528c, 0x01}, ++{0x528d, 0x01}, ++{0x528e, 0x01}, ++{0x528f, 0x01}, ++{0x5290, 0x00}, ++{0x5291, 0x00}, ++{0x5292, 0x00}, ++{0x5293, 0x00}, ++{0x5294, 0x00}, ++{0x5295, 0x00}, ++{0x5296, 0x07}, ++{0x5297, 0x8b}, ++{0x5298, 0x00}, ++{0x5299, 0x00}, ++{0x5300, 0x00}, ++{0x5301, 0x00}, ++{0x5302, 0xff}, ++{0x5303, 0xff}, ++{0x5304, 0x02}, ++{0x5305, 0x6c}, ++{0x5306, 0x00}, ++{0x5307, 0x00}, ++{0x5309, 0x08}, ++{0x530a, 0x00}, ++{0x530b, 0x07}, ++{0x530c, 0x01}, ++{0x530d, 0x01}, ++{0x530e, 0x01}, ++{0x530f, 0x01}, ++{0x5310, 0x00}, ++{0x5311, 0x00}, ++{0x5312, 0x00}, ++{0x5313, 0x00}, ++{0x5314, 0x00}, ++{0x5315, 0x00}, ++{0x5316, 0x07}, ++{0x5317, 0x8b}, ++{0x5318, 0x00}, ++{0x5319, 0x00}, ++#ifdef OX03A_DISPLAY_PATTERN_COLOR_BAR ++{0x5080, 0xc0}, /* Rolling test pattern for HCG */ ++#else ++{0x5080, 0x00}, ++#endif ++{0x5081, 0x01}, ++{0x5082, 0xb0}, ++{0x5083, 0x0f}, ++{0x5084, 0x00}, ++{0x5085, 0x00}, ++{0x5086, 0x00}, ++{0x5087, 0x01}, ++{0x5088, 0x00}, ++{0x5089, 0x00}, ++{0x508a, 0x00}, ++{0x508b, 0x00}, ++{0x508c, 0x00}, ++{0x508d, 0x00}, ++{0x508e, 0x00}, ++{0x508f, 0x00}, ++{0x5090, 0x00}, ++{0x5091, 0x00}, ++{0x5092, 0x00}, ++{0x5093, 0x00}, ++{0x5094, 0x00}, ++{0x5095, 0x00}, ++{0x5096, 0x00}, ++{0x5097, 0x00}, ++#ifdef OX03A_DISPLAY_PATTERN_COLOR_BAR ++{0x50c0, 0xc0}, /* Rolling test pattern for LCG */ ++#else ++{0x50c0, 0x00}, ++#endif ++{0x50c1, 0x01}, ++{0x50c2, 0xb0}, ++{0x50c3, 0x0f}, ++{0x50c4, 0x00}, ++{0x50c5, 0x00}, ++{0x50c6, 0x00}, ++{0x50c7, 0x01}, ++{0x50c8, 0x00}, ++{0x50c9, 0x00}, ++{0x50ca, 0x00}, ++{0x50cb, 0x00}, ++{0x50cc, 0x00}, ++{0x50cd, 0x00}, ++{0x50ce, 0x00}, ++{0x50cf, 0x00}, ++{0x50d0, 0x00}, ++{0x50d1, 0x00}, ++{0x50d2, 0x00}, ++{0x50d3, 0x00}, ++{0x50d4, 0x00}, ++{0x50d5, 0x00}, ++{0x50d6, 0x00}, ++{0x50d7, 0x00}, ++#ifdef OX03A_DISPLAY_PATTERN_COLOR_BAR ++{0x5100, 0xc0}, /* Rolling test pattern for VS */ ++#else ++{0x5100, 0x00}, ++#endif ++{0x5101, 0x01}, ++{0x5102, 0xb0}, ++{0x5103, 0x0f}, ++{0x5104, 0x00}, ++{0x5105, 0x00}, ++{0x5106, 0x00}, ++{0x5107, 0x01}, ++{0x5108, 0x00}, ++{0x5109, 0x00}, ++{0x510a, 0x00}, ++{0x510b, 0x00}, ++{0x510c, 0x00}, ++{0x510d, 0x00}, ++{0x510e, 0x00}, ++{0x510f, 0x00}, ++{0x5110, 0x00}, ++{0x5111, 0x00}, ++{0x5112, 0x00}, ++{0x5113, 0x00}, ++{0x5114, 0x00}, ++{0x5115, 0x00}, ++{0x5116, 0x00}, ++{0x5117, 0x00}, ++/* patch start */ ++{0x0325, 0x68}, ++{0x0400, 0xe8}, ++{0x0401, 0x00}, ++{0x0406, 0x35}, ++{0x0407, 0x8a}, ++{0x0410, 0xe8}, ++{0x0411, 0x00}, ++{0x0416, 0x35}, ++{0x0417, 0x8a}, ++{0x3501, 0x01}, ++{0x3502, 0x90}, ++{0x3508, 0x04}, ++{0x3549, 0x80}, ++{0x3674, 0x7b}, ++{0x3675, 0xb8}, ++{0x3676, 0x3e}, ++{0x3677, 0xa8}, ++{0x384c, 0x03}, ++{0x384d, 0xc2}, ++{0x4d0e, 0x20}, ++{0x3208, 0x04}, ++{0x3501, 0x02}, ++{0x3508, 0x04}, ++{0x3208, 0x14}, ++{0x3208, 0x05}, ++{0x3501, 0x02}, ++{0x3508, 0x04}, ++{0x3208, 0x15}, ++/* patch end */ ++/* patch2 start */ ++//{0x3208, 0x03}, // start recording group3 ++{0x3501, 0x08}, // HCG exposure integration time MSB ++{0x3502, 0x80}, // HCG exposure integration time LSB ++{0x3508, 0x06}, // HCG real gain ++{0x350a, 0x06}, // HCG digital gain ++{0x3548, 0x06}, // LCG real gain ++{0x354a, 0x06}, // LCG digital gain ++{0x3588, 0x06}, // VS real gain ++{0x358a, 0x06}, // VS digital gain ++//{0x3208, 0x13}, // stop recording group3 ++//{0x3208, 0xe3}, // launch group3 ++/* patch2 end */ ++{0x0100, 0x01}, ++}; +diff --git a/drivers/media/i2c/soc_camera/ti9x4.c b/drivers/media/i2c/soc_camera/ti9x4.c +index 7704bfa..e36ecdb 100644 +--- a/drivers/media/i2c/soc_camera/ti9x4.c ++++ b/drivers/media/i2c/soc_camera/ti9x4.c +@@ -17,10 +17,9 @@ + #include + #include + +-#include + #include ++#include + #include +-#include + #include + + #include "ti9x4.h" +@@ -43,7 +42,11 @@ struct ti9x4_priv { + int ti9x3_addr_map[4]; + char chip_id[6]; + int ser_id; ++ int vc_map; ++ int csi_map; ++ struct gpio_desc *pwen; /* chip power en */ + struct gpio_desc *poc_gpio[4]; /* PoC power supply */ ++ struct v4l2_clk *ref_clk; /* ref clock */ + }; + + static int ser_id; +@@ -70,6 +73,14 @@ static int poc_delay; + module_param(poc_delay, int, 0644); + MODULE_PARM_DESC(poc_delay, " Delay in ms after POC enable (default: 0 ms)"); + ++static int vc_map = 0x3210; ++module_param(vc_map, int, 0644); ++MODULE_PARM_DESC(vc_map, " CSI VC MAP (default: 0xe4 - linear map VCx=LINKx)"); ++ ++static int csi_map = 0; ++module_param(csi_map, int, 0644); ++MODULE_PARM_DESC(csi_map, " CSI TX MAP (default: 0 - forwarding of all links to CSI0)"); ++ + #ifdef TI954_SILICON_ERRATA + static int indirect_write(struct i2c_client *client, unsigned int page, u8 reg, u8 val) + { +@@ -121,29 +132,35 @@ static void ti9x4_initial_setup(struct i2c_client *client) + reg8_write(client, 0x0d, 0xb9); /* VDDIO 3.3V */ + switch (priv->csi_rate) { + case 1600: /* REFCLK = 25MHZ */ ++ case 1500: /* REFCLK = 23MHZ */ + case 1450: /* REFCLK = 22.5MHZ */ + reg8_write(client, 0x1f, 0x00); /* CSI rate 1.5/1.6Gbps */ + break; ++ case 1200: /* REFCLK = 25MHZ */ ++ case 1100: /* REFCLK = 22.5MHZ */ ++ reg8_write(client, 0x1f, 0x01); /* CSI rate 1.1/1.2Gbps */ ++ break; + case 800: /* REFCLK = 25MHZ */ + case 700: /* REFCLK = 22.5MHZ */ + reg8_write(client, 0x1f, 0x02); /* CSI rate 700/800Mbps */ + break; + case 400: /* REFCLK = 25MHZ */ +- reg8_write(client, 0x1f, 0x03); /* CSI rate 400Mbps */ ++ case 350: /* REFCLK = 22.5MHZ */ ++ reg8_write(client, 0x1f, 0x03); /* CSI rate 350/400Mbps */ + break; + default: + dev_err(&client->dev, "unsupported CSI rate %d\n", priv->csi_rate); + } + + if (strcmp(priv->forwarding_mode, "round-robin") == 0) { +- reg8_write(client, 0x21, 0x01); /* Round Robin forwarding enable */ ++ reg8_write(client, 0x21, 0x03); /* Round Robin forwarding enable for CSI0/CSI1 */ + } else if (strcmp(priv->forwarding_mode, "synchronized") == 0) { +- reg8_write(client, 0x21, 0x44); /* Basic Syncronized forwarding enable (FrameSync must be enabled!!) */ ++ reg8_write(client, 0x21, 0x54); /* Basic Syncronized forwarding enable (FrameSync must be enabled!!) for CSI0/CSI1 */ + } + +- reg8_write(client, 0x32, 0x01); /* Select TX (CSI) port 0 */ ++ reg8_write(client, 0x32, 0x03); /* Select TX for CSI0/CSI1, RX for CSI0 */ + reg8_write(client, 0x33, ((priv->lanes - 1) ^ 0x3) << 4); /* disable CSI output, set CSI lane count, non-continuous CSI mode */ +- reg8_write(client, 0x20, 0xf0); /* disable port forwarding */ ++ reg8_write(client, 0x20, 0xf0 | priv->csi_map); /* disable port forwarding */ + #if 0 + /* FrameSync setup for REFCLK=25MHz, FPS=30: period_counts=1/2/FPS*25MHz =1/2/30*25Mhz =416666 -> FS_TIME=416666 */ + /* FrameSync setup for REFCLK=22.5MHz, FPS=30: period_counts=1/2/FPS*22.5Mhz=1/2/30*22.5Mhz=375000 -> FS_TIME=375000 */ +@@ -156,12 +173,15 @@ static void ti9x4_initial_setup(struct i2c_client *client) + #else + /* FrameSync setup for REFCLK=25MHz, FPS=30: period_counts=1/FPS/12mks=1/30/12e-6=2777 -> HI=2, LO=2775 */ + /* FrameSync setup for REFCLK=22.5MHz, FPS=30: period_counts=1/FPS/13.333mks=1/30/13.333e-6=2500 -> HI=2, LO=2498 */ +- #define FS_TIME (priv->csi_rate == 1450 ? (2498+15) : (2775+15)) ++// #define FS_TIME (priv->csi_rate == 1450 ? (2498+15) : (2775+15)) ++// #define FS_TIME (2498+15) ++ #define FS_TIME (2498+15) + reg8_write(client, 0x19, 2 >> 8); /* FrameSync high time MSB */ + reg8_write(client, 0x1a, 2 & 0xff); /* FrameSync high time LSB */ + reg8_write(client, 0x1b, FS_TIME >> 8); /* FrameSync low time MSB */ + reg8_write(client, 0x1c, FS_TIME & 0xff); /* FrameSync low time LSB */ + reg8_write(client, 0x18, 0x01); /* Enable FrameSync, HI/LO mode, Frame clock from port0 */ ++// reg8_write(client, 0x18, 0x80); /* Enable FrameSync, HI/LO mode, Frame clock from port0 */ + #endif + } + +@@ -220,10 +240,11 @@ static void ti9x4_fpdlink3_setup(struct i2c_client *client, int idx) + + reg8_write(client, 0x6d, port_config); + reg8_write(client, 0x7c, port_config2); +- reg8_write(client, 0x70, (idx << 6) | 0x1e); /* CSI data type: yuv422 8-bit, assign VC */ +- reg8_write(client, 0x71, (idx << 6) | 0x2a); /* CSI data type: RAW8, assign VC */ ++ reg8_write(client, 0x70, ((priv->vc_map >> (idx * 4)) << 6) | 0x1e); /* CSI data type: yuv422 8-bit, assign VC */ ++ reg8_write(client, 0x71, ((priv->vc_map >> (idx * 4)) << 6) | 0x2c); /* CSI data type: RAW12, assign VC */ + reg8_write(client, 0xbc, 0x00); /* Setup minimal time between FV and LV to 3 PCLKs */ + reg8_write(client, 0x6e, 0x88); /* Sensor reset: backchannel GPIO0/GPIO1 set low */ ++ reg8_write(client, 0x72, priv->vc_map >> (idx * 4)); /* CSI VC MAP */ + } + + static int ti9x4_initialize(struct i2c_client *client) +@@ -286,10 +307,10 @@ static int ti9x4_s_power(struct v4l2_subdev *sd, int on) + + if (on) { + if (atomic_inc_return(&priv->use_count) == 1) +- reg8_write(client, 0x20, 0x00); /* enable port forwarding to CSI */ ++ reg8_write(client, 0x20, 0x00 | priv->csi_map); /* enable port forwarding to CSI */ + } else { + if (atomic_dec_return(&priv->use_count) == 0) +- reg8_write(client, 0x20, 0xf0); /* disable port forwarding to CSI */ ++ reg8_write(client, 0x20, 0xf0 | priv->csi_map); /* disable port forwarding to CSI */ + } + + return 0; +@@ -324,7 +345,7 @@ static int ti9x4_parse_dt(struct i2c_client *client) + struct device_node *np = client->dev.of_node; + struct device_node *endpoint = NULL, *rendpoint = NULL; + struct property *prop; +- int err, pwen, i; ++ int i; + int sensor_delay; + char forwarding_mode_default[20] = "round-robin"; /* round-robin, synchronized */ + struct property *csi_rate_prop, *dvp_order_prop; +@@ -337,18 +358,22 @@ static int ti9x4_parse_dt(struct i2c_client *client) + if (of_property_read_u32(np, "ti,lanes", &priv->lanes)) + priv->lanes = 4; + +- pwen = of_get_gpio(np, 0); +- if (pwen > 0) { +- err = devm_gpio_request_one(&client->dev, pwen, GPIOF_OUT_INIT_LOW, dev_name(&client->dev)); +- if (err) +- dev_err(&client->dev, "cannot request PWEN gpio %d: %d\n", pwen, err); +- else +- mdelay(250); ++ priv->ref_clk = v4l2_clk_get(&client->dev, "ref_clk"); ++ if (!IS_ERR(priv->ref_clk)) { ++ dev_info(&client->dev, "ref_clk = %luKHz", v4l2_clk_get_rate(priv->ref_clk) / 1000); ++ v4l2_clk_enable(priv->ref_clk); ++ } ++ ++ priv->pwen = devm_gpiod_get(&client->dev, NULL, GPIOF_OUT_INIT_HIGH); ++ if (!IS_ERR(priv->pwen)) { ++ mdelay(5); ++ gpiod_direction_output(priv->pwen, 0); ++ mdelay(5); + } + + for (i = 0; i < 4; i++) { + sprintf(poc_name, "POC%d", i); +- priv->poc_gpio[i] = devm_gpiod_get_optional(&client->dev, poc_name, 0); ++ priv->poc_gpio[i] = devm_gpiod_get_optional(&client->dev, kstrdup(poc_name, GFP_KERNEL), 0); + } + + reg8_read(client, 0x00, &val); /* read TI9x4 I2C address */ +@@ -379,13 +404,34 @@ static int ti9x4_parse_dt(struct i2c_client *client) + if (of_property_read_u32(np, "ti,dvp_bus", &priv->dvp_bus)) + priv->dvp_bus = 8; + if (of_property_read_u32(np, "ti,hsync", &priv->hsync)) +- priv->vsync = 0; ++ priv->hsync = 0; + if (of_property_read_u32(np, "ti,vsync", &priv->vsync)) + priv->vsync = 1; + if (of_property_read_u32(np, "ti,ser_id", &priv->ser_id)) + priv->ser_id = TI913_ID; + if (of_property_read_u32(np, "ti,poc-delay", &priv->poc_delay)) + priv->poc_delay = 50; ++ if (of_property_read_u32(np, "ti,vc-map", &priv->vc_map)) ++ priv->vc_map = 0x3210; ++ ++ /* ++ * CSI forwarding of all links is to CSI0 by default. ++ * Decide if any link will be forwarded to CSI1 instead CSI0 ++ */ ++ prop = of_find_property(np, "ti,csi1-links", NULL); ++ if (prop) { ++ const __be32 *link = NULL; ++ u32 v; ++ ++ for (i = 0; i < 4; i++) { ++ link = of_prop_next_u32(prop, link, &v); ++ if (!link) ++ break; ++ priv->csi_map |= BIT(v); ++ } ++ } else { ++ priv->csi_map = 0; ++ } + + /* module params override dts */ + if (is_stp) +@@ -400,6 +446,10 @@ static int ti9x4_parse_dt(struct i2c_client *client) + priv->ser_id = ser_id; + if (poc_delay) + priv->poc_delay = poc_delay; ++ if (vc_map != 0x3210) ++ priv->vc_map = vc_map; ++ if (csi_map) ++ priv->csi_map = csi_map; + + for (i = 0; ; i++) { + endpoint = of_graph_get_next_endpoint(np, endpoint); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0132-lvds-ti960-fix-frame-sync-time-for-different-ref-clo.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0132-lvds-ti960-fix-frame-sync-time-for-different-ref-clo.patch new file mode 100644 index 00000000..25d424f7 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0132-lvds-ti960-fix-frame-sync-time-for-different-ref-clo.patch @@ -0,0 +1,85 @@ +From a3dec1c8cc2b3de7116cede7aa7b2000b800a70d Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Thu, 8 Nov 2018 21:34:37 +0300 +Subject: [PATCH 081/122] lvds: ti960: fix frame sync time for different ref + clock + +This fixes frame sync signal for different reference clock + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ti9x4.c | 35 +++++++++++++++++++++++++++-------- + 1 file changed, 27 insertions(+), 8 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ti9x4.c b/drivers/media/i2c/soc_camera/ti9x4.c +index e36ecdb..effcf6c 100644 +--- a/drivers/media/i2c/soc_camera/ti9x4.c ++++ b/drivers/media/i2c/soc_camera/ti9x4.c +@@ -123,6 +123,7 @@ static void ti9x4_read_chipid(struct i2c_client *client) + static void ti9x4_initial_setup(struct i2c_client *client) + { + struct ti9x4_priv *priv = i2c_get_clientdata(client); ++ int fs_time = 0; + + /* Initial setup */ + client->addr = priv->des_addr; /* TI9x4 I2C */ +@@ -132,7 +133,7 @@ static void ti9x4_initial_setup(struct i2c_client *client) + reg8_write(client, 0x0d, 0xb9); /* VDDIO 3.3V */ + switch (priv->csi_rate) { + case 1600: /* REFCLK = 25MHZ */ +- case 1500: /* REFCLK = 23MHZ */ ++ case 1500: /* REFCLK = 23.5MHZ */ + case 1450: /* REFCLK = 22.5MHZ */ + reg8_write(client, 0x1f, 0x00); /* CSI rate 1.5/1.6Gbps */ + break; +@@ -152,6 +153,29 @@ static void ti9x4_initial_setup(struct i2c_client *client) + dev_err(&client->dev, "unsupported CSI rate %d\n", priv->csi_rate); + } + ++ switch (priv->csi_rate) { ++ case 1600: ++ case 1200: ++ case 800: ++ case 400: ++ /* FrameSync setup for REFCLK=25MHz, FPS=30: period_counts=1/FPS/12mks=1/30/12e-6=2777 -> HI=2, LO=2775 */ ++ fs_time = 2790; ++ break; ++ case 1500: ++ /* FrameSync setup for REFCLK=23.5MHz, FPS=30: period_counts=1/FPS/12.766mks=1/30/12.766e-6=2612 -> HI=2, LO=2610 */ ++ fs_time = 2625; ++ break; ++ case 1450: ++ case 1100: ++ case 700: ++ case 350: ++ /* FrameSync setup for REFCLK=22.5MHz, FPS=30: period_counts=1/FPS/13.333mks=1/30/13.333e-6=2500 -> HI=2, LO=2498 */ ++ fs_time = 2513; ++ break; ++ default: ++ dev_err(&client->dev, "unsupported CSI rate %d\n", priv->csi_rate); ++ } ++ + if (strcmp(priv->forwarding_mode, "round-robin") == 0) { + reg8_write(client, 0x21, 0x03); /* Round Robin forwarding enable for CSI0/CSI1 */ + } else if (strcmp(priv->forwarding_mode, "synchronized") == 0) { +@@ -171,15 +195,10 @@ static void ti9x4_initial_setup(struct i2c_client *client) + reg8_write(client, 0x1c, FS_TIME & 0xff); + reg8_write(client, 0x18, 0x43); /* Enable FrameSync, 50/50 mode, Frame clock from 25MHz */ + #else +- /* FrameSync setup for REFCLK=25MHz, FPS=30: period_counts=1/FPS/12mks=1/30/12e-6=2777 -> HI=2, LO=2775 */ +- /* FrameSync setup for REFCLK=22.5MHz, FPS=30: period_counts=1/FPS/13.333mks=1/30/13.333e-6=2500 -> HI=2, LO=2498 */ +-// #define FS_TIME (priv->csi_rate == 1450 ? (2498+15) : (2775+15)) +-// #define FS_TIME (2498+15) +- #define FS_TIME (2498+15) + reg8_write(client, 0x19, 2 >> 8); /* FrameSync high time MSB */ + reg8_write(client, 0x1a, 2 & 0xff); /* FrameSync high time LSB */ +- reg8_write(client, 0x1b, FS_TIME >> 8); /* FrameSync low time MSB */ +- reg8_write(client, 0x1c, FS_TIME & 0xff); /* FrameSync low time LSB */ ++ reg8_write(client, 0x1b, fs_time >> 8); /* FrameSync low time MSB */ ++ reg8_write(client, 0x1c, fs_time & 0xff); /* FrameSync low time LSB */ + reg8_write(client, 0x18, 0x01); /* Enable FrameSync, HI/LO mode, Frame clock from port0 */ + // reg8_write(client, 0x18, 0x80); /* Enable FrameSync, HI/LO mode, Frame clock from port0 */ + #endif +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0133-lvds-add-AR0323-imager.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0133-lvds-add-AR0323-imager.patch new file mode 100644 index 00000000..332de5b9 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0133-lvds-add-AR0323-imager.patch @@ -0,0 +1,1998 @@ +From 0ae24c08919a48946c7a91762938ef2888d9ab90 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Tue, 13 Nov 2018 02:06:40 +0300 +Subject: [PATCH 082/122] lvds: add AR0323 imager + +This adds AR0323 imager support + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ar0323.c | 581 ++++++++++++++ + drivers/media/i2c/soc_camera/ar0323.h | 1335 ++++++++++++++++++++++++++++++++ + drivers/media/i2c/soc_camera/ov106xx.c | 13 +- + 3 files changed, 1928 insertions(+), 1 deletion(-) + create mode 100644 drivers/media/i2c/soc_camera/ar0323.c + create mode 100644 drivers/media/i2c/soc_camera/ar0323.h + +diff --git a/drivers/media/i2c/soc_camera/ar0323.c b/drivers/media/i2c/soc_camera/ar0323.c +new file mode 100644 +index 0000000..467367b +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0323.c +@@ -0,0 +1,581 @@ ++/* ++ * ON Semiconductor AR0323 sensor camera driver ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "ar0323.h" ++ ++#define AR0323_I2C_ADDR 0x10 ++ ++#define AR0323_PID 0x3000 ++#define AR0323_VERSION_REG 0x0D56 ++ ++#define AR0323_MEDIA_BUS_FMT MEDIA_BUS_FMT_SGRBG12_1X12 ++ ++struct ar0323_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int init_complete; ++ u8 id[6]; ++ /* serializers */ ++ int ti9x4_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++}; ++ ++static inline struct ar0323_priv *to_ar0323(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct ar0323_priv, sd); ++} ++ ++static int ar0323_set_regs(struct i2c_client *client, ++ const struct ar0323_reg *regs, int nr_regs) ++{ ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (regs[i].reg == AR0323_DELAY) { ++ mdelay(regs[i].val); ++ continue; ++ } ++ ++ reg16_write16(client, regs[i].reg, regs[i].val); ++ } ++ ++ return 0; ++} ++ ++static int ar0323_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int ar0323_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0323_priv *priv = to_ar0323(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = AR0323_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int ar0323_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = AR0323_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int ar0323_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = AR0323_MEDIA_BUS_FMT; ++ ++ return 0; ++} ++ ++static int ar0323_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0323_priv *priv = to_ar0323(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = AR0323_VERSION_REG >> 8; ++ edid->edid[9] = AR0323_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int ar0323_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0323_priv *priv = to_ar0323(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > AR0323_MAX_WIDTH) || ++ (rect->top + rect->height > AR0323_MAX_HEIGHT)) ++ *rect = priv->rect; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ return 0; ++} ++ ++static int ar0323_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0323_priv *priv = to_ar0323(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = AR0323_MAX_WIDTH; ++ sel->r.height = AR0323_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = AR0323_MAX_WIDTH; ++ sel->r.height = AR0323_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ar0323_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int ar0323_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u16 val = 0; ++ ++ ret = reg16_read16(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int ar0323_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return reg16_write16(client, (u16)reg->reg, (u16)reg->val); ++} ++#endif ++ ++static struct v4l2_subdev_core_ops ar0323_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ar0323_g_register, ++ .s_register = ar0323_s_register, ++#endif ++}; ++ ++static int ar0323_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0323_priv *priv = to_ar0323(client); ++ int ret = -EINVAL; ++ u16 val = 0; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ case V4L2_CID_CONTRAST: ++ case V4L2_CID_SATURATION: ++ case V4L2_CID_HUE: ++ case V4L2_CID_GAMMA: ++ case V4L2_CID_SHARPNESS: ++ case V4L2_CID_AUTOGAIN: ++ break; ++ case V4L2_CID_GAIN: ++ /* Digital gain */ ++ ret = reg16_write16(client, 0x3308, ctrl->val); ++ break; ++ case V4L2_CID_ANALOGUE_GAIN: ++ /* Analog gain */ ++ ret = reg16_write16(client, 0x3366, (ctrl->val << 8) | (ctrl->val << 4) | ctrl->val); ++ break; ++ case V4L2_CID_EXPOSURE: ++ /* T1 exposure */ ++ ret = reg16_write16(client, 0x3012, ctrl->val); ++ break; ++ case V4L2_CID_HFLIP: ++ ret = reg16_read16(client, 0x3040, &val); ++ if (ctrl->val) ++ val |= (1 << 14); ++ else ++ val &= ~(1 << 14); ++ ret |= reg16_write16(client, 0x3040, val); ++ break; ++ case V4L2_CID_VFLIP: ++ ret = reg16_read16(client, 0x3040, &val); ++ if (ctrl->val) ++ val |= (1 << 15); ++ else ++ val &= ~(1 << 15); ++ ret |= reg16_write16(client, 0x3040, val); ++ break; ++ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: ++ ret = 0; ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ar0323_ctrl_ops = { ++ .s_ctrl = ar0323_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops ar0323_video_ops = { ++ .s_stream = ar0323_s_stream, ++ .g_mbus_config = ar0323_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops ar0323_subdev_pad_ops = { ++ .get_edid = ar0323_get_edid, ++ .enum_mbus_code = ar0323_enum_mbus_code, ++ .get_selection = ar0323_get_selection, ++ .set_selection = ar0323_set_selection, ++ .get_fmt = ar0323_get_fmt, ++ .set_fmt = ar0323_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops ar0323_subdev_ops = { ++ .core = &ar0323_core_ops, ++ .video = &ar0323_video_ops, ++ .pad = &ar0323_subdev_pad_ops, ++}; ++ ++static void ar0323_otp_id_read(struct i2c_client *client) ++{ ++ struct ar0323_priv *priv = to_ar0323(client); ++ int i; ++ u16 val = 0; ++ ++ /* read camera id from ar014x OTP memory */ ++ reg16_write16(client, 0x3054, 0x400); ++ reg16_write16(client, 0x304a, 0x110); ++ usleep_range(25000, 25500); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i += 2) { ++ /* first 4 bytes are equal on all ar014x */ ++ reg16_read16(client, 0x3800 + i + 4, &val); ++ priv->id[i] = val >> 8; ++ priv->id[i + 1] = val & 0xff; ++ } ++} ++ ++static ssize_t ar0323_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0323_priv *priv = to_ar0323(client); ++ ++ ar0323_otp_id_read(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_ar0323, S_IRUGO, ar0323_otp_id_show, NULL); ++ ++static int ar0323_initialize(struct i2c_client *client) ++{ ++ struct ar0323_priv *priv = to_ar0323(client); ++ u16 val = 0; ++ u16 pid = 0; ++ int ret = 0; ++// int tmp_addr; ++ ++ /* check and show model ID */ ++ reg16_read16(client, AR0323_PID, &pid); ++ ++ if (pid != AR0323_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x\n\n\n\n", pid); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++#if 0 ++ /* setup XCLK */ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ /* CLK_OUT=22.5792*160*M/N/CLKDIV -> CLK_OUT=27MHz: CLKDIV=2, M=15, N=251: 22.5792*160/8*15/251=26.987MHz=CLK_OUT */ ++ client->addr = priv->ti9x3_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x06, 0x6f); /* Set CLKDIV and M */ ++ reg8_write(client, 0x07, 0xfb); /* Set N */ ++ reg8_write(client, 0x0e, 0x1f); /* Set FSIN GPIO to output */ ++ } ++ client->addr = tmp_addr; ++#endif ++ ++ /* Program wizard registers */ ++ ar0323_set_regs(client, ar0323_regs_wizard, ARRAY_SIZE(ar0323_regs_wizard)); ++ ++ /* Enable stream */ ++ reg16_read16(client, 0x301a, &val); // read inital reset_register value ++ val |= (1 << 2); // Set streamOn bit ++ reg16_write16(client, 0x301a, val); // Start Streaming ++ ++ /* Read OTP IDs */ ++ ar0323_otp_id_read(client); ++ ++ dev_info(&client->dev, "ar0323 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, AR0323_MAX_WIDTH, AR0323_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ return ret; ++} ++ ++static int ar0323_parse_dt(struct device_node *np, struct ar0323_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ if (!priv->ti9x4_addr) { ++ dev_err(&client->dev, "deserializer does not present\n"); ++ return -EINVAL; ++ } ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, AR0323_I2C_ADDR << 1); /* Sensor native I2C address */ ++ ++// reg8_write(client, 0x6e, 0xa9); /* GPIO0 - reset, GPIO1 - fsin ??????? */ ++ } ++ client->addr = tmp_addr; ++ ++ mdelay(10); ++ ++ return 0; ++} ++ ++static int ar0323_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ar0323_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &ar0323_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0323_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0323_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0323_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0323_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0323_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0323_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0323_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0323_ctrl_ops, ++ V4L2_CID_GAIN, 1, 0x7ff, 1, 0x200); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0323_ctrl_ops, ++ V4L2_CID_ANALOGUE_GAIN, 1, 0xe, 1, 0xa); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0323_ctrl_ops, ++ V4L2_CID_EXPOSURE, 1, 0x600, 1, 0x144); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0323_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0323_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = ar0323_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = ar0323_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = AR0323_MAX_WIDTH; ++ priv->rect.height = AR0323_MAX_HEIGHT; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ar0323) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_AR0323 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int ar0323_remove(struct i2c_client *client) ++{ ++ struct ar0323_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ar0323); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_AR0323 ++static const struct i2c_device_id ar0323_id[] = { ++ { "ar0323", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ar0323_id); ++ ++static const struct of_device_id ar0323_of_ids[] = { ++ { .compatible = "aptina,ar0323", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ar0323_of_ids); ++ ++static struct i2c_driver ar0323_i2c_driver = { ++ .driver = { ++ .name = "ar0323", ++ .of_match_table = ar0323_of_ids, ++ }, ++ .probe = ar0323_probe, ++ .remove = ar0323_remove, ++ .id_table = ar0323_id, ++}; ++ ++module_i2c_driver(ar0323_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for AR0323"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/ar0323.h b/drivers/media/i2c/soc_camera/ar0323.h +new file mode 100644 +index 0000000..0711dd8 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0323.h +@@ -0,0 +1,1335 @@ ++/* ++ * ON Semiconductor AR0323 sensor camera wizard 1920x1080@30/BGGR/MIPI ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++//#define AR0323_DISPLAY_PATTERN_FIXED ++//#define AR0323_DISPLAY_PATTERN_COLOR_BAR ++ ++#define AR0323_MAX_WIDTH 2560 ++#define AR0323_MAX_HEIGHT 1080 ++ ++#define AR0323_DELAY 0xffff ++ ++#define AR0323_SENSOR_WIDTH 2880 ++#define AR0323_SENSOR_HEIGHT 1080 ++ ++#define AR0323_X_START ((AR0323_SENSOR_WIDTH - AR0323_MAX_WIDTH) / 2) ++#define AR0323_Y_START ((AR0323_SENSOR_HEIGHT - AR0323_MAX_HEIGHT) / 2) ++#define AR0323_X_END (AR0323_X_START + AR0323_MAX_WIDTH - 1) ++#define AR0323_Y_END (AR0323_Y_START + AR0323_MAX_HEIGHT - 1) ++ ++struct ar0323_reg { ++ u16 reg; ++ u16 val; ++}; ++ ++static const struct ar0323_reg ar0323_regs_wizard[] = { ++#if 0 ++{0x301A, 0x0018}, // RESET_REGISTER ++{AR0323_DELAY, 500}, // Wait 500ms ++{0x3070, 0x0000}, // 1: Solid color test pattern, ++ // 2: Full color bar test pattern, ++ // 3: Fade to grey color bar test pattern, ++ //256: Walking 1 test pattern (12 bit) ++{0x3072, 0x0123}, // R ++{0x3074, 0x0456}, // G(GR row) ++{0x3076, 0x0abc}, // B ++{0x3078, 0x0def}, // G(GB row) ++#ifdef AR0323_DISPLAY_PATTERN_FIXED ++{0x3070, 0x0001}, ++#endif ++#ifdef AR0323_DISPLAY_PATTERN_COLOR_BAR ++{0x3070, 0x0002}, ++#endif ++{AR0323_DELAY, 100}, // Wait 100ms ++#endif ++ ++{0x301A, 0x0059}, // RESET_REGISTER ++{0x301A, 0x0058}, // RESET_REGISTER ++{AR0323_DELAY, 200}, // Wait 200ms ++ ++//continuous MIPI 12bit ++{0x3342, 0x122C}, // MIPI_F1_PDT_EDT ++{0x3346, 0x122C}, // MIPI_F2_PDT_EDT ++{0x334A, 0x122C}, // MIPI_F3_PDT_EDT ++{0x334E, 0x122C}, // MIPI_F4_PDT_EDT ++ ++//PLL settings ++{0x302E, 0x0002}, // PRE_PLL_CLK_DIV ++{0x3030, 0x0052}, // PLL_MULTIPLIER ++{0x302C, 0x0001}, // VT_SYS_CLK_DIV ++{0x302A, 0x0008}, // VT_PIX_CLK_DIV ++{0x3038, 0x0004}, // OP_SYS_CLK_DIV ++{0x3036, 0x0006}, // OP_WORD_CLK_DIV ++ ++//MIPI timing ++{0x31B0, 0x0059}, // FRAME_PREAMBLE ++{0x31B2, 0x003B}, // LINE_PREAMBLE ++{0x31B4, 0x31C5}, // MIPI_TIMING_0 ++{0x31B6, 0x114E}, // MIPI_TIMING_1 ++{0x31B8, 0x5048}, // MIPI_TIMING_2 ++{0x31BA, 0x0186}, // MIPI_TIMING_3 ++{0x31BC, 0x8885}, // MIPI_TIMING_4 ++ ++//HDR ++{0x3E00, 0x8000}, // LFM2_T1_CTRL ++{0x3082, 0x0004}, // OPERATION_MODE_CTRL ++{0x30BA, 0x1103}, // DIGITAL_CTRL ++ ++//new sequencer ++{0x2512, 0x8000}, ++{0x2510, 0x0712}, ++{0x2510, 0x1314}, ++{0x2510, 0x1518}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0x1b1d}, ++{0x2510, 0x2224}, ++{0x2510, 0x2628}, ++{0x2510, 0xffff}, ++{0x2510, 0x2a48}, ++{0x2510, 0x5672}, ++{0x2510, 0x7f85}, ++{0x2510, 0x8991}, ++{0x2510, 0xaeb3}, ++{0x2510, 0xbdc4}, ++{0x2510, 0xc5c8}, ++{0x2510, 0xccd0}, ++{0x2510, 0xd4d6}, ++{0x2510, 0xd8dd}, ++{0x2510, 0xdfe2}, ++{0x2510, 0xe5e8}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xc003}, ++{0x2510, 0xa0e0}, ++{0x2510, 0x3041}, ++{0x2510, 0x3042}, ++{0x2510, 0x2000}, ++{0x2510, 0x3048}, ++{0x2510, 0x3081}, ++{0x2510, 0x3084}, ++{0x2510, 0x3082}, ++{0x2510, 0x2003}, ++{0x2510, 0x3044}, ++{0x2510, 0x2000}, ++{0x2510, 0xa004}, ++{0x2510, 0x20ff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x807c}, ++{0x2510, 0xa0e0}, ++{0x2510, 0x3041}, ++{0x2510, 0x3042}, ++{0x2510, 0x2000}, ++{0x2510, 0xa0c0}, ++{0x2510, 0x9008}, ++{0x2510, 0x8802}, ++{0x2510, 0x20ff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x9018}, ++{0x2510, 0x891a}, ++{0x2510, 0x807c}, ++{0x2510, 0x20ff}, ++{0x2510, 0x895b}, ++{0x2510, 0x20ff}, ++{0x2510, 0x897b}, ++{0x2510, 0x20ff}, ++{0x2510, 0x897f}, ++{0x2510, 0x20ff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xa0c4}, ++{0x2510, 0x20ff}, ++{0x2510, 0x8058}, ++{0x2510, 0x9039}, ++{0x2510, 0x20ff}, ++{0x2510, 0x907f}, ++{0x2510, 0x895b}, ++{0x2510, 0x2064}, ++{0x2510, 0x891b}, ++{0x2510, 0x2010}, ++{0x2510, 0x8803}, ++{0x2510, 0x7fff}, ++{0x2510, 0x3088}, ++{0x2510, 0x3090}, ++{0x2510, 0x20ff}, ++{0x2510, 0x906b}, ++{0x2510, 0x2064}, ++{0x2510, 0x3084}, ++{0x2510, 0x2003}, ++{0x2510, 0x3044}, ++{0x2510, 0x2000}, ++{0x2510, 0xa004}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2400}, ++{0x2510, 0x2401}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2400}, ++{0x2510, 0x2401}, ++{0x2510, 0x2702}, ++{0x2510, 0x3242}, ++{0x2510, 0x2420}, ++{0x2510, 0x2702}, ++{0x2510, 0x2421}, ++{0x2510, 0x2703}, ++{0x2510, 0x3242}, ++{0x2510, 0x2420}, ++{0x2510, 0x2703}, ++{0x2510, 0x2421}, ++{0x2510, 0x2704}, ++{0x2510, 0x3242}, ++{0x2510, 0x2420}, ++{0x2510, 0x2704}, ++{0x2510, 0x2421}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2402}, ++{0x2510, 0x2403}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2741}, ++{0x2510, 0x2429}, ++{0x2510, 0x2740}, ++{0x2510, 0x242a}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2404}, ++{0x2510, 0x2779}, ++{0x2510, 0x242c}, ++{0x2510, 0x2781}, ++{0x2510, 0x242d}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2703}, ++{0x2510, 0x2432}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xb800}, ++{0x2510, 0x8058}, ++{0x2510, 0xa005}, ++{0x2510, 0x30c1}, ++{0x2510, 0x3101}, ++{0x2510, 0x3041}, ++{0x2510, 0x3041}, ++{0x2510, 0x3250}, ++{0x2510, 0x3108}, ++{0x2510, 0x3104}, ++{0x2510, 0x3102}, ++{0x2510, 0x3041}, ++{0x2510, 0xf860}, ++{0x2510, 0xb095}, ++{0x2510, 0x3141}, ++{0x2510, 0x3042}, ++{0x2510, 0xb848}, ++{0x2510, 0xb84c}, ++{0x2510, 0x8843}, ++{0x2510, 0x916f}, ++{0x2510, 0x3110}, ++{0x2510, 0x3042}, ++{0x2510, 0xb84e}, ++{0x2510, 0xf905}, ++{0x2510, 0xf907}, ++{0x2510, 0x3202}, ++{0x2510, 0x885b}, ++{0x2510, 0xa898}, ++{0x2510, 0xa8d8}, ++{0x2510, 0xb397}, ++{0x2510, 0xf8e8}, ++{0x2510, 0x80dc}, ++{0x2510, 0x2206}, ++{0x2510, 0xb137}, ++{0x2510, 0xb808}, ++{0x2510, 0xc800}, ++{0x2510, 0xe809}, ++{0x2510, 0xb177}, ++{0x2510, 0x88df}, ++{0x2510, 0xf8a8}, ++{0x2510, 0xf888}, ++{0x2510, 0x2203}, ++{0x2510, 0xb07b}, ++{0x2510, 0x2000}, ++{0x2510, 0x80cc}, ++{0x2510, 0x808c}, ++{0x2510, 0x220b}, ++{0x2510, 0xb06a}, ++{0x2510, 0x88cf}, ++{0x2510, 0x888f}, ++{0x2510, 0x222f}, ++{0x2510, 0x2771}, ++{0x2510, 0x2512}, ++{0x2510, 0xb04a}, ++{0x2510, 0x2213}, ++{0x2510, 0x2771}, ++{0x2510, 0x2525}, ++{0x2510, 0xb04b}, ++{0x2510, 0x902f}, ++{0x2510, 0xf880}, ++{0x2510, 0x220e}, ++{0x2510, 0x2201}, ++{0x2510, 0x2201}, ++{0x2510, 0x2204}, ++{0x2510, 0xb043}, ++{0x2510, 0x2201}, ++{0x2510, 0xa8c9}, ++{0x2510, 0x31c1}, ++{0x2510, 0x80ac}, ++{0x2510, 0x916f}, ++{0x2510, 0x2112}, ++{0x2510, 0x88af}, ++{0x2510, 0x2440}, ++{0x2510, 0xf110}, ++{0x2510, 0xf804}, ++{0x2510, 0x2000}, ++{0x2510, 0x8088}, ++{0x2510, 0xb838}, ++{0x2510, 0xa8c8}, ++{0x2510, 0xb04b}, ++{0x2510, 0x2442}, ++{0x2510, 0x3210}, ++{0x2510, 0x3002}, ++{0x2510, 0x220c}, ++{0x2510, 0x888b}, ++{0x2510, 0x2204}, ++{0x2510, 0x3202}, ++{0x2510, 0x2204}, ++{0x2510, 0xf880}, ++{0x2510, 0xb830}, ++{0x2510, 0xc801}, ++{0x2510, 0x30c2}, ++{0x2510, 0xe80c}, ++{0x2510, 0x2201}, ++{0x2510, 0xb04a}, ++{0x2510, 0x2229}, ++{0x2510, 0x2771}, ++{0x2510, 0x2513}, ++{0x2510, 0x902f}, ++{0x2510, 0x221f}, ++{0x2510, 0x2201}, ++{0x2510, 0x2204}, ++{0x2510, 0xb042}, ++{0x2510, 0x2201}, ++{0x2510, 0xa9a1}, ++{0x2510, 0x8008}, ++{0x2510, 0xb093}, ++{0x2510, 0x31c1}, ++{0x2510, 0x916b}, ++{0x2510, 0x2009}, ++{0x2510, 0x8803}, ++{0x2510, 0xa044}, ++{0x2510, 0x3044}, ++{0x2510, 0x2000}, ++{0x2510, 0xa004}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xa084}, ++{0x2510, 0x8078}, ++{0x2510, 0x3141}, ++{0x2510, 0x3041}, ++{0x2510, 0x3042}, ++{0x2510, 0x2000}, ++{0x2510, 0x3142}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x3110}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x3120}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x3144}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x3148}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x2206}, ++{0x2510, 0x881b}, ++{0x2510, 0x887b}, ++{0x2510, 0x2440}, ++{0x2510, 0xb095}, ++{0x2510, 0xf110}, ++{0x2510, 0xf804}, ++{0x2510, 0xf90d}, ++{0x2510, 0x3084}, ++{0x2510, 0x3090}, ++{0x2510, 0x3088}, ++{0x2510, 0x8058}, ++{0x2510, 0x3001}, ++{0x2510, 0x2442}, ++{0x2510, 0x3260}, ++{0x2510, 0x3248}, ++{0x2510, 0x3220}, ++{0x2510, 0x2002}, ++{0x2510, 0x8863}, ++{0x2510, 0x2004}, ++{0x2510, 0x8803}, ++{0x2510, 0x2204}, ++{0x2510, 0x30c2}, ++{0x2510, 0xa9a0}, ++{0x2510, 0xb094}, ++{0x2510, 0x2201}, ++{0x2510, 0xa0c4}, ++{0x2510, 0x3044}, ++{0x2510, 0x2000}, ++{0x2510, 0xa004}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xb980}, ++{0x2510, 0x8108}, ++{0x2510, 0xa105}, ++{0x2510, 0x30c1}, ++{0x2510, 0x2000}, ++{0x2510, 0x3101}, ++{0x2510, 0x3041}, ++{0x2510, 0x3250}, ++{0x2510, 0x3108}, ++{0x2510, 0x3104}, ++{0x2510, 0x3102}, ++{0x2510, 0x3041}, ++{0x2510, 0xf860}, ++{0x2510, 0xb095}, ++{0x2510, 0x3141}, ++{0x2510, 0x3042}, ++{0x2510, 0xb9f8}, ++{0x2510, 0xb9fc}, ++{0x2510, 0x8803}, ++{0x2510, 0x916f}, ++{0x2510, 0x3110}, ++{0x2510, 0x3042}, ++{0x2510, 0xb9fe}, ++{0x2510, 0xf905}, ++{0x2510, 0xf907}, ++{0x2510, 0x3202}, ++{0x2510, 0x880b}, ++{0x2510, 0xa888}, ++{0x2510, 0xa8c8}, ++{0x2510, 0xb397}, ++{0x2510, 0xf8e8}, ++{0x2510, 0x818c}, ++{0x2510, 0x2206}, ++{0x2510, 0xb137}, ++{0x2510, 0xb9b8}, ++{0x2510, 0xc801}, ++{0x2510, 0xe809}, ++{0x2510, 0xb177}, ++{0x2510, 0x888f}, ++{0x2510, 0xf8a8}, ++{0x2510, 0xf888}, ++{0x2510, 0x2203}, ++{0x2510, 0xb07b}, ++{0x2510, 0x2000}, ++{0x2510, 0x2206}, ++{0x2510, 0xb06a}, ++{0x2510, 0x2210}, ++{0x2510, 0x818c}, ++{0x2510, 0x2204}, ++{0x2510, 0x888f}, ++{0x2510, 0x888f}, ++{0x2510, 0x2215}, ++{0x2510, 0xb04a}, ++{0x2510, 0x2212}, ++{0x2510, 0x2111}, ++{0x2510, 0xb04b}, ++{0x2510, 0x902f}, ++{0x2510, 0xf880}, ++{0x2510, 0x220e}, ++{0x2510, 0x2201}, ++{0x2510, 0x2204}, ++{0x2510, 0xb043}, ++{0x2510, 0x2201}, ++{0x2510, 0xa8d9}, ++{0x2510, 0x31c1}, ++{0x2510, 0x80cc}, ++{0x2510, 0x916f}, ++{0x2510, 0x2110}, ++{0x2510, 0x88cf}, ++{0x2510, 0x2440}, ++{0x2510, 0xf110}, ++{0x2510, 0xf804}, ++{0x2510, 0x2000}, ++{0x2510, 0xb988}, ++{0x2510, 0xa8d8}, ++{0x2510, 0xb04b}, ++{0x2510, 0x3002}, ++{0x2510, 0x2442}, ++{0x2510, 0x3210}, ++{0x2510, 0x220a}, ++{0x2510, 0x2204}, ++{0x2510, 0x3202}, ++{0x2510, 0x2204}, ++{0x2510, 0xb980}, ++{0x2510, 0xc800}, ++{0x2510, 0x30c2}, ++{0x2510, 0xe80c}, ++{0x2510, 0x2201}, ++{0x2510, 0xb04a}, ++{0x2510, 0x221f}, ++{0x2510, 0x8088}, ++{0x2510, 0x220a}, ++{0x2510, 0x888b}, ++{0x2510, 0x902f}, ++{0x2510, 0x221e}, ++{0x2510, 0x2201}, ++{0x2510, 0x2204}, ++{0x2510, 0xb042}, ++{0x2510, 0x2201}, ++{0x2510, 0xa9a1}, ++{0x2510, 0x8018}, ++{0x2510, 0xb093}, ++{0x2510, 0x31c1}, ++{0x2510, 0x916b}, ++{0x2510, 0x2009}, ++{0x2510, 0x8803}, ++{0x2510, 0x2000}, ++{0x2510, 0xa004}, ++{0x2510, 0xb800}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x8078}, ++{0x2510, 0xa184}, ++{0x2510, 0xb981}, ++{0x2510, 0x3141}, ++{0x2510, 0x3041}, ++{0x2510, 0x3042}, ++{0x2510, 0x2000}, ++{0x2510, 0x3142}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x3110}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x3120}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x30a0}, ++{0x2510, 0x2206}, ++{0x2510, 0x881b}, ++{0x2510, 0x887b}, ++{0x2510, 0x2282}, ++{0x2510, 0xb095}, ++{0x2510, 0xf110}, ++{0x2510, 0xf804}, ++{0x2510, 0xf90d}, ++{0x2510, 0x3090}, ++{0x2510, 0x3088}, ++{0x2510, 0x8058}, ++{0x2510, 0x2202}, ++{0x2510, 0x3001}, ++{0x2510, 0x3260}, ++{0x2510, 0x3248}, ++{0x2510, 0x2002}, ++{0x2510, 0x885b}, ++{0x2510, 0x2004}, ++{0x2510, 0x2204}, ++{0x2510, 0x8018}, ++{0x2510, 0x2209}, ++{0x2510, 0x881b}, ++{0x2510, 0xa9a0}, ++{0x2510, 0xb094}, ++{0x2510, 0x2209}, ++{0x2510, 0x8000}, ++{0x2510, 0x2209}, ++{0x2510, 0x8803}, ++{0x2510, 0xa1c4}, ++{0x2510, 0x3044}, ++{0x2510, 0xb800}, ++{0x2510, 0xa004}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x9818}, ++{0x2510, 0xb800}, ++{0x2510, 0x3101}, ++{0x2510, 0x3041}, ++{0x2510, 0x2200}, ++{0x2510, 0x3102}, ++{0x2510, 0x3041}, ++{0x2510, 0x2200}, ++{0x2510, 0x8018}, ++{0x2510, 0x2002}, ++{0x2510, 0x8038}, ++{0x2510, 0x2205}, ++{0x2510, 0x881b}, ++{0x2510, 0x883b}, ++{0x2510, 0x213e}, ++{0x2510, 0x8018}, ++{0x2510, 0x2202}, ++{0x2510, 0x8000}, ++{0x2510, 0x2202}, ++{0x2510, 0x8803}, ++{0x2510, 0x9800}, ++{0x2510, 0xa004}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2440}, ++{0x2510, 0xb095}, ++{0x2510, 0xf110}, ++{0x2510, 0xf804}, ++{0x2510, 0xf90d}, ++{0x2510, 0x2442}, ++{0x2510, 0x3260}, ++{0x2510, 0x3248}, ++{0x2510, 0x3220}, ++{0x2510, 0x2007}, ++{0x2510, 0x2204}, ++{0x2510, 0x30c2}, ++{0x2510, 0xa9a0}, ++{0x2510, 0xb094}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xb981}, ++{0x2510, 0x3101}, ++{0x2510, 0x3041}, ++{0x2510, 0x3102}, ++{0x2510, 0x3041}, ++{0x2510, 0x8028}, ++{0x2510, 0x2212}, ++{0x2510, 0x880b}, ++{0x2510, 0x882b}, ++{0x2510, 0x2440}, ++{0x2510, 0xb095}, ++{0x2510, 0xf110}, ++{0x2510, 0xf804}, ++{0x2510, 0xf90d}, ++{0x2510, 0x8008}, ++{0x2510, 0x2202}, ++{0x2510, 0x3001}, ++{0x2510, 0x3260}, ++{0x2510, 0x3248}, ++{0x2510, 0x2442}, ++{0x2510, 0x8823}, ++{0x2510, 0x3220}, ++{0x2510, 0x2007}, ++{0x2510, 0x8803}, ++{0x2510, 0x2204}, ++{0x2510, 0x30c2}, ++{0x2510, 0xa8a0}, ++{0x2510, 0xb094}, ++{0x2510, 0x2201}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xb800}, ++{0x2510, 0x8058}, ++{0x2510, 0xa005}, ++{0x2510, 0x30c1}, ++{0x2510, 0x3101}, ++{0x2510, 0x3041}, ++{0x2510, 0x3041}, ++{0x2510, 0x3250}, ++{0x2510, 0x3108}, ++{0x2510, 0x3104}, ++{0x2510, 0x3102}, ++{0x2510, 0x3041}, ++{0x2510, 0xf860}, ++{0x2510, 0xb095}, ++{0x2510, 0x3141}, ++{0x2510, 0x3042}, ++{0x2510, 0xb848}, ++{0x2510, 0xb84c}, ++{0x2510, 0x8843}, ++{0x2510, 0x916f}, ++{0x2510, 0x3110}, ++{0x2510, 0x3042}, ++{0x2510, 0xb84e}, ++{0x2510, 0xf905}, ++{0x2510, 0xf907}, ++{0x2510, 0x3202}, ++{0x2510, 0x885b}, ++{0x2510, 0xa898}, ++{0x2510, 0xa8d8}, ++{0x2510, 0xb397}, ++{0x2510, 0xf8e8}, ++{0x2510, 0x80dc}, ++{0x2510, 0x2206}, ++{0x2510, 0xb137}, ++{0x2510, 0xb808}, ++{0x2510, 0xc800}, ++{0x2510, 0xe809}, ++{0x2510, 0xb177}, ++{0x2510, 0x88df}, ++{0x2510, 0xf8a8}, ++{0x2510, 0xf888}, ++{0x2510, 0x2203}, ++{0x2510, 0xb07b}, ++{0x2510, 0x2000}, ++{0x2510, 0x80cc}, ++{0x2510, 0x808c}, ++{0x2510, 0x220b}, ++{0x2510, 0xb06a}, ++{0x2510, 0x88cf}, ++{0x2510, 0x888f}, ++{0x2510, 0x222f}, ++{0x2510, 0x2771}, ++{0x2510, 0x251e}, ++{0x2510, 0xb04a}, ++{0x2510, 0x2213}, ++{0x2510, 0x2771}, ++{0x2510, 0x2525}, ++{0x2510, 0xb04b}, ++{0x2510, 0x902f}, ++{0x2510, 0xf880}, ++{0x2510, 0x221e}, ++{0x2510, 0x2201}, ++{0x2510, 0x2204}, ++{0x2510, 0xb043}, ++{0x2510, 0x2201}, ++{0x2510, 0xa8c9}, ++{0x2510, 0x31c1}, ++{0x2510, 0x80ac}, ++{0x2510, 0x916f}, ++{0x2510, 0x2112}, ++{0x2510, 0x88af}, ++{0x2510, 0x2440}, ++{0x2510, 0xf110}, ++{0x2510, 0xf804}, ++{0x2510, 0x2000}, ++{0x2510, 0x8088}, ++{0x2510, 0xb838}, ++{0x2510, 0xa8c8}, ++{0x2510, 0xb04b}, ++{0x2510, 0x2442}, ++{0x2510, 0x3210}, ++{0x2510, 0x3002}, ++{0x2510, 0x220c}, ++{0x2510, 0x888b}, ++{0x2510, 0x2204}, ++{0x2510, 0x3202}, ++{0x2510, 0xf880}, ++{0x2510, 0xb830}, ++{0x2510, 0xc801}, ++{0x2510, 0x30c2}, ++{0x2510, 0xe80c}, ++{0x2510, 0x2201}, ++{0x2510, 0xb04a}, ++{0x2510, 0x2229}, ++{0x2510, 0x2771}, ++{0x2510, 0x2513}, ++{0x2510, 0x902f}, ++{0x2510, 0x221f}, ++{0x2510, 0x2201}, ++{0x2510, 0x2204}, ++{0x2510, 0xb042}, ++{0x2510, 0x2201}, ++{0x2510, 0xa8e1}, ++{0x2510, 0x8008}, ++{0x2510, 0xb093}, ++{0x2510, 0x31c1}, ++{0x2510, 0x916b}, ++{0x2510, 0x2009}, ++{0x2510, 0x8803}, ++{0x2510, 0x2000}, ++{0x2510, 0xa004}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2440}, ++{0x2510, 0xb095}, ++{0x2510, 0xf110}, ++{0x2510, 0xf804}, ++{0x2510, 0xf90d}, ++{0x2510, 0x2442}, ++{0x2510, 0x3220}, ++{0x2510, 0x2002}, ++{0x2510, 0x2204}, ++{0x2510, 0x30c2}, ++{0x2510, 0xa9a0}, ++{0x2510, 0x2004}, ++{0x2510, 0xb094}, ++{0x2510, 0x2201}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2749}, ++{0x2510, 0x2422}, ++{0x2510, 0x2749}, ++{0x2510, 0x2423}, ++{0x2510, 0x2709}, ++{0x2510, 0x2420}, ++{0x2510, 0x2729}, ++{0x2510, 0x2423}, ++{0x2510, 0x3242}, ++{0x2510, 0x2722}, ++{0x2510, 0x2422}, ++{0x2510, 0x2769}, ++{0x2510, 0x2421}, ++{0x2510, 0x2702}, ++{0x2510, 0x2421}, ++{0x2510, 0x3242}, ++{0x2510, 0x276a}, ++{0x2510, 0x2420}, ++{0x2510, 0x276a}, ++{0x2510, 0x2421}, ++{0x2510, 0x2703}, ++{0x2510, 0x2420}, ++{0x2510, 0x2703}, ++{0x2510, 0x2421}, ++{0x2510, 0x3242}, ++{0x2510, 0x276b}, ++{0x2510, 0x2420}, ++{0x2510, 0x276b}, ++{0x2510, 0x2421}, ++{0x2510, 0x2704}, ++{0x2510, 0x2420}, ++{0x2510, 0x2704}, ++{0x2510, 0x2421}, ++{0x2510, 0x3242}, ++{0x2510, 0x276c}, ++{0x2510, 0x2420}, ++{0x2510, 0x276c}, ++{0x2510, 0x2421}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2759}, ++{0x2510, 0x2422}, ++{0x2510, 0x2758}, ++{0x2510, 0x2420}, ++{0x2510, 0x2403}, ++{0x2510, 0x2712}, ++{0x2510, 0x3242}, ++{0x2510, 0x2422}, ++{0x2510, 0x271a}, ++{0x2510, 0x3242}, ++{0x2510, 0x2420}, ++{0x2510, 0x2702}, ++{0x2510, 0x2423}, ++{0x2510, 0x2703}, ++{0x2510, 0x3242}, ++{0x2510, 0x2420}, ++{0x2510, 0x2703}, ++{0x2510, 0x2423}, ++{0x2510, 0x2704}, ++{0x2510, 0x3242}, ++{0x2510, 0x2420}, ++{0x2510, 0x2704}, ++{0x2510, 0x2423}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xc023}, ++{0x2510, 0x2402}, ++{0x2510, 0x2405}, ++{0x2510, 0x2789}, ++{0x2510, 0x242e}, ++{0x2510, 0x2788}, ++{0x2510, 0x242f}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xc027}, ++{0x2510, 0x2407}, ++{0x2510, 0x2406}, ++{0x2510, 0xc063}, ++{0x2510, 0x2402}, ++{0x2510, 0x2751}, ++{0x2510, 0x2423}, ++{0x2510, 0x2750}, ++{0x2510, 0x2421}, ++{0x2510, 0xc003}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xc021}, ++{0x2510, 0x2400}, ++{0x2510, 0x2405}, ++{0x2510, 0xc062}, ++{0x2510, 0x2400}, ++{0x2510, 0xc063}, ++{0x2510, 0x2751}, ++{0x2510, 0x2423}, ++{0x2510, 0x2750}, ++{0x2510, 0x2421}, ++{0x2510, 0xc003}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xc0e3}, ++{0x2510, 0x2400}, ++{0x2510, 0x27b1}, ++{0x2510, 0x2425}, ++{0x2510, 0xc063}, ++{0x2510, 0x2420}, ++{0x2510, 0x2751}, ++{0x2510, 0x2423}, ++{0x2510, 0x2750}, ++{0x2510, 0x2421}, ++{0x2510, 0xc003}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2404}, ++{0x2510, 0x2779}, ++{0x2510, 0x242c}, ++{0x2510, 0x2781}, ++{0x2510, 0x242d}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2791}, ++{0x2510, 0x2430}, ++{0x2510, 0x2799}, ++{0x2510, 0x2428}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2417}, ++{0x2510, 0xc023}, ++{0x2510, 0x2403}, ++{0x2510, 0x2703}, ++{0x2510, 0x3242}, ++{0x2510, 0x2404}, ++{0x2510, 0x240d}, ++{0x2510, 0xc003}, ++{0x2510, 0x2703}, ++{0x2510, 0x3242}, ++{0x2510, 0x2400}, ++{0x2510, 0x2408}, ++{0x2510, 0x2703}, ++{0x2510, 0x3242}, ++{0x2510, 0x2417}, ++{0x2510, 0x240b}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xc022}, ++{0x2510, 0x2402}, ++{0x2510, 0x2405}, ++{0x2510, 0x2414}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xc022}, ++{0x2510, 0x2407}, ++{0x2510, 0x2405}, ++{0x2510, 0xc061}, ++{0x2510, 0x2400}, ++{0x2510, 0xc023}, ++{0x2510, 0x2403}, ++{0x2510, 0xc003}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xc022}, ++{0x2510, 0x2404}, ++{0x2510, 0x2779}, ++{0x2510, 0x2433}, ++{0x2510, 0x2781}, ++{0x2510, 0x2436}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xc126}, ++{0x2510, 0x2407}, ++{0x2510, 0xc022}, ++{0x2510, 0x2406}, ++{0x2510, 0x2402}, ++{0x2510, 0xc023}, ++{0x2510, 0x2405}, ++{0x2510, 0x2417}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++ ++{AR0323_DELAY, 100}, // Wait 100ms ++{0x301A, 0x0058}, // RESET_REGISTER ++ ++{0x31AC, 0x140C}, // DATA_FORMAT_BITS ++{0x31D0, 0x0001}, // COMPANDING ++{0x336E, 0x01DF}, // DATAPATH_SELECT2 ++{0x3238, 0x0666}, // EXPOSURE_RATIO ++#if 1 ++{0x300C, 0x0A60}, // LINE_LENGTH_PCK_ ++{0x300A, 0x04A0}, // FRAME_LENGTH_LINES_ ++#else ++{0x300A, AR0323_SENSOR_HEIGHT + 208}, // FRAME_LENGTH_LINES_ ++{0x300C, AR0323_SENSOR_WIDTH + 300}, // LINE_LENGTH_PCK_ ++#endif ++ ++#if 0 ++//2880x1072 resolution ++{0x3004, 0x0008}, // X_ADDR_START_ ++{0x3008, 0x0B47}, // X_ADDR_END_ ++{0x3002, 0x010C}, // Y_ADDR_START_ ++{0x3006, 0x053B}, // Y_ADDR_END_ ++#else ++{0x3004, AR0323_X_START}, // X_ADDR_START_ ++{0x3008, AR0323_X_END}, // X_ADDR_END_ ++{0x3002, AR0323_Y_START}, // Y_ADDR_START_ ++{0x3006, AR0323_Y_END}, // Y_ADDR_END_ ++{0x3402, 0x0000 | AR0323_MAX_WIDTH}, // X_OUTPUT_CONTROL ++{0x3404, 0x0000 | AR0323_MAX_HEIGHT}, // Y_OUTPUT_CONTROL ++#endif ++ ++{0x3534, 0xA282}, // DAC_LD_52_53 ++{0x3524, 0x0FFF}, // DAC_LD_36_37 ++{0x3180, 0x1001}, // DELTA_DK_CONTROL ++{0x3576, 0x1F09}, // DAC_LD_118_119 ++ ++{0x3548, 0x7878}, // DAC_LD_72_73 ++{0x354C, 0x4141}, // DAC_LD_76_77 ++{0x354E, 0x4B4B}, // DAC_LD_78_79 ++{0x356E, 0x158A}, // DAC_LD_110_111 ++ ++//overflow},settings ++{0x3496, 0xCF0A}, // LFM_CONTROL ++{0x350E, 0x2181}, // DAC_LD_14_15 ++{0x3E02, 0x0834}, // LFM2_T1_E1_A ++{0x3E04, 0x0000}, // LFM2_T1_E1_B ++{0x3E08, 0x1FFF}, // LFM2_T1_E2_A ++{0x3E14, 0x0020}, // LFM2_T1_SLOPE ++{0x3E16, 0x1F40}, // LFM2_T1_E1_THRESHOLD ++// ++{0x562A, 0x05DC}, // OCL_T1_E2_E1_SAT ++{0x563A, 0x0011}, // OCL_T1_GAIN_ ++ ++{0x3364, 0x068C}, // DCG_TRIM ++{0x3290, 0xD354}, // T3_BARRIER_C0 ++{0x3292, 0xD354}, // T3_BARRIER_C1 ++{0x3294, 0xD354}, // T3_BARRIER_C2 ++{0x3296, 0xD354}, // T3_BARRIER_C3 ++{0x3298, 0xD354}, // T4_BARRIER_C0 ++{0x329A, 0xD354}, // T4_BARRIER_C1 ++{0x329C, 0xD354}, // T4_BARRIER_C2 ++{0x329E, 0xD354}, // T4_BARRIER_C3 ++{0x33DA, 0x0001}, // OC_LUT_CONTROL ++{0x3D00, 0x6007}, // MEC_CTRL1 ++ ++{0x3040, 0xC005}, // READ_MODE ++{0x3352, 0x2000}, // MIPI_DT_VC_CONFIG ++{0x3064, 0x0180}, // SMIA_TEST ++ ++{0x3D10, 0x0000}, // VIS_BOUND_X0 ++{0x3D12, 0x0B40}, // VIS_BOUND_X1 ++{0x3D14, 0x001E}, // VIS_BOUND_Y0 ++{0x3D16, 0x045A}, // VIS_BOUND_Y1 ++ ++{0x3D08, 0x0000}, // DTR_BOUND_X0 ++{0x3D0A, 0x0B40}, // DTR_BOUND_X1 ++{0x3D0C, 0x0004}, // DTR_BOUND_Y0 ++{0x3D0E, 0x000C}, // DTR_BOUND_Y1 ++{AR0323_DELAY, 100}, // Wait 100ms ++ ++//Pre HDR gain LG lens ++{0x3110, 0x0011}, // HDR_CONTROL0 ++{0x3056, 0x0031}, // GREEN1_GAIN ++{0x3058, 0x0080}, // BLUE_GAIN ++{0x305A, 0x0070}, // RED_GAIN ++{0x305C, 0x0031}, // GREEN2_GAIN ++{0x3308, 0x0539}, // GLOBAL_GAIN2_ ++{0x3D28, 0x3BD1}, // T1_STR_DEC_TH ++{0x3D2A, 0x4C2C}, // T1_END_DEC_TH ++ ++//booster ++{0x352C, 0x8146}, // DAC_LD_44_45 ++{0x352E, 0x1871}, // DAC_LD_46_47 ++{0x3538, 0x81EA}, // DAC_LD_56_57 ++ ++{0x3576, 0x1F49}, // DAC_LD_118_119 ++{0x3544, 0x03A1}, // DAC_LD_68_69 ++ ++{0x354C, 0x411E}, // DAC_LD_76_77 ++// ++{0x351A, 0x7900}, ++ ++//Temp_sensor_read ++{0x3E94, 0x3010}, // TEMPVSENS1_SREG_TRIM0 ++{0x30B8, 0x0003}, // TEMPSENS1_CTRL_REG ++{0x3F92, 0x4D00}, // TEMPVSENS1_TMG_CTRL ++{0x3F96, 0xFFFE}, //003E // TEMPVSENS1_FLAG_CTRL ++{0x3EE0, 0x0700}, //0000 // TEMPVSENS1_FLAG_CTRL_EXT ++{0x3E98, 0x4000}, // TEMPVSENS1_EN_CTRL ++ ++//analog},1x ++{0x3022, 0x01}, // GROUPED_PARAMETER_HOLD_ ++{0x3D34, 0x0562}, // T2_STR_DEC_TH ++{0x3D36, 0x0562}, // T2_END_DEC_TH ++{0x563A, 0x0011}, // OCL_T1_GAIN_ ++{0x3E18, 0x0EEE}, // LFM2_T1_E2_GAIN_CTRL ++{0x3366, 0x1121}, // ANALOG_GAIN ++{0x3364, 700}, //2D0 // DCG_TRIM ++{0x336A, 0x0080}, // ANALOG_GAIN2 ++{0x3E02, 0x09C4}, // LFM2_T1_E1_A ++{0x3022, 0x00}, // GROUPED_PARAMETER_HOLD_ ++ ++//updated},pink},reduction},settings ++{0x3D02, 0x6033}, // MEC_CTRL2 ++{0x3534, 0xA284}, // DAC_LD_52_53 ++{0x3546, 0x3601}, // DAC_LD_70_71 ++{0x3518, 0x4444}, // DAC_LD_24_25 ++ ++{0x3494, 0x0C0C}, // LFM_TX_PATTERN_CTRL ++{0x34BC, 0x000C}, // LFM_PATTERN_CTRL ++{0x3E02, 0x09C4}, // LFM2_T1_E1_A ++ ++//band},mitigation ++{0x3450, 0x00A4}, // LFM_PHASE0_PERIOD ++{0x3452, 0x004F}, // LFM_PHASE1_PERIOD ++{0x3454, 0x004F}, // LFM_PHASE2_PERIOD ++{0x3456, 0x004F}, // LFM_PHASE3_PERIOD ++{0x3458, 0x004F}, // LFM_PHASE4_PERIOD ++{0x345A, 0x004F}, // LFM_PHASE5_PERIOD ++{0x345C, 0x004F}, // LFM_PHASE6_PERIOD ++{0x345E, 0x004F}, // LFM_PHASE7_PERIOD ++{0x3460, 0x004F}, // LFM_PHASE8_PERIOD ++{0x3462, 0x004F}, // LFM_PHASE9_PERIOD ++{0x3464, 0x004F}, // LFM_PHASE10_PERIOD ++{0x3466, 0x004F}, // LFM_PHASE11_PERIOD ++{0x3468, 0x00A4}, // LFM_PHASE12_PERIOD ++{0x346A, 0x004F}, // LFM_PHASE13_PERIOD ++{0x346C, 0x004F}, // LFM_PHASE14_PERIOD ++{0x346E, 0x004F}, // LFM_PHASE15_PERIOD ++{0x3470, 0x004F}, // LFM_PHASE16_PERIOD ++{0x3472, 0x004F}, // LFM_PHASE17_PERIOD ++{0x3474, 0x004F}, // LFM_PHASE18_PERIOD ++{0x3476, 0x004F}, // LFM_PHASE19_PERIOD ++{0x3478, 0x004F}, // LFM_PHASE20_PERIOD ++{0x347A, 0x004F}, // LFM_PHASE21_PERIOD ++{0x347C, 0x004F}, // LFM_PHASE22_PERIOD ++{0x347E, 0x004F}, // LFM_PHASE23_PERIOD ++{0x3480, 0x004F}, // LFM_PHASE24_PERIOD ++{0x3482, 0x004F}, // LFM_PHASE25_PERIOD ++{0x3484, 0x00A4}, // LFM_PHASE26_PERIOD ++{0x3486, 0x004F}, // LFM_PHASE27_PERIOD ++{0x3488, 0x00A4}, // LFM_PHASE28_PERIOD ++{0x348A, 0x004F}, // LFM_PHASE29_PERIOD ++{0x348C, 0x004F}, // LFM_PHASE30_PERIOD ++{0x348E, 0x004F}, // LFM_PHASE31_PERIOD ++{0x3490, 0x004F}, // LFM_PHASE32_PERIOD ++ ++{0x3496, 0xDF00}, // LFM_CONTROL ++{0x349A, 0x0001}, // LFM_TX_SHIFT_CLK_CTRL ++{0x349C, 0x0003}, // LFM_TX_DATA_CLK_CTRL ++{0x349E, 0x0002}, // LFM_TX_GOTO_LOROW_CLK_CTRL ++{0x34A0, 0x003E}, // LFM_TX_DATA_CLR_CLK_CTRL ++{0x34A2, 0x0012}, // LFM_BST_TX_CLK_CTRL ++{0x34A4, 0x003D}, // LFM_BST_TXLO_CLK_CTRL ++{0x34A6, 0x004E}, // LFM_BST_TXLOROW_EN_CLK_CTRL ++{0x34A8, 0x0044}, // LFM_AB_SHIFT_CLK_CTRL ++{0x34AA, 0x0001}, // LFM_BST_AB_CLK_CTRL ++{0x34AC, 0x0043}, // LFM_BST_ABLO_CLK_CTRL ++{0x34AE, 0x004E}, // LFM_BST_ABLOROW_EN_CLK_CTRL ++{0x34B0, 0x0002}, // LFM_DCG_DATA_CLK_CTRL ++{0x34B2, 0x003F}, // LFM_DCG_DATA_CLR_CLK_CTRL ++{0x34B4, 0x004E}, // LFM_BST_DCGLOROW_EN_CLK_CTRL ++{0x34B6, 0x0012}, // LFM_BST_DCG_CLK_CTRL ++ ++{0x350E, 0x2189}, // DAC_LD_14_15 ++//pixel recommended settings Feb5 ++{0x352C, 0x8146}, // DAC_LD_44_45 ++{0x3526, 0x9812}, // DAC_LD_38_39 ++{0x3528, 0x99C0}, // DAC_LD_40_41 ++{0x352E, 0x0B71}, // DAC_LD_46_47 ++{0x352A, 0x0170}, // DAC_LD_42_43 ++{0x3530, 0x07F0}, // DAC_LD_48_49 ++{0x3514, 0xEEEE}, // DAC_LD_20_21 ++{0x3578, 0xEEEE}, // DAC_LD_120_121 ++{0x3518, 0x3333}, // DAC_LD_24_25 ++{0x3540, 0x0033}, // DAC_LD_64_65 ++{0x3542, 0x33F0}, // DAC_LD_66_67 ++ ++//CFPN},IMPROVEMENT ++{0x3568, 0x04BC}, ++{0x356A, 0x81AA}, ++{0x356E, 0x15E6}, ++ ++//E1-E2 Transision Noise Improvement ++{0x3E10, 0x000A}, // LFM2_T1_E2_OFFSET ++{0x3430, 0x070C}, // BST_MULTISHOT_CLK_0 ++{0x3432, 0x008C}, // BST_MULTISHOT_CLK_1 ++{0x37B2, 0x1F40}, // DBLC_OUT_CLIP_MAX ++ ++{0x3550, 0xFF6C}, // DAC_LD_80_81 ++{0x3546, 0x4201}, // DAC_LD_70_71 ++ ++//T2 white balance gains ++{0x30B0, 0x0880}, // DIGITAL_TEST ++{0x3300, 0x0030}, // GREEN1_GAIN2_ ++{0x3302, 0x0080}, // BLUE_GAIN2_ ++{0x3304, 0x0070}, // RED_GAIN2_ ++{0x3306, 0x0030}, // GREEN2_GAIN2_ ++{0x3056, 0x002F}, // GREEN1_GAIN ++{0x3058, 0x0080}, // BLUE_GAIN ++{0x305A, 0x0072}, // RED_GAIN ++{0x305C, 0x002F}, // GREEN2_GAIN ++ ++{0x301A, 0x005C}, // RESET_REGISTER ++}; +diff --git a/drivers/media/i2c/soc_camera/ov106xx.c b/drivers/media/i2c/soc_camera/ov106xx.c +index c7bd92e..906ec7e 100644 +--- a/drivers/media/i2c/soc_camera/ov106xx.c ++++ b/drivers/media/i2c/soc_camera/ov106xx.c +@@ -18,6 +18,7 @@ + #include "ar0220.c" + #include "ar0231.c" + #include "ar0233.c" ++#include "ar0323.c" + #include "ap0101_ar014x.c" + #include "gw4200_ar014x.c" + #include "ov2775.c" +@@ -34,6 +35,7 @@ static enum { + ID_AR0220, + ID_AR0231, + ID_AR0233, ++ ID_AR0323, + ID_AP0101_AR014X, + ID_GW4200_AR014X, + ID_OV2775, +@@ -95,6 +97,12 @@ static int ov106xx_probe(struct i2c_client *client, + goto out; + } + ++ ret = ar0323_probe(client, did); ++ if (!ret) { ++ chip_id = ID_AR0323; ++ goto out; ++ } ++ + ret = ar0231_probe(client, did); + if (!ret) { + chip_id = ID_AR0231; +@@ -167,6 +175,9 @@ static int ov106xx_remove(struct i2c_client *client) + case ID_AR0233: + ar0233_remove(client); + break; ++ case ID_AR0323: ++ ar0323_remove(client); ++ break; + case ID_AP0101_AR014X: + ap0101_remove(client); + break; +@@ -211,6 +222,6 @@ static struct i2c_driver ov106xx_i2c_driver = { + + module_i2c_driver(ov106xx_i2c_driver); + +-MODULE_DESCRIPTION("SoC Camera driver for OV10635, OV490+OV10640, OV495+OV2775, AR0132/140/143/220/223, AP0101+AR014X"); ++MODULE_DESCRIPTION("SoC Camera driver for OV10635, OV490+OV10640, OV495+OV2775, AR0132/140/143/220/223/323, AP0101+AR014X"); + MODULE_AUTHOR("Vladimir Barinov"); + MODULE_LICENSE("GPL"); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0134-lvds-add-ISX016-imager.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0134-lvds-add-ISX016-imager.patch new file mode 100644 index 00000000..4cb8a11e --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0134-lvds-add-ISX016-imager.patch @@ -0,0 +1,729 @@ +From 5673a8e83d5cf9f345b2fbcbaf157ee00c60f521 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Mon, 26 Nov 2018 23:28:23 +0300 +Subject: [PATCH 083/122] lvds: add ISX016 imager + +This adds ISX016 imager support + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/isx016.c | 628 +++++++++++++++++++++++++++++++++ + drivers/media/i2c/soc_camera/isx016.h | 27 ++ + drivers/media/i2c/soc_camera/ov106xx.c | 11 + + 3 files changed, 666 insertions(+) + create mode 100644 drivers/media/i2c/soc_camera/isx016.c + create mode 100644 drivers/media/i2c/soc_camera/isx016.h + +diff --git a/drivers/media/i2c/soc_camera/isx016.c b/drivers/media/i2c/soc_camera/isx016.c +new file mode 100644 +index 0000000..275bd8a +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/isx016.c +@@ -0,0 +1,628 @@ ++/* ++ * ON Semiconductor ISX016 sensor camera driver ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "isx016.h" ++ ++static const int isx016_i2c_addr[] = {0x1a}; ++ ++#define ISX016_PID 0x0000 ++#define ISX016_VERSION_REG 0x0740 ++ ++#define ISX016_MEDIA_BUS_FMT MEDIA_BUS_FMT_YUYV8_2X8 ++ ++static void isx016_otp_id_read(struct i2c_client *client); ++ ++struct isx016_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int max_width; ++ int max_height; ++ int init_complete; ++ u8 id[6]; ++ int exposure; ++ int gain; ++ int autogain; ++ /* serializers */ ++ int max9286_addr; ++ int max9271_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++}; ++ ++static inline struct isx016_priv *to_isx016(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct isx016_priv, sd); ++} ++ ++static void isx016_s_port(struct i2c_client *client, int fwd_en) ++{ ++ struct isx016_priv *priv = to_isx016(client); ++ int tmp_addr; ++ ++ if (priv->max9286_addr) { ++ tmp_addr = client->addr; ++ client->addr = priv->max9286_addr; /* Deserializer I2C address */ ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ client->addr = tmp_addr; ++ }; ++} ++ ++static int isx016_read16(struct i2c_client *client, u8 category, u16 reg, u16 *val) ++{ ++ int ret; ++ #define R_NUM_BYTES 9 ++ #define R_NUM_CMDS 1 ++ #define R_NUM_CMD_BYTES 6 ++ #define R_CMD 1 ++ #define R_BYTES 2 ++ u8 buf[R_NUM_BYTES] = {R_NUM_BYTES, R_NUM_CMDS, ++ R_NUM_CMD_BYTES, R_CMD, ++ category, reg >> 8, reg & 0xff, ++ R_BYTES, 0x00}; ++ ++ /* calculate checksum */ ++ buf[8] = R_NUM_BYTES + R_NUM_CMDS + R_NUM_CMD_BYTES + R_CMD + ++ category + (reg >> 8) + (reg & 0xff) + R_BYTES; ++ ++ ret = i2c_master_send(client, buf, R_NUM_BYTES); ++ if (ret == R_NUM_BYTES) ++ ret = i2c_master_recv(client, buf, R_NUM_BYTES - 2); ++ ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "read fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } else { ++ *val = ((u16)buf[4] << 8) | buf[5]; ++ } ++ ++ return ret < 0 ? ret : 0; ++} ++ ++static int isx016_write16(struct i2c_client *client, u8 category, u16 reg, u16 val) ++{ ++ int ret; ++ #define W_NUM_BYTES 10 ++ #define W_NUM_CMDS 1 ++ #define W_NUM_CMD_BYTES 7 ++ #define W_CMD 2 ++ u8 buf[W_NUM_BYTES] = {W_NUM_BYTES, W_NUM_CMDS, ++ W_NUM_CMD_BYTES, W_CMD, ++ category, reg >> 8, reg & 0xff, ++ val >> 8, val & 0xff}; ++ ++ /* calculate checksum */ ++ buf[9] = W_NUM_BYTES + W_NUM_CMDS + W_NUM_CMD_BYTES + W_CMD + ++ category + (reg >> 8) + (reg & 0xff) + (val >> 8) + (val & 0xff); ++ ++ ret = i2c_master_send(client, buf, W_NUM_BYTES); ++ ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "write fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } ++ ++ return ret < 0 ? ret : 0; ++} ++ ++static int isx016_set_regs(struct i2c_client *client, ++ const struct isx016_reg *regs, int nr_regs) ++{ ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (regs[i].reg == ISX016_DELAY) { ++ mdelay(regs[i].val); ++ continue; ++ } ++ ++ isx016_write16(client, regs[i].reg >> 8, regs[i].reg & 0xff, regs[i].val); ++ } ++ ++ return 0; ++} ++ ++static int isx016_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int isx016_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct isx016_priv *priv = to_isx016(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = ISX016_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int isx016_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = ISX016_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int isx016_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = ISX016_MEDIA_BUS_FMT; ++ ++ return 0; ++} ++ ++static int isx016_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct isx016_priv *priv = to_isx016(client); ++ ++ isx016_otp_id_read(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = ISX016_VERSION_REG >> 8; ++ edid->edid[9] = ISX016_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int isx016_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct isx016_priv *priv = to_isx016(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > priv->max_width) || ++ (rect->top + rect->height > priv->max_height)) ++ *rect = priv->rect; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ return 0; ++} ++ ++static int isx016_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct isx016_priv *priv = to_isx016(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = priv->max_width; ++ sel->r.height = priv->max_height; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = priv->max_width; ++ sel->r.height = priv->max_height; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int isx016_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int isx016_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u16 val = 0; ++ ++ ret = isx016_read16(client, (u16)reg->reg >> 8, (u16)reg->reg & 0xff, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int isx016_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return isx016_write16(client, (u16)reg->reg >> 8, (u16)reg->reg & 0xff, (u16)reg->val); ++} ++#endif ++ ++static struct v4l2_subdev_core_ops isx016_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = isx016_g_register, ++ .s_register = isx016_s_register, ++#endif ++}; ++ ++static int isx016_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct isx016_priv *priv = to_isx016(client); ++ int ret = -EINVAL; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ case V4L2_CID_CONTRAST: ++ case V4L2_CID_SATURATION: ++ case V4L2_CID_HUE: ++ case V4L2_CID_GAMMA: ++ case V4L2_CID_SHARPNESS: ++ case V4L2_CID_AUTOGAIN: ++ case V4L2_CID_GAIN: ++ case V4L2_CID_EXPOSURE: ++ case V4L2_CID_HFLIP: ++ case V4L2_CID_VFLIP: ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops isx016_ctrl_ops = { ++ .s_ctrl = isx016_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops isx016_video_ops = { ++ .s_stream = isx016_s_stream, ++ .g_mbus_config = isx016_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops isx016_subdev_pad_ops = { ++ .get_edid = isx016_get_edid, ++ .enum_mbus_code = isx016_enum_mbus_code, ++ .get_selection = isx016_get_selection, ++ .set_selection = isx016_set_selection, ++ .get_fmt = isx016_get_fmt, ++ .set_fmt = isx016_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops isx016_subdev_ops = { ++ .core = &isx016_core_ops, ++ .video = &isx016_video_ops, ++ .pad = &isx016_subdev_pad_ops, ++}; ++ ++static void isx016_otp_id_read(struct i2c_client *client) ++{ ++ struct isx016_priv *priv = to_isx016(client); ++ int i; ++ u16 val = 0; ++ ++ /* read camera id from isx016 OTP memory */ ++ for (i = 0; i < 6; i+=2) { ++ isx016_read16(client, 8, 0x60 + i, &val); ++ priv->id[i] = val >> 8; ++ priv->id[i+1] = val & 0xff; ++ } ++} ++ ++static ssize_t isx016_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct isx016_priv *priv = to_isx016(client); ++ ++ isx016_otp_id_read(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_isx016, S_IRUGO, isx016_otp_id_show, NULL); ++ ++static int isx016_initialize(struct i2c_client *client) ++{ ++ struct isx016_priv *priv = to_isx016(client); ++ u16 pid = 0; ++ int ret = 0; ++ int tmp_addr; ++ int i; ++ ++ isx016_s_port(client, 1); ++ ++ for (i = 0; i < ARRAY_SIZE(isx016_i2c_addr); i++) { ++ tmp_addr = client->addr; ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x0A, isx016_i2c_addr[i] << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ client->addr = tmp_addr; ++ ++ /* check model ID */ ++ isx016_read16(client, 0, ISX016_PID, &pid); ++ ++ if (pid == ISX016_VERSION_REG) ++ break; ++ } ++ ++ if (pid != ISX016_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x\n", pid); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ priv->max_width = ISX016_MAX_WIDTH; ++ priv->max_height = ISX016_MAX_HEIGHT; ++ ++ /* Read OTP IDs */ ++ isx016_otp_id_read(client); ++ /* Program wizard registers */ ++ isx016_set_regs(client, isx016_regs_wizard, ARRAY_SIZE(isx016_regs_wizard)); ++ ++ dev_info(&client->dev, "isx016 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, priv->max_width, priv->max_height, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ isx016_s_port(client, 0); ++ ++ return ret; ++} ++ ++static int isx016_parse_dt(struct device_node *np, struct isx016_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ if (!priv->max9286_addr) { ++ dev_err(&client->dev, "deserializer does not present for ISX016\n"); ++ return -EINVAL; ++ } ++ ++ isx016_s_port(client, 1); ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ client->addr = tmp_addr; ++ ++ mdelay(10); ++ ++ return 0; ++} ++ ++static int isx016_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct isx016_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &isx016_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ priv->exposure = 0x100; ++ priv->gain = 0x100; ++ priv->autogain = 1; ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); ++ v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); ++ v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure); ++ v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = isx016_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = isx016_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = priv->max_width; ++ priv->rect.height = priv->max_height; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_isx016) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_ISX016 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int isx016_remove(struct i2c_client *client) ++{ ++ struct isx016_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_isx016); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_ISX016 ++static const struct i2c_device_id isx016_id[] = { ++ { "isx016", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, isx016_id); ++ ++static const struct of_device_id isx016_of_ids[] = { ++ { .compatible = "aptina,isx016", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, isx016_of_ids); ++ ++static struct i2c_driver isx016_i2c_driver = { ++ .driver = { ++ .name = "isx016", ++ .of_match_table = isx016_of_ids, ++ }, ++ .probe = isx016_probe, ++ .remove = isx016_remove, ++ .id_table = isx016_id, ++}; ++ ++module_i2c_driver(isx016_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for ISX016"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/isx016.h b/drivers/media/i2c/soc_camera/isx016.h +new file mode 100644 +index 0000000..f20d735 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/isx016.h +@@ -0,0 +1,27 @@ ++/* ++ * ON Semiconductor isx016 sensor camera wizard 1280x800@30/UYVY/BT601/8bit ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++#define ISX016_MAX_WIDTH 1280 ++#define ISX016_MAX_HEIGHT 800 ++ ++#define ISX016_DELAY 0xffff ++ ++struct isx016_reg { ++ u16 reg; ++ u16 val; ++}; ++ ++static const struct isx016_reg isx016_regs_wizard[] = { ++#if 0 ++/* enable FSIN */ ++#endif ++{ISX016_DELAY, 100}, ++}; +diff --git a/drivers/media/i2c/soc_camera/ov106xx.c b/drivers/media/i2c/soc_camera/ov106xx.c +index 906ec7e..d6df193 100644 +--- a/drivers/media/i2c/soc_camera/ov106xx.c ++++ b/drivers/media/i2c/soc_camera/ov106xx.c +@@ -24,6 +24,7 @@ + #include "ov2775.c" + #include "imx390.c" + #include "ox03a.c" ++#include "isx016.c" + + static enum { + ID_OV10635, +@@ -41,6 +42,7 @@ static enum { + ID_OV2775, + ID_IMX390, + ID_OX03A, ++ ID_ISX016, + } chip_id; + + static int ov106xx_probe(struct i2c_client *client, +@@ -139,6 +141,12 @@ static int ov106xx_probe(struct i2c_client *client, + goto out; + } + ++ ret = isx016_probe(client, did); ++ if (!ret) { ++ chip_id = ID_ISX016; ++ goto out; ++ } ++ + v4l_err(client, "failed to probe @ 0x%02x (%s)\n", + client->addr, client->adapter->name); + out: +@@ -193,6 +201,9 @@ static int ov106xx_remove(struct i2c_client *client) + case ID_OX03A: + ox03a_remove(client); + break; ++ case ID_ISX016: ++ isx016_remove(client); ++ break; + }; + + return 0; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0135-LVDS-ar0233-set-frame-size-1920x1200.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0135-LVDS-ar0233-set-frame-size-1920x1200.patch new file mode 100644 index 00000000..0796810a --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0135-LVDS-ar0233-set-frame-size-1920x1200.patch @@ -0,0 +1,104 @@ +From 6e4407c3dfdcb3694b860d09024020135071343e Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Sat, 15 Dec 2018 18:32:45 +0300 +Subject: [PATCH 084/122] LVDS: ar0233: set frame size 1920x1200 + +1) Set default frame seze 1920x1200 accordingly to sequencer +2) add crop possibility in imager +--- + drivers/media/i2c/soc_camera/ar0233.c | 21 +++++++++++++++++++++ + drivers/media/i2c/soc_camera/ar0233.h | 21 +++++++++++---------- + 2 files changed, 32 insertions(+), 10 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ar0233.c b/drivers/media/i2c/soc_camera/ar0233.c +index 6d034e2..7c1141c 100644 +--- a/drivers/media/i2c/soc_camera/ar0233.c ++++ b/drivers/media/i2c/soc_camera/ar0233.c +@@ -71,6 +71,25 @@ static int ar0233_s_stream(struct v4l2_subdev *sd, int enable) + return 0; + } + ++static int ar0233_set_window(struct v4l2_subdev *sd) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0233_priv *priv = to_ar0233(client); ++ ++ dev_err(&client->dev, "L=%d T=%d %dx%d\n", priv->rect.left, priv->rect.top, priv->rect.width, priv->rect.height); ++ ++ /* horiz crop start */ ++ reg16_write16(client, 0x3004, priv->rect.left); ++ /* horiz crop end */ ++ reg16_write16(client, 0x3008, priv->rect.left + priv->rect.width - 1); ++ /* vert crop start */ ++ reg16_write16(client, 0x3002, priv->rect.top); ++ /* vert crop end */ ++ reg16_write16(client, 0x3006, priv->rect.top + priv->rect.height + 1); ++ ++ return 0; ++}; ++ + static int ar0233_get_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *format) +@@ -160,6 +179,8 @@ static int ar0233_set_selection(struct v4l2_subdev *sd, + priv->rect.width = rect->width; + priv->rect.height = rect->height; + ++ ar0233_set_window(sd); ++ + return 0; + } + +diff --git a/drivers/media/i2c/soc_camera/ar0233.h b/drivers/media/i2c/soc_camera/ar0233.h +index f88e5a3..ad65390 100644 +--- a/drivers/media/i2c/soc_camera/ar0233.h ++++ b/drivers/media/i2c/soc_camera/ar0233.h +@@ -12,13 +12,13 @@ + //#define AR0233_DISPLAY_PATTERN_FIXED + //#define AR0233_DISPLAY_PATTERN_COLOR_BAR + +-#define AR0233_MAX_WIDTH 1792 //1920 +-#define AR0233_MAX_HEIGHT 1080 ++#define AR0233_MAX_WIDTH 1920 ++#define AR0233_MAX_HEIGHT 1200 + + #define AR0233_DELAY 0xffff + + #define AR0233_SENSOR_WIDTH 1920 +-#define AR0233_SENSOR_HEIGHT 1280 ++#define AR0233_SENSOR_HEIGHT 1200 + + #define AR0233_X_START ((AR0233_SENSOR_WIDTH - AR0233_MAX_WIDTH) / 2) + #define AR0233_Y_START ((AR0233_SENSOR_HEIGHT - AR0233_MAX_HEIGHT) / 2) +@@ -311,12 +311,13 @@ static const struct ar0233_reg ar0233_regs_wizard[] = { + {0x32D6, 0x3C04}, + {0x32DC, 0x370A}, + {0x30B0, 0x0800}, +-{0x302A, 0x0006}, +-{0x302C, 0x0001}, +-{0x302E, 0x0002}, +-{0x3030, 0x002C}, +-{0x3036, 0x000C}, +-{0x3038, 0x0001}, ++/* PCLK=22Mhz/2 *44/1/6= 88.6Mhz - TI serializers */ ++{0x302A, 6}, // VT_PIX_CLK_DIV ++{0x302C, 1}, // VT_SYS_CLK_DIV ++{0x302E, 2}, // PRE_PLL_CLK_DIV ++{0x3030, 44}, // PLL_MULTIPLIER ++{0x3036, 0x000C}, // OP_WORD_CLK_DIV ++{0x3038, 0x0001}, // OP_SYS_CLK_DIV + {0x30B0, 0x0A00}, + {0x30A2, 0x0001}, + {0x30A6, 0x0001}, +@@ -355,7 +356,7 @@ static const struct ar0233_reg ar0233_regs_wizard[] = { + {0x300A, AR0233_SENSOR_HEIGHT + 356}, // FRAME_LENGTH_LINES_ + {0x300C, AR0233_SENSOR_WIDTH + 100}, // LINE_LENGTH_PCK_ + #else +-{0x300A, AR0233_SENSOR_HEIGHT + 208}, // FRAME_LENGTH_LINES_ ++{0x300A, AR0233_SENSOR_HEIGHT + 288}, // FRAME_LENGTH_LINES_ + {0x300C, AR0233_SENSOR_WIDTH + 300}, // LINE_LENGTH_PCK_ + #endif + {0x3042, 0x0000}, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0136-lvds-AR0233-add-different-vendor.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0136-lvds-AR0233-add-different-vendor.patch new file mode 100644 index 00000000..34d07a86 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0136-lvds-AR0233-add-different-vendor.patch @@ -0,0 +1,258 @@ +From 805e485b11c5aafacd2ab16a2d699c904ba13372 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Wed, 19 Dec 2018 00:02:17 +0300 +Subject: [PATCH 085/122] lvds: AR0233 add different vendor + +This adds possibility to setup cameras with different +gpio connection using dts or command line: +ti9x4.gpioX +--- + drivers/media/i2c/soc_camera/ar0233.c | 36 ++++++++++++++++++---------- + drivers/media/i2c/soc_camera/ov106xx.c | 12 +++++----- + drivers/media/i2c/soc_camera/ti9x4.c | 44 +++++++++++++++++++++++++++------- + 3 files changed, 64 insertions(+), 28 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ar0233.c b/drivers/media/i2c/soc_camera/ar0233.c +index 7c1141c..74ecc85 100644 +--- a/drivers/media/i2c/soc_camera/ar0233.c ++++ b/drivers/media/i2c/soc_camera/ar0233.c +@@ -22,7 +22,7 @@ + + #include "ar0233.h" + +-#define AR0233_I2C_ADDR 0x10 ++static const int ar0233_i2c_addr[] = {0x10, 0x20}; + + #define AR0233_PID 0x3000 + #define AR0233_VERSION_REG 0x0354 +@@ -380,9 +380,23 @@ static int ar0233_initialize(struct i2c_client *client) + u16 pid = 0; + int ret = 0; + int tmp_addr; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(ar0233_i2c_addr); i++) { ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr;/* Deserializer I2C address */ ++ reg8_write(client, 0x5d, ar0233_i2c_addr[i] << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ } ++ client->addr = tmp_addr; + +- /* check and show model ID */ +- reg16_read16(client, AR0233_PID, &pid); ++ /* check model ID */ ++ reg16_read16(client, AR0233_PID, &pid); ++ ++ if (pid == AR0233_VERSION_REG) ++ break; ++ } + + if (pid != AR0233_VERSION_REG) { + dev_dbg(&client->dev, "Product ID error %x\n", pid); +@@ -395,12 +409,16 @@ static int ar0233_initialize(struct i2c_client *client) + if (priv->ti9x4_addr) { + /* CLK_OUT=22.5792*160*M/N/CLKDIV -> CLK_OUT=27MHz: CLKDIV=2, M=15, N=251: 22.5792*160/8*15/251=26.987MHz=CLK_OUT */ + client->addr = priv->ti9x3_addr; /* Serializer I2C address */ ++#if 0 + reg8_write(client, 0x06, 0x6f); /* Set CLKDIV and M */ + reg8_write(client, 0x07, 0xfb); /* Set N */ +- reg8_write(client, 0x0e, 0x1f); /* Set FSIN GPIO to output */ ++#endif ++ reg8_write(client, 0x0e, 0xf0); /* Enable all remote gpios */ + } + client->addr = tmp_addr; + ++ /* Read OTP IDs */ ++ ar0233_otp_id_read(client); + /* Program wizard registers */ + ar0233_set_regs(client, ar0233_regs_wizard, ARRAY_SIZE(ar0233_regs_wizard)); + +@@ -409,9 +427,6 @@ static int ar0233_initialize(struct i2c_client *client) + val |= (1 << 2); // Set streamOn bit + reg16_write16(client, 0x301a, val); // Start Streaming + +- /* Read OTP IDs */ +- ar0233_otp_id_read(client); +- + dev_info(&client->dev, "ar0233 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", + pid, AR0233_MAX_WIDTH, AR0233_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); + err: +@@ -444,7 +459,7 @@ static int ar0233_parse_dt(struct device_node *np, struct ar0233_priv *priv) + of_node_put(endpoint); + + if (!priv->ti9x4_addr) { +- dev_err(&client->dev, "deserializer does not present\n"); ++ dev_dbg(&client->dev, "deserializer does not present\n"); + return -EINVAL; + } + +@@ -456,14 +471,9 @@ static int ar0233_parse_dt(struct device_node *np, struct ar0233_priv *priv) + reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ + usleep_range(2000, 2500); /* wait 2ms */ + reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ +- reg8_write(client, 0x5d, AR0233_I2C_ADDR << 1); /* Sensor native I2C address */ +- +- reg8_write(client, 0x6e, 0x8a); /* GPIO0 - fsin, GPIO1 - NC */ + } + client->addr = tmp_addr; + +- mdelay(10); +- + return 0; + } + +diff --git a/drivers/media/i2c/soc_camera/ov106xx.c b/drivers/media/i2c/soc_camera/ov106xx.c +index d6df193..e5d6b67 100644 +--- a/drivers/media/i2c/soc_camera/ov106xx.c ++++ b/drivers/media/i2c/soc_camera/ov106xx.c +@@ -51,6 +51,12 @@ static int ov106xx_probe(struct i2c_client *client, + int ret; + chip_id = -EINVAL; + ++ ret = ar0233_probe(client, did); ++ if (!ret) { ++ chip_id = ID_AR0233; ++ goto out; ++ } ++ + ret = ov10635_probe(client, did); + if (!ret) { + chip_id = ID_OV10635; +@@ -93,12 +99,6 @@ static int ov106xx_probe(struct i2c_client *client, + goto out; + } + +- ret = ar0233_probe(client, did); +- if (!ret) { +- chip_id = ID_AR0233; +- goto out; +- } +- + ret = ar0323_probe(client, did); + if (!ret) { + chip_id = ID_AR0323; +diff --git a/drivers/media/i2c/soc_camera/ti9x4.c b/drivers/media/i2c/soc_camera/ti9x4.c +index effcf6c..d03c0f9 100644 +--- a/drivers/media/i2c/soc_camera/ti9x4.c ++++ b/drivers/media/i2c/soc_camera/ti9x4.c +@@ -44,6 +44,7 @@ struct ti9x4_priv { + int ser_id; + int vc_map; + int csi_map; ++ int gpio[4]; + struct gpio_desc *pwen; /* chip power en */ + struct gpio_desc *poc_gpio[4]; /* PoC power supply */ + struct v4l2_clk *ref_clk; /* ref clock */ +@@ -81,6 +82,16 @@ static int csi_map = 0; + module_param(csi_map, int, 0644); + MODULE_PARM_DESC(csi_map, " CSI TX MAP (default: 0 - forwarding of all links to CSI0)"); + ++static int gpio0 = 0, gpio1 = 0, gpio2 = 0, gpio3 = 0; ++module_param(gpio0, int, 0644); ++MODULE_PARM_DESC(gpio0, " GPIO0 function select (default: GPIO0 low level)"); ++module_param(gpio1, int, 0644); ++MODULE_PARM_DESC(gpio1, " GPIO1 function select (default: GPIO1 low level)"); ++module_param(gpio2, int, 0644); ++MODULE_PARM_DESC(gpio2, " GPIO2 function select (default: GPIO2 low level)"); ++module_param(gpio3, int, 0644); ++MODULE_PARM_DESC(gpio3, " GPIO3 function select (default: GPIO3 low level)"); ++ + #ifdef TI954_SILICON_ERRATA + static int indirect_write(struct i2c_client *client, unsigned int page, u8 reg, u8 val) + { +@@ -204,9 +215,6 @@ static void ti9x4_initial_setup(struct i2c_client *client) + #endif + } + +-//#define SENSOR_ID 0x30 // ov10635 +-//#define SENSOR_ID 0x24 // ov490 +- + static void ti9x4_fpdlink3_setup(struct i2c_client *client, int idx) + { + struct ti9x4_priv *priv = i2c_get_clientdata(client); +@@ -230,7 +238,7 @@ static void ti9x4_fpdlink3_setup(struct i2c_client *client, int idx) + } + + reg8_write(client, 0x5c, priv->ti9x3_addr_map[idx] << 1); /* TI9X3 I2C addr */ +-// reg8_write(client, 0x5d, SENSOR_ID << 1); /* SENSOR I2C native - must be set by sensor driver */ ++// reg8_write(client, 0x5d, 0x30 << 1); /* SENSOR I2C native - must be set by sensor driver */ + // reg8_write(client, 0x65, (0x60 + idx) << 1); /* SENSOR I2C translated - must be set by sensor driver */ + + if (priv->is_coax) +@@ -262,7 +270,8 @@ static void ti9x4_fpdlink3_setup(struct i2c_client *client, int idx) + reg8_write(client, 0x70, ((priv->vc_map >> (idx * 4)) << 6) | 0x1e); /* CSI data type: yuv422 8-bit, assign VC */ + reg8_write(client, 0x71, ((priv->vc_map >> (idx * 4)) << 6) | 0x2c); /* CSI data type: RAW12, assign VC */ + reg8_write(client, 0xbc, 0x00); /* Setup minimal time between FV and LV to 3 PCLKs */ +- reg8_write(client, 0x6e, 0x88); /* Sensor reset: backchannel GPIO0/GPIO1 set low */ ++ reg8_write(client, 0x6e, 0x88 | (priv->gpio[1] << 4) | priv->gpio[0]); /* Remote GPIO1/GPIO0 setup */ ++ reg8_write(client, 0x6f, 0x88 | (priv->gpio[3] << 4) | priv->gpio[2]); /* Remote GPIO3/GPIO2 setup */ + reg8_write(client, 0x72, priv->vc_map >> (idx * 4)); /* CSI VC MAP */ + } + +@@ -285,6 +294,10 @@ static int ti9x4_initialize(struct i2c_client *client) + ti9x4_fpdlink3_setup(client, idx); + } + ++ /* extra delay to wait imager power up */ ++ if (priv->poc_delay) ++ mdelay(350); ++ + client->addr = priv->des_addr; + + return 0; +@@ -369,7 +382,7 @@ static int ti9x4_parse_dt(struct i2c_client *client) + char forwarding_mode_default[20] = "round-robin"; /* round-robin, synchronized */ + struct property *csi_rate_prop, *dvp_order_prop; + u8 val = 0; +- char poc_name[10]; ++ char name[10]; + + if (of_property_read_u32(np, "ti,links", &priv->links)) + priv->links = 4; +@@ -391,8 +404,8 @@ static int ti9x4_parse_dt(struct i2c_client *client) + } + + for (i = 0; i < 4; i++) { +- sprintf(poc_name, "POC%d", i); +- priv->poc_gpio[i] = devm_gpiod_get_optional(&client->dev, kstrdup(poc_name, GFP_KERNEL), 0); ++ sprintf(name, "POC%d", i); ++ priv->poc_gpio[i] = devm_gpiod_get_optional(&client->dev, kstrdup(name, GFP_KERNEL), 0); + } + + reg8_read(client, 0x00, &val); /* read TI9x4 I2C address */ +@@ -429,9 +442,14 @@ static int ti9x4_parse_dt(struct i2c_client *client) + if (of_property_read_u32(np, "ti,ser_id", &priv->ser_id)) + priv->ser_id = TI913_ID; + if (of_property_read_u32(np, "ti,poc-delay", &priv->poc_delay)) +- priv->poc_delay = 50; ++ priv->poc_delay = 10; + if (of_property_read_u32(np, "ti,vc-map", &priv->vc_map)) + priv->vc_map = 0x3210; ++ for (i = 0; i < 4; i++) { ++ sprintf(name, "ti,gpio%d", i); ++ if (of_property_read_u32(np, name, &priv->gpio[i])) ++ priv->gpio[i] = 0; ++ } + + /* + * CSI forwarding of all links is to CSI0 by default. +@@ -469,6 +487,14 @@ static int ti9x4_parse_dt(struct i2c_client *client) + priv->vc_map = vc_map; + if (csi_map) + priv->csi_map = csi_map; ++ if (gpio0) ++ priv->gpio[0] = gpio0; ++ if (gpio1) ++ priv->gpio[1] = gpio1; ++ if (gpio2) ++ priv->gpio[2] = gpio2; ++ if (gpio3) ++ priv->gpio[3] = gpio3; + + for (i = 0; ; i++) { + endpoint = of_graph_get_next_endpoint(np, endpoint); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0137-lvds-poll-ub960-deserializer-lock-status.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0137-lvds-poll-ub960-deserializer-lock-status.patch new file mode 100644 index 00000000..4d6ef176 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0137-lvds-poll-ub960-deserializer-lock-status.patch @@ -0,0 +1,70 @@ +From df920df1a7a26dd4b49f90d4ce4e94b2541348d6 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Thu, 3 Jan 2019 23:24:03 +0300 +Subject: [PATCH 086/122] lvds: poll ub960 deserializer lock status + +Poll FPDLINK lock status instead delay + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ti9x4.c | 35 ++++++++++++++++++++++++++++++----- + 1 file changed, 30 insertions(+), 5 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ti9x4.c b/drivers/media/i2c/soc_camera/ti9x4.c +index d03c0f9..f0b782f 100644 +--- a/drivers/media/i2c/soc_camera/ti9x4.c ++++ b/drivers/media/i2c/soc_camera/ti9x4.c +@@ -278,7 +278,9 @@ static void ti9x4_fpdlink3_setup(struct i2c_client *client, int idx) + static int ti9x4_initialize(struct i2c_client *client) + { + struct ti9x4_priv *priv = i2c_get_clientdata(client); +- int idx; ++ int idx, timeout; ++ u8 port_sts1 = 0, port_sts2 = 0; ++ int tmp_addr; + + dev_info(&client->dev, "LINKs=%d, LANES=%d, FORWARDING=%s, CABLE=%s, ID=%s\n", + priv->links, priv->lanes, priv->forwarding_mode, priv->is_coax ? "coax" : "stp", priv->chip_id); +@@ -294,12 +296,35 @@ static int ti9x4_initialize(struct i2c_client *client) + ti9x4_fpdlink3_setup(client, idx); + } + +- /* extra delay to wait imager power up */ +- if (priv->poc_delay) +- mdelay(350); +- + client->addr = priv->des_addr; + ++ /* check lock status */ ++ for (timeout = 500 / priv->links; timeout > 0; timeout--) { ++ for (idx = 0; idx < priv->links; idx++) { ++ reg8_write(client, 0x4c, (idx << 4) | (1 << idx)); /* Select RX port number */ ++ usleep_range(1000, 1500); /* wait 1ms */ ++ reg8_read(client, 0x4d, &port_sts1); /* Lock status */ ++ reg8_read(client, 0x4e, &port_sts2); /* Freq stable */ ++ ++ if (port_sts1 & 0x1) { ++ tmp_addr = client->addr; ++ client->addr = priv->ti9x3_addr_map[idx]; /* TI9X3 I2C addr */ ++ reg8_write(client, 0x0d, 0xf0); /* Enable all remote GPIOs */ ++ reg8_write(client, 0x0e, 0xf0); /* Enable serializer GPIOs */ ++ client->addr = tmp_addr; ++ } ++ ++ if ((port_sts1 & 0x1) && (port_sts2 & 0x4)) ++ goto out; ++ } ++ } ++ ++ if (!timeout) ++ dev_info(&client->dev, "Receiver is not locked\n"); ++out: ++ if (priv->poc_delay) ++ mdelay(100); ++ + return 0; + } + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0138-lvds-AR0231-modify-with-rev7-silicon.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0138-lvds-AR0231-modify-with-rev7-silicon.patch new file mode 100644 index 00000000..41161415 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0138-lvds-AR0231-modify-with-rev7-silicon.patch @@ -0,0 +1,633 @@ +From 4b901263653537d51deedc2d078086ccf7f2cfb4 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Thu, 3 Jan 2019 23:29:56 +0300 +Subject: [PATCH 087/122] lvds: AR0231 modify with rev7 silicon + +Use rev7 setup for AR0231. +Use MAX9286 and UB960 deserializer. +Use multiple sensor i2c addresses +Add crop + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ar0231.c | 86 ++++-- + drivers/media/i2c/soc_camera/ar0231_rev7.h | 418 +++++++++++++++++++++++++++++ + drivers/media/i2c/soc_camera/ov106xx.c | 12 +- + 3 files changed, 493 insertions(+), 23 deletions(-) + create mode 100644 drivers/media/i2c/soc_camera/ar0231_rev7.h + +diff --git a/drivers/media/i2c/soc_camera/ar0231.c b/drivers/media/i2c/soc_camera/ar0231.c +index 176e1bf..f575cb7 100644 +--- a/drivers/media/i2c/soc_camera/ar0231.c ++++ b/drivers/media/i2c/soc_camera/ar0231.c +@@ -20,9 +20,9 @@ + #include + #include + +-#include "ar0231.h" ++#include "ar0231_rev7.h" + +-#define AR0231_I2C_ADDR 0x10 ++static const int ar0231_i2c_addr[] = {0x10, 0x20}; + + #define AR0231_PID 0x3000 + #define AR0231_VERSION_REG 0x0354 +@@ -39,6 +39,8 @@ struct ar0231_priv { + /* serializers */ + int max9286_addr; + int max9271_addr; ++ int ti9x4_addr; ++ int ti9x3_addr; + int port; + int gpio_resetb; + int gpio_fsin; +@@ -85,6 +87,25 @@ static int ar0231_s_stream(struct v4l2_subdev *sd, int enable) + return 0; + } + ++static int ar0231_set_window(struct v4l2_subdev *sd) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0231_priv *priv = to_ar0231(client); ++ ++ dev_err(&client->dev, "L=%d T=%d %dx%d\n", priv->rect.left, priv->rect.top, priv->rect.width, priv->rect.height); ++ ++ /* horiz crop start */ ++ reg16_write16(client, 0x3004, priv->rect.left); ++ /* horiz crop end */ ++ reg16_write16(client, 0x3008, priv->rect.left + priv->rect.width - 1); ++ /* vert crop start */ ++ reg16_write16(client, 0x3002, priv->rect.top); ++ /* vert crop end */ ++ reg16_write16(client, 0x3006, priv->rect.top + priv->rect.height + 1); ++ ++ return 0; ++}; ++ + static int ar0231_get_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *format) +@@ -174,6 +195,8 @@ static int ar0231_set_selection(struct v4l2_subdev *sd, + priv->rect.width = rect->width; + priv->rect.height = rect->height; + ++ ar0231_set_window(sd); ++ + return 0; + } + +@@ -372,9 +395,29 @@ static int ar0231_initialize(struct i2c_client *client) + u16 val = 0; + u16 pid = 0; + int ret = 0; ++ int tmp_addr; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(ar0231_i2c_addr); i++) { ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ ++ reg8_write(client, 0x5d, ar0231_i2c_addr[i] << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ } ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x0a, ar0231_i2c_addr[i] << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ client->addr = tmp_addr; + +- /* check and show model ID */ +- reg16_read16(client, AR0231_PID, &pid); ++ /* check model ID */ ++ reg16_read16(client, AR0231_PID, &pid); ++ ++ if (pid == AR0231_VERSION_REG) ++ break; ++ } + + if (pid != AR0231_VERSION_REG) { + dev_dbg(&client->dev, "Product ID error %x\n", pid); +@@ -382,16 +425,15 @@ static int ar0231_initialize(struct i2c_client *client) + goto err; + } + ++ /* Read OTP IDs */ ++ ar0231_otp_id_read(client); + /* Program wizard registers */ +- ar0231_set_regs(client, ar0231_regs_wizard_rev4, ARRAY_SIZE(ar0231_regs_wizard_rev4)); ++ ar0231_set_regs(client, ar0231_regs_wizard_rev7, ARRAY_SIZE(ar0231_regs_wizard_rev7)); + + /* Enable stream */ +- reg16_read16(client, 0x301a, &val); // read inital reset_register value +- val |= (1 << 2); // Set streamOn bit +- reg16_write16(client, 0x301a, val); // Start Streaming +- +- /* Read OTP IDs */ +- ar0231_otp_id_read(client); ++ reg16_read16(client, 0x301a, &val); ++ val |= (1 << 2); ++ reg16_write16(client, 0x301a, val); + + dev_info(&client->dev, "ar0231 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", + pid, AR0231_MAX_WIDTH, AR0231_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); +@@ -419,13 +461,19 @@ static int ar0231_parse_dt(struct device_node *np, struct ar0231_priv *priv) + if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && + !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && + !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) +- break; ++ break; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; + } + + of_node_put(endpoint); + +- if (!priv->max9286_addr) { +- dev_err(&client->dev, "deserializer does not present\n"); ++ if (!priv->ti9x4_addr && !priv->max9286_addr) { ++ dev_dbg(&client->dev, "deserializer does not present\n"); + return -EINVAL; + } + +@@ -437,12 +485,16 @@ static int ar0231_parse_dt(struct device_node *np, struct ar0231_priv *priv) + client->addr = priv->max9271_addr; /* Serializer I2C address */ + + reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */ +- reg8_write(client, 0x0A, AR0231_I2C_ADDR << 1); /* Sensor native I2C address */ + usleep_range(2000, 2500); /* wait 2ms */ + }; +- client->addr = tmp_addr; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ + +- mdelay(10); ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ } ++ client->addr = tmp_addr; + + return 0; + } +diff --git a/drivers/media/i2c/soc_camera/ar0231_rev7.h b/drivers/media/i2c/soc_camera/ar0231_rev7.h +new file mode 100644 +index 0000000..c05c3ea +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0231_rev7.h +@@ -0,0 +1,418 @@ ++/* ++ * ON Semiconductor AR0231 sensor camera wizard 1928x1208@30/BGGR/MIPI ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++//#define AR0231_DISPLAY_PATTERN_FIXED ++//#define AR0231_DISPLAY_PATTERN_COLOR_BAR ++ ++#define AR0231_MAX_WIDTH 1920 ++#define AR0231_MAX_HEIGHT 1200 ++ ++#define AR0231_DELAY 0xffff ++ ++#define AR0231_SENSOR_WIDTH 1928 ++#define AR0231_SENSOR_HEIGHT 1208 ++ ++#define AR0231_X_START ((AR0231_SENSOR_WIDTH - AR0231_MAX_WIDTH) / 2) ++#define AR0231_Y_START ((AR0231_SENSOR_HEIGHT - AR0231_MAX_HEIGHT) / 2) ++#define AR0231_X_END (AR0231_X_START + AR0231_MAX_WIDTH - 1) ++#define AR0231_Y_END (AR0231_Y_START + AR0231_MAX_HEIGHT - 1) ++ ++struct ar0231_reg { ++ u16 reg; ++ u16 val; ++}; ++ ++/* 3Exp HDR Full Resolution Mode MIPI 4lane 12bit 30FPS, XCLK=27MHz */ ++static const struct ar0231_reg ar0231_regs_wizard_rev7[] = { ++{0x301A, 0x18}, // MIPI, stream OFF ++{AR0231_DELAY, 200}, // Wait 200ms ++ ++{0x3070, 0x0000}, // 1: Solid color test pattern, ++ // 2: Full color bar test pattern, ++ // 3: Fade to grey color bar test pattern, ++ //256: Walking 1 test pattern (12 bit) ++{0x3072, 0x0123}, // R ++{0x3074, 0x0456}, // G(GR row) ++{0x3076, 0x0abc}, // B ++{0x3078, 0x0def}, // G(GB row) ++#ifdef AR0231_DISPLAY_PATTERN_FIXED ++{0x3070, 0x0001}, ++#endif ++#ifdef AR0231_DISPLAY_PATTERN_COLOR_BAR ++{0x3070, 0x0002}, ++#endif ++{AR0231_DELAY, 100}, // Wait 100ms ++ ++#if 1 /* Sensor Setup */ ++#if 1 /* Recommended Settings */ ++{0x3092, 0x0C24}, ++{0x337A, 0x0C80}, ++{0x3520, 0x1288}, ++{0x3522, 0x880C}, ++{0x3524, 0x0C12}, ++{0x352C, 0x1212}, ++{0x354A, 0x007F}, ++{0x350C, 0x055C}, ++{0x3506, 0x3333}, ++{0x3508, 0x3333}, ++{0x3100, 0x4000}, ++{0x3280, 0x0FA0}, ++{0x3282, 0x0FA0}, ++{0x3284, 0x0FA0}, ++{0x3286, 0x0FA0}, ++{0x3288, 0x0FA0}, ++{0x328A, 0x0FA0}, ++{0x328C, 0x0FA0}, ++{0x328E, 0x0FA0}, ++{0x3290, 0x0FA0}, ++{0x3292, 0x0FA0}, ++{0x3294, 0x0FA0}, ++{0x3296, 0x0FA0}, ++{0x3298, 0x0FA0}, ++{0x329A, 0x0FA0}, ++{0x329C, 0x0FA0}, ++{0x329E, 0x0FA0}, ++#endif /* Recommended Settings */ ++ ++#if 1 /* Sequencer Update */ ++{0x2512, 0x8000}, ++{0x2510, 0x0905}, ++{0x2510, 0x3350}, ++{0x2510, 0x2004}, ++{0x2510, 0x1460}, ++{0x2510, 0x1578}, ++{0x2510, 0x0901}, ++{0x2510, 0x7B24}, ++{0x2510, 0xFF24}, ++{0x2510, 0xFF24}, ++{0x2510, 0xEA24}, ++{0x2510, 0x1022}, ++{0x2510, 0x2410}, ++{0x2510, 0x155A}, ++{0x2510, 0x0901}, ++{0x2510, 0x1400}, ++{0x2510, 0x24FF}, ++{0x2510, 0x24FF}, ++{0x2510, 0x24EA}, ++{0x2510, 0x2324}, ++{0x2510, 0x647A}, ++{0x2510, 0x2404}, ++{0x2510, 0x052C}, ++{0x2510, 0x400A}, ++{0x2510, 0xFF0A}, ++{0x2510, 0xFF0A}, ++{0x2510, 0x1008}, ++{0x2510, 0x3851}, ++{0x2510, 0x1440}, ++{0x2510, 0x0004}, ++{0x2510, 0x0801}, ++{0x2510, 0x0408}, ++{0x2510, 0x1180}, ++{0x2510, 0x2652}, ++{0x2510, 0x1518}, ++{0x2510, 0x0906}, ++{0x2510, 0x1348}, ++{0x2510, 0x1002}, ++{0x2510, 0x1016}, ++{0x2510, 0x1181}, ++{0x2510, 0x1189}, ++{0x2510, 0x1056}, ++{0x2510, 0x1210}, ++{0x2510, 0x0901}, ++{0x2510, 0x0D09}, ++{0x2510, 0x1413}, ++{0x2510, 0x8809}, ++{0x2510, 0x2B15}, ++{0x2510, 0x8809}, ++{0x2510, 0x0311}, ++{0x2510, 0xD909}, ++{0x2510, 0x1214}, ++{0x2510, 0x4109}, ++{0x2510, 0x0312}, ++{0x2510, 0x1409}, ++{0x2510, 0x0110}, ++{0x2510, 0xD612}, ++{0x2510, 0x1012}, ++{0x2510, 0x1212}, ++{0x2510, 0x1011}, ++{0x2510, 0xDD11}, ++{0x2510, 0xD910}, ++{0x2510, 0x5609}, ++{0x2510, 0x1511}, ++{0x2510, 0xDB09}, ++{0x2510, 0x1511}, ++{0x2510, 0x9B09}, ++{0x2510, 0x0F11}, ++{0x2510, 0xBB12}, ++{0x2510, 0x1A12}, ++{0x2510, 0x1014}, ++{0x2510, 0x6012}, ++{0x2510, 0x5010}, ++{0x2510, 0x7610}, ++{0x2510, 0xE609}, ++{0x2510, 0x0812}, ++{0x2510, 0x4012}, ++{0x2510, 0x6009}, ++{0x2510, 0x290B}, ++{0x2510, 0x0904}, ++{0x2510, 0x1440}, ++{0x2510, 0x0923}, ++{0x2510, 0x15C8}, ++{0x2510, 0x13C8}, ++{0x2510, 0x092C}, ++{0x2510, 0x1588}, ++{0x2510, 0x1388}, ++{0x2510, 0x0C09}, ++{0x2510, 0x0C14}, ++{0x2510, 0x4109}, ++{0x2510, 0x1112}, ++{0x2510, 0x6212}, ++{0x2510, 0x6011}, ++{0x2510, 0xBF11}, ++{0x2510, 0xBB10}, ++{0x2510, 0x6611}, ++{0x2510, 0xFB09}, ++{0x2510, 0x3511}, ++{0x2510, 0xBB12}, ++{0x2510, 0x6312}, ++{0x2510, 0x6014}, ++{0x2510, 0x0015}, ++{0x2510, 0x0011}, ++{0x2510, 0xB812}, ++{0x2510, 0xA012}, ++{0x2510, 0x0010}, ++{0x2510, 0x2610}, ++{0x2510, 0x0013}, ++{0x2510, 0x0011}, ++{0x2510, 0x0008}, ++{0x2510, 0x3053}, ++{0x2510, 0x4215}, ++{0x2510, 0x4013}, ++{0x2510, 0x4010}, ++{0x2510, 0x0210}, ++{0x2510, 0x1611}, ++{0x2510, 0x8111}, ++{0x2510, 0x8910}, ++{0x2510, 0x5612}, ++{0x2510, 0x1009}, ++{0x2510, 0x010D}, ++{0x2510, 0x0815}, ++{0x2510, 0xC015}, ++{0x2510, 0xD013}, ++{0x2510, 0x5009}, ++{0x2510, 0x1313}, ++{0x2510, 0xD009}, ++{0x2510, 0x0215}, ++{0x2510, 0xC015}, ++{0x2510, 0xC813}, ++{0x2510, 0xC009}, ++{0x2510, 0x0515}, ++{0x2510, 0x8813}, ++{0x2510, 0x8009}, ++{0x2510, 0x0213}, ++{0x2510, 0x8809}, ++{0x2510, 0x0411}, ++{0x2510, 0xC909}, ++{0x2510, 0x0814}, ++{0x2510, 0x0109}, ++{0x2510, 0x0B11}, ++{0x2510, 0xD908}, ++{0x2510, 0x1400}, ++{0x2510, 0x091A}, ++{0x2510, 0x1440}, ++{0x2510, 0x0903}, ++{0x2510, 0x1214}, ++{0x2510, 0x0901}, ++{0x2510, 0x10D6}, ++{0x2510, 0x1210}, ++{0x2510, 0x1212}, ++{0x2510, 0x1210}, ++{0x2510, 0x11DD}, ++{0x2510, 0x11D9}, ++{0x2510, 0x1056}, ++{0x2510, 0x0917}, ++{0x2510, 0x11DB}, ++{0x2510, 0x0913}, ++{0x2510, 0x11FB}, ++{0x2510, 0x0905}, ++{0x2510, 0x11BB}, ++{0x2510, 0x121A}, ++{0x2510, 0x1210}, ++{0x2510, 0x1460}, ++{0x2510, 0x1250}, ++{0x2510, 0x1076}, ++{0x2510, 0x10E6}, ++{0x2510, 0x0901}, ++{0x2510, 0x15A8}, ++{0x2510, 0x0901}, ++{0x2510, 0x13A8}, ++{0x2510, 0x1240}, ++{0x2510, 0x1260}, ++{0x2510, 0x0925}, ++{0x2510, 0x13AD}, ++{0x2510, 0x0902}, ++{0x2510, 0x0907}, ++{0x2510, 0x1588}, ++{0x2510, 0x0901}, ++{0x2510, 0x138D}, ++{0x2510, 0x0B09}, ++{0x2510, 0x0914}, ++{0x2510, 0x4009}, ++{0x2510, 0x0B13}, ++{0x2510, 0x8809}, ++{0x2510, 0x1C0C}, ++{0x2510, 0x0920}, ++{0x2510, 0x1262}, ++{0x2510, 0x1260}, ++{0x2510, 0x11BF}, ++{0x2510, 0x11BB}, ++{0x2510, 0x1066}, ++{0x2510, 0x090A}, ++{0x2510, 0x11FB}, ++{0x2510, 0x093B}, ++{0x2510, 0x11BB}, ++{0x2510, 0x1263}, ++{0x2510, 0x1260}, ++{0x2510, 0x1400}, ++{0x2510, 0x1508}, ++{0x2510, 0x11B8}, ++{0x2510, 0x12A0}, ++{0x2510, 0x1200}, ++{0x2510, 0x1026}, ++{0x2510, 0x1000}, ++{0x2510, 0x1300}, ++{0x2510, 0x1100}, ++{0x2510, 0x437A}, ++{0x2510, 0x0609}, ++{0x2510, 0x0B05}, ++{0x2510, 0x0708}, ++{0x2510, 0x4137}, ++{0x2510, 0x502C}, ++{0x2510, 0x2CFE}, ++{0x2510, 0x15FE}, ++{0x2510, 0x0C2C}, ++ ++{0x32e6, 0xe0}, ++{0x1008, 0x36f}, ++{0x100c, 0x58f}, ++{0x100e, 0x7af}, ++{0x1010, 0x14f}, ++ ++{0x3230, 0x312}, ++{0x3232, 0x532}, ++{0x3234, 0x752}, ++{0x3236, 0xf2}, ++#endif /* Sequencer Update */ ++ ++//{0x3566, 0x3328}, // clear bit6 ++{0x32D0, 0x3A02}, ++{0x32D2, 0x3508}, ++{0x32D4, 0x3702}, ++{0x32D6, 0x3C04}, ++{0x32DC, 0x370A}, ++{0x30B0, 0x800}, // clear bit9 ++#endif /* Sensor Setup */ ++ ++#if 1 /* Serial 12-bit Timing Setup */ ++{0x302A, 6}, // vt_pix_clk_div ++{0x302C, 1}, // vt_sys_clk_div ++{0x302E, 2}, // pre_pll_clk_div ++{0x3030, 44}, // pll_multiplier ++{0x3036, 12}, // op_word_clk_div ++{0x3038, 1}, // op_sys_clk_div ++{0x30B0, 0x800}, // digital_test: pll_complete_bypass=0 ++#endif /* Serial 12-bit Timing Setup */ ++ ++#if 1 /* Readout Mode Configuration */ ++{0x30A2, 1}, // x_odd_inc_ ++{0x30A6, 1}, // y_odd_inc_ ++{0x3040, 0}, // read_mode ++//{0x3082, 0x8}, // operation_mode_ctrl ++//{0x30BA, 0x11E2}, // digital_ctrl ++{0x3044, 0x400}, // dark_control ++#ifdef AR0231_EMBEDDED_LINE ++{0x3064, 0x1982}, // SMIA_TEST ++#else ++{0x3064, 0x1802}, // SMIA_TEST ++#endif ++//{0x33E0, 0xC80}, ++//{0x3180, 0x80}, ++//{0x33E4, 0x80}, ++#endif /* Readout Mode Configuration */ ++ ++#if 1 /* Full Res FOV */ ++{0x3004, AR0231_X_START}, // X_ADDR_START_ ++{0x3008, AR0231_X_END}, // X_ADDR_END_ ++{0x3002, AR0231_Y_START}, // Y_ADDR_START_ ++{0x3006, AR0231_Y_END}, // Y_ADDR_END_ ++{0x3032, 0x0}, // scaling_mode ++{0x3400, 0x10}, ++{0x3402, 0x0000 | AR0231_MAX_WIDTH}, // X_OUTPUT_CONTROL ++{0x3404, 0x0000 | AR0231_MAX_HEIGHT}, // Y_OUTPUT_CONTROL ++#endif /* Full Res FOV */ ++ ++#if 1 /* 3exp Timing and Exposure */ ++{0x3082, 0x8}, // operation_mode_ctrl ++{0x30BA, 0x11E2}, // digital_ctrl: num_exp_max=2 ++ ++/* Row and Pixel Timing */ ++{0x300C, 1674}, // line_length_pck_ ++{0x300A, 1314}, // frame_length_lines_ ++{0x3042, 0}, // extra_delay ++ ++/* Exposure Settings */ ++//{0x3238, 0x222}, // exposure_ratio ++{0x3012, 355}, // coarse_integration_time_ ++{0x3014, 1874}, // fine_integration_time_ ++{0x321E, 1874}, // fine_integration_time2 ++{0x3222, 1874}, // fine_integration_time3 ++{0x30B0, 0x800}, // digital_test: set bit11 ++{0x32EA, 0x3C0E}, ++{0x32EC, 0x72A1}, ++#endif /* 3exp Timing and Exposure - Serial */ ++ ++#if 1 /* HDR 12 bit Output */ ++{0x31D0, 1}, // companding ++{0x31AC, 0x140C}, // data_format_bits: RAW20, OUT12 ++#endif /* HDR 12 bit Output */ ++ ++#if 1 /* MIPI 12 bit Settings */ ++{0x31AE, 0x204}, // serial_format: MIPI 4 lanes ++//{0x3342, 0x122C}, // default, DT=0x12, DT=0x2C ++//{0x3346, 0x122C}, // default, DT=0x12, DT=0x2C ++//{0x334A, 0x122C}, // default, DT=0x12, DT=0x2C ++//{0x334E, 0x122C}, // default, DT=0x12, DT=0x2C ++//{0x3344, 0x0011}, // default, VC=0 ++//{0x3348, 0x0111}, // default, VC=1 ++//{0x334C, 0x0211}, // default, VC=2 ++//{0x3350, 0x0311}, // default, VC=3 ++//{0x31B0, 0x49}, // frame_preamble ++//{0x31B2, 0x33}, // line_preamble ++{0x31B4, 0x2185}, ++{0x31B6, 0x1146}, ++{0x31B8, 0x3047}, ++{0x31BA, 0x186}, ++{0x31BC, 0x805}, ++#endif /* MIPI 12 bit Settings */ ++ ++/* FPS = 124.5MHz / reg0x300A / reg0x300C * (DES_XTAL/27MHz), DES_XTAL=23.5MHz */ ++{0x300A, AR0231_SENSOR_HEIGHT + 100}, // Frame_length_Lines ++{0x300C, AR0231_SENSOR_WIDTH + 550}, // Line_length_pck ++{0x3012, 0x144}, //Integration_time ++ ++#if 1 /* Enable trigger input */ ++{0x340A, 0x00E0}, // GPIO_CONTROL1: GPIO1 is trigger ++{0x340C, 0x0002}, // GPIO_CONTROL2: GPIO1 is trigger ++{0x30CE, 0x0120}, // TRIGGER_MODE ++//{0x30DC, 0x0120}, // TRIGGER_DELAY ++{0x301A, 0x0118}, // GPI pins enable ++#endif ++}; +diff --git a/drivers/media/i2c/soc_camera/ov106xx.c b/drivers/media/i2c/soc_camera/ov106xx.c +index e5d6b67..aaadcc2 100644 +--- a/drivers/media/i2c/soc_camera/ov106xx.c ++++ b/drivers/media/i2c/soc_camera/ov106xx.c +@@ -51,6 +51,12 @@ static int ov106xx_probe(struct i2c_client *client, + int ret; + chip_id = -EINVAL; + ++ ret = ar0231_probe(client, did); ++ if (!ret) { ++ chip_id = ID_AR0231; ++ goto out; ++ } ++ + ret = ar0233_probe(client, did); + if (!ret) { + chip_id = ID_AR0233; +@@ -105,12 +111,6 @@ static int ov106xx_probe(struct i2c_client *client, + goto out; + } + +- ret = ar0231_probe(client, did); +- if (!ret) { +- chip_id = ID_AR0231; +- goto out; +- } +- + ret = ap0101_probe(client, did); + if (!ret) { + chip_id = ID_AP0101_AR014X; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0139-lvds-AR0233-modify-with-rev2-silicon.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0139-lvds-AR0233-modify-with-rev2-silicon.patch new file mode 100644 index 00000000..db5bffeb --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0139-lvds-AR0233-modify-with-rev2-silicon.patch @@ -0,0 +1,1349 @@ +From 23114c0a5904abe79b69129335dccf0c4aee0118 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Thu, 3 Jan 2019 23:43:46 +0300 +Subject: [PATCH 088/122] lvds: AR0233 modify with rev2 silicon + +Use rev2 setup for AR0233. +Remove code moved to ti9x4 driver + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ar0233.c | 19 +- + drivers/media/i2c/soc_camera/ar0233_rev2.h | 1281 ++++++++++++++++++++++++++++ + 2 files changed, 1284 insertions(+), 16 deletions(-) + create mode 100644 drivers/media/i2c/soc_camera/ar0233_rev2.h + +diff --git a/drivers/media/i2c/soc_camera/ar0233.c b/drivers/media/i2c/soc_camera/ar0233.c +index 74ecc85..2a0b7aa 100644 +--- a/drivers/media/i2c/soc_camera/ar0233.c ++++ b/drivers/media/i2c/soc_camera/ar0233.c +@@ -20,12 +20,12 @@ + #include + #include + +-#include "ar0233.h" ++#include "ar0233_rev2.h" + + static const int ar0233_i2c_addr[] = {0x10, 0x20}; + + #define AR0233_PID 0x3000 +-#define AR0233_VERSION_REG 0x0354 ++#define AR0233_VERSION_REG 0x0956 + + #define AR0233_MEDIA_BUS_FMT MEDIA_BUS_FMT_SGRBG12_1X12 + +@@ -404,23 +404,10 @@ static int ar0233_initialize(struct i2c_client *client) + goto err; + } + +- /* setup XCLK */ +- tmp_addr = client->addr; +- if (priv->ti9x4_addr) { +- /* CLK_OUT=22.5792*160*M/N/CLKDIV -> CLK_OUT=27MHz: CLKDIV=2, M=15, N=251: 22.5792*160/8*15/251=26.987MHz=CLK_OUT */ +- client->addr = priv->ti9x3_addr; /* Serializer I2C address */ +-#if 0 +- reg8_write(client, 0x06, 0x6f); /* Set CLKDIV and M */ +- reg8_write(client, 0x07, 0xfb); /* Set N */ +-#endif +- reg8_write(client, 0x0e, 0xf0); /* Enable all remote gpios */ +- } +- client->addr = tmp_addr; +- + /* Read OTP IDs */ + ar0233_otp_id_read(client); + /* Program wizard registers */ +- ar0233_set_regs(client, ar0233_regs_wizard, ARRAY_SIZE(ar0233_regs_wizard)); ++ ar0233_set_regs(client, ar0233_regs_wizard_rev2, ARRAY_SIZE(ar0233_regs_wizard_rev2)); + + /* Enable stream */ + reg16_read16(client, 0x301a, &val); // read inital reset_register value +diff --git a/drivers/media/i2c/soc_camera/ar0233_rev2.h b/drivers/media/i2c/soc_camera/ar0233_rev2.h +new file mode 100644 +index 0000000..fbc2649 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0233_rev2.h +@@ -0,0 +1,1281 @@ ++/* ++ * ON Semiconductor AR0233 sensor camera wizard 2048x1280@30/BGGR/MIPI ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++//#define AR0233_DISPLAY_PATTERN_FIXED ++//#define AR0233_DISPLAY_PATTERN_COLOR_BAR ++ ++#define AR0233_MAX_WIDTH 2048 ++#define AR0233_MAX_HEIGHT 1280 ++ ++#define AR0233_DELAY 0xffff ++ ++#define AR0233_SENSOR_WIDTH 2058 ++#define AR0233_SENSOR_HEIGHT 1284 ++ ++#define AR0233_X_START ((AR0233_SENSOR_WIDTH - AR0233_MAX_WIDTH) / 2) ++#define AR0233_Y_START ((AR0233_SENSOR_HEIGHT - AR0233_MAX_HEIGHT) / 2) ++#define AR0233_X_END (AR0233_X_START + AR0233_MAX_WIDTH - 1) ++#define AR0233_Y_END (AR0233_Y_START + AR0233_MAX_HEIGHT - 1) ++ ++struct ar0233_reg { ++ u16 reg; ++ u16 val; ++}; ++ ++#define O1_Recommended_Defaults_LFM_HDR ++#ifdef O1_Recommended_Defaults_LFM_HDR ++ #define Design_recommended_settings_REV2_V9 ++ #define Sequence_hidy_ar0233_REV2_V13 ++ #define Pre_hdr_gain_enable ++ #define Tempsensor_init ++#endif ++#define disable_embed_data_stat ++#define HDR_3exp_12bit ++#if 0 ++ #define pll_27_108_4lane_12b ++ #define mipi_108_12bit_4lane ++#else ++ #define pll_27_124p5_4lane_12b ++ #define mipi_124p5_12bit_4lane ++#endif ++#define MIPI_DT_bit12 ++#define LUT_24_to_12 ++#define HDR_ratio_gain_default ++#define Enable_trigger_input ++ ++/* 3Exp HDR 1280P Mipi_12bit_4lane_30fps, XCLK=27MHz */ ++static const struct ar0233_reg ar0233_regs_wizard_rev2[] = { ++{0x301A, 0x18}, // MIPI, stream OFF ++{AR0233_DELAY, 200}, // Wait 200ms ++ ++{0x3070, 0x0000}, // 1: Solid color test pattern, ++ // 2: Full color bar test pattern, ++ // 3: Fade to grey color bar test pattern, ++ //256: Walking 1 test pattern (12 bit) ++{0x3072, 0x0123}, // R ++{0x3074, 0x0456}, // G(GR row) ++{0x3076, 0x0abc}, // B ++{0x3078, 0x0def}, // G(GB row) ++#ifdef AR0233_DISPLAY_PATTERN_FIXED ++{0x3070, 0x0001}, ++#endif ++#ifdef AR0233_DISPLAY_PATTERN_COLOR_BAR ++{0x3070, 0x0002}, ++#endif ++{AR0233_DELAY, 100}, // Wait 100ms ++ ++#ifdef O1_Recommended_Defaults_LFM_HDR ++#ifdef Design_recommended_settings_REV2_V9 ++{0x3C72, 0x0076}, ++{0x3C74, 0x0031}, ++{0x3C76, 0x00DC}, ++{0x3C78, 0x01AA}, ++{0x3C7A, 0x0352}, ++{0x3C7C, 0x06AA}, ++{0x3520, 0x0084}, ++{0x3522, 0x7D19}, ++{0x356A, 0x81AA}, ++{0x3568, 0x0028}, ++{0x351A, 0xF400}, ++{0x3092, 0x000C}, ++{0x37B2, 0x1FFF}, ++{0x3562, 0x0C08}, ++{0x3496, 0xDF80}, ++{0x3492, 0x1001}, ++{0x34BC, 0x1010}, ++{0x3494, 0x1010}, ++{0x3520, 0x0080}, ++{0x3512, 0x0EDC}, ++{0x3530, 0x5F18}, ++{0x353C, 0x9A8A}, ++{0x3576, 0x1DFF}, ++{0x3544, 0x030F}, ++{0x3534, 0x3898}, ++{0x353A, 0x9A9A}, ++{0x356E, 0x048A}, ++{0x356C, 0x6A28}, ++{0x3564, 0x1223}, ++{0x3508, 0xAF1A}, ++{0x3086, 0x0000}, ++{0x34BA, 0x0001}, ++{0x34B8, 0x0001}, ++{0x3550, 0x806C}, ++{0x3522, 0x0519}, ++{0x34A0, 0x0036}, ++{0x34A4, 0x0035}, ++{0x34A6, 0x0040}, ++{0x342E, 0x0017}, ++{0x3E3E, 0x000C}, ++{0x3092, 0x408C}, ++{0x3530, 0x1F18}, ++{0x351C, 0xC0F2}, ++{0x3528, 0xE008}, ++{0x352A, 0x0827}, ++{0x352C, 0xA800}, ++{0x352E, 0x0908}, ++#endif /* Design_recommended_settings_REV2_V9 */ ++ ++#ifdef Sequence_hidy_ar0233_REV2_V13 ++{0x2512, 0x8000}, ++{0x2510, 0x070f}, ++{0x2510, 0x1011}, ++{0x2510, 0x1215}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0x1819}, ++{0x2510, 0x1d1e}, ++{0x2510, 0x2021}, ++{0x2510, 0xffff}, ++{0x2510, 0x2240}, ++{0x2510, 0x5172}, ++{0x2510, 0x8586}, ++{0x2510, 0x8788}, ++{0x2510, 0x898b}, ++{0x2510, 0x959a}, ++{0x2510, 0x9b9e}, ++{0x2510, 0xa2a6}, ++{0x2510, 0xaaac}, ++{0x2510, 0xaeb0}, ++{0x2510, 0xb3b5}, ++{0x2510, 0xcfd1}, ++{0x2510, 0xd9dd}, ++{0x2510, 0xe0e3}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xc003}, ++{0x2510, 0x805a}, ++{0x2510, 0xa0e0}, ++{0x2510, 0x3041}, ++{0x2510, 0x3042}, ++{0x2510, 0x2000}, ++{0x2510, 0x3048}, ++{0x2510, 0x3088}, ++{0x2510, 0x30a0}, ++{0x2510, 0x3090}, ++{0x2510, 0x32c2}, ++{0x2510, 0xa0c0}, ++{0x2510, 0x9008}, ++{0x2510, 0x8802}, ++{0x2510, 0x20ff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x9018}, ++{0x2510, 0x891a}, ++{0x2510, 0x807e}, ++{0x2510, 0x20ff}, ++{0x2510, 0x895b}, ++{0x2510, 0x20ff}, ++{0x2510, 0x897b}, ++{0x2510, 0x20ff}, ++{0x2510, 0x897f}, ++{0x2510, 0x20ff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xa0c4}, ++{0x2510, 0x20ff}, ++{0x2510, 0x805a}, ++{0x2510, 0x9039}, ++{0x2510, 0x20ff}, ++{0x2510, 0x907f}, ++{0x2510, 0x895b}, ++{0x2510, 0x2064}, ++{0x2510, 0x891b}, ++{0x2510, 0x2010}, ++{0x2510, 0x8803}, ++{0x2510, 0x7fff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x906b}, ++{0x2510, 0x2064}, ++{0x2510, 0x3084}, ++{0x2510, 0x2003}, ++{0x2510, 0x3044}, ++{0x2510, 0x2000}, ++{0x2510, 0xa004}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2400}, ++{0x2510, 0x2401}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2400}, ++{0x2510, 0x2401}, ++{0x2510, 0x2702}, ++{0x2510, 0x3242}, ++{0x2510, 0x2420}, ++{0x2510, 0x2421}, ++{0x2510, 0x2703}, ++{0x2510, 0x3242}, ++{0x2510, 0x2420}, ++{0x2510, 0x2421}, ++{0x2510, 0x2704}, ++{0x2510, 0x3242}, ++{0x2510, 0x2420}, ++{0x2510, 0x2421}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2402}, ++{0x2510, 0x2403}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2741}, ++{0x2510, 0x2429}, ++{0x2510, 0x2740}, ++{0x2510, 0x242a}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2201}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2201}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xb800}, ++{0x2510, 0x8058}, ++{0x2510, 0xa005}, ++{0x2510, 0x3101}, ++{0x2510, 0x3041}, ++{0x2510, 0x3104}, ++{0x2510, 0xb035}, ++{0x2510, 0xb075}, ++{0x2510, 0x30c1}, ++{0x2510, 0x3102}, ++{0x2510, 0x3041}, ++{0x2510, 0xb808}, ++{0x2510, 0x3202}, ++{0x2510, 0xb848}, ++{0x2510, 0xb84c}, ++{0x2510, 0x2201}, ++{0x2510, 0xb377}, ++{0x2510, 0x8843}, ++{0x2510, 0x916f}, ++{0x2510, 0x2201}, ++{0x2510, 0xb84e}, ++{0x2510, 0xf905}, ++{0x2510, 0xf907}, ++{0x2510, 0x2200}, ++{0x2510, 0x885b}, ++{0x2510, 0xa898}, ++{0x2510, 0xa8d8}, ++{0x2510, 0xf8e8}, ++{0x2510, 0x80d8}, ++{0x2510, 0x9007}, ++{0x2510, 0x916f}, ++{0x2510, 0x2206}, ++{0x2510, 0xb808}, ++{0x2510, 0xc800}, ++{0x2510, 0xe809}, ++{0x2510, 0x88db}, ++{0x2510, 0xf8a8}, ++{0x2510, 0xf888}, ++{0x2510, 0x2203}, ++{0x2510, 0xb07b}, ++{0x2510, 0x2000}, ++{0x2510, 0x80c8}, ++{0x2510, 0x8088}, ++{0x2510, 0x220b}, ++{0x2510, 0xb06a}, ++{0x2510, 0x88cb}, ++{0x2510, 0x888b}, ++{0x2510, 0x2224}, ++{0x2510, 0xb04a}, ++{0x2510, 0x2218}, ++{0x2510, 0x210d}, ++{0x2510, 0x2108}, ++{0x2510, 0x902f}, ++{0x2510, 0xb04b}, ++{0x2510, 0xf880}, ++{0x2510, 0x2205}, ++{0x2510, 0x2205}, ++{0x2510, 0x2203}, ++{0x2510, 0x9800}, ++{0x2510, 0xb043}, ++{0x2510, 0xa8c9}, ++{0x2510, 0x31c1}, ++{0x2510, 0x80a8}, ++{0x2510, 0x2205}, ++{0x2510, 0x916f}, ++{0x2510, 0x2104}, ++{0x2510, 0x88ab}, ++{0x2510, 0x2104}, ++{0x2510, 0xb808}, ++{0x2510, 0x9800}, ++{0x2510, 0x2440}, ++{0x2510, 0xf110}, ++{0x2510, 0xf804}, ++{0x2510, 0x2000}, ++{0x2510, 0x8088}, ++{0x2510, 0x3002}, ++{0x2510, 0xb838}, ++{0x2510, 0xa8c8}, ++{0x2510, 0xb04b}, ++{0x2510, 0x2442}, ++{0x2510, 0x3210}, ++{0x2510, 0x2206}, ++{0x2510, 0x888b}, ++{0x2510, 0x2203}, ++{0x2510, 0xf1cb}, ++{0x2510, 0xf1cc}, ++{0x2510, 0xf1cc}, ++{0x2510, 0x2201}, ++{0x2510, 0x3202}, ++{0x2510, 0xf880}, ++{0x2510, 0xb830}, ++{0x2510, 0xc801}, ++{0x2510, 0x30c2}, ++{0x2510, 0xe80c}, ++{0x2510, 0x2201}, ++{0x2510, 0xb04a}, ++{0x2510, 0x2226}, ++{0x2510, 0x2205}, ++{0x2510, 0x3241}, ++{0x2510, 0x2206}, ++{0x2510, 0x902f}, ++{0x2510, 0x220e}, ++{0x2510, 0x2205}, ++{0x2510, 0x2204}, ++{0x2510, 0xb042}, ++{0x2510, 0xa9a1}, ++{0x2510, 0x8008}, ++{0x2510, 0xb0d3}, ++{0x2510, 0x31c1}, ++{0x2510, 0x916b}, ++{0x2510, 0x2008}, ++{0x2510, 0x32c1}, ++{0x2510, 0x8803}, ++{0x2510, 0xa044}, ++{0x2510, 0x3044}, ++{0x2510, 0x2000}, ++{0x2510, 0xa004}, ++{0x2510, 0x2000}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xa084}, ++{0x2510, 0x30d0}, ++{0x2510, 0x807c}, ++{0x2510, 0x3141}, ++{0x2510, 0x3041}, ++{0x2510, 0x3042}, ++{0x2510, 0x2000}, ++{0x2510, 0x3142}, ++{0x2510, 0x3041}, ++{0x2510, 0x3042}, ++{0x2510, 0x2000}, ++{0x2510, 0x3281}, ++{0x2510, 0x3041}, ++{0x2510, 0x3042}, ++{0x2510, 0x2000}, ++{0x2510, 0x3290}, ++{0x2510, 0x3041}, ++{0x2510, 0x3042}, ++{0x2510, 0x2000}, ++{0x2510, 0x3110}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x3120}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x3282}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x32a0}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x881b}, ++{0x2510, 0x887f}, ++{0x2510, 0xa08c}, ++{0x2510, 0x221f}, ++{0x2510, 0xa084}, ++{0x2510, 0x2440}, ++{0x2510, 0x3260}, ++{0x2510, 0x3248}, ++{0x2510, 0xb095}, ++{0x2510, 0xf110}, ++{0x2510, 0xf864}, ++{0x2510, 0xf90d}, ++{0x2510, 0x3084}, ++{0x2510, 0x32c1}, ++{0x2510, 0x3090}, ++{0x2510, 0x3088}, ++{0x2510, 0x2443}, ++{0x2510, 0x8058}, ++{0x2510, 0x3001}, ++{0x2510, 0x2442}, ++{0x2510, 0x3220}, ++{0x2510, 0x2002}, ++{0x2510, 0x8867}, ++{0x2510, 0x2004}, ++{0x2510, 0x8803}, ++{0x2510, 0x2441}, ++{0x2510, 0x30c2}, ++{0x2510, 0xa9a0}, ++{0x2510, 0xb094}, ++{0x2510, 0x2201}, ++{0x2510, 0xa0c4}, ++{0x2510, 0x3044}, ++{0x2510, 0x2000}, ++{0x2510, 0xa004}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xb980}, ++{0x2510, 0xa881}, ++{0x2510, 0xa8c1}, ++{0x2510, 0x8108}, ++{0x2510, 0xa105}, ++{0x2510, 0x30c1}, ++{0x2510, 0x2020}, ++{0x2510, 0x3101}, ++{0x2510, 0x3041}, ++{0x2510, 0x3104}, ++{0x2510, 0x3102}, ++{0x2510, 0x3041}, ++{0x2510, 0xf860}, ++{0x2510, 0xb095}, ++{0x2510, 0x2001}, ++{0x2510, 0xb988}, ++{0x2510, 0xb9f8}, ++{0x2510, 0xb9fc}, ++{0x2510, 0x8803}, ++{0x2510, 0x916f}, ++{0x2510, 0x2001}, ++{0x2510, 0xb9fe}, ++{0x2510, 0xf905}, ++{0x2510, 0xf907}, ++{0x2510, 0x3202}, ++{0x2510, 0x880b}, ++{0x2510, 0xb397}, ++{0x2510, 0xf8e8}, ++{0x2510, 0x8188}, ++{0x2510, 0x9007}, ++{0x2510, 0x916f}, ++{0x2510, 0x2204}, ++{0x2510, 0xb137}, ++{0x2510, 0xb9b8}, ++{0x2510, 0xc801}, ++{0x2510, 0xe809}, ++{0x2510, 0xb177}, ++{0x2510, 0x888b}, ++{0x2510, 0xf8a8}, ++{0x2510, 0xf888}, ++{0x2510, 0x2203}, ++{0x2510, 0xa8c8}, ++{0x2510, 0xb07b}, ++{0x2510, 0x2000}, ++{0x2510, 0x8188}, ++{0x2510, 0x8088}, ++{0x2510, 0x220b}, ++{0x2510, 0xb06a}, ++{0x2510, 0x888b}, ++{0x2510, 0x888b}, ++{0x2510, 0x2224}, ++{0x2510, 0xb04a}, ++{0x2510, 0x2218}, ++{0x2510, 0x210a}, ++{0x2510, 0x210a}, ++{0x2510, 0xb04b}, ++{0x2510, 0x902f}, ++{0x2510, 0xf880}, ++{0x2510, 0x2211}, ++{0x2510, 0x2205}, ++{0x2510, 0x2204}, ++{0x2510, 0xb043}, ++{0x2510, 0xa8c1}, ++{0x2510, 0x31c1}, ++{0x2510, 0x2200}, ++{0x2510, 0x8048}, ++{0x2510, 0x2103}, ++{0x2510, 0x916f}, ++{0x2510, 0x2106}, ++{0x2510, 0x884b}, ++{0x2510, 0x210a}, ++{0x2510, 0xa8c1}, ++{0x2510, 0x2440}, ++{0x2510, 0xf110}, ++{0x2510, 0xf804}, ++{0x2510, 0x2000}, ++{0x2510, 0x8008}, ++{0x2510, 0x2002}, ++{0x2510, 0x880b}, ++{0x2510, 0x3002}, ++{0x2510, 0xb988}, ++{0x2510, 0x2442}, ++{0x2510, 0x3210}, ++{0x2510, 0x2206}, ++{0x2510, 0x2441}, ++{0x2510, 0xa8c1}, ++{0x2510, 0xf1cb}, ++{0x2510, 0xf1cc}, ++{0x2510, 0xf1cc}, ++{0x2510, 0x2010}, ++{0x2510, 0x8088}, ++{0x2510, 0x200c}, ++{0x2510, 0x888b}, ++{0x2510, 0x2005}, ++{0x2510, 0xa8d0}, ++{0x2510, 0xb04b}, ++{0x2510, 0x3202}, ++{0x2510, 0xf880}, ++{0x2510, 0xb980}, ++{0x2510, 0xc800}, ++{0x2510, 0x30c2}, ++{0x2510, 0xe80c}, ++{0x2510, 0x2201}, ++{0x2510, 0xb04a}, ++{0x2510, 0x2213}, ++{0x2510, 0x2225}, ++{0x2510, 0x8088}, ++{0x2510, 0x2205}, ++{0x2510, 0x888b}, ++{0x2510, 0x2203}, ++{0x2510, 0x3241}, ++{0x2510, 0x902f}, ++{0x2510, 0x2206}, ++{0x2510, 0x2204}, ++{0x2510, 0xb042}, ++{0x2510, 0xa9a1}, ++{0x2510, 0x8058}, ++{0x2510, 0xb093}, ++{0x2510, 0x31c1}, ++{0x2510, 0x916b}, ++{0x2510, 0x2008}, ++{0x2510, 0x32c1}, ++{0x2510, 0x8803}, ++{0x2510, 0xa144}, ++{0x2510, 0x3044}, ++{0x2510, 0x2000}, ++{0x2510, 0xa004}, ++{0x2510, 0xb800}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x30d0}, ++{0x2510, 0xa184}, ++{0x2510, 0xb980}, ++{0x2510, 0x807c}, ++{0x2510, 0x3141}, ++{0x2510, 0x3041}, ++{0x2510, 0x3042}, ++{0x2510, 0x2000}, ++{0x2510, 0x3142}, ++{0x2510, 0x3041}, ++{0x2510, 0x3042}, ++{0x2510, 0x2000}, ++{0x2510, 0x3281}, ++{0x2510, 0x3041}, ++{0x2510, 0x3042}, ++{0x2510, 0x2000}, ++{0x2510, 0x3290}, ++{0x2510, 0x3041}, ++{0x2510, 0x3042}, ++{0x2510, 0x2000}, ++{0x2510, 0x3110}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x3120}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x3282}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x32a0}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x881b}, ++{0x2510, 0x887f}, ++{0x2510, 0x2440}, ++{0x2510, 0x3260}, ++{0x2510, 0x3248}, ++{0x2510, 0xb095}, ++{0x2510, 0xf110}, ++{0x2510, 0xf864}, ++{0x2510, 0xf90d}, ++{0x2510, 0x32c2}, ++{0x2510, 0x30a0}, ++{0x2510, 0x3090}, ++{0x2510, 0x3088}, ++{0x2510, 0x2443}, ++{0x2510, 0x8058}, ++{0x2510, 0x3001}, ++{0x2510, 0x2202}, ++{0x2510, 0x885b}, ++{0x2510, 0x2442}, ++{0x2510, 0x3220}, ++{0x2510, 0x2003}, ++{0x2510, 0x8048}, ++{0x2510, 0x2001}, ++{0x2510, 0x884b}, ++{0x2510, 0x2441}, ++{0x2510, 0x30c2}, ++{0x2510, 0x2007}, ++{0x2510, 0x8008}, ++{0x2510, 0x2000}, ++{0x2510, 0x880b}, ++{0x2510, 0x2008}, ++{0x2510, 0x800a}, ++{0x2510, 0x200a}, ++{0x2510, 0x8002}, ++{0x2510, 0xa9a1}, ++{0x2510, 0xb094}, ++{0x2510, 0x2201}, ++{0x2510, 0x8803}, ++{0x2510, 0xa1c4}, ++{0x2510, 0x3044}, ++{0x2510, 0xb800}, ++{0x2510, 0xa004}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2201}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2201}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2201}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2201}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2400}, ++{0x2510, 0x2751}, ++{0x2510, 0x2423}, ++{0x2510, 0x2750}, ++{0x2510, 0x2421}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2749}, ++{0x2510, 0x2422}, ++{0x2510, 0x2749}, ++{0x2510, 0x2423}, ++{0x2510, 0x2709}, ++{0x2510, 0x2420}, ++{0x2510, 0x2729}, ++{0x2510, 0x2423}, ++{0x2510, 0x3242}, ++{0x2510, 0x2722}, ++{0x2510, 0x2422}, ++{0x2510, 0x2769}, ++{0x2510, 0x2421}, ++{0x2510, 0x2702}, ++{0x2510, 0x2421}, ++{0x2510, 0x3242}, ++{0x2510, 0x276a}, ++{0x2510, 0x2420}, ++{0x2510, 0x276a}, ++{0x2510, 0x2421}, ++{0x2510, 0x2703}, ++{0x2510, 0x2420}, ++{0x2510, 0x2703}, ++{0x2510, 0x2421}, ++{0x2510, 0x3242}, ++{0x2510, 0x276b}, ++{0x2510, 0x2420}, ++{0x2510, 0x276b}, ++{0x2510, 0x2421}, ++{0x2510, 0x2704}, ++{0x2510, 0x2420}, ++{0x2510, 0x2704}, ++{0x2510, 0x2421}, ++{0x2510, 0x3242}, ++{0x2510, 0x276c}, ++{0x2510, 0x2420}, ++{0x2510, 0x276c}, ++{0x2510, 0x2421}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2759}, ++{0x2510, 0x2422}, ++{0x2510, 0x2758}, ++{0x2510, 0x2420}, ++{0x2510, 0x2403}, ++{0x2510, 0x2712}, ++{0x2510, 0x3242}, ++{0x2510, 0x2422}, ++{0x2510, 0x271a}, ++{0x2510, 0x3242}, ++{0x2510, 0x2420}, ++{0x2510, 0x2702}, ++{0x2510, 0x2423}, ++{0x2510, 0x2759}, ++{0x2510, 0x2439}, ++{0x2510, 0x2758}, ++{0x2510, 0x243a}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2400}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x3250}, ++{0x2510, 0xc023}, ++{0x2510, 0x2402}, ++{0x2510, 0x2405}, ++{0x2510, 0x2789}, ++{0x2510, 0x242e}, ++{0x2510, 0x2788}, ++{0x2510, 0x242f}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x3250}, ++{0x2510, 0x27d8}, ++{0x2510, 0x2433}, ++{0x2510, 0x27d9}, ++{0x2510, 0x2434}, ++{0x2510, 0x3250}, ++{0x2510, 0xc023}, ++{0x2510, 0x2402}, ++{0x2510, 0xc023}, ++{0x2510, 0x2751}, ++{0x2510, 0x2423}, ++{0x2510, 0xc02b}, ++{0x2510, 0x2750}, ++{0x2510, 0x2421}, ++{0x2510, 0xc003}, ++{0x2510, 0x7fff}, ++{0x2510, 0x3250}, ++{0x2510, 0xc021}, ++{0x2510, 0x2400}, ++{0x2510, 0x2405}, ++{0x2510, 0xc062}, ++{0x2510, 0x3250}, ++{0x2510, 0x2400}, ++{0x2510, 0xc023}, ++{0x2510, 0x2751}, ++{0x2510, 0x2423}, ++{0x2510, 0xc02b}, ++{0x2510, 0x2750}, ++{0x2510, 0x2421}, ++{0x2510, 0xc003}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x3250}, ++{0x2510, 0xc0e3}, ++{0x2510, 0x2400}, ++{0x2510, 0x27b1}, ++{0x2510, 0x2437}, ++{0x2510, 0x3250}, ++{0x2510, 0xc02b}, ++{0x2510, 0x2422}, ++{0x2510, 0xc023}, ++{0x2510, 0x2751}, ++{0x2510, 0x2423}, ++{0x2510, 0xc02b}, ++{0x2510, 0x2750}, ++{0x2510, 0x2421}, ++{0x2510, 0xc003}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2404}, ++{0x2510, 0x2779}, ++{0x2510, 0x242c}, ++{0x2510, 0x2781}, ++{0x2510, 0x242d}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2791}, ++{0x2510, 0x2430}, ++{0x2510, 0x2799}, ++{0x2510, 0x2428}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x27a1}, ++{0x2510, 0x2430}, ++{0x2510, 0x27a9}, ++{0x2510, 0x2428}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xc165}, ++{0x2510, 0x2415}, ++{0x2510, 0xc026}, ++{0x2510, 0x2407}, ++{0x2510, 0xc027}, ++{0x2510, 0x2406}, ++{0x2510, 0x2296}, ++{0x2510, 0x2416}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xc167}, ++{0x2510, 0x2400}, ++{0x2510, 0xc067}, ++{0x2510, 0x2406}, ++{0x2510, 0x2416}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xb800}, ++{0x2510, 0x8058}, ++{0x2510, 0xa005}, ++{0x2510, 0x3101}, ++{0x2510, 0x3041}, ++{0x2510, 0x3104}, ++{0x2510, 0xb035}, ++{0x2510, 0xb075}, ++{0x2510, 0x30c1}, ++{0x2510, 0x3102}, ++{0x2510, 0x3041}, ++{0x2510, 0xb808}, ++{0x2510, 0x3202}, ++{0x2510, 0xb848}, ++{0x2510, 0xb84c}, ++{0x2510, 0x2201}, ++{0x2510, 0xb377}, ++{0x2510, 0x8843}, ++{0x2510, 0x916f}, ++{0x2510, 0x2201}, ++{0x2510, 0xb84e}, ++{0x2510, 0xf905}, ++{0x2510, 0xf907}, ++{0x2510, 0x2200}, ++{0x2510, 0x885b}, ++{0x2510, 0xa898}, ++{0x2510, 0xa8d8}, ++{0x2510, 0xf8e8}, ++{0x2510, 0x80d8}, ++{0x2510, 0x9007}, ++{0x2510, 0x916f}, ++{0x2510, 0x2206}, ++{0x2510, 0xb808}, ++{0x2510, 0xc800}, ++{0x2510, 0xe809}, ++{0x2510, 0x88db}, ++{0x2510, 0xf8a8}, ++{0x2510, 0xf888}, ++{0x2510, 0x2203}, ++{0x2510, 0xb07b}, ++{0x2510, 0x2000}, ++{0x2510, 0x80c8}, ++{0x2510, 0x8088}, ++{0x2510, 0x220b}, ++{0x2510, 0xb06a}, ++{0x2510, 0x88cb}, ++{0x2510, 0x888b}, ++{0x2510, 0x2224}, ++{0x2510, 0xb04a}, ++{0x2510, 0x2218}, ++{0x2510, 0x210d}, ++{0x2510, 0x2108}, ++{0x2510, 0x902f}, ++{0x2510, 0xb04b}, ++{0x2510, 0xf880}, ++{0x2510, 0x2211}, ++{0x2510, 0x2205}, ++{0x2510, 0x2204}, ++{0x2510, 0xb043}, ++{0x2510, 0xa8c9}, ++{0x2510, 0x31c1}, ++{0x2510, 0x80a8}, ++{0x2510, 0x2205}, ++{0x2510, 0x916f}, ++{0x2510, 0x2104}, ++{0x2510, 0x88ab}, ++{0x2510, 0x2440}, ++{0x2510, 0xf110}, ++{0x2510, 0xf804}, ++{0x2510, 0x2000}, ++{0x2510, 0x8088}, ++{0x2510, 0x3002}, ++{0x2510, 0xb838}, ++{0x2510, 0xa8c8}, ++{0x2510, 0xb04b}, ++{0x2510, 0x2442}, ++{0x2510, 0x3210}, ++{0x2510, 0x2206}, ++{0x2510, 0x888b}, ++{0x2510, 0x2441}, ++{0x2510, 0x3202}, ++{0x2510, 0xf880}, ++{0x2510, 0xb830}, ++{0x2510, 0xc801}, ++{0x2510, 0x30c2}, ++{0x2510, 0xe80c}, ++{0x2510, 0x2201}, ++{0x2510, 0xb04a}, ++{0x2510, 0x2227}, ++{0x2510, 0x2205}, ++{0x2510, 0x3241}, ++{0x2510, 0x2207}, ++{0x2510, 0x902f}, ++{0x2510, 0x220e}, ++{0x2510, 0x2205}, ++{0x2510, 0x2204}, ++{0x2510, 0xb042}, ++{0x2510, 0xa8c9}, ++{0x2510, 0xb043}, ++{0x2510, 0x31c1}, ++{0x2510, 0x916f}, ++{0x2510, 0x2009}, ++{0x2510, 0xa004}, ++{0x2510, 0x7fff}, ++{0x2510, 0x30c2}, ++{0x2510, 0xa9a0}, ++{0x2510, 0xb094}, ++{0x2510, 0x2201}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xb980}, ++{0x2510, 0x3260}, ++{0x2510, 0x3101}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x3102}, ++{0x2510, 0x3041}, ++{0x2510, 0x8038}, ++{0x2510, 0x220a}, ++{0x2510, 0x881b}, ++{0x2510, 0x883b}, ++{0x2510, 0x2440}, ++{0x2510, 0xb095}, ++{0x2510, 0xf110}, ++{0x2510, 0xf864}, ++{0x2510, 0xf90d}, ++{0x2510, 0x8018}, ++{0x2510, 0x3004}, ++{0x2510, 0x2202}, ++{0x2510, 0x2442}, ++{0x2510, 0x883b}, ++{0x2510, 0x3220}, ++{0x2510, 0x2004}, ++{0x2510, 0x881b}, ++{0x2510, 0x2441}, ++{0x2510, 0x30c2}, ++{0x2510, 0xa9a0}, ++{0x2510, 0xb094}, ++{0x2510, 0x2201}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xa005}, ++{0x2510, 0xc800}, ++{0x2510, 0xe802}, ++{0x2510, 0x31c1}, ++{0x2510, 0x2440}, ++{0x2510, 0x2442}, ++{0x2510, 0xc801}, ++{0x2510, 0x30c2}, ++{0x2510, 0x31c1}, ++{0x2510, 0xa044}, ++{0x2510, 0x3044}, ++{0x2510, 0x2000}, ++{0x2510, 0xa004}, ++{0x2510, 0x2000}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2703}, ++{0x2510, 0x3242}, ++{0x2510, 0x2438}, ++{0x2510, 0x2703}, ++{0x2510, 0x243b}, ++{0x2510, 0x2704}, ++{0x2510, 0x3242}, ++{0x2510, 0x2438}, ++{0x2510, 0x2704}, ++{0x2510, 0x243b}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2703}, ++{0x2510, 0x3242}, ++{0x2510, 0x2420}, ++{0x2510, 0x2703}, ++{0x2510, 0x2421}, ++{0x2510, 0x2704}, ++{0x2510, 0x3242}, ++{0x2510, 0x2420}, ++{0x2510, 0x2704}, ++{0x2510, 0x2421}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xb095}, ++{0x2510, 0xf110}, ++{0x2510, 0xf864}, ++{0x2510, 0xf90d}, ++{0x2510, 0x3001}, ++{0x2510, 0x2442}, ++{0x2510, 0x30c2}, ++{0x2510, 0xa9a0}, ++{0x2510, 0xb094}, ++{0x2510, 0xb800}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0x3426}, ++{0x2510, 0x3614}, ++{AR0233_DELAY, 100}, ++#endif /* Sequence_hidy_ar0233_REV2_V13 */ ++ ++#ifdef Pre_hdr_gain_enable ++{0x3110, 0x0011}, ++#endif /* Pre_hdr_gain_enable */ ++ ++#ifdef Tempsensor_init ++{0x3E94, 0x3007}, ++{0x3E6E, 0xE200}, ++{0x3E98, 0x1000}, ++{0x3F92, 0x4C00}, ++{0x30B8, 0x000B}, ++{0x30B8, 0x0003}, ++#endif /* Tempsensor_init */ ++ ++{0x3364, 0x0766}, //14.8 ++#endif /* O1_Recommended_Defaults_LFM_HDR */ ++ ++#ifdef disable_embed_data_stat ++{0x3064, 0x0}, // Disable embedded data and stat ++#endif /* disable_embed_data_stat */ ++ ++#ifdef HDR_3exp_12bit ++{0x3082, 0x8}, //num_exp = 3 ++{0x30BA, 0x1122}, //num_exp_max =3 ++{0x31AC, 0x140C}, //12 bit output ++#endif /* HDR_3exp_12bit */ ++ ++#ifdef pll_27_124p5_4lane_12b ++// serial_data_rate was *2 in REV1. but not in REV2 ++{0x3030, 0x53}, //PLL_MULTIPLIER ++{0x302E, 0x3}, //PRE_PLL_CLK_DIV ++{0x302C, 0x701}, //P1 divider (vt_sys_clk_div) ++{0x302A, 0x6}, //P2 divider (vt_pix_clk_div) ++{0x3038, 0x2}, //P3 divider (op_sys_clk_div) ++{0x3036, 0x6}, //P4 divider (op_word_clk_div) ++{0x31DC, 0x1FB0}, //vcodiv ++#endif /* pll_27_124p5_4lane_12b */ ++ ++#ifdef mipi_124p5_12bit_4lane ++{0x31AE, 0x204}, //serial type and lane ++{0x31B0, 0x67}, //frame_preamble ++{0x31B2, 0x30}, //line_preamble ++{0x31B4, 0x22CC}, //mipi_timing_0 ++{0x31B6, 0x33D3}, //mipi_timing_1 ++{0x31B8, 0xB04D}, //mipi_timing_2 ++{0x31BA, 0x411}, //mipi_timing_3 ++{0x31BC, 0x940E}, //mipi_timing_4 ++#endif /* mipi_124p5_12bit_4lane */ ++ ++#ifdef pll_27_108_4lane_12b ++// serial_data_rate was *2 in REV1. but not in REV2 ++/* PCLK=27Mhz/PRE_PLL_CLK_DIV *PLL_MULTIPLIER /P1 /P4 */ ++/* PCLK=27Mhz/0x3 *0x48/1/6= 108Mhz - TI serializers */ ++{0x3030, 0x48}, //PLL_MULTIPLIER ++{0x302E, 0x3}, //PRE_PLL_CLK_DIV ++{0x302C, 0x701}, //P1 divider (vt_sys_clk_div) ++{0x302A, 0x6}, //P2 divider (vt_pix_clk_div) ++{0x3038, 0x2}, //P3 divider (op_sys_clk_div) ++{0x3036, 0x6}, //P4 divider (op_word_clk_div) ++{0x31DC, 0x1FB0}, //vcodiv ++#endif /* pll_27_108_4lane_12b */ ++ ++#ifdef mipi_108_12bit_4lane ++{0x31AE, 0x204}, //MIPI_enable ++{0x31B0, 0x67}, //frame_preamble ++{0x31B2, 0x30}, //line_preamble ++{0x31B4, 0x22CC}, //mipi_timing_0 ++{0x31B6, 0x33D3}, //mipi_timing_1 ++{0x31B8, 0xB04D}, //mipi_timing_2 ++{0x31BA, 0x411}, //mipi_timing_3 ++{0x31BC, 0x940E}, //mipi_timing_4 ++#endif /* mipi_108_12bit_4lane */ ++ ++#ifdef MIPI_DT_bit12 ++{0x3342, 0x122C}, // MIPI_F1_PDT_EDT ++{0x3346, 0x122C}, // MIPI_F2_PDT_EDT ++{0x334A, 0x122C}, // MIPI_F3_PDT_EDT ++{0x334E, 0x122C}, // MIPI_F4_PDT_EDT ++#endif /* MIPI_DT_bit12 */ ++ ++#ifdef LUT_24_to_12 ++{0x31AC, 0x180C}, ++{0x31D0, 0x01}, //companding ++{0x33DA, 0}, ++{0x33C0, 0x2000}, //LUT_00 ++{0x33C2, 0x3450}, ++{0x33C4, 0x48A0}, ++{0x33C6, 0x5CF0}, ++{0x33C8, 0x7140}, ++{0x33CA, 0x8590}, ++{0x33CC, 0x99E0}, ++{0x33CE, 0xAE30}, ++{0x33D0, 0xC280}, ++{0x33D2, 0xD6D0}, ++{0x33D4, 0xEB20}, ++{0x33D6, 0xFF70}, ++{0x33F4, 0xFF70}, ++{0x33F6, 0xFF70}, ++{0x33F8, 0xFF70}, ++{0x33FA, 0xFF70}, //LUT_15 ++#endif /* LUT_24_to_12 */ ++ ++/* resolution */ ++{0x3004, AR0233_X_START}, // X_ADDR_START_ ++{0x3008, AR0233_X_END}, // X_ADDR_END_ ++{0x3002, AR0233_Y_START}, // Y_ADDR_START_ ++{0x3006, AR0233_Y_END}, // Y_ADDR_END_ ++ ++{0x3044, 0x0400}, //Dark_control ++ ++#ifdef HDR_ratio_gain_default ++{0x3362, 0x000F}, //HCG ++{0x3366, 0x1111}, //1x ++{0x3238, 0x0444}, // Ratio 16x, Use retio setting ++#endif /* HDR_ratio_gain_default */ ++ ++// FPS = 124.5MHz / reg0x300A / reg0x300C * (DES_REF_XTAL/27MHz) ++{0x300A, AR0233_SENSOR_HEIGHT + 100}, // Frame_length_Lines ++{0x300C, AR0233_SENSOR_WIDTH + 400}, // Line_length_pck ++{0x3012, 0x144}, //Integration_time ++ ++#ifdef Enable_trigger_input ++{0x340A, 0x0070}, // GPIO_CONTROL1: GPIO1 is trigger ++{0x340C, 0x0080}, // GPIO_CONTROL2: GPIO1 is trigger ++{0x30CE, 0x0120}, // TRIGGER_MODE ++//{0x30DC, 0x0120}, // TRIGGER_DELAY ++{0x301A, 0x0118}, // GPI pins enable ++#endif /* Enable_trigger_input */ ++}; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0140-lvds-ti9x4-fix-remote-gpio-enablement-for-4-cams.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0140-lvds-ti9x4-fix-remote-gpio-enablement-for-4-cams.patch new file mode 100644 index 00000000..9aae7cb4 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0140-lvds-ti9x4-fix-remote-gpio-enablement-for-4-cams.patch @@ -0,0 +1,81 @@ +From f07aa0200ffd820fdceb9a06816927d81071cc61 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Sun, 6 Jan 2019 18:18:23 +0300 +Subject: [PATCH 089/122] lvds: ti9x4: fix remote gpio enablement for 4 cams + +This fix enablemnet of remote gpio (ti953) on all 4 cams + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ti9x4.c | 39 ++++++++++++++++++++---------------- + 1 file changed, 22 insertions(+), 17 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ti9x4.c b/drivers/media/i2c/soc_camera/ti9x4.c +index f0b782f..7b8209b 100644 +--- a/drivers/media/i2c/soc_camera/ti9x4.c ++++ b/drivers/media/i2c/soc_camera/ti9x4.c +@@ -279,8 +279,7 @@ static int ti9x4_initialize(struct i2c_client *client) + { + struct ti9x4_priv *priv = i2c_get_clientdata(client); + int idx, timeout; +- u8 port_sts1 = 0, port_sts2 = 0; +- int tmp_addr; ++ u8 port_sts1[4] = {0, 0, 0, 0}, port_sts2[4] = {0, 0, 0, 0}; + + dev_info(&client->dev, "LINKs=%d, LANES=%d, FORWARDING=%s, CABLE=%s, ID=%s\n", + priv->links, priv->lanes, priv->forwarding_mode, priv->is_coax ? "coax" : "stp", priv->chip_id); +@@ -301,30 +300,36 @@ static int ti9x4_initialize(struct i2c_client *client) + /* check lock status */ + for (timeout = 500 / priv->links; timeout > 0; timeout--) { + for (idx = 0; idx < priv->links; idx++) { ++ if ((port_sts1[idx] & 0x1) && (port_sts2[idx] & 0x4)) ++ continue; ++ + reg8_write(client, 0x4c, (idx << 4) | (1 << idx)); /* Select RX port number */ + usleep_range(1000, 1500); /* wait 1ms */ +- reg8_read(client, 0x4d, &port_sts1); /* Lock status */ +- reg8_read(client, 0x4e, &port_sts2); /* Freq stable */ +- +- if (port_sts1 & 0x1) { +- tmp_addr = client->addr; +- client->addr = priv->ti9x3_addr_map[idx]; /* TI9X3 I2C addr */ +- reg8_write(client, 0x0d, 0xf0); /* Enable all remote GPIOs */ +- reg8_write(client, 0x0e, 0xf0); /* Enable serializer GPIOs */ +- client->addr = tmp_addr; +- } +- +- if ((port_sts1 & 0x1) && (port_sts2 & 0x4)) +- goto out; ++ reg8_read(client, 0x4d, &port_sts1[idx]); /* Lock status */ ++ reg8_read(client, 0x4e, &port_sts2[idx]); /* Freq stable */ + } + } + + if (!timeout) +- dev_info(&client->dev, "Receiver is not locked\n"); +-out: ++ dev_info(&client->dev, "Receiver lock status [%d,%d,%d,%d]\n", ++ (port_sts1[0] & 0x1) && (port_sts2[0] & 0x4), ++ (port_sts1[1] & 0x1) && (port_sts2[1] & 0x4), ++ (port_sts1[2] & 0x1) && (port_sts2[2] & 0x4), ++ (port_sts1[3] & 0x1) && (port_sts2[3] & 0x4)); ++ + if (priv->poc_delay) + mdelay(100); + ++ for (idx = 0; idx < priv->links; idx++) { ++ reg8_write(client, 0x4c, (idx << 4) | (1 << idx)); /* Select RX port number */ ++ usleep_range(1000, 1500); /* wait 1ms */ ++ ++ client->addr = priv->ti9x3_addr_map[idx]; /* TI9X3 I2C addr */ ++ reg8_write(client, 0x0d, 0xf0); /* Enable all remote GPIOs */ ++ reg8_write(client, 0x0e, 0xf0); /* Enable serializer GPIOs */ ++ client->addr = priv->des_addr; ++ } ++ + return 0; + } + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0141-media-soc_camera-imx390-Add-new-V4L-controls.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0141-media-soc_camera-imx390-Add-new-V4L-controls.patch new file mode 100644 index 00000000..ae3d3733 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0141-media-soc_camera-imx390-Add-new-V4L-controls.patch @@ -0,0 +1,122 @@ +From 4f8c6f74c5b107277a269ab559dabcb3ab574da8 Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Thu, 10 Jan 2019 18:15:44 +0300 +Subject: [PATCH 090/122] media: soc_camera: imx390: Add new V4L controls + +Add vertical and horizontal flips and digital and analog gains support. +--- + drivers/media/i2c/soc_camera/imx390.c | 62 +++++++++++++++++++++++++++++++---- + 1 file changed, 56 insertions(+), 6 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/imx390.c b/drivers/media/i2c/soc_camera/imx390.c +index fc73b4b..1834195 100644 +--- a/drivers/media/i2c/soc_camera/imx390.c ++++ b/drivers/media/i2c/soc_camera/imx390.c +@@ -249,6 +249,7 @@ static int imx390_s_ctrl(struct v4l2_ctrl *ctrl) + struct imx390_priv *priv = to_imx390(client); + int ret = -EINVAL; + int val; ++ uint8_t val8; + + if (!priv->init_complete) + return 0; +@@ -264,11 +265,29 @@ static int imx390_s_ctrl(struct v4l2_ctrl *ctrl) + break; + case V4L2_CID_GAIN: + /* Digital gain */ +- ret = 0; ++ /* Set PGA_GAIN_SP1H as Normal SP1 HCG mode is configured in wizard */ ++ val8 = ctrl->val & 0xff; ++ ret = reg16_write(client, 0x24, val8); ++#if 0 // stubs for other normal modes and HDR ++ /* Set PGA_GAIN_SP1L as Normal SP1 LCG mode is configured in wizard */ ++ val8 = ctrl->val & 0xff; ++ ret = reg16_write(client, 0x26, val8); ++ ++ /* Set PGA_GAIN_SP2 as Normal SP2 mode is configured in wizard */ ++ val8 = ctrl->val & 0xff; ++ ret = reg16_write(client, 0x28, val8); ++#endif + break; + case V4L2_CID_ANALOGUE_GAIN: + /* Analog gain */ +- ret = 0; ++ /* Set AGAIN_SP1H as Normal SP1 HCG mode is configured in wizard */ ++ val8 = ctrl->val & 0xff; ++ ret = reg16_write(client, 0x18, val8); ++#if 0 // stubs for other normal modes and HDR ++ /* Set AGAIN_SP1L as Normal SP1 LCG mode is configured in wizard */ ++ val8 = ctrl->val & 0xff; ++ ret = reg16_write(client, 0x1A, val8); ++#endif + break; + case V4L2_CID_EXPOSURE: + val = 0xfff - ctrl->val; +@@ -277,7 +296,38 @@ static int imx390_s_ctrl(struct v4l2_ctrl *ctrl) + // ret |= reg16_write(client, 0x0e, ctrl->val >> 16); /* MSB */ + break; + case V4L2_CID_HFLIP: ++ /* hflip */ ++ ret = reg16_read(client, 0x74, &val8); ++ if (ctrl->val) ++ val8 |= (1 << 1); ++ else ++ val8 &= ~(1 << 1); ++ ret |= reg16_write(client, 0x74, val8); ++ ++ /* hflip app lock */ ++ ret = reg16_read(client, 0x3c0, &val8); ++ if (ctrl->val) ++ val8 |= (1 << 3); ++ else ++ val8 &= ~(1 << 3); ++ ret |= reg16_write(client, 0x3c0, val8); ++ break; + case V4L2_CID_VFLIP: ++ /* vflip */ ++ ret = reg16_read(client, 0x74, &val8); ++ if (ctrl->val) ++ val8 |= (1 << 0); ++ else ++ val8 &= ~(1 << 0); ++ ret |= reg16_write(client, 0x74, val8); ++ ++ /* vflip app lock */ ++ ret = reg16_read(client, 0x3c0, &val8); ++ if (ctrl->val) ++ val8 |= (1 << 2); ++ else ++ val8 &= ~(1 << 2); ++ ret |= reg16_write(client, 0x3c0, val8); + break; + } + +@@ -452,7 +502,7 @@ static int imx390_probe(struct i2c_client *client, + priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; + + priv->exposure = 0x100; +- priv->gain = 0x100; ++ priv->gain = 0; + priv->autogain = 1; + v4l2_ctrl_handler_init(&priv->hdl, 4); + v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, +@@ -470,13 +520,13 @@ static int imx390_probe(struct i2c_client *client, + v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, + V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); + v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, +- V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); ++ V4L2_CID_GAIN, 0, 140, 1, priv->gain); + v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, +- V4L2_CID_ANALOGUE_GAIN, 1, 0xe, 1, 0x7); ++ V4L2_CID_ANALOGUE_GAIN, 0, 100, 1, 0x15); + v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, + V4L2_CID_EXPOSURE, 0, 0xff0, 1, 0xfff - 0x2f2); + v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, +- V4L2_CID_HFLIP, 0, 1, 1, 1); ++ V4L2_CID_HFLIP, 0, 1, 1, 0); + v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, + V4L2_CID_VFLIP, 0, 1, 1, 0); + priv->sd.ctrl_handler = &priv->hdl; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0142-lvds-AR233-add-rev1-silion-setup.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0142-lvds-AR233-add-rev1-silion-setup.patch new file mode 100644 index 00000000..7600e6d6 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0142-lvds-AR233-add-rev1-silion-setup.patch @@ -0,0 +1,1788 @@ +From 7b5b06aaf1f0d1551096b39418bf0b77d1dcf658 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Wed, 9 Jan 2019 04:38:34 +0300 +Subject: [PATCH 091/122] lvds: AR233: add rev1 silion setup + +Add silicon rev1 for AR0233 imager + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ar0233.c | 19 +- + drivers/media/i2c/soc_camera/ar0233.h | 392 +-------- + drivers/media/i2c/soc_camera/ar0233_rev1.h | 1258 ++++++++++++++++++++++++++++ + drivers/media/i2c/soc_camera/ar0233_rev2.h | 21 - + 4 files changed, 1280 insertions(+), 410 deletions(-) + create mode 100644 drivers/media/i2c/soc_camera/ar0233_rev1.h + +diff --git a/drivers/media/i2c/soc_camera/ar0233.c b/drivers/media/i2c/soc_camera/ar0233.c +index 2a0b7aa..19386bb 100644 +--- a/drivers/media/i2c/soc_camera/ar0233.c ++++ b/drivers/media/i2c/soc_camera/ar0233.c +@@ -20,11 +20,12 @@ + #include + #include + +-#include "ar0233_rev2.h" ++#include "ar0233.h" + + static const int ar0233_i2c_addr[] = {0x10, 0x20}; + + #define AR0233_PID 0x3000 ++#define AR0233_REV 0x300E + #define AR0233_VERSION_REG 0x0956 + + #define AR0233_MEDIA_BUS_FMT MEDIA_BUS_FMT_SGRBG12_1X12 +@@ -377,7 +378,7 @@ static int ar0233_initialize(struct i2c_client *client) + { + struct ar0233_priv *priv = to_ar0233(client); + u16 val = 0; +- u16 pid = 0; ++ u16 pid = 0, rev = 0; + int ret = 0; + int tmp_addr; + int i; +@@ -404,18 +405,26 @@ static int ar0233_initialize(struct i2c_client *client) + goto err; + } + ++ /* check revision */ ++ reg16_read16(client, AR0233_REV, &rev); + /* Read OTP IDs */ + ar0233_otp_id_read(client); + /* Program wizard registers */ +- ar0233_set_regs(client, ar0233_regs_wizard_rev2, ARRAY_SIZE(ar0233_regs_wizard_rev2)); ++ switch (rev) { ++ case 0x2015: ++ ar0233_set_regs(client, ar0233_regs_wizard_rev2, ARRAY_SIZE(ar0233_regs_wizard_rev2)); ++ break; ++ default: ++ ar0233_set_regs(client, ar0233_regs_wizard_rev1, ARRAY_SIZE(ar0233_regs_wizard_rev1)); ++ } + + /* Enable stream */ + reg16_read16(client, 0x301a, &val); // read inital reset_register value + val |= (1 << 2); // Set streamOn bit + reg16_write16(client, 0x301a, val); // Start Streaming + +- dev_info(&client->dev, "ar0233 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", +- pid, AR0233_MAX_WIDTH, AR0233_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++ dev_info(&client->dev, "ar0233 PID %x (rev %x), res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, rev, AR0233_MAX_WIDTH, AR0233_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); + err: + return ret; + } +diff --git a/drivers/media/i2c/soc_camera/ar0233.h b/drivers/media/i2c/soc_camera/ar0233.h +index ad65390..f6ba245 100644 +--- a/drivers/media/i2c/soc_camera/ar0233.h ++++ b/drivers/media/i2c/soc_camera/ar0233.h +@@ -1,7 +1,7 @@ + /* +- * ON Semiconductor AR0233 sensor camera wizard 1920x1080@30/BGGR/MIPI ++ * ON Semiconductor AR0233 sensor camera wizard 2048x1280@30/BGGR/MIPI + * +- * Copyright (C) 2018 Cogent Embedded, Inc. ++ * Copyright (C) 2019 Cogent Embedded, Inc. + * + * 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 +@@ -12,13 +12,13 @@ + //#define AR0233_DISPLAY_PATTERN_FIXED + //#define AR0233_DISPLAY_PATTERN_COLOR_BAR + +-#define AR0233_MAX_WIDTH 1920 +-#define AR0233_MAX_HEIGHT 1200 ++#define AR0233_MAX_WIDTH 2048 ++#define AR0233_MAX_HEIGHT 1280 + + #define AR0233_DELAY 0xffff + +-#define AR0233_SENSOR_WIDTH 1920 +-#define AR0233_SENSOR_HEIGHT 1200 ++#define AR0233_SENSOR_WIDTH 2058 ++#define AR0233_SENSOR_HEIGHT 1284 + + #define AR0233_X_START ((AR0233_SENSOR_WIDTH - AR0233_MAX_WIDTH) / 2) + #define AR0233_Y_START ((AR0233_SENSOR_HEIGHT - AR0233_MAX_HEIGHT) / 2) +@@ -30,381 +30,5 @@ struct ar0233_reg { + u16 val; + }; + +-static const struct ar0233_reg ar0233_regs_wizard[] = { +-{0x301A, 0x0018}, // RESET_REGISTER +-{AR0233_DELAY, 500}, // Wait 500ms +-{0x3070, 0x0000}, // 1: Solid color test pattern, +- // 2: Full color bar test pattern, +- // 3: Fade to grey color bar test pattern, +- //256: Walking 1 test pattern (12 bit) +-{0x3072, 0x0123}, // R +-{0x3074, 0x0456}, // G(GR row) +-{0x3076, 0x0abc}, // B +-{0x3078, 0x0def}, // G(GB row) +-#ifdef AR0233_DISPLAY_PATTERN_FIXED +-{0x3070, 0x0001}, +-#endif +-#ifdef AR0233_DISPLAY_PATTERN_COLOR_BAR +-{0x3070, 0x0002}, +-#endif +-{AR0233_DELAY, 100}, // Wait 100ms +- +-{0x3092, 0x0C24}, +-{0x337A, 0x0C80}, +-{0x3520, 0x1288}, +-{0x3522, 0x880C}, +-{0x3524, 0x0C12}, +-{0x352C, 0x1212}, +-{0x354A, 0x007F}, +-{0x350C, 0x0568}, +-{0x3506, 0x3333}, +-{0x3508, 0x3333}, +-{0x3100, 0x4000}, +-{0x3280, 0x0FA0}, +-{0x3282, 0x0FA0}, +-{0x3284, 0x0FA0}, +-{0x3286, 0x0FA0}, +-{0x3288, 0x0FA0}, +-{0x328A, 0x0FA0}, +-{0x328C, 0x0FA0}, +-{0x328E, 0x0FA0}, +-{0x3290, 0x0FA0}, +-{0x3292, 0x0FA0}, +-{0x3294, 0x0FA0}, +-{0x3296, 0x0FA0}, +-{0x3298, 0x0FA0}, +-{0x329A, 0x0FA0}, +-{0x329C, 0x0FA0}, +-{0x329E, 0x0FA0}, +- +-{AR0233_DELAY, 200}, // Wait 200ms +- +-{0x2512, 0x8000}, +-{0x2510, 0x0905}, +-{0x2510, 0x3350}, +-{0x2510, 0x2004}, +-{0x2510, 0x1460}, +-{0x2510, 0x1578}, +-{0x2510, 0x0901}, +-{0x2510, 0x7B24}, +-{0x2510, 0xFF24}, +-{0x2510, 0xFF24}, +-{0x2510, 0xEA24}, +-{0x2510, 0x1022}, +-{0x2510, 0x2410}, +-{0x2510, 0x155A}, +-{0x2510, 0x0901}, +-{0x2510, 0x1400}, +-{0x2510, 0x24FF}, +-{0x2510, 0x24FF}, +-{0x2510, 0x24EA}, +-{0x2510, 0x2324}, +-{0x2510, 0x647A}, +-{0x2510, 0x2404}, +-{0x2510, 0x052C}, +-{0x2510, 0x400A}, +-{0x2510, 0xFF0A}, +-{0x2510, 0xFF0A}, +-{0x2510, 0x1008}, +-{0x2510, 0x3851}, +-{0x2510, 0x1440}, +-{0x2510, 0x0004}, +-{0x2510, 0x0801}, +-{0x2510, 0x0408}, +-{0x2510, 0x1180}, +-{0x2510, 0x2652}, +-{0x2510, 0x1518}, +-{0x2510, 0x0906}, +-{0x2510, 0x1348}, +-{0x2510, 0x1002}, +-{0x2510, 0x1016}, +-{0x2510, 0x1181}, +-{0x2510, 0x1189}, +-{0x2510, 0x1056}, +-{0x2510, 0x1210}, +-{0x2510, 0x0901}, +-{0x2510, 0x0D09}, +-{0x2510, 0x1413}, +-{0x2510, 0x8809}, +-{0x2510, 0x2B15}, +-{0x2510, 0x8809}, +-{0x2510, 0x0311}, +-{0x2510, 0xD909}, +-{0x2510, 0x1214}, +-{0x2510, 0x4109}, +-{0x2510, 0x0312}, +-{0x2510, 0x1409}, +-{0x2510, 0x0110}, +-{0x2510, 0xD612}, +-{0x2510, 0x1012}, +-{0x2510, 0x1212}, +-{0x2510, 0x1011}, +-{0x2510, 0xDD11}, +-{0x2510, 0xD910}, +-{0x2510, 0x5609}, +-{0x2510, 0x1511}, +-{0x2510, 0xDB09}, +-{0x2510, 0x1511}, +-{0x2510, 0x9B09}, +-{0x2510, 0x0F11}, +-{0x2510, 0xBB12}, +-{0x2510, 0x1A12}, +-{0x2510, 0x1014}, +-{0x2510, 0x6012}, +-{0x2510, 0x5010}, +-{0x2510, 0x7610}, +-{0x2510, 0xE609}, +-{0x2510, 0x0812}, +-{0x2510, 0x4012}, +-{0x2510, 0x6009}, +-{0x2510, 0x290B}, +-{0x2510, 0x0904}, +-{0x2510, 0x1440}, +-{0x2510, 0x0923}, +-{0x2510, 0x15C8}, +-{0x2510, 0x13C8}, +-{0x2510, 0x092C}, +-{0x2510, 0x1588}, +-{0x2510, 0x1388}, +-{0x2510, 0x0C09}, +-{0x2510, 0x0C14}, +-{0x2510, 0x4109}, +-{0x2510, 0x1112}, +-{0x2510, 0x6212}, +-{0x2510, 0x6011}, +-{0x2510, 0xBF11}, +-{0x2510, 0xBB10}, +-{0x2510, 0x6611}, +-{0x2510, 0xFB09}, +-{0x2510, 0x3511}, +-{0x2510, 0xBB12}, +-{0x2510, 0x6312}, +-{0x2510, 0x6014}, +-{0x2510, 0x0015}, +-{0x2510, 0x0011}, +-{0x2510, 0xB812}, +-{0x2510, 0xA012}, +-{0x2510, 0x0010}, +-{0x2510, 0x2610}, +-{0x2510, 0x0013}, +-{0x2510, 0x0011}, +-{0x2510, 0x0008}, +-{0x2510, 0x3053}, +-{0x2510, 0x4215}, +-{0x2510, 0x4013}, +-{0x2510, 0x4010}, +-{0x2510, 0x0210}, +-{0x2510, 0x1611}, +-{0x2510, 0x8111}, +-{0x2510, 0x8910}, +-{0x2510, 0x5612}, +-{0x2510, 0x1009}, +-{0x2510, 0x010D}, +-{0x2510, 0x0815}, +-{0x2510, 0xC015}, +-{0x2510, 0xD013}, +-{0x2510, 0x5009}, +-{0x2510, 0x1313}, +-{0x2510, 0xD009}, +-{0x2510, 0x0215}, +-{0x2510, 0xC015}, +-{0x2510, 0xC813}, +-{0x2510, 0xC009}, +-{0x2510, 0x0515}, +-{0x2510, 0x8813}, +-{0x2510, 0x8009}, +-{0x2510, 0x0213}, +-{0x2510, 0x8809}, +-{0x2510, 0x0411}, +-{0x2510, 0xC909}, +-{0x2510, 0x0814}, +-{0x2510, 0x0109}, +-{0x2510, 0x0B11}, +-{0x2510, 0xD908}, +-{0x2510, 0x1400}, +-{0x2510, 0x091A}, +-{0x2510, 0x1440}, +-{0x2510, 0x0903}, +-{0x2510, 0x1214}, +-{0x2510, 0x0901}, +-{0x2510, 0x10D6}, +-{0x2510, 0x1210}, +-{0x2510, 0x1212}, +-{0x2510, 0x1210}, +-{0x2510, 0x11DD}, +-{0x2510, 0x11D9}, +-{0x2510, 0x1056}, +-{0x2510, 0x0917}, +-{0x2510, 0x11DB}, +-{0x2510, 0x0913}, +-{0x2510, 0x11FB}, +-{0x2510, 0x0905}, +-{0x2510, 0x11BB}, +-{0x2510, 0x121A}, +-{0x2510, 0x1210}, +-{0x2510, 0x1460}, +-{0x2510, 0x1250}, +-{0x2510, 0x1076}, +-{0x2510, 0x10E6}, +-{0x2510, 0x0901}, +-{0x2510, 0x15A8}, +-{0x2510, 0x0901}, +-{0x2510, 0x13A8}, +-{0x2510, 0x1240}, +-{0x2510, 0x1260}, +-{0x2510, 0x0925}, +-{0x2510, 0x13AD}, +-{0x2510, 0x0902}, +-{0x2510, 0x0907}, +-{0x2510, 0x1588}, +-{0x2510, 0x0901}, +-{0x2510, 0x138D}, +-{0x2510, 0x0B09}, +-{0x2510, 0x0914}, +-{0x2510, 0x4009}, +-{0x2510, 0x0B13}, +-{0x2510, 0x8809}, +-{0x2510, 0x1C0C}, +-{0x2510, 0x0920}, +-{0x2510, 0x1262}, +-{0x2510, 0x1260}, +-{0x2510, 0x11BF}, +-{0x2510, 0x11BB}, +-{0x2510, 0x1066}, +-{0x2510, 0x090A}, +-{0x2510, 0x11FB}, +-{0x2510, 0x093B}, +-{0x2510, 0x11BB}, +-{0x2510, 0x1263}, +-{0x2510, 0x1260}, +-{0x2510, 0x1400}, +-{0x2510, 0x1508}, +-{0x2510, 0x11B8}, +-{0x2510, 0x12A0}, +-{0x2510, 0x1200}, +-{0x2510, 0x1026}, +-{0x2510, 0x1000}, +-{0x2510, 0x1300}, +-{0x2510, 0x1100}, +-{0x2510, 0x437A}, +-{0x2510, 0x0609}, +-{0x2510, 0x0B05}, +-{0x2510, 0x0708}, +-{0x2510, 0x4137}, +-{0x2510, 0x502C}, +-{0x2510, 0x2CFE}, +-{0x2510, 0x15FE}, +-{0x2510, 0x0C2C}, +-{0x32E6, 0x00E0}, +-{0x1008, 0x036F}, +-{0x100C, 0x058F}, +-{0x100E, 0x07AF}, +-{0x1010, 0x014F}, +-{0x3230, 0x0312}, +-{0x3232, 0x0532}, +-{0x3234, 0x0752}, +-{0x3236, 0x00F2}, +-{0x3566, 0x3328}, +-{0x32D0, 0x3A02}, +-{0x32D2, 0x3508}, +-{0x32D4, 0x3702}, +-{0x32D6, 0x3C04}, +-{0x32DC, 0x370A}, +-{0x30B0, 0x0800}, +-/* PCLK=22Mhz/2 *44/1/6= 88.6Mhz - TI serializers */ +-{0x302A, 6}, // VT_PIX_CLK_DIV +-{0x302C, 1}, // VT_SYS_CLK_DIV +-{0x302E, 2}, // PRE_PLL_CLK_DIV +-{0x3030, 44}, // PLL_MULTIPLIER +-{0x3036, 0x000C}, // OP_WORD_CLK_DIV +-{0x3038, 0x0001}, // OP_SYS_CLK_DIV +-{0x30B0, 0x0A00}, +-{0x30A2, 0x0001}, +-{0x30A6, 0x0001}, +-{0x3040, 0x0000}, +-{0x3040, 0x0000}, +-{0x3044, 0x0400}, +-{0x3044, 0x0400}, +-{0x3044, 0x0400}, +-{0x3044, 0x0400}, +-{0x3064, 0x1882}, +-{0x3064, 0x1802}, +-{0x3064, 0x1802}, +-{0x3064, 0x1802}, +-{0x33E0, 0x0C80}, +-{0x33E0, 0x0C80}, +-{0x3180, 0x0080}, +-{0x33E4, 0x0080}, +-{0x33E0, 0x0C80}, +-{0x33E0, 0x0C80}, +-{0x3004, AR0233_X_START}, // X_ADDR_START_ +-{0x3008, AR0233_X_END}, // X_ADDR_END_ +-{0x3002, AR0233_Y_START}, // Y_ADDR_START_ +-{0x3006, AR0233_Y_END}, // Y_ADDR_END_ +-{0x3402, 0x0000 | AR0233_MAX_WIDTH}, // X_OUTPUT_CONTROL +-{0x3404, 0x0000 | AR0233_MAX_HEIGHT}, // Y_OUTPUT_CONTROL +-{0x3032, 0x0000}, +-{0x3400, 0x0010}, +-#if 1 +-/* disable HDR */ +-{0x3082, 0x0000}, +-{0x30BA, 0x11F2}, +-#endif +-{AR0233_DELAY, 100}, // Wait 100ms +- +-#if 0 +-{0x300A, AR0233_SENSOR_HEIGHT + 356}, // FRAME_LENGTH_LINES_ +-{0x300C, AR0233_SENSOR_WIDTH + 100}, // LINE_LENGTH_PCK_ +-#else +-{0x300A, AR0233_SENSOR_HEIGHT + 288}, // FRAME_LENGTH_LINES_ +-{0x300C, AR0233_SENSOR_WIDTH + 300}, // LINE_LENGTH_PCK_ +-#endif +-{0x3042, 0x0000}, +-{0x3238, 0x0222}, +-{0x3012, 0x0144}, +-{0x3014, AR0233_SENSOR_WIDTH + 100}, +-{0x321E, AR0233_SENSOR_WIDTH + 100}, +-{0x3222, AR0233_SENSOR_WIDTH + 100}, +-{0x30B0, 0x0B00}, +-{0x32EA, 0x3C0E}, +-{0x32EA, 0x3C0E}, +-{0x32EA, 0x3C0E}, +-{0x32EC, 0x72A1}, +-{0x32EC, 0x72A1}, +-{0x32EC, 0x72A1}, +-{0x32EC, 0x72A1}, +-{0x32EC, 0x72A1}, +-{0x32EC, 0x72A1}, +-{0x31D0, 0x0001}, // COMPANDING +-{0x31AE, 0x0004}, +-{0x31AE, 0x0304}, +-{0x31AC, 0x140C}, // DATA_FORMAT_BITS: RAW12 +-{0x301A, 0x1098}, +-{0x301A, 0x1018}, +-{0x301A, 0x1018}, +-{0x31AE, 0x0204}, +-{0x3342, 0x122C}, +-{0x3346, 0x122C}, +-{0x334A, 0x122C}, +-{0x334E, 0x122C}, +-{0x3344, 0x0011}, +-{0x3348, 0x0111}, +-{0x334C, 0x0211}, +-{0x3350, 0x0311}, +-{0x31B0, 0x0049}, +-{0x31B2, 0x0033}, +-{0x31B4, 0x2185}, +-{0x31B6, 0x1146}, +-{0x31B8, 0x3047}, +-{0x31BA, 0x0186}, +-{0x31BC, 0x0805}, +-#if 1 +-/* Enable trigger input */ +-{0x340A, 0x00E0}, // GPIO_CONTROL1: GPIO1 is trigger +-{0x340C, 0x0002}, // GPIO_CONTROL2: GPIO1 is trigger +-{0x30CE, 0x0120}, // TRIGGER_MODE +-//{0x30DC, 0x0120}, // TRIGGER_DELAY +-#endif +-{0x3366, 0x0aaa}, // ANALOG_GAIN +-{0x301A, 0x011C}, +-}; ++#include "ar0233_rev1.h" ++#include "ar0233_rev2.h" +diff --git a/drivers/media/i2c/soc_camera/ar0233_rev1.h b/drivers/media/i2c/soc_camera/ar0233_rev1.h +new file mode 100644 +index 0000000..c29ac6a +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0233_rev1.h +@@ -0,0 +1,1258 @@ ++/* ++ * ON Semiconductor AR0233 sensor camera wizard 2048x1280@30/BGGR/MIPI ++ * ++ * Copyright (C) 2019 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++/* 3Exp HDR 1080p Mode MIPI-4lane 12-bit 30FPS, XCLK=24MHz */ ++static const struct ar0233_reg ar0233_regs_wizard_rev1[] = { ++{0x301A, 0x18}, // MIPI, stream OFF ++{AR0233_DELAY, 200}, // Wait 200ms ++ ++{0x3070, 0x0000}, // 1: Solid color test pattern, ++ // 2: Full color bar test pattern, ++ // 3: Fade to grey color bar test pattern, ++ //256: Walking 1 test pattern (12 bit) ++{0x3072, 0x0123}, // R ++{0x3074, 0x0456}, // G(GR row) ++{0x3076, 0x0abc}, // B ++{0x3078, 0x0def}, // G(GB row) ++#ifdef AR0233_DISPLAY_PATTERN_FIXED ++{0x3070, 0x0001}, ++#endif ++#ifdef AR0233_DISPLAY_PATTERN_COLOR_BAR ++{0x3070, 0x0002}, ++#endif ++{AR0233_DELAY, 100}, // Wait 100ms ++ ++#if 1 /* Sequencer Settings */ ++#if 1 /* Design_recommended_settings_v5 */ ++{0x356C, 0xEA55}, //mte.Sensor.Register("DAC_LD_108_109").Value = 0xEA55& -- ADC write Memory delay 7 ++{0x3566, 0x2407}, //mte.Sensor.Register("DAC_LD_102_103").Value = 0x2407& -- Enable column amp bypass for 1x ++{0x3562, 0x1C08}, //mte.Sensor.Register("DAC_LD_98_99").Value = 0x1C08& -- Increase column amp current ++{0x3180, 0x1001}, //mte.Sensor.Register("DELTA_DK_CONTROL").Value = 0x1001& -- enable dither ++{0x3546, 0x4601}, //MTE.Sensor.Register("DAC_LD_70_71::ANA_SREG_VLN_CURR").Value = 17 -- VLN curr ++ //Sensor.Register(sbit_Dac_Ld_70_71_Ana_Sreg_Ae_Shs_Clamp_En).value = 0 ---- Eclipse ++{0x3548, 0x4141}, //MTE.Sensor.Register("DAC_LD_72_73::ANA_SREG_AE_SHR_HCG1").value = 65; //MTE.Sensor.Register("DAC_LD_72_73::ANA_SREG_AE_SHR_HCG0").value = 65 ++{0x354A, 0x5958}, //MTE.Sensor.Register("DAC_LD_74_75::ANA_SREG_AE_SHR_HCG3TO7").value = 88; //MTE.Sensor.Register("DAC_LD_74_75::ANA_SREG_AE_SHR_HCG2").value = 89 ++{0x3542, 0x44F0}, //MTE.Sensor.Register(sbit_Dac_Ld_66_67_Ana_Drstlo_Sel_Hcg_Lg_3_0).Value = 4, MTE.Sensor.Register(sbit_Dac_Ld_66_67_Ana_Drstlo_Sel_Hcg_Hg_3_0).Value = 4 ++ ++// Boosters_Hi_change settings for reduction in DSNU and hot pixels ++{0x3518, 0x4444}, //drstlo_lcg_lg(4), drstlo_hcg_lg(4), drstlo_lcg_hg(4), drstlo_hcg_hg(4) ++{0x3540, 0x44}, //drstlo_lcg_lg_3_0(4), lcg_hg_3_0(4) ++{0x3536, 0x9898}, //booster_ref_Vaa rsthi(1), dcghi(1) ++{0x3538, 0x981A}, //booster_ref_vaa rshi(1) ++{0x3530, 0x5F98}, //Boost_ref_Vaa Wellhi(1) ++{0x353C, 0x9A0A}, //Boost_ref_Vaa lfm_dcghi(1) ++{0x3526, 0x9000}, //DWellhi(16) ++{0x352E, 0x90D}, //Dlfm_Dcghi(13),(Dlfm_Txhi_Buffer) = 9 ++#endif /* Design_recommended_settings_v5 */ ++ ++#if 1 /* Pixel_char_recommended_settings_v2 */ ++//TXLO @HCG ++{0x3514, 0x555B}, //-0.85V ++{0x3578, 0x555B}, //-0.85V ++//TXLO @LCG ++{0x3514, 0x5B5B}, //-0.85V ++{0x3578, 0x5B5B}, //-0.85V ++//TXHI ++{0x3528, 0xE018}, //2.8V ++//RSHI ++{0x352A, 0x1533},//3.36V ++//DDCGHI ++{0x3528, 0xEB0D}, //Ddcghi(13), txhi(11) ++//DRSTHI, DRSHI ++{0x352A, 0xA27}, //Drsthi (10), Drshi(7) ++#endif /* Pixel_char_recommended_settings_v2 */ ++ ++#if 1 /* AR0233_Sequencer_LFM_HDR_v6 */ ++{0x2512, 0x8000}, ++{0x2510, 0x070f}, ++{0x2510, 0x1011}, ++{0x2510, 0x1216}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0x191b}, ++{0x2510, 0x2123}, ++{0x2510, 0x2528}, ++{0x2510, 0xffff}, ++{0x2510, 0x2e4a}, ++{0x2510, 0x5874}, ++{0x2510, 0x8187}, ++{0x2510, 0x8b93}, ++{0x2510, 0x9496}, ++{0x2510, 0xa1a9}, ++{0x2510, 0xaaad}, ++{0x2510, 0xb1b5}, ++{0x2510, 0xb9bb}, ++{0x2510, 0xbdff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xc003}, ++{0x2510, 0x8058}, ++{0x2510, 0xa0e0}, ++{0x2510, 0x3041}, ++{0x2510, 0x3042}, ++{0x2510, 0x2000}, ++{0x2510, 0x3048}, ++{0x2510, 0x3088}, ++{0x2510, 0x30a0}, ++{0x2510, 0x3090}, ++{0x2510, 0xa0c0}, ++{0x2510, 0x9008}, ++{0x2510, 0x8802}, ++{0x2510, 0x20ff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x9018}, ++{0x2510, 0x891a}, ++{0x2510, 0x807c}, ++{0x2510, 0x20ff}, ++{0x2510, 0x895b}, ++{0x2510, 0x20ff}, ++{0x2510, 0x897b}, ++{0x2510, 0x20ff}, ++{0x2510, 0x897f}, ++{0x2510, 0x20ff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x3081}, ++{0x2510, 0x3082}, ++{0x2510, 0xa0c4}, ++{0x2510, 0x20ff}, ++{0x2510, 0x8058}, ++{0x2510, 0x9039}, ++{0x2510, 0x20ff}, ++{0x2510, 0x907f}, ++{0x2510, 0x895b}, ++{0x2510, 0x2064}, ++{0x2510, 0x891b}, ++{0x2510, 0x2010}, ++{0x2510, 0x8803}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x20ff}, ++{0x2510, 0x906b}, ++{0x2510, 0x2064}, ++{0x2510, 0x3084}, ++{0x2510, 0x2003}, ++{0x2510, 0x3044}, ++{0x2510, 0x2000}, ++{0x2510, 0xa004}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x3108}, ++{0x2510, 0x2400}, ++{0x2510, 0x2401}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x3108}, ++{0x2510, 0x2400}, ++{0x2510, 0x2401}, ++{0x2510, 0x2702}, ++{0x2510, 0x3242}, ++{0x2510, 0x3108}, ++{0x2510, 0x2420}, ++{0x2510, 0x2421}, ++{0x2510, 0x2703}, ++{0x2510, 0x3242}, ++{0x2510, 0x3108}, ++{0x2510, 0x2420}, ++{0x2510, 0x2421}, ++{0x2510, 0x2704}, ++{0x2510, 0x3242}, ++{0x2510, 0x3108}, ++{0x2510, 0x2420}, ++{0x2510, 0x2421}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x3108}, ++{0x2510, 0x2402}, ++{0x2510, 0x2403}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x3108}, ++{0x2510, 0x2741}, ++{0x2510, 0x2429}, ++{0x2510, 0x2740}, ++{0x2510, 0x242a}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x3108}, ++{0x2510, 0x2404}, ++{0x2510, 0x2779}, ++{0x2510, 0x242c}, ++{0x2510, 0x2781}, ++{0x2510, 0x242d}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x3108}, ++{0x2510, 0x2703}, ++{0x2510, 0x2432}, ++{0x2510, 0x2703}, ++{0x2510, 0x3242}, ++{0x2510, 0x3108}, ++{0x2510, 0x27bb}, ++{0x2510, 0x2430}, ++{0x2510, 0x27bb}, ++{0x2510, 0x3242}, ++{0x2510, 0x3108}, ++{0x2510, 0x2702}, ++{0x2510, 0x2431}, ++{0x2510, 0x2702}, ++{0x2510, 0x3242}, ++{0x2510, 0x3108}, ++{0x2510, 0x27c3}, ++{0x2510, 0x2430}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xb800}, ++{0x2510, 0x8058}, ++{0x2510, 0xa005}, ++{0x2510, 0x3101}, ++{0x2510, 0x3041}, ++{0x2510, 0x3104}, ++{0x2510, 0xb035}, ++{0x2510, 0xb075}, ++{0x2510, 0x30c1}, ++{0x2510, 0x3102}, ++{0x2510, 0x3041}, ++{0x2510, 0x3202}, ++{0x2510, 0xb848}, ++{0x2510, 0xb84c}, ++{0x2510, 0x2200}, ++{0x2510, 0x3141}, ++{0x2510, 0x3042}, ++{0x2510, 0xb377}, ++{0x2510, 0x8843}, ++{0x2510, 0x916f}, ++{0x2510, 0x3110}, ++{0x2510, 0x3042}, ++{0x2510, 0xb84e}, ++{0x2510, 0xf905}, ++{0x2510, 0xf907}, ++{0x2510, 0x2200}, ++{0x2510, 0x885b}, ++{0x2510, 0xa898}, ++{0x2510, 0xa8d8}, ++{0x2510, 0xf8e8}, ++{0x2510, 0x80dc}, ++{0x2510, 0x9007}, ++{0x2510, 0x916f}, ++{0x2510, 0x2206}, ++{0x2510, 0xb808}, ++{0x2510, 0xc800}, ++{0x2510, 0xe809}, ++{0x2510, 0x88df}, ++{0x2510, 0xf8a8}, ++{0x2510, 0xf888}, ++{0x2510, 0x2203}, ++{0x2510, 0xb07b}, ++{0x2510, 0x2000}, ++{0x2510, 0x80cc}, ++{0x2510, 0x808c}, ++{0x2510, 0x220b}, ++{0x2510, 0xb06a}, ++{0x2510, 0x88cf}, ++{0x2510, 0x888f}, ++{0x2510, 0x2224}, ++{0x2510, 0xb04a}, ++{0x2510, 0x2218}, ++{0x2510, 0x2116}, ++{0x2510, 0x902f}, ++{0x2510, 0xb04b}, ++{0x2510, 0xf880}, ++{0x2510, 0x2217}, ++{0x2510, 0x2204}, ++{0x2510, 0xb043}, ++{0x2510, 0xa8c9}, ++{0x2510, 0x31c1}, ++{0x2510, 0x80ac}, ++{0x2510, 0x2205}, ++{0x2510, 0x916f}, ++{0x2510, 0x2104}, ++{0x2510, 0x88af}, ++{0x2510, 0x2440}, ++{0x2510, 0xf110}, ++{0x2510, 0xf804}, ++{0x2510, 0x2000}, ++{0x2510, 0x8088}, ++{0x2510, 0x3002}, ++{0x2510, 0xb838}, ++{0x2510, 0xa8c8}, ++{0x2510, 0xb04b}, ++{0x2510, 0x2442}, ++{0x2510, 0x3210}, ++{0x2510, 0x2206}, ++{0x2510, 0x888b}, ++{0x2510, 0x2441}, ++{0x2510, 0x3202}, ++{0x2510, 0xf108}, ++{0x2510, 0xf0d7}, ++{0x2510, 0xb830}, ++{0x2510, 0xf880}, ++{0x2510, 0xc801}, ++{0x2510, 0x30c2}, ++{0x2510, 0xe80c}, ++{0x2510, 0x2201}, ++{0x2510, 0xb04a}, ++{0x2510, 0x222d}, ++{0x2510, 0x3241}, ++{0x2510, 0x2207}, ++{0x2510, 0x902f}, ++{0x2510, 0x2214}, ++{0x2510, 0x2204}, ++{0x2510, 0xb042}, ++{0x2510, 0xa9a1}, ++{0x2510, 0x8008}, ++{0x2510, 0xb093}, ++{0x2510, 0x31c1}, ++{0x2510, 0x916b}, ++{0x2510, 0x2009}, ++{0x2510, 0x8803}, ++{0x2510, 0xa044}, ++{0x2510, 0x3044}, ++{0x2510, 0x2000}, ++{0x2510, 0xa004}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xa084}, ++{0x2510, 0x30d0}, ++{0x2510, 0x8078}, ++{0x2510, 0x3141}, ++{0x2510, 0x3041}, ++{0x2510, 0x3042}, ++{0x2510, 0x2000}, ++{0x2510, 0x3142}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x3110}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x3120}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x3144}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x3148}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x2206}, ++{0x2510, 0x881b}, ++{0x2510, 0x887b}, ++{0x2510, 0xa08c}, ++{0x2510, 0x221f}, ++{0x2510, 0xa084}, ++{0x2510, 0x2440}, ++{0x2510, 0xb095}, ++{0x2510, 0xf110}, ++{0x2510, 0xf864}, ++{0x2510, 0xf90d}, ++{0x2510, 0x3084}, ++{0x2510, 0x3090}, ++{0x2510, 0x3088}, ++{0x2510, 0x8058}, ++{0x2510, 0x3001}, ++{0x2510, 0x2442}, ++{0x2510, 0x3220}, ++{0x2510, 0x2002}, ++{0x2510, 0x8863}, ++{0x2510, 0x2004}, ++{0x2510, 0x8803}, ++{0x2510, 0x2441}, ++{0x2510, 0x30c2}, ++{0x2510, 0xa9a0}, ++{0x2510, 0xb094}, ++{0x2510, 0x2201}, ++{0x2510, 0xa0c4}, ++{0x2510, 0x3044}, ++{0x2510, 0x2000}, ++{0x2510, 0xa004}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xb980}, ++{0x2510, 0x8108}, ++{0x2510, 0xa105}, ++{0x2510, 0x30c1}, ++{0x2510, 0x2000}, ++{0x2510, 0x3101}, ++{0x2510, 0x3041}, ++{0x2510, 0x3104}, ++{0x2510, 0x3102}, ++{0x2510, 0x3041}, ++{0x2510, 0xf860}, ++{0x2510, 0xb095}, ++{0x2510, 0x3141}, ++{0x2510, 0x3042}, ++{0x2510, 0xb9f8}, ++{0x2510, 0xb9fc}, ++{0x2510, 0x8803}, ++{0x2510, 0x916f}, ++{0x2510, 0x3110}, ++{0x2510, 0x3042}, ++{0x2510, 0xb9fe}, ++{0x2510, 0xf905}, ++{0x2510, 0xf907}, ++{0x2510, 0x3202}, ++{0x2510, 0x880b}, ++{0x2510, 0xa888}, ++{0x2510, 0xa8c8}, ++{0x2510, 0xb397}, ++{0x2510, 0xf8e8}, ++{0x2510, 0x818c}, ++{0x2510, 0x9007}, ++{0x2510, 0x916f}, ++{0x2510, 0x2204}, ++{0x2510, 0xb137}, ++{0x2510, 0xb9b8}, ++{0x2510, 0xc801}, ++{0x2510, 0xe809}, ++{0x2510, 0xb177}, ++{0x2510, 0x888f}, ++{0x2510, 0xf8a8}, ++{0x2510, 0xf888}, ++{0x2510, 0x2203}, ++{0x2510, 0xb07b}, ++{0x2510, 0x2000}, ++{0x2510, 0x818c}, ++{0x2510, 0x808c}, ++{0x2510, 0x220b}, ++{0x2510, 0xb06a}, ++{0x2510, 0x888f}, ++{0x2510, 0x888f}, ++{0x2510, 0x2224}, ++{0x2510, 0xb04a}, ++{0x2510, 0x2218}, ++{0x2510, 0x2115}, ++{0x2510, 0xb04b}, ++{0x2510, 0x902f}, ++{0x2510, 0xf880}, ++{0x2510, 0x2217}, ++{0x2510, 0x2204}, ++{0x2510, 0xb043}, ++{0x2510, 0xa8d9}, ++{0x2510, 0x31c1}, ++{0x2510, 0x80cc}, ++{0x2510, 0x2103}, ++{0x2510, 0x916f}, ++{0x2510, 0x2106}, ++{0x2510, 0x88cf}, ++{0x2510, 0x2440}, ++{0x2510, 0xf110}, ++{0x2510, 0xf804}, ++{0x2510, 0x2000}, ++{0x2510, 0x8088}, ++{0x2510, 0x3002}, ++{0x2510, 0xb988}, ++{0x2510, 0xa8d8}, ++{0x2510, 0xb04b}, ++{0x2510, 0x2442}, ++{0x2510, 0x3210}, ++{0x2510, 0x2206}, ++{0x2510, 0x888b}, ++{0x2510, 0x2441}, ++{0x2510, 0x3202}, ++{0x2510, 0xf108}, ++{0x2510, 0xf0d7}, ++{0x2510, 0xb980}, ++{0x2510, 0xf880}, ++{0x2510, 0xc800}, ++{0x2510, 0x30c2}, ++{0x2510, 0xe80c}, ++{0x2510, 0x2201}, ++{0x2510, 0xb04a}, ++{0x2510, 0x2230}, ++{0x2510, 0x3241}, ++{0x2510, 0x902f}, ++{0x2510, 0x221b}, ++{0x2510, 0x2204}, ++{0x2510, 0xb042}, ++{0x2510, 0xa9a1}, ++{0x2510, 0x8058}, ++{0x2510, 0xb093}, ++{0x2510, 0x31c1}, ++{0x2510, 0x916b}, ++{0x2510, 0x2009}, ++{0x2510, 0x8803}, ++{0x2510, 0xa144}, ++{0x2510, 0x3044}, ++{0x2510, 0x2000}, ++{0x2510, 0xa004}, ++{0x2510, 0xb800}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x8078}, ++{0x2510, 0x30d0}, ++{0x2510, 0xa184}, ++{0x2510, 0xb980}, ++{0x2510, 0x3141}, ++{0x2510, 0x3041}, ++{0x2510, 0x3042}, ++{0x2510, 0x2000}, ++{0x2510, 0x3142}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x3110}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x3120}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x2206}, ++{0x2510, 0x881b}, ++{0x2510, 0x887b}, ++{0x2510, 0x2440}, ++{0x2510, 0xb095}, ++{0x2510, 0xf110}, ++{0x2510, 0xf864}, ++{0x2510, 0xf90d}, ++{0x2510, 0x30a0}, ++{0x2510, 0x3090}, ++{0x2510, 0x3088}, ++{0x2510, 0x8058}, ++{0x2510, 0x3001}, ++{0x2510, 0x2202}, ++{0x2510, 0x2442}, ++{0x2510, 0x3220}, ++{0x2510, 0x2002}, ++{0x2510, 0x885b}, ++{0x2510, 0x2441}, ++{0x2510, 0x30c2}, ++{0x2510, 0x8018}, ++{0x2510, 0x2000}, ++{0x2510, 0x881b}, ++{0x2510, 0x2008}, ++{0x2510, 0x8000}, ++{0x2510, 0xa9a0}, ++{0x2510, 0xb094}, ++{0x2510, 0x2201}, ++{0x2510, 0x8803}, ++{0x2510, 0xa1c4}, ++{0x2510, 0x3044}, ++{0x2510, 0xb800}, ++{0x2510, 0xa004}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x9818}, ++{0x2510, 0x3101}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x3102}, ++{0x2510, 0x3041}, ++{0x2510, 0x8008}, ++{0x2510, 0x2002}, ++{0x2510, 0x8028}, ++{0x2510, 0x2205}, ++{0x2510, 0x880b}, ++{0x2510, 0x882b}, ++{0x2510, 0x213e}, ++{0x2510, 0x8008}, ++{0x2510, 0x2202}, ++{0x2510, 0x8000}, ++{0x2510, 0x2202}, ++{0x2510, 0xa044}, ++{0x2510, 0x3044}, ++{0x2510, 0x8803}, ++{0x2510, 0x9800}, ++{0x2510, 0xa004}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2440}, ++{0x2510, 0xb095}, ++{0x2510, 0xf110}, ++{0x2510, 0xf864}, ++{0x2510, 0xf90d}, ++{0x2510, 0x2442}, ++{0x2510, 0x3220}, ++{0x2510, 0x2007}, ++{0x2510, 0x2441}, ++{0x2510, 0x30c2}, ++{0x2510, 0xa9a0}, ++{0x2510, 0xb094}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xb980}, ++{0x2510, 0x3101}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x3102}, ++{0x2510, 0x3041}, ++{0x2510, 0x8028}, ++{0x2510, 0x220a}, ++{0x2510, 0x880b}, ++{0x2510, 0x882b}, ++{0x2510, 0x2440}, ++{0x2510, 0xb095}, ++{0x2510, 0xf110}, ++{0x2510, 0xf864}, ++{0x2510, 0xf90d}, ++{0x2510, 0x8008}, ++{0x2510, 0x3001}, ++{0x2510, 0x2202}, ++{0x2510, 0x2442}, ++{0x2510, 0x8823}, ++{0x2510, 0x3220}, ++{0x2510, 0x2000}, ++{0x2510, 0x8803}, ++{0x2510, 0x2441}, ++{0x2510, 0x30c2}, ++{0x2510, 0xa9a0}, ++{0x2510, 0xb094}, ++{0x2510, 0x2201}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2000}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2400}, ++{0x2510, 0x2751}, ++{0x2510, 0x2423}, ++{0x2510, 0x2750}, ++{0x2510, 0x2421}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2749}, ++{0x2510, 0x2422}, ++{0x2510, 0x2749}, ++{0x2510, 0x2423}, ++{0x2510, 0x2709}, ++{0x2510, 0x2420}, ++{0x2510, 0x2729}, ++{0x2510, 0x2423}, ++{0x2510, 0x3242}, ++{0x2510, 0x3108}, ++{0x2510, 0x2722}, ++{0x2510, 0x2422}, ++{0x2510, 0x2769}, ++{0x2510, 0x2421}, ++{0x2510, 0x2702}, ++{0x2510, 0x2421}, ++{0x2510, 0x3242}, ++{0x2510, 0x3108}, ++{0x2510, 0x276a}, ++{0x2510, 0x2420}, ++{0x2510, 0x276a}, ++{0x2510, 0x2421}, ++{0x2510, 0x2703}, ++{0x2510, 0x2420}, ++{0x2510, 0x2703}, ++{0x2510, 0x2421}, ++{0x2510, 0x3242}, ++{0x2510, 0x3108}, ++{0x2510, 0x276b}, ++{0x2510, 0x2420}, ++{0x2510, 0x276b}, ++{0x2510, 0x2421}, ++{0x2510, 0x2704}, ++{0x2510, 0x2420}, ++{0x2510, 0x2704}, ++{0x2510, 0x2421}, ++{0x2510, 0x3242}, ++{0x2510, 0x3108}, ++{0x2510, 0x276c}, ++{0x2510, 0x2420}, ++{0x2510, 0x276c}, ++{0x2510, 0x2421}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2759}, ++{0x2510, 0x2422}, ++{0x2510, 0x2758}, ++{0x2510, 0x2420}, ++{0x2510, 0x2403}, ++{0x2510, 0x2712}, ++{0x2510, 0x3242}, ++{0x2510, 0x3108}, ++{0x2510, 0x2422}, ++{0x2510, 0x271a}, ++{0x2510, 0x3242}, ++{0x2510, 0x3108}, ++{0x2510, 0x2420}, ++{0x2510, 0x2702}, ++{0x2510, 0x2423}, ++{0x2510, 0x2703}, ++{0x2510, 0x3242}, ++{0x2510, 0x3108}, ++{0x2510, 0x2420}, ++{0x2510, 0x2703}, ++{0x2510, 0x2423}, ++{0x2510, 0x2704}, ++{0x2510, 0x3242}, ++{0x2510, 0x3108}, ++{0x2510, 0x2420}, ++{0x2510, 0x2704}, ++{0x2510, 0x2423}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2400}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xc023}, ++{0x2510, 0x2402}, ++{0x2510, 0x2405}, ++{0x2510, 0x2789}, ++{0x2510, 0x242e}, ++{0x2510, 0x2788}, ++{0x2510, 0x242f}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xc027}, ++{0x2510, 0x2400}, ++{0x2510, 0x2406}, ++{0x2510, 0xc063}, ++{0x2510, 0x2402}, ++{0x2510, 0x2751}, ++{0x2510, 0x2423}, ++{0x2510, 0x2750}, ++{0x2510, 0x2421}, ++{0x2510, 0xc003}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xc021}, ++{0x2510, 0x2400}, ++{0x2510, 0x2405}, ++{0x2510, 0xc062}, ++{0x2510, 0x2400}, ++{0x2510, 0xc063}, ++{0x2510, 0x2751}, ++{0x2510, 0x2423}, ++{0x2510, 0x2750}, ++{0x2510, 0x2421}, ++{0x2510, 0xc003}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xc0e3}, ++{0x2510, 0x2400}, ++{0x2510, 0x27b1}, ++{0x2510, 0x2425}, ++{0x2510, 0xc063}, ++{0x2510, 0x2420}, ++{0x2510, 0x2751}, ++{0x2510, 0x2423}, ++{0x2510, 0x2750}, ++{0x2510, 0x2421}, ++{0x2510, 0xc003}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2404}, ++{0x2510, 0x2779}, ++{0x2510, 0x242c}, ++{0x2510, 0x2781}, ++{0x2510, 0x242d}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x2791}, ++{0x2510, 0x2430}, ++{0x2510, 0x2799}, ++{0x2510, 0x2428}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x27a1}, ++{0x2510, 0x2430}, ++{0x2510, 0x27a9}, ++{0x2510, 0x2428}, ++{0x2510, 0x3244}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0x7fff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{0x2510, 0xffff}, ++{AR0233_DELAY, 100}, ++#endif /* AR0233_Sequencer_LFM_HDR_v6 */ ++#endif /* Sequencer Settings */ ++ ++{0x3082, 0x8}, //0x3082 = 2, 3 exposures ++{0x3110, 0x11}, //Set bypass pix comb for HDR,Pre_hdr_gain_enable_07Jul ++{0x30BA, 0x1122}, //Num_exp_max ++{0x3012, 0x144}, //Integration_time ++ ++#if 1 /* Serial 12-bit Timing Setup_108Mhz */ ++/* PCLK=24Mhz/PRE_PLL_CLK_DIV *PLL_MULTIPLIER /P1 /P4 */ ++/* PCLK=24Mhz/2 *54/1/6= 108Mhz - TI serializers */ ++{0x3030, 54}, //PLL_MULTIPLIER ; 0x3030 [11:0] ++{0x302E, 2}, //PRE_PLL_CLK_DIV ; 0x302E [5:0] ++{0x302C, 1}, //P1 divider (vt_sys_clk_div) ++{0x302A, 6}, //P2 divider (vt_pix_clk_div); 0x302A [4:0] ++{0x3038, 2}, //P3 divider (op_sys_clk_div); 0x3038 [4:0] ++{0x3036, 6}, //P4 divider (op_word_clk_div); 0x3036 [4:0] ++{0x31DC, 0x1FB0}, ++#endif /* Serial 12-bit Timing Setup_108Mhz */ ++ ++#if 1 /* MIPI 4 Lane 12BITS 30FPS_ext24_LIM */ ++{0x31AE, 0x204}, //MIPI enable, 4 lanes ++{0x31B0, 0x4B}, //frame_preamble ++{0x31B2, 0x33}, //line_preamble ++{0x31B4, 0x1185}, //mipi_timing_0 ++{0x31B6, 0x110B}, //mipi_timing_1 ++{0x31B8, 0x4047}, //mipi_timing_2 ++{0x31BA, 0x105}, //mipi_timing_3 ++{0x31BC, 0x704}, //mipi_timing_4 ++#endif /* MIPI 4 Lane 12BITS 30FPS_ext24_LIM */ ++ ++#if 1 /* MIPI_DT_bit12 */ ++{0x3342, 0x122C}, // MIPI_F1_PDT_EDT ++{0x3346, 0x122C}, // MIPI_F2_PDT_EDT ++{0x334A, 0x122C}, // MIPI_F3_PDT_EDT ++{0x334E, 0x122C}, // MIPI_F4_PDT_EDT ++#endif /* MIPI_DT_bit12 */ ++ ++/* resolution */ ++{0x3004, AR0233_X_START}, // X_ADDR_START_ ++{0x3008, AR0233_X_END}, // X_ADDR_END_ ++{0x3002, AR0233_Y_START}, // Y_ADDR_START_ ++{0x3006, AR0233_Y_END}, // Y_ADDR_END_ ++ ++#ifdef AR0233_EMBEDDED_LINE ++{0x3040, 0x0000}, //Embedded stat2 and data2 rows ++{0x3064, 0x0180}, //Enable embedded data and stat ++#else ++{0x3064, 0x0}, //Disable embedded data and stat ++#endif ++ ++// FPS = 108MHz / reg0x300A / reg0x300C * (DES_REF_XTAL/24MHz) ++{0x300A, AR0233_SENSOR_HEIGHT + 100}, // Frame_length_Lines ++{0x300C, AR0233_SENSOR_WIDTH + 400}, // Line_length_pck ++//{0x300C, 0x960}, //Line_lenth_pck_FRN AEF ++//{0x300A, 0x5DC}, //FLL ++ ++#if 1 /* Gain_3.28x */ ++{0x3022, 0x01}, // GROUPED_PARAMETER_HOLD_ ++{0x3362, 0x000F}, // DC_GAIN ++{0x3366, 0x1111}, ++{0x336A, 0x0000}, ++{0x3022, 0x00}, // GROUPED_PARAMETER_HOLD_ ++#endif /* Gain_3.28x */ ++ ++{0x31D0, 0x1}, // Companding ++{0x31AC, 0x140C}, // DLO20 to 12output ++ ++#if 1 /* MEC DLO default */ ++{0x3D00, 0x6F73}, // control ++{0x3D02, 0x0033}, ++{0x3364, 0x068C}, // dcg_trim = 13.1 ++{0x3D28, 0x09C4}, // weights ++{0x3D2A, 0x0DAC}, ++{0x3D30, 0x0FFF}, ++{0x3D32, 0x0FFF}, ++{0x3D34, 0x09C4}, ++{0x3D36, 0x0DAC}, ++{0x3D3C, 0x0FFF}, ++{0x3D3E, 0x0FFF}, ++{0x3D40, 0x09C4}, ++{0x3D42, 0x0DAC}, ++{0x3D48, 0x0FFF}, ++{0x3D4A, 0x0FFF}, ++{0x3D4C, 0x0DAC}, ++{0x3D64, 0x0DAC}, // clip ++{0x3D66, 0x0DAC}, ++{0x3D68, 0x0DAC}, ++{0x3D6A, 0x0DAC}, ++{0x3D6C, 0x0DAC}, ++{0x3D6E, 0x0DAC}, ++{0x3D70, 0x0DAC}, ++{0x3D72, 0x0DAC}, ++{0x3D74, 0x0DAC}, ++{0x3D76, 0x0DAC}, ++{0x3D78, 0x0DAC}, ++{0x3D7A, 0x0DAC}, ++{0x3D7C, 0x0DAC}, ++{0x3D7E, 0x0DAC}, ++{0x3D80, 0x0DAC}, ++{0x3D82, 0x0DAC}, ++{0x3D84, 0x0DAC}, // motion_clip ++{0x3D86, 0x0DAC}, ++{0x3D88, 0x0000}, ++{0x3D8A, 0x0DAC}, ++{0x3D8C, 0x0DAC}, ++{0x3D8E, 0x0000}, ++{0x3DB4, 0x0001}, // motion_q ++{0x3DB6, 0x000E}, ++{0x3DB8, 0x0080}, ++{0x3DBA, 0x3920}, // t?_s12_k ++{0x3DBC, 0x3920}, ++{0x3DBE, 0x3920}, ++{0x3DC0, 0x0080}, // wb_gain ++{0x3DC2, 0x0080}, ++{0x3DC4, 0x0080}, ++{0x3DC6, 0x0080}, ++{0x3DC8, 0x0000}, // color_th ++{0x3DCA, 0x0000}, ++{0x3DCC, 0x0000}, ++{0x3DCE, 0x0000}, ++{0x3DD0, 0x0000}, ++{0x3DD2, 0x0000}, ++{0x3DD4, 0x0000}, ++{0x3DD6, 0x0000}, ++{0x3DD8, 0x0000}, ++{0x3DDA, 0x0000}, ++{0x3DDC, 0x0000}, ++{0x3DDE, 0x0000}, ++{0x3DE0, 0x0000}, ++{0x3290, 0x1B58}, // t3_barrier ++{0x3292, 0x1B58}, ++{0x3294, 0x1B58}, ++{0x3296, 0x1B58}, ++{0x3298, 0x2904}, // t4_barrier ++{0x329A, 0x2904}, ++{0x329C, 0x2904}, ++{0x329E, 0x2904}, ++{0x32A0, 0x0000}, ++{0x32A2, 0x0000}, ++{0x32A4, 0x0000}, ++{0x32A6, 0x0000}, ++{0x3D08, 0x0000}, // dtr_bound ++{0x3D0A, 0x0000}, ++{0x3D0C, 0x0000}, ++{0x3D0E, 0x0000}, ++{0x3D10, 0x0000}, // vis_bound ++{0x3D12, 0x0798}, ++{0x3D14, 0x001E}, ++{0x3D16, 0x045E}, ++#endif /* MEC DLO default */ ++ ++#if 1 /* Enable_trigger_input */ ++{0x340A, 0x0070}, // GPIO_CONTROL1: GPIO1 is trigger ++{0x340C, 0x0080}, // GPIO_CONTROL2: GPIO1 is trigger ++{0x30CE, 0x0120}, // TRIGGER_MODE ++//{0x30DC, 0x0120}, // TRIGGER_DELAY ++{0x301A, 0x0118}, // GPI pins enable ++#endif /* Enable_trigger_input */ ++}; +diff --git a/drivers/media/i2c/soc_camera/ar0233_rev2.h b/drivers/media/i2c/soc_camera/ar0233_rev2.h +index fbc2649..f4b75a2 100644 +--- a/drivers/media/i2c/soc_camera/ar0233_rev2.h ++++ b/drivers/media/i2c/soc_camera/ar0233_rev2.h +@@ -9,27 +9,6 @@ + * option) any later version. + */ + +-//#define AR0233_DISPLAY_PATTERN_FIXED +-//#define AR0233_DISPLAY_PATTERN_COLOR_BAR +- +-#define AR0233_MAX_WIDTH 2048 +-#define AR0233_MAX_HEIGHT 1280 +- +-#define AR0233_DELAY 0xffff +- +-#define AR0233_SENSOR_WIDTH 2058 +-#define AR0233_SENSOR_HEIGHT 1284 +- +-#define AR0233_X_START ((AR0233_SENSOR_WIDTH - AR0233_MAX_WIDTH) / 2) +-#define AR0233_Y_START ((AR0233_SENSOR_HEIGHT - AR0233_MAX_HEIGHT) / 2) +-#define AR0233_X_END (AR0233_X_START + AR0233_MAX_WIDTH - 1) +-#define AR0233_Y_END (AR0233_Y_START + AR0233_MAX_HEIGHT - 1) +- +-struct ar0233_reg { +- u16 reg; +- u16 val; +-}; +- + #define O1_Recommended_Defaults_LFM_HDR + #ifdef O1_Recommended_Defaults_LFM_HDR + #define Design_recommended_settings_REV2_V9 +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0143-LVDS-AR0231-add-rev6-rev4-on-max9286.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0143-LVDS-AR0231-add-rev6-rev4-on-max9286.patch new file mode 100644 index 00000000..dae7a578 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0143-LVDS-AR0231-add-rev6-rev4-on-max9286.patch @@ -0,0 +1,663 @@ +From 209a765a09c2de8f24ffb0b8c78ccddac64bb849 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Thu, 10 Jan 2019 21:50:07 +0300 +Subject: [PATCH 092/122] LVDS: AR0231: add rev6,rev4 on max9286 + +This reenables support on MAX9286 + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ar0231.c | 16 +- + drivers/media/i2c/soc_camera/ar0231.h | 7 +- + drivers/media/i2c/soc_camera/ar0231_rev4.h | 38 ++-- + drivers/media/i2c/soc_camera/ar0231_rev6.h | 343 +++++++++++++++++++++++++++++ + drivers/media/i2c/soc_camera/ar0231_rev7.h | 77 ++++--- + 5 files changed, 427 insertions(+), 54 deletions(-) + create mode 100644 drivers/media/i2c/soc_camera/ar0231_rev6.h + +diff --git a/drivers/media/i2c/soc_camera/ar0231.c b/drivers/media/i2c/soc_camera/ar0231.c +index f575cb7..07f2b5e 100644 +--- a/drivers/media/i2c/soc_camera/ar0231.c ++++ b/drivers/media/i2c/soc_camera/ar0231.c +@@ -20,11 +20,12 @@ + #include + #include + +-#include "ar0231_rev7.h" ++#include "ar0231.h" + + static const int ar0231_i2c_addr[] = {0x10, 0x20}; + + #define AR0231_PID 0x3000 ++#define AR0231_REV 0x300E + #define AR0231_VERSION_REG 0x0354 + + #define AR0231_MEDIA_BUS_FMT MEDIA_BUS_FMT_SGRBG12_1X12 +@@ -393,7 +394,7 @@ static int ar0231_initialize(struct i2c_client *client) + { + struct ar0231_priv *priv = to_ar0231(client); + u16 val = 0; +- u16 pid = 0; ++ u16 pid = 0, rev = 0; + int ret = 0; + int tmp_addr; + int i; +@@ -425,18 +426,23 @@ static int ar0231_initialize(struct i2c_client *client) + goto err; + } + ++ /* check revision */ ++ reg16_read16(client, AR0231_REV, &rev); + /* Read OTP IDs */ + ar0231_otp_id_read(client); + /* Program wizard registers */ +- ar0231_set_regs(client, ar0231_regs_wizard_rev7, ARRAY_SIZE(ar0231_regs_wizard_rev7)); ++ if (priv->ti9x4_addr) ++ ar0231_set_regs(client, ar0231_regs_wizard_rev7, ARRAY_SIZE(ar0231_regs_wizard_rev7)); ++ if (priv->max9286_addr) ++ ar0231_set_regs(client, ar0231_regs_wizard_rev6_dvp, ARRAY_SIZE(ar0231_regs_wizard_rev6_dvp)); + + /* Enable stream */ + reg16_read16(client, 0x301a, &val); + val |= (1 << 2); + reg16_write16(client, 0x301a, val); + +- dev_info(&client->dev, "ar0231 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", +- pid, AR0231_MAX_WIDTH, AR0231_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++ dev_info(&client->dev, "ar0231 PID %x (rev %x), res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, rev, AR0231_MAX_WIDTH, AR0231_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); + err: + ar0231_s_port(client, 0); + return ret; +diff --git a/drivers/media/i2c/soc_camera/ar0231.h b/drivers/media/i2c/soc_camera/ar0231.h +index b63dc91..09fc7d2d 100644 +--- a/drivers/media/i2c/soc_camera/ar0231.h ++++ b/drivers/media/i2c/soc_camera/ar0231.h +@@ -12,8 +12,8 @@ + //#define AR0231_DISPLAY_PATTERN_FIXED + //#define AR0231_DISPLAY_PATTERN_COLOR_BAR + +-#define AR0231_MAX_WIDTH 1928 +-#define AR0231_MAX_HEIGHT 1208 ++#define AR0231_MAX_WIDTH 1920 ++#define AR0231_MAX_HEIGHT 1200 + + #define AR0231_DELAY 0xffff + +@@ -31,4 +31,5 @@ struct ar0231_reg { + }; + + #include "ar0231_rev4.h" +-//#include "ar0231_rev6.h" ++#include "ar0231_rev6.h" ++#include "ar0231_rev7.h" +diff --git a/drivers/media/i2c/soc_camera/ar0231_rev4.h b/drivers/media/i2c/soc_camera/ar0231_rev4.h +index d4614ec..0627d96 100644 +--- a/drivers/media/i2c/soc_camera/ar0231_rev4.h ++++ b/drivers/media/i2c/soc_camera/ar0231_rev4.h +@@ -9,7 +9,7 @@ + * option) any later version. + */ + +-static const struct ar0231_reg ar0231_regs_wizard_rev4[] = { ++static const struct ar0231_reg ar0231_regs_wizard_rev4_dvp[] = { + {0x301A, 0x0001}, // reset + {0x301A, 0x10D8}, // Stream off and setup parallel + {0x3070, 0x0000}, // 1: Solid color test pattern, +@@ -26,6 +26,7 @@ static const struct ar0231_reg ar0231_regs_wizard_rev4[] = { + #ifdef AR0231_DISPLAY_PATTERN_COLOR_BAR + {0x3070, 0x0002}, + #endif ++ + //Recommended Settings + {0x3366, 0x6666}, // ANALOG_GAIN + {0x3056, 0x0080}, // GREEN1_GAIN +@@ -116,6 +117,7 @@ static const struct ar0231_reg ar0231_regs_wizard_rev4[] = { + {0x3566, 0x1128}, // RESERVED_MFR_3566 + {0x3566, 0x1328}, // RESERVED_MFR_3566 + {0x3566, 0x3328}, // RESERVED_MFR_3566 ++ + //Sequencer Update + {0x2512, 0x8000}, // SEQ_CTRL_PORT + {0x2510, 0x0905}, // SEQ_DATA_PORT +@@ -251,6 +253,7 @@ static const struct ar0231_reg ar0231_regs_wizard_rev4[] = { + {0x32D4, 0x3702}, // RESERVED_MFR_32D4 + {0x32D6, 0x3C04}, // RESERVED_MFR_32D6 + {0x32DC, 0x370A}, // RESERVED_MFR_32DC ++ + //Parallel Timing Setup + {0x302A, 0x0009}, // VT_PIX_CLK_DIV + {0x302C, 0x0001}, // VT_SYS_CLK_DIV +@@ -259,21 +262,20 @@ static const struct ar0231_reg ar0231_regs_wizard_rev4[] = { + {0x3036, 0x0008}, // OP_WORD_CLK_DIV + {0x3038, 0x0001}, // OP_SYS_CLK_DIV + {0x30B0, 0x0A00}, // DIGITAL_TEST ++ + //Readout Mode Configuration + {0x30A2, 0x0001}, // X_ODD_INC_ + {0x30A6, 0x0001}, // Y_ODD_INC_ + {0x3040, 0x0000}, // READ_MODE + {0x3044, 0x0400}, // DARK_CONTROL +-{0x33E0, 0x0880}, // RESERVED_MFR_33E0 +-{0x3180, 0x0080}, // RESERVED_MFR_3180 +-{0x33E4, 0x0080}, // RESERVED_MFR_33E4 +- +-//HDR Readout Mode Configuration + #ifdef AR0231_EMBEDDED_LINE + {0x3064, 0x1982}, // SMIA_TEST + #else + {0x3064, 0x1802}, // SMIA_TEST + #endif ++{0x33E0, 0x0880}, // RESERVED_MFR_33E0 ++{0x3180, 0x0080}, // RESERVED_MFR_3180 ++{0x33E4, 0x0080}, // RESERVED_MFR_33E4 + + #if 1 + {0x3004, AR0231_X_START}, // X_ADDR_START_ +@@ -298,12 +300,8 @@ static const struct ar0231_reg ar0231_regs_wizard_rev4[] = { + //3exp Timing and Exposure + {0x3082, 0x0008}, // OPERATION_MODE_CTRL + {0x30BA, 0x11E2}, // DIGITAL_CTRL +- +-//Row and Pixel Timing +-{0x300A, 0x5af}, +-{0x300C, 0x7ba}, +- +-//Exposure Settings ++{0x300A, 0x05AF}, // FRAME_LENGTH_LINES_ ++{0x300C, 0x07BA}, // LINE_LENGTH_PCK_ + {0x3042, 0x0000}, // EXTRA_DELAY + {0x3238, 0x0222}, // EXPOSURE_RATIO + {0x1008, 0x0374}, // FINE_INTEGRATION_TIME_MIN +@@ -315,31 +313,29 @@ static const struct ar0231_reg ar0231_regs_wizard_rev4[] = { + {0x321E, 0x06A6}, // FINE_INTEGRATION_TIME2 + {0x3222, 0x06A6}, // FINE_INTEGRATION_TIME3 + {0x30B0, 0x0B02}, // DIGITAL_TEST +- + {0x32EA, 0x3C0E}, // RESERVED_MFR_32EA + {0x32EC, 0x72A1}, // RESERVED_MFR_32EC ++ + //Parallel HDR 12 bit Output + {0x31D0, 0x0001}, // COMPANDING ++{0x31AE, 0x0001}, // SERIAL_FORMAT + {0x31AC, 0x140C}, // DATA_FORMAT_BITS + +-//{0x301A, 0x01d8}, // RESET_REGISTER +-{0x301A, 0x01dc}, // RESET_REGISTER - stream on +- +-//{AR0231_DELAY, 100}, // Wait 100ms +- + #if 0 // no need for front only camera + /* Enable trigger input */ + {0x340A, 0x00E0}, // GPIO_CONTROL1: GPIO1 is trigger + {0x340C, 0x0002}, // GPIO_CONTROL2: GPIO1 is trigger + {0x30CE, 0x0120}, // TRIGGER_MODE + //{0x30DC, 0x0120}, // TRIGGER_DELAY ++{0x301A, 0x01D8}, // GPI pins enable + #endif + +-#define NEW_TIMINGS +-#ifdef NEW_TIMINGS +-/* the sequence must be updated to use following timings, now it is a hack */ ++{0x301A, 0x01DC}, // RESET_REGISTER - stream on ++ ++#if 1 + {0x300A, AR0231_SENSOR_HEIGHT + 225}, // FRAME_LENGTH_LINES_ + {0x300C, AR0231_SENSOR_WIDTH + 120}, // LINE_LENGTH_PCK_ ++/* the sequence must be updated to use following timings, now it is a hack */ + {0x1008, 0x0fff}, // FINE_INTEGRATION_TIME_MIN + {0x100C, 0x0fff}, // FINE_INTEGRATION_TIME2_MIN + {0x100E, 0x0fff}, // FINE_INTEGRATION_TIME3_MIN +diff --git a/drivers/media/i2c/soc_camera/ar0231_rev6.h b/drivers/media/i2c/soc_camera/ar0231_rev6.h +new file mode 100644 +index 0000000..12e0ce5 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0231_rev6.h +@@ -0,0 +1,343 @@ ++/* ++ * ON Semiconductor AR0231 sensor camera wizard 1920x1080@30/BGGR/MIPI ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++/* Parallel Timing Setup 27MHz In 88 MHz Out */ ++static const struct ar0231_reg ar0231_regs_wizard_rev6_dvp[] = { ++{0x301A, 0x0001}, // reset ++{0x301A, 0x10D8}, // Stream off and setup parallel ++{0x3070, 0x0000}, // 1: Solid color test pattern, ++ // 2: Full color bar test pattern, ++ // 3: Fade to grey color bar test pattern, ++ //256: Walking 1 test pattern (12 bit) ++{0x3072, 0x0123}, // R ++{0x3074, 0x0456}, // G(GR row) ++{0x3076, 0x0abc}, // B ++{0x3078, 0x0def}, // G(GB row) ++#ifdef AR0231_DISPLAY_PATTERN_FIXED ++{0x3070, 0x0001}, ++#endif ++#ifdef AR0231_DISPLAY_PATTERN_COLOR_BAR ++{0x3070, 0x0002}, ++#endif ++ ++//Recommended Settings ++{0x3056, 0x0080}, // GREEN1_GAIN ++{0x305C, 0x0080}, // GREEN2_GAIN ++{0x3058, 0x0080}, // BLUE_GAIN ++{0x305A, 0x0080}, // RED_GAIN ++{0x3138, 0x000B}, // OTPM_TCFG_OPT ++{0x3372, 0xF54F}, // RESERVED_MFR_3372 ++{0x337A, 0x0D70}, // RESERVED_MFR_337A ++{0x337E, 0x1FFD}, // RESERVED_MFR_337E ++{0x3382, 0x00C0}, // RESERVED_MFR_3382 ++{0x3C04, 0x0E80}, // RESERVED_MFR_3C04 ++{0x3F90, 0x06E1}, // RESERVED_MFR_3F90 ++{0x3F92, 0x06E1}, // RESERVED_MFR_3F92 ++{0x350E, 0x1F14}, // RESERVED_MFR_350E ++{0x350E, 0xFF10}, // RESERVED_MFR_350E ++{0x3506, 0x4444}, // RESERVED_MFR_3506 ++{0x3508, 0x4444}, // RESERVED_MFR_3508 ++{0x350A, 0x4465}, // RESERVED_MFR_350A ++{0x350C, 0x055F}, // RESERVED_MFR_350C ++{0x3566, 0x9D38}, // RESERVED_MFR_3566 ++{0x3518, 0x1FFE}, // RESERVED_MFR_3518 ++{0x3520, 0xC688}, // RESERVED_MFR_3520 ++{0x3522, 0x88C0}, // RESERVED_MFR_3522 ++{0x3524, 0xC0C6}, // RESERVED_MFR_3524 ++{0x352C, 0xC6C6}, // RESERVED_MFR_352C ++{0x3528, 0x0900}, // RESERVED_MFR_3528 ++{0x3528, 0x9900}, // RESERVED_MFR_3528 ++{0x3528, 0x9909}, // RESERVED_MFR_3528 ++{0x3528, 0x9999}, // RESERVED_MFR_3528 ++{0x352A, 0x089F}, // RESERVED_MFR_352A ++{0x352E, 0x0001}, // RESERVED_MFR_352E ++{0x352E, 0x0011}, // RESERVED_MFR_352E ++{0x3530, 0x0400}, // RESERVED_MFR_3530 ++{0x3530, 0x4400}, // RESERVED_MFR_3530 ++{0x3536, 0xFF00}, // RESERVED_MFR_3536 ++{0x3536, 0xFF00}, // RESERVED_MFR_3536 ++{0x3536, 0xFF00}, // RESERVED_MFR_3536 ++{0x3536, 0xFF00}, // RESERVED_MFR_3536 ++{0x3536, 0xFF00}, // RESERVED_MFR_3536 ++{0x3536, 0xFF00}, // RESERVED_MFR_3536 ++{0x3536, 0xFF00}, // RESERVED_MFR_3536 ++{0x3536, 0xFF00}, // RESERVED_MFR_3536 ++{0x3536, 0xFF02}, // RESERVED_MFR_3536 ++{0x3536, 0xFF06}, // RESERVED_MFR_3536 ++{0x3536, 0xFF06}, // RESERVED_MFR_3536 ++{0x3538, 0xFFFF}, // RESERVED_MFR_3538 ++{0x3538, 0xFFFF}, // RESERVED_MFR_3538 ++{0x3538, 0xFFFF}, // RESERVED_MFR_3538 ++{0x3538, 0xFFFF}, // RESERVED_MFR_3538 ++{0x3538, 0xFFFF}, // RESERVED_MFR_3538 ++{0x3538, 0xFFFF}, // RESERVED_MFR_3538 ++{0x3538, 0xFFFF}, // RESERVED_MFR_3538 ++{0x3538, 0xFFFF}, // RESERVED_MFR_3538 ++{0x3538, 0xFFFF}, // RESERVED_MFR_3538 ++{0x3538, 0xFFFF}, // RESERVED_MFR_3538 ++{0x353A, 0x9000}, // RESERVED_MFR_353A ++{0x353C, 0x3F00}, // RESERVED_MFR_353C ++{0x353C, 0x3F00}, // RESERVED_MFR_353C ++{0x353C, 0x3F00}, // RESERVED_MFR_353C ++{0x353C, 0x3F00}, // RESERVED_MFR_353C ++{0x353C, 0x3F00}, // RESERVED_MFR_353C ++{0x353C, 0x3F00}, // RESERVED_MFR_353C ++{0x32EC, 0x72A1}, // RESERVED_MFR_32EC ++{0x3540, 0xC637}, // RESERVED_MFR_3540 ++{0x3540, 0xC637}, // RESERVED_MFR_3540 ++{0x3540, 0xC637}, // RESERVED_MFR_3540 ++{0x3542, 0x584B}, // RESERVED_MFR_3542 ++{0x3542, 0x464B}, // RESERVED_MFR_3542 ++{0x3544, 0x565A}, // RESERVED_MFR_3544 ++{0x3544, 0x4B5A}, // RESERVED_MFR_3544 ++{0x3546, 0x545A}, // RESERVED_MFR_3546 ++{0x3546, 0x5A5A}, // RESERVED_MFR_3546 ++{0x3548, 0x6400}, // RESERVED_MFR_3548 ++{0x3556, 0x101F}, // RESERVED_MFR_3556 ++{0x3566, 0x9D38}, // RESERVED_MFR_3566 ++{0x3566, 0x1D38}, // RESERVED_MFR_3566 ++{0x3566, 0x1D28}, // RESERVED_MFR_3566 ++{0x3566, 0x1128}, // RESERVED_MFR_3566 ++{0x3566, 0x1328}, // RESERVED_MFR_3566 ++{0x3566, 0x3328}, // RESERVED_MFR_3566 ++{0x3528, 0xDDDD}, // RESERVED_MFR_3528 ++ ++//Sequencer Update ++{0x2512, 0x8000}, // SEQ_CTRL_PORT ++{0x2510, 0x0905}, // SEQ_DATA_PORT ++{0x2510, 0x3350}, // SEQ_DATA_PORT ++{0x2510, 0x2004}, // SEQ_DATA_PORT ++{0x2510, 0x1460}, // SEQ_DATA_PORT ++{0x2510, 0x1578}, // SEQ_DATA_PORT ++{0x2510, 0x1360}, // SEQ_DATA_PORT ++{0x2510, 0x7B24}, // SEQ_DATA_PORT ++{0x2510, 0xFF24}, // SEQ_DATA_PORT ++{0x2510, 0xFF24}, // SEQ_DATA_PORT ++{0x2510, 0xEA24}, // SEQ_DATA_PORT ++{0x2510, 0x1022}, // SEQ_DATA_PORT ++{0x2510, 0x2410}, // SEQ_DATA_PORT ++{0x2510, 0x155A}, // SEQ_DATA_PORT ++{0x2510, 0x1342}, // SEQ_DATA_PORT ++{0x2510, 0x1400}, // SEQ_DATA_PORT ++{0x2510, 0x24FF}, // SEQ_DATA_PORT ++{0x2510, 0x24FF}, // SEQ_DATA_PORT ++{0x2510, 0x24EA}, // SEQ_DATA_PORT ++{0x2510, 0x2324}, // SEQ_DATA_PORT ++{0x2510, 0x647A}, // SEQ_DATA_PORT ++{0x2510, 0x2404}, // SEQ_DATA_PORT ++{0x2510, 0x052C}, // SEQ_DATA_PORT ++{0x2510, 0x400A}, // SEQ_DATA_PORT ++{0x2510, 0xFF0A}, // SEQ_DATA_PORT ++{0x2510, 0xFF0A}, // SEQ_DATA_PORT ++{0x2510, 0x1808}, // SEQ_DATA_PORT ++{0x2510, 0x3851}, // SEQ_DATA_PORT ++{0x2510, 0x1440}, // SEQ_DATA_PORT ++{0x2510, 0x0004}, // SEQ_DATA_PORT ++{0x2510, 0x0801}, // SEQ_DATA_PORT ++{0x2510, 0x0408}, // SEQ_DATA_PORT ++{0x2510, 0x1180}, // SEQ_DATA_PORT ++{0x2510, 0x15DC}, // SEQ_DATA_PORT ++{0x2510, 0x134C}, // SEQ_DATA_PORT ++{0x2510, 0x1002}, // SEQ_DATA_PORT ++{0x2510, 0x1016}, // SEQ_DATA_PORT ++{0x2510, 0x1181}, // SEQ_DATA_PORT ++{0x2510, 0x1189}, // SEQ_DATA_PORT ++{0x2510, 0x1056}, // SEQ_DATA_PORT ++{0x2510, 0x1210}, // SEQ_DATA_PORT ++{0x2510, 0x0901}, // SEQ_DATA_PORT ++{0x2510, 0x0D08}, // SEQ_DATA_PORT ++{0x2510, 0x0913}, // SEQ_DATA_PORT ++{0x2510, 0x13C8}, // SEQ_DATA_PORT ++{0x2510, 0x092B}, // SEQ_DATA_PORT ++{0x2510, 0x1588}, // SEQ_DATA_PORT ++{0x2510, 0x1388}, // SEQ_DATA_PORT ++{0x2510, 0x090B}, // SEQ_DATA_PORT ++{0x2510, 0x11D9}, // SEQ_DATA_PORT ++{0x2510, 0x091D}, // SEQ_DATA_PORT ++{0x2510, 0x1441}, // SEQ_DATA_PORT ++{0x2510, 0x0903}, // SEQ_DATA_PORT ++{0x2510, 0x1214}, // SEQ_DATA_PORT ++{0x2510, 0x0901}, // SEQ_DATA_PORT ++{0x2510, 0x10D6}, // SEQ_DATA_PORT ++{0x2510, 0x1210}, // SEQ_DATA_PORT ++{0x2510, 0x1212}, // SEQ_DATA_PORT ++{0x2510, 0x1210}, // SEQ_DATA_PORT ++{0x2510, 0x11DD}, // SEQ_DATA_PORT ++{0x2510, 0x11D9}, // SEQ_DATA_PORT ++{0x2510, 0x1056}, // SEQ_DATA_PORT ++{0x2510, 0x090B}, // SEQ_DATA_PORT ++{0x2510, 0x11DB}, // SEQ_DATA_PORT ++{0x2510, 0x0915}, // SEQ_DATA_PORT ++{0x2510, 0x119B}, // SEQ_DATA_PORT ++{0x2510, 0x090F}, // SEQ_DATA_PORT ++{0x2510, 0x11BB}, // SEQ_DATA_PORT ++{0x2510, 0x121A}, // SEQ_DATA_PORT ++{0x2510, 0x1210}, // SEQ_DATA_PORT ++{0x2510, 0x1460}, // SEQ_DATA_PORT ++{0x2510, 0x1250}, // SEQ_DATA_PORT ++{0x2510, 0x1076}, // SEQ_DATA_PORT ++{0x2510, 0x10E6}, // SEQ_DATA_PORT ++{0x2510, 0x0901}, // SEQ_DATA_PORT ++{0x2510, 0x15AB}, // SEQ_DATA_PORT ++{0x2510, 0x0901}, // SEQ_DATA_PORT ++{0x2510, 0x13A8}, // SEQ_DATA_PORT ++{0x2510, 0x1240}, // SEQ_DATA_PORT ++{0x2510, 0x1260}, // SEQ_DATA_PORT ++{0x2510, 0x0923}, // SEQ_DATA_PORT ++{0x2510, 0x158D}, // SEQ_DATA_PORT ++{0x2510, 0x138D}, // SEQ_DATA_PORT ++{0x2510, 0x0901}, // SEQ_DATA_PORT ++{0x2510, 0x0B09}, // SEQ_DATA_PORT ++{0x2510, 0x0108}, // SEQ_DATA_PORT ++{0x2510, 0x0901}, // SEQ_DATA_PORT ++{0x2510, 0x1440}, // SEQ_DATA_PORT ++{0x2510, 0x091D}, // SEQ_DATA_PORT ++{0x2510, 0x1588}, // SEQ_DATA_PORT ++{0x2510, 0x1388}, // SEQ_DATA_PORT ++{0x2510, 0x092D}, // SEQ_DATA_PORT ++{0x2510, 0x1066}, // SEQ_DATA_PORT ++{0x2510, 0x0905}, // SEQ_DATA_PORT ++{0x2510, 0x0C08}, // SEQ_DATA_PORT ++{0x2510, 0x090B}, // SEQ_DATA_PORT ++{0x2510, 0x1441}, // SEQ_DATA_PORT ++{0x2510, 0x090D}, // SEQ_DATA_PORT ++{0x2510, 0x10E6}, // SEQ_DATA_PORT ++{0x2510, 0x0901}, // SEQ_DATA_PORT ++{0x2510, 0x1262}, // SEQ_DATA_PORT ++{0x2510, 0x1260}, // SEQ_DATA_PORT ++{0x2510, 0x11BF}, // SEQ_DATA_PORT ++{0x2510, 0x11BB}, // SEQ_DATA_PORT ++{0x2510, 0x1066}, // SEQ_DATA_PORT ++{0x2510, 0x11FB}, // SEQ_DATA_PORT ++{0x2510, 0x0935}, // SEQ_DATA_PORT ++{0x2510, 0x11BB}, // SEQ_DATA_PORT ++{0x2510, 0x1263}, // SEQ_DATA_PORT ++{0x2510, 0x1260}, // SEQ_DATA_PORT ++{0x2510, 0x1400}, // SEQ_DATA_PORT ++{0x2510, 0x1510}, // SEQ_DATA_PORT ++{0x2510, 0x11B8}, // SEQ_DATA_PORT ++{0x2510, 0x12A0}, // SEQ_DATA_PORT ++{0x2510, 0x1200}, // SEQ_DATA_PORT ++{0x2510, 0x1026}, // SEQ_DATA_PORT ++{0x2510, 0x1000}, // SEQ_DATA_PORT ++{0x2510, 0x1342}, // SEQ_DATA_PORT ++{0x2510, 0x1100}, // SEQ_DATA_PORT ++{0x2510, 0x7A06}, // SEQ_DATA_PORT ++{0x2510, 0x0915}, // SEQ_DATA_PORT ++{0x2510, 0x0507}, // SEQ_DATA_PORT ++{0x2510, 0x0841}, // SEQ_DATA_PORT ++{0x2510, 0x3750}, // SEQ_DATA_PORT ++{0x2510, 0x2C2C}, // SEQ_DATA_PORT ++{0x2510, 0xFE05}, // SEQ_DATA_PORT ++{0x2510, 0xFE13}, // SEQ_DATA_PORT ++{0x1008, 0x0361}, // FINE_INTEGRATION_TIME_MIN ++{0x100C, 0x0589}, // FINE_INTEGRATION_TIME2_MIN ++{0x100E, 0x07B1}, // FINE_INTEGRATION_TIME3_MIN ++{0x1010, 0x0139}, // FINE_INTEGRATION_TIME4_MIN ++{0x3230, 0x0304}, // FINE_CORRECTION ++{0x3232, 0x052C}, // FINE_CORRECTION2 ++{0x3234, 0x0754}, // FINE_CORRECTION3 ++{0x3236, 0x00DC}, // FINE_CORRECTION4 ++{0x3566, 0x3328}, // RESERVED_MFR_3566 ++{0x350C, 0x055F}, // RESERVED_MFR_350C ++{0x32D0, 0x3A02}, // RESERVED_MFR_32D0 ++{0x32D2, 0x3508}, // RESERVED_MFR_32D2 ++{0x32D4, 0x3702}, // RESERVED_MFR_32D4 ++{0x32D6, 0x3C04}, // RESERVED_MFR_32D6 ++{0x32DC, 0x370A}, // RESERVED_MFR_32DC ++ ++//Parallel Timing Setup 27MHz In 88 MHz Out ++{0x302A, 0x0009}, // VT_PIX_CLK_DIV ++{0x302C, 0x0001}, // VT_SYS_CLK_DIV ++{0x302E, 0x0003}, // PRE_PLL_CLK_DIV ++{0x3030, 0x0058}, // PLL_MULTIPLIER ++{0x3036, 0x0008}, // OP_WORD_CLK_DIV ++{0x3038, 0x0001}, // OP_SYS_CLK_DIV ++{0x30B0, 0x0B02}, // DIGITAL_TEST ++ ++//Readout Mode Configuration ++{0x30A2, 0x0001}, // X_ODD_INC_ ++{0x30A6, 0x0001}, // Y_ODD_INC_ ++{0x3040, 0x0000}, // READ_MODE ++{0x3082, 0x0008}, // OPERATION_MODE_CTRL ++{0x30BA, 0x11E2}, // DIGITAL_CTRL ++{0x3044, 0x0400}, // DARK_CONTROL ++#ifdef AR0231_EMBEDDED_LINE ++{0x3064, 0x1982}, // SMIA_TEST ++#else ++{0x3064, 0x1802}, // SMIA_TEST ++#endif ++{0x33E0, 0x0880}, // RESERVED_MFR_33E0 ++{0x3180, 0x0080}, // RESERVED_MFR_3180 ++{0x33E4, 0x0080}, // RESERVED_MFR_33E4 ++{0x33E0, 0x0C80}, // RESERVED_MFR_33E0 ++ ++#if 1 ++{0x3004, AR0231_X_START}, // X_ADDR_START_ ++{0x3008, AR0231_X_END}, // X_ADDR_END_ ++{0x3002, AR0231_Y_START}, // Y_ADDR_START_ ++{0x3006, AR0231_Y_END}, // Y_ADDR_END_ ++{0x3402, 0x0000 | AR0231_MAX_WIDTH}, // X_OUTPUT_CONTROL ++{0x3404, 0x0000 | AR0231_MAX_HEIGHT}, // Y_OUTPUT_CONTROL ++#else ++{0x3004, 0}, // X_ADDR_START_ ++{0x3008, 0x0787}, // X_ADDR_END_ ++{0x3002, 0x0000}, // Y_ADDR_START_ ++{0x3006, 0x04B7}, // Y_ADDR_END_ ++{0x3402, 0x0788}, // RESERVED_MFR_3402 ++{0x3402, 0x0F10}, // RESERVED_MFR_3402 ++{0x3404, 0x0440}, // RESERVED_MFR_3404 ++{0x3404, 0x0970}, // RESERVED_MFR_3404 ++#endif ++{0x3032, 0x0000}, // SCALING_MODE ++{0x3400, 0x0010}, // RESERVED_MFR_3400 ++ ++//3exp Timing and Exposure ++{0x3082, 0x0008}, // OPERATION_MODE_CTRL ++{0x30BA, 0x11E2}, // DIGITAL_CTRL ++{0x300A, 0x05CA}, // FRAME_LENGTH_LINES_ ++{0x300C, 0x07BA}, // LINE_LENGTH_PCK_ ++{0x3042, 0x0000}, // EXTRA_DELAY ++{0x3238, 0x0222}, // EXPOSURE_RATIO ++{0x3012, 0x0163}, // COARSE_INTEGRATION_TIME_ ++{0x3014, 0x08CC}, // FINE_INTEGRATION_TIME_ ++{0x321E, 0x08CC}, // FINE_INTEGRATION_TIME2 ++{0x3222, 0x0254}, // FINE_INTEGRATION_TIME3 ++{0x30B0, 0x0A00}, // DIGITAL_TEST ++{0x32EA, 0x3C0E}, // RESERVED_MFR_32EA ++{0x32EC, 0x72A1}, // RESERVED_MFR_32EC ++ ++//Parallel HDR 12 bit Output ++{0x31D0, 0x0001}, // COMPANDING ++{0x31AE, 0x0001}, // SERIAL_FORMAT ++{0x31AC, 0x140C}, // DATA_FORMAT_BITS ++ ++#if 0 // no need for front only camera ++/* Enable trigger input */ ++{0x340A, 0x00E0}, // GPIO_CONTROL1: GPIO1 is trigger ++{0x340C, 0x0002}, // GPIO_CONTROL2: GPIO1 is trigger ++{0x30CE, 0x0120}, // TRIGGER_MODE ++//{0x30DC, 0x0120}, // TRIGGER_DELAY ++{0x301A, 0x01D8}, // GPI pins enable ++#endif ++ ++{0x301A, 0x01DC}, // RESET_REGISTER - stream on ++ ++#if 1 ++{0x300A, AR0231_SENSOR_HEIGHT + 225}, // FRAME_LENGTH_LINES_ ++{0x300C, AR0231_SENSOR_WIDTH + 120}, // LINE_LENGTH_PCK_ ++/* the sequence must be updated to use following timings, now it is a hack */ ++{0x1008, 0x0fff}, // FINE_INTEGRATION_TIME_MIN ++{0x100C, 0x0fff}, // FINE_INTEGRATION_TIME2_MIN ++{0x100E, 0x0fff}, // FINE_INTEGRATION_TIME3_MIN ++{0x1010, 0x0fff}, // FINE_INTEGRATION_TIME4_MIN ++#endif ++}; +diff --git a/drivers/media/i2c/soc_camera/ar0231_rev7.h b/drivers/media/i2c/soc_camera/ar0231_rev7.h +index c05c3ea..885d34e 100644 +--- a/drivers/media/i2c/soc_camera/ar0231_rev7.h ++++ b/drivers/media/i2c/soc_camera/ar0231_rev7.h +@@ -9,27 +9,6 @@ + * option) any later version. + */ + +-//#define AR0231_DISPLAY_PATTERN_FIXED +-//#define AR0231_DISPLAY_PATTERN_COLOR_BAR +- +-#define AR0231_MAX_WIDTH 1920 +-#define AR0231_MAX_HEIGHT 1200 +- +-#define AR0231_DELAY 0xffff +- +-#define AR0231_SENSOR_WIDTH 1928 +-#define AR0231_SENSOR_HEIGHT 1208 +- +-#define AR0231_X_START ((AR0231_SENSOR_WIDTH - AR0231_MAX_WIDTH) / 2) +-#define AR0231_Y_START ((AR0231_SENSOR_HEIGHT - AR0231_MAX_HEIGHT) / 2) +-#define AR0231_X_END (AR0231_X_START + AR0231_MAX_WIDTH - 1) +-#define AR0231_Y_END (AR0231_Y_START + AR0231_MAX_HEIGHT - 1) +- +-struct ar0231_reg { +- u16 reg; +- u16 val; +-}; +- + /* 3Exp HDR Full Resolution Mode MIPI 4lane 12bit 30FPS, XCLK=27MHz */ + static const struct ar0231_reg ar0231_regs_wizard_rev7[] = { + {0x301A, 0x18}, // MIPI, stream OFF +@@ -322,12 +301,14 @@ static const struct ar0231_reg ar0231_regs_wizard_rev7[] = { + #endif /* Sensor Setup */ + + #if 1 /* Serial 12-bit Timing Setup */ +-{0x302A, 6}, // vt_pix_clk_div +-{0x302C, 1}, // vt_sys_clk_div ++/* PCLK=27Mhz/PRE_PLL_CLK_DIV *PLL_MULTIPLIER /P1 /P4 *2 */ ++/* PCLK=27Mhz/2 *44/1/12 *2= 99Mhz - TI serializers */ ++{0x302A, 6}, // vt_pix_clk_div (P2 divider) ++{0x302C, 1}, // vt_sys_clk_div (P1 divider) + {0x302E, 2}, // pre_pll_clk_div + {0x3030, 44}, // pll_multiplier +-{0x3036, 12}, // op_word_clk_div +-{0x3038, 1}, // op_sys_clk_div ++{0x3036, 12}, // op_word_clk_div (P4 divider) ++{0x3038, 1}, // op_sys_clk_div (P3 divider) + {0x30B0, 0x800}, // digital_test: pll_complete_bypass=0 + #endif /* Serial 12-bit Timing Setup */ + +@@ -416,3 +397,49 @@ static const struct ar0231_reg ar0231_regs_wizard_rev7[] = { + {0x301A, 0x0118}, // GPI pins enable + #endif + }; ++ ++/* 3Exp HDR Full Resolution Mode Parallel 12bit 30FPS, XCLK=24MHz */ ++static const struct ar0231_reg ar0231_regs_wizard_rev7_dvp[] = { ++#if 1 /* Parallel Timing Setup */ ++/* PCLK=24Mhz/PRE_PLL_CLK_DIV *PLL_MULTIPLIER /P1 /P4 */ ++/* PCLK=24Mhz/3 *88/1/8 = 88Mhz - TI serializers */ ++{0x302A, 8}, // vt_pix_clk_div (P2 divider) ++{0x302C, 1}, // vt_sys_clk_div (P1 divider) ++{0x302E, 3}, // pre_pll_clk_div ++{0x3030, 88}, // pll_multiplier ++{0x3036, 8}, // op_word_clk_div (P4 divider) ++{0x3038, 1}, // op_sys_clk_div (P3 divider) ++{0x30B0, 0x800}, // digital_test: pll_complete_bypass=0 ++#endif ++ ++#if 1 /* 3exp Timing and Exposure - Parallel */ ++{0x3082, 0x8}, // operation_mode_ctrl ++{0x30BA, 0x11E2}, // digital_ctrl: num_exp_max=2 ++ ++/* Row and Pixel Timing */ ++#if 1 ++{0x300A, AR0231_SENSOR_HEIGHT + 225}, // frame_length_lines_ ++{0x300C, AR0231_SENSOR_WIDTH + 120}, // line_length_pck_ ++#else ++{0x300C, 1978}, // line_length_pck_ ++{0x300A, 1482}, // frame_length_lines_ ++#endif ++{0x3042, 0}, // extra_delay ++ ++/* Exposure Settings */ ++//{0x3238, 0x222}, // exposure_ratio ++//{0x3012, 355}, // coarse_integration_time_ ++{0x3014, 2178}, // fine_integration_time_ ++{0x321E, 2178}, // fine_integration_time2 ++{0x3222, 2178}, // fine_integration_time3 ++{0x30B0, 0x800}, // digital_test: set bit11 ++{0x32EA, 0x3C0E}, ++{0x32EC, 0x72A1}, ++#endif /* 3exp Timing and Exposure - Parallel */ ++ ++#if 1 /* Parallel HDR 12 bit Output */ ++{0x31AE, 0x001}, // serial_format: ++#endif ++ ++{0x301A, 0x01d8}, // RESET_REGISTER parallel pins enable ++}; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0144-lvds-add-OV10640-imager.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0144-lvds-add-OV10640-imager.patch new file mode 100644 index 00000000..c2dce0a8 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0144-lvds-add-OV10640-imager.patch @@ -0,0 +1,3174 @@ +From e454ddd45aaf59fd3ad98a9ec35e70051270a579 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Mon, 14 Jan 2019 16:36:37 +0300 +Subject: [PATCH 093/122] lvds: add OV10640 imager + +This adds OV10640 imager support (RDACM24B) + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ov10640.c | 685 +++++++++ + drivers/media/i2c/soc_camera/ov10640.h | 2407 ++++++++++++++++++++++++++++++++ + drivers/media/i2c/soc_camera/ov106xx.c | 13 +- + 3 files changed, 3104 insertions(+), 1 deletion(-) + create mode 100644 drivers/media/i2c/soc_camera/ov10640.c + create mode 100644 drivers/media/i2c/soc_camera/ov10640.h + +diff --git a/drivers/media/i2c/soc_camera/ov10640.c b/drivers/media/i2c/soc_camera/ov10640.c +new file mode 100644 +index 0000000..8746988 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov10640.c +@@ -0,0 +1,685 @@ ++/* ++ * OmniVision ov10640 sensor camera driver ++ * ++ * Copyright (C) 2015-2017 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "max9286.h" ++#include "ov10640.h" ++ ++#define OV10640_I2C_ADDR 0x30 ++ ++#define OV10640_PID 0x300a ++#define OV10640_VER 0x300b ++#define OV10640_VERSION_REG 0xa640 ++ ++#define OV10640_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR12_1X12 ++ ++struct ov10640_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int subsampling; ++ int fps_denominator; ++ int init_complete; ++ u8 id[6]; ++ int dvp_order; ++ /* serializers */ ++ int max9286_addr; ++ int max9271_addr; ++ int ti9x4_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++}; ++ ++static inline struct ov10640_priv *to_ov10640(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct ov10640_priv, sd); ++} ++ ++static inline struct v4l2_subdev *ov10640_to_sd(struct v4l2_ctrl *ctrl) ++{ ++ return &container_of(ctrl->handler, struct ov10640_priv, hdl)->sd; ++} ++ ++static void ov10640_s_port(struct i2c_client *client, int fwd_en) ++{ ++ struct ov10640_priv *priv = to_ov10640(client); ++ int tmp_addr; ++ ++ if (priv->max9286_addr) { ++ tmp_addr = client->addr; ++ client->addr = priv->max9286_addr; /* Deserializer I2C address */ ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ client->addr = tmp_addr; ++ }; ++} ++ ++static int ov10640_set_regs(struct i2c_client *client, ++ const struct ov10640_reg *regs, int nr_regs) ++{ ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (regs[i].reg == OV10640_DELAY) { ++ mdelay(regs[i].val); ++ continue; ++ } ++ ++ if (reg16_write(client, regs[i].reg, regs[i].val)) { ++ usleep_range(100, 150); /* wait 100ns */ ++ reg16_write(client, regs[i].reg, regs[i].val); ++ } ++ } ++ ++ return 0; ++} ++ ++static int ov10640_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int ov10640_set_window(struct v4l2_subdev *sd) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10640_priv *priv = to_ov10640(client); ++ ++ dev_dbg(&client->dev, "L=%d T=%d %dx%d\n", priv->rect.left, priv->rect.top, priv->rect.width, priv->rect.height); ++ ++ /* horiz crop start (reverse) */ ++ reg16_write(client, 0x3074, (OV10640_MAX_WIDTH - priv->rect.width - priv->rect.left) >> 8); ++ reg16_write(client, 0x3075, (OV10640_MAX_WIDTH - priv->rect.width - priv->rect.left) & 0xff); ++ /* horiz crop end (reverse) */ ++ reg16_write(client, 0x3078, (OV10640_MAX_WIDTH - priv->rect.left - 1) >> 8); ++ reg16_write(client, 0x3079, (OV10640_MAX_WIDTH - priv->rect.left - 1) & 0xff); ++ /* vert crop start */ ++ reg16_write(client, 0x3076, priv->rect.top >> 8); ++ reg16_write(client, 0x3077, priv->rect.top & 0xff); ++ /* vert crop end */ ++ reg16_write(client, 0x307a, (priv->rect.top + priv->rect.height + 1) >> 8); ++ reg16_write(client, 0x307b, (priv->rect.top + priv->rect.height + 1) & 0xff); ++ /* horiz output */ ++ reg16_write(client, 0x307c, priv->rect.width >> 8); ++ reg16_write(client, 0x307d, priv->rect.width & 0xff); ++ /* vert output */ ++ reg16_write(client, 0x307e, priv->rect.height >> 8); ++ reg16_write(client, 0x307f, priv->rect.height & 0xff); ++ ++ return 0; ++}; ++ ++static int ov10640_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10640_priv *priv = to_ov10640(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = OV10640_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int ov10640_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = OV10640_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int ov10640_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = OV10640_MEDIA_BUS_FMT; ++ ++ return 0; ++} ++ ++static int ov10640_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10640_priv *priv = to_ov10640(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = OV10640_VERSION_REG >> 8; ++ edid->edid[9] = OV10640_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int ov10640_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10640_priv *priv = to_ov10640(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > OV10640_MAX_WIDTH) || ++ (rect->top + rect->height > OV10640_MAX_HEIGHT)) ++ *rect = priv->rect; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ ov10640_set_window(sd); ++ ++ return 0; ++} ++ ++static int ov10640_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10640_priv *priv = to_ov10640(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = OV10640_MAX_WIDTH; ++ sel->r.height = OV10640_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = OV10640_MAX_WIDTH; ++ sel->r.height = OV10640_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ov10640_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int ov10640_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u8 val = 0; ++ ++ ret = reg16_read(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int ov10640_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return reg16_write(client, (u16)reg->reg, (u8)reg->val); ++} ++#endif ++ ++static struct v4l2_subdev_core_ops ov10640_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ov10640_g_register, ++ .s_register = ov10640_s_register, ++#endif ++}; ++ ++static int ov10640_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = ov10640_to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10640_priv *priv = to_ov10640(client); ++ int ret = -EINVAL; ++ u8 val = 0; ++ u16 val16 = 0; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ case V4L2_CID_CONTRAST: ++ case V4L2_CID_SATURATION: ++ case V4L2_CID_HUE: ++ case V4L2_CID_GAMMA: ++ break; ++ case V4L2_CID_GAIN: ++ reg16_write(client, 0x30EC, ctrl->val); // L ++ reg16_write(client, 0x30EE, ctrl->val); // S ++ reg16_write(client, 0x30F0, ctrl->val); // VS ++ break; ++ case V4L2_CID_ANALOGUE_GAIN: ++ reg16_read(client, 0x30EB, &val); ++ val &= ~(0x3f << 0); // VS, S, L - Gauss curve ++ val |= ((ctrl->val / 2) << 0); // L ++ val |= (ctrl->val << 2); // S ++ val |= ((ctrl->val / 2) << 4); // VS ++ reg16_write(client, 0x30EB, val); ++ break; ++ case V4L2_CID_EXPOSURE: ++ val16 = 0xfff - ctrl->val; ++ ++ reg16_write(client, 0x30E6, val16 >> 8); // L ++ reg16_write(client, 0x30E7, val16 & 0xff); // L ++ ++ reg16_write(client, 0x30E8, val16 >> 8); // S ++ reg16_write(client, 0x30E9, val16 & 0xff); // S ++ ++// reg16_write(client, 0x30EA, val >> 8); // VS - fractional ... ++ break; ++ case V4L2_CID_EXPOSURE_AUTO: ++ reg16_read(client, 0x30FA, &val); ++ val &= ~(0x1 << 6); ++ val |= (ctrl->val << 6); ++ reg16_write(client, 0x30FA, val); ++ break; ++ case V4L2_CID_HFLIP: ++ reg16_read(client, 0x3128, &val); ++ val &= ~(0x1 << 0); ++ val |= (ctrl->val << 0); ++ reg16_write(client, 0x3128, val); ++ ++ reg16_read(client, 0x3291, &val); ++ val &= ~(0x1 << 1); ++ val |= (ctrl->val << 1); ++ reg16_write(client, 0x3291, val); ++ ++ reg16_read(client, 0x3090, &val); ++ val &= ~(0x1 << 2); ++ val |= (ctrl->val << 2); ++ ret = reg16_write(client, 0x3090, val); ++ break; ++ case V4L2_CID_VFLIP: ++ reg16_read(client, 0x3128, &val); ++ val &= ~(0x1 << 1); ++ val |= (ctrl->val << 1); ++ reg16_write(client, 0x3128, val); ++ ++ reg16_read(client, 0x3291, &val); ++ val &= ~(0x1 << 2); ++ val |= (ctrl->val << 2); ++ reg16_write(client, 0x3291, val); ++ ++ reg16_read(client, 0x3090, &val); ++ val &= ~(0x1 << 3); ++ val |= (ctrl->val << 3); ++ ret = reg16_write(client, 0x3090, val); ++ break; ++ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: ++ ret = 0; ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ov10640_ctrl_ops = { ++ .s_ctrl = ov10640_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops ov10640_video_ops = { ++ .s_stream = ov10640_s_stream, ++ .g_mbus_config = ov10640_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops ov10640_subdev_pad_ops = { ++ .get_edid = ov10640_get_edid, ++ .enum_mbus_code = ov10640_enum_mbus_code, ++ .get_selection = ov10640_get_selection, ++ .set_selection = ov10640_set_selection, ++ .get_fmt = ov10640_get_fmt, ++ .set_fmt = ov10640_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops ov10640_subdev_ops = { ++ .core = &ov10640_core_ops, ++ .video = &ov10640_video_ops, ++ .pad = &ov10640_subdev_pad_ops, ++}; ++ ++static void ov10640_otp_id_read(struct i2c_client *client) ++{ ++ struct ov10640_priv *priv = to_ov10640(client); ++ int i; ++ int otp_bank0_allzero = 1; ++ ++ reg16_write(client, 0x349C, 1); ++ usleep_range(25000, 25500); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i++) { ++ /* first 6 bytes are equal on all ov10640 */ ++ reg16_read(client, 0x349e + i + 6, &priv->id[i]); ++ if (priv->id[i]) ++ otp_bank0_allzero = 0; ++ } ++ ++ if (otp_bank0_allzero) { ++ reg16_write(client, 0x3495, 0x41); /* bank#1 */ ++ reg16_write(client, 0x349C, 1); ++ usleep_range(25000, 25500); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i++) ++ reg16_read(client, 0x34ae + i, &priv->id[i]); ++ } ++} ++ ++static ssize_t ov10640_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10640_priv *priv = to_ov10640(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_ov10640, S_IRUGO, ov10640_otp_id_show, NULL); ++ ++static int ov10640_initialize(struct i2c_client *client) ++{ ++ struct ov10640_priv *priv = to_ov10640(client); ++ u16 pid; ++ u8 val = 0; ++ int ret = 0; ++ ++ ov10640_s_port(client, 1); ++ ++ /* check and show product ID and manufacturer ID */ ++ reg16_read(client, OV10640_PID, &val); ++ pid = val; ++ reg16_read(client, OV10640_VER, &val); ++ pid = (pid << 8) | val; ++ ++ if (pid != OV10640_VERSION_REG) { ++ dev_err(&client->dev, "Product ID error %x\n", pid); ++ ret = -ENODEV; ++ goto out; ++ } ++ ++ /* Read OTP IDs */ ++ ov10640_otp_id_read(client); ++ /* Program wizard registers */ ++ ov10640_set_regs(client, ov10640_regs_wizard_r1e, ARRAY_SIZE(ov10640_regs_wizard_r1e)); ++ ++ dev_info(&client->dev, "ov10640 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, OV10640_MAX_WIDTH, OV10640_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++out: ++ ov10640_s_port(client, 0); ++ ++ return ret; ++} ++ ++static int ov10640_parse_dt(struct device_node *np, struct ov10640_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order); ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ if (!priv->max9286_addr && !priv->ti9x4_addr) { ++ dev_err(&client->dev, "deserializer does not present for OV10640\n"); ++ return -EINVAL; ++ } ++ ++ ov10640_s_port(client, 1); ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ ++ reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x0A, OV10640_I2C_ADDR << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, OV10640_I2C_ADDR << 1); /* Sensor native I2C address */ ++ ++// reg8_write(client, 0x6e, 0x9a); /* GPIO0 - fsin, GPIO1 - resetb */ ++// udelay(100); ++ } ++ client->addr = tmp_addr; ++ ++ return 0; ++} ++ ++static int ov10640_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ov10640_priv *priv; ++ struct v4l2_ctrl *ctrl; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &ov10640_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = OV10640_MAX_WIDTH; ++ priv->rect.height = OV10640_MAX_HEIGHT; ++ priv->fps_denominator = 30; ++ ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10640_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 0xff, 1, 0x30); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10640_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 4, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10640_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 0xff, 1, 0xff); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10640_ctrl_ops, ++ V4L2_CID_HUE, 0, 255, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10640_ctrl_ops, ++ V4L2_CID_GAMMA, 0, 0xffff, 1, 0x233); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10640_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0x3f, 1, 0x1); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10640_ctrl_ops, ++ V4L2_CID_ANALOGUE_GAIN, 0, 3, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10640_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0xfff, 1, 0x448); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10640_ctrl_ops, ++ V4L2_CID_EXPOSURE_AUTO, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10640_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10640_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov10640_ctrl_ops, ++ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 9); ++ if (ctrl) ++ ctrl->flags &= ~V4L2_CTRL_FLAG_READ_ONLY; ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = ov10640_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = ov10640_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ov10640) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_OV10640 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int ov10640_remove(struct i2c_client *client) ++{ ++ struct ov10640_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ov10640); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_OV10640 ++static const struct i2c_device_id ov10640_id[] = { ++ { "ov10640", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ov10640_id); ++ ++static const struct of_device_id ov10640_of_ids[] = { ++ { .compatible = "ovti,ov10640", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ov10640_of_ids); ++ ++static struct i2c_driver ov10640_i2c_driver = { ++ .driver = { ++ .name = "ov10640", ++ .of_match_table = ov10640_of_ids, ++ }, ++ .probe = ov10640_probe, ++ .remove = ov10640_remove, ++ .id_table = ov10640_id, ++}; ++ ++module_i2c_driver(ov10640_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for OV10640"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/ov10640.h b/drivers/media/i2c/soc_camera/ov10640.h +new file mode 100644 +index 0000000..dbc6c0b +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov10640.h +@@ -0,0 +1,2407 @@ ++/* ++ * OmniVision ov10640 sensor camera wizard 1280x800@30/UYVY/BT601/8bit ++ * ++ * Copyright (C) 2015-2017 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++//#define OV10640_DISPLAY_PATTERN ++#define OV10640_FSIN_ENABLE ++ ++#define OV10640_MAX_WIDTH 1280 ++#define OV10640_MAX_HEIGHT 1080 ++ ++#define OV10640_DELAY 0xffff ++ ++#define OV10640_SENSOR_WIDTH 1292 ++#define OV10640_SENSOR_HEIGHT 1092 ++ ++#define OV10640_X_START ((OV10640_SENSOR_WIDTH - OV10640_MAX_WIDTH) / 2) ++#define OV10640_Y_START ((OV10640_SENSOR_HEIGHT - OV10640_MAX_HEIGHT) / 2) ++#define OV10640_X_END (OV10640_X_START + OV10640_MAX_WIDTH - 1) ++#define OV10640_Y_END (OV10640_Y_START + OV10640_MAX_HEIGHT - 1) ++ ++struct ov10640_reg { ++ u16 reg; ++ u8 val; ++}; ++ ++/* DVP_1280x1080_COMB12_raw 60fps */ ++static const struct ov10640_reg ov10640_regs_wizard_r1f[] = { ++{0x3013, 0x01}, ++{OV10640_DELAY, 10}, ++{0x31be, 0x01}, ++{0x3133, 0xb7}, ++{0x3134, 0xca}, ++{0x3135, 0xcc}, ++{0x313f, 0x80}, ++{0x3132, 0x24}, ++{0x3000, 0x03}, ++{0x3001, 0x62}, ++{0x3002, 0x07}, ++//{0x3002, 0x0f}, // for 30fps wizard ++{0x3004, 0x03}, ++#if 0 ++{0x3005, 0x62}, ++#else ++{0x3005, 0x48}, ++#endif ++{0x3006, 0x07}, ++{0x3007, 0x01}, ++{0x3023, 0x05}, ++{0x3032, 0x35}, ++{0x3033, 0x04}, ++{0x3054, 0x00}, ++{0x3055, 0x0f}, ++{0x3056, 0x01}, ++{0x3057, 0xff}, ++{0x3058, 0xaf}, ++{0x3059, 0x44}, ++{0x305a, 0x02}, ++{0x305b, 0x00}, ++{0x305c, 0x30}, ++{0x305d, 0x9e}, ++{0x305e, 0x19}, ++{0x305f, 0x18}, ++{0x3060, 0xf9}, ++{0x3061, 0xf0}, ++#ifdef OV10640_FSIN_ENABLE ++{0x308c, 0xb2}, ++#else ++{0x308c, 0x03}, ++#endif ++{0x308f, 0x10}, ++{0x3090, 0x00}, ++{0x3091, 0x00}, ++{0x30eb, 0x00}, ++{0x30a3, 0x08}, ++{0x30ad, 0x03}, ++{0x30ae, 0x80}, ++{0x30af, 0x80}, ++{0x30b0, 0xff}, ++{0x30b1, 0x3f}, ++{0x30b2, 0x22}, ++{0x30b9, 0x22}, ++{0x30bb, 0x00}, ++{0x30bc, 0x00}, ++{0x30bd, 0x00}, ++{0x30be, 0x00}, ++{0x30bf, 0x00}, ++{0x30c0, 0x00}, ++{0x30c1, 0x00}, ++{0x30c2, 0x00}, ++{0x30c3, 0x00}, ++{0x30c4, 0x80}, ++{0x30c5, 0x00}, ++{0x30c6, 0x80}, ++{0x30c7, 0x00}, ++{0x30c8, 0x80}, ++{0x3119, 0x44}, ++{0x311a, 0x01}, ++{0x311b, 0x4a}, ++{0x3074, 0x00}, ++{0x3075, 0x00}, ++{0x3076, 0x00}, ++{0x3077, 0x02}, ++{0x3078, 0x05}, ++{0x3079, 0x07}, ++{0x307a, 0x04}, ++{0x307b, 0x41}, ++{0x307c, 0x05}, ++{0x307d, 0x00}, ++{0x307e, 0x04}, ++{0x307f, 0x38}, ++#if 0 ++{0x3080, 0x05}, ++{0x3081, 0xbe}, ++#else ++{0x3080, 0x06}, // minimal VTS for FPDLINK3 ++{0x3081, 0xe0}, ++#endif ++{0x3082, 0x04}, ++{0x3083, 0x57}, ++{0x3084, 0x00}, ++{0x3085, 0x04}, ++{0x3086, 0x00}, ++{0x3087, 0x04}, ++{0x3088, 0x00}, ++{0x3089, 0x40}, ++{0x308d, 0x92}, ++{0x3094, 0xa5}, ++{0x30e6, 0x04}, ++{0x30e7, 0x48}, ++{0x30e8, 0x04}, ++{0x30e9, 0x48}, ++{0x30ea, 0x11}, ++{0x30ec, 0x01}, ++{0x30fa, 0x06}, ++{0x3120, 0x00}, ++{0x3121, 0x01}, ++{0x3122, 0x00}, ++{0x3127, 0x63}, ++{0x3128, 0xc0}, ++#ifdef OV10640_DISPLAY_PATTERN ++{0x3129, 0x80}, ++#else ++{0x3129, 0x00}, ++#endif ++{0x31be, 0x01}, ++{0x30a5, 0x78}, ++{0x30a6, 0x40}, ++{0x30a7, 0x78}, ++{0x30a8, 0x80}, ++{0x30a9, 0x79}, ++{0x30aa, 0x00}, ++{0x30ab, 0x79}, ++{0x30ac, 0xf8}, ++{0x3440, 0x04}, ++{0x3444, 0x28}, ++{0x344e, 0x2c}, ++{0x3457, 0x33}, ++{0x345e, 0x38}, ++{0x3461, 0xa8}, ++{0x7002, 0xaa}, ++{0x7001, 0xdf}, ++{0x7048, 0x00}, ++{0x7049, 0x02}, ++{0x704a, 0x02}, ++{0x704b, 0x00}, ++{0x704c, 0x01}, ++{0x704d, 0x00}, ++{0x7043, 0x04}, ++{0x7040, 0x3c}, ++{0x7047, 0x00}, ++{0x7044, 0x01}, ++{0x7000, 0x1f}, ++{0x7084, 0x01}, ++{0x7085, 0x03}, ++{0x7086, 0x02}, ++{0x7087, 0x40}, ++{0x7088, 0x01}, ++{0x7089, 0x20}, ++{0x707f, 0x04}, ++{0x707c, 0x3c}, ++{0x7083, 0x00}, ++{0x7080, 0x01}, ++{0x7003, 0xdf}, ++{0x70c0, 0x00}, ++{0x70c1, 0x02}, ++{0x70c2, 0x02}, ++{0x70c3, 0x00}, ++{0x70c4, 0x01}, ++{0x70c5, 0x00}, ++{0x70b8, 0x03}, ++{0x70b9, 0x98}, ++{0x70bc, 0x00}, ++{0x70bd, 0x80}, ++{0x7004, 0x02}, ++{0x7005, 0x00}, ++{0x7006, 0x01}, ++{0x7007, 0x80}, ++{0x7008, 0x02}, ++{0x7009, 0x00}, ++{0x700a, 0x04}, ++{0x700b, 0x00}, ++{0x700e, 0x00}, ++{0x700f, 0x60}, ++{0x701a, 0x02}, ++{0x701b, 0x00}, ++{0x701c, 0x01}, ++{0x701d, 0x80}, ++{0x701e, 0x02}, ++{0x701f, 0x00}, ++{0x7020, 0x04}, ++{0x7021, 0x00}, ++{0x7024, 0x00}, ++{0x7025, 0x60}, ++{0x70e7, 0x00}, ++{0x70e4, 0x10}, ++{0x70e5, 0x00}, ++{0x70e6, 0x00}, ++{0x70eb, 0x00}, ++{0x70e8, 0x10}, ++{0x70e9, 0x00}, ++{0x70ea, 0x00}, ++{0x70ef, 0x00}, ++{0x70ec, 0xfd}, ++{0x70ed, 0x00}, ++{0x70ee, 0x00}, ++{0x70eb, 0x00}, ++{0x70f0, 0xfd}, ++{0x70f1, 0x00}, ++{0x70f2, 0x00}, ++{0x30fb, 0x06}, ++{0x30fc, 0x80}, ++{0x30fd, 0x02}, ++{0x30fe, 0x93}, ++{0x6000, 0xc1}, ++{0x6001, 0xb9}, ++{0x6002, 0xba}, ++{0x6003, 0xa4}, ++{0x6004, 0xa4}, ++{0x6005, 0xb5}, ++{0x6006, 0xa0}, ++{0x6007, 0x82}, ++{0x6008, 0xa7}, ++{0x6009, 0xa7}, ++{0x600a, 0xb7}, ++{0x600b, 0x5c}, ++{0x600c, 0x9e}, ++{0x600d, 0xc0}, ++{0x600e, 0xd2}, ++{0x600f, 0x33}, ++{0x6010, 0xcc}, ++{0x6011, 0xe2}, ++{0x6012, 0xc1}, ++{0x6013, 0xab}, ++{0x6014, 0xab}, ++{0x6015, 0xb7}, ++{0x6016, 0x00}, ++{0x6017, 0x00}, ++{0x6018, 0x00}, ++{0x6019, 0x00}, ++{0x601a, 0x00}, ++{0x601b, 0x00}, ++{0x601c, 0x00}, ++{0x601d, 0x00}, ++{0x601e, 0x00}, ++{0x601f, 0x00}, ++{0x6020, 0x00}, ++{0x6021, 0x00}, ++{0x6022, 0x00}, ++{0x6023, 0x9c}, ++{0x6024, 0x94}, ++{0x6025, 0x90}, ++{0x6026, 0xc5}, ++{0x6027, 0x00}, ++{0x6028, 0x54}, ++{0x6029, 0x2a}, ++{0x602a, 0x61}, ++{0x602b, 0xd2}, ++{0x602c, 0xcc}, ++{0x602d, 0x04}, ++{0x602e, 0x35}, ++{0x602f, 0xb1}, ++{0x6030, 0xb2}, ++{0x6031, 0xb3}, ++{0x6032, 0xd2}, ++{0x6033, 0xd3}, ++{0x6034, 0x11}, ++{0x6035, 0x31}, ++{0x6036, 0xcc}, ++{0x6037, 0x06}, ++{0x6038, 0xd2}, ++{0x6039, 0x00}, ++{0x603a, 0xce}, ++{0x603b, 0x18}, ++{0x603c, 0xcf}, ++{0x603d, 0x1e}, ++{0x603e, 0xd0}, ++{0x603f, 0x24}, ++{0x6040, 0xc5}, ++{0x6041, 0xd2}, ++{0x6042, 0xbc}, ++{0x6043, 0xcc}, ++{0x6044, 0x52}, ++{0x6045, 0x2b}, ++{0x6046, 0xd2}, ++{0x6047, 0xd3}, ++{0x6048, 0x01}, ++{0x6049, 0xcc}, ++{0x604a, 0x0a}, ++{0x604b, 0xd2}, ++{0x604c, 0xd3}, ++{0x604d, 0x0f}, ++{0x604e, 0x1a}, ++{0x604f, 0x2a}, ++{0x6050, 0xd4}, ++{0x6051, 0xe3}, ++{0x6052, 0xba}, ++{0x6053, 0x56}, ++{0x6054, 0xd3}, ++{0x6055, 0x2e}, ++{0x6056, 0x54}, ++{0x6057, 0x26}, ++{0x6058, 0xd2}, ++{0x6059, 0xcc}, ++{0x605a, 0x60}, ++{0x605b, 0xd2}, ++{0x605c, 0xd3}, ++{0x605d, 0x27}, ++{0x605e, 0x27}, ++{0x605f, 0x08}, ++{0x6060, 0x1a}, ++{0x6061, 0xcc}, ++{0x6062, 0x88}, ++{0x6063, 0x00}, ++{0x6064, 0x12}, ++{0x6065, 0x2c}, ++{0x6066, 0x60}, ++{0x6067, 0xc2}, ++{0x6068, 0xb9}, ++{0x6069, 0xa5}, ++{0x606a, 0xa5}, ++{0x606b, 0xb5}, ++{0x606c, 0xa0}, ++{0x606d, 0x82}, ++{0x606e, 0x5c}, ++{0x606f, 0xd4}, ++{0x6070, 0xab}, ++{0x6071, 0xd4}, ++{0x6072, 0xab}, ++{0x6073, 0xd3}, ++{0x6074, 0x01}, ++{0x6075, 0x7c}, ++{0x6076, 0x74}, ++{0x6077, 0x00}, ++{0x6078, 0x61}, ++{0x6079, 0x2a}, ++{0x607a, 0xd2}, ++{0x607b, 0xcc}, ++{0x607c, 0xdf}, ++{0x607d, 0xc6}, ++{0x607e, 0x35}, ++{0x607f, 0xd2}, ++{0x6080, 0xcc}, ++{0x6081, 0x06}, ++{0x6082, 0x31}, ++{0x6083, 0xd2}, ++{0x6084, 0x00}, ++{0x6085, 0xbb}, ++{0x6086, 0xcc}, ++{0x6087, 0x18}, ++{0x6088, 0xc6}, ++{0x6089, 0xd2}, ++{0x608a, 0xbd}, ++{0x608b, 0xcc}, ++{0x608c, 0x52}, ++{0x608d, 0x2b}, ++{0x608e, 0xd2}, ++{0x608f, 0xd3}, ++{0x6090, 0x01}, ++{0x6091, 0xcc}, ++{0x6092, 0x0a}, ++{0x6093, 0xd2}, ++{0x6094, 0xd3}, ++{0x6095, 0x0f}, ++{0x6096, 0x1a}, ++{0x6097, 0x71}, ++{0x6098, 0x2a}, ++{0x6099, 0xd4}, ++{0x609a, 0xe3}, ++{0x609b, 0xd3}, ++{0x609c, 0x22}, ++{0x609d, 0x70}, ++{0x609e, 0xca}, ++{0x609f, 0x26}, ++{0x60a0, 0xd2}, ++{0x60a1, 0xcc}, ++{0x60a2, 0x60}, ++{0x60a3, 0xd2}, ++{0x60a4, 0xd3}, ++{0x60a5, 0x27}, ++{0x60a6, 0x27}, ++{0x60a7, 0x08}, ++{0x60a8, 0x1a}, ++{0x60a9, 0xcc}, ++{0x60aa, 0x88}, ++{0x60ab, 0x00}, ++{0x60ac, 0x12}, ++{0x60ad, 0x2c}, ++{0x60ae, 0x60}, ++{0x60af, 0x00}, ++{0x60b0, 0x00}, ++{0x60b1, 0xc0}, ++{0x60b2, 0xb9}, ++{0x60b3, 0xa3}, ++{0x60b4, 0xa3}, ++{0x60b5, 0xb5}, ++{0x60b6, 0x00}, ++{0x60b7, 0xa0}, ++{0x60b8, 0x82}, ++{0x60b9, 0x5c}, ++{0x60ba, 0xd4}, ++{0x60bb, 0x8b}, ++{0x60bc, 0x9d}, ++{0x60bd, 0xd3}, ++{0x60be, 0x21}, ++{0x60bf, 0xb0}, ++{0x60c0, 0xb0}, ++{0x60c1, 0xb7}, ++{0x60c2, 0x05}, ++{0x60c3, 0xd3}, ++{0x60c4, 0x0a}, ++{0x60c5, 0xd3}, ++{0x60c6, 0x10}, ++{0x60c7, 0x9c}, ++{0x60c8, 0x94}, ++{0x60c9, 0x90}, ++{0x60ca, 0xc8}, ++{0x60cb, 0xba}, ++{0x60cc, 0x7c}, ++{0x60cd, 0x74}, ++{0x60ce, 0x00}, ++{0x60cf, 0x61}, ++{0x60d0, 0x2a}, ++{0x60d1, 0x00}, ++{0x60d2, 0xd2}, ++{0x60d3, 0xcc}, ++{0x60d4, 0xdf}, ++{0x60d5, 0xc4}, ++{0x60d6, 0x35}, ++{0x60d7, 0xd3}, ++{0x60d8, 0x13}, ++{0x60d9, 0xd2}, ++{0x60da, 0xcc}, ++{0x60db, 0x06}, ++{0x60dc, 0x31}, ++{0x60dd, 0xd2}, ++{0x60de, 0xcc}, ++{0x60df, 0x15}, ++{0x60e0, 0xd2}, ++{0x60e1, 0xbb}, ++{0x60e2, 0xcc}, ++{0x60e3, 0x1a}, ++{0x60e4, 0xd2}, ++{0x60e5, 0xbe}, ++{0x60e6, 0xce}, ++{0x60e7, 0x52}, ++{0x60e8, 0xcf}, ++{0x60e9, 0x56}, ++{0x60ea, 0xd0}, ++{0x60eb, 0x5b}, ++{0x60ec, 0x2b}, ++{0x60ed, 0xd2}, ++{0x60ee, 0xd3}, ++{0x60ef, 0x01}, ++{0x60f0, 0xcc}, ++{0x60f1, 0x0a}, ++{0x60f2, 0xd2}, ++{0x60f3, 0xd3}, ++{0x60f4, 0x0f}, ++{0x60f5, 0xd9}, ++{0x60f6, 0xb4}, ++{0x60f7, 0xda}, ++{0x60f8, 0xbb}, ++{0x60f9, 0x1a}, ++{0x60fa, 0xd4}, ++{0x60fb, 0xe3}, ++{0x60fc, 0xd4}, ++{0x60fd, 0x96}, ++{0x60fe, 0x27}, ++{0x60ff, 0x00}, ++{0x6100, 0xd2}, ++{0x6101, 0xcc}, ++{0x6102, 0x60}, ++{0x6103, 0xd2}, ++{0x6104, 0xd3}, ++{0x6105, 0x2d}, ++{0x6106, 0xd9}, ++{0x6107, 0xcc}, ++{0x6108, 0xda}, ++{0x6109, 0xd2}, ++{0x610a, 0x1a}, ++{0x610b, 0x12}, ++{0x610c, 0xcc}, ++{0x610d, 0x88}, ++{0x610e, 0xd6}, ++{0x610f, 0x9e}, ++{0x6110, 0xb9}, ++{0x6111, 0xba}, ++{0x6112, 0xaf}, ++{0x6113, 0xdc}, ++{0x6114, 0x00}, ++{0x6115, 0xd5}, ++{0x6116, 0xba}, ++{0x6117, 0x00}, ++{0x6118, 0x00}, ++{0x6119, 0x00}, ++{0x611a, 0x00}, ++{0x611b, 0x00}, ++{0x611c, 0x00}, ++{0x611d, 0x00}, ++{0x611e, 0x00}, ++{0x611f, 0xaa}, ++{0x6120, 0xaa}, ++{0x6121, 0xb7}, ++{0x6122, 0x00}, ++{0x6123, 0x00}, ++{0x6124, 0x00}, ++{0x6125, 0x00}, ++{0x6126, 0x00}, ++{0x6127, 0xa6}, ++{0x6128, 0xa6}, ++{0x6129, 0xb7}, ++{0x612a, 0x00}, ++{0x612b, 0xd5}, ++{0x612c, 0x71}, ++{0x612d, 0xd3}, ++{0x612e, 0x30}, ++{0x612f, 0xba}, ++{0x6130, 0x00}, ++{0x6131, 0x00}, ++{0x6132, 0x00}, ++{0x6133, 0x00}, ++{0x6134, 0xd3}, ++{0x6135, 0x10}, ++{0x6136, 0x70}, ++{0x6137, 0x00}, ++{0x6138, 0x00}, ++{0x6139, 0x00}, ++{0x613a, 0x00}, ++{0x613b, 0xd5}, ++{0x613c, 0xba}, ++{0x613d, 0xb0}, ++{0x613e, 0xb0}, ++{0x613f, 0xb7}, ++{0x6140, 0x9d}, ++{0x6141, 0x02}, ++{0x6142, 0xd3}, ++{0x6143, 0x0a}, ++{0x6144, 0x9d}, ++{0x6145, 0x9d}, ++{0x6146, 0xd3}, ++{0x6147, 0x10}, ++{0x6148, 0x9c}, ++{0x6149, 0x94}, ++{0x614a, 0x90}, ++{0x614b, 0xc8}, ++{0x614c, 0xba}, ++{0x614d, 0xd2}, ++{0x614e, 0x60}, ++{0x614f, 0x2c}, ++{0x6150, 0x50}, ++{0x6151, 0x11}, ++{0x6152, 0xcc}, ++{0x6153, 0x00}, ++{0x6154, 0x30}, ++{0x6155, 0xd5}, ++{0x6156, 0xba}, ++{0x6157, 0xb0}, ++{0x6158, 0xb0}, ++{0x6159, 0xb7}, ++{0x615a, 0x9d}, ++{0x615b, 0x02}, ++{0x615c, 0xd3}, ++{0x615d, 0x0a}, ++{0x615e, 0x9d}, ++{0x615f, 0x9d}, ++{0x6160, 0xd3}, ++{0x6161, 0x10}, ++{0x6162, 0x9c}, ++{0x6163, 0x94}, ++{0x6164, 0x90}, ++{0x6165, 0xc8}, ++{0x6166, 0xba}, ++{0x6167, 0xd5}, ++{0x6168, 0x01}, ++{0x6169, 0x1a}, ++{0x616a, 0xcc}, ++{0x616b, 0x12}, ++{0x616c, 0x12}, ++{0x616d, 0x00}, ++{0x616e, 0xcc}, ++{0x616f, 0x9c}, ++{0x6170, 0xd2}, ++{0x6171, 0xcc}, ++{0x6172, 0x60}, ++{0x6173, 0xd2}, ++{0x6174, 0x04}, ++{0x6175, 0xd5}, ++{0x6176, 0x1a}, ++{0x6177, 0xcc}, ++{0x6178, 0x12}, ++{0x6179, 0x00}, ++{0x617a, 0x12}, ++{0x617b, 0xcc}, ++{0x617c, 0x9c}, ++{0x617d, 0xd2}, ++{0x617e, 0xcc}, ++{0x617f, 0x60}, ++{0x6180, 0xd2}, ++{0x6181, 0x1a}, ++{0x6182, 0xcc}, ++{0x6183, 0x12}, ++{0x6184, 0x00}, ++{0x6185, 0x12}, ++{0x6186, 0xcc}, ++{0x6187, 0x9c}, ++{0x6188, 0xd2}, ++{0x6189, 0xcc}, ++{0x618a, 0x60}, ++{0x618b, 0xd2}, ++{0x618c, 0x1a}, ++{0x618d, 0xcc}, ++{0x618e, 0x12}, ++{0x618f, 0x00}, ++{0x6190, 0x12}, ++{0x6191, 0xcc}, ++{0x6192, 0x9c}, ++{0x6193, 0xd2}, ++{0x6194, 0xcc}, ++{0x6195, 0x60}, ++{0x6196, 0xd2}, ++{0x6197, 0xd5}, ++{0x6198, 0x1a}, ++{0x6199, 0xcc}, ++{0x619a, 0x12}, ++{0x619b, 0x12}, ++{0x619c, 0x00}, ++{0x619d, 0xcc}, ++{0x619e, 0x8a}, ++{0x619f, 0xd2}, ++{0x61a0, 0xcc}, ++{0x61a1, 0x74}, ++{0x61a2, 0xd2}, ++{0x61a3, 0xd5}, ++{0x61a4, 0x1a}, ++{0x61a5, 0xcc}, ++{0x61a6, 0x12}, ++{0x61a7, 0x00}, ++{0x61a8, 0x12}, ++{0x61a9, 0xcc}, ++{0x61aa, 0x8a}, ++{0x61ab, 0xd2}, ++{0x61ac, 0xcc}, ++{0x61ad, 0x74}, ++{0x61ae, 0xd2}, ++{0x61af, 0x1a}, ++{0x61b0, 0xcc}, ++{0x61b1, 0x12}, ++{0x61b2, 0x00}, ++{0x61b3, 0x12}, ++{0x61b4, 0xcc}, ++{0x61b5, 0x8a}, ++{0x61b6, 0xd2}, ++{0x61b7, 0xcc}, ++{0x61b8, 0x74}, ++{0x61b9, 0xd2}, ++{0x61ba, 0x1a}, ++{0x61bb, 0xcc}, ++{0x61bc, 0x12}, ++{0x61bd, 0x00}, ++{0x61be, 0x12}, ++{0x61bf, 0xcc}, ++{0x61c0, 0x8a}, ++{0x61c1, 0xd2}, ++{0x61c2, 0xcc}, ++{0x61c3, 0x74}, ++{0x61c4, 0xd2}, ++{0x61c5, 0xd5}, ++{0x61c6, 0xcc}, ++{0x61c7, 0x12}, ++{0x61c8, 0x00}, ++{0x61c9, 0x12}, ++{0x61ca, 0xcc}, ++{0x61cb, 0x9c}, ++{0x61cc, 0xd5}, ++{0x6400, 0x04}, ++{0x6401, 0x04}, ++{0x6402, 0x00}, ++{0x6403, 0xff}, ++{0x6404, 0x00}, ++{0x6405, 0x08}, ++{0x6406, 0x00}, ++{0x6407, 0xff}, ++{0x6408, 0x04}, ++{0x6409, 0x70}, ++{0x640a, 0x00}, ++{0x640b, 0xff}, ++{0x640c, 0x05}, ++{0x640d, 0x14}, ++{0x640e, 0x04}, ++{0x640f, 0x71}, ++{0x6410, 0x05}, ++{0x6411, 0x74}, ++{0x6412, 0x00}, ++{0x6413, 0xff}, ++{0x6414, 0x05}, ++{0x6415, 0x54}, ++{0x6416, 0x05}, ++{0x6417, 0x44}, ++{0x6418, 0x04}, ++{0x6419, 0x30}, ++{0x641a, 0x05}, ++{0x641b, 0x46}, ++{0x641c, 0x00}, ++{0x641d, 0xff}, ++{0x641e, 0x04}, ++{0x641f, 0x31}, ++{0x6420, 0x04}, ++{0x6421, 0x30}, ++{0x6422, 0x00}, ++{0x6423, 0xff}, ++{0x6424, 0x04}, ++{0x6425, 0x20}, ++{0x6426, 0x05}, ++{0x6427, 0x06}, ++{0x6428, 0x00}, ++{0x6429, 0xff}, ++{0x642a, 0x08}, ++{0x642b, 0x2a}, ++{0x642c, 0x08}, ++{0x642d, 0x31}, ++{0x642e, 0x00}, ++{0x642f, 0xff}, ++{0x6430, 0x08}, ++{0x6431, 0x2a}, ++{0x6432, 0x08}, ++{0x6433, 0x31}, ++{0x6434, 0x06}, ++{0x6435, 0x20}, ++{0x6436, 0x07}, ++{0x6437, 0x00}, ++{0x6438, 0x08}, ++{0x6439, 0x40}, ++{0x643a, 0x00}, ++{0x643b, 0xff}, ++{0x643c, 0x08}, ++{0x643d, 0x2a}, ++{0x643e, 0x08}, ++{0x643f, 0x36}, ++{0x6440, 0x06}, ++{0x6441, 0x10}, ++{0x6442, 0x07}, ++{0x6443, 0x00}, ++{0x6444, 0x08}, ++{0x6445, 0x40}, ++{0x6446, 0x00}, ++{0x6447, 0xff}, ++{0x6448, 0x08}, ++{0x6449, 0x2a}, ++{0x644a, 0x08}, ++{0x644b, 0x3b}, ++{0x644c, 0x06}, ++{0x644d, 0x00}, ++{0x644e, 0x07}, ++{0x644f, 0x00}, ++{0x6450, 0x08}, ++{0x6451, 0x40}, ++{0x6452, 0x00}, ++{0x6453, 0xff}, ++{0x6454, 0x06}, ++{0x6455, 0x00}, ++{0x6456, 0x07}, ++{0x6457, 0x05}, ++{0x6458, 0x01}, ++{0x6459, 0xaf}, ++{0x645a, 0x01}, ++{0x645b, 0x0f}, ++{0x645c, 0x01}, ++{0x645d, 0x90}, ++{0x645e, 0x01}, ++{0x645f, 0xc8}, ++{0x6460, 0x00}, ++{0x6461, 0xff}, ++{0x6462, 0x01}, ++{0x6463, 0xac}, ++{0x6464, 0x01}, ++{0x6465, 0x0c}, ++{0x6466, 0x01}, ++{0x6467, 0x90}, ++{0x6468, 0x01}, ++{0x6469, 0xe8}, ++{0x646a, 0x00}, ++{0x646b, 0xff}, ++{0x646c, 0x01}, ++{0x646d, 0xad}, ++{0x646e, 0x01}, ++{0x646f, 0x0d}, ++{0x6470, 0x01}, ++{0x6471, 0x90}, ++{0x6472, 0x01}, ++{0x6473, 0xe8}, ++{0x6474, 0x00}, ++{0x6475, 0xff}, ++{0x6476, 0x01}, ++{0x6477, 0xae}, ++{0x6478, 0x01}, ++{0x6479, 0x0e}, ++{0x647a, 0x01}, ++{0x647b, 0x90}, ++{0x647c, 0x01}, ++{0x647d, 0xe8}, ++{0x647e, 0x00}, ++{0x647f, 0xff}, ++{0x6480, 0x01}, ++{0x6481, 0xb0}, ++{0x6482, 0x01}, ++{0x6483, 0xb1}, ++{0x6484, 0x01}, ++{0x6485, 0xb2}, ++{0x6486, 0x01}, ++{0x6487, 0xb3}, ++{0x6488, 0x01}, ++{0x6489, 0xb4}, ++{0x648a, 0x01}, ++{0x648b, 0xb5}, ++{0x648c, 0x01}, ++{0x648d, 0xb6}, ++{0x648e, 0x01}, ++{0x648f, 0xb7}, ++{0x6490, 0x01}, ++{0x6491, 0xb8}, ++{0x6492, 0x01}, ++{0x6493, 0xb9}, ++{0x6494, 0x01}, ++{0x6495, 0xba}, ++{0x6496, 0x01}, ++{0x6497, 0xbb}, ++{0x6498, 0x01}, ++{0x6499, 0xbc}, ++{0x649a, 0x01}, ++{0x649b, 0xbd}, ++{0x649c, 0x01}, ++{0x649d, 0xbe}, ++{0x649e, 0x01}, ++{0x649f, 0xbf}, ++{0x64a0, 0x01}, ++{0x64a1, 0xc0}, ++{0x64a2, 0x00}, ++{0x64a3, 0xff}, ++{0x64a4, 0x06}, ++{0x64a5, 0x00}, ++{0x64a6, 0x01}, ++{0x64a7, 0xf6}, ++{0x64a8, 0x04}, ++{0x64a9, 0x30}, ++{0x64aa, 0x00}, ++{0x64ab, 0xff}, ++{0x64ac, 0x06}, ++{0x64ad, 0x10}, ++{0x64ae, 0x01}, ++{0x64af, 0xf6}, ++{0x64b0, 0x04}, ++{0x64b1, 0x30}, ++{0x64b2, 0x06}, ++{0x64b3, 0x00}, ++{0x64b4, 0x00}, ++{0x64b5, 0xff}, ++{0x64b6, 0x06}, ++{0x64b7, 0x20}, ++{0x64b8, 0x01}, ++{0x64b9, 0xf6}, ++{0x64ba, 0x04}, ++{0x64bb, 0x30}, ++{0x64bc, 0x06}, ++{0x64bd, 0x00}, ++{0x64be, 0x00}, ++{0x64bf, 0xff}, ++{0x64c0, 0x04}, ++{0x64c1, 0x31}, ++{0x64c2, 0x04}, ++{0x64c3, 0x30}, ++{0x64c4, 0x01}, ++{0x64c5, 0x20}, ++{0x64c6, 0x01}, ++{0x64c7, 0x31}, ++{0x64c8, 0x01}, ++{0x64c9, 0x32}, ++{0x64ca, 0x01}, ++{0x64cb, 0x33}, ++{0x64cc, 0x01}, ++{0x64cd, 0x34}, ++{0x64ce, 0x01}, ++{0x64cf, 0x35}, ++{0x64d0, 0x01}, ++{0x64d1, 0x36}, ++{0x64d2, 0x01}, ++{0x64d3, 0x37}, ++{0x64d4, 0x01}, ++{0x64d5, 0x38}, ++{0x64d6, 0x01}, ++{0x64d7, 0x39}, ++{0x64d8, 0x01}, ++{0x64d9, 0x3a}, ++{0x64da, 0x01}, ++{0x64db, 0x3b}, ++{0x64dc, 0x01}, ++{0x64dd, 0x3c}, ++{0x64de, 0x01}, ++{0x64df, 0x3d}, ++{0x64e0, 0x01}, ++{0x64e1, 0x3e}, ++{0x64e2, 0x01}, ++{0x64e3, 0x3f}, ++{0x64e4, 0x02}, ++{0x64e5, 0xa0}, ++{0x64e6, 0x00}, ++{0x64e7, 0xff}, ++{0x64e8, 0x04}, ++{0x64e9, 0x31}, ++{0x64ea, 0x04}, ++{0x64eb, 0x30}, ++{0x64ec, 0x01}, ++{0x64ed, 0x00}, ++{0x64ee, 0x01}, ++{0x64ef, 0x11}, ++{0x64f0, 0x01}, ++{0x64f1, 0x12}, ++{0x64f2, 0x01}, ++{0x64f3, 0x13}, ++{0x64f4, 0x01}, ++{0x64f5, 0x14}, ++{0x64f6, 0x01}, ++{0x64f7, 0x15}, ++{0x64f8, 0x01}, ++{0x64f9, 0x16}, ++{0x64fa, 0x01}, ++{0x64fb, 0x17}, ++{0x64fc, 0x01}, ++{0x64fd, 0x18}, ++{0x64fe, 0x01}, ++{0x64ff, 0x19}, ++{0x6500, 0x01}, ++{0x6501, 0x1a}, ++{0x6502, 0x01}, ++{0x6503, 0x1b}, ++{0x6504, 0x01}, ++{0x6505, 0x1c}, ++{0x6506, 0x01}, ++{0x6507, 0x1d}, ++{0x6508, 0x01}, ++{0x6509, 0x1e}, ++{0x650a, 0x01}, ++{0x650b, 0x1f}, ++{0x650c, 0x02}, ++{0x650d, 0xa0}, ++{0x650e, 0x00}, ++{0x650f, 0xff}, ++{0x6510, 0x04}, ++{0x6511, 0x20}, ++{0x6512, 0x05}, ++{0x6513, 0x86}, ++{0x6514, 0x03}, ++{0x6515, 0x0b}, ++{0x6516, 0x05}, ++{0x6517, 0x86}, ++{0x6518, 0x00}, ++{0x6519, 0x00}, ++{0x651a, 0x05}, ++{0x651b, 0x06}, ++{0x651c, 0x00}, ++{0x651d, 0x04}, ++{0x651e, 0x05}, ++{0x651f, 0x04}, ++{0x6520, 0x00}, ++{0x6521, 0x04}, ++{0x6522, 0x05}, ++{0x6523, 0x00}, ++{0x6524, 0x05}, ++{0x6525, 0x0a}, ++{0x6526, 0x03}, ++{0x6527, 0x9a}, ++{0x6528, 0x05}, ++{0x6529, 0x86}, ++{0x652a, 0x00}, ++{0x652b, 0x00}, ++{0x652c, 0x05}, ++{0x652d, 0x06}, ++{0x652e, 0x00}, ++{0x652f, 0x01}, ++{0x6530, 0x05}, ++{0x6531, 0x04}, ++{0x6532, 0x00}, ++{0x6533, 0x04}, ++{0x6534, 0x05}, ++{0x6535, 0x00}, ++{0x6536, 0x05}, ++{0x6537, 0x0a}, ++{0x6538, 0x03}, ++{0x6539, 0x99}, ++{0x653a, 0x05}, ++{0x653b, 0x06}, ++{0x653c, 0x00}, ++{0x653d, 0x00}, ++{0x653e, 0x05}, ++{0x653f, 0x04}, ++{0x6540, 0x00}, ++{0x6541, 0x04}, ++{0x6542, 0x05}, ++{0x6543, 0x00}, ++{0x6544, 0x05}, ++{0x6545, 0x0a}, ++{0x6546, 0x03}, ++{0x6547, 0x98}, ++{0x6548, 0x05}, ++{0x6549, 0x06}, ++{0x654a, 0x00}, ++{0x654b, 0x00}, ++{0x654c, 0x05}, ++{0x654d, 0x04}, ++{0x654e, 0x00}, ++{0x654f, 0x04}, ++{0x6550, 0x05}, ++{0x6551, 0x00}, ++{0x6552, 0x05}, ++{0x6553, 0x0a}, ++{0x6554, 0x03}, ++{0x6555, 0x97}, ++{0x6556, 0x05}, ++{0x6557, 0x06}, ++{0x6558, 0x05}, ++{0x6559, 0x04}, ++{0x655a, 0x00}, ++{0x655b, 0x04}, ++{0x655c, 0x05}, ++{0x655d, 0x00}, ++{0x655e, 0x05}, ++{0x655f, 0x0a}, ++{0x6560, 0x03}, ++{0x6561, 0x96}, ++{0x6562, 0x05}, ++{0x6563, 0x06}, ++{0x6564, 0x05}, ++{0x6565, 0x04}, ++{0x6566, 0x00}, ++{0x6567, 0x04}, ++{0x6568, 0x05}, ++{0x6569, 0x00}, ++{0x656a, 0x05}, ++{0x656b, 0x0a}, ++{0x656c, 0x03}, ++{0x656d, 0x95}, ++{0x656e, 0x05}, ++{0x656f, 0x06}, ++{0x6570, 0x05}, ++{0x6571, 0x04}, ++{0x6572, 0x00}, ++{0x6573, 0x04}, ++{0x6574, 0x05}, ++{0x6575, 0x00}, ++{0x6576, 0x05}, ++{0x6577, 0x0a}, ++{0x6578, 0x03}, ++{0x6579, 0x94}, ++{0x657a, 0x05}, ++{0x657b, 0x06}, ++{0x657c, 0x00}, ++{0x657d, 0x00}, ++{0x657e, 0x05}, ++{0x657f, 0x04}, ++{0x6580, 0x00}, ++{0x6581, 0x04}, ++{0x6582, 0x05}, ++{0x6583, 0x00}, ++{0x6584, 0x05}, ++{0x6585, 0x0a}, ++{0x6586, 0x03}, ++{0x6587, 0x93}, ++{0x6588, 0x05}, ++{0x6589, 0x06}, ++{0x658a, 0x00}, ++{0x658b, 0x00}, ++{0x658c, 0x05}, ++{0x658d, 0x04}, ++{0x658e, 0x00}, ++{0x658f, 0x04}, ++{0x6590, 0x05}, ++{0x6591, 0x00}, ++{0x6592, 0x05}, ++{0x6593, 0x0a}, ++{0x6594, 0x03}, ++{0x6595, 0x92}, ++{0x6596, 0x05}, ++{0x6597, 0x06}, ++{0x6598, 0x05}, ++{0x6599, 0x04}, ++{0x659a, 0x00}, ++{0x659b, 0x04}, ++{0x659c, 0x05}, ++{0x659d, 0x00}, ++{0x659e, 0x05}, ++{0x659f, 0x0a}, ++{0x65a0, 0x03}, ++{0x65a1, 0x91}, ++{0x65a2, 0x05}, ++{0x65a3, 0x06}, ++{0x65a4, 0x05}, ++{0x65a5, 0x04}, ++{0x65a6, 0x00}, ++{0x65a7, 0x04}, ++{0x65a8, 0x05}, ++{0x65a9, 0x00}, ++{0x65aa, 0x05}, ++{0x65ab, 0x0a}, ++{0x65ac, 0x03}, ++{0x65ad, 0x90}, ++{0x65ae, 0x05}, ++{0x65af, 0x06}, ++{0x65b0, 0x05}, ++{0x65b1, 0x04}, ++{0x65b2, 0x00}, ++{0x65b3, 0x04}, ++{0x65b4, 0x05}, ++{0x65b5, 0x00}, ++{0x65b6, 0x05}, ++{0x65b7, 0x0a}, ++{0x65b8, 0x02}, ++{0x65b9, 0x90}, ++{0x65ba, 0x05}, ++{0x65bb, 0x06}, ++{0x65bc, 0x00}, ++{0x65bd, 0xff}, ++{0x65be, 0x04}, ++{0x65bf, 0x70}, ++{0x65c0, 0x08}, ++{0x65c1, 0x76}, ++{0x65c2, 0x00}, ++{0x65c3, 0xff}, ++{0x65c4, 0x08}, ++{0x65c5, 0x76}, ++{0x65c6, 0x04}, ++{0x65c7, 0x0c}, ++{0x65c8, 0x05}, ++{0x65c9, 0x07}, ++{0x65ca, 0x04}, ++{0x65cb, 0x04}, ++{0x65cc, 0x00}, ++{0x65cd, 0xff}, ++{0x65ce, 0x00}, ++{0x65cf, 0xff}, ++{0x65d0, 0x00}, ++{0x65d1, 0xff}, ++{0x30eb, 0x04}, ++{0x30ed, 0x5a}, ++{0x30ee, 0x01}, ++{0x30ef, 0x80}, ++{0x30f1, 0x5a}, ++{0x303a, 0x04}, ++{0x303b, 0x7f}, ++{0x303c, 0xfe}, ++{0x303d, 0x19}, ++{0x303e, 0xd7}, ++{0x303f, 0x09}, ++{0x3040, 0x78}, ++{0x3042, 0x05}, ++{0x328a, 0x10}, ++{0x3012, 0x01}, // stream on ++}; ++ ++/* DVP_1280x1080_COMB12_raw 30fps */ ++static const struct ov10640_reg ov10640_regs_wizard_r1e[] = { ++/* ov10640_R1E_setting_3x12_1280x1080_MIPIin_4lane_raw */ ++{0x3013, 0x01}, ++{OV10640_DELAY, 10}, ++{0x328a, 0x11}, ++{0x313f, 0x80}, ++{0x3132, 0x24}, ++ ++/* PLL settings */ ++{0x3000, 0x03}, ++{0x3001, 0x60}, ++{0x3002, 0x0f}, ++{0x3004, 0x03}, ++{0x3005, 0x44}, ++{0x3006, 0x07}, ++{0x3007, 0x01}, ++ ++{0x3014, 0x03}, ++{0x3023, 0x05}, ++{0x3032, 0x35}, ++{0x3033, 0x04}, ++{0x3054, 0x00}, ++{0x3055, 0x03}, ++{0x3056, 0x01}, ++{0x3057, 0xff}, ++{0x3058, 0xaf}, ++{0x3059, 0x44}, ++{0x305a, 0x02}, ++{0x305b, 0x00}, ++{0x305c, 0x30}, ++{0x305d, 0x9c}, ++{0x305e, 0x19}, ++{0x305f, 0x18}, ++{0x3060, 0xf9}, ++{0x3061, 0xf0}, ++{0x308a, 0x00}, ++{0x308b, 0x00}, ++#ifdef OV10640_FSIN_ENABLE ++{0x308c, 0xb2}, ++#else ++{0x308c, 0x03}, ++#endif ++{0x308f, 0x10}, ++{0x3090, 0x04}, /* c:enable flip and mirror */ ++{0x3091, 0x00}, ++{0x30eb, 0x00}, ++{0x30a3, 0x08}, ++{0x30ad, 0x03}, ++{0x30ae, 0x80}, ++{0x30af, 0x80}, ++{0x30b0, 0xff}, ++{0x30b1, 0x3f}, ++{0x30b2, 0x22}, ++{0x30b9, 0x22}, ++{0x30bb, 0x00}, ++{0x30bc, 0x00}, ++{0x30bd, 0x00}, ++{0x30be, 0x00}, ++{0x30bf, 0x00}, ++{0x30c0, 0x00}, ++{0x30c1, 0x00}, ++{0x30c2, 0x00}, ++{0x30c3, 0x00}, ++{0x30c4, 0x80}, ++{0x30c5, 0x00}, ++{0x30c6, 0x80}, ++{0x30c7, 0x00}, ++{0x30c8, 0x80}, ++{0x3119, 0x49}, ++{0x311a, 0x01}, ++{0x311b, 0x4a}, ++ ++/* Crop Setting */ ++{0x3074, 0x00}, // crop_h_start ++{0x3075, 0x00}, ++{0x3076, 0x00}, // crop_v_start ++{0x3077, 0xf0}, ++{0x3078, 0x05}, // crop_h_end ++{0x3079, 0x09}, ++{0x307a, 0x04}, // crop_v_end ++{0x307b, 0x18}, ++{0x307c, 0x05}, // dvp_h_size ++{0x307d, 0x08}, ++{0x307e, 0x03}, // dvp_v_size ++{0x307f, 0x28}, ++{0x3080, 0x07}, // hts ++{0x3081, 0x44}, ++{0x3082, 0x03}, // vts ++{0x3083, 0x5c}, ++{0x3084, 0x00}, // win_hoffs ++{0x3085, 0x00}, ++{0x3086, 0x00}, // win_voffs ++{0x3087, 0x00}, ++ ++{0x3088, 0x00}, ++{0x3089, 0x40}, ++{0x308d, 0x92}, ++{0x3094, 0xa5}, ++{0x30e6, 0x04}, ++{0x30e7, 0x48}, ++{0x30e8, 0x04}, ++{0x30e9, 0x48}, ++{0x30e9, 0x05}, ++{0x30ec, 0x01}, ++{0x30fa, 0x06}, ++{0x3120, 0x00}, ++{0x3121, 0x20}, /* VSYNC delay */ ++{0x3122, 0x00}, ++{0x3127, 0x43}, /* 43 :dpc off, 63 */ ++{0x3128, 0xc0}, ++#ifdef OV10640_DISPLAY_PATTERN ++{0x3129, 0x80}, ++#else ++{0x3129, 0x00}, ++#endif ++{0x31be, 0x00}, ++{0x30a5, 0x78}, ++{0x30a6, 0x40}, ++{0x30a7, 0x78}, ++{0x30a8, 0x80}, ++{0x30a9, 0x78}, ++{0x30aa, 0xe0}, ++{0x30ab, 0xf9}, ++{0x30ac, 0xc0}, ++{0x3440, 0x04}, ++{0x3444, 0x28}, ++{0x344e, 0x2c}, ++{0x3457, 0x33}, ++{0x345e, 0x38}, ++{0x3461, 0xa8}, ++{0x7002, 0xaa}, ++{0x7001, 0xdf}, ++{0x7048, 0x00}, ++{0x7049, 0x02}, ++{0x704a, 0x02}, ++{0x704b, 0x00}, ++{0x704c, 0x01}, ++{0x704d, 0x00}, ++{0x7043, 0x04}, ++{0x7040, 0x3c}, ++{0x7047, 0x00}, ++{0x7044, 0x01}, ++{0x7000, 0x1f}, ++{0x7084, 0x01}, ++{0x7085, 0x03}, ++{0x7086, 0x02}, ++{0x7087, 0x40}, ++{0x7088, 0x01}, ++{0x7089, 0x20}, ++{0x707f, 0x04}, ++{0x707c, 0x3c}, ++{0x7083, 0x00}, ++{0x7080, 0x01}, ++{0x7003, 0xdf}, ++{0x70c0, 0x00}, ++{0x70c1, 0x02}, ++{0x70c2, 0x02}, ++{0x70c3, 0x00}, ++{0x70c4, 0x01}, ++{0x70c5, 0x00}, ++{0x70b8, 0x03}, ++{0x70b9, 0x98}, ++{0x70bc, 0x00}, ++{0x70bd, 0x80}, ++{0x7004, 0x02}, ++{0x7005, 0x00}, ++{0x7006, 0x01}, ++{0x7007, 0x80}, ++{0x7008, 0x02}, ++{0x7009, 0x00}, ++{0x700a, 0x04}, ++{0x700b, 0x00}, ++{0x700e, 0x00}, ++{0x700f, 0x60}, ++{0x701a, 0x02}, ++{0x701b, 0x00}, ++{0x701c, 0x01}, ++{0x701d, 0x80}, ++{0x701e, 0x02}, ++{0x701f, 0x00}, ++{0x7020, 0x04}, ++{0x7021, 0x00}, ++{0x7024, 0x00}, ++{0x7025, 0x60}, ++{0x70e7, 0x00}, ++{0x70e4, 0x10}, ++{0x70e5, 0x00}, ++{0x70e6, 0x00}, ++{0x70eb, 0x00}, ++{0x70e8, 0x10}, ++{0x70e9, 0x00}, ++{0x70ea, 0x00}, ++{0x70ef, 0x00}, ++{0x70ec, 0xfd}, ++{0x70ed, 0x00}, ++{0x70ee, 0x00}, ++{0x70eb, 0x00}, ++{0x70f0, 0xfd}, ++{0x70f1, 0x00}, ++{0x70f2, 0x00}, ++{0x30fb, 0x06}, ++{0x30fc, 0x80}, ++{0x30fd, 0x02}, ++{0x30fe, 0x93}, ++{0x6000, 0xc1}, ++{0x6001, 0xb9}, ++{0x6002, 0xba}, ++{0x6003, 0xa4}, ++{0x6004, 0xb5}, ++{0x6005, 0xa0}, ++{0x6006, 0x82}, ++{0x6007, 0xa7}, ++{0x6008, 0xb7}, ++{0x6009, 0x5c}, ++{0x600a, 0x9e}, ++{0x600b, 0xc0}, ++{0x600c, 0xd2}, ++{0x600d, 0x33}, ++{0x600e, 0xcc}, ++{0x600f, 0xe2}, ++{0x6010, 0xc1}, ++{0x6011, 0xab}, ++{0x6012, 0xb7}, ++{0x6013, 0x00}, ++{0x6014, 0x00}, ++{0x6015, 0x00}, ++{0x6016, 0x00}, ++{0x6017, 0x00}, ++{0x6018, 0x00}, ++{0x6019, 0x00}, ++{0x601a, 0x00}, ++{0x601b, 0x00}, ++{0x601c, 0x00}, ++{0x601d, 0x00}, ++{0x601e, 0x9c}, ++{0x601f, 0x94}, ++{0x6020, 0x90}, ++{0x6021, 0xc5}, ++{0x6022, 0x01}, ++{0x6023, 0x54}, ++{0x6024, 0x2a}, ++{0x6025, 0x61}, ++{0x6026, 0xd2}, ++{0x6027, 0xcc}, ++{0x6028, 0x04}, ++{0x6029, 0x35}, ++{0x602a, 0xb1}, ++{0x602b, 0xb2}, ++{0x602c, 0xb3}, ++{0x602d, 0xd2}, ++{0x602e, 0xd3}, ++{0x602f, 0x12}, ++{0x6030, 0x31}, ++{0x6031, 0xcc}, ++{0x6032, 0x06}, ++{0x6033, 0xd2}, ++{0x6034, 0xc4}, ++{0x6035, 0xce}, ++{0x6036, 0x18}, ++{0x6037, 0xcf}, ++{0x6038, 0x1e}, ++{0x6039, 0xd0}, ++{0x603a, 0x24}, ++{0x603b, 0xc5}, ++{0x603c, 0xd2}, ++{0x603d, 0xbc}, ++{0x603e, 0xcc}, ++{0x603f, 0x52}, ++{0x6040, 0x2b}, ++{0x6041, 0xd2}, ++{0x6042, 0xd3}, ++{0x6043, 0x02}, ++{0x6044, 0xcc}, ++{0x6045, 0x0a}, ++{0x6046, 0xd2}, ++{0x6047, 0xd3}, ++{0x6048, 0x0f}, ++{0x6049, 0x1a}, ++{0x604a, 0x2a}, ++{0x604b, 0xd4}, ++{0x604c, 0xf6}, ++{0x604d, 0xba}, ++{0x604e, 0x56}, ++{0x604f, 0xd3}, ++{0x6050, 0x2e}, ++{0x6051, 0x54}, ++{0x6052, 0x26}, ++{0x6053, 0xd2}, ++{0x6054, 0xcc}, ++{0x6055, 0x60}, ++{0x6056, 0xd2}, ++{0x6057, 0xd3}, ++{0x6058, 0x27}, ++{0x6059, 0x27}, ++{0x605a, 0x08}, ++{0x605b, 0x1a}, ++{0x605c, 0xcc}, ++{0x605d, 0x88}, ++{0x605e, 0x00}, ++{0x605f, 0x12}, ++{0x6060, 0x2c}, ++{0x6061, 0x60}, ++{0x6062, 0xc2}, ++{0x6063, 0xb9}, ++{0x6064, 0xa5}, ++{0x6065, 0xb5}, ++{0x6066, 0xa0}, ++{0x6067, 0x82}, ++{0x6068, 0x5c}, ++{0x6069, 0xd4}, ++{0x606a, 0xbe}, ++{0x606b, 0xd4}, ++{0x606c, 0xbe}, ++{0x606d, 0xd3}, ++{0x606e, 0x01}, ++{0x606f, 0x7c}, ++{0x6070, 0x74}, ++{0x6071, 0x00}, ++{0x6072, 0x61}, ++{0x6073, 0x2a}, ++{0x6074, 0xd2}, ++{0x6075, 0xcc}, ++{0x6076, 0xdf}, ++{0x6077, 0xc6}, ++{0x6078, 0x35}, ++{0x6079, 0xd2}, ++{0x607a, 0xcc}, ++{0x607b, 0x06}, ++{0x607c, 0x31}, ++{0x607d, 0xd2}, ++{0x607e, 0xc5}, ++{0x607f, 0xbb}, ++{0x6080, 0xcc}, ++{0x6081, 0x18}, ++{0x6082, 0xc6}, ++{0x6083, 0xd2}, ++{0x6084, 0xbd}, ++{0x6085, 0xcc}, ++{0x6086, 0x52}, ++{0x6087, 0x2b}, ++{0x6088, 0xd2}, ++{0x6089, 0xd3}, ++{0x608a, 0x01}, ++{0x608b, 0xcc}, ++{0x608c, 0x0a}, ++{0x608d, 0xd2}, ++{0x608e, 0xd3}, ++{0x608f, 0x0f}, ++{0x6090, 0x1a}, ++{0x6091, 0x71}, ++{0x6092, 0x2a}, ++{0x6093, 0xd4}, ++{0x6094, 0xf6}, ++{0x6095, 0xd3}, ++{0x6096, 0x22}, ++{0x6097, 0x70}, ++{0x6098, 0xca}, ++{0x6099, 0x26}, ++{0x609a, 0xd2}, ++{0x609b, 0xcc}, ++{0x609c, 0x60}, ++{0x609d, 0xd2}, ++{0x609e, 0xd3}, ++{0x609f, 0x27}, ++{0x60a0, 0x27}, ++{0x60a1, 0x08}, ++{0x60a2, 0x1a}, ++{0x60a3, 0xcc}, ++{0x60a4, 0x88}, ++{0x60a5, 0x12}, ++{0x60a6, 0x2c}, ++{0x60a7, 0x60}, ++{0x60a8, 0x00}, ++{0x60a9, 0x00}, ++{0x60aa, 0xc0}, ++{0x60ab, 0xb9}, ++{0x60ac, 0xa3}, ++{0x60ad, 0xb5}, ++{0x60ae, 0x00}, ++{0x60af, 0xa0}, ++{0x60b0, 0x82}, ++{0x60b1, 0x5c}, ++{0x60b2, 0xd4}, ++{0x60b3, 0xa0}, ++{0x60b4, 0x9d}, ++{0x60b5, 0xd3}, ++{0x60b6, 0x26}, ++{0x60b7, 0xb0}, ++{0x60b8, 0xb7}, ++{0x60b9, 0x00}, ++{0x60ba, 0xd3}, ++{0x60bb, 0x0a}, ++{0x60bc, 0xd3}, ++{0x60bd, 0x10}, ++{0x60be, 0x9c}, ++{0x60bf, 0x94}, ++{0x60c0, 0x90}, ++{0x60c1, 0xc8}, ++{0x60c2, 0xba}, ++{0x60c3, 0x7c}, ++{0x60c4, 0x74}, ++{0x60c5, 0x00}, ++{0x60c6, 0x61}, ++{0x60c7, 0x2a}, ++{0x60c8, 0x00}, ++{0x60c9, 0xd2}, ++{0x60ca, 0xcc}, ++{0x60cb, 0xdf}, ++{0x60cc, 0xc4}, ++{0x60cd, 0x35}, ++{0x60ce, 0xd2}, ++{0x60cf, 0xcc}, ++{0x60d0, 0x06}, ++{0x60d1, 0x31}, ++{0x60d2, 0xd2}, ++{0x60d3, 0xcc}, ++{0x60d4, 0x15}, ++{0x60d5, 0xd2}, ++{0x60d6, 0xbb}, ++{0x60d7, 0xcc}, ++{0x60d8, 0x1a}, ++{0x60d9, 0xd2}, ++{0x60da, 0xbe}, ++{0x60db, 0xce}, ++{0x60dc, 0x52}, ++{0x60dd, 0xcf}, ++{0x60de, 0x56}, ++{0x60df, 0xd0}, ++{0x60e0, 0x5b}, ++{0x60e1, 0x2b}, ++{0x60e2, 0xd2}, ++{0x60e3, 0xd3}, ++{0x60e4, 0x01}, ++{0x60e5, 0xcc}, ++{0x60e6, 0x0a}, ++{0x60e7, 0xd2}, ++{0x60e8, 0xd3}, ++{0x60e9, 0x0f}, ++{0x60ea, 0xd9}, ++{0x60eb, 0xc7}, ++{0x60ec, 0xda}, ++{0x60ed, 0xce}, ++{0x60ee, 0x1a}, ++{0x60ef, 0xd4}, ++{0x60f0, 0xf6}, ++{0x60f1, 0xd4}, ++{0x60f2, 0xa9}, ++{0x60f3, 0x27}, ++{0x60f4, 0x00}, ++{0x60f5, 0xd2}, ++{0x60f6, 0xcc}, ++{0x60f7, 0x60}, ++{0x60f8, 0xd2}, ++{0x60f9, 0xd3}, ++{0x60fa, 0x2d}, ++{0x60fb, 0xd9}, ++{0x60fc, 0xdf}, ++{0x60fd, 0xda}, ++{0x60fe, 0xe5}, ++{0x60ff, 0x1a}, ++{0x6100, 0x12}, ++{0x6101, 0xcc}, ++{0x6102, 0x88}, ++{0x6103, 0xd6}, ++{0x6104, 0xb1}, ++{0x6105, 0xb9}, ++{0x6106, 0xba}, ++{0x6107, 0xaf}, ++{0x6108, 0xdc}, ++{0x6109, 0x00}, ++{0x610a, 0xcb}, ++{0x610b, 0xc3}, ++{0x610c, 0xb9}, ++{0x610d, 0xa4}, ++{0x610e, 0xb5}, ++{0x610f, 0x5c}, ++{0x6110, 0x12}, ++{0x6111, 0x2a}, ++{0x6112, 0x61}, ++{0x6113, 0xd2}, ++{0x6114, 0xcc}, ++{0x6115, 0xdf}, ++{0x6116, 0xc7}, ++{0x6117, 0x35}, ++{0x6118, 0xd2}, ++{0x6119, 0xcc}, ++{0x611a, 0x06}, ++{0x611b, 0x31}, ++{0x611c, 0xc6}, ++{0x611d, 0xbb}, ++{0x611e, 0xd2}, ++{0x611f, 0xcc}, ++{0x6120, 0x18}, ++{0x6121, 0xd2}, ++{0x6122, 0xbe}, ++{0x6123, 0xcc}, ++{0x6124, 0x52}, ++{0x6125, 0xc7}, ++{0x6126, 0xd2}, ++{0x6127, 0xcc}, ++{0x6128, 0x0a}, ++{0x6129, 0xb4}, ++{0x612a, 0xb7}, ++{0x612b, 0x94}, ++{0x612c, 0xd2}, ++{0x612d, 0x12}, ++{0x612e, 0x26}, ++{0x612f, 0x42}, ++{0x6130, 0x46}, ++{0x6131, 0x42}, ++{0x6132, 0xd3}, ++{0x6133, 0x20}, ++{0x6134, 0x27}, ++{0x6135, 0x00}, ++{0x6136, 0x1a}, ++{0x6137, 0xcc}, ++{0x6138, 0x88}, ++{0x6139, 0x60}, ++{0x613a, 0x2c}, ++{0x613b, 0x12}, ++{0x613c, 0x40}, ++{0x613d, 0xb8}, ++{0x613e, 0x90}, ++{0x613f, 0xd5}, ++{0x6140, 0xba}, ++{0x6141, 0x00}, ++{0x6142, 0x00}, ++{0x6143, 0x00}, ++{0x6144, 0x00}, ++{0x6145, 0x00}, ++{0x6146, 0x00}, ++{0x6147, 0xaa}, ++{0x6148, 0xb7}, ++{0x6149, 0x00}, ++{0x614a, 0x00}, ++{0x614b, 0x00}, ++{0x614c, 0x00}, ++{0x614d, 0xa6}, ++{0x614e, 0xb7}, ++{0x614f, 0x00}, ++{0x6150, 0xd5}, ++{0x6151, 0x00}, ++{0x6152, 0x71}, ++{0x6153, 0xd3}, ++{0x6154, 0x30}, ++{0x6155, 0xba}, ++{0x6156, 0x00}, ++{0x6157, 0x00}, ++{0x6158, 0x00}, ++{0x6159, 0x00}, ++{0x615a, 0xd3}, ++{0x615b, 0x10}, ++{0x615c, 0x70}, ++{0x615d, 0x00}, ++{0x615e, 0x00}, ++{0x615f, 0x00}, ++{0x6160, 0x00}, ++{0x6161, 0xd5}, ++{0x6162, 0xba}, ++{0x6163, 0xb0}, ++{0x6164, 0xb7}, ++{0x6165, 0x00}, ++{0x6166, 0x9d}, ++{0x6167, 0xd3}, ++{0x6168, 0x0a}, ++{0x6169, 0x9d}, ++{0x616a, 0x9d}, ++{0x616b, 0xd3}, ++{0x616c, 0x10}, ++{0x616d, 0x9c}, ++{0x616e, 0x94}, ++{0x616f, 0x90}, ++{0x6170, 0xc8}, ++{0x6171, 0xba}, ++{0x6172, 0xd2}, ++{0x6173, 0x60}, ++{0x6174, 0x2c}, ++{0x6175, 0x50}, ++{0x6176, 0x11}, ++{0x6177, 0xcc}, ++{0x6178, 0x00}, ++{0x6179, 0x30}, ++{0x617a, 0xd5}, ++{0x617b, 0x00}, ++{0x617c, 0xba}, ++{0x617d, 0xb0}, ++{0x617e, 0xb7}, ++{0x617f, 0x00}, ++{0x6180, 0x9d}, ++{0x6181, 0xd3}, ++{0x6182, 0x0a}, ++{0x6183, 0x9d}, ++{0x6184, 0x9d}, ++{0x6185, 0xd3}, ++{0x6186, 0x10}, ++{0x6187, 0x9c}, ++{0x6188, 0x94}, ++{0x6189, 0x90}, ++{0x618a, 0xc8}, ++{0x618b, 0xba}, ++{0x618c, 0xd5}, ++{0x618d, 0x00}, ++{0x618e, 0x01}, ++{0x618f, 0x1a}, ++{0x6190, 0xcc}, ++{0x6191, 0x12}, ++{0x6192, 0x12}, ++{0x6193, 0x00}, ++{0x6194, 0xcc}, ++{0x6195, 0x9c}, ++{0x6196, 0xd2}, ++{0x6197, 0xcc}, ++{0x6198, 0x60}, ++{0x6199, 0xd2}, ++{0x619a, 0x04}, ++{0x619b, 0xd5}, ++{0x619c, 0x1a}, ++{0x619d, 0xcc}, ++{0x619e, 0x12}, ++{0x619f, 0x00}, ++{0x61a0, 0x12}, ++{0x61a1, 0xcc}, ++{0x61a2, 0x9c}, ++{0x61a3, 0xd2}, ++{0x61a4, 0xcc}, ++{0x61a5, 0x60}, ++{0x61a6, 0xd2}, ++{0x61a7, 0x1a}, ++{0x61a8, 0xcc}, ++{0x61a9, 0x12}, ++{0x61aa, 0x00}, ++{0x61ab, 0x12}, ++{0x61ac, 0xcc}, ++{0x61ad, 0x9c}, ++{0x61ae, 0xd2}, ++{0x61af, 0xcc}, ++{0x61b0, 0x60}, ++{0x61b1, 0xd2}, ++{0x61b2, 0x1a}, ++{0x61b3, 0xcc}, ++{0x61b4, 0x12}, ++{0x61b5, 0x00}, ++{0x61b6, 0x12}, ++{0x61b7, 0xcc}, ++{0x61b8, 0x9c}, ++{0x61b9, 0xd2}, ++{0x61ba, 0xcc}, ++{0x61bb, 0x60}, ++{0x61bc, 0xd2}, ++{0x61bd, 0xd5}, ++{0x61be, 0x1a}, ++{0x61bf, 0xcc}, ++{0x61c0, 0x12}, ++{0x61c1, 0x12}, ++{0x61c2, 0x00}, ++{0x61c3, 0xcc}, ++{0x61c4, 0x8a}, ++{0x61c5, 0xd2}, ++{0x61c6, 0xcc}, ++{0x61c7, 0x74}, ++{0x61c8, 0xd2}, ++{0x61c9, 0xd5}, ++{0x61ca, 0x1a}, ++{0x61cb, 0xcc}, ++{0x61cc, 0x12}, ++{0x61cd, 0x00}, ++{0x61ce, 0x12}, ++{0x61cf, 0xcc}, ++{0x61d0, 0x8a}, ++{0x61d1, 0xd2}, ++{0x61d2, 0xcc}, ++{0x61d3, 0x74}, ++{0x61d4, 0xd2}, ++{0x61d5, 0x1a}, ++{0x61d6, 0xcc}, ++{0x61d7, 0x12}, ++{0x61d8, 0x00}, ++{0x61d9, 0x12}, ++{0x61da, 0xcc}, ++{0x61db, 0x8a}, ++{0x61dc, 0xd2}, ++{0x61dd, 0xcc}, ++{0x61de, 0x74}, ++{0x61df, 0xd2}, ++{0x61e0, 0x1a}, ++{0x61e1, 0xcc}, ++{0x61e2, 0x12}, ++{0x61e3, 0x00}, ++{0x61e4, 0x12}, ++{0x61e5, 0xcc}, ++{0x61e6, 0x8a}, ++{0x61e7, 0xd2}, ++{0x61e8, 0xcc}, ++{0x61e9, 0x74}, ++{0x61ea, 0xd2}, ++{0x61eb, 0xd5}, ++{0x61ec, 0xcc}, ++{0x61ed, 0x12}, ++{0x61ee, 0x00}, ++{0x61ef, 0x12}, ++{0x61f0, 0xcc}, ++{0x61f1, 0x9c}, ++{0x61f2, 0xd5}, ++{0x6400, 0x04}, ++{0x6401, 0x04}, ++{0x6402, 0x00}, ++{0x6403, 0xff}, ++{0x6404, 0x00}, ++{0x6405, 0x08}, ++{0x6406, 0x00}, ++{0x6407, 0xff}, ++{0x6408, 0x04}, ++{0x6409, 0x70}, ++{0x640a, 0x00}, ++{0x640b, 0xff}, ++{0x640c, 0x05}, ++{0x640d, 0x14}, ++{0x640e, 0x04}, ++{0x640f, 0x71}, ++{0x6410, 0x05}, ++{0x6411, 0x74}, ++{0x6412, 0x00}, ++{0x6413, 0xff}, ++{0x6414, 0x05}, ++{0x6415, 0x54}, ++{0x6416, 0x05}, ++{0x6417, 0x44}, ++{0x6418, 0x04}, ++{0x6419, 0x30}, ++{0x641a, 0x05}, ++{0x641b, 0x46}, ++{0x641c, 0x00}, ++{0x641d, 0xff}, ++{0x641e, 0x04}, ++{0x641f, 0x31}, ++{0x6420, 0x04}, ++{0x6421, 0x30}, ++{0x6422, 0x00}, ++{0x6423, 0xff}, ++{0x6424, 0x04}, ++{0x6425, 0x20}, ++{0x6426, 0x05}, ++{0x6427, 0x06}, ++{0x6428, 0x00}, ++{0x6429, 0xff}, ++{0x642a, 0x08}, ++{0x642b, 0x2a}, ++{0x642c, 0x08}, ++{0x642d, 0x31}, ++{0x642e, 0x00}, ++{0x642f, 0xff}, ++{0x6430, 0x08}, ++{0x6431, 0x2a}, ++{0x6432, 0x08}, ++{0x6433, 0x31}, ++{0x6434, 0x06}, ++{0x6435, 0x20}, ++{0x6436, 0x07}, ++{0x6437, 0x00}, ++{0x6438, 0x08}, ++{0x6439, 0x40}, ++{0x643a, 0x00}, ++{0x643b, 0xff}, ++{0x643c, 0x08}, ++{0x643d, 0x2a}, ++{0x643e, 0x08}, ++{0x643f, 0x36}, ++{0x6440, 0x06}, ++{0x6441, 0x10}, ++{0x6442, 0x07}, ++{0x6443, 0x00}, ++{0x6444, 0x08}, ++{0x6445, 0x40}, ++{0x6446, 0x00}, ++{0x6447, 0xff}, ++{0x6448, 0x08}, ++{0x6449, 0x2a}, ++{0x644a, 0x08}, ++{0x644b, 0x3b}, ++{0x644c, 0x06}, ++{0x644d, 0x00}, ++{0x644e, 0x07}, ++{0x644f, 0x00}, ++{0x6450, 0x08}, ++{0x6451, 0x40}, ++{0x6452, 0x00}, ++{0x6453, 0xff}, ++{0x6454, 0x06}, ++{0x6455, 0x00}, ++{0x6456, 0x07}, ++{0x6457, 0x05}, ++{0x6458, 0x01}, ++{0x6459, 0xaf}, ++{0x645a, 0x01}, ++{0x645b, 0x0f}, ++{0x645c, 0x01}, ++{0x645d, 0x90}, ++{0x645e, 0x01}, ++{0x645f, 0xc8}, ++{0x6460, 0x00}, ++{0x6461, 0xff}, ++{0x6462, 0x01}, ++{0x6463, 0xac}, ++{0x6464, 0x01}, ++{0x6465, 0x0c}, ++{0x6466, 0x01}, ++{0x6467, 0x90}, ++{0x6468, 0x01}, ++{0x6469, 0xe8}, ++{0x646a, 0x00}, ++{0x646b, 0xff}, ++{0x646c, 0x01}, ++{0x646d, 0xad}, ++{0x646e, 0x01}, ++{0x646f, 0x0d}, ++{0x6470, 0x01}, ++{0x6471, 0x90}, ++{0x6472, 0x01}, ++{0x6473, 0xe8}, ++{0x6474, 0x00}, ++{0x6475, 0xff}, ++{0x6476, 0x01}, ++{0x6477, 0xae}, ++{0x6478, 0x01}, ++{0x6479, 0x0e}, ++{0x647a, 0x01}, ++{0x647b, 0x90}, ++{0x647c, 0x01}, ++{0x647d, 0xe8}, ++{0x647e, 0x00}, ++{0x647f, 0xff}, ++{0x6480, 0x01}, ++{0x6481, 0xb0}, ++{0x6482, 0x01}, ++{0x6483, 0xb1}, ++{0x6484, 0x01}, ++{0x6485, 0xb2}, ++{0x6486, 0x01}, ++{0x6487, 0xb3}, ++{0x6488, 0x01}, ++{0x6489, 0xb4}, ++{0x648a, 0x01}, ++{0x648b, 0xb5}, ++{0x648c, 0x01}, ++{0x648d, 0xb6}, ++{0x648e, 0x01}, ++{0x648f, 0xb7}, ++{0x6490, 0x01}, ++{0x6491, 0xb8}, ++{0x6492, 0x01}, ++{0x6493, 0xb9}, ++{0x6494, 0x01}, ++{0x6495, 0xba}, ++{0x6496, 0x01}, ++{0x6497, 0xbb}, ++{0x6498, 0x01}, ++{0x6499, 0xbc}, ++{0x649a, 0x01}, ++{0x649b, 0xbd}, ++{0x649c, 0x01}, ++{0x649d, 0xbe}, ++{0x649e, 0x01}, ++{0x649f, 0xbf}, ++{0x64a0, 0x01}, ++{0x64a1, 0xc0}, ++{0x64a2, 0x00}, ++{0x64a3, 0xff}, ++{0x64a4, 0x06}, ++{0x64a5, 0x00}, ++{0x64a6, 0x01}, ++{0x64a7, 0xf6}, ++{0x64a8, 0x04}, ++{0x64a9, 0x30}, ++{0x64aa, 0x00}, ++{0x64ab, 0xff}, ++{0x64ac, 0x06}, ++{0x64ad, 0x10}, ++{0x64ae, 0x01}, ++{0x64af, 0xf6}, ++{0x64b0, 0x04}, ++{0x64b1, 0x30}, ++{0x64b2, 0x06}, ++{0x64b3, 0x00}, ++{0x64b4, 0x00}, ++{0x64b5, 0xff}, ++{0x64b6, 0x06}, ++{0x64b7, 0x20}, ++{0x64b8, 0x01}, ++{0x64b9, 0xf6}, ++{0x64ba, 0x04}, ++{0x64bb, 0x30}, ++{0x64bc, 0x06}, ++{0x64bd, 0x00}, ++{0x64be, 0x00}, ++{0x64bf, 0xff}, ++{0x64c0, 0x04}, ++{0x64c1, 0x31}, ++{0x64c2, 0x04}, ++{0x64c3, 0x30}, ++{0x64c4, 0x01}, ++{0x64c5, 0x20}, ++{0x64c6, 0x01}, ++{0x64c7, 0x31}, ++{0x64c8, 0x01}, ++{0x64c9, 0x32}, ++{0x64ca, 0x01}, ++{0x64cb, 0x33}, ++{0x64cc, 0x01}, ++{0x64cd, 0x34}, ++{0x64ce, 0x01}, ++{0x64cf, 0x35}, ++{0x64d0, 0x01}, ++{0x64d1, 0x36}, ++{0x64d2, 0x01}, ++{0x64d3, 0x37}, ++{0x64d4, 0x01}, ++{0x64d5, 0x38}, ++{0x64d6, 0x01}, ++{0x64d7, 0x39}, ++{0x64d8, 0x01}, ++{0x64d9, 0x3a}, ++{0x64da, 0x01}, ++{0x64db, 0x3b}, ++{0x64dc, 0x01}, ++{0x64dd, 0x3c}, ++{0x64de, 0x01}, ++{0x64df, 0x3d}, ++{0x64e0, 0x01}, ++{0x64e1, 0x3e}, ++{0x64e2, 0x01}, ++{0x64e3, 0x3f}, ++{0x64e4, 0x02}, ++{0x64e5, 0xa0}, ++{0x64e6, 0x00}, ++{0x64e7, 0xff}, ++{0x64e8, 0x04}, ++{0x64e9, 0x31}, ++{0x64ea, 0x04}, ++{0x64eb, 0x30}, ++{0x64ec, 0x01}, ++{0x64ed, 0x00}, ++{0x64ee, 0x01}, ++{0x64ef, 0x11}, ++{0x64f0, 0x01}, ++{0x64f1, 0x12}, ++{0x64f2, 0x01}, ++{0x64f3, 0x13}, ++{0x64f4, 0x01}, ++{0x64f5, 0x14}, ++{0x64f6, 0x01}, ++{0x64f7, 0x15}, ++{0x64f8, 0x01}, ++{0x64f9, 0x16}, ++{0x64fa, 0x01}, ++{0x64fb, 0x17}, ++{0x64fc, 0x01}, ++{0x64fd, 0x18}, ++{0x64fe, 0x01}, ++{0x64ff, 0x19}, ++{0x6500, 0x01}, ++{0x6501, 0x1a}, ++{0x6502, 0x01}, ++{0x6503, 0x1b}, ++{0x6504, 0x01}, ++{0x6505, 0x1c}, ++{0x6506, 0x01}, ++{0x6507, 0x1d}, ++{0x6508, 0x01}, ++{0x6509, 0x1e}, ++{0x650a, 0x01}, ++{0x650b, 0x1f}, ++{0x650c, 0x02}, ++{0x650d, 0xa0}, ++{0x650e, 0x00}, ++{0x650f, 0xff}, ++{0x6510, 0x04}, ++{0x6511, 0x20}, ++{0x6512, 0x05}, ++{0x6513, 0x86}, ++{0x6514, 0x03}, ++{0x6515, 0x0b}, ++{0x6516, 0x05}, ++{0x6517, 0x86}, ++{0x6518, 0x00}, ++{0x6519, 0x00}, ++{0x651a, 0x05}, ++{0x651b, 0x06}, ++{0x651c, 0x00}, ++{0x651d, 0x04}, ++{0x651e, 0x05}, ++{0x651f, 0x04}, ++{0x6520, 0x00}, ++{0x6521, 0x04}, ++{0x6522, 0x05}, ++{0x6523, 0x00}, ++{0x6524, 0x05}, ++{0x6525, 0x0a}, ++{0x6526, 0x03}, ++{0x6527, 0x9a}, ++{0x6528, 0x05}, ++{0x6529, 0x86}, ++{0x652a, 0x00}, ++{0x652b, 0x00}, ++{0x652c, 0x05}, ++{0x652d, 0x06}, ++{0x652e, 0x00}, ++{0x652f, 0x01}, ++{0x6530, 0x05}, ++{0x6531, 0x04}, ++{0x6532, 0x00}, ++{0x6533, 0x04}, ++{0x6534, 0x05}, ++{0x6535, 0x00}, ++{0x6536, 0x05}, ++{0x6537, 0x0a}, ++{0x6538, 0x03}, ++{0x6539, 0x99}, ++{0x653a, 0x05}, ++{0x653b, 0x06}, ++{0x653c, 0x00}, ++{0x653d, 0x00}, ++{0x653e, 0x05}, ++{0x653f, 0x04}, ++{0x6540, 0x00}, ++{0x6541, 0x04}, ++{0x6542, 0x05}, ++{0x6543, 0x00}, ++{0x6544, 0x05}, ++{0x6545, 0x0a}, ++{0x6546, 0x03}, ++{0x6547, 0x98}, ++{0x6548, 0x05}, ++{0x6549, 0x06}, ++{0x654a, 0x00}, ++{0x654b, 0x00}, ++{0x654c, 0x05}, ++{0x654d, 0x04}, ++{0x654e, 0x00}, ++{0x654f, 0x04}, ++{0x6550, 0x05}, ++{0x6551, 0x00}, ++{0x6552, 0x05}, ++{0x6553, 0x0a}, ++{0x6554, 0x03}, ++{0x6555, 0x97}, ++{0x6556, 0x05}, ++{0x6557, 0x06}, ++{0x6558, 0x05}, ++{0x6559, 0x04}, ++{0x655a, 0x00}, ++{0x655b, 0x04}, ++{0x655c, 0x05}, ++{0x655d, 0x00}, ++{0x655e, 0x05}, ++{0x655f, 0x0a}, ++{0x6560, 0x03}, ++{0x6561, 0x96}, ++{0x6562, 0x05}, ++{0x6563, 0x06}, ++{0x6564, 0x05}, ++{0x6565, 0x04}, ++{0x6566, 0x00}, ++{0x6567, 0x04}, ++{0x6568, 0x05}, ++{0x6569, 0x00}, ++{0x656a, 0x05}, ++{0x656b, 0x0a}, ++{0x656c, 0x03}, ++{0x656d, 0x95}, ++{0x656e, 0x05}, ++{0x656f, 0x06}, ++{0x6570, 0x05}, ++{0x6571, 0x04}, ++{0x6572, 0x00}, ++{0x6573, 0x04}, ++{0x6574, 0x05}, ++{0x6575, 0x00}, ++{0x6576, 0x05}, ++{0x6577, 0x0a}, ++{0x6578, 0x03}, ++{0x6579, 0x94}, ++{0x657a, 0x05}, ++{0x657b, 0x06}, ++{0x657c, 0x00}, ++{0x657d, 0x00}, ++{0x657e, 0x05}, ++{0x657f, 0x04}, ++{0x6580, 0x00}, ++{0x6581, 0x04}, ++{0x6582, 0x05}, ++{0x6583, 0x00}, ++{0x6584, 0x05}, ++{0x6585, 0x0a}, ++{0x6586, 0x03}, ++{0x6587, 0x93}, ++{0x6588, 0x05}, ++{0x6589, 0x06}, ++{0x658a, 0x00}, ++{0x658b, 0x00}, ++{0x658c, 0x05}, ++{0x658d, 0x04}, ++{0x658e, 0x00}, ++{0x658f, 0x04}, ++{0x6590, 0x05}, ++{0x6591, 0x00}, ++{0x6592, 0x05}, ++{0x6593, 0x0a}, ++{0x6594, 0x03}, ++{0x6595, 0x92}, ++{0x6596, 0x05}, ++{0x6597, 0x06}, ++{0x6598, 0x05}, ++{0x6599, 0x04}, ++{0x659a, 0x00}, ++{0x659b, 0x04}, ++{0x659c, 0x05}, ++{0x659d, 0x00}, ++{0x659e, 0x05}, ++{0x659f, 0x0a}, ++{0x65a0, 0x03}, ++{0x65a1, 0x91}, ++{0x65a2, 0x05}, ++{0x65a3, 0x06}, ++{0x65a4, 0x05}, ++{0x65a5, 0x04}, ++{0x65a6, 0x00}, ++{0x65a7, 0x04}, ++{0x65a8, 0x05}, ++{0x65a9, 0x00}, ++{0x65aa, 0x05}, ++{0x65ab, 0x0a}, ++{0x65ac, 0x03}, ++{0x65ad, 0x90}, ++{0x65ae, 0x05}, ++{0x65af, 0x06}, ++{0x65b0, 0x05}, ++{0x65b1, 0x04}, ++{0x65b2, 0x00}, ++{0x65b3, 0x04}, ++{0x65b4, 0x05}, ++{0x65b5, 0x00}, ++{0x65b6, 0x05}, ++{0x65b7, 0x0a}, ++{0x65b8, 0x02}, ++{0x65b9, 0x90}, ++{0x65ba, 0x05}, ++{0x65bb, 0x06}, ++{0x65bc, 0x00}, ++{0x65bd, 0xff}, ++{0x65be, 0x04}, ++{0x65bf, 0x70}, ++{0x65c0, 0x08}, ++{0x65c1, 0x76}, ++{0x65c2, 0x00}, ++{0x65c3, 0xff}, ++{0x65c4, 0x08}, ++{0x65c5, 0x76}, ++{0x65c6, 0x04}, ++{0x65c7, 0x0c}, ++{0x65c8, 0x05}, ++{0x65c9, 0x07}, ++{0x65ca, 0x04}, ++{0x65cb, 0x04}, ++{0x65cc, 0x00}, ++{0x65cd, 0xff}, ++{0x65ce, 0x00}, ++{0x65cf, 0xff}, ++{0x65d0, 0x00}, ++{0x65d1, 0xff}, ++{0x30eb, 0x04}, ++{0x30ed, 0x5a}, ++{0x30ee, 0x01}, ++{0x30ef, 0x80}, ++{0x30f1, 0x5a}, ++{0x303a, 0x04}, ++{0x303b, 0x7f}, ++{0x303c, 0xfe}, ++{0x303d, 0x19}, ++{0x303e, 0xd7}, ++{0x303f, 0x09}, ++{0x3040, 0x78}, ++{0x3042, 0x05}, ++{0x328a, 0x10}, ++ ++{0x3291, 0x03}, /* 7:enable flip and mirror offset may on 20150330 */ ++ ++/* change settings to 1280x1080 COMB12 30 fps, 96MHz */ ++{0x3012, 0x0}, ++{0x3000, 0x3}, ++{0x3001, 0x50}, ++{0x3002, 0x0a}, ++{0x3004, 0x3}, ++{0x3005, 0x48}, ++{0x3006, 0x7}, ++{0x308f, 0x10}, ++{0x3127, 0x63}, ++{0x3074, OV10640_X_START >> 8}, ++{0x3075, OV10640_X_START & 0xff}, ++{0x3076, OV10640_Y_START >> 8}, ++{0x3077, OV10640_Y_START & 0xff}, ++{0x3078, OV10640_X_END >> 8}, ++{0x3079, OV10640_X_END & 0xff}, ++{0x307a, OV10640_Y_END >> 8}, ++{0x307b, OV10640_Y_END & 0xff}, ++{0x307c, OV10640_MAX_WIDTH >> 8}, ++{0x307d, OV10640_MAX_WIDTH & 0xff}, ++{0x307e, OV10640_MAX_HEIGHT >> 8}, ++{0x307f, OV10640_MAX_HEIGHT & 0xff}, ++{0x3080, (OV10640_SENSOR_WIDTH + 200) >> 8}, // HTS ++{0x3081, (OV10640_SENSOR_WIDTH + 200) & 0xff}, ++{0x3082, (OV10640_SENSOR_HEIGHT + 208) >> 8}, //VTS ++{0x3083, (OV10640_SENSOR_HEIGHT + 208) & 0xff}, ++{0x3084, 0x0}, ++{0x3085, 0x0}, ++{0x3086, 0x0}, ++{0x3087, 0x0}, ++{0x346d, 0x14}, ++{0x3444, 0x28}, ++{0x3091, 0x0}, ++{0x3119, 0x44}, // COMB12 ++{0x3012, 0x1}, ++}; +diff --git a/drivers/media/i2c/soc_camera/ov106xx.c b/drivers/media/i2c/soc_camera/ov106xx.c +index aaadcc2..b0a3c90 100644 +--- a/drivers/media/i2c/soc_camera/ov106xx.c ++++ b/drivers/media/i2c/soc_camera/ov106xx.c +@@ -10,6 +10,7 @@ + */ + + #include "ov10635.c" ++#include "ov10640.c" + #include "ov490_ov10640.c" + #include "ov495_ov2775.c" + #include "ar0132.c" +@@ -28,6 +29,7 @@ + + static enum { + ID_OV10635, ++ ID_OV10640, + ID_OV490_OV10640, + ID_OV495_OV2775, + ID_AR0132, +@@ -63,6 +65,12 @@ static int ov106xx_probe(struct i2c_client *client, + goto out; + } + ++ ret = ov10640_probe(client, did); ++ if (!ret) { ++ chip_id = ID_OV10640; ++ goto out; ++ } ++ + ret = ov10635_probe(client, did); + if (!ret) { + chip_id = ID_OV10635; +@@ -159,6 +167,9 @@ static int ov106xx_remove(struct i2c_client *client) + case ID_OV10635: + ov10635_remove(client); + break; ++ case ID_OV10640: ++ ov10640_remove(client); ++ break; + case ID_OV490_OV10640: + ov490_remove(client); + break; +@@ -233,6 +244,6 @@ static struct i2c_driver ov106xx_i2c_driver = { + + module_i2c_driver(ov106xx_i2c_driver); + +-MODULE_DESCRIPTION("SoC Camera driver for OV10635, OV490+OV10640, OV495+OV2775, AR0132/140/143/220/223/323, AP0101+AR014X"); ++MODULE_DESCRIPTION("SoC Camera driver for OV10635/10640/OV490/OV495, AR0132/140/143/220/223/323, AP0101"); + MODULE_AUTHOR("Vladimir Barinov"); + MODULE_LICENSE("GPL"); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0145-lvds-ti9x4-fix-remote-gpio-enablement-on-UB913.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0145-lvds-ti9x4-fix-remote-gpio-enablement-on-UB913.patch new file mode 100644 index 00000000..f9addd09 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0145-lvds-ti9x4-fix-remote-gpio-enablement-on-UB913.patch @@ -0,0 +1,37 @@ +From 047c89263645b7ab71162b40f60815487662fbec Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Mon, 14 Jan 2019 16:41:09 +0300 +Subject: [PATCH 094/122] lvds: ti9x4: fix remote gpio enablement on UB913 + +This fix enablemnet of remote gpios on UB913 + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ti9x4.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ti9x4.c b/drivers/media/i2c/soc_camera/ti9x4.c +index 7b8209b..db60ebd 100644 +--- a/drivers/media/i2c/soc_camera/ti9x4.c ++++ b/drivers/media/i2c/soc_camera/ti9x4.c +@@ -325,8 +325,15 @@ static int ti9x4_initialize(struct i2c_client *client) + usleep_range(1000, 1500); /* wait 1ms */ + + client->addr = priv->ti9x3_addr_map[idx]; /* TI9X3 I2C addr */ +- reg8_write(client, 0x0d, 0xf0); /* Enable all remote GPIOs */ +- reg8_write(client, 0x0e, 0xf0); /* Enable serializer GPIOs */ ++ switch (priv->ser_id) { ++ case TI913_ID: ++ reg8_write(client, 0x0d, 0x55); /* Enable remote GPIO0/1 */ ++ break; ++ case TI953_ID: ++ reg8_write(client, 0x0d, 0xf0); /* Enable all remote GPIOs */ ++ reg8_write(client, 0x0e, 0xf0); /* Enable serializer GPIOs */ ++ break; ++ } + client->addr = priv->des_addr; + } + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0146-lvds-add-dummy-imager-driver.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0146-lvds-add-dummy-imager-driver.patch new file mode 100644 index 00000000..34b35bb6 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0146-lvds-add-dummy-imager-driver.patch @@ -0,0 +1,350 @@ +From f44ff8e351a4c5447f3bcf7e0138e2373793a55a Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Thu, 17 Jan 2019 10:41:34 +0300 +Subject: [PATCH 095/122] lvds: add dummy imager driver + +Dummy imager glue driver + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/Makefile | 1 + + drivers/media/i2c/soc_camera/dummy.c | 317 ++++++++++++++++++++++++++++++++++ + 2 files changed, 318 insertions(+) + create mode 100644 drivers/media/i2c/soc_camera/dummy.c + +diff --git a/drivers/media/i2c/soc_camera/Makefile b/drivers/media/i2c/soc_camera/Makefile +index eed6e24..4aa5046 100644 +--- a/drivers/media/i2c/soc_camera/Makefile ++++ b/drivers/media/i2c/soc_camera/Makefile +@@ -15,4 +15,5 @@ obj-$(CONFIG_SOC_CAMERA_MAX9286) += max9286.o + obj-$(CONFIG_SOC_CAMERA_TI9X4) += ti9x4.o + obj-$(CONFIG_SOC_CAMERA_OV106XX) += ov106xx.o + obj-$(CONFIG_SOC_CAMERA_IMX219) += imx219.o ++obj-y += dummy.o + +diff --git a/drivers/media/i2c/soc_camera/dummy.c b/drivers/media/i2c/soc_camera/dummy.c +new file mode 100644 +index 0000000..a38d7c4 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/dummy.c +@@ -0,0 +1,317 @@ ++/* ++ * Dummy sensor camera driver ++ * ++ * Copyright (C) 2019 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#define MEDIA_BUS_FORMAT MEDIA_BUS_FMT_YUYV8_2X8 ++ ++struct dummy_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int max_width; ++ int max_height; ++}; ++ ++static inline struct dummy_priv *to_dummy(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct dummy_priv, sd); ++} ++ ++static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) ++{ ++ return &container_of(ctrl->handler, struct dummy_priv, hdl)->sd; ++} ++ ++static int dummy_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int dummy_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct dummy_priv *priv = to_dummy(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = MEDIA_BUS_FORMAT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int dummy_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = MEDIA_BUS_FORMAT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int dummy_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = MEDIA_BUS_FORMAT; ++ ++ return 0; ++} ++ ++static int dummy_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct dummy_priv *priv = to_dummy(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > priv->max_width) || ++ (rect->top + rect->height > priv->max_height)) ++ *rect = priv->rect; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ return 0; ++} ++ ++static int dummy_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct dummy_priv *priv = to_dummy(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = priv->max_width; ++ sel->r.height = priv->max_height; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = priv->max_width; ++ sel->r.height = priv->max_height; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int dummy_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++static int dummy_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ return -EINVAL; ++} ++ ++static const struct v4l2_ctrl_ops dummy_ctrl_ops = { ++ .s_ctrl = dummy_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops dummy_video_ops = { ++ .s_stream = dummy_s_stream, ++ .g_mbus_config = dummy_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops dummy_subdev_pad_ops = { ++ .enum_mbus_code = dummy_enum_mbus_code, ++ .get_selection = dummy_get_selection, ++ .set_selection = dummy_set_selection, ++ .get_fmt = dummy_get_fmt, ++ .set_fmt = dummy_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops dummy_subdev_ops = { ++ .video = &dummy_video_ops, ++ .pad = &dummy_subdev_pad_ops, ++}; ++ ++static int dummy_initialize(struct i2c_client *client) ++{ ++ struct dummy_priv *priv = to_dummy(client); ++ ++ dev_info(&client->dev, "Dummy sensor res %dx%d\n", priv->max_width, priv->max_height); ++ ++ return 0; ++} ++ ++static int dummy_parse_dt(struct device_node *np, struct dummy_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int err; ++ ++ err = of_property_read_u32(np, "dummy,width", &priv->max_width); ++ if (err) { ++ dev_err(&client->dev, "dummy,width must be defined\n"); ++ goto out; ++ } ++ ++ err = of_property_read_u32(np, "dummy,height", &priv->max_height); ++ if (err) { ++ dev_err(&client->dev, "dummy,height must be defined\n"); ++ goto out; ++ } ++ ++out: ++ return err; ++} ++ ++static int dummy_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct dummy_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &dummy_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = dummy_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = dummy_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = priv->max_width; ++ priv->rect.height = priv->max_height; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++ return ret; ++} ++ ++static int dummy_remove(struct i2c_client *client) ++{ ++ struct dummy_priv *priv = i2c_get_clientdata(client); ++ ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++static const struct i2c_device_id dummy_id[] = { ++ { "dummy-camera", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, dummy_id); ++ ++static const struct of_device_id dummy_of_ids[] = { ++ { .compatible = "dummy-camera", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, dummy_of_ids); ++ ++static struct i2c_driver dummy_i2c_driver = { ++ .driver = { ++ .name = "dummy-camera", ++ .of_match_table = dummy_of_ids, ++ }, ++ .probe = dummy_probe, ++ .remove = dummy_remove, ++ .id_table = dummy_id, ++}; ++module_i2c_driver(dummy_i2c_driver); ++ ++MODULE_DESCRIPTION("Dummy SoC camera driver"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0147-lvds-ti9x4-use-REFCLK-23.0MHz.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0147-lvds-ti9x4-use-REFCLK-23.0MHz.patch new file mode 100644 index 00000000..eee6d9b6 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0147-lvds-ti9x4-use-REFCLK-23.0MHz.patch @@ -0,0 +1,39 @@ +From cd625ee08e7e815083795182c79521c13067321e Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Thu, 7 Feb 2019 11:49:46 +0300 +Subject: [PATCH 096/122] lvds: ti9x4: use REFCLK=23.0MHz + +This fixes data integrity on FPDLink channel + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ti9x4.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ti9x4.c b/drivers/media/i2c/soc_camera/ti9x4.c +index db60ebd..373652a 100644 +--- a/drivers/media/i2c/soc_camera/ti9x4.c ++++ b/drivers/media/i2c/soc_camera/ti9x4.c +@@ -144,7 +144,7 @@ static void ti9x4_initial_setup(struct i2c_client *client) + reg8_write(client, 0x0d, 0xb9); /* VDDIO 3.3V */ + switch (priv->csi_rate) { + case 1600: /* REFCLK = 25MHZ */ +- case 1500: /* REFCLK = 23.5MHZ */ ++ case 1500: /* REFCLK = 23MHZ */ + case 1450: /* REFCLK = 22.5MHZ */ + reg8_write(client, 0x1f, 0x00); /* CSI rate 1.5/1.6Gbps */ + break; +@@ -173,8 +173,8 @@ static void ti9x4_initial_setup(struct i2c_client *client) + fs_time = 2790; + break; + case 1500: +- /* FrameSync setup for REFCLK=23.5MHz, FPS=30: period_counts=1/FPS/12.766mks=1/30/12.766e-6=2612 -> HI=2, LO=2610 */ +- fs_time = 2625; ++ /* FrameSync setup for REFCLK=23MHz, FPS=30: period_counts=1/FPS/13.043mks=1/30/13.043e-6=2556 -> HI=2, LO=2554 */ ++ fs_time = 2570; + break; + case 1450: + case 1100: +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0148-lvds-ar0231-fix-comments.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0148-lvds-ar0231-fix-comments.patch new file mode 100644 index 00000000..df0a1748 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0148-lvds-ar0231-fix-comments.patch @@ -0,0 +1,48 @@ +From 85f8c9a60ec11fe59913cb93442e380249e95d13 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Thu, 7 Feb 2019 11:55:03 +0300 +Subject: [PATCH 097/122] lvds: ar0231: fix comments + +This fixes comments on PLL calculation + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ar0231_rev7.h | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ar0231_rev7.h b/drivers/media/i2c/soc_camera/ar0231_rev7.h +index 885d34e..5f196e8 100644 +--- a/drivers/media/i2c/soc_camera/ar0231_rev7.h ++++ b/drivers/media/i2c/soc_camera/ar0231_rev7.h +@@ -301,14 +301,14 @@ static const struct ar0231_reg ar0231_regs_wizard_rev7[] = { + #endif /* Sensor Setup */ + + #if 1 /* Serial 12-bit Timing Setup */ +-/* PCLK=27Mhz/PRE_PLL_CLK_DIV *PLL_MULTIPLIER /P1 /P4 *2 */ +-/* PCLK=27Mhz/2 *44/1/12 *2= 99Mhz - TI serializers */ +-{0x302A, 6}, // vt_pix_clk_div (P2 divider) +-{0x302C, 1}, // vt_sys_clk_div (P1 divider) ++/* PCLK=24Mhz/PRE_PLL_CLK_DIV *PLL_MULTIPLIER /P1 /P4 *2 */ ++/* PCLK=24Mhz/2 *44/1/12 *2= 88Mhz - TI serializers */ + {0x302E, 2}, // pre_pll_clk_div + {0x3030, 44}, // pll_multiplier +-{0x3036, 12}, // op_word_clk_div (P4 divider) ++{0x302C, 1}, // vt_sys_clk_div (P1 divider) ++{0x302A, 6}, // vt_pix_clk_div (P2 divider) + {0x3038, 1}, // op_sys_clk_div (P3 divider) ++{0x3036, 12}, // op_word_clk_div (P4 divider) + {0x30B0, 0x800}, // digital_test: pll_complete_bypass=0 + #endif /* Serial 12-bit Timing Setup */ + +@@ -384,7 +384,7 @@ static const struct ar0231_reg ar0231_regs_wizard_rev7[] = { + {0x31BC, 0x805}, + #endif /* MIPI 12 bit Settings */ + +-/* FPS = 124.5MHz / reg0x300A / reg0x300C * (DES_XTAL/27MHz), DES_XTAL=23.5MHz */ ++/* FPS = 105MHz / reg0x300A / reg0x300C * (DES_XTAL/27MHz), DES_XTAL=23.5MHz */ + {0x300A, AR0231_SENSOR_HEIGHT + 100}, // Frame_length_Lines + {0x300C, AR0231_SENSOR_WIDTH + 550}, // Line_length_pck + {0x3012, 0x144}, //Integration_time +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0149-lvds-ISX019-rename-isx016-to-isx019.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0149-lvds-ISX019-rename-isx016-to-isx019.patch new file mode 100644 index 00000000..7f8a8898 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0149-lvds-ISX019-rename-isx016-to-isx019.patch @@ -0,0 +1,1402 @@ +From 2cf498aeeae73aa2d3719a5ab3dc47f2f4e29187 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Thu, 7 Feb 2019 12:02:09 +0300 +Subject: [PATCH 098/122] lvds: ISX019: rename isx016 to isx019 + +Rename misnamed imager + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/isx016.c | 628 --------------------------------- + drivers/media/i2c/soc_camera/isx016.h | 27 -- + drivers/media/i2c/soc_camera/isx019.c | 628 +++++++++++++++++++++++++++++++++ + drivers/media/i2c/soc_camera/isx019.h | 27 ++ + drivers/media/i2c/soc_camera/ov106xx.c | 12 +- + 5 files changed, 661 insertions(+), 661 deletions(-) + delete mode 100644 drivers/media/i2c/soc_camera/isx016.c + delete mode 100644 drivers/media/i2c/soc_camera/isx016.h + create mode 100644 drivers/media/i2c/soc_camera/isx019.c + create mode 100644 drivers/media/i2c/soc_camera/isx019.h + +diff --git a/drivers/media/i2c/soc_camera/isx016.c b/drivers/media/i2c/soc_camera/isx016.c +deleted file mode 100644 +index 275bd8a..0000000 +--- a/drivers/media/i2c/soc_camera/isx016.c ++++ /dev/null +@@ -1,628 +0,0 @@ +-/* +- * ON Semiconductor ISX016 sensor camera driver +- * +- * Copyright (C) 2018 Cogent Embedded, Inc. +- * +- * 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 +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +- +-#include "isx016.h" +- +-static const int isx016_i2c_addr[] = {0x1a}; +- +-#define ISX016_PID 0x0000 +-#define ISX016_VERSION_REG 0x0740 +- +-#define ISX016_MEDIA_BUS_FMT MEDIA_BUS_FMT_YUYV8_2X8 +- +-static void isx016_otp_id_read(struct i2c_client *client); +- +-struct isx016_priv { +- struct v4l2_subdev sd; +- struct v4l2_ctrl_handler hdl; +- struct media_pad pad; +- struct v4l2_rect rect; +- int max_width; +- int max_height; +- int init_complete; +- u8 id[6]; +- int exposure; +- int gain; +- int autogain; +- /* serializers */ +- int max9286_addr; +- int max9271_addr; +- int port; +- int gpio_resetb; +- int gpio_fsin; +-}; +- +-static inline struct isx016_priv *to_isx016(const struct i2c_client *client) +-{ +- return container_of(i2c_get_clientdata(client), struct isx016_priv, sd); +-} +- +-static void isx016_s_port(struct i2c_client *client, int fwd_en) +-{ +- struct isx016_priv *priv = to_isx016(client); +- int tmp_addr; +- +- if (priv->max9286_addr) { +- tmp_addr = client->addr; +- client->addr = priv->max9286_addr; /* Deserializer I2C address */ +- reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ +- usleep_range(5000, 5500); /* wait 5ms */ +- client->addr = tmp_addr; +- }; +-} +- +-static int isx016_read16(struct i2c_client *client, u8 category, u16 reg, u16 *val) +-{ +- int ret; +- #define R_NUM_BYTES 9 +- #define R_NUM_CMDS 1 +- #define R_NUM_CMD_BYTES 6 +- #define R_CMD 1 +- #define R_BYTES 2 +- u8 buf[R_NUM_BYTES] = {R_NUM_BYTES, R_NUM_CMDS, +- R_NUM_CMD_BYTES, R_CMD, +- category, reg >> 8, reg & 0xff, +- R_BYTES, 0x00}; +- +- /* calculate checksum */ +- buf[8] = R_NUM_BYTES + R_NUM_CMDS + R_NUM_CMD_BYTES + R_CMD + +- category + (reg >> 8) + (reg & 0xff) + R_BYTES; +- +- ret = i2c_master_send(client, buf, R_NUM_BYTES); +- if (ret == R_NUM_BYTES) +- ret = i2c_master_recv(client, buf, R_NUM_BYTES - 2); +- +- if (ret < 0) { +- dev_err(&client->dev, +- "read fail: chip 0x%x register 0x%x: %d\n", +- client->addr, reg, ret); +- } else { +- *val = ((u16)buf[4] << 8) | buf[5]; +- } +- +- return ret < 0 ? ret : 0; +-} +- +-static int isx016_write16(struct i2c_client *client, u8 category, u16 reg, u16 val) +-{ +- int ret; +- #define W_NUM_BYTES 10 +- #define W_NUM_CMDS 1 +- #define W_NUM_CMD_BYTES 7 +- #define W_CMD 2 +- u8 buf[W_NUM_BYTES] = {W_NUM_BYTES, W_NUM_CMDS, +- W_NUM_CMD_BYTES, W_CMD, +- category, reg >> 8, reg & 0xff, +- val >> 8, val & 0xff}; +- +- /* calculate checksum */ +- buf[9] = W_NUM_BYTES + W_NUM_CMDS + W_NUM_CMD_BYTES + W_CMD + +- category + (reg >> 8) + (reg & 0xff) + (val >> 8) + (val & 0xff); +- +- ret = i2c_master_send(client, buf, W_NUM_BYTES); +- +- if (ret < 0) { +- dev_err(&client->dev, +- "write fail: chip 0x%x register 0x%x: %d\n", +- client->addr, reg, ret); +- } +- +- return ret < 0 ? ret : 0; +-} +- +-static int isx016_set_regs(struct i2c_client *client, +- const struct isx016_reg *regs, int nr_regs) +-{ +- int i; +- +- for (i = 0; i < nr_regs; i++) { +- if (regs[i].reg == ISX016_DELAY) { +- mdelay(regs[i].val); +- continue; +- } +- +- isx016_write16(client, regs[i].reg >> 8, regs[i].reg & 0xff, regs[i].val); +- } +- +- return 0; +-} +- +-static int isx016_s_stream(struct v4l2_subdev *sd, int enable) +-{ +- return 0; +-} +- +-static int isx016_get_fmt(struct v4l2_subdev *sd, +- struct v4l2_subdev_pad_config *cfg, +- struct v4l2_subdev_format *format) +-{ +- struct v4l2_mbus_framefmt *mf = &format->format; +- struct i2c_client *client = v4l2_get_subdevdata(sd); +- struct isx016_priv *priv = to_isx016(client); +- +- if (format->pad) +- return -EINVAL; +- +- mf->width = priv->rect.width; +- mf->height = priv->rect.height; +- mf->code = ISX016_MEDIA_BUS_FMT; +- mf->colorspace = V4L2_COLORSPACE_SMPTE170M; +- mf->field = V4L2_FIELD_NONE; +- +- return 0; +-} +- +-static int isx016_set_fmt(struct v4l2_subdev *sd, +- struct v4l2_subdev_pad_config *cfg, +- struct v4l2_subdev_format *format) +-{ +- struct v4l2_mbus_framefmt *mf = &format->format; +- +- mf->code = ISX016_MEDIA_BUS_FMT; +- mf->colorspace = V4L2_COLORSPACE_SMPTE170M; +- mf->field = V4L2_FIELD_NONE; +- +- if (format->which == V4L2_SUBDEV_FORMAT_TRY) +- cfg->try_fmt = *mf; +- +- return 0; +-} +- +-static int isx016_enum_mbus_code(struct v4l2_subdev *sd, +- struct v4l2_subdev_pad_config *cfg, +- struct v4l2_subdev_mbus_code_enum *code) +-{ +- if (code->pad || code->index > 0) +- return -EINVAL; +- +- code->code = ISX016_MEDIA_BUS_FMT; +- +- return 0; +-} +- +-static int isx016_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) +-{ +- struct i2c_client *client = v4l2_get_subdevdata(sd); +- struct isx016_priv *priv = to_isx016(client); +- +- isx016_otp_id_read(client); +- +- memcpy(edid->edid, priv->id, 6); +- +- edid->edid[6] = 0xff; +- edid->edid[7] = client->addr; +- edid->edid[8] = ISX016_VERSION_REG >> 8; +- edid->edid[9] = ISX016_VERSION_REG & 0xff; +- +- return 0; +-} +- +-static int isx016_set_selection(struct v4l2_subdev *sd, +- struct v4l2_subdev_pad_config *cfg, +- struct v4l2_subdev_selection *sel) +-{ +- struct v4l2_rect *rect = &sel->r; +- struct i2c_client *client = v4l2_get_subdevdata(sd); +- struct isx016_priv *priv = to_isx016(client); +- +- if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || +- sel->target != V4L2_SEL_TGT_CROP) +- return -EINVAL; +- +- rect->left = ALIGN(rect->left, 2); +- rect->top = ALIGN(rect->top, 2); +- rect->width = ALIGN(rect->width, 2); +- rect->height = ALIGN(rect->height, 2); +- +- if ((rect->left + rect->width > priv->max_width) || +- (rect->top + rect->height > priv->max_height)) +- *rect = priv->rect; +- +- priv->rect.left = rect->left; +- priv->rect.top = rect->top; +- priv->rect.width = rect->width; +- priv->rect.height = rect->height; +- +- return 0; +-} +- +-static int isx016_get_selection(struct v4l2_subdev *sd, +- struct v4l2_subdev_pad_config *cfg, +- struct v4l2_subdev_selection *sel) +-{ +- struct i2c_client *client = v4l2_get_subdevdata(sd); +- struct isx016_priv *priv = to_isx016(client); +- +- if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) +- return -EINVAL; +- +- switch (sel->target) { +- case V4L2_SEL_TGT_CROP_BOUNDS: +- sel->r.left = 0; +- sel->r.top = 0; +- sel->r.width = priv->max_width; +- sel->r.height = priv->max_height; +- return 0; +- case V4L2_SEL_TGT_CROP_DEFAULT: +- sel->r.left = 0; +- sel->r.top = 0; +- sel->r.width = priv->max_width; +- sel->r.height = priv->max_height; +- return 0; +- case V4L2_SEL_TGT_CROP: +- sel->r = priv->rect; +- return 0; +- default: +- return -EINVAL; +- } +-} +- +-static int isx016_g_mbus_config(struct v4l2_subdev *sd, +- struct v4l2_mbus_config *cfg) +-{ +- cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | +- V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; +- cfg->type = V4L2_MBUS_CSI2; +- +- return 0; +-} +- +-#ifdef CONFIG_VIDEO_ADV_DEBUG +-static int isx016_g_register(struct v4l2_subdev *sd, +- struct v4l2_dbg_register *reg) +-{ +- struct i2c_client *client = v4l2_get_subdevdata(sd); +- int ret; +- u16 val = 0; +- +- ret = isx016_read16(client, (u16)reg->reg >> 8, (u16)reg->reg & 0xff, &val); +- if (ret < 0) +- return ret; +- +- reg->val = val; +- reg->size = sizeof(u16); +- +- return 0; +-} +- +-static int isx016_s_register(struct v4l2_subdev *sd, +- const struct v4l2_dbg_register *reg) +-{ +- struct i2c_client *client = v4l2_get_subdevdata(sd); +- +- return isx016_write16(client, (u16)reg->reg >> 8, (u16)reg->reg & 0xff, (u16)reg->val); +-} +-#endif +- +-static struct v4l2_subdev_core_ops isx016_core_ops = { +-#ifdef CONFIG_VIDEO_ADV_DEBUG +- .g_register = isx016_g_register, +- .s_register = isx016_s_register, +-#endif +-}; +- +-static int isx016_s_ctrl(struct v4l2_ctrl *ctrl) +-{ +- struct v4l2_subdev *sd = to_sd(ctrl); +- struct i2c_client *client = v4l2_get_subdevdata(sd); +- struct isx016_priv *priv = to_isx016(client); +- int ret = -EINVAL; +- +- if (!priv->init_complete) +- return 0; +- +- switch (ctrl->id) { +- case V4L2_CID_BRIGHTNESS: +- case V4L2_CID_CONTRAST: +- case V4L2_CID_SATURATION: +- case V4L2_CID_HUE: +- case V4L2_CID_GAMMA: +- case V4L2_CID_SHARPNESS: +- case V4L2_CID_AUTOGAIN: +- case V4L2_CID_GAIN: +- case V4L2_CID_EXPOSURE: +- case V4L2_CID_HFLIP: +- case V4L2_CID_VFLIP: +- break; +- } +- +- return ret; +-} +- +-static const struct v4l2_ctrl_ops isx016_ctrl_ops = { +- .s_ctrl = isx016_s_ctrl, +-}; +- +-static struct v4l2_subdev_video_ops isx016_video_ops = { +- .s_stream = isx016_s_stream, +- .g_mbus_config = isx016_g_mbus_config, +-}; +- +-static const struct v4l2_subdev_pad_ops isx016_subdev_pad_ops = { +- .get_edid = isx016_get_edid, +- .enum_mbus_code = isx016_enum_mbus_code, +- .get_selection = isx016_get_selection, +- .set_selection = isx016_set_selection, +- .get_fmt = isx016_get_fmt, +- .set_fmt = isx016_set_fmt, +-}; +- +-static struct v4l2_subdev_ops isx016_subdev_ops = { +- .core = &isx016_core_ops, +- .video = &isx016_video_ops, +- .pad = &isx016_subdev_pad_ops, +-}; +- +-static void isx016_otp_id_read(struct i2c_client *client) +-{ +- struct isx016_priv *priv = to_isx016(client); +- int i; +- u16 val = 0; +- +- /* read camera id from isx016 OTP memory */ +- for (i = 0; i < 6; i+=2) { +- isx016_read16(client, 8, 0x60 + i, &val); +- priv->id[i] = val >> 8; +- priv->id[i+1] = val & 0xff; +- } +-} +- +-static ssize_t isx016_otp_id_show(struct device *dev, +- struct device_attribute *attr, char *buf) +-{ +- struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); +- struct i2c_client *client = v4l2_get_subdevdata(sd); +- struct isx016_priv *priv = to_isx016(client); +- +- isx016_otp_id_read(client); +- +- return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", +- priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); +-} +- +-static DEVICE_ATTR(otp_id_isx016, S_IRUGO, isx016_otp_id_show, NULL); +- +-static int isx016_initialize(struct i2c_client *client) +-{ +- struct isx016_priv *priv = to_isx016(client); +- u16 pid = 0; +- int ret = 0; +- int tmp_addr; +- int i; +- +- isx016_s_port(client, 1); +- +- for (i = 0; i < ARRAY_SIZE(isx016_i2c_addr); i++) { +- tmp_addr = client->addr; +- if (priv->max9286_addr) { +- client->addr = priv->max9271_addr; /* Serializer I2C address */ +- reg8_write(client, 0x0A, isx016_i2c_addr[i] << 1); /* Sensor native I2C address */ +- usleep_range(2000, 2500); /* wait 2ms */ +- }; +- client->addr = tmp_addr; +- +- /* check model ID */ +- isx016_read16(client, 0, ISX016_PID, &pid); +- +- if (pid == ISX016_VERSION_REG) +- break; +- } +- +- if (pid != ISX016_VERSION_REG) { +- dev_dbg(&client->dev, "Product ID error %x\n", pid); +- ret = -ENODEV; +- goto err; +- } +- +- priv->max_width = ISX016_MAX_WIDTH; +- priv->max_height = ISX016_MAX_HEIGHT; +- +- /* Read OTP IDs */ +- isx016_otp_id_read(client); +- /* Program wizard registers */ +- isx016_set_regs(client, isx016_regs_wizard, ARRAY_SIZE(isx016_regs_wizard)); +- +- dev_info(&client->dev, "isx016 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", +- pid, priv->max_width, priv->max_height, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); +-err: +- isx016_s_port(client, 0); +- +- return ret; +-} +- +-static int isx016_parse_dt(struct device_node *np, struct isx016_priv *priv) +-{ +- struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); +- int i; +- struct device_node *endpoint = NULL, *rendpoint = NULL; +- int tmp_addr = 0; +- +- for (i = 0; ; i++) { +- endpoint = of_graph_get_next_endpoint(np, endpoint); +- if (!endpoint) +- break; +- +- of_node_put(endpoint); +- +- rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); +- if (!rendpoint) +- continue; +- +- if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && +- !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && +- !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) +- break; +- } +- +- if (!priv->max9286_addr) { +- dev_err(&client->dev, "deserializer does not present for ISX016\n"); +- return -EINVAL; +- } +- +- isx016_s_port(client, 1); +- +- /* setup I2C translator address */ +- tmp_addr = client->addr; +- if (priv->max9286_addr) { +- client->addr = priv->max9271_addr; /* Serializer I2C address */ +- reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */ +- usleep_range(2000, 2500); /* wait 2ms */ +- }; +- client->addr = tmp_addr; +- +- mdelay(10); +- +- return 0; +-} +- +-static int isx016_probe(struct i2c_client *client, +- const struct i2c_device_id *did) +-{ +- struct isx016_priv *priv; +- int ret; +- +- priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); +- if (!priv) +- return -ENOMEM; +- +- v4l2_i2c_subdev_init(&priv->sd, client, &isx016_subdev_ops); +- priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; +- +- priv->exposure = 0x100; +- priv->gain = 0x100; +- priv->autogain = 1; +- v4l2_ctrl_handler_init(&priv->hdl, 4); +- v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, +- V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); +- v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, +- V4L2_CID_CONTRAST, 0, 16, 1, 7); +- v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, +- V4L2_CID_SATURATION, 0, 7, 1, 2); +- v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, +- V4L2_CID_HUE, 0, 23, 1, 12); +- v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, +- V4L2_CID_GAMMA, -128, 128, 1, 0); +- v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, +- V4L2_CID_SHARPNESS, 0, 10, 1, 3); +- v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, +- V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); +- v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, +- V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); +- v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, +- V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure); +- v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, +- V4L2_CID_HFLIP, 0, 1, 1, 1); +- v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, +- V4L2_CID_VFLIP, 0, 1, 1, 0); +- priv->sd.ctrl_handler = &priv->hdl; +- +- ret = priv->hdl.error; +- if (ret) +- goto cleanup; +- +- v4l2_ctrl_handler_setup(&priv->hdl); +- +- priv->pad.flags = MEDIA_PAD_FL_SOURCE; +- priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; +- ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); +- if (ret < 0) +- goto cleanup; +- +- ret = isx016_parse_dt(client->dev.of_node, priv); +- if (ret) +- goto cleanup; +- +- ret = isx016_initialize(client); +- if (ret < 0) +- goto cleanup; +- +- priv->rect.left = 0; +- priv->rect.top = 0; +- priv->rect.width = priv->max_width; +- priv->rect.height = priv->max_height; +- +- ret = v4l2_async_register_subdev(&priv->sd); +- if (ret) +- goto cleanup; +- +- if (device_create_file(&client->dev, &dev_attr_otp_id_isx016) != 0) { +- dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); +- goto cleanup; +- } +- +- priv->init_complete = 1; +- +- return 0; +- +-cleanup: +- media_entity_cleanup(&priv->sd.entity); +- v4l2_ctrl_handler_free(&priv->hdl); +- v4l2_device_unregister_subdev(&priv->sd); +-#ifdef CONFIG_SOC_CAMERA_ISX016 +- v4l_err(client, "failed to probe @ 0x%02x (%s)\n", +- client->addr, client->adapter->name); +-#endif +- return ret; +-} +- +-static int isx016_remove(struct i2c_client *client) +-{ +- struct isx016_priv *priv = i2c_get_clientdata(client); +- +- device_remove_file(&client->dev, &dev_attr_otp_id_isx016); +- v4l2_async_unregister_subdev(&priv->sd); +- media_entity_cleanup(&priv->sd.entity); +- v4l2_ctrl_handler_free(&priv->hdl); +- v4l2_device_unregister_subdev(&priv->sd); +- +- return 0; +-} +- +-#ifdef CONFIG_SOC_CAMERA_ISX016 +-static const struct i2c_device_id isx016_id[] = { +- { "isx016", 0 }, +- { } +-}; +-MODULE_DEVICE_TABLE(i2c, isx016_id); +- +-static const struct of_device_id isx016_of_ids[] = { +- { .compatible = "aptina,isx016", }, +- { } +-}; +-MODULE_DEVICE_TABLE(of, isx016_of_ids); +- +-static struct i2c_driver isx016_i2c_driver = { +- .driver = { +- .name = "isx016", +- .of_match_table = isx016_of_ids, +- }, +- .probe = isx016_probe, +- .remove = isx016_remove, +- .id_table = isx016_id, +-}; +- +-module_i2c_driver(isx016_i2c_driver); +- +-MODULE_DESCRIPTION("SoC Camera driver for ISX016"); +-MODULE_AUTHOR("Vladimir Barinov"); +-MODULE_LICENSE("GPL"); +-#endif +diff --git a/drivers/media/i2c/soc_camera/isx016.h b/drivers/media/i2c/soc_camera/isx016.h +deleted file mode 100644 +index f20d735..0000000 +--- a/drivers/media/i2c/soc_camera/isx016.h ++++ /dev/null +@@ -1,27 +0,0 @@ +-/* +- * ON Semiconductor isx016 sensor camera wizard 1280x800@30/UYVY/BT601/8bit +- * +- * Copyright (C) 2018 Cogent Embedded, Inc. +- * +- * 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. +- */ +- +-#define ISX016_MAX_WIDTH 1280 +-#define ISX016_MAX_HEIGHT 800 +- +-#define ISX016_DELAY 0xffff +- +-struct isx016_reg { +- u16 reg; +- u16 val; +-}; +- +-static const struct isx016_reg isx016_regs_wizard[] = { +-#if 0 +-/* enable FSIN */ +-#endif +-{ISX016_DELAY, 100}, +-}; +diff --git a/drivers/media/i2c/soc_camera/isx019.c b/drivers/media/i2c/soc_camera/isx019.c +new file mode 100644 +index 0000000..8064789 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/isx019.c +@@ -0,0 +1,628 @@ ++/* ++ * ON Semiconductor ISX019 (isp) camera driver ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "isx019.h" ++ ++static const int isx019_i2c_addr[] = {0x1a}; ++ ++#define ISX019_PID 0x0000 ++#define ISX019_VERSION_REG 0x0740 ++ ++#define ISX019_MEDIA_BUS_FMT MEDIA_BUS_FMT_YUYV8_2X8 ++ ++static void isx019_otp_id_read(struct i2c_client *client); ++ ++struct isx019_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int max_width; ++ int max_height; ++ int init_complete; ++ u8 id[6]; ++ int exposure; ++ int gain; ++ int autogain; ++ /* serializers */ ++ int max9286_addr; ++ int max9271_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++}; ++ ++static inline struct isx019_priv *to_isx019(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct isx019_priv, sd); ++} ++ ++static void isx019_s_port(struct i2c_client *client, int fwd_en) ++{ ++ struct isx019_priv *priv = to_isx019(client); ++ int tmp_addr; ++ ++ if (priv->max9286_addr) { ++ tmp_addr = client->addr; ++ client->addr = priv->max9286_addr; /* Deserializer I2C address */ ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ client->addr = tmp_addr; ++ }; ++} ++ ++static int isx019_read16(struct i2c_client *client, u8 category, u16 reg, u16 *val) ++{ ++ int ret; ++ #define R_NUM_BYTES 9 ++ #define R_NUM_CMDS 1 ++ #define R_NUM_CMD_BYTES 6 ++ #define R_CMD 1 ++ #define R_BYTES 2 ++ u8 buf[R_NUM_BYTES] = {R_NUM_BYTES, R_NUM_CMDS, ++ R_NUM_CMD_BYTES, R_CMD, ++ category, reg >> 8, reg & 0xff, ++ R_BYTES, 0x00}; ++ ++ /* calculate checksum */ ++ buf[8] = R_NUM_BYTES + R_NUM_CMDS + R_NUM_CMD_BYTES + R_CMD + ++ category + (reg >> 8) + (reg & 0xff) + R_BYTES; ++ ++ ret = i2c_master_send(client, buf, R_NUM_BYTES); ++ if (ret == R_NUM_BYTES) ++ ret = i2c_master_recv(client, buf, R_NUM_BYTES - 2); ++ ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "read fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } else { ++ *val = ((u16)buf[4] << 8) | buf[5]; ++ } ++ ++ return ret < 0 ? ret : 0; ++} ++ ++static int isx019_write16(struct i2c_client *client, u8 category, u16 reg, u16 val) ++{ ++ int ret; ++ #define W_NUM_BYTES 10 ++ #define W_NUM_CMDS 1 ++ #define W_NUM_CMD_BYTES 7 ++ #define W_CMD 2 ++ u8 buf[W_NUM_BYTES] = {W_NUM_BYTES, W_NUM_CMDS, ++ W_NUM_CMD_BYTES, W_CMD, ++ category, reg >> 8, reg & 0xff, ++ val >> 8, val & 0xff}; ++ ++ /* calculate checksum */ ++ buf[9] = W_NUM_BYTES + W_NUM_CMDS + W_NUM_CMD_BYTES + W_CMD + ++ category + (reg >> 8) + (reg & 0xff) + (val >> 8) + (val & 0xff); ++ ++ ret = i2c_master_send(client, buf, W_NUM_BYTES); ++ ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "write fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } ++ ++ return ret < 0 ? ret : 0; ++} ++ ++static int isx019_set_regs(struct i2c_client *client, ++ const struct isx019_reg *regs, int nr_regs) ++{ ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (regs[i].reg == ISX019_DELAY) { ++ mdelay(regs[i].val); ++ continue; ++ } ++ ++ isx019_write16(client, regs[i].reg >> 8, regs[i].reg & 0xff, regs[i].val); ++ } ++ ++ return 0; ++} ++ ++static int isx019_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int isx019_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct isx019_priv *priv = to_isx019(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = ISX019_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int isx019_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = ISX019_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int isx019_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = ISX019_MEDIA_BUS_FMT; ++ ++ return 0; ++} ++ ++static int isx019_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct isx019_priv *priv = to_isx019(client); ++ ++ isx019_otp_id_read(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = ISX019_VERSION_REG >> 8; ++ edid->edid[9] = ISX019_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int isx019_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct isx019_priv *priv = to_isx019(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > priv->max_width) || ++ (rect->top + rect->height > priv->max_height)) ++ *rect = priv->rect; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ return 0; ++} ++ ++static int isx019_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct isx019_priv *priv = to_isx019(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = priv->max_width; ++ sel->r.height = priv->max_height; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = priv->max_width; ++ sel->r.height = priv->max_height; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int isx019_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int isx019_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u16 val = 0; ++ ++ ret = isx019_read16(client, (u16)reg->reg >> 8, (u16)reg->reg & 0xff, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int isx019_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return isx019_write16(client, (u16)reg->reg >> 8, (u16)reg->reg & 0xff, (u16)reg->val); ++} ++#endif ++ ++static struct v4l2_subdev_core_ops isx019_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = isx019_g_register, ++ .s_register = isx019_s_register, ++#endif ++}; ++ ++static int isx019_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct isx019_priv *priv = to_isx019(client); ++ int ret = -EINVAL; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ case V4L2_CID_CONTRAST: ++ case V4L2_CID_SATURATION: ++ case V4L2_CID_HUE: ++ case V4L2_CID_GAMMA: ++ case V4L2_CID_SHARPNESS: ++ case V4L2_CID_AUTOGAIN: ++ case V4L2_CID_GAIN: ++ case V4L2_CID_EXPOSURE: ++ case V4L2_CID_HFLIP: ++ case V4L2_CID_VFLIP: ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops isx019_ctrl_ops = { ++ .s_ctrl = isx019_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops isx019_video_ops = { ++ .s_stream = isx019_s_stream, ++ .g_mbus_config = isx019_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops isx019_subdev_pad_ops = { ++ .get_edid = isx019_get_edid, ++ .enum_mbus_code = isx019_enum_mbus_code, ++ .get_selection = isx019_get_selection, ++ .set_selection = isx019_set_selection, ++ .get_fmt = isx019_get_fmt, ++ .set_fmt = isx019_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops isx019_subdev_ops = { ++ .core = &isx019_core_ops, ++ .video = &isx019_video_ops, ++ .pad = &isx019_subdev_pad_ops, ++}; ++ ++static void isx019_otp_id_read(struct i2c_client *client) ++{ ++ struct isx019_priv *priv = to_isx019(client); ++ int i; ++ u16 val = 0; ++ ++ /* read camera id from isx019 OTP memory */ ++ for (i = 0; i < 6; i+=2) { ++ isx019_read16(client, 8, 0x60 + i, &val); ++ priv->id[i] = val >> 8; ++ priv->id[i+1] = val & 0xff; ++ } ++} ++ ++static ssize_t isx019_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct isx019_priv *priv = to_isx019(client); ++ ++ isx019_otp_id_read(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_isx019, S_IRUGO, isx019_otp_id_show, NULL); ++ ++static int isx019_initialize(struct i2c_client *client) ++{ ++ struct isx019_priv *priv = to_isx019(client); ++ u16 pid = 0; ++ int ret = 0; ++ int tmp_addr; ++ int i; ++ ++ isx019_s_port(client, 1); ++ ++ for (i = 0; i < ARRAY_SIZE(isx019_i2c_addr); i++) { ++ tmp_addr = client->addr; ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x0A, isx019_i2c_addr[i] << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ client->addr = tmp_addr; ++ ++ /* check model ID */ ++ isx019_read16(client, 0, ISX019_PID, &pid); ++ ++ if (pid == ISX019_VERSION_REG) ++ break; ++ } ++ ++ if (pid != ISX019_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x\n", pid); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ priv->max_width = ISX019_MAX_WIDTH; ++ priv->max_height = ISX019_MAX_HEIGHT; ++ ++ /* Read OTP IDs */ ++ isx019_otp_id_read(client); ++ /* Program wizard registers */ ++ isx019_set_regs(client, isx019_regs_wizard, ARRAY_SIZE(isx019_regs_wizard)); ++ ++ dev_info(&client->dev, "isx019 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, priv->max_width, priv->max_height, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ isx019_s_port(client, 0); ++ ++ return ret; ++} ++ ++static int isx019_parse_dt(struct device_node *np, struct isx019_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ if (!priv->max9286_addr) { ++ dev_err(&client->dev, "deserializer does not present for ISX019\n"); ++ return -EINVAL; ++ } ++ ++ isx019_s_port(client, 1); ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ client->addr = tmp_addr; ++ ++ mdelay(10); ++ ++ return 0; ++} ++ ++static int isx019_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct isx019_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &isx019_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ priv->exposure = 0x100; ++ priv->gain = 0x100; ++ priv->autogain = 1; ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &isx019_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &isx019_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &isx019_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &isx019_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &isx019_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &isx019_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &isx019_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); ++ v4l2_ctrl_new_std(&priv->hdl, &isx019_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); ++ v4l2_ctrl_new_std(&priv->hdl, &isx019_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure); ++ v4l2_ctrl_new_std(&priv->hdl, &isx019_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &isx019_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = isx019_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = isx019_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = priv->max_width; ++ priv->rect.height = priv->max_height; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_isx019) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_ISX019 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int isx019_remove(struct i2c_client *client) ++{ ++ struct isx019_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_isx019); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_ISX019 ++static const struct i2c_device_id isx019_id[] = { ++ { "isx019", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, isx019_id); ++ ++static const struct of_device_id isx019_of_ids[] = { ++ { .compatible = "aptina,isx019", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, isx019_of_ids); ++ ++static struct i2c_driver isx019_i2c_driver = { ++ .driver = { ++ .name = "isx019", ++ .of_match_table = isx019_of_ids, ++ }, ++ .probe = isx019_probe, ++ .remove = isx019_remove, ++ .id_table = isx019_id, ++}; ++ ++module_i2c_driver(isx019_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for ISX019"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/isx019.h b/drivers/media/i2c/soc_camera/isx019.h +new file mode 100644 +index 0000000..0593be1 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/isx019.h +@@ -0,0 +1,27 @@ ++/* ++ * ON Semiconductor isx019 (isp) camera wizard 1280x800@30/UYVY/BT601/8bit ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++#define ISX019_MAX_WIDTH 1280 ++#define ISX019_MAX_HEIGHT 800 ++ ++#define ISX019_DELAY 0xffff ++ ++struct isx019_reg { ++ u16 reg; ++ u16 val; ++}; ++ ++static const struct isx019_reg isx019_regs_wizard[] = { ++#if 0 ++/* enable FSIN */ ++#endif ++{ISX019_DELAY, 100}, ++}; +diff --git a/drivers/media/i2c/soc_camera/ov106xx.c b/drivers/media/i2c/soc_camera/ov106xx.c +index b0a3c90..79a69a0 100644 +--- a/drivers/media/i2c/soc_camera/ov106xx.c ++++ b/drivers/media/i2c/soc_camera/ov106xx.c +@@ -25,7 +25,7 @@ + #include "ov2775.c" + #include "imx390.c" + #include "ox03a.c" +-#include "isx016.c" ++#include "isx019.c" + + static enum { + ID_OV10635, +@@ -44,7 +44,7 @@ static enum { + ID_OV2775, + ID_IMX390, + ID_OX03A, +- ID_ISX016, ++ ID_ISX019, + } chip_id; + + static int ov106xx_probe(struct i2c_client *client, +@@ -149,9 +149,9 @@ static int ov106xx_probe(struct i2c_client *client, + goto out; + } + +- ret = isx016_probe(client, did); ++ ret = isx019_probe(client, did); + if (!ret) { +- chip_id = ID_ISX016; ++ chip_id = ID_ISX019; + goto out; + } + +@@ -212,8 +212,8 @@ static int ov106xx_remove(struct i2c_client *client) + case ID_OX03A: + ox03a_remove(client); + break; +- case ID_ISX016: +- isx016_remove(client); ++ case ID_ISX019: ++ isx019_remove(client); + break; + }; + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0150-lvds-add-ISX016-imager.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0150-lvds-add-ISX016-imager.patch new file mode 100644 index 00000000..b4468e7e --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0150-lvds-add-ISX016-imager.patch @@ -0,0 +1,705 @@ +From b22b3f2f5d7a5d112451569df9e81d842bd5af02 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Thu, 7 Feb 2019 12:07:05 +0300 +Subject: [PATCH 099/122] lvds: add ISX016 imager + +This adds ISX016 imager support + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/isx016.c | 604 +++++++++++++++++++++++++++++++++ + drivers/media/i2c/soc_camera/isx016.h | 27 ++ + drivers/media/i2c/soc_camera/ov106xx.c | 11 + + 3 files changed, 642 insertions(+) + create mode 100644 drivers/media/i2c/soc_camera/isx016.c + create mode 100644 drivers/media/i2c/soc_camera/isx016.h + +diff --git a/drivers/media/i2c/soc_camera/isx016.c b/drivers/media/i2c/soc_camera/isx016.c +new file mode 100644 +index 0000000..4002008 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/isx016.c +@@ -0,0 +1,604 @@ ++/* ++ * ON Semiconductor ISX016 (isp) camera driver ++ * ++ * Copyright (C) 2019 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "isx016.h" ++ ++static const int isx016_i2c_addr[] = {0x1a}; ++ ++#define ISX016_PID 0x0000 ++#define ISX016_VERSION_REG 0x0D20 ++ ++#define ISX016_MEDIA_BUS_FMT MEDIA_BUS_FMT_YUYV8_2X8 ++ ++static void isx016_otp_id_read(struct i2c_client *client); ++ ++struct isx016_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int max_width; ++ int max_height; ++ int init_complete; ++ u8 id[6]; ++ int exposure; ++ int gain; ++ int autogain; ++ /* serializers */ ++ int max9286_addr; ++ int max9271_addr; ++ int ti9x4_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++}; ++ ++static inline struct isx016_priv *to_isx016(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct isx016_priv, sd); ++} ++ ++static void isx016_s_port(struct i2c_client *client, int fwd_en) ++{ ++ struct isx016_priv *priv = to_isx016(client); ++ int tmp_addr; ++ ++ if (priv->max9286_addr) { ++ tmp_addr = client->addr; ++ client->addr = priv->max9286_addr; /* Deserializer I2C address */ ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ client->addr = tmp_addr; ++ }; ++} ++ ++static int isx016_read16(struct i2c_client *client, u8 category, u16 reg, u16 *val) ++{ ++ reg16_write(client, 0xFFFF, category); ++ reg16_read16(client, reg, val); ++ ++ return 0; ++} ++ ++static int isx016_write16(struct i2c_client *client, u8 category, u16 reg, u16 val) ++{ ++ reg16_write(client, 0xFFFF, category); ++ reg16_write16(client, reg, val); ++ ++ return 0; ++} ++ ++static int isx016_set_regs(struct i2c_client *client, ++ const struct isx016_reg *regs, int nr_regs) ++{ ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (regs[i].reg == ISX016_DELAY) { ++ mdelay(regs[i].val); ++ continue; ++ } ++ ++ isx016_write16(client, regs[i].reg >> 8, regs[i].reg & 0xff, regs[i].val); ++ } ++ ++ return 0; ++} ++ ++static int isx016_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int isx016_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct isx016_priv *priv = to_isx016(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = ISX016_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int isx016_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = ISX016_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int isx016_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = ISX016_MEDIA_BUS_FMT; ++ ++ return 0; ++} ++ ++static int isx016_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct isx016_priv *priv = to_isx016(client); ++ ++ isx016_otp_id_read(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = ISX016_VERSION_REG >> 8; ++ edid->edid[9] = ISX016_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int isx016_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct isx016_priv *priv = to_isx016(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > priv->max_width) || ++ (rect->top + rect->height > priv->max_height)) ++ *rect = priv->rect; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ return 0; ++} ++ ++static int isx016_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct isx016_priv *priv = to_isx016(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = priv->max_width; ++ sel->r.height = priv->max_height; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = priv->max_width; ++ sel->r.height = priv->max_height; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int isx016_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int isx016_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u16 val = 0; ++ ++ ret = isx016_read16(client, (u16)reg->reg >> 8, (u16)reg->reg & 0xff, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int isx016_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return isx016_write16(client, (u16)reg->reg >> 8, (u16)reg->reg & 0xff, (u16)reg->val); ++} ++#endif ++ ++static struct v4l2_subdev_core_ops isx016_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = isx016_g_register, ++ .s_register = isx016_s_register, ++#endif ++}; ++ ++static int isx016_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct isx016_priv *priv = to_isx016(client); ++ int ret = -EINVAL; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ case V4L2_CID_CONTRAST: ++ case V4L2_CID_SATURATION: ++ case V4L2_CID_HUE: ++ case V4L2_CID_GAMMA: ++ case V4L2_CID_SHARPNESS: ++ case V4L2_CID_AUTOGAIN: ++ case V4L2_CID_GAIN: ++ case V4L2_CID_EXPOSURE: ++ case V4L2_CID_HFLIP: ++ case V4L2_CID_VFLIP: ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops isx016_ctrl_ops = { ++ .s_ctrl = isx016_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops isx016_video_ops = { ++ .s_stream = isx016_s_stream, ++ .g_mbus_config = isx016_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops isx016_subdev_pad_ops = { ++ .get_edid = isx016_get_edid, ++ .enum_mbus_code = isx016_enum_mbus_code, ++ .get_selection = isx016_get_selection, ++ .set_selection = isx016_set_selection, ++ .get_fmt = isx016_get_fmt, ++ .set_fmt = isx016_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops isx016_subdev_ops = { ++ .core = &isx016_core_ops, ++ .video = &isx016_video_ops, ++ .pad = &isx016_subdev_pad_ops, ++}; ++ ++static void isx016_otp_id_read(struct i2c_client *client) ++{ ++ struct isx016_priv *priv = to_isx016(client); ++ int i; ++ u16 val = 0; ++ ++ /* read camera id from isx016 FUSEs */ ++ for (i = 0; i < 6; i+=2) { ++ isx016_read16(client, 92, 0x0a + i, &val); ++ priv->id[i] = val >> 8; ++ priv->id[i+1] = val & 0xff; ++ } ++} ++ ++static ssize_t isx016_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct isx016_priv *priv = to_isx016(client); ++ ++ isx016_otp_id_read(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_isx016, S_IRUGO, isx016_otp_id_show, NULL); ++ ++static int isx016_initialize(struct i2c_client *client) ++{ ++ struct isx016_priv *priv = to_isx016(client); ++ u16 pid = 0; ++ int ret = 0; ++ int tmp_addr; ++ int i; ++ ++ isx016_s_port(client, 1); ++ ++ for (i = 0; i < ARRAY_SIZE(isx016_i2c_addr); i++) { ++ tmp_addr = client->addr; ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x0A, isx016_i2c_addr[i] << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ ++ reg8_write(client, 0x5d, isx016_i2c_addr[i] << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ } ++ client->addr = tmp_addr; ++ ++ /* check model ID */ ++ isx016_read16(client, 0, ISX016_PID, &pid); ++ ++ if (pid == ISX016_VERSION_REG) ++ break; ++ } ++ ++ if (pid != ISX016_VERSION_REG) { ++ dev_err(&client->dev, "Product ID error %x\n", pid); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ priv->max_width = ISX016_MAX_WIDTH; ++ priv->max_height = ISX016_MAX_HEIGHT; ++ ++ /* Read OTP IDs */ ++ isx016_otp_id_read(client); ++ /* Program wizard registers */ ++ isx016_set_regs(client, isx016_regs_wizard, ARRAY_SIZE(isx016_regs_wizard)); ++ ++ dev_info(&client->dev, "isx016 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, priv->max_width, priv->max_height, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ isx016_s_port(client, 0); ++ ++ return ret; ++} ++ ++static int isx016_parse_dt(struct device_node *np, struct isx016_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ if (!priv->max9286_addr && !priv->ti9x4_addr) { ++ dev_err(&client->dev, "deserializer does not present for ISX016\n"); ++ return -EINVAL; ++ } ++ ++ isx016_s_port(client, 1); ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ ++ reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ } ++ client->addr = tmp_addr; ++ ++ return 0; ++} ++ ++static int isx016_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct isx016_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &isx016_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ priv->exposure = 0x100; ++ priv->gain = 0x100; ++ priv->autogain = 1; ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); ++ v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); ++ v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure); ++ v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &isx016_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = isx016_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = isx016_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = priv->max_width; ++ priv->rect.height = priv->max_height; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_isx016) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_ISX016 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int isx016_remove(struct i2c_client *client) ++{ ++ struct isx016_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_isx016); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_ISX016 ++static const struct i2c_device_id isx016_id[] = { ++ { "isx016", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, isx016_id); ++ ++static const struct of_device_id isx016_of_ids[] = { ++ { .compatible = "aptina,isx016", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, isx016_of_ids); ++ ++static struct i2c_driver isx016_i2c_driver = { ++ .driver = { ++ .name = "isx016", ++ .of_match_table = isx016_of_ids, ++ }, ++ .probe = isx016_probe, ++ .remove = isx016_remove, ++ .id_table = isx016_id, ++}; ++ ++module_i2c_driver(isx016_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for ISX016"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/isx016.h b/drivers/media/i2c/soc_camera/isx016.h +new file mode 100644 +index 0000000..8ca35a10 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/isx016.h +@@ -0,0 +1,27 @@ ++/* ++ * ON Semiconductor isx016 (isp) camera wizard 1280x960@30/UYVY/BT601/8bit ++ * ++ * Copyright (C) 2019 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++#define ISX016_MAX_WIDTH 1280 ++#define ISX016_MAX_HEIGHT 960 ++ ++#define ISX016_DELAY 0xffff ++ ++struct isx016_reg { ++ u16 reg; ++ u16 val; ++}; ++ ++static const struct isx016_reg isx016_regs_wizard[] = { ++#if 0 ++/* enable FSIN */ ++#endif ++{ISX016_DELAY, 100}, ++}; +diff --git a/drivers/media/i2c/soc_camera/ov106xx.c b/drivers/media/i2c/soc_camera/ov106xx.c +index 79a69a0..d06c1f0 100644 +--- a/drivers/media/i2c/soc_camera/ov106xx.c ++++ b/drivers/media/i2c/soc_camera/ov106xx.c +@@ -25,6 +25,7 @@ + #include "ov2775.c" + #include "imx390.c" + #include "ox03a.c" ++#include "isx016.c" + #include "isx019.c" + + static enum { +@@ -44,6 +45,7 @@ static enum { + ID_OV2775, + ID_IMX390, + ID_OX03A, ++ ID_ISX016, + ID_ISX019, + } chip_id; + +@@ -149,6 +151,12 @@ static int ov106xx_probe(struct i2c_client *client, + goto out; + } + ++ ret = isx016_probe(client, did); ++ if (!ret) { ++ chip_id = ID_ISX016; ++ goto out; ++ } ++ + ret = isx019_probe(client, did); + if (!ret) { + chip_id = ID_ISX019; +@@ -212,6 +220,9 @@ static int ov106xx_remove(struct i2c_client *client) + case ID_OX03A: + ox03a_remove(client); + break; ++ case ID_ISX016: ++ isx016_remove(client); ++ break; + case ID_ISX019: + isx019_remove(client); + break; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0151-lvds-ti9x4-add-DVP-LSB-MSB-selection.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0151-lvds-ti9x4-add-DVP-LSB-MSB-selection.patch new file mode 100644 index 00000000..384997d0 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0151-lvds-ti9x4-add-DVP-LSB-MSB-selection.patch @@ -0,0 +1,67 @@ +From ad5be16342cea9a6bb17f8f9c8d2635a0d6b027f Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Thu, 7 Feb 2019 17:33:53 +0300 +Subject: [PATCH 100/122] lvds: ti9x4: add DVP LSB/MSB selection + +This add DVP 8bits LSB/MSB selection from 12bit bus + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ti9x4.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/i2c/soc_camera/ti9x4.c b/drivers/media/i2c/soc_camera/ti9x4.c +index 373652a..fdb50e5 100644 +--- a/drivers/media/i2c/soc_camera/ti9x4.c ++++ b/drivers/media/i2c/soc_camera/ti9x4.c +@@ -34,6 +34,7 @@ struct ti9x4_priv { + const char *forwarding_mode; + int is_coax; + int dvp_bus; ++ int dvp_lsb; + int hsync; + int vsync; + int poc_delay; +@@ -62,6 +63,10 @@ static int dvp_bus = 8; + module_param(dvp_bus, int, 0644); + MODULE_PARM_DESC(dvp_bus, " DVP/CSI over FPDLink (default: DVP 8-bit)"); + ++static int dvp_lsb = 0; ++module_param(dvp_lsb, int, 0644); ++MODULE_PARM_DESC(dvp_lsb, " DVP 8-bit LSB/MSB selection (default: DVP 8-bit MSB)"); ++ + static int hsync; + module_param(hsync, int, 0644); + MODULE_PARM_DESC(hsync, " HSYNC invertion (default: 0 - not inverted)"); +@@ -248,7 +253,7 @@ static void ti9x4_fpdlink3_setup(struct i2c_client *client, int idx) + + switch (priv->dvp_bus) { + case 8: +- port_config2 |= 0x80; /* RAW10 as 8-bit prosessing using upper bits */ ++ port_config2 |= (priv->dvp_lsb ? 0xC0 : 0x80); /* RAW10 as 8-bit prosessing using LSB/MSB bits */ + /* fall through */ + case 10: + port_config |= 0x03; /* DVP over FPDLink (TI913 compatible) RAW10/RAW8 */ +@@ -472,6 +477,10 @@ static int ti9x4_parse_dt(struct i2c_client *client) + priv->is_coax = 1; + if (of_property_read_u32(np, "ti,dvp_bus", &priv->dvp_bus)) + priv->dvp_bus = 8; ++ if (of_property_read_bool(np, "ti,dvp_lsb")) ++ priv->dvp_lsb = 1; ++ else ++ priv->dvp_lsb = 0; + if (of_property_read_u32(np, "ti,hsync", &priv->hsync)) + priv->hsync = 0; + if (of_property_read_u32(np, "ti,vsync", &priv->vsync)) +@@ -512,6 +521,8 @@ static int ti9x4_parse_dt(struct i2c_client *client) + priv->is_coax = 0; + if (dvp_bus != 8) + priv->dvp_bus = dvp_bus; ++ if (dvp_lsb) ++ priv->dvp_lsb = dvp_lsb; + if (hsync) + priv->hsync = hsync; + if (!vsync) +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0152-lvds-AR323-fix-reset-gpio-nadling.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0152-lvds-AR323-fix-reset-gpio-nadling.patch new file mode 100644 index 00000000..9aebe463 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0152-lvds-AR323-fix-reset-gpio-nadling.patch @@ -0,0 +1,145 @@ +From 26540d896b8fed3869f426de37c01fa2a913e09d Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Tue, 12 Feb 2019 17:45:59 +0300 +Subject: [PATCH 101/122] lvds: AR323: fix reset gpio nadling + +This fixes gpio reset handling on AR0323 imager +GPIO0 - NRESET +GPIO1 - FSIN +kernel parameter requred: ti9x4.gpio0=1 + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ar0323.c | 45 ++++++++++++++++++++-------------- + drivers/media/i2c/soc_camera/ov106xx.c | 12 ++++----- + 2 files changed, 33 insertions(+), 24 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ar0323.c b/drivers/media/i2c/soc_camera/ar0323.c +index 467367b..d29f4ad 100644 +--- a/drivers/media/i2c/soc_camera/ar0323.c ++++ b/drivers/media/i2c/soc_camera/ar0323.c +@@ -22,9 +22,10 @@ + + #include "ar0323.h" + +-#define AR0323_I2C_ADDR 0x10 ++static const int ar0323_i2c_addr[] = {0x10, 0x20}; + + #define AR0323_PID 0x3000 ++#define AR0323_REV 0x300E + #define AR0323_VERSION_REG 0x0D56 + + #define AR0323_MEDIA_BUS_FMT MEDIA_BUS_FMT_SGRBG12_1X12 +@@ -356,19 +357,32 @@ static int ar0323_initialize(struct i2c_client *client) + { + struct ar0323_priv *priv = to_ar0323(client); + u16 val = 0; +- u16 pid = 0; ++ u16 pid = 0, rev = 0; + int ret = 0; +-// int tmp_addr; ++ int tmp_addr; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(ar0323_i2c_addr); i++) { ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr;/* Deserializer I2C address */ ++ reg8_write(client, 0x5d, ar0323_i2c_addr[i] << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ } ++ client->addr = tmp_addr; ++ ++ /* check model ID */ ++ reg16_read16(client, AR0323_PID, &pid); + +- /* check and show model ID */ +- reg16_read16(client, AR0323_PID, &pid); ++ if (pid == AR0323_VERSION_REG) ++ break; ++ } + + if (pid != AR0323_VERSION_REG) { +- dev_dbg(&client->dev, "Product ID error %x\n\n\n\n", pid); ++ dev_dbg(&client->dev, "Product ID error %x\n", pid); + ret = -ENODEV; + goto err; + } +- + #if 0 + /* setup XCLK */ + tmp_addr = client->addr; +@@ -381,7 +395,10 @@ static int ar0323_initialize(struct i2c_client *client) + } + client->addr = tmp_addr; + #endif +- ++ /* check revision */ ++ reg16_read16(client, AR0323_REV, &rev); ++ /* Read OTP IDs */ ++ ar0323_otp_id_read(client); + /* Program wizard registers */ + ar0323_set_regs(client, ar0323_regs_wizard, ARRAY_SIZE(ar0323_regs_wizard)); + +@@ -390,11 +407,8 @@ static int ar0323_initialize(struct i2c_client *client) + val |= (1 << 2); // Set streamOn bit + reg16_write16(client, 0x301a, val); // Start Streaming + +- /* Read OTP IDs */ +- ar0323_otp_id_read(client); +- +- dev_info(&client->dev, "ar0323 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", +- pid, AR0323_MAX_WIDTH, AR0323_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++ dev_info(&client->dev, "ar0323 PID %x (rev %x), res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, rev, AR0323_MAX_WIDTH, AR0323_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); + err: + return ret; + } +@@ -437,14 +451,9 @@ static int ar0323_parse_dt(struct device_node *np, struct ar0323_priv *priv) + reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ + usleep_range(2000, 2500); /* wait 2ms */ + reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ +- reg8_write(client, 0x5d, AR0323_I2C_ADDR << 1); /* Sensor native I2C address */ +- +-// reg8_write(client, 0x6e, 0xa9); /* GPIO0 - reset, GPIO1 - fsin ??????? */ + } + client->addr = tmp_addr; + +- mdelay(10); +- + return 0; + } + +diff --git a/drivers/media/i2c/soc_camera/ov106xx.c b/drivers/media/i2c/soc_camera/ov106xx.c +index d06c1f0..8962ab9 100644 +--- a/drivers/media/i2c/soc_camera/ov106xx.c ++++ b/drivers/media/i2c/soc_camera/ov106xx.c +@@ -67,6 +67,12 @@ static int ov106xx_probe(struct i2c_client *client, + goto out; + } + ++ ret = ar0323_probe(client, did); ++ if (!ret) { ++ chip_id = ID_AR0323; ++ goto out; ++ } ++ + ret = ov10640_probe(client, did); + if (!ret) { + chip_id = ID_OV10640; +@@ -115,12 +121,6 @@ static int ov106xx_probe(struct i2c_client *client, + goto out; + } + +- ret = ar0323_probe(client, did); +- if (!ret) { +- chip_id = ID_AR0323; +- goto out; +- } +- + ret = ap0101_probe(client, did); + if (!ret) { + chip_id = ID_AP0101_AR014X; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0153-lvds-OV495-fix-reset-gpio-handling.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0153-lvds-OV495-fix-reset-gpio-handling.patch new file mode 100644 index 00000000..3535dd86 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0153-lvds-OV495-fix-reset-gpio-handling.patch @@ -0,0 +1,65 @@ +From 8241a96db8e7365a23b5ba76a33af47fcc6b7ee8 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Tue, 12 Feb 2019 22:29:24 +0300 +Subject: [PATCH 102/122] lvds: OV495: fix reset gpio handling + +This fixes gpio reset handling on OV495 imager +GPIO0 - NRESET +GPIO1 - NC (no FSIN!) +kernel parameter requred: ti9x4.gpio0=1 + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ov106xx.c | 12 ++++++------ + drivers/media/i2c/soc_camera/ov495_ov2775.c | 5 +---- + 2 files changed, 7 insertions(+), 10 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ov106xx.c b/drivers/media/i2c/soc_camera/ov106xx.c +index 8962ab9..d641907 100644 +--- a/drivers/media/i2c/soc_camera/ov106xx.c ++++ b/drivers/media/i2c/soc_camera/ov106xx.c +@@ -73,6 +73,12 @@ static int ov106xx_probe(struct i2c_client *client, + goto out; + } + ++ ret = ov495_probe(client, did); ++ if (!ret) { ++ chip_id = ID_OV495_OV2775; ++ goto out; ++ } ++ + ret = ov10640_probe(client, did); + if (!ret) { + chip_id = ID_OV10640; +@@ -91,12 +97,6 @@ static int ov106xx_probe(struct i2c_client *client, + goto out; + } + +- ret = ov495_probe(client, did); +- if (!ret) { +- chip_id = ID_OV495_OV2775; +- goto out; +- } +- + ret = ar0132_probe(client, did); + if (!ret) { + chip_id = ID_AR0132; +diff --git a/drivers/media/i2c/soc_camera/ov495_ov2775.c b/drivers/media/i2c/soc_camera/ov495_ov2775.c +index 34b2f46..aee8145 100644 +--- a/drivers/media/i2c/soc_camera/ov495_ov2775.c ++++ b/drivers/media/i2c/soc_camera/ov495_ov2775.c +@@ -503,10 +503,7 @@ static int ov495_parse_dt(struct device_node *np, struct ov495_priv *priv) + usleep_range(2000, 2500); /* wait 2ms */ + reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ + reg8_write(client, 0x5d, OV495_I2C_ADDR << 1); /* Sensor native I2C address */ +- +- reg8_write(client, 0x6e, 0x9a); /* GPIO0 - fsin, GPIO1 - resetb */ +- /* TODO: why too long? move logic to workqueue? */ +- mdelay(350); /* time needed to boot all sensor IPs */ ++ usleep_range(2000, 2500); /* wait 2ms */ + } + client->addr = tmp_addr; + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0154-lvds-AR0323-replace-with-REV2-setup-table.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0154-lvds-AR0323-replace-with-REV2-setup-table.patch new file mode 100644 index 00000000..01f93c7c --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0154-lvds-AR0323-replace-with-REV2-setup-table.patch @@ -0,0 +1,2888 @@ +From d28f2cdef61df4e852a25667ba2a82c0cc6fb52b Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Thu, 14 Feb 2019 13:07:27 +0300 +Subject: [PATCH 103/122] lvds: AR0323: replace with REV2 setup table + +Superseed wizard table with REV2 setup + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ar0323.h | 2840 ++++++++++++++++++--------------- + 1 file changed, 1578 insertions(+), 1262 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ar0323.h b/drivers/media/i2c/soc_camera/ar0323.h +index 0711dd8..b30d0d5 100644 +--- a/drivers/media/i2c/soc_camera/ar0323.h ++++ b/drivers/media/i2c/soc_camera/ar0323.h +@@ -13,7 +13,7 @@ + //#define AR0323_DISPLAY_PATTERN_COLOR_BAR + + #define AR0323_MAX_WIDTH 2560 +-#define AR0323_MAX_HEIGHT 1080 ++#define AR0323_MAX_HEIGHT 992 + + #define AR0323_DELAY 0xffff + +@@ -52,1084 +52,17 @@ static const struct ar0323_reg ar0323_regs_wizard[] = { + #endif + + {0x301A, 0x0059}, // RESET_REGISTER +-{0x301A, 0x0058}, // RESET_REGISTER +-{AR0323_DELAY, 200}, // Wait 200ms +- +-//continuous MIPI 12bit +-{0x3342, 0x122C}, // MIPI_F1_PDT_EDT +-{0x3346, 0x122C}, // MIPI_F2_PDT_EDT +-{0x334A, 0x122C}, // MIPI_F3_PDT_EDT +-{0x334E, 0x122C}, // MIPI_F4_PDT_EDT +- +-//PLL settings +-{0x302E, 0x0002}, // PRE_PLL_CLK_DIV +-{0x3030, 0x0052}, // PLL_MULTIPLIER +-{0x302C, 0x0001}, // VT_SYS_CLK_DIV +-{0x302A, 0x0008}, // VT_PIX_CLK_DIV +-{0x3038, 0x0004}, // OP_SYS_CLK_DIV +-{0x3036, 0x0006}, // OP_WORD_CLK_DIV +- +-//MIPI timing +-{0x31B0, 0x0059}, // FRAME_PREAMBLE +-{0x31B2, 0x003B}, // LINE_PREAMBLE +-{0x31B4, 0x31C5}, // MIPI_TIMING_0 +-{0x31B6, 0x114E}, // MIPI_TIMING_1 +-{0x31B8, 0x5048}, // MIPI_TIMING_2 +-{0x31BA, 0x0186}, // MIPI_TIMING_3 +-{0x31BC, 0x8885}, // MIPI_TIMING_4 +- +-//HDR +-{0x3E00, 0x8000}, // LFM2_T1_CTRL +-{0x3082, 0x0004}, // OPERATION_MODE_CTRL +-{0x30BA, 0x1103}, // DIGITAL_CTRL +- +-//new sequencer +-{0x2512, 0x8000}, +-{0x2510, 0x0712}, +-{0x2510, 0x1314}, +-{0x2510, 0x1518}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0x1b1d}, +-{0x2510, 0x2224}, +-{0x2510, 0x2628}, +-{0x2510, 0xffff}, +-{0x2510, 0x2a48}, +-{0x2510, 0x5672}, +-{0x2510, 0x7f85}, +-{0x2510, 0x8991}, +-{0x2510, 0xaeb3}, +-{0x2510, 0xbdc4}, +-{0x2510, 0xc5c8}, +-{0x2510, 0xccd0}, +-{0x2510, 0xd4d6}, +-{0x2510, 0xd8dd}, +-{0x2510, 0xdfe2}, +-{0x2510, 0xe5e8}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xc003}, +-{0x2510, 0xa0e0}, +-{0x2510, 0x3041}, +-{0x2510, 0x3042}, +-{0x2510, 0x2000}, +-{0x2510, 0x3048}, +-{0x2510, 0x3081}, +-{0x2510, 0x3084}, +-{0x2510, 0x3082}, +-{0x2510, 0x2003}, +-{0x2510, 0x3044}, +-{0x2510, 0x2000}, +-{0x2510, 0xa004}, +-{0x2510, 0x20ff}, +-{0x2510, 0x20ff}, +-{0x2510, 0x20ff}, +-{0x2510, 0x20ff}, +-{0x2510, 0x20ff}, +-{0x2510, 0x807c}, +-{0x2510, 0xa0e0}, +-{0x2510, 0x3041}, +-{0x2510, 0x3042}, +-{0x2510, 0x2000}, +-{0x2510, 0xa0c0}, +-{0x2510, 0x9008}, +-{0x2510, 0x8802}, +-{0x2510, 0x20ff}, +-{0x2510, 0x20ff}, +-{0x2510, 0x20ff}, +-{0x2510, 0x20ff}, +-{0x2510, 0x20ff}, +-{0x2510, 0x9018}, +-{0x2510, 0x891a}, +-{0x2510, 0x807c}, +-{0x2510, 0x20ff}, +-{0x2510, 0x895b}, +-{0x2510, 0x20ff}, +-{0x2510, 0x897b}, +-{0x2510, 0x20ff}, +-{0x2510, 0x897f}, +-{0x2510, 0x20ff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x20ff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x20ff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x20ff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0xa0c4}, +-{0x2510, 0x20ff}, +-{0x2510, 0x8058}, +-{0x2510, 0x9039}, +-{0x2510, 0x20ff}, +-{0x2510, 0x907f}, +-{0x2510, 0x895b}, +-{0x2510, 0x2064}, +-{0x2510, 0x891b}, +-{0x2510, 0x2010}, +-{0x2510, 0x8803}, +-{0x2510, 0x7fff}, +-{0x2510, 0x3088}, +-{0x2510, 0x3090}, +-{0x2510, 0x20ff}, +-{0x2510, 0x906b}, +-{0x2510, 0x2064}, +-{0x2510, 0x3084}, +-{0x2510, 0x2003}, +-{0x2510, 0x3044}, +-{0x2510, 0x2000}, +-{0x2510, 0xa004}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x2400}, +-{0x2510, 0x2401}, +-{0x2510, 0x3244}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x2400}, +-{0x2510, 0x2401}, +-{0x2510, 0x2702}, +-{0x2510, 0x3242}, +-{0x2510, 0x2420}, +-{0x2510, 0x2702}, +-{0x2510, 0x2421}, +-{0x2510, 0x2703}, +-{0x2510, 0x3242}, +-{0x2510, 0x2420}, +-{0x2510, 0x2703}, +-{0x2510, 0x2421}, +-{0x2510, 0x2704}, +-{0x2510, 0x3242}, +-{0x2510, 0x2420}, +-{0x2510, 0x2704}, +-{0x2510, 0x2421}, +-{0x2510, 0x3244}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x2402}, +-{0x2510, 0x2403}, +-{0x2510, 0x3244}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x2741}, +-{0x2510, 0x2429}, +-{0x2510, 0x2740}, +-{0x2510, 0x242a}, +-{0x2510, 0x3244}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x2404}, +-{0x2510, 0x2779}, +-{0x2510, 0x242c}, +-{0x2510, 0x2781}, +-{0x2510, 0x242d}, +-{0x2510, 0x3244}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x2703}, +-{0x2510, 0x2432}, +-{0x2510, 0x3244}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0xb800}, +-{0x2510, 0x8058}, +-{0x2510, 0xa005}, +-{0x2510, 0x30c1}, +-{0x2510, 0x3101}, +-{0x2510, 0x3041}, +-{0x2510, 0x3041}, +-{0x2510, 0x3250}, +-{0x2510, 0x3108}, +-{0x2510, 0x3104}, +-{0x2510, 0x3102}, +-{0x2510, 0x3041}, +-{0x2510, 0xf860}, +-{0x2510, 0xb095}, +-{0x2510, 0x3141}, +-{0x2510, 0x3042}, +-{0x2510, 0xb848}, +-{0x2510, 0xb84c}, +-{0x2510, 0x8843}, +-{0x2510, 0x916f}, +-{0x2510, 0x3110}, +-{0x2510, 0x3042}, +-{0x2510, 0xb84e}, +-{0x2510, 0xf905}, +-{0x2510, 0xf907}, +-{0x2510, 0x3202}, +-{0x2510, 0x885b}, +-{0x2510, 0xa898}, +-{0x2510, 0xa8d8}, +-{0x2510, 0xb397}, +-{0x2510, 0xf8e8}, +-{0x2510, 0x80dc}, +-{0x2510, 0x2206}, +-{0x2510, 0xb137}, +-{0x2510, 0xb808}, +-{0x2510, 0xc800}, +-{0x2510, 0xe809}, +-{0x2510, 0xb177}, +-{0x2510, 0x88df}, +-{0x2510, 0xf8a8}, +-{0x2510, 0xf888}, +-{0x2510, 0x2203}, +-{0x2510, 0xb07b}, +-{0x2510, 0x2000}, +-{0x2510, 0x80cc}, +-{0x2510, 0x808c}, +-{0x2510, 0x220b}, +-{0x2510, 0xb06a}, +-{0x2510, 0x88cf}, +-{0x2510, 0x888f}, +-{0x2510, 0x222f}, +-{0x2510, 0x2771}, +-{0x2510, 0x2512}, +-{0x2510, 0xb04a}, +-{0x2510, 0x2213}, +-{0x2510, 0x2771}, +-{0x2510, 0x2525}, +-{0x2510, 0xb04b}, +-{0x2510, 0x902f}, +-{0x2510, 0xf880}, +-{0x2510, 0x220e}, +-{0x2510, 0x2201}, +-{0x2510, 0x2201}, +-{0x2510, 0x2204}, +-{0x2510, 0xb043}, +-{0x2510, 0x2201}, +-{0x2510, 0xa8c9}, +-{0x2510, 0x31c1}, +-{0x2510, 0x80ac}, +-{0x2510, 0x916f}, +-{0x2510, 0x2112}, +-{0x2510, 0x88af}, +-{0x2510, 0x2440}, +-{0x2510, 0xf110}, +-{0x2510, 0xf804}, +-{0x2510, 0x2000}, +-{0x2510, 0x8088}, +-{0x2510, 0xb838}, +-{0x2510, 0xa8c8}, +-{0x2510, 0xb04b}, +-{0x2510, 0x2442}, +-{0x2510, 0x3210}, +-{0x2510, 0x3002}, +-{0x2510, 0x220c}, +-{0x2510, 0x888b}, +-{0x2510, 0x2204}, +-{0x2510, 0x3202}, +-{0x2510, 0x2204}, +-{0x2510, 0xf880}, +-{0x2510, 0xb830}, +-{0x2510, 0xc801}, +-{0x2510, 0x30c2}, +-{0x2510, 0xe80c}, +-{0x2510, 0x2201}, +-{0x2510, 0xb04a}, +-{0x2510, 0x2229}, +-{0x2510, 0x2771}, +-{0x2510, 0x2513}, +-{0x2510, 0x902f}, +-{0x2510, 0x221f}, +-{0x2510, 0x2201}, +-{0x2510, 0x2204}, +-{0x2510, 0xb042}, +-{0x2510, 0x2201}, +-{0x2510, 0xa9a1}, +-{0x2510, 0x8008}, +-{0x2510, 0xb093}, +-{0x2510, 0x31c1}, +-{0x2510, 0x916b}, +-{0x2510, 0x2009}, +-{0x2510, 0x8803}, +-{0x2510, 0xa044}, +-{0x2510, 0x3044}, +-{0x2510, 0x2000}, +-{0x2510, 0xa004}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0xa084}, +-{0x2510, 0x8078}, +-{0x2510, 0x3141}, +-{0x2510, 0x3041}, +-{0x2510, 0x3042}, +-{0x2510, 0x2000}, +-{0x2510, 0x3142}, +-{0x2510, 0x3041}, +-{0x2510, 0x2000}, +-{0x2510, 0x3110}, +-{0x2510, 0x3041}, +-{0x2510, 0x2000}, +-{0x2510, 0x3120}, +-{0x2510, 0x3041}, +-{0x2510, 0x2000}, +-{0x2510, 0x3144}, +-{0x2510, 0x3041}, +-{0x2510, 0x2000}, +-{0x2510, 0x3148}, +-{0x2510, 0x3041}, +-{0x2510, 0x2000}, +-{0x2510, 0x2206}, +-{0x2510, 0x881b}, +-{0x2510, 0x887b}, +-{0x2510, 0x2440}, +-{0x2510, 0xb095}, +-{0x2510, 0xf110}, +-{0x2510, 0xf804}, +-{0x2510, 0xf90d}, +-{0x2510, 0x3084}, +-{0x2510, 0x3090}, +-{0x2510, 0x3088}, +-{0x2510, 0x8058}, +-{0x2510, 0x3001}, +-{0x2510, 0x2442}, +-{0x2510, 0x3260}, +-{0x2510, 0x3248}, +-{0x2510, 0x3220}, +-{0x2510, 0x2002}, +-{0x2510, 0x8863}, +-{0x2510, 0x2004}, +-{0x2510, 0x8803}, +-{0x2510, 0x2204}, +-{0x2510, 0x30c2}, +-{0x2510, 0xa9a0}, +-{0x2510, 0xb094}, +-{0x2510, 0x2201}, +-{0x2510, 0xa0c4}, +-{0x2510, 0x3044}, +-{0x2510, 0x2000}, +-{0x2510, 0xa004}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0xb980}, +-{0x2510, 0x8108}, +-{0x2510, 0xa105}, +-{0x2510, 0x30c1}, +-{0x2510, 0x2000}, +-{0x2510, 0x3101}, +-{0x2510, 0x3041}, +-{0x2510, 0x3250}, +-{0x2510, 0x3108}, +-{0x2510, 0x3104}, +-{0x2510, 0x3102}, +-{0x2510, 0x3041}, +-{0x2510, 0xf860}, +-{0x2510, 0xb095}, +-{0x2510, 0x3141}, +-{0x2510, 0x3042}, +-{0x2510, 0xb9f8}, +-{0x2510, 0xb9fc}, +-{0x2510, 0x8803}, +-{0x2510, 0x916f}, +-{0x2510, 0x3110}, +-{0x2510, 0x3042}, +-{0x2510, 0xb9fe}, +-{0x2510, 0xf905}, +-{0x2510, 0xf907}, +-{0x2510, 0x3202}, +-{0x2510, 0x880b}, +-{0x2510, 0xa888}, +-{0x2510, 0xa8c8}, +-{0x2510, 0xb397}, +-{0x2510, 0xf8e8}, +-{0x2510, 0x818c}, +-{0x2510, 0x2206}, +-{0x2510, 0xb137}, +-{0x2510, 0xb9b8}, +-{0x2510, 0xc801}, +-{0x2510, 0xe809}, +-{0x2510, 0xb177}, +-{0x2510, 0x888f}, +-{0x2510, 0xf8a8}, +-{0x2510, 0xf888}, +-{0x2510, 0x2203}, +-{0x2510, 0xb07b}, +-{0x2510, 0x2000}, +-{0x2510, 0x2206}, +-{0x2510, 0xb06a}, +-{0x2510, 0x2210}, +-{0x2510, 0x818c}, +-{0x2510, 0x2204}, +-{0x2510, 0x888f}, +-{0x2510, 0x888f}, +-{0x2510, 0x2215}, +-{0x2510, 0xb04a}, +-{0x2510, 0x2212}, +-{0x2510, 0x2111}, +-{0x2510, 0xb04b}, +-{0x2510, 0x902f}, +-{0x2510, 0xf880}, +-{0x2510, 0x220e}, +-{0x2510, 0x2201}, +-{0x2510, 0x2204}, +-{0x2510, 0xb043}, +-{0x2510, 0x2201}, +-{0x2510, 0xa8d9}, +-{0x2510, 0x31c1}, +-{0x2510, 0x80cc}, +-{0x2510, 0x916f}, +-{0x2510, 0x2110}, +-{0x2510, 0x88cf}, +-{0x2510, 0x2440}, +-{0x2510, 0xf110}, +-{0x2510, 0xf804}, +-{0x2510, 0x2000}, +-{0x2510, 0xb988}, +-{0x2510, 0xa8d8}, +-{0x2510, 0xb04b}, +-{0x2510, 0x3002}, +-{0x2510, 0x2442}, +-{0x2510, 0x3210}, +-{0x2510, 0x220a}, +-{0x2510, 0x2204}, +-{0x2510, 0x3202}, +-{0x2510, 0x2204}, +-{0x2510, 0xb980}, +-{0x2510, 0xc800}, +-{0x2510, 0x30c2}, +-{0x2510, 0xe80c}, +-{0x2510, 0x2201}, +-{0x2510, 0xb04a}, +-{0x2510, 0x221f}, +-{0x2510, 0x8088}, +-{0x2510, 0x220a}, +-{0x2510, 0x888b}, +-{0x2510, 0x902f}, +-{0x2510, 0x221e}, +-{0x2510, 0x2201}, +-{0x2510, 0x2204}, +-{0x2510, 0xb042}, +-{0x2510, 0x2201}, +-{0x2510, 0xa9a1}, +-{0x2510, 0x8018}, +-{0x2510, 0xb093}, +-{0x2510, 0x31c1}, +-{0x2510, 0x916b}, +-{0x2510, 0x2009}, +-{0x2510, 0x8803}, +-{0x2510, 0x2000}, +-{0x2510, 0xa004}, +-{0x2510, 0xb800}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x8078}, +-{0x2510, 0xa184}, +-{0x2510, 0xb981}, +-{0x2510, 0x3141}, +-{0x2510, 0x3041}, +-{0x2510, 0x3042}, +-{0x2510, 0x2000}, +-{0x2510, 0x3142}, +-{0x2510, 0x3041}, +-{0x2510, 0x2000}, +-{0x2510, 0x3110}, +-{0x2510, 0x3041}, +-{0x2510, 0x2000}, +-{0x2510, 0x3120}, +-{0x2510, 0x3041}, +-{0x2510, 0x2000}, +-{0x2510, 0x30a0}, +-{0x2510, 0x2206}, +-{0x2510, 0x881b}, +-{0x2510, 0x887b}, +-{0x2510, 0x2282}, +-{0x2510, 0xb095}, +-{0x2510, 0xf110}, +-{0x2510, 0xf804}, +-{0x2510, 0xf90d}, +-{0x2510, 0x3090}, +-{0x2510, 0x3088}, +-{0x2510, 0x8058}, +-{0x2510, 0x2202}, +-{0x2510, 0x3001}, +-{0x2510, 0x3260}, +-{0x2510, 0x3248}, +-{0x2510, 0x2002}, +-{0x2510, 0x885b}, +-{0x2510, 0x2004}, +-{0x2510, 0x2204}, +-{0x2510, 0x8018}, +-{0x2510, 0x2209}, +-{0x2510, 0x881b}, +-{0x2510, 0xa9a0}, +-{0x2510, 0xb094}, +-{0x2510, 0x2209}, +-{0x2510, 0x8000}, +-{0x2510, 0x2209}, +-{0x2510, 0x8803}, +-{0x2510, 0xa1c4}, +-{0x2510, 0x3044}, +-{0x2510, 0xb800}, +-{0x2510, 0xa004}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x9818}, +-{0x2510, 0xb800}, +-{0x2510, 0x3101}, +-{0x2510, 0x3041}, +-{0x2510, 0x2200}, +-{0x2510, 0x3102}, +-{0x2510, 0x3041}, +-{0x2510, 0x2200}, +-{0x2510, 0x8018}, +-{0x2510, 0x2002}, +-{0x2510, 0x8038}, +-{0x2510, 0x2205}, +-{0x2510, 0x881b}, +-{0x2510, 0x883b}, +-{0x2510, 0x213e}, +-{0x2510, 0x8018}, +-{0x2510, 0x2202}, +-{0x2510, 0x8000}, +-{0x2510, 0x2202}, +-{0x2510, 0x8803}, +-{0x2510, 0x9800}, +-{0x2510, 0xa004}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x2440}, +-{0x2510, 0xb095}, +-{0x2510, 0xf110}, +-{0x2510, 0xf804}, +-{0x2510, 0xf90d}, +-{0x2510, 0x2442}, +-{0x2510, 0x3260}, +-{0x2510, 0x3248}, +-{0x2510, 0x3220}, +-{0x2510, 0x2007}, +-{0x2510, 0x2204}, +-{0x2510, 0x30c2}, +-{0x2510, 0xa9a0}, +-{0x2510, 0xb094}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0xb981}, +-{0x2510, 0x3101}, +-{0x2510, 0x3041}, +-{0x2510, 0x3102}, +-{0x2510, 0x3041}, +-{0x2510, 0x8028}, +-{0x2510, 0x2212}, +-{0x2510, 0x880b}, +-{0x2510, 0x882b}, +-{0x2510, 0x2440}, +-{0x2510, 0xb095}, +-{0x2510, 0xf110}, +-{0x2510, 0xf804}, +-{0x2510, 0xf90d}, +-{0x2510, 0x8008}, +-{0x2510, 0x2202}, +-{0x2510, 0x3001}, +-{0x2510, 0x3260}, +-{0x2510, 0x3248}, +-{0x2510, 0x2442}, +-{0x2510, 0x8823}, +-{0x2510, 0x3220}, +-{0x2510, 0x2007}, +-{0x2510, 0x8803}, +-{0x2510, 0x2204}, +-{0x2510, 0x30c2}, +-{0x2510, 0xa8a0}, +-{0x2510, 0xb094}, +-{0x2510, 0x2201}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0xb800}, +-{0x2510, 0x8058}, +-{0x2510, 0xa005}, +-{0x2510, 0x30c1}, +-{0x2510, 0x3101}, +-{0x2510, 0x3041}, +-{0x2510, 0x3041}, +-{0x2510, 0x3250}, +-{0x2510, 0x3108}, +-{0x2510, 0x3104}, +-{0x2510, 0x3102}, +-{0x2510, 0x3041}, +-{0x2510, 0xf860}, +-{0x2510, 0xb095}, +-{0x2510, 0x3141}, +-{0x2510, 0x3042}, +-{0x2510, 0xb848}, +-{0x2510, 0xb84c}, +-{0x2510, 0x8843}, +-{0x2510, 0x916f}, +-{0x2510, 0x3110}, +-{0x2510, 0x3042}, +-{0x2510, 0xb84e}, +-{0x2510, 0xf905}, +-{0x2510, 0xf907}, +-{0x2510, 0x3202}, +-{0x2510, 0x885b}, +-{0x2510, 0xa898}, +-{0x2510, 0xa8d8}, +-{0x2510, 0xb397}, +-{0x2510, 0xf8e8}, +-{0x2510, 0x80dc}, +-{0x2510, 0x2206}, +-{0x2510, 0xb137}, +-{0x2510, 0xb808}, +-{0x2510, 0xc800}, +-{0x2510, 0xe809}, +-{0x2510, 0xb177}, +-{0x2510, 0x88df}, +-{0x2510, 0xf8a8}, +-{0x2510, 0xf888}, +-{0x2510, 0x2203}, +-{0x2510, 0xb07b}, +-{0x2510, 0x2000}, +-{0x2510, 0x80cc}, +-{0x2510, 0x808c}, +-{0x2510, 0x220b}, +-{0x2510, 0xb06a}, +-{0x2510, 0x88cf}, +-{0x2510, 0x888f}, +-{0x2510, 0x222f}, +-{0x2510, 0x2771}, +-{0x2510, 0x251e}, +-{0x2510, 0xb04a}, +-{0x2510, 0x2213}, +-{0x2510, 0x2771}, +-{0x2510, 0x2525}, +-{0x2510, 0xb04b}, +-{0x2510, 0x902f}, +-{0x2510, 0xf880}, +-{0x2510, 0x221e}, +-{0x2510, 0x2201}, +-{0x2510, 0x2204}, +-{0x2510, 0xb043}, +-{0x2510, 0x2201}, +-{0x2510, 0xa8c9}, +-{0x2510, 0x31c1}, +-{0x2510, 0x80ac}, +-{0x2510, 0x916f}, +-{0x2510, 0x2112}, +-{0x2510, 0x88af}, +-{0x2510, 0x2440}, +-{0x2510, 0xf110}, +-{0x2510, 0xf804}, +-{0x2510, 0x2000}, +-{0x2510, 0x8088}, +-{0x2510, 0xb838}, +-{0x2510, 0xa8c8}, +-{0x2510, 0xb04b}, +-{0x2510, 0x2442}, +-{0x2510, 0x3210}, +-{0x2510, 0x3002}, +-{0x2510, 0x220c}, +-{0x2510, 0x888b}, +-{0x2510, 0x2204}, +-{0x2510, 0x3202}, +-{0x2510, 0xf880}, +-{0x2510, 0xb830}, +-{0x2510, 0xc801}, +-{0x2510, 0x30c2}, +-{0x2510, 0xe80c}, +-{0x2510, 0x2201}, +-{0x2510, 0xb04a}, +-{0x2510, 0x2229}, +-{0x2510, 0x2771}, +-{0x2510, 0x2513}, +-{0x2510, 0x902f}, +-{0x2510, 0x221f}, +-{0x2510, 0x2201}, +-{0x2510, 0x2204}, +-{0x2510, 0xb042}, +-{0x2510, 0x2201}, +-{0x2510, 0xa8e1}, +-{0x2510, 0x8008}, +-{0x2510, 0xb093}, +-{0x2510, 0x31c1}, +-{0x2510, 0x916b}, +-{0x2510, 0x2009}, +-{0x2510, 0x8803}, +-{0x2510, 0x2000}, +-{0x2510, 0xa004}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x2440}, +-{0x2510, 0xb095}, +-{0x2510, 0xf110}, +-{0x2510, 0xf804}, +-{0x2510, 0xf90d}, +-{0x2510, 0x2442}, +-{0x2510, 0x3220}, +-{0x2510, 0x2002}, +-{0x2510, 0x2204}, +-{0x2510, 0x30c2}, +-{0x2510, 0xa9a0}, +-{0x2510, 0x2004}, +-{0x2510, 0xb094}, +-{0x2510, 0x2201}, +-{0x2510, 0x3244}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x2749}, +-{0x2510, 0x2422}, +-{0x2510, 0x2749}, +-{0x2510, 0x2423}, +-{0x2510, 0x2709}, +-{0x2510, 0x2420}, +-{0x2510, 0x2729}, +-{0x2510, 0x2423}, +-{0x2510, 0x3242}, +-{0x2510, 0x2722}, +-{0x2510, 0x2422}, +-{0x2510, 0x2769}, +-{0x2510, 0x2421}, +-{0x2510, 0x2702}, +-{0x2510, 0x2421}, +-{0x2510, 0x3242}, +-{0x2510, 0x276a}, +-{0x2510, 0x2420}, +-{0x2510, 0x276a}, +-{0x2510, 0x2421}, +-{0x2510, 0x2703}, +-{0x2510, 0x2420}, +-{0x2510, 0x2703}, +-{0x2510, 0x2421}, +-{0x2510, 0x3242}, +-{0x2510, 0x276b}, +-{0x2510, 0x2420}, +-{0x2510, 0x276b}, +-{0x2510, 0x2421}, +-{0x2510, 0x2704}, +-{0x2510, 0x2420}, +-{0x2510, 0x2704}, +-{0x2510, 0x2421}, +-{0x2510, 0x3242}, +-{0x2510, 0x276c}, +-{0x2510, 0x2420}, +-{0x2510, 0x276c}, +-{0x2510, 0x2421}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x2759}, +-{0x2510, 0x2422}, +-{0x2510, 0x2758}, +-{0x2510, 0x2420}, +-{0x2510, 0x2403}, +-{0x2510, 0x2712}, +-{0x2510, 0x3242}, +-{0x2510, 0x2422}, +-{0x2510, 0x271a}, +-{0x2510, 0x3242}, +-{0x2510, 0x2420}, +-{0x2510, 0x2702}, +-{0x2510, 0x2423}, +-{0x2510, 0x2703}, +-{0x2510, 0x3242}, +-{0x2510, 0x2420}, +-{0x2510, 0x2703}, +-{0x2510, 0x2423}, +-{0x2510, 0x2704}, +-{0x2510, 0x3242}, +-{0x2510, 0x2420}, +-{0x2510, 0x2704}, +-{0x2510, 0x2423}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0xc023}, +-{0x2510, 0x2402}, +-{0x2510, 0x2405}, +-{0x2510, 0x2789}, +-{0x2510, 0x242e}, +-{0x2510, 0x2788}, +-{0x2510, 0x242f}, +-{0x2510, 0x3244}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0xc027}, +-{0x2510, 0x2407}, +-{0x2510, 0x2406}, +-{0x2510, 0xc063}, +-{0x2510, 0x2402}, +-{0x2510, 0x2751}, +-{0x2510, 0x2423}, +-{0x2510, 0x2750}, +-{0x2510, 0x2421}, +-{0x2510, 0xc003}, +-{0x2510, 0x3244}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0xc021}, +-{0x2510, 0x2400}, +-{0x2510, 0x2405}, +-{0x2510, 0xc062}, +-{0x2510, 0x2400}, +-{0x2510, 0xc063}, +-{0x2510, 0x2751}, +-{0x2510, 0x2423}, +-{0x2510, 0x2750}, +-{0x2510, 0x2421}, +-{0x2510, 0xc003}, +-{0x2510, 0x3244}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0xc0e3}, +-{0x2510, 0x2400}, +-{0x2510, 0x27b1}, +-{0x2510, 0x2425}, +-{0x2510, 0xc063}, +-{0x2510, 0x2420}, +-{0x2510, 0x2751}, +-{0x2510, 0x2423}, +-{0x2510, 0x2750}, +-{0x2510, 0x2421}, +-{0x2510, 0xc003}, +-{0x2510, 0x3244}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x2404}, +-{0x2510, 0x2779}, +-{0x2510, 0x242c}, +-{0x2510, 0x2781}, +-{0x2510, 0x242d}, +-{0x2510, 0x3244}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x2791}, +-{0x2510, 0x2430}, +-{0x2510, 0x2799}, +-{0x2510, 0x2428}, +-{0x2510, 0x3244}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x2417}, +-{0x2510, 0xc023}, +-{0x2510, 0x2403}, +-{0x2510, 0x2703}, +-{0x2510, 0x3242}, +-{0x2510, 0x2404}, +-{0x2510, 0x240d}, +-{0x2510, 0xc003}, +-{0x2510, 0x2703}, +-{0x2510, 0x3242}, +-{0x2510, 0x2400}, +-{0x2510, 0x2408}, +-{0x2510, 0x2703}, +-{0x2510, 0x3242}, +-{0x2510, 0x2417}, +-{0x2510, 0x240b}, +-{0x2510, 0x3244}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0xc022}, +-{0x2510, 0x2402}, +-{0x2510, 0x2405}, +-{0x2510, 0x2414}, +-{0x2510, 0x3244}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0xc022}, +-{0x2510, 0x2407}, +-{0x2510, 0x2405}, +-{0x2510, 0xc061}, +-{0x2510, 0x2400}, +-{0x2510, 0xc023}, +-{0x2510, 0x2403}, +-{0x2510, 0xc003}, +-{0x2510, 0x3244}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0xc022}, +-{0x2510, 0x2404}, +-{0x2510, 0x2779}, +-{0x2510, 0x2433}, +-{0x2510, 0x2781}, +-{0x2510, 0x2436}, +-{0x2510, 0x3244}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0xc126}, +-{0x2510, 0x2407}, +-{0x2510, 0xc022}, +-{0x2510, 0x2406}, +-{0x2510, 0x2402}, +-{0x2510, 0xc023}, +-{0x2510, 0x2405}, +-{0x2510, 0x2417}, +-{0x2510, 0x3244}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x3244}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0x7fff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +-{0x2510, 0xffff}, +- + {AR0323_DELAY, 100}, // Wait 100ms + {0x301A, 0x0058}, // RESET_REGISTER ++{AR0323_DELAY, 200}, // Wait 200ms + +-{0x31AC, 0x140C}, // DATA_FORMAT_BITS +-{0x31D0, 0x0001}, // COMPANDING +-{0x336E, 0x01DF}, // DATAPATH_SELECT2 +-{0x3238, 0x0666}, // EXPOSURE_RATIO + #if 1 +-{0x300C, 0x0A60}, // LINE_LENGTH_PCK_ +-{0x300A, 0x04A0}, // FRAME_LENGTH_LINES_ +-#else +-{0x300A, AR0323_SENSOR_HEIGHT + 208}, // FRAME_LENGTH_LINES_ +-{0x300C, AR0323_SENSOR_WIDTH + 300}, // LINE_LENGTH_PCK_ +-#endif ++//2880x992 resolution ++{0x3004, 0x00A8}, // X_ADDR_START_ ++{0x3008, 0x0AA7}, // X_ADDR_END_ ++{0x3002, 0x0030}, // Y_ADDR_START_ ++{0x3006, 0x040F}, // Y_ADDR_END_ + +-#if 0 +-//2880x1072 resolution +-{0x3004, 0x0008}, // X_ADDR_START_ +-{0x3008, 0x0B47}, // X_ADDR_END_ +-{0x3002, 0x010C}, // Y_ADDR_START_ +-{0x3006, 0x053B}, // Y_ADDR_END_ + #else + {0x3004, AR0323_X_START}, // X_ADDR_START_ + {0x3008, AR0323_X_END}, // X_ADDR_END_ +@@ -1139,197 +72,1580 @@ static const struct ar0323_reg ar0323_regs_wizard[] = { + {0x3404, 0x0000 | AR0323_MAX_HEIGHT}, // Y_OUTPUT_CONTROL + #endif + +-{0x3534, 0xA282}, // DAC_LD_52_53 +-{0x3524, 0x0FFF}, // DAC_LD_36_37 +-{0x3180, 0x1001}, // DELTA_DK_CONTROL +-{0x3576, 0x1F09}, // DAC_LD_118_119 +- +-{0x3548, 0x7878}, // DAC_LD_72_73 +-{0x354C, 0x4141}, // DAC_LD_76_77 +-{0x354E, 0x4B4B}, // DAC_LD_78_79 +-{0x356E, 0x158A}, // DAC_LD_110_111 +- +-//overflow},settings +-{0x3496, 0xCF0A}, // LFM_CONTROL +-{0x350E, 0x2181}, // DAC_LD_14_15 +-{0x3E02, 0x0834}, // LFM2_T1_E1_A +-{0x3E04, 0x0000}, // LFM2_T1_E1_B +-{0x3E08, 0x1FFF}, // LFM2_T1_E2_A +-{0x3E14, 0x0020}, // LFM2_T1_SLOPE +-{0x3E16, 0x1F40}, // LFM2_T1_E1_THRESHOLD +-// +-{0x562A, 0x05DC}, // OCL_T1_E2_E1_SAT +-{0x563A, 0x0011}, // OCL_T1_GAIN_ +- +-{0x3364, 0x068C}, // DCG_TRIM +-{0x3290, 0xD354}, // T3_BARRIER_C0 +-{0x3292, 0xD354}, // T3_BARRIER_C1 +-{0x3294, 0xD354}, // T3_BARRIER_C2 +-{0x3296, 0xD354}, // T3_BARRIER_C3 +-{0x3298, 0xD354}, // T4_BARRIER_C0 +-{0x329A, 0xD354}, // T4_BARRIER_C1 +-{0x329C, 0xD354}, // T4_BARRIER_C2 +-{0x329E, 0xD354}, // T4_BARRIER_C3 +-{0x33DA, 0x0001}, // OC_LUT_CONTROL +-{0x3D00, 0x6007}, // MEC_CTRL1 +- +-{0x3040, 0xC005}, // READ_MODE +-{0x3352, 0x2000}, // MIPI_DT_VC_CONFIG +-{0x3064, 0x0180}, // SMIA_TEST +- +-{0x3D10, 0x0000}, // VIS_BOUND_X0 +-{0x3D12, 0x0B40}, // VIS_BOUND_X1 +-{0x3D14, 0x001E}, // VIS_BOUND_Y0 +-{0x3D16, 0x045A}, // VIS_BOUND_Y1 +- +-{0x3D08, 0x0000}, // DTR_BOUND_X0 +-{0x3D0A, 0x0B40}, // DTR_BOUND_X1 +-{0x3D0C, 0x0004}, // DTR_BOUND_Y0 +-{0x3D0E, 0x000C}, // DTR_BOUND_Y1 +-{AR0323_DELAY, 100}, // Wait 100ms +- +-//Pre HDR gain LG lens ++#if 1 ++{0x300A, 0x047E}, // FRAME_LENGTH_LINES_ ++{0x300C, 0x0A6E}, // LINE_LENGTH_PCK_ ++#else ++{0x300A, AR0323_SENSOR_HEIGHT + 208}, // FRAME_LENGTH_LINES_ ++{0x300C, AR0323_SENSOR_WIDTH + 300}, // LINE_LENGTH_PCK_ ++#endif ++{0x3030, 0x0050}, // PLL_MULTIPLIER ++{0x302E, 0x0004}, // PRE_PLL_CLK_DIV ++{0x302C, 0x0001}, // VT_SYS_CLK_DIV ++{0x302A, 0x0004}, // VT_PIX_CLK_DIV ++{0x3038, 0x0002}, // OP_SYS_CLK_DIV ++{0x3036, 0x0006}, // OP_WORD_CLK_DIV ++{0x31DC, 0x1FA0}, // RESERVED_MFR_31DC ++{0x31B0, 0x0036}, // FRAME_PREAMBLE ++{0x31B2, 0x001F}, // LINE_PREAMBLE ++{0x31B4, 0x4145}, // RESERVED_MFR_31B4 ++{0x31B6, 0x3184}, // RESERVED_MFR_31B6 ++{0x31B8, 0x4048}, // RESERVED_MFR_31B8 ++{0x31BA, 0x0206}, // RESERVED_MFR_31BA ++{0x31BC, 0x8705}, // RESERVED_MFR_31BC ++{0x3342, 0x122C}, // MIPI_F1_PDT_EDT ++{0x3346, 0x122C}, // MIPI_F2_PDT_EDT ++{0x334A, 0x122C}, // MIPI_F3_PDT_EDT ++{0x334E, 0x122C}, // MIPI_F4_PDT_EDT ++{0x3546, 0x4603}, // RESERVED_MFR_3546 ++{0x342E, 0x0017}, // RESERVED_MFR_342E ++{0x3092, 0x400C}, // RESERVED_MFR_3092 ++{0x3E3E, 0x000C}, // RESERVED_MFR_3E3E ++{0x3550, 0x806C}, // RESERVED_MFR_3550 ++{0x356A, 0x81AA}, // RESERVED_MFR_356A ++{0x356E, 0x068A}, // RESERVED_MFR_356E ++{0x356C, 0x6A28}, // RESERVED_MFR_356C ++{0x3C72, 0x0076}, // ADC_DEC_CTRL7 ++{0x3C74, 0x0031}, // ADC_DEC_CTRL8 ++{0x3C76, 0x00DC}, // ADC_DEC_CTRL9 ++{0x3C78, 0x01AA}, // ADC_DEC_CTRL10 ++{0x3C7A, 0x0352}, // ADC_DEC_CTRL11 ++{0x3C7C, 0x06AA}, // ADC_DEC_CTRL12 ++{0x37B2, 0x1FFF}, // RESERVED_MFR_37B2 ++{0x3562, 0x0C08}, // RESERVED_MFR_3562 ++{0x3086, 0x0000}, // RESERVED_MFR_3086 ++{0x3576, 0x1DFF}, // RESERVED_MFR_3576 ++{0x3564, 0x1A23}, // RESERVED_MFR_3564 ++{0x3508, 0xEF1A}, // RESERVED_MFR_3508 ++{0x3544, 0x030F}, // RESERVED_MFR_3544 ++{0x336E, 0x0147}, // DATAPATH_SELECT2 ++{0x3E40, 0x00E0}, // RESERVED_MFR_3E40 ++{0x3EF0, 0x0B70}, // BALANCER_CTRL_0 + {0x3110, 0x0011}, // HDR_CONTROL0 +-{0x3056, 0x0031}, // GREEN1_GAIN +-{0x3058, 0x0080}, // BLUE_GAIN +-{0x305A, 0x0070}, // RED_GAIN +-{0x305C, 0x0031}, // GREEN2_GAIN +-{0x3308, 0x0539}, // GLOBAL_GAIN2_ +-{0x3D28, 0x3BD1}, // T1_STR_DEC_TH +-{0x3D2A, 0x4C2C}, // T1_END_DEC_TH +- +-//booster +-{0x352C, 0x8146}, // DAC_LD_44_45 +-{0x352E, 0x1871}, // DAC_LD_46_47 +-{0x3538, 0x81EA}, // DAC_LD_56_57 +- +-{0x3576, 0x1F49}, // DAC_LD_118_119 +-{0x3544, 0x03A1}, // DAC_LD_68_69 +- +-{0x354C, 0x411E}, // DAC_LD_76_77 +-// +-{0x351A, 0x7900}, +- +-//Temp_sensor_read +-{0x3E94, 0x3010}, // TEMPVSENS1_SREG_TRIM0 ++{0x350E, 0x2088}, // RESERVED_MFR_350E ++{0x3510, 0x780F}, // RESERVED_MFR_3510 ++{0x351E, 0x7FDE}, // RESERVED_MFR_351E ++{0x3520, 0x0080}, // RESERVED_MFR_3520 ++{0x3526, 0x5000}, // RESERVED_MFR_3526 ++{0x3528, 0x200A}, // RESERVED_MFR_3528 ++{0x352A, 0x0F27}, // RESERVED_MFR_352A ++{0x3530, 0x1010}, // RESERVED_MFR_3530 ++{0x3532, 0x9000}, // RESERVED_MFR_3532 ++{0x3534, 0x3098}, // RESERVED_MFR_3534 ++{0x3536, 0x90C0}, // RESERVED_MFR_3536 ++{0x3538, 0x0702}, // RESERVED_MFR_3538 ++{0x353A, 0x02B2}, // RESERVED_MFR_353A ++{0x353C, 0x9A01}, // RESERVED_MFR_353C ++{0x3552, 0x0832}, // RESERVED_MFR_3552 ++{0x3570, 0xAA6A}, // RESERVED_MFR_3570 ++{0x357E, 0x5B5B}, // RESERVED_MFR_357E ++{0x3496, 0x6F00}, // RESERVED_MFR_3496 ++{0x34BC, 0x0808}, // LFM_PATTERN_CTRL ++{0x3494, 0x0808}, // RESERVED_MFR_3494 ++{0x3492, 0x0004}, // RESERVED_MFR_3492 ++{0x34BA, 0x0001}, // RESERVED_MFR_34BA ++{0x34B8, 0x0001}, // RESERVED_MFR_34B8 ++{0x3E00, 0x8000}, // LFM2_T1_CTRL ++{0x3E04, 0x0000}, // RESERVED_MFR_3E04 ++{0x3E06, 0x0000}, // RESERVED_MFR_3E06 ++{0x3E10, 0x0006}, // RESERVED_MFR_3E10 ++{0x3E16, 0x1FFF}, // RESERVED_MFR_3E16 ++{0x350E, 0x2090}, // RESERVED_MFR_350E ++{0x350E, 0x2091}, // RESERVED_MFR_350E ++{0x3450, 0x00D7}, // RESERVED_MFR_3450 ++{0x3452, 0x00D7}, // RESERVED_MFR_3452 ++{0x3454, 0x00D7}, // RESERVED_MFR_3454 ++{0x3456, 0x00D7}, // RESERVED_MFR_3456 ++{0x3458, 0x00D7}, // RESERVED_MFR_3458 ++{0x345A, 0x00D7}, // RESERVED_MFR_345A ++{0x345C, 0x00D7}, // RESERVED_MFR_345C ++{0x345E, 0x00D7}, // RESERVED_MFR_345E ++{0x3460, 0x00D7}, // RESERVED_MFR_3460 ++{0x3462, 0x00D7}, // RESERVED_MFR_3462 ++{0x3464, 0x00D7}, // RESERVED_MFR_3464 ++{0x3466, 0x00D7}, // RESERVED_MFR_3466 ++{0x3468, 0x00D7}, // RESERVED_MFR_3468 ++{0x346A, 0x00D7}, // RESERVED_MFR_346A ++{0x346C, 0x00D7}, // RESERVED_MFR_346C ++{0x346E, 0x00D7}, // RESERVED_MFR_346E ++{0x3470, 0x00D7}, // RESERVED_MFR_3470 ++{0x3472, 0x00D7}, // RESERVED_MFR_3472 ++{0x3474, 0x00D7}, // RESERVED_MFR_3474 ++{0x3476, 0x00D7}, // RESERVED_MFR_3476 ++{0x3478, 0x00D7}, // RESERVED_MFR_3478 ++{0x347A, 0x00D7}, // RESERVED_MFR_347A ++{0x347C, 0x00D7}, // RESERVED_MFR_347C ++{0x347E, 0x00D7}, // RESERVED_MFR_347E ++{0x3480, 0x00D7}, // RESERVED_MFR_3480 ++{0x3482, 0x00D7}, // RESERVED_MFR_3482 ++{0x3484, 0x00D7}, // RESERVED_MFR_3484 ++{0x3486, 0x00D7}, // RESERVED_MFR_3486 ++{0x3488, 0x00D7}, // RESERVED_MFR_3488 ++{0x348A, 0x00D7}, // RESERVED_MFR_348A ++{0x348C, 0x00D7}, // RESERVED_MFR_348C ++{0x348E, 0x00D7}, // RESERVED_MFR_348E ++{0x3490, 0x00D7}, // RESERVED_MFR_3490 ++{0x357C, 0x4E00}, // RESERVED_MFR_357C ++{0x352C, 0xA004}, // RESERVED_MFR_352C ++{0x34AA, 0x0001}, // RESERVED_MFR_34AA ++{0x34AC, 0x0097}, // RESERVED_MFR_34AC ++{0x34A8, 0x0098}, // RESERVED_MFR_34A8 ++{0x34AE, 0x00B6}, // RESERVED_MFR_34AE ++{0x349A, 0x0001}, // RESERVED_MFR_349A ++{0x349E, 0x0002}, // RESERVED_MFR_349E ++{0x35F0, 0x0002}, // LFM_BST_DCGBOT_SEL_CLK_CTRL ++{0x35F4, 0x0003}, // LFM_BST_DCGBOT_VAAPIX_CLK_CTRL ++{0x34B0, 0x0003}, // RESERVED_MFR_34B0 ++{0x349C, 0x0004}, // RESERVED_MFR_349C ++{0x34B6, 0x001D}, // RESERVED_MFR_34B6 ++{0x34A2, 0x001D}, // RESERVED_MFR_34A2 ++{0x34A4, 0x0084}, // RESERVED_MFR_34A4 ++{0x34A0, 0x0085}, // RESERVED_MFR_34A0 ++{0x35F6, 0x0099}, // LFM_BST_DCGBOT_VAAPIX_CLR_CLK_CTRL ++{0x34A6, 0x0099}, // RESERVED_MFR_34A6 ++{0x34B2, 0x00AD}, // RESERVED_MFR_34B2 ++{0x34B4, 0x00C1}, // RESERVED_MFR_34B4 ++{0x35F2, 0x00C1}, // LFM_BST_DCGBOT_DESEL_CLK_CTRL ++{0x351A, 0xE900}, // RESERVED_MFR_351A ++{0x357A, 0x0044}, // RESERVED_MFR_357A ++{0x3514, 0x5B5B}, // RESERVED_MFR_3514 ++{0x3578, 0x5B5B}, // RESERVED_MFR_3578 ++{0x3526, 0x5000}, // RESERVED_MFR_3526 ++{0x352A, 0x0827}, // RESERVED_MFR_352A ++{0x3512, 0x0EDB}, // RESERVED_MFR_3512 ++{0x3518, 0x4040}, // RESERVED_MFR_3518 ++{0x352E, 0x080A}, // RESERVED_MFR_352E ++{0x3528, 0x200A}, // RESERVED_MFR_3528 ++{0x353A, 0x02B2}, // RESERVED_MFR_353A ++{0x3496, 0x6B00}, // RESERVED_MFR_3496 ++{0x3516, 0x8888}, // RESERVED_MFR_3516 ++{0x351C, 0xCFF2}, // RESERVED_MFR_351C ++{0x353E, 0x2044}, // RESERVED_MFR_353E ++{0x3540, 0x4444}, // RESERVED_MFR_3540 ++{0x3542, 0x448F}, // RESERVED_MFR_3542 ++{0x2512, 0x8000}, // RESERVED_MFR2_2512 ++{0x2510, 0x0409}, // RESERVED_MFR2_2510 ++{0x2510, 0x0A0B}, // RESERVED_MFR2_2510 ++{0x2510, 0x0C0E}, // RESERVED_MFR2_2510 ++{0x2510, 0xFFFF}, // RESERVED_MFR2_2510 ++{0x2510, 0xFFFF}, // RESERVED_MFR2_2510 ++{0x2510, 0xFFFF}, // RESERVED_MFR2_2510 ++{0x2510, 0xFFFF}, // RESERVED_MFR2_2510 ++{0x2510, 0xFFFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x1011}, // RESERVED_MFR2_2510 ++{0x2510, 0x1314}, // RESERVED_MFR2_2510 ++{0x2510, 0x1516}, // RESERVED_MFR2_2510 ++{0x2510, 0xFFFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x1827}, // RESERVED_MFR2_2510 ++{0x2510, 0x2F3F}, // RESERVED_MFR2_2510 ++{0x2510, 0x484B}, // RESERVED_MFR2_2510 ++{0x2510, 0x4D51}, // RESERVED_MFR2_2510 ++{0x2510, 0x5859}, // RESERVED_MFR2_2510 ++{0x2510, 0x5E61}, // RESERVED_MFR2_2510 ++{0x2510, 0x6263}, // RESERVED_MFR2_2510 ++{0x2510, 0x6567}, // RESERVED_MFR2_2510 ++{0x2510, 0x696A}, // RESERVED_MFR2_2510 ++{0x2510, 0x6B6C}, // RESERVED_MFR2_2510 ++{0x2510, 0x6E6F}, // RESERVED_MFR2_2510 ++{0x2510, 0x7D7E}, // RESERVED_MFR2_2510 ++{0x2510, 0x828C}, // RESERVED_MFR2_2510 ++{0x2510, 0xFFFF}, // RESERVED_MFR2_2510 ++{0x2510, 0xFFFF}, // RESERVED_MFR2_2510 ++{0x2510, 0xFFFF}, // RESERVED_MFR2_2510 ++{0x2510, 0xFFFF}, // RESERVED_MFR2_2510 ++{0x2510, 0xFFFF}, // RESERVED_MFR2_2510 ++{0x2510, 0xFFFF}, // RESERVED_MFR2_2510 ++{0x2510, 0xFFFF}, // RESERVED_MFR2_2510 ++{0x2510, 0xC003}, // RESERVED_MFR2_2510 ++{0x2510, 0x8058}, // RESERVED_MFR2_2510 ++{0x2510, 0xD802}, // RESERVED_MFR2_2510 ++{0x2510, 0xA0E0}, // RESERVED_MFR2_2510 ++{0x2510, 0x3041}, // RESERVED_MFR2_2510 ++{0x2510, 0x3042}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x3050}, // RESERVED_MFR2_2510 ++{0x2510, 0x3088}, // RESERVED_MFR2_2510 ++{0x2510, 0x30A0}, // RESERVED_MFR2_2510 ++{0x2510, 0x3090}, // RESERVED_MFR2_2510 ++{0x2510, 0x32C2}, // RESERVED_MFR2_2510 ++{0x2510, 0xA0C0}, // RESERVED_MFR2_2510 ++{0x2510, 0x9008}, // RESERVED_MFR2_2510 ++{0x2510, 0x8802}, // RESERVED_MFR2_2510 ++{0x2510, 0x20FF}, // RESERVED_MFR2_2510 ++{0x2510, 0x20FF}, // RESERVED_MFR2_2510 ++{0x2510, 0x20FF}, // RESERVED_MFR2_2510 ++{0x2510, 0x20FF}, // RESERVED_MFR2_2510 ++{0x2510, 0x20FF}, // RESERVED_MFR2_2510 ++{0x2510, 0x9018}, // RESERVED_MFR2_2510 ++{0x2510, 0x881A}, // RESERVED_MFR2_2510 ++{0x2510, 0xD80A}, // RESERVED_MFR2_2510 ++{0x2510, 0x8078}, // RESERVED_MFR2_2510 ++{0x2510, 0xD80E}, // RESERVED_MFR2_2510 ++{0x2510, 0x20FF}, // RESERVED_MFR2_2510 ++{0x2510, 0x885B}, // RESERVED_MFR2_2510 ++{0x2510, 0x20FF}, // RESERVED_MFR2_2510 ++{0x2510, 0x887B}, // RESERVED_MFR2_2510 ++{0x2510, 0x20FF}, // RESERVED_MFR2_2510 ++{0x2510, 0x887F}, // RESERVED_MFR2_2510 ++{0x2510, 0x20FF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x20FF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x20FF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x20FF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0xA0C4}, // RESERVED_MFR2_2510 ++{0x2510, 0x20FF}, // RESERVED_MFR2_2510 ++{0x2510, 0x8058}, // RESERVED_MFR2_2510 ++{0x2510, 0xD80A}, // RESERVED_MFR2_2510 ++{0x2510, 0x9039}, // RESERVED_MFR2_2510 ++{0x2510, 0x20FF}, // RESERVED_MFR2_2510 ++{0x2510, 0x907F}, // RESERVED_MFR2_2510 ++{0x2510, 0x885B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2064}, // RESERVED_MFR2_2510 ++{0x2510, 0x881B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2010}, // RESERVED_MFR2_2510 ++{0x2510, 0x8803}, // RESERVED_MFR2_2510 ++{0x2510, 0xD802}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x20FF}, // RESERVED_MFR2_2510 ++{0x2510, 0x906B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2064}, // RESERVED_MFR2_2510 ++{0x2510, 0x3084}, // RESERVED_MFR2_2510 ++{0x2510, 0x2003}, // RESERVED_MFR2_2510 ++{0x2510, 0x3048}, // RESERVED_MFR2_2510 ++{0x2510, 0x3044}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0xA004}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x2400}, // RESERVED_MFR2_2510 ++{0x2510, 0x2401}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x2400}, // RESERVED_MFR2_2510 ++{0x2510, 0x2401}, // RESERVED_MFR2_2510 ++{0x2510, 0x2702}, // RESERVED_MFR2_2510 ++{0x2510, 0x3242}, // RESERVED_MFR2_2510 ++{0x2510, 0x2420}, // RESERVED_MFR2_2510 ++{0x2510, 0x2421}, // RESERVED_MFR2_2510 ++{0x2510, 0x2703}, // RESERVED_MFR2_2510 ++{0x2510, 0x3242}, // RESERVED_MFR2_2510 ++{0x2510, 0x2420}, // RESERVED_MFR2_2510 ++{0x2510, 0x2421}, // RESERVED_MFR2_2510 ++{0x2510, 0x2704}, // RESERVED_MFR2_2510 ++{0x2510, 0x3242}, // RESERVED_MFR2_2510 ++{0x2510, 0x2420}, // RESERVED_MFR2_2510 ++{0x2510, 0x2421}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x2402}, // RESERVED_MFR2_2510 ++{0x2510, 0x2403}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x2741}, // RESERVED_MFR2_2510 ++{0x2510, 0x2429}, // RESERVED_MFR2_2510 ++{0x2510, 0x2740}, // RESERVED_MFR2_2510 ++{0x2510, 0x242A}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x2779}, // RESERVED_MFR2_2510 ++{0x2510, 0x242C}, // RESERVED_MFR2_2510 ++{0x2510, 0x2781}, // RESERVED_MFR2_2510 ++{0x2510, 0x242D}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x2703}, // RESERVED_MFR2_2510 ++{0x2510, 0x2432}, // RESERVED_MFR2_2510 ++{0x2510, 0x2703}, // RESERVED_MFR2_2510 ++{0x2510, 0x3242}, // RESERVED_MFR2_2510 ++{0x2510, 0x27BB}, // RESERVED_MFR2_2510 ++{0x2510, 0x2430}, // RESERVED_MFR2_2510 ++{0x2510, 0x27BB}, // RESERVED_MFR2_2510 ++{0x2510, 0x3242}, // RESERVED_MFR2_2510 ++{0x2510, 0x2702}, // RESERVED_MFR2_2510 ++{0x2510, 0x2431}, // RESERVED_MFR2_2510 ++{0x2510, 0x2702}, // RESERVED_MFR2_2510 ++{0x2510, 0x3242}, // RESERVED_MFR2_2510 ++{0x2510, 0x27C3}, // RESERVED_MFR2_2510 ++{0x2510, 0x2430}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0xB800}, // RESERVED_MFR2_2510 ++{0x2510, 0x3250}, // RESERVED_MFR2_2510 ++{0x2510, 0x3108}, // RESERVED_MFR2_2510 ++{0x2510, 0x8058}, // RESERVED_MFR2_2510 ++{0x2510, 0xD800}, // RESERVED_MFR2_2510 ++{0x2510, 0xA005}, // RESERVED_MFR2_2510 ++{0x2510, 0x3101}, // RESERVED_MFR2_2510 ++{0x2510, 0x3041}, // RESERVED_MFR2_2510 ++{0x2510, 0x3104}, // RESERVED_MFR2_2510 ++{0x2510, 0xB035}, // RESERVED_MFR2_2510 ++{0x2510, 0xB075}, // RESERVED_MFR2_2510 ++{0x2510, 0x30C1}, // RESERVED_MFR2_2510 ++{0x2510, 0x3102}, // RESERVED_MFR2_2510 ++{0x2510, 0x3041}, // RESERVED_MFR2_2510 ++{0x2510, 0xB808}, // RESERVED_MFR2_2510 ++{0x2510, 0x3202}, // RESERVED_MFR2_2510 ++{0x2510, 0xB848}, // RESERVED_MFR2_2510 ++{0x2510, 0xB84C}, // RESERVED_MFR2_2510 ++{0x2510, 0x2201}, // RESERVED_MFR2_2510 ++{0x2510, 0xB377}, // RESERVED_MFR2_2510 ++{0x2510, 0x8843}, // RESERVED_MFR2_2510 ++{0x2510, 0x916F}, // RESERVED_MFR2_2510 ++{0x2510, 0x2201}, // RESERVED_MFR2_2510 ++{0x2510, 0xB84E}, // RESERVED_MFR2_2510 ++{0x2510, 0xF905}, // RESERVED_MFR2_2510 ++{0x2510, 0xF907}, // RESERVED_MFR2_2510 ++{0x2510, 0x2200}, // RESERVED_MFR2_2510 ++{0x2510, 0x885B}, // RESERVED_MFR2_2510 ++{0x2510, 0xA898}, // RESERVED_MFR2_2510 ++{0x2510, 0xA8D8}, // RESERVED_MFR2_2510 ++{0x2510, 0xF8E8}, // RESERVED_MFR2_2510 ++{0x2510, 0x80D8}, // RESERVED_MFR2_2510 ++{0x2510, 0x9007}, // RESERVED_MFR2_2510 ++{0x2510, 0x916F}, // RESERVED_MFR2_2510 ++{0x2510, 0x2206}, // RESERVED_MFR2_2510 ++{0x2510, 0xB808}, // RESERVED_MFR2_2510 ++{0x2510, 0xC800}, // RESERVED_MFR2_2510 ++{0x2510, 0xE807}, // RESERVED_MFR2_2510 ++{0x2510, 0x88DB}, // RESERVED_MFR2_2510 ++{0x2510, 0xF8A8}, // RESERVED_MFR2_2510 ++{0x2510, 0xF888}, // RESERVED_MFR2_2510 ++{0x2510, 0x2203}, // RESERVED_MFR2_2510 ++{0x2510, 0xB07B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x80C8}, // RESERVED_MFR2_2510 ++{0x2510, 0x8088}, // RESERVED_MFR2_2510 ++{0x2510, 0x220B}, // RESERVED_MFR2_2510 ++{0x2510, 0xB06A}, // RESERVED_MFR2_2510 ++{0x2510, 0x88CB}, // RESERVED_MFR2_2510 ++{0x2510, 0x888B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2224}, // RESERVED_MFR2_2510 ++{0x2510, 0xB04A}, // RESERVED_MFR2_2510 ++{0x2510, 0x2218}, // RESERVED_MFR2_2510 ++{0x2510, 0x210D}, // RESERVED_MFR2_2510 ++{0x2510, 0x2108}, // RESERVED_MFR2_2510 ++{0x2510, 0x902F}, // RESERVED_MFR2_2510 ++{0x2510, 0xB04B}, // RESERVED_MFR2_2510 ++{0x2510, 0xF880}, // RESERVED_MFR2_2510 ++{0x2510, 0x220F}, // RESERVED_MFR2_2510 ++{0x2510, 0x2205}, // RESERVED_MFR2_2510 ++{0x2510, 0x2203}, // RESERVED_MFR2_2510 ++{0x2510, 0x9800}, // RESERVED_MFR2_2510 ++{0x2510, 0xB043}, // RESERVED_MFR2_2510 ++{0x2510, 0xA8C9}, // RESERVED_MFR2_2510 ++{0x2510, 0x31C1}, // RESERVED_MFR2_2510 ++{0x2510, 0x80A8}, // RESERVED_MFR2_2510 ++{0x2510, 0x2205}, // RESERVED_MFR2_2510 ++{0x2510, 0x916F}, // RESERVED_MFR2_2510 ++{0x2510, 0x2104}, // RESERVED_MFR2_2510 ++{0x2510, 0x88AB}, // RESERVED_MFR2_2510 ++{0x2510, 0x2104}, // RESERVED_MFR2_2510 ++{0x2510, 0xB808}, // RESERVED_MFR2_2510 ++{0x2510, 0x9800}, // RESERVED_MFR2_2510 ++{0x2510, 0x2440}, // RESERVED_MFR2_2510 ++{0x2510, 0xF110}, // RESERVED_MFR2_2510 ++{0x2510, 0xF804}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x8088}, // RESERVED_MFR2_2510 ++{0x2510, 0x3002}, // RESERVED_MFR2_2510 ++{0x2510, 0xB838}, // RESERVED_MFR2_2510 ++{0x2510, 0xA8C8}, // RESERVED_MFR2_2510 ++{0x2510, 0xB04B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2442}, // RESERVED_MFR2_2510 ++{0x2510, 0x3210}, // RESERVED_MFR2_2510 ++{0x2510, 0x2206}, // RESERVED_MFR2_2510 ++{0x2510, 0x888B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2441}, // RESERVED_MFR2_2510 ++{0x2510, 0x3202}, // RESERVED_MFR2_2510 ++{0x2510, 0xF880}, // RESERVED_MFR2_2510 ++{0x2510, 0xB830}, // RESERVED_MFR2_2510 ++{0x2510, 0xC801}, // RESERVED_MFR2_2510 ++{0x2510, 0x30C2}, // RESERVED_MFR2_2510 ++{0x2510, 0xE80C}, // RESERVED_MFR2_2510 ++{0x2510, 0x2201}, // RESERVED_MFR2_2510 ++{0x2510, 0xB04A}, // RESERVED_MFR2_2510 ++{0x2510, 0x2227}, // RESERVED_MFR2_2510 ++{0x2510, 0x2205}, // RESERVED_MFR2_2510 ++{0x2510, 0x2207}, // RESERVED_MFR2_2510 ++{0x2510, 0x902F}, // RESERVED_MFR2_2510 ++{0x2510, 0x220E}, // RESERVED_MFR2_2510 ++{0x2510, 0x2205}, // RESERVED_MFR2_2510 ++{0x2510, 0x2204}, // RESERVED_MFR2_2510 ++{0x2510, 0xB042}, // RESERVED_MFR2_2510 ++{0x2510, 0xA9A1}, // RESERVED_MFR2_2510 ++{0x2510, 0x8008}, // RESERVED_MFR2_2510 ++{0x2510, 0xB093}, // RESERVED_MFR2_2510 ++{0x2510, 0x31C1}, // RESERVED_MFR2_2510 ++{0x2510, 0x916B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2008}, // RESERVED_MFR2_2510 ++{0x2510, 0x32C1}, // RESERVED_MFR2_2510 ++{0x2510, 0x8803}, // RESERVED_MFR2_2510 ++{0x2510, 0xA044}, // RESERVED_MFR2_2510 ++{0x2510, 0x3044}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0xA004}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0xA084}, // RESERVED_MFR2_2510 ++{0x2510, 0x30D0}, // RESERVED_MFR2_2510 ++{0x2510, 0x8107}, // RESERVED_MFR2_2510 ++{0x2510, 0xD804}, // RESERVED_MFR2_2510 ++{0x2510, 0x3141}, // RESERVED_MFR2_2510 ++{0x2510, 0x3042}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x3142}, // RESERVED_MFR2_2510 ++{0x2510, 0x3042}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x3281}, // RESERVED_MFR2_2510 ++{0x2510, 0x3042}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x3290}, // RESERVED_MFR2_2510 ++{0x2510, 0x3042}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x3110}, // RESERVED_MFR2_2510 ++{0x2510, 0x3042}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x3120}, // RESERVED_MFR2_2510 ++{0x2510, 0x3042}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x3282}, // RESERVED_MFR2_2510 ++{0x2510, 0x3042}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x32A0}, // RESERVED_MFR2_2510 ++{0x2510, 0x3042}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x881B}, // RESERVED_MFR2_2510 ++{0x2510, 0x895F}, // RESERVED_MFR2_2510 ++{0x2510, 0xA08C}, // RESERVED_MFR2_2510 ++{0x2510, 0x2200}, // RESERVED_MFR2_2510 ++{0x2510, 0xA084}, // RESERVED_MFR2_2510 ++{0x2510, 0x2440}, // RESERVED_MFR2_2510 ++{0x2510, 0xB095}, // RESERVED_MFR2_2510 ++{0x2510, 0xF010}, // RESERVED_MFR2_2510 ++{0x2510, 0xF864}, // RESERVED_MFR2_2510 ++{0x2510, 0xF90D}, // RESERVED_MFR2_2510 ++{0x2510, 0x3084}, // RESERVED_MFR2_2510 ++{0x2510, 0x32C1}, // RESERVED_MFR2_2510 ++{0x2510, 0x3090}, // RESERVED_MFR2_2510 ++{0x2510, 0x3088}, // RESERVED_MFR2_2510 ++{0x2510, 0x2443}, // RESERVED_MFR2_2510 ++{0x2510, 0x8103}, // RESERVED_MFR2_2510 ++{0x2510, 0xD800}, // RESERVED_MFR2_2510 ++{0x2510, 0x3001}, // RESERVED_MFR2_2510 ++{0x2510, 0x2442}, // RESERVED_MFR2_2510 ++{0x2510, 0x3220}, // RESERVED_MFR2_2510 ++{0x2510, 0x2002}, // RESERVED_MFR2_2510 ++{0x2510, 0x8947}, // RESERVED_MFR2_2510 ++{0x2510, 0x2004}, // RESERVED_MFR2_2510 ++{0x2510, 0x8803}, // RESERVED_MFR2_2510 ++{0x2510, 0x2441}, // RESERVED_MFR2_2510 ++{0x2510, 0x30C2}, // RESERVED_MFR2_2510 ++{0x2510, 0xA9A0}, // RESERVED_MFR2_2510 ++{0x2510, 0xB094}, // RESERVED_MFR2_2510 ++{0x2510, 0x2201}, // RESERVED_MFR2_2510 ++{0x2510, 0xA0C4}, // RESERVED_MFR2_2510 ++{0x2510, 0x3048}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0xA004}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0xB980}, // RESERVED_MFR2_2510 ++{0x2510, 0x3250}, // RESERVED_MFR2_2510 ++{0x2510, 0x3108}, // RESERVED_MFR2_2510 ++{0x2510, 0xA881}, // RESERVED_MFR2_2510 ++{0x2510, 0xA8C1}, // RESERVED_MFR2_2510 ++{0x2510, 0x8008}, // RESERVED_MFR2_2510 ++{0x2510, 0xD900}, // RESERVED_MFR2_2510 ++{0x2510, 0xA105}, // RESERVED_MFR2_2510 ++{0x2510, 0x30C1}, // RESERVED_MFR2_2510 ++{0x2510, 0x2020}, // RESERVED_MFR2_2510 ++{0x2510, 0x3101}, // RESERVED_MFR2_2510 ++{0x2510, 0x3041}, // RESERVED_MFR2_2510 ++{0x2510, 0x3104}, // RESERVED_MFR2_2510 ++{0x2510, 0x3102}, // RESERVED_MFR2_2510 ++{0x2510, 0x3041}, // RESERVED_MFR2_2510 ++{0x2510, 0xF860}, // RESERVED_MFR2_2510 ++{0x2510, 0xB095}, // RESERVED_MFR2_2510 ++{0x2510, 0x2001}, // RESERVED_MFR2_2510 ++{0x2510, 0xB988}, // RESERVED_MFR2_2510 ++{0x2510, 0xB9F8}, // RESERVED_MFR2_2510 ++{0x2510, 0xB9FC}, // RESERVED_MFR2_2510 ++{0x2510, 0x8803}, // RESERVED_MFR2_2510 ++{0x2510, 0x916F}, // RESERVED_MFR2_2510 ++{0x2510, 0x2001}, // RESERVED_MFR2_2510 ++{0x2510, 0xB9FE}, // RESERVED_MFR2_2510 ++{0x2510, 0xF905}, // RESERVED_MFR2_2510 ++{0x2510, 0xF907}, // RESERVED_MFR2_2510 ++{0x2510, 0x3202}, // RESERVED_MFR2_2510 ++{0x2510, 0x880B}, // RESERVED_MFR2_2510 ++{0x2510, 0xB397}, // RESERVED_MFR2_2510 ++{0x2510, 0xF8E8}, // RESERVED_MFR2_2510 ++{0x2510, 0x8088}, // RESERVED_MFR2_2510 ++{0x2510, 0x9007}, // RESERVED_MFR2_2510 ++{0x2510, 0x916F}, // RESERVED_MFR2_2510 ++{0x2510, 0x2204}, // RESERVED_MFR2_2510 ++{0x2510, 0xB137}, // RESERVED_MFR2_2510 ++{0x2510, 0xB9B8}, // RESERVED_MFR2_2510 ++{0x2510, 0xC801}, // RESERVED_MFR2_2510 ++{0x2510, 0xE809}, // RESERVED_MFR2_2510 ++{0x2510, 0x3241}, // RESERVED_MFR2_2510 ++{0x2510, 0xB177}, // RESERVED_MFR2_2510 ++{0x2510, 0x888B}, // RESERVED_MFR2_2510 ++{0x2510, 0xF8A8}, // RESERVED_MFR2_2510 ++{0x2510, 0xF888}, // RESERVED_MFR2_2510 ++{0x2510, 0x2203}, // RESERVED_MFR2_2510 ++{0x2510, 0xA8C8}, // RESERVED_MFR2_2510 ++{0x2510, 0xB07B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x8088}, // RESERVED_MFR2_2510 ++{0x2510, 0x8088}, // RESERVED_MFR2_2510 ++{0x2510, 0xD800}, // RESERVED_MFR2_2510 ++{0x2510, 0x220B}, // RESERVED_MFR2_2510 ++{0x2510, 0xB06A}, // RESERVED_MFR2_2510 ++{0x2510, 0x888B}, // RESERVED_MFR2_2510 ++{0x2510, 0x888B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2224}, // RESERVED_MFR2_2510 ++{0x2510, 0xB04A}, // RESERVED_MFR2_2510 ++{0x2510, 0x2218}, // RESERVED_MFR2_2510 ++{0x2510, 0xB04B}, // RESERVED_MFR2_2510 ++{0x2510, 0x902F}, // RESERVED_MFR2_2510 ++{0x2510, 0xF880}, // RESERVED_MFR2_2510 ++{0x2510, 0x2211}, // RESERVED_MFR2_2510 ++{0x2510, 0x2205}, // RESERVED_MFR2_2510 ++{0x2510, 0x2204}, // RESERVED_MFR2_2510 ++{0x2510, 0xB043}, // RESERVED_MFR2_2510 ++{0x2510, 0xA8C1}, // RESERVED_MFR2_2510 ++{0x2510, 0x31C1}, // RESERVED_MFR2_2510 ++{0x2510, 0x2200}, // RESERVED_MFR2_2510 ++{0x2510, 0x8048}, // RESERVED_MFR2_2510 ++{0x2510, 0x2103}, // RESERVED_MFR2_2510 ++{0x2510, 0x916F}, // RESERVED_MFR2_2510 ++{0x2510, 0x2106}, // RESERVED_MFR2_2510 ++{0x2510, 0x884B}, // RESERVED_MFR2_2510 ++{0x2510, 0xA8C1}, // RESERVED_MFR2_2510 ++{0x2510, 0x2440}, // RESERVED_MFR2_2510 ++{0x2510, 0xF010}, // RESERVED_MFR2_2510 ++{0x2510, 0xF804}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x8008}, // RESERVED_MFR2_2510 ++{0x2510, 0x3002}, // RESERVED_MFR2_2510 ++{0x2510, 0xB988}, // RESERVED_MFR2_2510 ++{0x2510, 0x2442}, // RESERVED_MFR2_2510 ++{0x2510, 0x3210}, // RESERVED_MFR2_2510 ++{0x2510, 0x2206}, // RESERVED_MFR2_2510 ++{0x2510, 0x2207}, // RESERVED_MFR2_2510 ++{0x2510, 0x3202}, // RESERVED_MFR2_2510 ++{0x2510, 0xA8C1}, // RESERVED_MFR2_2510 ++{0x2510, 0x2013}, // RESERVED_MFR2_2510 ++{0x2510, 0x8088}, // RESERVED_MFR2_2510 ++{0x2510, 0x200C}, // RESERVED_MFR2_2510 ++{0x2510, 0x888B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2005}, // RESERVED_MFR2_2510 ++{0x2510, 0xA8D0}, // RESERVED_MFR2_2510 ++{0x2510, 0xB04B}, // RESERVED_MFR2_2510 ++{0x2510, 0xF880}, // RESERVED_MFR2_2510 ++{0x2510, 0xB980}, // RESERVED_MFR2_2510 ++{0x2510, 0xC800}, // RESERVED_MFR2_2510 ++{0x2510, 0x30C2}, // RESERVED_MFR2_2510 ++{0x2510, 0xE80C}, // RESERVED_MFR2_2510 ++{0x2510, 0x2201}, // RESERVED_MFR2_2510 ++{0x2510, 0xB04A}, // RESERVED_MFR2_2510 ++{0x2510, 0x2213}, // RESERVED_MFR2_2510 ++{0x2510, 0x2225}, // RESERVED_MFR2_2510 ++{0x2510, 0x8088}, // RESERVED_MFR2_2510 ++{0x2510, 0x2205}, // RESERVED_MFR2_2510 ++{0x2510, 0x888B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2203}, // RESERVED_MFR2_2510 ++{0x2510, 0x3241}, // RESERVED_MFR2_2510 ++{0x2510, 0x902F}, // RESERVED_MFR2_2510 ++{0x2510, 0x2215}, // RESERVED_MFR2_2510 ++{0x2510, 0x2205}, // RESERVED_MFR2_2510 ++{0x2510, 0x2204}, // RESERVED_MFR2_2510 ++{0x2510, 0xB042}, // RESERVED_MFR2_2510 ++{0x2510, 0xA9A1}, // RESERVED_MFR2_2510 ++{0x2510, 0x8058}, // RESERVED_MFR2_2510 ++{0x2510, 0xB093}, // RESERVED_MFR2_2510 ++{0x2510, 0x31C1}, // RESERVED_MFR2_2510 ++{0x2510, 0x916B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2008}, // RESERVED_MFR2_2510 ++{0x2510, 0x32C1}, // RESERVED_MFR2_2510 ++{0x2510, 0x8803}, // RESERVED_MFR2_2510 ++{0x2510, 0xA144}, // RESERVED_MFR2_2510 ++{0x2510, 0x3044}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0xA004}, // RESERVED_MFR2_2510 ++{0x2510, 0xB800}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x30D0}, // RESERVED_MFR2_2510 ++{0x2510, 0xA184}, // RESERVED_MFR2_2510 ++{0x2510, 0xB980}, // RESERVED_MFR2_2510 ++{0x2510, 0x8107}, // RESERVED_MFR2_2510 ++{0x2510, 0xD804}, // RESERVED_MFR2_2510 ++{0x2510, 0x3141}, // RESERVED_MFR2_2510 ++{0x2510, 0x3042}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x3142}, // RESERVED_MFR2_2510 ++{0x2510, 0x3042}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x3281}, // RESERVED_MFR2_2510 ++{0x2510, 0x3042}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x3290}, // RESERVED_MFR2_2510 ++{0x2510, 0x3042}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x3110}, // RESERVED_MFR2_2510 ++{0x2510, 0x3042}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x3120}, // RESERVED_MFR2_2510 ++{0x2510, 0x3042}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x3282}, // RESERVED_MFR2_2510 ++{0x2510, 0x3042}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x32A0}, // RESERVED_MFR2_2510 ++{0x2510, 0x3042}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x881B}, // RESERVED_MFR2_2510 ++{0x2510, 0x895F}, // RESERVED_MFR2_2510 ++{0x2510, 0x2440}, // RESERVED_MFR2_2510 ++{0x2510, 0xB095}, // RESERVED_MFR2_2510 ++{0x2510, 0xF010}, // RESERVED_MFR2_2510 ++{0x2510, 0xF864}, // RESERVED_MFR2_2510 ++{0x2510, 0xF90D}, // RESERVED_MFR2_2510 ++{0x2510, 0x32C2}, // RESERVED_MFR2_2510 ++{0x2510, 0x30A0}, // RESERVED_MFR2_2510 ++{0x2510, 0x3090}, // RESERVED_MFR2_2510 ++{0x2510, 0x3088}, // RESERVED_MFR2_2510 ++{0x2510, 0x2443}, // RESERVED_MFR2_2510 ++{0x2510, 0x8103}, // RESERVED_MFR2_2510 ++{0x2510, 0xD860}, // RESERVED_MFR2_2510 ++{0x2510, 0x3001}, // RESERVED_MFR2_2510 ++{0x2510, 0x2202}, // RESERVED_MFR2_2510 ++{0x2510, 0x2442}, // RESERVED_MFR2_2510 ++{0x2510, 0x3220}, // RESERVED_MFR2_2510 ++{0x2510, 0x2004}, // RESERVED_MFR2_2510 ++{0x2510, 0x885B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2441}, // RESERVED_MFR2_2510 ++{0x2510, 0x30C2}, // RESERVED_MFR2_2510 ++{0x2510, 0x8003}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x881B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0xD840}, // RESERVED_MFR2_2510 ++{0x2510, 0x2006}, // RESERVED_MFR2_2510 ++{0x2510, 0xD842}, // RESERVED_MFR2_2510 ++{0x2510, 0x200A}, // RESERVED_MFR2_2510 ++{0x2510, 0x8000}, // RESERVED_MFR2_2510 ++{0x2510, 0xA9A1}, // RESERVED_MFR2_2510 ++{0x2510, 0xB094}, // RESERVED_MFR2_2510 ++{0x2510, 0x2200}, // RESERVED_MFR2_2510 ++{0x2510, 0xD802}, // RESERVED_MFR2_2510 ++{0x2510, 0x8803}, // RESERVED_MFR2_2510 ++{0x2510, 0xA1C4}, // RESERVED_MFR2_2510 ++{0x2510, 0x3048}, // RESERVED_MFR2_2510 ++{0x2510, 0xB800}, // RESERVED_MFR2_2510 ++{0x2510, 0xA004}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0xD802}, // RESERVED_MFR2_2510 ++{0x2510, 0x9818}, // RESERVED_MFR2_2510 ++{0x2510, 0x3101}, // RESERVED_MFR2_2510 ++{0x2510, 0x3041}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x3102}, // RESERVED_MFR2_2510 ++{0x2510, 0x3041}, // RESERVED_MFR2_2510 ++{0x2510, 0x8018}, // RESERVED_MFR2_2510 ++{0x2510, 0xD800}, // RESERVED_MFR2_2510 ++{0x2510, 0x2002}, // RESERVED_MFR2_2510 ++{0x2510, 0x8038}, // RESERVED_MFR2_2510 ++{0x2510, 0x2205}, // RESERVED_MFR2_2510 ++{0x2510, 0x881B}, // RESERVED_MFR2_2510 ++{0x2510, 0x883B}, // RESERVED_MFR2_2510 ++{0x2510, 0x213E}, // RESERVED_MFR2_2510 ++{0x2510, 0x8018}, // RESERVED_MFR2_2510 ++{0x2510, 0x2202}, // RESERVED_MFR2_2510 ++{0x2510, 0x8000}, // RESERVED_MFR2_2510 ++{0x2510, 0x2201}, // RESERVED_MFR2_2510 ++{0x2510, 0x8803}, // RESERVED_MFR2_2510 ++{0x2510, 0x9800}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x2440}, // RESERVED_MFR2_2510 ++{0x2510, 0xB095}, // RESERVED_MFR2_2510 ++{0x2510, 0xF110}, // RESERVED_MFR2_2510 ++{0x2510, 0xF864}, // RESERVED_MFR2_2510 ++{0x2510, 0xF90D}, // RESERVED_MFR2_2510 ++{0x2510, 0x2442}, // RESERVED_MFR2_2510 ++{0x2510, 0x3220}, // RESERVED_MFR2_2510 ++{0x2510, 0x2007}, // RESERVED_MFR2_2510 ++{0x2510, 0x2441}, // RESERVED_MFR2_2510 ++{0x2510, 0x30C2}, // RESERVED_MFR2_2510 ++{0x2510, 0xA9A0}, // RESERVED_MFR2_2510 ++{0x2510, 0xB094}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0xB980}, // RESERVED_MFR2_2510 ++{0x2510, 0x3101}, // RESERVED_MFR2_2510 ++{0x2510, 0x3041}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x3102}, // RESERVED_MFR2_2510 ++{0x2510, 0x3041}, // RESERVED_MFR2_2510 ++{0x2510, 0x8028}, // RESERVED_MFR2_2510 ++{0x2510, 0xD800}, // RESERVED_MFR2_2510 ++{0x2510, 0x220A}, // RESERVED_MFR2_2510 ++{0x2510, 0x880B}, // RESERVED_MFR2_2510 ++{0x2510, 0x882B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2440}, // RESERVED_MFR2_2510 ++{0x2510, 0xB095}, // RESERVED_MFR2_2510 ++{0x2510, 0xF110}, // RESERVED_MFR2_2510 ++{0x2510, 0xF864}, // RESERVED_MFR2_2510 ++{0x2510, 0xF90D}, // RESERVED_MFR2_2510 ++{0x2510, 0x8008}, // RESERVED_MFR2_2510 ++{0x2510, 0x3004}, // RESERVED_MFR2_2510 ++{0x2510, 0x2202}, // RESERVED_MFR2_2510 ++{0x2510, 0x2442}, // RESERVED_MFR2_2510 ++{0x2510, 0x882B}, // RESERVED_MFR2_2510 ++{0x2510, 0x3220}, // RESERVED_MFR2_2510 ++{0x2510, 0x2004}, // RESERVED_MFR2_2510 ++{0x2510, 0x880B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2441}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x80A8}, // RESERVED_MFR2_2510 ++{0x2510, 0xD800}, // RESERVED_MFR2_2510 ++{0x2510, 0x220A}, // RESERVED_MFR2_2510 ++{0x2510, 0x88AB}, // RESERVED_MFR2_2510 ++{0x2510, 0x2440}, // RESERVED_MFR2_2510 ++{0x2510, 0xB043}, // RESERVED_MFR2_2510 ++{0x2510, 0x2200}, // RESERVED_MFR2_2510 ++{0x2510, 0xF110}, // RESERVED_MFR2_2510 ++{0x2510, 0xF804}, // RESERVED_MFR2_2510 ++{0x2510, 0xF907}, // RESERVED_MFR2_2510 ++{0x2510, 0x8088}, // RESERVED_MFR2_2510 ++{0x2510, 0x3001}, // RESERVED_MFR2_2510 ++{0x2510, 0x2202}, // RESERVED_MFR2_2510 ++{0x2510, 0xA8C8}, // RESERVED_MFR2_2510 ++{0x2510, 0xB04B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2442}, // RESERVED_MFR2_2510 ++{0x2510, 0x88A3}, // RESERVED_MFR2_2510 ++{0x2510, 0x3220}, // RESERVED_MFR2_2510 ++{0x2510, 0x2004}, // RESERVED_MFR2_2510 ++{0x2510, 0x8883}, // RESERVED_MFR2_2510 ++{0x2510, 0x2441}, // RESERVED_MFR2_2510 ++{0x2510, 0x3202}, // RESERVED_MFR2_2510 ++{0x2510, 0xF880}, // RESERVED_MFR2_2510 ++{0x2510, 0x30C2}, // RESERVED_MFR2_2510 ++{0x2510, 0xE80C}, // RESERVED_MFR2_2510 ++{0x2510, 0x2201}, // RESERVED_MFR2_2510 ++{0x2510, 0xB04A}, // RESERVED_MFR2_2510 ++{0x2510, 0x2227}, // RESERVED_MFR2_2510 ++{0x2510, 0x2205}, // RESERVED_MFR2_2510 ++{0x2510, 0x3241}, // RESERVED_MFR2_2510 ++{0x2510, 0x2207}, // RESERVED_MFR2_2510 ++{0x2510, 0x902F}, // RESERVED_MFR2_2510 ++{0x2510, 0x220E}, // RESERVED_MFR2_2510 ++{0x2510, 0x2205}, // RESERVED_MFR2_2510 ++{0x2510, 0x2204}, // RESERVED_MFR2_2510 ++{0x2510, 0xB042}, // RESERVED_MFR2_2510 ++{0x2510, 0xA9A1}, // RESERVED_MFR2_2510 ++{0x2510, 0x8008}, // RESERVED_MFR2_2510 ++{0x2510, 0xB093}, // RESERVED_MFR2_2510 ++{0x2510, 0x31C1}, // RESERVED_MFR2_2510 ++{0x2510, 0x916B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2008}, // RESERVED_MFR2_2510 ++{0x2510, 0x32C1}, // RESERVED_MFR2_2510 ++{0x2510, 0x8803}, // RESERVED_MFR2_2510 ++{0x2510, 0xA044}, // RESERVED_MFR2_2510 ++{0x2510, 0x3044}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0xA004}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x2400}, // RESERVED_MFR2_2510 ++{0x2510, 0x2751}, // RESERVED_MFR2_2510 ++{0x2510, 0x2438}, // RESERVED_MFR2_2510 ++{0x2510, 0x2750}, // RESERVED_MFR2_2510 ++{0x2510, 0x2421}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x2749}, // RESERVED_MFR2_2510 ++{0x2510, 0x2422}, // RESERVED_MFR2_2510 ++{0x2510, 0x2749}, // RESERVED_MFR2_2510 ++{0x2510, 0x2423}, // RESERVED_MFR2_2510 ++{0x2510, 0x2709}, // RESERVED_MFR2_2510 ++{0x2510, 0x2420}, // RESERVED_MFR2_2510 ++{0x2510, 0x2729}, // RESERVED_MFR2_2510 ++{0x2510, 0x2423}, // RESERVED_MFR2_2510 ++{0x2510, 0x3242}, // RESERVED_MFR2_2510 ++{0x2510, 0x2722}, // RESERVED_MFR2_2510 ++{0x2510, 0x2422}, // RESERVED_MFR2_2510 ++{0x2510, 0x2769}, // RESERVED_MFR2_2510 ++{0x2510, 0x2421}, // RESERVED_MFR2_2510 ++{0x2510, 0x2702}, // RESERVED_MFR2_2510 ++{0x2510, 0x2421}, // RESERVED_MFR2_2510 ++{0x2510, 0x3242}, // RESERVED_MFR2_2510 ++{0x2510, 0x276A}, // RESERVED_MFR2_2510 ++{0x2510, 0x2420}, // RESERVED_MFR2_2510 ++{0x2510, 0x276A}, // RESERVED_MFR2_2510 ++{0x2510, 0x2421}, // RESERVED_MFR2_2510 ++{0x2510, 0x2703}, // RESERVED_MFR2_2510 ++{0x2510, 0x2420}, // RESERVED_MFR2_2510 ++{0x2510, 0x2703}, // RESERVED_MFR2_2510 ++{0x2510, 0x2421}, // RESERVED_MFR2_2510 ++{0x2510, 0x3242}, // RESERVED_MFR2_2510 ++{0x2510, 0x276B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2420}, // RESERVED_MFR2_2510 ++{0x2510, 0x276B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2421}, // RESERVED_MFR2_2510 ++{0x2510, 0x2704}, // RESERVED_MFR2_2510 ++{0x2510, 0x2420}, // RESERVED_MFR2_2510 ++{0x2510, 0x2704}, // RESERVED_MFR2_2510 ++{0x2510, 0x2421}, // RESERVED_MFR2_2510 ++{0x2510, 0x3242}, // RESERVED_MFR2_2510 ++{0x2510, 0x276C}, // RESERVED_MFR2_2510 ++{0x2510, 0x2420}, // RESERVED_MFR2_2510 ++{0x2510, 0x276C}, // RESERVED_MFR2_2510 ++{0x2510, 0x2421}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x2759}, // RESERVED_MFR2_2510 ++{0x2510, 0x2422}, // RESERVED_MFR2_2510 ++{0x2510, 0x2758}, // RESERVED_MFR2_2510 ++{0x2510, 0x2420}, // RESERVED_MFR2_2510 ++{0x2510, 0x2403}, // RESERVED_MFR2_2510 ++{0x2510, 0x2712}, // RESERVED_MFR2_2510 ++{0x2510, 0x3242}, // RESERVED_MFR2_2510 ++{0x2510, 0x2422}, // RESERVED_MFR2_2510 ++{0x2510, 0x271A}, // RESERVED_MFR2_2510 ++{0x2510, 0x3242}, // RESERVED_MFR2_2510 ++{0x2510, 0x2420}, // RESERVED_MFR2_2510 ++{0x2510, 0x2702}, // RESERVED_MFR2_2510 ++{0x2510, 0x2423}, // RESERVED_MFR2_2510 ++{0x2510, 0x2703}, // RESERVED_MFR2_2510 ++{0x2510, 0x3242}, // RESERVED_MFR2_2510 ++{0x2510, 0x2420}, // RESERVED_MFR2_2510 ++{0x2510, 0x2703}, // RESERVED_MFR2_2510 ++{0x2510, 0x2423}, // RESERVED_MFR2_2510 ++{0x2510, 0x2704}, // RESERVED_MFR2_2510 ++{0x2510, 0x3242}, // RESERVED_MFR2_2510 ++{0x2510, 0x2420}, // RESERVED_MFR2_2510 ++{0x2510, 0x2704}, // RESERVED_MFR2_2510 ++{0x2510, 0x2423}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x2400}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0xC023}, // RESERVED_MFR2_2510 ++{0x2510, 0x2402}, // RESERVED_MFR2_2510 ++{0x2510, 0x2405}, // RESERVED_MFR2_2510 ++{0x2510, 0x2789}, // RESERVED_MFR2_2510 ++{0x2510, 0x242E}, // RESERVED_MFR2_2510 ++{0x2510, 0x2788}, // RESERVED_MFR2_2510 ++{0x2510, 0x242F}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x27D8}, // RESERVED_MFR2_2510 ++{0x2510, 0x2433}, // RESERVED_MFR2_2510 ++{0x2510, 0x27D9}, // RESERVED_MFR2_2510 ++{0x2510, 0x2434}, // RESERVED_MFR2_2510 ++{0x2510, 0xC023}, // RESERVED_MFR2_2510 ++{0x2510, 0x2402}, // RESERVED_MFR2_2510 ++{0x2510, 0xC023}, // RESERVED_MFR2_2510 ++{0x2510, 0x2751}, // RESERVED_MFR2_2510 ++{0x2510, 0x2438}, // RESERVED_MFR2_2510 ++{0x2510, 0xC02B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2750}, // RESERVED_MFR2_2510 ++{0x2510, 0x2421}, // RESERVED_MFR2_2510 ++{0x2510, 0xC003}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x3250}, // RESERVED_MFR2_2510 ++{0x2510, 0xC021}, // RESERVED_MFR2_2510 ++{0x2510, 0x2400}, // RESERVED_MFR2_2510 ++{0x2510, 0x2405}, // RESERVED_MFR2_2510 ++{0x2510, 0xC062}, // RESERVED_MFR2_2510 ++{0x2510, 0x3250}, // RESERVED_MFR2_2510 ++{0x2510, 0x2400}, // RESERVED_MFR2_2510 ++{0x2510, 0xC023}, // RESERVED_MFR2_2510 ++{0x2510, 0x2751}, // RESERVED_MFR2_2510 ++{0x2510, 0x2438}, // RESERVED_MFR2_2510 ++{0x2510, 0xC02B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2750}, // RESERVED_MFR2_2510 ++{0x2510, 0x2421}, // RESERVED_MFR2_2510 ++{0x2510, 0xC003}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x3250}, // RESERVED_MFR2_2510 ++{0x2510, 0xC0E3}, // RESERVED_MFR2_2510 ++{0x2510, 0x2400}, // RESERVED_MFR2_2510 ++{0x2510, 0x27B1}, // RESERVED_MFR2_2510 ++{0x2510, 0x2437}, // RESERVED_MFR2_2510 ++{0x2510, 0x3250}, // RESERVED_MFR2_2510 ++{0x2510, 0xC02B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2422}, // RESERVED_MFR2_2510 ++{0x2510, 0xC023}, // RESERVED_MFR2_2510 ++{0x2510, 0x2751}, // RESERVED_MFR2_2510 ++{0x2510, 0x2438}, // RESERVED_MFR2_2510 ++{0x2510, 0xC02B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2750}, // RESERVED_MFR2_2510 ++{0x2510, 0x2421}, // RESERVED_MFR2_2510 ++{0x2510, 0xC003}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x2779}, // RESERVED_MFR2_2510 ++{0x2510, 0x242C}, // RESERVED_MFR2_2510 ++{0x2510, 0x2781}, // RESERVED_MFR2_2510 ++{0x2510, 0x242D}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x2791}, // RESERVED_MFR2_2510 ++{0x2510, 0x2430}, // RESERVED_MFR2_2510 ++{0x2510, 0x2799}, // RESERVED_MFR2_2510 ++{0x2510, 0x2428}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x27A1}, // RESERVED_MFR2_2510 ++{0x2510, 0x2430}, // RESERVED_MFR2_2510 ++{0x2510, 0x27A9}, // RESERVED_MFR2_2510 ++{0x2510, 0x2428}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0xC165}, // RESERVED_MFR2_2510 ++{0x2510, 0x2415}, // RESERVED_MFR2_2510 ++{0x2510, 0xC026}, // RESERVED_MFR2_2510 ++{0x2510, 0x2407}, // RESERVED_MFR2_2510 ++{0x2510, 0xC027}, // RESERVED_MFR2_2510 ++{0x2510, 0x2406}, // RESERVED_MFR2_2510 ++{0x2510, 0x2296}, // RESERVED_MFR2_2510 ++{0x2510, 0x2416}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0xC167}, // RESERVED_MFR2_2510 ++{0x2510, 0x2400}, // RESERVED_MFR2_2510 ++{0x2510, 0xC067}, // RESERVED_MFR2_2510 ++{0x2510, 0x2406}, // RESERVED_MFR2_2510 ++{0x2510, 0x2416}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0xB800}, // RESERVED_MFR2_2510 ++{0x2510, 0x8058}, // RESERVED_MFR2_2510 ++{0x2510, 0xD800}, // RESERVED_MFR2_2510 ++{0x2510, 0xA005}, // RESERVED_MFR2_2510 ++{0x2510, 0x3101}, // RESERVED_MFR2_2510 ++{0x2510, 0x3041}, // RESERVED_MFR2_2510 ++{0x2510, 0x3104}, // RESERVED_MFR2_2510 ++{0x2510, 0xB035}, // RESERVED_MFR2_2510 ++{0x2510, 0xB075}, // RESERVED_MFR2_2510 ++{0x2510, 0x30C1}, // RESERVED_MFR2_2510 ++{0x2510, 0x3102}, // RESERVED_MFR2_2510 ++{0x2510, 0x3041}, // RESERVED_MFR2_2510 ++{0x2510, 0xB808}, // RESERVED_MFR2_2510 ++{0x2510, 0x3202}, // RESERVED_MFR2_2510 ++{0x2510, 0xB848}, // RESERVED_MFR2_2510 ++{0x2510, 0xB84C}, // RESERVED_MFR2_2510 ++{0x2510, 0x2201}, // RESERVED_MFR2_2510 ++{0x2510, 0xB377}, // RESERVED_MFR2_2510 ++{0x2510, 0x8843}, // RESERVED_MFR2_2510 ++{0x2510, 0x916F}, // RESERVED_MFR2_2510 ++{0x2510, 0x2201}, // RESERVED_MFR2_2510 ++{0x2510, 0xB84E}, // RESERVED_MFR2_2510 ++{0x2510, 0xF905}, // RESERVED_MFR2_2510 ++{0x2510, 0xF907}, // RESERVED_MFR2_2510 ++{0x2510, 0x2200}, // RESERVED_MFR2_2510 ++{0x2510, 0x885B}, // RESERVED_MFR2_2510 ++{0x2510, 0xA898}, // RESERVED_MFR2_2510 ++{0x2510, 0xA8D8}, // RESERVED_MFR2_2510 ++{0x2510, 0xF8E8}, // RESERVED_MFR2_2510 ++{0x2510, 0x80D8}, // RESERVED_MFR2_2510 ++{0x2510, 0x9007}, // RESERVED_MFR2_2510 ++{0x2510, 0x916F}, // RESERVED_MFR2_2510 ++{0x2510, 0x2206}, // RESERVED_MFR2_2510 ++{0x2510, 0xB808}, // RESERVED_MFR2_2510 ++{0x2510, 0xC800}, // RESERVED_MFR2_2510 ++{0x2510, 0xE809}, // RESERVED_MFR2_2510 ++{0x2510, 0x88DB}, // RESERVED_MFR2_2510 ++{0x2510, 0xF8A8}, // RESERVED_MFR2_2510 ++{0x2510, 0xF888}, // RESERVED_MFR2_2510 ++{0x2510, 0x2203}, // RESERVED_MFR2_2510 ++{0x2510, 0xB07B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x80C8}, // RESERVED_MFR2_2510 ++{0x2510, 0x8088}, // RESERVED_MFR2_2510 ++{0x2510, 0x220B}, // RESERVED_MFR2_2510 ++{0x2510, 0xB06A}, // RESERVED_MFR2_2510 ++{0x2510, 0x88CB}, // RESERVED_MFR2_2510 ++{0x2510, 0x888B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2224}, // RESERVED_MFR2_2510 ++{0x2510, 0xB04A}, // RESERVED_MFR2_2510 ++{0x2510, 0x2218}, // RESERVED_MFR2_2510 ++{0x2510, 0x210D}, // RESERVED_MFR2_2510 ++{0x2510, 0x2108}, // RESERVED_MFR2_2510 ++{0x2510, 0x902F}, // RESERVED_MFR2_2510 ++{0x2510, 0xB04B}, // RESERVED_MFR2_2510 ++{0x2510, 0xF880}, // RESERVED_MFR2_2510 ++{0x2510, 0x2211}, // RESERVED_MFR2_2510 ++{0x2510, 0x2205}, // RESERVED_MFR2_2510 ++{0x2510, 0x2204}, // RESERVED_MFR2_2510 ++{0x2510, 0xB043}, // RESERVED_MFR2_2510 ++{0x2510, 0xA8C9}, // RESERVED_MFR2_2510 ++{0x2510, 0x31C1}, // RESERVED_MFR2_2510 ++{0x2510, 0x80A8}, // RESERVED_MFR2_2510 ++{0x2510, 0x2205}, // RESERVED_MFR2_2510 ++{0x2510, 0x916F}, // RESERVED_MFR2_2510 ++{0x2510, 0x2104}, // RESERVED_MFR2_2510 ++{0x2510, 0x88AB}, // RESERVED_MFR2_2510 ++{0x2510, 0x2440}, // RESERVED_MFR2_2510 ++{0x2510, 0xF110}, // RESERVED_MFR2_2510 ++{0x2510, 0xF804}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x8088}, // RESERVED_MFR2_2510 ++{0x2510, 0x3002}, // RESERVED_MFR2_2510 ++{0x2510, 0xB838}, // RESERVED_MFR2_2510 ++{0x2510, 0xA8C8}, // RESERVED_MFR2_2510 ++{0x2510, 0xB04B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2442}, // RESERVED_MFR2_2510 ++{0x2510, 0x3210}, // RESERVED_MFR2_2510 ++{0x2510, 0x2206}, // RESERVED_MFR2_2510 ++{0x2510, 0x888B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2441}, // RESERVED_MFR2_2510 ++{0x2510, 0x3202}, // RESERVED_MFR2_2510 ++{0x2510, 0xF880}, // RESERVED_MFR2_2510 ++{0x2510, 0xB830}, // RESERVED_MFR2_2510 ++{0x2510, 0xC801}, // RESERVED_MFR2_2510 ++{0x2510, 0x30C2}, // RESERVED_MFR2_2510 ++{0x2510, 0xE80C}, // RESERVED_MFR2_2510 ++{0x2510, 0x2201}, // RESERVED_MFR2_2510 ++{0x2510, 0xB04A}, // RESERVED_MFR2_2510 ++{0x2510, 0x2227}, // RESERVED_MFR2_2510 ++{0x2510, 0x2205}, // RESERVED_MFR2_2510 ++{0x2510, 0x3241}, // RESERVED_MFR2_2510 ++{0x2510, 0x2207}, // RESERVED_MFR2_2510 ++{0x2510, 0x902F}, // RESERVED_MFR2_2510 ++{0x2510, 0x220E}, // RESERVED_MFR2_2510 ++{0x2510, 0x2205}, // RESERVED_MFR2_2510 ++{0x2510, 0x2204}, // RESERVED_MFR2_2510 ++{0x2510, 0xB042}, // RESERVED_MFR2_2510 ++{0x2510, 0xA8C9}, // RESERVED_MFR2_2510 ++{0x2510, 0xB043}, // RESERVED_MFR2_2510 ++{0x2510, 0x31C1}, // RESERVED_MFR2_2510 ++{0x2510, 0x916F}, // RESERVED_MFR2_2510 ++{0x2510, 0x2009}, // RESERVED_MFR2_2510 ++{0x2510, 0xA004}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x30C2}, // RESERVED_MFR2_2510 ++{0x2510, 0xA9A0}, // RESERVED_MFR2_2510 ++{0x2510, 0xB094}, // RESERVED_MFR2_2510 ++{0x2510, 0x2201}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0xB980}, // RESERVED_MFR2_2510 ++{0x2510, 0x3101}, // RESERVED_MFR2_2510 ++{0x2510, 0x3041}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x3102}, // RESERVED_MFR2_2510 ++{0x2510, 0x3041}, // RESERVED_MFR2_2510 ++{0x2510, 0x8038}, // RESERVED_MFR2_2510 ++{0x2510, 0x220A}, // RESERVED_MFR2_2510 ++{0x2510, 0x881B}, // RESERVED_MFR2_2510 ++{0x2510, 0x883B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2440}, // RESERVED_MFR2_2510 ++{0x2510, 0xB095}, // RESERVED_MFR2_2510 ++{0x2510, 0xF110}, // RESERVED_MFR2_2510 ++{0x2510, 0xF864}, // RESERVED_MFR2_2510 ++{0x2510, 0xF90D}, // RESERVED_MFR2_2510 ++{0x2510, 0x8018}, // RESERVED_MFR2_2510 ++{0x2510, 0x3004}, // RESERVED_MFR2_2510 ++{0x2510, 0x2202}, // RESERVED_MFR2_2510 ++{0x2510, 0x2442}, // RESERVED_MFR2_2510 ++{0x2510, 0x883B}, // RESERVED_MFR2_2510 ++{0x2510, 0x3220}, // RESERVED_MFR2_2510 ++{0x2510, 0x2004}, // RESERVED_MFR2_2510 ++{0x2510, 0x881B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2441}, // RESERVED_MFR2_2510 ++{0x2510, 0x30C2}, // RESERVED_MFR2_2510 ++{0x2510, 0xA9A0}, // RESERVED_MFR2_2510 ++{0x2510, 0xB094}, // RESERVED_MFR2_2510 ++{0x2510, 0x2201}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x30D0}, // RESERVED_MFR2_2510 ++{0x2510, 0xA184}, // RESERVED_MFR2_2510 ++{0x2510, 0xB800}, // RESERVED_MFR2_2510 ++{0x2510, 0x811F}, // RESERVED_MFR2_2510 ++{0x2510, 0xD806}, // RESERVED_MFR2_2510 ++{0x2510, 0x9810}, // RESERVED_MFR2_2510 ++{0x2510, 0x32C4}, // RESERVED_MFR2_2510 ++{0x2510, 0x3041}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0xD816}, // RESERVED_MFR2_2510 ++{0x2510, 0xD814}, // RESERVED_MFR2_2510 ++{0x2510, 0x3141}, // RESERVED_MFR2_2510 ++{0x2510, 0x3042}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x3142}, // RESERVED_MFR2_2510 ++{0x2510, 0x3042}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x3281}, // RESERVED_MFR2_2510 ++{0x2510, 0x3042}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x3290}, // RESERVED_MFR2_2510 ++{0x2510, 0x3042}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x3110}, // RESERVED_MFR2_2510 ++{0x2510, 0x3042}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x3120}, // RESERVED_MFR2_2510 ++{0x2510, 0x3042}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x3282}, // RESERVED_MFR2_2510 ++{0x2510, 0x3042}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x32A0}, // RESERVED_MFR2_2510 ++{0x2510, 0x3042}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x813F}, // RESERVED_MFR2_2510 ++{0x2510, 0x881B}, // RESERVED_MFR2_2510 ++{0x2510, 0x897F}, // RESERVED_MFR2_2510 ++{0x2510, 0x2440}, // RESERVED_MFR2_2510 ++{0x2510, 0xB095}, // RESERVED_MFR2_2510 ++{0x2510, 0xF110}, // RESERVED_MFR2_2510 ++{0x2510, 0xF864}, // RESERVED_MFR2_2510 ++{0x2510, 0xF90D}, // RESERVED_MFR2_2510 ++{0x2510, 0x32C2}, // RESERVED_MFR2_2510 ++{0x2510, 0x30A0}, // RESERVED_MFR2_2510 ++{0x2510, 0x3090}, // RESERVED_MFR2_2510 ++{0x2510, 0x3088}, // RESERVED_MFR2_2510 ++{0x2510, 0x2443}, // RESERVED_MFR2_2510 ++{0x2510, 0x811B}, // RESERVED_MFR2_2510 ++{0x2510, 0xD870}, // RESERVED_MFR2_2510 ++{0x2510, 0x3001}, // RESERVED_MFR2_2510 ++{0x2510, 0x2202}, // RESERVED_MFR2_2510 ++{0x2510, 0x2442}, // RESERVED_MFR2_2510 ++{0x2510, 0x3220}, // RESERVED_MFR2_2510 ++{0x2510, 0x2004}, // RESERVED_MFR2_2510 ++{0x2510, 0x885B}, // RESERVED_MFR2_2510 ++{0x2510, 0x9800}, // RESERVED_MFR2_2510 ++{0x2510, 0x2441}, // RESERVED_MFR2_2510 ++{0x2510, 0x30C2}, // RESERVED_MFR2_2510 ++{0x2510, 0x801B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0x881B}, // RESERVED_MFR2_2510 ++{0x2510, 0x2000}, // RESERVED_MFR2_2510 ++{0x2510, 0xD850}, // RESERVED_MFR2_2510 ++{0x2510, 0x2006}, // RESERVED_MFR2_2510 ++{0x2510, 0xD852}, // RESERVED_MFR2_2510 ++{0x2510, 0x200A}, // RESERVED_MFR2_2510 ++{0x2510, 0x8018}, // RESERVED_MFR2_2510 ++{0x2510, 0xA9A0}, // RESERVED_MFR2_2510 ++{0x2510, 0xB094}, // RESERVED_MFR2_2510 ++{0x2510, 0x2200}, // RESERVED_MFR2_2510 ++{0x2510, 0xD812}, // RESERVED_MFR2_2510 ++{0x2510, 0x8803}, // RESERVED_MFR2_2510 ++{0x2510, 0xA1C4}, // RESERVED_MFR2_2510 ++{0x2510, 0x3048}, // RESERVED_MFR2_2510 ++{0x2510, 0xB800}, // RESERVED_MFR2_2510 ++{0x2510, 0xA004}, // RESERVED_MFR2_2510 ++{0x2510, 0xD810}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0xC166}, // RESERVED_MFR2_2510 ++{0x2510, 0x2400}, // RESERVED_MFR2_2510 ++{0x2510, 0xC066}, // RESERVED_MFR2_2510 ++{0x2510, 0x2406}, // RESERVED_MFR2_2510 ++{0x2510, 0x2416}, // RESERVED_MFR2_2510 ++{0x2510, 0xC022}, // RESERVED_MFR2_2510 ++{0x2510, 0x2402}, // RESERVED_MFR2_2510 ++{0x2510, 0x2405}, // RESERVED_MFR2_2510 ++{0x2510, 0xC023}, // RESERVED_MFR2_2510 ++{0x2510, 0x2400}, // RESERVED_MFR2_2510 ++{0x2510, 0x2403}, // RESERVED_MFR2_2510 ++{0x2510, 0xC003}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x7FFF}, // RESERVED_MFR2_2510 ++{0x2510, 0x342A}, // RESERVED_MFR2_2510 ++{0x2510, 0x3618}, // RESERVED_MFR2_2510 ++{0x301E, 0x80A8}, // DATA_PEDESTAL_ ++{0x30FE, 0x00A8}, // RESERVED_MFR_30FE ++{0x37B4, 0x3F58}, // RESERVED_MFR_37B4 ++{0x3064, 0x0180}, // SMIA_TEST ++{0x3352, 0x2000}, // MIPI_DT_VC_CONFIG ++{0x3E94, 0x2006}, // RESERVED_MFR_3E94 ++{0x3E6E, 0xE200}, // TEMPVSENS1_TMG_CTRL_K0 ++{0x3E98, 0x1000}, // TEMPVSENS1_EN_CTRL ++{0x3F92, 0x4C00}, // TEMPVSENS1_TMG_CTRL ++{0x30B8, 0x000B}, // TEMPSENS1_CTRL_REG + {0x30B8, 0x0003}, // TEMPSENS1_CTRL_REG +-{0x3F92, 0x4D00}, // TEMPVSENS1_TMG_CTRL +-{0x3F96, 0xFFFE}, //003E // TEMPVSENS1_FLAG_CTRL +-{0x3EE0, 0x0700}, //0000 // TEMPVSENS1_FLAG_CTRL_EXT +-{0x3E98, 0x4000}, // TEMPVSENS1_EN_CTRL +- +-//analog},1x +-{0x3022, 0x01}, // GROUPED_PARAMETER_HOLD_ +-{0x3D34, 0x0562}, // T2_STR_DEC_TH +-{0x3D36, 0x0562}, // T2_END_DEC_TH +-{0x563A, 0x0011}, // OCL_T1_GAIN_ +-{0x3E18, 0x0EEE}, // LFM2_T1_E2_GAIN_CTRL +-{0x3366, 0x1121}, // ANALOG_GAIN +-{0x3364, 700}, //2D0 // DCG_TRIM ++{0x3112, 0x71E7}, // RESERVED_MFR_3112 ++{0x31D0, 0x0001}, // COMPANDING ++{0x3082, 0x0004}, // OPERATION_MODE_CTRL ++{0x30BA, 0x1101}, // DIGITAL_CTRL ++{0x31AC, 0x180C}, // DATA_FORMAT_BITS ++{0x31AE, 0x0204}, // SERIAL_FORMAT ++{0x34D4, 0x0001}, // DISCRETE_FINE_INTEGRATION ++{0x3C08, 0x0104}, // RESERVED_MFR_3C08 ++{0x3C06, 0x0C3C}, // RESERVED_MFR_3C06 ++{0x3C06, 0x0C3C}, // RESERVED_MFR_3C06 ++{0x3D28, 0xDAC0}, // RESERVED_MFR_3D28 ++{0x3D2A, 0xDAC0}, // RESERVED_MFR_3D2A ++{0x3290, 0xE86C}, // RESERVED_MFR_3290 ++{0x3292, 0xE86C}, // RESERVED_MFR_3292 ++{0x3294, 0xE86C}, // RESERVED_MFR_3294 ++{0x3296, 0xE86C}, // RESERVED_MFR_3296 ++{0x3298, 0xF618}, // RESERVED_MFR_3298 ++{0x329A, 0xF618}, // RESERVED_MFR_329A ++{0x329C, 0xF618}, // RESERVED_MFR_329C ++{0x329E, 0xF618}, // RESERVED_MFR_329E ++{0x31AC, 0x180C}, // DATA_FORMAT_BITS ++{0x31D0, 0x0001}, // COMPANDING ++{0x33DA, 0x0000}, // OC_LUT_CONTROL ++{0x33C0, 0x2000}, // OC_LUT_00 ++{0x33C2, 0x4000}, // OC_LUT_01 ++{0x33C4, 0x8000}, // OC_LUT_02 ++{0x33C6, 0x8200}, // OC_LUT_03 ++{0x33C8, 0x8600}, // OC_LUT_04 ++{0x33CA, 0x8E00}, // OC_LUT_05 ++{0x33CC, 0x9E00}, // OC_LUT_06 ++{0x33CE, 0xBE00}, // OC_LUT_07 ++{0x33D0, 0xC200}, // OC_LUT_08 ++{0x33D2, 0xCA00}, // OC_LUT_09 ++{0x33D4, 0xDA00}, // OC_LUT_10 ++{0x33D6, 0xFA00}, // OC_LUT_11 ++{0x33F4, 0xFA00}, // OC_LUT_12 ++{0x33F6, 0xFA00}, // OC_LUT_13 ++{0x33F8, 0xFA00}, // OC_LUT_14 ++{0x33FA, 0xFA00}, // OC_LUT_15 ++{0x300A, 0x047E}, // FRAME_LENGTH_LINES_ ++{0x300C, 0x0A6E}, // LINE_LENGTH_PCK_ ++{0x3362, 0x0001}, // DC_GAIN ++{0x3044, 0x0400}, // DARK_CONTROL ++{0x3238, 0x8446}, // EXPOSURE_RATIO ++{0x3012, 0x0286}, // COARSE_INTEGRATION_TIME_ ++{0x3212, 0x0009}, // COARSE_INTEGRATION_TIME2 ++{0x563A, 0x0111}, // RESERVED_MFR_563A ++{0x3366, 0x1131}, // ANALOG_GAIN + {0x336A, 0x0080}, // ANALOG_GAIN2 +-{0x3E02, 0x09C4}, // LFM2_T1_E1_A +-{0x3022, 0x00}, // GROUPED_PARAMETER_HOLD_ +- +-//updated},pink},reduction},settings +-{0x3D02, 0x6033}, // MEC_CTRL2 +-{0x3534, 0xA284}, // DAC_LD_52_53 +-{0x3546, 0x3601}, // DAC_LD_70_71 +-{0x3518, 0x4444}, // DAC_LD_24_25 +- +-{0x3494, 0x0C0C}, // LFM_TX_PATTERN_CTRL +-{0x34BC, 0x000C}, // LFM_PATTERN_CTRL +-{0x3E02, 0x09C4}, // LFM2_T1_E1_A +- +-//band},mitigation +-{0x3450, 0x00A4}, // LFM_PHASE0_PERIOD +-{0x3452, 0x004F}, // LFM_PHASE1_PERIOD +-{0x3454, 0x004F}, // LFM_PHASE2_PERIOD +-{0x3456, 0x004F}, // LFM_PHASE3_PERIOD +-{0x3458, 0x004F}, // LFM_PHASE4_PERIOD +-{0x345A, 0x004F}, // LFM_PHASE5_PERIOD +-{0x345C, 0x004F}, // LFM_PHASE6_PERIOD +-{0x345E, 0x004F}, // LFM_PHASE7_PERIOD +-{0x3460, 0x004F}, // LFM_PHASE8_PERIOD +-{0x3462, 0x004F}, // LFM_PHASE9_PERIOD +-{0x3464, 0x004F}, // LFM_PHASE10_PERIOD +-{0x3466, 0x004F}, // LFM_PHASE11_PERIOD +-{0x3468, 0x00A4}, // LFM_PHASE12_PERIOD +-{0x346A, 0x004F}, // LFM_PHASE13_PERIOD +-{0x346C, 0x004F}, // LFM_PHASE14_PERIOD +-{0x346E, 0x004F}, // LFM_PHASE15_PERIOD +-{0x3470, 0x004F}, // LFM_PHASE16_PERIOD +-{0x3472, 0x004F}, // LFM_PHASE17_PERIOD +-{0x3474, 0x004F}, // LFM_PHASE18_PERIOD +-{0x3476, 0x004F}, // LFM_PHASE19_PERIOD +-{0x3478, 0x004F}, // LFM_PHASE20_PERIOD +-{0x347A, 0x004F}, // LFM_PHASE21_PERIOD +-{0x347C, 0x004F}, // LFM_PHASE22_PERIOD +-{0x347E, 0x004F}, // LFM_PHASE23_PERIOD +-{0x3480, 0x004F}, // LFM_PHASE24_PERIOD +-{0x3482, 0x004F}, // LFM_PHASE25_PERIOD +-{0x3484, 0x00A4}, // LFM_PHASE26_PERIOD +-{0x3486, 0x004F}, // LFM_PHASE27_PERIOD +-{0x3488, 0x00A4}, // LFM_PHASE28_PERIOD +-{0x348A, 0x004F}, // LFM_PHASE29_PERIOD +-{0x348C, 0x004F}, // LFM_PHASE30_PERIOD +-{0x348E, 0x004F}, // LFM_PHASE31_PERIOD +-{0x3490, 0x004F}, // LFM_PHASE32_PERIOD +- +-{0x3496, 0xDF00}, // LFM_CONTROL +-{0x349A, 0x0001}, // LFM_TX_SHIFT_CLK_CTRL +-{0x349C, 0x0003}, // LFM_TX_DATA_CLK_CTRL +-{0x349E, 0x0002}, // LFM_TX_GOTO_LOROW_CLK_CTRL +-{0x34A0, 0x003E}, // LFM_TX_DATA_CLR_CLK_CTRL +-{0x34A2, 0x0012}, // LFM_BST_TX_CLK_CTRL +-{0x34A4, 0x003D}, // LFM_BST_TXLO_CLK_CTRL +-{0x34A6, 0x004E}, // LFM_BST_TXLOROW_EN_CLK_CTRL +-{0x34A8, 0x0044}, // LFM_AB_SHIFT_CLK_CTRL +-{0x34AA, 0x0001}, // LFM_BST_AB_CLK_CTRL +-{0x34AC, 0x0043}, // LFM_BST_ABLO_CLK_CTRL +-{0x34AE, 0x004E}, // LFM_BST_ABLOROW_EN_CLK_CTRL +-{0x34B0, 0x0002}, // LFM_DCG_DATA_CLK_CTRL +-{0x34B2, 0x003F}, // LFM_DCG_DATA_CLR_CLK_CTRL +-{0x34B4, 0x004E}, // LFM_BST_DCGLOROW_EN_CLK_CTRL +-{0x34B6, 0x0012}, // LFM_BST_DCG_CLK_CTRL +- +-{0x350E, 0x2189}, // DAC_LD_14_15 +-//pixel recommended settings Feb5 +-{0x352C, 0x8146}, // DAC_LD_44_45 +-{0x3526, 0x9812}, // DAC_LD_38_39 +-{0x3528, 0x99C0}, // DAC_LD_40_41 +-{0x352E, 0x0B71}, // DAC_LD_46_47 +-{0x352A, 0x0170}, // DAC_LD_42_43 +-{0x3530, 0x07F0}, // DAC_LD_48_49 +-{0x3514, 0xEEEE}, // DAC_LD_20_21 +-{0x3578, 0xEEEE}, // DAC_LD_120_121 +-{0x3518, 0x3333}, // DAC_LD_24_25 +-{0x3540, 0x0033}, // DAC_LD_64_65 +-{0x3542, 0x33F0}, // DAC_LD_66_67 +- +-//CFPN},IMPROVEMENT +-{0x3568, 0x04BC}, +-{0x356A, 0x81AA}, +-{0x356E, 0x15E6}, +- +-//E1-E2 Transision Noise Improvement +-{0x3E10, 0x000A}, // LFM2_T1_E2_OFFSET +-{0x3430, 0x070C}, // BST_MULTISHOT_CLK_0 +-{0x3432, 0x008C}, // BST_MULTISHOT_CLK_1 +-{0x37B2, 0x1F40}, // DBLC_OUT_CLIP_MAX +- +-{0x3550, 0xFF6C}, // DAC_LD_80_81 +-{0x3546, 0x4201}, // DAC_LD_70_71 +- +-//T2 white balance gains ++{0x3E18, 0x0F68}, // RESERVED_MFR_3E18 ++{0x3E02, 0x0B61}, // RESERVED_MFR_3E02 ++{0x562A, 0x0361}, // RESERVED_MFR_562A ++{0x3E10, 0x0002}, // RESERVED_MFR_3E10 ++{0x3364, 0x072E}, // RESERVED_MFR_3364 ++{0x37B0, 0x8080}, // RESERVED_MFR_37B0 ++{0x37B0, 0x8080}, // RESERVED_MFR_37B0 ++{0x37B6, 0x8080}, // DBLC_OUT_PIX_GAIN_GB_B ++{0x37B6, 0x8080}, // DBLC_OUT_PIX_GAIN_GB_B ++{0x3D28, 0xDAC0}, // RESERVED_MFR_3D28 ++{0x3D2A, 0xDAC0}, // RESERVED_MFR_3D2A ++{0x3D34, 0x09C4}, // RESERVED_MFR_3D34 ++{0x3D36, 0x0DAC}, // RESERVED_MFR_3D36 ++{0x3364, 0x072E}, // RESERVED_MFR_3364 ++{0x3E14, 0x003F}, // RESERVED_MFR_3E14 ++{0x3568, 0x0228}, // RESERVED_MFR_3568 ++{0x3548, 0x2323}, // RESERVED_MFR_3548 ++{0x354C, 0x3219}, // RESERVED_MFR_354C ++{0x3040, 0xC005}, // READ_MODE + {0x30B0, 0x0880}, // DIGITAL_TEST +-{0x3300, 0x0030}, // GREEN1_GAIN2_ +-{0x3302, 0x0080}, // BLUE_GAIN2_ +-{0x3304, 0x0070}, // RED_GAIN2_ +-{0x3306, 0x0030}, // GREEN2_GAIN2_ +-{0x3056, 0x002F}, // GREEN1_GAIN +-{0x3058, 0x0080}, // BLUE_GAIN +-{0x305A, 0x0072}, // RED_GAIN +-{0x305C, 0x002F}, // GREEN2_GAIN +- ++{0x3056, 0x0080}, // GREEN1_GAIN ++{0x3058, 0x016E}, // BLUE_GAIN ++{0x305A, 0x011D}, // RED_GAIN ++{0x305C, 0x0080}, // GREEN2_GAIN ++{0x3300, 0x0080}, // GREEN1_GAIN2_ ++{0x3302, 0x0162}, // BLUE_GAIN2_ ++{0x3304, 0x0121}, // RED_GAIN2_ ++{0x3306, 0x0080}, // GREEN2_GAIN2_ + {0x301A, 0x005C}, // RESET_REGISTER ++{AR0323_DELAY, 33}, // Wait 33ms ++{0x301A, 0x0058}, // RESET_REGISTER ++{AR0323_DELAY, 33}, // Wait 33ms ++{0x3044, 0x3400}, // DARK_CONTROL ++{0x3112, 0x7FE7}, // RESERVED_MFR_3112 ++{0x3352, 0x2000}, // MIPI_DT_VC_CONFIG ++{0x33E0, 0x0F80}, // TEST_ASIL_ROWS ++{0x3E3E, 0x000C}, // RESERVED_MFR_3E3E ++{0x3562, 0x0C48}, // RESERVED_MFR_3562 ++{0x33E6, 0x3220}, // RESERVED_MFR_33E6 ++{0x33EC, 0xEFDC}, // RESERVED_MFR_33EC ++{0x3558, 0x7F3B}, // RESERVED_MFR_3558 ++{0x3554, 0x0101}, // RESERVED_MFR_3554 ++{0x357C, 0x3E00}, // RESERVED_MFR_357C ++{0x3358, 0x0000}, // CRC_DTR_CALC_CHECKSUM_LOW ++{0x335C, 0x0000}, // CRC_FR_DTR_CALC_CHECKSUM_HIGH ++{0x3388, 0x0009}, // TPG_CONTROL ++{0x338A, 0x0000}, // TPG_COLOR0_GR1_HI ++{0x338C, 0x000A}, // TPG_COLOR0_GR1_LO ++{0x338E, 0x0000}, // TPG_COLOR0_RED_HI ++{0x3390, 0x000B}, // TPG_COLOR0_RED_LO ++{0x3392, 0x0000}, // TPG_COLOR0_BLU_HI ++{0x3394, 0x000C}, // TPG_COLOR0_BLU_LO ++{0x3396, 0x0000}, // TPG_COLOR0_GR2_HI ++{0x3398, 0x000D}, // TPG_COLOR0_GR2_LO ++{0x339A, 0x0000}, // TPG_COLOR1_GR1_HI ++{0x339C, 0x0010}, // TPG_COLOR1_GR1_LO ++{0x339E, 0x0000}, // TPG_COLOR1_RED_HI ++{0x33A0, 0x0020}, // TPG_COLOR1_RED_LO ++{0x33A2, 0x0000}, // TPG_COLOR1_BLU_HI ++{0x33A4, 0x0030}, // TPG_COLOR1_BLU_LO ++{0x33A6, 0x0000}, // TPG_COLOR1_GR2_HI ++{0x33A8, 0x0040}, // TPG_COLOR1_GR2_LO ++{0x33AA, 0x1001}, // TPG_STDPAT_REGION1 ++{0x33AC, 0x1001}, // TPG_STDPAT_REGION2 ++{0x33BC, 0x0000}, // TPG_HDR_RATIOS ++{0x3E64, 0x0000}, // TPG_PD0_PD1_RATIOS ++{0x3E6A, 0x0000}, // RESERVED_MFR_3E6A ++{0x3180, 0x0000}, // RESERVED_MFR_3180 ++{0x3F70, 0x06BA}, // PROCESS_DTR ++{0x3D08, 0x0000}, // DTR_BOUND_X0 ++{0x3D0A, 0x0000}, // DTR_BOUND_X1 ++{0x3D0C, 0x0000}, // DTR_BOUND_Y0 ++{0x3D0E, 0x0000}, // DTR_BOUND_Y1 ++{0x3092, 0x000C}, // RESERVED_MFR_3092 ++{0x3F64, 0x2000}, // ASIL_CHECK_ENABLES_02 ++{0x3F6C, 0x2000}, // ASIL_PIN_ENABLES_02 ++{0x3356, 0xBC39}, // CRC_DTR_WRT_CHECKSUM_LOW ++{0x335E, 0x0500}, // CRC_FR_DTR_WRT_CHECKSUM_HIGH ++{0x31F8, 0x0001}, // MIPI_CONFIG_2 ++{0x31FA, 0x1212}, // MIPI_F1_F2_ADT ++{0x31FC, 0x1212}, // MIPI_F3_F4_ADT ++{0x301A, 0x005C}, // RESET_REGISTER ++ ++{AR0323_DELAY, 33}, // Wait 33ms + }; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0155-AR0143-add-original-ONSEMI-setup.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0155-AR0143-add-original-ONSEMI-setup.patch new file mode 100644 index 00000000..cae8f645 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0155-AR0143-add-original-ONSEMI-setup.patch @@ -0,0 +1,1552 @@ +From 5edb91334b70ed3df3466830b94f3bbe9f93e48d Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Tue, 19 Mar 2019 13:42:28 +0300 +Subject: [PATCH 104/122] AR0143: add original ONSEMI setup + +This adds ONSEMI rev1 setup + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ar0143.c | 2 +- + drivers/media/i2c/soc_camera/ar0143.h | 517 +------------------------- + drivers/media/i2c/soc_camera/ar0143_custom.h | 526 +++++++++++++++++++++++++++ + drivers/media/i2c/soc_camera/ar0143_rev1.h | 456 +++++++++++++++++++++++ + 4 files changed, 985 insertions(+), 516 deletions(-) + create mode 100644 drivers/media/i2c/soc_camera/ar0143_custom.h + create mode 100644 drivers/media/i2c/soc_camera/ar0143_rev1.h + +diff --git a/drivers/media/i2c/soc_camera/ar0143.c b/drivers/media/i2c/soc_camera/ar0143.c +index b51dcfc..65dc4fb 100644 +--- a/drivers/media/i2c/soc_camera/ar0143.c ++++ b/drivers/media/i2c/soc_camera/ar0143.c +@@ -448,7 +448,7 @@ static int ar0143_initialize(struct i2c_client *client) + } + + /* Program wizard registers */ +- ar0143_set_regs(client, ar0143_regs_wizard, ARRAY_SIZE(ar0143_regs_wizard)); ++ ar0143_set_regs(client, ar0143_regs_wizard_rev1, ARRAY_SIZE(ar0143_regs_wizard_rev1)); + + tmp_addr = client->addr; + if (priv->max9271_addr) { +diff --git a/drivers/media/i2c/soc_camera/ar0143.h b/drivers/media/i2c/soc_camera/ar0143.h +index 774a438..042dd50 100644 +--- a/drivers/media/i2c/soc_camera/ar0143.h ++++ b/drivers/media/i2c/soc_camera/ar0143.h +@@ -32,518 +32,5 @@ struct ar0143_reg { + u16 val; + }; + +-static const struct ar0143_reg ar0143_regs_wizard[] = { +-{0x301A, 0x0001}, // reset +-{AR0143_DELAY, 100}, +-{0x301A, 0x10D8}, // Stream off and setup parallel +-{0x3070, 0x0001}, +-{0x3070, 0x0000}, // 1: Solid color test pattern, +- // 2: Full color bar test pattern, +- // 3: Fade to grey color bar test pattern, +- //256: Walking 1 test pattern (12 bit) +-#ifdef AR0143_DISPLAY_PATTERN_FIXED +-{0x3070, 0x0001}, +-#endif +-{0x3072, 0x0fff}, // R +-{0x3074, 0x0fff}, // G(GR row) +-{0x3076, 0x0fff}, // B +-{0x3078, 0x0fff}, // G(GB row) +-#ifdef AR0143_DISPLAY_PATTERN_COLOR_BAR +-{0x3070, 0x0002}, +-#endif +-{AR0143_DELAY, 250}, +-// start demo init +-{0x3100, 0x4000}, // DLO_CONTROL0 +-{0x3102, 0x6060}, // RESERVED_MFR_3102 +-{0x3104, 0x6060}, // RESERVED_MFR_3104 +-{0x3106, 0x6060}, // RESERVED_MFR_3106 +-{0x3108, 0x0F9F}, // RESERVED_MFR_3108 +-{0x3280, 0x0FA0}, // T1_BARRIER_C0 +-{0x3282, 0x0FA0}, // T1_BARRIER_C1 +-{0x3284, 0x0FA0}, // T1_BARRIER_C2 +-{0x3286, 0x0FA0}, // T1_BARRIER_C3 +-{0x3288, 0x0FA0}, // T2_BARRIER_C0 +-{0x328A, 0x0FA0}, // T2_BARRIER_C1 +-{0x328C, 0x0FA0}, // T2_BARRIER_C2 +-{0x328E, 0x0FA0}, // T2_BARRIER_C3 +-{0x3290, 0x0FA0}, // T3_BARRIER_C0 +-{0x3292, 0x0FA0}, // T3_BARRIER_C1 +-{0x3294, 0x0FA0}, // T3_BARRIER_C2 +-{0x3296, 0x0FA0}, // T3_BARRIER_C3 +-{0x3298, 0x0FA0}, // T4_BARRIER_C0 +-{0x329A, 0x0FA0}, // T4_BARRIER_C1 +-{0x329C, 0x0FA0}, // T4_BARRIER_C2 +-{0x329E, 0x0FA0}, // T4_BARRIER_C3 +-{0x3110, 0x0011}, // HDR_CONTROL0 +-{0x3112, 0x7FE7}, // RESERVED_MFR_3112 +-{0x3114, 0x0000}, // RESERVED_MFR_3114 +-{0x3116, 0xC000}, // HDR_CONTROL3 +-{0x3120, 0x0BA0}, // HDR_SC_CONTROL0 +-{0x3122, 0x0FA0}, // HDR_SC_CONTROL1 +-{0x3124, 0x00B4}, // HDR_MD_CONTROL0 +-{0x3126, 0x0030}, // HDR_MD_CONTROL1 +-{0x3128, 0x6100}, // RESERVED_MFR_3128 +-{0x3506, 0x3333}, // RESERVED_MFR_3506 +-{0x3508, 0x3333}, // RESERVED_MFR_3508 +-{0x350A, 0x3333}, // RESERVED_MFR_350A +-{0x350C, 0x035F}, // RESERVED_MFR_350C +-{0x350E, 0xEF14}, // RESERVED_MFR_350E +-{0x3086, 0x0600}, // RESERVED_MFR_3086 +-{0x3C00, 0xDD67}, // RESERVED_MFR_3C00 +-{0x3092, 0x1C24}, // RESERVED_MFR_3092 +-{0x3096, 0x147E}, // RESERVED_MFR_3096 +-{0x3750, 0x147E}, // RESERVED_MFR_3750 +-{0x30B0, 0x0800}, // DIGITAL_TEST +-{0x30FE, 0x0000}, // NOISE_PEDESTAL +-{0x32D0, 0x3A02}, // RESERVED_MFR_32D0 +-{0x32D6, 0x3C04}, // RESERVED_MFR_32D6 +-{0x3C0C, 0x0516}, // DELAY_BUFFER_LLPCK_RD_WR_OVERLAP +-{0x3F94, 0x483e}, // TEMPVSENS0_FLAG_CTRL +-{0x3F96, 0xFFFE}, // TEMPVSENS1_FLAG_CTRL +-{0x3088, 0x6680}, // LFM_CTRL +-{0x33E2, 0x0000}, // SAMPLE_CTRL +-{0x3366, 0x7777}, // ANALOG_GAIN +-{0x3056, 0x0080}, // GREEN1_GAIN +-{0x305C, 0x0080}, // GREEN2_GAIN +-{0x3058, 0x0080}, // BLUE_GAIN +-{0x305A, 0x0080}, // RED_GAIN +-{0x306E, 0x9010}, // DATAPATH_SELECT +-{0x3044, 0x0400}, // DARK_CONTROL +-{0x30BA, 0x01E2}, // DIGITAL_CTRL +-{0x32EA, 0x3C0E}, // RESERVED_MFR_32EA +-{0x3362, 0x0000}, // DC_GAIN +-{0x3364, 0x005B}, // RESERVED_MFR_3364 +-{0x3370, 0x0131}, // DBLC_CONTROL +-{0x3372, 0x700F}, // DBLC_FS0_CONTROL +-{0x3386, 0x0000}, // DBLC_PEDESTAL +-{0x3C04, 0x0E80}, // RESERVED_MFR_3C04 +-{0x30B4, 0x01C7}, // TEMPSENS0_CTRL_REG +-{0x30B8, 0x0007}, // TEMPSENS1_CTRL_REG +-{0x3F90, 0x8D03}, // TEMPVSENS0_TMG_CTRL +-{0x3F92, 0x0D03}, // TEMPVSENS1_TMG_CTRL +-{0x3502, 0x0808}, // RESERVED_MFR_3502 +-{0x3566, 0x1D28}, // RESERVED_MFR_3566 +-{0x3518, 0x1FFE}, // RESERVED_MFR_3518 +-{0x3526, 0x0F00}, // RESERVED_MFR_3526 +-{0x3528, 0xDDDD}, // RESERVED_MFR_3528 +-{0x352A, 0x089F}, // RESERVED_MFR_352A +-{0x352E, 0x0011}, // RESERVED_MFR_352E +-{0x3530, 0x4400}, // RESERVED_MFR_3530 +-{0x3536, 0xFF07}, // RESERVED_MFR_3536 +-{0x3538, 0xFFFF}, // RESERVED_MFR_3538 +-{0x353A, 0x9000}, // RESERVED_MFR_353A +-{0x353C, 0x3F00}, // RESERVED_MFR_353C +-{0x32EC, 0x72A1}, // RESERVED_MFR_32EC +-{0x3540, 0xC637}, // RESERVED_MFR_3540 +-{0x3542, 0x464B}, // RESERVED_MFR_3542 +-{0x3544, 0x4B50}, // RESERVED_MFR_3544 +-{0x3546, 0x545A}, // RESERVED_MFR_3546 +-{0x3548, 0x5A00}, // RESERVED_MFR_3548 +-{0x354A, 0x007F}, // RESERVED_MFR_354A +-{0x3556, 0x101F}, // RESERVED_MFR_3556 +-{0x3566, 0x3328}, // RESERVED_MFR_3566 +-{0x337A, 0x0CA3}, // DBLC_SCALE0 +-{0x3372, 0x710F}, // DBLC_FS0_CONTROL +-{0x3520, 0x4688}, // RESERVED_MFR_3520 +-{0x3522, 0x8840}, // RESERVED_MFR_3522 +-{0x3524, 0x4046}, // RESERVED_MFR_3524 +-{0x352C, 0x4646}, // RESERVED_MFR_352C +-{0x2512, 0x8000}, // SEQ_CTRL_PORT +-{0x2510, 0x0903}, // SEQ_DATA_PORT +-{0x2510, 0x3350}, // SEQ_DATA_PORT +-{0x2510, 0x2004}, // SEQ_DATA_PORT +-{0x2510, 0x1420}, // SEQ_DATA_PORT +-{0x2510, 0x1578}, // SEQ_DATA_PORT +-{0x2510, 0x087B}, // SEQ_DATA_PORT +-{0x2510, 0x24FF}, // SEQ_DATA_PORT +-{0x2510, 0x24FF}, // SEQ_DATA_PORT +-{0x2510, 0x24EA}, // SEQ_DATA_PORT +-{0x2510, 0x2410}, // SEQ_DATA_PORT +-{0x2510, 0x2224}, // SEQ_DATA_PORT +-{0x2510, 0x1015}, // SEQ_DATA_PORT +-{0x2510, 0x5813}, // SEQ_DATA_PORT +-{0x2510, 0x0214}, // SEQ_DATA_PORT +-{0x2510, 0x0024}, // SEQ_DATA_PORT +-{0x2510, 0xFF24}, // SEQ_DATA_PORT +-{0x2510, 0xFF24}, // SEQ_DATA_PORT +-{0x2510, 0xEA23}, // SEQ_DATA_PORT +-{0x2510, 0x2464}, // SEQ_DATA_PORT +-{0x2510, 0x7A24}, // SEQ_DATA_PORT +-{0x2510, 0x0405}, // SEQ_DATA_PORT +-{0x2510, 0x2C40}, // SEQ_DATA_PORT +-{0x2510, 0x0AFF}, // SEQ_DATA_PORT +-{0x2510, 0x0ACC}, // SEQ_DATA_PORT +-{0x2510, 0x0A07}, // SEQ_DATA_PORT +-{0x2510, 0x3851}, // SEQ_DATA_PORT +-{0x2510, 0x1440}, // SEQ_DATA_PORT +-{0x2510, 0x0004}, // SEQ_DATA_PORT +-{0x2510, 0x0801}, // SEQ_DATA_PORT +-{0x2510, 0x0408}, // SEQ_DATA_PORT +-{0x2510, 0x1180}, // SEQ_DATA_PORT +-{0x2510, 0x2652}, // SEQ_DATA_PORT +-{0x2510, 0x0815}, // SEQ_DATA_PORT +-{0x2510, 0x1813}, // SEQ_DATA_PORT +-{0x2510, 0xC810}, // SEQ_DATA_PORT +-{0x2510, 0x0210}, // SEQ_DATA_PORT +-{0x2510, 0x1611}, // SEQ_DATA_PORT +-{0x2510, 0x8111}, // SEQ_DATA_PORT +-{0x2510, 0x8910}, // SEQ_DATA_PORT +-{0x2510, 0x5612}, // SEQ_DATA_PORT +-{0x2510, 0x1009}, // SEQ_DATA_PORT +-{0x2510, 0x020D}, // SEQ_DATA_PORT +-{0x2510, 0x0905}, // SEQ_DATA_PORT +-{0x2510, 0x1588}, // SEQ_DATA_PORT +-{0x2510, 0x1388}, // SEQ_DATA_PORT +-{0x2510, 0x0938}, // SEQ_DATA_PORT +-{0x2510, 0x1199}, // SEQ_DATA_PORT +-{0x2510, 0x11D9}, // SEQ_DATA_PORT +-{0x2510, 0x091E}, // SEQ_DATA_PORT +-{0x2510, 0x1214}, // SEQ_DATA_PORT +-{0x2510, 0x10D6}, // SEQ_DATA_PORT +-{0x2510, 0x0901}, // SEQ_DATA_PORT +-{0x2510, 0x1210}, // SEQ_DATA_PORT +-{0x2510, 0x1212}, // SEQ_DATA_PORT +-{0x2510, 0x1210}, // SEQ_DATA_PORT +-{0x2510, 0x11DD}, // SEQ_DATA_PORT +-{0x2510, 0x11D9}, // SEQ_DATA_PORT +-{0x2510, 0x0901}, // SEQ_DATA_PORT +-{0x2510, 0x1441}, // SEQ_DATA_PORT +-{0x2510, 0x0904}, // SEQ_DATA_PORT +-{0x2510, 0x1056}, // SEQ_DATA_PORT +-{0x2510, 0x0811}, // SEQ_DATA_PORT +-{0x2510, 0xDB09}, // SEQ_DATA_PORT +-{0x2510, 0x0311}, // SEQ_DATA_PORT +-{0x2510, 0xFB11}, // SEQ_DATA_PORT +-{0x2510, 0xBB12}, // SEQ_DATA_PORT +-{0x2510, 0x1A12}, // SEQ_DATA_PORT +-{0x2510, 0x1008}, // SEQ_DATA_PORT +-{0x2510, 0x1250}, // SEQ_DATA_PORT +-{0x2510, 0x1076}, // SEQ_DATA_PORT +-{0x2510, 0x10E6}, // SEQ_DATA_PORT +-{0x2510, 0x1461}, // SEQ_DATA_PORT +-{0x2510, 0x0906}, // SEQ_DATA_PORT +-{0x2510, 0x1240}, // SEQ_DATA_PORT +-{0x2510, 0x1260}, // SEQ_DATA_PORT +-{0x2510, 0x091C}, // SEQ_DATA_PORT +-{0x2510, 0x1460}, // SEQ_DATA_PORT +-{0x2510, 0x090C}, // SEQ_DATA_PORT +-{0x2510, 0x0B09}, // SEQ_DATA_PORT +-{0x2510, 0x0515}, // SEQ_DATA_PORT +-{0x2510, 0xC813}, // SEQ_DATA_PORT +-{0x2510, 0xC808}, // SEQ_DATA_PORT +-{0x2510, 0x1066}, // SEQ_DATA_PORT +-{0x2510, 0x090B}, // SEQ_DATA_PORT +-{0x2510, 0x1588}, // SEQ_DATA_PORT +-{0x2510, 0x1388}, // SEQ_DATA_PORT +-{0x2510, 0x0913}, // SEQ_DATA_PORT +-{0x2510, 0x0C14}, // SEQ_DATA_PORT +-{0x2510, 0x4009}, // SEQ_DATA_PORT +-{0x2510, 0x0310}, // SEQ_DATA_PORT +-{0x2510, 0xE611}, // SEQ_DATA_PORT +-{0x2510, 0xFB12}, // SEQ_DATA_PORT +-{0x2510, 0x6212}, // SEQ_DATA_PORT +-{0x2510, 0x6011}, // SEQ_DATA_PORT +-{0x2510, 0xFF11}, // SEQ_DATA_PORT +-{0x2510, 0xFB14}, // SEQ_DATA_PORT +-{0x2510, 0x4109}, // SEQ_DATA_PORT +-{0x2510, 0x0210}, // SEQ_DATA_PORT +-{0x2510, 0x6609}, // SEQ_DATA_PORT +-{0x2510, 0x1211}, // SEQ_DATA_PORT +-{0x2510, 0xBB12}, // SEQ_DATA_PORT +-{0x2510, 0x6312}, // SEQ_DATA_PORT +-{0x2510, 0x6014}, // SEQ_DATA_PORT +-{0x2510, 0x0015}, // SEQ_DATA_PORT +-{0x2510, 0x1811}, // SEQ_DATA_PORT +-{0x2510, 0xB812}, // SEQ_DATA_PORT +-{0x2510, 0xA012}, // SEQ_DATA_PORT +-{0x2510, 0x0010}, // SEQ_DATA_PORT +-{0x2510, 0x2610}, // SEQ_DATA_PORT +-{0x2510, 0x0013}, // SEQ_DATA_PORT +-{0x2510, 0x0011}, // SEQ_DATA_PORT +-{0x2510, 0x8030}, // SEQ_DATA_PORT +-{0x2510, 0x5342}, // SEQ_DATA_PORT +-{0x2510, 0x1100}, // SEQ_DATA_PORT +-{0x2510, 0x1002}, // SEQ_DATA_PORT +-{0x2510, 0x1016}, // SEQ_DATA_PORT +-{0x2510, 0x1101}, // SEQ_DATA_PORT +-{0x2510, 0x1109}, // SEQ_DATA_PORT +-{0x2510, 0x1056}, // SEQ_DATA_PORT +-{0x2510, 0x1210}, // SEQ_DATA_PORT +-{0x2510, 0x0D09}, // SEQ_DATA_PORT +-{0x2510, 0x0614}, // SEQ_DATA_PORT +-{0x2510, 0x4009}, // SEQ_DATA_PORT +-{0x2510, 0x0214}, // SEQ_DATA_PORT +-{0x2510, 0x6009}, // SEQ_DATA_PORT +-{0x2510, 0x0615}, // SEQ_DATA_PORT +-{0x2510, 0x4C13}, // SEQ_DATA_PORT +-{0x2510, 0x0C09}, // SEQ_DATA_PORT +-{0x2510, 0x0713}, // SEQ_DATA_PORT +-{0x2510, 0x4C09}, // SEQ_DATA_PORT +-{0x2510, 0x0715}, // SEQ_DATA_PORT +-{0x2510, 0xCC09}, // SEQ_DATA_PORT +-{0x2510, 0x0211}, // SEQ_DATA_PORT +-{0x2510, 0x4908}, // SEQ_DATA_PORT +-{0x2510, 0x1461}, // SEQ_DATA_PORT +-{0x2510, 0x1460}, // SEQ_DATA_PORT +-{0x2510, 0x0903}, // SEQ_DATA_PORT +-{0x2510, 0x1588}, // SEQ_DATA_PORT +-{0x2510, 0x1308}, // SEQ_DATA_PORT +-{0x2510, 0x0905}, // SEQ_DATA_PORT +-{0x2510, 0x1388}, // SEQ_DATA_PORT +-{0x2510, 0x0913}, // SEQ_DATA_PORT +-{0x2510, 0x1159}, // SEQ_DATA_PORT +-{0x2510, 0x090B}, // SEQ_DATA_PORT +-{0x2510, 0x1214}, // SEQ_DATA_PORT +-{0x2510, 0x0901}, // SEQ_DATA_PORT +-{0x2510, 0x1210}, // SEQ_DATA_PORT +-{0x2510, 0x10D6}, // SEQ_DATA_PORT +-{0x2510, 0x1212}, // SEQ_DATA_PORT +-{0x2510, 0x1210}, // SEQ_DATA_PORT +-{0x2510, 0x115D}, // SEQ_DATA_PORT +-{0x2510, 0x1159}, // SEQ_DATA_PORT +-{0x2510, 0x1056}, // SEQ_DATA_PORT +-{0x2510, 0x0903}, // SEQ_DATA_PORT +-{0x2510, 0x115B}, // SEQ_DATA_PORT +-{0x2510, 0x0913}, // SEQ_DATA_PORT +-{0x2510, 0x111B}, // SEQ_DATA_PORT +-{0x2510, 0x113B}, // SEQ_DATA_PORT +-{0x2510, 0x121A}, // SEQ_DATA_PORT +-{0x2510, 0x1210}, // SEQ_DATA_PORT +-{0x2510, 0x0901}, // SEQ_DATA_PORT +-{0x2510, 0x1250}, // SEQ_DATA_PORT +-{0x2510, 0x10F6}, // SEQ_DATA_PORT +-{0x2510, 0x10E6}, // SEQ_DATA_PORT +-{0x2510, 0x0903}, // SEQ_DATA_PORT +-{0x2510, 0x15AB}, // SEQ_DATA_PORT +-{0x2510, 0x13AB}, // SEQ_DATA_PORT +-{0x2510, 0x1240}, // SEQ_DATA_PORT +-{0x2510, 0x1260}, // SEQ_DATA_PORT +-{0x2510, 0x0964}, // SEQ_DATA_PORT +-{0x2510, 0x1588}, // SEQ_DATA_PORT +-{0x2510, 0x0903}, // SEQ_DATA_PORT +-{0x2510, 0x0B08}, // SEQ_DATA_PORT +-{0x2510, 0x0813}, // SEQ_DATA_PORT +-{0x2510, 0x8809}, // SEQ_DATA_PORT +-{0x2510, 0x0715}, // SEQ_DATA_PORT +-{0x2510, 0x8D13}, // SEQ_DATA_PORT +-{0x2510, 0x8D09}, // SEQ_DATA_PORT +-{0x2510, 0x0D15}, // SEQ_DATA_PORT +-{0x2510, 0x8813}, // SEQ_DATA_PORT +-{0x2510, 0x8809}, // SEQ_DATA_PORT +-{0x2510, 0x0310}, // SEQ_DATA_PORT +-{0x2510, 0x6609}, // SEQ_DATA_PORT +-{0x2510, 0x030C}, // SEQ_DATA_PORT +-{0x2510, 0x0914}, // SEQ_DATA_PORT +-{0x2510, 0x10E6}, // SEQ_DATA_PORT +-{0x2510, 0x1262}, // SEQ_DATA_PORT +-{0x2510, 0x1260}, // SEQ_DATA_PORT +-{0x2510, 0x113F}, // SEQ_DATA_PORT +-{0x2510, 0x113B}, // SEQ_DATA_PORT +-{0x2510, 0x1066}, // SEQ_DATA_PORT +-{0x2510, 0x117B}, // SEQ_DATA_PORT +-{0x2510, 0x0927}, // SEQ_DATA_PORT +-{0x2510, 0x113B}, // SEQ_DATA_PORT +-{0x2510, 0x1263}, // SEQ_DATA_PORT +-{0x2510, 0x1260}, // SEQ_DATA_PORT +-{0x2510, 0x1400}, // SEQ_DATA_PORT +-{0x2510, 0x155A}, // SEQ_DATA_PORT +-{0x2510, 0x1138}, // SEQ_DATA_PORT +-{0x2510, 0x12A0}, // SEQ_DATA_PORT +-{0x2510, 0x1200}, // SEQ_DATA_PORT +-{0x2510, 0x1026}, // SEQ_DATA_PORT +-{0x2510, 0x1000}, // SEQ_DATA_PORT +-{0x2510, 0x1342}, // SEQ_DATA_PORT +-{0x2510, 0x1100}, // SEQ_DATA_PORT +-{0x2510, 0x437A}, // SEQ_DATA_PORT +-{0x2510, 0x0605}, // SEQ_DATA_PORT +-{0x2510, 0x0807}, // SEQ_DATA_PORT +-{0x2510, 0x4137}, // SEQ_DATA_PORT +-{0x2510, 0x502C}, // SEQ_DATA_PORT +-{0x2510, 0x2CFE}, // SEQ_DATA_PORT +-{0x2510, 0x16FE}, // SEQ_DATA_PORT +-{0x2510, 0x0C2C}, // SEQ_DATA_PORT +-{0x1008, 0x0338}, // FINE_INTEGRATION_TIME_MIN +-{0x100C, 0x051B}, // FINE_INTEGRATION_TIME2_MIN +-{0x100E, 0x06FE}, // FINE_INTEGRATION_TIME3_MIN +-{0x1010, 0x0155}, // FINE_INTEGRATION_TIME4_MIN +-{0x3230, 0x02D6}, // FINE_CORRECTION +-{0x3232, 0x04B9}, // FINE_CORRECTION2 +-{0x3234, 0x069C}, // FINE_CORRECTION3 +-{0x3236, 0x00F3}, // FINE_CORRECTION4 +-{0x32E6, 0x00DA}, // RESERVED_MFR_32E6 +-{0x350C, 0x035F}, // RESERVED_MFR_350C +-{0x32D0, 0x3A02}, // RESERVED_MFR_32D0 +-{0x32D2, 0x3508}, // RESERVED_MFR_32D2 +-{0x32D4, 0x3702}, // RESERVED_MFR_32D4 +-{0x32D6, 0x3C04}, // RESERVED_MFR_32D6 +-{0x32DC, 0x370A}, // RESERVED_MFR_32DC +-{0x302A, 0x0008}, // VT_PIX_CLK_DIV +-{0x302C, 0x0001}, // VT_SYS_CLK_DIV +-{0x302E, 0x0002}, // PRE_PLL_CLK_DIV +-{0x3030, 0x0034}, // PLL_MULTIPLIER +-{0x3036, 0x0008}, // OP_WORD_CLK_DIV +-{0x3038, 0x0001}, // OP_SYS_CLK_DIV +-{0x31DC, 0x0030}, // RESERVED_MFR_31DC +-{0x30A2, 0x0001}, // X_ODD_INC_ +-{0x30A6, 0x0001}, // Y_ODD_INC_ +-{0x3040, 0x0000}, // READ_MODE +-{0x3044, 0x0400}, // DARK_CONTROL +-{0x3180, 0x0080}, // RESERVED_MFR_3180 +-{0x33E4, 0x0080}, // RESERVED_MFR_33E4 +-{0x33E0, 0x0880}, // TEST_ASIL_ROWS +-#ifdef AR0143_EMBEDDED_LINE +-{0x3064, 0x1982}, // SMIA_TEST +-#else +-{0x3064, 0x1802}, // SMIA_TEST +-#endif +-{0x3004, 0x0000}, // X_ADDR_START_ +-{0x3008, 0x053F}, // X_ADDR_END_ +-{0x3002, 0x0000}, // Y_ADDR_START_ +-{0x3006, 0x03C7}, // Y_ADDR_END_ +-{0x3400, 0x0010}, // RESERVED_MFR_3400 +-{0x3402, 0x0A80}, // X_OUTPUT_CONTROL +-{0x3404, 0x0790}, // Y_OUTPUT_CONTROL +-{0x3082, 0x0008}, // OPERATION_MODE_CTRL +-{0x30BA, 0x01E2}, // DIGITAL_CTRL +-{0x300C, 0x09A0}, // LINE_LENGTH_PCK_ +-{0x300A, 0x041E}, // FRAME_LENGTH_LINES_ +-{0x3042, 0x0000}, // EXTRA_DELAY +-{0x3238, 0x0333}, // EXPOSURE_RATIO +-{0x3012, 0x036E}, // COARSE_INTEGRATION_TIME_ +-{0x3014, 0x0A7A}, // FINE_INTEGRATION_TIME_ +-{0x321E, 0x0A7A}, // FINE_INTEGRATION_TIME2 +-{0x3222, 0x0A7A}, // FINE_INTEGRATION_TIME3 +-{0x32EA, 0x3C0E}, // RESERVED_MFR_32EA +-{0x32EA, 0x3C0E}, // RESERVED_MFR_32EA +-{0x32EA, 0x3C0E}, // RESERVED_MFR_32EA +-{0x32EC, 0x72A1}, // RESERVED_MFR_32EC +-{0x32EC, 0x72A1}, // RESERVED_MFR_32EC +-{0x32EC, 0x72A1}, // RESERVED_MFR_32EC +-{0x32EC, 0x72A1}, // RESERVED_MFR_32EC +-{0x32EC, 0x72A1}, // RESERVED_MFR_32EC +-{0x32EC, 0x72A1}, // RESERVED_MFR_32EC +-{0x3C06, 0x083C}, // RESERVED_MFR_3C06 +-{0x3C08, 0x0100}, // RESERVED_MFR_3C08 +-{0x31D0, 0x0001}, // COMPANDING +-{0x31AC, 0x1410}, // DATA_FORMAT_BITS: 2xRAW8 +-{0x301A, 0x1098}, // RESET_REGISTER +-{0x301A, 0x1018}, // RESET_REGISTER +-{0x301A, 0x0018}, // RESET_REGISTER +-{0x31AE, 0x0204}, // SERIAL_FORMAT +-{0x3342, 0x122A}, // MIPI_F1_PDT_EDT +-{0x3346, 0x122A}, // MIPI_F2_PDT_EDT +-{0x334A, 0x122A}, // MIPI_F3_PDT_EDT +-{0x334E, 0x122A}, // MIPI_F4_PDT_EDT +-{0x3344, 0x0011}, // MIPI_F1_VDT_VC +-{0x3348, 0x0111}, // MIPI_F2_VDT_VC +-{0x334C, 0x0211}, // MIPI_F3_VDT_VC +-{0x3350, 0x0311}, // MIPI_F4_VDT_VC +-{0x31B0, 0x0061}, // FRAME_PREAMBLE +-{0x31B2, 0x004C}, // LINE_PREAMBLE +-{0x31B4, 0x51C8}, // RESERVED_MFR_31B4 +-{0x31B6, 0x424B}, // RESERVED_MFR_31B6 +-{0x31B8, 0x40CF}, // RESERVED_MFR_31B8 +-{0x31BA, 0x028B}, // RESERVED_MFR_31BA +-{0x31BC, 0x0D09}, // RESERVED_MFR_31BC +-// end demo init +-// start reg wizard WIDTHxHEIGHT@30fps +-#define NEW_TBL +-#ifdef NEW_TBL +-/* PCLK=27Mhz/0x5 *0x5d /1/0xa - MAXIM serializers */ +-{0x302A, 0x000A}, // VT_PIX_CLK_DIV +-{0x302C, 0x0001}, // VT_SYS_CLK_DIV +-{0x302E, 0x0005}, // PRE_PLL_CLK_DIV +-{0x3030, 0x005d}, // PLL_MULTIPLIER +-{0x3036, 0x000A}, // OP_WORD_CLK_DIV +-{0x3038, 0x0001}, // OP_SYS_CLK_DIV +-#else +-/* PCLK=27Mhz/0x9 *134 /1/8 - MAXIM serializers */ +-{0x302A, 0x0008}, // VT_PIX_CLK_DIV +-{0x302C, 0x0001}, // VT_SYS_CLK_DIV +-{0x302E, 0x0009}, // PRE_PLL_CLK_DIV +-{0x3030, 134}, // PLL_MULTIPLIER +-{0x3036, 0x0008}, // OP_WORD_CLK_DIV +-{0x3038, 0x0001}, // OP_SYS_CLK_DIV +-#endif +-{0x31B0, 0x0056}, // FRAME_PREAMBLE +-{0x31B2, 0x0045}, // LINE_PREAMBLE +-{0x3004, AR0143_X_START}, // X_ADDR_START_ +-{0x3008, AR0143_X_END}, // X_ADDR_END_ +-{0x3002, AR0143_Y_START}, // Y_ADDR_START_ +-{0x3006, AR0143_Y_END}, // Y_ADDR_END_ +-{0x3402, 0x0000 | AR0143_MAX_WIDTH}, // X_OUTPUT_CONTROL +-{0x3404, 0x0000 | AR0143_MAX_HEIGHT}, // Y_OUTPUT_CONTROL +-{0x31B4, 0x2207}, // RESERVED_MFR_31B4 +-{0x31B6, 0x220B}, // RESERVED_MFR_31B6 +-{0x31B8, 0x404B}, // RESERVED_MFR_31B8 +-{0x31BA, 0x020A}, // RESERVED_MFR_31BA +-{0x31BC, 0x0C08}, // RESERVED_MFR_31BC +-{0x3040, 0x0000}, // READ_MODE +-{0x30BA, 0x01E2}, // DIGITAL_CTRL +-{0x3082, 0x0008}, // OPERATION_MODE_CTRL +-{0x3044, 0x0400}, // DARK_CONTROL +-{0x33E0, 0x0880}, // TEST_ASIL_ROWS +-{0x3180, 0x0080}, // RESERVED_MFR_3180 +-{0x33E4, 0x0080}, // RESERVED_MFR_33E4 +-{0x3032, 0x0000}, // RESERVED_MFR_3032 +-{0x3400, 0x0010}, // RESERVED_MFR_3400 +-{0x31D0, 0x0001}, // COMPANDING +-//{0x31AC, 0x1410}, // DATA_FORMAT_BITS: 2xRAW8 +-{0x31AC, 0x140C}, // DATA_FORMAT_BITS: RAW12 +-{0x3C08, 0x0100}, // RESERVED_MFR_3C08 +-{0x3C0C, 0x0518}, // DELAY_BUFFER_LLPCK_RD_WR_OVERLAP +-#ifdef NEW_TBL +-//{0x300A, 0x0438}, // FRAME_LENGTH_LINES_ +-//{0x300C, 0x060e}, // LINE_LENGTH_PCK_ +-{0x300A, AR0143_SENSOR_HEIGHT + 157}, // FRAME_LENGTH_LINES_ +-{0x300C, AR0143_SENSOR_WIDTH + 144}, // LINE_LENGTH_PCK_ +-#else +-{0x300A, 0x048A}, // FRAME_LENGTH_LINES_ +-{0x300C, 0x05BA}, // LINE_LENGTH_PCK_ +-#endif +-{0x3018, 0x0000}, // FINE_INTEGRATION_TIME_CB +-{0x1008, 0x0338}, // FINE_INTEGRATION_TIME_MIN +-{0x100C, 0x051B}, // FINE_INTEGRATION_TIME2_MIN +-{0x100E, 0x06FE}, // FINE_INTEGRATION_TIME3_MIN +-{0x1010, 0x0155}, // FINE_INTEGRATION_TIME4_MIN +-#ifdef NEW_TBL +-{0x3012, 0x0206}, // COARSE_INTEGRATION_TIME_ +-{0x3014, 0x06e8}, // FINE_INTEGRATION_TIME_ +-{0x321E, 0x06E8}, // FINE_INTEGRATION_TIME2 +-{0x3222, 0x06E8}, // FINE_INTEGRATION_TIME3 +-#else +-{0x3012, 0x0332}, // COARSE_INTEGRATION_TIME_ +-{0x3014, 0x0694}, // FINE_INTEGRATION_TIME_ +-{0x321E, 0x0694}, // FINE_INTEGRATION_TIME2 +-{0x3222, 0x0694}, // FINE_INTEGRATION_TIME3 +-#endif +-{0x32EC, 0x72A0}, // RESERVED_MFR_32EC +-{0x31C6, 0x0000}, // HISPI_CONTROL +-#ifdef NEW_TBL +-{0x3082, 0x0000}, // OPERATION_MODE_CTRL: 1 exposure +-{0x3238, 0x0222}, // auto exposure time ratio - Fixed! +-#else +-// patch start +-//{0x30BA, 0x01E2}, // DIGITAL_CTRL: 3 exposures +-//{0x3082, 0x0008}, // OPERATION_MODE_CTRL: 3 exposures +-{0x3082, 0x0000}, // OPERATION_MODE_CTRL: 1 exposure +-//{0x30fe, 0x07ff}, // NOISE PEDESTAL +-//{0x305e, 0x3333}, // DIGITAL COLOR GLOBAL GAIN +-{0x3308, 0x200}, // DIGITAL GLOBAL GAIN: max=0x7ff +-//{0x3060, 0x7777}, // ANALOG COLOR GAIN +-{0x3366, 0x0666}, // ANALOG_GAIN - Fixed! +-//{0x3238, 0x8000}, // manual exposure time +-{0x3238, 0x0222}, // auto exposure time ratio - Fixed! +-{0x3012, 0x0300}, // T1 exposure - max=0x400 +-//{0x3212, 0x0004}, // T2 exposure - not used in auto +-//{0x3216, 0x0001}, // T3 exposure - not used in auto +-#endif +-// patch eof +-{0x301A, 0x01d8}, // RESET_REGISTER +-// enable trigger +-{0x340A, 0x0070}, // GPIO_CONTROL1: GPIO3 is trigger +-{0x340C, 0x0080}, // GPIO_CONTROL2: GPIO3 is trigger +-{0x30CE, 0x0120}, // TRIGGER_MODE +-//{0x30DC, 0x0120}, // TRIGGER_DELAY +-// end reg wizard WIDTHxHEIGHT@30fps +-}; ++//#include "ar0143_custom.h" ++#include "ar0143_rev1.h" +diff --git a/drivers/media/i2c/soc_camera/ar0143_custom.h b/drivers/media/i2c/soc_camera/ar0143_custom.h +new file mode 100644 +index 0000000..2d4aa1c +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0143_custom.h +@@ -0,0 +1,526 @@ ++/* ++ * ON Semiconductor AR0143 sensor camera wizard 1344x968@30/BGGR/BT601/RAW12 ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++static const struct ar0143_reg ar0143_regs_wizard_custom[] = { ++{0x301A, 0x0001}, // reset ++{AR0143_DELAY, 100}, ++{0x301A, 0x10D8}, // Stream off and setup parallel ++{0x3070, 0x0001}, ++{0x3070, 0x0000}, // 1: Solid color test pattern, ++ // 2: Full color bar test pattern, ++ // 3: Fade to grey color bar test pattern, ++ //256: Walking 1 test pattern (12 bit) ++#ifdef AR0143_DISPLAY_PATTERN_FIXED ++{0x3070, 0x0001}, ++#endif ++{0x3072, 0x0fff}, // R ++{0x3074, 0x0fff}, // G(GR row) ++{0x3076, 0x0fff}, // B ++{0x3078, 0x0fff}, // G(GB row) ++#ifdef AR0143_DISPLAY_PATTERN_COLOR_BAR ++{0x3070, 0x0002}, ++#endif ++{AR0143_DELAY, 250}, ++// start demo init ++{0x3100, 0x4000}, // DLO_CONTROL0 ++{0x3102, 0x6060}, // RESERVED_MFR_3102 ++{0x3104, 0x6060}, // RESERVED_MFR_3104 ++{0x3106, 0x6060}, // RESERVED_MFR_3106 ++{0x3108, 0x0F9F}, // RESERVED_MFR_3108 ++{0x3280, 0x0FA0}, // T1_BARRIER_C0 ++{0x3282, 0x0FA0}, // T1_BARRIER_C1 ++{0x3284, 0x0FA0}, // T1_BARRIER_C2 ++{0x3286, 0x0FA0}, // T1_BARRIER_C3 ++{0x3288, 0x0FA0}, // T2_BARRIER_C0 ++{0x328A, 0x0FA0}, // T2_BARRIER_C1 ++{0x328C, 0x0FA0}, // T2_BARRIER_C2 ++{0x328E, 0x0FA0}, // T2_BARRIER_C3 ++{0x3290, 0x0FA0}, // T3_BARRIER_C0 ++{0x3292, 0x0FA0}, // T3_BARRIER_C1 ++{0x3294, 0x0FA0}, // T3_BARRIER_C2 ++{0x3296, 0x0FA0}, // T3_BARRIER_C3 ++{0x3298, 0x0FA0}, // T4_BARRIER_C0 ++{0x329A, 0x0FA0}, // T4_BARRIER_C1 ++{0x329C, 0x0FA0}, // T4_BARRIER_C2 ++{0x329E, 0x0FA0}, // T4_BARRIER_C3 ++{0x3110, 0x0011}, // HDR_CONTROL0 ++{0x3112, 0x7FE7}, // RESERVED_MFR_3112 ++{0x3114, 0x0000}, // RESERVED_MFR_3114 ++{0x3116, 0xC000}, // HDR_CONTROL3 ++{0x3120, 0x0BA0}, // HDR_SC_CONTROL0 ++{0x3122, 0x0FA0}, // HDR_SC_CONTROL1 ++{0x3124, 0x00B4}, // HDR_MD_CONTROL0 ++{0x3126, 0x0030}, // HDR_MD_CONTROL1 ++{0x3128, 0x6100}, // RESERVED_MFR_3128 ++{0x3506, 0x3333}, // RESERVED_MFR_3506 ++{0x3508, 0x3333}, // RESERVED_MFR_3508 ++{0x350A, 0x3333}, // RESERVED_MFR_350A ++{0x350C, 0x035F}, // RESERVED_MFR_350C ++{0x350E, 0xEF14}, // RESERVED_MFR_350E ++{0x3086, 0x0600}, // RESERVED_MFR_3086 ++{0x3C00, 0xDD67}, // RESERVED_MFR_3C00 ++{0x3092, 0x1C24}, // RESERVED_MFR_3092 ++{0x3096, 0x147E}, // RESERVED_MFR_3096 ++{0x3750, 0x147E}, // RESERVED_MFR_3750 ++{0x30B0, 0x0800}, // DIGITAL_TEST ++{0x30FE, 0x0000}, // NOISE_PEDESTAL ++{0x32D0, 0x3A02}, // RESERVED_MFR_32D0 ++{0x32D6, 0x3C04}, // RESERVED_MFR_32D6 ++{0x3C0C, 0x0516}, // DELAY_BUFFER_LLPCK_RD_WR_OVERLAP ++{0x3F94, 0x483e}, // TEMPVSENS0_FLAG_CTRL ++{0x3F96, 0xFFFE}, // TEMPVSENS1_FLAG_CTRL ++{0x3088, 0x6680}, // LFM_CTRL ++{0x33E2, 0x0000}, // SAMPLE_CTRL ++{0x3366, 0x7777}, // ANALOG_GAIN ++{0x3056, 0x0080}, // GREEN1_GAIN ++{0x305C, 0x0080}, // GREEN2_GAIN ++{0x3058, 0x0080}, // BLUE_GAIN ++{0x305A, 0x0080}, // RED_GAIN ++{0x306E, 0x9010}, // DATAPATH_SELECT ++{0x3044, 0x0400}, // DARK_CONTROL ++{0x30BA, 0x01E2}, // DIGITAL_CTRL ++{0x32EA, 0x3C0E}, // RESERVED_MFR_32EA ++{0x3362, 0x0000}, // DC_GAIN ++{0x3364, 0x005B}, // RESERVED_MFR_3364 ++{0x3370, 0x0131}, // DBLC_CONTROL ++{0x3372, 0x700F}, // DBLC_FS0_CONTROL ++{0x3386, 0x0000}, // DBLC_PEDESTAL ++{0x3C04, 0x0E80}, // RESERVED_MFR_3C04 ++{0x30B4, 0x01C7}, // TEMPSENS0_CTRL_REG ++{0x30B8, 0x0007}, // TEMPSENS1_CTRL_REG ++{0x3F90, 0x8D03}, // TEMPVSENS0_TMG_CTRL ++{0x3F92, 0x0D03}, // TEMPVSENS1_TMG_CTRL ++{0x3502, 0x0808}, // RESERVED_MFR_3502 ++{0x3566, 0x1D28}, // RESERVED_MFR_3566 ++{0x3518, 0x1FFE}, // RESERVED_MFR_3518 ++{0x3526, 0x0F00}, // RESERVED_MFR_3526 ++{0x3528, 0xDDDD}, // RESERVED_MFR_3528 ++{0x352A, 0x089F}, // RESERVED_MFR_352A ++{0x352E, 0x0011}, // RESERVED_MFR_352E ++{0x3530, 0x4400}, // RESERVED_MFR_3530 ++{0x3536, 0xFF07}, // RESERVED_MFR_3536 ++{0x3538, 0xFFFF}, // RESERVED_MFR_3538 ++{0x353A, 0x9000}, // RESERVED_MFR_353A ++{0x353C, 0x3F00}, // RESERVED_MFR_353C ++{0x32EC, 0x72A1}, // RESERVED_MFR_32EC ++{0x3540, 0xC637}, // RESERVED_MFR_3540 ++{0x3542, 0x464B}, // RESERVED_MFR_3542 ++{0x3544, 0x4B50}, // RESERVED_MFR_3544 ++{0x3546, 0x545A}, // RESERVED_MFR_3546 ++{0x3548, 0x5A00}, // RESERVED_MFR_3548 ++{0x354A, 0x007F}, // RESERVED_MFR_354A ++{0x3556, 0x101F}, // RESERVED_MFR_3556 ++{0x3566, 0x3328}, // RESERVED_MFR_3566 ++{0x337A, 0x0CA3}, // DBLC_SCALE0 ++{0x3372, 0x710F}, // DBLC_FS0_CONTROL ++{0x3520, 0x4688}, // RESERVED_MFR_3520 ++{0x3522, 0x8840}, // RESERVED_MFR_3522 ++{0x3524, 0x4046}, // RESERVED_MFR_3524 ++{0x352C, 0x4646}, // RESERVED_MFR_352C ++{0x2512, 0x8000}, // SEQ_CTRL_PORT ++{0x2510, 0x0903}, // SEQ_DATA_PORT ++{0x2510, 0x3350}, // SEQ_DATA_PORT ++{0x2510, 0x2004}, // SEQ_DATA_PORT ++{0x2510, 0x1420}, // SEQ_DATA_PORT ++{0x2510, 0x1578}, // SEQ_DATA_PORT ++{0x2510, 0x087B}, // SEQ_DATA_PORT ++{0x2510, 0x24FF}, // SEQ_DATA_PORT ++{0x2510, 0x24FF}, // SEQ_DATA_PORT ++{0x2510, 0x24EA}, // SEQ_DATA_PORT ++{0x2510, 0x2410}, // SEQ_DATA_PORT ++{0x2510, 0x2224}, // SEQ_DATA_PORT ++{0x2510, 0x1015}, // SEQ_DATA_PORT ++{0x2510, 0x5813}, // SEQ_DATA_PORT ++{0x2510, 0x0214}, // SEQ_DATA_PORT ++{0x2510, 0x0024}, // SEQ_DATA_PORT ++{0x2510, 0xFF24}, // SEQ_DATA_PORT ++{0x2510, 0xFF24}, // SEQ_DATA_PORT ++{0x2510, 0xEA23}, // SEQ_DATA_PORT ++{0x2510, 0x2464}, // SEQ_DATA_PORT ++{0x2510, 0x7A24}, // SEQ_DATA_PORT ++{0x2510, 0x0405}, // SEQ_DATA_PORT ++{0x2510, 0x2C40}, // SEQ_DATA_PORT ++{0x2510, 0x0AFF}, // SEQ_DATA_PORT ++{0x2510, 0x0ACC}, // SEQ_DATA_PORT ++{0x2510, 0x0A07}, // SEQ_DATA_PORT ++{0x2510, 0x3851}, // SEQ_DATA_PORT ++{0x2510, 0x1440}, // SEQ_DATA_PORT ++{0x2510, 0x0004}, // SEQ_DATA_PORT ++{0x2510, 0x0801}, // SEQ_DATA_PORT ++{0x2510, 0x0408}, // SEQ_DATA_PORT ++{0x2510, 0x1180}, // SEQ_DATA_PORT ++{0x2510, 0x2652}, // SEQ_DATA_PORT ++{0x2510, 0x0815}, // SEQ_DATA_PORT ++{0x2510, 0x1813}, // SEQ_DATA_PORT ++{0x2510, 0xC810}, // SEQ_DATA_PORT ++{0x2510, 0x0210}, // SEQ_DATA_PORT ++{0x2510, 0x1611}, // SEQ_DATA_PORT ++{0x2510, 0x8111}, // SEQ_DATA_PORT ++{0x2510, 0x8910}, // SEQ_DATA_PORT ++{0x2510, 0x5612}, // SEQ_DATA_PORT ++{0x2510, 0x1009}, // SEQ_DATA_PORT ++{0x2510, 0x020D}, // SEQ_DATA_PORT ++{0x2510, 0x0905}, // SEQ_DATA_PORT ++{0x2510, 0x1588}, // SEQ_DATA_PORT ++{0x2510, 0x1388}, // SEQ_DATA_PORT ++{0x2510, 0x0938}, // SEQ_DATA_PORT ++{0x2510, 0x1199}, // SEQ_DATA_PORT ++{0x2510, 0x11D9}, // SEQ_DATA_PORT ++{0x2510, 0x091E}, // SEQ_DATA_PORT ++{0x2510, 0x1214}, // SEQ_DATA_PORT ++{0x2510, 0x10D6}, // SEQ_DATA_PORT ++{0x2510, 0x0901}, // SEQ_DATA_PORT ++{0x2510, 0x1210}, // SEQ_DATA_PORT ++{0x2510, 0x1212}, // SEQ_DATA_PORT ++{0x2510, 0x1210}, // SEQ_DATA_PORT ++{0x2510, 0x11DD}, // SEQ_DATA_PORT ++{0x2510, 0x11D9}, // SEQ_DATA_PORT ++{0x2510, 0x0901}, // SEQ_DATA_PORT ++{0x2510, 0x1441}, // SEQ_DATA_PORT ++{0x2510, 0x0904}, // SEQ_DATA_PORT ++{0x2510, 0x1056}, // SEQ_DATA_PORT ++{0x2510, 0x0811}, // SEQ_DATA_PORT ++{0x2510, 0xDB09}, // SEQ_DATA_PORT ++{0x2510, 0x0311}, // SEQ_DATA_PORT ++{0x2510, 0xFB11}, // SEQ_DATA_PORT ++{0x2510, 0xBB12}, // SEQ_DATA_PORT ++{0x2510, 0x1A12}, // SEQ_DATA_PORT ++{0x2510, 0x1008}, // SEQ_DATA_PORT ++{0x2510, 0x1250}, // SEQ_DATA_PORT ++{0x2510, 0x1076}, // SEQ_DATA_PORT ++{0x2510, 0x10E6}, // SEQ_DATA_PORT ++{0x2510, 0x1461}, // SEQ_DATA_PORT ++{0x2510, 0x0906}, // SEQ_DATA_PORT ++{0x2510, 0x1240}, // SEQ_DATA_PORT ++{0x2510, 0x1260}, // SEQ_DATA_PORT ++{0x2510, 0x091C}, // SEQ_DATA_PORT ++{0x2510, 0x1460}, // SEQ_DATA_PORT ++{0x2510, 0x090C}, // SEQ_DATA_PORT ++{0x2510, 0x0B09}, // SEQ_DATA_PORT ++{0x2510, 0x0515}, // SEQ_DATA_PORT ++{0x2510, 0xC813}, // SEQ_DATA_PORT ++{0x2510, 0xC808}, // SEQ_DATA_PORT ++{0x2510, 0x1066}, // SEQ_DATA_PORT ++{0x2510, 0x090B}, // SEQ_DATA_PORT ++{0x2510, 0x1588}, // SEQ_DATA_PORT ++{0x2510, 0x1388}, // SEQ_DATA_PORT ++{0x2510, 0x0913}, // SEQ_DATA_PORT ++{0x2510, 0x0C14}, // SEQ_DATA_PORT ++{0x2510, 0x4009}, // SEQ_DATA_PORT ++{0x2510, 0x0310}, // SEQ_DATA_PORT ++{0x2510, 0xE611}, // SEQ_DATA_PORT ++{0x2510, 0xFB12}, // SEQ_DATA_PORT ++{0x2510, 0x6212}, // SEQ_DATA_PORT ++{0x2510, 0x6011}, // SEQ_DATA_PORT ++{0x2510, 0xFF11}, // SEQ_DATA_PORT ++{0x2510, 0xFB14}, // SEQ_DATA_PORT ++{0x2510, 0x4109}, // SEQ_DATA_PORT ++{0x2510, 0x0210}, // SEQ_DATA_PORT ++{0x2510, 0x6609}, // SEQ_DATA_PORT ++{0x2510, 0x1211}, // SEQ_DATA_PORT ++{0x2510, 0xBB12}, // SEQ_DATA_PORT ++{0x2510, 0x6312}, // SEQ_DATA_PORT ++{0x2510, 0x6014}, // SEQ_DATA_PORT ++{0x2510, 0x0015}, // SEQ_DATA_PORT ++{0x2510, 0x1811}, // SEQ_DATA_PORT ++{0x2510, 0xB812}, // SEQ_DATA_PORT ++{0x2510, 0xA012}, // SEQ_DATA_PORT ++{0x2510, 0x0010}, // SEQ_DATA_PORT ++{0x2510, 0x2610}, // SEQ_DATA_PORT ++{0x2510, 0x0013}, // SEQ_DATA_PORT ++{0x2510, 0x0011}, // SEQ_DATA_PORT ++{0x2510, 0x8030}, // SEQ_DATA_PORT ++{0x2510, 0x5342}, // SEQ_DATA_PORT ++{0x2510, 0x1100}, // SEQ_DATA_PORT ++{0x2510, 0x1002}, // SEQ_DATA_PORT ++{0x2510, 0x1016}, // SEQ_DATA_PORT ++{0x2510, 0x1101}, // SEQ_DATA_PORT ++{0x2510, 0x1109}, // SEQ_DATA_PORT ++{0x2510, 0x1056}, // SEQ_DATA_PORT ++{0x2510, 0x1210}, // SEQ_DATA_PORT ++{0x2510, 0x0D09}, // SEQ_DATA_PORT ++{0x2510, 0x0614}, // SEQ_DATA_PORT ++{0x2510, 0x4009}, // SEQ_DATA_PORT ++{0x2510, 0x0214}, // SEQ_DATA_PORT ++{0x2510, 0x6009}, // SEQ_DATA_PORT ++{0x2510, 0x0615}, // SEQ_DATA_PORT ++{0x2510, 0x4C13}, // SEQ_DATA_PORT ++{0x2510, 0x0C09}, // SEQ_DATA_PORT ++{0x2510, 0x0713}, // SEQ_DATA_PORT ++{0x2510, 0x4C09}, // SEQ_DATA_PORT ++{0x2510, 0x0715}, // SEQ_DATA_PORT ++{0x2510, 0xCC09}, // SEQ_DATA_PORT ++{0x2510, 0x0211}, // SEQ_DATA_PORT ++{0x2510, 0x4908}, // SEQ_DATA_PORT ++{0x2510, 0x1461}, // SEQ_DATA_PORT ++{0x2510, 0x1460}, // SEQ_DATA_PORT ++{0x2510, 0x0903}, // SEQ_DATA_PORT ++{0x2510, 0x1588}, // SEQ_DATA_PORT ++{0x2510, 0x1308}, // SEQ_DATA_PORT ++{0x2510, 0x0905}, // SEQ_DATA_PORT ++{0x2510, 0x1388}, // SEQ_DATA_PORT ++{0x2510, 0x0913}, // SEQ_DATA_PORT ++{0x2510, 0x1159}, // SEQ_DATA_PORT ++{0x2510, 0x090B}, // SEQ_DATA_PORT ++{0x2510, 0x1214}, // SEQ_DATA_PORT ++{0x2510, 0x0901}, // SEQ_DATA_PORT ++{0x2510, 0x1210}, // SEQ_DATA_PORT ++{0x2510, 0x10D6}, // SEQ_DATA_PORT ++{0x2510, 0x1212}, // SEQ_DATA_PORT ++{0x2510, 0x1210}, // SEQ_DATA_PORT ++{0x2510, 0x115D}, // SEQ_DATA_PORT ++{0x2510, 0x1159}, // SEQ_DATA_PORT ++{0x2510, 0x1056}, // SEQ_DATA_PORT ++{0x2510, 0x0903}, // SEQ_DATA_PORT ++{0x2510, 0x115B}, // SEQ_DATA_PORT ++{0x2510, 0x0913}, // SEQ_DATA_PORT ++{0x2510, 0x111B}, // SEQ_DATA_PORT ++{0x2510, 0x113B}, // SEQ_DATA_PORT ++{0x2510, 0x121A}, // SEQ_DATA_PORT ++{0x2510, 0x1210}, // SEQ_DATA_PORT ++{0x2510, 0x0901}, // SEQ_DATA_PORT ++{0x2510, 0x1250}, // SEQ_DATA_PORT ++{0x2510, 0x10F6}, // SEQ_DATA_PORT ++{0x2510, 0x10E6}, // SEQ_DATA_PORT ++{0x2510, 0x0903}, // SEQ_DATA_PORT ++{0x2510, 0x15AB}, // SEQ_DATA_PORT ++{0x2510, 0x13AB}, // SEQ_DATA_PORT ++{0x2510, 0x1240}, // SEQ_DATA_PORT ++{0x2510, 0x1260}, // SEQ_DATA_PORT ++{0x2510, 0x0964}, // SEQ_DATA_PORT ++{0x2510, 0x1588}, // SEQ_DATA_PORT ++{0x2510, 0x0903}, // SEQ_DATA_PORT ++{0x2510, 0x0B08}, // SEQ_DATA_PORT ++{0x2510, 0x0813}, // SEQ_DATA_PORT ++{0x2510, 0x8809}, // SEQ_DATA_PORT ++{0x2510, 0x0715}, // SEQ_DATA_PORT ++{0x2510, 0x8D13}, // SEQ_DATA_PORT ++{0x2510, 0x8D09}, // SEQ_DATA_PORT ++{0x2510, 0x0D15}, // SEQ_DATA_PORT ++{0x2510, 0x8813}, // SEQ_DATA_PORT ++{0x2510, 0x8809}, // SEQ_DATA_PORT ++{0x2510, 0x0310}, // SEQ_DATA_PORT ++{0x2510, 0x6609}, // SEQ_DATA_PORT ++{0x2510, 0x030C}, // SEQ_DATA_PORT ++{0x2510, 0x0914}, // SEQ_DATA_PORT ++{0x2510, 0x10E6}, // SEQ_DATA_PORT ++{0x2510, 0x1262}, // SEQ_DATA_PORT ++{0x2510, 0x1260}, // SEQ_DATA_PORT ++{0x2510, 0x113F}, // SEQ_DATA_PORT ++{0x2510, 0x113B}, // SEQ_DATA_PORT ++{0x2510, 0x1066}, // SEQ_DATA_PORT ++{0x2510, 0x117B}, // SEQ_DATA_PORT ++{0x2510, 0x0927}, // SEQ_DATA_PORT ++{0x2510, 0x113B}, // SEQ_DATA_PORT ++{0x2510, 0x1263}, // SEQ_DATA_PORT ++{0x2510, 0x1260}, // SEQ_DATA_PORT ++{0x2510, 0x1400}, // SEQ_DATA_PORT ++{0x2510, 0x155A}, // SEQ_DATA_PORT ++{0x2510, 0x1138}, // SEQ_DATA_PORT ++{0x2510, 0x12A0}, // SEQ_DATA_PORT ++{0x2510, 0x1200}, // SEQ_DATA_PORT ++{0x2510, 0x1026}, // SEQ_DATA_PORT ++{0x2510, 0x1000}, // SEQ_DATA_PORT ++{0x2510, 0x1342}, // SEQ_DATA_PORT ++{0x2510, 0x1100}, // SEQ_DATA_PORT ++{0x2510, 0x437A}, // SEQ_DATA_PORT ++{0x2510, 0x0605}, // SEQ_DATA_PORT ++{0x2510, 0x0807}, // SEQ_DATA_PORT ++{0x2510, 0x4137}, // SEQ_DATA_PORT ++{0x2510, 0x502C}, // SEQ_DATA_PORT ++{0x2510, 0x2CFE}, // SEQ_DATA_PORT ++{0x2510, 0x16FE}, // SEQ_DATA_PORT ++{0x2510, 0x0C2C}, // SEQ_DATA_PORT ++{0x1008, 0x0338}, // FINE_INTEGRATION_TIME_MIN ++{0x100C, 0x051B}, // FINE_INTEGRATION_TIME2_MIN ++{0x100E, 0x06FE}, // FINE_INTEGRATION_TIME3_MIN ++{0x1010, 0x0155}, // FINE_INTEGRATION_TIME4_MIN ++{0x3230, 0x02D6}, // FINE_CORRECTION ++{0x3232, 0x04B9}, // FINE_CORRECTION2 ++{0x3234, 0x069C}, // FINE_CORRECTION3 ++{0x3236, 0x00F3}, // FINE_CORRECTION4 ++{0x32E6, 0x00DA}, // RESERVED_MFR_32E6 ++{0x350C, 0x035F}, // RESERVED_MFR_350C ++{0x32D0, 0x3A02}, // RESERVED_MFR_32D0 ++{0x32D2, 0x3508}, // RESERVED_MFR_32D2 ++{0x32D4, 0x3702}, // RESERVED_MFR_32D4 ++{0x32D6, 0x3C04}, // RESERVED_MFR_32D6 ++{0x32DC, 0x370A}, // RESERVED_MFR_32DC ++{0x302A, 0x0008}, // VT_PIX_CLK_DIV ++{0x302C, 0x0001}, // VT_SYS_CLK_DIV ++{0x302E, 0x0002}, // PRE_PLL_CLK_DIV ++{0x3030, 0x0034}, // PLL_MULTIPLIER ++{0x3036, 0x0008}, // OP_WORD_CLK_DIV ++{0x3038, 0x0001}, // OP_SYS_CLK_DIV ++{0x31DC, 0x0030}, // RESERVED_MFR_31DC ++{0x30A2, 0x0001}, // X_ODD_INC_ ++{0x30A6, 0x0001}, // Y_ODD_INC_ ++{0x3040, 0x0000}, // READ_MODE ++{0x3044, 0x0400}, // DARK_CONTROL ++{0x3180, 0x0080}, // RESERVED_MFR_3180 ++{0x33E4, 0x0080}, // RESERVED_MFR_33E4 ++{0x33E0, 0x0880}, // TEST_ASIL_ROWS ++#ifdef AR0143_EMBEDDED_LINE ++{0x3064, 0x1982}, // SMIA_TEST ++#else ++{0x3064, 0x1802}, // SMIA_TEST ++#endif ++{0x3004, 0x0000}, // X_ADDR_START_ ++{0x3008, 0x053F}, // X_ADDR_END_ ++{0x3002, 0x0000}, // Y_ADDR_START_ ++{0x3006, 0x03C7}, // Y_ADDR_END_ ++{0x3400, 0x0010}, // RESERVED_MFR_3400 ++{0x3402, 0x0A80}, // X_OUTPUT_CONTROL ++{0x3404, 0x0790}, // Y_OUTPUT_CONTROL ++{0x3082, 0x0008}, // OPERATION_MODE_CTRL ++{0x30BA, 0x01E2}, // DIGITAL_CTRL ++{0x300C, 0x09A0}, // LINE_LENGTH_PCK_ ++{0x300A, 0x041E}, // FRAME_LENGTH_LINES_ ++{0x3042, 0x0000}, // EXTRA_DELAY ++{0x3238, 0x0333}, // EXPOSURE_RATIO ++{0x3012, 0x036E}, // COARSE_INTEGRATION_TIME_ ++{0x3014, 0x0A7A}, // FINE_INTEGRATION_TIME_ ++{0x321E, 0x0A7A}, // FINE_INTEGRATION_TIME2 ++{0x3222, 0x0A7A}, // FINE_INTEGRATION_TIME3 ++{0x32EA, 0x3C0E}, // RESERVED_MFR_32EA ++{0x32EA, 0x3C0E}, // RESERVED_MFR_32EA ++{0x32EA, 0x3C0E}, // RESERVED_MFR_32EA ++{0x32EC, 0x72A1}, // RESERVED_MFR_32EC ++{0x32EC, 0x72A1}, // RESERVED_MFR_32EC ++{0x32EC, 0x72A1}, // RESERVED_MFR_32EC ++{0x32EC, 0x72A1}, // RESERVED_MFR_32EC ++{0x32EC, 0x72A1}, // RESERVED_MFR_32EC ++{0x32EC, 0x72A1}, // RESERVED_MFR_32EC ++{0x3C06, 0x083C}, // RESERVED_MFR_3C06 ++{0x3C08, 0x0100}, // RESERVED_MFR_3C08 ++{0x31D0, 0x0001}, // COMPANDING ++{0x31AC, 0x1410}, // DATA_FORMAT_BITS: 2xRAW8 ++{0x301A, 0x1098}, // RESET_REGISTER ++{0x301A, 0x1018}, // RESET_REGISTER ++{0x301A, 0x0018}, // RESET_REGISTER ++{0x31AE, 0x0204}, // SERIAL_FORMAT ++{0x3342, 0x122A}, // MIPI_F1_PDT_EDT ++{0x3346, 0x122A}, // MIPI_F2_PDT_EDT ++{0x334A, 0x122A}, // MIPI_F3_PDT_EDT ++{0x334E, 0x122A}, // MIPI_F4_PDT_EDT ++{0x3344, 0x0011}, // MIPI_F1_VDT_VC ++{0x3348, 0x0111}, // MIPI_F2_VDT_VC ++{0x334C, 0x0211}, // MIPI_F3_VDT_VC ++{0x3350, 0x0311}, // MIPI_F4_VDT_VC ++{0x31B0, 0x0061}, // FRAME_PREAMBLE ++{0x31B2, 0x004C}, // LINE_PREAMBLE ++{0x31B4, 0x51C8}, // RESERVED_MFR_31B4 ++{0x31B6, 0x424B}, // RESERVED_MFR_31B6 ++{0x31B8, 0x40CF}, // RESERVED_MFR_31B8 ++{0x31BA, 0x028B}, // RESERVED_MFR_31BA ++{0x31BC, 0x0D09}, // RESERVED_MFR_31BC ++// end demo init ++// start reg wizard WIDTHxHEIGHT@30fps ++#define NEW_TBL ++#ifdef NEW_TBL ++/* PCLK=27Mhz/0x5 *0x5d /1/0xa - MAXIM serializers */ ++{0x302A, 0x000A}, // VT_PIX_CLK_DIV ++{0x302C, 0x0001}, // VT_SYS_CLK_DIV ++{0x302E, 0x0005}, // PRE_PLL_CLK_DIV ++{0x3030, 0x005d}, // PLL_MULTIPLIER ++{0x3036, 0x000A}, // OP_WORD_CLK_DIV ++{0x3038, 0x0001}, // OP_SYS_CLK_DIV ++#else ++/* PCLK=27Mhz/0x9 *134 /1/8 - MAXIM serializers */ ++{0x302A, 0x0008}, // VT_PIX_CLK_DIV ++{0x302C, 0x0001}, // VT_SYS_CLK_DIV ++{0x302E, 0x0009}, // PRE_PLL_CLK_DIV ++{0x3030, 134}, // PLL_MULTIPLIER ++{0x3036, 0x0008}, // OP_WORD_CLK_DIV ++{0x3038, 0x0001}, // OP_SYS_CLK_DIV ++#endif ++{0x31B0, 0x0056}, // FRAME_PREAMBLE ++{0x31B2, 0x0045}, // LINE_PREAMBLE ++{0x3004, AR0143_X_START}, // X_ADDR_START_ ++{0x3008, AR0143_X_END}, // X_ADDR_END_ ++{0x3002, AR0143_Y_START}, // Y_ADDR_START_ ++{0x3006, AR0143_Y_END}, // Y_ADDR_END_ ++{0x3402, 0x0000 | AR0143_MAX_WIDTH}, // X_OUTPUT_CONTROL ++{0x3404, 0x0000 | AR0143_MAX_HEIGHT}, // Y_OUTPUT_CONTROL ++{0x31B4, 0x2207}, // RESERVED_MFR_31B4 ++{0x31B6, 0x220B}, // RESERVED_MFR_31B6 ++{0x31B8, 0x404B}, // RESERVED_MFR_31B8 ++{0x31BA, 0x020A}, // RESERVED_MFR_31BA ++{0x31BC, 0x0C08}, // RESERVED_MFR_31BC ++{0x3040, 0x0000}, // READ_MODE ++{0x30BA, 0x01E2}, // DIGITAL_CTRL ++{0x3082, 0x0008}, // OPERATION_MODE_CTRL ++{0x3044, 0x0400}, // DARK_CONTROL ++{0x33E0, 0x0880}, // TEST_ASIL_ROWS ++{0x3180, 0x0080}, // RESERVED_MFR_3180 ++{0x33E4, 0x0080}, // RESERVED_MFR_33E4 ++{0x3032, 0x0000}, // RESERVED_MFR_3032 ++{0x3400, 0x0010}, // RESERVED_MFR_3400 ++{0x31D0, 0x0001}, // COMPANDING ++//{0x31AC, 0x1410}, // DATA_FORMAT_BITS: 2xRAW8 ++{0x31AC, 0x140C}, // DATA_FORMAT_BITS: RAW12 ++{0x3C08, 0x0100}, // RESERVED_MFR_3C08 ++{0x3C0C, 0x0518}, // DELAY_BUFFER_LLPCK_RD_WR_OVERLAP ++#ifdef NEW_TBL ++//{0x300A, 0x0438}, // FRAME_LENGTH_LINES_ ++//{0x300C, 0x060e}, // LINE_LENGTH_PCK_ ++{0x300A, AR0143_SENSOR_HEIGHT + 157}, // FRAME_LENGTH_LINES_ ++{0x300C, AR0143_SENSOR_WIDTH + 144}, // LINE_LENGTH_PCK_ ++#else ++{0x300A, 0x048A}, // FRAME_LENGTH_LINES_ ++{0x300C, 0x05BA}, // LINE_LENGTH_PCK_ ++#endif ++{0x3018, 0x0000}, // FINE_INTEGRATION_TIME_CB ++{0x1008, 0x0338}, // FINE_INTEGRATION_TIME_MIN ++{0x100C, 0x051B}, // FINE_INTEGRATION_TIME2_MIN ++{0x100E, 0x06FE}, // FINE_INTEGRATION_TIME3_MIN ++{0x1010, 0x0155}, // FINE_INTEGRATION_TIME4_MIN ++#ifdef NEW_TBL ++{0x3012, 0x0206}, // COARSE_INTEGRATION_TIME_ ++{0x3014, 0x06e8}, // FINE_INTEGRATION_TIME_ ++{0x321E, 0x06E8}, // FINE_INTEGRATION_TIME2 ++{0x3222, 0x06E8}, // FINE_INTEGRATION_TIME3 ++#else ++{0x3012, 0x0332}, // COARSE_INTEGRATION_TIME_ ++{0x3014, 0x0694}, // FINE_INTEGRATION_TIME_ ++{0x321E, 0x0694}, // FINE_INTEGRATION_TIME2 ++{0x3222, 0x0694}, // FINE_INTEGRATION_TIME3 ++#endif ++{0x32EC, 0x72A0}, // RESERVED_MFR_32EC ++{0x31C6, 0x0000}, // HISPI_CONTROL ++#ifdef NEW_TBL ++{0x3082, 0x0000}, // OPERATION_MODE_CTRL: 1 exposure ++{0x3238, 0x0222}, // auto exposure time ratio - Fixed! ++#else ++// patch start ++//{0x30BA, 0x01E2}, // DIGITAL_CTRL: 3 exposures ++//{0x3082, 0x0008}, // OPERATION_MODE_CTRL: 3 exposures ++{0x3082, 0x0000}, // OPERATION_MODE_CTRL: 1 exposure ++//{0x30fe, 0x07ff}, // NOISE PEDESTAL ++//{0x305e, 0x3333}, // DIGITAL COLOR GLOBAL GAIN ++{0x3308, 0x200}, // DIGITAL GLOBAL GAIN: max=0x7ff ++//{0x3060, 0x7777}, // ANALOG COLOR GAIN ++{0x3366, 0x0666}, // ANALOG_GAIN - Fixed! ++//{0x3238, 0x8000}, // manual exposure time ++{0x3238, 0x0222}, // auto exposure time ratio - Fixed! ++{0x3012, 0x0300}, // T1 exposure - max=0x400 ++//{0x3212, 0x0004}, // T2 exposure - not used in auto ++//{0x3216, 0x0001}, // T3 exposure - not used in auto ++#endif ++// patch eof ++{0x301A, 0x01d8}, // RESET_REGISTER ++// enable trigger ++{0x340A, 0x0070}, // GPIO_CONTROL1: GPIO3 is trigger ++{0x340C, 0x0080}, // GPIO_CONTROL2: GPIO3 is trigger ++{0x30CE, 0x0120}, // TRIGGER_MODE ++//{0x30DC, 0x0120}, // TRIGGER_DELAY ++// end reg wizard WIDTHxHEIGHT@30fps ++}; +diff --git a/drivers/media/i2c/soc_camera/ar0143_rev1.h b/drivers/media/i2c/soc_camera/ar0143_rev1.h +new file mode 100644 +index 0000000..ec941d8 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0143_rev1.h +@@ -0,0 +1,456 @@ ++/* ++ * ON Semiconductor AR0143 sensor camera wizard 1344x968@30/BGGR/BT601/RAW12 ++ * ++ * Copyright (C) 2018-2019 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++#define AR0143_Sensor_Setup ++#define AR0143_Recommended_Settings ++#define AR0143_Sequencer_Update ++#define AR0143_Parallel_Timing_Setup ++#define AR0143_Readout_Mode_Configuration ++#define AR0143_HDR_Readout_Mode_Configuration ++#define AR0143_Full_Res_FOV ++#define AR0143_3exp_30FPS_Timing_and_Exposure ++#define AR0143_Parallel_HDR_12_bit_Output ++#define AR0143_Trigger_Enable ++ ++/* 3-Exp HDR Mode Full Resolution Parallel Mode 30FPS PLL Enable, XCLK=27MHz */ ++static const struct ar0143_reg ar0143_regs_wizard_rev1[] = { ++//{0x301A, 0x0001}, // reset (broken) ++//{AR0143_DELAY, 100}, ++ ++#ifdef AR0143_Sensor_Setup ++{0x301A, 0x10D8}, // Stream off and setup parallel ++{0x3070, 0x0001}, ++{0x3070, 0x0000}, // 1: Solid color test pattern, ++ // 2: Full color bar test pattern, ++ // 3: Fade to grey color bar test pattern, ++ //256: Walking 1 test pattern (12 bit) ++#ifdef AR0143_DISPLAY_PATTERN_FIXED ++{0x3070, 0x0001}, ++#endif ++{0x3072, 0x0fff}, // R ++{0x3074, 0x0fff}, // G(GR row) ++{0x3076, 0x0fff}, // B ++{0x3078, 0x0fff}, // G(GB row) ++#ifdef AR0143_DISPLAY_PATTERN_COLOR_BAR ++{0x3070, 0x0002}, ++#endif ++{AR0143_DELAY, 250}, ++ ++#ifdef AR0143_Recommended_Settings ++{0x3100, 0x4000}, ++{0x3102, 0x6060}, ++{0x3104, 0x6060}, ++{0x3106, 0x6060}, ++{0x3108, 0x0F9F}, ++{0x3280, 0x0FA0}, ++{0x3282, 0x0FA0}, ++{0x3284, 0x0FA0}, ++{0x3286, 0x0FA0}, ++{0x3288, 0x0FA0}, ++{0x328A, 0x0FA0}, ++{0x328C, 0x0FA0}, ++{0x328E, 0x0FA0}, ++{0x3290, 0x0FA0}, ++{0x3292, 0x0FA0}, ++{0x3294, 0x0FA0}, ++{0x3296, 0x0FA0}, ++{0x3298, 0x0FA0}, ++{0x329A, 0x0FA0}, ++{0x329C, 0x0FA0}, ++{0x329E, 0x0FA0}, ++{0x3110, 0x0011}, ++{0x3112, 0x7FE7}, ++{0x3114, 0x0000}, ++{0x3116, 0xC000}, ++{0x3120, 0x0BA0}, ++{0x3122, 0x0FA0}, ++{0x3124, 0x00B4}, ++{0x3126, 0x0030}, ++{0x3128, 0x6100}, ++{0x3506, 0x3333}, ++{0x3508, 0x3333}, ++{0x350A, 0x3333}, ++{0x350C, 0x035F}, ++{0x350E, 0xEF14}, ++{0x3086, 0x0600}, ++{0x3C00, 0xDD67}, ++{0x3092, 0x1C24}, ++{0x3096, 0x147E}, ++{0x3750, 0x147E}, ++{0x30B0, 0x0800}, ++{0x30FE, 0x0020}, ++{0x32D0, 0x3A02}, ++{0x32D6, 0x3C04}, ++{0x3C0C, 0x0516}, ++{0x3F96, 0xFFFE}, ++{0x3088, 0x6680}, ++{0x33E2, 0x0000}, ++{0x3366, 0x7777}, ++{0x3056, 0x0080}, ++{0x305C, 0x0080}, ++{0x3058, 0x0080}, ++{0x305A, 0x0080}, ++{0x306E, 0x9010}, ++{0x3044, 0x0400}, ++{0x30BA, 0x01E0}, ++{0x32EA, 0x3C0E}, ++{0x3362, 0x0000}, ++{0x3364, 0x005B}, ++{0x3370, 0x0131}, ++{0x3372, 0x700F}, ++{0x3386, 0x0000}, ++{0x3C04, 0x0E80}, ++{0x30B4, 0x0007}, ++{0x30B8, 0x0007}, ++{0x3F90, 0x0403}, ++{0x3F92, 0x0403}, ++{0x3502, 0x0808}, ++{0x3566, 0x1D28}, ++{0x3518, 0x1FFE}, ++{0x3520, 0x4688}, ++{0x3522, 0x8840}, ++{0x3524, 0x4046}, ++{0x3526, 0x0F00}, ++{0x3528, 0xDDDD}, ++{0x352C, 0x4646}, ++{0x352A, 0x089F}, ++{0x352E, 0x0011}, ++{0x3530, 0x4400}, ++{0x3536, 0xFF07}, ++{0x3538, 0xFFFF}, ++{0x353A, 0x9000}, ++{0x353C, 0x3F00}, ++{0x32EC, 0x72A1}, ++{0x3540, 0xC637}, ++{0x3542, 0x464B}, ++{0x3544, 0x4B50}, ++{0x3546, 0x545A}, ++{0x3548, 0x5500}, ++{0x354A, 0x007F}, ++{0x3556, 0x101F}, ++{0x3566, 0x3328}, ++{0x337A, 0x0B74}, ++{0x3372, 0x710F}, ++#endif /* AR0143_Recommended_Settings */ ++ ++#ifdef AR0143_Sequencer_Update ++{0x2512, 0x8000}, ++{0x2510, 0x0903}, ++{0x2510, 0x3350}, ++{0x2510, 0x2004}, ++{0x2510, 0x1420}, ++{0x2510, 0x1578}, ++{0x2510, 0x087B}, ++{0x2510, 0x24FF}, ++{0x2510, 0x24FF}, ++{0x2510, 0x24EA}, ++{0x2510, 0x2410}, ++{0x2510, 0x2224}, ++{0x2510, 0x1015}, ++{0x2510, 0x5813}, ++{0x2510, 0x0214}, ++{0x2510, 0x0024}, ++{0x2510, 0xFF24}, ++{0x2510, 0xFF24}, ++{0x2510, 0xEA23}, ++{0x2510, 0x2464}, ++{0x2510, 0x7A24}, ++{0x2510, 0x0405}, ++{0x2510, 0x2C40}, ++{0x2510, 0x0AFF}, ++{0x2510, 0x0A75}, ++{0x2510, 0x0A07}, ++{0x2510, 0x3851}, ++{0x2510, 0x1440}, ++{0x2510, 0x0004}, ++{0x2510, 0x0801}, ++{0x2510, 0x0408}, ++{0x2510, 0x1180}, ++{0x2510, 0x2652}, ++{0x2510, 0x0815}, ++{0x2510, 0x1813}, ++{0x2510, 0xC810}, ++{0x2510, 0x0210}, ++{0x2510, 0x1611}, ++{0x2510, 0x8111}, ++{0x2510, 0x8910}, ++{0x2510, 0x5612}, ++{0x2510, 0x1009}, ++{0x2510, 0x020D}, ++{0x2510, 0x0905}, ++{0x2510, 0x1588}, ++{0x2510, 0x1388}, ++{0x2510, 0x0938}, ++{0x2510, 0x1199}, ++{0x2510, 0x11D9}, ++{0x2510, 0x091E}, ++{0x2510, 0x1214}, ++{0x2510, 0x10D6}, ++{0x2510, 0x0901}, ++{0x2510, 0x1210}, ++{0x2510, 0x1212}, ++{0x2510, 0x1210}, ++{0x2510, 0x11DD}, ++{0x2510, 0x11D9}, ++{0x2510, 0x0901}, ++{0x2510, 0x1441}, ++{0x2510, 0x0904}, ++{0x2510, 0x1056}, ++{0x2510, 0x0811}, ++{0x2510, 0xDB09}, ++{0x2510, 0x0311}, ++{0x2510, 0xFB11}, ++{0x2510, 0xBB12}, ++{0x2510, 0x1A12}, ++{0x2510, 0x1008}, ++{0x2510, 0x1250}, ++{0x2510, 0x1076}, ++{0x2510, 0x10E6}, ++{0x2510, 0x1461}, ++{0x2510, 0x0906}, ++{0x2510, 0x1240}, ++{0x2510, 0x1260}, ++{0x2510, 0x091C}, ++{0x2510, 0x1460}, ++{0x2510, 0x090C}, ++{0x2510, 0x0B09}, ++{0x2510, 0x0515}, ++{0x2510, 0xC813}, ++{0x2510, 0xC808}, ++{0x2510, 0x1066}, ++{0x2510, 0x090B}, ++{0x2510, 0x1588}, ++{0x2510, 0x1388}, ++{0x2510, 0x0913}, ++{0x2510, 0x0C14}, ++{0x2510, 0x4009}, ++{0x2510, 0x0310}, ++{0x2510, 0xE611}, ++{0x2510, 0xFB12}, ++{0x2510, 0x6212}, ++{0x2510, 0x6011}, ++{0x2510, 0xFF11}, ++{0x2510, 0xFB14}, ++{0x2510, 0x4109}, ++{0x2510, 0x0210}, ++{0x2510, 0x6609}, ++{0x2510, 0x1211}, ++{0x2510, 0xBB12}, ++{0x2510, 0x6312}, ++{0x2510, 0x6014}, ++{0x2510, 0x0015}, ++{0x2510, 0x1811}, ++{0x2510, 0xB812}, ++{0x2510, 0xA012}, ++{0x2510, 0x0010}, ++{0x2510, 0x2610}, ++{0x2510, 0x0013}, ++{0x2510, 0x0011}, ++{0x2510, 0x8030}, ++{0x2510, 0x5342}, ++{0x2510, 0x1100}, ++{0x2510, 0x1002}, ++{0x2510, 0x1016}, ++{0x2510, 0x1101}, ++{0x2510, 0x1109}, ++{0x2510, 0x1056}, ++{0x2510, 0x1210}, ++{0x2510, 0x0D09}, ++{0x2510, 0x0614}, ++{0x2510, 0x4109}, ++{0x2510, 0x0714}, ++{0x2510, 0x4009}, ++{0x2510, 0x0115}, ++{0x2510, 0xCC13}, ++{0x2510, 0xCC09}, ++{0x2510, 0x1611}, ++{0x2510, 0x4909}, ++{0x2510, 0x0815}, ++{0x2510, 0x8813}, ++{0x2510, 0x8809}, ++{0x2510, 0x1B11}, ++{0x2510, 0x5909}, ++{0x2510, 0x0B12}, ++{0x2510, 0x1409}, ++{0x2510, 0x0112}, ++{0x2510, 0x1010}, ++{0x2510, 0xD612}, ++{0x2510, 0x1212}, ++{0x2510, 0x1011}, ++{0x2510, 0x5D11}, ++{0x2510, 0x5910}, ++{0x2510, 0x5609}, ++{0x2510, 0x0311}, ++{0x2510, 0x5B08}, ++{0x2510, 0x1441}, ++{0x2510, 0x0901}, ++{0x2510, 0x1440}, ++{0x2510, 0x090C}, ++{0x2510, 0x117B}, ++{0x2510, 0x113B}, ++{0x2510, 0x121A}, ++{0x2510, 0x1210}, ++{0x2510, 0x0901}, ++{0x2510, 0x1250}, ++{0x2510, 0x10F6}, ++{0x2510, 0x10E6}, ++{0x2510, 0x1460}, ++{0x2510, 0x0901}, ++{0x2510, 0x15AB}, ++{0x2510, 0x13AB}, ++{0x2510, 0x1240}, ++{0x2510, 0x1260}, ++{0x2510, 0x0924}, ++{0x2510, 0x1588}, ++{0x2510, 0x0902}, ++{0x2510, 0x1066}, ++{0x2510, 0x0B08}, ++{0x2510, 0x1388}, ++{0x2510, 0x0907}, ++{0x2510, 0x158D}, ++{0x2510, 0x138D}, ++{0x2510, 0x090D}, ++{0x2510, 0x1588}, ++{0x2510, 0x1388}, ++{0x2510, 0x0909}, ++{0x2510, 0x0C09}, ++{0x2510, 0x0214}, ++{0x2510, 0x4009}, ++{0x2510, 0x0710}, ++{0x2510, 0xE612}, ++{0x2510, 0x6212}, ++{0x2510, 0x6011}, ++{0x2510, 0x7F11}, ++{0x2510, 0x7B10}, ++{0x2510, 0x6609}, ++{0x2510, 0x0614}, ++{0x2510, 0x4109}, ++{0x2510, 0x0114}, ++{0x2510, 0x4009}, ++{0x2510, 0x0D11}, ++{0x2510, 0x3B12}, ++{0x2510, 0x6312}, ++{0x2510, 0x6014}, ++{0x2510, 0x0015}, ++{0x2510, 0x5A11}, ++{0x2510, 0x3812}, ++{0x2510, 0xA012}, ++{0x2510, 0x0010}, ++{0x2510, 0x2610}, ++{0x2510, 0x0013}, ++{0x2510, 0x4211}, ++{0x2510, 0x0043}, ++{0x2510, 0x7A06}, ++{0x2510, 0x0508}, ++{0x2510, 0x0741}, ++{0x2510, 0x3750}, ++{0x2510, 0x2C2C}, ++{0x2510, 0xFE11}, ++{0x2510, 0xFE05}, ++{0x2510, 0x2C2C}, ++ ++{0x1008, 0x02A1}, ++{0x100C, 0x042D}, ++{0x100E, 0x05B9}, ++{0x1010, 0x0115}, ++ ++{0x3230, 0x023F}, ++{0x3232, 0x03CB}, ++{0x3234, 0x0557}, ++{0x3236, 0x00B3}, ++{0x32E6, 0x009A}, ++#endif /* AR0143_Sequencer_Update */ ++ ++{0x350C, 0x035F}, ++{0x32D0, 0x3A02}, ++{0x32D2, 0x3508}, ++{0x32D4, 0x3702}, ++{0x32D6, 0x3C04}, ++{0x32DC, 0x370A}, ++#endif /* AR0143_Sensor_Setup */ ++ ++#ifdef AR0143_Parallel_Timing_Setup ++/* PCLK=27MHz/5 *93 /1/10 = 50.22MHz - MAXIM serializers */ ++{0x302A, 10}, // VT_PIX_CLK_DIV ++{0x302C, 1}, // VT_SYS_CLK_DIV ++{0x302E, 5}, // PRE_PLL_CLK_DIV ++{0x3030, 93}, // PLL_MULTIPLIER ++{0x3036, 10}, // OP_WORD_CLK_DIV ++{0x3038, 1}, // OP_SYS_CLK_DIV ++#endif /* AR0143_Parallel_Timing_Setup */ ++ ++#ifdef AR0143_Readout_Mode_Configuration ++{0x30A2, 0x0001}, // X_ODD_INC_ ++{0x30A6, 0x0001}, // Y_ODD_INC_ ++{0x3040, 0x0000}, // READ_MODE ++{0x3082, 0x0008}, // OPERATION_MODE_CTRL: 3exp ++{0x30BA, 0x01E2}, // DIGITAL_CTRL: 3exp max ++{0x3044, 0x0400}, // DARK_CONTROL ++{0x3064, 0x1802}, // SMIA_TEST: disable emb data and stats ++{0x33E0, 0x0880}, // TEST_ASIL_ROWS ++{0x3180, 0x0080}, // RESERVED_MFR_3180 ++{0x33E4, 0x0080}, // RESERVED_MFR_33E4 ++#endif /* AR0143_Readout_Mode_Configuration */ ++ ++#ifdef AR0143_HDR_Readout_Mode_Configuration ++#ifdef AR0143_EMBEDDED_LINE ++{0x3064, 0x1982}, // SMIA_TEST: enable emb data and stats ++#endif ++#endif /* AR0143_HDR_Readout_Mode_Configuration */ ++ ++#ifdef AR0143_Full_Res_FOV ++{0x31B0, 0x0006}, // FRAME_PREAMBLE ++{0x31B2, 0x0045}, // LINE_PREAMBLE ++{0x3004, AR0143_X_START}, // X_ADDR_START_ ++{0x3008, AR0143_X_END}, // X_ADDR_END_ ++{0x3002, AR0143_Y_START}, // Y_ADDR_START_ ++{0x3006, AR0143_Y_END}, // Y_ADDR_END_ ++{0x3400, 0x10}, ++{0x3402, 0x0000 | AR0143_MAX_WIDTH}, // X_OUTPUT_CONTROL ++{0x3404, 0x0000 | AR0143_MAX_HEIGHT}, // Y_OUTPUT_CONTROL ++#endif /* AR0143_Full_Res_FOV */ ++ ++#ifdef AR0143_3exp_30FPS_Timing_and_Exposure ++{0x3082, 0x0008}, // OPERATION_MODE_CTRL: 3exp ++{0x30BA, 0x01E2}, // DIGITAL_CTRL: 3exp max ++/* Row and Pixel Timing */ ++{0x300C, AR0143_SENSOR_WIDTH + 144}, // LINE_LENGTH_PCK_ ++{0x300A, AR0143_SENSOR_HEIGHT + 157}, // FRAME_LENGTH_LINES_ ++{0x3042, 0}, // EXTRA_DELAY ++/* Exposure Settings */ ++{0x3238, 0x0222}, // EXPOSURE_RATIO ++{0x3012, 0x0300}, // COARSE_INTEGRATION_TIME_ ++ ++{0x3014, AR0143_SENSOR_WIDTH + 144 + 154}, // FINE_INTEGRATION_TIME_ = LINE_LENGTH_PCK_ + 154 ++{0x321E, AR0143_SENSOR_WIDTH + 144 + 154}, // FINE_INTEGRATION_TIME2 ++{0x3222, AR0143_SENSOR_WIDTH + 144 + 154}, // FINE_INTEGRATION_TIME3 ++ ++{0x30B0, 0x0800}, // DIGITAL_TEST ++{0x32EA, 0x3C0E}, ++{0x32EC, 0x72A1}, ++{0x3C06, 0x083C}, ++{0x3C08, 0x0100}, ++#endif /* AR0143_3exp_30FPS_Timing_and_Exposure */ ++ ++#ifdef AR0143_Parallel_HDR_12_bit_Output ++{0x31D0, 0x0001}, // COMPANDING ++{0x31AE, 0x0001}, // SERIAL_FORMAT ++{0x31AC, 0x140C}, // DATA_FORMAT_BITS: ADC20, RAW12 ++{0x301A, 0x11d8}, // RESET_REGISTER ++#endif /* AR0143_Parallel_HDR_12_bit_Output */ ++ ++#ifdef AR0143_Trigger_Enable ++{0x340A, 0x0070}, // GPIO_CONTROL1: GPIO3 is trigger ++{0x340C, 0x0080}, // GPIO_CONTROL2: GPIO3 is trigger ++{0x30CE, 0x0120}, // TRIGGER_MODE ++//{0x30DC, 0x0120}, // TRIGGER_DELAY ++#endif ++}; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0156-AR0143-enable-3exp-in-custom-setup.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0156-AR0143-enable-3exp-in-custom-setup.patch new file mode 100644 index 00000000..b6f930c2 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0156-AR0143-enable-3exp-in-custom-setup.patch @@ -0,0 +1,61 @@ +From cc691c2648df88a97908cb8d689267db82d0055d Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Tue, 19 Mar 2019 13:43:32 +0300 +Subject: [PATCH 105/122] AR0143: enable 3exp in custom setup + +This enabled 3exp in custom setup + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ar0143_custom.h | 22 ++++++++++++---------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ar0143_custom.h b/drivers/media/i2c/soc_camera/ar0143_custom.h +index 2d4aa1c..e5bc37a 100644 +--- a/drivers/media/i2c/soc_camera/ar0143_custom.h ++++ b/drivers/media/i2c/soc_camera/ar0143_custom.h +@@ -10,8 +10,8 @@ + */ + + static const struct ar0143_reg ar0143_regs_wizard_custom[] = { +-{0x301A, 0x0001}, // reset +-{AR0143_DELAY, 100}, ++//{0x301A, 0x0001}, // reset (broken) ++//{AR0143_DELAY, 100}, + {0x301A, 0x10D8}, // Stream off and setup parallel + {0x3070, 0x0001}, + {0x3070, 0x0000}, // 1: Solid color test pattern, +@@ -485,20 +485,22 @@ static const struct ar0143_reg ar0143_regs_wizard_custom[] = { + {0x1010, 0x0155}, // FINE_INTEGRATION_TIME4_MIN + #ifdef NEW_TBL + {0x3012, 0x0206}, // COARSE_INTEGRATION_TIME_ +-{0x3014, 0x06e8}, // FINE_INTEGRATION_TIME_ +-{0x321E, 0x06E8}, // FINE_INTEGRATION_TIME2 +-{0x3222, 0x06E8}, // FINE_INTEGRATION_TIME3 ++{0x3014, AR0143_SENSOR_WIDTH + 144 + 154}, // FINE_INTEGRATION_TIME_ ++{0x321E, AR0143_SENSOR_WIDTH + 144 + 154}, // FINE_INTEGRATION_TIME2 ++{0x3222, AR0143_SENSOR_WIDTH + 144 + 154}, // FINE_INTEGRATION_TIME3 + #else + {0x3012, 0x0332}, // COARSE_INTEGRATION_TIME_ +-{0x3014, 0x0694}, // FINE_INTEGRATION_TIME_ +-{0x321E, 0x0694}, // FINE_INTEGRATION_TIME2 +-{0x3222, 0x0694}, // FINE_INTEGRATION_TIME3 ++{0x3014, AR0143_SENSOR_WIDTH + 144 + 154}, // FINE_INTEGRATION_TIME_ ++{0x321E, AR0143_SENSOR_WIDTH + 144 + 154}, // FINE_INTEGRATION_TIME2 ++{0x3222, AR0143_SENSOR_WIDTH + 144 + 154}, // FINE_INTEGRATION_TIME3 + #endif + {0x32EC, 0x72A0}, // RESERVED_MFR_32EC + {0x31C6, 0x0000}, // HISPI_CONTROL + #ifdef NEW_TBL +-{0x3082, 0x0000}, // OPERATION_MODE_CTRL: 1 exposure +-{0x3238, 0x0222}, // auto exposure time ratio - Fixed! ++{0x3082, 0x0008}, // OPERATION_MODE_CTRL: 3 exposures ++{0x3238, 0x0444}, // auto exposure time ratio ++{0x33DA, 0x0001}, // OC_LUT_CONTROL: OC_LEGACY_COMPANDNG ++{0x301E, 0x00A8}, // DATA_PEDESTAL + #else + // patch start + //{0x30BA, 0x01E2}, // DIGITAL_CTRL: 3 exposures +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0157-AR0143-add-choose-of-imager-setup.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0157-AR0143-add-choose-of-imager-setup.patch new file mode 100644 index 00000000..ff076cf0 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0157-AR0143-add-choose-of-imager-setup.patch @@ -0,0 +1,132 @@ +From fa541006e93ceccfbee6a8b89026c3aa96036c16 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Sat, 16 Mar 2019 10:28:42 +0300 +Subject: [PATCH 106/122] AR0143: add choose of imager setup + +in command line: +ar0143.setup=0 - choose custom setup +ar0143.setup=1 - choose ONSEMI rev1 setup (default) + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ar0143.c | 41 ++++++++++++++++++++++++++--------- + drivers/media/i2c/soc_camera/ar0143.h | 2 +- + 2 files changed, 32 insertions(+), 11 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ar0143.c b/drivers/media/i2c/soc_camera/ar0143.c +index 65dc4fb..b0ed9ff 100644 +--- a/drivers/media/i2c/soc_camera/ar0143.c ++++ b/drivers/media/i2c/soc_camera/ar0143.c +@@ -25,6 +25,7 @@ + #define AR0143_I2C_ADDR 0x10 + + #define AR0143_PID 0x3000 ++#define AR0143_REV 0x300E + #define AR0143_VERSION_REG 0x0D54 + + #define AR0143_MEDIA_BUS_FMT MEDIA_BUS_FMT_SGRBG12_1X12 +@@ -36,6 +37,7 @@ struct ar0143_priv { + struct v4l2_rect rect; + int init_complete; + u8 id[6]; ++ int setup; + /* serializers */ + int max9286_addr; + int max9271_addr; +@@ -49,6 +51,10 @@ struct ar0143_priv { + int frame_preamble; + }; + ++static int setup = 1; ++module_param(setup, int, 0644); ++MODULE_PARM_DESC(setup, " Forse setup (default: 1 - rev1)"); ++ + static inline struct ar0143_priv *to_ar0143(const struct i2c_client *client) + { + return container_of(i2c_get_clientdata(client), struct ar0143_priv, sd); +@@ -432,7 +438,7 @@ static int ar0143_initialize(struct i2c_client *client) + { + struct ar0143_priv *priv = to_ar0143(client); + u16 val = 0; +- u16 pid = 0; ++ u16 pid = 0, rev = 0; + int ret = 0; + int tmp_addr; + +@@ -447,8 +453,19 @@ static int ar0143_initialize(struct i2c_client *client) + goto err; + } + ++ /* check revision */ ++ reg16_read16(client, AR0143_REV, &rev); ++ /* Read OTP IDs */ ++ ar0143_otp_id_read(client); + /* Program wizard registers */ +- ar0143_set_regs(client, ar0143_regs_wizard_rev1, ARRAY_SIZE(ar0143_regs_wizard_rev1)); ++ switch (priv->setup) { ++ case 0: ++ ar0143_set_regs(client, ar0143_regs_wizard_custom, ARRAY_SIZE(ar0143_regs_wizard_custom)); ++ break; ++ case 1: ++ default: ++ ar0143_set_regs(client, ar0143_regs_wizard_rev1, ARRAY_SIZE(ar0143_regs_wizard_rev1)); ++ } + + tmp_addr = client->addr; + if (priv->max9271_addr) { +@@ -467,15 +484,12 @@ static int ar0143_initialize(struct i2c_client *client) + client->addr = tmp_addr; + + /* Enable stream */ +- reg16_read16(client, 0x301a, &val); // read inital reset_register value +- val |= (1 << 2); // Set streamOn bit +- reg16_write16(client, 0x301a, val); // Start Streaming ++ reg16_read16(client, 0x301a, &val); ++ val |= (1 << 2); ++ reg16_write16(client, 0x301a, val); + +- /* Read OTP IDs */ +- ar0143_otp_id_read(client); +- +- dev_info(&client->dev, "ar0143 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", +- pid, AR0143_MAX_WIDTH, AR0143_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++ dev_info(&client->dev, "ar0143 PID %x (rev %x), res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, rev, AR0143_MAX_WIDTH, AR0143_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); + err: + ar0143_s_port(client, 0); + +@@ -489,6 +503,9 @@ static int ar0143_parse_dt(struct device_node *np, struct ar0143_priv *priv) + struct device_node *endpoint = NULL, *rendpoint = NULL; + int tmp_addr = 0; + ++ if (of_property_read_u32(np, "onnn,setup", &priv->setup)) ++ priv->setup = 1; ++ + for (i = 0; ; i++) { + endpoint = of_graph_get_next_endpoint(np, endpoint); + if (!endpoint) +@@ -542,6 +559,10 @@ static int ar0143_parse_dt(struct device_node *np, struct ar0143_priv *priv) + + mdelay(10); + ++ /* module params override dts */ ++ if (setup != 1) ++ priv->setup = setup; ++ + return 0; + } + +diff --git a/drivers/media/i2c/soc_camera/ar0143.h b/drivers/media/i2c/soc_camera/ar0143.h +index 042dd50..14d8175 100644 +--- a/drivers/media/i2c/soc_camera/ar0143.h ++++ b/drivers/media/i2c/soc_camera/ar0143.h +@@ -32,5 +32,5 @@ struct ar0143_reg { + u16 val; + }; + +-//#include "ar0143_custom.h" ++#include "ar0143_custom.h" + #include "ar0143_rev1.h" +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0158-MAX9286-fix-BWS-setup-to-reserve-reboot.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0158-MAX9286-fix-BWS-setup-to-reserve-reboot.patch new file mode 100644 index 00000000..1c8cd843 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0158-MAX9286-fix-BWS-setup-to-reserve-reboot.patch @@ -0,0 +1,85 @@ +From 7684c917aba38e78e8ded754662de7ee5bec18be Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Tue, 19 Mar 2019 13:49:20 +0300 +Subject: [PATCH 107/122] MAX9286: fix BWS setup to reserve reboot + +This fixes reset/reboot for BWS=1 mode + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/max9286.c | 24 +++++++++++++++++------- + 1 file changed, 17 insertions(+), 7 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/max9286.c b/drivers/media/i2c/soc_camera/max9286.c +index 88eab02..c69be50 100644 +--- a/drivers/media/i2c/soc_camera/max9286.c ++++ b/drivers/media/i2c/soc_camera/max9286.c +@@ -212,7 +212,8 @@ static void max9286_preinit(struct i2c_client *client, int addr) + reg8_write(client, 0x00, 0x00); /* disable all GMSL links [0:3] */ + // usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ + reg8_write(client, 0x1b, priv->switchin); /* coax polarity (default - normal) */ +- reg8_write(client, 0x1c, priv->him ? 0xf4 : 0x04); /* high-immunity/legacy mode, BWS: 24-bit */ ++ reg8_write(client, 0x1c, (priv->him ? 0xf0 : 0x00) | ++ (priv->bws ? 0x05 : 0x04)); /* high-immunity/legacy mode, BWS 24bit */ + } + + static void max9286_sensor_reset(struct i2c_client *client, int addr, int reset_on) +@@ -253,8 +254,6 @@ static void max9286_postinit(struct i2c_client *client, int addr) + reg8_write(client, 0x0b, priv->csi2_outord); /* CSI2 output order */ + reg8_write(client, 0x15, 0x9b); /* enable CSI output, VC is set accordingly to Link number, BIT7 magic must be set */ + reg8_write(client, 0x1b, priv->switchin | priv->links_mask); /* coax polarity, enable equalizer for CAMs */ +- reg8_write(client, 0x1c, (priv->him ? 0xf0 : 0x00) | +- (priv->bws ? 0x05 : 0x04)); /* high-immunity/legacy mode, BWS 24/32-bit */ + usleep_range(5000, 5500); /* wait 2ms after any change of reverse channel settings */ + + if (strcmp(priv->fsync_mode, "manual") == 0) { +@@ -292,6 +291,12 @@ static int max9286_reverse_channel_setup(struct i2c_client *client, int idx) + usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ + reg8_write(client, 0x04, 0x43); /* wake-up, enable reverse_control/conf_link */ + usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ if (priv->bws) { ++ reg8_write(client, 0x07, 0x04 | (priv->pclk_rising_edge ? 0 : 0x10) | ++ (priv->dbl ? 0x80 : 0) | ++ (priv->bws ? 0x20 : 0)); /* RAW/YUV, PCLK edge, HS/VS encoding enabled, DBL mode, BWS 24/32-bit */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ } + } else { + /* Legacy mode setup */ + client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ +@@ -305,6 +310,12 @@ static int max9286_reverse_channel_setup(struct i2c_client *client, int idx) + reg8_write(client, 0x08, 0x01); /* reverse channel receiver high threshold enable */ + reg8_write(client, 0x97, 0x5f); /* enable reverse control channel programming (MAX96705-MAX96711 only) */ + usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ if (priv->bws) { ++ reg8_write(client, 0x07, 0x04 | (priv->pclk_rising_edge ? 0 : 0x10) | ++ (priv->dbl ? 0x80 : 0) | ++ (priv->bws ? 0x20 : 0)); /* RAW/YUV, PCLK edge, HS/VS encoding enabled, DBL mode, BWS 24/32-bit */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ } + + client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ + reg8_write(client, 0x3b, 0x19); /* reverse channel increase amplitude 170mV to compensate high threshold enabled */ +@@ -391,7 +402,9 @@ static void max9286_gmsl_link_setup(struct i2c_client *client, int idx) + /* GMSL setup */ + client->addr = 0x40; /* MAX9271-CAMx I2C */ + reg8_write(client, 0x0d, 0x22 | MAXIM_I2C_I2C_SPEED); /* disable artificial ACK, I2C speed set */ +- reg8_write(client, 0x07, 0x04 | (priv->pclk_rising_edge ? 0 : 0x10) | (priv->dbl ? 0x80 : 0)); /* RAW/YUV, PCLK edge, HS/VS encoding enabled, DBL mode, BWS 24-bit */ ++ reg8_write(client, 0x07, 0x04 | (priv->pclk_rising_edge ? 0 : 0x10) | ++ (priv->dbl ? 0x80 : 0) | ++ (priv->bws ? 0x20 : 0)); /* RAW/YUV, PCLK edge, HS/VS encoding enabled, DBL mode, BWS 24/32-bit */ + usleep_range(2000, 2500); /* wait 2ms */ + reg8_write(client, 0x02, 0xff); /* spread spectrum +-4%, pclk range automatic, Gbps automatic */ + usleep_range(2000, 2500); /* wait 2ms */ +@@ -507,9 +520,6 @@ static void max9286_gmsl_link_setup(struct i2c_client *client, int idx) + client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C new */ + maxim_max927x_dump_regs(client); + #endif +- reg8_write(client, 0x07, 0x04 | (priv->pclk_rising_edge ? 0 : 0x10) | +- (priv->dbl ? 0x80 : 0) | +- (priv->bws ? 0x20 : 0)); /* RAW/YUV, PCLK edge, HS/VS encoding enabled, DBL mode, BWS 24/32-bit */ + } + + static int max9286_initialize(struct i2c_client *client) +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0159-MAX9286-adjust-POC-trigger-for-unstable-link.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0159-MAX9286-adjust-POC-trigger-for-unstable-link.patch new file mode 100644 index 00000000..0084006a --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0159-MAX9286-adjust-POC-trigger-for-unstable-link.patch @@ -0,0 +1,88 @@ +From 3eb6986dcd340226956239c94adceff9e7a4f7af Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Tue, 19 Mar 2019 13:51:26 +0300 +Subject: [PATCH 108/122] MAX9286: adjust POC trigger for unstable link + +Enhance POC trgger on camera detect fails +Add lock/link status show + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/max9286.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/max9286.c b/drivers/media/i2c/soc_camera/max9286.c +index c69be50..3184ff1 100644 +--- a/drivers/media/i2c/soc_camera/max9286.c ++++ b/drivers/media/i2c/soc_camera/max9286.c +@@ -108,6 +108,10 @@ static int active_low_resetb; + module_param(active_low_resetb, int, 0644); + MODULE_PARM_DESC(active_low_resetb, " Serializer GPIO reset level (default: 0 - active high)"); + ++static int timeout_n = 100; ++module_param(timeout_n, int, 0644); ++MODULE_PARM_DESC(timeout_n, " Timeout of link detection (default: 100 retries)"); ++ + static int poc_delay = 50; + module_param(poc_delay, int, 0644); + MODULE_PARM_DESC(poc_delay, " Delay in ms after POC enable (default: 50 ms)"); +@@ -270,9 +274,9 @@ static void max9286_postinit(struct i2c_client *client, int addr) + static int max9286_reverse_channel_setup(struct i2c_client *client, int idx) + { + struct max9286_priv *priv = i2c_get_clientdata(client); +- u8 val = 0; ++ u8 val = 0, lock_sts = 0, link_sts = 0; + int timeout = priv->timeout; +- char timeout_str[10]; ++ char timeout_str[40]; + int ret = 0; + + /* Reverse channel enable */ +@@ -340,8 +344,8 @@ static int max9286_reverse_channel_setup(struct i2c_client *client, int idx) + break; + } + +- if (timeout == priv->timeout / 2 && poc_trig) { +- if (!IS_ERR(priv->poc_gpio[idx])) { ++ if (poc_trig) { ++ if (!IS_ERR(priv->poc_gpio[idx]) && (timeout % poc_trig == 0)) { + gpiod_direction_output(priv->poc_gpio[idx], 0); /* POC power off */ + mdelay(200); + gpiod_direction_output(priv->poc_gpio[idx], 1); /* POC power on */ +@@ -352,6 +356,10 @@ static int max9286_reverse_channel_setup(struct i2c_client *client, int idx) + + max9286_sensor_reset(client, client->addr, 1); /* sensor reset */ + ++ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ ++ reg8_read(client, 0x27, &lock_sts); /* LOCK status */ ++ reg8_read(client, 0x49, &link_sts); /* LINK status */ ++ + if (!timeout) { + ret = -ETIMEDOUT; + goto out; +@@ -362,11 +370,11 @@ static int max9286_reverse_channel_setup(struct i2c_client *client, int idx) + priv->csi2_outord |= ((hweight8(priv->links_mask) - 1) << (idx * 2)); + + out: +- sprintf(timeout_str, "retries=%d", priv->timeout - timeout); ++ sprintf(timeout_str, "retries=%d lock_sts=%d link_sts=0x%x", priv->timeout - timeout, !!(lock_sts & 0x80), link_sts & (0x11 << idx)); + dev_info(&client->dev, "link%d %s %sat 0x%x %s %s\n", idx, ser_name(priv->ser_id), + ret == -EADDRINUSE ? "already " : "", priv->max9271_addr_map[idx], + ret == -ETIMEDOUT ? "not found: timeout GMSL link establish" : "", +- priv->timeout - timeout? timeout_str : ""); ++ priv->timeout - timeout ? timeout_str : ""); + + return ret; + } +@@ -741,6 +749,8 @@ static int max9286_parse_dt(struct i2c_client *client) + priv->gpio_resetb = gpio_resetb; + if (active_low_resetb) + priv->active_low_resetb = active_low_resetb; ++ if (timeout_n) ++ priv->timeout = timeout_n; + if (poc_delay) + priv->poc_delay = poc_delay; + if (bws) +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0160-lvds-onsemi-fix-revsion-parsing.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0160-lvds-onsemi-fix-revsion-parsing.patch new file mode 100644 index 00000000..fa302da8 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0160-lvds-onsemi-fix-revsion-parsing.patch @@ -0,0 +1,89 @@ +From 9a42f3263afe102eb8573f68a20054235a32b3c6 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Thu, 25 Apr 2019 12:38:47 +0300 +Subject: [PATCH 109/122] lvds: onsemi: fix revsion parsing + +Fix revision parsing on ONSEMI imagers + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ar0143.c | 2 +- + drivers/media/i2c/soc_camera/ar0231.c | 2 +- + drivers/media/i2c/soc_camera/ar0233.c | 11 +++++++---- + drivers/media/i2c/soc_camera/ar0323.c | 2 +- + 4 files changed, 10 insertions(+), 7 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ar0143.c b/drivers/media/i2c/soc_camera/ar0143.c +index b0ed9ff..01494fe 100644 +--- a/drivers/media/i2c/soc_camera/ar0143.c ++++ b/drivers/media/i2c/soc_camera/ar0143.c +@@ -25,7 +25,7 @@ + #define AR0143_I2C_ADDR 0x10 + + #define AR0143_PID 0x3000 +-#define AR0143_REV 0x300E ++#define AR0143_REV 0x31FE + #define AR0143_VERSION_REG 0x0D54 + + #define AR0143_MEDIA_BUS_FMT MEDIA_BUS_FMT_SGRBG12_1X12 +diff --git a/drivers/media/i2c/soc_camera/ar0231.c b/drivers/media/i2c/soc_camera/ar0231.c +index 07f2b5e..05037c7 100644 +--- a/drivers/media/i2c/soc_camera/ar0231.c ++++ b/drivers/media/i2c/soc_camera/ar0231.c +@@ -25,7 +25,7 @@ + static const int ar0231_i2c_addr[] = {0x10, 0x20}; + + #define AR0231_PID 0x3000 +-#define AR0231_REV 0x300E ++#define AR0231_REV 0x31FE + #define AR0231_VERSION_REG 0x0354 + + #define AR0231_MEDIA_BUS_FMT MEDIA_BUS_FMT_SGRBG12_1X12 +diff --git a/drivers/media/i2c/soc_camera/ar0233.c b/drivers/media/i2c/soc_camera/ar0233.c +index 19386bb..e18fa55 100644 +--- a/drivers/media/i2c/soc_camera/ar0233.c ++++ b/drivers/media/i2c/soc_camera/ar0233.c +@@ -25,7 +25,7 @@ + static const int ar0233_i2c_addr[] = {0x10, 0x20}; + + #define AR0233_PID 0x3000 +-#define AR0233_REV 0x300E ++#define AR0233_REV 0x31FE + #define AR0233_VERSION_REG 0x0956 + + #define AR0233_MEDIA_BUS_FMT MEDIA_BUS_FMT_SGRBG12_1X12 +@@ -410,12 +410,15 @@ static int ar0233_initialize(struct i2c_client *client) + /* Read OTP IDs */ + ar0233_otp_id_read(client); + /* Program wizard registers */ +- switch (rev) { +- case 0x2015: ++ switch (rev & 0xf) { ++ case 0x1: ++ ar0233_set_regs(client, ar0233_regs_wizard_rev1, ARRAY_SIZE(ar0233_regs_wizard_rev1)); ++ break; ++ case 0x2: + ar0233_set_regs(client, ar0233_regs_wizard_rev2, ARRAY_SIZE(ar0233_regs_wizard_rev2)); + break; + default: +- ar0233_set_regs(client, ar0233_regs_wizard_rev1, ARRAY_SIZE(ar0233_regs_wizard_rev1)); ++ dev_err(&client->dev, "Unsupported chip revision\n"); + } + + /* Enable stream */ +diff --git a/drivers/media/i2c/soc_camera/ar0323.c b/drivers/media/i2c/soc_camera/ar0323.c +index d29f4ad..2ee5526 100644 +--- a/drivers/media/i2c/soc_camera/ar0323.c ++++ b/drivers/media/i2c/soc_camera/ar0323.c +@@ -25,7 +25,7 @@ + static const int ar0323_i2c_addr[] = {0x10, 0x20}; + + #define AR0323_PID 0x3000 +-#define AR0323_REV 0x300E ++#define AR0323_REV 0x31FE + #define AR0323_VERSION_REG 0x0D56 + + #define AR0323_MEDIA_BUS_FMT MEDIA_BUS_FMT_SGRBG12_1X12 +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0161-lvds-AR0233-add-module-trigger-parameter.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0161-lvds-AR0233-add-module-trigger-parameter.patch new file mode 100644 index 00000000..192a637d --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0161-lvds-AR0233-add-module-trigger-parameter.patch @@ -0,0 +1,116 @@ +From 86f4fd9830600c2ffe9fbdb169a356a5a623fb0c Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Thu, 25 Apr 2019 22:33:55 +0300 +Subject: [PATCH 110/122] lvds: AR0233: add module trigger parameter + +This add trigger as module parameter or dts since this is hardware +dependent + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ar0233.c | 20 ++++++++++++++++++-- + drivers/media/i2c/soc_camera/ar0233_rev1.h | 8 -------- + drivers/media/i2c/soc_camera/ar0233_rev2.h | 9 --------- + 3 files changed, 18 insertions(+), 19 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ar0233.c b/drivers/media/i2c/soc_camera/ar0233.c +index e18fa55..8257cf1 100644 +--- a/drivers/media/i2c/soc_camera/ar0233.c ++++ b/drivers/media/i2c/soc_camera/ar0233.c +@@ -41,10 +41,13 @@ struct ar0233_priv { + int ti9x4_addr; + int ti9x3_addr; + int port; +- int gpio_resetb; +- int gpio_fsin; ++ int trigger; + }; + ++static int trigger = 0; ++module_param(trigger, int, 0644); ++MODULE_PARM_DESC(trigger, " Trigger gpio number (default: 0 - GPIO0) "); ++ + static inline struct ar0233_priv *to_ar0233(const struct i2c_client *client) + { + return container_of(i2c_get_clientdata(client), struct ar0233_priv, sd); +@@ -421,8 +424,15 @@ static int ar0233_initialize(struct i2c_client *client) + dev_err(&client->dev, "Unsupported chip revision\n"); + } + ++ /* Enable trigger*/ ++ reg16_write16(client, 0x340A, (~(BIT(priv->trigger) << 4)) & 0xf0); /* GPIO_CONTROL1: GPIOn input enable */ ++ reg16_write16(client, 0x340C, (0x2 << 2*priv->trigger)); /* GPIO_CONTROL2: GPIOn is trigger */ ++ reg16_write16(client, 0x30CE, 0x0120); /* TRIGGER_MODE */ ++ //reg16_write16(client, 0x30DC, 0x0120); /* TRIGGER_DELAY */ ++ + /* Enable stream */ + reg16_read16(client, 0x301a, &val); // read inital reset_register value ++ val |= (1 << 8); /* GPI pins enable */ + val |= (1 << 2); // Set streamOn bit + reg16_write16(client, 0x301a, val); // Start Streaming + +@@ -444,6 +454,8 @@ static int ar0233_parse_dt(struct device_node *np, struct ar0233_priv *priv) + if (!endpoint) + break; + ++ of_property_read_u32(endpoint, "trigger", &priv->trigger); ++ + rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); + if (!rendpoint) + continue; +@@ -473,6 +485,10 @@ static int ar0233_parse_dt(struct device_node *np, struct ar0233_priv *priv) + } + client->addr = tmp_addr; + ++ /* module params override dts */ ++ if (trigger) ++ priv->trigger = trigger; ++ + return 0; + } + +diff --git a/drivers/media/i2c/soc_camera/ar0233_rev1.h b/drivers/media/i2c/soc_camera/ar0233_rev1.h +index c29ac6a..288b465 100644 +--- a/drivers/media/i2c/soc_camera/ar0233_rev1.h ++++ b/drivers/media/i2c/soc_camera/ar0233_rev1.h +@@ -1247,12 +1247,4 @@ static const struct ar0233_reg ar0233_regs_wizard_rev1[] = { + {0x3D14, 0x001E}, + {0x3D16, 0x045E}, + #endif /* MEC DLO default */ +- +-#if 1 /* Enable_trigger_input */ +-{0x340A, 0x0070}, // GPIO_CONTROL1: GPIO1 is trigger +-{0x340C, 0x0080}, // GPIO_CONTROL2: GPIO1 is trigger +-{0x30CE, 0x0120}, // TRIGGER_MODE +-//{0x30DC, 0x0120}, // TRIGGER_DELAY +-{0x301A, 0x0118}, // GPI pins enable +-#endif /* Enable_trigger_input */ + }; +diff --git a/drivers/media/i2c/soc_camera/ar0233_rev2.h b/drivers/media/i2c/soc_camera/ar0233_rev2.h +index f4b75a2..0dea2dd 100644 +--- a/drivers/media/i2c/soc_camera/ar0233_rev2.h ++++ b/drivers/media/i2c/soc_camera/ar0233_rev2.h +@@ -28,7 +28,6 @@ + #define MIPI_DT_bit12 + #define LUT_24_to_12 + #define HDR_ratio_gain_default +-#define Enable_trigger_input + + /* 3Exp HDR 1280P Mipi_12bit_4lane_30fps, XCLK=27MHz */ + static const struct ar0233_reg ar0233_regs_wizard_rev2[] = { +@@ -1249,12 +1248,4 @@ static const struct ar0233_reg ar0233_regs_wizard_rev2[] = { + {0x300A, AR0233_SENSOR_HEIGHT + 100}, // Frame_length_Lines + {0x300C, AR0233_SENSOR_WIDTH + 400}, // Line_length_pck + {0x3012, 0x144}, //Integration_time +- +-#ifdef Enable_trigger_input +-{0x340A, 0x0070}, // GPIO_CONTROL1: GPIO1 is trigger +-{0x340C, 0x0080}, // GPIO_CONTROL2: GPIO1 is trigger +-{0x30CE, 0x0120}, // TRIGGER_MODE +-//{0x30DC, 0x0120}, // TRIGGER_DELAY +-{0x301A, 0x0118}, // GPI pins enable +-#endif /* Enable_trigger_input */ + }; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0162-lvds-AR0233-migrate-to-composed-tables.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0162-lvds-AR0233-migrate-to-composed-tables.patch new file mode 100644 index 00000000..f6475b00 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0162-lvds-AR0233-migrate-to-composed-tables.patch @@ -0,0 +1,539 @@ +From 31f98f9d7765dca4405ccf7b982d094bcd56e9d3 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Mon, 6 May 2019 22:51:09 +0300 +Subject: [PATCH 111/122] lvds: AR0233: migrate to composed tables + +Migrate to composed table +Add seperate EXTCLK (coming not from CLKOUT) +--- + drivers/media/i2c/soc_camera/ar0233.c | 49 +++++++--- + drivers/media/i2c/soc_camera/ar0233_rev1.h | 104 ++++++++++++-------- + drivers/media/i2c/soc_camera/ar0233_rev2.h | 147 ++++++++++++++--------------- + 3 files changed, 171 insertions(+), 129 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ar0233.c b/drivers/media/i2c/soc_camera/ar0233.c +index 8257cf1..54cc38a 100644 +--- a/drivers/media/i2c/soc_camera/ar0233.c ++++ b/drivers/media/i2c/soc_camera/ar0233.c +@@ -48,23 +48,42 @@ static int trigger = 0; + module_param(trigger, int, 0644); + MODULE_PARM_DESC(trigger, " Trigger gpio number (default: 0 - GPIO0) "); + ++static int extclk = 23; ++module_param(extclk, int, 0644); ++MODULE_PARM_DESC(extclk, " EXTCLK value in MHz (default: 23) "); ++ ++static char *mode = "hdr"; ++module_param(mode, charp, 0644); ++MODULE_PARM_DESC(mode, " Modes linear,hdr,seplus (default: hdr)"); ++ + static inline struct ar0233_priv *to_ar0233(const struct i2c_client *client) + { + return container_of(i2c_get_clientdata(client), struct ar0233_priv, sd); + } + +-static int ar0233_set_regs(struct i2c_client *client, +- const struct ar0233_reg *regs, int nr_regs) ++static int ar0233_set_regs(struct i2c_client *client, const struct ar0233_reg **pregs) + { +- int i; ++ struct ar0233_priv *priv = to_ar0233(client); ++ const struct ar0233_reg *regs; ++ int i, j; + +- for (i = 0; i < nr_regs; i++) { +- if (regs[i].reg == AR0233_DELAY) { +- mdelay(regs[i].val); +- continue; +- } ++ for (j = 0; ; j++) { ++ regs = pregs[j]; + +- reg16_write16(client, regs[i].reg, regs[i].val); ++ if (!pregs[j]) ++ break; ++ ++ for (i = 0; ; i++) { ++ if (!regs[i].reg && !regs[i].val) ++ break; ++ ++ if (regs[i].reg == AR0233_DELAY) { ++ mdelay(regs[i].val); ++ continue; ++ } ++ ++ reg16_write16(client, regs[i].reg, regs[i].val); ++ } + } + + return 0; +@@ -415,16 +434,22 @@ static int ar0233_initialize(struct i2c_client *client) + /* Program wizard registers */ + switch (rev & 0xf) { + case 0x1: +- ar0233_set_regs(client, ar0233_regs_wizard_rev1, ARRAY_SIZE(ar0233_regs_wizard_rev1)); ++ ar0233_set_regs(client, ar0233_regs_hdr_mipi_12bit_30fps_rev1); + break; + case 0x2: +- ar0233_set_regs(client, ar0233_regs_wizard_rev2, ARRAY_SIZE(ar0233_regs_wizard_rev2)); ++ if (extclk == 27) ++ ar0233_regs_hdr_mipi_12bit_30fps_rev2[4] = ar0233_rev2_pll_27_102_4lane_12b; ++ ++ if (strcmp(mode, "hdr") == 0) ++ ar0233_set_regs(client, ar0233_regs_hdr_mipi_12bit_30fps_rev2); ++ else ++ dev_err(&client->dev, "Unsupported mode %s\n", mode); + break; + default: + dev_err(&client->dev, "Unsupported chip revision\n"); + } + +- /* Enable trigger*/ ++ /* Enable trigger */ + reg16_write16(client, 0x340A, (~(BIT(priv->trigger) << 4)) & 0xf0); /* GPIO_CONTROL1: GPIOn input enable */ + reg16_write16(client, 0x340C, (0x2 << 2*priv->trigger)); /* GPIO_CONTROL2: GPIOn is trigger */ + reg16_write16(client, 0x30CE, 0x0120); /* TRIGGER_MODE */ +diff --git a/drivers/media/i2c/soc_camera/ar0233_rev1.h b/drivers/media/i2c/soc_camera/ar0233_rev1.h +index 288b465..7b6370b 100644 +--- a/drivers/media/i2c/soc_camera/ar0233_rev1.h ++++ b/drivers/media/i2c/soc_camera/ar0233_rev1.h +@@ -9,11 +9,9 @@ + * option) any later version. + */ + +-/* 3Exp HDR 1080p Mode MIPI-4lane 12-bit 30FPS, XCLK=24MHz */ +-static const struct ar0233_reg ar0233_regs_wizard_rev1[] = { +-{0x301A, 0x18}, // MIPI, stream OFF +-{AR0233_DELAY, 200}, // Wait 200ms +- ++static const struct ar0233_reg ar0233_rev1_Reset[] = { ++{0x301A, 0x0018}, // Stream off and setup MIPI ++{AR0233_DELAY, 200}, + {0x3070, 0x0000}, // 1: Solid color test pattern, + // 2: Full color bar test pattern, + // 3: Fade to grey color bar test pattern, +@@ -28,10 +26,12 @@ static const struct ar0233_reg ar0233_regs_wizard_rev1[] = { + #ifdef AR0233_DISPLAY_PATTERN_COLOR_BAR + {0x3070, 0x0002}, + #endif +-{AR0233_DELAY, 100}, // Wait 100ms ++{AR0233_DELAY, 100}, ++{ } ++}; /* Reset */ + +-#if 1 /* Sequencer Settings */ +-#if 1 /* Design_recommended_settings_v5 */ ++static const struct ar0233_reg ar0233_rev1_Sequencer_Settings[] = { ++/* Design_recommended_settings_v5 */ + {0x356C, 0xEA55}, //mte.Sensor.Register("DAC_LD_108_109").Value = 0xEA55& -- ADC write Memory delay 7 + {0x3566, 0x2407}, //mte.Sensor.Register("DAC_LD_102_103").Value = 0x2407& -- Enable column amp bypass for 1x + {0x3562, 0x1C08}, //mte.Sensor.Register("DAC_LD_98_99").Value = 0x1C08& -- Increase column amp current +@@ -51,9 +51,9 @@ static const struct ar0233_reg ar0233_regs_wizard_rev1[] = { + {0x353C, 0x9A0A}, //Boost_ref_Vaa lfm_dcghi(1) + {0x3526, 0x9000}, //DWellhi(16) + {0x352E, 0x90D}, //Dlfm_Dcghi(13),(Dlfm_Txhi_Buffer) = 9 +-#endif /* Design_recommended_settings_v5 */ ++/* Design_recommended_settings_v5 */ + +-#if 1 /* Pixel_char_recommended_settings_v2 */ ++/* Pixel_char_recommended_settings_v2 */ + //TXLO @HCG + {0x3514, 0x555B}, //-0.85V + {0x3578, 0x555B}, //-0.85V +@@ -68,9 +68,9 @@ static const struct ar0233_reg ar0233_regs_wizard_rev1[] = { + {0x3528, 0xEB0D}, //Ddcghi(13), txhi(11) + //DRSTHI, DRSHI + {0x352A, 0xA27}, //Drsthi (10), Drshi(7) +-#endif /* Pixel_char_recommended_settings_v2 */ ++/* Pixel_char_recommended_settings_v2 */ + +-#if 1 /* AR0233_Sequencer_LFM_HDR_v6 */ ++/* Sequencer_LFM_HDR_v6 */ + {0x2512, 0x8000}, + {0x2510, 0x070f}, + {0x2510, 0x1011}, +@@ -1096,17 +1096,29 @@ static const struct ar0233_reg ar0233_regs_wizard_rev1[] = { + {0x2510, 0xffff}, + {0x2510, 0xffff}, + {AR0233_DELAY, 100}, +-#endif /* AR0233_Sequencer_LFM_HDR_v6 */ +-#endif /* Sequencer Settings */ ++/* Sequencer_LFM_HDR_v6 */ ++{ } ++}; /* Sequencer_Settings */ ++ ++static const struct ar0233_reg ar0233_rev1_HDR_3exp_12bit[] = { ++{0x3082, 0x8}, //num_exp = 3 ++{0x3110, 0x11}, //Set bypass pix comb for HDR,Pre_hdr_gain_enable_07Jul ++{0x30BA, 0x1122}, //num_exp_max =3 ++{0x31AC, 0x140C}, //12 bit output ++{0x31D0, 0x1}, // Companding + +-{0x3082, 0x8}, //0x3082 = 2, 3 exposures +-{0x3110, 0x11}, //Set bypass pix comb for HDR,Pre_hdr_gain_enable_07Jul +-{0x30BA, 0x1122}, //Num_exp_max ++{0x3044, 0x0400}, //Dark_control ++ ++// FPS = 103.5MHz / reg0x300A / reg0x300C ++{0x300A, AR0233_SENSOR_HEIGHT + 100}, // Frame_length_Lines ++{0x300C, AR0233_SENSOR_WIDTH + 400}, // Line_length_pck + {0x3012, 0x144}, //Integration_time ++{ } ++}; /* HDR_3exp_12bit */ + +-#if 1 /* Serial 12-bit Timing Setup_108Mhz */ +-/* PCLK=24Mhz/PRE_PLL_CLK_DIV *PLL_MULTIPLIER /P1 /P4 */ +-/* PCLK=24Mhz/2 *54/1/6= 108Mhz - TI serializers */ ++static const struct ar0233_reg ar0233_rev1_Serial_12bit_Timing_Setup_103p5[] = { ++/* PCLK=DES_REFCLK /PRE_PLL_CLK_DIV *PLL_MULTIPLIER /P1 /P4 */ ++/* PCLK=23MHz/2 *54/1/6= 103.5Mhz - TI serializers */ + {0x3030, 54}, //PLL_MULTIPLIER ; 0x3030 [11:0] + {0x302E, 2}, //PRE_PLL_CLK_DIV ; 0x302E [5:0] + {0x302C, 1}, //P1 divider (vt_sys_clk_div) +@@ -1114,9 +1126,10 @@ static const struct ar0233_reg ar0233_regs_wizard_rev1[] = { + {0x3038, 2}, //P3 divider (op_sys_clk_div); 0x3038 [4:0] + {0x3036, 6}, //P4 divider (op_word_clk_div); 0x3036 [4:0] + {0x31DC, 0x1FB0}, +-#endif /* Serial 12-bit Timing Setup_108Mhz */ ++{ } ++}; /* Serial_12bit_Timing_Setup_103p5 */ + +-#if 1 /* MIPI 4 Lane 12BITS 30FPS_ext24_LIM */ ++static const struct ar0233_reg ar0233_rev1_MIPI_4Lane_12BITS[] = { + {0x31AE, 0x204}, //MIPI enable, 4 lanes + {0x31B0, 0x4B}, //frame_preamble + {0x31B2, 0x33}, //line_preamble +@@ -1125,46 +1138,43 @@ static const struct ar0233_reg ar0233_regs_wizard_rev1[] = { + {0x31B8, 0x4047}, //mipi_timing_2 + {0x31BA, 0x105}, //mipi_timing_3 + {0x31BC, 0x704}, //mipi_timing_4 +-#endif /* MIPI 4 Lane 12BITS 30FPS_ext24_LIM */ +- +-#if 1 /* MIPI_DT_bit12 */ + {0x3342, 0x122C}, // MIPI_F1_PDT_EDT + {0x3346, 0x122C}, // MIPI_F2_PDT_EDT + {0x334A, 0x122C}, // MIPI_F3_PDT_EDT + {0x334E, 0x122C}, // MIPI_F4_PDT_EDT +-#endif /* MIPI_DT_bit12 */ ++{ } ++}; /* MIPI_4Lane_12BITS */ + +-/* resolution */ ++static const struct ar0233_reg ar0233_rev1_Full_resolution[] = { + {0x3004, AR0233_X_START}, // X_ADDR_START_ + {0x3008, AR0233_X_END}, // X_ADDR_END_ + {0x3002, AR0233_Y_START}, // Y_ADDR_START_ + {0x3006, AR0233_Y_END}, // Y_ADDR_END_ ++{0x3402, (0x8000 & 0) | AR0233_MAX_WIDTH}, // X_OUTPUT_CONTROL ++{0x3404, (0x8000 & 0) | AR0233_MAX_HEIGHT}, // Y_OUTPUT_CONTROL ++{ } ++}; /* Full_resolution */ + ++static const struct ar0233_reg ar0233_rev1_disable_embed_data_stat[] = { + #ifdef AR0233_EMBEDDED_LINE + {0x3040, 0x0000}, //Embedded stat2 and data2 rows + {0x3064, 0x0180}, //Enable embedded data and stat + #else + {0x3064, 0x0}, //Disable embedded data and stat + #endif ++{ } ++}; /* disable_embed_data_stat */ + +-// FPS = 108MHz / reg0x300A / reg0x300C * (DES_REF_XTAL/24MHz) +-{0x300A, AR0233_SENSOR_HEIGHT + 100}, // Frame_length_Lines +-{0x300C, AR0233_SENSOR_WIDTH + 400}, // Line_length_pck +-//{0x300C, 0x960}, //Line_lenth_pck_FRN AEF +-//{0x300A, 0x5DC}, //FLL +- +-#if 1 /* Gain_3.28x */ ++static const struct ar0233_reg ar0233_rev1_Gain_3p28x[] = { + {0x3022, 0x01}, // GROUPED_PARAMETER_HOLD_ + {0x3362, 0x000F}, // DC_GAIN + {0x3366, 0x1111}, + {0x336A, 0x0000}, + {0x3022, 0x00}, // GROUPED_PARAMETER_HOLD_ +-#endif /* Gain_3.28x */ ++{ } ++}; /* Gain_3.28x */ + +-{0x31D0, 0x1}, // Companding +-{0x31AC, 0x140C}, // DLO20 to 12output +- +-#if 1 /* MEC DLO default */ ++static const struct ar0233_reg ar0233_rev1_MEC_DLO_default[] = { + {0x3D00, 0x6F73}, // control + {0x3D02, 0x0033}, + {0x3364, 0x068C}, // dcg_trim = 13.1 +@@ -1246,5 +1256,19 @@ static const struct ar0233_reg ar0233_regs_wizard_rev1[] = { + {0x3D12, 0x0798}, + {0x3D14, 0x001E}, + {0x3D16, 0x045E}, +-#endif /* MEC DLO default */ ++{ } ++}; /* MEC_DLO_default */ ++ ++/* 3Exp HDR, 1280P, MIPI 4-lane 12-bit, 30fps, EXTCLK=23MHz (comes from deser) */ ++static const struct ar0233_reg *ar0233_regs_hdr_mipi_12bit_30fps_rev1[] = { ++ ar0233_rev1_Reset, ++ ar0233_rev1_Sequencer_Settings, ++ ar0233_rev1_disable_embed_data_stat, ++ ar0233_rev1_HDR_3exp_12bit, ++ ar0233_rev1_Serial_12bit_Timing_Setup_103p5, ++ ar0233_rev1_MIPI_4Lane_12BITS, ++ ar0233_rev1_Full_resolution, ++ ar0233_rev1_Gain_3p28x, ++ ar0233_rev1_MEC_DLO_default, ++ NULL, + }; +diff --git a/drivers/media/i2c/soc_camera/ar0233_rev2.h b/drivers/media/i2c/soc_camera/ar0233_rev2.h +index 0dea2dd..c821d35 100644 +--- a/drivers/media/i2c/soc_camera/ar0233_rev2.h ++++ b/drivers/media/i2c/soc_camera/ar0233_rev2.h +@@ -1,7 +1,7 @@ + /* + * ON Semiconductor AR0233 sensor camera wizard 2048x1280@30/BGGR/MIPI + * +- * Copyright (C) 2018 Cogent Embedded, Inc. ++ * Copyright (C) 2018-2019 Cogent Embedded, Inc. + * + * 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 +@@ -9,31 +9,9 @@ + * option) any later version. + */ + +-#define O1_Recommended_Defaults_LFM_HDR +-#ifdef O1_Recommended_Defaults_LFM_HDR +- #define Design_recommended_settings_REV2_V9 +- #define Sequence_hidy_ar0233_REV2_V13 +- #define Pre_hdr_gain_enable +- #define Tempsensor_init +-#endif +-#define disable_embed_data_stat +-#define HDR_3exp_12bit +-#if 0 +- #define pll_27_108_4lane_12b +- #define mipi_108_12bit_4lane +-#else +- #define pll_27_124p5_4lane_12b +- #define mipi_124p5_12bit_4lane +-#endif +-#define MIPI_DT_bit12 +-#define LUT_24_to_12 +-#define HDR_ratio_gain_default +- +-/* 3Exp HDR 1280P Mipi_12bit_4lane_30fps, XCLK=27MHz */ +-static const struct ar0233_reg ar0233_regs_wizard_rev2[] = { +-{0x301A, 0x18}, // MIPI, stream OFF +-{AR0233_DELAY, 200}, // Wait 200ms +- ++static const struct ar0233_reg ar0233_rev2_Reset[] = { ++{0x301A, 0x0018}, // Stream off and setup MIPI ++{AR0233_DELAY, 200}, + {0x3070, 0x0000}, // 1: Solid color test pattern, + // 2: Full color bar test pattern, + // 3: Fade to grey color bar test pattern, +@@ -48,10 +26,12 @@ static const struct ar0233_reg ar0233_regs_wizard_rev2[] = { + #ifdef AR0233_DISPLAY_PATTERN_COLOR_BAR + {0x3070, 0x0002}, + #endif +-{AR0233_DELAY, 100}, // Wait 100ms ++{AR0233_DELAY, 100}, ++{ } ++}; /* Reset */ + +-#ifdef O1_Recommended_Defaults_LFM_HDR +-#ifdef Design_recommended_settings_REV2_V9 ++static const struct ar0233_reg ar0233_rev2_O1_Recommended_Defaults_LFM_HDR[] = { ++/* Design_recommended_settings_REV2_V9 */ + {0x3C72, 0x0076}, + {0x3C74, 0x0031}, + {0x3C76, 0x00DC}, +@@ -99,9 +79,9 @@ static const struct ar0233_reg ar0233_regs_wizard_rev2[] = { + {0x352A, 0x0827}, + {0x352C, 0xA800}, + {0x352E, 0x0908}, +-#endif /* Design_recommended_settings_REV2_V9 */ ++/* Design_recommended_settings_REV2_V9 */ + +-#ifdef Sequence_hidy_ar0233_REV2_V13 ++/* Sequence_hidy_ar0233_REV2_V13 */ + {0x2512, 0x8000}, + {0x2510, 0x070f}, + {0x2510, 0x1011}, +@@ -1127,71 +1107,74 @@ static const struct ar0233_reg ar0233_regs_wizard_rev2[] = { + {0x2510, 0x3426}, + {0x2510, 0x3614}, + {AR0233_DELAY, 100}, +-#endif /* Sequence_hidy_ar0233_REV2_V13 */ ++/* Sequence_hidy_ar0233_REV2_V13 */ + +-#ifdef Pre_hdr_gain_enable ++/* Pre_hdr_gain_enable */ + {0x3110, 0x0011}, +-#endif /* Pre_hdr_gain_enable */ + +-#ifdef Tempsensor_init ++/* Tempsensor_init */ + {0x3E94, 0x3007}, + {0x3E6E, 0xE200}, + {0x3E98, 0x1000}, + {0x3F92, 0x4C00}, + {0x30B8, 0x000B}, + {0x30B8, 0x0003}, +-#endif /* Tempsensor_init */ + + {0x3364, 0x0766}, //14.8 +-#endif /* O1_Recommended_Defaults_LFM_HDR */ ++{ } ++}; /* O1_Recommended_Defaults_LFM_HDR */ + +-#ifdef disable_embed_data_stat ++static const struct ar0233_reg ar0233_rev2_disable_embed_data_stat[] = { + {0x3064, 0x0}, // Disable embedded data and stat +-#endif /* disable_embed_data_stat */ ++#ifdef AR0233_EMBEDDED_LINE ++{0x3064, 0x0180}, // SMIA_TEST: enable emb data and stats ++#endif ++{ } ++}; /* disable_embed_data_stat */ + +-#ifdef HDR_3exp_12bit ++static const struct ar0233_reg ar0233_rev2_HDR_3exp_12bit[] = { + {0x3082, 0x8}, //num_exp = 3 + {0x30BA, 0x1122}, //num_exp_max =3 + {0x31AC, 0x140C}, //12 bit output +-#endif /* HDR_3exp_12bit */ + +-#ifdef pll_27_124p5_4lane_12b ++{0x3044, 0x0400}, //Dark_control ++ ++// FPS = 102MHz / reg0x300A / reg0x300C ++{0x300A, AR0233_SENSOR_HEIGHT + 100}, // Frame_length_Lines ++{0x300C, AR0233_SENSOR_WIDTH + 400}, // Line_length_pck ++{0x3012, 0x144}, //Integration_time ++{ } ++}; /* HDR_3exp_12bit */ ++ ++static const struct ar0233_reg ar0233_rev2_pll_23_102_4lane_12b[] = { + // serial_data_rate was *2 in REV1. but not in REV2 +-{0x3030, 0x53}, //PLL_MULTIPLIER ++/* PCLK=DES_REFCLK/PRE_PLL_CLK_DIV *PLL_MULTIPLIER /P1 /P4 */ ++/* PCLK=23Mhz/0x3 *0x50/1/6= 102Mhz - TI serializers */ ++{0x3030, 0x50}, //PLL_MULTIPLIER + {0x302E, 0x3}, //PRE_PLL_CLK_DIV + {0x302C, 0x701}, //P1 divider (vt_sys_clk_div) + {0x302A, 0x6}, //P2 divider (vt_pix_clk_div) + {0x3038, 0x2}, //P3 divider (op_sys_clk_div) + {0x3036, 0x6}, //P4 divider (op_word_clk_div) + {0x31DC, 0x1FB0}, //vcodiv +-#endif /* pll_27_124p5_4lane_12b */ +- +-#ifdef mipi_124p5_12bit_4lane +-{0x31AE, 0x204}, //serial type and lane +-{0x31B0, 0x67}, //frame_preamble +-{0x31B2, 0x30}, //line_preamble +-{0x31B4, 0x22CC}, //mipi_timing_0 +-{0x31B6, 0x33D3}, //mipi_timing_1 +-{0x31B8, 0xB04D}, //mipi_timing_2 +-{0x31BA, 0x411}, //mipi_timing_3 +-{0x31BC, 0x940E}, //mipi_timing_4 +-#endif /* mipi_124p5_12bit_4lane */ ++{ } ++}; /* pll_23_102_4lane_12b */ + +-#ifdef pll_27_108_4lane_12b ++static const struct ar0233_reg ar0233_rev2_pll_27_102_4lane_12b[] = { + // serial_data_rate was *2 in REV1. but not in REV2 +-/* PCLK=27Mhz/PRE_PLL_CLK_DIV *PLL_MULTIPLIER /P1 /P4 */ +-/* PCLK=27Mhz/0x3 *0x48/1/6= 108Mhz - TI serializers */ +-{0x3030, 0x48}, //PLL_MULTIPLIER ++/* PCLK=27Mhz/0x3 *0x44/1/6= 102Mhz - TI serializers */ ++{0x3030, 0x44}, //PLL_MULTIPLIER + {0x302E, 0x3}, //PRE_PLL_CLK_DIV + {0x302C, 0x701}, //P1 divider (vt_sys_clk_div) + {0x302A, 0x6}, //P2 divider (vt_pix_clk_div) + {0x3038, 0x2}, //P3 divider (op_sys_clk_div) + {0x3036, 0x6}, //P4 divider (op_word_clk_div) + {0x31DC, 0x1FB0}, //vcodiv +-#endif /* pll_27_108_4lane_12b */ ++{ } ++}; /* pll_27_102_4lane_12b */ + +-#ifdef mipi_108_12bit_4lane +-{0x31AE, 0x204}, //MIPI_enable ++static const struct ar0233_reg ar0233_rev2_mipi_12bit_4lane[] = { ++{0x31AE, 0x204}, //serial type and lane + {0x31B0, 0x67}, //frame_preamble + {0x31B2, 0x30}, //line_preamble + {0x31B4, 0x22CC}, //mipi_timing_0 +@@ -1199,16 +1182,14 @@ static const struct ar0233_reg ar0233_regs_wizard_rev2[] = { + {0x31B8, 0xB04D}, //mipi_timing_2 + {0x31BA, 0x411}, //mipi_timing_3 + {0x31BC, 0x940E}, //mipi_timing_4 +-#endif /* mipi_108_12bit_4lane */ +- +-#ifdef MIPI_DT_bit12 + {0x3342, 0x122C}, // MIPI_F1_PDT_EDT + {0x3346, 0x122C}, // MIPI_F2_PDT_EDT + {0x334A, 0x122C}, // MIPI_F3_PDT_EDT + {0x334E, 0x122C}, // MIPI_F4_PDT_EDT +-#endif /* MIPI_DT_bit12 */ ++{ } ++}; /* mipi_12bit_4lane */ + +-#ifdef LUT_24_to_12 ++static const struct ar0233_reg ar0233_rev2_LUT_24_to_12[] = { + {0x31AC, 0x180C}, + {0x31D0, 0x01}, //companding + {0x33DA, 0}, +@@ -1228,24 +1209,36 @@ static const struct ar0233_reg ar0233_regs_wizard_rev2[] = { + {0x33F6, 0xFF70}, + {0x33F8, 0xFF70}, + {0x33FA, 0xFF70}, //LUT_15 +-#endif /* LUT_24_to_12 */ ++{ } ++}; /* LUT_24_to_12 */ + +-/* resolution */ ++static const struct ar0233_reg ar0233_rev2_Full_resolution[] = { + {0x3004, AR0233_X_START}, // X_ADDR_START_ + {0x3008, AR0233_X_END}, // X_ADDR_END_ + {0x3002, AR0233_Y_START}, // Y_ADDR_START_ + {0x3006, AR0233_Y_END}, // Y_ADDR_END_ ++{0x3402, (0x8000 & 0) | AR0233_MAX_WIDTH}, // X_OUTPUT_CONTROL ++{0x3404, (0x8000 & 0) | AR0233_MAX_HEIGHT}, // Y_OUTPUT_CONTROL ++{ } ++}; /* Full_resolution */ + +-{0x3044, 0x0400}, //Dark_control +- +-#ifdef HDR_ratio_gain_default ++static const struct ar0233_reg ar0233_rev2_HDR_ratio_gain_default[] = { + {0x3362, 0x000F}, //HCG + {0x3366, 0x1111}, //1x + {0x3238, 0x0444}, // Ratio 16x, Use retio setting +-#endif /* HDR_ratio_gain_default */ ++{ } ++}; /* HDR_ratio_gain_default */ + +-// FPS = 124.5MHz / reg0x300A / reg0x300C * (DES_REF_XTAL/27MHz) +-{0x300A, AR0233_SENSOR_HEIGHT + 100}, // Frame_length_Lines +-{0x300C, AR0233_SENSOR_WIDTH + 400}, // Line_length_pck +-{0x3012, 0x144}, //Integration_time ++/* 3Exp HDR, 1280P, MIPI 4-lane 12-bit, 30fps, EXTCLK=23MHz (comes from deser) */ ++static const struct ar0233_reg *ar0233_regs_hdr_mipi_12bit_30fps_rev2[] = { ++ ar0233_rev2_Reset, ++ ar0233_rev2_O1_Recommended_Defaults_LFM_HDR, ++ ar0233_rev2_disable_embed_data_stat, ++ ar0233_rev2_HDR_3exp_12bit, ++ ar0233_rev2_pll_23_102_4lane_12b, ++ ar0233_rev2_mipi_12bit_4lane, ++ ar0233_rev2_LUT_24_to_12, ++ ar0233_rev2_Full_resolution, ++ ar0233_rev2_HDR_ratio_gain_default, ++ NULL, + }; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0163-lvds-AP0101-AR014X-add-TI-serializers.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0163-lvds-AP0101-AR014X-add-TI-serializers.patch new file mode 100644 index 00000000..568e8843 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0163-lvds-AP0101-AR014X-add-TI-serializers.patch @@ -0,0 +1,76 @@ +From f0063d3e6918319b9817e2074bcf0ffefde1e2ea Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Tue, 7 May 2019 13:00:24 +0300 +Subject: [PATCH 112/122] lvds: AP0101-AR014X: add TI serializers + +Add TI UB913 support + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ap0101_ar014x.c | 23 ++++++++++++++++++++--- + 1 file changed, 20 insertions(+), 3 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ap0101_ar014x.c b/drivers/media/i2c/soc_camera/ap0101_ar014x.c +index 142942d..e4f2bda 100644 +--- a/drivers/media/i2c/soc_camera/ap0101_ar014x.c ++++ b/drivers/media/i2c/soc_camera/ap0101_ar014x.c +@@ -46,6 +46,8 @@ struct ap0101_priv { + /* serializers */ + int max9286_addr; + int max9271_addr; ++ int ti9x4_addr; ++ int ti9x3_addr; + int port; + int gpio_resetb; + int gpio_fsin; +@@ -390,10 +392,13 @@ static int ap0101_initialize(struct i2c_client *client) + int tmp_addr; + int i; + +- ap0101_s_port(client, 1); +- + for (i = 0; i < ARRAY_SIZE(ap0101_i2c_addr); i++) { + tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ ++ reg8_write(client, 0x5d, ap0101_i2c_addr[i] << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ } + if (priv->max9286_addr) { + client->addr = priv->max9271_addr; /* Serializer I2C address */ + reg8_write(client, 0x0A, ap0101_i2c_addr[i] << 1); /* Sensor native I2C address */ +@@ -478,11 +483,17 @@ static int ap0101_parse_dt(struct device_node *np, struct ap0101_priv *priv) + !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && + !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) + break; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; + } + + of_node_put(endpoint); + +- if (!priv->max9286_addr) { ++ if (!priv->max9286_addr && !priv->ti9x4_addr) { + dev_err(&client->dev, "deserializer does not present for AP0101\n"); + return -EINVAL; + } +@@ -496,6 +507,12 @@ static int ap0101_parse_dt(struct device_node *np, struct ap0101_priv *priv) + reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */ + usleep_range(2000, 2500); /* wait 2ms */ + }; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ } + client->addr = tmp_addr; + + mdelay(10); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0164-lvds-fix-vendor-names.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0164-lvds-fix-vendor-names.patch new file mode 100644 index 00000000..14e9aa3f --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0164-lvds-fix-vendor-names.patch @@ -0,0 +1,125 @@ +From b7c746dad25e649fc4990805c12b2f51817acf0c Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Tue, 7 May 2019 18:11:34 +0300 +Subject: [PATCH 113/122] lvds: fix vendor names + +Fix vendor names + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/gw4200_ar014x.c | 4 ++-- + drivers/media/i2c/soc_camera/imx390.c | 2 +- + drivers/media/i2c/soc_camera/imx390.h | 2 +- + drivers/media/i2c/soc_camera/isx016.c | 4 ++-- + drivers/media/i2c/soc_camera/isx016.h | 2 +- + drivers/media/i2c/soc_camera/isx019.c | 4 ++-- + drivers/media/i2c/soc_camera/isx019.h | 2 +- + 7 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/gw4200_ar014x.c b/drivers/media/i2c/soc_camera/gw4200_ar014x.c +index 2de6fe7..674e409 100644 +--- a/drivers/media/i2c/soc_camera/gw4200_ar014x.c ++++ b/drivers/media/i2c/soc_camera/gw4200_ar014x.c +@@ -1,5 +1,5 @@ + /* +- * ON Semiconductor GW4200-AR014X sensor camera driver ++ * GEO Semiconductor GW4200-AR014X sensor camera driver + * + * Copyright (C) 2018 Cogent Embedded, Inc. + * +@@ -569,7 +569,7 @@ static const struct i2c_device_id gw4200_id[] = { + MODULE_DEVICE_TABLE(i2c, gw4200_id); + + static const struct of_device_id gw4200_of_ids[] = { +- { .compatible = "aptina,gw4200", }, ++ { .compatible = "geosemi,gw4200", }, + { } + }; + MODULE_DEVICE_TABLE(of, gw4200_of_ids); +diff --git a/drivers/media/i2c/soc_camera/imx390.c b/drivers/media/i2c/soc_camera/imx390.c +index 1834195..7171d70 100644 +--- a/drivers/media/i2c/soc_camera/imx390.c ++++ b/drivers/media/i2c/soc_camera/imx390.c +@@ -1,5 +1,5 @@ + /* +- * OmniVision IMX390 sensor camera driver ++ * Sony IMX390 sensor camera driver + * + * Copyright (C) 2018 Cogent Embedded, Inc. + * +diff --git a/drivers/media/i2c/soc_camera/imx390.h b/drivers/media/i2c/soc_camera/imx390.h +index a7189e8..efd75a7 100644 +--- a/drivers/media/i2c/soc_camera/imx390.h ++++ b/drivers/media/i2c/soc_camera/imx390.h +@@ -1,5 +1,5 @@ + /* +- * OmniVision IMX390 sensor camera wizard 1920x1080@30/BGGR/MIPI ++ * Sony IMX390 sensor camera wizard 1920x1080@30/BGGR/MIPI + * + * Copyright (C) 2018 Cogent Embedded, Inc. + * +diff --git a/drivers/media/i2c/soc_camera/isx016.c b/drivers/media/i2c/soc_camera/isx016.c +index 4002008..eab155c 100644 +--- a/drivers/media/i2c/soc_camera/isx016.c ++++ b/drivers/media/i2c/soc_camera/isx016.c +@@ -1,5 +1,5 @@ + /* +- * ON Semiconductor ISX016 (isp) camera driver ++ * Sony ISX016 (isp) camera driver + * + * Copyright (C) 2019 Cogent Embedded, Inc. + * +@@ -581,7 +581,7 @@ static const struct i2c_device_id isx016_id[] = { + MODULE_DEVICE_TABLE(i2c, isx016_id); + + static const struct of_device_id isx016_of_ids[] = { +- { .compatible = "aptina,isx016", }, ++ { .compatible = "sony,isx016", }, + { } + }; + MODULE_DEVICE_TABLE(of, isx016_of_ids); +diff --git a/drivers/media/i2c/soc_camera/isx016.h b/drivers/media/i2c/soc_camera/isx016.h +index 8ca35a10..379766f 100644 +--- a/drivers/media/i2c/soc_camera/isx016.h ++++ b/drivers/media/i2c/soc_camera/isx016.h +@@ -1,5 +1,5 @@ + /* +- * ON Semiconductor isx016 (isp) camera wizard 1280x960@30/UYVY/BT601/8bit ++ * Sony isx016 (isp) camera wizard 1280x960@30/UYVY/BT601/8bit + * + * Copyright (C) 2019 Cogent Embedded, Inc. + * +diff --git a/drivers/media/i2c/soc_camera/isx019.c b/drivers/media/i2c/soc_camera/isx019.c +index 8064789..650b533 100644 +--- a/drivers/media/i2c/soc_camera/isx019.c ++++ b/drivers/media/i2c/soc_camera/isx019.c +@@ -1,5 +1,5 @@ + /* +- * ON Semiconductor ISX019 (isp) camera driver ++ * Sony ISX019 (isp) camera driver + * + * Copyright (C) 2018 Cogent Embedded, Inc. + * +@@ -605,7 +605,7 @@ static const struct i2c_device_id isx019_id[] = { + MODULE_DEVICE_TABLE(i2c, isx019_id); + + static const struct of_device_id isx019_of_ids[] = { +- { .compatible = "aptina,isx019", }, ++ { .compatible = "sony,isx019", }, + { } + }; + MODULE_DEVICE_TABLE(of, isx019_of_ids); +diff --git a/drivers/media/i2c/soc_camera/isx019.h b/drivers/media/i2c/soc_camera/isx019.h +index 0593be1..edaa767 100644 +--- a/drivers/media/i2c/soc_camera/isx019.h ++++ b/drivers/media/i2c/soc_camera/isx019.h +@@ -1,5 +1,5 @@ + /* +- * ON Semiconductor isx019 (isp) camera wizard 1280x800@30/UYVY/BT601/8bit ++ * Sony isx019 (isp) camera wizard 1280x800@30/UYVY/BT601/8bit + * + * Copyright (C) 2018 Cogent Embedded, Inc. + * +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0165-LVDS-add-GW5200-IMX390-camera.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0165-LVDS-add-GW5200-IMX390-camera.patch new file mode 100644 index 00000000..92456a06 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0165-LVDS-add-GW5200-IMX390-camera.patch @@ -0,0 +1,673 @@ +From ef4f0fb34567958cba956e2292216e370fc982c1 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Tue, 7 May 2019 19:30:06 +0300 +Subject: [PATCH 114/122] LVDS: add GW5200-IMX390 camera + +This add GW5200 isp with IMX390 imager + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/gw5200_imx390.c | 574 +++++++++++++++++++++++++++ + drivers/media/i2c/soc_camera/gw5200_imx390.h | 25 ++ + drivers/media/i2c/soc_camera/ov106xx.c | 11 + + 3 files changed, 610 insertions(+) + create mode 100644 drivers/media/i2c/soc_camera/gw5200_imx390.c + create mode 100644 drivers/media/i2c/soc_camera/gw5200_imx390.h + +diff --git a/drivers/media/i2c/soc_camera/gw5200_imx390.c b/drivers/media/i2c/soc_camera/gw5200_imx390.c +new file mode 100644 +index 0000000..0703c3d +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/gw5200_imx390.c +@@ -0,0 +1,574 @@ ++/* ++ * GEO Semiconductor GW5200-IMX390 sensor camera driver ++ * ++ * Copyright (C) 2019 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "gw5200_imx390.h" ++ ++static const int gw5200_i2c_addr[] = {0x18}; ++ ++#define GW5200_PID 0x00 ++#define GW5200_VERSION_REG 0x30 ++ ++#define GW5200_MEDIA_BUS_FMT MEDIA_BUS_FMT_YUYV8_2X8 ++ ++static void gw5200_otp_id_read(struct i2c_client *client); ++ ++struct gw5200_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int init_complete; ++ u8 id[6]; ++ int exposure; ++ int gain; ++ int autogain; ++ /* serializers */ ++ int max9286_addr; ++ int max9271_addr; ++ int ti9x4_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++}; ++ ++static inline struct gw5200_priv *to_gw5200(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct gw5200_priv, sd); ++} ++ ++static void gw5200_s_port(struct i2c_client *client, int fwd_en) ++{ ++ struct gw5200_priv *priv = to_gw5200(client); ++ int tmp_addr; ++ ++ if (priv->max9286_addr) { ++ tmp_addr = client->addr; ++ client->addr = priv->max9286_addr; /* Deserializer I2C address */ ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ client->addr = tmp_addr; ++ }; ++} ++ ++#if 0 ++static int gw5200_set_regs(struct i2c_client *client, ++ const struct gw5200_reg *regs, int nr_regs) ++{ ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (regs[i].reg == GW5200_DELAY) { ++ mdelay(regs[i].val); ++ continue; ++ } ++ ++ reg16_write16(client, regs[i].reg, regs[i].val); ++ } ++ ++ return 0; ++} ++#endif ++ ++static int gw5200_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int gw5200_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct gw5200_priv *priv = to_gw5200(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = GW5200_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int gw5200_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = GW5200_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int gw5200_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = GW5200_MEDIA_BUS_FMT; ++ ++ return 0; ++} ++ ++static int gw5200_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct gw5200_priv *priv = to_gw5200(client); ++ ++ gw5200_otp_id_read(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = GW5200_VERSION_REG >> 8; ++ edid->edid[9] = GW5200_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int gw5200_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct gw5200_priv *priv = to_gw5200(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > GW5200_MAX_WIDTH) || ++ (rect->top + rect->height > GW5200_MAX_HEIGHT)) ++ *rect = priv->rect; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ return 0; ++} ++ ++static int gw5200_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct gw5200_priv *priv = to_gw5200(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = GW5200_MAX_WIDTH; ++ sel->r.height = GW5200_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = GW5200_MAX_WIDTH; ++ sel->r.height = GW5200_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int gw5200_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int gw5200_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u16 val = 0; ++ ++ ret = reg16_read16(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int gw5200_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return reg16_write16(client, (u16)reg->reg, (u16)reg->val); ++} ++#endif ++ ++static struct v4l2_subdev_core_ops gw5200_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = gw5200_g_register, ++ .s_register = gw5200_s_register, ++#endif ++}; ++ ++static int gw5200_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct gw5200_priv *priv = to_gw5200(client); ++ int ret = -EINVAL; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ case V4L2_CID_CONTRAST: ++ case V4L2_CID_SATURATION: ++ case V4L2_CID_HUE: ++ case V4L2_CID_GAMMA: ++ case V4L2_CID_SHARPNESS: ++ case V4L2_CID_AUTOGAIN: ++ case V4L2_CID_GAIN: ++ case V4L2_CID_EXPOSURE: ++ case V4L2_CID_HFLIP: ++ case V4L2_CID_VFLIP: ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops gw5200_ctrl_ops = { ++ .s_ctrl = gw5200_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops gw5200_video_ops = { ++ .s_stream = gw5200_s_stream, ++ .g_mbus_config = gw5200_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops gw5200_subdev_pad_ops = { ++ .get_edid = gw5200_get_edid, ++ .enum_mbus_code = gw5200_enum_mbus_code, ++ .get_selection = gw5200_get_selection, ++ .set_selection = gw5200_set_selection, ++ .get_fmt = gw5200_get_fmt, ++ .set_fmt = gw5200_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops gw5200_subdev_ops = { ++ .core = &gw5200_core_ops, ++ .video = &gw5200_video_ops, ++ .pad = &gw5200_subdev_pad_ops, ++}; ++ ++static void gw5200_otp_id_read(struct i2c_client *client) ++{ ++} ++ ++static ssize_t gw5200_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct gw5200_priv *priv = to_gw5200(client); ++ ++ gw5200_otp_id_read(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_gw5200, S_IRUGO, gw5200_otp_id_show, NULL); ++ ++static int gw5200_initialize(struct i2c_client *client) ++{ ++ struct gw5200_priv *priv = to_gw5200(client); ++ u8 pid = 0; ++ int ret = 0; ++ int tmp_addr; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(gw5200_i2c_addr); i++) { ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ ++ reg8_write(client, 0x5d, gw5200_i2c_addr[i] << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ } ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x0a, gw5200_i2c_addr[i] << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ client->addr = tmp_addr; ++ ++ /* check model ID */ ++ reg8_read(client, GW5200_PID, &pid); ++ ++ if (pid == GW5200_VERSION_REG) ++ break; ++ } ++ ++ if (pid != GW5200_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x\n", pid); ++ ret = -ENODEV; ++ goto err; ++ } ++#if 0 ++ /* Program wizard registers */ ++ gw5200_set_regs(client, gw5200_regs_wizard, ARRAY_SIZE(gw5200_regs_wizard)); ++ /* Read OTP IDs */ ++ gw5200_otp_id_read(client); ++#endif ++ dev_info(&client->dev, "gw5200 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, GW5200_MAX_WIDTH, GW5200_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ gw5200_s_port(client, 0); ++ return ret; ++} ++ ++static int gw5200_parse_dt(struct device_node *np, struct gw5200_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ of_node_put(endpoint); ++ ++ if (!priv->ti9x4_addr && !priv->max9286_addr) { ++ dev_dbg(&client->dev, "deserializer does not present\n"); ++ return -EINVAL; ++ } ++ ++ gw5200_s_port(client, 1); ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ ++ reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ } ++ client->addr = tmp_addr; ++ ++ mdelay(10); ++ ++ return 0; ++} ++ ++static int gw5200_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct gw5200_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &gw5200_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ priv->exposure = 0x100; ++ priv->gain = 0x100; ++ priv->autogain = 1; ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &gw5200_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &gw5200_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &gw5200_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &gw5200_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &gw5200_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &gw5200_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &gw5200_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); ++ v4l2_ctrl_new_std(&priv->hdl, &gw5200_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); ++ v4l2_ctrl_new_std(&priv->hdl, &gw5200_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure); ++ v4l2_ctrl_new_std(&priv->hdl, &gw5200_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &gw5200_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = gw5200_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = gw5200_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = GW5200_MAX_WIDTH; ++ priv->rect.height = GW5200_MAX_HEIGHT; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_gw5200) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_GW5200 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int gw5200_remove(struct i2c_client *client) ++{ ++ struct gw5200_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_gw5200); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_GW5200 ++static const struct i2c_device_id gw5200_id[] = { ++ { "gw5200", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, gw5200_id); ++ ++static const struct of_device_id gw5200_of_ids[] = { ++ { .compatible = "geosemi,gw5200", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, gw5200_of_ids); ++ ++static struct i2c_driver gw5200_i2c_driver = { ++ .driver = { ++ .name = "gw5200", ++ .of_match_table = gw5200_of_ids, ++ }, ++ .probe = gw5200_probe, ++ .remove = gw5200_remove, ++ .id_table = gw5200_id, ++}; ++ ++module_i2c_driver(gw5200_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for GW5200"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/gw5200_imx390.h b/drivers/media/i2c/soc_camera/gw5200_imx390.h +new file mode 100644 +index 0000000..6c0bf5f +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/gw5200_imx390.h +@@ -0,0 +1,25 @@ ++/* ++ * GEO Semiconductor GW5200-IMX390 sensor camera wizard 1920x1080@30/UYVY/BT601/8bit ++ * ++ * Copyright (C) 2019 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++#define GW5200_MAX_WIDTH 1920 ++#define GW5200_MAX_HEIGHT 1080 ++ ++#define GW5200_DELAY 0xffff ++ ++struct gw5200_reg { ++ u16 reg; ++ u16 val; ++}; ++ ++static const struct gw5200_reg gw5200_regs_wizard[] = { ++/* enable FSIN */ ++{GW5200_DELAY, 100}, ++}; +diff --git a/drivers/media/i2c/soc_camera/ov106xx.c b/drivers/media/i2c/soc_camera/ov106xx.c +index d641907..442e54a 100644 +--- a/drivers/media/i2c/soc_camera/ov106xx.c ++++ b/drivers/media/i2c/soc_camera/ov106xx.c +@@ -22,6 +22,7 @@ + #include "ar0323.c" + #include "ap0101_ar014x.c" + #include "gw4200_ar014x.c" ++#include "gw5200_imx390.c" + #include "ov2775.c" + #include "imx390.c" + #include "ox03a.c" +@@ -42,6 +43,7 @@ static enum { + ID_AR0323, + ID_AP0101_AR014X, + ID_GW4200_AR014X, ++ ID_GW5200_IMX390, + ID_OV2775, + ID_IMX390, + ID_OX03A, +@@ -133,6 +135,12 @@ static int ov106xx_probe(struct i2c_client *client, + goto out; + } + ++ ret = gw5200_probe(client, did); ++ if (!ret) { ++ chip_id = ID_GW5200_IMX390; ++ goto out; ++ } ++ + ret = ov2775_probe(client, did); + if (!ret) { + chip_id = ID_OV2775; +@@ -211,6 +219,9 @@ static int ov106xx_remove(struct i2c_client *client) + case ID_GW4200_AR014X: + gw4200_remove(client); + break; ++ case ID_GW5200_IMX390: ++ gw5200_remove(client); ++ break; + case ID_OV2775: + ov2775_remove(client); + break; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0166-lvds-AR0233-add-superexposure-plus.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0166-lvds-AR0233-add-superexposure-plus.patch new file mode 100644 index 00000000..841b08cc --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0166-lvds-AR0233-add-superexposure-plus.patch @@ -0,0 +1,1251 @@ +From d16da38f64e935e60d82356f2f9c35f82aa51a4a Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Wed, 8 May 2019 16:45:54 +0300 +Subject: [PATCH 115/122] lvds: AR0233: add superexposure plus + +This adds superexposure plus T2 + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ar0233.c | 6 +- + drivers/media/i2c/soc_camera/ar0233_rev2.h | 1182 ++++++++++++++++++++++++++++ + 2 files changed, 1186 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ar0233.c b/drivers/media/i2c/soc_camera/ar0233.c +index 54cc38a..5c3d4e1 100644 +--- a/drivers/media/i2c/soc_camera/ar0233.c ++++ b/drivers/media/i2c/soc_camera/ar0233.c +@@ -442,6 +442,8 @@ static int ar0233_initialize(struct i2c_client *client) + + if (strcmp(mode, "hdr") == 0) + ar0233_set_regs(client, ar0233_regs_hdr_mipi_12bit_30fps_rev2); ++ else if (strcmp(mode, "seplus") == 0) ++ ar0233_set_regs(client, ar0233_regs_seplus_mipi_12bit_30fps_rev2); + else + dev_err(&client->dev, "Unsupported mode %s\n", mode); + break; +@@ -461,8 +463,8 @@ static int ar0233_initialize(struct i2c_client *client) + val |= (1 << 2); // Set streamOn bit + reg16_write16(client, 0x301a, val); // Start Streaming + +- dev_info(&client->dev, "ar0233 PID %x (rev %x), res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", +- pid, rev, AR0233_MAX_WIDTH, AR0233_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++ dev_info(&client->dev, "ar0233 PID %x (rev %x), res %dx%d, mode=%s, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, rev, AR0233_MAX_WIDTH, AR0233_MAX_HEIGHT, mode, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); + err: + return ret; + } +diff --git a/drivers/media/i2c/soc_camera/ar0233_rev2.h b/drivers/media/i2c/soc_camera/ar0233_rev2.h +index c821d35..02d9af1 100644 +--- a/drivers/media/i2c/soc_camera/ar0233_rev2.h ++++ b/drivers/media/i2c/soc_camera/ar0233_rev2.h +@@ -1124,6 +1124,1146 @@ static const struct ar0233_reg ar0233_rev2_O1_Recommended_Defaults_LFM_HDR[] = { + { } + }; /* O1_Recommended_Defaults_LFM_HDR */ + ++static const struct ar0233_reg ar0233_rev2_O1_Recommended_Defaults_SE_T1_LIN_T2[] = { ++/* Design_recommended_settings_REV2_seplus */ ++{0x3086, 0x0000}, ++{0x3092, 0x400C}, ++{0x3362, 0x0001}, // DC_GAIN ++{0x342E, 0x0014}, ++{0x34B8, 0x0001}, ++{0x34BA, 0x0001}, ++{0x3508, 0xAF1A}, ++{0x351A, 0xF400}, ++{0x3520, 0x0080}, ++{0x3522, 0x7D19}, ++{0x3524, 0xFF9F}, ++{0x3528, 0xF02D}, ++{0x352C, 0x0F02}, ++{0x3530, 0x1F18}, ++{0x3534, 0x3898}, ++{0x353A, 0x9ABA}, ++{0x353C, 0x9A8A}, ++{0x3544, 0x030F}, ++{0x3550, 0x806C}, ++{0x3562, 0x0C08}, ++{0x3564, 0x1223}, ++{0x3568, 0x0028}, ++{0x356A, 0x81AA}, ++{0x356C, 0x6A7F}, ++{0x356E, 0x068A}, ++{0x3576, 0x1DFF}, ++{0x37B2, 0x1FFF}, // DBLC_OUT_CLIP_MAX ++{0x3C72, 0x0076}, // ADC_DEC_CTRL7 ++{0x3C74, 0x0031}, // ADC_DEC_CTRL8 ++{0x3C76, 0x00DC}, // ADC_DEC_CTRL9 ++{0x3C78, 0x01AA}, // ADC_DEC_CTRL10 ++{0x3C7A, 0x0352}, // ADC_DEC_CTRL11 ++{0x3C7C, 0x06AA}, // ADC_DEC_CTRL12 ++{0x3E3E, 0x004A}, ++{0x3044, 0x0400}, // DARK_CONTROL ++{0x336E, 0x0147}, // DATAPATH_SELECT2 ++{0x3192, 0x2249}, ++{0x3194, 0x1AA6}, ++{0x3198, 0xB691}, ++{0x3546, 0x5203}, ++{0x34D4, 0x0001}, // DISCRETE_FINE_INTEGRATION ++{0x3E00, 0x8000}, // LFM2_T1_CTRL ++{0x34BC, 0x0808}, // LFM_PATTERN_CTRL ++{0x3494, 0x0808}, // LFM_TX_PATTERN_CTRL ++{0x3496, 0x5F00}, // LFM_CONTROL ++{0x3474, 0x006F}, ++{0x3458, 0x008D}, ++{0x3490, 0x0045}, ++{0x3C08, 0x0104}, ++{0x3C06, 0x0C3C}, ++{0x3C08, 0x0104}, ++{0x3D28, 0xEA60}, ++{0x3D2A, 0xEA60}, ++{0x3290, 0xF80C}, ++{0x3292, 0xF80C}, ++{0x3294, 0xF80C}, ++{0x3296, 0xF80C}, ++{0x3298, 0xFFFF}, ++{0x329A, 0xFFFF}, ++{0x329C, 0xFFFF}, ++{0x329E, 0xFFFF}, ++{0x3110, 0x0011}, // HDR_CONTROL0 ++{0x3492, 0x0004}, ++{0x3496, 0x5B00}, // LFM_CONTROL ++{0x34A0, 0x0036}, ++{0x34A4, 0x0035}, ++{0x34A6, 0x0040}, ++{0x3512, 0x0ED6}, ++{0x3516, 0x8888}, ++{0x3518, 0x4040}, ++{0x351C, 0xCFF6}, ++{0x3528, 0xE00A}, ++{0x352A, 0x0827}, ++{0x352E, 0x060A}, ++{0x353A, 0x1ABA}, ++{0x353E, 0x2044}, ++{0x3540, 0x4444}, ++{0x3542, 0x448F}, ++{0x3548, 0x3A3C}, ++{0x354A, 0x3C3C}, ++{0x354C, 0x321E}, ++{0x354E, 0x1E1E}, ++{0x3E02, 0x0F32}, ++{0x3E04, 0x0000}, ++{0x3E06, 0x0000}, ++{0x3E10, 0x0000}, ++{0x3E14, 0x003F}, ++{0x3E16, 0x1FFF}, ++{0x3E18, 0x0F52}, ++{0x562A, 0x03E8}, // OCL_T1_E2_E1_SAT ++/* Design_recommended_settings_REV2_seplus */ ++ ++/* Sequence_hidy_ar0233_REV2_seplus */ ++{0x2512, 0x8000}, ++{0x2510, 0x070F}, ++{0x2510, 0x1011}, ++{0x2510, 0x1216}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0x191A}, ++{0x2510, 0x1E1F}, ++{0x2510, 0x2022}, ++{0x2510, 0xFFFF}, ++{0x2510, 0x2644}, ++{0x2510, 0x5574}, ++{0x2510, 0x878D}, ++{0x2510, 0x9496}, ++{0x2510, 0x9B9D}, ++{0x2510, 0x9FA1}, ++{0x2510, 0xA3A5}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xC003}, ++{0x2510, 0x805A}, ++{0x2510, 0xA0E0}, ++{0x2510, 0x3041}, ++{0x2510, 0x3042}, ++{0x2510, 0x2000}, ++{0x2510, 0x3048}, ++{0x2510, 0x3088}, ++{0x2510, 0x30A0}, ++{0x2510, 0x3090}, ++{0x2510, 0x32C2}, ++{0x2510, 0xA0C0}, ++{0x2510, 0x9008}, ++{0x2510, 0x8802}, ++{0x2510, 0x20FF}, ++{0x2510, 0x20FF}, ++{0x2510, 0x20FF}, ++{0x2510, 0x20FF}, ++{0x2510, 0x20FF}, ++{0x2510, 0x9018}, ++{0x2510, 0x891A}, ++{0x2510, 0x807E}, ++{0x2510, 0x20FF}, ++{0x2510, 0x895B}, ++{0x2510, 0x20FF}, ++{0x2510, 0x897B}, ++{0x2510, 0x20FF}, ++{0x2510, 0x897F}, ++{0x2510, 0x20FF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x20FF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x20FF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x20FF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0xA0C4}, ++{0x2510, 0x20FF}, ++{0x2510, 0x805A}, ++{0x2510, 0x9039}, ++{0x2510, 0x20FF}, ++{0x2510, 0x907F}, ++{0x2510, 0x895B}, ++{0x2510, 0x2064}, ++{0x2510, 0x891B}, ++{0x2510, 0x2010}, ++{0x2510, 0x8803}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x20FF}, ++{0x2510, 0x906B}, ++{0x2510, 0x2064}, ++{0x2510, 0x3084}, ++{0x2510, 0x2003}, ++{0x2510, 0x3044}, ++{0x2510, 0x2000}, ++{0x2510, 0xA004}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x2400}, ++{0x2510, 0x2401}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x2400}, ++{0x2510, 0x2401}, ++{0x2510, 0x2702}, ++{0x2510, 0x3242}, ++{0x2510, 0x2420}, ++{0x2510, 0x2421}, ++{0x2510, 0x2703}, ++{0x2510, 0x3242}, ++{0x2510, 0x2420}, ++{0x2510, 0x2421}, ++{0x2510, 0x2704}, ++{0x2510, 0x3242}, ++{0x2510, 0x2420}, ++{0x2510, 0x2421}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x2201}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x2201}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x2404}, ++{0x2510, 0x2779}, ++{0x2510, 0x2427}, ++{0x2510, 0x2781}, ++{0x2510, 0x2427}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x2703}, ++{0x2510, 0x242A}, ++{0x2510, 0x2703}, ++{0x2510, 0x3242}, ++{0x2510, 0x27BB}, ++{0x2510, 0x2428}, ++{0x2510, 0x27BB}, ++{0x2510, 0x3242}, ++{0x2510, 0x2702}, ++{0x2510, 0x2429}, ++{0x2510, 0x2702}, ++{0x2510, 0x3242}, ++{0x2510, 0x27C3}, ++{0x2510, 0x2428}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0xB800}, ++{0x2510, 0x8058}, ++{0x2510, 0xA005}, ++{0x2510, 0x3101}, ++{0x2510, 0x3041}, ++{0x2510, 0x3104}, ++{0x2510, 0xB035}, ++{0x2510, 0xB075}, ++{0x2510, 0x30C1}, ++{0x2510, 0x3102}, ++{0x2510, 0x3041}, ++{0x2510, 0xB808}, ++{0x2510, 0x3202}, ++{0x2510, 0xB848}, ++{0x2510, 0xB84C}, ++{0x2510, 0x2201}, ++{0x2510, 0xB377}, ++{0x2510, 0x8843}, ++{0x2510, 0x916F}, ++{0x2510, 0x2201}, ++{0x2510, 0xB84E}, ++{0x2510, 0xF905}, ++{0x2510, 0xF907}, ++{0x2510, 0x2200}, ++{0x2510, 0x885B}, ++{0x2510, 0xA898}, ++{0x2510, 0xA8D8}, ++{0x2510, 0xF8E8}, ++{0x2510, 0x80D8}, ++{0x2510, 0x9007}, ++{0x2510, 0x916F}, ++{0x2510, 0x2206}, ++{0x2510, 0xB808}, ++{0x2510, 0xC800}, ++{0x2510, 0xE807}, ++{0x2510, 0x88DB}, ++{0x2510, 0xF8A8}, ++{0x2510, 0xF888}, ++{0x2510, 0x2203}, ++{0x2510, 0xB07B}, ++{0x2510, 0x2000}, ++{0x2510, 0x80C8}, ++{0x2510, 0x8088}, ++{0x2510, 0x220B}, ++{0x2510, 0xB06A}, ++{0x2510, 0x88CB}, ++{0x2510, 0x888B}, ++{0x2510, 0x2224}, ++{0x2510, 0xB04A}, ++{0x2510, 0x2218}, ++{0x2510, 0x210D}, ++{0x2510, 0x2108}, ++{0x2510, 0x902F}, ++{0x2510, 0xB04B}, ++{0x2510, 0xF880}, ++{0x2510, 0x2205}, ++{0x2510, 0x2205}, ++{0x2510, 0x2203}, ++{0x2510, 0x9800}, ++{0x2510, 0xB043}, ++{0x2510, 0xA8C9}, ++{0x2510, 0x31C1}, ++{0x2510, 0x80A8}, ++{0x2510, 0x2205}, ++{0x2510, 0x916F}, ++{0x2510, 0x2104}, ++{0x2510, 0x88AB}, ++{0x2510, 0x2104}, ++{0x2510, 0xB808}, ++{0x2510, 0x9800}, ++{0x2510, 0x2440}, ++{0x2510, 0xF110}, ++{0x2510, 0xF804}, ++{0x2510, 0x2000}, ++{0x2510, 0x8088}, ++{0x2510, 0x3002}, ++{0x2510, 0xB838}, ++{0x2510, 0xA8C8}, ++{0x2510, 0xB04B}, ++{0x2510, 0x2442}, ++{0x2510, 0x3210}, ++{0x2510, 0x2206}, ++{0x2510, 0x888B}, ++{0x2510, 0x2203}, ++{0x2510, 0xF1CB}, ++{0x2510, 0x2201}, ++{0x2510, 0x3202}, ++{0x2510, 0xF880}, ++{0x2510, 0xB830}, ++{0x2510, 0xC801}, ++{0x2510, 0x30C2}, ++{0x2510, 0xE80C}, ++{0x2510, 0x2201}, ++{0x2510, 0xB04A}, ++{0x2510, 0x2227}, ++{0x2510, 0x2205}, ++{0x2510, 0x2200}, ++{0x2510, 0x2207}, ++{0x2510, 0x902F}, ++{0x2510, 0x220E}, ++{0x2510, 0x2205}, ++{0x2510, 0x2204}, ++{0x2510, 0xB042}, ++{0x2510, 0xA9A1}, ++{0x2510, 0x8008}, ++{0x2510, 0xB0D3}, ++{0x2510, 0x31C1}, ++{0x2510, 0x916B}, ++{0x2510, 0x2008}, ++{0x2510, 0x32C1}, ++{0x2510, 0x8803}, ++{0x2510, 0xA044}, ++{0x2510, 0x3044}, ++{0x2510, 0x2000}, ++{0x2510, 0xA004}, ++{0x2510, 0x2000}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0xA084}, ++{0x2510, 0x30D0}, ++{0x2510, 0x807C}, ++{0x2510, 0x3141}, ++{0x2510, 0x3041}, ++{0x2510, 0x3042}, ++{0x2510, 0x2000}, ++{0x2510, 0x3142}, ++{0x2510, 0x3041}, ++{0x2510, 0x3042}, ++{0x2510, 0x2000}, ++{0x2510, 0x3281}, ++{0x2510, 0x3041}, ++{0x2510, 0x3042}, ++{0x2510, 0x2000}, ++{0x2510, 0x3290}, ++{0x2510, 0x3041}, ++{0x2510, 0x3042}, ++{0x2510, 0x2000}, ++{0x2510, 0x3110}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x3120}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x3282}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x32A0}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x881B}, ++{0x2510, 0x887F}, ++{0x2510, 0xA08C}, ++{0x2510, 0x221F}, ++{0x2510, 0xA084}, ++{0x2510, 0x2440}, ++{0x2510, 0x3260}, ++{0x2510, 0x3248}, ++{0x2510, 0xB095}, ++{0x2510, 0xF110}, ++{0x2510, 0xF864}, ++{0x2510, 0xF90D}, ++{0x2510, 0x3084}, ++{0x2510, 0x32C1}, ++{0x2510, 0x3090}, ++{0x2510, 0x3088}, ++{0x2510, 0x2443}, ++{0x2510, 0x8058}, ++{0x2510, 0x3001}, ++{0x2510, 0x2442}, ++{0x2510, 0x3220}, ++{0x2510, 0x2002}, ++{0x2510, 0x8867}, ++{0x2510, 0x2004}, ++{0x2510, 0x8803}, ++{0x2510, 0x2002}, ++{0x2510, 0x30C2}, ++{0x2510, 0xA9A0}, ++{0x2510, 0xB094}, ++{0x2510, 0x2201}, ++{0x2510, 0xA0C4}, ++{0x2510, 0x3044}, ++{0x2510, 0x2000}, ++{0x2510, 0xA004}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0xB980}, ++{0x2510, 0xA881}, ++{0x2510, 0xA8C1}, ++{0x2510, 0x8108}, ++{0x2510, 0xA105}, ++{0x2510, 0x30C1}, ++{0x2510, 0x2020}, ++{0x2510, 0x3101}, ++{0x2510, 0x3041}, ++{0x2510, 0x3104}, ++{0x2510, 0x3102}, ++{0x2510, 0x3041}, ++{0x2510, 0xF860}, ++{0x2510, 0xB095}, ++{0x2510, 0x2001}, ++{0x2510, 0xB988}, ++{0x2510, 0xB9F8}, ++{0x2510, 0xB9FC}, ++{0x2510, 0x8803}, ++{0x2510, 0x916F}, ++{0x2510, 0x2001}, ++{0x2510, 0xB9FE}, ++{0x2510, 0xF905}, ++{0x2510, 0xF907}, ++{0x2510, 0x3202}, ++{0x2510, 0x880B}, ++{0x2510, 0xB397}, ++{0x2510, 0xF8E8}, ++{0x2510, 0x8188}, ++{0x2510, 0x9007}, ++{0x2510, 0x916F}, ++{0x2510, 0x2204}, ++{0x2510, 0xB137}, ++{0x2510, 0xB9B8}, ++{0x2510, 0xC801}, ++{0x2510, 0xE807}, ++{0x2510, 0xB177}, ++{0x2510, 0x888B}, ++{0x2510, 0xF8A8}, ++{0x2510, 0xF888}, ++{0x2510, 0x2203}, ++{0x2510, 0xA8C8}, ++{0x2510, 0xB07B}, ++{0x2510, 0x2000}, ++{0x2510, 0x8188}, ++{0x2510, 0x8088}, ++{0x2510, 0x220B}, ++{0x2510, 0xB06A}, ++{0x2510, 0x888B}, ++{0x2510, 0x888B}, ++{0x2510, 0x2224}, ++{0x2510, 0xB04A}, ++{0x2510, 0x2214}, ++{0x2510, 0xB04B}, ++{0x2510, 0x902F}, ++{0x2510, 0xF880}, ++{0x2510, 0x2211}, ++{0x2510, 0x2205}, ++{0x2510, 0x2204}, ++{0x2510, 0xB043}, ++{0x2510, 0xA8C1}, ++{0x2510, 0x31C1}, ++{0x2510, 0x2200}, ++{0x2510, 0x80C8}, ++{0x2510, 0x2103}, ++{0x2510, 0x916F}, ++{0x2510, 0x2106}, ++{0x2510, 0x88CB}, ++{0x2510, 0x210A}, ++{0x2510, 0xA8C1}, ++{0x2510, 0x2440}, ++{0x2510, 0xF110}, ++{0x2510, 0xF804}, ++{0x2510, 0x2000}, ++{0x2510, 0x8088}, ++{0x2510, 0x2002}, ++{0x2510, 0x888B}, ++{0x2510, 0x3002}, ++{0x2510, 0xB988}, ++{0x2510, 0x2442}, ++{0x2510, 0x3210}, ++{0x2510, 0x2206}, ++{0x2510, 0x2207}, ++{0x2510, 0x3202}, ++{0x2510, 0xA8C1}, ++{0x2510, 0x2013}, ++{0x2510, 0x8088}, ++{0x2510, 0x200C}, ++{0x2510, 0x888B}, ++{0x2510, 0x2005}, ++{0x2510, 0xA8D0}, ++{0x2510, 0xB04B}, ++{0x2510, 0xF880}, ++{0x2510, 0xB980}, ++{0x2510, 0xC800}, ++{0x2510, 0x30C2}, ++{0x2510, 0xE80C}, ++{0x2510, 0x2201}, ++{0x2510, 0xB04A}, ++{0x2510, 0x2213}, ++{0x2510, 0x2225}, ++{0x2510, 0x8088}, ++{0x2510, 0x2205}, ++{0x2510, 0x888B}, ++{0x2510, 0x2203}, ++{0x2510, 0x902F}, ++{0x2510, 0x2206}, ++{0x2510, 0x2204}, ++{0x2510, 0xB042}, ++{0x2510, 0xA9A1}, ++{0x2510, 0x8058}, ++{0x2510, 0xB093}, ++{0x2510, 0x31C1}, ++{0x2510, 0x916B}, ++{0x2510, 0x2007}, ++{0x2510, 0x3084}, ++{0x2510, 0x32C1}, ++{0x2510, 0x8803}, ++{0x2510, 0xA144}, ++{0x2510, 0x3044}, ++{0x2510, 0x2000}, ++{0x2510, 0xA004}, ++{0x2510, 0xB800}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x30D0}, ++{0x2510, 0xA981}, ++{0x2510, 0xA9C1}, ++{0x2510, 0x2006}, ++{0x2510, 0xA184}, ++{0x2510, 0xB800}, ++{0x2510, 0x80FC}, ++{0x2510, 0x3141}, ++{0x2510, 0x3041}, ++{0x2510, 0x3042}, ++{0x2510, 0x2000}, ++{0x2510, 0x3142}, ++{0x2510, 0x3041}, ++{0x2510, 0x3042}, ++{0x2510, 0x2000}, ++{0x2510, 0x3281}, ++{0x2510, 0x3041}, ++{0x2510, 0x3042}, ++{0x2510, 0x2000}, ++{0x2510, 0x3290}, ++{0x2510, 0x3041}, ++{0x2510, 0x3042}, ++{0x2510, 0x2000}, ++{0x2510, 0x3110}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x3120}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x3282}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x32A0}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x889B}, ++{0x2510, 0x88FF}, ++{0x2510, 0x2440}, ++{0x2510, 0x3260}, ++{0x2510, 0x3248}, ++{0x2510, 0xB095}, ++{0x2510, 0xF110}, ++{0x2510, 0xF864}, ++{0x2510, 0xF90D}, ++{0x2510, 0x32C2}, ++{0x2510, 0x30A0}, ++{0x2510, 0x3090}, ++{0x2510, 0x3088}, ++{0x2510, 0x2443}, ++{0x2510, 0x80D8}, ++{0x2510, 0x3001}, ++{0x2510, 0x2206}, ++{0x2510, 0x88DB}, ++{0x2510, 0x2442}, ++{0x2510, 0x3220}, ++{0x2510, 0x2010}, ++{0x2510, 0x2001}, ++{0x2510, 0x30C2}, ++{0x2510, 0x8098}, ++{0x2510, 0x2010}, ++{0x2510, 0x889B}, ++{0x2510, 0x2008}, ++{0x2510, 0x809A}, ++{0x2510, 0x200A}, ++{0x2510, 0x8002}, ++{0x2510, 0xA9A1}, ++{0x2510, 0xB094}, ++{0x2510, 0x2201}, ++{0x2510, 0x8803}, ++{0x2510, 0xA1C4}, ++{0x2510, 0x3044}, ++{0x2510, 0xB800}, ++{0x2510, 0xA004}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x8002}, ++{0x2510, 0x9818}, ++{0x2510, 0x3101}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x3102}, ++{0x2510, 0x3041}, ++{0x2510, 0x8018}, ++{0x2510, 0x2002}, ++{0x2510, 0x8038}, ++{0x2510, 0x2205}, ++{0x2510, 0x881B}, ++{0x2510, 0x883B}, ++{0x2510, 0x2119}, ++{0x2510, 0x8018}, ++{0x2510, 0x2202}, ++{0x2510, 0x8000}, ++{0x2510, 0x2201}, ++{0x2510, 0x8803}, ++{0x2510, 0x9800}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0xB980}, ++{0x2510, 0x3260}, ++{0x2510, 0x3101}, ++{0x2510, 0x3041}, ++{0x2510, 0x2000}, ++{0x2510, 0x3102}, ++{0x2510, 0x3041}, ++{0x2510, 0x8028}, ++{0x2510, 0x220A}, ++{0x2510, 0x880B}, ++{0x2510, 0x882B}, ++{0x2510, 0x2440}, ++{0x2510, 0xB095}, ++{0x2510, 0xF110}, ++{0x2510, 0xF864}, ++{0x2510, 0xF90D}, ++{0x2510, 0x8008}, ++{0x2510, 0x3004}, ++{0x2510, 0x2202}, ++{0x2510, 0x2442}, ++{0x2510, 0x882B}, ++{0x2510, 0x3220}, ++{0x2510, 0x2004}, ++{0x2510, 0x880B}, ++{0x2510, 0x2004}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x240D}, ++{0x2510, 0x2751}, ++{0x2510, 0x2423}, ++{0x2510, 0x2750}, ++{0x2510, 0x2421}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x3250}, ++{0x2510, 0x27D8}, ++{0x2510, 0x242B}, ++{0x2510, 0x27D9}, ++{0x2510, 0x242B}, ++{0x2510, 0x3250}, ++{0x2510, 0xC023}, ++{0x2510, 0x2402}, ++{0x2510, 0xC023}, ++{0x2510, 0x2751}, ++{0x2510, 0x2423}, ++{0x2510, 0xC02B}, ++{0x2510, 0x2750}, ++{0x2510, 0x2421}, ++{0x2510, 0xC003}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x2404}, ++{0x2510, 0x2779}, ++{0x2510, 0x2427}, ++{0x2510, 0x2781}, ++{0x2510, 0x2427}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x2791}, ++{0x2510, 0x2428}, ++{0x2510, 0x2799}, ++{0x2510, 0x2426}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x27A1}, ++{0x2510, 0x2428}, ++{0x2510, 0x27A9}, ++{0x2510, 0x2426}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0xC167}, ++{0x2510, 0x2400}, ++{0x2510, 0xC067}, ++{0x2510, 0x2405}, ++{0x2510, 0x240C}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x30C2}, ++{0x2510, 0xA9A0}, ++{0x2510, 0xB094}, ++{0x2510, 0x2201}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0x7FFF}, ++{0x2510, 0xB800}, ++{0x2510, 0x8058}, ++{0x2510, 0xA005}, ++{0x2510, 0x3101}, ++{0x2510, 0x3041}, ++{0x2510, 0x3104}, ++{0x2510, 0xB035}, ++{0x2510, 0xB075}, ++{0x2510, 0x30C1}, ++{0x2510, 0x3102}, ++{0x2510, 0x3041}, ++{0x2510, 0xB808}, ++{0x2510, 0x3202}, ++{0x2510, 0xB848}, ++{0x2510, 0xB84C}, ++{0x2510, 0x2201}, ++{0x2510, 0xB377}, ++{0x2510, 0x8843}, ++{0x2510, 0x916F}, ++{0x2510, 0x2201}, ++{0x2510, 0xB84E}, ++{0x2510, 0xF905}, ++{0x2510, 0xF907}, ++{0x2510, 0x2200}, ++{0x2510, 0x885B}, ++{0x2510, 0xA898}, ++{0x2510, 0xA8D8}, ++{0x2510, 0xF8E8}, ++{0x2510, 0x80D8}, ++{0x2510, 0x9007}, ++{0x2510, 0x916F}, ++{0x2510, 0x2206}, ++{0x2510, 0xB808}, ++{0x2510, 0xC800}, ++{0x2510, 0xE807}, ++{0x2510, 0x88DB}, ++{0x2510, 0xF8A8}, ++{0x2510, 0xF888}, ++{0x2510, 0x2203}, ++{0x2510, 0xB07B}, ++{0x2510, 0x2000}, ++{0x2510, 0x80C8}, ++{0x2510, 0x8088}, ++{0x2510, 0x220B}, ++{0x2510, 0xB06A}, ++{0x2510, 0x88CB}, ++{0x2510, 0x888B}, ++{0x2510, 0x221F}, ++{0x2510, 0xB04A}, ++{0x2510, 0x2213}, ++{0x2510, 0x210D}, ++{0x2510, 0x2108}, ++{0x2510, 0x902F}, ++{0x2510, 0xB04B}, ++{0x2510, 0xF880}, ++{0x2510, 0x2205}, ++{0x2510, 0x2205}, ++{0x2510, 0x2203}, ++{0x2510, 0x9800}, ++{0x2510, 0xB043}, ++{0x2510, 0xA8C9}, ++{0x2510, 0x31C1}, ++{0x2510, 0x80A8}, ++{0x2510, 0x2205}, ++{0x2510, 0x916F}, ++{0x2510, 0x2104}, ++{0x2510, 0x88AB}, ++{0x2510, 0x2104}, ++{0x2510, 0xB808}, ++{0x2510, 0x9800}, ++{0x2510, 0x2440}, ++{0x2510, 0xF110}, ++{0x2510, 0xF804}, ++{0x2510, 0x2000}, ++{0x2510, 0x8088}, ++{0x2510, 0x3002}, ++{0x2510, 0xB838}, ++{0x2510, 0xA8C8}, ++{0x2510, 0xB04B}, ++{0x2510, 0x2442}, ++{0x2510, 0x3210}, ++{0x2510, 0x2206}, ++{0x2510, 0x888B}, ++{0x2510, 0x2203}, ++{0x2510, 0xF1CB}, ++{0x2510, 0x2201}, ++{0x2510, 0x3202}, ++{0x2510, 0xF880}, ++{0x2510, 0xB830}, ++{0x2510, 0xC801}, ++{0x2510, 0x30C2}, ++{0x2510, 0xE80C}, ++{0x2510, 0x2201}, ++{0x2510, 0xB04A}, ++{0x2510, 0x2217}, ++{0x2510, 0x2205}, ++{0x2510, 0x2207}, ++{0x2510, 0x902F}, ++{0x2510, 0x220E}, ++{0x2510, 0x2205}, ++{0x2510, 0x2204}, ++{0x2510, 0xB042}, ++{0x2510, 0xA9A1}, ++{0x2510, 0x8008}, ++{0x2510, 0xB0D3}, ++{0x2510, 0x31C1}, ++{0x2510, 0x916B}, ++{0x2510, 0x2008}, ++{0x2510, 0x32C1}, ++{0x2510, 0x8803}, ++{0x2510, 0xA044}, ++{0x2510, 0x3044}, ++{0x2510, 0x2000}, ++{0x2510, 0xA004}, ++{0x2510, 0x2000}, ++{0x2510, 0x7FFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{0x2510, 0xFFFF}, ++{AR0233_DELAY, 100}, ++/* Sequence_hidy_ar0233_REV2_seplus */ ++ ++{0x3E14, 0x003F}, ++{0x3E14, 0x003F}, ++{0x3E18, 0x0F52}, ++{0x3E18, 0x0F52}, ++{0x562A, 0x03E8}, // OCL_T1_E2_E1_SAT ++ ++{0x3364, 0x06F4}, ++ ++/* Tempsensor_init */ ++{0x3E94, 0x3007}, ++{0x3E6E, 0xE200}, // TEMPVSENS1_TMG_CTRL_K0 ++{0x3E98, 0x1000}, // TEMPVSENS1_EN_CTRL ++{0x3F92, 0x4C00}, // TEMPVSENS1_TMG_CTRL ++{0x30B8, 0x000B}, // TEMPSENS1_CTRL_REG ++{0x30B8, 0x0003}, // TEMPSENS1_CTRL_REG ++{ } ++}; /* O1_Recommended_Defaults_SE_T1_LIN_T2 */ ++ + static const struct ar0233_reg ar0233_rev2_disable_embed_data_stat[] = { + {0x3064, 0x0}, // Disable embedded data and stat + #ifdef AR0233_EMBEDDED_LINE +@@ -1146,6 +2286,22 @@ static const struct ar0233_reg ar0233_rev2_HDR_3exp_12bit[] = { + { } + }; /* HDR_3exp_12bit */ + ++static const struct ar0233_reg ar0233_rev2_SEPLUS_12bit[] = { ++{0x3082, 0x4}, //num_exp = 2 ++{0x30BA, 0x1121}, //num_exp_max =2 ++{0x31AC, 0x140C}, //12 bit output ++ ++{0x3044, 0x0400}, //Dark_control ++ ++// FPS = 102MHz / reg0x300A / reg0x300C ++{0x300A, AR0233_SENSOR_HEIGHT + 100}, // Frame_length_Lines ++{0x300C, AR0233_SENSOR_WIDTH + 400}, // Line_length_pck ++{0x3012, 0x0299}, // COARSE_INTEGRATION_TIME_ ++{0x3212, 0x0006}, // COARSE_INTEGRATION_TIME2 ++{0x3112, 0x71E7}, ++{ } ++}; /* HDR_3exp_12bit */ ++ + static const struct ar0233_reg ar0233_rev2_pll_23_102_4lane_12b[] = { + // serial_data_rate was *2 in REV1. but not in REV2 + /* PCLK=DES_REFCLK/PRE_PLL_CLK_DIV *PLL_MULTIPLIER /P1 /P4 */ +@@ -1229,6 +2385,18 @@ static const struct ar0233_reg ar0233_rev2_HDR_ratio_gain_default[] = { + { } + }; /* HDR_ratio_gain_default */ + ++static const struct ar0233_reg ar0233_rev2_SEPLUS_ratio_gain_default[] = { ++{0x3362, 0x0001}, // DC_GAIN ++{0x3238, 0x8446}, // EXPOSURE_RATIO ++{0x562E, 0x0111}, // OCL_T1_GAIN_ ++{0x562E, 0x0111}, // OCL_T1_GAIN_ ++{0x3366, 0x4441}, // ANALOG_GAIN ++{0x3366, 0x4431}, // ANALOG_GAIN ++{0x336A, 0x0000}, // ANALOG_GAIN2 ++{0x336A, 0x00C0}, // ANALOG_GAIN2 ++{ } ++}; /* SEPLUS_ratio_gain_default */ ++ + /* 3Exp HDR, 1280P, MIPI 4-lane 12-bit, 30fps, EXTCLK=23MHz (comes from deser) */ + static const struct ar0233_reg *ar0233_regs_hdr_mipi_12bit_30fps_rev2[] = { + ar0233_rev2_Reset, +@@ -1242,3 +2410,17 @@ static const struct ar0233_reg *ar0233_regs_hdr_mipi_12bit_30fps_rev2[] = { + ar0233_rev2_HDR_ratio_gain_default, + NULL, + }; ++ ++/* SE_T1 + Lin_T2, 1280P, MIPI 750MBPS 4-lane 12-bit, 30fps, EXTCLK=23MHz (comes from deser) */ ++static const struct ar0233_reg *ar0233_regs_seplus_mipi_12bit_30fps_rev2[] = { ++ ar0233_rev2_Reset, ++ ar0233_rev2_Full_resolution, ++ ar0233_rev2_pll_23_102_4lane_12b, ++ ar0233_rev2_mipi_12bit_4lane, ++ ar0233_rev2_O1_Recommended_Defaults_SE_T1_LIN_T2, ++ ar0233_rev2_disable_embed_data_stat, ++ ar0233_rev2_SEPLUS_12bit, ++ ar0233_rev2_LUT_24_to_12, ++ ar0233_rev2_SEPLUS_ratio_gain_default, ++ NULL, ++}; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0167-lvds-AR0233-fix-matrix-size-set-default-h-vflip.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0167-lvds-AR0233-fix-matrix-size-set-default-h-vflip.patch new file mode 100644 index 00000000..3659060d --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0167-lvds-AR0233-fix-matrix-size-set-default-h-vflip.patch @@ -0,0 +1,90 @@ +From 42172a5124173f1c30ac097f2d788a1beaacbe3d Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Thu, 9 May 2019 23:09:53 +0300 +Subject: [PATCH 116/122] lvds: AR0233: fix matrix size, set default h/vflip + +AR0233 matrix array 2072x1296 +set default hflip and vflip as perspecitve view i.e. flipped + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ar0233.c | 6 +++--- + drivers/media/i2c/soc_camera/ar0233.h | 4 ++-- + drivers/media/i2c/soc_camera/ar0233_rev1.h | 2 +- + drivers/media/i2c/soc_camera/ar0233_rev2.h | 4 +++- + 4 files changed, 9 insertions(+), 7 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ar0233.c b/drivers/media/i2c/soc_camera/ar0233.c +index 5c3d4e1..862c820 100644 +--- a/drivers/media/i2c/soc_camera/ar0233.c ++++ b/drivers/media/i2c/soc_camera/ar0233.c +@@ -99,7 +99,7 @@ static int ar0233_set_window(struct v4l2_subdev *sd) + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ar0233_priv *priv = to_ar0233(client); + +- dev_err(&client->dev, "L=%d T=%d %dx%d\n", priv->rect.left, priv->rect.top, priv->rect.width, priv->rect.height); ++ dev_dbg(&client->dev, "L=%d T=%d %dx%d\n", priv->rect.left, priv->rect.top, priv->rect.width, priv->rect.height); + + /* horiz crop start */ + reg16_write16(client, 0x3004, priv->rect.left); +@@ -554,9 +554,9 @@ static int ar0233_probe(struct i2c_client *client, + v4l2_ctrl_new_std(&priv->hdl, &ar0233_ctrl_ops, + V4L2_CID_EXPOSURE, 1, 0x600, 1, 0x144); + v4l2_ctrl_new_std(&priv->hdl, &ar0233_ctrl_ops, +- V4L2_CID_HFLIP, 0, 1, 1, 0); ++ V4L2_CID_HFLIP, 0, 1, 1, 1); + v4l2_ctrl_new_std(&priv->hdl, &ar0233_ctrl_ops, +- V4L2_CID_VFLIP, 0, 1, 1, 0); ++ V4L2_CID_VFLIP, 0, 1, 1, 1); + priv->sd.ctrl_handler = &priv->hdl; + + ret = priv->hdl.error; +diff --git a/drivers/media/i2c/soc_camera/ar0233.h b/drivers/media/i2c/soc_camera/ar0233.h +index f6ba245..5f2bada 100644 +--- a/drivers/media/i2c/soc_camera/ar0233.h ++++ b/drivers/media/i2c/soc_camera/ar0233.h +@@ -17,8 +17,8 @@ + + #define AR0233_DELAY 0xffff + +-#define AR0233_SENSOR_WIDTH 2058 +-#define AR0233_SENSOR_HEIGHT 1284 ++#define AR0233_SENSOR_WIDTH 2072 ++#define AR0233_SENSOR_HEIGHT 1296 + + #define AR0233_X_START ((AR0233_SENSOR_WIDTH - AR0233_MAX_WIDTH) / 2) + #define AR0233_Y_START ((AR0233_SENSOR_HEIGHT - AR0233_MAX_HEIGHT) / 2) +diff --git a/drivers/media/i2c/soc_camera/ar0233_rev1.h b/drivers/media/i2c/soc_camera/ar0233_rev1.h +index 7b6370b..ddc1612 100644 +--- a/drivers/media/i2c/soc_camera/ar0233_rev1.h ++++ b/drivers/media/i2c/soc_camera/ar0233_rev1.h +@@ -1156,8 +1156,8 @@ static const struct ar0233_reg ar0233_rev1_Full_resolution[] = { + }; /* Full_resolution */ + + static const struct ar0233_reg ar0233_rev1_disable_embed_data_stat[] = { ++{0x3040, 0xC000}, //Embedded stat2 and data2 rows, hflip/vflip=1 + #ifdef AR0233_EMBEDDED_LINE +-{0x3040, 0x0000}, //Embedded stat2 and data2 rows + {0x3064, 0x0180}, //Enable embedded data and stat + #else + {0x3064, 0x0}, //Disable embedded data and stat +diff --git a/drivers/media/i2c/soc_camera/ar0233_rev2.h b/drivers/media/i2c/soc_camera/ar0233_rev2.h +index 02d9af1..66c79ca 100644 +--- a/drivers/media/i2c/soc_camera/ar0233_rev2.h ++++ b/drivers/media/i2c/soc_camera/ar0233_rev2.h +@@ -2265,9 +2265,11 @@ static const struct ar0233_reg ar0233_rev2_O1_Recommended_Defaults_SE_T1_LIN_T2[ + }; /* O1_Recommended_Defaults_SE_T1_LIN_T2 */ + + static const struct ar0233_reg ar0233_rev2_disable_embed_data_stat[] = { +-{0x3064, 0x0}, // Disable embedded data and stat ++{0x3040, 0xC000}, //Embedded stat2 and data2 rows, hflip/vflip=1 + #ifdef AR0233_EMBEDDED_LINE + {0x3064, 0x0180}, // SMIA_TEST: enable emb data and stats ++#else ++{0x3064, 0x0}, // Disable embedded data and stat + #endif + { } + }; /* disable_embed_data_stat */ +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0168-lvds-ISX019-fix-add-address-intf-fix-read-write.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0168-lvds-ISX019-fix-add-address-intf-fix-read-write.patch new file mode 100644 index 00000000..efe99fbd --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0168-lvds-ISX019-fix-add-address-intf-fix-read-write.patch @@ -0,0 +1,228 @@ +From 95a48f63ed8839cce6d91c53a72f67551c2f7a92 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Mon, 13 May 2019 16:38:48 +0300 +Subject: [PATCH 117/122] lvds: ISX019: fix add address intf, fix read/write + +- Add command/address register access interfaces +- fix endianess of data +- read resolution from registers +--- + drivers/media/i2c/soc_camera/isx019.c | 112 ++++++++++++++++++++-------------- + drivers/media/i2c/soc_camera/isx019.h | 9 ++- + 2 files changed, 73 insertions(+), 48 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/isx019.c b/drivers/media/i2c/soc_camera/isx019.c +index 650b533..c2f5a4a 100644 +--- a/drivers/media/i2c/soc_camera/isx019.c ++++ b/drivers/media/i2c/soc_camera/isx019.c +@@ -25,7 +25,7 @@ + static const int isx019_i2c_addr[] = {0x1a}; + + #define ISX019_PID 0x0000 +-#define ISX019_VERSION_REG 0x0740 ++#define ISX019_VERSION_REG 0x4000 + + #define ISX019_MEDIA_BUS_FMT MEDIA_BUS_FMT_YUYV8_2X8 + +@@ -51,6 +51,10 @@ struct isx019_priv { + int gpio_fsin; + }; + ++static char *intf = "command"; ++module_param(intf, charp, 0644); ++MODULE_PARM_DESC(intf, " Registers access interface command,address (default: command)"); ++ + static inline struct isx019_priv *to_isx019(const struct i2c_client *client) + { + return container_of(i2c_get_clientdata(client), struct isx019_priv, sd); +@@ -72,31 +76,40 @@ static void isx019_s_port(struct i2c_client *client, int fwd_en) + + static int isx019_read16(struct i2c_client *client, u8 category, u16 reg, u16 *val) + { +- int ret; ++ int ret = -1; ++ ++ if (strcmp(intf, "command") == 0) { + #define R_NUM_BYTES 9 + #define R_NUM_CMDS 1 + #define R_NUM_CMD_BYTES 6 + #define R_CMD 1 + #define R_BYTES 2 +- u8 buf[R_NUM_BYTES] = {R_NUM_BYTES, R_NUM_CMDS, +- R_NUM_CMD_BYTES, R_CMD, +- category, reg >> 8, reg & 0xff, +- R_BYTES, 0x00}; +- +- /* calculate checksum */ +- buf[8] = R_NUM_BYTES + R_NUM_CMDS + R_NUM_CMD_BYTES + R_CMD + +- category + (reg >> 8) + (reg & 0xff) + R_BYTES; +- +- ret = i2c_master_send(client, buf, R_NUM_BYTES); +- if (ret == R_NUM_BYTES) +- ret = i2c_master_recv(client, buf, R_NUM_BYTES - 2); +- +- if (ret < 0) { +- dev_err(&client->dev, +- "read fail: chip 0x%x register 0x%x: %d\n", +- client->addr, reg, ret); ++ u8 buf[R_NUM_BYTES] = {R_NUM_BYTES, R_NUM_CMDS, ++ R_NUM_CMD_BYTES, R_CMD, ++ category, reg >> 8, reg & 0xff, ++ R_BYTES, 0x00}; ++ ++ /* calculate checksum */ ++ buf[8] = R_NUM_BYTES + R_NUM_CMDS + R_NUM_CMD_BYTES + R_CMD + ++ category + (reg >> 8) + (reg & 0xff) + R_BYTES; ++ ++ ret = i2c_master_send(client, buf, R_NUM_BYTES); ++ if (ret == R_NUM_BYTES) ++ ret = i2c_master_recv(client, buf, R_NUM_BYTES - 2); ++ ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "read fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } else { ++ *val = buf[4] | ((u16)buf[5] << 8); ++ } ++ } else if (strcmp(intf, "address") == 0) { ++ reg16_write(client, 0xFFFF, category); ++ ret = reg16_read16(client, reg, val); ++ *val = swab16p(val); + } else { +- *val = ((u16)buf[4] << 8) | buf[5]; ++ dev_err(&client->dev, "invalid register access interface %s\n", intf); + } + + return ret < 0 ? ret : 0; +@@ -104,26 +117,35 @@ static int isx019_read16(struct i2c_client *client, u8 category, u16 reg, u16 *v + + static int isx019_write16(struct i2c_client *client, u8 category, u16 reg, u16 val) + { +- int ret; ++ int ret = -1; ++ ++ if (strcmp(intf, "command") == 0) { + #define W_NUM_BYTES 10 + #define W_NUM_CMDS 1 + #define W_NUM_CMD_BYTES 7 + #define W_CMD 2 +- u8 buf[W_NUM_BYTES] = {W_NUM_BYTES, W_NUM_CMDS, +- W_NUM_CMD_BYTES, W_CMD, +- category, reg >> 8, reg & 0xff, +- val >> 8, val & 0xff}; ++ u8 buf[W_NUM_BYTES] = {W_NUM_BYTES, W_NUM_CMDS, ++ W_NUM_CMD_BYTES, W_CMD, ++ category, reg >> 8, reg & 0xff, ++ val & 0xff, val >> 8}; + +- /* calculate checksum */ +- buf[9] = W_NUM_BYTES + W_NUM_CMDS + W_NUM_CMD_BYTES + W_CMD + +- category + (reg >> 8) + (reg & 0xff) + (val >> 8) + (val & 0xff); ++ /* calculate checksum */ ++ buf[9] = W_NUM_BYTES + W_NUM_CMDS + W_NUM_CMD_BYTES + W_CMD + ++ category + (reg >> 8) + (reg & 0xff) + (val >> 8) + (val & 0xff); + +- ret = i2c_master_send(client, buf, W_NUM_BYTES); ++ ret = i2c_master_send(client, buf, W_NUM_BYTES); + +- if (ret < 0) { +- dev_err(&client->dev, +- "write fail: chip 0x%x register 0x%x: %d\n", +- client->addr, reg, ret); ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "write fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } ++ } else if (strcmp(intf, "address") == 0) { ++ val = swab16(val); ++ reg16_write(client, 0xFFFF, category); ++ ret = reg16_write16(client, reg, val); ++ } else { ++ dev_err(&client->dev, "invalid register acces interface %s\n", intf); + } + + return ret < 0 ? ret : 0; +@@ -404,13 +426,11 @@ static DEVICE_ATTR(otp_id_isx019, S_IRUGO, isx019_otp_id_show, NULL); + static int isx019_initialize(struct i2c_client *client) + { + struct isx019_priv *priv = to_isx019(client); +- u16 pid = 0; ++ u16 pid = 0, val = 0; + int ret = 0; + int tmp_addr; + int i; + +- isx019_s_port(client, 1); +- + for (i = 0; i < ARRAY_SIZE(isx019_i2c_addr); i++) { + tmp_addr = client->addr; + if (priv->max9286_addr) { +@@ -423,26 +443,28 @@ static int isx019_initialize(struct i2c_client *client) + /* check model ID */ + isx019_read16(client, 0, ISX019_PID, &pid); + +- if (pid == ISX019_VERSION_REG) ++ if ((pid & 0xff00) == ISX019_VERSION_REG) + break; + } + +- if (pid != ISX019_VERSION_REG) { +- dev_dbg(&client->dev, "Product ID error %x\n", pid); ++ if ((pid & 0xff00) != ISX019_VERSION_REG) { ++ dev_err(&client->dev, "Product ID error %x\n", pid); + ret = -ENODEV; + goto err; + } + +- priv->max_width = ISX019_MAX_WIDTH; +- priv->max_height = ISX019_MAX_HEIGHT; +- + /* Read OTP IDs */ + isx019_otp_id_read(client); + /* Program wizard registers */ + isx019_set_regs(client, isx019_regs_wizard, ARRAY_SIZE(isx019_regs_wizard)); +- +- dev_info(&client->dev, "isx019 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", +- pid, priv->max_width, priv->max_height, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++ /* read resolution used by current firmware */ ++ isx019_read16(client, 86, 0x8, &val); ++ priv->max_width = val; ++ isx019_read16(client, 86, 0xa, &val); ++ priv->max_height = val; ++ ++ dev_info(&client->dev, "isx019 PID %x (rev %x), res %dx%d, if=%s, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid & 0xff00, pid & 0xff, priv->max_width, priv->max_height, intf, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); + err: + isx019_s_port(client, 0); + +diff --git a/drivers/media/i2c/soc_camera/isx019.h b/drivers/media/i2c/soc_camera/isx019.h +index edaa767..c7072a3 100644 +--- a/drivers/media/i2c/soc_camera/isx019.h ++++ b/drivers/media/i2c/soc_camera/isx019.h +@@ -9,8 +9,8 @@ + * option) any later version. + */ + +-#define ISX019_MAX_WIDTH 1280 +-#define ISX019_MAX_HEIGHT 800 ++//#define ISX019_MAX_WIDTH 1280 ++//#define ISX019_MAX_HEIGHT 960 + + #define ISX019_DELAY 0xffff + +@@ -22,6 +22,9 @@ struct isx019_reg { + static const struct isx019_reg isx019_regs_wizard[] = { + #if 0 + /* enable FSIN */ +-#endif + {ISX019_DELAY, 100}, ++#endif ++/* disable embedded data */ ++{0x504c, 0x0}, ++{0x504e, 0x0}, + }; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0169-lvds-OVT-add-dvp_order-parameter-for-ov10635.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0169-lvds-OVT-add-dvp_order-parameter-for-ov10635.patch new file mode 100644 index 00000000..8b8a8385 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0169-lvds-OVT-add-dvp_order-parameter-for-ov10635.patch @@ -0,0 +1,67 @@ +From ec363617669effd4e49f0b27ab12015a60455930 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Tue, 14 May 2019 16:33:15 +0300 +Subject: [PATCH 118/122] lvds: OVT: add dvp_order parameter for ov10635 + +Fix dvp_order for both ov490 and ov10635 + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ov10635.c | 9 +++++++++ + drivers/media/i2c/soc_camera/ov490_ov10640.c | 6 +----- + 2 files changed, 10 insertions(+), 5 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ov10635.c b/drivers/media/i2c/soc_camera/ov10635.c +index 916173c..1bbde91 100644 +--- a/drivers/media/i2c/soc_camera/ov10635.c ++++ b/drivers/media/i2c/soc_camera/ov10635.c +@@ -50,6 +50,11 @@ struct ov10635_priv { + int gpio_fsin; + }; + ++ ++static int dvp_order = -1; ++module_param(dvp_order, int, 0644); ++MODULE_PARM_DESC(dvp_order, " DVP bus bits order"); ++ + static inline struct ov10635_priv *to_ov10635(const struct i2c_client *client) + { + return container_of(i2c_get_clientdata(client), struct ov10635_priv, sd); +@@ -601,6 +606,10 @@ static int ov10635_parse_dt(struct device_node *np, struct ov10635_priv *priv) + + udelay(100); + ++ /* module params override dts */ ++ if (dvp_order != -1) ++ priv->dvp_order = dvp_order; ++ + return 0; + } + +diff --git a/drivers/media/i2c/soc_camera/ov490_ov10640.c b/drivers/media/i2c/soc_camera/ov490_ov10640.c +index 1c8aac8..0ea9a54 100644 +--- a/drivers/media/i2c/soc_camera/ov490_ov10640.c ++++ b/drivers/media/i2c/soc_camera/ov490_ov10640.c +@@ -69,10 +69,6 @@ static int conf_link; + module_param(conf_link, int, 0644); + MODULE_PARM_DESC(conf_link, " Force configuration link. Used only if robust firmware flashing required (f.e. recovery)"); + +-static int dvp_order; +-module_param(dvp_order, int, 0644); +-MODULE_PARM_DESC(dvp_order, " DVP bus bits order"); +- + static int max_width; + module_param(max_width, int, 0644); + MODULE_PARM_DESC(max_width, " Fixed sensor width"); +@@ -972,7 +968,7 @@ static int ov490_parse_dt(struct device_node *np, struct ov490_priv *priv) + } + + /* module params override dts */ +- if (dvp_order) ++ if (dvp_order != -1) + priv->dvp_order = dvp_order; + if (max_width && max_height) { + priv->max_width = max_width; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0170-media-i2c-add-AR0147-imager.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0170-media-i2c-add-AR0147-imager.patch new file mode 100644 index 00000000..b07b7b87 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0170-media-i2c-add-AR0147-imager.patch @@ -0,0 +1,2224 @@ +From 0901b9accc0ee11072daebedbc385cf38364144a Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Sun, 21 Apr 2019 19:44:00 +0300 +Subject: [PATCH 119/122] media: i2c: add AR0147 imager + +This adds AR0147 imager + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/Kconfig | 6 + + drivers/media/i2c/soc_camera/Makefile | 1 + + drivers/media/i2c/soc_camera/ar0147.c | 714 ++++++++++++++++++++++++++ + drivers/media/i2c/soc_camera/ar0147.h | 36 ++ + drivers/media/i2c/soc_camera/ar0147_rev1.h | 607 ++++++++++++++++++++++ + drivers/media/i2c/soc_camera/ar0147_rev2.h | 796 +++++++++++++++++++++++++++++ + 6 files changed, 2160 insertions(+) + create mode 100644 drivers/media/i2c/soc_camera/ar0147.c + create mode 100644 drivers/media/i2c/soc_camera/ar0147.h + create mode 100644 drivers/media/i2c/soc_camera/ar0147_rev1.h + create mode 100644 drivers/media/i2c/soc_camera/ar0147_rev2.h + +diff --git a/drivers/media/i2c/soc_camera/Kconfig b/drivers/media/i2c/soc_camera/Kconfig +index 627d8d9..edff0b0 100644 +--- a/drivers/media/i2c/soc_camera/Kconfig ++++ b/drivers/media/i2c/soc_camera/Kconfig +@@ -106,3 +106,9 @@ config SOC_CAMERA_IMX219 + depends on SOC_CAMERA && I2C + help + This is Sony IMX219 driver ++ ++config SOC_CAMERA_AR0147 ++ tristate "AR0147 camera support" ++ depends on SOC_CAMERA && I2C ++ help ++ This is an AR0147 imager glue +diff --git a/drivers/media/i2c/soc_camera/Makefile b/drivers/media/i2c/soc_camera/Makefile +index 4aa5046..367674b 100644 +--- a/drivers/media/i2c/soc_camera/Makefile ++++ b/drivers/media/i2c/soc_camera/Makefile +@@ -17,3 +17,4 @@ obj-$(CONFIG_SOC_CAMERA_OV106XX) += ov106xx.o + obj-$(CONFIG_SOC_CAMERA_IMX219) += imx219.o + obj-y += dummy.o + ++obj-$(CONFIG_SOC_CAMERA_AR0147) += ar0147.o +diff --git a/drivers/media/i2c/soc_camera/ar0147.c b/drivers/media/i2c/soc_camera/ar0147.c +new file mode 100644 +index 0000000..cc7face +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0147.c +@@ -0,0 +1,714 @@ ++/* ++ * ON Semiconductor AR0147 sensor camera driver ++ * ++ * Copyright (C) 2019 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "max9286.h" ++#include "ar0147.h" ++ ++#define AR0147_I2C_ADDR 0x10 ++ ++#define AR0147_PID 0x3000 ++#define AR0147_REV 0x31FE ++#define AR0147_VERSION_REG 0x1D54 ++ ++#define AR0147_MEDIA_BUS_FMT MEDIA_BUS_FMT_SGRBG12_1X12 ++ ++struct ar0147_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int init_complete; ++ u8 id[6]; ++ /* serializers */ ++ int max9286_addr; ++ int max9271_addr; ++ int ti9x4_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++ int hts; ++ int vts; ++ int frame_preamble; ++}; ++ ++static char *mode = "hdr"; ++module_param(mode, charp, 0644); ++MODULE_PARM_DESC(mode, " Modes linear,hdr,se,seplus (default: hdr)"); ++ ++static inline struct ar0147_priv *to_ar0147(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct ar0147_priv, sd); ++} ++ ++static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) ++{ ++ return &container_of(ctrl->handler, struct ar0147_priv, hdl)->sd; ++} ++ ++static void ar0147_s_port(struct i2c_client *client, int fwd_en) ++{ ++ struct ar0147_priv *priv = to_ar0147(client); ++ int tmp_addr; ++ ++ if (priv->max9286_addr) { ++ tmp_addr = client->addr; ++ client->addr = priv->max9286_addr; /* Deserializer I2C address */ ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ client->addr = tmp_addr; ++ }; ++} ++ ++static int ar0147_set_regs(struct i2c_client *client, const struct ar0147_reg **pregs) ++{ ++ struct ar0147_priv *priv = to_ar0147(client); ++ const struct ar0147_reg *regs; ++ int i, j; ++ ++ for (j = 0; ; j++) { ++ regs = pregs[j]; ++ ++ if (!pregs[j]) ++ break; ++ ++ for (i = 0; ; i++) { ++ if (!regs[i].reg && !regs[i].val) ++ break; ++ ++ if (regs[i].reg == AR0147_DELAY) { ++ mdelay(regs[i].val); ++ continue; ++ } ++ /* cache timings */ ++ if (regs[i].reg == 0x300a) ++ priv->vts = regs[i].val; ++ if (regs[i].reg == 0x300c) ++ priv->hts = regs[i].val; ++ if (regs[i].reg == 0x31b0) ++ priv->frame_preamble = regs[i].val - 1; ++ ++ if (priv->ti9x4_addr) { ++ /* Override default (MAXIM serializer) table */ ++ /* PCLK=16Mhz/2 *48/1/8= 48Mhz - TI serializers */ ++ switch (regs[i].reg) { ++ case 0x302A: ++ reg16_write16(client, regs[i].reg, 8); // VT_PIX_CLK_DIV ++ continue; ++ case 0x302C: ++ reg16_write16(client, regs[i].reg, 1); // VT_SYS_CLK_DIV ++ continue; ++ case 0x302E: ++ reg16_write16(client, regs[i].reg, 2); // PRE_PLL_CLK_DIV ++ continue; ++ case 0x3030: ++ reg16_write16(client, regs[i].reg, 48); // PLL_MULTIPLIER ++ continue; ++ case 0x3036: ++ reg16_write16(client, regs[i].reg, 8); // OP_WORD_CLK_DIV ++ continue; ++ case 0x3038: ++ reg16_write16(client, regs[i].reg, 1); // OP_SYS_CLK_DIV ++ continue; ++ case 0x300A: ++ reg16_write16(client, regs[i].reg, AR0147_SENSOR_HEIGHT + 142); // FRAME_LENGTH_LINES_ ++ continue; ++ } ++ } ++ ++ reg16_write16(client, regs[i].reg, regs[i].val); ++ } ++ } ++ ++ return 0; ++} ++ ++static int ar0147_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int ar0147_set_window(struct v4l2_subdev *sd) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0147_priv *priv = to_ar0147(client); ++ ++ dev_dbg(&client->dev, "L=%d T=%d %dx%d\n", priv->rect.left, priv->rect.top, priv->rect.width, priv->rect.height); ++ ++ /* horiz crop start */ ++ reg16_write16(client, 0x3004, priv->rect.left); ++ /* horiz crop end */ ++ reg16_write16(client, 0x3008, priv->rect.left + priv->rect.width - 1); ++ /* vert crop start */ ++ reg16_write16(client, 0x3002, priv->rect.top); ++ /* vert crop end */ ++ reg16_write16(client, 0x3006, priv->rect.top + priv->rect.height - 1); ++ ++ return 0; ++}; ++ ++static int ar0147_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0147_priv *priv = to_ar0147(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = AR0147_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int ar0147_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = AR0147_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int ar0147_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = AR0147_MEDIA_BUS_FMT; ++ ++ return 0; ++} ++ ++static int ar0147_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0147_priv *priv = to_ar0147(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = AR0147_VERSION_REG >> 8; ++ edid->edid[9] = AR0147_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int ar0147_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0147_priv *priv = to_ar0147(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > AR0147_MAX_WIDTH) || ++ (rect->top + rect->height > AR0147_MAX_HEIGHT)) ++ *rect = priv->rect; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ ar0147_set_window(sd); ++ ++ return 0; ++} ++ ++static int ar0147_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0147_priv *priv = to_ar0147(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = AR0147_MAX_WIDTH; ++ sel->r.height = AR0147_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = AR0147_MAX_WIDTH; ++ sel->r.height = AR0147_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ar0147_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int ar0147_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u16 val = 0; ++ ++ ret = reg16_read16(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int ar0147_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return reg16_write16(client, (u16)reg->reg, (u16)reg->val); ++} ++#endif ++ ++static struct v4l2_subdev_core_ops ar0147_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ar0147_g_register, ++ .s_register = ar0147_s_register, ++#endif ++}; ++ ++static int ar0147_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0147_priv *priv = to_ar0147(client); ++ int ret = -EINVAL; ++ u16 val = 0; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ case V4L2_CID_CONTRAST: ++ case V4L2_CID_SATURATION: ++ case V4L2_CID_HUE: ++ case V4L2_CID_GAMMA: ++ case V4L2_CID_SHARPNESS: ++ case V4L2_CID_AUTOGAIN: ++ break; ++ case V4L2_CID_GAIN: ++ /* Digital gain */ ++ ret = reg16_write16(client, 0x3308, ctrl->val); ++ break; ++ case V4L2_CID_ANALOGUE_GAIN: ++ /* Analog gain */ ++ ret = reg16_write16(client, 0x3366, ctrl->val); ++ break; ++ case V4L2_CID_EXPOSURE: ++ /* T1 exposure */ ++ ret = reg16_write16(client, 0x3012, ctrl->val); ++ break; ++ case V4L2_CID_HFLIP: ++ ret = reg16_read16(client, 0x3040, &val); ++ if (ctrl->val) ++ val |= 0x4000; ++ else ++ val &= ~0x4000; ++ ret |= reg16_write16(client, 0x3040, val); ++ break; ++ case V4L2_CID_VFLIP: ++ ret = reg16_read16(client, 0x3040, &val); ++ if (ctrl->val) ++ val |= 0x8000; ++ else ++ val &= ~0x8000; ++ ret |= reg16_write16(client, 0x3040, val); ++ break; ++ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: ++ ret = 0; ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ar0147_ctrl_ops = { ++ .s_ctrl = ar0147_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops ar0147_video_ops = { ++ .s_stream = ar0147_s_stream, ++ .g_mbus_config = ar0147_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops ar0147_subdev_pad_ops = { ++ .get_edid = ar0147_get_edid, ++ .enum_mbus_code = ar0147_enum_mbus_code, ++ .get_selection = ar0147_get_selection, ++ .set_selection = ar0147_set_selection, ++ .get_fmt = ar0147_get_fmt, ++ .set_fmt = ar0147_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops ar0147_subdev_ops = { ++ .core = &ar0147_core_ops, ++ .video = &ar0147_video_ops, ++ .pad = &ar0147_subdev_pad_ops, ++}; ++ ++static void ar0147_otp_id_read(struct i2c_client *client) ++{ ++ struct ar0147_priv *priv = to_ar0147(client); ++ int i; ++ u16 val = 0; ++ ++ /* read camera id from ar014x OTP memory */ ++ reg16_write16(client, 0x3054, 0x400); ++ reg16_write16(client, 0x304a, 0x110); ++ usleep_range(25000, 25500); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i += 2) { ++ /* first 4 bytes are equal on all ar014x */ ++ reg16_read16(client, 0x3800 + i + 4, &val); ++ priv->id[i] = val >> 8; ++ priv->id[i + 1] = val & 0xff; ++ } ++} ++ ++static ssize_t ar0147_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0147_priv *priv = to_ar0147(client); ++ ++ ar0147_otp_id_read(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_ar0147, S_IRUGO, ar0147_otp_id_show, NULL); ++ ++static int ar0147_initialize(struct i2c_client *client) ++{ ++ struct ar0147_priv *priv = to_ar0147(client); ++ u16 val = 0; ++ u16 pid = 0, rev = 0; ++ int ret = 0; ++ int tmp_addr; ++ ++ ar0147_s_port(client, 1); ++ ++ /* check and show model ID */ ++ reg16_read16(client, AR0147_PID, &pid); ++ ++ if (pid != AR0147_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x\n\n\n", pid); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ /* check revision */ ++ reg16_read16(client, AR0147_REV, &rev); ++ /* Read OTP IDs */ ++ ar0147_otp_id_read(client); ++ /* Program wizard registers */ ++ switch (rev & 0xf) { ++ case 0x1: ++ ar0147_set_regs(client, ar0147_regs_hdr_mipi450mbps_12bit_30fps_rev1); ++ break; ++ case 0x2: ++ if (strcmp(mode, "hdr") == 0) ++ ar0147_set_regs(client, ar0147_regs_hdr_mipi450mbps_12bit_30fps_rev2); ++ else if (strcmp(mode, "seplus") == 0) ++ ar0147_set_regs(client, ar0147_regs_seplus_mipi450mbps_12bit_30fps_rev2); ++ else ++ dev_err(&client->dev, "Unsupported mode %s\n", mode); ++ break; ++ default: ++ dev_err(&client->dev, "Unsupported chip revision\n"); ++ } ++ ++ tmp_addr = client->addr; ++ if (priv->max9271_addr) { ++ /* setup serializer HS generator */ ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x4e, priv->frame_preamble >> 16); /* HS delay */ ++ reg8_write(client, 0x4f, (priv->frame_preamble >> 8) & 0xff); ++ reg8_write(client, 0x50, priv->frame_preamble & 0xff); ++ reg8_write(client, 0x54, AR0147_MAX_WIDTH >> 8); /* HS high period */ ++ reg8_write(client, 0x55, AR0147_MAX_WIDTH & 0xff); ++ reg8_write(client, 0x56, (priv->hts - AR0147_MAX_WIDTH) >> 8); /* HS low period */ ++ reg8_write(client, 0x57, (priv->hts - AR0147_MAX_WIDTH) & 0xff); ++ reg8_write(client, 0x58, priv->vts >> 8); /* HS count */ ++ reg8_write(client, 0x59, priv->vts & 0xff); ++ } ++ client->addr = tmp_addr; ++ ++ /* Enable stream */ ++ reg16_read16(client, 0x301a, &val); ++ val |= (1 << 2); ++ reg16_write16(client, 0x301a, val); ++ ++ dev_info(&client->dev, "ar0147 PID %x (rev %x), res %dx%d, mode=%s, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, rev, AR0147_MAX_WIDTH, AR0147_MAX_HEIGHT, mode, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ ar0147_s_port(client, 0); ++ ++ return ret; ++} ++ ++static int ar0147_parse_dt(struct device_node *np, struct ar0147_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ of_node_put(endpoint); ++ ++ if (!priv->max9286_addr && !priv->ti9x4_addr) { ++ dev_err(&client->dev, "deserializer does not present for AR0147\n"); ++// return -EINVAL; ++ } ++ ++ ar0147_s_port(client, 1); ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ ++ reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x0A, AR0147_I2C_ADDR << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, AR0147_I2C_ADDR << 1); /* Sensor native I2C address */ ++ ++ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - reset, GPIO1 - fsin */ ++ } ++ client->addr = tmp_addr; ++ ++ mdelay(10); ++ ++ return 0; ++} ++ ++static int ar0147_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ar0147_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &ar0147_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops, ++ V4L2_CID_GAIN, 1, 0x7ff, 1, 0x200); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops, ++ V4L2_CID_ANALOGUE_GAIN, 1, 0xe, 1, 0x7); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops, ++ V4L2_CID_EXPOSURE, 1, 0x400, 1, 0x300); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0147_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = ar0147_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = ar0147_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = AR0147_MAX_WIDTH; ++ priv->rect.height = AR0147_MAX_HEIGHT; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ar0147) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_AR0147 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int ar0147_remove(struct i2c_client *client) ++{ ++ struct ar0147_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ar0147); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_AR0147 ++static const struct i2c_device_id ar0147_id[] = { ++ { "ar0147", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ar0147_id); ++ ++static const struct of_device_id ar0147_of_ids[] = { ++ { .compatible = "onnn,ar0147", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ar0147_of_ids); ++ ++static struct i2c_driver ar0147_i2c_driver = { ++ .driver = { ++ .name = "ar0147", ++ .of_match_table = ar0147_of_ids, ++ }, ++ .probe = ar0147_probe, ++ .remove = ar0147_remove, ++ .id_table = ar0147_id, ++}; ++ ++module_i2c_driver(ar0147_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for AR0147"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/ar0147.h b/drivers/media/i2c/soc_camera/ar0147.h +new file mode 100644 +index 0000000..0f7ce31 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0147.h +@@ -0,0 +1,36 @@ ++/* ++ * ON Semiconductor AR0147 sensor camera wizard 1344x968@30/BGGR/BT601/RAW12 ++ * ++ * Copyright (C) 2019 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++//#define AR0147_DISPLAY_PATTERN_FIXED ++//#define AR0147_DISPLAY_PATTERN_COLOR_BAR ++ ++//#define AR0147_EMBEDDED_LINE ++ ++#define AR0147_MAX_WIDTH 1344 ++#define AR0147_MAX_HEIGHT 968 ++ ++#define AR0147_DELAY 0xffff ++ ++#define AR0147_SENSOR_WIDTH 1344 ++#define AR0147_SENSOR_HEIGHT 968 ++ ++#define AR0147_X_START ((AR0147_SENSOR_WIDTH - AR0147_MAX_WIDTH) / 2) ++#define AR0147_Y_START ((AR0147_SENSOR_HEIGHT - AR0147_MAX_HEIGHT) / 2) ++#define AR0147_X_END (AR0147_X_START + AR0147_MAX_WIDTH - 1) ++#define AR0147_Y_END (AR0147_Y_START + AR0147_MAX_HEIGHT - 1) ++ ++struct ar0147_reg { ++ u16 reg; ++ u16 val; ++}; ++ ++#include "ar0147_rev1.h" ++#include "ar0147_rev2.h" +diff --git a/drivers/media/i2c/soc_camera/ar0147_rev1.h b/drivers/media/i2c/soc_camera/ar0147_rev1.h +new file mode 100644 +index 0000000..430e265 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0147_rev1.h +@@ -0,0 +1,607 @@ ++/* ++ * ON Semiconductor AR0147 sensor camera wizard 1344x968@30/BGGR/BT601/RAW12 ++ * ++ * Copyright (C) 2019 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++// #define AR0147_REV1_2_Recommended_Settings ++ ++static const struct ar0147_reg ar0147_rev1_Reset[] = { ++{0x301A, 0x0001}, // reset ++{AR0147_DELAY, 100}, ++{0x301A, 0x10D8}, // Stream off and setup parallel ++{0x3070, 0x0001}, ++{0x3070, 0x0000}, // 1: Solid color test pattern, ++ // 2: Full color bar test pattern, ++ // 3: Fade to grey color bar test pattern, ++ //256: Walking 1 test pattern (12 bit) ++#ifdef AR0147_DISPLAY_PATTERN_FIXED ++{0x3070, 0x0001}, ++#endif ++{0x3072, 0x0fff}, // R ++{0x3074, 0x0fff}, // G(GR row) ++{0x3076, 0x0fff}, // B ++{0x3078, 0x0fff}, // G(GB row) ++#ifdef AR0147_DISPLAY_PATTERN_COLOR_BAR ++{0x3070, 0x0002}, ++#endif ++{AR0147_DELAY, 250}, ++{ } ++}; /* Reset */ ++ ++static const struct ar0147_reg ar0147_rev1_Sensor_Setup[] = { ++/* Recommended_Settings */ ++{0x30B0, 0x980C}, // DIGITAL_TEST ++{0x3C08, 0x0100}, ++{0x3C0C, 0x0518}, ++{0x3092, 0x1A24}, ++{0x30B4, 0x01C7}, // TEMPSENS0_CTRL_REG ++{0x30B8, 0x0007}, // TEMPSENS1_CTRL_REG ++{0x3364, 0x0680}, ++{0x3372, 0x700F}, ++{0x350C, 0x035A}, ++{0x350E, 0x0514}, ++{0x3518, 0x14FE}, ++{0x351A, 0x6000}, ++{0x3520, 0x08CC}, ++{0x3522, 0xCC08}, ++{0x3524, 0x0C00}, ++{0x3526, 0x0F00}, ++{0x3528, 0xFFFF}, ++{0x352A, 0x0897}, ++{0x352C, 0x0012}, ++{0x352E, 0x00FF}, ++{0x3530, 0xFF00}, ++{0x3536, 0xFF24}, ++{0x3538, 0x3CFF}, ++{0x353A, 0x90E0}, ++{0x353C, 0x3F00}, ++{0x3540, 0xC63C}, ++{0x3542, 0x3C3C}, ++{0x3544, 0x3C46}, ++{0x3546, 0x5458}, ++{0x3548, 0x5800}, ++{0x354A, 0x007F}, ++{0x3556, 0x1010}, ++{0x3F90, 0x0800}, // TEMPVSENS0_TMG_CTRL ++{0x3F9A, 0x0000}, // TEMPVSENS0_BOOST_SAMP_CTRL ++{0x3116, 0x0001}, // HDR_CONTROL3 ++{0x3102, 0x60A0}, ++{0x3104, 0x60A0}, ++{0x3106, 0x60A0}, ++ ++//Set REV1 Minimum Analog Gain to LCG 3.5X ++{0x3366, 0xCCCC}, ++{0x3362, 0x0000}, ++#ifdef AR0147_REV1_REV1_2_Recommended_Settings ++//Set REV1.2 Default Analog Gain to LCG 8X (minimum recommended) ++{0x3366, 0xEEEE}, ++#endif /* REV1.2_Recommended_Settings */ ++/* Recommended_Settings */ ++ ++/* Sequencer_Update */ ++{0x2512, 0x8000}, ++{0x2510, 0x0901}, ++{0x2510, 0x3350}, ++{0x2510, 0x2004}, ++{0x2510, 0x1420}, ++{0x2510, 0x1578}, ++{0x2510, 0x087B}, ++{0x2510, 0x24FF}, ++{0x2510, 0x24FF}, ++{0x2510, 0x24EA}, ++{0x2510, 0x2410}, ++{0x2510, 0x2224}, ++{0x2510, 0x1015}, ++{0x2510, 0x5813}, ++{0x2510, 0x0214}, ++{0x2510, 0x0024}, ++{0x2510, 0xFF24}, ++{0x2510, 0xFF24}, ++{0x2510, 0xEA23}, ++{0x2510, 0x2464}, ++{0x2510, 0x7A24}, ++{0x2510, 0x0405}, ++{0x2510, 0x2C40}, ++{0x2510, 0x2A54}, ++{0x2510, 0x0AFF}, ++{0x2510, 0x0A78}, ++{0x2510, 0x4538}, ++{0x2510, 0x5114}, ++{0x2510, 0x4000}, ++{0x2510, 0x0408}, ++{0x2510, 0x0104}, ++{0x2510, 0x0826}, ++{0x2510, 0x5208}, ++{0x2510, 0x1518}, ++{0x2510, 0x13C8}, ++{0x2510, 0x1002}, ++{0x2510, 0x1016}, ++{0x2510, 0x1181}, ++{0x2510, 0x1189}, ++{0x2510, 0x1056}, ++{0x2510, 0x1210}, ++{0x2510, 0x0902}, ++{0x2510, 0x0D09}, ++{0x2510, 0x0515}, ++{0x2510, 0x8813}, ++{0x2510, 0x8809}, ++{0x2510, 0x3811}, ++{0x2510, 0x9911}, ++{0x2510, 0xD909}, ++{0x2510, 0x1E12}, ++{0x2510, 0x1410}, ++{0x2510, 0xD609}, ++{0x2510, 0x0112}, ++{0x2510, 0x1012}, ++{0x2510, 0x1212}, ++{0x2510, 0x1011}, ++{0x2510, 0xDD11}, ++{0x2510, 0xD909}, ++{0x2510, 0x0114}, ++{0x2510, 0x4109}, ++{0x2510, 0x0410}, ++{0x2510, 0x5608}, ++{0x2510, 0x11DB}, ++{0x2510, 0x0903}, ++{0x2510, 0x11FB}, ++{0x2510, 0x11BB}, ++{0x2510, 0x121A}, ++{0x2510, 0x1210}, ++{0x2510, 0x0812}, ++{0x2510, 0x5010}, ++{0x2510, 0x7610}, ++{0x2510, 0xE614}, ++{0x2510, 0x6109}, ++{0x2510, 0x0612}, ++{0x2510, 0x4012}, ++{0x2510, 0x6009}, ++{0x2510, 0x1C14}, ++{0x2510, 0x6009}, ++{0x2510, 0x0C0B}, ++{0x2510, 0x0905}, ++{0x2510, 0x15C8}, ++{0x2510, 0x13C8}, ++{0x2510, 0x0810}, ++{0x2510, 0x6609}, ++{0x2510, 0x0B15}, ++{0x2510, 0x8813}, ++{0x2510, 0x8809}, ++{0x2510, 0x130C}, ++{0x2510, 0x1440}, ++{0x2510, 0x0903}, ++{0x2510, 0x10E6}, ++{0x2510, 0x11FB}, ++{0x2510, 0x1262}, ++{0x2510, 0x1260}, ++{0x2510, 0x11FF}, ++{0x2510, 0x11FB}, ++{0x2510, 0x1441}, ++{0x2510, 0x0902}, ++{0x2510, 0x1066}, ++{0x2510, 0x0912}, ++{0x2510, 0x11BB}, ++{0x2510, 0x1263}, ++{0x2510, 0x1260}, ++{0x2510, 0x1400}, ++{0x2510, 0x1518}, ++{0x2510, 0x11B8}, ++{0x2510, 0x12A0}, ++{0x2510, 0x1200}, ++{0x2510, 0x1026}, ++{0x2510, 0x1000}, ++{0x2510, 0x1300}, ++{0x2510, 0x1100}, ++{0x2510, 0x3053}, ++{0x2510, 0x4211}, ++{0x2510, 0x0010}, ++{0x2510, 0x0210}, ++{0x2510, 0x1611}, ++{0x2510, 0x0111}, ++{0x2510, 0x0910}, ++{0x2510, 0x5612}, ++{0x2510, 0x100D}, ++{0x2510, 0x0905}, ++{0x2510, 0x1441}, ++{0x2510, 0x0907}, ++{0x2510, 0x1440}, ++{0x2510, 0x0901}, ++{0x2510, 0x15C8}, ++{0x2510, 0x13C8}, ++{0x2510, 0x091A}, ++{0x2510, 0x1149}, ++{0x2510, 0x0908}, ++{0x2510, 0x1588}, ++{0x2510, 0x1388}, ++{0x2510, 0x091B}, ++{0x2510, 0x1159}, ++{0x2510, 0x090B}, ++{0x2510, 0x1214}, ++{0x2510, 0x0901}, ++{0x2510, 0x1210}, ++{0x2510, 0x10D6}, ++{0x2510, 0x1212}, ++{0x2510, 0x1210}, ++{0x2510, 0x115D}, ++{0x2510, 0x1159}, ++{0x2510, 0x1056}, ++{0x2510, 0x0903}, ++{0x2510, 0x115B}, ++{0x2510, 0x0814}, ++{0x2510, 0x4109}, ++{0x2510, 0x0114}, ++{0x2510, 0x4009}, ++{0x2510, 0x0C11}, ++{0x2510, 0x7B11}, ++{0x2510, 0x3B12}, ++{0x2510, 0x1A12}, ++{0x2510, 0x1009}, ++{0x2510, 0x0112}, ++{0x2510, 0x5010}, ++{0x2510, 0xF610}, ++{0x2510, 0xE614}, ++{0x2510, 0x6009}, ++{0x2510, 0x0115}, ++{0x2510, 0xA813}, ++{0x2510, 0xA812}, ++{0x2510, 0x4012}, ++{0x2510, 0x6009}, ++{0x2510, 0x2415}, ++{0x2510, 0x8809}, ++{0x2510, 0x0110}, ++{0x2510, 0x660B}, ++{0x2510, 0x0813}, ++{0x2510, 0x8809}, ++{0x2510, 0x250C}, ++{0x2510, 0x0902}, ++{0x2510, 0x1440}, ++{0x2510, 0x0907}, ++{0x2510, 0x10E6}, ++{0x2510, 0x1262}, ++{0x2510, 0x1260}, ++{0x2510, 0x117F}, ++{0x2510, 0x117B}, ++{0x2510, 0x1066}, ++{0x2510, 0x0906}, ++{0x2510, 0x1441}, ++{0x2510, 0x0901}, ++{0x2510, 0x1440}, ++{0x2510, 0x090D}, ++{0x2510, 0x113B}, ++{0x2510, 0x1263}, ++{0x2510, 0x1260}, ++{0x2510, 0x1400}, ++{0x2510, 0x1518}, ++{0x2510, 0x1138}, ++{0x2510, 0x12A0}, ++{0x2510, 0x1200}, ++{0x2510, 0x1026}, ++{0x2510, 0x1000}, ++{0x2510, 0x1300}, ++{0x2510, 0x1100}, ++{0x2510, 0x437A}, ++{0x2510, 0x0605}, ++{0x2510, 0x0741}, ++{0x2510, 0x0E02}, ++{0x2510, 0x3750}, ++{0x2510, 0x2C44}, ++{0x2510, 0x3714}, ++{0x2510, 0x4000}, ++{0x2510, 0x0408}, ++{0x2510, 0x0104}, ++{0x2510, 0x0811}, ++{0x2510, 0x0010}, ++{0x2510, 0x0210}, ++{0x2510, 0x1611}, ++{0x2510, 0x0111}, ++{0x2510, 0x0910}, ++{0x2510, 0x5612}, ++{0x2510, 0x100D}, ++{0x2510, 0x0906}, ++{0x2510, 0x1441}, ++{0x2510, 0x0907}, ++{0x2510, 0x1440}, ++{0x2510, 0x0901}, ++{0x2510, 0x1588}, ++{0x2510, 0x1388}, ++{0x2510, 0x0921}, ++{0x2510, 0x1149}, ++{0x2510, 0x0908}, ++{0x2510, 0x1588}, ++{0x2510, 0x1388}, ++{0x2510, 0x091B}, ++{0x2510, 0x1159}, ++{0x2510, 0x090B}, ++{0x2510, 0x1214}, ++{0x2510, 0x0901}, ++{0x2510, 0x1210}, ++{0x2510, 0x10D6}, ++{0x2510, 0x1212}, ++{0x2510, 0x1210}, ++{0x2510, 0x115D}, ++{0x2510, 0x1159}, ++{0x2510, 0x1056}, ++{0x2510, 0x0903}, ++{0x2510, 0x115B}, ++{0x2510, 0x0814}, ++{0x2510, 0x4109}, ++{0x2510, 0x0114}, ++{0x2510, 0x4009}, ++{0x2510, 0x0C11}, ++{0x2510, 0x7B11}, ++{0x2510, 0x3B12}, ++{0x2510, 0x1A12}, ++{0x2510, 0x1009}, ++{0x2510, 0x0112}, ++{0x2510, 0x5010}, ++{0x2510, 0xF610}, ++{0x2510, 0xE614}, ++{0x2510, 0x6009}, ++{0x2510, 0x0115}, ++{0x2510, 0xA813}, ++{0x2510, 0xA812}, ++{0x2510, 0x4012}, ++{0x2510, 0x6009}, ++{0x2510, 0x2415}, ++{0x2510, 0x8809}, ++{0x2510, 0x0110}, ++{0x2510, 0x660B}, ++{0x2510, 0x0813}, ++{0x2510, 0x8809}, ++{0x2510, 0x250C}, ++{0x2510, 0x0902}, ++{0x2510, 0x1440}, ++{0x2510, 0x0907}, ++{0x2510, 0x10E6}, ++{0x2510, 0x1262}, ++{0x2510, 0x1260}, ++{0x2510, 0x117F}, ++{0x2510, 0x117B}, ++{0x2510, 0x1066}, ++{0x2510, 0x0906}, ++{0x2510, 0x1441}, ++{0x2510, 0x0901}, ++{0x2510, 0x1440}, ++{0x2510, 0x090D}, ++{0x2510, 0x113B}, ++{0x2510, 0x1263}, ++{0x2510, 0x1260}, ++{0x2510, 0x1440}, ++{0x2510, 0x1598}, ++{0x2510, 0x1139}, ++{0x2510, 0x12A0}, ++{0x2510, 0x1200}, ++{0x2510, 0x1066}, ++{0x2510, 0x1066}, ++{0x2510, 0x1380}, ++{0x2510, 0x1109}, ++{0x2510, 0x0E02}, ++{0x2510, 0x0920}, ++{0x2510, 0x3708}, ++{0x2510, 0x0015}, ++{0x2510, 0x9813}, ++{0x2510, 0x9810}, ++{0x2510, 0x6610}, ++{0x2510, 0x6611}, ++{0x2510, 0x8911}, ++{0x2510, 0x8910}, ++{0x2510, 0x5612}, ++{0x2510, 0x1009}, ++{0x2510, 0x020D}, ++{0x2510, 0x0905}, ++{0x2510, 0x15A8}, ++{0x2510, 0x13A8}, ++{0x2510, 0x0934}, ++{0x2510, 0x1588}, ++{0x2510, 0x1388}, ++{0x2510, 0x1199}, ++{0x2510, 0x11D9}, ++{0x2510, 0x091E}, ++{0x2510, 0x1214}, ++{0x2510, 0x10D6}, ++{0x2510, 0x0901}, ++{0x2510, 0x1210}, ++{0x2510, 0x1212}, ++{0x2510, 0x1210}, ++{0x2510, 0x11DD}, ++{0x2510, 0x11D9}, ++{0x2510, 0x0901}, ++{0x2510, 0x1441}, ++{0x2510, 0x0904}, ++{0x2510, 0x1056}, ++{0x2510, 0x0811}, ++{0x2510, 0xDB09}, ++{0x2510, 0x0311}, ++{0x2510, 0xFB11}, ++{0x2510, 0xBB12}, ++{0x2510, 0x1A12}, ++{0x2510, 0x1008}, ++{0x2510, 0x1250}, ++{0x2510, 0x1076}, ++{0x2510, 0x10E6}, ++{0x2510, 0x1461}, ++{0x2510, 0x0906}, ++{0x2510, 0x1240}, ++{0x2510, 0x1260}, ++{0x2510, 0x091C}, ++{0x2510, 0x1460}, ++{0x2510, 0x090C}, ++{0x2510, 0x0B09}, ++{0x2510, 0x0515}, ++{0x2510, 0xC813}, ++{0x2510, 0xC808}, ++{0x2510, 0x1066}, ++{0x2510, 0x090B}, ++{0x2510, 0x1588}, ++{0x2510, 0x1388}, ++{0x2510, 0x0913}, ++{0x2510, 0x0C14}, ++{0x2510, 0x4009}, ++{0x2510, 0x0310}, ++{0x2510, 0xE611}, ++{0x2510, 0xFB12}, ++{0x2510, 0x6212}, ++{0x2510, 0x6011}, ++{0x2510, 0xFF11}, ++{0x2510, 0xFB14}, ++{0x2510, 0x4109}, ++{0x2510, 0x0210}, ++{0x2510, 0x6609}, ++{0x2510, 0x1211}, ++{0x2510, 0xBB12}, ++{0x2510, 0x6312}, ++{0x2510, 0x6014}, ++{0x2510, 0x0015}, ++{0x2510, 0x1811}, ++{0x2510, 0xB812}, ++{0x2510, 0xA012}, ++{0x2510, 0x0010}, ++{0x2510, 0x2610}, ++{0x2510, 0x0013}, ++{0x2510, 0x0011}, ++{0x2510, 0x007A}, ++{0x2510, 0x0605}, ++{0x2510, 0x0807}, ++{0x2510, 0x0E02}, ++{0x2510, 0x3709}, ++{0x2510, 0x0655}, ++{0x2510, 0x2CFE}, ++{0x2510, 0x12FE}, ++{0x2510, 0x062C}, ++ ++{0x1010, 0x0115}, ++{0x3236, 0x00b3}, ++{0x32e6, 0x009a}, ++{0x322e, 0x258c}, ++/* Sequencer_Update */ ++ ++{0x32D0, 0x3A02}, ++{0x32D2, 0x3508}, ++{0x32D4, 0x3702}, ++{0x32D6, 0x3C04}, ++{0x32DC, 0x370A}, ++{ } ++}; /* Sensor_Setup */ ++ ++static const struct ar0147_reg ar0147_rev1_Serial_12_bit_Timing_Setup[] = { ++#if 0 ++/* PCLK=24Mhz/3 *50 /1/8 = 50MHz */ ++{0x302A, 8}, // VT_PIX_CLK_DIV ++{0x302C, 1}, // VT_SYS_CLK_DIV ++{0x302E, 3}, // PRE_PLL_CLK_DIV ++{0x3030, 50}, // PLL_MULTIPLIER ++{0x3036, 8}, // OP_WORD_CLK_DIV ++{0x3038, 1}, // OP_SYS_CLK_DIV ++#else ++/* PCLK=24Mhz/4 *75 /1/9 = 50MHz */ ++{0x302A, 9}, // VT_PIX_CLK_DIV ++{0x302C, 1}, // VT_SYS_CLK_DIV ++{0x302E, 4}, // PRE_PLL_CLK_DIV ++{0x3030, 75}, // PLL_MULTIPLIER ++{0x3036, 12}, // OP_WORD_CLK_DIV ++{0x3038, 1}, // OP_SYS_CLK_DIV ++#endif ++{0x30B0, 0x980C}, // DIGITAL_TEST ++{0x31DC, 0x1FB0}, ++{ } ++}; /* Serial_12_bit_Timing_Setup */ ++ ++static const struct ar0147_reg ar0147_rev1_Readout_Mode_Configuration[] = { ++{0x30A2, 0x0001}, // X_ODD_INC_ ++{0x30A6, 0x0001}, // Y_ODD_INC_ ++{0x3040, 0x0000}, // READ_MODE ++{0x3082, 0x0008}, // OPERATION_MODE_CTRL: 3exp ++{0x3044, 0x0400}, // DARK_CONTROL ++{0x3064, 0x0000}, // SMIA_TEST: disable emb data and stats ++{0x33E0, 0x0C80}, // TEST_ASIL_ROWS ++{0x3180, 0x0080}, // RESERVED_MFR_3180 ++{0x33E4, 0x0080}, // RESERVED_MFR_33E4 ++#ifdef AR0147_EMBEDDED_LINE ++{0x3064, 0x0180}, // SMIA_TEST: enable emb data and stats ++#endif /* HDR_Readout_Mode_Configuration */ ++{ } ++}; /* Readout_Mode_Configuration */ ++ ++static const struct ar0147_reg ar0147_rev1_Full_Res_FOV[] = { ++{0x31B0, 0x0056}, // FRAME_PREAMBLE ++{0x31B2, 0x0045}, // LINE_PREAMBLE ++{0x3004, AR0147_X_START}, // X_ADDR_START_ ++{0x3008, AR0147_X_END}, // X_ADDR_END_ ++{0x3002, AR0147_Y_START}, // Y_ADDR_START_ ++{0x3006, AR0147_Y_END}, // Y_ADDR_END_ ++{0x3400, 0x10}, ++{0x3402, (0x8000 & 0) | AR0147_MAX_WIDTH}, // X_OUTPUT_CONTROL ++{0x3404, (0x8000 & 0) | AR0147_MAX_HEIGHT}, // Y_OUTPUT_CONTROL ++{ } ++}; /* Full_Res_FOV */ ++ ++static const struct ar0147_reg ar0147_rev1_3exp_30FPS_Timing_and_Exposure[] = { ++{0x3082, 0x0008}, // OPERATION_MODE_CTRL: 3exp ++{0x30BA, 0x1002}, // DIGITAL_CTRL: 3exp max ++/* Row and Pixel Timing */ ++{0x300C, AR0147_SENSOR_WIDTH + 52}, // LINE_LENGTH_PCK_ (1396) ++{0x300A, AR0147_SENSOR_HEIGHT + 226}, // FRAME_LENGTH_LINES_ ++{0x3042, 0x0000}, // EXTRA_DELAY ++/* Exposure Settings */ ++{0x3238, 0x0222}, // EXPOSURE_RATIO ++{0x3012, 0x0300}, // COARSE_INTEGRATION_TIME_ ++ ++{0x3014, 1550}, // FINE_INTEGRATION_TIME_ ++{0x321E, 1550}, // FINE_INTEGRATION_TIME2 ++{0x3222, 1550}, // FINE_INTEGRATION_TIME3 ++ ++{0x30B0, 0x980C}, // DIGITAL_TEST (MIPI ...) ++{0x32EA, 0x3C0E}, ++{0x32EC, 0x72A1}, ++{0x3C06, 0x083C}, ++{0x3C08, 0x0100}, ++{ } ++}; /* 3exp_30FPS_Timing_and_Exposure */ ++ ++static const struct ar0147_reg ar0147_rev1_Serial_HDR_12_bit_Output[] = { ++{0x31D0, 0x0001}, // COMPANDING ++{0x31AE, 0x0304}, // SERIAL_FORMAT: HISPI 4-lanes ++{0x31AC, 0x140C}, // DATA_FORMAT_BITS: ADC20, RAW12 ++//{0x301A, 0x0118}, // RESET_REGISTER ++{0x301A, 0x0018}, // RESET_REGISTER ++{ } ++}; /* Serial_HDR_12_bit_Output */ ++ ++static const struct ar0147_reg ar0147_rev1_MIPI_12_bit_450MBps_Settings[] = { ++{0x31AE, 0x0204}, // SERIAL_FORMAT: MIPI 4-lanes ++{0x3342, 0x122C}, // exposure1 DT=0x2c emb=0x12 ++{0x3346, 0x122C}, // exposure2 DT=0x2c emb=0x12 ++{0x334A, 0x122C}, // exposure3 DT=0x2c emb=0x12 ++{0x334E, 0x122C}, // exposure4 DT=0x2c emb=0x12 ++{0x3344, 0x0011}, // exposure1 VC=0 ++{0x3348, 0x0111}, // exposure1 VC=1 ++{0x334C, 0x0211}, // exposure1 VC=2 ++{0x3350, 0x0311}, // exposure1 VC=3 ++{0x31B0, 0x41}, // frame_preamble ++{0x31B2, 0x2e}, // line_preamble ++ ++{0x31B4, 0x2185}, ++{0x31B6, 0x1105}, ++{0x31B8, 0x2047}, ++{0x31BA, 0x105}, ++{0x31BC, 0x704}, ++{ } ++}; /* MIPI_12_bit_450MBps_Settings */ ++ ++/* 3 Exp HDR, Full Resolution, MIPI 450MBps 4 lane 12-bit, 30FPS, XMCLK=24MHz */ ++static const struct ar0147_reg *ar0147_regs_hdr_mipi450mbps_12bit_30fps_rev1[] = { ++ ar0147_rev1_Reset, ++ ar0147_rev1_Sensor_Setup, ++ ar0147_rev1_Serial_12_bit_Timing_Setup, ++ ar0147_rev1_Readout_Mode_Configuration, ++ ar0147_rev1_Full_Res_FOV, ++ ar0147_rev1_3exp_30FPS_Timing_and_Exposure, ++ ar0147_rev1_Serial_HDR_12_bit_Output, ++ ar0147_rev1_MIPI_12_bit_450MBps_Settings, ++ NULL ++}; +diff --git a/drivers/media/i2c/soc_camera/ar0147_rev2.h b/drivers/media/i2c/soc_camera/ar0147_rev2.h +new file mode 100644 +index 0000000..e5ccb8f +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0147_rev2.h +@@ -0,0 +1,796 @@ ++/* ++ * ON Semiconductor AR0147 sensor camera wizard 1344x968@30/BGGR/BT601/RAW12 ++ * ++ * Copyright (C) 2019 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++static const struct ar0147_reg ar0147_rev2_Reset[] = { ++{0x301A, 0x0001}, // reset ++{AR0147_DELAY, 100}, ++{0x301A, 0x10D8}, // Stream off and setup parallel ++{0x3070, 0x0001}, ++{0x3070, 0x0000}, // 1: Solid color test pattern, ++ // 2: Full color bar test pattern, ++ // 3: Fade to grey color bar test pattern, ++ //256: Walking 1 test pattern (12 bit) ++#ifdef AR0147_DISPLAY_PATTERN_FIXED ++{0x3070, 0x0001}, ++#endif ++{0x3072, 0x0fff}, // R ++{0x3074, 0x0fff}, // G(GR row) ++{0x3076, 0x0fff}, // B ++{0x3078, 0x0fff}, // G(GB row) ++#ifdef AR0147_DISPLAY_PATTERN_COLOR_BAR ++{0x3070, 0x0002}, ++#endif ++{AR0147_DELAY, 250}, ++{ } ++}; /* Reset */ ++ ++static const struct ar0147_reg ar0147_rev2_Sensor_Setup[] = { ++/* Recommended_Settings */ ++{0x30B0, 0x980E}, // DIGITAL_TEST ++{0x3C08, 0x0000}, ++{0x3C0C, 0x0518}, // DELAY_BUFFER_LLPCK_RD_WR_OVERLAP ++{0x3092, 0x1A24}, ++{0x30B4, 0x01C7}, // TEMPSENS0_CTRL_REG ++{0x3372, 0x700F}, // DBLC_FS0_CONTROL ++{0x33EE, 0x0344}, ++{0x350C, 0x035A}, ++{0x350E, 0x0514}, ++{0x3518, 0x14FE}, ++{0x351A, 0x6000}, ++{0x3520, 0x08CC}, ++{0x3522, 0xCC08}, ++{0x3524, 0x0C00}, ++{0x3526, 0x0F00}, ++{0x3528, 0xEEEE}, ++{0x352A, 0x089F}, ++{0x352C, 0x0012}, ++{0x352E, 0x00EE}, ++{0x3530, 0xEE00}, ++{0x3536, 0xFF20}, ++{0x3538, 0x3CFF}, ++{0x353A, 0x9000}, ++{0x353C, 0x7F00}, ++{0x3540, 0xC62C}, ++{0x3542, 0x4B4B}, ++{0x3544, 0x3C46}, ++{0x3546, 0x5A5A}, ++{0x3548, 0x6400}, ++{0x354A, 0x007F}, ++{0x3556, 0x1010}, ++{0x3566, 0x7328}, ++{0x3F90, 0x0800}, // TEMPVSENS0_TMG_CTRL ++{0x3510, 0x011F}, ++{0x353E, 0x801F}, ++{0x3F9A, 0x0001}, // TEMPVSENS0_BOOST_SAMP_CTRL ++{0x3116, 0x0001}, // HDR_CONTROL3 ++{0x3102, 0x60A0}, ++{0x3104, 0x60A0}, ++{0x3106, 0x60A0}, ++{0x3362, 0x0000}, // DC_GAIN ++{0x3366, 0xCCCC}, // ANALOG_GAIN ++ ++// Writes to bitfield R0x3552[5:4]. ++// Be sure not to overwrite the other bitfields in this register. ++{0x3552, 0x0FB0}, ++/* Recommended_Settings */ ++ ++/* Sequencer_Update */ ++{0x2512, 0x8000}, ++{0x2510, 0x0901}, ++{0x2510, 0x3350}, ++{0x2510, 0x2004}, ++{0x2510, 0x1420}, ++{0x2510, 0x1578}, ++{0x2510, 0x087B}, ++{0x2510, 0x24FF}, ++{0x2510, 0x24FF}, ++{0x2510, 0x24EA}, ++{0x2510, 0x2410}, ++{0x2510, 0x2224}, ++{0x2510, 0x1015}, ++{0x2510, 0xD813}, ++{0x2510, 0x0214}, ++{0x2510, 0x0024}, ++{0x2510, 0xFF24}, ++{0x2510, 0xFF24}, ++{0x2510, 0xEA23}, ++{0x2510, 0x2464}, ++{0x2510, 0x7A24}, ++{0x2510, 0x0405}, ++{0x2510, 0x2C40}, ++{0x2510, 0x0AFF}, ++{0x2510, 0x0A78}, ++{0x2510, 0x3851}, ++{0x2510, 0x2A54}, ++{0x2510, 0x1440}, ++{0x2510, 0x0015}, ++{0x2510, 0x0804}, ++{0x2510, 0x0801}, ++{0x2510, 0x0408}, ++{0x2510, 0x2652}, ++{0x2510, 0x0813}, ++{0x2510, 0xC810}, ++{0x2510, 0x0210}, ++{0x2510, 0x1611}, ++{0x2510, 0x8111}, ++{0x2510, 0x8910}, ++{0x2510, 0x5612}, ++{0x2510, 0x1009}, ++{0x2510, 0x020D}, ++{0x2510, 0x0903}, ++{0x2510, 0x1402}, ++{0x2510, 0x15A8}, ++{0x2510, 0x1388}, ++{0x2510, 0x0938}, ++{0x2510, 0x1199}, ++{0x2510, 0x11D9}, ++{0x2510, 0x091E}, ++{0x2510, 0x1214}, ++{0x2510, 0x10D6}, ++{0x2510, 0x0901}, ++{0x2510, 0x1210}, ++{0x2510, 0x1212}, ++{0x2510, 0x1210}, ++{0x2510, 0x11DD}, ++{0x2510, 0x11D9}, ++{0x2510, 0x0901}, ++{0x2510, 0x1441}, ++{0x2510, 0x0904}, ++{0x2510, 0x1056}, ++{0x2510, 0x0811}, ++{0x2510, 0xDB09}, ++{0x2510, 0x0311}, ++{0x2510, 0xFB11}, ++{0x2510, 0xBB12}, ++{0x2510, 0x1A12}, ++{0x2510, 0x1008}, ++{0x2510, 0x1250}, ++{0x2510, 0x0B10}, ++{0x2510, 0x7610}, ++{0x2510, 0xE614}, ++{0x2510, 0x6109}, ++{0x2510, 0x0612}, ++{0x2510, 0x4012}, ++{0x2510, 0x6009}, ++{0x2510, 0x1C14}, ++{0x2510, 0x6009}, ++{0x2510, 0x1215}, ++{0x2510, 0xC813}, ++{0x2510, 0xC808}, ++{0x2510, 0x1066}, ++{0x2510, 0x090B}, ++{0x2510, 0x1588}, ++{0x2510, 0x1388}, ++{0x2510, 0x0913}, ++{0x2510, 0x0C14}, ++{0x2510, 0x4009}, ++{0x2510, 0x0310}, ++{0x2510, 0xE611}, ++{0x2510, 0xFB12}, ++{0x2510, 0x6212}, ++{0x2510, 0x6011}, ++{0x2510, 0xFF11}, ++{0x2510, 0xFB14}, ++{0x2510, 0x4109}, ++{0x2510, 0x0210}, ++{0x2510, 0x6609}, ++{0x2510, 0x1211}, ++{0x2510, 0xBB12}, ++{0x2510, 0x6312}, ++{0x2510, 0x6014}, ++{0x2510, 0x0015}, ++{0x2510, 0x1811}, ++{0x2510, 0xB812}, ++{0x2510, 0xA012}, ++{0x2510, 0x0010}, ++{0x2510, 0x2610}, ++{0x2510, 0x0013}, ++{0x2510, 0x0011}, ++{0x2510, 0x0030}, ++{0x2510, 0x5342}, ++{0x2510, 0x1100}, ++{0x2510, 0x1002}, ++{0x2510, 0x1016}, ++{0x2510, 0x1101}, ++{0x2510, 0x1109}, ++{0x2510, 0x1056}, ++{0x2510, 0x1210}, ++{0x2510, 0x0D09}, ++{0x2510, 0x0314}, ++{0x2510, 0x0214}, ++{0x2510, 0x4309}, ++{0x2510, 0x0514}, ++{0x2510, 0x4009}, ++{0x2510, 0x0115}, ++{0x2510, 0xC813}, ++{0x2510, 0xC809}, ++{0x2510, 0x1A11}, ++{0x2510, 0x4909}, ++{0x2510, 0x0815}, ++{0x2510, 0x8813}, ++{0x2510, 0x8809}, ++{0x2510, 0x1B11}, ++{0x2510, 0x5909}, ++{0x2510, 0x0B12}, ++{0x2510, 0x1409}, ++{0x2510, 0x0112}, ++{0x2510, 0x1010}, ++{0x2510, 0xD612}, ++{0x2510, 0x1212}, ++{0x2510, 0x1011}, ++{0x2510, 0x5D11}, ++{0x2510, 0x5910}, ++{0x2510, 0x5609}, ++{0x2510, 0x0311}, ++{0x2510, 0x5B08}, ++{0x2510, 0x1441}, ++{0x2510, 0x0901}, ++{0x2510, 0x1440}, ++{0x2510, 0x090C}, ++{0x2510, 0x117B}, ++{0x2510, 0x113B}, ++{0x2510, 0x121A}, ++{0x2510, 0x1210}, ++{0x2510, 0x0901}, ++{0x2510, 0x1250}, ++{0x2510, 0x10F6}, ++{0x2510, 0x10E6}, ++{0x2510, 0x1460}, ++{0x2510, 0x0901}, ++{0x2510, 0x15A8}, ++{0x2510, 0x13A8}, ++{0x2510, 0x1240}, ++{0x2510, 0x1260}, ++{0x2510, 0x0924}, ++{0x2510, 0x1588}, ++{0x2510, 0x0901}, ++{0x2510, 0x1066}, ++{0x2510, 0x0B08}, ++{0x2510, 0x1388}, ++{0x2510, 0x0925}, ++{0x2510, 0x0C09}, ++{0x2510, 0x0214}, ++{0x2510, 0x4009}, ++{0x2510, 0x0710}, ++{0x2510, 0xE612}, ++{0x2510, 0x6212}, ++{0x2510, 0x6011}, ++{0x2510, 0x7F11}, ++{0x2510, 0x7B10}, ++{0x2510, 0x6609}, ++{0x2510, 0x0614}, ++{0x2510, 0x4109}, ++{0x2510, 0x0114}, ++{0x2510, 0x4009}, ++{0x2510, 0x0D11}, ++{0x2510, 0x3B12}, ++{0x2510, 0x6312}, ++{0x2510, 0x6014}, ++{0x2510, 0x0015}, ++{0x2510, 0x1811}, ++{0x2510, 0x3812}, ++{0x2510, 0xA012}, ++{0x2510, 0x0010}, ++{0x2510, 0x2610}, ++{0x2510, 0x0013}, ++{0x2510, 0x0011}, ++{0x2510, 0x0043}, ++{0x2510, 0x7A06}, ++{0x2510, 0x0507}, ++{0x2510, 0x410E}, ++{0x2510, 0x0237}, ++{0x2510, 0x502C}, ++{0x2510, 0x4414}, ++{0x2510, 0x4000}, ++{0x2510, 0x1508}, ++{0x2510, 0x0408}, ++{0x2510, 0x0104}, ++{0x2510, 0x0826}, ++{0x2510, 0x5508}, ++{0x2510, 0x13C8}, ++{0x2510, 0x1002}, ++{0x2510, 0x1016}, ++{0x2510, 0x1181}, ++{0x2510, 0x1189}, ++{0x2510, 0x1056}, ++{0x2510, 0x1210}, ++{0x2510, 0x0902}, ++{0x2510, 0x0D09}, ++{0x2510, 0x0314}, ++{0x2510, 0x0215}, ++{0x2510, 0xA813}, ++{0x2510, 0xA814}, ++{0x2510, 0x0309}, ++{0x2510, 0x0614}, ++{0x2510, 0x0209}, ++{0x2510, 0x1F15}, ++{0x2510, 0x8813}, ++{0x2510, 0x8809}, ++{0x2510, 0x0B11}, ++{0x2510, 0x9911}, ++{0x2510, 0xD909}, ++{0x2510, 0x1E12}, ++{0x2510, 0x1409}, ++{0x2510, 0x0312}, ++{0x2510, 0x1012}, ++{0x2510, 0x1212}, ++{0x2510, 0x1011}, ++{0x2510, 0xDD11}, ++{0x2510, 0xD909}, ++{0x2510, 0x0114}, ++{0x2510, 0x4009}, ++{0x2510, 0x0711}, ++{0x2510, 0xDB09}, ++{0x2510, 0x0311}, ++{0x2510, 0xFB11}, ++{0x2510, 0xBB12}, ++{0x2510, 0x1A12}, ++{0x2510, 0x1009}, ++{0x2510, 0x0112}, ++{0x2510, 0x500B}, ++{0x2510, 0x1076}, ++{0x2510, 0x1066}, ++{0x2510, 0x1460}, ++{0x2510, 0x0901}, ++{0x2510, 0x15C8}, ++{0x2510, 0x0901}, ++{0x2510, 0x1240}, ++{0x2510, 0x1260}, ++{0x2510, 0x0901}, ++{0x2510, 0x13C8}, ++{0x2510, 0x0956}, ++{0x2510, 0x1588}, ++{0x2510, 0x0901}, ++{0x2510, 0x0C14}, ++{0x2510, 0x4009}, ++{0x2510, 0x0511}, ++{0x2510, 0xFB12}, ++{0x2510, 0x6212}, ++{0x2510, 0x6011}, ++{0x2510, 0xFF11}, ++{0x2510, 0xFB09}, ++{0x2510, 0x1911}, ++{0x2510, 0xBB12}, ++{0x2510, 0x6312}, ++{0x2510, 0x6014}, ++{0x2510, 0x0015}, ++{0x2510, 0x1811}, ++{0x2510, 0xB812}, ++{0x2510, 0xA012}, ++{0x2510, 0x0010}, ++{0x2510, 0x2610}, ++{0x2510, 0x0013}, ++{0x2510, 0x0011}, ++{0x2510, 0x0030}, ++{0x2510, 0x5345}, ++{0x2510, 0x1444}, ++{0x2510, 0x1002}, ++{0x2510, 0x1016}, ++{0x2510, 0x1101}, ++{0x2510, 0x1109}, ++{0x2510, 0x1056}, ++{0x2510, 0x1210}, ++{0x2510, 0x0D09}, ++{0x2510, 0x0314}, ++{0x2510, 0x0614}, ++{0x2510, 0x4709}, ++{0x2510, 0x0514}, ++{0x2510, 0x4409}, ++{0x2510, 0x0115}, ++{0x2510, 0x9813}, ++{0x2510, 0x9809}, ++{0x2510, 0x1A11}, ++{0x2510, 0x4909}, ++{0x2510, 0x0815}, ++{0x2510, 0x8813}, ++{0x2510, 0x8809}, ++{0x2510, 0x1B11}, ++{0x2510, 0x5909}, ++{0x2510, 0x0B12}, ++{0x2510, 0x1409}, ++{0x2510, 0x0112}, ++{0x2510, 0x1009}, ++{0x2510, 0x0112}, ++{0x2510, 0x1212}, ++{0x2510, 0x1011}, ++{0x2510, 0x5D11}, ++{0x2510, 0x5909}, ++{0x2510, 0x0511}, ++{0x2510, 0x5B09}, ++{0x2510, 0x1311}, ++{0x2510, 0x7B11}, ++{0x2510, 0x3B12}, ++{0x2510, 0x1A12}, ++{0x2510, 0x1009}, ++{0x2510, 0x0112}, ++{0x2510, 0x5010}, ++{0x2510, 0x7610}, ++{0x2510, 0x6614}, ++{0x2510, 0x6409}, ++{0x2510, 0x0115}, ++{0x2510, 0xA813}, ++{0x2510, 0xA812}, ++{0x2510, 0x4012}, ++{0x2510, 0x6009}, ++{0x2510, 0x2015}, ++{0x2510, 0x8809}, ++{0x2510, 0x020B}, ++{0x2510, 0x0901}, ++{0x2510, 0x1388}, ++{0x2510, 0x0925}, ++{0x2510, 0x0C09}, ++{0x2510, 0x0214}, ++{0x2510, 0x4409}, ++{0x2510, 0x0912}, ++{0x2510, 0x6212}, ++{0x2510, 0x6011}, ++{0x2510, 0x7F11}, ++{0x2510, 0x7B09}, ++{0x2510, 0x1C11}, ++{0x2510, 0x3B12}, ++{0x2510, 0x6312}, ++{0x2510, 0x6014}, ++{0x2510, 0x0015}, ++{0x2510, 0x1811}, ++{0x2510, 0x3812}, ++{0x2510, 0xA012}, ++{0x2510, 0x0010}, ++{0x2510, 0x2610}, ++{0x2510, 0x0013}, ++{0x2510, 0x0011}, ++{0x2510, 0x0008}, ++{0x2510, 0x7A06}, ++{0x2510, 0x0508}, ++{0x2510, 0x070E}, ++{0x2510, 0x0237}, ++{0x2510, 0x502C}, ++{0x2510, 0xFE32}, ++{0x2510, 0xFE06}, ++{0x2510, 0x2C2C}, ++ ++{AR0147_DELAY, 200}, ++ ++{0x32e6, 0x009a}, //min_subrow ++{0x322e, 0x258c}, //clks_per_sample 396 ++/* Sequencer_Update */ ++ ++{0x32D0, 0x3A02}, ++{0x32D2, 0x3508}, ++{0x32D4, 0x3702}, ++{0x32D6, 0x3C04}, ++{0x32DC, 0x370A}, ++{0x32EA, 0x3CA8}, ++{0x351E, 0x0000}, ++{0x3510, 0x811F}, ++ ++//settings to rev1 default for non-Super Exposure mode settings ++//Super Exposure mode settings have additional settings ++{0x1010, 0x0155}, // FINE_INTEGRATION_TIME4_MIN ++{0x3236, 0x00B2}, // FINE_CORRECTION4 ++{0x32EA, 0x3C0E}, ++{0x32EC, 0x7151}, ++{0x3116, 0x0001}, // HDR_CONTROL3 ++{0x33E2, 0x0000}, // SAMPLE_CTRL ++{0x3088, 0x0400}, // LFM_CTRL ++{0x322A, 0x0039}, // FINE_INTEGRATION_CTRL ++{0x3238, 0x0333}, // EXPOSURE_RATIO ++{ } ++}; /* Sensor_Setup */ ++ ++static const struct ar0147_reg ar0147_rev2_Super_Exposure_Default_Plus_T2_Setup[] = { ++{0x3082, 0x0008}, // OPERATION_MODE_CTRL ++{0x30BA, 0x1003}, // DIGITAL_CTRL ++{0x3C06, 0x2024}, // CONFIGURE_BUFFERS1 ++{0x3C08, 0x2100}, // CONFIGURE_BUFFERS2 ++{0x3088, 0x0400}, ++{0x32EA, 0x3CA9}, ++{0x3510, 0x814F}, ++{0x351E, 0x0100}, ++{0x32EA, 0x3CA9}, ++{0x32EC, 0x7281}, ++{0x3212, 0x0000}, // COARSE_INTEGRATION_TIME2 ++{0x3216, 0x0004}, // COARSE_INTEGRATION_TIME3 ++{0x3238, 0x8222}, // EXPOSURE_RATIO ++{0x33E2, 0x0A10}, // SAMPLE_CTRL ++{0x3362, 0x0001}, // DC_GAIN ++{0x322A, 0x0539}, // FINE_INTEGRATION_CTRL ++{0x3014, 0x0123}, // FINE_INTEGRATION_TIME_ ++{0x3222, 0x0490}, // FINE_INTEGRATION_TIME3 ++{0x1008, 0x0123}, // FINE_INTEGRATION_TIME_MIN ++{0x100E, 0x043B}, // FINE_INTEGRATION_TIME3_MIN ++{0x3230, 0x00C7}, // FINE_CORRECTION ++{0x3234, 0x03DF}, // FINE_CORRECTION3 ++{0x32D0, 0x3A02}, ++{0x32D2, 0x3508}, ++{0x32D4, 0x3702}, ++{0x32D6, 0x3C04}, ++{0x32DC, 0x370A}, ++{0x3528, 0x99EE}, ++{0x30FE, 0x0040}, // NOISE_PEDESTAL ++{0x3096, 0x0000}, // ROW_NOISE_ADJUST_1X_LCG_T2 ++ ++/* Digital_Lateral_Overflow_for_SE */ ++{0x3116, 0x0001}, ++{0x3100, 0xC001}, // FIELD_WR= DLO_CONTROL0, 0xE001 ++{0x3102, 0x6100}, ++{0x3104, 0x6100}, ++{0x3106, 0x6100}, ++{0x3108, 0x0CB1}, ++{0x312A, 0x83E8}, ++{0x3C82, 0x0FFF}, ++/* Digital_Lateral_Overflow_for_SE */ ++ ++/* Other_Super_Exposure_Setup */ ++{0x3536, 0xFF20}, ++{0x3520, 0x0800}, ++{0x3522, 0x0008}, ++{0x3536, 0xFF20}, ++{0x350C, 0x034A}, ++{0x350E, 0x051C}, ++{0x3540, 0xC62C}, ++{0x3542, 0x4B4B}, ++{0x3544, 0x4B46}, ++{0x3546, 0x5A5A}, ++{0x3548, 0x6400}, ++{0x354A, 0x007F}, ++{0x3524, 0x0600}, ++{0x3372, 0xF40F}, // DBLC_FS0_CONTROL ++{0x3180, 0x0188}, ++{0x3280, 0x0CB2}, // T1_BARRIER_C0 ++{0x3282, 0x0CB2}, // T1_BARRIER_C1 ++{0x3284, 0x0CB2}, // T1_BARRIER_C2 ++{0x3286, 0x0CB2}, // T1_BARRIER_C3 ++{0x3288, 0x0CB2}, // T2_BARRIER_C0 ++{0x328A, 0x0CB2}, // T2_BARRIER_C1 ++{0x328C, 0x0CB2}, // T2_BARRIER_C2 ++{0x328E, 0x0CB2}, // T2_BARRIER_C3 ++{0x3290, 0x0CB2}, // T3_BARRIER_C0 ++{0x3292, 0x0CB2}, // T3_BARRIER_C1 ++{0x3294, 0x0CB2}, // T3_BARRIER_C2 ++{0x3296, 0x0CB2}, // T3_BARRIER_C3 ++{0x3298, 0x0CB2}, // T4_BARRIER_C0 ++{0x329A, 0x0CB2}, // T4_BARRIER_C1 ++{0x329C, 0x0CB2}, // T4_BARRIER_C2 ++{0x329E, 0x0CB2}, // T4_BARRIER_C3 ++{0x3108, 0x0CB1}, ++{0x312A, 0x83E8}, ++{0x3C82, 0x0FFF}, ++{0x3102, 0x6100}, ++{0x3104, 0x6100}, ++{0x3106, 0x6100}, ++{0x3120, 0x0AF0}, ++{0x3122, 0x0CB2}, ++/* Other_Super_Exposure_Setup */ ++{ } ++}; /* Super_Exposure_Default_Plus_T2_Setup */ ++ ++static const struct ar0147_reg ar0147_rev2_Serial_12_bit_Timing_Setup[] = { ++#if 0 ++/* PCLK=24Mhz/3 *50 /1/8 = 50MHz */ ++{0x302A, 8}, // VT_PIX_CLK_DIV ++{0x302C, 1}, // VT_SYS_CLK_DIV ++{0x302E, 3}, // PRE_PLL_CLK_DIV ++{0x3030, 50}, // PLL_MULTIPLIER ++{0x3036, 8}, // OP_WORD_CLK_DIV ++{0x3038, 1}, // OP_SYS_CLK_DIV ++#else ++/* PCLK=24Mhz/4 *75 /1/9 = 50MHz */ ++{0x302A, 9}, // VT_PIX_CLK_DIV ++{0x302C, 1}, // VT_SYS_CLK_DIV ++{0x302E, 4}, // PRE_PLL_CLK_DIV ++{0x3030, 75}, // PLL_MULTIPLIER ++{0x3036, 12}, // OP_WORD_CLK_DIV ++{0x3038, 1}, // OP_SYS_CLK_DIV ++#endif ++{0x30B0, 0x980C}, // DIGITAL_TEST ++{0x31DC, 0x1FB0}, ++{ } ++}; /* Serial_12_bit_Timing_Setup */ ++ ++static const struct ar0147_reg ar0147_rev2_Readout_Mode_Configuration[] = { ++{0x30A2, 0x0001}, // X_ODD_INC_ ++{0x30A6, 0x0001}, // Y_ODD_INC_ ++{0x3040, 0x0000}, // READ_MODE ++{0x3082, 0x0008}, // OPERATION_MODE_CTRL: 3exp ++{0x3044, 0x0400}, // DARK_CONTROL ++{0x3064, 0x0000}, // SMIA_TEST: disable emb data and stats ++{0x33E0, 0x0C80}, // TEST_ASIL_ROWS ++{0x3180, 0x0080}, // RESERVED_MFR_3180 ++{0x33E4, 0x0080}, // RESERVED_MFR_33E4 ++#ifdef AR0147_EMBEDDED_LINE ++{0x3064, 0x0180}, // SMIA_TEST: enable emb data and stats ++#endif ++{ } ++}; /* Readout_Mode_Configuration */ ++ ++static const struct ar0147_reg ar0147_rev2_Full_Res_FOV[] = { ++{0x31B0, 0x0056}, // FRAME_PREAMBLE ++{0x31B2, 0x0045}, // LINE_PREAMBLE ++{0x3004, AR0147_X_START}, // X_ADDR_START_ ++{0x3008, AR0147_X_END}, // X_ADDR_END_ ++{0x3002, AR0147_Y_START}, // Y_ADDR_START_ ++{0x3006, AR0147_Y_END}, // Y_ADDR_END_ ++{0x3400, 0x10}, ++{0x3402, (0x8000 & 0) | AR0147_MAX_WIDTH}, // X_OUTPUT_CONTROL ++{0x3404, (0x8000 & 0) | AR0147_MAX_HEIGHT}, // Y_OUTPUT_CONTROL ++{ } ++}; /* Full_Res_FOV */ ++ ++static const struct ar0147_reg ar0147_rev2_3exp_30FPS_Timing_and_Exposure[] = { ++{0x3082, 0x0008}, // OPERATION_MODE_CTRL: 3exp ++{0x30BA, 0x1002}, // DIGITAL_CTRL: 3exp max ++ ++/* Row and Pixel Timing */ ++{0x300C, AR0147_SENSOR_WIDTH + 52}, // LINE_LENGTH_PCK_ (1396) ++{0x300A, AR0147_SENSOR_HEIGHT + 226}, // FRAME_LENGTH_LINES_ ++{0x3042, 0x0000}, // EXTRA_DELAY ++ ++/* Exposure Settings */ ++{0x3238, 0x0222}, // EXPOSURE_RATIO ++{0x3012, 0x0300}, // COARSE_INTEGRATION_TIME_ ++ ++{0x3014, 1550}, // FINE_INTEGRATION_TIME_ ++{0x321E, 1550}, // FINE_INTEGRATION_TIME2 ++{0x3222, 1550}, // FINE_INTEGRATION_TIME3 ++{0x30B0, 0x980C}, // DIGITAL_TEST (MIPI ...) ++{0x32EA, 0x3C0E}, ++{0x32EC, 0x72A1}, ++{0x3362, 0x0000}, // DC_GAIN ++{0x3366, 0xCCCC}, // ANALOG_GAIN ++{0x3364, 0x01CF}, // DCG_TRIM ++{0x3C06, 0x083C}, ++{0x3C08, 0x0100}, ++{ } ++}; /* 3exp_30FPS_Timing_and_Exposure */ ++ ++static const struct ar0147_reg ar0147_rev2_SE_Plus_T2_Default_Mode_30FPS_Timing_and_Exposure[] = { ++{0x3082, 0x0008}, // OPERATION_MODE_CTRL: 3exp ++{0x30BA, 0x1003}, // DIGITAL_CTRL: 4exp max ++ ++/* Row and Pixel Timing */ ++{0x300C, AR0147_SENSOR_WIDTH + 52}, // LINE_LENGTH_PCK_ (1396) ++{0x300A, AR0147_SENSOR_HEIGHT + 226}, // FRAME_LENGTH_LINES_ ++{0x3042, 0x0000}, // EXTRA_DELAY ++ ++/* Exposure Settings */ ++{0x3238, 0x8222}, // EXPOSURE_RATIO: separate integartion time!? ++{0x3012, 0x0300}, // COARSE_INTEGRATION_TIME_ ++ ++{0x322A, 0x0539}, // FINE_INTEGRATION_CTRL ++{0x3014, 0x0123}, // FINE_INTEGRATION_TIME_ ++{0x3222, 0x0490}, // FINE_INTEGRATION_TIME3 ++{0x3362, 0x0001}, // DC_GAIN ++{0x3366, 0xFDF7}, // ANALOG_GAIN ++{0x3364, 0x01CF}, // DCG_TRIM ++ ++{0x30B0, 0x980C}, // DIGITAL_TEST (MIPI ...) ++{0x32EC, 0x7281}, ++{ } ++}; /* SE_Plus_T2_Default_Mode_30FPS_Timing_and_Exposure */ ++ ++static const struct ar0147_reg ar0147_rev2_Serial_4_Lane_20_to_12_bit_Output[] = { ++{0x31D0, 0x0001}, // COMPANDING ++{0x31AE, 0x0304}, // SERIAL_FORMAT: HISPI 4-lanes ++{0x31AC, 0x140C}, // DATA_FORMAT_BITS: ADC20, RAW12 ++//{0x301A, 0x0118}, // RESET_REGISTER ++{0x301A, 0x0018}, // RESET_REGISTER ++{ } ++}; /* Serial_4_Lane_20_to_12_bit_Output */ ++ ++static const struct ar0147_reg ar0147_rev2_MIPI_12_bit_450MBps_Settings[] = { ++{0x31AE, 0x0204}, // SERIAL_FORMAT: MIPI 4-lanes ++{0x3342, 0x122C}, // exposure1 DT=0x2c emb=0x12 ++{0x3346, 0x122C}, // exposure2 DT=0x2c emb=0x12 ++{0x334A, 0x122C}, // exposure3 DT=0x2c emb=0x12 ++{0x334E, 0x122C}, // exposure4 DT=0x2c emb=0x12 ++{0x3344, 0x0011}, // exposure1 VC=0 ++{0x3348, 0x0111}, // exposure1 VC=1 ++{0x334C, 0x0211}, // exposure1 VC=2 ++{0x3350, 0x0311}, // exposure1 VC=3 ++{0x31B0, 0x41}, // frame_preamble ++{0x31B2, 0x2e}, // line_preamble ++ ++{0x31B4, 0x2185}, ++{0x31B6, 0x1105}, ++{0x31B8, 0x2047}, ++{0x31BA, 0x105}, ++{0x31BC, 0x704}, ++{ } ++}; /* MIPI_12_bit_450MBps_Settings */ ++ ++static const struct ar0147_reg ar0147_rev2_shutter_and_booster_settings[] = { ++{0x32EA, 0x3CA8}, ++{0x32F6, 0x3A01}, ++{0x32D2, 0x200A}, ++{0x32D0, 0x3005}, ++{0x32D4, 0x3505}, ++{0x32F8, 0x3C03}, ++{0x32DC, 0x220C}, ++{0x32D6, 0x3207}, ++{0x32E2, 0x3707}, ++{0x3260, 0x00FF}, ++{0x3262, 0x00FF}, ++{0x3528, 0xEEEE}, ++{0x353E, 0x801F}, ++{0x3532, 0x8F4C}, ++{0x3250, 0x0005}, ++{0x3252, 0x0107}, ++{0x3256, 0x03E8}, ++{0x3258, 0x0300}, ++{0x325A, 0x0A13}, ++{0x325E, 0x0186}, ++{0x3524, 0x0C00}, ++{0x3536, 0xFF38}, ++{0x3532, 0x8F48}, ++{0x3526, 0x8F00}, ++{0x3536, 0xDF18}, ++{0x3520, 0x0C00}, ++{0x352E, 0x00FF}, ++{0x3530, 0xFF00}, ++{0x3532, 0x8F68}, ++{0x3536, 0xDF18}, ++{0x3252, 0x0107}, ++{0x325E, 0x0186}, ++{0x3096, 0x0000}, ++{0x3504, 0x9100}, ++{0x354E, 0x1480}, ++{0x355A, 0x0B0E}, ++{0x3372, 0xF50F}, ++{0x337A, 0x100E}, ++{0x3554, 0x1599}, ++{0x32EA, 0x3CA9}, ++{0x3510, 0x9753}, ++{0x3520, 0x0800}, ++{0x3522, 0x0008}, ++{0x3524, 0x0C00}, ++{0x3526, 0x0F00}, ++{0x3528, 0xDDDD}, ++{0x352A, 0x089F}, ++{0x352C, 0x0012}, ++{0x352E, 0x00FF}, ++{0x3530, 0xFF00}, ++{0x3532, 0x8F48}, ++{0x3536, 0xFF38}, ++{0x3538, 0x24FF}, ++{0x353A, 0x9000}, ++{0x353C, 0x7F00}, ++{0x312A, 0x83E8}, ++{0x3C82, 0x0FFF}, ++{ } ++}; /* shutter_and_booster_settings */ ++ ++/* 3 Exp HDR, Full Resolution, MIPI 450MBPS 4 lane 12-bit, 30FPS, XMCLK=24MHz */ ++static const struct ar0147_reg *ar0147_regs_hdr_mipi450mbps_12bit_30fps_rev2[] = { ++ ar0147_rev2_Reset, ++ ar0147_rev2_Sensor_Setup, ++ ar0147_rev2_Serial_12_bit_Timing_Setup, ++ ar0147_rev2_Readout_Mode_Configuration, ++ ar0147_rev2_Full_Res_FOV, ++ ar0147_rev2_3exp_30FPS_Timing_and_Exposure, ++ ar0147_rev2_Serial_4_Lane_20_to_12_bit_Output, ++ ar0147_rev2_MIPI_12_bit_450MBps_Settings, ++ NULL ++}; ++ ++/* Super-Exposure Plus T2, Full Resolution, MIPI 450MBPS 4 lane 12-bit, 30FPS, XMCLK=24MHz */ ++static const struct ar0147_reg *ar0147_regs_seplus_mipi450mbps_12bit_30fps_rev2[] = { ++ ar0147_rev2_Reset, ++ ar0147_rev2_Sensor_Setup, ++ ar0147_rev2_Super_Exposure_Default_Plus_T2_Setup, ++ ar0147_rev2_Serial_12_bit_Timing_Setup, ++ ar0147_rev2_Readout_Mode_Configuration, ++ ar0147_rev2_Full_Res_FOV, ++ ar0147_rev2_SE_Plus_T2_Default_Mode_30FPS_Timing_and_Exposure, ++ ar0147_rev2_Serial_4_Lane_20_to_12_bit_Output, ++ ar0147_rev2_MIPI_12_bit_450MBps_Settings, ++ ar0147_rev2_shutter_and_booster_settings, ++ NULL ++}; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0171-lvds-ONSEMI-fix-matrix-position-during-crop.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0171-lvds-ONSEMI-fix-matrix-position-during-crop.patch new file mode 100644 index 00000000..4142f489 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0171-lvds-ONSEMI-fix-matrix-position-during-crop.patch @@ -0,0 +1,130 @@ +From 7d4a772671d98789186d9c1eb7b44cb22c1d9981 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Fri, 17 May 2019 23:18:30 +0300 +Subject: [PATCH 120/122] lvds: ONSEMI: fix matrix position during crop + +This preserves the centered window poition on imager +matrix during crop + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ar0140.c | 8 ++++---- + drivers/media/i2c/soc_camera/ar0143.c | 8 ++++---- + drivers/media/i2c/soc_camera/ar0147.c | 8 ++++---- + drivers/media/i2c/soc_camera/ar0231.c | 8 ++++---- + drivers/media/i2c/soc_camera/ar0233.c | 8 ++++---- + 5 files changed, 20 insertions(+), 20 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ar0140.c b/drivers/media/i2c/soc_camera/ar0140.c +index 807b6f8..c52ca4e 100644 +--- a/drivers/media/i2c/soc_camera/ar0140.c ++++ b/drivers/media/i2c/soc_camera/ar0140.c +@@ -106,13 +106,13 @@ static int ar0140_set_window(struct v4l2_subdev *sd) + dev_dbg(&client->dev, "L=%d T=%d %dx%d\n", priv->rect.left, priv->rect.top, priv->rect.width, priv->rect.height); + + /* horiz crop start */ +- reg16_write16(client, 0x3004, priv->rect.left); ++ reg16_write16(client, 0x3004, priv->rect.left + AR0140_X_START); + /* horiz crop end */ +- reg16_write16(client, 0x3008, priv->rect.left + priv->rect.width - 1); ++ reg16_write16(client, 0x3008, priv->rect.left + priv->rect.width - 1 + AR0140_X_START); + /* vert crop start */ +- reg16_write16(client, 0x3002, priv->rect.top); ++ reg16_write16(client, 0x3002, priv->rect.top + AR0140_Y_START); + /* vert crop end */ +- reg16_write16(client, 0x3006, priv->rect.top + priv->rect.height + 1); ++ reg16_write16(client, 0x3006, priv->rect.top + priv->rect.height - 1 + AR0140_Y_START); + + return 0; + }; +diff --git a/drivers/media/i2c/soc_camera/ar0143.c b/drivers/media/i2c/soc_camera/ar0143.c +index 01494fe..b61c7eb 100644 +--- a/drivers/media/i2c/soc_camera/ar0143.c ++++ b/drivers/media/i2c/soc_camera/ar0143.c +@@ -140,13 +140,13 @@ static int ar0143_set_window(struct v4l2_subdev *sd) + dev_dbg(&client->dev, "L=%d T=%d %dx%d\n", priv->rect.left, priv->rect.top, priv->rect.width, priv->rect.height); + + /* horiz crop start */ +- reg16_write16(client, 0x3004, priv->rect.left); ++ reg16_write16(client, 0x3004, priv->rect.left + AR0143_X_START); + /* horiz crop end */ +- reg16_write16(client, 0x3008, priv->rect.left + priv->rect.width - 1); ++ reg16_write16(client, 0x3008, priv->rect.left + priv->rect.width - 1 + AR0143_X_START); + /* vert crop start */ +- reg16_write16(client, 0x3002, priv->rect.top); ++ reg16_write16(client, 0x3002, priv->rect.top + AR0143_Y_START); + /* vert crop end */ +- reg16_write16(client, 0x3006, priv->rect.top + priv->rect.height + 1); ++ reg16_write16(client, 0x3006, priv->rect.top + priv->rect.height + 1 + AR0143_Y_START); + + return 0; + }; +diff --git a/drivers/media/i2c/soc_camera/ar0147.c b/drivers/media/i2c/soc_camera/ar0147.c +index cc7face..cc4e761 100644 +--- a/drivers/media/i2c/soc_camera/ar0147.c ++++ b/drivers/media/i2c/soc_camera/ar0147.c +@@ -155,13 +155,13 @@ static int ar0147_set_window(struct v4l2_subdev *sd) + dev_dbg(&client->dev, "L=%d T=%d %dx%d\n", priv->rect.left, priv->rect.top, priv->rect.width, priv->rect.height); + + /* horiz crop start */ +- reg16_write16(client, 0x3004, priv->rect.left); ++ reg16_write16(client, 0x3004, priv->rect.left + AR0147_X_START); + /* horiz crop end */ +- reg16_write16(client, 0x3008, priv->rect.left + priv->rect.width - 1); ++ reg16_write16(client, 0x3008, priv->rect.left + priv->rect.width - 1 + AR0147_X_START); + /* vert crop start */ +- reg16_write16(client, 0x3002, priv->rect.top); ++ reg16_write16(client, 0x3002, priv->rect.top + AR0147_Y_START); + /* vert crop end */ +- reg16_write16(client, 0x3006, priv->rect.top + priv->rect.height - 1); ++ reg16_write16(client, 0x3006, priv->rect.top + priv->rect.height - 1 + AR0147_Y_START); + + return 0; + }; +diff --git a/drivers/media/i2c/soc_camera/ar0231.c b/drivers/media/i2c/soc_camera/ar0231.c +index 05037c7..b239f56 100644 +--- a/drivers/media/i2c/soc_camera/ar0231.c ++++ b/drivers/media/i2c/soc_camera/ar0231.c +@@ -96,13 +96,13 @@ static int ar0231_set_window(struct v4l2_subdev *sd) + dev_err(&client->dev, "L=%d T=%d %dx%d\n", priv->rect.left, priv->rect.top, priv->rect.width, priv->rect.height); + + /* horiz crop start */ +- reg16_write16(client, 0x3004, priv->rect.left); ++ reg16_write16(client, 0x3004, priv->rect.left + AR0231_X_START); + /* horiz crop end */ +- reg16_write16(client, 0x3008, priv->rect.left + priv->rect.width - 1); ++ reg16_write16(client, 0x3008, priv->rect.left + priv->rect.width - 1 + AR0231_X_START); + /* vert crop start */ +- reg16_write16(client, 0x3002, priv->rect.top); ++ reg16_write16(client, 0x3002, priv->rect.top + AR0231_Y_START); + /* vert crop end */ +- reg16_write16(client, 0x3006, priv->rect.top + priv->rect.height + 1); ++ reg16_write16(client, 0x3006, priv->rect.top + priv->rect.height - 1 + AR0231_Y_START); + + return 0; + }; +diff --git a/drivers/media/i2c/soc_camera/ar0233.c b/drivers/media/i2c/soc_camera/ar0233.c +index 862c820..543b8a6 100644 +--- a/drivers/media/i2c/soc_camera/ar0233.c ++++ b/drivers/media/i2c/soc_camera/ar0233.c +@@ -102,13 +102,13 @@ static int ar0233_set_window(struct v4l2_subdev *sd) + dev_dbg(&client->dev, "L=%d T=%d %dx%d\n", priv->rect.left, priv->rect.top, priv->rect.width, priv->rect.height); + + /* horiz crop start */ +- reg16_write16(client, 0x3004, priv->rect.left); ++ reg16_write16(client, 0x3004, priv->rect.left + AR0233_X_START); + /* horiz crop end */ +- reg16_write16(client, 0x3008, priv->rect.left + priv->rect.width - 1); ++ reg16_write16(client, 0x3008, priv->rect.left + priv->rect.width - 1 + AR0233_X_START); + /* vert crop start */ +- reg16_write16(client, 0x3002, priv->rect.top); ++ reg16_write16(client, 0x3002, priv->rect.top + AR0233_Y_START); + /* vert crop end */ +- reg16_write16(client, 0x3006, priv->rect.top + priv->rect.height + 1); ++ reg16_write16(client, 0x3006, priv->rect.top + priv->rect.height - 1 + AR0233_Y_START); + + return 0; + }; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0172-media-i2c-ar0147-fix-super-exposure-artifact-line.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0172-media-i2c-ar0147-fix-super-exposure-artifact-line.patch new file mode 100644 index 00000000..a1191ede --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0172-media-i2c-ar0147-fix-super-exposure-artifact-line.patch @@ -0,0 +1,28 @@ +From 21a04e5800c8114edd5e4459cae4154eaaa71388 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Tue, 21 May 2019 14:36:29 +0300 +Subject: [PATCH 121/122] media: i2c: ar0147: fix super exposure artifact line + +This fixes artifact line at SE+T2 mode + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ar0147_rev2.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/media/i2c/soc_camera/ar0147_rev2.h b/drivers/media/i2c/soc_camera/ar0147_rev2.h +index e5ccb8f..04d8e5e 100644 +--- a/drivers/media/i2c/soc_camera/ar0147_rev2.h ++++ b/drivers/media/i2c/soc_camera/ar0147_rev2.h +@@ -747,7 +747,7 @@ static const struct ar0147_reg ar0147_rev2_shutter_and_booster_settings[] = { + {0x337A, 0x100E}, + {0x3554, 0x1599}, + {0x32EA, 0x3CA9}, +-{0x3510, 0x9753}, ++//{0x3510, 0x9753}, + {0x3520, 0x0800}, + {0x3522, 0x0008}, + {0x3524, 0x0C00}, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0173-lvds-ti9x4-fix-remote-gpio-setup.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0173-lvds-ti9x4-fix-remote-gpio-setup.patch new file mode 100644 index 00000000..b7c39af0 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0173-lvds-ti9x4-fix-remote-gpio-setup.patch @@ -0,0 +1,132 @@ +From 76e798d5f852d1551474a27a519cd008ff29f4f1 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Tue, 28 May 2019 16:07:28 +0300 +Subject: [PATCH 122/122] lvds: ti9x4: fix remote gpio setup + +The remote gpio must be set after remote gpio enablement on +serializer side. +Fix compilation warnings. +GEOEMI registers addresing is 1 byte. + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ar0233.c | 1 - + drivers/media/i2c/soc_camera/gw4200_ar014x.c | 8 ++++---- + drivers/media/i2c/soc_camera/gw5200_imx390.c | 8 ++++---- + drivers/media/i2c/soc_camera/imx390.c | 2 +- + drivers/media/i2c/soc_camera/ti9x4.c | 5 +++-- + 5 files changed, 12 insertions(+), 12 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ar0233.c b/drivers/media/i2c/soc_camera/ar0233.c +index 543b8a6..f3b899e 100644 +--- a/drivers/media/i2c/soc_camera/ar0233.c ++++ b/drivers/media/i2c/soc_camera/ar0233.c +@@ -63,7 +63,6 @@ static inline struct ar0233_priv *to_ar0233(const struct i2c_client *client) + + static int ar0233_set_regs(struct i2c_client *client, const struct ar0233_reg **pregs) + { +- struct ar0233_priv *priv = to_ar0233(client); + const struct ar0233_reg *regs; + int i, j; + +diff --git a/drivers/media/i2c/soc_camera/gw4200_ar014x.c b/drivers/media/i2c/soc_camera/gw4200_ar014x.c +index 674e409..45123ae 100644 +--- a/drivers/media/i2c/soc_camera/gw4200_ar014x.c ++++ b/drivers/media/i2c/soc_camera/gw4200_ar014x.c +@@ -267,14 +267,14 @@ static int gw4200_g_register(struct v4l2_subdev *sd, + { + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret; +- u16 val = 0; ++ u8 val = 0; + +- ret = reg16_read16(client, (u16)reg->reg, &val); ++ ret = reg8_read(client, (u8)reg->reg, &val); + if (ret < 0) + return ret; + + reg->val = val; +- reg->size = sizeof(u16); ++ reg->size = sizeof(u8); + + return 0; + } +@@ -284,7 +284,7 @@ static int gw4200_s_register(struct v4l2_subdev *sd, + { + struct i2c_client *client = v4l2_get_subdevdata(sd); + +- return reg16_write16(client, (u16)reg->reg, (u16)reg->val); ++ return reg8_write(client, (u8)reg->reg, (u8)reg->val); + } + #endif + +diff --git a/drivers/media/i2c/soc_camera/gw5200_imx390.c b/drivers/media/i2c/soc_camera/gw5200_imx390.c +index 0703c3d..90de41f 100644 +--- a/drivers/media/i2c/soc_camera/gw5200_imx390.c ++++ b/drivers/media/i2c/soc_camera/gw5200_imx390.c +@@ -235,14 +235,14 @@ static int gw5200_g_register(struct v4l2_subdev *sd, + { + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret; +- u16 val = 0; ++ u8 val = 0; + +- ret = reg16_read16(client, (u16)reg->reg, &val); ++ ret = reg8_read(client, (u8)reg->reg, &val); + if (ret < 0) + return ret; + + reg->val = val; +- reg->size = sizeof(u16); ++ reg->size = sizeof(u8); + + return 0; + } +@@ -252,7 +252,7 @@ static int gw5200_s_register(struct v4l2_subdev *sd, + { + struct i2c_client *client = v4l2_get_subdevdata(sd); + +- return reg16_write16(client, (u16)reg->reg, (u16)reg->val); ++ return reg8_write(client, (u8)reg->reg, (u8)reg->val); + } + #endif + +diff --git a/drivers/media/i2c/soc_camera/imx390.c b/drivers/media/i2c/soc_camera/imx390.c +index 7171d70..87279d0 100644 +--- a/drivers/media/i2c/soc_camera/imx390.c ++++ b/drivers/media/i2c/soc_camera/imx390.c +@@ -249,7 +249,7 @@ static int imx390_s_ctrl(struct v4l2_ctrl *ctrl) + struct imx390_priv *priv = to_imx390(client); + int ret = -EINVAL; + int val; +- uint8_t val8; ++ uint8_t val8 = 0; + + if (!priv->init_complete) + return 0; +diff --git a/drivers/media/i2c/soc_camera/ti9x4.c b/drivers/media/i2c/soc_camera/ti9x4.c +index fdb50e5..0cfcfaa 100644 +--- a/drivers/media/i2c/soc_camera/ti9x4.c ++++ b/drivers/media/i2c/soc_camera/ti9x4.c +@@ -275,8 +275,6 @@ static void ti9x4_fpdlink3_setup(struct i2c_client *client, int idx) + reg8_write(client, 0x70, ((priv->vc_map >> (idx * 4)) << 6) | 0x1e); /* CSI data type: yuv422 8-bit, assign VC */ + reg8_write(client, 0x71, ((priv->vc_map >> (idx * 4)) << 6) | 0x2c); /* CSI data type: RAW12, assign VC */ + reg8_write(client, 0xbc, 0x00); /* Setup minimal time between FV and LV to 3 PCLKs */ +- reg8_write(client, 0x6e, 0x88 | (priv->gpio[1] << 4) | priv->gpio[0]); /* Remote GPIO1/GPIO0 setup */ +- reg8_write(client, 0x6f, 0x88 | (priv->gpio[3] << 4) | priv->gpio[2]); /* Remote GPIO3/GPIO2 setup */ + reg8_write(client, 0x72, priv->vc_map >> (idx * 4)); /* CSI VC MAP */ + } + +@@ -340,6 +338,9 @@ static int ti9x4_initialize(struct i2c_client *client) + break; + } + client->addr = priv->des_addr; ++ ++ reg8_write(client, 0x6e, 0x88 | (priv->gpio[1] << 4) | priv->gpio[0]); /* Remote GPIO1/GPIO0 setup */ ++ reg8_write(client, 0x6f, 0x88 | (priv->gpio[3] << 4) | priv->gpio[2]); /* Remote GPIO3/GPIO2 setup */ + } + + return 0; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0174-arm64-dts-renesas-ulcb-vb2-Drive-CAN-controller-rese.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0174-arm64-dts-renesas-ulcb-vb2-Drive-CAN-controller-rese.patch new file mode 100644 index 00000000..ae8eb8b0 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0174-arm64-dts-renesas-ulcb-vb2-Drive-CAN-controller-rese.patch @@ -0,0 +1,89 @@ +From fb760e67e0336587583eb32cf77bbdf4b4e1fc74 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Tue, 28 May 2019 19:55:13 +0300 +Subject: [PATCH] arm64: dts: renesas: ulcb-vb2: Drive CAN controller reset + through regulators + +This uses regulators instead of GPIO hogs for controlling CAN +reset pins on VideoBox v2 which fixes CAN cold-start issues. + +Signed-off-by: Andrey Gusakov +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 32 +++++++++++++++++++------------ + 1 file changed, 20 insertions(+), 12 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi +index 1610949..5831d12 100644 +--- a/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi ++++ b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi +@@ -94,6 +94,24 @@ + regulator-always-on; + }; + ++ can2_power: regulator@11 { ++ compatible = "regulator-fixed"; ++ regulator-name = "can2_power"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio_ext_pwr 8 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ can3_power: regulator@12 { ++ compatible = "regulator-fixed"; ++ regulator-name = "can3_power"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio_ext_pwr 9 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ + /delete-node/sound; + + rsnd_ak4613: sound@0 { +@@ -187,6 +205,7 @@ + interrupt-parent = <&gpio0>; + interrupts = <15 GPIO_ACTIVE_LOW>; + spi-max-frequency = <10000000>; ++ vdd-supply = <&can2_power>; + }; + spican1: spidev@1 { + compatible = "microchip,mcp2515"; +@@ -195,6 +214,7 @@ + interrupt-parent = <&gpio1>; + interrupts = <5 GPIO_ACTIVE_LOW>; + spi-max-frequency = <10000000>; ++ vdd-supply = <&can3_power>; + }; + }; + }; +@@ -1147,12 +1167,6 @@ + output-high; + line-name = "can2_120R_load"; + }; +- can2_rst { +- gpio-hog; +- gpios = <8 GPIO_ACTIVE_HIGH>; +- output-high; +- line-name = "can2_rst"; +- }; + /* CAN3 */ + can3_stby { + gpio-hog; +@@ -1166,12 +1180,6 @@ + output-high; + line-name = "can3_120R_load"; + }; +- can3_rst { +- gpio-hog; +- gpios = <9 GPIO_ACTIVE_HIGH>; +- output-high; +- line-name = "can3_rst"; +- }; + }; + }; + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0175-lvds-ov2775-add-exposure-gain.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0175-lvds-ov2775-add-exposure-gain.patch new file mode 100644 index 00000000..5d257116 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0175-lvds-ov2775-add-exposure-gain.patch @@ -0,0 +1,76 @@ +From 2abfbc0f83952075f87a9eaf8ea239a260ca2a60 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Tue, 4 Jun 2019 19:44:00 +0300 +Subject: [PATCH 1/5] lvds: ov2775: add exposure, gain + +This add exposure and gain for ov2775 imager + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ov2775.c | 20 +++++++++++++++++--- + drivers/media/i2c/soc_camera/ov2775.h | 2 +- + 2 files changed, 18 insertions(+), 4 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ov2775.c b/drivers/media/i2c/soc_camera/ov2775.c +index 2022d47..989e7ca 100644 +--- a/drivers/media/i2c/soc_camera/ov2775.c ++++ b/drivers/media/i2c/soc_camera/ov2775.c +@@ -262,7 +262,21 @@ static int ov2775_s_ctrl(struct v4l2_ctrl *ctrl) + case V4L2_CID_SHARPNESS: + case V4L2_CID_AUTOGAIN: + case V4L2_CID_GAIN: ++ /* HCG digital gain */ ++ ret = reg16_write(client, 0x315a, ctrl->val >> 8); ++ ret |= reg16_write(client, 0x315b, ctrl->val & 0xff); ++ /* LCG digital gain */ ++ ret |= reg16_write(client, 0x315c, ctrl->val >> 8); ++ ret |= reg16_write(client, 0x315d, ctrl->val & 0xff); ++ /* VS digital gain */ ++ ret |= reg16_write(client, 0x315e, ctrl->val >> 8); ++ ret |= reg16_write(client, 0x315f, ctrl->val & 0xff); ++ break; + case V4L2_CID_EXPOSURE: ++ /* HCG/LCG exposure time */ ++ ret = reg16_write(client, 0x30B6, ctrl->val >> 8); ++ ret |= reg16_write(client, 0x30B7, ctrl->val & 0xff); ++ break; + case V4L2_CID_HFLIP: + case V4L2_CID_VFLIP: + break; +@@ -418,7 +432,7 @@ static int ov2775_probe(struct i2c_client *client, + priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; + + priv->exposure = 0x100; +- priv->gain = 0x100; ++ priv->gain = 0x200; + priv->autogain = 1; + v4l2_ctrl_handler_init(&priv->hdl, 4); + v4l2_ctrl_new_std(&priv->hdl, &ov2775_ctrl_ops, +@@ -436,9 +450,9 @@ static int ov2775_probe(struct i2c_client *client, + v4l2_ctrl_new_std(&priv->hdl, &ov2775_ctrl_ops, + V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); + v4l2_ctrl_new_std(&priv->hdl, &ov2775_ctrl_ops, +- V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); ++ V4L2_CID_GAIN, 0, 0x3fff, 1, priv->gain); + v4l2_ctrl_new_std(&priv->hdl, &ov2775_ctrl_ops, +- V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure); ++ V4L2_CID_EXPOSURE, 0, 0x7ff, 1, priv->exposure); + v4l2_ctrl_new_std(&priv->hdl, &ov2775_ctrl_ops, + V4L2_CID_HFLIP, 0, 1, 1, 1); + v4l2_ctrl_new_std(&priv->hdl, &ov2775_ctrl_ops, +diff --git a/drivers/media/i2c/soc_camera/ov2775.h b/drivers/media/i2c/soc_camera/ov2775.h +index 7e1ee31..9ff8968 100644 +--- a/drivers/media/i2c/soc_camera/ov2775.h ++++ b/drivers/media/i2c/soc_camera/ov2775.h +@@ -9,7 +9,7 @@ + * option) any later version. + */ + +-#define OV2775_DISPLAY_PATTERN_COLOR_BAR ++//#define OV2775_DISPLAY_PATTERN_COLOR_BAR + + #define OV2775_MAX_WIDTH 1920 + #define OV2775_MAX_HEIGHT 1080 +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0176-lvds-geosemi-put-imager-to-autodetect-tail.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0176-lvds-geosemi-put-imager-to-autodetect-tail.patch new file mode 100644 index 00000000..a3413667 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0176-lvds-geosemi-put-imager-to-autodetect-tail.patch @@ -0,0 +1,58 @@ +From a0b6b13ecaa44559b02574814e941d5fbbf6589c Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Tue, 4 Jun 2019 20:03:35 +0300 +Subject: [PATCH 2/5] lvds: geosemi: put imager to autodetect tail + +Put Geosemi cameras to tail since their produce ID is +just an i2c address + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ov106xx.c | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ov106xx.c b/drivers/media/i2c/soc_camera/ov106xx.c +index 442e54a..36aa88a 100644 +--- a/drivers/media/i2c/soc_camera/ov106xx.c ++++ b/drivers/media/i2c/soc_camera/ov106xx.c +@@ -129,18 +129,6 @@ static int ov106xx_probe(struct i2c_client *client, + goto out; + } + +- ret = gw4200_probe(client, did); +- if (!ret) { +- chip_id = ID_GW4200_AR014X; +- goto out; +- } +- +- ret = gw5200_probe(client, did); +- if (!ret) { +- chip_id = ID_GW5200_IMX390; +- goto out; +- } +- + ret = ov2775_probe(client, did); + if (!ret) { + chip_id = ID_OV2775; +@@ -171,6 +159,18 @@ static int ov106xx_probe(struct i2c_client *client, + goto out; + } + ++ ret = gw4200_probe(client, did); ++ if (!ret) { ++ chip_id = ID_GW4200_AR014X; ++ goto out; ++ } ++ ++ ret = gw5200_probe(client, did); ++ if (!ret) { ++ chip_id = ID_GW5200_IMX390; ++ goto out; ++ } ++ + v4l_err(client, "failed to probe @ 0x%02x (%s)\n", + client->addr, client->adapter->name); + out: +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0177-media-rcar_vin-add-GREY-Y8-bypass.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0177-media-rcar_vin-add-GREY-Y8-bypass.patch new file mode 100644 index 00000000..3a1278d9 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0177-media-rcar_vin-add-GREY-Y8-bypass.patch @@ -0,0 +1,85 @@ +From 59876245439d2c5602bccdd454d1ef0a72cdb571 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Fri, 7 Jun 2019 19:18:51 +0300 +Subject: [PATCH 3/5] media: rcar_vin: add GREY (Y8) bypass + +This adds bypass of luma Y8 stream + +Signed-off-by: Vladimir Barinov +--- + drivers/media/platform/soc_camera/rcar_vin.c | 22 +++++++++++++++++----- + 1 file changed, 17 insertions(+), 5 deletions(-) + +diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c +index 5239938..291d115 100644 +--- a/drivers/media/platform/soc_camera/rcar_vin.c ++++ b/drivers/media/platform/soc_camera/rcar_vin.c +@@ -1076,6 +1076,7 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + break; + case MEDIA_BUS_FMT_SBGGR8_1X8: + case MEDIA_BUS_FMT_SBGGR12_1X12: ++ case MEDIA_BUS_FMT_Y8_1X8: + vnmc |= VNMC_INF_RAW8 | VNMC_BPS; + break; + default: +@@ -1111,8 +1112,11 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + output_is_yuv = true; + break; + case V4L2_PIX_FMT_GREY: +- dmr = VNDMR_DTMD_YCSEP | VNDMR_YMODE_Y8; +- output_is_yuv = true; ++ if (input_is_yuv) { ++ dmr = VNDMR_DTMD_YCSEP | VNDMR_YMODE_Y8; ++ output_is_yuv = true; ++ } else ++ dmr = 0; + break; + case V4L2_PIX_FMT_ARGB555: + dmr = VNDMR_DTMD_ARGB; +@@ -1802,14 +1806,16 @@ static int rcar_vin_set_rect(struct soc_camera_device *icd) + priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) { + if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12) && + (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR8) && +- (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR12) ++ (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR12) && ++ ((icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_GREY) && (icd->current_fmt->code == MEDIA_BUS_FMT_Y8_1X8)) + && is_scaling(cam)) { + ret = rcar_vin_uds_set(priv, cam); + if (ret < 0) + return ret; + } + if ((icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_SBGGR8) || +- (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_SBGGR12)) ++ (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_SBGGR12) || ++ ((icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_GREY) && (icd->current_fmt->code == MEDIA_BUS_FMT_Y8_1X8))) + iowrite32(ALIGN(cam->out_width / 2, 0x10), + priv->base + VNIS_REG); + else if (is_scaling(cam) || +@@ -2228,6 +2234,7 @@ static int rcar_vin_get_formats(struct soc_camera_device *icd, unsigned int idx, + case MEDIA_BUS_FMT_RGB888_1X24: + case MEDIA_BUS_FMT_SBGGR8_1X8: + case MEDIA_BUS_FMT_SBGGR12_1X12: ++ case MEDIA_BUS_FMT_Y8_1X8: + if (cam->extra_fmt) + break; + +@@ -2447,10 +2454,15 @@ static int rcar_vin_set_fmt(struct soc_camera_device *icd, + case V4L2_PIX_FMT_XBGR32: + can_scale = priv->chip != RCAR_E1; + break; ++ case V4L2_PIX_FMT_GREY: ++ if (icd->current_fmt->code == MEDIA_BUS_FMT_Y8_1X8) ++ can_scale = false; ++ else ++ can_scale = true; ++ break; + case V4L2_PIX_FMT_ABGR32: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_YUYV: +- case V4L2_PIX_FMT_GREY: + case V4L2_PIX_FMT_RGB565: + case V4L2_PIX_FMT_ARGB555: + case V4L2_PIX_FMT_NV16: +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0178-lvds-add-OV2311-imager.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0178-lvds-add-OV2311-imager.patch new file mode 100644 index 00000000..9f773f70 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0178-lvds-add-OV2311-imager.patch @@ -0,0 +1,935 @@ +From 5c4b2dfb06a275237855fe86e6d3d7952a75d013 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Fri, 7 Jun 2019 20:51:35 +0300 +Subject: [PATCH 4/5] lvds: add OV2311 imager + +This add OV2311 lvds imager + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ov106xx.c | 13 +- + drivers/media/i2c/soc_camera/ov2311.c | 637 +++++++++++++++++++++++++++++++++ + drivers/media/i2c/soc_camera/ov2311.h | 217 +++++++++++ + 3 files changed, 866 insertions(+), 1 deletion(-) + create mode 100644 drivers/media/i2c/soc_camera/ov2311.c + create mode 100644 drivers/media/i2c/soc_camera/ov2311.h + +diff --git a/drivers/media/i2c/soc_camera/ov106xx.c b/drivers/media/i2c/soc_camera/ov106xx.c +index 36aa88a..70067d7 100644 +--- a/drivers/media/i2c/soc_camera/ov106xx.c ++++ b/drivers/media/i2c/soc_camera/ov106xx.c +@@ -28,6 +28,7 @@ + #include "ox03a.c" + #include "isx016.c" + #include "isx019.c" ++#include "ov2311.c" + + static enum { + ID_OV10635, +@@ -49,12 +50,13 @@ static enum { + ID_OX03A, + ID_ISX016, + ID_ISX019, ++ ID_OV2311, + } chip_id; + + static int ov106xx_probe(struct i2c_client *client, + const struct i2c_device_id *did) + { +- int ret; ++ int ret = -1; + chip_id = -EINVAL; + + ret = ar0231_probe(client, did); +@@ -135,6 +137,12 @@ static int ov106xx_probe(struct i2c_client *client, + goto out; + } + ++ ret = ov2311_probe(client, did); ++ if (!ret) { ++ chip_id = ID_OV2311; ++ goto out; ++ } ++ + ret = imx390_probe(client, did); + if (!ret) { + chip_id = ID_IMX390; +@@ -237,6 +245,9 @@ static int ov106xx_remove(struct i2c_client *client) + case ID_ISX019: + isx019_remove(client); + break; ++ case ID_OV2311: ++ ov2311_remove(client); ++ break; + }; + + return 0; +diff --git a/drivers/media/i2c/soc_camera/ov2311.c b/drivers/media/i2c/soc_camera/ov2311.c +new file mode 100644 +index 0000000..06e57dd +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov2311.c +@@ -0,0 +1,637 @@ ++/* ++ * OmniVision ov2311 sensor camera driver ++ * ++ * Copyright (C) 2015-2019 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "max9286.h" ++#include "ov2311.h" ++ ++#define OV2311_I2C_ADDR 0x60 ++ ++#define OV2311_PID 0x300a ++#define OV2311_VER 0x300b ++#define OV2311_REV 0x300c ++#define OV2311_VERSION_REG 0x2311 ++ ++#define OV2311_MEDIA_BUS_FMT MEDIA_BUS_FMT_Y8_1X8 ++ ++struct ov2311_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int subsampling; ++ int fps_denominator; ++ int init_complete; ++ u8 id[6]; ++ int dvp_order; ++ /* serializers */ ++ int max9286_addr; ++ int max9271_addr; ++ int ti9x4_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++}; ++ ++static inline struct ov2311_priv *to_ov2311(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct ov2311_priv, sd); ++} ++ ++static inline struct v4l2_subdev *ov2311_to_sd(struct v4l2_ctrl *ctrl) ++{ ++ return &container_of(ctrl->handler, struct ov2311_priv, hdl)->sd; ++} ++ ++static void ov2311_s_port(struct i2c_client *client, int fwd_en) ++{ ++ struct ov2311_priv *priv = to_ov2311(client); ++ int tmp_addr; ++ ++ if (priv->max9286_addr) { ++ tmp_addr = client->addr; ++ client->addr = priv->max9286_addr; /* Deserializer I2C address */ ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ client->addr = tmp_addr; ++ }; ++} ++ ++static int ov2311_set_regs(struct i2c_client *client, ++ const struct ov2311_reg *regs, int nr_regs) ++{ ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (regs[i].reg == OV2311_DELAY) { ++ mdelay(regs[i].val); ++ continue; ++ } ++ ++ if (reg16_write(client, regs[i].reg, regs[i].val)) { ++ usleep_range(100, 150); /* wait 100ns */ ++ reg16_write(client, regs[i].reg, regs[i].val); ++ } ++ } ++ ++ return 0; ++} ++ ++static int ov2311_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int ov2311_set_window(struct v4l2_subdev *sd) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov2311_priv *priv = to_ov2311(client); ++ ++ dev_dbg(&client->dev, "L=%d T=%d %dx%d\n", priv->rect.left, priv->rect.top, priv->rect.width, priv->rect.height); ++#if 0 ++ /* setup resolution */ ++ reg16_write(client, 0x3808, priv->rect.width >> 8); ++ reg16_write(client, 0x3809, priv->rect.width & 0xff); ++ reg16_write(client, 0x380a, priv->rect.height >> 8); ++ reg16_write(client, 0x380b, priv->rect.height & 0xff); ++ ++ /* horiz isp windowstart */ ++ reg16_write(client, 0x3810, priv->rect.left >> 8); ++ reg16_write(client, 0x3811, priv->rect.left & 0xff); ++ reg16_write(client, 0x3812, priv->rect.top >> 8); ++ reg16_write(client, 0x3813, priv->rect.top & 0xff); ++#endif ++ return 0; ++}; ++ ++static int ov2311_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov2311_priv *priv = to_ov2311(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = OV2311_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int ov2311_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = OV2311_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int ov2311_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = OV2311_MEDIA_BUS_FMT; ++ ++ return 0; ++} ++ ++static int ov2311_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov2311_priv *priv = to_ov2311(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = OV2311_VERSION_REG >> 8; ++ edid->edid[9] = OV2311_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int ov2311_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov2311_priv *priv = to_ov2311(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > OV2311_MAX_WIDTH) || ++ (rect->top + rect->height > OV2311_MAX_HEIGHT)) ++ *rect = priv->rect; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ ov2311_set_window(sd); ++ ++ return 0; ++} ++ ++static int ov2311_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov2311_priv *priv = to_ov2311(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = OV2311_MAX_WIDTH; ++ sel->r.height = OV2311_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = OV2311_MAX_WIDTH; ++ sel->r.height = OV2311_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ov2311_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int ov2311_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u8 val = 0; ++ ++ ret = reg16_read(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int ov2311_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return reg16_write(client, (u16)reg->reg, (u8)reg->val); ++} ++#endif ++ ++static struct v4l2_subdev_core_ops ov2311_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ov2311_g_register, ++ .s_register = ov2311_s_register, ++#endif ++}; ++ ++static int ov2311_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = ov2311_to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov2311_priv *priv = to_ov2311(client); ++ int ret = 0; ++ u8 val = 0; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ case V4L2_CID_CONTRAST: ++ case V4L2_CID_SATURATION: ++ case V4L2_CID_HUE: ++ case V4L2_CID_GAMMA: ++ break; ++ case V4L2_CID_GAIN: ++ reg16_write(client, 0x350A, ctrl->val / 0x3ff); // COARSE: 4.10 format ++ reg16_write(client, 0x350B, (ctrl->val % 0x3ff) >> 2); // FINE: 4.10 format ++ reg16_write(client, 0x350C, (ctrl->val % 0x3ff) << 6); // FINE: 4.10 format ++ break; ++ case V4L2_CID_ANALOGUE_GAIN: ++ reg16_write(client, 0x3508, ctrl->val / 0xf); // COARSE: 5.4 format ++ reg16_write(client, 0x3509, (ctrl->val % 0xf) << 4); // FINE: 5.4 format ++ break; ++ case V4L2_CID_EXPOSURE: ++ reg16_write(client, 0x3501, ctrl->val >> 8); ++ reg16_write(client, 0x3502, ctrl->val & 0xff); ++ break; ++ case V4L2_CID_HFLIP: ++ reg16_read(client, 0x3821, &val); ++ val &= ~0x04; ++ val |= (ctrl->val ? 0x04 : 0); ++ reg16_write(client, 0x3821, val); ++ break; ++ case V4L2_CID_VFLIP: ++ reg16_read(client, 0x3820, &val); ++ val &= ~0x44; ++ val |= (ctrl->val ? 0x44 : 0); ++ reg16_write(client, 0x3820, val); ++ break; ++ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: ++ ret = 0; ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ov2311_ctrl_ops = { ++ .s_ctrl = ov2311_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops ov2311_video_ops = { ++ .s_stream = ov2311_s_stream, ++ .g_mbus_config = ov2311_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops ov2311_subdev_pad_ops = { ++ .get_edid = ov2311_get_edid, ++ .enum_mbus_code = ov2311_enum_mbus_code, ++ .get_selection = ov2311_get_selection, ++ .set_selection = ov2311_set_selection, ++ .get_fmt = ov2311_get_fmt, ++ .set_fmt = ov2311_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops ov2311_subdev_ops = { ++ .core = &ov2311_core_ops, ++ .video = &ov2311_video_ops, ++ .pad = &ov2311_subdev_pad_ops, ++}; ++ ++static void ov2311_otp_id_read(struct i2c_client *client) ++{ ++ struct ov2311_priv *priv = to_ov2311(client); ++ int i; ++ ++ reg16_write(client, 0x100, 1); ++ reg16_write(client, 0x3d81, 1); ++ usleep_range(25000, 25500); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i++) { ++ /* first 6 bytes are equal on all ov2311 */ ++ reg16_read(client, 0x7000 + i + 6, &priv->id[i]); ++ } ++ ++ reg16_write(client, 0x100, 0); ++} ++ ++static ssize_t ov2311_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov2311_priv *priv = to_ov2311(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_ov2311, S_IRUGO, ov2311_otp_id_show, NULL); ++ ++static int ov2311_initialize(struct i2c_client *client) ++{ ++ struct ov2311_priv *priv = to_ov2311(client); ++ u16 pid; ++ u8 val = 0, rev = 0; ++ int ret = 0; ++ int tmp_addr = 0; ++ ++ ov2311_s_port(client, 1); ++ ++ /* check and show product ID and manufacturer ID */ ++ reg16_read(client, OV2311_PID, &val); ++ pid = val; ++ reg16_read(client, OV2311_VER, &val); ++ pid = (pid << 8) | val; ++ ++ if (pid != OV2311_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x\n", pid); ++ ret = -ENODEV; ++ goto out; ++ } ++ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x3_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x02, 0x13); /* MIPI 2-lanes */ ++ } ++ client->addr = tmp_addr; ++ ++ /* check revision */ ++ reg16_read(client, OV2311_REV, &rev); ++ /* Read OTP IDs */ ++ ov2311_otp_id_read(client); ++ /* Program wizard registers */ ++ ov2311_set_regs(client, ov2311_regs_wizard_r1c, ARRAY_SIZE(ov2311_regs_wizard_r1c)); ++ ++ dev_info(&client->dev, "ov2311 PID %x (rev %x), res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, rev, OV2311_MAX_WIDTH, OV2311_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++out: ++ ov2311_s_port(client, 0); ++ ++ return ret; ++} ++ ++static int ov2311_parse_dt(struct device_node *np, struct ov2311_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order); ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ if (!priv->max9286_addr && !priv->ti9x4_addr) { ++ dev_err(&client->dev, "deserializer does not present for OV2311\n"); ++ return -EINVAL; ++ } ++ ++ ov2311_s_port(client, 1); ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ ++ reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x0A, OV2311_I2C_ADDR << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, OV2311_I2C_ADDR << 1); /* Sensor native I2C address */ ++ } ++ client->addr = tmp_addr; ++ ++ return 0; ++} ++ ++static int ov2311_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ov2311_priv *priv; ++ struct v4l2_ctrl *ctrl; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &ov2311_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = OV2311_MAX_WIDTH; ++ priv->rect.height = OV2311_MAX_HEIGHT; ++ priv->fps_denominator = 30; ++ ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2311_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 0xff, 1, 0x30); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2311_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 4, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2311_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 0xff, 1, 0xff); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2311_ctrl_ops, ++ V4L2_CID_HUE, 0, 255, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2311_ctrl_ops, ++ V4L2_CID_GAMMA, 0, 0xffff, 1, 0x233); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2311_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0x3ff*4, 1, 0x3ff); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2311_ctrl_ops, ++ V4L2_CID_ANALOGUE_GAIN, 0, 0xf*5, 1, 0xf); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2311_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0x580, 1, 0x57c); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2311_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2311_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov2311_ctrl_ops, ++ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 9); ++ if (ctrl) ++ ctrl->flags &= ~V4L2_CTRL_FLAG_READ_ONLY; ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = ov2311_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = ov2311_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ov2311) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_OV2311 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int ov2311_remove(struct i2c_client *client) ++{ ++ struct ov2311_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ov2311); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_OV2311 ++static const struct i2c_device_id ov2311_id[] = { ++ { "ov2311", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ov2311_id); ++ ++static const struct of_device_id ov2311_of_ids[] = { ++ { .compatible = "ovti,ov2311", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ov2311_of_ids); ++ ++static struct i2c_driver ov2311_i2c_driver = { ++ .driver = { ++ .name = "ov2311", ++ .of_match_table = ov2311_of_ids, ++ }, ++ .probe = ov2311_probe, ++ .remove = ov2311_remove, ++ .id_table = ov2311_id, ++}; ++ ++module_i2c_driver(ov2311_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for OV2311"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/ov2311.h b/drivers/media/i2c/soc_camera/ov2311.h +new file mode 100644 +index 0000000..3a56b0b +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov2311.h +@@ -0,0 +1,217 @@ ++/* ++ * OmniVision ov2311 sensor camera wizard 1600x130@30/GREY8/MIPI ++ * ++ * Copyright (C) 2015-2017 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++//#define OV2311_DISPLAY_PATTERN ++//#define OV2311_FSIN_ENABLE ++ ++#define OV2311_MAX_WIDTH 1600 ++#define OV2311_MAX_HEIGHT 1300 ++ ++#define OV2311_DELAY 0xffff ++ ++#define OV2311_SENSOR_WIDTH 1616 ++#define OV2311_SENSOR_HEIGHT 1316 ++ ++#define OV2311_X_START ((OV2311_SENSOR_WIDTH - OV2311_MAX_WIDTH) / 2) ++#define OV2311_Y_START ((OV2311_SENSOR_HEIGHT - OV2311_MAX_HEIGHT) / 2) ++#define OV2311_X_END (OV2311_X_START + OV2311_MAX_WIDTH - 1) ++#define OV2311_Y_END (OV2311_Y_START + OV2311_MAX_HEIGHT - 1) ++ ++struct ov2311_reg { ++ u16 reg; ++ u8 val; ++}; ++ ++/* R1600x1300 RAW10 MIPI 60fps */ ++static const struct ov2311_reg ov2311_regs_wizard_r1c[] = { ++{0x0103, 0x01}, ++{0x0100, 0x00}, ++{0x010c, 0x02}, ++{0x010b, 0x01}, ++{0x0300, 0x01}, ++{0x0302, 0x32}, ++{0x0303, 0x00}, ++{0x0304, 0x03}, ++{0x0305, 0x02}, ++{0x0306, 0x01}, ++{0x030d, 0x5a}, ++{0x030e, 0x04}, ++{0x3001, 0x02}, ++{0x3004, 0x00}, ++{0x3005, 0x00}, ++{0x3006, 0x0a}, ++{0x3011, 0x0d}, ++{0x3014, 0x04}, ++{0x301c, 0xf0}, ++{0x3020, 0x20}, ++{0x302c, 0x00}, ++{0x302d, 0x00}, ++{0x302e, 0x00}, ++{0x302f, 0x03}, ++{0x3030, 0x10}, ++{0x303f, 0x03}, ++{0x3103, 0x00}, ++{0x3106, 0x08}, ++{0x31ff, 0x01}, ++{0x3501, 0x05}, ++{0x3502, 0x7c}, ++{0x3506, 0x00}, ++{0x3507, 0x00}, ++{0x3620, 0x67}, ++{0x3633, 0x78}, ++{0x3662, 0x65}, ++{0x3664, 0xb0}, ++{0x3666, 0x70}, ++{0x3670, 0x68}, ++{0x3674, 0x10}, ++{0x3675, 0x00}, ++{0x367e, 0x90}, ++{0x3680, 0x84}, ++{0x36a2, 0x04}, ++{0x36a3, 0x80}, ++{0x36b0, 0x00}, ++{0x3700, 0x35}, ++{0x3704, 0x39}, ++{0x370a, 0x50}, ++{0x3712, 0x00}, ++{0x3713, 0x02}, ++{0x3778, 0x00}, ++{0x379b, 0x01}, ++{0x379c, 0x10}, ++{0x3800, 0x00}, ++{0x3801, 0x00}, ++{0x3802, 0x00}, ++{0x3803, 0x00}, ++{0x3804, 0x06}, ++{0x3805, 0x4f}, ++{0x3806, 0x05}, ++{0x3807, 0x23}, ++{0x3808, OV2311_MAX_WIDTH >> 8}, ++{0x3809, OV2311_MAX_WIDTH & 0xff}, ++{0x380a, OV2311_MAX_HEIGHT >> 8}, ++{0x380b, OV2311_MAX_HEIGHT & 0xff}, ++{0x380c, 0x03}, ++{0x380d, 0xa8}, ++{0x380e, 0x05}, ++{0x380f, 0x88}, ++{0x3810, OV2311_X_START >> 8}, ++{0x3811, OV2311_X_START & 0xff}, ++{0x3812, OV2311_Y_START >> 8}, ++{0x3813, OV2311_X_START & 0xff}, ++{0x3814, 0x11}, ++{0x3815, 0x11}, ++{0x3816, 0x00}, ++{0x3817, 0x01}, ++{0x3818, 0x00}, ++{0x3819, 0x05}, ++{0x3820, 0x00}, ++{0x3821, 0x00}, ++{0x382b, 0x5a}, ++{0x382c, 0x0a}, ++{0x382d, 0xf8}, ++{0x3881, 0x44}, ++{0x3882, 0x02}, ++{0x3883, 0x8c}, ++{0x3885, 0x07}, ++{0x389d, 0x03}, ++{0x38a6, 0x00}, ++{0x38a7, 0x01}, ++{0x38b3, 0x07}, ++{0x38b1, 0x00}, ++{0x38e5, 0x02}, ++{0x38e7, 0x00}, ++{0x38e8, 0x00}, ++{0x3910, 0xff}, ++{0x3911, 0xff}, ++{0x3912, 0x08}, ++{0x3913, 0x00}, ++{0x3914, 0x00}, ++{0x3915, 0x00}, ++{0x391c, 0x00}, ++{0x3920, 0xff}, ++{0x3921, 0x80}, ++{0x3922, 0x00}, ++{0x3923, 0x00}, ++{0x3924, 0x05}, ++{0x3925, 0x00}, ++{0x3926, 0x00}, ++{0x3927, 0x00}, ++{0x3928, 0x1a}, ++{0x392d, 0x03}, ++{0x392e, 0xa8}, ++{0x392f, 0x08}, ++{0x4001, 0x00}, ++{0x4003, 0x40}, ++{0x4008, 0x04}, ++{0x4009, 0x1b}, ++{0x400c, 0x04}, ++{0x400d, 0x1b}, ++{0x4010, 0xf4}, ++{0x4011, 0x00}, ++{0x4016, 0x00}, ++{0x4017, 0x04}, ++{0x4042, 0x11}, ++{0x4043, 0x70}, ++{0x4045, 0x00}, ++{0x4409, 0x5f}, ++{0x4509, 0x00}, ++{0x450b, 0x00}, ++{0x4600, 0x00}, ++{0x4601, 0xa0}, ++{0x4708, 0x09}, ++{0x470c, 0x81}, ++{0x4710, 0x06}, ++{0x4711, 0x00}, ++{0x4800, 0x00}, ++{0x481f, 0x30}, ++{0x4837, 0x14}, ++{0x4f00, 0x00}, ++{0x4f07, 0x00}, ++{0x4f08, 0x03}, ++{0x4f09, 0x08}, ++{0x4f0c, 0x05}, ++{0x4f0d, 0xb4}, ++{0x4f10, 0x00}, ++{0x4f11, 0x00}, ++{0x4f12, 0x07}, ++{0x4f13, 0xe2}, ++{0x5000, 0x9f}, ++{0x5001, 0x20}, ++{0x5026, 0x00}, ++{0x5c00, 0x00}, ++{0x5c01, 0x2c}, ++{0x5c02, 0x00}, ++{0x5c03, 0x7f}, ++{0x5e00, 0x00}, ++{0x5e01, 0x41}, ++{0x38b1, 0x02}, ++{0x3880, 0x00}, ++ ++#if 1 /* Y8 mode */ ++{0x3016, 0xF1}, ++{0x0100, 0x01}, ++{0x4814, 0x6A}, //; dt_man en, both embed/image data type are 0x2A ++{0x3218, 0x32}, ++{0x3216, 0x01}, ++{0x3208, 0x04}, ++{0x3D81, 0x01}, ++{0x4605, 0x02}, ++{0x4816, 0x0A}, ++{0x3208, 0x14}, ++{0x3662, 0x67}, //; [1] raw8 ++{0x366F, 0x1A}, //; [6] MSB ++//{0x3674, 0x11}, //; [0] embed_en, add embed data before normal image ++{0x3674, 0x10}, //; [0] embed_dis, add embed data before normal image ++{0x3016, 0xF0}, ++#endif ++ ++{0x0100, 0x01}, ++}; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0179-media-i2c-soc_camera-Fix-more-Bad-of_node_put-errors.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0179-media-i2c-soc_camera-Fix-more-Bad-of_node_put-errors.patch new file mode 100644 index 00000000..b4d8f0f7 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0179-media-i2c-soc_camera-Fix-more-Bad-of_node_put-errors.patch @@ -0,0 +1,139 @@ +From 100251b8221f88cccb27ad3997a7010a77501a44 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Mon, 17 Jun 2019 18:15:58 +0300 +Subject: [PATCH 5/5] media: i2c: soc_camera: Fix more "Bad of_node_put" errors + +This fixes "OF: ERROR: Bad of_node_put()" error and possible kernel crash +when probing i2c soc_camera sensor devices in the recently added drivers. + +When CONFIG_OF_DYNAMIC is not enabled, the error message is not displayed, +and everything seems to work fine. However, there's an error in the sensor +parse_dt callbacks which causes inconsistent reference counter management. + +Move of_node_put() out of a loop scope to prevent bad of_node_put error. +We don't need to call of_node_put() for every node since subsequent +calls to of_graph_get_next_endpoint() decrement reference counter of +the previous node. We only need to call of_node_put() for the last node. + +Signed-off-by: Valentine Barshak +--- + drivers/media/i2c/soc_camera/ar0323.c | 4 ++-- + drivers/media/i2c/soc_camera/isx016.c | 4 ++-- + drivers/media/i2c/soc_camera/isx019.c | 4 ++-- + drivers/media/i2c/soc_camera/ov10640.c | 4 ++-- + drivers/media/i2c/soc_camera/ov2311.c | 4 ++-- + 5 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ar0323.c b/drivers/media/i2c/soc_camera/ar0323.c +index 2ee5526..2104d6a 100644 +--- a/drivers/media/i2c/soc_camera/ar0323.c ++++ b/drivers/media/i2c/soc_camera/ar0323.c +@@ -425,8 +425,6 @@ static int ar0323_parse_dt(struct device_node *np, struct ar0323_priv *priv) + if (!endpoint) + break; + +- of_node_put(endpoint); +- + rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); + if (!rendpoint) + continue; +@@ -438,6 +436,8 @@ static int ar0323_parse_dt(struct device_node *np, struct ar0323_priv *priv) + break; + } + ++ of_node_put(endpoint); ++ + if (!priv->ti9x4_addr) { + dev_err(&client->dev, "deserializer does not present\n"); + return -EINVAL; +diff --git a/drivers/media/i2c/soc_camera/isx016.c b/drivers/media/i2c/soc_camera/isx016.c +index eab155c..ab85b7d 100644 +--- a/drivers/media/i2c/soc_camera/isx016.c ++++ b/drivers/media/i2c/soc_camera/isx016.c +@@ -425,8 +425,6 @@ static int isx016_parse_dt(struct device_node *np, struct isx016_priv *priv) + if (!endpoint) + break; + +- of_node_put(endpoint); +- + rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); + if (!rendpoint) + continue; +@@ -443,6 +441,8 @@ static int isx016_parse_dt(struct device_node *np, struct isx016_priv *priv) + break; + } + ++ of_node_put(endpoint); ++ + if (!priv->max9286_addr && !priv->ti9x4_addr) { + dev_err(&client->dev, "deserializer does not present for ISX016\n"); + return -EINVAL; +diff --git a/drivers/media/i2c/soc_camera/isx019.c b/drivers/media/i2c/soc_camera/isx019.c +index c2f5a4a..188fd28 100644 +--- a/drivers/media/i2c/soc_camera/isx019.c ++++ b/drivers/media/i2c/soc_camera/isx019.c +@@ -483,8 +483,6 @@ static int isx019_parse_dt(struct device_node *np, struct isx019_priv *priv) + if (!endpoint) + break; + +- of_node_put(endpoint); +- + rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); + if (!rendpoint) + continue; +@@ -495,6 +493,8 @@ static int isx019_parse_dt(struct device_node *np, struct isx019_priv *priv) + break; + } + ++ of_node_put(endpoint); ++ + if (!priv->max9286_addr) { + dev_err(&client->dev, "deserializer does not present for ISX019\n"); + return -EINVAL; +diff --git a/drivers/media/i2c/soc_camera/ov10640.c b/drivers/media/i2c/soc_camera/ov10640.c +index 8746988..31117e5 100644 +--- a/drivers/media/i2c/soc_camera/ov10640.c ++++ b/drivers/media/i2c/soc_camera/ov10640.c +@@ -496,8 +496,6 @@ static int ov10640_parse_dt(struct device_node *np, struct ov10640_priv *priv) + if (!endpoint) + break; + +- of_node_put(endpoint); +- + of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order); + + rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); +@@ -516,6 +514,8 @@ static int ov10640_parse_dt(struct device_node *np, struct ov10640_priv *priv) + break; + } + ++ of_node_put(endpoint); ++ + if (!priv->max9286_addr && !priv->ti9x4_addr) { + dev_err(&client->dev, "deserializer does not present for OV10640\n"); + return -EINVAL; +diff --git a/drivers/media/i2c/soc_camera/ov2311.c b/drivers/media/i2c/soc_camera/ov2311.c +index 06e57dd..c8d260c 100644 +--- a/drivers/media/i2c/soc_camera/ov2311.c ++++ b/drivers/media/i2c/soc_camera/ov2311.c +@@ -453,8 +453,6 @@ static int ov2311_parse_dt(struct device_node *np, struct ov2311_priv *priv) + if (!endpoint) + break; + +- of_node_put(endpoint); +- + of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order); + + rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); +@@ -473,6 +471,8 @@ static int ov2311_parse_dt(struct device_node *np, struct ov2311_priv *priv) + break; + } + ++ of_node_put(endpoint); ++ + if (!priv->max9286_addr && !priv->ti9x4_addr) { + dev_err(&client->dev, "deserializer does not present for OV2311\n"); + return -EINVAL; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0180-media-i2c-ov490-add-LI-cameras.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0180-media-i2c-ov490-add-LI-cameras.patch new file mode 100644 index 00000000..85389113 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0180-media-i2c-ov490-add-LI-cameras.patch @@ -0,0 +1,61 @@ +From 9611ea32f2db0150cc9d7e69110cb48df05af238 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Fri, 28 Jun 2019 00:35:26 +0300 +Subject: [PATCH] media: i2c: ov490: add LI cameras + +This adds Leopard Imaging firmware support + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ov490_ov10640.c | 3 +++ + drivers/media/i2c/soc_camera/ov490_ov10640.h | 10 +++++++++- + 2 files changed, 12 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/i2c/soc_camera/ov490_ov10640.c b/drivers/media/i2c/soc_camera/ov490_ov10640.c +index 0ea9a54..0f1a0d4 100644 +--- a/drivers/media/i2c/soc_camera/ov490_ov10640.c ++++ b/drivers/media/i2c/soc_camera/ov490_ov10640.c +@@ -138,6 +138,9 @@ static int ov490_set_regs(struct i2c_client *client, + usleep_range(100, 150); /* wait 100 us */ + reg16_write(client, regs[i].reg, regs[i].val); + } ++ ++ if (regs[i].reg == 0xFFFE) ++ usleep_range(100, 150); /* wait 100 us */ + } + + return 0; +diff --git a/drivers/media/i2c/soc_camera/ov490_ov10640.h b/drivers/media/i2c/soc_camera/ov490_ov10640.h +index b22e93e..b00dc3ade 100644 +--- a/drivers/media/i2c/soc_camera/ov490_ov10640.h ++++ b/drivers/media/i2c/soc_camera/ov490_ov10640.h +@@ -17,6 +17,12 @@ struct ov490_reg { + }; + + static const struct ov490_reg ov490_regs_wizard[] = { ++/* Firmware start (some firmwares need this to kick processing) */ ++{0xfffd, 0x80}, ++{0xfffe, 0x19}, ++{0x5000, 0x05}, ++{0xfffe, 0x80}, ++{0x00c0, 0x3f}, + /* The following registers should match firmware */ + {0xfffd, 0x80}, + {0xfffe, 0x82}, +@@ -93,10 +99,12 @@ static const struct ov490_reg ov490_regs_wizard[] = { + {0xfffe, 0x80}, + {0x00c0, 0xdc}, + #ifdef OV490_DISPLAY_PATTERN +-{0xfffd, 0x80}, + {0xfffe, 0x19}, + {0x5000, 0x02}, + {0xfffe, 0x80}, + {0x00c0, 0xd6}, + #endif ++/* respin register 0x6010 due to added firmware start HOST command */ ++{0xfffe, 0x29}, ++{0x6010, 0x01}, + }; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0181-ARM64-dts-Remove-conflicting-with-mainline-V3M-and-V.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0181-ARM64-dts-Remove-conflicting-with-mainline-V3M-and-V.patch new file mode 100644 index 00000000..d5862978 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0181-ARM64-dts-Remove-conflicting-with-mainline-V3M-and-V.patch @@ -0,0 +1,635 @@ +From 9f7a9e36a59ee22644202e590117f780ed58110e Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Tue, 4 Jun 2019 21:42:40 +0300 +Subject: [PATCH 001/211] ARM64: dts: Remove conflicting with mainline V3M and + V3H device tree parts + +This removes V3M and V3H device tree parts which conflict +with the mainline renesas-devel-20190603-v5.2-rc3 tag. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/Makefile | 10 - + arch/arm64/boot/dts/renesas/r8a77970-eagle.dts | 356 ------------------------ + arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts | 71 ----- + arch/arm64/boot/dts/renesas/r8a77980-condor.dts | 40 --- + arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts | 41 --- + 5 files changed, 518 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile +index f7f8638..294d38a 100644 +--- a/arch/arm64/boot/dts/renesas/Makefile ++++ b/arch/arm64/boot/dts/renesas/Makefile +@@ -33,15 +33,5 @@ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-vb2.dtb r8a7795-es1-h3ulcb-vb2.dtb + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-vb2.1.dtb r8a7795-h3ulcb-4x2g-vb2.1.dtb + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-vbm.dtb r8a7795-es1-h3ulcb-vbm.dtb r8a7795-h3ulcb-4x2g-vbm.dtb + dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-m3nulcb-kf.dtb +-#dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-eagle-function.dtb +-#dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-es1-eagle.dtb r8a77970-es1-eagle-function.dtb +-#dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-es1-v3msk.dtb +-#dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-view.dtb r8a77970-es1-v3msk-view.dtb +-#dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-kf.dtb r8a77970-es1-v3msk-kf.dtb +-#dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-vbm.dtb r8a77970-es1-v3msk-vbm.dtb +-#dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-vbm-v2.dtb r8a77970-es1-v3msk-vbm-v2.dtb +-#dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3mzf.dtb +-#dtb-$(CONFIG_ARCH_R8A77980) += r8a77980-v3hsk-vbm.dtb +-#dtb-$(CONFIG_ARCH_R8A77980) += r8a77980-v3hsk-vbm-v2.dtb + + always := $(dtb-y) +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +index 6338ab3..b6d5332 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +@@ -8,7 +8,6 @@ + + /dts-v1/; + #include "r8a77970.dtsi" +-#include + + / { + model = "Renesas Eagle board based on r8a77970"; +@@ -30,58 +29,6 @@ + reg = <0x0 0x48000000 0x0 0x38000000>; + }; + +- reserved-memory { +- #address-cells = <2>; +- #size-cells = <2>; +- ranges; +- +- /* device specific region for Lossy Decompression */ +- lossy_decompress: linux,lossy_decompress { +- no-map; +- reg = <0x00000000 0x6c000000 0x0 0x03000000>; +- }; +- +- /* global autoconfigured region for contiguous allocations */ +- linux,cma { +- compatible = "shared-dma-pool"; +- reusable; +- reg = <0x00000000 0x6f000000 0x0 0x10000000>; +- linux,cma-default; +- }; +- +- /* device specific region for contiguous allocations */ +- linux,multimedia { +- compatible = "shared-dma-pool"; +- reusable; +- reg = <0x00000000 0x7f000000 0x0 0x01000000>; +- }; +- }; +- +- mmngr { +- compatible = "renesas,mmngr"; +- memory-region = <&lossy_decompress>; +- }; +- +- mmngrbuf { +- compatible = "renesas,mmngrbuf"; +- }; +- +- vspm_if { +- compatible = "renesas,vspm_if"; +- }; +- +- dclkin_p0: clock-out0 { +- compatible = "fixed-clock"; +- #clock-cells = <0>; +- clock-frequency = <148500000>; +- }; +- +- msiof_ref_clk: msiof-ref-clock { +- compatible = "fixed-clock"; +- #clock-cells = <0>; +- clock-frequency = <66666666>; +- }; +- + hdmi-out { + compatible = "hdmi-connector"; + type = "a"; +@@ -155,40 +102,6 @@ + }; + }; + +-&csi40 { +- status = "okay"; +- +- virtual,channel { +- csi2_vc0 { +- data,type = "ycbcr422"; +- receive,vc = <0>; +- }; +- csi2_vc1 { +- data,type = "ycbcr422"; +- receive,vc = <1>; +- }; +- csi2_vc2 { +- data,type = "ycbcr422"; +- receive,vc = <2>; +- }; +- csi2_vc3 { +- data,type = "ycbcr422"; +- receive,vc = <3>; +- }; +- }; +- +- port { +- #address-cells = <1>; +- #size-cells = <0>; +- +- csi2_40_ep: endpoint { +- clock-lanes = <0>; +- data-lanes = <1 2 3 4>; +- csi-rate = <300>; +- }; +- }; +-}; +- + &extal_clk { + clock-frequency = <16666666>; + }; +@@ -242,158 +155,6 @@ + }; + }; + }; +- +- pmic@5A { +- compatible = "dlg,da9063"; +- reg = <0x5A>; +- interrupt-parent = <&intc_ex>; +- interrupts = <0 IRQ_TYPE_LEVEL_LOW>; +- interrupt-controller; +- +- rtc { +- compatible = "dlg,da9063-rtc"; +- }; +- +- wdt { +- compatible = "dlg,da9063-watchdog"; +- }; +- +- regulators { +- DA9063_LDO11: bmem { +- regulator-name = "bmem"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- regulator-always-on; +- regulator-boot-on; +- }; +- }; +- +- onkey { +- compatible = "dlg,da9063-onkey"; +- }; +- }; +-}; +- +-&i2c3 { +- pinctrl-0 = <&i2c3_pins>; +- pinctrl-names = "default"; +- +- status = "okay"; +- clock-frequency = <400000>; +- +- ov106xx@0 { +- compatible = "ovti,ov106xx"; +- reg = <0x60>; +- +- port@0 { +- ov106xx_in0: endpoint { +- clock-lanes = <0>; +- data-lanes = <1 2 3 4>; +- remote-endpoint = <&vin0ep0>; +- }; +- }; +- port@1 { +- ov106xx_max9286_des0ep0: endpoint@0 { +- remote-endpoint = <&max9286_des0ep0>; +- }; +- }; +- }; +- +- ov106xx@1 { +- compatible = "ovti,ov106xx"; +- reg = <0x61>; +- +- port@0 { +- ov106xx_in1: endpoint { +- clock-lanes = <0>; +- data-lanes = <1 2 3 4>; +- remote-endpoint = <&vin1ep0>; +- }; +- }; +- port@1 { +- ov106xx_max9286_des0ep1: endpoint@0 { +- remote-endpoint = <&max9286_des0ep1>; +- }; +- }; +- }; +- +- ov106xx@2 { +- compatible = "ovti,ov106xx"; +- reg = <0x62>; +- +- port@0 { +- ov106xx_in2: endpoint { +- clock-lanes = <0>; +- data-lanes = <1 2 3 4>; +- remote-endpoint = <&vin2ep0>; +- }; +- }; +- port@1 { +- ov106xx_max9286_des0ep2: endpoint@0 { +- remote-endpoint = <&max9286_des0ep2>; +- }; +- }; +- }; +- +- ov106xx@3 { +- compatible = "ovti,ov106xx"; +- reg = <0x63>; +- +- port@0 { +- ov106xx_in3: endpoint { +- clock-lanes = <0>; +- data-lanes = <1 2 3 4>; +- remote-endpoint = <&vin3ep0>; +- }; +- }; +- port@1 { +- ov106xx_des0ep3: endpoint { +- remote-endpoint = <&max9286_des0ep3>; +- }; +- }; +- }; +- +- max9286@0 { +- compatible = "maxim,max9286"; +- reg = <0x48>; +- gpios = <&io_expander 0 GPIO_ACTIVE_LOW>; /* CSI0 DE_PDn */ +- maxim,gpio0 = <0>; +- maxim,sensor_delay = <100>; +- maxim,links = <4>; +- maxim,lanes = <4>; +- maxim,resetb-gpio = <1>; +- maxim,fsync-mode = "automatic"; +- maxim,timeout = <100>; +- +- port@0 { +- max9286_des0ep0: endpoint@0 { +- max9271-addr = <0x50>; +- dvp-order = <1>; +- remote-endpoint = <&ov106xx_in0>; +- }; +- max9286_des0ep1: endpoint@1 { +- max9271-addr = <0x51>; +- dvp-order = <1>; +- remote-endpoint = <&ov106xx_in1>; +- }; +- max9286_des0ep2: endpoint@2 { +- max9271-addr = <0x52>; +- dvp-order = <1>; +- remote-endpoint = <&ov106xx_in2>; +- }; +- max9286_des0ep3: endpoint@3 { +- max9271-addr = <0x53>; +- dvp-order = <1>; +- remote-endpoint = <&ov106xx_in3>; +- }; +- }; +- port@1 { +- max9286_csi0ep0: endpoint { +- csi-rate = <700>; +- remote-endpoint = <&csi2_40_ep>; +- }; +- }; +- }; + }; + + &pfc { +@@ -412,11 +173,6 @@ + function = "i2c0"; + }; + +- i2c3_pins: i2c3 { +- groups = "i2c3"; +- function = "i2c3"; +- }; +- + scif0_pins: scif0 { + groups = "scif0_data"; + function = "scif0"; +@@ -435,118 +191,6 @@ + status = "okay"; + }; + +-&vin0 { +- status = "okay"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@0 { +- vin0ep0: endpoint { +- csi,select = "csi40"; +- virtual,channel = <0>; +- data-lanes = <1 2 3 4>; +- remote-endpoint = <&ov106xx_in0>; +- }; +- }; +- port@1 { +- csi0ep0: endpoint { +- remote-endpoint = <&csi2_40_ep>; +- }; +- }; +- port@2 { +- vin0_max9286_des0ep0: endpoint@0 { +- remote-endpoint = <&max9286_des0ep0>; +- }; +- }; +- }; +-}; +- +-&vin1 { +- status = "okay"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@0 { +- vin1ep0: endpoint { +- csi,select = "csi40"; +- virtual,channel = <1>; +- data-lanes = <1 2 3 4>; +- remote-endpoint = <&ov106xx_in1>; +- }; +- }; +- port@1 { +- csi0ep1: endpoint { +- remote-endpoint = <&csi2_40_ep>; +- }; +- }; +- port@2 { +- vin1_max9286_des0ep1: endpoint@0 { +- remote-endpoint = <&max9286_des0ep1>; +- }; +- }; +- }; +-}; +- +-&vin2 { +- status = "okay"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@0 { +- vin2ep0: endpoint { +- csi,select = "csi40"; +- virtual,channel = <2>; +- data-lanes = <1 2 3 4>; +- remote-endpoint = <&ov106xx_in2>; +- }; +- }; +- port@1 { +- csi0ep2: endpoint { +- remote-endpoint = <&csi2_40_ep>; +- }; +- }; +- port@2 { +- vin2_max9286_des0ep2: endpoint@0 { +- remote-endpoint = <&max9286_des0ep2>; +- }; +- }; +- }; +-}; +- +-&vin3 { +- status = "okay"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@0 { +- vin3ep0: endpoint { +- csi,select = "csi40"; +- virtual,channel = <3>; +- data-lanes = <1 2 3 4>; +- remote-endpoint = <&ov106xx_in3>; +- }; +- }; +- port@1 { +- csi0ep3: endpoint { +- remote-endpoint = <&csi2_40_ep>; +- }; +- }; +- port@2 { +- vin3_max9286_des0ep3: endpoint@0 { +- remote-endpoint = <&max9286_des0ep3>; +- }; +- }; +- }; +-}; +- + &du { + status = "okay"; + }; +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +index 2b614e4..8eac8ca 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +@@ -27,46 +27,6 @@ + reg = <0x0 0x48000000 0x0 0x38000000>; + }; + +- reserved-memory { +- #address-cells = <2>; +- #size-cells = <2>; +- ranges; +- +- /* device specific region for Lossy Decompression */ +- lossy_decompress: linux,lossy_decompress { +- no-map; +- reg = <0x00000000 0x6c000000 0x0 0x03000000>; +- }; +- +- /* global autoconfigured region for contiguous allocations */ +- linux,cma { +- compatible = "shared-dma-pool"; +- reusable; +- reg = <0x00000000 0x6f000000 0x0 0x10000000>; +- linux,cma-default; +- }; +- +- /* device specific region for contiguous allocations */ +- linux,multimedia { +- compatible = "shared-dma-pool"; +- reusable; +- reg = <0x00000000 0x7f000000 0x0 0x01000000>; +- }; +- }; +- +- mmngr { +- compatible = "renesas,mmngr"; +- memory-region = <&lossy_decompress>; +- }; +- +- mmngrbuf { +- compatible = "renesas,mmngrbuf"; +- }; +- +- vspm_if { +- compatible = "renesas,vspm_if"; +- }; +- + osc5_clk: osc5-clock { + compatible = "fixed-clock"; + #clock-cells = <0>; +@@ -218,37 +178,6 @@ + }; + }; + }; +- +- pmic@5A { +- compatible = "dlg,da9063"; +- reg = <0x5A>; +- interrupt-parent = <&intc_ex>; +- interrupts = <0 IRQ_TYPE_LEVEL_LOW>; +- interrupt-controller; +- +- rtc { +- compatible = "dlg,da9063-rtc"; +- }; +- +- wdt { +- compatible = "dlg,da9063-watchdog"; +- }; +- +- regulators { +- DA9063_LDO11: bmem { +- regulator-name = "bmem"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- regulator-always-on; +- regulator-boot-on; +- }; +- }; +- +- onkey { +- compatible = "dlg,da9063-onkey"; +- }; +- }; +- + }; + + &lvds0 { +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +index e270cc0..0b93a7d 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +@@ -28,46 +28,6 @@ + reg = <0 0x48000000 0 0x78000000>; + }; + +- reserved-memory { +- #address-cells = <2>; +- #size-cells = <2>; +- ranges; +- +- /* device specific region for Lossy Decompression */ +- lossy_decompress: linux,lossy_decompress { +- no-map; +- reg = <0x00000000 0x6c000000 0x0 0x03000000>; +- }; +- +- /* global autoconfigured region for contiguous allocations */ +- linux,cma { +- compatible = "shared-dma-pool"; +- reusable; +- reg = <0x00000000 0x6f000000 0x0 0x10000000>; +- linux,cma-default; +- }; +- +- /* device specific region for contiguous allocations */ +- linux,multimedia { +- compatible = "shared-dma-pool"; +- reusable; +- reg = <0x00000000 0x7f000000 0x0 0x01000000>; +- }; +- }; +- +- mmngr { +- compatible = "renesas,mmngr"; +- memory-region = <&lossy_decompress>; +- }; +- +- mmngrbuf { +- compatible = "renesas,mmngrbuf"; +- }; +- +- vspm_if { +- compatible = "renesas,vspm_if"; +- }; +- + d3_3v: regulator-0 { + compatible = "regulator-fixed"; + regulator-name = "D3.3V"; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +index dff7d02..c968099 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +@@ -26,47 +26,6 @@ + /* first 128MB is reserved for secure area. */ + reg = <0 0x48000000 0 0x78000000>; + }; +- +- reserved-memory { +- #address-cells = <2>; +- #size-cells = <2>; +- ranges; +- +- /* device specific region for Lossy Decompression */ +- lossy_decompress: linux,lossy_decompress { +- no-map; +- reg = <0x00000000 0x6c000000 0x0 0x03000000>; +- }; +- +- /* global autoconfigured region for contiguous allocations */ +- linux,cma { +- compatible = "shared-dma-pool"; +- reusable; +- reg = <0x00000000 0x6f000000 0x0 0x10000000>; +- linux,cma-default; +- }; +- +- /* device specific region for contiguous allocations */ +- linux,multimedia { +- compatible = "shared-dma-pool"; +- reusable; +- reg = <0x00000000 0x7f000000 0x0 0x01000000>; +- }; +- }; +- +- mmngr { +- compatible = "renesas,mmngr"; +- memory-region = <&lossy_decompress>; +- }; +- +- mmngrbuf { +- compatible = "renesas,mmngrbuf"; +- }; +- +- vspm_if { +- compatible = "renesas,vspm_if"; +- }; +- + }; + + &extal_clk { +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0182-iommu-msm-Claim-bus-ops-on-probe.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0182-iommu-msm-Claim-bus-ops-on-probe.patch new file mode 100644 index 00000000..5f2f7e29 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0182-iommu-msm-Claim-bus-ops-on-probe.patch @@ -0,0 +1,58 @@ +From feb15c008da506989868369195e3982ff8131fcd Mon Sep 17 00:00:00 2001 +From: Robin Murphy +Date: Tue, 9 Jan 2018 16:17:25 +0000 +Subject: [PATCH 002/211] iommu/msm: Claim bus ops on probe + +Since the MSM IOMMU driver now probes via DT exclusively rather than +platform data, dependent masters should be deferred until the IOMMU +itself is ready. Thus we can do away with the early initialisation +hook to unconditionally claim the bus ops, and instead do that only +once an IOMMU is actually probed. Furthermore, this should also make +the driver safe for multiplatform kernels on non-MSM SoCs. + +Reviewed-by: Sricharan R +Signed-off-by: Robin Murphy +Signed-off-by: Joerg Roedel +(cherry picked from commit 892d7aaddb24b0d3eaf05534ed29a264d3b52646) +Signed-off-by: Valentine Barshak +--- + drivers/iommu/msm_iommu.c | 16 +++------------- + 1 file changed, 3 insertions(+), 13 deletions(-) + +diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c +index 92c8c83..350ed3d 100644 +--- a/drivers/iommu/msm_iommu.c ++++ b/drivers/iommu/msm_iommu.c +@@ -817,6 +817,8 @@ static int msm_iommu_probe(struct platform_device *pdev) + goto fail; + } + ++ bus_set_iommu(&platform_bus_type, &msm_iommu_ops); ++ + pr_info("device mapped at %p, irq %d with %d ctx banks\n", + iommu->base, iommu->irq, iommu->ncb); + +@@ -869,19 +871,7 @@ static void __exit msm_iommu_driver_exit(void) + subsys_initcall(msm_iommu_driver_init); + module_exit(msm_iommu_driver_exit); + +-static int __init msm_iommu_init(void) +-{ +- bus_set_iommu(&platform_bus_type, &msm_iommu_ops); +- return 0; +-} +- +-static int __init msm_iommu_of_setup(struct device_node *np) +-{ +- msm_iommu_init(); +- return 0; +-} +- +-IOMMU_OF_DECLARE(msm_iommu_of, "qcom,apq8064-iommu", msm_iommu_of_setup); ++IOMMU_OF_DECLARE(msm_iommu_of, "qcom,apq8064-iommu", NULL); + + MODULE_LICENSE("GPL v2"); + MODULE_AUTHOR("Stepan Moskovchenko "); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0183-iommu-Clean-up-of_iommu_init_fn.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0183-iommu-Clean-up-of_iommu_init_fn.patch new file mode 100644 index 00000000..9afb101f --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0183-iommu-Clean-up-of_iommu_init_fn.patch @@ -0,0 +1,163 @@ +From 4badb868e01d346cd749536f8059d0972d3e258f Mon Sep 17 00:00:00 2001 +From: Robin Murphy +Date: Tue, 9 Jan 2018 16:17:27 +0000 +Subject: [PATCH 003/211] iommu: Clean up of_iommu_init_fn + +Now that no more drivers rely on arbitrary early initialisation via an +of_iommu_init_fn hook, let's clean up the redundant remnants. The +IOMMU_OF_DECLARE() macro needs to remain for now, as the probe-deferral +mechanism has no other nice way to detect built-in drivers before they +have registered themselves, such that it can make the right decision. + +Reviewed-by: Sricharan R +Signed-off-by: Robin Murphy +Signed-off-by: Joerg Roedel +(cherry picked from commit b0c560f7d8a4b333bcc18f692d0af0d5cca90fe2) +[valentine.barshak: resolved minor conflicts] +Signed-off-by: Valentine Barshak +--- + drivers/iommu/arm-smmu-v3.c | 2 +- + drivers/iommu/arm-smmu.c | 12 ++++++------ + drivers/iommu/exynos-iommu.c | 2 +- + drivers/iommu/ipmmu-vmsa.c | 10 +++++----- + drivers/iommu/msm_iommu.c | 2 +- + drivers/iommu/of_iommu.c | 16 ---------------- + drivers/iommu/qcom_iommu.c | 2 +- + include/linux/of_iommu.h | 5 +---- + 8 files changed, 16 insertions(+), 35 deletions(-) + +diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c +index 3d5851e..fb4e621 100644 +--- a/drivers/iommu/arm-smmu-v3.c ++++ b/drivers/iommu/arm-smmu-v3.c +@@ -2898,7 +2898,7 @@ static struct platform_driver arm_smmu_driver = { + }; + module_platform_driver(arm_smmu_driver); + +-IOMMU_OF_DECLARE(arm_smmuv3, "arm,smmu-v3", NULL); ++IOMMU_OF_DECLARE(arm_smmuv3, "arm,smmu-v3"); + + MODULE_DESCRIPTION("IOMMU API for ARM architected SMMUv3 implementations"); + MODULE_AUTHOR("Will Deacon "); +diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c +index 335bcc1..21a0eb3 100644 +--- a/drivers/iommu/arm-smmu.c ++++ b/drivers/iommu/arm-smmu.c +@@ -2222,12 +2222,12 @@ static struct platform_driver arm_smmu_driver = { + }; + module_platform_driver(arm_smmu_driver); + +-IOMMU_OF_DECLARE(arm_smmuv1, "arm,smmu-v1", NULL); +-IOMMU_OF_DECLARE(arm_smmuv2, "arm,smmu-v2", NULL); +-IOMMU_OF_DECLARE(arm_mmu400, "arm,mmu-400", NULL); +-IOMMU_OF_DECLARE(arm_mmu401, "arm,mmu-401", NULL); +-IOMMU_OF_DECLARE(arm_mmu500, "arm,mmu-500", NULL); +-IOMMU_OF_DECLARE(cavium_smmuv2, "cavium,smmu-v2", NULL); ++IOMMU_OF_DECLARE(arm_smmuv1, "arm,smmu-v1"); ++IOMMU_OF_DECLARE(arm_smmuv2, "arm,smmu-v2"); ++IOMMU_OF_DECLARE(arm_mmu400, "arm,mmu-400"); ++IOMMU_OF_DECLARE(arm_mmu401, "arm,mmu-401"); ++IOMMU_OF_DECLARE(arm_mmu500, "arm,mmu-500"); ++IOMMU_OF_DECLARE(cavium_smmuv2, "cavium,smmu-v2"); + + MODULE_DESCRIPTION("IOMMU API for ARM architected SMMU implementations"); + MODULE_AUTHOR("Will Deacon "); +diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c +index 13485a4..1fcb618 100644 +--- a/drivers/iommu/exynos-iommu.c ++++ b/drivers/iommu/exynos-iommu.c +@@ -1392,4 +1392,4 @@ static int __init exynos_iommu_init(void) + } + core_initcall(exynos_iommu_init); + +-IOMMU_OF_DECLARE(exynos_iommu_of, "samsung,exynos-sysmmu", NULL); ++IOMMU_OF_DECLARE(exynos_iommu_of, "samsung,exynos-sysmmu"); +diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c +index e1aabb7..8b4e5d9 100644 +--- a/drivers/iommu/ipmmu-vmsa.c ++++ b/drivers/iommu/ipmmu-vmsa.c +@@ -1853,11 +1853,11 @@ static void __exit ipmmu_exit(void) + subsys_initcall(ipmmu_init); + module_exit(ipmmu_exit); + +-IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa", NULL); +-IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795", NULL); +-IOMMU_OF_DECLARE(ipmmu_r8a7796_iommu_of, "renesas,ipmmu-r8a7796", NULL); +-IOMMU_OF_DECLARE(ipmmu_r8a77965_iommu_of, "renesas,ipmmu-r8a77965", NULL); +-IOMMU_OF_DECLARE(ipmmu_r8a77990_iommu_of, "renesas,ipmmu-r8a77990", NULL); ++IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa"); ++IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795"); ++IOMMU_OF_DECLARE(ipmmu_r8a7796_iommu_of, "renesas,ipmmu-r8a7796"); ++IOMMU_OF_DECLARE(ipmmu_r8a77965_iommu_of, "renesas,ipmmu-r8a77965"); ++IOMMU_OF_DECLARE(ipmmu_r8a77990_iommu_of, "renesas,ipmmu-r8a77990"); + + MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU"); + MODULE_AUTHOR("Laurent Pinchart "); +diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c +index 350ed3d..9a95c9b 100644 +--- a/drivers/iommu/msm_iommu.c ++++ b/drivers/iommu/msm_iommu.c +@@ -871,7 +871,7 @@ static void __exit msm_iommu_driver_exit(void) + subsys_initcall(msm_iommu_driver_init); + module_exit(msm_iommu_driver_exit); + +-IOMMU_OF_DECLARE(msm_iommu_of, "qcom,apq8064-iommu", NULL); ++IOMMU_OF_DECLARE(msm_iommu_of, "qcom,apq8064-iommu"); + + MODULE_LICENSE("GPL v2"); + MODULE_AUTHOR("Stepan Moskovchenko "); +diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c +index 50947eb..5c36a8b 100644 +--- a/drivers/iommu/of_iommu.c ++++ b/drivers/iommu/of_iommu.c +@@ -231,19 +231,3 @@ const struct iommu_ops *of_iommu_configure(struct device *dev, + + return ops; + } +- +-static int __init of_iommu_init(void) +-{ +- struct device_node *np; +- const struct of_device_id *match, *matches = &__iommu_of_table; +- +- for_each_matching_node_and_match(np, matches, &match) { +- const of_iommu_init_fn init_fn = match->data; +- +- if (init_fn && init_fn(np)) +- pr_err("Failed to initialise IOMMU %pOF\n", np); +- } +- +- return 0; +-} +-postcore_initcall_sync(of_iommu_init); +diff --git a/drivers/iommu/qcom_iommu.c b/drivers/iommu/qcom_iommu.c +index c8a587d..37ecc49 100644 +--- a/drivers/iommu/qcom_iommu.c ++++ b/drivers/iommu/qcom_iommu.c +@@ -924,7 +924,7 @@ static void __exit qcom_iommu_exit(void) + module_init(qcom_iommu_init); + module_exit(qcom_iommu_exit); + +-IOMMU_OF_DECLARE(qcom_iommu_dev, "qcom,msm-iommu-v1", NULL); ++IOMMU_OF_DECLARE(qcom_iommu_dev, "qcom,msm-iommu-v1"); + + MODULE_DESCRIPTION("IOMMU API for QCOM IOMMU v1 implementations"); + MODULE_LICENSE("GPL v2"); +diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h +index cddfaff..4fa654e 100644 +--- a/include/linux/of_iommu.h ++++ b/include/linux/of_iommu.h +@@ -34,9 +34,6 @@ static inline const struct iommu_ops *of_iommu_configure(struct device *dev, + + extern struct of_device_id __iommu_of_table; + +-typedef int (*of_iommu_init_fn)(struct device_node *); +- +-#define IOMMU_OF_DECLARE(name, compat, fn) \ +- _OF_DECLARE(iommu, name, compat, fn, of_iommu_init_fn) ++#define IOMMU_OF_DECLARE(name, compat) OF_DECLARE_1(iommu, name, compat, NULL) + + #endif /* __OF_IOMMU_H */ +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0184-iommu-ipmmu-vmsa-Hook-up-r8a779-70-95-DT-matching-co.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0184-iommu-ipmmu-vmsa-Hook-up-r8a779-70-95-DT-matching-co.patch new file mode 100644 index 00000000..31888216 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0184-iommu-ipmmu-vmsa-Hook-up-r8a779-70-95-DT-matching-co.patch @@ -0,0 +1,67 @@ +From 3f6395b17673c4fda770651c1d657457741ee65a Mon Sep 17 00:00:00 2001 +From: Simon Horman +Date: Thu, 14 Jun 2018 12:48:23 +0200 +Subject: [PATCH 004/211] iommu/ipmmu-vmsa: Hook up r8a779(70|95) DT matching + code + +Support the r8a77970 (R-Car V3M) and r8a77995 (R-Car D3) IPMMUs by sharing +feature flags with r8a7795 (R-Car H3) and r8a7796 (R-Car M3-W). Also update +IOMMU_OF_DECLARE to hook up the compat strings. + +Based on work for the r8a7796 by Magnus Damm + +[rebased on v4.17] +Signed-off-by: Jacopo Mondi +Signed-off-by: Simon Horman +Reviewed-by: Geert Uytterhoeven +Signed-off-by: Joerg Roedel +(cherry picked from commit 3701c123e1c13cdf258e10b26df7ae4bef6a5a93) +[valentine.barshak: resolved minor confilicts] +Signed-off-by: Valentine Barshak +--- + drivers/iommu/ipmmu-vmsa.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c +index 8b4e5d9..5844dc7 100644 +--- a/drivers/iommu/ipmmu-vmsa.c ++++ b/drivers/iommu/ipmmu-vmsa.c +@@ -1122,7 +1122,9 @@ static const struct soc_device_attribute soc_rcar_gen3[] = { + { .soc_id = "r8a7795", }, + { .soc_id = "r8a7796", }, + { .soc_id = "r8a77965", }, ++ { .soc_id = "r8a77970", }, + { .soc_id = "r8a77990", }, ++ { .soc_id = "r8a77995", }, + { /* sentinel */ } + }; + +@@ -1421,9 +1423,15 @@ static const struct of_device_id ipmmu_of_ids[] = { + .compatible = "renesas,ipmmu-r8a77965", + .data = &ipmmu_features_rcar_gen3, + }, { ++ .compatible = "renesas,ipmmu-r8a77970", ++ .data = &ipmmu_features_rcar_gen3, ++ }, { + .compatible = "renesas,ipmmu-r8a77990", + .data = &ipmmu_features_rcar_gen3, + }, { ++ .compatible = "renesas,ipmmu-r8a77995", ++ .data = &ipmmu_features_rcar_gen3, ++ }, { + /* Terminator */ + }, + }; +@@ -1857,7 +1865,9 @@ IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa"); + IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795"); + IOMMU_OF_DECLARE(ipmmu_r8a7796_iommu_of, "renesas,ipmmu-r8a7796"); + IOMMU_OF_DECLARE(ipmmu_r8a77965_iommu_of, "renesas,ipmmu-r8a77965"); ++IOMMU_OF_DECLARE(ipmmu_r8a77970_iommu_of, "renesas,ipmmu-r8a77970"); + IOMMU_OF_DECLARE(ipmmu_r8a77990_iommu_of, "renesas,ipmmu-r8a77990"); ++IOMMU_OF_DECLARE(ipmmu_r8a77995_iommu_of, "renesas,ipmmu-r8a77995"); + + MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU"); + MODULE_AUTHOR("Laurent Pinchart "); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0185-dt-bindings-display-bridge-Document-THC63LVD1024-LVD.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0185-dt-bindings-display-bridge-Document-THC63LVD1024-LVD.patch new file mode 100644 index 00000000..ddd19e33 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0185-dt-bindings-display-bridge-Document-THC63LVD1024-LVD.patch @@ -0,0 +1,96 @@ +From 339c404b36bb8461c63c36b4ade4c5cad9ac345d Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Wed, 18 Apr 2018 16:40:28 +0200 +Subject: [PATCH 005/211] dt-bindings: display: bridge: Document THC63LVD1024 + LVDS decoder +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Document Thine THC63LVD1024 LVDS decoder device tree bindings. + +Signed-off-by: Jacopo Mondi +Reviewed-by: Andrzej Hajda +Reviewed-by: Niklas Söderlund +Reviewed-by: Laurent Pinchart +Reviewed-by: Rob Herring +Reviewed-by: Vladimir Zapolskiy +Signed-off-by: Andrzej Hajda +Link: https://patchwork.freedesktop.org/patch/msgid/1524062429-325-2-git-send-email-jacopo+renesas@jmondi.org +Link: https://patchwork.freedesktop.org/patch/msgid/1524062429-325-2-git-send-email-jacopo+renesas@jmondi.org +(cherry picked from commit f2ce15c72ae8aae06ba22b23f90ccc7d5b5e087c) +Signed-off-by: Valentine Barshak +--- + .../bindings/display/bridge/thine,thc63lvd1024.txt | 60 ++++++++++++++++++++++ + 1 file changed, 60 insertions(+) + create mode 100644 Documentation/devicetree/bindings/display/bridge/thine,thc63lvd1024.txt + +diff --git a/Documentation/devicetree/bindings/display/bridge/thine,thc63lvd1024.txt b/Documentation/devicetree/bindings/display/bridge/thine,thc63lvd1024.txt +new file mode 100644 +index 0000000..37f0c04 +--- /dev/null ++++ b/Documentation/devicetree/bindings/display/bridge/thine,thc63lvd1024.txt +@@ -0,0 +1,60 @@ ++Thine Electronics THC63LVD1024 LVDS decoder ++------------------------------------------- ++ ++The THC63LVD1024 is a dual link LVDS receiver designed to convert LVDS streams ++to parallel data outputs. The chip supports single/dual input/output modes, ++handling up to two LVDS input streams and up to two digital CMOS/TTL outputs. ++ ++Single or dual operation mode, output data mapping and DDR output modes are ++configured through input signals and the chip does not expose any control bus. ++ ++Required properties: ++- compatible: Shall be "thine,thc63lvd1024" ++- vcc-supply: Power supply for TTL output, TTL CLOCKOUT signal, LVDS input, ++ PPL and digital circuitry ++ ++Optional properties: ++- powerdown-gpios: Power down GPIO signal, pin name "/PDWN". Active low ++- oe-gpios: Output enable GPIO signal, pin name "OE". Active high ++ ++The THC63LVD1024 video port connections are modeled according ++to OF graph bindings specified by Documentation/devicetree/bindings/graph.txt ++ ++Required video port nodes: ++- port@0: First LVDS input port ++- port@2: First digital CMOS/TTL parallel output ++ ++Optional video port nodes: ++- port@1: Second LVDS input port ++- port@3: Second digital CMOS/TTL parallel output ++ ++Example: ++-------- ++ ++ thc63lvd1024: lvds-decoder { ++ compatible = "thine,thc63lvd1024"; ++ ++ vcc-supply = <®_lvds_vcc>; ++ powerdown-gpios = <&gpio4 15 GPIO_ACTIVE_LOW>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ ++ lvds_dec_in_0: endpoint { ++ remote-endpoint = <&lvds_out>; ++ }; ++ }; ++ ++ port@2{ ++ reg = <2>; ++ ++ lvds_dec_out_2: endpoint { ++ remote-endpoint = <&adv7511_in>; ++ }; ++ }; ++ }; ++ }; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0186-gpio-rcar-document-R8A77980-bindings.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0186-gpio-rcar-document-R8A77980-bindings.patch new file mode 100644 index 00000000..29276275 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0186-gpio-rcar-document-R8A77980-bindings.patch @@ -0,0 +1,32 @@ +From 47127037672bd4cafe38cc2984fb10b2edbfdb90 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Fri, 1 Jun 2018 23:13:47 +0300 +Subject: [PATCH 006/211] gpio-rcar: document R8A77980 bindings + +Renesas R-Car V3H (R8A77980) SoC also has the R-Car gen3 compatible GPIO +controllers, so document the SoC specific bindings. + +Signed-off-by: Sergei Shtylyov +Reviewed-by: Geert Uytterhoeven +Signed-off-by: Linus Walleij +(cherry picked from commit 29d43c22e480b150e00f1ac28a6653efca31cce4) +Signed-off-by: Valentine Barshak +--- + Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt b/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt +index 378f132..cd5ccdc 100644 +--- a/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt ++++ b/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt +@@ -17,6 +17,7 @@ Required Properties: + - "renesas,gpio-r8a7796": for R8A7796 (R-Car M3-W) compatible GPIO controller. + - "renesas,gpio-r8a77965": for R8A77965 (R-Car M3-N) compatible GPIO controller. + - "renesas,gpio-r8a77970": for R8A77970 (R-Car V3M) compatible GPIO controller. ++ - "renesas,gpio-r8a77980": for R8A77980 (R-Car V3H) compatible GPIO controller. + - "renesas,gpio-r8a77990": for R8A77990 (R-Car E3) compatible GPIO controller. + - "renesas,gpio-r8a77995": for R8A77995 (R-Car D3) compatible GPIO controller. + - "renesas,rcar-gen1-gpio": for a generic R-Car Gen1 GPIO controller. +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0187-arm64-dts-renesas-r8a77980-add-SMP-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0187-arm64-dts-renesas-r8a77980-add-SMP-support.patch new file mode 100644 index 00000000..6a6e4b03 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0187-arm64-dts-renesas-r8a77980-add-SMP-support.patch @@ -0,0 +1,93 @@ +From e5c859035c3fd62ef27f14ec34a4dc0a2d736eff Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Thu, 17 May 2018 23:19:44 +0300 +Subject: [PATCH 007/211] arm64: dts: renesas: r8a77980: add SMP support + +Add the device nodes for 3 more Cortex-A53 CPU cores; adjust the interrupt +delivery masks for the ARM GIC and Architectured Timer. + +Based on the original (and large) patch by Vladimir Barinov. + +Signed-off-by: Vladimir Barinov +Signed-off-by: Sergei Shtylyov +Reviewed-by: Geert Uytterhoeven +[simon: corrected whitespace] +Signed-off-by: Simon Horman + +(cherry picked from commit 2ec1e4b4a815ee872fb29753f4872abf1a2e62a4) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 40 +++++++++++++++++++++++++++---- + 1 file changed, 35 insertions(+), 5 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index 8ecda23..1920b86 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -30,6 +30,36 @@ + enable-method = "psci"; + }; + ++ a53_1: cpu@1 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a53", "arm,armv8"; ++ reg = <1>; ++ clocks = <&cpg CPG_CORE R8A77980_CLK_Z2>; ++ power-domains = <&sysc R8A77980_PD_CA53_CPU1>; ++ next-level-cache = <&L2_CA53>; ++ enable-method = "psci"; ++ }; ++ ++ a53_2: cpu@2 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a53", "arm,armv8"; ++ reg = <2>; ++ clocks = <&cpg CPG_CORE R8A77980_CLK_Z2>; ++ power-domains = <&sysc R8A77980_PD_CA53_CPU2>; ++ next-level-cache = <&L2_CA53>; ++ enable-method = "psci"; ++ }; ++ ++ a53_3: cpu@3 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a53", "arm,armv8"; ++ reg = <3>; ++ clocks = <&cpg CPG_CORE R8A77980_CLK_Z2>; ++ power-domains = <&sysc R8A77980_PD_CA53_CPU3>; ++ next-level-cache = <&L2_CA53>; ++ enable-method = "psci"; ++ }; ++ + L2_CA53: cache-controller { + compatible = "cache"; + power-domains = <&sysc R8A77980_PD_CA53_SCU>; +@@ -471,7 +501,7 @@ + <0x0 0xf1020000 0 0x20000>, + <0x0 0xf1040000 0 0x20000>, + <0x0 0xf1060000 0 0x20000>; +- interrupts = ; + clocks = <&cpg CPG_MOD 408>; + clock-names = "clk"; +@@ -487,13 +517,13 @@ + + timer { + compatible = "arm,armv8-timer"; +- interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(1) | ++ interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | + IRQ_TYPE_LEVEL_LOW)>, +- <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(1) | ++ <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | + IRQ_TYPE_LEVEL_LOW)>, +- <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(1) | ++ <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | + IRQ_TYPE_LEVEL_LOW)>, +- <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(1) | ++ <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | + IRQ_TYPE_LEVEL_LOW)>; + }; + }; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0188-arm64-dts-renesas-r8a77980-add-GEther-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0188-arm64-dts-renesas-r8a77980-add-GEther-support.patch new file mode 100644 index 00000000..a45e49ab --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0188-arm64-dts-renesas-r8a77980-add-GEther-support.patch @@ -0,0 +1,47 @@ +From a58a7ac394a82da1eec426fa9c016f686bb1767e Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Fri, 18 May 2018 22:45:36 +0300 +Subject: [PATCH 008/211] arm64: dts: renesas: r8a77980: add GEther support + +Define the generic R8A77980 part of the GEther device node. + +Based on the original (and large) patch by Vladimir Barinov. + +Signed-off-by: Vladimir Barinov +Signed-off-by: Sergei Shtylyov +Reviewed-by: Geert Uytterhoeven +[simon: add resets property] +Signed-off-by: Simon Horman + +(cherry picked from commit 87bea6780b952dac7f58ed2395d2eaa434deb0fb) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index 1920b86..188f7e7 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -480,6 +480,18 @@ + dma-channels = <16>; + }; + ++ gether: ethernet@e7400000 { ++ compatible = "renesas,gether-r8a77980"; ++ reg = <0 0xe7400000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 813>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 813>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ + mmc0: mmc@ee140000 { + compatible = "renesas,sdhi-r8a77980", + "renesas,rcar-gen3-sdhi"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0189-arm64-dts-renesas-v3hsk-add-GEther-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0189-arm64-dts-renesas-v3hsk-add-GEther-support.patch new file mode 100644 index 00000000..c79bd5d1 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0189-arm64-dts-renesas-v3hsk-add-GEther-support.patch @@ -0,0 +1,61 @@ +From feb40ba2154f898c74cad79f0f2f2a5112645782 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Fri, 18 May 2018 22:46:19 +0300 +Subject: [PATCH 009/211] arm64: dts: renesas: v3hsk: add GEther support + +Define the V3H Starter Kit board dependent part of the GEther device node. + +Based on the original (and large) patch by Vladimir Barinov. + +Signed-off-by: Vladimir Barinov +Signed-off-by: Sergei Shtylyov +Signed-off-by: Simon Horman +(cherry picked from commit c0f91cac37df2d6b7f2d6692552a2f16099f7755) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +index c968099..bb7e0e5 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +@@ -15,6 +15,7 @@ + + aliases { + serial0 = &scif0; ++ ethernet0 = &gether; + }; + + chosen { +@@ -36,7 +37,27 @@ + clock-frequency = <32768>; + }; + ++&gether { ++ pinctrl-0 = <&gether_pins>; ++ pinctrl-names = "default"; ++ ++ phy-mode = "rgmii"; ++ phy-handle = <&phy0>; ++ renesas,no-ether-link; ++ status = "okay"; ++ ++ phy0: ethernet-phy@0 { ++ reg = <0>; ++ }; ++}; ++ + &pfc { ++ gether_pins: gether { ++ groups = "gether_mdio_a", "gether_rgmii", ++ "gether_txcrefclk", "gether_txcrefclk_mega"; ++ function = "gether"; ++ }; ++ + scif0_pins: scif0 { + groups = "scif0_data"; + function = "scif0"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0190-arm64-dts-renesas-r8a77980-add-I2C-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0190-arm64-dts-renesas-r8a77980-add-I2C-support.patch new file mode 100644 index 00000000..1e617858 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0190-arm64-dts-renesas-r8a77980-add-I2C-support.patch @@ -0,0 +1,145 @@ +From 4d71784469e02f168c85262b1703f840a9f9da23 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Thu, 31 May 2018 23:22:39 +0300 +Subject: [PATCH 010/211] arm64: dts: renesas: r8a77980: add I2C support + +Define the generic R8A77980 parts of the I2C[0-5] device nodes. + +Based on the original (and large) patch by Vladimir Barinov. + +Signed-off-by: Vladimir Barinov +Signed-off-by: Sergei Shtylyov +Reviewed-by: Geert Uytterhoeven +Signed-off-by: Simon Horman +(cherry picked from commit bc620474c6e283c0e1e60796ed0ac9b04da9890c) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 105 ++++++++++++++++++++++++++++++ + 1 file changed, 105 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index 188f7e7..15dde72 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -16,6 +16,15 @@ + #address-cells = <2>; + #size-cells = <2>; + ++ aliases { ++ i2c0 = &i2c0; ++ i2c1 = &i2c1; ++ i2c2 = &i2c2; ++ i2c3 = &i2c3; ++ i2c4 = &i2c4; ++ i2c5 = &i2c5; ++ }; ++ + cpus { + #address-cells = <1>; + #size-cells = <0>; +@@ -135,6 +144,102 @@ + #power-domain-cells = <1>; + }; + ++ i2c0: i2c@e6500000 { ++ compatible = "renesas,i2c-r8a77980", ++ "renesas,rcar-gen3-i2c"; ++ reg = <0 0xe6500000 0 0x40>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 931>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 931>; ++ dmas = <&dmac1 0x91>, <&dmac1 0x90>, ++ <&dmac2 0x91>, <&dmac2 0x90>; ++ dma-names = "tx", "rx", "tx", "rx"; ++ i2c-scl-internal-delay-ns = <6>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c1: i2c@e6508000 { ++ compatible = "renesas,i2c-r8a77980", ++ "renesas,rcar-gen3-i2c"; ++ reg = <0 0xe6508000 0 0x40>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 930>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 930>; ++ dmas = <&dmac1 0x93>, <&dmac1 0x92>, ++ <&dmac2 0x93>, <&dmac2 0x92>; ++ dma-names = "tx", "rx", "tx", "rx"; ++ i2c-scl-internal-delay-ns = <6>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c2: i2c@e6510000 { ++ compatible = "renesas,i2c-r8a77980", ++ "renesas,rcar-gen3-i2c"; ++ reg = <0 0xe6510000 0 0x40>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 929>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 929>; ++ dmas = <&dmac1 0x95>, <&dmac1 0x94>, ++ <&dmac2 0x95>, <&dmac2 0x94>; ++ dma-names = "tx", "rx", "tx", "rx"; ++ i2c-scl-internal-delay-ns = <6>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c3: i2c@e66d0000 { ++ compatible = "renesas,i2c-r8a77980", ++ "renesas,rcar-gen3-i2c"; ++ reg = <0 0xe66d0000 0 0x40>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 928>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 928>; ++ i2c-scl-internal-delay-ns = <6>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c4: i2c@e66d8000 { ++ compatible = "renesas,i2c-r8a77980", ++ "renesas,rcar-gen3-i2c"; ++ reg = <0 0xe66d8000 0 0x40>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 927>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 927>; ++ i2c-scl-internal-delay-ns = <6>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c5: i2c@e66e0000 { ++ compatible = "renesas,i2c-r8a77980", ++ "renesas,rcar-gen3-i2c"; ++ reg = <0 0xe66e0000 0 0x40>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 919>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 919>; ++ dmas = <&dmac1 0x9b>, <&dmac1 0x9a>, ++ <&dmac2 0x9b>, <&dmac2 0x9a>; ++ dma-names = "tx", "rx", "tx", "rx"; ++ i2c-scl-internal-delay-ns = <6>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ + hscif0: serial@e6540000 { + compatible = "renesas,hscif-r8a77980", + "renesas,rcar-gen3-hscif", +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0191-arm64-dts-renesas-condor-add-I2C0-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0191-arm64-dts-renesas-condor-add-I2C0-support.patch new file mode 100644 index 00000000..443bdac4 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0191-arm64-dts-renesas-condor-add-I2C0-support.patch @@ -0,0 +1,67 @@ +From ef4b9080dc83f007f2b767d9176bae80d005b75c Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Thu, 31 May 2018 23:26:49 +0300 +Subject: [PATCH 011/211] arm64: dts: renesas: condor: add I2C0 support + +Define the Condor board dependent part of the I2C0 device node. + +The I2C0 bus is populated by 2 ON Semiconductor PCA9654 I/O expanders +and Analog Devices ADV7511W HDMI transmitter (but we're only describing +the former chips now). + +Signed-off-by: Sergei Shtylyov +Signed-off-by: Simon Horman +(cherry picked from commit 45fde0d498dc77e5fc221960843fa377e0c70822) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980-condor.dts | 27 +++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +index 0b93a7d..cc3ee25 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +@@ -80,6 +80,28 @@ + clock-frequency = <32768>; + }; + ++&i2c0 { ++ pinctrl-0 = <&i2c0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ clock-frequency = <400000>; ++ ++ io_expander0: gpio@20 { ++ compatible = "onnn,pca9654"; ++ reg = <0x20>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ }; ++ ++ io_expander1: gpio@21 { ++ compatible = "onnn,pca9654"; ++ reg = <0x21>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ }; ++}; ++ + &mmc0 { + pinctrl-0 = <&mmc_pins>; + pinctrl-1 = <&mmc_pins_uhs>; +@@ -104,6 +126,11 @@ + function = "canfd0"; + }; + ++ i2c0_pins: i2c0 { ++ groups = "i2c0"; ++ function = "i2c0"; ++ }; ++ + mmc_pins: mmc { + groups = "mmc_data8", "mmc_ctrl", "mmc_ds"; + function = "mmc"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0192-arm64-dts-renesas-r8a77980-add-GPIO-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0192-arm64-dts-renesas-r8a77980-add-GPIO-support.patch new file mode 100644 index 00000000..0edfd83c --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0192-arm64-dts-renesas-r8a77980-add-GPIO-support.patch @@ -0,0 +1,123 @@ +From fdda1aa294ce0aa67f2966a2f7192f10a7220ce4 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Fri, 1 Jun 2018 23:44:46 +0300 +Subject: [PATCH 012/211] arm64: dts: renesas: r8a77980: add GPIO support + +Describe all 6 GPIO controllers in the R8A77980 device tree. + +Based on the original (and large) patch by Vladimir Barinov. + +Signed-off-by: Vladimir Barinov +Signed-off-by: Sergei Shtylyov +Reviewed-by: Geert Uytterhoeven +Signed-off-by: Simon Horman +(cherry picked from commit efcb52e35d162dc9104be56492b65049a17dc6a4) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 90 +++++++++++++++++++++++++++++++ + 1 file changed, 90 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index 15dde72..682a782 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -118,6 +118,96 @@ + #size-cells = <2>; + ranges; + ++ gpio0: gpio@e6050000 { ++ compatible = "renesas,gpio-r8a77980", ++ "renesas,rcar-gen3-gpio"; ++ reg = <0 0xe6050000 0 0x50>; ++ interrupts = ; ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 0 22>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 912>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 912>; ++ }; ++ ++ gpio1: gpio@e6051000 { ++ compatible = "renesas,gpio-r8a77980", ++ "renesas,rcar-gen3-gpio"; ++ reg = <0 0xe6051000 0 0x50>; ++ interrupts = ; ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 32 28>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 911>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 911>; ++ }; ++ ++ gpio2: gpio@e6052000 { ++ compatible = "renesas,gpio-r8a77980", ++ "renesas,rcar-gen3-gpio"; ++ reg = <0 0xe6052000 0 0x50>; ++ interrupts = ; ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 64 30>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 910>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 910>; ++ }; ++ ++ gpio3: gpio@e6053000 { ++ compatible = "renesas,gpio-r8a77980", ++ "renesas,rcar-gen3-gpio"; ++ reg = <0 0xe6053000 0 0x50>; ++ interrupts = ; ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 96 17>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 909>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 909>; ++ }; ++ ++ gpio4: gpio@e6054000 { ++ compatible = "renesas,gpio-r8a77980", ++ "renesas,rcar-gen3-gpio"; ++ reg = <0 0xe6054000 0 0x50>; ++ interrupts = ; ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 128 25>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 908>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 908>; ++ }; ++ ++ gpio5: gpio@e6055000 { ++ compatible = "renesas,gpio-r8a77980", ++ "renesas,rcar-gen3-gpio"; ++ reg = <0 0xe6055000 0 0x50>; ++ interrupts = ; ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 160 15>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 907>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 907>; ++ }; ++ + pfc: pin-controller@e6060000 { + compatible = "renesas,pfc-r8a77980"; + reg = <0 0xe6060000 0 0x50c>; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0193-arm64-dts-renesas-condor-v3hsk-specify-Ethernet-PHY-.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0193-arm64-dts-renesas-condor-v3hsk-specify-Ethernet-PHY-.patch new file mode 100644 index 00000000..cccc11ae --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0193-arm64-dts-renesas-condor-v3hsk-specify-Ethernet-PHY-.patch @@ -0,0 +1,50 @@ +From 37d10d9dca2423dc6482631d5b6477fc678326f9 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Wed, 13 Jun 2018 19:42:15 +0300 +Subject: [PATCH 013/211] arm64: dts: renesas: condor/v3hsk: specify Ethernet + PHY IRQs + +Specify Ethernet PHY IRQs in the Condor/V3HSK board device trees, now that +we have the GPIO support (previously phylib had to resort to polling). + +Based on the original (and large) patch by Vladimir Barinov. + +Signed-off-by: Vladimir Barinov +Signed-off-by: Sergei Shtylyov +Signed-off-by: Simon Horman +(cherry picked from commit ffbd52352208534a30d5bbe2e15ee9e5cbb98c6d) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980-condor.dts | 2 ++ + arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +index cc3ee25..9f25c40 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +@@ -59,6 +59,8 @@ + phy0: ethernet-phy@0 { + rxc-skew-ps = <1500>; + reg = <0>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <17 IRQ_TYPE_LEVEL_LOW>; + }; + }; + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +index bb7e0e5..9dac42f 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +@@ -48,6 +48,8 @@ + + phy0: ethernet-phy@0 { + reg = <0>; ++ interrupt-parent = <&gpio4>; ++ interrupts = <23 IRQ_TYPE_LEVEL_LOW>; + }; + }; + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0194-arm64-dts-renesas-r8a77980-add-FCPVD-VSPD-DU-LVDS-su.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0194-arm64-dts-renesas-r8a77980-add-FCPVD-VSPD-DU-LVDS-su.patch new file mode 100644 index 00000000..4e69b8ac --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0194-arm64-dts-renesas-r8a77980-add-FCPVD-VSPD-DU-LVDS-su.patch @@ -0,0 +1,112 @@ +From 2131b446d83bfcf2d47af73ead18eec97990d82d Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Wed, 13 Jun 2018 23:11:27 +0300 +Subject: [PATCH 014/211] arm64: dts: renesas: r8a77980: add FCPVD/VSPD/DU/LVDS + support + +Describe the interconnected FCPVD0, VSPD0, DU, and LVDS0 devices in the +R8A77980 device tree... + +Based on the original (and large) patch by Vladimir Barinov. + +Signed-off-by: Vladimir Barinov +Signed-off-by: Sergei Shtylyov +Reviewed-by: Laurent Pinchart +Signed-off-by: Simon Horman +(cherry picked from commit a334e781e01afeb97634480ec0d9819287b79a68) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 77 +++++++++++++++++++++++++++++++ + 1 file changed, 77 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index 682a782..873b80a 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -716,6 +716,83 @@ + resets = <&cpg 408>; + }; + ++ vspd0: vsp@fea20000 { ++ compatible = "renesas,vsp2"; ++ reg = <0 0xfea20000 0 0x5000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 623>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 623>; ++ renesas,fcp = <&fcpvd0>; ++ }; ++ ++ fcpvd0: fcp@fea27000 { ++ compatible = "renesas,fcpv"; ++ reg = <0 0xfea27000 0 0x200>; ++ clocks = <&cpg CPG_MOD 603>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 603>; ++ }; ++ ++ du: display@feb00000 { ++ compatible = "renesas,du-r8a77980", ++ "renesas,du-r8a77970"; ++ reg = <0 0xfeb00000 0 0x80000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 724>; ++ clock-names = "du.0"; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 724>; ++ vsps = <&vspd0>; ++ status = "disabled"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ du_out_rgb: endpoint { ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ du_out_lvds0: endpoint { ++ remote-endpoint = <&lvds0_in>; ++ }; ++ }; ++ }; ++ }; ++ ++ lvds0: lvds-encoder@feb90000 { ++ compatible = "renesas,r8a77980-lvds"; ++ reg = <0 0xfeb90000 0 0x14>; ++ clocks = <&cpg CPG_MOD 727>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 727>; ++ status = "disabled"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ lvds0_in: endpoint { ++ remote-endpoint = ++ <&du_out_lvds0>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ lvds0_out: endpoint { ++ }; ++ }; ++ }; ++ }; ++ + prr: chipid@fff00044 { + compatible = "renesas,prr"; + reg = <0 0xfff00044 0 4>; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0195-sh_eth-fix-enum-RPADIR_BIT.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0195-sh_eth-fix-enum-RPADIR_BIT.patch new file mode 100644 index 00000000..96a9be64 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0195-sh_eth-fix-enum-RPADIR_BIT.patch @@ -0,0 +1,38 @@ +From adad896f249ec55add54183120256250224caa11 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Mon, 25 Jun 2018 23:36:21 +0300 +Subject: [PATCH 015/211] sh_eth: fix *enum* RPADIR_BIT + +The *enum* RPADIR_BIT was declared in the commit 86a74ff21a7a ("net: +sh_eth: add support for Renesas SuperH Ethernet") adding SH771x support, +however the SH771x manual doesn't have the RPADIR register described and, +moreover, tells why the padding insertion must not be used. The newer SoC +manuals do have RPADIR documented, though with somewhat different layout -- +update the *enum* according to these manuals... + +Signed-off-by: Sergei Shtylyov +Reviewed-by: Geert Uytterhoeven +Signed-off-by: David S. Miller +(cherry picked from commit b13ca098fd35bb0cfbe027f2415a17a6ceb6f47f) +Signed-off-by: Valentine Barshak +--- + drivers/net/ethernet/renesas/sh_eth.h | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h +index 726c55a..ae3ef5d 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.h ++++ b/drivers/net/ethernet/renesas/sh_eth.h +@@ -403,8 +403,7 @@ enum DESC_I_BIT { + + /* RPADIR */ + enum RPADIR_BIT { +- RPADIR_PADS1 = 0x20000, RPADIR_PADS0 = 0x10000, +- RPADIR_PADR = 0x0003f, ++ RPADIR_PADS = 0x1f0000, RPADIR_PADR = 0xffff, + }; + + /* FDR */ +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0196-sh_eth-remove-sh_eth_cpu_data-rpadir_value.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0196-sh_eth-remove-sh_eth_cpu_data-rpadir_value.patch new file mode 100644 index 00000000..db774e11 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0196-sh_eth-remove-sh_eth_cpu_data-rpadir_value.patch @@ -0,0 +1,95 @@ +From 3edb531642371a70dc3efbd3c468581521e03c9c Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Mon, 25 Jun 2018 23:37:06 +0300 +Subject: [PATCH 016/211] sh_eth: remove sh_eth_cpu_data::rpadir_value + +If RPADIR exists, the value written to it is always the same for all SoCs +(and derived from NET_IP_ALIGN), so there has not been any need to store +it in the *struct* sh_eth_cpu_data... + +Signed-off-by: Sergei Shtylyov +Reviewed-by: Geert Uytterhoeven +Signed-off-by: David S. Miller +(cherry picked from commit 470103dc840ec9cda91b5049d82f4bb599cea759) +Signed-off-by: Valentine Barshak +--- + drivers/net/ethernet/renesas/sh_eth.c | 8 +------- + drivers/net/ethernet/renesas/sh_eth.h | 1 - + 2 files changed, 1 insertion(+), 8 deletions(-) + +diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c +index 87a6bcd..981ea16 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.c ++++ b/drivers/net/ethernet/renesas/sh_eth.c +@@ -622,7 +622,6 @@ static struct sh_eth_cpu_data r7s72100_data = { + .tpauser = 1, + .hw_swap = 1, + .rpadir = 1, +- .rpadir_value = 2 << 16, + .no_trimd = 1, + .no_ade = 1, + .xdfar_rw = 1, +@@ -672,7 +671,6 @@ static struct sh_eth_cpu_data r8a7740_data = { + .bculr = 1, + .hw_swap = 1, + .rpadir = 1, +- .rpadir_value = 2 << 16, + .no_trimd = 1, + .no_ade = 1, + .xdfar_rw = 1, +@@ -798,7 +796,6 @@ static struct sh_eth_cpu_data r8a77980_data = { + .hw_swap = 1, + .nbst = 1, + .rpadir = 1, +- .rpadir_value = 2 << 16, + .no_trimd = 1, + .no_ade = 1, + .xdfar_rw = 1, +@@ -851,7 +848,6 @@ static struct sh_eth_cpu_data sh7724_data = { + .tpauser = 1, + .hw_swap = 1, + .rpadir = 1, +- .rpadir_value = 0x00020000, /* NET_IP_ALIGN assumed to be 2 */ + }; + + static void sh_eth_set_rate_sh7757(struct net_device *ndev) +@@ -898,7 +894,6 @@ static struct sh_eth_cpu_data sh7757_data = { + .hw_swap = 1, + .no_ade = 1, + .rpadir = 1, +- .rpadir_value = 2 << 16, + .rtrate = 1, + .dual_port = 1, + }; +@@ -978,7 +973,6 @@ static struct sh_eth_cpu_data sh7757_data_giga = { + .bculr = 1, + .hw_swap = 1, + .rpadir = 1, +- .rpadir_value = 2 << 16, + .no_trimd = 1, + .no_ade = 1, + .xdfar_rw = 1, +@@ -1467,7 +1461,7 @@ static int sh_eth_dev_init(struct net_device *ndev) + /* Descriptor format */ + sh_eth_ring_format(ndev); + if (mdp->cd->rpadir) +- sh_eth_write(ndev, mdp->cd->rpadir_value, RPADIR); ++ sh_eth_write(ndev, NET_IP_ALIGN << 16, RPADIR); + + /* all sh_eth int mask */ + sh_eth_write(ndev, 0, EESIPR); +diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h +index ae3ef5d..a03d99f 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.h ++++ b/drivers/net/ethernet/renesas/sh_eth.h +@@ -487,7 +487,6 @@ struct sh_eth_cpu_data { + u32 ecsipr_value; + u32 fdr_value; + u32 fcftr_value; +- u32 rpadir_value; + + /* interrupt checking mask */ + u32 tx_check; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0197-sh_eth-fix-enum-A-M-PR_BIT.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0197-sh_eth-fix-enum-A-M-PR_BIT.patch new file mode 100644 index 00000000..e3bf0199 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0197-sh_eth-fix-enum-A-M-PR_BIT.patch @@ -0,0 +1,62 @@ +From d511f84c6154eea75e1f00bc1806279a8aec4499 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Tue, 26 Jun 2018 18:42:33 +0300 +Subject: [PATCH 017/211] sh_eth: fix *enum* {A|M}PR_BIT + +The *enum* {A|M}PR_BIT were declared in the commit 86a74ff21a7a ("net: +sh_eth: add support for Renesas SuperH Ethernet") adding SH771x support, +however the SH771x manual doesn't have the APR/MPR registers described +and the code writing to them for SH7710 was later removed by the commit +380af9e390ec ("net: sh_eth: CPU dependency code collect to "struct +sh_eth_cpu_data""). All the newer SoC manuals have these registers +documented as having a 16-bit TIME parameter of the PAUSE frame, not +1-bit -- update the *enum* accordingly, fixing up the APR/MPR writes... + +Signed-off-by: Sergei Shtylyov +Reviewed-by: Geert Uytterhoeven +Signed-off-by: David S. Miller +(cherry picked from commit 782e85c5f7aee0294cefb52a190b05e082c178d5) +Signed-off-by: Valentine Barshak +--- + drivers/net/ethernet/renesas/sh_eth.c | 4 ++-- + drivers/net/ethernet/renesas/sh_eth.h | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c +index 981ea16..f11b12f 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.c ++++ b/drivers/net/ethernet/renesas/sh_eth.c +@@ -1521,9 +1521,9 @@ static int sh_eth_dev_init(struct net_device *ndev) + + /* mask reset */ + if (mdp->cd->apr) +- sh_eth_write(ndev, APR_AP, APR); ++ sh_eth_write(ndev, 1, APR); + if (mdp->cd->mpr) +- sh_eth_write(ndev, MPR_MP, MPR); ++ sh_eth_write(ndev, 1, MPR); + if (mdp->cd->tpauser) + sh_eth_write(ndev, TPAUSER_UNLIMITED, TPAUSER); + +diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h +index a03d99f..140ad2c 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.h ++++ b/drivers/net/ethernet/renesas/sh_eth.h +@@ -383,12 +383,12 @@ enum ECSIPR_STATUS_MASK_BIT { + + /* APR */ + enum APR_BIT { +- APR_AP = 0x00000001, ++ APR_AP = 0x0000ffff, + }; + + /* MPR */ + enum MPR_BIT { +- MPR_MP = 0x00000001, ++ MPR_MP = 0x0000ffff, + }; + + /* TRSCER */ +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0198-iommu-ipmmu-vmsa-Document-R-Car-V3H-and-E3-IPMMU-DT-.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0198-iommu-ipmmu-vmsa-Document-R-Car-V3H-and-E3-IPMMU-DT-.patch new file mode 100644 index 00000000..116ee0f4 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0198-iommu-ipmmu-vmsa-Document-R-Car-V3H-and-E3-IPMMU-DT-.patch @@ -0,0 +1,36 @@ +From 3d4aa8d0b234e1aa000b027889126bc9f1ca1dbb Mon Sep 17 00:00:00 2001 +From: Magnus Damm +Date: Thu, 14 Jun 2018 12:48:26 +0200 +Subject: [PATCH 018/211] iommu/ipmmu-vmsa: Document R-Car V3H and E3 IPMMU DT + bindings + +Update the IPMMU DT binding documentation to include the compat strings +for the IPMMU devices included in the R-Car V3H and E3 SoCs. + +Signed-off-by: Magnus Damm +Reviewed-by: Simon Horman +Acked-by: Rob Herring +Reviewed-by: Geert Uytterhoeven +Signed-off-by: Joerg Roedel +(cherry picked from commit bc24f62bf8763660110f915cead86dd13840ed26) +[valentine.barshak: resolved minor conflicts] +Signed-off-by: Valentine Barshak +--- + Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt b/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt +index 67d00c2..c6e2d85 100644 +--- a/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt ++++ b/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt +@@ -21,6 +21,7 @@ Required Properties: + - "renesas,ipmmu-r8a7796" for the R8A7796 (R-Car M3-W) IPMMU. + - "renesas,ipmmu-r8a77965" for the R8A77965 (R-Car M3-N) IPMMU. + - "renesas,ipmmu-r8a77970" for the R8A77970 (R-Car V3M) IPMMU. ++ - "renesas,ipmmu-r8a77980" for the R8A77980 (R-Car V3H) IPMMU. + - "renesas,ipmmu-r8a77990" for the R8A77990 (R-Car E3) IPMMU. + - "renesas,ipmmu-r8a77995" for the R8A77995 (R-Car D3) IPMMU. + - "renesas,ipmmu-vmsa" for generic R-Car Gen2 or RZ/G1 VMSA-compatible +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0199-dt-bindings-phy-Renesas-R-Car-Gen3-PCIe-PHY-bindings.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0199-dt-bindings-phy-Renesas-R-Car-Gen3-PCIe-PHY-bindings.patch new file mode 100644 index 00000000..42a7407e --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0199-dt-bindings-phy-Renesas-R-Car-Gen3-PCIe-PHY-bindings.patch @@ -0,0 +1,54 @@ +From d181283b4a17b6109aff85b02952f49642ec63e0 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Sun, 10 Jun 2018 21:22:46 +0300 +Subject: [PATCH 019/211] dt-bindings: phy: Renesas R-Car Gen3 PCIe PHY + bindings + +This PHY is still mostly undocumented -- the only documented registers +exist on R-Car V3H (R8A77980) SoC. Add the corresponding device tree +bindings. + +Signed-off-by: Sergei Shtylyov +Reviewed-by: Simon Horman +Reviewed-by: Rob Herring +Signed-off-by: Kishon Vijay Abraham I +(cherry picked from commit 4fa88cd3370ed33119863747a4db7f5e3f1dc308) +Signed-off-by: Valentine Barshak +--- + .../devicetree/bindings/phy/rcar-gen3-phy-pcie.txt | 24 ++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + create mode 100644 Documentation/devicetree/bindings/phy/rcar-gen3-phy-pcie.txt + +diff --git a/Documentation/devicetree/bindings/phy/rcar-gen3-phy-pcie.txt b/Documentation/devicetree/bindings/phy/rcar-gen3-phy-pcie.txt +new file mode 100644 +index 0000000..63853b3 +--- /dev/null ++++ b/Documentation/devicetree/bindings/phy/rcar-gen3-phy-pcie.txt +@@ -0,0 +1,24 @@ ++* Renesas R-Car generation 3 PCIe PHY ++ ++This file provides information on what the device node for the R-Car ++generation 3 PCIe PHY contains. ++ ++Required properties: ++- compatible: "renesas,r8a77980-pcie-phy" if the device is a part of the ++ R8A77980 SoC. ++- reg: offset and length of the register block. ++- clocks: clock phandle and specifier pair. ++- power-domains: power domain phandle and specifier pair. ++- resets: reset phandle and specifier pair. ++- #phy-cells: see phy-bindings.txt in the same directory, must be <0>. ++ ++Example (R-Car V3H): ++ ++ pcie-phy@e65d0000 { ++ compatible = "renesas,r8a77980-pcie-phy"; ++ reg = <0 0xe65d0000 0 0x8000>; ++ #phy-cells = <0>; ++ clocks = <&cpg CPG_MOD 319>; ++ power-domains = <&sysc 32>; ++ resets = <&cpg 319>; ++ }; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0200-phy-Renesas-R-Car-gen3-PCIe-PHY-driver.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0200-phy-Renesas-R-Car-gen3-PCIe-PHY-driver.patch new file mode 100644 index 00000000..c1146651 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0200-phy-Renesas-R-Car-gen3-PCIe-PHY-driver.patch @@ -0,0 +1,208 @@ +From 1136cf52385aa768427840ebcbc457284d42b8a2 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Sun, 10 Jun 2018 21:24:13 +0300 +Subject: [PATCH 020/211] phy: Renesas R-Car gen3 PCIe PHY driver + +This PHY is still mostly undocumented -- the only documented registers +exist on R-Car V3H (R8A77980) SoC where this PHY stays in a powered-down +state after a reset and thus we must power it up for PCIe to work... + +Signed-off-by: Sergei Shtylyov +Reviewed-by: Simon Horman +Signed-off-by: Kishon Vijay Abraham I +(cherry picked from commit 2ce7f2f425ef7464a2a9a872d2e9acad49e6cb3e) +Signed-off-by: Valentine Barshak +--- + drivers/phy/renesas/Kconfig | 7 ++ + drivers/phy/renesas/Makefile | 1 + + drivers/phy/renesas/phy-rcar-gen3-pcie.c | 151 +++++++++++++++++++++++++++++++ + 3 files changed, 159 insertions(+) + create mode 100644 drivers/phy/renesas/phy-rcar-gen3-pcie.c + +diff --git a/drivers/phy/renesas/Kconfig b/drivers/phy/renesas/Kconfig +index c845fac..4bd390c 100644 +--- a/drivers/phy/renesas/Kconfig ++++ b/drivers/phy/renesas/Kconfig +@@ -8,6 +8,13 @@ config PHY_RCAR_GEN2 + help + Support for USB PHY found on Renesas R-Car generation 2 SoCs. + ++config PHY_RCAR_GEN3_PCIE ++ tristate "Renesas R-Car generation 3 PCIe PHY driver" ++ depends on ARCH_RENESAS ++ select GENERIC_PHY ++ help ++ Support for the PCIe PHY found on Renesas R-Car generation 3 SoCs. ++ + config PHY_RCAR_GEN3_USB2 + tristate "Renesas R-Car generation 3 USB 2.0 PHY driver" + depends on ARCH_RENESAS +diff --git a/drivers/phy/renesas/Makefile b/drivers/phy/renesas/Makefile +index 8b60259..4b76fc4 100644 +--- a/drivers/phy/renesas/Makefile ++++ b/drivers/phy/renesas/Makefile +@@ -1,3 +1,4 @@ + obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o ++obj-$(CONFIG_PHY_RCAR_GEN3_PCIE) += phy-rcar-gen3-pcie.o + obj-$(CONFIG_PHY_RCAR_GEN3_USB2) += phy-rcar-gen3-usb2.o + obj-$(CONFIG_PHY_RCAR_GEN3_USB3) += phy-rcar-gen3-usb3.o +diff --git a/drivers/phy/renesas/phy-rcar-gen3-pcie.c b/drivers/phy/renesas/phy-rcar-gen3-pcie.c +new file mode 100644 +index 0000000..c4e4aa2 +--- /dev/null ++++ b/drivers/phy/renesas/phy-rcar-gen3-pcie.c +@@ -0,0 +1,151 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Renesas R-Car Gen3 PCIe PHY driver ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define PHY_CTRL 0x4000 /* R8A77980 only */ ++ ++/* PHY control register (PHY_CTRL) */ ++#define PHY_CTRL_PHY_PWDN BIT(2) ++ ++struct rcar_gen3_phy { ++ struct phy *phy; ++ spinlock_t lock; ++ void __iomem *base; ++}; ++ ++static void rcar_gen3_phy_pcie_modify_reg(struct phy *p, unsigned int reg, ++ u32 clear, u32 set) ++{ ++ struct rcar_gen3_phy *phy = phy_get_drvdata(p); ++ void __iomem *base = phy->base; ++ unsigned long flags; ++ u32 value; ++ ++ spin_lock_irqsave(&phy->lock, flags); ++ ++ value = readl(base + reg); ++ value &= ~clear; ++ value |= set; ++ writel(value, base + reg); ++ ++ spin_unlock_irqrestore(&phy->lock, flags); ++} ++ ++static int r8a77980_phy_pcie_power_on(struct phy *p) ++{ ++ /* Power on the PCIe PHY */ ++ rcar_gen3_phy_pcie_modify_reg(p, PHY_CTRL, PHY_CTRL_PHY_PWDN, 0); ++ ++ return 0; ++} ++ ++static int r8a77980_phy_pcie_power_off(struct phy *p) ++{ ++ /* Power off the PCIe PHY */ ++ rcar_gen3_phy_pcie_modify_reg(p, PHY_CTRL, 0, PHY_CTRL_PHY_PWDN); ++ ++ return 0; ++} ++ ++static const struct phy_ops r8a77980_phy_pcie_ops = { ++ .power_on = r8a77980_phy_pcie_power_on, ++ .power_off = r8a77980_phy_pcie_power_off, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct of_device_id rcar_gen3_phy_pcie_match_table[] = { ++ { .compatible = "renesas,r8a77980-pcie-phy" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, rcar_gen3_phy_pcie_match_table); ++ ++static int rcar_gen3_phy_pcie_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct phy_provider *provider; ++ struct rcar_gen3_phy *phy; ++ struct resource *res; ++ void __iomem *base; ++ int error; ++ ++ if (!dev->of_node) { ++ dev_err(dev, ++ "This driver must only be instantiated from the device tree\n"); ++ return -EINVAL; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); ++ if (!phy) ++ return -ENOMEM; ++ ++ spin_lock_init(&phy->lock); ++ ++ phy->base = base; ++ ++ /* ++ * devm_phy_create() will call pm_runtime_enable(&phy->dev); ++ * And then, phy-core will manage runtime PM for this device. ++ */ ++ pm_runtime_enable(dev); ++ ++ phy->phy = devm_phy_create(dev, NULL, &r8a77980_phy_pcie_ops); ++ if (IS_ERR(phy->phy)) { ++ dev_err(dev, "Failed to create PCIe PHY\n"); ++ error = PTR_ERR(phy->phy); ++ goto error; ++ } ++ phy_set_drvdata(phy->phy, phy); ++ ++ provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); ++ if (IS_ERR(provider)) { ++ dev_err(dev, "Failed to register PHY provider\n"); ++ error = PTR_ERR(provider); ++ goto error; ++ } ++ ++ return 0; ++ ++error: ++ pm_runtime_disable(dev); ++ ++ return error; ++} ++ ++static int rcar_gen3_phy_pcie_remove(struct platform_device *pdev) ++{ ++ pm_runtime_disable(&pdev->dev); ++ ++ return 0; ++}; ++ ++static struct platform_driver rcar_gen3_phy_driver = { ++ .driver = { ++ .name = "phy_rcar_gen3_pcie", ++ .of_match_table = rcar_gen3_phy_pcie_match_table, ++ }, ++ .probe = rcar_gen3_phy_pcie_probe, ++ .remove = rcar_gen3_phy_pcie_remove, ++}; ++ ++module_platform_driver(rcar_gen3_phy_driver); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("Renesas R-Car Gen3 PCIe PHY"); ++MODULE_AUTHOR("Sergei Shtylyov "); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0201-dt-bindings-irqchip-renesas-irqc-Document-r8a77980-s.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0201-dt-bindings-irqchip-renesas-irqc-Document-r8a77980-s.patch new file mode 100644 index 00000000..7d337f0c --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0201-dt-bindings-irqchip-renesas-irqc-Document-r8a77980-s.patch @@ -0,0 +1,33 @@ +From ed1df4bb5937065d06cd7893d7ee3bdd5324eb7e Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Tue, 17 Jul 2018 22:23:17 +0300 +Subject: [PATCH 021/211] dt-bindings: irqchip: renesas-irqc: Document r8a77980 + support + +Document R-Car V3H (AKA R8A77980) SoC bindings. + +Reviewed-by: Geert Uytterhoeven +Reviewed-by: Simon Horman +Signed-off-by: Sergei Shtylyov +Signed-off-by: Marc Zyngier +(cherry picked from commit d5fd14803573e57941100d11dd9cf3e84d17e180) +Signed-off-by: Valentine Barshak +--- + Documentation/devicetree/bindings/interrupt-controller/renesas,irqc.txt | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Documentation/devicetree/bindings/interrupt-controller/renesas,irqc.txt b/Documentation/devicetree/bindings/interrupt-controller/renesas,irqc.txt +index 20f121d..c389791 100644 +--- a/Documentation/devicetree/bindings/interrupt-controller/renesas,irqc.txt ++++ b/Documentation/devicetree/bindings/interrupt-controller/renesas,irqc.txt +@@ -16,6 +16,7 @@ Required properties: + - "renesas,intc-ex-r8a7796" (R-Car M3-W) + - "renesas,intc-ex-r8a77965" (R-Car M3-N) + - "renesas,intc-ex-r8a77970" (R-Car V3M) ++ - "renesas,intc-ex-r8a77980" (R-Car V3H) + - "renesas,intc-ex-r8a77995" (R-Car D3) + - #interrupt-cells: has to be <2>: an interrupt index and flags, as defined in + interrupts.txt in this directory +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0202-arm64-dts-renesas-r8a77980-add-INTC-EX-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0202-arm64-dts-renesas-r8a77980-add-INTC-EX-support.patch new file mode 100644 index 00000000..f8b0da52 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0202-arm64-dts-renesas-r8a77980-add-INTC-EX-support.patch @@ -0,0 +1,49 @@ +From 090f8ee8e91a9cde0b4bdc59800db219aaa83951 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Tue, 17 Jul 2018 23:08:27 +0300 +Subject: [PATCH 022/211] arm64: dts: renesas: r8a77980: add INTC-EX support + +Describe the INTC-EX interrupt controller in the R8A77980 device tree. + +Based on the original (and large) patch by Vladimir Barinov. + +Signed-off-by: Vladimir Barinov +Signed-off-by: Sergei Shtylyov +Reviewed-by: Geert Uytterhoeven +Signed-off-by: Simon Horman +(cherry picked from commit 9a6c158f62ccdd37c921ec8b1484418bad5f7984) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index 873b80a..5bd9628 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -234,6 +234,22 @@ + #power-domain-cells = <1>; + }; + ++ intc_ex: interrupt-controller@e61c0000 { ++ compatible = "renesas,intc-ex-r8a77980", "renesas,irqc"; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ reg = <0 0xe61c0000 0 0x200>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 407>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 407>; ++ }; ++ + i2c0: i2c@e6500000 { + compatible = "renesas,i2c-r8a77980", + "renesas,rcar-gen3-i2c"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0203-net-phy-allow-scanning-busses-with-missing-phys.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0203-net-phy-allow-scanning-busses-with-missing-phys.patch new file mode 100644 index 00000000..5b80edca --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0203-net-phy-allow-scanning-busses-with-missing-phys.patch @@ -0,0 +1,50 @@ +From c6eac988444567bfb55644206d8a55f7e78b1df9 Mon Sep 17 00:00:00 2001 +From: Alexandre Belloni +Date: Tue, 24 Apr 2018 18:09:04 +0200 +Subject: [PATCH 023/211] net: phy: allow scanning busses with missing phys + +Some MDIO busses will error out when trying to read a phy address with no +phy present at that address. In that case, probing the bus will fail +because __mdiobus_register() is scanning the bus for all possible phys +addresses. + +In case MII_PHYSID1 returns -EIO or -ENODEV, consider there is no phy at +this address and set the phy ID to 0xffffffff which is then properly +handled in get_phy_device(). + +Suggested-by: Andrew Lunn +Signed-off-by: Alexandre Belloni +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +(cherry picked from commit 02a6efcab675fe32815d824837784c3f42a7d892) +Signed-off-by: Valentine Barshak +--- + drivers/net/phy/phy_device.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c +index eff5327..64e5ed9 100644 +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -536,8 +536,17 @@ static int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id, + + /* Grab the bits from PHYIR1, and put them in the upper half */ + phy_reg = mdiobus_read(bus, addr, MII_PHYSID1); +- if (phy_reg < 0) ++ if (phy_reg < 0) { ++ /* if there is no device, return without an error so scanning ++ * the bus works properly ++ */ ++ if (phy_reg == -EIO || phy_reg == -ENODEV) { ++ *phy_id = 0xffffffff; ++ return 0; ++ } ++ + return -EIO; ++ } + + *phy_id = (phy_reg & 0xffff) << 16; + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0204-arm64-dts-renesas-r8a77980-add-RWDT-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0204-arm64-dts-renesas-r8a77980-add-RWDT-support.patch new file mode 100644 index 00000000..419cc988 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0204-arm64-dts-renesas-r8a77980-add-RWDT-support.patch @@ -0,0 +1,79 @@ +From 1193ccc27a8321a628c1003322c7bc093565817d Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Fri, 20 Jul 2018 22:21:45 +0300 +Subject: [PATCH 024/211] arm64: dts: renesas: r8a77980: add RWDT support + +Describe RWDT in the R8A77980 SoC device tree. + +Enable RWDT on the Condor and V3H Starter Kit boards. + +Based on the original (and large) patch by Vladimir Barinov. + +Signed-off-by: Vladimir Barinov +Signed-off-by: Sergei Shtylyov +Reviewed-by: Geert Uytterhoeven +Signed-off-by: Simon Horman +(cherry picked from commit bcee502ceb6c0dcbc7ccd460ed7040c3d6998c3e) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980-condor.dts | 5 +++++ + arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts | 5 +++++ + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 10 ++++++++++ + 3 files changed, 20 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +index 9f25c40..494f4ef 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +@@ -156,6 +156,11 @@ + }; + }; + ++&rwdt { ++ timeout-sec = <60>; ++ status = "okay"; ++}; ++ + &scif0 { + pinctrl-0 = <&scif0_pins>, <&scif_clk_pins>; + pinctrl-names = "default"; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +index 9dac42f..9147d85 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +@@ -71,6 +71,11 @@ + }; + }; + ++&rwdt { ++ timeout-sec = <60>; ++ status = "okay"; ++}; ++ + &scif0 { + pinctrl-0 = <&scif0_pins>, <&scif_clk_pins>; + pinctrl-names = "default"; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index 5bd9628..d3532fd 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -118,6 +118,16 @@ + #size-cells = <2>; + ranges; + ++ rwdt: watchdog@e6020000 { ++ compatible = "renesas,r8a77980-wdt", ++ "renesas,rcar-gen3-wdt"; ++ reg = <0 0xe6020000 0 0x0c>; ++ clocks = <&cpg CPG_MOD 402>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 402>; ++ status = "disabled"; ++ }; ++ + gpio0: gpio@e6050000 { + compatible = "renesas,gpio-r8a77980", + "renesas,rcar-gen3-gpio"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0205-arm64-enable-CMT-TMU-support-for-Renesas-SoC.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0205-arm64-enable-CMT-TMU-support-for-Renesas-SoC.patch new file mode 100644 index 00000000..7f044095 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0205-arm64-enable-CMT-TMU-support-for-Renesas-SoC.patch @@ -0,0 +1,33 @@ +From 777db7fda6f37341c0fca7afd0973c2196229453 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Fri, 31 Aug 2018 22:54:42 +0300 +Subject: [PATCH 025/211] arm64: enable CMT/TMU support for Renesas SoC + +Renesas R-Car gen3 SoCs have both CMT and TMU timers, so we have to enable +building them in Kconfig.platforms (as they don't normally have the prompts +in Kconfig). + +Signed-off-by: Sergei Shtylyov +Signed-off-by: Simon Horman +(cherry picked from commit c1801ad028456267dde2111e470ac43f7882debf) +Signed-off-by: Valentine Barshak +--- + arch/arm64/Kconfig.platforms | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms +index 20ef69a..aba998f 100644 +--- a/arch/arm64/Kconfig.platforms ++++ b/arch/arm64/Kconfig.platforms +@@ -171,6 +171,8 @@ config ARCH_RENESAS + select PM_GENERIC_DOMAINS + select RENESAS_IRQC + select SOC_BUS ++ select SYS_SUPPORTS_SH_CMT ++ select SYS_SUPPORTS_SH_TMU + help + This enables support for the ARMv8 based Renesas SoCs. + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0206-arm64-dts-renesas-r8a77980-add-Cortex-A53-PMU-suppor.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0206-arm64-dts-renesas-r8a77980-add-Cortex-A53-PMU-suppor.patch new file mode 100644 index 00000000..d2950867 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0206-arm64-dts-renesas-r8a77980-add-Cortex-A53-PMU-suppor.patch @@ -0,0 +1,44 @@ +From 9f3f0eecc9e1ff190aeffd4705b5fa0190c660c4 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Wed, 25 Jul 2018 19:43:41 +0300 +Subject: [PATCH 026/211] arm64: dts: renesas: r8a77980: add Cortex-A53 PMU + support + +Describe the performance monitor unit (PMU) for the Cortex-A53 cores in +the R8A77980 SoC's device tree. + +Based on the original (and large) patch by Vladimir Barinov. + +Signed-off-by: Vladimir Barinov +Signed-off-by: Sergei Shtylyov +Reviewed-by: Geert Uytterhoeven +Signed-off-by: Simon Horman +(cherry picked from commit 0dba24a8e17dc60dba5882b907e923fcf0d3d1e7) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index d3532fd..1013da3 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -98,6 +98,15 @@ + clock-frequency = <0>; + }; + ++ pmu_a53 { ++ compatible = "arm,cortex-a53-pmu"; ++ interrupts-extended = <&gic GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>, ++ <&gic GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>, ++ <&gic GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>, ++ <&gic GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>; ++ interrupt-affinity = <&a53_0>, <&a53_1>, <&a53_2>, <&a53_3>; ++ }; ++ + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2"; + method = "smc"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0207-arm64-dts-renesas-r8a77980-move-IPMMU-nodes.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0207-arm64-dts-renesas-r8a77980-move-IPMMU-nodes.patch new file mode 100644 index 00000000..ab198e2e --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0207-arm64-dts-renesas-r8a77980-move-IPMMU-nodes.patch @@ -0,0 +1,164 @@ +From bca8873bffd97737ab712a4962ee12c48f5a0518 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Thu, 26 Jul 2018 21:51:18 +0300 +Subject: [PATCH 027/211] arm64: dts: renesas: r8a77980: move IPMMU nodes + +The IPMMU nodes should follow the GEther node, not the CAN-FD node, +according to the part of the startng IPMMU-DS1 node. +While moving the nodes, also do sort them by label alphanumerically... + +Signed-off-by: Sergei Shtylyov +Signed-off-by: Simon Horman +(cherry picked from commit f14bfabc5472ebc637a9ed8c5bc4ab7b77db209f) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 126 +++++++++++++++--------------- + 1 file changed, 63 insertions(+), 63 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index 1013da3..fbfe654 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -462,69 +462,6 @@ + }; + }; + +- ipmmu_ds1: mmu@e7740000 { +- compatible = "renesas,ipmmu-r8a77980"; +- reg = <0 0xe7740000 0 0x1000>; +- renesas,ipmmu-main = <&ipmmu_mm 0>; +- power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; +- #iommu-cells = <1>; +- }; +- +- ipmmu_vip0: mmu@e7b00000 { +- compatible = "renesas,ipmmu-r8a77980"; +- reg = <0 0xe7b00000 0 0x1000>; +- power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; +- #iommu-cells = <1>; +- }; +- +- ipmmu_vip1: mmu@e7960000 { +- compatible = "renesas,ipmmu-r8a77980"; +- reg = <0 0xe7960000 0 0x1000>; +- power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; +- #iommu-cells = <1>; +- }; +- +- ipmmu_ir: mmu@ff8b0000 { +- compatible = "renesas,ipmmu-r8a77980"; +- reg = <0 0xff8b0000 0 0x1000>; +- renesas,ipmmu-main = <&ipmmu_mm 3>; +- power-domains = <&sysc R8A77980_PD_A3IR>; +- #iommu-cells = <1>; +- }; +- +- ipmmu_mm: mmu@e67b0000 { +- compatible = "renesas,ipmmu-r8a77980"; +- reg = <0 0xe67b0000 0 0x1000>; +- interrupts = , +- ; +- power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; +- #iommu-cells = <1>; +- }; +- +- ipmmu_rt: mmu@ffc80000 { +- compatible = "renesas,ipmmu-r8a77980"; +- reg = <0 0xffc80000 0 0x1000>; +- renesas,ipmmu-main = <&ipmmu_mm 10>; +- power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; +- #iommu-cells = <1>; +- }; +- +- ipmmu_vc0: mmu@fe6b0000 { +- compatible = "renesas,ipmmu-r8a77980"; +- reg = <0 0xfe6b0000 0 0x1000>; +- renesas,ipmmu-main = <&ipmmu_mm 12>; +- power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; +- #iommu-cells = <1>; +- }; +- +- ipmmu_vi0: mmu@febd0000 { +- compatible = "renesas,ipmmu-r8a77980"; +- reg = <0 0xfebd0000 0 0x1000>; +- renesas,ipmmu-main = <&ipmmu_mm 14>; +- power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; +- #iommu-cells = <1>; +- }; +- + avb: ethernet@e6800000 { + compatible = "renesas,etheravb-r8a77980", + "renesas,etheravb-rcar-gen3"; +@@ -722,6 +659,69 @@ + status = "disabled"; + }; + ++ ipmmu_ds1: mmu@e7740000 { ++ compatible = "renesas,ipmmu-r8a77980"; ++ reg = <0 0xe7740000 0 0x1000>; ++ renesas,ipmmu-main = <&ipmmu_mm 0>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ #iommu-cells = <1>; ++ }; ++ ++ ipmmu_ir: mmu@ff8b0000 { ++ compatible = "renesas,ipmmu-r8a77980"; ++ reg = <0 0xff8b0000 0 0x1000>; ++ renesas,ipmmu-main = <&ipmmu_mm 3>; ++ power-domains = <&sysc R8A77980_PD_A3IR>; ++ #iommu-cells = <1>; ++ }; ++ ++ ipmmu_mm: mmu@e67b0000 { ++ compatible = "renesas,ipmmu-r8a77980"; ++ reg = <0 0xe67b0000 0 0x1000>; ++ interrupts = , ++ ; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ #iommu-cells = <1>; ++ }; ++ ++ ipmmu_rt: mmu@ffc80000 { ++ compatible = "renesas,ipmmu-r8a77980"; ++ reg = <0 0xffc80000 0 0x1000>; ++ renesas,ipmmu-main = <&ipmmu_mm 10>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ #iommu-cells = <1>; ++ }; ++ ++ ipmmu_vc0: mmu@fe6b0000 { ++ compatible = "renesas,ipmmu-r8a77980"; ++ reg = <0 0xfe6b0000 0 0x1000>; ++ renesas,ipmmu-main = <&ipmmu_mm 12>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ #iommu-cells = <1>; ++ }; ++ ++ ipmmu_vi0: mmu@febd0000 { ++ compatible = "renesas,ipmmu-r8a77980"; ++ reg = <0 0xfebd0000 0 0x1000>; ++ renesas,ipmmu-main = <&ipmmu_mm 14>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ #iommu-cells = <1>; ++ }; ++ ++ ipmmu_vip0: mmu@e7b00000 { ++ compatible = "renesas,ipmmu-r8a77980"; ++ reg = <0 0xe7b00000 0 0x1000>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ #iommu-cells = <1>; ++ }; ++ ++ ipmmu_vip1: mmu@e7960000 { ++ compatible = "renesas,ipmmu-r8a77980"; ++ reg = <0 0xe7960000 0 0x1000>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ #iommu-cells = <1>; ++ }; ++ + mmc0: mmc@ee140000 { + compatible = "renesas,sdhi-r8a77980", + "renesas,rcar-gen3-sdhi"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0208-arm64-dts-renesas-r8a779-7-8-0-move-CAN-clock-node.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0208-arm64-dts-renesas-r8a779-7-8-0-move-CAN-clock-node.patch new file mode 100644 index 00000000..cddb5ab5 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0208-arm64-dts-renesas-r8a779-7-8-0-move-CAN-clock-node.patch @@ -0,0 +1,86 @@ +From d6867c17620e9e615af1aad9a100d94062ef917b Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Mon, 30 Jul 2018 21:22:37 +0300 +Subject: [PATCH 028/211] arm64: dts: renesas: r8a779{7|8}0: move CAN clock + node + +The CAN clock node should precede the "cpus" node in the R8A779{7|8}0 +device trees, according to the alphanumeric node sorting rule... + +Signed-off-by: Sergei Shtylyov +Reviewed-by: Geert Uytterhoeven +Signed-off-by: Simon Horman +(cherry picked from commit 18281dec2ba086b93bee2dd5f9ee0e3633d25a8d) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970.dtsi | 14 +++++++------- + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 14 +++++++------- + 2 files changed, 14 insertions(+), 14 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +index 3dc30a7..96feaa0 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +@@ -24,6 +24,13 @@ + i2c4 = &i2c4; + }; + ++ /* External CAN clock - to be overridden by boards that provide it */ ++ can_clk: can { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <0>; ++ }; ++ + cpus { + #address-cells = <1>; + #size-cells = <0>; +@@ -82,13 +89,6 @@ + method = "smc"; + }; + +- /* External CAN clock - to be overridden by boards that provide it */ +- can_clk: can { +- compatible = "fixed-clock"; +- #clock-cells = <0>; +- clock-frequency = <0>; +- }; +- + /* External SCIF clock - to be overridden by boards that provide it */ + scif_clk: scif { + compatible = "fixed-clock"; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index fbfe654..4bc99d6 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -25,6 +25,13 @@ + i2c5 = &i2c5; + }; + ++ /* External CAN clock - to be overridden by boards that provide it */ ++ can_clk: can { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <0>; ++ }; ++ + cpus { + #address-cells = <1>; + #size-cells = <0>; +@@ -77,13 +84,6 @@ + }; + }; + +- /* External CAN clock - to be overridden by boards that provide it */ +- can_clk: can { +- compatible = "fixed-clock"; +- #clock-cells = <0>; +- clock-frequency = <0>; +- }; +- + extal_clk: extal { + compatible = "fixed-clock"; + #clock-cells = <0>; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0209-arm64-dts-renesas-r8a77980-add-CSI2-VIN-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0209-arm64-dts-renesas-r8a77980-add-CSI2-VIN-support.patch new file mode 100644 index 00000000..929e9637 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0209-arm64-dts-renesas-r8a77980-add-CSI2-VIN-support.patch @@ -0,0 +1,411 @@ +From 54b520b432cd8d50d1c2a32a8f51dbef0d7a849f Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Mon, 6 Aug 2018 22:55:00 +0300 +Subject: [PATCH 029/211] arm64: dts: renesas: r8a77980: add CSI2/VIN support + +Describe the CSI2 and VIN (and their interconnections) in the R8A77980 +device tree. + +Signed-off-by: Sergei Shtylyov +Signed-off-by: Simon Horman +(cherry picked from commit 3182aa4e0bf4d0ee0b29fea4b5ca21290d6d6251) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 374 ++++++++++++++++++++++++++++++ + 1 file changed, 374 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index 4bc99d6..c099053 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -579,6 +579,302 @@ + status = "disabled"; + }; + ++ vin0: video@e6ef0000 { ++ compatible = "renesas,vin-r8a77980"; ++ reg = <0 0xe6ef0000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 811>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 811>; ++ status = "disabled"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ reg = <1>; ++ ++ vin0csi40: endpoint@2 { ++ reg = <2>; ++ remote-endpoint= <&csi40vin0>; ++ }; ++ }; ++ }; ++ }; ++ ++ vin1: video@e6ef1000 { ++ compatible = "renesas,vin-r8a77980"; ++ reg = <0 0xe6ef1000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 810>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ status = "disabled"; ++ resets = <&cpg 810>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ reg = <1>; ++ ++ vin1csi40: endpoint@2 { ++ reg = <2>; ++ remote-endpoint= <&csi40vin1>; ++ }; ++ }; ++ }; ++ }; ++ ++ vin2: video@e6ef2000 { ++ compatible = "renesas,vin-r8a77980"; ++ reg = <0 0xe6ef2000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 809>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 809>; ++ status = "disabled"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ reg = <1>; ++ ++ vin2csi40: endpoint@2 { ++ reg = <2>; ++ remote-endpoint= <&csi40vin2>; ++ }; ++ }; ++ }; ++ }; ++ ++ vin3: video@e6ef3000 { ++ compatible = "renesas,vin-r8a77980"; ++ reg = <0 0xe6ef3000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 808>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 808>; ++ status = "disabled"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ reg = <1>; ++ ++ vin3csi40: endpoint@2 { ++ reg = <2>; ++ remote-endpoint= <&csi40vin3>; ++ }; ++ }; ++ }; ++ }; ++ ++ vin4: video@e6ef4000 { ++ compatible = "renesas,vin-r8a77980"; ++ reg = <0 0xe6ef4000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 807>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 807>; ++ status = "disabled"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ reg = <1>; ++ ++ vin4csi41: endpoint@2 { ++ reg = <2>; ++ remote-endpoint= <&csi41vin4>; ++ }; ++ }; ++ }; ++ }; ++ ++ vin5: video@e6ef5000 { ++ compatible = "renesas,vin-r8a77980"; ++ reg = <0 0xe6ef5000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 806>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 806>; ++ status = "disabled"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ reg = <1>; ++ ++ vin5csi41: endpoint@2 { ++ reg = <2>; ++ remote-endpoint= <&csi41vin5>; ++ }; ++ }; ++ }; ++ }; ++ ++ vin6: video@e6ef6000 { ++ compatible = "renesas,vin-r8a77980"; ++ reg = <0 0xe6ef6000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 805>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 805>; ++ status = "disabled"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ reg = <1>; ++ ++ vin6csi41: endpoint@2 { ++ reg = <2>; ++ remote-endpoint= <&csi41vin6>; ++ }; ++ }; ++ }; ++ }; ++ ++ vin7: video@e6ef7000 { ++ compatible = "renesas,vin-r8a77980"; ++ reg = <0 0xe6ef7000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 804>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 804>; ++ status = "disabled"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ reg = <1>; ++ ++ vin7csi41: endpoint@2 { ++ reg = <2>; ++ remote-endpoint= <&csi41vin7>; ++ }; ++ }; ++ }; ++ }; ++ ++ vin8: video@e6ef8000 { ++ compatible = "renesas,vin-r8a77980"; ++ reg = <0 0xe6ef8000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 628>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 628>; ++ status = "disabled"; ++ }; ++ ++ vin9: video@e6ef9000 { ++ compatible = "renesas,vin-r8a77980"; ++ reg = <0 0xe6ef9000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 627>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 627>; ++ status = "disabled"; ++ }; ++ ++ vin10: video@e6efa000 { ++ compatible = "renesas,vin-r8a77980"; ++ reg = <0 0xe6efa000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 625>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 625>; ++ status = "disabled"; ++ }; ++ ++ vin11: video@e6efb000 { ++ compatible = "renesas,vin-r8a77980"; ++ reg = <0 0xe6efb000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 618>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 618>; ++ status = "disabled"; ++ }; ++ ++ vin12: video@e6efc000 { ++ compatible = "renesas,vin-r8a77980"; ++ reg = <0 0xe6efc000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 612>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 612>; ++ status = "disabled"; ++ }; ++ ++ vin13: video@e6efd000 { ++ compatible = "renesas,vin-r8a77980"; ++ reg = <0 0xe6efd000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 608>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 608>; ++ status = "disabled"; ++ }; ++ ++ vin14: video@e6efe000 { ++ compatible = "renesas,vin-r8a77980"; ++ reg = <0 0xe6efe000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 605>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 605>; ++ status = "disabled"; ++ }; ++ ++ vin15: video@e6eff000 { ++ compatible = "renesas,vin-r8a77980"; ++ reg = <0 0xe6eff000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 604>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 604>; ++ status = "disabled"; ++ }; ++ + dmac1: dma-controller@e7300000 { + compatible = "renesas,dmac-r8a77980", + "renesas,rcar-dmac"; +@@ -769,6 +1065,84 @@ + resets = <&cpg 603>; + }; + ++ csi40: csi2@feaa0000 { ++ compatible = "renesas,r8a77980-csi2"; ++ reg = <0 0xfeaa0000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 716>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 716>; ++ status = "disabled"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ reg = <1>; ++ ++ csi40vin0: endpoint@0 { ++ reg = <0>; ++ remote-endpoint = <&vin0csi40>; ++ }; ++ csi40vin1: endpoint@1 { ++ reg = <1>; ++ remote-endpoint = <&vin1csi40>; ++ }; ++ csi40vin2: endpoint@2 { ++ reg = <2>; ++ remote-endpoint = <&vin2csi40>; ++ }; ++ csi40vin3: endpoint@3 { ++ reg = <3>; ++ remote-endpoint = <&vin3csi40>; ++ }; ++ }; ++ }; ++ }; ++ ++ csi41: csi2@feab0000 { ++ compatible = "renesas,r8a77980-csi2"; ++ reg = <0 0xfeab0000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 715>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 715>; ++ status = "disabled"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ reg = <1>; ++ ++ csi41vin4: endpoint@0 { ++ reg = <0>; ++ remote-endpoint = <&vin4csi41>; ++ }; ++ csi41vin5: endpoint@1 { ++ reg = <1>; ++ remote-endpoint = <&vin5csi41>; ++ }; ++ csi41vin6: endpoint@2 { ++ reg = <2>; ++ remote-endpoint = <&vin6csi41>; ++ }; ++ csi41vin7: endpoint@3 { ++ reg = <3>; ++ remote-endpoint = <&vin7csi41>; ++ }; ++ }; ++ }; ++ }; ++ + du: display@feb00000 { + compatible = "renesas,du-r8a77980", + "renesas,du-r8a77970"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0210-arm64-dts-renesas-r8a77970-add-MMC-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0210-arm64-dts-renesas-r8a77970-add-MMC-support.patch new file mode 100644 index 00000000..a166973f --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0210-arm64-dts-renesas-r8a77970-add-MMC-support.patch @@ -0,0 +1,44 @@ +From 2b59da4cd554a6bbbd89f6417e0a188d1eba1118 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Tue, 21 Aug 2018 22:49:26 +0300 +Subject: [PATCH 030/211] arm64: dts: renesas: r8a77970: add MMC support + +Define the generic R8A77970 part of the MMC0 (SDHI2) device node. + +Based on the original (and large) patches by Vladimir Barinov. + +Signed-off-by: Vladimir Barinov +Signed-off-by: Sergei Shtylyov +Signed-off-by: Simon Horman +(cherry picked from commit 979e32b5265d6b42a568e950c5b5e2f6ab283ff3) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970.dtsi | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +index 96feaa0..f4b0270 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +@@ -754,6 +754,18 @@ + #iommu-cells = <1>; + }; + ++ mmc0: mmc@ee140000 { ++ compatible = "renesas,sdhi-r8a77970", ++ "renesas,rcar-gen3-sdhi"; ++ reg = <0 0xee140000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 314>; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ resets = <&cpg 314>; ++ max-frequency = <200000000>; ++ status = "disabled"; ++ }; ++ + gic: interrupt-controller@f1010000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0211-arm64-dts-renesas-v3msk-add-eMMC-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0211-arm64-dts-renesas-v3msk-add-eMMC-support.patch new file mode 100644 index 00000000..e27a8381 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0211-arm64-dts-renesas-v3msk-add-eMMC-support.patch @@ -0,0 +1,72 @@ +From 03b37015831c2f575276e140cf7b8ca6a3b31b22 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Tue, 21 Aug 2018 22:50:31 +0300 +Subject: [PATCH 031/211] arm64: dts: renesas: v3msk: add eMMC support + +Add the eMMC chip support for the V3M Started Kit board. + +Based on the original (and large) patches by Vladimir Barinov. + +Signed-off-by: Vladimir Barinov +Signed-off-by: Sergei Shtylyov +Signed-off-by: Simon Horman +(cherry picked from commit 8d9923b3a2f6c0e4ad3f9d9cad6e9010cf0d67e6) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +index 8eac8ca..0dbcb4c 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +@@ -51,6 +51,15 @@ + regulator-always-on; + }; + ++ vcc_vddq_vin0: regulator-2 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VCC_VDDQ_VIN0"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ + lvds-decoder { + compatible = "thine,thc63lvd1024"; + vcc-supply = <&vcc_d3_3v>; +@@ -128,6 +137,12 @@ + function = "i2c0"; + }; + ++ mmc_pins: mmc_3_3v { ++ groups = "mmc_data8", "mmc_ctrl"; ++ function = "mmc"; ++ power-source = <3300>; ++ }; ++ + scif0_pins: scif0 { + groups = "scif0_data"; + function = "scif0"; +@@ -192,6 +207,17 @@ + }; + }; + ++&mmc0 { ++ pinctrl-0 = <&mmc_pins>; ++ pinctrl-names = "default"; ++ ++ vmmc-supply = <&vcc_d3_3v>; ++ vqmmc-supply = <&vcc_vddq_vin0>; ++ bus-width = <8>; ++ non-removable; ++ status = "okay"; ++}; ++ + &scif0 { + pinctrl-0 = <&scif0_pins>; + pinctrl-names = "default"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0212-arm64-dts-renesas-condor-v3hsk-add-DU-LVDS-HDMI-supp.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0212-arm64-dts-renesas-condor-v3hsk-add-DU-LVDS-HDMI-supp.patch new file mode 100644 index 00000000..6349fabf --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0212-arm64-dts-renesas-condor-v3hsk-add-DU-LVDS-HDMI-supp.patch @@ -0,0 +1,312 @@ +From 57a51e0b21a62757886386da60e8c0724b43e36a Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Thu, 23 Aug 2018 19:59:20 +0300 +Subject: [PATCH 032/211] arm64: dts: renesas: condor/v3hsk: add DU/LVDS/HDMI + support + +Define the Condor/V3HSK board dependent parts of the DU and LVDS device +nodes. Also add the device nodes for Thine THC63LVD1024 LVDS decoder and +Analog Devices ADV7511W HDMI transmitter... + +Based on the original (and large) patch by Vladimir Barinov. + +Signed-off-by: Vladimir Barinov +Signed-off-by: Sergei Shtylyov +Reviewed-by: Ulrich Hecht +Reviewed-by: Laurent Pinchart +Signed-off-by: Simon Horman +(cherry picked from commit 70fd8b6a4846362991ead7b68f951d519a9c71df) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980-condor.dts | 106 +++++++++++++++++++ + arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts | 129 ++++++++++++++++++++++++ + 2 files changed, 235 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +index 494f4ef..59db4c1 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +@@ -45,6 +45,56 @@ + regulator-boot-on; + regulator-always-on; + }; ++ ++ d1_8v: regulator-2 { ++ compatible = "regulator-fixed"; ++ regulator-name = "D1.8V"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ hdmi-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_con: endpoint { ++ remote-endpoint = <&adv7511_out>; ++ }; ++ }; ++ }; ++ ++ lvds-decoder { ++ compatible = "thine,thc63lvd1024"; ++ vcc-supply = <&d3_3v>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ thc63lvd1024_in: endpoint { ++ remote-endpoint = <&lvds0_out>; ++ }; ++ }; ++ ++ port@2 { ++ reg = <2>; ++ thc63lvd1024_out: endpoint { ++ remote-endpoint = <&adv7511_in>; ++ }; ++ }; ++ }; ++ }; ++ ++ x1_clk: x1-clock { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <148500000>; ++ }; + }; + + &avb { +@@ -74,6 +124,13 @@ + }; + }; + ++&du { ++ clocks = <&cpg CPG_MOD 724>, ++ <&x1_clk>; ++ clock-names = "du.0", "dclkin.0"; ++ status = "okay"; ++}; ++ + &extal_clk { + clock-frequency = <16666666>; + }; +@@ -102,6 +159,55 @@ + gpio-controller; + #gpio-cells = <2>; + }; ++ ++ hdmi@39 { ++ compatible = "adi,adv7511w"; ++ reg = <0x39>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <20 IRQ_TYPE_LEVEL_LOW>; ++ avdd-supply = <&d1_8v>; ++ dvdd-supply = <&d1_8v>; ++ pvdd-supply = <&d1_8v>; ++ bgvdd-supply = <&d1_8v>; ++ dvdd-3v-supply = <&d3_3v>; ++ ++ adi,input-depth = <8>; ++ adi,input-colorspace = "rgb"; ++ adi,input-clock = "1x"; ++ adi,input-style = <1>; ++ adi,input-justification = "evenly"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ adv7511_in: endpoint { ++ remote-endpoint = <&thc63lvd1024_out>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ adv7511_out: endpoint { ++ remote-endpoint = <&hdmi_con>; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&lvds0 { ++ status = "okay"; ++ ++ ports { ++ port@1 { ++ lvds0_out: endpoint { ++ remote-endpoint = <&thc63lvd1024_in>; ++ }; ++ }; ++ }; + }; + + &mmc0 { +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +index 9147d85..44ab734 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +@@ -27,6 +27,72 @@ + /* first 128MB is reserved for secure area. */ + reg = <0 0x48000000 0 0x78000000>; + }; ++ ++ hdmi-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_con: endpoint { ++ remote-endpoint = <&adv7511_out>; ++ }; ++ }; ++ }; ++ ++ lvds-decoder { ++ compatible = "thine,thc63lvd1024"; ++ vcc-supply = <&vcc3v3_d5>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ thc63lvd1024_in: endpoint { ++ remote-endpoint = <&lvds0_out>; ++ }; ++ }; ++ ++ port@2 { ++ reg = <2>; ++ thc63lvd1024_out: endpoint { ++ remote-endpoint = <&adv7511_in>; ++ }; ++ }; ++ }; ++ }; ++ ++ osc1_clk: osc1-clock { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <148500000>; ++ }; ++ ++ vcc1v8_d4: regulator-0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VCC1V8_D4"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ vcc3v3_d5: regulator-1 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VCC3V3_D5"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++}; ++ ++&du { ++ clocks = <&cpg CPG_MOD 724>, ++ <&osc1_clk>; ++ clock-names = "du.0", "dclkin.0"; ++ status = "okay"; + }; + + &extal_clk { +@@ -53,6 +119,64 @@ + }; + }; + ++&lvds0 { ++ status = "okay"; ++ ++ ports { ++ port@1 { ++ lvds0_out: endpoint { ++ remote-endpoint = <&thc63lvd1024_in>; ++ }; ++ }; ++ }; ++}; ++ ++&i2c0 { ++ pinctrl-0 = <&i2c0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ clock-frequency = <400000>; ++ ++ hdmi@39 { ++ compatible = "adi,adv7511w"; ++ #sound-dai-cells = <0>; ++ reg = <0x39>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <20 IRQ_TYPE_LEVEL_LOW>; ++ avdd-supply = <&vcc1v8_d4>; ++ dvdd-supply = <&vcc1v8_d4>; ++ pvdd-supply = <&vcc1v8_d4>; ++ bgvdd-supply = <&vcc1v8_d4>; ++ dvdd-3v-supply = <&vcc3v3_d5>; ++ ++ adi,input-depth = <8>; ++ adi,input-colorspace = "rgb"; ++ adi,input-clock = "1x"; ++ adi,input-style = <1>; ++ adi,input-justification = "evenly"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ adv7511_in: endpoint { ++ remote-endpoint = <&thc63lvd1024_out>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ adv7511_out: endpoint { ++ remote-endpoint = <&hdmi_con>; ++ }; ++ }; ++ }; ++ }; ++}; ++ + &pfc { + gether_pins: gether { + groups = "gether_mdio_a", "gether_rgmii", +@@ -60,6 +184,11 @@ + function = "gether"; + }; + ++ i2c0_pins: i2c0 { ++ groups = "i2c0"; ++ function = "i2c0"; ++ }; ++ + scif0_pins: scif0 { + groups = "scif0_data"; + function = "scif0"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0213-arm64-dts-renesas-r8a77980-add-PCIe-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0213-arm64-dts-renesas-r8a77980-add-PCIe-support.patch new file mode 100644 index 00000000..7202c432 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0213-arm64-dts-renesas-r8a77980-add-PCIe-support.patch @@ -0,0 +1,96 @@ +From 3c2e68276ac116a525359c306f9ff76d83ad8fad Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Mon, 27 Aug 2018 21:53:40 +0300 +Subject: [PATCH 033/211] arm64: dts: renesas: r8a77980: add PCIe support + +Describe the PCIe PHY, PCIEC, and PCIe bus clock in the R8A77980 device +tree. + +Based on the original (and large) patch by Vladimir Barinov. + +Signed-off-by: Vladimir Barinov +Signed-off-by: Sergei Shtylyov +Signed-off-by: Simon Horman +(cherry picked from commit ffa967e24c5817b48a3d5ecea2c12b9cdd807f0c) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 49 +++++++++++++++++++++++++++++++ + 1 file changed, 49 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index c099053..d58e9f2 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -98,6 +98,13 @@ + clock-frequency = <0>; + }; + ++ /* External PCIe clock - can be overridden by the board */ ++ pcie_bus_clk: pcie_bus { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <0>; ++ }; ++ + pmu_a53 { + compatible = "arm,cortex-a53-pmu"; + interrupts-extended = <&gic GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>, +@@ -437,6 +444,16 @@ + status = "disabled"; + }; + ++ pcie_phy: pcie-phy@e65d0000 { ++ compatible = "renesas,r8a77980-pcie-phy"; ++ reg = <0 0xe65d0000 0 0x8000>; ++ #phy-cells = <0>; ++ clocks = <&cpg CPG_MOD 319>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 319>; ++ status = "disabled"; ++ }; ++ + canfd: can@e66c0000 { + compatible = "renesas,r8a77980-canfd", + "renesas,rcar-gen3-canfd"; +@@ -1047,6 +1064,38 @@ + resets = <&cpg 408>; + }; + ++ pciec: pcie@fe000000 { ++ compatible = "renesas,pcie-r8a77980", ++ "renesas,pcie-rcar-gen3"; ++ reg = <0 0xfe000000 0 0x80000>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ bus-range = <0x00 0xff>; ++ device_type = "pci"; ++ ranges = < ++ 0x01000000 0 0x00000000 0 0xfe100000 0 0x0100000 ++ 0x02000000 0 0xfe200000 0 0xfe200000 0 0x0200000 ++ 0x02000000 0 0x30000000 0 0x30000000 0 0x8000000 ++ 0x42000000 0 0x38000000 0 0x38000000 0 0x8000000 ++ >; ++ dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 ++ 0 0x80000000>; ++ interrupts = , ++ , ++ ; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 0>; ++ interrupt-map = <0 0 0 0 &gic GIC_SPI 148 ++ IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&cpg CPG_MOD 319>, <&pcie_bus_clk>; ++ clock-names = "pcie", "pcie_bus"; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 319>; ++ phys = <&pcie_phy>; ++ phy-names = "pcie"; ++ status = "disabled"; ++ }; ++ + vspd0: vsp@fea20000 { + compatible = "renesas,vsp2"; + reg = <0 0xfea20000 0 0x5000>; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0214-arm64-dts-renesas-condor-add-PCIe-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0214-arm64-dts-renesas-condor-add-PCIe-support.patch new file mode 100644 index 00000000..6f4f4d64 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0214-arm64-dts-renesas-condor-add-PCIe-support.patch @@ -0,0 +1,45 @@ +From 61d409555937f91063cea81334fe8b7c89f7cdff Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Mon, 27 Aug 2018 21:54:35 +0300 +Subject: [PATCH 034/211] arm64: dts: renesas: condor: add PCIe support + +Enable PCIe PHY and PCIEC and specify the PCIe bus clock for the Condor +board. + +Based on the original (and large) patch by Vladimir Barinov. + +Signed-off-by: Vladimir Barinov +Signed-off-by: Sergei Shtylyov +Signed-off-by: Simon Horman +(cherry picked from commit c6eb20473f0b296c671dc6f7a7766ea6bedf2d59) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980-condor.dts | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +index 59db4c1..fe2e2c0 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +@@ -223,6 +223,18 @@ + status = "okay"; + }; + ++&pciec { ++ status = "okay"; ++}; ++ ++&pcie_bus_clk { ++ clock-frequency = <100000000>; ++}; ++ ++&pcie_phy { ++ status = "okay"; ++}; ++ + &pfc { + avb_pins: avb { + groups = "avb_mdio", "avb_rgmii"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0215-arm64-dts-renesas-v3hsk-Move-lvds0-node.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0215-arm64-dts-renesas-v3hsk-Move-lvds0-node.patch new file mode 100644 index 00000000..df40fc43 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0215-arm64-dts-renesas-v3hsk-Move-lvds0-node.patch @@ -0,0 +1,61 @@ +From b681b5c0577d05ffa6bfbcd964d7128bd1407985 Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Tue, 28 Aug 2018 16:15:40 +0200 +Subject: [PATCH 035/211] arm64: dts: renesas: v3hsk: Move lvds0 node + +To preserve alphabetical sort order. + +Fixes: 4edac426aff11a37 ("arm64: dts: renesas: condor/v3hsk: add DU/LVDS/HDMI support") +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Simon Horman +(cherry picked from commit 47d7f6822864a8cf2f09d27cb1321bd36ab6d9e4) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +index 44ab734..dd14a41 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +@@ -119,18 +119,6 @@ + }; + }; + +-&lvds0 { +- status = "okay"; +- +- ports { +- port@1 { +- lvds0_out: endpoint { +- remote-endpoint = <&thc63lvd1024_in>; +- }; +- }; +- }; +-}; +- + &i2c0 { + pinctrl-0 = <&i2c0_pins>; + pinctrl-names = "default"; +@@ -177,6 +165,18 @@ + }; + }; + ++&lvds0 { ++ status = "okay"; ++ ++ ports { ++ port@1 { ++ lvds0_out: endpoint { ++ remote-endpoint = <&thc63lvd1024_in>; ++ }; ++ }; ++ }; ++}; ++ + &pfc { + gether_pins: gether { + groups = "gether_mdio_a", "gether_rgmii", +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0216-arm64-dts-renesas-r8a77980-Attach-the-SYS-DMAC-to-th.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0216-arm64-dts-renesas-r8a77980-Attach-the-SYS-DMAC-to-th.patch new file mode 100644 index 00000000..7e47fe8d --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0216-arm64-dts-renesas-r8a77980-Attach-the-SYS-DMAC-to-th.patch @@ -0,0 +1,54 @@ +From 4ecddcb2708e1035d82808a315eee47f77d90805 Mon Sep 17 00:00:00 2001 +From: Magnus Damm +Date: Mon, 17 Sep 2018 17:53:05 +0900 +Subject: [PATCH 036/211] arm64: dts: renesas: r8a77980: Attach the SYS-DMAC to + the IPMMU + +For R-Car V3H hook up SYS-DMAC1 and SYS-DMAC2 to IPMMU-DS1 to match +information in the R-Car Gen3 Rev.1.00 (April 2018) datasheet. + +Signed-off-by: Magnus Damm +Signed-off-by: Simon Horman +(cherry picked from commit d59b0784f1e64ad84756b485c622e3ee0712b946) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index d58e9f2..7dd4ad2 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -924,6 +924,14 @@ + resets = <&cpg 218>; + #dma-cells = <1>; + dma-channels = <16>; ++ iommus = <&ipmmu_ds1 0>, <&ipmmu_ds1 1>, ++ <&ipmmu_ds1 2>, <&ipmmu_ds1 3>, ++ <&ipmmu_ds1 4>, <&ipmmu_ds1 5>, ++ <&ipmmu_ds1 6>, <&ipmmu_ds1 7>, ++ <&ipmmu_ds1 8>, <&ipmmu_ds1 9>, ++ <&ipmmu_ds1 10>, <&ipmmu_ds1 11>, ++ <&ipmmu_ds1 12>, <&ipmmu_ds1 13>, ++ <&ipmmu_ds1 14>, <&ipmmu_ds1 15>; + }; + + dmac2: dma-controller@e7310000 { +@@ -958,6 +966,14 @@ + resets = <&cpg 217>; + #dma-cells = <1>; + dma-channels = <16>; ++ iommus = <&ipmmu_ds1 16>, <&ipmmu_ds1 17>, ++ <&ipmmu_ds1 18>, <&ipmmu_ds1 19>, ++ <&ipmmu_ds1 20>, <&ipmmu_ds1 21>, ++ <&ipmmu_ds1 22>, <&ipmmu_ds1 23>, ++ <&ipmmu_ds1 24>, <&ipmmu_ds1 25>, ++ <&ipmmu_ds1 26>, <&ipmmu_ds1 27>, ++ <&ipmmu_ds1 28>, <&ipmmu_ds1 29>, ++ <&ipmmu_ds1 30>, <&ipmmu_ds1 31>; + }; + + gether: ethernet@e7400000 { +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0217-arm64-dts-renesas-r8a779-7-8-0-add-CMT-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0217-arm64-dts-renesas-r8a779-7-8-0-add-CMT-support.patch new file mode 100644 index 00000000..b5bdf788 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0217-arm64-dts-renesas-r8a779-7-8-0-add-CMT-support.patch @@ -0,0 +1,185 @@ +From a0eacde243624af6648986c8f38caea744a4e5f8 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Fri, 7 Sep 2018 21:58:41 +0300 +Subject: [PATCH 037/211] arm64: dts: renesas: r8a779{7|8}0: add CMT support + +Describe CMTs in the R8A779{7|8}0 device trees. + +Based on the original (and large) patches by Vladimir Barinov. + +Signed-off-by: Vladimir Barinov +Signed-off-by: Sergei Shtylyov +Reviewed-by: Geert Uytterhoeven +Signed-off-by: Simon Horman +(cherry picked from commit a215af751dc5d24b4e3a8fc9976ae95737843934) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970.dtsi | 70 +++++++++++++++++++++++++++++++ + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 70 +++++++++++++++++++++++++++++++ + 2 files changed, 140 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +index f4b0270..934a15f 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +@@ -209,6 +209,76 @@ + reg = <0 0xe6060000 0 0x504>; + }; + ++ cmt0: timer@e60f0000 { ++ compatible = "renesas,r8a77970-cmt0", ++ "renesas,rcar-gen3-cmt0"; ++ reg = <0 0xe60f0000 0 0x1004>; ++ interrupts = , ++ ; ++ clocks = <&cpg CPG_MOD 303>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ resets = <&cpg 303>; ++ status = "disabled"; ++ }; ++ ++ cmt1: timer@e6130000 { ++ compatible = "renesas,r8a77970-cmt1", ++ "renesas,rcar-gen3-cmt1"; ++ reg = <0 0xe6130000 0 0x1004>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 302>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ resets = <&cpg 302>; ++ status = "disabled"; ++ }; ++ ++ cmt2: timer@e6140000 { ++ compatible = "renesas,r8a77970-cmt1", ++ "renesas,rcar-gen3-cmt1"; ++ reg = <0 0xe6140000 0 0x1004>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 301>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ resets = <&cpg 301>; ++ status = "disabled"; ++ }; ++ ++ cmt3: timer@e6148000 { ++ compatible = "renesas,r8a77970-cmt1", ++ "renesas,rcar-gen3-cmt1"; ++ reg = <0 0xe6148000 0 0x1004>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 300>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ resets = <&cpg 300>; ++ status = "disabled"; ++ }; ++ + cpg: clock-controller@e6150000 { + compatible = "renesas,r8a77970-cpg-mssr"; + reg = <0 0xe6150000 0 0x1000>; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index 7dd4ad2..cb135f6 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -239,6 +239,76 @@ + reg = <0 0xe6060000 0 0x50c>; + }; + ++ cmt0: timer@e60f0000 { ++ compatible = "renesas,r8a77980-cmt0", ++ "renesas,rcar-gen3-cmt0"; ++ reg = <0 0xe60f0000 0 0x1004>; ++ interrupts = , ++ ; ++ clocks = <&cpg CPG_MOD 303>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 303>; ++ status = "disabled"; ++ }; ++ ++ cmt1: timer@e6130000 { ++ compatible = "renesas,r8a77980-cmt1", ++ "renesas,rcar-gen3-cmt1"; ++ reg = <0 0xe6130000 0 0x1004>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 302>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 302>; ++ status = "disabled"; ++ }; ++ ++ cmt2: timer@e6140000 { ++ compatible = "renesas,r8a77980-cmt1", ++ "renesas,rcar-gen3-cmt1"; ++ reg = <0 0xe6140000 0 0x1004>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 301>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 301>; ++ status = "disabled"; ++ }; ++ ++ cmt3: timer@e6148000 { ++ compatible = "renesas,r8a77980-cmt1", ++ "renesas,rcar-gen3-cmt1"; ++ reg = <0 0xe6148000 0 0x1004>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 300>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 300>; ++ status = "disabled"; ++ }; ++ + cpg: clock-controller@e6150000 { + compatible = "renesas,r8a77980-cpg-mssr"; + reg = <0 0xe6150000 0 0x1000>; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0218-dt-bindings-timer-renesas-tmu-document-R8A779-7-8-0-.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0218-dt-bindings-timer-renesas-tmu-document-R8A779-7-8-0-.patch new file mode 100644 index 00000000..9bbd07e8 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0218-dt-bindings-timer-renesas-tmu-document-R8A779-7-8-0-.patch @@ -0,0 +1,34 @@ +From 5d6939bac638468832c76cf3564576a712542859 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Fri, 7 Sep 2018 23:02:53 +0300 +Subject: [PATCH 038/211] dt-bindings: timer: renesas: tmu: document + R8A779{7|8}0 bindings + +Document the R-Car V3{M|H} (R8A779{7|8}0) SoC in the Renesas TMU bindings; +the TMU hardware in those is the Renesas standard 3-channel timer unit. + +Signed-off-by: Sergei Shtylyov +Reviewed-by: Geert Uytterhoeven +Signed-off-by: Simon Horman +(cherry picked from commit 5851fa4d088747af4a141110541594a2a4479b12) +Signed-off-by: Valentine Barshak +--- + Documentation/devicetree/bindings/timer/renesas,tmu.txt | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/Documentation/devicetree/bindings/timer/renesas,tmu.txt b/Documentation/devicetree/bindings/timer/renesas,tmu.txt +index cd5f20b..4ddff85 100644 +--- a/Documentation/devicetree/bindings/timer/renesas,tmu.txt ++++ b/Documentation/devicetree/bindings/timer/renesas,tmu.txt +@@ -12,6 +12,8 @@ Required Properties: + - "renesas,tmu-r8a7740" for the r8a7740 TMU + - "renesas,tmu-r8a7778" for the r8a7778 TMU + - "renesas,tmu-r8a7779" for the r8a7779 TMU ++ - "renesas,tmu-r8a77970" for the r8a77970 TMU ++ - "renesas,tmu-r8a77980" for the r8a77980 TMU + - "renesas,tmu" for any TMU. + This is a fallback for the above renesas,tmu-* entries + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0219-arm64-dts-renesas-r8a779-7-8-0-add-TPU-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0219-arm64-dts-renesas-r8a779-7-8-0-add-TPU-support.patch new file mode 100644 index 00000000..7f2a8b94 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0219-arm64-dts-renesas-r8a779-7-8-0-add-TPU-support.patch @@ -0,0 +1,66 @@ +From 09a60708855e01599deb5993dd4c2a89aa638e1e Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Mon, 24 Sep 2018 21:33:00 +0300 +Subject: [PATCH 039/211] arm64: dts: renesas: r8a779{7|8}0: add TPU support + +Describe TPU in the R8A779{7|8}0 device trees. + +Based on the original (and large) patches by Vladimir Barinov. + +Signed-off-by: Vladimir Barinov +Signed-off-by: Sergei Shtylyov +Reviewed-by: Geert Uytterhoeven +Signed-off-by: Simon Horman +(cherry picked from commit dd809b7de27cff710658febdde65304ec1a3ea82) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970.dtsi | 10 ++++++++++ + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 11 +++++++++++ + 2 files changed, 21 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +index 934a15f..cba7885 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +@@ -614,6 +614,16 @@ + status = "disabled"; + }; + ++ tpu: pwm@e6e80000 { ++ compatible = "renesas,tpu-r8a77970", "renesas,tpu"; ++ reg = <0 0xe6e80000 0 0x148>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 304>; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ resets = <&cpg 304>; ++ #pwm-cells = <3>; ++ status = "disabled"; ++ }; + + vin0: video@e6ef0000 { + compatible = "renesas,vin-r8a77970"; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index cb135f6..a5cba94 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -666,6 +666,17 @@ + status = "disabled"; + }; + ++ tpu: pwm@e6e80000 { ++ compatible = "renesas,tpu-r8a77980", "renesas,tpu"; ++ reg = <0 0xe6e80000 0 0x148>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 304>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 304>; ++ #pwm-cells = <3>; ++ status = "disabled"; ++ }; ++ + vin0: video@e6ef0000 { + compatible = "renesas,vin-r8a77980"; + reg = <0 0xe6ef0000 0 0x1000>; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0220-arm64-dts-renesas-r8a779-7-8-0-add-PWM-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0220-arm64-dts-renesas-r8a779-7-8-0-add-PWM-support.patch new file mode 100644 index 00000000..3c6b2378 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0220-arm64-dts-renesas-r8a779-7-8-0-add-PWM-support.patch @@ -0,0 +1,145 @@ +From f91a8bff14bb02353e97de882a3dede67986165e Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Mon, 1 Oct 2018 23:25:43 +0300 +Subject: [PATCH 040/211] arm64: dts: renesas: r8a779{7|8}0: add PWM support + +Describe PWMs in the R8A779{7|8}0 device trees. + +Based on the original (and large) patches by Vladimir Barinov. + +Signed-off-by: Vladimir Barinov +Signed-off-by: Sergei Shtylyov +Reviewed-by: Geert Uytterhoeven +Signed-off-by: Simon Horman +(cherry picked from commit b729c69f1d41b819f662e461f0ca793bb009f746) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970.dtsi | 50 +++++++++++++++++++++++++++++++ + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 50 +++++++++++++++++++++++++++++++ + 2 files changed, 100 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +index cba7885..e58040e 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +@@ -543,6 +543,56 @@ + status = "disabled"; + }; + ++ pwm0: pwm@e6e30000 { ++ compatible = "renesas,pwm-r8a77970", "renesas,pwm-rcar"; ++ reg = <0 0xe6e30000 0 8>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ resets = <&cpg 523>; ++ status = "disabled"; ++ }; ++ ++ pwm1: pwm@e6e31000 { ++ compatible = "renesas,pwm-r8a77970", "renesas,pwm-rcar"; ++ reg = <0 0xe6e31000 0 8>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ resets = <&cpg 523>; ++ status = "disabled"; ++ }; ++ ++ pwm2: pwm@e6e32000 { ++ compatible = "renesas,pwm-r8a77970", "renesas,pwm-rcar"; ++ reg = <0 0xe6e32000 0 8>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ resets = <&cpg 523>; ++ status = "disabled"; ++ }; ++ ++ pwm3: pwm@e6e33000 { ++ compatible = "renesas,pwm-r8a7790", "renesas,pwm-rcar"; ++ reg = <0 0xe6e33000 0 8>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ resets = <&cpg 523>; ++ status = "disabled"; ++ }; ++ ++ pwm4: pwm@e6e34000 { ++ compatible = "renesas,pwm-r8a77970", "renesas,pwm-rcar"; ++ reg = <0 0xe6e34000 0 8>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ resets = <&cpg 523>; ++ status = "disabled"; ++ }; ++ + scif0: serial@e6e60000 { + compatible = "renesas,scif-r8a77970", + "renesas,rcar-gen3-scif", +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index a5cba94..53d5dce 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -594,6 +594,56 @@ + status = "disabled"; + }; + ++ pwm0: pwm@e6e30000 { ++ compatible = "renesas,pwm-r8a77980", "renesas,pwm-rcar"; ++ reg = <0 0xe6e30000 0 0x10>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 523>; ++ status = "disabled"; ++ }; ++ ++ pwm1: pwm@e6e31000 { ++ compatible = "renesas,pwm-r8a77980", "renesas,pwm-rcar"; ++ reg = <0 0xe6e31000 0 0x10>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 523>; ++ status = "disabled"; ++ }; ++ ++ pwm2: pwm@e6e32000 { ++ compatible = "renesas,pwm-r8a77980", "renesas,pwm-rcar"; ++ reg = <0 0xe6e32000 0 0x10>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 523>; ++ status = "disabled"; ++ }; ++ ++ pwm3: pwm@e6e33000 { ++ compatible = "renesas,pwm-r8a77980", "renesas,pwm-rcar"; ++ reg = <0 0xe6e33000 0 0x10>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 523>; ++ status = "disabled"; ++ }; ++ ++ pwm4: pwm@e6e34000 { ++ compatible = "renesas,pwm-r8a77980", "renesas,pwm-rcar"; ++ reg = <0 0xe6e34000 0 0x10>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 523>; ++ status = "disabled"; ++ }; ++ + scif0: serial@e6e60000 { + compatible = "renesas,scif-r8a77980", + "renesas,rcar-gen3-scif", +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0221-media-vsp1-Use-header-display-lists-for-all-WPF-outp.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0221-media-vsp1-Use-header-display-lists-for-all-WPF-outp.patch new file mode 100644 index 00000000..829a07d4 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0221-media-vsp1-Use-header-display-lists-for-all-WPF-outp.patch @@ -0,0 +1,274 @@ +From a35f2ec07393895a134d6ff993fa23454f3fbcad Mon Sep 17 00:00:00 2001 +From: Kieran Bingham +Date: Fri, 3 Aug 2018 07:37:26 -0400 +Subject: [PATCH 041/211] media: vsp1: Use header display lists for all WPF + outputs linked to the DU + +Header mode display lists are now supported on all WPF outputs. To +support extended headers and auto-fld capabilities for interlaced mode +handling only header mode display lists can be used. + +Disable the headerless display list configuration, and remove the dead +code. + +Signed-off-by: Kieran Bingham +Signed-off-by: Laurent Pinchart +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit 08e41f6219c717d16bb22b53010ee7401c27fb11) +[valentine.barshak: resolved conflicts due to commits: 693d3a9, 3469001] +Signed-off-by: Valentine Barshak +--- + drivers/media/platform/vsp1/vsp1_dl.c | 127 ++++++++-------------------------- + 1 file changed, 30 insertions(+), 97 deletions(-) + +diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c +index 925f8a7..48542854 100644 +--- a/drivers/media/platform/vsp1/vsp1_dl.c ++++ b/drivers/media/platform/vsp1/vsp1_dl.c +@@ -129,7 +129,7 @@ struct vsp1_dl_body_pool { + * struct vsp1_dl_list - Display list + * @list: entry in the display list manager lists + * @dlm: the display list manager +- * @header: display list header, NULL for headerless lists ++ * @header: display list header + * @dma: DMA address for the header + * @body0: first display list body + * @bodies: list of extra display list bodies +@@ -153,15 +153,9 @@ struct vsp1_dl_list { + bool internal; + }; + +-enum vsp1_dl_mode { +- VSP1_DL_MODE_HEADER, +- VSP1_DL_MODE_HEADERLESS, +-}; +- + /** + * struct vsp1_dl_manager - Display List manager + * @index: index of the related WPF +- * @mode: display list operation mode (header or headerless) + * @singleshot: execute the display list in single-shot mode + * @vsp1: the VSP1 device + * @lock: protects the free, active, queued, and pending lists +@@ -173,7 +167,6 @@ enum vsp1_dl_mode { + */ + struct vsp1_dl_manager { + unsigned int index; +- enum vsp1_dl_mode mode; + bool singleshot; + struct vsp1_device *vsp1; + +@@ -448,6 +441,7 @@ void vsp1_dl_set_addr_auto_fld(struct vsp1_dl_body *dlb, + static struct vsp1_dl_list *vsp1_dl_list_alloc(struct vsp1_dl_manager *dlm) + { + struct vsp1_dl_list *dl; ++ size_t header_offset; + + dl = kzalloc(sizeof(*dl), GFP_KERNEL); + if (!dl) +@@ -460,16 +454,14 @@ static struct vsp1_dl_list *vsp1_dl_list_alloc(struct vsp1_dl_manager *dlm) + dl->body0 = vsp1_dl_body_get(dlm->pool); + if (!dl->body0) + return NULL; +- if (dlm->mode == VSP1_DL_MODE_HEADER) { +- size_t header_offset = dl->body0->max_entries +- * sizeof(*dl->body0->entries); + +- dl->header = ((void *)dl->body0->entries) + header_offset; +- dl->dma = dl->body0->dma + header_offset; ++ header_offset = dl->body0->max_entries * sizeof(*dl->body0->entries); + +- memset(dl->header, 0, sizeof(*dl->header)); +- dl->header->lists[0].addr = dl->body0->dma; +- } ++ dl->header = ((void *)dl->body0->entries) + header_offset; ++ dl->dma = dl->body0->dma + header_offset; ++ ++ memset(dl->header, 0, sizeof(*dl->header)); ++ dl->header->lists[0].addr = dl->body0->dma; + + return dl; + } +@@ -601,16 +593,9 @@ struct vsp1_dl_body *vsp1_dl_list_get_body0(struct vsp1_dl_list *dl) + * + * The reference must be explicitly released by a call to vsp1_dl_body_put() + * when the body isn't needed anymore. +- * +- * Additional bodies are only usable for display lists in header mode. +- * Attempting to add a body to a header-less display list will return an error. + */ + int vsp1_dl_list_add_body(struct vsp1_dl_list *dl, struct vsp1_dl_body *dlb) + { +- /* Multi-body lists are only available in header mode. */ +- if (dl->dlm->mode != VSP1_DL_MODE_HEADER) +- return -EINVAL; +- + refcount_inc(&dlb->refcnt); + + list_add_tail(&dlb->list, &dl->bodies); +@@ -631,17 +616,10 @@ int vsp1_dl_list_add_body(struct vsp1_dl_list *dl, struct vsp1_dl_body *dlb) + * Adding a display list to a chain passes ownership of the display list to + * the head display list item. The chain is released when the head dl item is + * put back with __vsp1_dl_list_put(). +- * +- * Chained display lists are only usable in header mode. Attempts to add a +- * display list to a chain in header-less mode will return an error. + */ + int vsp1_dl_list_add_chain(struct vsp1_dl_list *head, + struct vsp1_dl_list *dl) + { +- /* Chained lists are only available in header mode. */ +- if (head->dlm->mode != VSP1_DL_MODE_HEADER) +- return -EINVAL; +- + head->has_chain = true; + list_add_tail(&dl->chain, &head->chain); + return 0; +@@ -744,17 +722,10 @@ static bool vsp1_dl_list_hw_update_pending(struct vsp1_dl_manager *dlm) + return false; + + /* +- * Check whether the VSP1 has taken the update. In headerless mode the +- * hardware indicates this by clearing the UPD bit in the DL_BODY_SIZE +- * register, and in header mode by clearing the UPDHDR bit in the CMD +- * register. ++ * Check whether the VSP1 has taken the update. The hardware indicates ++ * this by clearing the UPDHDR bit in the CMD register. + */ +- if (dlm->mode == VSP1_DL_MODE_HEADERLESS) +- return !!(vsp1_read(vsp1, VI6_DL_BODY_SIZE) +- & VI6_DL_BODY_SIZE_UPD); +- else +- return !!(vsp1_read(vsp1, VI6_CMD(dlm->index)) +- & VI6_CMD_UPDHDR); ++ return !!(vsp1_read(vsp1, VI6_CMD(dlm->index)) & VI6_CMD_UPDHDR); + } + + static void vsp1_dl_list_hw_enqueue(struct vsp1_dl_list *dl) +@@ -762,34 +733,16 @@ static void vsp1_dl_list_hw_enqueue(struct vsp1_dl_list *dl) + struct vsp1_dl_manager *dlm = dl->dlm; + struct vsp1_device *vsp1 = dlm->vsp1; + +- if (dlm->mode == VSP1_DL_MODE_HEADERLESS) { +- /* +- * In headerless mode, program the hardware directly with the +- * display list body address and size and set the UPD bit. The +- * bit will be cleared by the hardware when the display list +- * processing starts. +- */ +- vsp1_write(vsp1, VI6_DL_HDR_ADDR(0), dl->body0->dma); +- vsp1_write(vsp1, VI6_DL_BODY_SIZE, VI6_DL_BODY_SIZE_UPD | +- (dl->body0->num_entries * sizeof(*dl->header->lists))); +- if (vsp1->ths_quirks & VSP1_UNDERRUN_WORKAROUND) { +- vsp1->dl_addr = dl->body0->dma; +- vsp1->dl_body = VI6_DL_BODY_SIZE_UPD | +- (dl->body0->num_entries * +- sizeof(*dl->header->lists)); +- } +- } else { +- /* +- * In header mode, program the display list header address. If +- * the hardware is idle (single-shot mode or first frame in +- * continuous mode) it will then be started independently. If +- * the hardware is operating, the VI6_DL_HDR_REF_ADDR register +- * will be updated with the display list address. +- */ +- vsp1_write(vsp1, VI6_DL_HDR_ADDR(dlm->index), dl->dma); +- if (vsp1->ths_quirks & VSP1_UNDERRUN_WORKAROUND) +- vsp1->dl_addr = dl->dma; +- } ++ /* ++ * Program the display list header address. If the hardware is idle ++ * (single-shot mode or first frame in continuous mode) it will then be ++ * started independently. If the hardware is operating, the ++ * VI6_DL_HDR_REF_ADDR register will be updated with the display list ++ * address. ++ */ ++ vsp1_write(vsp1, VI6_DL_HDR_ADDR(dlm->index), dl->dma); ++ if (vsp1->ths_quirks & VSP1_UNDERRUN_WORKAROUND) ++ vsp1->dl_addr = dl->dma; + } + + static void vsp1_dl_list_commit_continuous(struct vsp1_dl_list *dl) +@@ -848,16 +801,14 @@ void vsp1_dl_list_commit(struct vsp1_dl_list *dl, bool internal, + struct vsp1_dl_list *dl_child; + unsigned long flags; + +- if (dlm->mode == VSP1_DL_MODE_HEADER) { +- /* Fill the header for the head and chained display lists. */ +- vsp1_dl_list_fill_header(dl, list_empty(&dl->chain), +- pipe_index); ++ /* Fill the header for the head and chained display lists. */ ++ vsp1_dl_list_fill_header(dl, list_empty(&dl->chain), ++ pipe_index); + +- list_for_each_entry(dl_child, &dl->chain, chain) { +- bool last = list_is_last(&dl_child->chain, &dl->chain); ++ list_for_each_entry(dl_child, &dl->chain, chain) { ++ bool last = list_is_last(&dl_child->chain, &dl->chain); + +- vsp1_dl_list_fill_header(dl_child, last, pipe_index); +- } ++ vsp1_dl_list_fill_header(dl_child, last, pipe_index); + } + + dl->internal = internal; +@@ -886,7 +837,7 @@ void vsp1_dl_list_commit(struct vsp1_dl_list *dl, bool internal, + * has completed at frame end. If the flag is not returned display list + * completion has been delayed by one frame because the display list commit + * raced with the frame end interrupt. The function always returns with the flag +- * set in header mode as display list processing is then not continuous and ++ * set in single-shot mode as display list processing is then not continuous and + * races never occur. + * + * The VSP1_DL_FRAME_END_INTERNAL flag indicates that the previous display list +@@ -970,13 +921,6 @@ void vsp1_dlm_setup(struct vsp1_device *vsp1, unsigned int pipe_index) + (0x02 << VI6_DL_EXT_CTRL_POLINT_SHIFT) | + VI6_DL_EXT_CTRL_DLPRI | VI6_DL_EXT_CTRL_EXT); + } +- /* +- * The DRM pipeline operates with display lists in Continuous Frame +- * Mode, all other pipelines use manual start. +- */ +- if (vsp1->drm && vsp1->info->uapi) +- ctrl |= VI6_DL_CTRL_CFM0 | VI6_DL_CTRL_NH0; +- + vsp1_write(vsp1, VI6_DL_CTRL, ctrl); + vsp1_write(vsp1, VI6_DL_SWAP(pipe_index), VI6_DL_SWAP_LWS | + ((pipe_index == 1) ? VI6_DL_SWAP_IND : 0)); +@@ -1017,15 +961,6 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1, + return NULL; + + dlm->index = index; +- dlm->mode = index == 0 && !vsp1->info->uapi +- ? VSP1_DL_MODE_HEADERLESS : VSP1_DL_MODE_HEADER; +- +- if (((vsp1->version & VI6_IP_VERSION_MODEL_MASK) == +- VI6_IP_VERSION_MODEL_VSPDL_GEN3) || +- (vsp1->version & VI6_IP_VERSION_MODEL_MASK) == +- VI6_IP_VERSION_MODEL_VSPD_GEN3) +- dlm->mode = VSP1_DL_MODE_HEADER; +- + dlm->singleshot = vsp1->info->uapi; + dlm->vsp1 = vsp1; + +@@ -1034,14 +969,12 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1, + + /* + * Initialize the display list body and allocate DMA memory for the body +- * and the optional header. Both are allocated together to avoid memory ++ * and the header. Both are allocated together to avoid memory + * fragmentation, with the header located right after the body in + * memory. An extra body is allocated on top of the prealloc to account + * for the cached body used by the vsp1_pipeline object. + */ +- header_size = dlm->mode == VSP1_DL_MODE_HEADER +- ? ALIGN(sizeof(struct vsp1_dl_header), 8) +- : 0; ++ header_size = ALIGN(sizeof(struct vsp1_dl_header), 8); + + if (!vsp1->info->uapi && + !(vsp1->ths_quirks & VSP1_AUTO_FLD_NOT_SUPPORT)) { +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0222-arm64-dts-renesas-r8a77970-add-thermal-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0222-arm64-dts-renesas-r8a77970-add-thermal-support.patch new file mode 100644 index 00000000..ed894a51 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0222-arm64-dts-renesas-r8a77970-add-thermal-support.patch @@ -0,0 +1,72 @@ +From 1db57fb02780239e6f00e9c1083ee1caefb794c3 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Tue, 9 Oct 2018 22:47:47 +0300 +Subject: [PATCH 042/211] arm64: dts: renesas: r8a77970: add thermal support + +Describe THS/CIVM in the R8A77970 device tree. + +Based on the original (and large) patches by Vladimir Barinov. + +Signed-off-by: Vladimir Barinov +Signed-off-by: Sergei Shtylyov +Reviewed-by: Geert Uytterhoeven +Signed-off-by: Simon Horman +(cherry picked from commit c980ed422cd3e82accd1ca40be9501e5134aac5f) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970.dtsi | 32 +++++++++++++++++++++++++++++++ + 1 file changed, 32 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +index e58040e..ba903fc 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +@@ -300,6 +300,19 @@ + #power-domain-cells = <1>; + }; + ++ thermal: thermal@e6190000 { ++ compatible = "renesas,thermal-r8a77970"; ++ reg = <0 0xe6190000 0 0x10 ++ 0 0xe6190100 0 0x120>; ++ interrupts = , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 522>; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ resets = <&cpg 522>; ++ #thermal-sensor-cells = <0>; ++ }; ++ + intc_ex: interrupt-controller@e61c0000 { + compatible = "renesas,intc-ex-r8a77970", "renesas,irqc"; + #interrupt-cells = <2>; +@@ -1033,6 +1046,25 @@ + }; + }; + ++ thermal-zones { ++ cpu-thermal { ++ polling-delay-passive = <250>; ++ polling-delay = <1000>; ++ thermal-sensors = <&thermal>; ++ ++ trips { ++ cpu-crit { ++ temperature = <120000>; ++ hysteresis = <2000>; ++ type = "critical"; ++ }; ++ }; ++ ++ cooling-maps { ++ }; ++ }; ++ }; ++ + timer { + compatible = "arm,armv8-timer"; + interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0223-arm64-dts-renesas-r8a77980-add-thermal-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0223-arm64-dts-renesas-r8a77980-add-thermal-support.patch new file mode 100644 index 00000000..32e26b6f --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0223-arm64-dts-renesas-r8a77980-add-thermal-support.patch @@ -0,0 +1,93 @@ +From aedd723e67490511738a4da0c0065999eb8925cc Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Wed, 10 Oct 2018 22:18:11 +0300 +Subject: [PATCH 043/211] arm64: dts: renesas: r8a77980: add thermal support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Describe THS/CIVM in the R8A77980 device trees. + +Signed-off-by: Sergei Shtylyov +Reviewed-by: Niklas Söderlund +Signed-off-by: Simon Horman +(cherry picked from commit 4229ee439a2d8bead6c49145b1b2ca7b69e008c0) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 53 +++++++++++++++++++++++++++++++ + 1 file changed, 53 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index 53d5dce..f2c32b5 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -330,6 +330,19 @@ + #power-domain-cells = <1>; + }; + ++ tsc: thermal@e6198000 { ++ compatible = "renesas,r8a77980-thermal"; ++ reg = <0 0xe6198000 0 0x100>, ++ <0 0xe61a0000 0 0x100>; ++ interrupts = , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 522>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 522>; ++ #thermal-sensor-cells = <1>; ++ }; ++ + intc_ex: interrupt-controller@e61c0000 { + compatible = "renesas,intc-ex-r8a77980", "renesas,irqc"; + #interrupt-cells = <2>; +@@ -1404,6 +1417,46 @@ + }; + }; + ++ thermal-zones { ++ thermal-sensor-1 { ++ polling-delay-passive = <250>; ++ polling-delay = <1000>; ++ thermal-sensors = <&tsc 0>; ++ ++ trips { ++ sensor1-passive { ++ temperature = <95000>; ++ hysteresis = <1000>; ++ type = "passive"; ++ }; ++ sensor1-critical { ++ temperature = <120000>; ++ hysteresis = <1000>; ++ type = "critical"; ++ }; ++ }; ++ }; ++ ++ thermal-sensor-2 { ++ polling-delay-passive = <250>; ++ polling-delay = <1000>; ++ thermal-sensors = <&tsc 1>; ++ ++ trips { ++ sensor2-passive { ++ temperature = <95000>; ++ hysteresis = <1000>; ++ type = "passive"; ++ }; ++ sensor2-critical { ++ temperature = <120000>; ++ hysteresis = <1000>; ++ type = "critical"; ++ }; ++ }; ++ }; ++ }; ++ + timer { + compatible = "arm,armv8-timer"; + interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0224-arm64-dts-renesas-r8a779-7-8-0-add-TMU-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0224-arm64-dts-renesas-r8a779-7-8-0-add-TMU-support.patch new file mode 100644 index 00000000..956716b4 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0224-arm64-dts-renesas-r8a779-7-8-0-add-TMU-support.patch @@ -0,0 +1,174 @@ +From 0d39e40c1c415f1912465f6b3d0ac35298499312 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Mon, 24 Sep 2018 23:13:41 +0300 +Subject: [PATCH 044/211] arm64: dts: renesas: r8a779{7|8}0: add TMU support + +Describe TMUs in the R8A779{7|8}0 device trees. + +Based on the original (and large) patches by Vladimir Barinov. + +Signed-off-by: Vladimir Barinov +Signed-off-by: Sergei Shtylyov +Signed-off-by: Simon Horman +(cherry picked from commit 09ff63cbc6a95f2d69d07e7a04883446ad710271) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970.dtsi | 65 +++++++++++++++++++++++++++++++ + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 65 +++++++++++++++++++++++++++++++ + 2 files changed, 130 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +index ba903fc..65f3ad4 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +@@ -329,6 +329,71 @@ + resets = <&cpg 407>; + }; + ++ tmu0: timer@e61e0000 { ++ compatible = "renesas,tmu-r8a77970", "renesas,tmu"; ++ reg = <0 0xe61e0000 0 0x30>; ++ interrupts = , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 125>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ resets = <&cpg 125>; ++ status = "disabled"; ++ }; ++ ++ tmu1: timer@e6fc0000 { ++ compatible = "renesas,tmu-r8a77970", "renesas,tmu"; ++ reg = <0 0xe6fc0000 0 0x30>; ++ interrupts = , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 124>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ resets = <&cpg 124>; ++ status = "disabled"; ++ }; ++ ++ tmu2: timer@e6fd0000 { ++ compatible = "renesas,tmu-r8a77970", "renesas,tmu"; ++ reg = <0 0xe6fd0000 0 0x30>; ++ interrupts = , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 123>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ resets = <&cpg 123>; ++ status = "disabled"; ++ }; ++ ++ tmu3: timer@e6fe0000 { ++ compatible = "renesas,tmu-r8a77970", "renesas,tmu"; ++ reg = <0 0xe6fe0000 0 0x30>; ++ interrupts = , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 122>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ resets = <&cpg 122>; ++ status = "disabled"; ++ }; ++ ++ tmu4: timer@ffc00000 { ++ compatible = "renesas,tmu-r8a77970", "renesas,tmu"; ++ reg = <0 0xffc00000 0 0x30>; ++ interrupts = , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 121>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ resets = <&cpg 121>; ++ status = "disabled"; ++ }; ++ + i2c0: i2c@e6500000 { + compatible = "renesas,i2c-r8a77970", + "renesas,rcar-gen3-i2c"; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index f2c32b5..8e4cd1b 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -359,6 +359,71 @@ + resets = <&cpg 407>; + }; + ++ tmu0: timer@e61e0000 { ++ compatible = "renesas,tmu-r8a77980", "renesas,tmu"; ++ reg = <0 0xe61e0000 0 0x30>; ++ interrupts = , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 125>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 125>; ++ status = "disabled"; ++ }; ++ ++ tmu1: timer@e6fc0000 { ++ compatible = "renesas,tmu-r8a77980", "renesas,tmu"; ++ reg = <0 0xe6fc0000 0 0x30>; ++ interrupts = , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 124>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 124>; ++ status = "disabled"; ++ }; ++ ++ tmu2: timer@e6fd0000 { ++ compatible = "renesas,tmu-r8a77980", "renesas,tmu"; ++ reg = <0 0xe6fd0000 0 0x30>; ++ interrupts = , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 123>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 123>; ++ status = "disabled"; ++ }; ++ ++ tmu3: timer@e6fe0000 { ++ compatible = "renesas,tmu-r8a77980", "renesas,tmu"; ++ reg = <0 0xe6fe0000 0 0x30>; ++ interrupts = , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 122>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 122>; ++ status = "disabled"; ++ }; ++ ++ tmu4: timer@ffc00000 { ++ compatible = "renesas,tmu-r8a77980", "renesas,tmu"; ++ reg = <0 0xffc00000 0 0x30>; ++ interrupts = , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 121>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 121>; ++ status = "disabled"; ++ }; ++ + i2c0: i2c@e6500000 { + compatible = "renesas,i2c-r8a77980", + "renesas,rcar-gen3-i2c"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0225-arm64-dts-renesas-r8a779-7-8-0-add-MSIOF-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0225-arm64-dts-renesas-r8a779-7-8-0-add-MSIOF-support.patch new file mode 100644 index 00000000..a5b90eb7 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0225-arm64-dts-renesas-r8a779-7-8-0-add-MSIOF-support.patch @@ -0,0 +1,163 @@ +From 8b6a59b481437fb9e2ec376d97213a2a38a392dd Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Fri, 19 Oct 2018 22:10:44 +0300 +Subject: [PATCH 045/211] arm64: dts: renesas: r8a779{7|8}0: add MSIOF support + +Describe MSIOF in the R8A779{7|8}0 device trees. + +The DMA props are omitted for R8A77980 as the RT-DMAC isn't supported +(yet?)... + +Based on the original (and large) patches by Vladimir Barinov. + +Signed-off-by: Vladimir Barinov +Signed-off-by: Sergei Shtylyov +Signed-off-by: Simon Horman +(cherry picked from commit 5af954f5b74ac43378fa47fb908d88147d4e3c41) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970.dtsi | 64 +++++++++++++++++++++++++++++++ + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 52 +++++++++++++++++++++++++ + 2 files changed, 116 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +index 65f3ad4..563428d 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +@@ -753,6 +753,70 @@ + status = "disabled"; + }; + ++ msiof0: spi@e6e90000 { ++ compatible = "renesas,msiof-r8a77970", ++ "renesas,rcar-gen3-msiof"; ++ reg = <0 0xe6e90000 0 0x64>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 211>; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ resets = <&cpg 211>; ++ dmas = <&dmac1 0x41>, <&dmac1 0x40>, ++ <&dmac2 0x41>, <&dmac2 0x40>; ++ dma-names = "tx", "rx", "tx", "rx"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ msiof1: spi@e6ea0000 { ++ compatible = "renesas,msiof-r8a77970", ++ "renesas,rcar-gen3-msiof"; ++ reg = <0 0xe6ea0000 0 0x0064>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 210>; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ resets = <&cpg 210>; ++ dmas = <&dmac1 0x43>, <&dmac1 0x42>, ++ <&dmac2 0x43>, <&dmac2 0x42>; ++ dma-names = "tx", "rx", "tx", "rx"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ msiof2: spi@e6c00000 { ++ compatible = "renesas,msiof-r8a77970", ++ "renesas,rcar-gen3-msiof"; ++ reg = <0 0xe6c00000 0 0x0064>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 209>; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ resets = <&cpg 209>; ++ dmas = <&dmac1 0x45>, <&dmac1 0x44>, ++ <&dmac2 0x45>, <&dmac2 0x44>; ++ dma-names = "tx", "rx", "tx", "rx"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ msiof3: spi@e6c10000 { ++ compatible = "renesas,msiof-r8a77970", ++ "renesas,rcar-gen3-msiof"; ++ reg = <0 0xe6c10000 0 0x0064>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 208>; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ resets = <&cpg 208>; ++ dmas = <&dmac1 0x47>, <&dmac1 0x46>, ++ <&dmac2 0x47>, <&dmac2 0x46>; ++ dma-names = "tx", "rx", "tx", "rx"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ + vin0: video@e6ef0000 { + compatible = "renesas,vin-r8a77970"; + reg = <0 0xe6ef0000 0 0x1000>; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index 8e4cd1b..c11ee04 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -805,6 +805,58 @@ + status = "disabled"; + }; + ++ msiof0: spi@e6e90000 { ++ compatible = "renesas,msiof-r8a77980", ++ "renesas,rcar-gen3-msiof"; ++ reg = <0 0xe6e90000 0 0x64>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 211>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 211>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ msiof1: spi@e6ea0000 { ++ compatible = "renesas,msiof-r8a77980", ++ "renesas,rcar-gen3-msiof"; ++ reg = <0 0xe6ea0000 0 0x0064>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 210>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 210>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ msiof2: spi@e6c00000 { ++ compatible = "renesas,msiof-r8a77980", ++ "renesas,rcar-gen3-msiof"; ++ reg = <0 0xe6c00000 0 0x0064>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 209>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 209>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ msiof3: spi@e6c10000 { ++ compatible = "renesas,msiof-r8a77980", ++ "renesas,rcar-gen3-msiof"; ++ reg = <0 0xe6c10000 0 0x0064>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 208>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 208>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ + vin0: video@e6ef0000 { + compatible = "renesas,vin-r8a77980"; + reg = <0 0xe6ef0000 0 0x1000>; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0226-arm64-dts-renesas-r8a77980-Connect-R-Car-V3H-AVB-to-.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0226-arm64-dts-renesas-r8a77980-Connect-R-Car-V3H-AVB-to-.patch new file mode 100644 index 00000000..ae883ead --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0226-arm64-dts-renesas-r8a77980-Connect-R-Car-V3H-AVB-to-.patch @@ -0,0 +1,32 @@ +From c4db27990ce2f5ec7b44351ca27f8a5550710a25 Mon Sep 17 00:00:00 2001 +From: Magnus Damm +Date: Mon, 22 Oct 2018 02:14:54 +0900 +Subject: [PATCH 046/211] arm64: dts: renesas: r8a77980: Connect R-Car V3H AVB + to IPMMU + +Hook up the R-Car V3H AVB device to IPMMU-DS1 33 as described in +the data sheet. + +Signed-off-by: Magnus Damm +Signed-off-by: Simon Horman +(cherry picked from commit 8aa7fb3fee6b5105a612d49a10e06f8e64232fe8) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index c11ee04..4e019f7 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -667,6 +667,7 @@ + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 812>; + phy-mode = "rgmii"; ++ iommus = <&ipmmu_ds1 33>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0227-clk-renesas-r8a77980-Add-OSC-predivider-configuratio.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0227-clk-renesas-r8a77980-Add-OSC-predivider-configuratio.patch new file mode 100644 index 00000000..403dbde9 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0227-clk-renesas-r8a77980-Add-OSC-predivider-configuratio.patch @@ -0,0 +1,72 @@ +From 0eea7261a8e6d24d118182820bad4136145a4b3c Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Wed, 11 Jul 2018 14:16:40 +0200 +Subject: [PATCH 047/211] clk: renesas: r8a77980: Add OSC predivider + configuration and clock + +R-Car Gen3 Hardware Manual Rev.0.54 documents the relation between the +MD13 and MD14 mode pins, and the OSC EXTAL predivider, as used by the +OSC clock. Hence augment the configuration structure with all +documented predivider values. + +Add the OSC clock using the configured predivider. + +Signed-off-by: Geert Uytterhoeven +Reviewed-by: Simon Horman +(cherry picked from commit 3a251270e6c877092baded767eba07e9abb1e00d) +Signed-off-by: Valentine Barshak +--- + drivers/clk/renesas/r8a77980-cpg-mssr.c | 24 +++++++++++++----------- + 1 file changed, 13 insertions(+), 11 deletions(-) + +diff --git a/drivers/clk/renesas/r8a77980-cpg-mssr.c b/drivers/clk/renesas/r8a77980-cpg-mssr.c +index d7ebd9e..a8b8d86 100644 +--- a/drivers/clk/renesas/r8a77980-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a77980-cpg-mssr.c +@@ -96,6 +96,8 @@ static const struct cpg_core_clk r8a77980_core_clks[] __initconst = { + DEF_DIV6P1("canfd", R8A77980_CLK_CANFD, CLK_PLL1_DIV4, 0x244), + DEF_DIV6P1("csi0", R8A77980_CLK_CSI0, CLK_PLL1_DIV4, 0x00c), + DEF_DIV6P1("mso", R8A77980_CLK_MSO, CLK_PLL1_DIV4, 0x014), ++ ++ DEF_GEN3_OSC("osc", R8A77980_CLK_OSC, CLK_EXTAL, 8), + }; + + static const struct mssr_mod_clk r8a77980_mod_clks[] __initconst = { +@@ -171,23 +173,23 @@ static const unsigned int r8a77980_crit_mod_clks[] __initconst = { + */ + + /* +- * MD EXTAL PLL2 PLL1 PLL3 ++ * MD EXTAL PLL2 PLL1 PLL3 OSC + * 14 13 (MHz) +- * -------------------------------------------------- +- * 0 0 16.66 x 1 x240 x192 x192 +- * 0 1 20 x 1 x200 x160 x160 +- * 1 0 27 x 1 x148 x118 x118 +- * 1 1 33.33 / 2 x240 x192 x192 ++ * -------------------------------------------------------- ++ * 0 0 16.66 x 1 x240 x192 x192 /16 ++ * 0 1 20 x 1 x200 x160 x160 /19 ++ * 1 0 27 x 1 x148 x118 x118 /26 ++ * 1 1 33.33 / 2 x240 x192 x192 /32 + */ + #define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 13) | \ + (((md) & BIT(13)) >> 13)) + + static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[4] __initconst = { +- /* EXTAL div PLL1 mult/div PLL3 mult/div */ +- { 1, 192, 1, 192, 1, }, +- { 1, 160, 1, 160, 1, }, +- { 1, 118, 1, 118, 1, }, +- { 2, 192, 1, 192, 1, }, ++ /* EXTAL div PLL1 mult/div PLL3 mult/div OSC prediv */ ++ { 1, 192, 1, 192, 1, 16, }, ++ { 1, 160, 1, 160, 1, 19, }, ++ { 1, 118, 1, 118, 1, 26, }, ++ { 2, 192, 1, 192, 1, 32, }, + }; + + static int __init r8a77980_cpg_mssr_init(struct device *dev) +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0228-clk-renesas-r8a77980-Add-RCLK-for-watchdog-timer.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0228-clk-renesas-r8a77980-Add-RCLK-for-watchdog-timer.patch new file mode 100644 index 00000000..359e9ae4 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0228-clk-renesas-r8a77980-Add-RCLK-for-watchdog-timer.patch @@ -0,0 +1,55 @@ +From 0e839c513201f880af754deeb8a6b8c000428c4c Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Wed, 11 Jul 2018 14:25:07 +0200 +Subject: [PATCH 048/211] clk: renesas: r8a77980: Add RCLK for watchdog timer + +On R-Car V3H, RCLK can be switched between EXTALR and the On-Chip +Oscillator using mode pin MD19. + +Signed-off-by: Geert Uytterhoeven +Reviewed-by: Simon Horman +(cherry picked from commit f3824deb46332d1f037f9a26c8f01e3143e64c7e) +Signed-off-by: Valentine Barshak +--- + drivers/clk/renesas/r8a77980-cpg-mssr.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/clk/renesas/r8a77980-cpg-mssr.c b/drivers/clk/renesas/r8a77980-cpg-mssr.c +index a8b8d86..acf2b4d 100644 +--- a/drivers/clk/renesas/r8a77980-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a77980-cpg-mssr.c +@@ -41,6 +41,7 @@ enum clk_ids { + CLK_S2, + CLK_S3, + CLK_SDSRC, ++ CLK_OCO, + + /* Module Clocks */ + MOD_CLK_BASE +@@ -64,6 +65,7 @@ static const struct cpg_core_clk r8a77980_core_clks[] __initconst = { + DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1), + DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1), + DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1), ++ DEF_RATE(".oco", CLK_OCO, 32768), + + /* Core Clock Outputs */ + DEF_FIXED("ztr", R8A77980_CLK_ZTR, CLK_PLL1_DIV2, 6, 1), +@@ -98,6 +100,7 @@ static const struct cpg_core_clk r8a77980_core_clks[] __initconst = { + DEF_DIV6P1("mso", R8A77980_CLK_MSO, CLK_PLL1_DIV4, 0x014), + + DEF_GEN3_OSC("osc", R8A77980_CLK_OSC, CLK_EXTAL, 8), ++ DEF_GEN3_MDSEL("r", R8A77980_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1), + }; + + static const struct mssr_mod_clk r8a77980_mod_clks[] __initconst = { +@@ -119,6 +122,7 @@ static const struct mssr_mod_clk r8a77980_mod_clks[] __initconst = { + DEF_MOD("tpu0", 304, R8A77980_CLK_S3D4), + DEF_MOD("sdif", 314, R8A77980_CLK_SD0), + DEF_MOD("pciec0", 319, R8A77980_CLK_S2D2), ++ DEF_MOD("rwdt", 402, R8A77980_CLK_R), + DEF_MOD("intc-ex", 407, R8A77980_CLK_CP), + DEF_MOD("intc-ap", 408, R8A77980_CLK_S0D3), + DEF_MOD("hscif3", 517, R8A77980_CLK_S3D1), +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0229-drm-rcar-du-lvds-add-R8A77980-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0229-drm-rcar-du-lvds-add-R8A77980-support.patch new file mode 100644 index 00000000..920b72d5 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0229-drm-rcar-du-lvds-add-R8A77980-support.patch @@ -0,0 +1,31 @@ +From 8ee3b9cd4da329e900ac02f5f6ea9b39ea290c87 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Tue, 5 Jun 2018 23:30:36 +0300 +Subject: [PATCH 049/211] drm: rcar-du: lvds: add R8A77980 support + +Add support for the R-Car V3H (R8A77980) SoC to the LVDS encoder driver. + +Signed-off-by: Sergei Shtylyov +Reviewed-by: Laurent Pinchart +Signed-off-by: Laurent Pinchart +(cherry picked from commit c4341442acb14d8f1cec6999123a70f9d2bfe48f) +Signed-off-by: Valentine Barshak +--- + drivers/gpu/drm/rcar-du/rcar_lvds.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c +index 03a74fa..c41c9ee6 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_lvds.c ++++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c +@@ -1075,6 +1075,7 @@ static const struct of_device_id rcar_lvds_of_table[] = { + { .compatible = "renesas,r8a77990-lvds", .data = &rcar_lvds_r8a77990_info }, + { .compatible = "renesas,r8a77995-lvds", .data = &rcar_lvds_r8a77995_info }, + { .compatible = "renesas,r8a77970-lvds", .data = &rcar_lvds_r8a77970_info }, ++ { .compatible = "renesas,r8a77980-lvds", .data = &rcar_lvds_gen3_info }, + { } + }; + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0230-drivers-flag-buses-which-demand-DMA-configuration.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0230-drivers-flag-buses-which-demand-DMA-configuration.patch new file mode 100644 index 00000000..bcf79a0d --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0230-drivers-flag-buses-which-demand-DMA-configuration.patch @@ -0,0 +1,139 @@ +From 0d69d1e8b840a47bd72dd4b7ca873403a200db8d Mon Sep 17 00:00:00 2001 +From: Robin Murphy +Date: Thu, 12 Oct 2017 16:56:14 +0100 +Subject: [PATCH 050/211] drivers: flag buses which demand DMA configuration + +We do not want the common dma_configure() pathway to apply +indiscriminately to all devices, since there are plenty of buses which +do not have DMA capability, and if their child devices were used for +DMA API calls it would only be indicative of a driver bug. However, +there are a number of buses for which DMA is implicitly expected even +when not described by firmware - those we whitelist with an automatic +opt-in to dma_configure(), assuming that the DMA address space and the +physical address space are equivalent if not otherwise specified. + +Commit 723288836628 ("of: restrict DMA configuration") introduced a +short-term fix by comparing explicit bus types, but this approach is far +from pretty, doesn't scale well, and fails to cope at all with bus +drivers which may be built as modules, like host1x. Let's refine things +by making that opt-in a property of the bus type, which neatly addresses +those problems and lets the decision of whether firmware description of +DMA capability should be optional or mandatory stay internal to the bus +drivers themselves. + +Signed-off-by: Robin Murphy +Acked-by: Rob Herring +Acked-by: Greg Kroah-Hartman +Acked-by: Thierry Reding +Signed-off-by: Christoph Hellwig +(cherry picked from commit d89e2378a97fafdc74cbf997e7c88af75b81610a) +Signed-off-by: Valentine Barshak +--- + drivers/amba/bus.c | 1 + + drivers/base/platform.c | 1 + + drivers/gpu/host1x/bus.c | 1 + + drivers/of/device.c | 8 +------- + drivers/pci/pci-driver.c | 1 + + include/linux/device.h | 4 ++++ + 6 files changed, 9 insertions(+), 7 deletions(-) + +diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c +index 8a99fbe..4a3ac31 100644 +--- a/drivers/amba/bus.c ++++ b/drivers/amba/bus.c +@@ -200,6 +200,7 @@ struct bus_type amba_bustype = { + .match = amba_match, + .uevent = amba_uevent, + .pm = &amba_pm, ++ .force_dma = true, + }; + + static int __init amba_init(void) +diff --git a/drivers/base/platform.c b/drivers/base/platform.c +index 9045c5f..c203fb9 100644 +--- a/drivers/base/platform.c ++++ b/drivers/base/platform.c +@@ -1143,6 +1143,7 @@ struct bus_type platform_bus_type = { + .match = platform_match, + .uevent = platform_uevent, + .pm = &platform_dev_pm_ops, ++ .force_dma = true, + }; + EXPORT_SYMBOL_GPL(platform_bus_type); + +diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c +index f9cde03..ed03b32 100644 +--- a/drivers/gpu/host1x/bus.c ++++ b/drivers/gpu/host1x/bus.c +@@ -320,6 +320,7 @@ struct bus_type host1x_bus_type = { + .name = "host1x", + .match = host1x_device_match, + .pm = &host1x_device_pm_ops, ++ .force_dma = true, + }; + + static void __host1x_device_del(struct host1x_device *device) +diff --git a/drivers/of/device.c b/drivers/of/device.c +index 64b7102..25bddf9 100644 +--- a/drivers/of/device.c ++++ b/drivers/of/device.c +@@ -9,9 +9,7 @@ + #include + #include + #include +-#include + #include +-#include + + #include + #include "of_private.h" +@@ -101,11 +99,7 @@ int of_dma_configure(struct device *dev, struct device_node *np) + * DMA configuration regardless of whether "dma-ranges" is + * correctly specified or not. + */ +- if (!dev_is_pci(dev) && +-#ifdef CONFIG_ARM_AMBA +- dev->bus != &amba_bustype && +-#endif +- dev->bus != &platform_bus_type) ++ if (!dev->bus->force_dma) + return ret == -ENODEV ? 0 : ret; + + dma_addr = offset = 0; +diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c +index ea69b4d..e453f26 100644 +--- a/drivers/pci/pci-driver.c ++++ b/drivers/pci/pci-driver.c +@@ -1476,6 +1476,7 @@ struct bus_type pci_bus_type = { + .drv_groups = pci_drv_groups, + .pm = PCI_PM_OPS_PTR, + .num_vf = pci_bus_num_vf, ++ .force_dma = true, + }; + EXPORT_SYMBOL(pci_bus_type); + +diff --git a/include/linux/device.h b/include/linux/device.h +index f232081..144ca07 100644 +--- a/include/linux/device.h ++++ b/include/linux/device.h +@@ -97,6 +97,8 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *); + * @p: The private data of the driver core, only the driver core can + * touch this. + * @lock_key: Lock class key for use by the lock validator ++ * @force_dma: Assume devices on this bus should be set up by dma_configure() ++ * even if DMA capability is not explicitly described by firmware. + * + * A bus is a channel between the processor and one or more devices. For the + * purposes of the device model, all devices are connected via a bus, even if +@@ -135,6 +137,8 @@ struct bus_type { + + struct subsys_private *p; + struct lock_class_key lock_key; ++ ++ bool force_dma; + }; + + extern int __must_check bus_register(struct bus_type *bus); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0231-gpu-host1x-Call-of_dma_configure-after-setting-bus.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0231-gpu-host1x-Call-of_dma_configure-after-setting-bus.patch new file mode 100644 index 00000000..54344348 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0231-gpu-host1x-Call-of_dma_configure-after-setting-bus.patch @@ -0,0 +1,39 @@ +From de91461e14544bde491e9513733cb4e7dcac24aa Mon Sep 17 00:00:00 2001 +From: Mikko Perttunen +Date: Sun, 24 Sep 2017 12:04:53 +0300 +Subject: [PATCH 051/211] gpu: host1x: Call of_dma_configure() after setting + bus + +of_dma_configure() now checks the device's bus before configuring it, so +we need to set the device's bus before calling. + +Signed-off-by: Mikko Perttunen +Signed-off-by: Thierry Reding +(cherry picked from commit 2fb0dceb69ce957f01bdb6fddf7baf4c4b9cbc0d) +Signed-off-by: Valentine Barshak +--- + drivers/gpu/host1x/bus.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c +index ed03b32..2e57c9ce 100644 +--- a/drivers/gpu/host1x/bus.c ++++ b/drivers/gpu/host1x/bus.c +@@ -404,12 +404,13 @@ static int host1x_device_add(struct host1x *host1x, + device->dev.coherent_dma_mask = host1x->dev->coherent_dma_mask; + device->dev.dma_mask = &device->dev.coherent_dma_mask; + dev_set_name(&device->dev, "%s", driver->driver.name); +- of_dma_configure(&device->dev, host1x->dev->of_node); + device->dev.release = host1x_device_release; + device->dev.of_node = host1x->dev->of_node; + device->dev.bus = &host1x_bus_type; + device->dev.parent = host1x->dev; + ++ of_dma_configure(&device->dev, host1x->dev->of_node); ++ + err = host1x_device_parse_dt(device, driver); + if (err < 0) { + kfree(device); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0232-gpu-host1x-Cleanup-on-initialization-failure.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0232-gpu-host1x-Cleanup-on-initialization-failure.patch new file mode 100644 index 00000000..018a3b1e --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0232-gpu-host1x-Cleanup-on-initialization-failure.patch @@ -0,0 +1,48 @@ +From e7cc9cf9ab044fcd12251f74905715d5415a12b3 Mon Sep 17 00:00:00 2001 +From: Thierry Reding +Date: Wed, 8 Nov 2017 13:08:21 +0100 +Subject: [PATCH 052/211] gpu: host1x: Cleanup on initialization failure + +When an error happens during the initialization of one of the sub- +devices, make sure to properly cleanup all sub-devices that have been +initialized up to that point. + +Signed-off-by: Thierry Reding +(cherry picked from commit 8f7da1578e90bf1af30269dc6dd8806c96e9c683) +Signed-off-by: Valentine Barshak +--- + drivers/gpu/host1x/bus.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c +index 2e57c9ce..88a3558 100644 +--- a/drivers/gpu/host1x/bus.c ++++ b/drivers/gpu/host1x/bus.c +@@ -211,8 +211,7 @@ int host1x_device_init(struct host1x_device *device) + dev_err(&device->dev, + "failed to initialize %s: %d\n", + dev_name(client->dev), err); +- mutex_unlock(&device->clients_lock); +- return err; ++ goto teardown; + } + } + } +@@ -220,6 +219,14 @@ int host1x_device_init(struct host1x_device *device) + mutex_unlock(&device->clients_lock); + + return 0; ++ ++teardown: ++ list_for_each_entry_continue_reverse(client, &device->clients, list) ++ if (client->ops->exit) ++ client->ops->exit(client); ++ ++ mutex_unlock(&device->clients_lock); ++ return err; + } + EXPORT_SYMBOL(host1x_device_init); + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0233-dma-mapping-move-dma-configuration-to-bus-infrastruc.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0233-dma-mapping-move-dma-configuration-to-bus-infrastruc.patch new file mode 100644 index 00000000..ccb0354b --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0233-dma-mapping-move-dma-configuration-to-bus-infrastruc.patch @@ -0,0 +1,261 @@ +From 119a8b25ee3745650dc7205f2601acf4b3d32c2b Mon Sep 17 00:00:00 2001 +From: Nipun Gupta +Date: Sat, 28 Apr 2018 08:21:58 +0530 +Subject: [PATCH 053/211] dma-mapping: move dma configuration to bus + infrastructure + +ACPI/OF support for configuration of DMA is a bus specific aspect, and +thus should be configured by the bus. Introduces a 'dma_configure' bus +method so that busses can control their DMA capabilities. + +Also update the PCI, Platform, ACPI and host1x buses to use the new +method. + +Suggested-by: Christoph Hellwig +Signed-off-by: Nipun Gupta +Acked-by: Bjorn Helgaas # PCI parts +Acked-by: Thierry Reding +Reviewed-by: Greg Kroah-Hartman +[hch: simplified host1x_dma_configure based on a comment from Thierry, + rewrote changelog] +Signed-off-by: Christoph Hellwig + +(cherry picked from commit 07397df29e57cde5799af16e8f148ae10ed75285) +Signed-off-by: Valentine Barshak +--- + drivers/amba/bus.c | 4 ++++ + drivers/base/dma-mapping.c | 31 ++++--------------------------- + drivers/base/platform.c | 17 +++++++++++++++++ + drivers/gpu/host1x/bus.c | 6 ++++++ + drivers/pci/pci-driver.c | 32 ++++++++++++++++++++++++++++++++ + include/linux/device.h | 4 ++++ + include/linux/platform_device.h | 2 ++ + 7 files changed, 69 insertions(+), 27 deletions(-) + +diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c +index 4a3ac31..b1f41f7 100644 +--- a/drivers/amba/bus.c ++++ b/drivers/amba/bus.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + + #include + +@@ -193,12 +194,15 @@ static const struct dev_pm_ops amba_pm = { + /* + * Primecells are part of the Advanced Microcontroller Bus Architecture, + * so we call the bus "amba". ++ * DMA configuration for platform and AMBA bus is same. So here we reuse ++ * platform's DMA config routine. + */ + struct bus_type amba_bustype = { + .name = "amba", + .dev_groups = amba_dev_groups, + .match = amba_match, + .uevent = amba_uevent, ++ .dma_configure = platform_dma_configure, + .pm = &amba_pm, + .force_dma = true, + }; +diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c +index e584edd..98f30b5 100644 +--- a/drivers/base/dma-mapping.c ++++ b/drivers/base/dma-mapping.c +@@ -332,36 +332,13 @@ void dma_common_free_remap(void *cpu_addr, size_t size, unsigned long vm_flags) + #endif + + /* +- * Common configuration to enable DMA API use for a device ++ * enables DMA API use for a device + */ +-#include +- + int dma_configure(struct device *dev) + { +- struct device *bridge = NULL, *dma_dev = dev; +- enum dev_dma_attr attr; +- int ret = 0; +- +- if (dev_is_pci(dev)) { +- bridge = pci_get_host_bridge_device(to_pci_dev(dev)); +- dma_dev = bridge; +- if (IS_ENABLED(CONFIG_OF) && dma_dev->parent && +- dma_dev->parent->of_node) +- dma_dev = dma_dev->parent; +- } +- +- if (dma_dev->of_node) { +- ret = of_dma_configure(dev, dma_dev->of_node); +- } else if (has_acpi_companion(dma_dev)) { +- attr = acpi_get_dma_attr(to_acpi_device_node(dma_dev->fwnode)); +- if (attr != DEV_DMA_NOT_SUPPORTED) +- ret = acpi_dma_configure(dev, attr); +- } +- +- if (bridge) +- pci_put_host_bridge_device(bridge); +- +- return ret; ++ if (dev->bus->dma_configure) ++ return dev->bus->dma_configure(dev); ++ return 0; + } + + void dma_deconfigure(struct device *dev) +diff --git a/drivers/base/platform.c b/drivers/base/platform.c +index c203fb9..5b43ace 100644 +--- a/drivers/base/platform.c ++++ b/drivers/base/platform.c +@@ -1131,6 +1131,22 @@ int platform_pm_restore(struct device *dev) + + #endif /* CONFIG_HIBERNATE_CALLBACKS */ + ++int platform_dma_configure(struct device *dev) ++{ ++ enum dev_dma_attr attr; ++ int ret = 0; ++ ++ if (dev->of_node) { ++ ret = of_dma_configure(dev, dev->of_node); ++ } else if (has_acpi_companion(dev)) { ++ attr = acpi_get_dma_attr(to_acpi_device_node(dev->fwnode)); ++ if (attr != DEV_DMA_NOT_SUPPORTED) ++ ret = acpi_dma_configure(dev, attr); ++ } ++ ++ return ret; ++} ++ + static const struct dev_pm_ops platform_dev_pm_ops = { + .runtime_suspend = pm_generic_runtime_suspend, + .runtime_resume = pm_generic_runtime_resume, +@@ -1142,6 +1158,7 @@ struct bus_type platform_bus_type = { + .dev_groups = platform_dev_groups, + .match = platform_match, + .uevent = platform_uevent, ++ .dma_configure = platform_dma_configure, + .pm = &platform_dev_pm_ops, + .force_dma = true, + }; +diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c +index 88a3558..0c79baf 100644 +--- a/drivers/gpu/host1x/bus.c ++++ b/drivers/gpu/host1x/bus.c +@@ -314,6 +314,11 @@ static int host1x_device_match(struct device *dev, struct device_driver *drv) + return strcmp(dev_name(dev), drv->name) == 0; + } + ++static int host1x_dma_configure(struct device *dev) ++{ ++ return of_dma_configure(dev, dev->of_node); ++} ++ + static const struct dev_pm_ops host1x_device_pm_ops = { + .suspend = pm_generic_suspend, + .resume = pm_generic_resume, +@@ -326,6 +331,7 @@ static const struct dev_pm_ops host1x_device_pm_ops = { + struct bus_type host1x_bus_type = { + .name = "host1x", + .match = host1x_device_match, ++ .dma_configure = host1x_dma_configure, + .pm = &host1x_device_pm_ops, + .force_dma = true, + }; +diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c +index e453f26..fddbb24 100644 +--- a/drivers/pci/pci-driver.c ++++ b/drivers/pci/pci-driver.c +@@ -20,6 +20,8 @@ + #include + #include + #include ++#include ++#include + #include "pci.h" + + struct pci_dynid { +@@ -1464,6 +1466,35 @@ static int pci_bus_num_vf(struct device *dev) + return pci_num_vf(to_pci_dev(dev)); + } + ++/** ++ * pci_dma_configure - Setup DMA configuration ++ * @dev: ptr to dev structure ++ * ++ * Function to update PCI devices's DMA configuration using the same ++ * info from the OF node or ACPI node of host bridge's parent (if any). ++ */ ++static int pci_dma_configure(struct device *dev) ++{ ++ struct device *bridge; ++ int ret = 0; ++ ++ bridge = pci_get_host_bridge_device(to_pci_dev(dev)); ++ ++ if (IS_ENABLED(CONFIG_OF) && bridge->parent && ++ bridge->parent->of_node) { ++ ret = of_dma_configure(dev, bridge->parent->of_node); ++ } else if (has_acpi_companion(bridge)) { ++ struct acpi_device *adev = to_acpi_device_node(bridge->fwnode); ++ enum dev_dma_attr attr = acpi_get_dma_attr(adev); ++ ++ if (attr != DEV_DMA_NOT_SUPPORTED) ++ ret = acpi_dma_configure(dev, attr); ++ } ++ ++ pci_put_host_bridge_device(bridge); ++ return ret; ++} ++ + struct bus_type pci_bus_type = { + .name = "pci", + .match = pci_bus_match, +@@ -1476,6 +1507,7 @@ struct bus_type pci_bus_type = { + .drv_groups = pci_drv_groups, + .pm = PCI_PM_OPS_PTR, + .num_vf = pci_bus_num_vf, ++ .dma_configure = pci_dma_configure, + .force_dma = true, + }; + EXPORT_SYMBOL(pci_bus_type); +diff --git a/include/linux/device.h b/include/linux/device.h +index 144ca07..012c4377 100644 +--- a/include/linux/device.h ++++ b/include/linux/device.h +@@ -89,6 +89,8 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *); + * @resume: Called to bring a device on this bus out of sleep mode. + * @num_vf: Called to find out how many virtual functions a device on this + * bus supports. ++ * @dma_configure: Called to setup DMA configuration on a device on ++ this bus. + * @pm: Power management operations of this bus, callback the specific + * device driver's pm-ops. + * @iommu_ops: IOMMU specific operations for this bus, used to attach IOMMU +@@ -131,6 +133,8 @@ struct bus_type { + + int (*num_vf)(struct device *dev); + ++ int (*dma_configure)(struct device *dev); ++ + const struct dev_pm_ops *pm; + + const struct iommu_ops *iommu_ops; +diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h +index 49f634d..3097c94 100644 +--- a/include/linux/platform_device.h ++++ b/include/linux/platform_device.h +@@ -356,6 +356,8 @@ extern int platform_pm_restore(struct device *dev); + #define platform_pm_restore NULL + #endif + ++extern int platform_dma_configure(struct device *dev); ++ + #ifdef CONFIG_PM_SLEEP + #define USE_PLATFORM_PM_SLEEP_OPS \ + .suspend = platform_pm_suspend, \ +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0234-drivers-remove-force-dma-flag-from-buses.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0234-drivers-remove-force-dma-flag-from-buses.patch new file mode 100644 index 00000000..65f8b500 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0234-drivers-remove-force-dma-flag-from-buses.patch @@ -0,0 +1,252 @@ +From 90ea8f9afa19363f0bb98e9fd243079159cb4ca4 Mon Sep 17 00:00:00 2001 +From: Christoph Hellwig +Date: Thu, 3 May 2018 16:25:08 +0200 +Subject: [PATCH 054/211] drivers: remove force dma flag from buses + +With each bus implementing its own DMA configuration callback, there is no +need for bus to explicitly set the force_dma flag. Modify the +of_dma_configure function to accept an input parameter which specifies if +implicit DMA configuration is required when it is not described by the +firmware. + +Signed-off-by: Nipun Gupta +Acked-by: Bjorn Helgaas # PCI parts +Reviewed-by: Rob Herring +[hch: tweaked the changelog a bit] +Signed-off-by: Christoph Hellwig + +(cherry picked from commit 3d6ce86ee79465e1b1b6e287f8ea26b553fc768e) +[valentine.barshak: changed drivers/pci/endpoint/pci-epc-core.c as well] +Signed-off-by: Valentine Barshak +--- + drivers/amba/bus.c | 1 - + drivers/base/platform.c | 3 +-- + drivers/bcma/main.c | 2 +- + drivers/dma/qcom/hidma_mgmt.c | 2 +- + drivers/gpu/host1x/bus.c | 5 ++--- + drivers/of/device.c | 6 ++++-- + drivers/of/of_reserved_mem.c | 2 +- + drivers/pci/endpoint/pci-epc-core.c | 2 +- + drivers/pci/pci-driver.c | 3 +-- + include/linux/device.h | 4 ---- + include/linux/of_device.h | 8 ++++++-- + 11 files changed, 18 insertions(+), 20 deletions(-) + +diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c +index b1f41f7..3b01187 100644 +--- a/drivers/amba/bus.c ++++ b/drivers/amba/bus.c +@@ -204,7 +204,6 @@ struct bus_type amba_bustype = { + .uevent = amba_uevent, + .dma_configure = platform_dma_configure, + .pm = &amba_pm, +- .force_dma = true, + }; + + static int __init amba_init(void) +diff --git a/drivers/base/platform.c b/drivers/base/platform.c +index 5b43ace..55e9456 100644 +--- a/drivers/base/platform.c ++++ b/drivers/base/platform.c +@@ -1137,7 +1137,7 @@ int platform_dma_configure(struct device *dev) + int ret = 0; + + if (dev->of_node) { +- ret = of_dma_configure(dev, dev->of_node); ++ ret = of_dma_configure(dev, dev->of_node, true); + } else if (has_acpi_companion(dev)) { + attr = acpi_get_dma_attr(to_acpi_device_node(dev->fwnode)); + if (attr != DEV_DMA_NOT_SUPPORTED) +@@ -1160,7 +1160,6 @@ struct bus_type platform_bus_type = { + .uevent = platform_uevent, + .dma_configure = platform_dma_configure, + .pm = &platform_dev_pm_ops, +- .force_dma = true, + }; + EXPORT_SYMBOL_GPL(platform_bus_type); + +diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c +index e6986c7..fc1f4ac 100644 +--- a/drivers/bcma/main.c ++++ b/drivers/bcma/main.c +@@ -207,7 +207,7 @@ static void bcma_of_fill_device(struct device *parent, + + core->irq = bcma_of_get_irq(parent, core, 0); + +- of_dma_configure(&core->dev, node); ++ of_dma_configure(&core->dev, node, false); + } + + unsigned int bcma_core_irq(struct bcma_device *core, int num) +diff --git a/drivers/dma/qcom/hidma_mgmt.c b/drivers/dma/qcom/hidma_mgmt.c +index 7335e2e..3a0e363 100644 +--- a/drivers/dma/qcom/hidma_mgmt.c ++++ b/drivers/dma/qcom/hidma_mgmt.c +@@ -427,7 +427,7 @@ static int __init hidma_mgmt_of_populate_channels(struct device_node *np) + } + of_node_get(child); + new_pdev->dev.of_node = child; +- of_dma_configure(&new_pdev->dev, child); ++ of_dma_configure(&new_pdev->dev, child, true); + /* + * It is assumed that calling of_msi_configure is safe on + * platforms with or without MSI support. +diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c +index 0c79baf..815bdb4 100644 +--- a/drivers/gpu/host1x/bus.c ++++ b/drivers/gpu/host1x/bus.c +@@ -316,7 +316,7 @@ static int host1x_device_match(struct device *dev, struct device_driver *drv) + + static int host1x_dma_configure(struct device *dev) + { +- return of_dma_configure(dev, dev->of_node); ++ return of_dma_configure(dev, dev->of_node, true); + } + + static const struct dev_pm_ops host1x_device_pm_ops = { +@@ -333,7 +333,6 @@ struct bus_type host1x_bus_type = { + .match = host1x_device_match, + .dma_configure = host1x_dma_configure, + .pm = &host1x_device_pm_ops, +- .force_dma = true, + }; + + static void __host1x_device_del(struct host1x_device *device) +@@ -422,7 +421,7 @@ static int host1x_device_add(struct host1x *host1x, + device->dev.bus = &host1x_bus_type; + device->dev.parent = host1x->dev; + +- of_dma_configure(&device->dev, host1x->dev->of_node); ++ of_dma_configure(&device->dev, host1x->dev->of_node, true); + + err = host1x_device_parse_dt(device, driver); + if (err < 0) { +diff --git a/drivers/of/device.c b/drivers/of/device.c +index 25bddf9..4404903 100644 +--- a/drivers/of/device.c ++++ b/drivers/of/device.c +@@ -75,6 +75,8 @@ int of_device_add(struct platform_device *ofdev) + * of_dma_configure - Setup DMA configuration + * @dev: Device to apply DMA configuration + * @np: Pointer to OF node having DMA configuration ++ * @force_dma: Whether device is to be set up by of_dma_configure() even if ++ * DMA capability is not explicitly described by firmware. + * + * Try to get devices's DMA configuration from DT and update it + * accordingly. +@@ -83,7 +85,7 @@ int of_device_add(struct platform_device *ofdev) + * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events + * to fix up DMA configuration. + */ +-int of_dma_configure(struct device *dev, struct device_node *np) ++int of_dma_configure(struct device *dev, struct device_node *np, bool force_dma) + { + u64 dma_addr, paddr, size = 0; + int ret; +@@ -99,7 +101,7 @@ int of_dma_configure(struct device *dev, struct device_node *np) + * DMA configuration regardless of whether "dma-ranges" is + * correctly specified or not. + */ +- if (!dev->bus->force_dma) ++ if (!force_dma) + return ret == -ENODEV ? 0 : ret; + + dma_addr = offset = 0; +diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c +index 32771c2..e36c119 100644 +--- a/drivers/of/of_reserved_mem.c ++++ b/drivers/of/of_reserved_mem.c +@@ -357,7 +357,7 @@ int of_reserved_mem_device_init_by_idx(struct device *dev, + /* ensure that dma_ops is set for virtual devices + * using reserved memory + */ +- of_dma_configure(dev, np); ++ of_dma_configure(dev, np, true); + + dev_info(dev, "assigned reserved memory node %s\n", rmem->name); + } else { +diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c +index 42c2a11..c09e08c 100644 +--- a/drivers/pci/endpoint/pci-epc-core.c ++++ b/drivers/pci/endpoint/pci-epc-core.c +@@ -384,7 +384,7 @@ int pci_epc_add_epf(struct pci_epc *epc, struct pci_epf *epf) + + epf->epc = epc; + if (dev->of_node) { +- of_dma_configure(&epf->dev, dev->of_node); ++ of_dma_configure(&epf->dev, dev->of_node, true); + } else { + dma_set_coherent_mask(&epf->dev, epc->dev.coherent_dma_mask); + epf->dev.dma_mask = epc->dev.dma_mask; +diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c +index fddbb24..2d67f5f 100644 +--- a/drivers/pci/pci-driver.c ++++ b/drivers/pci/pci-driver.c +@@ -1482,7 +1482,7 @@ static int pci_dma_configure(struct device *dev) + + if (IS_ENABLED(CONFIG_OF) && bridge->parent && + bridge->parent->of_node) { +- ret = of_dma_configure(dev, bridge->parent->of_node); ++ ret = of_dma_configure(dev, bridge->parent->of_node, true); + } else if (has_acpi_companion(bridge)) { + struct acpi_device *adev = to_acpi_device_node(bridge->fwnode); + enum dev_dma_attr attr = acpi_get_dma_attr(adev); +@@ -1508,7 +1508,6 @@ struct bus_type pci_bus_type = { + .pm = PCI_PM_OPS_PTR, + .num_vf = pci_bus_num_vf, + .dma_configure = pci_dma_configure, +- .force_dma = true, + }; + EXPORT_SYMBOL(pci_bus_type); + +diff --git a/include/linux/device.h b/include/linux/device.h +index 012c4377..d57443b 100644 +--- a/include/linux/device.h ++++ b/include/linux/device.h +@@ -99,8 +99,6 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *); + * @p: The private data of the driver core, only the driver core can + * touch this. + * @lock_key: Lock class key for use by the lock validator +- * @force_dma: Assume devices on this bus should be set up by dma_configure() +- * even if DMA capability is not explicitly described by firmware. + * + * A bus is a channel between the processor and one or more devices. For the + * purposes of the device model, all devices are connected via a bus, even if +@@ -141,8 +139,6 @@ struct bus_type { + + struct subsys_private *p; + struct lock_class_key lock_key; +- +- bool force_dma; + }; + + extern int __must_check bus_register(struct bus_type *bus); +diff --git a/include/linux/of_device.h b/include/linux/of_device.h +index 8da5a1b..165fd30 100644 +--- a/include/linux/of_device.h ++++ b/include/linux/of_device.h +@@ -55,7 +55,9 @@ static inline struct device_node *of_cpu_device_node_get(int cpu) + return of_node_get(cpu_dev->of_node); + } + +-int of_dma_configure(struct device *dev, struct device_node *np); ++int of_dma_configure(struct device *dev, ++ struct device_node *np, ++ bool force_dma); + void of_dma_deconfigure(struct device *dev); + #else /* CONFIG_OF */ + +@@ -105,7 +107,9 @@ static inline struct device_node *of_cpu_device_node_get(int cpu) + return NULL; + } + +-static inline int of_dma_configure(struct device *dev, struct device_node *np) ++static inline int of_dma_configure(struct device *dev, ++ struct device_node *np, ++ bool force_dma) + { + return 0; + } +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0235-clk-renesas-r8a77980-Add-CMT-clocks.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0235-clk-renesas-r8a77980-Add-CMT-clocks.patch new file mode 100644 index 00000000..2645cb56 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0235-clk-renesas-r8a77980-Add-CMT-clocks.patch @@ -0,0 +1,36 @@ +From 872df28a16628edbc81d821a4b54915baccbf467 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Sat, 1 Sep 2018 21:54:27 +0300 +Subject: [PATCH 055/211] clk: renesas: r8a77980: Add CMT clocks + +Now that RCLK has been added by Geert, we can add the CMT module clocks. + +Based on the original (and large) patch by Vladimir Barinov. + +Signed-off-by: Vladimir Barinov +Signed-off-by: Sergei Shtylyov +Signed-off-by: Geert Uytterhoeven +(cherry picked from commit 0a87bf6cd5297d8ae99f3560a7969a0b141f7350) +Signed-off-by: Valentine Barshak +--- + drivers/clk/renesas/r8a77980-cpg-mssr.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/clk/renesas/r8a77980-cpg-mssr.c b/drivers/clk/renesas/r8a77980-cpg-mssr.c +index acf2b4d..25a3083 100644 +--- a/drivers/clk/renesas/r8a77980-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a77980-cpg-mssr.c +@@ -119,6 +119,10 @@ static const struct mssr_mod_clk r8a77980_mod_clks[] __initconst = { + DEF_MOD("msiof0", 211, R8A77980_CLK_MSO), + DEF_MOD("sys-dmac2", 217, R8A77980_CLK_S0D3), + DEF_MOD("sys-dmac1", 218, R8A77980_CLK_S0D3), ++ DEF_MOD("cmt3", 300, R8A77980_CLK_R), ++ DEF_MOD("cmt2", 301, R8A77980_CLK_R), ++ DEF_MOD("cmt1", 302, R8A77980_CLK_R), ++ DEF_MOD("cmt0", 303, R8A77980_CLK_R), + DEF_MOD("tpu0", 304, R8A77980_CLK_S3D4), + DEF_MOD("sdif", 314, R8A77980_CLK_SD0), + DEF_MOD("pciec0", 319, R8A77980_CLK_S2D2), +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0236-clk-renesas-r8a77970-Add-SD0H-SD0-clocks-for-SDHI.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0236-clk-renesas-r8a77970-Add-SD0H-SD0-clocks-for-SDHI.patch new file mode 100644 index 00000000..adeb72eb --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0236-clk-renesas-r8a77970-Add-SD0H-SD0-clocks-for-SDHI.patch @@ -0,0 +1,169 @@ +From 5dce30d0e8c7b82b39e98b397c6ac9c741a8ed41 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Sat, 1 Sep 2018 23:12:28 +0300 +Subject: [PATCH 056/211] clk: renesas: r8a77970: Add SD0H/SD0 clocks for SDHI + +On R-Car V3M (AKA R8A77970), the SD0CKCR is laid out differently than on +the other R-Car gen3 SoCs. In fact, the layout is the same as on R-Car gen2 +SoCs, so we'll need to copy the divisor tables from the R-Car gen2 driver. +We'll also need to support the SoC specific clock types, thus we're adding +CLK_TYPE_GEN3_SOC_BASE at the end of 'enum rcar_gen3_clk_types', declare +SD0H/SDH clocks in 'enum r8a77970_clk_types', and handle those clocks in +the overridden cpg_clk_register() method; then, finally, add the SD-IF +module clock (derived from the SD0 clock). + +Signed-off-by: Sergei Shtylyov +Signed-off-by: Geert Uytterhoeven +(cherry picked from commit 381081ffc2948e1e1a7cbbafe3b91631530a1936) +Signed-off-by: Valentine Barshak +--- + drivers/clk/renesas/r8a77970-cpg-mssr.c | 66 ++++++++++++++++++++++++++++++++- + drivers/clk/renesas/rcar-gen3-cpg.h | 3 ++ + 2 files changed, 67 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/renesas/r8a77970-cpg-mssr.c b/drivers/clk/renesas/r8a77970-cpg-mssr.c +index f558429..07d0ddc 100644 +--- a/drivers/clk/renesas/r8a77970-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a77970-cpg-mssr.c +@@ -1,7 +1,7 @@ + /* + * r8a77970 Clock Pulse Generator / Module Standby and Software Reset + * +- * Copyright (C) 2017 Cogent Embedded Inc. ++ * Copyright (C) 2017-2018 Cogent Embedded Inc. + * + * Based on r8a7795-cpg-mssr.c + * +@@ -12,6 +12,7 @@ + * the Free Software Foundation; version 2 of the License. + */ + ++#include + #include + #include + #include +@@ -22,6 +23,13 @@ + #include "renesas-cpg-mssr.h" + #include "rcar-gen3-cpg.h" + ++#define CPG_SD0CKCR 0x0074 ++ ++enum r8a77970_clk_types { ++ CLK_TYPE_R8A77970_SD0H = CLK_TYPE_GEN3_SOC_BASE, ++ CLK_TYPE_R8A77970_SD0, ++}; ++ + enum clk_ids { + /* Core Clock Outputs exported to DT */ + LAST_DT_CORE_CLK = R8A77970_CLK_OSC, +@@ -42,6 +50,20 @@ enum clk_ids { + MOD_CLK_BASE + }; + ++static spinlock_t cpg_lock; ++ ++static const struct clk_div_table cpg_sd0h_div_table[] = { ++ { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 }, ++ { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 }, ++ { 8, 24 }, { 10, 36 }, { 11, 48 }, { 0, 0 }, ++}; ++ ++static const struct clk_div_table cpg_sd0_div_table[] = { ++ { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 }, ++ { 8, 24 }, { 10, 36 }, { 11, 48 }, { 12, 10 }, ++ { 0, 0 }, ++}; ++ + static const struct cpg_core_clk r8a77970_core_clks[] __initconst = { + /* External Clock Inputs */ + DEF_INPUT("extal", CLK_EXTAL), +@@ -68,6 +90,10 @@ static const struct cpg_core_clk r8a77970_core_clks[] __initconst = { + DEF_FIXED("s2d2", R8A77970_CLK_S2D2, CLK_PLL1_DIV2, 12, 1), + DEF_FIXED("s2d4", R8A77970_CLK_S2D4, CLK_PLL1_DIV2, 24, 1), + ++ DEF_BASE("sd0h", R8A77970_CLK_SD0H, CLK_TYPE_R8A77970_SD0H, ++ CLK_PLL1_DIV2), ++ DEF_BASE("sd0", R8A77970_CLK_SD0, CLK_TYPE_R8A77970_SD0, CLK_PLL1_DIV2), ++ + DEF_FIXED("cl", R8A77970_CLK_CL, CLK_PLL1_DIV2, 48, 1), + DEF_FIXED("cp", R8A77970_CLK_CP, CLK_EXTAL, 2, 1), + +@@ -92,6 +118,7 @@ static const struct mssr_mod_clk r8a77970_mod_clks[] __initconst = { + DEF_MOD("mfis", 213, R8A77970_CLK_S2D2), + DEF_MOD("sys-dmac2", 217, R8A77970_CLK_S2D1), + DEF_MOD("sys-dmac1", 218, R8A77970_CLK_S2D1), ++ DEF_MOD("sd-if", 314, R8A77970_CLK_SD0), + DEF_MOD("rwdt", 402, R8A77970_CLK_R), + DEF_MOD("intc-ex", 407, R8A77970_CLK_CP), + DEF_MOD("intc-ap", 408, R8A77970_CLK_S2D1), +@@ -173,11 +200,46 @@ static int __init r8a77970_cpg_mssr_init(struct device *dev) + if (error) + return error; + ++ spin_lock_init(&cpg_lock); ++ + cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)]; + + return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode); + } + ++static struct clk * __init r8a77970_cpg_clk_register(struct device *dev, ++ const struct cpg_core_clk *core, const struct cpg_mssr_info *info, ++ struct clk **clks, void __iomem *base, ++ struct raw_notifier_head *notifiers) ++{ ++ const struct clk_div_table *table; ++ const struct clk *parent; ++ unsigned int shift; ++ ++ switch (core->type) { ++ case CLK_TYPE_R8A77970_SD0H: ++ table = cpg_sd0h_div_table; ++ shift = 8; ++ break; ++ case CLK_TYPE_R8A77970_SD0: ++ table = cpg_sd0_div_table; ++ shift = 4; ++ break; ++ default: ++ return rcar_gen3_cpg_clk_register(dev, core, info, clks, base, ++ notifiers); ++ } ++ ++ parent = clks[core->parent]; ++ if (IS_ERR(parent)) ++ return ERR_CAST(parent); ++ ++ return clk_register_divider_table(NULL, core->name, ++ __clk_get_name(parent), 0, ++ base + CPG_SD0CKCR, ++ shift, 4, 0, table, &cpg_lock); ++} ++ + const struct cpg_mssr_info r8a77970_cpg_mssr_info __initconst = { + /* Core Clocks */ + .core_clks = r8a77970_core_clks, +@@ -196,5 +258,5 @@ const struct cpg_mssr_info r8a77970_cpg_mssr_info __initconst = { + + /* Callbacks */ + .init = r8a77970_cpg_mssr_init, +- .cpg_clk_register = rcar_gen3_cpg_clk_register, ++ .cpg_clk_register = r8a77970_cpg_clk_register, + }; +diff --git a/drivers/clk/renesas/rcar-gen3-cpg.h b/drivers/clk/renesas/rcar-gen3-cpg.h +index 8bca3298..8834afe 100644 +--- a/drivers/clk/renesas/rcar-gen3-cpg.h ++++ b/drivers/clk/renesas/rcar-gen3-cpg.h +@@ -27,6 +27,9 @@ enum rcar_gen3_clk_types { + CLK_TYPE_GEN3_ZG, + CLK_TYPE_GEN3_OSC, /* OSC EXTAL predivider and fixed divider */ + CLK_TYPE_GEN3_RCKSEL, /* Select parent/divider using RCKCR.CKSEL */ ++ ++ /* SoC specific definitions start here */ ++ CLK_TYPE_GEN3_SOC_BASE, + }; + + #define DEF_GEN3_SD(_name, _id, _parent, _offset) \ +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0237-clk-renesas-r8a77970-Add-CMT-clocks.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0237-clk-renesas-r8a77970-Add-CMT-clocks.patch new file mode 100644 index 00000000..ae2d085d --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0237-clk-renesas-r8a77970-Add-CMT-clocks.patch @@ -0,0 +1,37 @@ +From eb3fd6dd525a000338fb6c5c98c7b6abe2597aca Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Wed, 5 Sep 2018 19:59:48 +0300 +Subject: [PATCH 057/211] clk: renesas: r8a77970: Add CMT clocks + +Add the R8A77970 CMT module clocks. + +Based on the original (and large) patch by Vladimir Barinov. + +Signed-off-by: Vladimir Barinov +Signed-off-by: Sergei Shtylyov +Reviewed-by: Chris Paterson +Signed-off-by: Geert Uytterhoeven +(cherry picked from commit 5986b503da614df3fccbf90edab3afa4c7550fa1) +Signed-off-by: Valentine Barshak +--- + drivers/clk/renesas/r8a77970-cpg-mssr.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/clk/renesas/r8a77970-cpg-mssr.c b/drivers/clk/renesas/r8a77970-cpg-mssr.c +index 07d0ddc..f07a1ee 100644 +--- a/drivers/clk/renesas/r8a77970-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a77970-cpg-mssr.c +@@ -118,6 +118,10 @@ static const struct mssr_mod_clk r8a77970_mod_clks[] __initconst = { + DEF_MOD("mfis", 213, R8A77970_CLK_S2D2), + DEF_MOD("sys-dmac2", 217, R8A77970_CLK_S2D1), + DEF_MOD("sys-dmac1", 218, R8A77970_CLK_S2D1), ++ DEF_MOD("cmt3", 300, R8A77970_CLK_R), ++ DEF_MOD("cmt2", 301, R8A77970_CLK_R), ++ DEF_MOD("cmt1", 302, R8A77970_CLK_R), ++ DEF_MOD("cmt0", 303, R8A77970_CLK_R), + DEF_MOD("sd-if", 314, R8A77970_CLK_SD0), + DEF_MOD("rwdt", 402, R8A77970_CLK_R), + DEF_MOD("intc-ex", 407, R8A77970_CLK_CP), +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0238-clk-renesas-r8a77970-Add-TMU-clocks.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0238-clk-renesas-r8a77970-Add-TMU-clocks.patch new file mode 100644 index 00000000..b4e03690 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0238-clk-renesas-r8a77970-Add-TMU-clocks.patch @@ -0,0 +1,38 @@ +From d70dba2e0a107d08b455bd47e31c2c8878b218df Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Thu, 6 Sep 2018 23:28:12 +0300 +Subject: [PATCH 058/211] clk: renesas: r8a77970: Add TMU clocks + +The TMU clocks weren't present in the original R8A77970 patch by Daisuke +Matsushita, they were added in a later BSP version... + +Based on the original (and large) patch by Vladimir Barinov. + +Signed-off-by: Vladimir Barinov +Signed-off-by: Sergei Shtylyov +Signed-off-by: Geert Uytterhoeven +(cherry picked from commit 6207ba04347705481d5e4021206179aadeb8e917) +Signed-off-by: Valentine Barshak +--- + drivers/clk/renesas/r8a77970-cpg-mssr.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/clk/renesas/r8a77970-cpg-mssr.c b/drivers/clk/renesas/r8a77970-cpg-mssr.c +index f07a1ee..7a85e1a 100644 +--- a/drivers/clk/renesas/r8a77970-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a77970-cpg-mssr.c +@@ -106,6 +106,11 @@ static const struct cpg_core_clk r8a77970_core_clks[] __initconst = { + }; + + static const struct mssr_mod_clk r8a77970_mod_clks[] __initconst = { ++ DEF_MOD("tmu4", 121, R8A77970_CLK_S2D2), ++ DEF_MOD("tmu3", 122, R8A77970_CLK_S2D2), ++ DEF_MOD("tmu2", 123, R8A77970_CLK_S2D2), ++ DEF_MOD("tmu1", 124, R8A77970_CLK_S2D2), ++ DEF_MOD("tmu0", 125, R8A77970_CLK_CP), + DEF_MOD("ivcp1e", 127, R8A77970_CLK_S2D1), + DEF_MOD("scif4", 203, R8A77970_CLK_S2D4), + DEF_MOD("scif3", 204, R8A77970_CLK_S2D4), +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0239-dt-bindings-display-renesas-du-document-R8A77980-bin.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0239-dt-bindings-display-renesas-du-document-R8A77980-bin.patch new file mode 100644 index 00000000..f20394f0 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0239-dt-bindings-display-renesas-du-document-R8A77980-bin.patch @@ -0,0 +1,43 @@ +From 9c2fc01ec6af67cbe69d61e15caf98f620cff08a Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Mon, 4 Jun 2018 22:04:59 +0300 +Subject: [PATCH 059/211] dt-bindings: display: renesas: du: document R8A77980 + bindings + +Document the R-Car V3H (R8A77980) SoC in the R-Car DU bindings; the DU +hardware has the same topology as in the R-Car V3M (R8A77970). + +Signed-off-by: Sergei Shtylyov +Reviewed-by: Simon Horman +Reviewed-by: Laurent Pinchart +Signed-off-by: Laurent Pinchart +(cherry picked from commit 4ffe5aa53791ac5ab2c29e99f23c07cb85922dd5) +[valentine.barshak: resolved minor conflicts] +Signed-off-by: Valentine Barshak +--- + Documentation/devicetree/bindings/display/renesas,du.txt | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/Documentation/devicetree/bindings/display/renesas,du.txt b/Documentation/devicetree/bindings/display/renesas,du.txt +index 7110432..101614c 100644 +--- a/Documentation/devicetree/bindings/display/renesas,du.txt ++++ b/Documentation/devicetree/bindings/display/renesas,du.txt +@@ -15,6 +15,7 @@ Required Properties: + - "renesas,du-r8a7796" for R8A7796 (R-Car M3-W) compatible DU + - "renesas,du-r8a77965" for R8A77965 (R-Car M3-N) compatible DU + - "renesas,du-r8a77970" for R8A77970 (R-Car V3M) compatible DU ++ - "renesas,du-r8a77980" for R8A77980 (R-Car V3H) compatible DU + - "renesas,du-r8a77990" for R8A77990 (R-Car E3) compatible DU + - "renesas,du-r8a77995" for R8A77995 (R-Car D3) compatible DU + +@@ -63,6 +64,7 @@ corresponding to each DU output. + R8A7796 (R-Car M3-W) DPAD 0 HDMI 0 LVDS 0 - + R8A77965 (R-Car M3-N) DPAD 0 HDMI 0 LVDS 0 - + R8A77970 (R-Car V3M) DPAD 0 LVDS 0 - - ++ R8A77980 (R-Car V3H) DPAD 0 LVDS 0 - - + R8A77990 (R-Car E3) DPAD 0 LVDS 0 LVDS 1 - + R8A77995 (R-Car D3) DPAD 0 LVDS 0 LVDS 1 - + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0240-dt-bindings-display-renesas-lvds-document-R8A77980-b.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0240-dt-bindings-display-renesas-lvds-document-R8A77980-b.patch new file mode 100644 index 00000000..6d5977e0 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0240-dt-bindings-display-renesas-lvds-document-R8A77980-b.patch @@ -0,0 +1,34 @@ +From 4200cbf65e9462e8cf342a2feb25361f3939f8d0 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Tue, 5 Jun 2018 23:28:58 +0300 +Subject: [PATCH 060/211] dt-bindings: display: renesas: lvds: document + R8A77980 bindings + +Document the R-Car V3H (R8A77980) SoC in the R-Car LVDS bindings. + +Signed-off-by: Sergei Shtylyov +Acked-by: Rob Herring +Reviewed-by: Laurent Pinchart +Signed-off-by: Laurent Pinchart +(cherry picked from commit ab77eb4c4de77a3095abbc213b8f191c58ebdca1) +[valentine.barshak: resolved minor conflicts] +Signed-off-by: Valentine Barshak +--- + Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt +index 3589e54..32df75a 100644 +--- a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt ++++ b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt +@@ -15,6 +15,7 @@ Required properties: + - "renesas,r8a7796-lvds" for R8A7796 (R-Car M3-W) compatible LVDS encoders + - "renesas,r8a77965-lvds" for R8A77965 (R-Car M3-N) compatible LVDS encoders + - "renesas,r8a77970-lvds" for R8A77970 (R-Car V3M) compatible LVDS encoders ++ - "renesas,r8a77980-lvds" for R8A77980 (R-Car V3H) compatible LVDS encoders + - "renesas,r8a77990-lvds" for R8A77990 (R-Car E3) compatible LVDS encoders + - "renesas,r8a77995-lvds" for R8A77995 (R-Car D3) compatible LVDS encoders + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0241-clk-renesas-r8a77970-Add-TPU-clock.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0241-clk-renesas-r8a77970-Add-TPU-clock.patch new file mode 100644 index 00000000..c6897487 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0241-clk-renesas-r8a77970-Add-TPU-clock.patch @@ -0,0 +1,35 @@ +From 09bc907bbaf56b2fdc8e917da0c98353ccb66ea4 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Wed, 19 Sep 2018 21:10:40 +0300 +Subject: [PATCH 061/211] clk: renesas: r8a77970: Add TPU clock + +The TPU0 clock wasn't present in the original R8A77970 patch by Daisuke +Matsushita, it was added in a later BSP version... + +Based on the original (and large) patch by Vladimir Barinov. + +Signed-off-by: Vladimir Barinov +Signed-off-by: Sergei Shtylyov +Reviewed-by: Simon Horman +Signed-off-by: Geert Uytterhoeven +(cherry picked from commit 9ef5e0370d3834a1ff11e22ae0a3220330890d36) +Signed-off-by: Valentine Barshak +--- + drivers/clk/renesas/r8a77970-cpg-mssr.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/clk/renesas/r8a77970-cpg-mssr.c b/drivers/clk/renesas/r8a77970-cpg-mssr.c +index 7a85e1a..71341ff 100644 +--- a/drivers/clk/renesas/r8a77970-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a77970-cpg-mssr.c +@@ -127,6 +127,7 @@ static const struct mssr_mod_clk r8a77970_mod_clks[] __initconst = { + DEF_MOD("cmt2", 301, R8A77970_CLK_R), + DEF_MOD("cmt1", 302, R8A77970_CLK_R), + DEF_MOD("cmt0", 303, R8A77970_CLK_R), ++ DEF_MOD("tpu0", 304, R8A77970_CLK_S2D4), + DEF_MOD("sd-if", 314, R8A77970_CLK_SD0), + DEF_MOD("rwdt", 402, R8A77970_CLK_R), + DEF_MOD("intc-ex", 407, R8A77970_CLK_CP), +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0242-mmc-renesas_sdhi_internal_dmac-add-R8A77970-to-white.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0242-mmc-renesas_sdhi_internal_dmac-add-R8A77970-to-white.patch new file mode 100644 index 00000000..84b37ef4 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0242-mmc-renesas_sdhi_internal_dmac-add-R8A77970-to-white.patch @@ -0,0 +1,35 @@ +From bd790ed9192f0d4f0e3c18af05fb6a39e101fba6 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Sat, 18 Aug 2018 21:08:26 +0300 +Subject: [PATCH 062/211] mmc: renesas_sdhi_internal_dmac: add R8A77970 to + whitelist + +I've successfully tested eMMC on the V3H Starter Kit board and since the +R8A77970 SoC has a single SDHI core, it can't be a subject to the known RX +DMA errata. + +Signed-off-by: Sergei Shtylyov +Reviewed-by: Wolfram Sang +Signed-off-by: Ulf Hansson +Reviewed-by: Simon Horman +(cherry picked from commit 16a129b3caacb9bf86187de8342986457e09faa9) +Signed-off-by: Valentine Barshak +--- + drivers/mmc/host/renesas_sdhi_internal_dmac.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c +index 32acb7d..6c3f657 100644 +--- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c ++++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c +@@ -331,6 +331,7 @@ static const struct soc_device_attribute gen3_soc_whitelist[] = { + { .soc_id = "r8a7795" }, + { .soc_id = "r8a7796" }, + { .soc_id = "r8a77965" }, ++ { .soc_id = "r8a77970" }, + { .soc_id = "r8a77980" }, + { .soc_id = "r8a77990" }, + { .soc_id = "r8a77995" }, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0243-dt-bindings-mmc-tmio_mmc-document-Renesas-R8A77970-b.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0243-dt-bindings-mmc-tmio_mmc-document-Renesas-R8A77970-b.patch new file mode 100644 index 00000000..a482dd6a --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0243-dt-bindings-mmc-tmio_mmc-document-Renesas-R8A77970-b.patch @@ -0,0 +1,33 @@ +From d8aa4c14b62f4a1b96677b4e3173a64cf0ced214 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Tue, 21 Aug 2018 22:14:12 +0300 +Subject: [PATCH 063/211] dt-bindings: mmc: tmio_mmc: document Renesas R8A77970 + bindings + +Document the R-Car V3M (R8A77970) SoC in the R-Car SDHI bindings -- it's +the usual R-Car gen3 compatible controller with the internal DMA engine. + +Signed-off-by: Sergei Shtylyov +Signed-off-by: Ulf Hansson +Reviewed-by: Simon Horman +(cherry picked from commit 00c6527b8311e598ad9bfec8415fe96a94fa1b1b) +Signed-off-by: Valentine Barshak +--- + Documentation/devicetree/bindings/mmc/tmio_mmc.txt | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Documentation/devicetree/bindings/mmc/tmio_mmc.txt b/Documentation/devicetree/bindings/mmc/tmio_mmc.txt +index c434200..9d0ea43 100644 +--- a/Documentation/devicetree/bindings/mmc/tmio_mmc.txt ++++ b/Documentation/devicetree/bindings/mmc/tmio_mmc.txt +@@ -27,6 +27,7 @@ Required properties: + "renesas,sdhi-r8a7795" - SDHI IP on R8A7795 SoC + "renesas,sdhi-r8a7796" - SDHI IP on R8A7796 SoC + "renesas,sdhi-r8a77965" - SDHI IP on R8A77965 SoC ++ "renesas,sdhi-r8a77970" - SDHI IP on R8A77970 SoC + "renesas,sdhi-r8a77980" - SDHI IP on R8A77980 SoC + "renesas,sdhi-r8a77990" - SDHI IP on R8A77990 SoC + "renesas,sdhi-r8a77995" - SDHI IP on R8A77995 SoC +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0244-dt-bindings-thermal-rcar-gen3-thermal-document-R8A77.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0244-dt-bindings-thermal-rcar-gen3-thermal-document-R8A77.patch new file mode 100644 index 00000000..34ff8a6c --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0244-dt-bindings-thermal-rcar-gen3-thermal-document-R8A77.patch @@ -0,0 +1,49 @@ +From f33694d540db9a8c5e0e736c22d764b85ec4eea8 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Tue, 9 Oct 2018 22:10:14 +0300 +Subject: [PATCH 064/211] dt-bindings: thermal: rcar-gen3-thermal: document + R8A77980 bindings +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Document the R-Car V3H (R8A77980) SoC in the Renesas R-Car gen3 thermal +bindings. + +Signed-off-by: Sergei Shtylyov +Reviewed-by: Simon Horman +Reviewed-by: Niklas Söderlund +Reviewed-by: Rob Herring +Signed-off-by: Eduardo Valentin +(cherry picked from commit 8583d8d621eb7f38e388dfe53a45fff908ccf07d) +[valentine.barshak: resolved a minor conflict] +Signed-off-by: Valentine Barshak +--- + Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.txt | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.txt b/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.txt +index 261c3fe..7bb6d0b 100644 +--- a/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.txt ++++ b/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.txt +@@ -11,6 +11,7 @@ Required properties: + - "renesas,r8a7796-thermal" (R-Car M3-W) + - "renesas,r8a77965-thermal" (R-Car M3-N) + - "renesas,r8a77990-thermal" (R-Car E3) ++ - "renesas,r8a77980-thermal" (R-Car V3H) + - reg : Address ranges of the thermal registers. Each sensor + needs one address range. Sorting must be done in + increasing order according to datasheet, i.e. +@@ -20,7 +21,8 @@ Required properties: + + Optional properties: + +-- interrupts : interrupts routed to the TSC (3 for H3, M3-W and M3-N) ++- interrupts : interrupts routed to the TSC (3 for H3, M3-W, M3-N, ++ and V3H) + - power-domain : Must contain a reference to the power domain. This + property is mandatory if the thermal sensor instance + is part of a controllable power domain. +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0245-thermal-rcar_gen3_thermal-add-R8A77980-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0245-thermal-rcar_gen3_thermal-add-R8A77980-support.patch new file mode 100644 index 00000000..6b20a2b5 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0245-thermal-rcar_gen3_thermal-add-R8A77980-support.patch @@ -0,0 +1,39 @@ +From d156c8fc896a879704fcbbe87e2b923d84df89e9 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Tue, 9 Oct 2018 22:11:51 +0300 +Subject: [PATCH 065/211] thermal: rcar_gen3_thermal: add R8A77980 support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add the R-Car V3H (R8A77980) SoC support to the R-Car gen3 thermal driver. + +Signed-off-by: Sergei Shtylyov +Reviewed-by: Simon Horman +Reviewed-by: Niklas Söderlund +Signed-off-by: Eduardo Valentin +(cherry picked from commit 853cbc1f2d3a6ef9d5f6f99fe7c4b7595eae9d3a) +[valentine.barshak: resolved a minor conflict] +Signed-off-by: Valentine Barshak +--- + drivers/thermal/rcar_gen3_thermal.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c +index ae17e73..37e9308 100644 +--- a/drivers/thermal/rcar_gen3_thermal.c ++++ b/drivers/thermal/rcar_gen3_thermal.c +@@ -516,8 +516,10 @@ static const struct of_device_id rcar_gen3_thermal_dt_ids[] = { + { .compatible = "renesas,r8a7795-thermal", }, + { .compatible = "renesas,r8a7796-thermal", }, + { .compatible = "renesas,r8a77965-thermal", }, ++ { .compatible = "renesas,r8a77980-thermal", }, + { .compatible = "renesas,r8a77990-thermal", }, + { /*sentinel*/ }, ++ {}, + }; + MODULE_DEVICE_TABLE(of, rcar_gen3_thermal_dt_ids); + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0246-dt-bindings-thermal-rcar-thermal-document-R8A77970-b.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0246-dt-bindings-thermal-rcar-thermal-document-R8A77970-b.patch new file mode 100644 index 00000000..8f2da116 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0246-dt-bindings-thermal-rcar-thermal-document-R8A77970-b.patch @@ -0,0 +1,54 @@ +From 6a99288d90a45d6b92664a89ec5ab2939840ecf2 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Fri, 5 Oct 2018 00:01:38 +0300 +Subject: [PATCH 066/211] dt-bindings: thermal: rcar-thermal: document R8A77970 + bindings + +Document the R-Car V3M (R8A77970) SoC in the Renesas R-Car gen2 thermal +bindings. The hardware is the same as in the R-Car D3 (R8A77995) plus an +extra status register. + +Signed-off-by: Sergei Shtylyov +Reviewed-by: Geert Uytterhoeven +Reviewed-by: Simon Horman +Reviewed-by: Rob Herring +Signed-off-by: Eduardo Valentin +(cherry picked from commit a14404a9f04b904bd0c22f34e2119afbf1425abe) +Signed-off-by: Valentine Barshak +--- + Documentation/devicetree/bindings/thermal/rcar-thermal.txt | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/Documentation/devicetree/bindings/thermal/rcar-thermal.txt b/Documentation/devicetree/bindings/thermal/rcar-thermal.txt +index 67c563f..6176558 100644 +--- a/Documentation/devicetree/bindings/thermal/rcar-thermal.txt ++++ b/Documentation/devicetree/bindings/thermal/rcar-thermal.txt +@@ -4,7 +4,7 @@ Required properties: + - compatible : "renesas,thermal-", + "renesas,rcar-gen2-thermal" (with thermal-zone) or + "renesas,rcar-thermal" (without thermal-zone) as +- fallback except R-Car D3. ++ fallback except R-Car V3M/D3. + Examples with soctypes are: + - "renesas,thermal-r8a73a4" (R-Mobile APE6) + - "renesas,thermal-r8a7743" (RZ/G1M) +@@ -13,6 +13,7 @@ Required properties: + - "renesas,thermal-r8a7791" (R-Car M2-W) + - "renesas,thermal-r8a7792" (R-Car V2H) + - "renesas,thermal-r8a7793" (R-Car M2-N) ++ - "renesas,thermal-r8a77970" (R-Car V3M) + - "renesas,thermal-r8a77995" (R-Car D3) + - reg : Address range of the thermal registers. + The 1st reg will be recognized as common register +@@ -21,7 +22,7 @@ Required properties: + Option properties: + + - interrupts : If present should contain 3 interrupts for +- R-Car D3 or 1 interrupt otherwise. ++ R-Car V3M/D3 or 1 interrupt otherwise. + + Example (non interrupt support): + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0247-thermal-rcar_thermal-add-R8A77970-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0247-thermal-rcar_thermal-add-R8A77970-support.patch new file mode 100644 index 00000000..af4b3d6a --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0247-thermal-rcar_thermal-add-R8A77970-support.patch @@ -0,0 +1,37 @@ +From 02c9e06095279dff4a1a91b1aacfc21c184c6c53 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Fri, 5 Oct 2018 00:03:13 +0300 +Subject: [PATCH 067/211] thermal: rcar_thermal: add R8A77970 support + +Add the R-Car V3M (R8A77970) SoC support to the R-Car gen2 thermal driver. +The hardware is the same as in the R-Car D3 (R8A77995) plus the CIVM status +register (we don't use). + +Signed-off-by: Sergei Shtylyov +Reviewed-by: Geert Uytterhoeven +Reviewed-by: Simon Horman +Signed-off-by: Eduardo Valentin +(cherry picked from commit 92ca366e9b835ada0bfe3c663da91ae44d7e8184) +Signed-off-by: Valentine Barshak +--- + drivers/thermal/rcar_thermal.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c +index e77e6307..e3fd253 100644 +--- a/drivers/thermal/rcar_thermal.c ++++ b/drivers/thermal/rcar_thermal.c +@@ -125,6 +125,10 @@ static const struct of_device_id rcar_thermal_dt_ids[] = { + .data = &rcar_gen2_thermal, + }, + { ++ .compatible = "renesas,thermal-r8a77970", ++ .data = &rcar_gen3_thermal, ++ }, ++ { + .compatible = "renesas,thermal-r8a77995", + .data = &rcar_gen3_thermal, + }, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0248-clk-renesas-r8a77970-Add-RPC-clocks.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0248-clk-renesas-r8a77970-Add-RPC-clocks.patch new file mode 100644 index 00000000..3f885120 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0248-clk-renesas-r8a77970-Add-RPC-clocks.patch @@ -0,0 +1,41 @@ +From 75998e4d0480f8aba180df2c6da5b0b374487b6b Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Fri, 2 Nov 2018 22:25:54 +0300 +Subject: [PATCH 068/211] clk: renesas: r8a77970: Add RPC clocks + +On R-Car V3M (R8A77970), the RPC/RPCD2 clocks are output by the common +divider. Describe them, as well as the RPC-IF module clock. + +Signed-off-by: Sergei Shtylyov +Signed-off-by: Geert Uytterhoeven +(cherry picked from commit 6f44610c30c5f10a8ea06bd714015cc4d2e534f5) +Signed-off-by: Valentine Barshak +--- + drivers/clk/renesas/r8a77970-cpg-mssr.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/clk/renesas/r8a77970-cpg-mssr.c b/drivers/clk/renesas/r8a77970-cpg-mssr.c +index 71341ff..6885c62 100644 +--- a/drivers/clk/renesas/r8a77970-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a77970-cpg-mssr.c +@@ -94,6 +94,9 @@ static const struct cpg_core_clk r8a77970_core_clks[] __initconst = { + CLK_PLL1_DIV2), + DEF_BASE("sd0", R8A77970_CLK_SD0, CLK_TYPE_R8A77970_SD0, CLK_PLL1_DIV2), + ++ DEF_FIXED("rpc", R8A77970_CLK_RPC, CLK_PLL1_DIV2, 5, 1), ++ DEF_FIXED("rpcd2", R8A77970_CLK_RPCD2, CLK_PLL1_DIV2, 10, 1), ++ + DEF_FIXED("cl", R8A77970_CLK_CL, CLK_PLL1_DIV2, 48, 1), + DEF_FIXED("cp", R8A77970_CLK_CP, CLK_EXTAL, 2, 1), + +@@ -155,6 +158,7 @@ static const struct mssr_mod_clk r8a77970_mod_clks[] __initconst = { + DEF_MOD("gpio1", 911, R8A77970_CLK_CP), + DEF_MOD("gpio0", 912, R8A77970_CLK_CP), + DEF_MOD("can-fd", 914, R8A77970_CLK_S2D2), ++ DEF_MOD("rpc-if", 917, R8A77970_CLK_RPC), + DEF_MOD("i2c4", 927, R8A77970_CLK_S2D2), + DEF_MOD("i2c3", 928, R8A77970_CLK_S2D2), + DEF_MOD("i2c2", 929, R8A77970_CLK_S2D2), +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0249-pinctrl-sh-pfc-r8a77970-Add-QSPI-pins-groups-and-fun.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0249-pinctrl-sh-pfc-r8a77970-Add-QSPI-pins-groups-and-fun.patch new file mode 100644 index 00000000..50a25854 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0249-pinctrl-sh-pfc-r8a77970-Add-QSPI-pins-groups-and-fun.patch @@ -0,0 +1,128 @@ +From 41ae73397a4480f0061be5ac96c73ea73601fe40 Mon Sep 17 00:00:00 2001 +From: Dmitry Shifrin +Date: Tue, 6 Nov 2018 21:52:55 +0300 +Subject: [PATCH 069/211] pinctrl: sh-pfc: r8a77970: Add QSPI pins, groups, and + functions + +Add the QSPI{0|1} pins/groups/functions to the R8A77970 PFC driver. + +[Sergei: ported to the upstream driver, fixed up the swapped QSPI0 SPCLK/ +SSL pins, fixed up the comments, moved the QSPI pins/groups/functions to +be in the alphanumeric order, removed unneeded empty lines, renamed the +patch.] + +Signed-off-by: Dmitry Shifrin +Signed-off-by: Sergei Shtylyov +Reviewed-by: Simon Horman +Signed-off-by: Geert Uytterhoeven +(cherry picked from commit 3ad8fbd83fab8125004c6953563779c89331fa25) +Signed-off-by: Valentine Barshak +--- + drivers/pinctrl/sh-pfc/pfc-r8a77970.c | 70 +++++++++++++++++++++++++++++++++++ + 1 file changed, 70 insertions(+) + +diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a77970.c b/drivers/pinctrl/sh-pfc/pfc-r8a77970.c +index eeb58b3..9b96e5d 100644 +--- a/drivers/pinctrl/sh-pfc/pfc-r8a77970.c ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a77970.c +@@ -1385,6 +1385,56 @@ static const unsigned int pwm4_b_mux[] = { + PWM4_B_MARK, + }; + ++/* - QSPI0 ------------------------------------------------------------------ */ ++static const unsigned int qspi0_ctrl_pins[] = { ++ /* SPCLK, SSL */ ++ RCAR_GP_PIN(5, 0), RCAR_GP_PIN(5, 5), ++}; ++static const unsigned int qspi0_ctrl_mux[] = { ++ QSPI0_SPCLK_MARK, QSPI0_SSL_MARK, ++}; ++static const unsigned int qspi0_data2_pins[] = { ++ /* MOSI_IO0, MISO_IO1 */ ++ RCAR_GP_PIN(5, 1), RCAR_GP_PIN(5, 2), ++}; ++static const unsigned int qspi0_data2_mux[] = { ++ QSPI0_MOSI_IO0_MARK, QSPI0_MISO_IO1_MARK, ++}; ++static const unsigned int qspi0_data4_pins[] = { ++ /* MOSI_IO0, MISO_IO1, IO2, IO3 */ ++ RCAR_GP_PIN(5, 1), RCAR_GP_PIN(5, 2), ++ RCAR_GP_PIN(5, 3), RCAR_GP_PIN(5, 4), ++}; ++static const unsigned int qspi0_data4_mux[] = { ++ QSPI0_MOSI_IO0_MARK, QSPI0_MISO_IO1_MARK, ++ QSPI0_IO2_MARK, QSPI0_IO3_MARK ++}; ++ ++/* - QSPI1 ------------------------------------------------------------------ */ ++static const unsigned int qspi1_ctrl_pins[] = { ++ /* SPCLK, SSL */ ++ RCAR_GP_PIN(5, 6), RCAR_GP_PIN(5, 11), ++}; ++static const unsigned int qspi1_ctrl_mux[] = { ++ QSPI1_SPCLK_MARK, QSPI1_SSL_MARK, ++}; ++static const unsigned int qspi1_data2_pins[] = { ++ /* MOSI_IO0, MISO_IO1 */ ++ RCAR_GP_PIN(5, 7), RCAR_GP_PIN(5, 8), ++}; ++static const unsigned int qspi1_data2_mux[] = { ++ QSPI1_MOSI_IO0_MARK, QSPI1_MISO_IO1_MARK, ++}; ++static const unsigned int qspi1_data4_pins[] = { ++ /* MOSI_IO0, MISO_IO1, IO2, IO3 */ ++ RCAR_GP_PIN(5, 7), RCAR_GP_PIN(5, 8), ++ RCAR_GP_PIN(5, 9), RCAR_GP_PIN(5, 10), ++}; ++static const unsigned int qspi1_data4_mux[] = { ++ QSPI1_MOSI_IO0_MARK, QSPI1_MISO_IO1_MARK, ++ QSPI1_IO2_MARK, QSPI1_IO3_MARK ++}; ++ + /* - SCIF Clock ------------------------------------------------------------- */ + static const unsigned int scif_clk_a_pins[] = { + /* SCIF_CLK */ +@@ -1759,6 +1809,12 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { + SH_PFC_PIN_GROUP(pwm3_b), + SH_PFC_PIN_GROUP(pwm4_a), + SH_PFC_PIN_GROUP(pwm4_b), ++ SH_PFC_PIN_GROUP(qspi0_ctrl), ++ SH_PFC_PIN_GROUP(qspi0_data2), ++ SH_PFC_PIN_GROUP(qspi0_data4), ++ SH_PFC_PIN_GROUP(qspi1_ctrl), ++ SH_PFC_PIN_GROUP(qspi1_data2), ++ SH_PFC_PIN_GROUP(qspi1_data4), + SH_PFC_PIN_GROUP(scif_clk_a), + SH_PFC_PIN_GROUP(scif_clk_b), + SH_PFC_PIN_GROUP(scif0_data), +@@ -1953,6 +2009,18 @@ static const char * const pwm4_groups[] = { + "pwm4_b", + }; + ++static const char * const qspi0_groups[] = { ++ "qspi0_ctrl", ++ "qspi0_data2", ++ "qspi0_data4", ++}; ++ ++static const char * const qspi1_groups[] = { ++ "qspi1_ctrl", ++ "qspi1_data2", ++ "qspi1_data4", ++}; ++ + static const char * const scif_clk_groups[] = { + "scif_clk_a", + "scif_clk_b", +@@ -2036,6 +2104,8 @@ static const struct sh_pfc_function pinmux_functions[] = { + SH_PFC_FUNCTION(pwm2), + SH_PFC_FUNCTION(pwm3), + SH_PFC_FUNCTION(pwm4), ++ SH_PFC_FUNCTION(qspi0), ++ SH_PFC_FUNCTION(qspi1), + SH_PFC_FUNCTION(scif_clk), + SH_PFC_FUNCTION(scif0), + SH_PFC_FUNCTION(scif1), +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0250-pinctrl-sh-pfc-r8a77980-Add-QSPI-pins-groups-and-fun.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0250-pinctrl-sh-pfc-r8a77980-Add-QSPI-pins-groups-and-fun.patch new file mode 100644 index 00000000..3be45faf --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0250-pinctrl-sh-pfc-r8a77980-Add-QSPI-pins-groups-and-fun.patch @@ -0,0 +1,127 @@ +From 45a14984163349d8ea4db1463322944e54e7ce54 Mon Sep 17 00:00:00 2001 +From: Dmitry Shifrin +Date: Mon, 19 Nov 2018 20:30:06 +0300 +Subject: [PATCH 070/211] pinctrl: sh-pfc: r8a77980: Add QSPI pins, groups, and + functions + +Add the QSPI{0|1} pins/groups/functions to the R8A77980 PFC driver. + +[Sergei: ported to the upstream driver, fixed up the swapped QSPI0 SPCLK/ +SSL pins, fixed up the comments, moved the QSPI pins/groups/functions to +be in the alphanumeric order, removed unneeded empty lines, renamed the +patch.] + +Signed-off-by: Dmitry Shifrin +Signed-off-by: Sergei Shtylyov +Signed-off-by: Geert Uytterhoeven +(cherry picked from commit c21b73235e1fa644dcc725078af38e13cdb778fb) +Signed-off-by: Valentine Barshak +--- + drivers/pinctrl/sh-pfc/pfc-r8a77980.c | 70 +++++++++++++++++++++++++++++++++++ + 1 file changed, 70 insertions(+) + +diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a77980.c b/drivers/pinctrl/sh-pfc/pfc-r8a77980.c +index 3f69673..aa1d50b 100644 +--- a/drivers/pinctrl/sh-pfc/pfc-r8a77980.c ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a77980.c +@@ -1660,6 +1660,56 @@ static const unsigned int pwm4_b_mux[] = { + PWM4_B_MARK, + }; + ++/* - QSPI0 ------------------------------------------------------------------ */ ++static const unsigned int qspi0_ctrl_pins[] = { ++ /* SPCLK, SSL */ ++ RCAR_GP_PIN(5, 0), RCAR_GP_PIN(5, 5), ++}; ++static const unsigned int qspi0_ctrl_mux[] = { ++ QSPI0_SPCLK_MARK, QSPI0_SSL_MARK, ++}; ++static const unsigned int qspi0_data2_pins[] = { ++ /* MOSI_IO0, MISO_IO1 */ ++ RCAR_GP_PIN(5, 1), RCAR_GP_PIN(5, 2), ++}; ++static const unsigned int qspi0_data2_mux[] = { ++ QSPI0_MOSI_IO0_MARK, QSPI0_MISO_IO1_MARK, ++}; ++static const unsigned int qspi0_data4_pins[] = { ++ /* MOSI_IO0, MISO_IO1, IO2, IO3 */ ++ RCAR_GP_PIN(5, 1), RCAR_GP_PIN(5, 2), ++ RCAR_GP_PIN(5, 3), RCAR_GP_PIN(5, 4), ++}; ++static const unsigned int qspi0_data4_mux[] = { ++ QSPI0_MOSI_IO0_MARK, QSPI0_MISO_IO1_MARK, ++ QSPI0_IO2_MARK, QSPI0_IO3_MARK ++}; ++ ++/* - QSPI1 ------------------------------------------------------------------ */ ++static const unsigned int qspi1_ctrl_pins[] = { ++ /* SPCLK, SSL */ ++ RCAR_GP_PIN(5, 6), RCAR_GP_PIN(5, 11), ++}; ++static const unsigned int qspi1_ctrl_mux[] = { ++ QSPI1_SPCLK_MARK, QSPI1_SSL_MARK, ++}; ++static const unsigned int qspi1_data2_pins[] = { ++ /* MOSI_IO0, MISO_IO1 */ ++ RCAR_GP_PIN(5, 7), RCAR_GP_PIN(5, 8), ++}; ++static const unsigned int qspi1_data2_mux[] = { ++ QSPI1_MOSI_IO0_MARK, QSPI1_MISO_IO1_MARK, ++}; ++static const unsigned int qspi1_data4_pins[] = { ++ /* MOSI_IO0, MISO_IO1, IO2, IO3 */ ++ RCAR_GP_PIN(5, 7), RCAR_GP_PIN(5, 8), ++ RCAR_GP_PIN(5, 9), RCAR_GP_PIN(5, 10), ++}; ++static const unsigned int qspi1_data4_mux[] = { ++ QSPI1_MOSI_IO0_MARK, QSPI1_MISO_IO1_MARK, ++ QSPI1_IO2_MARK, QSPI1_IO3_MARK ++}; ++ + /* - SCIF0 ------------------------------------------------------------------ */ + static const unsigned int scif0_data_pins[] = { + /* RX0, TX0 */ +@@ -2092,6 +2142,12 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { + SH_PFC_PIN_GROUP(pwm3_b), + SH_PFC_PIN_GROUP(pwm4_a), + SH_PFC_PIN_GROUP(pwm4_b), ++ SH_PFC_PIN_GROUP(qspi0_ctrl), ++ SH_PFC_PIN_GROUP(qspi0_data2), ++ SH_PFC_PIN_GROUP(qspi0_data4), ++ SH_PFC_PIN_GROUP(qspi1_ctrl), ++ SH_PFC_PIN_GROUP(qspi1_data2), ++ SH_PFC_PIN_GROUP(qspi1_data4), + SH_PFC_PIN_GROUP(scif0_data), + SH_PFC_PIN_GROUP(scif0_clk), + SH_PFC_PIN_GROUP(scif0_ctrl), +@@ -2316,6 +2372,18 @@ static const char * const pwm4_groups[] = { + "pwm4_b", + }; + ++static const char * const qspi0_groups[] = { ++ "qspi0_ctrl", ++ "qspi0_data2", ++ "qspi0_data4", ++}; ++ ++static const char * const qspi1_groups[] = { ++ "qspi1_ctrl", ++ "qspi1_data2", ++ "qspi1_data4", ++}; ++ + static const char * const scif0_groups[] = { + "scif0_data", + "scif0_clk", +@@ -2412,6 +2480,8 @@ static const struct sh_pfc_function pinmux_functions[] = { + SH_PFC_FUNCTION(pwm2), + SH_PFC_FUNCTION(pwm3), + SH_PFC_FUNCTION(pwm4), ++ SH_PFC_FUNCTION(qspi0), ++ SH_PFC_FUNCTION(qspi1), + SH_PFC_FUNCTION(scif0), + SH_PFC_FUNCTION(scif1), + SH_PFC_FUNCTION(scif3), +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0251-media-rcar-rcar-csi2-Update-V3M-E3-PHTW-tables.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0251-media-rcar-rcar-csi2-Update-V3M-E3-PHTW-tables.patch new file mode 100644 index 00000000..3ea4c31f --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0251-media-rcar-rcar-csi2-Update-V3M-E3-PHTW-tables.patch @@ -0,0 +1,94 @@ +From edadae825e47850cdfeb8fe8c31dbf795a33ec8a Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Tue, 6 Nov 2018 05:54:26 -0500 +Subject: [PATCH 071/211] media: rcar: rcar-csi2: Update V3M/E3 PHTW tables + +Update PHTW tables for V3M and E3 SoCs to the latest datasheet release +(R-Car Series, 3rd Generation manual rev1.00 20181017). + +Signed-off-by: Jacopo Mondi +Reviewed-by: Laurent Pinchart +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit 10c08812fe60ddfd480730a58bb78616262d659a) +Signed-off-by: Valentine Barshak +--- + drivers/media/platform/rcar-vin/rcar-csi2.c | 62 ++++++++++++++--------------- + 1 file changed, 31 insertions(+), 31 deletions(-) + +diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c +index 7cb1365..52a6d52 100644 +--- a/drivers/media/platform/rcar-vin/rcar-csi2.c ++++ b/drivers/media/platform/rcar-vin/rcar-csi2.c +@@ -156,37 +156,37 @@ static const struct rcsi2_mbps_reg phtw_mbps_h3_v3h_m3n[] = { + }; + + static const struct rcsi2_mbps_reg phtw_mbps_v3m_e3[] = { +- { .mbps = 80, .reg = 0x00 }, +- { .mbps = 90, .reg = 0x20 }, +- { .mbps = 100, .reg = 0x40 }, +- { .mbps = 110, .reg = 0x02 }, +- { .mbps = 130, .reg = 0x22 }, +- { .mbps = 140, .reg = 0x42 }, +- { .mbps = 150, .reg = 0x04 }, +- { .mbps = 170, .reg = 0x24 }, +- { .mbps = 180, .reg = 0x44 }, +- { .mbps = 200, .reg = 0x06 }, +- { .mbps = 220, .reg = 0x26 }, +- { .mbps = 240, .reg = 0x46 }, +- { .mbps = 250, .reg = 0x08 }, +- { .mbps = 270, .reg = 0x28 }, +- { .mbps = 300, .reg = 0x0a }, +- { .mbps = 330, .reg = 0x2a }, +- { .mbps = 360, .reg = 0x4a }, +- { .mbps = 400, .reg = 0x0c }, +- { .mbps = 450, .reg = 0x2c }, +- { .mbps = 500, .reg = 0x0e }, +- { .mbps = 550, .reg = 0x2e }, +- { .mbps = 600, .reg = 0x10 }, +- { .mbps = 650, .reg = 0x30 }, +- { .mbps = 700, .reg = 0x12 }, +- { .mbps = 750, .reg = 0x32 }, +- { .mbps = 800, .reg = 0x52 }, +- { .mbps = 850, .reg = 0x72 }, +- { .mbps = 900, .reg = 0x14 }, +- { .mbps = 950, .reg = 0x34 }, +- { .mbps = 1000, .reg = 0x54 }, +- { .mbps = 1050, .reg = 0x74 }, ++ { .mbps = 89, .reg = 0x00 }, ++ { .mbps = 99, .reg = 0x20 }, ++ { .mbps = 109, .reg = 0x40 }, ++ { .mbps = 129, .reg = 0x02 }, ++ { .mbps = 139, .reg = 0x22 }, ++ { .mbps = 149, .reg = 0x42 }, ++ { .mbps = 169, .reg = 0x04 }, ++ { .mbps = 179, .reg = 0x24 }, ++ { .mbps = 199, .reg = 0x44 }, ++ { .mbps = 219, .reg = 0x06 }, ++ { .mbps = 239, .reg = 0x26 }, ++ { .mbps = 249, .reg = 0x46 }, ++ { .mbps = 269, .reg = 0x08 }, ++ { .mbps = 299, .reg = 0x28 }, ++ { .mbps = 329, .reg = 0x0a }, ++ { .mbps = 359, .reg = 0x2a }, ++ { .mbps = 399, .reg = 0x4a }, ++ { .mbps = 449, .reg = 0x0c }, ++ { .mbps = 499, .reg = 0x2c }, ++ { .mbps = 549, .reg = 0x0e }, ++ { .mbps = 599, .reg = 0x2e }, ++ { .mbps = 649, .reg = 0x10 }, ++ { .mbps = 699, .reg = 0x30 }, ++ { .mbps = 749, .reg = 0x12 }, ++ { .mbps = 799, .reg = 0x32 }, ++ { .mbps = 849, .reg = 0x52 }, ++ { .mbps = 899, .reg = 0x72 }, ++ { .mbps = 949, .reg = 0x14 }, ++ { .mbps = 999, .reg = 0x34 }, ++ { .mbps = 1049, .reg = 0x54 }, ++ { .mbps = 1099, .reg = 0x74 }, + { .mbps = 1125, .reg = 0x16 }, + { /* sentinel */ }, + }; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0252-soc-renesas-r8a77970-sysc-Remove-non-existent-CR7-po.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0252-soc-renesas-r8a77970-sysc-Remove-non-existent-CR7-po.patch new file mode 100644 index 00000000..f758b41d --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0252-soc-renesas-r8a77970-sysc-Remove-non-existent-CR7-po.patch @@ -0,0 +1,50 @@ +From 03b06b8d0210a6fd5f417515eb40af24c2a60878 Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Thu, 29 Nov 2018 11:56:15 +0100 +Subject: [PATCH 072/211] soc: renesas: r8a77970-sysc: Remove non-existent CR7 + power domain + +The R-Car Gen3 HardWare Manual Errata for Rev. 0.80 (Feb 28, 2018) +removed the CR7 power domain on R-Car V3M, as this SoC does not have an +ARM Cortex-R7 Realtime Core. + +As this definition was never used from DT, it can just be removed. + +Fixes: 833bdb47c826a1a6 ("dt-bindings: power: add R8A77970 SYSC power domain definitions") +Fixes: bab9b2a74fe9da96 ("soc: renesas: rcar-sysc: add R8A77970 support") +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Simon Horman +(cherry picked from commit da3e1c57caf93ed379f14686e877f806111abe7c) +Signed-off-by: Valentine Barshak +--- + drivers/soc/renesas/r8a77970-sysc.c | 1 - + include/dt-bindings/power/r8a77970-sysc.h | 1 - + 2 files changed, 2 deletions(-) + +diff --git a/drivers/soc/renesas/r8a77970-sysc.c b/drivers/soc/renesas/r8a77970-sysc.c +index a6ce15d..bd0263f 100644 +--- a/drivers/soc/renesas/r8a77970-sysc.c ++++ b/drivers/soc/renesas/r8a77970-sysc.c +@@ -24,7 +24,6 @@ static const struct rcar_sysc_area r8a77970_areas[] __initconst = { + PD_CPU_NOCR }, + { "ca53-cpu1", 0x200, 1, R8A77970_PD_CA53_CPU1, R8A77970_PD_CA53_SCU, + PD_CPU_NOCR }, +- { "cr7", 0x240, 0, R8A77970_PD_CR7, R8A77970_PD_ALWAYS_ON }, + { "a3ir", 0x180, 0, R8A77970_PD_A3IR, R8A77970_PD_ALWAYS_ON }, + { "a2ir0", 0x400, 0, R8A77970_PD_A2IR0, R8A77970_PD_A3IR }, + { "a2ir1", 0x400, 1, R8A77970_PD_A2IR1, R8A77970_PD_A3IR }, +diff --git a/include/dt-bindings/power/r8a77970-sysc.h b/include/dt-bindings/power/r8a77970-sysc.h +index bf54779..5c1ef13 100644 +--- a/include/dt-bindings/power/r8a77970-sysc.h ++++ b/include/dt-bindings/power/r8a77970-sysc.h +@@ -16,7 +16,6 @@ + + #define R8A77970_PD_CA53_CPU0 5 + #define R8A77970_PD_CA53_CPU1 6 +-#define R8A77970_PD_CR7 13 + #define R8A77970_PD_CA53_SCU 21 + #define R8A77970_PD_A2IR0 23 + #define R8A77970_PD_A3IR 24 +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0253-soc-renesas-r8a77970-sysc-Correct-names-of-A2DP-A2CN.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0253-soc-renesas-r8a77970-sysc-Correct-names-of-A2DP-A2CN.patch new file mode 100644 index 00000000..1258d2b5 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0253-soc-renesas-r8a77970-sysc-Correct-names-of-A2DP-A2CN.patch @@ -0,0 +1,61 @@ +From d55cfce2c5247cef7e9b53a0552034d247a645c7 Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Thu, 29 Nov 2018 11:56:16 +0100 +Subject: [PATCH 073/211] soc: renesas: r8a77970-sysc: Correct names of + A2DP/A2CN power domains + +The R-Car Gen3 HardWare Manual Errata for Rev. 0.80 (Feb 28, 2018) +renamed the A2IR2 and A2IR3 power domains on R-Car V3M to A2DP resp. +A2CN. + +As these definitions are not yet used from DT, they can just be renamed. + +While at it, fix the indentation of the A3IR definition. + +Fixes: 833bdb47c826a1a6 ("dt-bindings: power: add R8A77970 SYSC power domain definitions") +Fixes: bab9b2a74fe9da96 ("soc: renesas: rcar-sysc: add R8A77970 support") +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Simon Horman +(cherry picked from commit b5eb730e031acaba2d25e8f522ac5966a70885ae) +Signed-off-by: Valentine Barshak +--- + drivers/soc/renesas/r8a77970-sysc.c | 4 ++-- + include/dt-bindings/power/r8a77970-sysc.h | 6 +++--- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/soc/renesas/r8a77970-sysc.c b/drivers/soc/renesas/r8a77970-sysc.c +index bd0263f..e2c05c3 100644 +--- a/drivers/soc/renesas/r8a77970-sysc.c ++++ b/drivers/soc/renesas/r8a77970-sysc.c +@@ -27,8 +27,8 @@ static const struct rcar_sysc_area r8a77970_areas[] __initconst = { + { "a3ir", 0x180, 0, R8A77970_PD_A3IR, R8A77970_PD_ALWAYS_ON }, + { "a2ir0", 0x400, 0, R8A77970_PD_A2IR0, R8A77970_PD_A3IR }, + { "a2ir1", 0x400, 1, R8A77970_PD_A2IR1, R8A77970_PD_A3IR }, +- { "a2ir2", 0x400, 2, R8A77970_PD_A2IR2, R8A77970_PD_A3IR }, +- { "a2ir3", 0x400, 3, R8A77970_PD_A2IR3, R8A77970_PD_A3IR }, ++ { "a2dp", 0x400, 2, R8A77970_PD_A2DP, R8A77970_PD_A3IR }, ++ { "a2cn", 0x400, 3, R8A77970_PD_A2CN, R8A77970_PD_A3IR }, + { "a2sc0", 0x400, 4, R8A77970_PD_A2SC0, R8A77970_PD_A3IR }, + { "a2sc1", 0x400, 5, R8A77970_PD_A2SC1, R8A77970_PD_A3IR }, + }; +diff --git a/include/dt-bindings/power/r8a77970-sysc.h b/include/dt-bindings/power/r8a77970-sysc.h +index 5c1ef13..85cc5f2 100644 +--- a/include/dt-bindings/power/r8a77970-sysc.h ++++ b/include/dt-bindings/power/r8a77970-sysc.h +@@ -18,10 +18,10 @@ + #define R8A77970_PD_CA53_CPU1 6 + #define R8A77970_PD_CA53_SCU 21 + #define R8A77970_PD_A2IR0 23 +-#define R8A77970_PD_A3IR 24 ++#define R8A77970_PD_A3IR 24 + #define R8A77970_PD_A2IR1 27 +-#define R8A77970_PD_A2IR2 28 +-#define R8A77970_PD_A2IR3 29 ++#define R8A77970_PD_A2DP 28 ++#define R8A77970_PD_A2CN 29 + #define R8A77970_PD_A2SC0 30 + #define R8A77970_PD_A2SC1 31 + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0254-soc-renesas-r8a77980-sysc-Correct-names-of-A2DP-01-p.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0254-soc-renesas-r8a77980-sysc-Correct-names-of-A2DP-01-p.patch new file mode 100644 index 00000000..c9628dd7 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0254-soc-renesas-r8a77980-sysc-Correct-names-of-A2DP-01-p.patch @@ -0,0 +1,56 @@ +From f7f151d46fd48005b16db98a00d38c83b9792c3d Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Thu, 29 Nov 2018 11:56:17 +0100 +Subject: [PATCH 074/211] soc: renesas: r8a77980-sysc: Correct names of + A2DP[01] power domains + +The R-Car Gen3 HardWare Manual Errata for Rev. 0.80 (Feb 28, 2018) +renamed the A2PD0 and A2DP0 power domains on R-Car V3H to A2DP0 resp. +A2DP1. + +As these definitions are not yet used from DT, they can just be renamed. + +Fixes: 7755b40d07a8dba7 ("dt-bindings: power: add R8A77980 SYSC power domain definitions") +Fixes: 41d6d8bd8ae94ca9 ("soc: renesas: rcar-sysc: add R8A77980 support") +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Simon Horman +(cherry picked from commit 97473bc85b22ac610b1810b6a9a4669a6cb0b7b0) +Signed-off-by: Valentine Barshak +--- + drivers/soc/renesas/r8a77980-sysc.c | 4 ++-- + include/dt-bindings/power/r8a77980-sysc.h | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/soc/renesas/r8a77980-sysc.c b/drivers/soc/renesas/r8a77980-sysc.c +index 9265fb5..dbb2621 100644 +--- a/drivers/soc/renesas/r8a77980-sysc.c ++++ b/drivers/soc/renesas/r8a77980-sysc.c +@@ -38,8 +38,8 @@ static const struct rcar_sysc_area r8a77980_areas[] __initconst = { + { "a2sc2", 0x400, 8, R8A77980_PD_A2SC2, R8A77980_PD_A3IR }, + { "a2sc3", 0x400, 9, R8A77980_PD_A2SC3, R8A77980_PD_A3IR }, + { "a2sc4", 0x400, 10, R8A77980_PD_A2SC4, R8A77980_PD_A3IR }, +- { "a2pd0", 0x400, 11, R8A77980_PD_A2PD0, R8A77980_PD_A3IR }, +- { "a2pd1", 0x400, 12, R8A77980_PD_A2PD1, R8A77980_PD_A3IR }, ++ { "a2dp0", 0x400, 11, R8A77980_PD_A2DP0, R8A77980_PD_A3IR }, ++ { "a2dp1", 0x400, 12, R8A77980_PD_A2DP1, R8A77980_PD_A3IR }, + { "a2cn", 0x400, 13, R8A77980_PD_A2CN, R8A77980_PD_A3IR }, + { "a3vip", 0x2c0, 0, R8A77980_PD_A3VIP, R8A77980_PD_ALWAYS_ON }, + { "a3vip1", 0x300, 0, R8A77980_PD_A3VIP1, R8A77980_PD_A3VIP }, +diff --git a/include/dt-bindings/power/r8a77980-sysc.h b/include/dt-bindings/power/r8a77980-sysc.h +index 2c90c12..7bebe7e 100644 +--- a/include/dt-bindings/power/r8a77980-sysc.h ++++ b/include/dt-bindings/power/r8a77980-sysc.h +@@ -15,8 +15,8 @@ + #define R8A77980_PD_A2SC2 0 + #define R8A77980_PD_A2SC3 1 + #define R8A77980_PD_A2SC4 2 +-#define R8A77980_PD_A2PD0 3 +-#define R8A77980_PD_A2PD1 4 ++#define R8A77980_PD_A2DP0 3 ++#define R8A77980_PD_A2DP1 4 + #define R8A77980_PD_CA53_CPU0 5 + #define R8A77980_PD_CA53_CPU1 6 + #define R8A77980_PD_CA53_CPU2 7 +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0255-soc-renesas-r8a77980-sysc-Correct-A3VIP-012-power-do.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0255-soc-renesas-r8a77980-sysc-Correct-A3VIP-012-power-do.patch new file mode 100644 index 00000000..6a793247 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0255-soc-renesas-r8a77980-sysc-Correct-A3VIP-012-power-do.patch @@ -0,0 +1,57 @@ +From bd93251ce884a70ef9596b078886417a9d47dd8c Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Thu, 29 Nov 2018 11:56:18 +0100 +Subject: [PATCH 075/211] soc: renesas: r8a77980-sysc: Correct A3VIP[012] power + domain hierarchy + +The R-Car Gen3 HardWare Manual Errata for Rev. 0.80 (Feb 28, 2018) +renamed the A3VIP power domain on R-Car V3H to A3VIP0, and clarified the +power domain hierarchy for the A3VIP[012] power domains. + +As the definition for the A3VIP0 domain is not yet used from DT, it can +just be renamed. + +Fixes: 7755b40d07a8dba7 ("dt-bindings: power: add R8A77980 SYSC power domain definitions") +Fixes: 41d6d8bd8ae94ca9 ("soc: renesas: rcar-sysc: add R8A77980 support") +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Simon Horman +(cherry picked from commit 160bfa7c724b348a90a12dd9694f351927a15b8e) +Signed-off-by: Valentine Barshak +--- + drivers/soc/renesas/r8a77980-sysc.c | 6 +++--- + include/dt-bindings/power/r8a77980-sysc.h | 2 +- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/soc/renesas/r8a77980-sysc.c b/drivers/soc/renesas/r8a77980-sysc.c +index dbb2621..a8dbe55 100644 +--- a/drivers/soc/renesas/r8a77980-sysc.c ++++ b/drivers/soc/renesas/r8a77980-sysc.c +@@ -41,9 +41,9 @@ static const struct rcar_sysc_area r8a77980_areas[] __initconst = { + { "a2dp0", 0x400, 11, R8A77980_PD_A2DP0, R8A77980_PD_A3IR }, + { "a2dp1", 0x400, 12, R8A77980_PD_A2DP1, R8A77980_PD_A3IR }, + { "a2cn", 0x400, 13, R8A77980_PD_A2CN, R8A77980_PD_A3IR }, +- { "a3vip", 0x2c0, 0, R8A77980_PD_A3VIP, R8A77980_PD_ALWAYS_ON }, +- { "a3vip1", 0x300, 0, R8A77980_PD_A3VIP1, R8A77980_PD_A3VIP }, +- { "a3vip2", 0x280, 0, R8A77980_PD_A3VIP2, R8A77980_PD_A3VIP }, ++ { "a3vip0", 0x2c0, 0, R8A77980_PD_A3VIP0, R8A77980_PD_ALWAYS_ON }, ++ { "a3vip1", 0x300, 0, R8A77980_PD_A3VIP1, R8A77980_PD_ALWAYS_ON }, ++ { "a3vip2", 0x280, 0, R8A77980_PD_A3VIP2, R8A77980_PD_ALWAYS_ON }, + }; + + const struct rcar_sysc_info r8a77980_sysc_info __initconst = { +diff --git a/include/dt-bindings/power/r8a77980-sysc.h b/include/dt-bindings/power/r8a77980-sysc.h +index 7bebe7e..e12c858 100644 +--- a/include/dt-bindings/power/r8a77980-sysc.h ++++ b/include/dt-bindings/power/r8a77980-sysc.h +@@ -22,7 +22,7 @@ + #define R8A77980_PD_CA53_CPU2 7 + #define R8A77980_PD_CA53_CPU3 8 + #define R8A77980_PD_A2CN 10 +-#define R8A77980_PD_A3VIP 11 ++#define R8A77980_PD_A3VIP0 11 + #define R8A77980_PD_A2IR5 12 + #define R8A77980_PD_CR7 13 + #define R8A77980_PD_A2IR4 15 +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0256-clk-renesas-r8a77970-Add-CPEX-clock.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0256-clk-renesas-r8a77970-Add-CPEX-clock.patch new file mode 100644 index 00000000..188b77a7 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0256-clk-renesas-r8a77970-Add-CPEX-clock.patch @@ -0,0 +1,31 @@ +From 3674769e16cf1368462cb8e57d111a0937c4d329 Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Wed, 21 Nov 2018 10:44:32 +0100 +Subject: [PATCH 076/211] clk: renesas: r8a77970: Add CPEX clock + +Implement support for the CPEX clock on R-Car V3M. This clock can be +selected as a clock source for CMT1 (Compare Match Timer Type 1). + +Signed-off-by: Geert Uytterhoeven +Acked-by: Stephen Boyd +(cherry picked from commit 396bc9d40d694befa1c2c88f9873afc62a189b5f) +Signed-off-by: Valentine Barshak +--- + drivers/clk/renesas/r8a77970-cpg-mssr.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/clk/renesas/r8a77970-cpg-mssr.c b/drivers/clk/renesas/r8a77970-cpg-mssr.c +index 6885c62..cbac67e 100644 +--- a/drivers/clk/renesas/r8a77970-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a77970-cpg-mssr.c +@@ -99,6 +99,7 @@ static const struct cpg_core_clk r8a77970_core_clks[] __initconst = { + + DEF_FIXED("cl", R8A77970_CLK_CL, CLK_PLL1_DIV2, 48, 1), + DEF_FIXED("cp", R8A77970_CLK_CP, CLK_EXTAL, 2, 1), ++ DEF_FIXED("cpex", R8A77970_CLK_CPEX, CLK_EXTAL, 2, 1), + + DEF_DIV6P1("canfd", R8A77970_CLK_CANFD, CLK_PLL1_DIV4, 0x244), + DEF_DIV6P1("mso", R8A77970_CLK_MSO, CLK_PLL1_DIV4, 0x014), +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0257-media-rcar-csi2-add-R8A77980-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0257-media-rcar-csi2-add-R8A77980-support.patch new file mode 100644 index 00000000..99530c73 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0257-media-rcar-csi2-add-R8A77980-support.patch @@ -0,0 +1,62 @@ +From 23b44555c526c046bd1ce117c6ea19f20ba6e57c Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Mon, 6 Aug 2018 12:56:27 -0400 +Subject: [PATCH 077/211] media: rcar-csi2: add R8A77980 support + +Add the R-Car V3H (AKA R8A77980) SoC support to the R-Car CSI2 driver. + +Signed-off-by: Sergei Shtylyov +Acked-by: Rob Herring +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit 3ba37c2bcb0cb5dc9b278f730e520f61b2597fe3) +Signed-off-by: Valentine Barshak +--- + Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt | 1 + + drivers/media/platform/rcar-vin/rcar-csi2.c | 11 +++++++++++ + 2 files changed, 12 insertions(+) + +diff --git a/Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt b/Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt +index 2824489..541d936 100644 +--- a/Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt ++++ b/Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt +@@ -12,6 +12,7 @@ Mandatory properties + - "renesas,r8a7796-csi2" for the R8A7796 device. + - "renesas,r8a77965-csi2" for the R8A77965 device. + - "renesas,r8a77970-csi2" for the R8A77970 device. ++ - "renesas,r8a77980-csi2" for the R8A77980 device. + - "renesas,r8a77990-csi2" for the R8A77990 device. + + - reg: the register base and size for the device registers +diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c +index 52a6d52..c21cc80 100644 +--- a/drivers/media/platform/rcar-vin/rcar-csi2.c ++++ b/drivers/media/platform/rcar-vin/rcar-csi2.c +@@ -1037,6 +1037,13 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a77970 = { + .init_v3m_e3_phtw = rcsi2_init_phtw_v3m_e3, + }; + ++static const struct rcar_csi2_info rcar_csi2_info_r8a77980 = { ++ .init_phtw = rcsi2_init_phtw_h3_v3h_m3n, ++ .hsfreqrange = hsfreqrange_h3_v3h_m3n, ++ .csi0clkfreqrange = 0x20, ++ .clear_ulps = true, ++}; ++ + static const struct rcar_csi2_info rcar_csi2_info_r8a77990 = { + .init_v3m_e3_phtw = rcsi2_init_phtw_v3m_e3, + }; +@@ -1059,6 +1066,10 @@ static const struct of_device_id rcar_csi2_of_table[] = { + .data = &rcar_csi2_info_r8a77970, + }, + { ++ .compatible = "renesas,r8a77980-csi2", ++ .data = &rcar_csi2_info_r8a77980, ++ }, ++ { + .compatible = "renesas,r8a77990-csi2", + .data = &rcar_csi2_info_r8a77990, + }, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0258-media-rcar-vin-add-R8A77980-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0258-media-rcar-vin-add-R8A77980-support.patch new file mode 100644 index 00000000..0e351ed0 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0258-media-rcar-vin-add-R8A77980-support.patch @@ -0,0 +1,87 @@ +From 2c14590a9c414df1a74e96f4baa2ef8cd2005ae4 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Mon, 6 Aug 2018 14:48:20 -0400 +Subject: [PATCH 078/211] media: rcar-vin: add R8A77980 support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add the R8A77980 SoC support to the R-Car VIN driver. + +Signed-off-by: Sergei Shtylyov +Acked-by: Niklas Söderlund +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit a383096c98b4b44151a9fde106b01500ccc2a060) +[valentine.barshak: resolved minor conflicts in rcar_vin binding docs] +Signed-off-by: Valentine Barshak +--- + .../devicetree/bindings/media/rcar_vin.txt | 1 + + drivers/media/platform/rcar-vin/rcar-core.c | 32 ++++++++++++++++++++++ + 2 files changed, 33 insertions(+) + +diff --git a/Documentation/devicetree/bindings/media/rcar_vin.txt b/Documentation/devicetree/bindings/media/rcar_vin.txt +index 845c786..bcd2e3a 100644 +--- a/Documentation/devicetree/bindings/media/rcar_vin.txt ++++ b/Documentation/devicetree/bindings/media/rcar_vin.txt +@@ -23,6 +23,7 @@ on Gen3 platforms to a CSI-2 receiver. + - "renesas,vin-r8a7796" for the R8A7796 device + - "renesas,vin-r8a77970" for the R8A77970 device + - "renesas,vin-r8a77965" for the R8A77965 device ++ - "renesas,vin-r8a77980" for the R8A77980 device + - "renesas,vin-r8a77990" for the R8A77990 device + - "renesas,vin-r8a77995" for the R8A77995 device + - "renesas,rcar-gen2-vin" for a generic R-Car Gen2 or RZ/G1 compatible +diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c +index d6f99db..adb4ac1 100644 +--- a/drivers/media/platform/rcar-vin/rcar-core.c ++++ b/drivers/media/platform/rcar-vin/rcar-core.c +@@ -1055,6 +1055,34 @@ static const struct rvin_info rcar_info_r8a77965 = { + .routes = _rcar_info_r8a77965_routes, + }; + ++static const struct rvin_group_route rcar_info_r8a77980_routes[] = { ++ { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) }, ++ { .csi = RVIN_CSI40, .channel = 1, .vin = 0, .mask = BIT(2) }, ++ { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) }, ++ { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(1) | BIT(3) }, ++ { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) }, ++ { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) }, ++ { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) }, ++ { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) }, ++ { .csi = RVIN_CSI41, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) }, ++ { .csi = RVIN_CSI41, .channel = 1, .vin = 4, .mask = BIT(2) }, ++ { .csi = RVIN_CSI41, .channel = 0, .vin = 5, .mask = BIT(2) }, ++ { .csi = RVIN_CSI41, .channel = 1, .vin = 5, .mask = BIT(1) | BIT(3) }, ++ { .csi = RVIN_CSI41, .channel = 0, .vin = 6, .mask = BIT(1) }, ++ { .csi = RVIN_CSI41, .channel = 2, .vin = 6, .mask = BIT(3) }, ++ { .csi = RVIN_CSI41, .channel = 1, .vin = 7, .mask = BIT(0) }, ++ { .csi = RVIN_CSI41, .channel = 3, .vin = 7, .mask = BIT(3) }, ++ { /* Sentinel */ } ++}; ++ ++static const struct rvin_info rcar_info_r8a77980 = { ++ .model = RCAR_GEN3, ++ .use_mc = true, ++ .max_width = 4096, ++ .max_height = 4096, ++ .routes = rcar_info_r8a77980_routes, ++}; ++ + static const struct rvin_group_route rcar_info_r8a77990_routes[] = { + { .csi = RVIN_CSI40, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) }, + { .csi = RVIN_CSI40, .channel = 0, .vin = 5, .mask = BIT(2) }, +@@ -1148,6 +1176,10 @@ static const struct of_device_id rvin_of_id_table[] = { + .data = &rcar_info_r8a77970, + }, + { ++ .compatible = "renesas,vin-r8a77980", ++ .data = &rcar_info_r8a77980, ++ }, ++ { + .compatible = "renesas,vin-r8a77990", + .data = &rcar_info_r8a77990, + }, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0259-pinctrl-sh-pfc-r8a77970-Add-missing-MOD_SEL0-field.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0259-pinctrl-sh-pfc-r8a77970-Add-missing-MOD_SEL0-field.patch new file mode 100644 index 00000000..4539d3de --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0259-pinctrl-sh-pfc-r8a77970-Add-missing-MOD_SEL0-field.patch @@ -0,0 +1,34 @@ +From e5217975e934d8f241c30df1cbda960d6378812a Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Wed, 12 Dec 2018 14:29:02 +0100 +Subject: [PATCH 079/211] pinctrl: sh-pfc: r8a77970: Add missing MOD_SEL0 field + +The Module Select Register 0 contains 20 (= 5 x 4) reserved bits, and 12 +single-bit fields, but the variable field descriptor lacks a field of 4 +reserved bits. + +Fixes: b92ac66a1819602b ("pinctrl: sh-pfc: Add R8A77970 PFC support") +Signed-off-by: Geert Uytterhoeven +Reviewed-by: Simon Horman +(cherry picked from commit 67d7745bc78e16ec6b3af02bc1da6c8c868cbd89) +Signed-off-by: Valentine Barshak +--- + drivers/pinctrl/sh-pfc/pfc-r8a77970.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a77970.c b/drivers/pinctrl/sh-pfc/pfc-r8a77970.c +index 9b96e5d..e331e93 100644 +--- a/drivers/pinctrl/sh-pfc/pfc-r8a77970.c ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a77970.c +@@ -2424,7 +2424,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { + #define F_(x, y) x, + #define FM(x) FN_##x, + { PINMUX_CFG_REG_VAR("MOD_SEL0", 0xe6060500, 32, +- 4, 4, 4, 4, ++ 4, 4, 4, 4, 4, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) { + /* RESERVED 31, 30, 29, 28 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0260-pinctrl-sh-pfc-r8a77980-Add-missing-MOD_SEL0-field.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0260-pinctrl-sh-pfc-r8a77980-Add-missing-MOD_SEL0-field.patch new file mode 100644 index 00000000..a9a77550 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0260-pinctrl-sh-pfc-r8a77980-Add-missing-MOD_SEL0-field.patch @@ -0,0 +1,34 @@ +From 64f86bb82bfff30da4106d0d8b1a684da42edced Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Wed, 12 Dec 2018 14:36:54 +0100 +Subject: [PATCH 080/211] pinctrl: sh-pfc: r8a77980: Add missing MOD_SEL0 field + +The Module Select Register 0 contains 20 (= 5 x 4) reserved bits, and 12 +single-bit fields, but the variable field descriptor lacks a field of 4 +reserved bits. + +Fixes: f59125248a691dfe ("pinctrl: sh-pfc: Add R8A77980 PFC support") +Signed-off-by: Geert Uytterhoeven +Reviewed-by: Simon Horman +(cherry picked from commit b0f77269f6bba385f1f4dce44e7756cf8fbc0176) +Signed-off-by: Valentine Barshak +--- + drivers/pinctrl/sh-pfc/pfc-r8a77980.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a77980.c b/drivers/pinctrl/sh-pfc/pfc-r8a77980.c +index aa1d50b..8bef245 100644 +--- a/drivers/pinctrl/sh-pfc/pfc-r8a77980.c ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a77980.c +@@ -2821,7 +2821,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { + #define F_(x, y) x, + #define FM(x) FN_##x, + { PINMUX_CFG_REG_VAR("MOD_SEL0", 0xe6060500, 32, +- 4, 4, 4, 4, ++ 4, 4, 4, 4, 4, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) { + /* RESERVED 31, 30, 29, 28 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0261-media-rcar-csi2-Fix-PHTW-table-values-for-E3-V3M.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0261-media-rcar-csi2-Fix-PHTW-table-values-for-E3-V3M.patch new file mode 100644 index 00000000..943d7037 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0261-media-rcar-csi2-Fix-PHTW-table-values-for-E3-V3M.patch @@ -0,0 +1,99 @@ +From 0bd47cde3778ac16d6b9d90579d3f40e0c0716db Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Mon, 10 Dec 2018 09:53:55 -0500 +Subject: [PATCH 081/211] media: rcar-csi2: Fix PHTW table values for E3/V3M +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The PHTW selection algorithm implemented in rcsi2_phtw_write_mbps() checks for +lower bound of the interval used to match the desired bandwidth. Use that +in place of the currently used upper bound. + +Fixes: 10c08812fe60 ("media: rcar: rcar-csi2: Update V3M/E3 PHTW tables") + +Signed-off-by: Jacopo Mondi +Acked-by: Niklas Söderlund +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit aa8a1012ba624e92fd1ab58463f22501bce78af8) +Signed-off-by: Valentine Barshak +--- + drivers/media/platform/rcar-vin/rcar-csi2.c | 62 ++++++++++++++--------------- + 1 file changed, 31 insertions(+), 31 deletions(-) + +diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c +index c21cc80..5d230b0 100644 +--- a/drivers/media/platform/rcar-vin/rcar-csi2.c ++++ b/drivers/media/platform/rcar-vin/rcar-csi2.c +@@ -156,37 +156,37 @@ static const struct rcsi2_mbps_reg phtw_mbps_h3_v3h_m3n[] = { + }; + + static const struct rcsi2_mbps_reg phtw_mbps_v3m_e3[] = { +- { .mbps = 89, .reg = 0x00 }, +- { .mbps = 99, .reg = 0x20 }, +- { .mbps = 109, .reg = 0x40 }, +- { .mbps = 129, .reg = 0x02 }, +- { .mbps = 139, .reg = 0x22 }, +- { .mbps = 149, .reg = 0x42 }, +- { .mbps = 169, .reg = 0x04 }, +- { .mbps = 179, .reg = 0x24 }, +- { .mbps = 199, .reg = 0x44 }, +- { .mbps = 219, .reg = 0x06 }, +- { .mbps = 239, .reg = 0x26 }, +- { .mbps = 249, .reg = 0x46 }, +- { .mbps = 269, .reg = 0x08 }, +- { .mbps = 299, .reg = 0x28 }, +- { .mbps = 329, .reg = 0x0a }, +- { .mbps = 359, .reg = 0x2a }, +- { .mbps = 399, .reg = 0x4a }, +- { .mbps = 449, .reg = 0x0c }, +- { .mbps = 499, .reg = 0x2c }, +- { .mbps = 549, .reg = 0x0e }, +- { .mbps = 599, .reg = 0x2e }, +- { .mbps = 649, .reg = 0x10 }, +- { .mbps = 699, .reg = 0x30 }, +- { .mbps = 749, .reg = 0x12 }, +- { .mbps = 799, .reg = 0x32 }, +- { .mbps = 849, .reg = 0x52 }, +- { .mbps = 899, .reg = 0x72 }, +- { .mbps = 949, .reg = 0x14 }, +- { .mbps = 999, .reg = 0x34 }, +- { .mbps = 1049, .reg = 0x54 }, +- { .mbps = 1099, .reg = 0x74 }, ++ { .mbps = 80, .reg = 0x00 }, ++ { .mbps = 90, .reg = 0x20 }, ++ { .mbps = 100, .reg = 0x40 }, ++ { .mbps = 110, .reg = 0x02 }, ++ { .mbps = 130, .reg = 0x22 }, ++ { .mbps = 140, .reg = 0x42 }, ++ { .mbps = 150, .reg = 0x04 }, ++ { .mbps = 170, .reg = 0x24 }, ++ { .mbps = 180, .reg = 0x44 }, ++ { .mbps = 200, .reg = 0x06 }, ++ { .mbps = 220, .reg = 0x26 }, ++ { .mbps = 240, .reg = 0x46 }, ++ { .mbps = 250, .reg = 0x08 }, ++ { .mbps = 270, .reg = 0x28 }, ++ { .mbps = 300, .reg = 0x0a }, ++ { .mbps = 330, .reg = 0x2a }, ++ { .mbps = 360, .reg = 0x4a }, ++ { .mbps = 400, .reg = 0x0c }, ++ { .mbps = 450, .reg = 0x2c }, ++ { .mbps = 500, .reg = 0x0e }, ++ { .mbps = 550, .reg = 0x2e }, ++ { .mbps = 600, .reg = 0x10 }, ++ { .mbps = 650, .reg = 0x30 }, ++ { .mbps = 700, .reg = 0x12 }, ++ { .mbps = 750, .reg = 0x32 }, ++ { .mbps = 800, .reg = 0x52 }, ++ { .mbps = 850, .reg = 0x72 }, ++ { .mbps = 900, .reg = 0x14 }, ++ { .mbps = 950, .reg = 0x34 }, ++ { .mbps = 1000, .reg = 0x54 }, ++ { .mbps = 1050, .reg = 0x74 }, + { .mbps = 1125, .reg = 0x16 }, + { /* sentinel */ }, + }; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0262-pinctrl-sh-pfc-Reduce-kernel-size-for-narrow-VIN-cha.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0262-pinctrl-sh-pfc-Reduce-kernel-size-for-narrow-VIN-cha.patch new file mode 100644 index 00000000..d09795b9 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0262-pinctrl-sh-pfc-Reduce-kernel-size-for-narrow-VIN-cha.patch @@ -0,0 +1,165 @@ +From 429290a136aea89f4af18539b86fc3159d4573ab Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Tue, 16 Oct 2018 09:46:12 +0200 +Subject: [PATCH 082/211] pinctrl: sh-pfc: Reduce kernel size for narrow VIN + channels +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Some VIN channels support less than 24 lanes. As union vin_data always +consumes space for 24 lanes, this wastes memory. + +Hence introduce new smaller unions vin_data12 and vin_data16, to +accommodate VIN channels with only 12 or 16 lanes. + +This reduces the static pin controller driver size by 320 bytes for +R-Car V2H, and by 96 bytes for R-Car E2. + +Signed-off-by: Geert Uytterhoeven +Reviewed-by: Simon Horman +Reviewed-by: Niklas Söderlund +(cherry picked from commit 50f3f2d73e3426ba5aac0fe62098870579a0b357) +Signed-off-by: Valentine Barshak +--- + drivers/pinctrl/sh-pfc/pfc-r8a7792.c | 16 ++++++++-------- + drivers/pinctrl/sh-pfc/pfc-r8a7794.c | 4 ++-- + drivers/pinctrl/sh-pfc/sh_pfc.h | 17 +++++++++++++++-- + 3 files changed, 25 insertions(+), 12 deletions(-) + +diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7792.c b/drivers/pinctrl/sh-pfc/pfc-r8a7792.c +index cc3597f..a3acfd6 100644 +--- a/drivers/pinctrl/sh-pfc/pfc-r8a7792.c ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a7792.c +@@ -1477,7 +1477,7 @@ static const unsigned int vin1_clk_mux[] = { + VI1_CLK_MARK, + }; + /* - VIN2 ------------------------------------------------------------------- */ +-static const union vin_data vin2_data_pins = { ++static const union vin_data16 vin2_data_pins = { + .data16 = { + RCAR_GP_PIN(6, 4), RCAR_GP_PIN(6, 5), + RCAR_GP_PIN(6, 6), RCAR_GP_PIN(6, 7), +@@ -1489,7 +1489,7 @@ static const union vin_data vin2_data_pins = { + RCAR_GP_PIN(8, 11), RCAR_GP_PIN(8, 12), + }, + }; +-static const union vin_data vin2_data_mux = { ++static const union vin_data16 vin2_data_mux = { + .data16 = { + VI2_D0_C0_MARK, VI2_D1_C1_MARK, + VI2_D2_C2_MARK, VI2_D3_C3_MARK, +@@ -1527,7 +1527,7 @@ static const unsigned int vin2_clk_mux[] = { + VI2_CLK_MARK, + }; + /* - VIN3 ------------------------------------------------------------------- */ +-static const union vin_data vin3_data_pins = { ++static const union vin_data16 vin3_data_pins = { + .data16 = { + RCAR_GP_PIN(7, 4), RCAR_GP_PIN(7, 5), + RCAR_GP_PIN(7, 6), RCAR_GP_PIN(7, 7), +@@ -1539,7 +1539,7 @@ static const union vin_data vin3_data_pins = { + RCAR_GP_PIN(8, 15), RCAR_GP_PIN(8, 16), + }, + }; +-static const union vin_data vin3_data_mux = { ++static const union vin_data16 vin3_data_mux = { + .data16 = { + VI3_D0_C0_MARK, VI3_D1_C1_MARK, + VI3_D2_C2_MARK, VI3_D3_C3_MARK, +@@ -1577,7 +1577,7 @@ static const unsigned int vin3_clk_mux[] = { + VI3_CLK_MARK, + }; + /* - VIN4 ------------------------------------------------------------------- */ +-static const union vin_data vin4_data_pins = { ++static const union vin_data12 vin4_data_pins = { + .data12 = { + RCAR_GP_PIN(8, 4), RCAR_GP_PIN(8, 5), + RCAR_GP_PIN(8, 6), RCAR_GP_PIN(8, 7), +@@ -1587,7 +1587,7 @@ static const union vin_data vin4_data_pins = { + RCAR_GP_PIN(8, 14), RCAR_GP_PIN(8, 15), + }, + }; +-static const union vin_data vin4_data_mux = { ++static const union vin_data12 vin4_data_mux = { + .data12 = { + VI4_D0_C0_MARK, VI4_D1_C1_MARK, + VI4_D2_C2_MARK, VI4_D3_C3_MARK, +@@ -1623,7 +1623,7 @@ static const unsigned int vin4_clk_mux[] = { + VI4_CLK_MARK, + }; + /* - VIN5 ------------------------------------------------------------------- */ +-static const union vin_data vin5_data_pins = { ++static const union vin_data12 vin5_data_pins = { + .data12 = { + RCAR_GP_PIN(9, 4), RCAR_GP_PIN(9, 5), + RCAR_GP_PIN(9, 6), RCAR_GP_PIN(9, 7), +@@ -1633,7 +1633,7 @@ static const union vin_data vin5_data_pins = { + RCAR_GP_PIN(9, 14), RCAR_GP_PIN(9, 15), + }, + }; +-static const union vin_data vin5_data_mux = { ++static const union vin_data12 vin5_data_mux = { + .data12 = { + VI5_D0_C0_MARK, VI5_D1_C1_MARK, + VI5_D2_C2_MARK, VI5_D3_C3_MARK, +diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7794.c b/drivers/pinctrl/sh-pfc/pfc-r8a7794.c +index 1640024..bbb1a37 100644 +--- a/drivers/pinctrl/sh-pfc/pfc-r8a7794.c ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a7794.c +@@ -3707,7 +3707,7 @@ static const unsigned int vin0_clk_mux[] = { + VI0_CLK_MARK, + }; + /* - VIN1 ------------------------------------------------------------------- */ +-static const union vin_data vin1_data_pins = { ++static const union vin_data12 vin1_data_pins = { + .data12 = { + RCAR_GP_PIN(5, 12), RCAR_GP_PIN(5, 13), + RCAR_GP_PIN(5, 14), RCAR_GP_PIN(5, 15), +@@ -3717,7 +3717,7 @@ static const union vin_data vin1_data_pins = { + RCAR_GP_PIN(1, 12), RCAR_GP_PIN(1, 13), + }, + }; +-static const union vin_data vin1_data_mux = { ++static const union vin_data12 vin1_data_mux = { + .data12 = { + VI1_DATA0_MARK, VI1_DATA1_MARK, + VI1_DATA2_MARK, VI1_DATA3_MARK, +diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h +index 3d0b316..e0c8245 100644 +--- a/drivers/pinctrl/sh-pfc/sh_pfc.h ++++ b/drivers/pinctrl/sh-pfc/sh_pfc.h +@@ -56,8 +56,8 @@ struct sh_pfc_pin_group { + }; + + /* +- * Using union vin_data saves memory occupied by the VIN data pins. +- * VIN_DATA_PIN_GROUP() is a macro used to describe the VIN pin groups ++ * Using union vin_data{,12,16} saves memory occupied by the VIN data pins. ++ * VIN_DATA_PIN_GROUP() is a macro used to describe the VIN pin groups + * in this case. + */ + #define VIN_DATA_PIN_GROUP(n, s) \ +@@ -68,6 +68,19 @@ struct sh_pfc_pin_group { + .nr_pins = ARRAY_SIZE(n##_pins.data##s), \ + } + ++union vin_data12 { ++ unsigned int data12[12]; ++ unsigned int data10[10]; ++ unsigned int data8[8]; ++}; ++ ++union vin_data16 { ++ unsigned int data16[16]; ++ unsigned int data12[12]; ++ unsigned int data10[10]; ++ unsigned int data8[8]; ++}; ++ + union vin_data { + unsigned int data24[24]; + unsigned int data20[20]; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0263-pinctrl-sh-pfc-r8a77970-Deduplicate-VIN-01-pin-defin.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0263-pinctrl-sh-pfc-r8a77970-Deduplicate-VIN-01-pin-defin.patch new file mode 100644 index 00000000..79a5f81f --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0263-pinctrl-sh-pfc-r8a77970-Deduplicate-VIN-01-pin-defin.patch @@ -0,0 +1,186 @@ +From f551856450c9182f125d4b0989224f7d6720e1ff Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Wed, 9 Jan 2019 15:56:12 +0100 +Subject: [PATCH 083/211] pinctrl: sh-pfc: r8a77970: Deduplicate VIN[01] pin + definitions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use union vin_data12 and VIN_DATA_PIN_GROUP() to reduce redundancies in +pin definitions for the VIN0 and VIN1 channels. + +This reduces kernel size by 288 bytes. + +Signed-off-by: Geert Uytterhoeven +Reviewed-by: Jacopo Mondi +Reviewed-by: Simon Horman +Reviewed-by: Niklas Söderlund +(cherry picked from commit 81c585c96b7dd47caede1bf6d2920a81498385dc) +Signed-off-by: Valentine Barshak +--- + drivers/pinctrl/sh-pfc/pfc-r8a77970.c | 128 +++++++++++----------------------- + 1 file changed, 42 insertions(+), 86 deletions(-) + +diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a77970.c b/drivers/pinctrl/sh-pfc/pfc-r8a77970.c +index e331e93..53ad813 100644 +--- a/drivers/pinctrl/sh-pfc/pfc-r8a77970.c ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a77970.c +@@ -1581,47 +1581,25 @@ static const unsigned int tmu_tclk2_b_mux[] = { + }; + + /* - VIN0 ------------------------------------------------------------------- */ +-static const unsigned int vin0_data8_pins[] = { +- RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 5), +- RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 7), +- RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9), +- RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11), +-}; +-static const unsigned int vin0_data8_mux[] = { +- VI0_DATA0_MARK, VI0_DATA1_MARK, +- VI0_DATA2_MARK, VI0_DATA3_MARK, +- VI0_DATA4_MARK, VI0_DATA5_MARK, +- VI0_DATA6_MARK, VI0_DATA7_MARK, ++static const union vin_data12 vin0_data_pins = { ++ .data12 = { ++ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 5), ++ RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 7), ++ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9), ++ RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11), ++ RCAR_GP_PIN(2, 12), RCAR_GP_PIN(2, 13), ++ RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 15), ++ }, + }; +-static const unsigned int vin0_data10_pins[] = { +- RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 5), +- RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 7), +- RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9), +- RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11), +- RCAR_GP_PIN(2, 12), RCAR_GP_PIN(2, 13), +-}; +-static const unsigned int vin0_data10_mux[] = { +- VI0_DATA0_MARK, VI0_DATA1_MARK, +- VI0_DATA2_MARK, VI0_DATA3_MARK, +- VI0_DATA4_MARK, VI0_DATA5_MARK, +- VI0_DATA6_MARK, VI0_DATA7_MARK, +- VI0_DATA8_MARK, VI0_DATA9_MARK, +-}; +-static const unsigned int vin0_data12_pins[] = { +- RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 5), +- RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 7), +- RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9), +- RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11), +- RCAR_GP_PIN(2, 12), RCAR_GP_PIN(2, 13), +- RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 15), +-}; +-static const unsigned int vin0_data12_mux[] = { +- VI0_DATA0_MARK, VI0_DATA1_MARK, +- VI0_DATA2_MARK, VI0_DATA3_MARK, +- VI0_DATA4_MARK, VI0_DATA5_MARK, +- VI0_DATA6_MARK, VI0_DATA7_MARK, +- VI0_DATA8_MARK, VI0_DATA9_MARK, +- VI0_DATA10_MARK, VI0_DATA11_MARK, ++static const union vin_data12 vin0_data_mux = { ++ .data12 = { ++ VI0_DATA0_MARK, VI0_DATA1_MARK, ++ VI0_DATA2_MARK, VI0_DATA3_MARK, ++ VI0_DATA4_MARK, VI0_DATA5_MARK, ++ VI0_DATA6_MARK, VI0_DATA7_MARK, ++ VI0_DATA8_MARK, VI0_DATA9_MARK, ++ VI0_DATA10_MARK, VI0_DATA11_MARK, ++ }, + }; + static const unsigned int vin0_sync_pins[] = { + /* HSYNC#, VSYNC# */ +@@ -1653,47 +1631,25 @@ static const unsigned int vin0_clk_mux[] = { + }; + + /* - VIN1 ------------------------------------------------------------------- */ +-static const unsigned int vin1_data8_pins[] = { +- RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5), +- RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), +- RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), +- RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11), +-}; +-static const unsigned int vin1_data8_mux[] = { +- VI1_DATA0_MARK, VI1_DATA1_MARK, +- VI1_DATA2_MARK, VI1_DATA3_MARK, +- VI1_DATA4_MARK, VI1_DATA5_MARK, +- VI1_DATA6_MARK, VI1_DATA7_MARK, +-}; +-static const unsigned int vin1_data10_pins[] = { +- RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5), +- RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), +- RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), +- RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11), +- RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 13), +-}; +-static const unsigned int vin1_data10_mux[] = { +- VI1_DATA0_MARK, VI1_DATA1_MARK, +- VI1_DATA2_MARK, VI1_DATA3_MARK, +- VI1_DATA4_MARK, VI1_DATA5_MARK, +- VI1_DATA6_MARK, VI1_DATA7_MARK, +- VI1_DATA8_MARK, VI1_DATA9_MARK, +-}; +-static const unsigned int vin1_data12_pins[] = { +- RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5), +- RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), +- RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), +- RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11), +- RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 13), +- RCAR_GP_PIN(3, 14), RCAR_GP_PIN(3, 15), ++static const union vin_data12 vin1_data_pins = { ++ .data12 = { ++ RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5), ++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), ++ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), ++ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11), ++ RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 13), ++ RCAR_GP_PIN(3, 14), RCAR_GP_PIN(3, 15), ++ }, + }; +-static const unsigned int vin1_data12_mux[] = { +- VI1_DATA0_MARK, VI1_DATA1_MARK, +- VI1_DATA2_MARK, VI1_DATA3_MARK, +- VI1_DATA4_MARK, VI1_DATA5_MARK, +- VI1_DATA6_MARK, VI1_DATA7_MARK, +- VI1_DATA8_MARK, VI1_DATA9_MARK, +- VI1_DATA10_MARK, VI1_DATA11_MARK, ++static const union vin_data12 vin1_data_mux = { ++ .data12 = { ++ VI1_DATA0_MARK, VI1_DATA1_MARK, ++ VI1_DATA2_MARK, VI1_DATA3_MARK, ++ VI1_DATA4_MARK, VI1_DATA5_MARK, ++ VI1_DATA6_MARK, VI1_DATA7_MARK, ++ VI1_DATA8_MARK, VI1_DATA9_MARK, ++ VI1_DATA10_MARK, VI1_DATA11_MARK, ++ }, + }; + static const unsigned int vin1_sync_pins[] = { + /* HSYNC#, VSYNC# */ +@@ -1834,16 +1790,16 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { + SH_PFC_PIN_GROUP(tmu_tclk1_b), + SH_PFC_PIN_GROUP(tmu_tclk2_a), + SH_PFC_PIN_GROUP(tmu_tclk2_b), +- SH_PFC_PIN_GROUP(vin0_data8), +- SH_PFC_PIN_GROUP(vin0_data10), +- SH_PFC_PIN_GROUP(vin0_data12), ++ VIN_DATA_PIN_GROUP(vin0_data, 8), ++ VIN_DATA_PIN_GROUP(vin0_data, 10), ++ VIN_DATA_PIN_GROUP(vin0_data, 12), + SH_PFC_PIN_GROUP(vin0_sync), + SH_PFC_PIN_GROUP(vin0_field), + SH_PFC_PIN_GROUP(vin0_clkenb), + SH_PFC_PIN_GROUP(vin0_clk), +- SH_PFC_PIN_GROUP(vin1_data8), +- SH_PFC_PIN_GROUP(vin1_data10), +- SH_PFC_PIN_GROUP(vin1_data12), ++ VIN_DATA_PIN_GROUP(vin1_data, 8), ++ VIN_DATA_PIN_GROUP(vin1_data, 10), ++ VIN_DATA_PIN_GROUP(vin1_data, 12), + SH_PFC_PIN_GROUP(vin1_sync), + SH_PFC_PIN_GROUP(vin1_field), + SH_PFC_PIN_GROUP(vin1_clkenb), +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0264-pinctrl-sh-pfc-r8a77980-Deduplicate-VIN1-pin-definit.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0264-pinctrl-sh-pfc-r8a77980-Deduplicate-VIN1-pin-definit.patch new file mode 100644 index 00000000..ace0561e --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0264-pinctrl-sh-pfc-r8a77980-Deduplicate-VIN1-pin-definit.patch @@ -0,0 +1,110 @@ +From 4a51481da796493b420fed4026b6643102997d05 Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Wed, 9 Jan 2019 15:57:57 +0100 +Subject: [PATCH 084/211] pinctrl: sh-pfc: r8a77980: Deduplicate VIN1 pin + definitions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use union vin_data12 and VIN_DATA_PIN_GROUP() to reduce redundancies in +pin definitions for the VIN1 channel. + +This reduces kernel size by 144 bytes. + +Signed-off-by: Geert Uytterhoeven +Reviewed-by: Jacopo Mondi +Reviewed-by: Simon Horman +Reviewed-by: Niklas Söderlund +(cherry picked from commit 9dd1731306d90f08d726987d3d7e39ba6e23a015) +Signed-off-by: Valentine Barshak +--- + drivers/pinctrl/sh-pfc/pfc-r8a77980.c | 64 ++++++++++++----------------------- + 1 file changed, 21 insertions(+), 43 deletions(-) + +diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a77980.c b/drivers/pinctrl/sh-pfc/pfc-r8a77980.c +index 8bef245..b807b67a 100644 +--- a/drivers/pinctrl/sh-pfc/pfc-r8a77980.c ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a77980.c +@@ -1970,47 +1970,25 @@ static const unsigned int vin0_clk_mux[] = { + }; + + /* - VIN1 ------------------------------------------------------------------- */ +-static const unsigned int vin1_data8_pins[] = { +- RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5), +- RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), +- RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), +- RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11), +-}; +-static const unsigned int vin1_data8_mux[] = { +- VI1_DATA0_MARK, VI1_DATA1_MARK, +- VI1_DATA2_MARK, VI1_DATA3_MARK, +- VI1_DATA4_MARK, VI1_DATA5_MARK, +- VI1_DATA6_MARK, VI1_DATA7_MARK, +-}; +-static const unsigned int vin1_data10_pins[] = { +- RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5), +- RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), +- RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), +- RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11), +- RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 13), +-}; +-static const unsigned int vin1_data10_mux[] = { +- VI1_DATA0_MARK, VI1_DATA1_MARK, +- VI1_DATA2_MARK, VI1_DATA3_MARK, +- VI1_DATA4_MARK, VI1_DATA5_MARK, +- VI1_DATA6_MARK, VI1_DATA7_MARK, +- VI1_DATA8_MARK, VI1_DATA9_MARK, +-}; +-static const unsigned int vin1_data12_pins[] = { +- RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5), +- RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), +- RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), +- RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11), +- RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 13), +- RCAR_GP_PIN(3, 14), RCAR_GP_PIN(3, 15), ++static const union vin_data12 vin1_data_pins = { ++ .data12 = { ++ RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5), ++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), ++ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), ++ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11), ++ RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 13), ++ RCAR_GP_PIN(3, 14), RCAR_GP_PIN(3, 15), ++ }, + }; +-static const unsigned int vin1_data12_mux[] = { +- VI1_DATA0_MARK, VI1_DATA1_MARK, +- VI1_DATA2_MARK, VI1_DATA3_MARK, +- VI1_DATA4_MARK, VI1_DATA5_MARK, +- VI1_DATA6_MARK, VI1_DATA7_MARK, +- VI1_DATA8_MARK, VI1_DATA9_MARK, +- VI1_DATA10_MARK, VI1_DATA11_MARK, ++static const union vin_data12 vin1_data_mux = { ++ .data12 = { ++ VI1_DATA0_MARK, VI1_DATA1_MARK, ++ VI1_DATA2_MARK, VI1_DATA3_MARK, ++ VI1_DATA4_MARK, VI1_DATA5_MARK, ++ VI1_DATA6_MARK, VI1_DATA7_MARK, ++ VI1_DATA8_MARK, VI1_DATA9_MARK, ++ VI1_DATA10_MARK, VI1_DATA11_MARK, ++ }, + }; + static const unsigned int vin1_sync_pins[] = { + /* VI1_VSYNC#, VI1_HSYNC# */ +@@ -2182,9 +2160,9 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { + SH_PFC_PIN_GROUP(vin0_field), + SH_PFC_PIN_GROUP(vin0_clkenb), + SH_PFC_PIN_GROUP(vin0_clk), +- SH_PFC_PIN_GROUP(vin1_data8), +- SH_PFC_PIN_GROUP(vin1_data10), +- SH_PFC_PIN_GROUP(vin1_data12), ++ VIN_DATA_PIN_GROUP(vin1_data, 8), ++ VIN_DATA_PIN_GROUP(vin1_data, 10), ++ VIN_DATA_PIN_GROUP(vin1_data, 12), + SH_PFC_PIN_GROUP(vin1_sync), + SH_PFC_PIN_GROUP(vin1_field), + SH_PFC_PIN_GROUP(vin1_clkenb), +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0265-arm64-dts-renesas-v3msk-specify-EtherAVB-PHY-IRQ.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0265-arm64-dts-renesas-v3msk-specify-EtherAVB-PHY-IRQ.patch new file mode 100644 index 00000000..cd1de217 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0265-arm64-dts-renesas-v3msk-specify-EtherAVB-PHY-IRQ.patch @@ -0,0 +1,33 @@ +From ed37112995e8f12bb85a9b5b936336d81507511c Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Tue, 8 Jan 2019 22:56:50 +0300 +Subject: [PATCH 085/211] arm64: dts: renesas: v3msk: specify EtherAVB PHY IRQ + +Specify EtherAVB PHY IRQ in the V3M Starter Kit board's device tree, now +that we have the GPIO support (previously phylib had to resort to polling). + +Signed-off-by: Sergei Shtylyov +Reviewed-by: Geert Uytterhoeven +Signed-off-by: Simon Horman +(cherry picked from commit d5e5790c6ff0b6825f6d8b4baf67fa13810ce4fc) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +index 0dbcb4c..15cc9fe 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +@@ -108,6 +108,8 @@ + phy0: ethernet-phy@0 { + rxc-skew-ps = <1500>; + reg = <0>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <17 IRQ_TYPE_LEVEL_LOW>; + }; + }; + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0266-sh_eth-rename-sh_eth_cpu_data-hw_checksum.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0266-sh_eth-rename-sh_eth_cpu_data-hw_checksum.patch new file mode 100644 index 00000000..8f3283da --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0266-sh_eth-rename-sh_eth_cpu_data-hw_checksum.patch @@ -0,0 +1,104 @@ +From 3f271260224b6f9a242f4c9541f8d676e4cbbac8 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Mon, 4 Feb 2019 21:05:55 +0300 +Subject: [PATCH 086/211] sh_eth: rename sh_eth_cpu_data::hw_checksum + +Commit 62e04b7e0e3c ("sh_eth: rename 'sh_eth_cpu_data::hw_crc'") renamed +the field to 'hw_checksum' for the Ether DMAC "intelligent checksum", +however some Ether MACs implement a simpler checksumming scheme, so that +name now seems misleading. Rename that field to 'csmr' as the "intelligent +checksum" is always controlled by the CSMR register. + +Signed-off-by: Sergei Shtylyov +Reviewed-by: Geert Uytterhoeven +Signed-off-by: David S. Miller +(cherry picked from commit 2c2ab5af7d1470d7ba56525cc0c3eebe5ee2bad0) +Signed-off-by: Valentine Barshak +--- + drivers/net/ethernet/renesas/sh_eth.c | 14 +++++++------- + drivers/net/ethernet/renesas/sh_eth.h | 2 +- + 2 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c +index f11b12f..61b9fcb 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.c ++++ b/drivers/net/ethernet/renesas/sh_eth.c +@@ -561,7 +561,7 @@ static int sh_eth_soft_reset_gether(struct net_device *ndev) + sh_eth_write(ndev, 0, RDFFR); + + /* Reset HW CRC register */ +- if (mdp->cd->hw_checksum) ++ if (mdp->cd->csmr) + sh_eth_write(ndev, 0, CSMR); + + /* Select MII mode */ +@@ -625,7 +625,7 @@ static struct sh_eth_cpu_data r7s72100_data = { + .no_trimd = 1, + .no_ade = 1, + .xdfar_rw = 1, +- .hw_checksum = 1, ++ .csmr = 1, + .tsu = 1, + .no_tx_cntrs = 1, + }; +@@ -674,7 +674,7 @@ static struct sh_eth_cpu_data r8a7740_data = { + .no_trimd = 1, + .no_ade = 1, + .xdfar_rw = 1, +- .hw_checksum = 1, ++ .csmr = 1, + .tsu = 1, + .select_mii = 1, + .magic = 1, +@@ -799,7 +799,7 @@ static struct sh_eth_cpu_data r8a77980_data = { + .no_trimd = 1, + .no_ade = 1, + .xdfar_rw = 1, +- .hw_checksum = 1, ++ .csmr = 1, + .select_mii = 1, + .magic = 1, + .cexcr = 1, +@@ -1016,7 +1016,7 @@ static struct sh_eth_cpu_data sh7734_data = { + .no_ade = 1, + .xdfar_rw = 1, + .tsu = 1, +- .hw_checksum = 1, ++ .csmr = 1, + .select_mii = 1, + .magic = 1, + .cexcr = 1, +@@ -1604,7 +1604,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota) + * the RFS bits are from bit 25 to bit 16. So, the + * driver needs right shifting by 16. + */ +- if (mdp->cd->hw_checksum) ++ if (mdp->cd->csmr) + desc_status >>= 16; + + skb = mdp->rx_skbuff[entry]; +@@ -2144,7 +2144,7 @@ static size_t __sh_eth_get_regs(struct net_device *ndev, u32 *buf) + add_reg(MAFCR); + if (cd->rtrate) + add_reg(RTRATE); +- if (cd->hw_checksum) ++ if (cd->csmr) + add_reg(CSMR); + if (cd->select_mii) + add_reg(RMII_MII); +diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h +index 140ad2c..1e73433 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.h ++++ b/drivers/net/ethernet/renesas/sh_eth.h +@@ -510,7 +510,7 @@ struct sh_eth_cpu_data { + unsigned no_ade:1; /* E-DMAC DOES NOT have ADE bit in EESR */ + unsigned no_xdfar:1; /* E-DMAC DOES NOT have RDFAR/TDFAR */ + unsigned xdfar_rw:1; /* E-DMAC has writeable RDFAR/TDFAR */ +- unsigned hw_checksum:1; /* E-DMAC has CSMR */ ++ unsigned csmr:1; /* E-DMAC has CSMR */ + unsigned select_mii:1; /* EtherC has RMII_MII (MII select register) */ + unsigned rmiimode:1; /* EtherC has RMIIMODE register */ + unsigned rtrate:1; /* EtherC has RTRATE register */ +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0267-sh_eth-RX-checksum-offload-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0267-sh_eth-RX-checksum-offload-support.patch new file mode 100644 index 00000000..8abd0acb --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0267-sh_eth-RX-checksum-offload-support.patch @@ -0,0 +1,232 @@ +From d2a497014563885f67787a993118ab0e2597a4a8 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Mon, 4 Feb 2019 21:06:52 +0300 +Subject: [PATCH 087/211] sh_eth: RX checksum offload support + +Add support for the RX checksum offload. This is enabled by default and +may be disabled and re-enabled using 'ethtool': + +# ethtool -K eth0 rx off +# ethtool -K eth0 rx on + +Some Ether MACs provide a simple checksumming scheme which appears to be +completely compatible with CHECKSUM_COMPLETE: sum of all packet data after +the L2 header is appended to packet data; this may be trivially read by +the driver and used to update the skb accordingly. The same checksumming +scheme is implemented in the EtherAVB MACs and now supported by the 'ravb' +driver. + +In terms of performance, throughput is close to gigabit line rate with the +RX checksum offload both enabled and disabled. The 'perf' output, however, +appears to indicate that significantly less time is spent in do_csum() -- +this is as expected. + +Test results with RX checksum offload enabled: + +~/netperf-2.2pl4# perf record -a ./netperf -t TCP_MAERTS -H 192.168.2.4 +TCP MAERTS TEST to 192.168.2.4 +Recv Send Send +Socket Socket Message Elapsed +Size Size Size Time Throughput +bytes bytes bytes secs. 10^6bits/sec + +131072 16384 16384 10.01 933.93 +[ perf record: Woken up 8 times to write data ] +[ perf record: Captured and wrote 1.955 MB perf.data (41940 samples) ] +~/netperf-2.2pl4# perf report +Samples: 41K of event 'cycles:ppp', Event count (approx.): 9915302763 +Overhead Command Shared Object Symbol + 9.44% netperf [kernel.kallsyms] [k] __arch_copy_to_user + 7.75% swapper [kernel.kallsyms] [k] _raw_spin_unlock_irq + 6.31% swapper [kernel.kallsyms] [k] default_idle_call + 5.89% swapper [kernel.kallsyms] [k] arch_cpu_idle + 4.37% swapper [kernel.kallsyms] [k] tick_nohz_idle_exit + 4.02% netperf [kernel.kallsyms] [k] _raw_spin_unlock_irq + 2.52% netperf [kernel.kallsyms] [k] preempt_count_sub + 1.81% netperf [kernel.kallsyms] [k] tcp_recvmsg + 1.80% netperf [kernel.kallsyms] [k] _raw_spin_unlock_irqres + 1.78% netperf [kernel.kallsyms] [k] preempt_count_add + 1.36% netperf [kernel.kallsyms] [k] __tcp_transmit_skb + 1.20% netperf [kernel.kallsyms] [k] __local_bh_enable_ip + 1.10% netperf [kernel.kallsyms] [k] sh_eth_start_xmit + +Test results with RX checksum offload disabled: + +~/netperf-2.2pl4# perf record -a ./netperf -t TCP_MAERTS -H 192.168.2.4 +TCP MAERTS TEST to 192.168.2.4 +Recv Send Send +Socket Socket Message Elapsed +Size Size Size Time Throughput +bytes bytes bytes secs. 10^6bits/sec +131072 16384 16384 10.01 932.04 +[ perf record: Woken up 14 times to write data ] +[ perf record: Captured and wrote 3.642 MB perf.data (78817 samples) ] +~/netperf-2.2pl4# perf report +Samples: 78K of event 'cycles:ppp', Event count (approx.): 18091442796 +Overhead Command Shared Object Symbol + 7.00% swapper [kernel.kallsyms] [k] do_csum + 3.94% swapper [kernel.kallsyms] [k] sh_eth_poll + 3.83% ksoftirqd/0 [kernel.kallsyms] [k] do_csum + 3.23% swapper [kernel.kallsyms] [k] _raw_spin_unlock_irq + 2.87% netperf [kernel.kallsyms] [k] __arch_copy_to_user + 2.86% swapper [kernel.kallsyms] [k] arch_cpu_idle + 2.13% swapper [kernel.kallsyms] [k] default_idle_call + 2.12% ksoftirqd/0 [kernel.kallsyms] [k] sh_eth_poll + 2.02% swapper [kernel.kallsyms] [k] _raw_spin_unlock_irqrestore + 1.84% swapper [kernel.kallsyms] [k] __softirqentry_text_start + 1.64% swapper [kernel.kallsyms] [k] tick_nohz_idle_exit + 1.53% netperf [kernel.kallsyms] [k] _raw_spin_unlock_irq + 1.32% netperf [kernel.kallsyms] [k] preempt_count_sub + 1.27% swapper [kernel.kallsyms] [k] __pi___inval_dcache_area + 1.22% swapper [kernel.kallsyms] [k] check_preemption_disabled + 1.01% ksoftirqd/0 [kernel.kallsyms] [k] _raw_spin_unlock_irqrestore + +The above results collected on the R-Car V3H Starter Kit board. + +Based on the commit 4d86d3818627 ("ravb: RX checksum offload")... + +Signed-off-by: Sergei Shtylyov +Signed-off-by: David S. Miller +(cherry picked from commit f8e022db50564705e9e957a729a955f396a71093) +Signed-off-by: Valentine Barshak +--- + drivers/net/ethernet/renesas/sh_eth.c | 60 +++++++++++++++++++++++++++++++++-- + drivers/net/ethernet/renesas/sh_eth.h | 1 + + 2 files changed, 59 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c +index 61b9fcb..959e0cb 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.c ++++ b/drivers/net/ethernet/renesas/sh_eth.c +@@ -1503,8 +1503,9 @@ static int sh_eth_dev_init(struct net_device *ndev) + mdp->irq_enabled = true; + sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR); + +- /* PAUSE Prohibition */ ++ /* EMAC Mode: PAUSE prohibition; Duplex; RX Checksum; TX; RX */ + sh_eth_write(ndev, ECMR_ZPF | (mdp->duplex ? ECMR_DM : 0) | ++ (ndev->features & NETIF_F_RXCSUM ? ECMR_RCSC : 0) | + ECMR_TE | ECMR_RE, ECMR); + + if (mdp->cd->set_rate) +@@ -1563,6 +1564,19 @@ static void sh_eth_dev_exit(struct net_device *ndev) + update_mac_address(ndev); + } + ++static void sh_eth_rx_csum(struct sk_buff *skb) ++{ ++ u8 *hw_csum; ++ ++ /* The hardware checksum is 2 bytes appended to packet data */ ++ if (unlikely(skb->len < sizeof(__sum16))) ++ return; ++ hw_csum = skb_tail_pointer(skb) - sizeof(__sum16); ++ skb->csum = csum_unfold((__force __sum16)get_unaligned_le16(hw_csum)); ++ skb->ip_summed = CHECKSUM_COMPLETE; ++ skb_trim(skb, skb->len - sizeof(__sum16)); ++} ++ + /* Packet receive function */ + static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota) + { +@@ -1637,6 +1651,8 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota) + DMA_FROM_DEVICE); + skb_put(skb, pkt_len); + skb->protocol = eth_type_trans(skb, ndev); ++ if (ndev->features & NETIF_F_RXCSUM) ++ sh_eth_rx_csum(skb); + netif_receive_skb(skb); + ndev->stats.rx_packets++; + ndev->stats.rx_bytes += pkt_len; +@@ -2890,6 +2906,39 @@ static void sh_eth_set_rx_mode(struct net_device *ndev) + spin_unlock_irqrestore(&mdp->lock, flags); + } + ++static void sh_eth_set_rx_csum(struct net_device *ndev, bool enable) ++{ ++ struct sh_eth_private *mdp = netdev_priv(ndev); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&mdp->lock, flags); ++ ++ /* Disable TX and RX */ ++ sh_eth_rcv_snd_disable(ndev); ++ ++ /* Modify RX Checksum setting */ ++ sh_eth_modify(ndev, ECMR, ECMR_RCSC, enable ? ECMR_RCSC : 0); ++ ++ /* Enable TX and RX */ ++ sh_eth_rcv_snd_enable(ndev); ++ ++ spin_unlock_irqrestore(&mdp->lock, flags); ++} ++ ++static int sh_eth_set_features(struct net_device *ndev, ++ netdev_features_t features) ++{ ++ netdev_features_t changed = ndev->features ^ features; ++ struct sh_eth_private *mdp = netdev_priv(ndev); ++ ++ if (changed & NETIF_F_RXCSUM && mdp->cd->rx_csum) ++ sh_eth_set_rx_csum(ndev, features & NETIF_F_RXCSUM); ++ ++ ndev->features = features; ++ ++ return 0; ++} ++ + static int sh_eth_get_vtag_index(struct sh_eth_private *mdp) + { + if (!mdp->port) +@@ -3076,6 +3125,7 @@ static const struct net_device_ops sh_eth_netdev_ops = { + .ndo_change_mtu = sh_eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, ++ .ndo_set_features = sh_eth_set_features, + }; + + static const struct net_device_ops sh_eth_netdev_ops_tsu = { +@@ -3091,6 +3141,7 @@ static const struct net_device_ops sh_eth_netdev_ops_tsu = { + .ndo_change_mtu = sh_eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, ++ .ndo_set_features = sh_eth_set_features, + }; + + #ifdef CONFIG_OF +@@ -3218,6 +3269,11 @@ static int sh_eth_drv_probe(struct platform_device *pdev) + ndev->max_mtu = 2000 - (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN); + ndev->min_mtu = ETH_MIN_MTU; + ++ if (mdp->cd->rx_csum) { ++ ndev->features = NETIF_F_RXCSUM; ++ ndev->hw_features = NETIF_F_RXCSUM; ++ } ++ + /* set function */ + if (mdp->cd->tsu) + ndev->netdev_ops = &sh_eth_netdev_ops_tsu; +@@ -3267,7 +3323,7 @@ static int sh_eth_drv_probe(struct platform_device *pdev) + goto out_release; + } + mdp->port = port; +- ndev->features = NETIF_F_HW_VLAN_CTAG_FILTER; ++ ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; + + /* Need to init only the first port of the two sharing a TSU */ + if (port == 0) { +diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h +index 1e73433..7a172c4 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.h ++++ b/drivers/net/ethernet/renesas/sh_eth.h +@@ -511,6 +511,7 @@ struct sh_eth_cpu_data { + unsigned no_xdfar:1; /* E-DMAC DOES NOT have RDFAR/TDFAR */ + unsigned xdfar_rw:1; /* E-DMAC has writeable RDFAR/TDFAR */ + unsigned csmr:1; /* E-DMAC has CSMR */ ++ unsigned rx_csum:1; /* EtherC has ECMR.RCSC */ + unsigned select_mii:1; /* EtherC has RMII_MII (MII select register) */ + unsigned rmiimode:1; /* EtherC has RMIIMODE register */ + unsigned rtrate:1; /* EtherC has RTRATE register */ +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0268-sh_eth-offload-RX-checksum-on-R7S72100.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0268-sh_eth-offload-RX-checksum-on-R7S72100.patch new file mode 100644 index 00000000..a40a7c56 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0268-sh_eth-offload-RX-checksum-on-R7S72100.patch @@ -0,0 +1,31 @@ +From 026258a2809e44f4e689e75b809d49f8d3865fc0 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Mon, 4 Feb 2019 21:07:53 +0300 +Subject: [PATCH 088/211] sh_eth: offload RX checksum on R7S72100 + +The RZ/A1H (R7S721000) SoC manual describes the Ether MAC's RX checksum +offload the same way as it's implemented in the EtherAVB MACs... + +Signed-off-by: Sergei Shtylyov +Signed-off-by: David S. Miller +(cherry picked from commit 48132cd0c6317701421df3232a77c0a642292859) +Signed-off-by: Valentine Barshak +--- + drivers/net/ethernet/renesas/sh_eth.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c +index 959e0cb..e1ec382 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.c ++++ b/drivers/net/ethernet/renesas/sh_eth.c +@@ -626,6 +626,7 @@ static struct sh_eth_cpu_data r7s72100_data = { + .no_ade = 1, + .xdfar_rw = 1, + .csmr = 1, ++ .rx_csum = 1, + .tsu = 1, + .no_tx_cntrs = 1, + }; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0269-sh_eth-offload-RX-checksum-on-R8A7740.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0269-sh_eth-offload-RX-checksum-on-R8A7740.patch new file mode 100644 index 00000000..a9dc1411 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0269-sh_eth-offload-RX-checksum-on-R8A7740.patch @@ -0,0 +1,32 @@ +From c3f40e9d9ab4794ad3bf74fa50a82a7bd08c7a80 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Mon, 4 Feb 2019 21:08:54 +0300 +Subject: [PATCH 089/211] sh_eth: offload RX checksum on R8A7740 + +The R-Mobile A1 (R8A7740) SoC manual describes the Ether MAC's RX checksum +offload the same way as it's implemented in the EtherAVB MAC... + +Signed-off-by: Sergei Shtylyov +Tested-by: Geert Uytterhoeven +Signed-off-by: David S. Miller +(cherry picked from commit 040c16fd5974a947bcfb2fe2e66fe4f42eeef08a) +Signed-off-by: Valentine Barshak +--- + drivers/net/ethernet/renesas/sh_eth.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c +index e1ec382..63bf7ee 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.c ++++ b/drivers/net/ethernet/renesas/sh_eth.c +@@ -676,6 +676,7 @@ static struct sh_eth_cpu_data r8a7740_data = { + .no_ade = 1, + .xdfar_rw = 1, + .csmr = 1, ++ .rx_csum = 1, + .tsu = 1, + .select_mii = 1, + .magic = 1, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0270-sh_eth-offload-RX-checksum-on-R8A77980.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0270-sh_eth-offload-RX-checksum-on-R8A77980.patch new file mode 100644 index 00000000..c379959c --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0270-sh_eth-offload-RX-checksum-on-R8A77980.patch @@ -0,0 +1,31 @@ +From 87b96e342f43398a7fdde613c1dc420dfd05faec Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Mon, 4 Feb 2019 21:10:32 +0300 +Subject: [PATCH 090/211] sh_eth: offload RX checksum on R8A77980 + +The R-Car V3H (R8A77980) SoC manual describes the Ether MAC's RX checksum +offload the same way as it's implemented in the EtherAVB MAC... + +Signed-off-by: Sergei Shtylyov +Signed-off-by: David S. Miller +(cherry picked from commit 0da843adeefb4953a1a73a24d5a8dfbbffcd9a47) +Signed-off-by: Valentine Barshak +--- + drivers/net/ethernet/renesas/sh_eth.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c +index 63bf7ee..a08b800 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.c ++++ b/drivers/net/ethernet/renesas/sh_eth.c +@@ -802,6 +802,7 @@ static struct sh_eth_cpu_data r8a77980_data = { + .no_ade = 1, + .xdfar_rw = 1, + .csmr = 1, ++ .rx_csum = 1, + .select_mii = 1, + .magic = 1, + .cexcr = 1, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0271-sh_eth-offload-RX-checksum-on-SH7734.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0271-sh_eth-offload-RX-checksum-on-SH7734.patch new file mode 100644 index 00000000..de67c015 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0271-sh_eth-offload-RX-checksum-on-SH7734.patch @@ -0,0 +1,31 @@ +From 403ffdf4d56c06d4e83553da19d1081799681e77 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Mon, 4 Feb 2019 21:11:32 +0300 +Subject: [PATCH 091/211] sh_eth: offload RX checksum on SH7734 + +The SH7734 SoC manual describes the Ether MAC's RX checksum offload +the same way as it's implemented in the EtherAVB MACs... + +Signed-off-by: Sergei Shtylyov +Signed-off-by: David S. Miller +(cherry picked from commit 06240e1b526d426acfe7b21e673da49e12f5a225) +Signed-off-by: Valentine Barshak +--- + drivers/net/ethernet/renesas/sh_eth.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c +index a08b800..95fd30b 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.c ++++ b/drivers/net/ethernet/renesas/sh_eth.c +@@ -1020,6 +1020,7 @@ static struct sh_eth_cpu_data sh7734_data = { + .xdfar_rw = 1, + .tsu = 1, + .csmr = 1, ++ .rx_csum = 1, + .select_mii = 1, + .magic = 1, + .cexcr = 1, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0272-sh_eth-offload-RX-checksum-on-SH7763.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0272-sh_eth-offload-RX-checksum-on-SH7763.patch new file mode 100644 index 00000000..40851dc3 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0272-sh_eth-offload-RX-checksum-on-SH7763.patch @@ -0,0 +1,31 @@ +From df34c845a5a29bdca6efdf4245e95329995dfb9a Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Mon, 4 Feb 2019 21:12:39 +0300 +Subject: [PATCH 092/211] sh_eth: offload RX checksum on SH7763 + +The SH7763 SoC manual describes the Ether MAC's RX checksum offload +the same way as it's implemented in the EtherAVB MACs... + +Signed-off-by: Sergei Shtylyov +Signed-off-by: David S. Miller +(cherry picked from commit 997feb11b83bd1c3b0100587a773629cabb83ce2) +Signed-off-by: Valentine Barshak +--- + drivers/net/ethernet/renesas/sh_eth.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c +index 95fd30b..f969aa4 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.c ++++ b/drivers/net/ethernet/renesas/sh_eth.c +@@ -1063,6 +1063,7 @@ static struct sh_eth_cpu_data sh7763_data = { + .irq_flags = IRQF_SHARED, + .magic = 1, + .cexcr = 1, ++ .rx_csum = 1, + .dual_port = 1, + }; + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0273-clk-renesas-rcar-gen3-Factor-out-cpg_reg_modify.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0273-clk-renesas-rcar-gen3-Factor-out-cpg_reg_modify.patch new file mode 100644 index 00000000..3ee6b267 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0273-clk-renesas-rcar-gen3-Factor-out-cpg_reg_modify.patch @@ -0,0 +1,119 @@ +From 934ce0eb9a13d26c8c46b8af9ceea5912357dd79 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Tue, 22 Jan 2019 22:57:38 +0300 +Subject: [PATCH 093/211] clk: renesas: rcar-gen3: Factor out cpg_reg_modify() + +There's quite often repeated sequence of a CPG register read-modify-write, +so it seems worth factoring it out into a function -- this saves 68 bytes +of the object code (AArch64 gcc 4.8.5) and simplifies protecting all such +sequences with a spinlock in the next patch... + +Signed-off-by: Sergei Shtylyov +Signed-off-by: Geert Uytterhoeven +(cherry picked from commit 8cb8f16c62e5ea9c77ca7d25af761f4eaea670ba) +[valentine.barshak: resolved a minor conflict with cpg_quirks] +Signed-off-by: Valentine Barshak +--- + drivers/clk/renesas/rcar-gen3-cpg.c | 38 +++++++++++++++++++------------------ + 1 file changed, 20 insertions(+), 18 deletions(-) + +diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c +index d45437d..d99b666 100644 +--- a/drivers/clk/renesas/rcar-gen3-cpg.c ++++ b/drivers/clk/renesas/rcar-gen3-cpg.c +@@ -46,6 +46,16 @@ static u32 cpg_quirks; + #define Z2FC_BIT_MASK_SFT_8 BIT(2) /* Use Z2FC bit mask range to [12:8] */ + #define ZG_PARENT_PLL0 BIT(3) /* Use PLL0 as ZG clock parent */ + ++static void cpg_reg_modify(void __iomem *reg, u32 clear, u32 set) ++{ ++ u32 val; ++ ++ val = readl(reg); ++ val &= ~clear; ++ val |= set; ++ writel(val, reg); ++}; ++ + struct cpg_simple_notifier { + struct notifier_block nb; + void __iomem *reg; +@@ -269,7 +279,6 @@ static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long prate = parent_rate / zclk->fixed_div; + unsigned int mult; + unsigned int i; +- u32 val, kick; + + if (!zclk->max_freq) + mult = DIV_ROUND_CLOSEST_ULL(rate * 32ULL, prate); +@@ -283,17 +292,14 @@ static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate, + if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK) + return -EBUSY; + +- val = readl(zclk->reg) & ~zclk->mask; +- val |= ((32 - mult) << __ffs(zclk->mask)) & zclk->mask; +- writel(val, zclk->reg); ++ cpg_reg_modify(zclk->reg, zclk->mask, ++ ((32 - mult) << __ffs(zclk->mask)) & zclk->mask); + + /* + * Set KICK bit in FRQCRB to update hardware setting and wait for + * clock change completion. + */ +- kick = readl(zclk->kick_reg); +- kick |= CPG_FRQCRB_KICK; +- writel(kick, zclk->kick_reg); ++ cpg_reg_modify(zclk->kick_reg, 0, CPG_FRQCRB_KICK); + + /* + * Note: There is no HW information about the worst case latency. +@@ -568,12 +574,10 @@ static const struct sd_div_table cpg_sd_div_table[] = { + static int cpg_sd_clock_enable(struct clk_hw *hw) + { + struct sd_clock *clock = to_sd_clock(hw); +- u32 val = readl(clock->csn.reg); + +- val &= ~(CPG_SD_STP_MASK); +- val |= clock->div_table[clock->cur_div_idx].val & CPG_SD_STP_MASK; +- +- writel(val, clock->csn.reg); ++ cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK, ++ clock->div_table[clock->cur_div_idx].val & ++ CPG_SD_STP_MASK); + + return 0; + } +@@ -582,7 +586,7 @@ static void cpg_sd_clock_disable(struct clk_hw *hw) + { + struct sd_clock *clock = to_sd_clock(hw); + +- writel(readl(clock->csn.reg) | CPG_SD_STP_MASK, clock->csn.reg); ++ cpg_reg_modify(clock->csn.reg, 0, CPG_SD_STP_MASK); + } + + static int cpg_sd_clock_is_enabled(struct clk_hw *hw) +@@ -635,7 +639,6 @@ static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate, + { + struct sd_clock *clock = to_sd_clock(hw); + unsigned int div = cpg_sd_clock_calc_div(clock, rate, parent_rate); +- u32 val; + unsigned int i; + + for (i = 0; i < clock->div_num; i++) +@@ -647,10 +650,9 @@ static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate, + + clock->cur_div_idx = i; + +- val = readl(clock->csn.reg); +- val &= ~(CPG_SD_STP_MASK | CPG_SD_FC_MASK); +- val |= clock->div_table[i].val & (CPG_SD_STP_MASK | CPG_SD_FC_MASK); +- writel(val, clock->csn.reg); ++ cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK | CPG_SD_FC_MASK, ++ clock->div_table[i].val & ++ (CPG_SD_STP_MASK | CPG_SD_FC_MASK)); + + return 0; + } +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0274-clk-renesas-rcar-gen3-Add-spinlock.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0274-clk-renesas-rcar-gen3-Add-spinlock.patch new file mode 100644 index 00000000..b6b889c5 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0274-clk-renesas-rcar-gen3-Add-spinlock.patch @@ -0,0 +1,52 @@ +From da07480ffaecd44e65f4361dc375f428f8889e22 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Tue, 22 Jan 2019 22:58:38 +0300 +Subject: [PATCH 094/211] clk: renesas: rcar-gen3: Add spinlock + +Protect the CPG register read-modify-write sequence with a spinlock. + +Signed-off-by: Sergei Shtylyov +Signed-off-by: Geert Uytterhoeven +(cherry picked from commit 875e8f6b0156c0ad56fd0c29c78e3f2f67ec0b16) +[valentine.barshak: resolved a minor conflict with cpg_quirks] +Signed-off-by: Valentine Barshak +--- + drivers/clk/renesas/rcar-gen3-cpg.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c +index d99b666..8e41380 100644 +--- a/drivers/clk/renesas/rcar-gen3-cpg.c ++++ b/drivers/clk/renesas/rcar-gen3-cpg.c +@@ -46,14 +46,19 @@ static u32 cpg_quirks; + #define Z2FC_BIT_MASK_SFT_8 BIT(2) /* Use Z2FC bit mask range to [12:8] */ + #define ZG_PARENT_PLL0 BIT(3) /* Use PLL0 as ZG clock parent */ + ++static spinlock_t cpg_lock; ++ + static void cpg_reg_modify(void __iomem *reg, u32 clear, u32 set) + { ++ unsigned long flags; + u32 val; + ++ spin_lock_irqsave(&cpg_lock, flags); + val = readl(reg); + val &= ~clear; + val |= set; + writel(val, reg); ++ spin_unlock_irqrestore(&cpg_lock, flags); + }; + + struct cpg_simple_notifier { +@@ -911,5 +916,8 @@ int __init rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config, + if (attr) + cpg_quirks = (uintptr_t)attr->data; + pr_debug("%s: mode = 0x%x quirks = 0x%x\n", __func__, mode, cpg_quirks); ++ ++ spin_lock_init(&cpg_lock); ++ + return 0; + } +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0275-clk-renesas-rcar-gen3-Add-RPC-clocks.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0275-clk-renesas-rcar-gen3-Add-RPC-clocks.patch new file mode 100644 index 00000000..813e0c27 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0275-clk-renesas-rcar-gen3-Add-RPC-clocks.patch @@ -0,0 +1,169 @@ +From c4d21aa145e4a995725af98d273eb33f63013082 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Tue, 22 Jan 2019 22:59:35 +0300 +Subject: [PATCH 095/211] clk: renesas: rcar-gen3: Add RPC clocks + +The RPCSRC internal clock is controlled by the RPCCKCR.DIV[4:3] on all +the R-Car gen3 SoCs except V3M (R8A77970) but the encoding of this field +is different between SoCs; it makes sense to support the most common case +of this encoding in the R-Car gen3 CPG driver... + +After adding the RPCSRC clock, we can add the RPC[D2] clocks derived from +it and controlled by the RPCCKCR register on all the R-Car gen3 SoCs except +V3M (R8A77970); the composite clock driver seems handy for this task, using +the spinlock added in the previous patch... + +Signed-off-by: Sergei Shtylyov +Signed-off-by: Geert Uytterhoeven +(cherry picked from commit db4a0073cc82a95d8d1a9b05fde82355fcce77d8) +[valentine.barshak: resolved minor conflicts] +Signed-off-by: Valentine Barshak +--- + drivers/clk/renesas/rcar-gen3-cpg.c | 101 ++++++++++++++++++++++++++++++++++++ + drivers/clk/renesas/rcar-gen3-cpg.h | 4 ++ + 2 files changed, 105 insertions(+) + +diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c +index 8e41380..c73b269 100644 +--- a/drivers/clk/renesas/rcar-gen3-cpg.c ++++ b/drivers/clk/renesas/rcar-gen3-cpg.c +@@ -720,6 +720,92 @@ static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core, + return clk; + } + ++struct rpc_clock { ++ struct clk_divider div; ++ struct clk_gate gate; ++ /* ++ * One notifier covers both RPC and RPCD2 clocks as they are both ++ * controlled by the same RPCCKCR register... ++ */ ++ struct cpg_simple_notifier csn; ++}; ++ ++static const struct clk_div_table cpg_rpcsrc_div_table[] = { ++ { 2, 5 }, { 3, 6 }, { 0, 0 }, ++}; ++ ++static const struct clk_div_table cpg_rpc_div_table[] = { ++ { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 }, { 0, 0 }, ++}; ++ ++static struct clk * __init cpg_rpc_clk_register(const char *name, ++ void __iomem *base, const char *parent_name, ++ struct raw_notifier_head *notifiers) ++{ ++ struct rpc_clock *rpc; ++ struct clk *clk; ++ ++ rpc = kzalloc(sizeof(*rpc), GFP_KERNEL); ++ if (!rpc) ++ return ERR_PTR(-ENOMEM); ++ ++ rpc->div.reg = base + CPG_RPCCKCR; ++ rpc->div.width = 3; ++ rpc->div.table = cpg_rpc_div_table; ++ rpc->div.lock = &cpg_lock; ++ ++ rpc->gate.reg = base + CPG_RPCCKCR; ++ rpc->gate.bit_idx = 8; ++ rpc->gate.flags = CLK_GATE_SET_TO_DISABLE; ++ rpc->gate.lock = &cpg_lock; ++ ++ rpc->csn.reg = base + CPG_RPCCKCR; ++ ++ clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL, ++ &rpc->div.hw, &clk_divider_ops, ++ &rpc->gate.hw, &clk_gate_ops, 0); ++ if (IS_ERR(clk)) { ++ kfree(rpc); ++ return clk; ++ } ++ ++ cpg_simple_notifier_register(notifiers, &rpc->csn); ++ return clk; ++} ++ ++struct rpcd2_clock { ++ struct clk_fixed_factor fixed; ++ struct clk_gate gate; ++}; ++ ++static struct clk * __init cpg_rpcd2_clk_register(const char *name, ++ void __iomem *base, ++ const char *parent_name) ++{ ++ struct rpcd2_clock *rpcd2; ++ struct clk *clk; ++ ++ rpcd2 = kzalloc(sizeof(*rpcd2), GFP_KERNEL); ++ if (!rpcd2) ++ return ERR_PTR(-ENOMEM); ++ ++ rpcd2->fixed.mult = 1; ++ rpcd2->fixed.div = 2; ++ ++ rpcd2->gate.reg = base + CPG_RPCCKCR; ++ rpcd2->gate.bit_idx = 9; ++ rpcd2->gate.flags = CLK_GATE_SET_TO_DISABLE; ++ rpcd2->gate.lock = &cpg_lock; ++ ++ clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL, ++ &rpcd2->fixed.hw, &clk_fixed_factor_ops, ++ &rpcd2->gate.hw, &clk_gate_ops, 0); ++ if (IS_ERR(clk)) ++ kfree(rpcd2); ++ ++ return clk; ++} ++ + static const struct rcar_gen3_cpg_pll_config *cpg_pll_config __initdata; + static unsigned int cpg_clk_extalr __initdata; + static u32 cpg_mode __initdata; +@@ -896,6 +982,21 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, + return cpg_zg_clk_register(core->name, __clk_get_name(parent), + base, core->div); + ++ case CLK_TYPE_GEN3_RPCSRC: ++ return clk_register_divider_table(NULL, core->name, ++ __clk_get_name(parent), 0, ++ base + CPG_RPCCKCR, 3, 2, 0, ++ cpg_rpcsrc_div_table, ++ &cpg_lock); ++ ++ case CLK_TYPE_GEN3_RPC: ++ return cpg_rpc_clk_register(core->name, base, ++ __clk_get_name(parent), notifiers); ++ ++ case CLK_TYPE_GEN3_RPCD2: ++ return cpg_rpcd2_clk_register(core->name, base, ++ __clk_get_name(parent)); ++ + default: + return ERR_PTR(-EINVAL); + } +diff --git a/drivers/clk/renesas/rcar-gen3-cpg.h b/drivers/clk/renesas/rcar-gen3-cpg.h +index 8834afe..a39c11a 100644 +--- a/drivers/clk/renesas/rcar-gen3-cpg.h ++++ b/drivers/clk/renesas/rcar-gen3-cpg.h +@@ -27,6 +27,9 @@ enum rcar_gen3_clk_types { + CLK_TYPE_GEN3_ZG, + CLK_TYPE_GEN3_OSC, /* OSC EXTAL predivider and fixed divider */ + CLK_TYPE_GEN3_RCKSEL, /* Select parent/divider using RCKCR.CKSEL */ ++ CLK_TYPE_GEN3_RPCSRC, ++ CLK_TYPE_GEN3_RPC, ++ CLK_TYPE_GEN3_RPCD2, + + /* SoC specific definitions start here */ + CLK_TYPE_GEN3_SOC_BASE, +@@ -64,6 +67,7 @@ struct rcar_gen3_cpg_pll_config { + u8 osc_prediv; + }; + ++#define CPG_RPCCKCR 0x238 + #define CPG_RCKCR 0x240 + + struct clk *rcar_gen3_cpg_clk_register(struct device *dev, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0276-clk-renesas-r8a77980-Add-RPC-clocks.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0276-clk-renesas-r8a77980-Add-RPC-clocks.patch new file mode 100644 index 00000000..a589bc56 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0276-clk-renesas-r8a77980-Add-RPC-clocks.patch @@ -0,0 +1,55 @@ +From a00e5d2291fba5c3df1164f33b9e75333a9697e0 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Tue, 22 Jan 2019 23:01:07 +0300 +Subject: [PATCH 096/211] clk: renesas: r8a77980: Add RPC clocks + +Describe the RPCSRC internal clock and the RPC[D2] clocks derived from it, +as well as the RPC-IF module clock, in the R-Car V3H (R8A77980) CPG/MSSR +driver. + +Signed-off-by: Sergei Shtylyov +Signed-off-by: Geert Uytterhoeven +(cherry picked from commit 94e3935b5756a790396b57c7a5116460db511b29) +Signed-off-by: Valentine Barshak +--- + drivers/clk/renesas/r8a77980-cpg-mssr.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/clk/renesas/r8a77980-cpg-mssr.c b/drivers/clk/renesas/r8a77980-cpg-mssr.c +index 25a3083..f9e07fc 100644 +--- a/drivers/clk/renesas/r8a77980-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a77980-cpg-mssr.c +@@ -41,6 +41,7 @@ enum clk_ids { + CLK_S2, + CLK_S3, + CLK_SDSRC, ++ CLK_RPCSRC, + CLK_OCO, + + /* Module Clocks */ +@@ -65,8 +66,14 @@ static const struct cpg_core_clk r8a77980_core_clks[] __initconst = { + DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1), + DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1), + DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1), ++ DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1), + DEF_RATE(".oco", CLK_OCO, 32768), + ++ DEF_BASE("rpc", R8A77980_CLK_RPC, CLK_TYPE_GEN3_RPC, ++ CLK_RPCSRC), ++ DEF_BASE("rpcd2", R8A77980_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, ++ R8A77980_CLK_RPC), ++ + /* Core Clock Outputs */ + DEF_FIXED("ztr", R8A77980_CLK_ZTR, CLK_PLL1_DIV2, 6, 1), + DEF_FIXED("ztrd2", R8A77980_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1), +@@ -164,6 +171,7 @@ static const struct mssr_mod_clk r8a77980_mod_clks[] __initconst = { + DEF_MOD("gpio1", 911, R8A77980_CLK_CP), + DEF_MOD("gpio0", 912, R8A77980_CLK_CP), + DEF_MOD("can-fd", 914, R8A77980_CLK_S3D2), ++ DEF_MOD("rpc-if", 917, R8A77980_CLK_RPC), + DEF_MOD("i2c4", 927, R8A77980_CLK_S0D6), + DEF_MOD("i2c3", 928, R8A77980_CLK_S0D6), + DEF_MOD("i2c2", 929, R8A77980_CLK_S3D2), +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0277-pinctrl-sh-pfc-r8a77970-Rename-IOCTRLx-registers.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0277-pinctrl-sh-pfc-r8a77970-Rename-IOCTRLx-registers.patch new file mode 100644 index 00000000..dcb23351 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0277-pinctrl-sh-pfc-r8a77970-Rename-IOCTRLx-registers.patch @@ -0,0 +1,65 @@ +From 7e60a2c1600ba242739092dba055235ca5be1872 Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Mon, 18 Feb 2019 10:35:39 +0100 +Subject: [PATCH 097/211] pinctrl: sh-pfc: r8a77970: Rename IOCTRLx registers + +The R-Car Gen3 HardWare Manual Errata for Rev. 1.00 (Jul 2, 2018) +renamed the various miscellaneous I/O control registers (IOCTRLx) on +R-Car V3M, to reflect better their actual purposes, and matching other +SoCs. + +Update the code to match this. + +Signed-off-by: Geert Uytterhoeven +Reviewed-by: Ulrich Hecht +(cherry picked from commit 1c5c1101755c5ed9f1e74763dbf39c01c3dc7cf8) +Signed-off-by: Valentine Barshak +--- + drivers/pinctrl/sh-pfc/pfc-r8a77970.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a77970.c b/drivers/pinctrl/sh-pfc/pfc-r8a77970.c +index 53ad813..a609949 100644 +--- a/drivers/pinctrl/sh-pfc/pfc-r8a77970.c ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a77970.c +@@ -2409,15 +2409,15 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { + }; + + enum ioctrl_regs { +- IOCTRL30, +- IOCTRL31, +- IOCTRL32, ++ POCCTRL0, ++ POCCTRL1, ++ POCCTRL2, + }; + + static const struct pinmux_ioctrl_reg pinmux_ioctrl_regs[] = { +- [IOCTRL30] = { 0xe6060380 }, +- [IOCTRL31] = { 0xe6060384 }, +- [IOCTRL32] = { 0xe6060388 }, ++ [POCCTRL0] = { 0xe6060380 }, ++ [POCCTRL1] = { 0xe6060384 }, ++ [POCCTRL2] = { 0xe6060388 }, + { /* sentinel */ }, + }; + +@@ -2426,13 +2426,13 @@ static int r8a77970_pin_to_pocctrl(struct sh_pfc *pfc, unsigned int pin, + { + int bit = pin & 0x1f; + +- *pocctrl = pinmux_ioctrl_regs[IOCTRL30].reg; ++ *pocctrl = pinmux_ioctrl_regs[POCCTRL0].reg; + if (pin >= RCAR_GP_PIN(0, 0) && pin <= RCAR_GP_PIN(0, 21)) + return bit; + if (pin >= RCAR_GP_PIN(2, 0) && pin <= RCAR_GP_PIN(2, 9)) + return bit + 22; + +- *pocctrl = pinmux_ioctrl_regs[IOCTRL31].reg; ++ *pocctrl = pinmux_ioctrl_regs[POCCTRL1].reg; + if (pin >= RCAR_GP_PIN(2, 10) && pin <= RCAR_GP_PIN(2, 16)) + return bit - 10; + if (pin >= RCAR_GP_PIN(3, 0) && pin <= RCAR_GP_PIN(3, 16)) +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0278-pinctrl-sh-pfc-r8a77980-Rename-IOCTRLx-registers.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0278-pinctrl-sh-pfc-r8a77980-Rename-IOCTRLx-registers.patch new file mode 100644 index 00000000..c7ac6882 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0278-pinctrl-sh-pfc-r8a77980-Rename-IOCTRLx-registers.patch @@ -0,0 +1,77 @@ +From 8f0ff040259e8d24830c87cd8d2e5f262de9cb92 Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Mon, 18 Feb 2019 10:42:21 +0100 +Subject: [PATCH 098/211] pinctrl: sh-pfc: r8a77980: Rename IOCTRLx registers + +The R-Car Gen3 HardWare Manual Errata for Rev. 1.00 (Jul 2, 2018) +renamed the various miscellaneous I/O control registers (IOCTRLx) on +R-Car V3H, to reflect better their actual purposes, and matching other +SoCs. + +Update the code to match this. + +Signed-off-by: Geert Uytterhoeven +Reviewed-by: Ulrich Hecht +(cherry picked from commit a8d728a0c59cd508b3cdcef8950409089156bf70) +Signed-off-by: Valentine Barshak +--- + drivers/pinctrl/sh-pfc/pfc-r8a77980.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a77980.c b/drivers/pinctrl/sh-pfc/pfc-r8a77980.c +index b807b67a..1dcc508 100644 +--- a/drivers/pinctrl/sh-pfc/pfc-r8a77980.c ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a77980.c +@@ -2828,17 +2828,17 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { + }; + + enum ioctrl_regs { +- IOCTRL30, +- IOCTRL31, +- IOCTRL32, +- IOCTRL33, ++ POCCTRL0, ++ POCCTRL1, ++ POCCTRL2, ++ POCCTRL3, + }; + + static const struct pinmux_ioctrl_reg pinmux_ioctrl_regs[] = { +- [IOCTRL30] = { 0xe6060380, }, +- [IOCTRL31] = { 0xe6060384, }, +- [IOCTRL32] = { 0xe6060388, }, +- [IOCTRL33] = { 0xe606038c, }, ++ [POCCTRL0] = { 0xe6060380, }, ++ [POCCTRL1] = { 0xe6060384, }, ++ [POCCTRL2] = { 0xe6060388, }, ++ [POCCTRL3] = { 0xe606038c, }, + { /* sentinel */ }, + }; + +@@ -2847,20 +2847,20 @@ static int r8a77980_pin_to_pocctrl(struct sh_pfc *pfc, unsigned int pin, + { + int bit = pin & 0x1f; + +- *pocctrl = pinmux_ioctrl_regs[IOCTRL30].reg; ++ *pocctrl = pinmux_ioctrl_regs[POCCTRL0].reg; + if (pin >= RCAR_GP_PIN(0, 0) && pin <= RCAR_GP_PIN(0, 21)) + return bit; + else if (pin >= RCAR_GP_PIN(2, 0) && pin <= RCAR_GP_PIN(2, 9)) + return bit + 22; + +- *pocctrl = pinmux_ioctrl_regs[IOCTRL31].reg; ++ *pocctrl = pinmux_ioctrl_regs[POCCTRL1].reg; + if (pin >= RCAR_GP_PIN(2, 10) && pin <= RCAR_GP_PIN(2, 16)) + return bit - 10; + if ((pin >= RCAR_GP_PIN(2, 17) && pin <= RCAR_GP_PIN(2, 24)) || + (pin >= RCAR_GP_PIN(3, 0) && pin <= RCAR_GP_PIN(3, 16))) + return bit + 7; + +- *pocctrl = pinmux_ioctrl_regs[IOCTRL32].reg; ++ *pocctrl = pinmux_ioctrl_regs[POCCTRL2].reg; + if (pin >= RCAR_GP_PIN(2, 25) && pin <= RCAR_GP_PIN(2, 29)) + return pin - 25; + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0279-clk-renesas-r8a77980-Fix-RPC-IF-module-clock-s-paren.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0279-clk-renesas-r8a77980-Fix-RPC-IF-module-clock-s-paren.patch new file mode 100644 index 00000000..06387d96 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0279-clk-renesas-r8a77980-Fix-RPC-IF-module-clock-s-paren.patch @@ -0,0 +1,34 @@ +From 9ae10e7766a229a577973da7c2c04234a9772810 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Thu, 7 Mar 2019 22:53:19 +0300 +Subject: [PATCH 099/211] clk: renesas: r8a77980: Fix RPC-IF module clock's + parent + +Testing has shown that the RPC-IF module clock's parent is the RPCD2 +clock, not the RPC one -- the RPC-IF register reads stall otherwise... + +Fixes: 94e3935b5756 ("clk: renesas: r8a77980: Add RPC clocks") +Signed-off-by: Sergei Shtylyov +Signed-off-by: Geert Uytterhoeven +(cherry picked from commit 21ab095cbc069a351fa9cef919f2dafc43a8fde7) +Signed-off-by: Valentine Barshak +--- + drivers/clk/renesas/r8a77980-cpg-mssr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/renesas/r8a77980-cpg-mssr.c b/drivers/clk/renesas/r8a77980-cpg-mssr.c +index f9e07fc..7227f67 100644 +--- a/drivers/clk/renesas/r8a77980-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a77980-cpg-mssr.c +@@ -171,7 +171,7 @@ static const struct mssr_mod_clk r8a77980_mod_clks[] __initconst = { + DEF_MOD("gpio1", 911, R8A77980_CLK_CP), + DEF_MOD("gpio0", 912, R8A77980_CLK_CP), + DEF_MOD("can-fd", 914, R8A77980_CLK_S3D2), +- DEF_MOD("rpc-if", 917, R8A77980_CLK_RPC), ++ DEF_MOD("rpc-if", 917, R8A77980_CLK_RPCD2), + DEF_MOD("i2c4", 927, R8A77980_CLK_S0D6), + DEF_MOD("i2c3", 928, R8A77980_CLK_S0D6), + DEF_MOD("i2c2", 929, R8A77980_CLK_S3D2), +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0280-arm64-dts-renesas-r8a77980-Add-renesas-id-to-VIN.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0280-arm64-dts-renesas-r8a77980-Add-renesas-id-to-VIN.patch new file mode 100644 index 00000000..8b4ebecd --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0280-arm64-dts-renesas-r8a77980-Add-renesas-id-to-VIN.patch @@ -0,0 +1,157 @@ +From 5046390d1114d716fece7508cc199516df4ee610 Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Fri, 12 Apr 2019 13:38:32 +0200 +Subject: [PATCH 100/211] arm64: dts: renesas: r8a77980: Add "renesas,id" to + VIN +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add the "renesas,id" property to VIN nodes in the R-Car V3H R8A77980 +device tree. + +Fixes: 3182aa4e0bf4 ("arm64: dts: renesas: r8a77980: add CSI2/VIN support") +Signed-off-by: Jacopo Mondi +Reviewed-by: Niklas Söderlund +Signed-off-by: Simon Horman +(cherry picked from commit b7f5a8e435ecc7198407f44a2a5a6cdae1056b0d) +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index 4e019f7..1b56b1f 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -865,6 +865,7 @@ + clocks = <&cpg CPG_MOD 811>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 811>; ++ renesas,id = <0>; + status = "disabled"; + + ports { +@@ -892,6 +893,7 @@ + clocks = <&cpg CPG_MOD 810>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + status = "disabled"; ++ renesas,id = <1>; + resets = <&cpg 810>; + + ports { +@@ -919,6 +921,7 @@ + clocks = <&cpg CPG_MOD 809>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 809>; ++ renesas,id = <2>; + status = "disabled"; + + ports { +@@ -946,6 +949,7 @@ + clocks = <&cpg CPG_MOD 808>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 808>; ++ renesas,id = <3>; + status = "disabled"; + + ports { +@@ -973,6 +977,7 @@ + clocks = <&cpg CPG_MOD 807>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 807>; ++ renesas,id = <4>; + status = "disabled"; + + ports { +@@ -1000,6 +1005,7 @@ + clocks = <&cpg CPG_MOD 806>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 806>; ++ renesas,id = <5>; + status = "disabled"; + + ports { +@@ -1027,6 +1033,7 @@ + clocks = <&cpg CPG_MOD 805>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 805>; ++ renesas,id = <6>; + status = "disabled"; + + ports { +@@ -1054,6 +1061,7 @@ + clocks = <&cpg CPG_MOD 804>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 804>; ++ renesas,id = <7>; + status = "disabled"; + + ports { +@@ -1081,6 +1089,7 @@ + clocks = <&cpg CPG_MOD 628>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 628>; ++ renesas,id = <8>; + status = "disabled"; + }; + +@@ -1091,6 +1100,7 @@ + clocks = <&cpg CPG_MOD 627>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 627>; ++ renesas,id = <9>; + status = "disabled"; + }; + +@@ -1101,6 +1111,7 @@ + clocks = <&cpg CPG_MOD 625>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 625>; ++ renesas,id = <10>; + status = "disabled"; + }; + +@@ -1111,6 +1122,7 @@ + clocks = <&cpg CPG_MOD 618>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 618>; ++ renesas,id = <11>; + status = "disabled"; + }; + +@@ -1121,6 +1133,7 @@ + clocks = <&cpg CPG_MOD 612>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 612>; ++ renesas,id = <12>; + status = "disabled"; + }; + +@@ -1131,6 +1144,7 @@ + clocks = <&cpg CPG_MOD 608>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 608>; ++ renesas,id = <13>; + status = "disabled"; + }; + +@@ -1141,6 +1155,7 @@ + clocks = <&cpg CPG_MOD 605>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 605>; ++ renesas,id = <14>; + status = "disabled"; + }; + +@@ -1151,6 +1166,7 @@ + clocks = <&cpg CPG_MOD 604>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 604>; ++ renesas,id = <15>; + status = "disabled"; + }; + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0281-arm64-dts-renesas-eagle-Add-x1-clock.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0281-arm64-dts-renesas-eagle-Add-x1-clock.patch new file mode 100644 index 00000000..6a87090a --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0281-arm64-dts-renesas-eagle-Add-x1-clock.patch @@ -0,0 +1,43 @@ +From d4f29ab5f63ca7e588e9f064e2d551b20c810c60 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Mon, 10 Jun 2019 16:08:07 +0300 +Subject: [PATCH 101/211] arm64: dts: renesas: eagle: Add x1 clock + +This adds X1 clock which supplies a frequency of 148.5 MHz. +This clock is connected to the external dot clock input signal. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970-eagle.dts | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +index b6d5332..800643b 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +@@ -73,6 +73,12 @@ + }; + }; + }; ++ ++ x1_clk: x1-clock { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <148500000>; ++ }; + }; + + &avb { +@@ -192,6 +198,9 @@ + }; + + &du { ++ clocks = <&cpg CPG_MOD 724>, ++ <&x1_clk>; ++ clock-names = "du.0", "dclkin.0"; + status = "okay"; + }; + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0282-arm64-dts-renesas-r8a77980-condor-Add-GEther-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0282-arm64-dts-renesas-r8a77980-condor-Add-GEther-support.patch new file mode 100644 index 00000000..679b9d0b --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0282-arm64-dts-renesas-r8a77980-condor-Add-GEther-support.patch @@ -0,0 +1,80 @@ +From f42db72c483cddaefd0196a0070882d40eeb52a7 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Wed, 17 Oct 2018 22:26:12 +0300 +Subject: [PATCH 102/211] arm64: dts: renesas: r8a77980: condor: Add GEther + support + +This is based on commit eab53fdfd60a84b0cc514d4f1f5d79226c76df01 +from Sergei Shtylyov, which adds GEther support to the R8A77980 +Condor board. The difference is that instead of removing AVB +Ethernet we just disable it. The official Condor boards have +GEther support by default, so we use ethernet0 alias to GEther. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980-condor.dts | 28 +++++++++++++++++++++++-- + 1 file changed, 26 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +index fe2e2c0..738edf0 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +@@ -15,7 +15,8 @@ + + aliases { + serial0 = &scif0; +- ethernet0 = &avb; ++ ethernet0 = &gether; ++ ethernet1 = &avb; + }; + + chosen { +@@ -104,7 +105,7 @@ + phy-mode = "rgmii-id"; + phy-handle = <&phy0>; + renesas,no-ether-link; +- status = "okay"; ++ status = "disabled"; + + phy0: ethernet-phy@0 { + rxc-skew-ps = <1500>; +@@ -139,6 +140,23 @@ + clock-frequency = <32768>; + }; + ++&gether { ++ pinctrl-0 = <&gether_pins>; ++ pinctrl-names = "default"; ++ ++ phy-mode = "rgmii-id"; ++ phy-handle = <&phy1>; ++ renesas,no-ether-link; ++ status = "okay"; ++ ++ phy1: ethernet-phy@1 { ++ rxc-skew-ps = <1500>; ++ reg = <0>; ++ interrupt-parent = <&gpio4>; ++ interrupts = <23 IRQ_TYPE_LEVEL_LOW>; ++ }; ++}; ++ + &i2c0 { + pinctrl-0 = <&i2c0_pins>; + pinctrl-names = "default"; +@@ -246,6 +264,12 @@ + function = "canfd0"; + }; + ++ gether_pins: gether { ++ groups = "gether_mdio_a", "gether_rgmii", ++ "gether_txcrefclk", "gether_txcrefclk_mega"; ++ function = "gether"; ++ }; ++ + i2c0_pins: i2c0 { + groups = "i2c0"; + function = "i2c0"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0283-iommu-ipmmu-vmsa-Add-r8a77980-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0283-iommu-ipmmu-vmsa-Add-r8a77980-support.patch new file mode 100644 index 00000000..06c19a60 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0283-iommu-ipmmu-vmsa-Add-r8a77980-support.patch @@ -0,0 +1,45 @@ +From 64a70b1e21ac951c879fbc7d2200f692a0e58afa Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Fri, 26 Oct 2018 23:49:18 +0300 +Subject: [PATCH 103/211] iommu: ipmmu-vmsa: Add r8a77980 support + +This adds R-Car V3H support to IPMMU VMSA driver. + +Signed-off-by: Valentine Barshak +--- + drivers/iommu/ipmmu-vmsa.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c +index 5844dc7..4a3055f 100644 +--- a/drivers/iommu/ipmmu-vmsa.c ++++ b/drivers/iommu/ipmmu-vmsa.c +@@ -1123,6 +1123,7 @@ static const struct soc_device_attribute soc_rcar_gen3[] = { + { .soc_id = "r8a7796", }, + { .soc_id = "r8a77965", }, + { .soc_id = "r8a77970", }, ++ { .soc_id = "r8a77980", }, + { .soc_id = "r8a77990", }, + { .soc_id = "r8a77995", }, + { /* sentinel */ } +@@ -1426,6 +1427,9 @@ static const struct of_device_id ipmmu_of_ids[] = { + .compatible = "renesas,ipmmu-r8a77970", + .data = &ipmmu_features_rcar_gen3, + }, { ++ .compatible = "renesas,ipmmu-r8a77980", ++ .data = &ipmmu_features_rcar_gen3, ++ }, { + .compatible = "renesas,ipmmu-r8a77990", + .data = &ipmmu_features_rcar_gen3, + }, { +@@ -1866,6 +1870,7 @@ IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795"); + IOMMU_OF_DECLARE(ipmmu_r8a7796_iommu_of, "renesas,ipmmu-r8a7796"); + IOMMU_OF_DECLARE(ipmmu_r8a77965_iommu_of, "renesas,ipmmu-r8a77965"); + IOMMU_OF_DECLARE(ipmmu_r8a77970_iommu_of, "renesas,ipmmu-r8a77970"); ++IOMMU_OF_DECLARE(ipmmu_r8a77980_iommu_of, "renesas,ipmmu-r8a77980"); + IOMMU_OF_DECLARE(ipmmu_r8a77990_iommu_of, "renesas,ipmmu-r8a77990"); + IOMMU_OF_DECLARE(ipmmu_r8a77995_iommu_of, "renesas,ipmmu-r8a77995"); + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0284-iommu-ipmmu-vmsa-Fix-NULL-pointer-dereference.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0284-iommu-ipmmu-vmsa-Fix-NULL-pointer-dereference.patch new file mode 100644 index 00000000..fadd0d73 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0284-iommu-ipmmu-vmsa-Fix-NULL-pointer-dereference.patch @@ -0,0 +1,29 @@ +From 500bf0198a7cdfc9dc2b854715728ce74944cfec Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Tue, 25 Jun 2019 22:43:44 +0300 +Subject: [PATCH 104/211] iommu: ipmmu-vmsa: Fix NULL pointer dereference + +This fixes possible NULL pointer dereference +in case no whitelist is initialized. + +Signed-off-by: Valentine Barshak +--- + drivers/iommu/ipmmu-vmsa.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c +index 4a3055f..cdbfc53 100644 +--- a/drivers/iommu/ipmmu-vmsa.c ++++ b/drivers/iommu/ipmmu-vmsa.c +@@ -1485,7 +1485,7 @@ static int ipmmu_whitelist_init(struct ipmmu_vmsa_device *mmu) + else + mmu->whitelist = NULL; + +- if (!mmu->whitelist[0]) ++ if (!mmu->whitelist) + return -1; + + return ipmmu_bm_init(mmu); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0285-iommu-ipmmu-vmsa-Add-r8a779-7-8-0-whitelist.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0285-iommu-ipmmu-vmsa-Add-r8a779-7-8-0-whitelist.patch new file mode 100644 index 00000000..8ec4be85 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0285-iommu-ipmmu-vmsa-Add-r8a779-7-8-0-whitelist.patch @@ -0,0 +1,65 @@ +From 48a84430fd00e74e4a380324acd3f96b7a2873ad Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Tue, 25 Jun 2019 22:40:40 +0300 +Subject: [PATCH 105/211] iommu: ipmmu-vmsa: Add r8a779{7|8}0 whitelist + +This adds empty r8a779{7|8}0 whitelist disabling +IPMMU on R-Car V3M and V3H SoCs. + +Signed-off-by: Valentine Barshak +--- + drivers/iommu/ipmmu-vmsa.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c +index cdbfc53..52e292a 100644 +--- a/drivers/iommu/ipmmu-vmsa.c ++++ b/drivers/iommu/ipmmu-vmsa.c +@@ -243,6 +243,16 @@ static struct ipmmu_whitelist *r8a77965_whitelist[] = { + NULL, /* Terminator */ + }; + ++/* R-Car E3 (R8A77970) */ ++static struct ipmmu_whitelist *r8a77970_whitelist[] = { ++ NULL, /* Terminator */ ++}; ++ ++/* R-Car E3 (R8A77980) */ ++static struct ipmmu_whitelist *r8a77980_whitelist[] = { ++ NULL, /* Terminator */ ++}; ++ + /* R-Car E3 (R8A77990) */ + static struct ipmmu_whitelist r8a77990_ipmmu_vi0 = { + .ipmmu_name = "febd0000.mmu", +@@ -1145,6 +1155,16 @@ static const struct soc_device_attribute r8a77965[] = { + { /* sentinel */ } + }; + ++static const struct soc_device_attribute r8a77970[] = { ++ { .soc_id = "r8a77970" }, ++ { /* sentinel */ } ++}; ++ ++static const struct soc_device_attribute r8a77980[] = { ++ { .soc_id = "r8a77980" }, ++ { /* sentinel */ } ++}; ++ + static const struct soc_device_attribute r8a77990[] = { + { .soc_id = "r8a77990" }, + { /* sentinel */ } +@@ -1482,6 +1502,10 @@ static int ipmmu_whitelist_init(struct ipmmu_vmsa_device *mmu) + mmu->whitelist = r8a77965_whitelist; + else if (soc_device_match(r8a77990)) + mmu->whitelist = r8a77990_whitelist; ++ else if (soc_device_match(r8a77970)) ++ mmu->whitelist = r8a77970_whitelist; ++ else if (soc_device_match(r8a77980)) ++ mmu->whitelist = r8a77980_whitelist; + else + mmu->whitelist = NULL; + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0286-clk-renesas-r8a77980-cpg-mssr-Add-VIN-clocks.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0286-clk-renesas-r8a77980-cpg-mssr-Add-VIN-clocks.patch new file mode 100644 index 00000000..c8ac9d86 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0286-clk-renesas-r8a77980-cpg-mssr-Add-VIN-clocks.patch @@ -0,0 +1,34 @@ +From a8feccd1f7457b094dcb0cad572d661e7e470740 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Fri, 26 Oct 2018 19:21:28 +0300 +Subject: [PATCH 106/211] clk: renesas: r8a77980: cpg-mssr: Add VIN clocks + +This adds VIN clocks to R8A77980 CPG MSSR driver. + +Signed-off-by: Valentine Barshak +--- + drivers/clk/renesas/r8a77980-cpg-mssr.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/clk/renesas/r8a77980-cpg-mssr.c b/drivers/clk/renesas/r8a77980-cpg-mssr.c +index 7227f67..711a1c5 100644 +--- a/drivers/clk/renesas/r8a77980-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a77980-cpg-mssr.c +@@ -154,6 +154,14 @@ static const struct mssr_mod_clk r8a77980_mod_clks[] __initconst = { + DEF_MOD("csi40", 716, R8A77980_CLK_CSI0), + DEF_MOD("du0", 724, R8A77980_CLK_S2D1), + DEF_MOD("lvds", 727, R8A77980_CLK_S2D1), ++ DEF_MOD("vin7", 804, R8A77980_CLK_S2D1), ++ DEF_MOD("vin6", 805, R8A77980_CLK_S2D1), ++ DEF_MOD("vin5", 806, R8A77980_CLK_S2D1), ++ DEF_MOD("vin4", 807, R8A77980_CLK_S2D1), ++ DEF_MOD("vin3", 808, R8A77980_CLK_S2D1), ++ DEF_MOD("vin2", 809, R8A77980_CLK_S2D1), ++ DEF_MOD("vin1", 810, R8A77980_CLK_S2D1), ++ DEF_MOD("vin0", 811, R8A77980_CLK_S2D1), + DEF_MOD("etheravb", 812, R8A77980_CLK_S3D2), + DEF_MOD("gether", 813, R8A77980_CLK_S3D2), + DEF_MOD("imp3", 824, R8A77980_CLK_S1D1), +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0287-clk-renesas-r8a77970-cpg-mssr-Add-IMR-clocks.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0287-clk-renesas-r8a77970-cpg-mssr-Add-IMR-clocks.patch new file mode 100644 index 00000000..ef035f5e --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0287-clk-renesas-r8a77970-cpg-mssr-Add-IMR-clocks.patch @@ -0,0 +1,30 @@ +From ab197e0f74638e62a8619cbf085055f438df5e5f Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Fri, 26 Oct 2018 19:14:40 +0300 +Subject: [PATCH 107/211] clk: renesas: r8a77970: cpg-mssr: Add IMR clocks + +This adds IMR clocks to R8A7790 CPG MSSR driver. + +Signed-off-by: Valentine Barshak +--- + drivers/clk/renesas/r8a77970-cpg-mssr.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/clk/renesas/r8a77970-cpg-mssr.c b/drivers/clk/renesas/r8a77970-cpg-mssr.c +index cbac67e..ab847ee 100644 +--- a/drivers/clk/renesas/r8a77970-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a77970-cpg-mssr.c +@@ -152,6 +152,10 @@ static const struct mssr_mod_clk r8a77970_mod_clks[] __initconst = { + DEF_MOD("vin1", 810, R8A77970_CLK_S2D1), + DEF_MOD("vin0", 811, R8A77970_CLK_S2D1), + DEF_MOD("etheravb", 812, R8A77970_CLK_S2D2), ++ DEF_MOD("imr3", 820, R8A77970_CLK_S2D1), ++ DEF_MOD("imr2", 821, R8A77970_CLK_S2D1), ++ DEF_MOD("imr1", 822, R8A77970_CLK_S2D1), ++ DEF_MOD("imr0", 823, R8A77970_CLK_S2D1), + DEF_MOD("gpio5", 907, R8A77970_CLK_CP), + DEF_MOD("gpio4", 908, R8A77970_CLK_CP), + DEF_MOD("gpio3", 909, R8A77970_CLK_CP), +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0288-clk-renesas-r8a77980-cpg-mssr-Add-IMR-clocks.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0288-clk-renesas-r8a77980-cpg-mssr-Add-IMR-clocks.patch new file mode 100644 index 00000000..2bc5a100 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0288-clk-renesas-r8a77980-cpg-mssr-Add-IMR-clocks.patch @@ -0,0 +1,39 @@ +From a971c62087b1ffe2e074b832c7b4a0a584ffe09f Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Fri, 26 Oct 2018 19:23:58 +0300 +Subject: [PATCH 108/211] clk: renesas: r8a77980: cpg-mssr: Add IMR clocks + +This adds IMR clocks to R8A77980 CPG MSSR driver. + +Signed-off-by: Valentine Barshak +--- + drivers/clk/renesas/r8a77980-cpg-mssr.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/clk/renesas/r8a77980-cpg-mssr.c b/drivers/clk/renesas/r8a77980-cpg-mssr.c +index 711a1c5..dfa947a 100644 +--- a/drivers/clk/renesas/r8a77980-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a77980-cpg-mssr.c +@@ -150,6 +150,8 @@ static const struct mssr_mod_clk r8a77980_mod_clks[] __initconst = { + DEF_MOD("imp-ocv2", 531, R8A77980_CLK_S1D1), + DEF_MOD("fcpvd0", 603, R8A77980_CLK_S3D1), + DEF_MOD("vspd0", 623, R8A77980_CLK_S3D1), ++ DEF_MOD("imr5", 706, R8A77980_CLK_S2D1), ++ DEF_MOD("imr4", 707, R8A77980_CLK_S2D1), + DEF_MOD("csi41", 715, R8A77980_CLK_CSI0), + DEF_MOD("csi40", 716, R8A77980_CLK_CSI0), + DEF_MOD("du0", 724, R8A77980_CLK_S2D1), +@@ -164,6 +166,10 @@ static const struct mssr_mod_clk r8a77980_mod_clks[] __initconst = { + DEF_MOD("vin0", 811, R8A77980_CLK_S2D1), + DEF_MOD("etheravb", 812, R8A77980_CLK_S3D2), + DEF_MOD("gether", 813, R8A77980_CLK_S3D2), ++ DEF_MOD("imr3", 820, R8A77980_CLK_S2D1), ++ DEF_MOD("imr2", 821, R8A77980_CLK_S2D1), ++ DEF_MOD("imr1", 822, R8A77980_CLK_S2D1), ++ DEF_MOD("imr0", 823, R8A77980_CLK_S2D1), + DEF_MOD("imp3", 824, R8A77980_CLK_S1D1), + DEF_MOD("imp2", 825, R8A77980_CLK_S1D1), + DEF_MOD("imp1", 826, R8A77980_CLK_S1D1), +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0289-clk-renesas-r8a77970-cpg-mssr-Add-ISP-clock.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0289-clk-renesas-r8a77970-cpg-mssr-Add-ISP-clock.patch new file mode 100644 index 00000000..7a2c8e79 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0289-clk-renesas-r8a77970-cpg-mssr-Add-ISP-clock.patch @@ -0,0 +1,27 @@ +From 58543097fab7bfb26c3f81ebb8cdfe8a29161c16 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Mon, 29 Oct 2018 13:37:25 +0300 +Subject: [PATCH 109/211] clk: renesas: r8a77970: cpg-mssr: Add ISP clock + +This adds ISP clock. + +Signed-off-by: Valentine Barshak +--- + drivers/clk/renesas/r8a77970-cpg-mssr.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/clk/renesas/r8a77970-cpg-mssr.c b/drivers/clk/renesas/r8a77970-cpg-mssr.c +index ab847ee..5ae694b 100644 +--- a/drivers/clk/renesas/r8a77970-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a77970-cpg-mssr.c +@@ -152,6 +152,7 @@ static const struct mssr_mod_clk r8a77970_mod_clks[] __initconst = { + DEF_MOD("vin1", 810, R8A77970_CLK_S2D1), + DEF_MOD("vin0", 811, R8A77970_CLK_S2D1), + DEF_MOD("etheravb", 812, R8A77970_CLK_S2D2), ++ DEF_MOD("isp", 817, R8A77970_CLK_S2D1), + DEF_MOD("imr3", 820, R8A77970_CLK_S2D1), + DEF_MOD("imr2", 821, R8A77970_CLK_S2D1), + DEF_MOD("imr1", 822, R8A77970_CLK_S2D1), +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0290-clk-renesas-r8a77980-cpg-mssr-Add-ISP-clocks.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0290-clk-renesas-r8a77980-cpg-mssr-Add-ISP-clocks.patch new file mode 100644 index 00000000..d0aa7eab --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0290-clk-renesas-r8a77980-cpg-mssr-Add-ISP-clocks.patch @@ -0,0 +1,28 @@ +From 4636088d830f0cf114e50ed997dcd8cdaf80f12f Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Mon, 29 Oct 2018 13:58:17 +0300 +Subject: [PATCH 110/211] clk: renesas: r8a77980: cpg-mssr: Add ISP clocks + +This adds ISP clocks. + +Signed-off-by: Valentine Barshak +--- + drivers/clk/renesas/r8a77980-cpg-mssr.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/clk/renesas/r8a77980-cpg-mssr.c b/drivers/clk/renesas/r8a77980-cpg-mssr.c +index dfa947a..61ffe60 100644 +--- a/drivers/clk/renesas/r8a77980-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a77980-cpg-mssr.c +@@ -166,6 +166,8 @@ static const struct mssr_mod_clk r8a77980_mod_clks[] __initconst = { + DEF_MOD("vin0", 811, R8A77980_CLK_S2D1), + DEF_MOD("etheravb", 812, R8A77980_CLK_S3D2), + DEF_MOD("gether", 813, R8A77980_CLK_S3D2), ++ DEF_MOD("isp1", 814, R8A77980_CLK_S3D1), ++ DEF_MOD("isp0", 817, R8A77980_CLK_S3D1), + DEF_MOD("imr3", 820, R8A77980_CLK_S2D1), + DEF_MOD("imr2", 821, R8A77980_CLK_S2D1), + DEF_MOD("imr1", 822, R8A77980_CLK_S2D1), +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0291-clk-renesas-r8a77980-cpg-mssr-Add-IMP-clocks.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0291-clk-renesas-r8a77980-cpg-mssr-Add-IMP-clocks.patch new file mode 100644 index 00000000..6b6727ae --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0291-clk-renesas-r8a77980-cpg-mssr-Add-IMP-clocks.patch @@ -0,0 +1,36 @@ +From f259ce6a01dfc0ece91e461c050b74414649de20 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Tue, 6 Nov 2018 02:54:57 +0300 +Subject: [PATCH 111/211] clk: renesas: r8a77980: cpg-mssr: Add IMP clocks + +This adds more IMP clocks. + +Signed-off-by: Valentine Barshak +--- + drivers/clk/renesas/r8a77980-cpg-mssr.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/clk/renesas/r8a77980-cpg-mssr.c b/drivers/clk/renesas/r8a77980-cpg-mssr.c +index 61ffe60..feb5eab 100644 +--- a/drivers/clk/renesas/r8a77980-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a77980-cpg-mssr.c +@@ -136,6 +136,7 @@ static const struct mssr_mod_clk r8a77980_mod_clks[] __initconst = { + DEF_MOD("rwdt", 402, R8A77980_CLK_R), + DEF_MOD("intc-ex", 407, R8A77980_CLK_CP), + DEF_MOD("intc-ap", 408, R8A77980_CLK_S0D3), ++ DEF_MOD("simp", 500, R8A77980_CLK_S1D1), + DEF_MOD("hscif3", 517, R8A77980_CLK_S3D1), + DEF_MOD("hscif2", 518, R8A77980_CLK_S3D1), + DEF_MOD("hscif1", 519, R8A77980_CLK_S3D1), +@@ -143,6 +144,8 @@ static const struct mssr_mod_clk r8a77980_mod_clks[] __initconst = { + DEF_MOD("imp4", 521, R8A77980_CLK_S1D1), + DEF_MOD("thermal", 522, R8A77980_CLK_CP), + DEF_MOD("pwm", 523, R8A77980_CLK_S0D12), ++ DEF_MOD("imppsc1", 524, R8A77980_CLK_S1D1), ++ DEF_MOD("imppsc0", 525, R8A77980_CLK_S1D1), + DEF_MOD("impdma1", 526, R8A77980_CLK_S1D1), + DEF_MOD("impdma0", 527, R8A77980_CLK_S1D1), + DEF_MOD("imp-ocv4", 528, R8A77980_CLK_S1D1), +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0292-clk-renesas-r8a77980-cpg-mssr-Add-VIP-clocks.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0292-clk-renesas-r8a77980-cpg-mssr-Add-VIP-clocks.patch new file mode 100644 index 00000000..0039ccad --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0292-clk-renesas-r8a77980-cpg-mssr-Add-VIP-clocks.patch @@ -0,0 +1,43 @@ +From e9bc27fd3805d8ff37435ddc28e56eff017a8e2f Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Tue, 6 Nov 2018 02:59:39 +0300 +Subject: [PATCH 112/211] clk: renesas: r8a77980: cpg-mssr: Add VIP clocks + +This adds VIP clocks. + +Signed-off-by: Valentine Barshak +--- + drivers/clk/renesas/r8a77980-cpg-mssr.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/clk/renesas/r8a77980-cpg-mssr.c b/drivers/clk/renesas/r8a77980-cpg-mssr.c +index feb5eab..5371c27 100644 +--- a/drivers/clk/renesas/r8a77980-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a77980-cpg-mssr.c +@@ -111,6 +111,8 @@ static const struct cpg_core_clk r8a77980_core_clks[] __initconst = { + }; + + static const struct mssr_mod_clk r8a77980_mod_clks[] __initconst = { ++ DEF_MOD("disp", 101, R8A77980_CLK_S1D1), ++ DEF_MOD("umf", 102, R8A77980_CLK_S1D1), + DEF_MOD("tmu4", 121, R8A77980_CLK_S0D6), + DEF_MOD("tmu3", 122, R8A77980_CLK_S0D6), + DEF_MOD("tmu2", 123, R8A77980_CLK_S0D6), +@@ -196,6 +198,14 @@ static const struct mssr_mod_clk r8a77980_mod_clks[] __initconst = { + DEF_MOD("i2c2", 929, R8A77980_CLK_S3D2), + DEF_MOD("i2c1", 930, R8A77980_CLK_S3D2), + DEF_MOD("i2c0", 931, R8A77980_CLK_S3D2), ++ DEF_MOD("cle4", 1000, R8A77980_CLK_S1D1), ++ DEF_MOD("cle3", 1001, R8A77980_CLK_S1D1), ++ DEF_MOD("cle2", 1002, R8A77980_CLK_S1D1), ++ DEF_MOD("cle1", 1003, R8A77980_CLK_S1D1), ++ DEF_MOD("cle0", 1004, R8A77980_CLK_S1D1), ++ DEF_MOD("smd_post", 1100, R8A77980_CLK_S0D3), ++ DEF_MOD("smd_est", 1101, R8A77980_CLK_S0D3), ++ DEF_MOD("smd_ps", 1102, R8A77980_CLK_S0D3), + }; + + static const unsigned int r8a77980_crit_mod_clks[] __initconst = { +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0293-clk-renesas-r8a77970-cpg-mssr-Add-IMP-clocks.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0293-clk-renesas-r8a77970-cpg-mssr-Add-IMP-clocks.patch new file mode 100644 index 00000000..7d8e7e2a --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0293-clk-renesas-r8a77970-cpg-mssr-Add-IMP-clocks.patch @@ -0,0 +1,33 @@ +From b55a082af8abefb51feedbecd20df65689302697 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Tue, 6 Nov 2018 03:24:54 +0300 +Subject: [PATCH 113/211] clk: renesas: r8a77970: cpg-mssr: Add IMP clocks + +This adds IMP clocks. + +Signed-off-by: Valentine Barshak +--- + drivers/clk/renesas/r8a77970-cpg-mssr.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/clk/renesas/r8a77970-cpg-mssr.c b/drivers/clk/renesas/r8a77970-cpg-mssr.c +index 5ae694b..29833b6 100644 +--- a/drivers/clk/renesas/r8a77970-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a77970-cpg-mssr.c +@@ -157,6 +157,13 @@ static const struct mssr_mod_clk r8a77970_mod_clks[] __initconst = { + DEF_MOD("imr2", 821, R8A77970_CLK_S2D1), + DEF_MOD("imr1", 822, R8A77970_CLK_S2D1), + DEF_MOD("imr0", 823, R8A77970_CLK_S2D1), ++ DEF_MOD("imp3", 824, R8A77970_CLK_S1D1), ++ DEF_MOD("imp2", 825, R8A77970_CLK_S1D1), ++ DEF_MOD("imp1", 826, R8A77970_CLK_S1D1), ++ DEF_MOD("imp0", 827, R8A77970_CLK_S1D1), ++ DEF_MOD("imp-ocv1", 828, R8A77970_CLK_S1D1), ++ DEF_MOD("imp-ocv0", 829, R8A77970_CLK_S1D1), ++ DEF_MOD("impram", 830, R8A77970_CLK_S1D1), + DEF_MOD("gpio5", 907, R8A77970_CLK_CP), + DEF_MOD("gpio4", 908, R8A77970_CLK_CP), + DEF_MOD("gpio3", 909, R8A77970_CLK_CP), +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0294-media-soc_camera-Add-CONFIG_VIDEO_ADV_DEBUG-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0294-media-soc_camera-Add-CONFIG_VIDEO_ADV_DEBUG-support.patch new file mode 100644 index 00000000..879051f8 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0294-media-soc_camera-Add-CONFIG_VIDEO_ADV_DEBUG-support.patch @@ -0,0 +1,78 @@ +From 83c415759f5b2ebdd19e0e3e1932bac3a63206f9 Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Mon, 12 Nov 2018 15:43:59 +0300 +Subject: [PATCH 114/211] media: soc_camera: Add CONFIG_VIDEO_ADV_DEBUG + support. + +Signed-off-by: Vladimir Barinov +--- + drivers/media/platform/soc_camera/soc_camera.c | 30 ++++++++++++++++++++++++++ + include/media/soc_camera.h | 4 ++++ + 2 files changed, 34 insertions(+) + +diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c +index 1f840cf..0fa1f52 100644 +--- a/drivers/media/platform/soc_camera/soc_camera.c ++++ b/drivers/media/platform/soc_camera/soc_camera.c +@@ -1056,6 +1056,32 @@ static int soc_camera_g_edid(struct file *file, void *fh, + return -ENOIOCTLCMD; + } + ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int soc_camera_g_register(struct file *file, void *priv, ++ struct v4l2_dbg_register *reg) ++{ ++ struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ ++ if (ici->ops->get_register) ++ return ici->ops->get_register(icd, reg); ++ ++ return -ENOIOCTLCMD; ++} ++ ++static int soc_camera_s_register(struct file *file, void *priv, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ ++ if (ici->ops->set_register) ++ return ici->ops->set_register(icd, reg); ++ ++ return -ENOIOCTLCMD; ++} ++#endif ++ + static int soc_camera_probe(struct soc_camera_host *ici, + struct soc_camera_device *icd); + +@@ -2026,6 +2052,10 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = { + .vidioc_g_parm = soc_camera_g_parm, + .vidioc_s_parm = soc_camera_s_parm, + .vidioc_g_edid = soc_camera_g_edid, ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .vidioc_g_register = soc_camera_g_register, ++ .vidioc_s_register = soc_camera_s_register, ++#endif + }; + + static int video_dev_create(struct soc_camera_device *icd) +diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h +index 4381be0..c2a7fc2 100644 +--- a/include/media/soc_camera.h ++++ b/include/media/soc_camera.h +@@ -119,6 +119,10 @@ struct soc_camera_host_ops { + int (*enum_framesizes)(struct soc_camera_device *, struct v4l2_frmsizeenum *); + unsigned int (*poll)(struct file *, poll_table *); + int (*get_edid)(struct soc_camera_device *, struct v4l2_edid *); ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ int (*get_register)(struct soc_camera_device *, struct v4l2_dbg_register *reg); ++ int (*set_register)(struct soc_camera_device *, const struct v4l2_dbg_register *reg); ++#endif + }; + + #define SOCAM_SENSOR_INVERT_PCLK (1 << 0) +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0295-media-platform-soc_camera-Add-V4L2-R-Car-ISP-driver.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0295-media-platform-soc_camera-Add-V4L2-R-Car-ISP-driver.patch new file mode 100644 index 00000000..05f180b7 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0295-media-platform-soc_camera-Add-V4L2-R-Car-ISP-driver.patch @@ -0,0 +1,2150 @@ +From 0b363ab08af71741db4eb51b31beab9f64e11dfe Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Tue, 15 May 2018 11:33:45 +0300 +Subject: [PATCH 115/211] media: platform: soc_camera: Add V4L2 R-Car ISP + driver + +This adds R-Car ISP driver. + +Signed-off-by: Vladimir Barinov +Signed-off-by: Valentine Barshak +--- + drivers/media/platform/soc_camera/Kconfig | 9 + + drivers/media/platform/soc_camera/Makefile | 1 + + drivers/media/platform/soc_camera/rcar_isp.c | 2094 ++++++++++++++++++++++++++ + 3 files changed, 2104 insertions(+) + create mode 100644 drivers/media/platform/soc_camera/rcar_isp.c + +diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig +index 6616d59..61b0dcf 100644 +--- a/drivers/media/platform/soc_camera/Kconfig ++++ b/drivers/media/platform/soc_camera/Kconfig +@@ -44,6 +44,15 @@ config VIDEO_RCAR_CSI2_LEGACY + ---help--- + This is a v4l2 driver for the R-Car CSI-2 Interface + ++config VIDEO_RCAR_ISP_LEGACY ++ tristate "R-Car Image Signal Processing (ISP) support" ++ depends on VIDEO_DEV && SOC_CAMERA ++ depends on ARCH_RENESAS || COMPILE_TEST ++ depends on HAS_DMA ++ select VIDEOBUF2_DMA_CONTIG ++ ---help--- ++ This is a v4l2 driver for the R-Car ISP Interface ++ + config VIDEO_SH_MOBILE_CEU + tristate "SuperH Mobile CEU Interface driver" + depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA && HAVE_CLK +diff --git a/drivers/media/platform/soc_camera/Makefile b/drivers/media/platform/soc_camera/Makefile +index 1a70361..49449e1 100644 +--- a/drivers/media/platform/soc_camera/Makefile ++++ b/drivers/media/platform/soc_camera/Makefile +@@ -8,4 +8,5 @@ obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o + # soc-camera host drivers have to be linked after camera drivers + obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o + obj-$(CONFIG_VIDEO_RCAR_CSI2_LEGACY) += rcar_csi2.o ++obj-$(CONFIG_VIDEO_RCAR_ISP_LEGACY) += rcar_isp.o + obj-$(CONFIG_VIDEO_RCAR_VIN_LEGACY) += rcar_vin.o +diff --git a/drivers/media/platform/soc_camera/rcar_isp.c b/drivers/media/platform/soc_camera/rcar_isp.c +new file mode 100644 +index 0000000..878df95 +--- /dev/null ++++ b/drivers/media/platform/soc_camera/rcar_isp.c +@@ -0,0 +1,2094 @@ ++/* ++ * SoC-camera host driver for Renesas R-Car ISP unit ++ * ++ * Copyright (C) 2018 Renesas Electronics Corporation ++ * Copyright (C) 2018 Cogent Embedded ++ * ++ * Based on V4L2 Driver for R-Car VIN interface "rca_vin.c" ++ * ++ * 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. ++ */ ++ ++//#define DEBUG ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "soc_scale_crop.h" ++ ++#define DRV_NAME "rcar_isp" ++ ++/* Register offsets for R-Car ISP Interface */ ++/* Basic Control */ ++#define ISPVCR_REG 0x0000 ++#define ISPFIFOCTRL_REG 0x0004 ++#define ISPINPUTSEL0_REG 0x0008 ++#define ISPSTART_REG 0x0014 ++#define ISPINT_STATUS_REG 0x0040 ++#define ISPERR0_STATUS_REG 0x0044 ++#define ISPERR1_STATUS_REG 0x0048 ++#define ISPINT_CLEAR_REG 0x0050 ++#define ISPERR0_CLEAR_REG 0x0054 ++#define ISPERR1_CLEAR_REG 0x0058 ++#define ISPINT_ENABLE_REG 0x0060 ++#define ISPERR0_ENABLE_REG 0x0064 ++#define ISPERR1_ENABLE_REG 0x0068 ++#define ISP_PADDING_CTRL_REG 0x00C0 ++ ++/* Register offsets for R-Car ISP Core */ ++/* Pipeline Frontend */ ++#define PIPEFE_GFSMR_REG 0x0020 ++ ++/* Interrupts */ ++#define INT_FSM_REG 0x0084 ++#define INT_FSS_REG 0x0088 ++#define INT_FSC_REG 0x008C ++#define INT_FEM_REG 0x0098 ++#define INT_FES_REG 0x009C ++#define INT_FEC_REG 0x00A0 ++#define INT_FEL0_REG 0x00A4 ++#define INT_FEL1_REG 0x00A8 ++#define INT_STM_REG 0x00B0 ++#define INT_STS_REG 0x00B4 ++#define INT_STC_REG 0x00B8 ++ ++/* Input Ports (Port n uses VC=n) */ ++#define INP_HCSTART0_REG(n) (0x010C + (n << 6)) ++#define INP_HCSIZE0_REG(n) (0x0110 + (n << 6)) ++#define INP_HCSTART1_REG(n) (0x0114 + (n << 6)) ++#define INP_HCSIZE1_REG(n) (0x0118 + (n << 6)) ++#define INP_VCSTART_REG(n) (0x0120 + (n << 6)) ++#define INP_VCSIZE_REG(n) (0x0124 + (n << 6)) ++#define INP_MR_REG 0x01F0 ++#define INP_MS_REG 0x01F4 ++ ++#define INP_MS(n) (1 << (n << 3)) ++ ++/* OUT_BUFFERS */ ++#define OBUF_BV_REG(n) (0x0C00 + (n << 5)) ++#define OBUF_BA_REG(n) (0x0C04 + (n << 5)) ++#define OBUF_LO_REG(n) (0x0C08 + (n << 5)) ++#define OBUF_AW_REG(n) (0x0C0C + (n << 5)) ++#define OBUF_AH_REG(n) (0x0C10 + (n << 5)) ++#define OBUF_HM_REG(n) (0x0C14 + (n << 5)) ++#define OBUF_ST_REG(n) (0x0C18 + (n << 5)) ++ ++/* Stream Crossbar */ ++#define SCB_SELECT_REG(n) (0x03E0 + (n << 2)) ++ ++/* Multichannel Frontend */ ++#define MCFE_FIFOC_REG 0x0400 ++#define MCFE_SCM_REG 0x0414 ++#define MCFE_OWL_REG 0x041C ++#define MCFE_SLM0_REG 0x0420 ++#define MCFE_SLM4_REG 0x0424 ++#define MCFE_SLCFGV0_REG 0x0458 ++#define MCFE_SLCFGV4_REG 0x045C ++#define MCFE_SLINP_REG(n) (0x04E0 + (n << 2)) ++#define MCFE_SLOUTBUF1_REG(n) (0x0500 + (n << 2)) ++#define MCFE_SLOUTBUF2_REG(n) (0x0520 + (n << 2)) ++#define MCFE_INM_REG 0x0540 ++#define MCFE_INAL_REG 0x0544 ++#define MCFE_INDW_REG 0x054C ++#define MCFE_INSV_REG 0x0550 ++ ++#define MCFE_SCM_STOPPED (0 << 0) ++#define MCFE_SCM_MANUAL (1 << 0) ++#define MCFE_SCM_1STREAM (2 << 0) ++ ++#define MCFE_SCM_SLOT(n) (n << 16) ++ ++#define MCFE_SLM0_PASSTHR(n) (1 << (n << 3)) ++ ++/* Top */ ++#define TOP_AW_REG 0xE010 ++#define TOP_AH_REG 0xE014 ++#define TOP_RGGB_REG 0xE018 ++ ++#define TOP_RGGB_RGrGbB (0 << 0) ++#define TOP_RGGB_GrRBGb (1 << 0) ++#define TOP_RGGB_GbBRGr (2 << 0) ++#define TOP_RGGB_BGbGrR (3 << 0) ++ ++#define TOP_CFA_RGGB (0 << 8) ++ ++/* Pipeline */ ++#define PIPE_CHS_REG 0xE020 ++#define PIPE_FSCHS_REG 0xE02C ++#define PIPE_CBM_REG 0xE030 ++#define PIPE_BP_REG 0xE040 ++ ++#define PIPE_BP_INF (1 << 2) ++#define PIPE_BP_DEMOSAIC (1 << 19) ++#define PIPE_BP_OUTF (1 << 20) ++ ++/* Input Formatter */ ++#define INF_MI_REG 0xE140 ++ ++#define INF_MI_LINEAR (0 << 0) ++#define INF_MI_8BITS (0 << 16) ++#define INF_MI_MSB (1 << 24) ++ ++/* Output Formatter */ ++#define OUTF_BP_REG 0xE600 ++#define OUTF_MODE_REG 0xE608 ++ ++#define OUTF_BP_RGB2YUV (1 << 9) ++#define OUTF_BP_RGB2YUV_SP (1 << 14) ++ ++/* Out format MUX for AXI */ ++#define AXIOUT_MS_REG 0xE740 ++ ++#define AXIOUT_MS_YUV_Y12 (4 << 0) ++#define AXIOUT_MS_YUV_UV8 (7 << 0) ++#define AXIOUT_MS_LUV_UV8 (12 << 0) ++#define AXIOUT_MS_RGB888 (15 << 0) ++#define AXIOUT_MS_RAW8 (24 << 0) ++#define AXIOUT_MS_RAW16 (27 << 0) ++ ++#define AXIOUT_MSB_ALIGN (1 << 7) ++ ++enum chip_id { ++ RCAR_GEN3, ++ RCAR_V3M, ++ RCAR_V3H, ++}; ++ ++enum csi2_ch { ++ RCAR_CSI_CH_NONE = -1, ++ RCAR_CSI40, ++ RCAR_CSI41, ++}; ++ ++enum gen3_isp_ch { ++ RCAR_ISP_CH_NONE = -1, ++ RCAR_ISP_CH_0, ++ RCAR_ISP_CH_1, ++}; ++ ++enum virtual_ch { ++ RCAR_VIRTUAL_NONE = -1, ++ RCAR_VIRTUAL_CH0, ++ RCAR_VIRTUAL_CH1, ++ RCAR_VIRTUAL_CH2, ++ RCAR_VIRTUAL_CH3, ++}; ++ ++enum rcar_isp_state { ++ STOPPED, ++ RUNNING, ++}; ++ ++struct isp_gen3_virtual_sel { ++ enum csi2_ch csi2_ch; ++ enum virtual_ch vc; ++}; ++ ++struct rcar_isp_async_client { ++ struct v4l2_async_subdev *sensor; ++ struct v4l2_async_notifier notifier; ++ struct platform_device *pdev; ++}; ++ ++struct soc_of_info { ++ struct soc_camera_async_subdev sasd; ++ struct rcar_isp_async_client sasc; ++ struct v4l2_async_subdev *subdev; ++}; ++ ++struct rcar_isp_interface { ++ void __iomem *base; ++}; ++ ++struct rcar_isp_priv { ++ struct device *dev; ++ void __iomem *base; ++ struct rcar_isp_interface interface; ++ spinlock_t lock; ++ int sequence; ++ /* State of the ISP module in capturing mode */ ++ enum rcar_isp_state state; ++ struct soc_camera_host ici; ++ struct list_head capture; ++#define MAX_BUFFER_NUM 1 ++ struct vb2_v4l2_buffer *queue_buf[MAX_BUFFER_NUM]; ++ enum v4l2_field field; ++ unsigned int vb_count; ++ unsigned int nr_hw_slots; ++ enum chip_id chip; ++ unsigned int max_width; ++ unsigned int max_height; ++ enum csi2_ch csi_ch; ++ enum virtual_ch vc; ++ bool csi_sync; ++ bool deser_sync; ++ ++ struct rcar_isp_async_client *async_client; ++ /* Asynchronous CSI2 linking */ ++ struct v4l2_subdev *csi2_sd; ++ /* Asynchronous Deserializer linking */ ++ struct v4l2_subdev *deser_sd; ++ /* ISP channel */ ++ unsigned int index; ++}; ++ ++struct rcar_isp_buffer { ++ struct vb2_v4l2_buffer vb; ++ struct list_head list; ++}; ++ ++#define to_buf_list(vb2_buffer) (&container_of(vb2_buffer, struct rcar_isp_buffer, vb)->list) ++ ++struct rcar_isp_cam { ++ /* ISP offsets within the camera output, before the ISP scaler */ ++ unsigned int isp_left; ++ unsigned int isp_top; ++ /* Client output, as seen by the ISP */ ++ unsigned int width; ++ unsigned int height; ++ unsigned int raw_bpp; ++ /* User window from S_FMT */ ++ unsigned int out_width; ++ unsigned int out_height; ++ unsigned int out_bpp; ++ /* ++ * User window from S_SELECTION / G_SELECTION, produced by client cropping and ++ * scaling, ISP scaling and ISP cropping, mapped back onto the client ++ * input window ++ */ ++ struct v4l2_rect subrect; ++ /* Camera cropping rectangle */ ++ struct v4l2_rect rect; ++ const struct soc_mbus_pixelfmt *extra_fmt; ++}; ++ ++static void rcar_isp_open(struct rcar_isp_priv *priv) ++{ ++ int timeout; ++ u32 val; ++ int inport = 0; ++ ++ /* ISP version */ ++ val = ioread32(priv->interface.base + ISPVCR_REG); ++// printk("ISP version =0x%x\n", val); ++ /* ISP Input CSI FIFO enable */ ++ iowrite32(0x4, priv->interface.base + ISPFIFOCTRL_REG); ++ /* ISP Input select CSI */ ++ iowrite32(0x800, priv->interface.base + ISPINPUTSEL0_REG); ++ /* ISP control start */ ++ iowrite32(0xffff, priv->interface.base + ISPSTART_REG); ++ ++ /* V3H CSI stream filter needs following */ ++ if (priv->chip == RCAR_V3H) { ++ // select CSI2_41 channel for Cogent ECU ++// iowrite32(0x800 | BIT(31), priv->interface.base + ISPINPUTSEL0_REG); ++ ++ iowrite32(0x02, priv->interface.base + 0x11b0); ++ iowrite32(0x01, priv->interface.base + 0x3000); ++ iowrite32(0xac, priv->interface.base + 0x3008); ++ } ++ ++ /* PipelineIP: immediate update mode */ ++ iowrite32(0, priv->base + PIPE_CBM_REG); ++ ++ /* PipelineFE: reset/freeze all state machines (NOTE: does NOT reset ISP to defaults) */ ++ iowrite32(1, priv->base + PIPEFE_GFSMR_REG); ++ udelay(10); ++ /* PipelineFE: unfreeze all state machines */ ++ iowrite32(0, priv->base + PIPEFE_GFSMR_REG); ++ ++ /* INP: safe stop */ ++ iowrite32(0, priv->base + INP_MR_REG); ++ /* INP: poll status */ ++ for (timeout = 0; timeout < 100; timeout++) { ++ val = ioread32(priv->base + INP_MS_REG); ++ if (!(val & (INP_MS(inport)))) ++ break; ++ udelay(1000); ++ } ++ if (timeout >= 100) ++ pr_err("%s timeout input port stop\n", __func__); ++ ++ /* MCFE: one FIFO on each input/output channel */ ++ iowrite32(0, priv->base + MCFE_FIFOC_REG); ++ ++ /* DMA/FIFO watermarks setup */ ++ iowrite32(0x70004, priv->base + 0x0590); ++ iowrite32(0x70004, priv->base + 0x0598); ++ iowrite32(0x70004, priv->base + 0x05a4); ++ iowrite32(0x70004, priv->base + 0x05ac); ++ iowrite32(0x2800140, priv->base + 0x0404); ++ iowrite32(0x2800140, priv->base + 0x0408); ++ iowrite32(0x2800140, priv->base + 0x040c); ++ iowrite32(0x2800140, priv->base + 0x0410); ++ iowrite32(0x7000e, priv->base + 0x05c0); ++ iowrite32(0x72f681d9, priv->base + 0x05c4); ++ iowrite32(1, priv->base + 0x05c8); ++ iowrite32(0x800080, priv->base + 0x05cc); ++ iowrite32(0x400080, priv->base + 0x05d0); ++ ++ /* Invalidate Slot cfg */ ++ iowrite32(0, priv->base + MCFE_SLCFGV0_REG); ++ iowrite32(0, priv->base + MCFE_SLCFGV4_REG); ++ ++ /* Pipeline: bypass all modules */ ++ iowrite32(0xf93ffffc, priv->base + PIPE_BP_REG); ++ /* Pipeline: source select for RAW/VTPG */ ++ iowrite32(0xe4, priv->base + PIPE_CHS_REG); ++ /* Pipeline: source select for frame stitch */ ++ iowrite32(0xe4, priv->base + PIPE_FSCHS_REG); ++ ++ /* PipelineIP: global update mode (during vertical blanking) */ ++ iowrite32(3, priv->base + PIPE_CBM_REG); ++ /* Pipeline: tag# */ ++ iowrite32(0, priv->base + 0xe060); ++ /* Pipeline: context# */ ++ iowrite32(0, priv->base + 0xe064); ++ ++ /* FAULTS_CFG: mask all errors */ ++ iowrite32(0xffffffff, priv->base + 0x1000); ++ iowrite32(0xffffffff, priv->base + 0x1004); ++ iowrite32(0xffffffff, priv->base + 0x1008); ++ iowrite32(0xffffffff, priv->base + 0x100C); ++ iowrite32(0xffffffff, priv->base + 0x1010); ++ iowrite32(0xffffffff, priv->base + 0x1014); ++ iowrite32(0xffffffff, priv->base + 0x1018); ++ iowrite32(0xffffffff, priv->base + 0x101C); ++ iowrite32(0xffffffff, priv->base + 0x1020); ++ iowrite32(0xffffffff, priv->base + 0x1024); ++ iowrite32(0xffffffff, priv->base + 0x1028); ++ iowrite32(0xffffffff, priv->base + 0x102C); ++ iowrite32(0xffffffff, priv->base + 0x1030); ++} ++ ++static void rcar_isp_close(struct rcar_isp_priv *priv) ++{ ++ /* Pipeline FE: reset/freeze all state machines (NOTE: does NOT reset ISP to defaults) */ ++ iowrite32(1, priv->base + PIPEFE_GFSMR_REG); ++ /* ISP control stop */ ++ iowrite32(0, priv->interface.base + 0x14); ++} ++ ++static void rcar_isp_start(struct rcar_isp_priv *priv) ++{ ++ int timeout; ++ u32 val; ++ int slot = 0; ++ int inport = 0; ++ ++ /* MCFE: disable scheduler, set slots IDLE state */ ++ iowrite32(0xf << 16, priv->base + MCFE_SCM_REG); ++ /* INP: safe start */ ++ iowrite32(0x1, priv->base + INP_MR_REG); ++ /* INP: poll status */ ++ for (timeout = 0; timeout < 100; timeout++) { ++ val = ioread32(priv->base + INP_MS_REG); ++ if (val & (INP_MS(inport))) ++ break; ++ udelay(1000); ++ } ++ if (timeout >= 100) ++ pr_err("%s timeout input port start\n", __func__); ++ /* MCFE: enable scheduler, start slot#0 */ ++ iowrite32(MCFE_SCM_1STREAM | MCFE_SCM_SLOT(slot), priv->base + MCFE_SCM_REG); ++ ++ for (timeout = 0; timeout < 100; timeout++) { ++ val = ioread32(priv->base + MCFE_OWL_REG); ++ if (val != 0x3f3f3f3f) ++ break; ++ udelay(1000); ++ } ++ if (timeout >= 100) ++ pr_err("%s timeout out_buffer start\n", __func__); ++ ++ /* disable interrupts */ ++ iowrite32(0, priv->base + INT_FSM_REG); ++ iowrite32(0, priv->base + INT_FEM_REG); ++ iowrite32(0xffff, priv->base + INT_FEL0_REG); ++ iowrite32(0, priv->base + INT_FEL1_REG); ++ iowrite32(0, priv->base + INT_STM_REG); ++ /* ack interrupts */ ++ iowrite32(ioread32(priv->base + INT_FSS_REG), priv->base + INT_FSC_REG); ++ iowrite32(ioread32(priv->base + INT_FES_REG), priv->base + INT_FEC_REG); ++ iowrite32(ioread32(priv->base + INT_STS_REG), priv->base + INT_STC_REG); ++ /* enable frame end interrupt */ ++ iowrite32(BIT(15), priv->base + INT_FEM_REG); ++} ++ ++static void rcar_isp_stop(struct rcar_isp_priv *priv) ++{ ++ int timeout; ++ u32 val; ++ int inport = 0; ++ ++ /* disable interrupts */ ++ iowrite32(0, priv->base + INT_FEM_REG); ++ /* ack interrups */ ++ iowrite32(ioread32(priv->base + INT_FES_REG), priv->base + INT_FEC_REG); ++ ++ /* MCFE: disable all slots */ ++ iowrite32(0, priv->base + MCFE_SLM0_REG); ++ iowrite32(0, priv->base + MCFE_SLM4_REG); ++ /* MCFE: input mode off */ ++ iowrite32(0, priv->base + MCFE_INM_REG); ++ /* MCFE: stop scheduler */ ++ iowrite32(0, priv->base + MCFE_SCM_REG); ++ /* INP: safe stop */ ++ iowrite32(0, priv->base + INP_MR_REG); ++ /* INP: poll status */ ++ for (timeout = 0; timeout < 100; timeout++) { ++ val = ioread32(priv->base + INP_MS_REG); ++ if (!(val & (INP_MS(inport)))) ++ break; ++ udelay(1000); ++ } ++ if (timeout >= 100) ++ pr_err("%s timeout input port stop\n", __func__); ++} ++ ++static void rcar_isp_setup_inputs(struct rcar_isp_priv *priv, int inport, int raw_bpp) ++{ ++ struct rcar_isp_cam *cam = priv->ici.icd->host_priv; ++ int timeout; ++ u32 val; ++ ++ /* MCFE: input mode off */ ++ iowrite32(0, priv->base + MCFE_INM_REG); ++ /* INP: safe stop */ ++ iowrite32(0, priv->base + INP_MR_REG); ++ /* INP: poll status */ ++ for (timeout = 0; timeout < 100; timeout++) { ++ val = ioread32(priv->base + INP_MS_REG); ++ if (!(val & (INP_MS(inport)))) ++ break; ++ udelay(1000); ++ } ++ if (timeout >= 100) ++ pr_err("%s timeout input port stop\n", __func__); ++ ++ /* INP: freeze */ ++ iowrite32(0x80, priv->base + INP_MR_REG); ++ udelay(100); ++ ++ /* Stream Crossbar for MCFE INP#1 */ ++ val = (0 << 16); /* virtual channel */ ++ val |= (0 << 8); /* input video port1 */ ++ val |= 1; /* select data from one input */ ++ iowrite32(val, priv->base + SCB_SELECT_REG(inport)); ++ ++ /* window0 setup */ ++ iowrite32(0, priv->base + INP_HCSTART0_REG(inport)); ++ iowrite32(0, priv->base + INP_VCSTART_REG(inport)); ++ iowrite32(cam->out_width, priv->base + INP_HCSIZE0_REG(inport)); ++ iowrite32(cam->out_height, priv->base + INP_VCSIZE_REG(inport)); ++ /* window1 setup */ ++ iowrite32(0, priv->base + INP_HCSTART1_REG(inport)); ++ iowrite32(cam->out_width, priv->base + INP_HCSIZE1_REG(inport)); ++ ++ /* MCFE: Invalidate Input stats */ ++ iowrite32(0, priv->base + MCFE_INSV_REG); ++ /* MCFE: input data bpp */ ++ val = (raw_bpp << 24) | (raw_bpp << 16) | (raw_bpp << 8) | raw_bpp; ++ iowrite32(val, priv->base + MCFE_INDW_REG); ++ /* MCFE: input data alignment LSB */ ++ iowrite32(0, priv->base + MCFE_INAL_REG); ++ /* MCFE: input mode setup */ ++ val = 1 << (inport * 8); /* direct through FIFO */ ++ iowrite32(val, priv->base + MCFE_INM_REG); ++ ++ /* INP: unfreeze, safe stop */ ++ iowrite32(0, priv->base + INP_MR_REG); ++} ++ ++static void rcar_isp_setup_mcfe(struct rcar_isp_priv *priv, int slot_mode) ++{ ++ u32 val; ++ int slot = 0; ++ int slot_input = 0; ++ ++ /* Slots cancel and clear errors */ ++ iowrite32(0x06060606, priv->base + MCFE_SLM0_REG); ++ iowrite32(0x00000606, priv->base + MCFE_SLM4_REG); ++ /* Invalidate Slot cfg */ ++ iowrite32(0, priv->base + MCFE_SLCFGV0_REG); ++ iowrite32(0, priv->base + MCFE_SLCFGV4_REG); ++ /* MCFE: input mode off */ ++ iowrite32(0, priv->base + MCFE_INM_REG); ++ /* MCFE: Invalidate Input stats */ ++ iowrite32(0, priv->base + MCFE_INSV_REG); ++ udelay(100); //100 ++ ++ /* input streams for this slot */ ++ val = ioread32(priv->base + MCFE_SLINP_REG(slot)); ++ val &= ~0xff; ++ val |= slot_input; ++ iowrite32(val, priv->base + MCFE_SLINP_REG(slot)); ++ /* AXI out_buffers for this slot */ ++ val = ioread32(priv->base + MCFE_SLOUTBUF1_REG(slot)); ++ val &= ~0xff; ++ val |= 0; /* AXI buffer1 */ ++ iowrite32(val, priv->base + MCFE_SLOUTBUF1_REG(slot)); ++ val = ioread32(priv->base + MCFE_SLOUTBUF2_REG(slot)); ++ val &= ~0xff; ++ val |= 1; /* AXI buffer2 */ ++ iowrite32(val, priv->base + MCFE_SLOUTBUF2_REG(slot)); ++ /* set slot mode */ ++ val = ioread32(priv->base + MCFE_SLM0_REG); ++ val &= ~(0xff << (slot * 8)); ++ val |= (slot_mode << (slot * 8)); ++ iowrite32(val, priv->base + MCFE_SLM0_REG); ++ iowrite32(0, priv->base + MCFE_SLM4_REG); ++} ++ ++static void rcar_isp_setup_pipeline(struct rcar_isp_priv *priv, int axi_colourspace, int axi_num, int is_yuv) ++{ ++ u32 val; ++ ++ /* Input formatter */ ++#if 0 ++ iowrite32(INF_MI_LINEAR | INF_MI_8BITS | INF_MI_MSB, priv->base + INF_MI_REG); ++#else ++ val = ioread32(priv->base + INF_MI_REG); ++ val &= ~(0x70007); ++ iowrite32(val, priv->base + INF_MI_REG); ++#endif ++ /* pipe input formatter, demosaic, output formatter */ ++ val = ioread32(priv->base + PIPE_BP_REG); ++ val &= ~(PIPE_BP_DEMOSAIC | PIPE_BP_OUTF | PIPE_BP_INF); ++ iowrite32(val, priv->base + PIPE_BP_REG); ++ /* pipe output formatter RGB2YUV */ ++ if (is_yuv) ++ iowrite32(~OUTF_BP_RGB2YUV, priv->base + OUTF_BP_REG); ++ ++ /* AXI output colourspace */ ++ val = ioread32(priv->base + AXIOUT_MS_REG); ++ val &= ~(0xff << axi_num); ++ val |= (axi_colourspace << axi_num); ++ iowrite32(val, priv->base + AXIOUT_MS_REG); ++} ++ ++static void rcar_isp_setup_top(struct rcar_isp_priv *priv, int bayer_pattern) ++{ ++ struct rcar_isp_cam *cam = priv->ici.icd->host_priv; ++ ++ /* Top setup */ ++ iowrite32(cam->out_width, priv->base + TOP_AW_REG); ++ iowrite32(cam->out_height, priv->base + TOP_AH_REG); ++ iowrite32(TOP_CFA_RGGB | bayer_pattern, priv->base + TOP_RGGB_REG); ++} ++ ++static void rcar_isp_setup_out_buffer(struct rcar_isp_priv *priv, int slot, dma_addr_t phys_addr_top) ++{ ++ struct soc_camera_device *icd = priv->ici.icd; ++ struct rcar_isp_cam *cam = icd->host_priv; ++ ++ /* invalidate out_buffer */ ++ iowrite32(0, priv->base + OBUF_BV_REG(slot)); ++ /* setup phys addr */ ++ iowrite32(phys_addr_top, priv->base + OBUF_BA_REG(slot)); ++ /* setup frame params */ ++ iowrite32(cam->out_width * (cam->out_bpp / 8), priv->base + OBUF_LO_REG(slot)); ++ iowrite32(cam->out_width, priv->base + OBUF_AW_REG(slot)); ++ iowrite32(cam->out_height, priv->base + OBUF_AH_REG(slot)); ++ iowrite32(cam->out_height, priv->base + OBUF_HM_REG(slot)); ++ /* empty and validate out_buffer */ ++ iowrite32(0, priv->base + OBUF_ST_REG(slot)); ++ iowrite32((cam->out_bpp << 8) | 0x1, priv->base + OBUF_BV_REG(slot)); ++} ++ ++static int rcar_isp_setup(struct rcar_isp_priv *priv) ++{ ++ struct soc_camera_device *icd = priv->ici.icd; ++ int bayer_pattern, axi_colourspace, raw_bpp; ++ int slot = 0; ++ int inport = 0; ++ int is_yuv = 0; ++ ++ /* input interface */ ++ switch (icd->current_fmt->code) { ++ case MEDIA_BUS_FMT_SRGGB8_1X8: ++ case MEDIA_BUS_FMT_SBGGR8_1X8: ++ case MEDIA_BUS_FMT_SGRBG8_1X8: ++ raw_bpp = 8; ++ break; ++ case MEDIA_BUS_FMT_SRGGB12_1X12: ++ case MEDIA_BUS_FMT_SBGGR12_1X12: ++ case MEDIA_BUS_FMT_SGRBG12_1X12: ++ raw_bpp = 12; ++ break; ++ case MEDIA_BUS_FMT_SGRBG14_1X14: ++ raw_bpp = 14; ++ break; ++ case MEDIA_BUS_FMT_SRGGB16_1X16: ++ case MEDIA_BUS_FMT_SBGGR16_1X16: ++ case MEDIA_BUS_FMT_SGRBG16_1X16: ++ raw_bpp = 16; ++ break; ++ default: ++ goto e_format; ++ } ++ ++ switch (icd->current_fmt->code) { ++ case MEDIA_BUS_FMT_SRGGB8_1X8: ++ case MEDIA_BUS_FMT_SRGGB12_1X12: ++ case MEDIA_BUS_FMT_SRGGB16_1X16: ++ bayer_pattern = TOP_RGGB_RGrGbB; /* IMX390, AR0143 */ ++ break; ++ case MEDIA_BUS_FMT_SBGGR8_1X8: ++ case MEDIA_BUS_FMT_SBGGR12_1X12: ++ case MEDIA_BUS_FMT_SBGGR16_1X16: ++ bayer_pattern = TOP_RGGB_BGbGrR; /* OV2775, OX03A */ ++ break; ++ case MEDIA_BUS_FMT_SGRBG8_1X8: ++ case MEDIA_BUS_FMT_SGRBG12_1X12: ++ case MEDIA_BUS_FMT_SGRBG14_1X14: ++ case MEDIA_BUS_FMT_SGRBG16_1X16: ++ bayer_pattern = TOP_RGGB_GrRBGb; /* AR0132, AR0220 */ ++ break; ++ default: ++ goto e_format; ++ } ++ ++ /* output format */ ++ switch (icd->current_fmt->host_fmt->fourcc) { ++ case V4L2_PIX_FMT_NV16: ++ axi_colourspace = AXIOUT_MS_YUV_UV8; ++ is_yuv = 1; ++ break; ++ case V4L2_PIX_FMT_XBGR32: ++ axi_colourspace = AXIOUT_MS_RGB888; ++ axi_colourspace |= AXIOUT_MSB_ALIGN; ++ break; ++ case V4L2_PIX_FMT_SBGGR8: ++ axi_colourspace = AXIOUT_MS_RAW8; ++ break; ++ case V4L2_PIX_FMT_SBGGR16: ++ axi_colourspace = AXIOUT_MS_RAW16; ++ axi_colourspace |= AXIOUT_MSB_ALIGN; ++ break; ++ default: ++ goto e_format; ++ } ++ ++ rcar_isp_setup_inputs(priv, inport, raw_bpp); ++ rcar_isp_setup_mcfe(priv, MCFE_SLM0_PASSTHR(slot)); ++ rcar_isp_setup_top(priv, bayer_pattern); ++ rcar_isp_setup_pipeline(priv, axi_colourspace, 0, is_yuv); ++ ++ return 0; ++ ++e_format: ++ dev_warn(icd->parent, "Invalid fourcc format (0x%x)\n", ++ icd->current_fmt->host_fmt->fourcc); ++ return -EINVAL; ++} ++ ++static int rcar_isp_get_free_hw_slot(struct rcar_isp_priv *priv) ++{ ++ int slot; ++ ++ for (slot = 0; slot < priv->nr_hw_slots; slot++) ++ if (priv->queue_buf[slot] == NULL) ++ return slot; ++ ++ return -1; ++} ++ ++static int rcar_isp_hw_ready(struct rcar_isp_priv *priv) ++{ ++ /* Ensure all HW slots are filled */ ++ return rcar_isp_get_free_hw_slot(priv) < 0 ? 1 : 0; ++} ++ ++/* Moves a buffer from the queue to the HW slot */ ++static int rcar_isp_fill_hw_slot(struct rcar_isp_priv *priv) ++{ ++ struct rcar_isp_cam *cam = priv->ici.icd->host_priv; ++ struct vb2_v4l2_buffer *vbuf; ++ dma_addr_t phys_addr_top; ++ int slot; ++ ++ if (list_empty(&priv->capture)) ++ return 0; ++ ++ /* Find a free HW slot */ ++ slot = rcar_isp_get_free_hw_slot(priv); ++ if (slot < 0) ++ return 0; ++ ++ vbuf = &list_entry(priv->capture.next, struct rcar_isp_buffer, list)->vb; ++ list_del_init(to_buf_list(vbuf)); ++ priv->queue_buf[slot] = vbuf; ++ phys_addr_top = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0); ++#if 1 ++ rcar_isp_setup_out_buffer(priv, slot, phys_addr_top); ++#else ++ rcar_isp_setup_out_buffer(priv, 0, phys_addr_top); // Y ++ rcar_isp_setup_out_buffer(priv, 1, phys_addr_top + cam->out_width * cam->out_height); // UV ++#endif ++ return 1; ++} ++ ++static int rcar_isp_videobuf_setup(struct vb2_queue *vq, unsigned int *count, ++ unsigned int *num_planes, ++ unsigned int sizes[], struct device *alloc_devs[]) ++{ ++ struct soc_camera_device *icd = soc_camera_from_vb2q(vq); ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_isp_priv *priv = ici->priv; ++ ++ if (!vq->num_buffers) ++ priv->sequence = 0; ++ ++ if (!*count) ++ *count = 2; ++ priv->vb_count = *count; ++ ++ /* Number of hardware slots */ ++ priv->nr_hw_slots = MAX_BUFFER_NUM; ++ ++ if (*num_planes) ++ return sizes[0] < icd->sizeimage ? -EINVAL : 0; ++ ++ sizes[0] = icd->sizeimage; ++ *num_planes = 1; ++ ++ dev_dbg(icd->parent, "count=%d, size=%u\n", *count, sizes[0]); ++ ++ return 0; ++} ++ ++static void rcar_isp_videobuf_queue(struct vb2_buffer *vb) ++{ ++ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); ++ struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_isp_priv *priv = ici->priv; ++ unsigned long size; ++ ++ size = icd->sizeimage; ++ ++ if (vb2_plane_size(vb, 0) < size) { ++ dev_err(icd->parent, "Buffer #%d too small (%lu < %lu)\n", ++ vb->index, vb2_plane_size(vb, 0), size); ++ goto error; ++ } ++ ++ vb2_set_plane_payload(vb, 0, size); ++ ++ dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, ++ vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); ++ ++ spin_lock_irq(&priv->lock); ++ ++ list_add_tail(to_buf_list(vbuf), &priv->capture); ++ rcar_isp_fill_hw_slot(priv); ++ ++ /* If we weren't running, and have enough buffers, start capturing! */ ++ if (priv->state != RUNNING && rcar_isp_hw_ready(priv)) { ++ if (rcar_isp_setup(priv)) { ++ /* Submit error */ ++ list_del_init(to_buf_list(vbuf)); ++ spin_unlock_irq(&priv->lock); ++ goto error; ++ } ++ priv->state = RUNNING; ++ rcar_isp_start(priv); ++ } ++ ++ spin_unlock_irq(&priv->lock); ++ ++ return; ++ ++error: ++ vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); ++} ++ ++static void rcar_isp_stop_streaming(struct vb2_queue *vq) ++{ ++ struct soc_camera_device *icd = soc_camera_from_vb2q(vq); ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_isp_priv *priv = ici->priv; ++ struct list_head *buf_head, *tmp; ++ int i; ++ ++ spin_lock_irq(&priv->lock); ++ ++ if (priv->state == RUNNING) { ++ rcar_isp_stop(priv); ++ priv->state = STOPPED; ++ } ++ ++ for (i = 0; i < MAX_BUFFER_NUM; i++) { ++ /* invalidate and empty out_buffer */ ++ iowrite32(0, priv->base + OBUF_BV_REG(i)); ++ iowrite32(0, priv->base + OBUF_ST_REG(i)); ++ if (priv->queue_buf[i]) { ++ vb2_buffer_done(&priv->queue_buf[i]->vb2_buf, ++ VB2_BUF_STATE_ERROR); ++ priv->queue_buf[i] = NULL; ++ } ++ } ++ ++ list_for_each_safe(buf_head, tmp, &priv->capture) { ++ vb2_buffer_done(&list_entry(buf_head, ++ struct rcar_isp_buffer, list)->vb.vb2_buf, ++ VB2_BUF_STATE_ERROR); ++ list_del_init(buf_head); ++ } ++ ++ spin_unlock_irq(&priv->lock); ++} ++ ++static const struct vb2_ops rcar_isp_vb2_ops = { ++ .queue_setup = rcar_isp_videobuf_setup, ++ .buf_queue = rcar_isp_videobuf_queue, ++ .stop_streaming = rcar_isp_stop_streaming, ++ .wait_prepare = vb2_ops_wait_prepare, ++ .wait_finish = vb2_ops_wait_finish, ++}; ++ ++static irqreturn_t rcar_isp_irq(int irq, void *data) ++{ ++ struct rcar_isp_priv *priv = data; ++ u32 int_status; ++ int slot; ++ unsigned int handled = 0; ++ ++ spin_lock(&priv->lock); ++ ++ int_status = ioread32(priv->base + INT_FES_REG); ++ if (!int_status) ++ goto done; ++ ++ /* ack interrupts */ ++ iowrite32(int_status, priv->base + INT_FEC_REG); ++ /* enable frame end interrupt */ ++ iowrite32(BIT(15), priv->base + INT_FEM_REG); ++ handled = 1; ++ ++ if (priv->state == STOPPED) ++ goto done; ++ ++ /* out_buffer not filled */ ++ slot = ioread32(priv->base + MCFE_OWL_REG); ++ if (slot == 0x3f3f3f3f) ++ goto done; ++ slot &= 0xff; // tnis is for 1 camera support ++ ++ if (!list_empty(&priv->capture)) { ++ priv->queue_buf[slot]->field = priv->field; ++ priv->queue_buf[slot]->sequence = priv->sequence++; ++ priv->queue_buf[slot]->vb2_buf.timestamp = ktime_get_ns(); ++ vb2_buffer_done(&priv->queue_buf[slot]->vb2_buf, VB2_BUF_STATE_DONE); ++ priv->queue_buf[slot] = NULL; ++ ++ rcar_isp_fill_hw_slot(priv); ++ } else { ++ rcar_isp_stop(priv); ++ priv->state = STOPPED; ++ } ++ ++done: ++ spin_unlock(&priv->lock); ++ ++ return IRQ_RETVAL(handled); ++} ++ ++static struct v4l2_subdev *find_csi2(struct rcar_isp_priv *pcdev) ++{ ++ struct v4l2_subdev *sd; ++ char name[] = "rcar_csi2"; ++ ++ v4l2_device_for_each_subdev(sd, &pcdev->ici.v4l2_dev) { ++ if (!strncmp(name, sd->name, sizeof(name) - 1)) { ++ pcdev->csi2_sd = sd; ++ return sd; ++ } ++ } ++ ++ return NULL; ++} ++ ++static struct v4l2_subdev *find_deser(struct rcar_isp_priv *pcdev) ++{ ++ struct v4l2_subdev *sd; ++ char name[] = "max9286"; ++ char name2[] = "ti9x4"; ++ ++ v4l2_device_for_each_subdev(sd, &pcdev->ici.v4l2_dev) { ++ if (!strncmp(name, sd->name, sizeof(name) - 1)) { ++ pcdev->deser_sd = sd; ++ return sd; ++ } ++ if (!strncmp(name2, sd->name, sizeof(name2) - 1)) { ++ pcdev->deser_sd = sd; ++ return sd; ++ } ++ } ++ ++ return NULL; ++} ++ ++static int rcar_isp_add_device(struct soc_camera_device *icd) ++{ ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_isp_priv *priv = ici->priv; ++ int i; ++ ++ for (i = 0; i < MAX_BUFFER_NUM; i++) ++ priv->queue_buf[i] = NULL; ++ ++ pm_runtime_get_sync(ici->v4l2_dev.dev); ++ ++ if (priv->chip == RCAR_V3M || priv->chip == RCAR_V3H) { ++ struct v4l2_subdev *csi2_sd = find_csi2(priv); ++ struct v4l2_subdev *deser_sd = find_deser(priv); ++ int ret = 0; ++ ++ if (csi2_sd) { ++ csi2_sd->grp_id = soc_camera_grp_id(icd); ++ v4l2_set_subdev_hostdata(csi2_sd, icd); ++ ++ ret = v4l2_subdev_call(csi2_sd, core, s_power, 1); ++ priv->csi_sync = true; ++ ++ if (ret < 0 && ret != -EINVAL) ++ priv->csi_sync = false; ++ ++ if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) ++ return ret; ++ } ++ if (deser_sd) { ++ v4l2_set_subdev_hostdata(deser_sd, icd); ++ ++ ret = v4l2_subdev_call(deser_sd, core, s_power, 1); ++ priv->deser_sync = true; ++ ++ if (ret < 0 && ret != -EINVAL) ++ priv->deser_sync = false; ++ ++ if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) ++ return ret; ++ } ++ /* ++ * -ENODEV is special: ++ * either csi2_sd == NULL or the CSI-2 driver ++ * has not found this soc-camera device among its clients ++ */ ++ if (csi2_sd && ret == -ENODEV) ++ csi2_sd->grp_id = 0; ++ ++ dev_dbg(icd->parent, ++ "R-Car ISP/CSI-2 driver attached to camera %d\n", ++ icd->devnum); ++ ++ } else ++ dev_dbg(icd->parent, "R-Car ISP driver attached to camera %d\n", ++ icd->devnum); ++ ++ rcar_isp_open(priv); ++ ++ return 0; ++} ++ ++static void rcar_isp_remove_device(struct soc_camera_device *icd) ++{ ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_isp_priv *priv = ici->priv; ++ struct vb2_v4l2_buffer *vbuf; ++ struct v4l2_subdev *csi2_sd = find_csi2(priv); ++ struct v4l2_subdev *deser_sd = find_deser(priv); ++ int i; ++ ++ /* make sure active buffer is cancelled */ ++ spin_lock_irq(&priv->lock); ++ for (i = 0; i < MAX_BUFFER_NUM; i++) { ++ vbuf = priv->queue_buf[i]; ++ if (vbuf) { ++ list_del_init(to_buf_list(vbuf)); ++ vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_ERROR); ++ } ++ } ++ spin_unlock_irq(&priv->lock); ++ ++ rcar_isp_close(priv); ++ ++ pm_runtime_put(ici->v4l2_dev.dev); ++ ++ if ((csi2_sd) && (priv->csi_sync)) ++ v4l2_subdev_call(csi2_sd, core, s_power, 0); ++ if ((deser_sd) && (priv->deser_sync)) ++ v4l2_subdev_call(deser_sd, core, s_power, 0); ++ ++ dev_dbg(icd->parent, "R-Car ISP driver detached from camera %d\n", ++ icd->devnum); ++} ++ ++/* rect is guaranteed to not exceed the scaled camera rectangle */ ++static int rcar_isp_set_rect(struct soc_camera_device *icd) ++{ ++ struct rcar_isp_cam *cam = icd->host_priv; ++ unsigned int left_offset, top_offset; ++ struct v4l2_rect *cam_subrect = &cam->subrect; ++ ++ dev_dbg(icd->parent, "Crop %ux%u@%u:%u\n", ++ icd->user_width, icd->user_height, cam->isp_left, cam->isp_top); ++ ++ left_offset = cam->isp_left; ++ top_offset = cam->isp_top; ++ ++ dev_dbg(icd->parent, "Cam %ux%u@%u:%u\n", ++ cam->width, cam->height, cam->isp_left, cam->isp_top); ++ dev_dbg(icd->parent, "Cam subrect %ux%u@%u:%u\n", ++ cam_subrect->width, cam_subrect->height, ++ cam_subrect->left, cam_subrect->top); ++ ++ return 0; ++} ++ ++#define ISP_MBUS_FLAGS (V4L2_MBUS_CSI2_LANES | \ ++ V4L2_MBUS_CSI2_CHANNELS | \ ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK | \ ++ V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK) ++ ++static int rcar_isp_set_bus_param(struct soc_camera_device *icd) ++{ ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ struct v4l2_mbus_config cfg; ++ unsigned long common_flags; ++ int ret; ++ ++ ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg); ++ if (!ret) { ++ common_flags = soc_mbus_config_compatible(&cfg, ISP_MBUS_FLAGS); ++ if (!common_flags) { ++ dev_warn(icd->parent, ++ "MBUS flags incompatible: camera 0x%x, host 0x%x\n", ++ cfg.flags, ISP_MBUS_FLAGS); ++ return -EINVAL; ++ } ++ } else if (ret != -ENOIOCTLCMD) { ++ return ret; ++ } else { ++ common_flags = ISP_MBUS_FLAGS; ++ } ++ ++ return 0; ++} ++ ++static int rcar_isp_try_bus_param(struct soc_camera_device *icd, ++ unsigned char buswidth) ++{ ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ struct v4l2_mbus_config cfg; ++ int ret; ++ ++ ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg); ++ if (ret == -ENOIOCTLCMD) ++ return 0; ++ else if (ret) ++ return ret; ++ ++ /* check is there common mbus flags */ ++ ret = soc_mbus_config_compatible(&cfg, ISP_MBUS_FLAGS); ++ if (ret) ++ return 0; ++ ++ dev_warn(icd->parent, ++ "MBUS flags incompatible: camera 0x%x, host 0x%x\n", ++ cfg.flags, ISP_MBUS_FLAGS); ++ ++ return -EINVAL; ++} ++ ++static bool rcar_isp_packing_supported(const struct soc_mbus_pixelfmt *fmt) ++{ ++ return fmt->packing == SOC_MBUS_PACKING_NONE || ++ (fmt->bits_per_sample > 8 && ++ fmt->packing == SOC_MBUS_PACKING_EXTEND16); ++} ++ ++static const struct soc_mbus_pixelfmt rcar_isp_formats[] = { ++ { ++ .fourcc = V4L2_PIX_FMT_NV16, ++ .name = "NV16", ++ .bits_per_sample = 16, ++ .packing = SOC_MBUS_PACKING_NONE, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_XBGR32, ++ .name = "RGBX8888", ++ .bits_per_sample = 32, ++ .packing = SOC_MBUS_PACKING_NONE, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_ABGR32, ++ .name = "ARGB8888", ++ .bits_per_sample = 32, ++ .packing = SOC_MBUS_PACKING_NONE, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SBGGR8, ++ .name = "Bayer 8 BGGR", ++ .bits_per_sample = 8, ++ .packing = SOC_MBUS_PACKING_NONE, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SBGGR16, ++ .name = "Bayer 16 BGGR", ++ .bits_per_sample = 16, ++ .packing = SOC_MBUS_PACKING_NONE, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, ++}; ++ ++static int rcar_isp_get_formats(struct soc_camera_device *icd, unsigned int idx, ++ struct soc_camera_format_xlate *xlate) ++{ ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ struct device *dev = icd->parent; ++ int ret, k, n; ++ int formats = 0; ++ struct rcar_isp_cam *cam; ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_isp_priv *priv = ici->priv; ++ struct v4l2_subdev_mbus_code_enum code = { ++ .which = V4L2_SUBDEV_FORMAT_ACTIVE, ++ .index = idx, ++ }; ++ const struct soc_mbus_pixelfmt *fmt; ++ ++ ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code); ++ if (ret < 0) ++ return 0; ++ ++ fmt = soc_mbus_get_fmtdesc(code.code); ++ if (!fmt) { ++ dev_warn(dev, "unsupported format code #%u: %d\n", idx, code.code); ++ return 0; ++ } ++ ++ ret = rcar_isp_try_bus_param(icd, fmt->bits_per_sample); ++ if (ret < 0) ++ return 0; ++ ++ if (!icd->host_priv) { ++ struct v4l2_subdev_format fmt = { ++ .which = V4L2_SUBDEV_FORMAT_ACTIVE, ++ }; ++ struct v4l2_mbus_framefmt *mf = &fmt.format; ++ struct v4l2_rect rect; ++ struct device *dev = icd->parent; ++ int shift; ++ ++ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt); ++ if (ret < 0) ++ return ret; ++ ++ /* Cache current client geometry */ ++ ret = soc_camera_client_g_rect(sd, &rect); ++ if (ret == -ENOIOCTLCMD) { ++ /* Sensor driver doesn't support cropping */ ++ rect.left = 0; ++ rect.top = 0; ++ rect.width = mf->width; ++ rect.height = mf->height; ++ } else if (ret < 0) { ++ return ret; ++ } ++ ++ /* ++ * If sensor proposes too large format then try smaller ones: ++ * 1280x960, 640x480, 320x240 ++ */ ++ for (shift = 0; shift < 3; shift++) { ++ if (mf->width <= priv->max_width && ++ mf->height <= priv->max_height) ++ break; ++ ++ mf->width = 1280 >> shift; ++ mf->height = 960 >> shift; ++ ret = v4l2_device_call_until_err(sd->v4l2_dev, ++ soc_camera_grp_id(icd), ++ pad, set_fmt, NULL, ++ &fmt); ++ if (ret < 0) ++ return ret; ++ } ++ ++ if (shift == 3) { ++ dev_err(dev, ++ "Failed to configure the client below %ux%u\n", ++ mf->width, mf->height); ++ return -EIO; ++ } ++ ++ dev_dbg(dev, "camera fmt %ux%u\n", mf->width, mf->height); ++ ++ cam = kzalloc(sizeof(*cam), GFP_KERNEL); ++ if (!cam) ++ return -ENOMEM; ++ /* ++ * We are called with current camera crop, ++ * initialise subrect with it ++ */ ++ cam->rect = rect; ++ cam->subrect = rect; ++ cam->width = mf->width; ++ cam->height = mf->height; ++ cam->out_width = mf->width; ++ cam->out_height = mf->height; ++ ++ icd->host_priv = cam; ++ } else { ++ cam = icd->host_priv; ++ } ++ ++ /* Beginning of a pass */ ++ if (!idx) ++ cam->extra_fmt = NULL; ++ ++ switch (code.code) { ++ case MEDIA_BUS_FMT_SBGGR8_1X8: ++ case MEDIA_BUS_FMT_SBGGR12_1X12: ++ case MEDIA_BUS_FMT_SBGGR16_1X16: ++ case MEDIA_BUS_FMT_SRGGB8_1X8: ++ case MEDIA_BUS_FMT_SRGGB12_1X12: ++ case MEDIA_BUS_FMT_SRGGB16_1X16: ++ case MEDIA_BUS_FMT_SGRBG8_1X8: ++ case MEDIA_BUS_FMT_SGRBG12_1X12: ++ case MEDIA_BUS_FMT_SGRBG14_1X14: ++ case MEDIA_BUS_FMT_SGRBG16_1X16: ++ if (cam->extra_fmt) ++ break; ++ ++ /* Add all our formats that can be generated by ISP */ ++ cam->extra_fmt = rcar_isp_formats; ++ ++ n = ARRAY_SIZE(rcar_isp_formats); ++ formats += n; ++ for (k = 0; xlate && k < n; k++, xlate++) { ++ xlate->host_fmt = &rcar_isp_formats[k]; ++ xlate->code = code.code; ++ dev_dbg(dev, "Providing format %s using code %d\n", ++ rcar_isp_formats[k].name, code.code); ++ } ++ break; ++ default: ++ if (!rcar_isp_packing_supported(fmt)) ++ return 0; ++ ++ dev_dbg(dev, "Providing format %s in pass-through mode\n", ++ fmt->name); ++ break; ++ } ++ ++ /* Generic pass-through */ ++ formats++; ++ if (xlate) { ++ xlate->host_fmt = fmt; ++ xlate->code = code.code; ++ xlate++; ++ } ++ ++ return formats; ++} ++ ++static void rcar_isp_put_formats(struct soc_camera_device *icd) ++{ ++ kfree(icd->host_priv); ++ icd->host_priv = NULL; ++} ++ ++static int rcar_isp_set_selection(struct soc_camera_device *icd, ++ struct v4l2_selection *sel) ++{ ++ const struct v4l2_rect *rect = &sel->r; ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_isp_priv *priv = ici->priv; ++ struct v4l2_selection cam_sel; ++ struct rcar_isp_cam *cam = icd->host_priv; ++ struct v4l2_rect *cam_rect = &cam_sel.r; ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ struct device *dev = icd->parent; ++ struct v4l2_subdev_format fmt = { ++ .which = V4L2_SUBDEV_FORMAT_ACTIVE, ++ }; ++ struct v4l2_mbus_framefmt *mf = &fmt.format; ++ int ret; ++ ++ dev_dbg(dev, "S_SELECTION(%ux%u@%u:%u)\n", rect->width, rect->height, ++ rect->left, rect->top); ++ ++ /* Apply iterative camera S_SELECTION for new input window. */ ++ ret = soc_camera_client_s_selection(sd, sel, &cam_sel, ++ &cam->rect, &cam->subrect); ++ if (ret < 0) ++ return ret; ++ ++ dev_dbg(dev, "camera cropped to %ux%u@%u:%u\n", ++ cam_rect->width, cam_rect->height, ++ cam_rect->left, cam_rect->top); ++ ++ /* On success cam_crop contains current camera crop */ ++ ++ /* Retrieve camera output window */ ++ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt); ++ if (ret < 0) ++ return ret; ++ ++ if (mf->width > priv->max_width || mf->height > priv->max_height) ++ return -EINVAL; ++ ++ /* Cache camera output window */ ++ cam->width = mf->width; ++ cam->height = mf->height; ++ ++ cam->isp_left = rect->left; ++ cam->isp_top = rect->top; ++ ++ /* Use ISP cropping to crop to the new window. */ ++ ret = rcar_isp_set_rect(icd); ++ if (ret < 0) ++ return ret; ++ ++ dev_dbg(dev, "ISP cropped to %ux%u@%u:%u\n", ++ icd->user_width, icd->user_height, ++ cam->isp_left, cam->isp_top); ++ ++ /* Even if only camera cropping succeeded */ ++ return ret; ++} ++ ++static int rcar_isp_get_selection(struct soc_camera_device *icd, ++ struct v4l2_selection *sel) ++{ ++ struct rcar_isp_cam *cam = icd->host_priv; ++ ++ sel->r = cam->subrect; ++ ++ return 0; ++} ++ ++static int rcar_isp_set_fmt(struct soc_camera_device *icd, ++ struct v4l2_format *f) ++{ ++ struct rcar_isp_cam *cam = icd->host_priv; ++ struct v4l2_pix_format *pix = &f->fmt.pix; ++ struct v4l2_mbus_framefmt mf; ++ struct device *dev = icd->parent; ++ __u32 pixfmt = pix->pixelformat; ++ const struct soc_camera_format_xlate *xlate; ++ unsigned int isp_sub_width = 0, isp_sub_height = 0; ++ int ret; ++ bool can_scale = false; ++ ++ dev_dbg(dev, "S_FMT(pix=0x%x, %ux%u)\n", pixfmt, pix->width, pix->height); ++ ++ xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); ++ if (!xlate) { ++ dev_warn(dev, "Format %x not found\n", pixfmt); ++ return -EINVAL; ++ } ++ /* Calculate client output geometry */ ++ soc_camera_calc_client_output(icd, &cam->rect, &cam->subrect, pix, &mf, 12); ++ mf.field = pix->field; ++ mf.colorspace = pix->colorspace; ++ mf.code = xlate->code; ++ ++ switch (pixfmt) { ++ case V4L2_PIX_FMT_XBGR32: ++ case V4L2_PIX_FMT_XRGB32: ++ cam->out_bpp = 32; ++ break; ++ case V4L2_PIX_FMT_NV16: ++ case V4L2_PIX_FMT_SBGGR16: ++ cam->out_bpp = 16; ++ break; ++ case V4L2_PIX_FMT_SBGGR8: ++ cam->out_bpp = 8; ++ break; ++ default: ++ break; ++ } ++ ++ dev_dbg(dev, "request camera output %ux%u\n", mf.width, mf.height); ++ ++ ret = soc_camera_client_scale(icd, &cam->rect, &cam->subrect, ++ &mf, &isp_sub_width, &isp_sub_height, ++ can_scale, 12); ++ ++ /* Done with the camera. Now see if we can improve the result */ ++ dev_dbg(dev, "Camera %d fmt %ux%u, requested %ux%u\n", ++ ret, mf.width, mf.height, pix->width, pix->height); ++ ++ if (ret == -ENOIOCTLCMD) ++ dev_dbg(dev, "Sensor doesn't support scaling\n"); ++ else if (ret < 0) ++ return ret; ++ ++ if (mf.code != xlate->code) ++ return -EINVAL; ++ ++ /* Prepare ISP crop */ ++ cam->width = mf.width; ++ cam->height = mf.height; ++ ++ /* We cannot scale up */ ++ if (pix->width > isp_sub_width) ++ isp_sub_width = pix->width; ++ ++ if (pix->height > isp_sub_height) ++ isp_sub_height = pix->height; ++ ++ pix->colorspace = mf.colorspace; ++ ++ if (!can_scale) { ++ pix->width = isp_sub_width; ++ pix->height = isp_sub_height; ++ } ++ ++ dev_dbg(dev, "W: %u : %u, H: %u : %u\n", ++ isp_sub_width, pix->width, isp_sub_height, pix->height); ++ ++ cam->out_width = pix->width; ++ cam->out_height = pix->height; ++ ++ icd->current_fmt = xlate; ++ ++ return 0; ++} ++ ++static int rcar_isp_try_fmt(struct soc_camera_device *icd, ++ struct v4l2_format *f) ++{ ++ const struct soc_camera_format_xlate *xlate; ++ struct v4l2_pix_format *pix = &f->fmt.pix; ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ struct v4l2_subdev_pad_config pad_cfg; ++ struct v4l2_subdev_format format = { ++ .which = V4L2_SUBDEV_FORMAT_TRY, ++ }; ++ struct v4l2_mbus_framefmt *mf = &format.format; ++ __u32 pixfmt = pix->pixelformat; ++ int width, height; ++ int ret; ++ ++ xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); ++ if (!xlate) { ++ xlate = icd->current_fmt; ++ dev_dbg(icd->parent, "Format %x not found, keeping %x\n", ++ pixfmt, xlate->host_fmt->fourcc); ++ pixfmt = xlate->host_fmt->fourcc; ++ pix->pixelformat = pixfmt; ++ pix->colorspace = icd->colorspace; ++ } ++ ++ width = pix->width; ++ height = pix->height; ++ ++ /* let soc-camera calculate these values */ ++ pix->bytesperline = 0; ++ pix->sizeimage = 0; ++ ++ /* limit to sensor capabilities */ ++ mf->width = pix->width; ++ mf->height = pix->height; ++ mf->field = pix->field; ++ mf->code = xlate->code; ++ mf->colorspace = pix->colorspace; ++ ++ ret = v4l2_device_call_until_err(sd->v4l2_dev, soc_camera_grp_id(icd), ++ pad, set_fmt, &pad_cfg, &format); ++ if (ret < 0) ++ return ret; ++ ++ pix->field = mf->field; ++ pix->colorspace = mf->colorspace; ++ ++ return ret; ++} ++ ++static unsigned int rcar_isp_poll(struct file *file, poll_table *pt) ++{ ++ struct soc_camera_device *icd = file->private_data; ++ ++ return vb2_poll(&icd->vb2_vidq, file, pt); ++} ++ ++static int rcar_isp_querycap(struct soc_camera_host *ici, ++ struct v4l2_capability *cap) ++{ ++ strlcpy(cap->card, "R_Car_ISP", sizeof(cap->card)); ++ cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; ++ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; ++ snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s%d", DRV_NAME, ici->nr); ++ ++ return 0; ++} ++ ++static int rcar_isp_init_videobuf2(struct vb2_queue *vq, ++ struct soc_camera_device *icd) ++{ ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ ++ vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; ++ vq->drv_priv = icd; ++ vq->ops = &rcar_isp_vb2_ops; ++ vq->mem_ops = &vb2_dma_contig_memops; ++ vq->buf_struct_size = sizeof(struct rcar_isp_buffer); ++ vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; ++ vq->lock = &ici->host_lock; ++ vq->dev = ici->v4l2_dev.dev; ++ ++ return vb2_queue_init(vq); ++} ++ ++static int rcar_isp_get_edid(struct soc_camera_device *icd, ++ struct v4l2_edid *edid) ++{ ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ int ret; ++ ++ ret = v4l2_subdev_call(sd, pad, get_edid, edid); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int rcar_isp_get_register(struct soc_camera_device *icd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_isp_priv *priv = ici->priv; ++ ++ if (reg->reg > 0x1ffff) ++ return -ERANGE; ++ ++ reg->val = ioread32(priv->base + reg->reg); ++// reg->val = ioread32(priv->interface.base + reg->reg); ++// reg->val = ioread32(slot_ctx[0].vaddr + reg->reg); ++ reg->size = sizeof(u32); ++ ++ return 0; ++} ++ ++static int rcar_isp_set_register(struct soc_camera_device *icd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_isp_priv *priv = ici->priv; ++ ++ if (reg->reg > 0x1ffff) ++ return -ERANGE; ++ iowrite32(reg->val, priv->base + reg->reg); ++// iowrite32(reg->val, priv->interface.base + reg->reg); ++// iowrite32(reg->val,slot_ctx[0].vaddr + reg->reg); ++ ++ return 0; ++} ++#endif ++ ++static struct soc_camera_host_ops rcar_isp_host_ops = { ++ .owner = THIS_MODULE, ++ .add = rcar_isp_add_device, ++ .remove = rcar_isp_remove_device, ++ .get_formats = rcar_isp_get_formats, ++ .put_formats = rcar_isp_put_formats, ++ .get_selection = rcar_isp_get_selection, ++ .set_selection = rcar_isp_set_selection, ++ .try_fmt = rcar_isp_try_fmt, ++ .set_fmt = rcar_isp_set_fmt, ++ .poll = rcar_isp_poll, ++ .querycap = rcar_isp_querycap, ++ .set_bus_param = rcar_isp_set_bus_param, ++ .init_videobuf2 = rcar_isp_init_videobuf2, ++ .get_edid = rcar_isp_get_edid, ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .get_register = rcar_isp_get_register, ++ .set_register = rcar_isp_set_register, ++#endif ++}; ++ ++#ifdef CONFIG_OF ++static const struct of_device_id rcar_isp_of_table[] = { ++ { .compatible = "renesas,isp-r8a77980", .data = (void *)RCAR_V3H }, ++ { .compatible = "renesas,isp-r8a77970", .data = (void *)RCAR_V3M }, ++ { .compatible = "renesas,rcar-gen3-isp", .data = (void *)RCAR_GEN3 }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, rcar_isp_of_table); ++#endif ++ ++#define MAP_MAX_NUM 128 ++static DECLARE_BITMAP(device_map, MAP_MAX_NUM); ++static DEFINE_MUTEX(list_lock); ++ ++static int rcar_isp_dyn_pdev(struct soc_camera_desc *sdesc, ++ struct rcar_isp_async_client *sasc) ++{ ++ struct platform_device *pdev; ++ int ret, i; ++ ++ mutex_lock(&list_lock); ++ i = find_first_zero_bit(device_map, MAP_MAX_NUM); ++ if (i < MAP_MAX_NUM) ++ set_bit(i, device_map); ++ mutex_unlock(&list_lock); ++ if (i >= MAP_MAX_NUM) ++ return -ENOMEM; ++ ++ pdev = platform_device_alloc("soc-camera-pdrv", ((2 * i) + 1)); ++ if (!pdev) ++ return -ENOMEM; ++ ++ ret = platform_device_add_data(pdev, sdesc, sizeof(*sdesc)); ++ if (ret < 0) { ++ platform_device_put(pdev); ++ return ret; ++ } ++ ++ sasc->pdev = pdev; ++ ++ return 0; ++} ++ ++static int rcar_isp_async_bound(struct v4l2_async_notifier *notifier, ++ struct v4l2_subdev *sd, ++ struct v4l2_async_subdev *asd) ++{ ++ return 0; ++} ++ ++static void rcar_isp_async_unbind(struct v4l2_async_notifier *notifier, ++ struct v4l2_subdev *sd, ++ struct v4l2_async_subdev *asd) ++{ ++} ++ ++static int rcar_isp_async_probe(struct soc_camera_host *ici, ++ struct soc_camera_device *icd) ++{ ++ struct soc_camera_desc *sdesc = to_soc_camera_desc(icd); ++ struct soc_camera_host_desc *shd = &sdesc->host_desc; ++ struct device *control = NULL; ++ int ret; ++ ++ ret = v4l2_ctrl_handler_init(&icd->ctrl_handler, 16); ++ if (ret < 0) ++ return ret; ++ ++ if (shd->module_name) ++ ret = request_module(shd->module_name); ++ ++ ret = shd->add_device(icd); ++ ++ control = to_soc_camera_control(icd); ++ if (!control || !control->driver || !dev_get_drvdata(control) || ++ !try_module_get(control->driver->owner)) { ++ shd->del_device(icd); ++ ret = -ENODEV; ++ } ++ ++ return ret; ++} ++ ++static int rcar_isp_async_complete(struct v4l2_async_notifier *notifier) ++{ ++ struct rcar_isp_async_client *sasc = container_of(notifier, ++ struct rcar_isp_async_client, notifier); ++ struct soc_camera_device *icd = platform_get_drvdata(sasc->pdev); ++ ++ if (to_soc_camera_control(icd)) { ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ int ret; ++ ++ mutex_lock(&list_lock); ++ ret = rcar_isp_async_probe(ici, icd); ++ mutex_unlock(&list_lock); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static struct soc_camera_device *rcar_isp_add_pdev(struct rcar_isp_async_client *sasc) ++{ ++ struct platform_device *pdev = sasc->pdev; ++ int ret; ++ ++ ret = platform_device_add(pdev); ++ ++ if (ret < 0 || !pdev->dev.driver) ++ return NULL; ++ ++ return platform_get_drvdata(pdev); ++} ++ ++static const struct v4l2_async_notifier_operations rcar_isp_notifier_ops = { ++ .bound = rcar_isp_async_bound, ++ .unbind = rcar_isp_async_unbind, ++ .complete = rcar_isp_async_complete, ++}; ++ ++static int rcar_isp_soc_of_bind(struct rcar_isp_priv *priv, ++ struct soc_camera_host *ici, ++ struct device_node *ep, ++ struct device_node *remote) ++{ ++ struct soc_camera_device *icd; ++ struct soc_camera_desc sdesc = {.host_desc.bus_id = ici->nr,}; ++ struct rcar_isp_async_client *sasc; ++ struct soc_of_info *info; ++ struct i2c_client *client; ++ char clk_name[V4L2_SUBDEV_NAME_SIZE]; ++ int ret; ++ ++ /* allocate a new subdev and add match info to it */ ++ info = devm_kzalloc(ici->v4l2_dev.dev, sizeof(struct soc_of_info), ++ GFP_KERNEL); ++ if (!info) ++ return -ENOMEM; ++ ++ info->sasd.asd.match.fwnode.fwnode = of_fwnode_handle(remote); ++ info->sasd.asd.match_type = V4L2_ASYNC_MATCH_FWNODE; ++ info->subdev = &info->sasd.asd; ++ ++ /* Or shall this be managed by the soc-camera device? */ ++ sasc = &info->sasc; ++ ++ ret = rcar_isp_dyn_pdev(&sdesc, sasc); ++ if (ret < 0) ++ goto eallocpdev; ++ ++ sasc->sensor = &info->sasd.asd; ++ ++ icd = rcar_isp_add_pdev(sasc); ++ if (!icd) { ++ ret = -ENOMEM; ++ goto eaddpdev; ++ } ++ ++ sasc->notifier.subdevs = &info->subdev; ++ sasc->notifier.num_subdevs = 1; ++ sasc->notifier.ops = &rcar_isp_notifier_ops; ++ ++ priv->async_client = sasc; ++ ++ client = of_find_i2c_device_by_node(remote); ++ ++ if (client) ++ snprintf(clk_name, sizeof(clk_name), "%d-%04x", ++ client->adapter->nr, client->addr); ++ else ++ snprintf(clk_name, sizeof(clk_name), "of-%s", ++ of_node_full_name(remote)); ++ ++ ret = v4l2_async_notifier_register(&ici->v4l2_dev, &sasc->notifier); ++ if (!ret) ++ return 0; ++ ++ platform_device_del(sasc->pdev); ++eaddpdev: ++ platform_device_put(sasc->pdev); ++eallocpdev: ++ devm_kfree(ici->v4l2_dev.dev, info); ++ dev_err(ici->v4l2_dev.dev, "group probe failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int rcar_isp_probe(struct platform_device *pdev) ++{ ++ const struct of_device_id *match = NULL; ++ struct rcar_isp_priv *priv; ++ struct v4l2_fwnode_endpoint ep; ++ struct device_node *np; ++ struct resource *mem; ++ int irq, ret; ++ const char *str; ++ unsigned int i; ++ struct device_node *epn = NULL, *ren = NULL; ++ struct device_node *csi2_ren = NULL, *max9286_ren = NULL, *ti9x4_ren = NULL; ++ bool csi_use = false; ++ bool max9286_use = false; ++ bool ti9x4_use = false; ++ ++ match = of_match_device(of_match_ptr(rcar_isp_of_table), &pdev->dev); ++ ++ np = of_graph_get_next_endpoint(pdev->dev.of_node, NULL); ++ if (!np) { ++ dev_err(&pdev->dev, "could not find endpoint\n"); ++ return -EINVAL; ++ } ++ ++ for (i = 0; ; i++) { ++ epn = of_graph_get_next_endpoint(pdev->dev.of_node, epn); ++ if (!epn) ++ break; ++ ++ ren = of_graph_get_remote_port(epn); ++ if (!ren) { ++ dev_notice(&pdev->dev, "no remote for %s\n", ++ of_node_full_name(epn)); ++ continue; ++ } ++ ++ dev_dbg(&pdev->dev, "node name:%s\n", of_node_full_name(ren->parent)); ++ ++ if (strcmp(ren->parent->name, "csi2") == 0) { ++ csi2_ren = ren; ++ csi_use = true; ++ } ++ ++ if (strcmp(ren->parent->name, "max9286") == 0) { ++ max9286_ren = of_parse_phandle(epn, "remote-endpoint", 0); ++ max9286_use = true; ++ } ++ ++ if (strcmp(ren->parent->name, "ti9x4") == 0) { ++ ti9x4_ren = of_parse_phandle(epn, "remote-endpoint", 0); ++ ti9x4_use = true; ++ } ++ ++ of_node_put(ren); ++ } ++ ++ ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(np), &ep); ++ if (ret) { ++ dev_err(&pdev->dev, "could not parse endpoint\n"); ++ return ret; ++ } ++ ++ of_node_put(np); ++ ++ priv = devm_kzalloc(&pdev->dev, sizeof(struct rcar_isp_priv), ++ GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ /* ISP Core */ ++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (mem == NULL) ++ return -EINVAL; ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq <= 0) ++ return -EINVAL; ++ ++ priv->base = devm_ioremap_resource(&pdev->dev, mem); ++ if (IS_ERR(priv->base)) ++ return PTR_ERR(priv->base); ++ ++ ret = devm_request_irq(&pdev->dev, irq, rcar_isp_irq, IRQF_SHARED, ++ dev_name(&pdev->dev), priv); ++ if (ret) ++ return ret; ++ ++ /* ISP Interface */ ++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ if (mem == NULL) ++ return -EINVAL; ++ ++ irq = platform_get_irq(pdev, 1); ++ if (irq <= 0) ++ return -EINVAL; ++ ++ priv->interface.base = devm_ioremap_resource(&pdev->dev, mem); ++ if (IS_ERR(priv->base)) ++ return PTR_ERR(priv->base); ++#if 0 ++ ret = devm_request_irq(&pdev->dev, irq, rcar_isp_interface_irq, IRQF_SHARED, ++ dev_name(&pdev->dev), priv); ++ if (ret) ++ return ret; ++#endif ++ priv->ici.priv = priv; ++ priv->ici.v4l2_dev.dev = &pdev->dev; ++ priv->ici.drv_name = dev_name(&pdev->dev); ++ priv->ici.ops = &rcar_isp_host_ops; ++ priv->csi_sync = false; ++ priv->deser_sync = false; ++ priv->dev = &pdev->dev; ++ ++ if (!match) { ++ priv->ici.nr = pdev->id; ++ priv->chip = pdev->id_entry->driver_data; ++ } else { ++ priv->ici.nr = of_alias_get_id(pdev->dev.of_node, "isp"); ++ priv->chip = (enum chip_id)match->data; ++ } ++ ++ priv->max_width = 4096; ++ priv->max_height = 4096; ++ ++ if ((priv->chip == RCAR_V3M || priv->chip == RCAR_V3H) && ++ !of_property_read_string(np, "csi,select", &str)) { ++ int vc; ++ ++ if (strcmp(dev_name(priv->ici.v4l2_dev.dev), ++ "fec00000.isp") == 0) ++ priv->index = RCAR_ISP_CH_0; ++ else if (strcmp(dev_name(priv->ici.v4l2_dev.dev), ++ "fee00000.isp") == 0) ++ priv->index = RCAR_ISP_CH_1; ++ else ++ priv->index = RCAR_ISP_CH_NONE; ++ ++ if (strcmp(str, "csi40") == 0) ++ priv->csi_ch = RCAR_CSI40; ++ else if (strcmp(str, "csi41") == 0) ++ priv->csi_ch = RCAR_CSI41; ++ else ++ priv->csi_ch = RCAR_CSI_CH_NONE; ++ ++ ret = of_property_read_u32(np, "virtual,channel", &vc); ++ if (ret) { ++ dev_err(&pdev->dev, ++ "could not parse virtual,channel\n"); ++ return ret; ++ } ++ ++ if (vc == 0) ++ priv->vc = RCAR_VIRTUAL_CH0; ++ else if (vc == 1) ++ priv->vc = RCAR_VIRTUAL_CH1; ++ else if (vc == 2) ++ priv->vc = RCAR_VIRTUAL_CH2; ++ else if (vc == 3) ++ priv->vc = RCAR_VIRTUAL_CH3; ++ else ++ priv->vc = RCAR_VIRTUAL_NONE; ++ ++ dev_dbg(&pdev->dev, "csi_ch:%d, vc:%d\n", ++ priv->csi_ch, priv->vc); ++ } ++ ++ spin_lock_init(&priv->lock); ++ INIT_LIST_HEAD(&priv->capture); ++ ++ priv->state = STOPPED; ++ ++ pm_suspend_ignore_children(&pdev->dev, true); ++ pm_runtime_enable(&pdev->dev); ++ ++ ret = soc_camera_host_register(&priv->ici); ++ if (ret) ++ goto cleanup; ++ ++ if (csi_use) { ++ ret = rcar_isp_soc_of_bind(priv, &priv->ici, epn, csi2_ren->parent); ++ if (ret) ++ goto cleanup; ++ } ++ ++ if (max9286_use) { ++ ret = rcar_isp_soc_of_bind(priv, &priv->ici, epn, max9286_ren); ++ if (ret) ++ goto cleanup; ++ } ++ ++ if (ti9x4_use) { ++ ret = rcar_isp_soc_of_bind(priv, &priv->ici, epn, ti9x4_ren); ++ if (ret) ++ goto cleanup; ++ } ++ ++ return 0; ++ ++cleanup: ++ pm_runtime_disable(&pdev->dev); ++ ++ return ret; ++} ++ ++static int rcar_isp_remove(struct platform_device *pdev) ++{ ++ struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); ++ struct rcar_isp_priv *priv = container_of(soc_host, ++ struct rcar_isp_priv, ici); ++ ++ platform_device_del(priv->async_client->pdev); ++ platform_device_put(priv->async_client->pdev); ++ ++ v4l2_async_notifier_unregister(&priv->async_client->notifier); ++ ++ soc_camera_host_unregister(soc_host); ++ pm_runtime_disable(&pdev->dev); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int rcar_isp_suspend(struct device *dev) ++{ ++ return 0; ++} ++ ++static int rcar_isp_resume(struct device *dev) ++{ ++ return 0; ++} ++ ++static SIMPLE_DEV_PM_OPS(rcar_isp_pm_ops, ++ rcar_isp_suspend, rcar_isp_resume); ++#define DEV_PM_OPS (&rcar_isp_pm_ops) ++#else ++#define DEV_PM_OPS NULL ++#endif /* CONFIG_PM_SLEEP */ ++ ++static struct platform_driver rcar_isp_driver = { ++ .probe = rcar_isp_probe, ++ .remove = rcar_isp_remove, ++ .driver = { ++ .name = DRV_NAME, ++ .pm = DEV_PM_OPS, ++ .of_match_table = of_match_ptr(rcar_isp_of_table), ++ }, ++}; ++ ++module_platform_driver(rcar_isp_driver); ++ ++MODULE_ALIAS("platform:rcar_isp"); ++MODULE_AUTHOR("Cogent Embedded Inc. "); ++MODULE_DESCRIPTION("Renesas R-Car ISP camera host driver"); ++MODULE_LICENSE("GPL"); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0296-media-platform-soc_camera-rcar_isp-Fix-unused-variab.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0296-media-platform-soc_camera-rcar_isp-Fix-unused-variab.patch new file mode 100644 index 00000000..482cf44b --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0296-media-platform-soc_camera-rcar_isp-Fix-unused-variab.patch @@ -0,0 +1,51 @@ +From 050b4c8341386b0221c546b01ec30be9aaa6c897 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Mon, 29 Oct 2018 11:57:06 +0300 +Subject: [PATCH 116/211] media: platform: soc_camera: rcar_isp: Fix unused + variable warning + +This fixes unused "cam" variable warning. + +Signed-off-by: Valentine Barshak +--- + drivers/media/platform/soc_camera/rcar_isp.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +diff --git a/drivers/media/platform/soc_camera/rcar_isp.c b/drivers/media/platform/soc_camera/rcar_isp.c +index 878df95..1127c7d 100644 +--- a/drivers/media/platform/soc_camera/rcar_isp.c ++++ b/drivers/media/platform/soc_camera/rcar_isp.c +@@ -728,7 +728,6 @@ static int rcar_isp_hw_ready(struct rcar_isp_priv *priv) + /* Moves a buffer from the queue to the HW slot */ + static int rcar_isp_fill_hw_slot(struct rcar_isp_priv *priv) + { +- struct rcar_isp_cam *cam = priv->ici.icd->host_priv; + struct vb2_v4l2_buffer *vbuf; + dma_addr_t phys_addr_top; + int slot; +@@ -745,12 +744,16 @@ static int rcar_isp_fill_hw_slot(struct rcar_isp_priv *priv) + list_del_init(to_buf_list(vbuf)); + priv->queue_buf[slot] = vbuf; + phys_addr_top = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0); +-#if 1 +- rcar_isp_setup_out_buffer(priv, slot, phys_addr_top); +-#else +- rcar_isp_setup_out_buffer(priv, 0, phys_addr_top); // Y +- rcar_isp_setup_out_buffer(priv, 1, phys_addr_top + cam->out_width * cam->out_height); // UV +-#endif ++ ++ if (1) { ++ rcar_isp_setup_out_buffer(priv, slot, phys_addr_top); ++ } else { ++ struct rcar_isp_cam *cam = priv->ici.icd->host_priv; ++ ++ rcar_isp_setup_out_buffer(priv, 0, phys_addr_top); // Y ++ rcar_isp_setup_out_buffer(priv, 1, phys_addr_top + ++ cam->out_width * cam->out_height); // UV ++ } + return 1; + } + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0297-media-platform-soc_camera-rcar_vin-Update-R-Car-V3M-.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0297-media-platform-soc_camera-rcar_vin-Update-R-Car-V3M-.patch new file mode 100644 index 00000000..34c018f9 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0297-media-platform-soc_camera-rcar_vin-Update-R-Car-V3M-.patch @@ -0,0 +1,57 @@ +From 8091f1f8f716fb33ecfd67f9c2adb54e3a4ca883 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Thu, 18 Oct 2018 15:24:59 +0300 +Subject: [PATCH 117/211] media: platform: soc_camera: rcar_vin: Update R-Car + V3M bindings + +This updates V3M compatible string to "renesas,vin-r8a77970". +While at it use more descriptive name for the V3M ifmd array. + +Signed-off-by: Valentine Barshak +--- + drivers/media/platform/soc_camera/rcar_vin.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c +index 291d115..ff4e521 100644 +--- a/drivers/media/platform/soc_camera/rcar_vin.c ++++ b/drivers/media/platform/soc_camera/rcar_vin.c +@@ -439,7 +439,7 @@ static const struct vin_gen3_ifmd vin_m3n_vc_ifmd[] = { + }, + }; + +-static const struct vin_gen3_ifmd vin_v3_vc_ifmd[] = { ++static const struct vin_gen3_ifmd vin_v3m_vc_ifmd[] = { + { 0x0000, + { + {RCAR_CSI40, RCAR_VIRTUAL_CH0}, +@@ -2770,7 +2770,7 @@ static struct soc_camera_host_ops rcar_vin_host_ops = { + + #ifdef CONFIG_OF + static const struct of_device_id rcar_vin_of_table[] = { +- { .compatible = "renesas,vin-r8a7797", .data = (void *)RCAR_V3M }, ++ { .compatible = "renesas,vin-r8a77970", .data = (void *)RCAR_V3M }, + { .compatible = "renesas,vin-r8a77965", .data = (void *)RCAR_M3N }, + { .compatible = "renesas,vin-r8a7796", .data = (void *)RCAR_M3 }, + { .compatible = "renesas,vin-r8a7795", .data = (void *)RCAR_H3 }, +@@ -3188,7 +3188,7 @@ static int rcar_vin_probe(struct platform_device *pdev) + ifmd = VNCSI_IFMD_DES1; + break; + case RCAR_V3M: +- gen3_ifmd_table = vin_v3_vc_ifmd; ++ gen3_ifmd_table = vin_v3m_vc_ifmd; + break; + default: + BUG(); +@@ -3358,7 +3358,7 @@ static int rcar_vin_resume(struct device *dev) + ifmd = VNCSI_IFMD_DES1; + break; + case RCAR_V3M: +- gen3_ifmd_table = vin_v3_vc_ifmd; ++ gen3_ifmd_table = vin_v3m_vc_ifmd; + break; + default: + return 0; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0298-media-platform-soc_camera-rcar_vin-Add-r8a77980-supp.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0298-media-platform-soc_camera-rcar_vin-Add-r8a77980-supp.patch new file mode 100644 index 00000000..a188de62 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0298-media-platform-soc_camera-rcar_vin-Add-r8a77980-supp.patch @@ -0,0 +1,256 @@ +From 166dc7905bc75f5e6682d47e2c2aa436c01f6cef Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Thu, 18 Oct 2018 15:37:29 +0300 +Subject: [PATCH 118/211] media: platform: soc_camera: rcar_vin: Add r8a77980 + support + +This adds R-Car V3H support. + +Signed-off-by: Valentine Barshak +--- + drivers/media/platform/soc_camera/rcar_vin.c | 111 +++++++++++++++++++++++---- + 1 file changed, 97 insertions(+), 14 deletions(-) + +diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c +index ff4e521..6ba94c3 100644 +--- a/drivers/media/platform/soc_camera/rcar_vin.c ++++ b/drivers/media/platform/soc_camera/rcar_vin.c +@@ -164,7 +164,8 @@ + #define VNCSI_IFMD_REG 0x20 /* Video n CSI2 Interface Mode Register */ + + #define VNCSI_IFMD_DES1 (1 << 26) /* CSI20 */ +-#define VNCSI_IFMD_DES0 (1 << 25) /* H3:CSI40/41, M3:CSI40, V3M:CSI40 */ ++#define VNCSI_IFMD_DES0 (1 << 25) /* H3:CSI40/41, M3:CSI40, ++ * V3M:CSI40 V3H:CSI40 */ + + #define VNCSI_IFMD_CSI_CHSEL(n) (n << 0) + #define VNCSI_IFMD_SEL_NUMBER 5 +@@ -199,6 +200,7 @@ static int ifmd4_init = true; + + enum chip_id { + RCAR_GEN3, ++ RCAR_V3H, + RCAR_V3M, + RCAR_M3N, + RCAR_M3, +@@ -482,6 +484,69 @@ static const struct vin_gen3_ifmd vin_v3m_vc_ifmd[] = { + }, + }; + ++static const struct vin_gen3_ifmd vin_v3h_vc_ifmd[] = { ++ { 0x0000, ++ { ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH1}, ++ } ++ }, ++ { 0x0001, ++ { ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ } ++ }, ++ { 0x0002, ++ { ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ } ++ }, ++ { 0x0003, ++ { ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH3}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH3}, ++ } ++ }, ++ { 0x0004, ++ { ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ } ++ }, ++}; ++ + enum csi2_fmt { + RCAR_CSI_FMT_NONE = -1, + RCAR_CSI_RGB888, +@@ -977,7 +1042,8 @@ static int rcar_vin_videobuf_setup(struct vb2_queue *vq, + struct rcar_vin_cam *cam = icd->host_priv; + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_M3N || priv->chip == RCAR_V3M || ++ priv->chip == RCAR_V3H) { + if ((priv->ratio_h > 0x10000) || (priv->ratio_v > 0x10000)) { + dev_err(icd->parent, "Scaling rate parameter error\n"); + return -EINVAL; +@@ -1087,7 +1153,8 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + switch (icd->current_fmt->host_fmt->fourcc) { + case V4L2_PIX_FMT_NV12: + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_M3N || priv->chip == RCAR_V3M || ++ priv->chip == RCAR_V3H) { + iowrite32(ALIGN((cam->out_width * cam->out_height), + 0x80), priv->base + VNUVAOF_REG); + dmr = VNDMR_DTMD_YCSEP_YCBCR420; +@@ -1127,15 +1194,16 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + case V4L2_PIX_FMT_XBGR32: + if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3 && + priv->chip != RCAR_M3N && priv->chip != RCAR_V3M && +- priv->chip != RCAR_GEN2 && priv->chip != RCAR_H1 && +- priv->chip != RCAR_E1) ++ priv->chip != RCAR_V3H && priv->chip != RCAR_GEN2 && ++ priv->chip != RCAR_H1 && priv->chip != RCAR_E1) + goto e_format; + + dmr = VNDMR_EXRGB; + break; + case V4L2_PIX_FMT_ABGR32: + if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3 && +- priv->chip != RCAR_M3N && priv->chip != RCAR_V3M) ++ priv->chip != RCAR_M3N && priv->chip != RCAR_V3M && ++ priv->chip != RCAR_V3H) + goto e_format; + + dmr = VNDMR_EXRGB | VNDMR_DTMD_ARGB; +@@ -1156,7 +1224,8 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + vnmc |= VNMC_BPS; + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_M3N || priv->chip == RCAR_V3M || ++ priv->chip == RCAR_V3H) { + if (priv->pdata_flags & RCAR_VIN_CSI2) + vnmc &= ~VNMC_DPINE; + else +@@ -1540,7 +1609,8 @@ static int rcar_vin_add_device(struct soc_camera_device *icd) + pm_runtime_get_sync(ici->v4l2_dev.dev); + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_M3N || priv->chip == RCAR_V3M || ++ priv->chip == RCAR_V3H) { + struct v4l2_subdev *csi2_sd = find_csi2(priv); + struct v4l2_subdev *deser_sd = find_deser(priv); + int ret = 0; +@@ -1803,7 +1873,8 @@ static int rcar_vin_set_rect(struct soc_camera_device *icd) + } + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_M3N || priv->chip == RCAR_V3M || ++ priv->chip == RCAR_V3H) { + if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12) && + (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR8) && + (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR12) && +@@ -1963,7 +2034,8 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd) + return ret; + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_M3N || priv->chip == RCAR_V3M || ++ priv->chip == RCAR_V3H) { + if (cfg.type == V4L2_MBUS_CSI2) + vnmc &= ~VNMC_DPINE; + else +@@ -1971,7 +2043,8 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd) + } + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) ++ priv->chip == RCAR_M3N || priv->chip == RCAR_V3M || ++ priv->chip == RCAR_V3H) + val = VNDMR2_FTEV; + else + val = VNDMR2_FTEV | VNDMR2_VLV(1); +@@ -2591,7 +2664,8 @@ static int rcar_vin_try_fmt(struct soc_camera_device *icd, + return ret; + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_M3N || priv->chip == RCAR_V3M || ++ priv->chip == RCAR_V3H) { + /* Adjust max scaling size for Gen3 */ + if (pix->width > 4096) + pix->width = priv->max_width; +@@ -2770,6 +2844,7 @@ static struct soc_camera_host_ops rcar_vin_host_ops = { + + #ifdef CONFIG_OF + static const struct of_device_id rcar_vin_of_table[] = { ++ { .compatible = "renesas,vin-r8a77980", .data = (void *)RCAR_V3H }, + { .compatible = "renesas,vin-r8a77970", .data = (void *)RCAR_V3M }, + { .compatible = "renesas,vin-r8a77965", .data = (void *)RCAR_M3N }, + { .compatible = "renesas,vin-r8a7796", .data = (void *)RCAR_M3 }, +@@ -3095,7 +3170,8 @@ static int rcar_vin_probe(struct platform_device *pdev) + } + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_M3N || priv->chip == RCAR_V3M || ++ priv->chip == RCAR_V3H) { + priv->max_width = 4096; + priv->max_height = 4096; + } else { +@@ -3104,7 +3180,8 @@ static int rcar_vin_probe(struct platform_device *pdev) + } + + if ((priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_M3N || priv->chip == RCAR_V3M) && ++ priv->chip == RCAR_M3N || priv->chip == RCAR_V3M || ++ priv->chip == RCAR_V3H) && + !of_property_read_string(np, "csi,select", &str)) { + u32 ifmd; + bool match_flag = false; +@@ -3190,6 +3267,9 @@ static int rcar_vin_probe(struct platform_device *pdev) + case RCAR_V3M: + gen3_ifmd_table = vin_v3m_vc_ifmd; + break; ++ case RCAR_V3H: ++ gen3_ifmd_table = vin_v3h_vc_ifmd; ++ break; + default: + BUG(); + break; +@@ -3360,6 +3440,9 @@ static int rcar_vin_resume(struct device *dev) + case RCAR_V3M: + gen3_ifmd_table = vin_v3m_vc_ifmd; + break; ++ case RCAR_V3H: ++ gen3_ifmd_table = vin_v3h_vc_ifmd; ++ break; + default: + return 0; + } +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0299-media-platform-soc_camera-rcar_csi2-r8a77970-Update-.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0299-media-platform-soc_camera-rcar_csi2-r8a77970-Update-.patch new file mode 100644 index 00000000..c4e8770e --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0299-media-platform-soc_camera-rcar_csi2-r8a77970-Update-.patch @@ -0,0 +1,73 @@ +From a5d325f3d587578aae5cae46dbdb2a7570b706fb Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Fri, 26 Oct 2018 19:40:35 +0300 +Subject: [PATCH 119/211] media: platform: soc_camera: rcar_csi2: r8a77970: + Update SoC id + +Use r8a77970 SoC id instead of r8a7797. + +Signed-off-by: Valentine Barshak +--- + drivers/media/platform/soc_camera/Kconfig | 3 ++- + drivers/media/platform/soc_camera/rcar_csi2.c | 10 +++++----- + 2 files changed, 7 insertions(+), 6 deletions(-) + +diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig +index 61b0dcf..ae9e0b3 100644 +--- a/drivers/media/platform/soc_camera/Kconfig ++++ b/drivers/media/platform/soc_camera/Kconfig +@@ -39,7 +39,8 @@ config VIDEO_RCAR_VIN_LEGACY_DEBUG + config VIDEO_RCAR_CSI2_LEGACY + tristate "R-Car MIPI CSI-2 Interface driver" + depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK +- depends on ARCH_R8A7795 || ARCH_R8A7796 || ARCH_R8A77965 || COMPILE_TEST ++ depends on ARCH_R8A7795 || ARCH_R8A7796 || ARCH_R8A77965 || \ ++ ARCH_R8A77970 || COMPILE_TEST + select V4L2_FWNODE + ---help--- + This is a v4l2 driver for the R-Car CSI-2 Interface +diff --git a/drivers/media/platform/soc_camera/rcar_csi2.c b/drivers/media/platform/soc_camera/rcar_csi2.c +index 384d7e9..838806d 100644 +--- a/drivers/media/platform/soc_camera/rcar_csi2.c ++++ b/drivers/media/platform/soc_camera/rcar_csi2.c +@@ -166,8 +166,8 @@ + #define RCAR_CSI2_INTSTATE_ERRSYNCESC (1 << 1) + #define RCAR_CSI2_INTSTATE_ERRCONTROL (1 << 0) + +-static const struct soc_device_attribute r8a7797[] = { +- { .soc_id = "r8a7797" }, ++static const struct soc_device_attribute r8a77970[] = { ++ { .soc_id = "r8a77970" }, + { } + }; + +@@ -409,7 +409,7 @@ static int rcar_csi2_set_phy_freq(struct rcar_csi2 *priv) + + dev_dbg(&priv->pdev->dev, "bps_per_lane (%d)\n", bps_per_lane); + +- if (soc_device_match(r8a7797)) ++ if (soc_device_match(r8a77970)) + iowrite32((hs_freq_range_v3m[bps_per_lane] << 16) | + RCAR_CSI2_PHTW_DWEN | RCAR_CSI2_PHTW_CWEN | 0x44, + priv->base + RCAR_CSI2_PHTW); +@@ -612,7 +612,7 @@ static struct v4l2_subdev_ops rcar_csi2_subdev_ops = { + + #ifdef CONFIG_OF + static const struct of_device_id rcar_csi2_of_table[] = { +- { .compatible = "renesas,r8a7797-csi2", .data = (void *)RCAR_GEN3 }, ++ { .compatible = "renesas,r8a77970-csi2", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,r8a77965-csi2", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,r8a7796-csi2", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,r8a7795-csi2", .data = (void *)RCAR_GEN3 }, +@@ -622,7 +622,7 @@ MODULE_DEVICE_TABLE(of, rcar_csi2_of_table); + #endif + + static struct platform_device_id rcar_csi2_id_table[] = { +- { "r8a7797-csi2", RCAR_GEN3 }, ++ { "r8a77970-csi2", RCAR_GEN3 }, + { "r8a77965-csi2", RCAR_GEN3 }, + { "r8a7796-csi2", RCAR_GEN3 }, + { "r8a7795-csi2", RCAR_GEN3 }, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0300-media-platform-soc_camera-rcar_csi2-Add-r8a77980-sup.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0300-media-platform-soc_camera-rcar_csi2-Add-r8a77980-sup.patch new file mode 100644 index 00000000..fbb9bedc --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0300-media-platform-soc_camera-rcar_csi2-Add-r8a77980-sup.patch @@ -0,0 +1,89 @@ +From 34bd7eb4d9826aa6229f797c57d4011d0beb995e Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Fri, 26 Oct 2018 19:52:08 +0300 +Subject: [PATCH 120/211] media: platform: soc_camera: rcar_csi2: Add r8a77980 + support + +This adds R8A77980 support to the R-Car CSI2 driver. + +Signed-off-by: Valentine Barshak +--- + drivers/media/platform/soc_camera/Kconfig | 2 +- + drivers/media/platform/soc_camera/rcar_csi2.c | 13 ++++++++++--- + 2 files changed, 11 insertions(+), 4 deletions(-) + +diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig +index ae9e0b3..19fd6c4 100644 +--- a/drivers/media/platform/soc_camera/Kconfig ++++ b/drivers/media/platform/soc_camera/Kconfig +@@ -40,7 +40,7 @@ config VIDEO_RCAR_CSI2_LEGACY + tristate "R-Car MIPI CSI-2 Interface driver" + depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK + depends on ARCH_R8A7795 || ARCH_R8A7796 || ARCH_R8A77965 || \ +- ARCH_R8A77970 || COMPILE_TEST ++ ARCH_R8A77970 || ARCH_R8A77980 || COMPILE_TEST + select V4L2_FWNODE + ---help--- + This is a v4l2 driver for the R-Car CSI-2 Interface +diff --git a/drivers/media/platform/soc_camera/rcar_csi2.c b/drivers/media/platform/soc_camera/rcar_csi2.c +index 838806d..737a686 100644 +--- a/drivers/media/platform/soc_camera/rcar_csi2.c ++++ b/drivers/media/platform/soc_camera/rcar_csi2.c +@@ -166,6 +166,11 @@ + #define RCAR_CSI2_INTSTATE_ERRSYNCESC (1 << 1) + #define RCAR_CSI2_INTSTATE_ERRCONTROL (1 << 0) + ++static const struct soc_device_attribute r8a77980[] = { ++ { .soc_id = "r8a77980" }, ++ { } ++}; ++ + static const struct soc_device_attribute r8a77970[] = { + { .soc_id = "r8a77970" }, + { } +@@ -413,7 +418,7 @@ static int rcar_csi2_set_phy_freq(struct rcar_csi2 *priv) + iowrite32((hs_freq_range_v3m[bps_per_lane] << 16) | + RCAR_CSI2_PHTW_DWEN | RCAR_CSI2_PHTW_CWEN | 0x44, + priv->base + RCAR_CSI2_PHTW); +- else if (soc_device_match(r8a7795)) ++ else if (soc_device_match(r8a7795) || soc_device_match(r8a77980)) + iowrite32(hs_freq_range_h3[bps_per_lane] << 16, + priv->base + RCAR_CSI2_PHYPLL); + else +@@ -500,7 +505,7 @@ static int rcar_csi2_hwinit(struct rcar_csi2 *priv) + return -EINVAL; + } + +- if (soc_device_match(r8a7795)) { ++ if (soc_device_match(r8a7795) || soc_device_match(r8a77980)) { + /* Set PHY Test Interface Write Register in R-Car H3(ES2.0) */ + iowrite32(0x01cc01e2, priv->base + RCAR_CSI2_PHTW); + iowrite32(0x010101e3, priv->base + RCAR_CSI2_PHTW); +@@ -518,7 +523,7 @@ static int rcar_csi2_hwinit(struct rcar_csi2 *priv) + /* Set CSI0CLK Frequency Configuration Preset Register + * in R-Car H3(ES2.0) + */ +- if (soc_device_match(r8a7795)) ++ if (soc_device_match(r8a7795) || soc_device_match(r8a77980)) + iowrite32(CSI0CLKFREQRANGE(32), priv->base + RCAR_CSI2_CSI0CLKFCPR); + + /* Enable lanes */ +@@ -612,6 +617,7 @@ static struct v4l2_subdev_ops rcar_csi2_subdev_ops = { + + #ifdef CONFIG_OF + static const struct of_device_id rcar_csi2_of_table[] = { ++ { .compatible = "renesas,r8a77980-csi2", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,r8a77970-csi2", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,r8a77965-csi2", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,r8a7796-csi2", .data = (void *)RCAR_GEN3 }, +@@ -622,6 +628,7 @@ MODULE_DEVICE_TABLE(of, rcar_csi2_of_table); + #endif + + static struct platform_device_id rcar_csi2_id_table[] = { ++ { "r8a77980-csi2", RCAR_GEN3 }, + { "r8a77970-csi2", RCAR_GEN3 }, + { "r8a77965-csi2", RCAR_GEN3 }, + { "r8a7796-csi2", RCAR_GEN3 }, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0301-arm64-dts-renesas-r8a77970-Convert-VIN-nodes-to-soc_.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0301-arm64-dts-renesas-r8a77970-Convert-VIN-nodes-to-soc_.patch new file mode 100644 index 00000000..40f38c48 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0301-arm64-dts-renesas-r8a77970-Convert-VIN-nodes-to-soc_.patch @@ -0,0 +1,116 @@ +From 8132f65ee9e530c4af291eef6b2f54196953ce51 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Tue, 25 Jun 2019 23:43:06 +0300 +Subject: [PATCH 121/211] arm64: dts: renesas: r8a77970: Convert VIN nodes to + soc_camera model + +This converts VIN nodes to soc_camera model. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970.dtsi | 68 ------------------------------- + 1 file changed, 68 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +index 563428d..2a35025 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +@@ -826,23 +826,6 @@ + resets = <&cpg 811>; + renesas,id = <0>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin0csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&csi40vin0>; +- }; +- }; +- }; + }; + + vin1: video@e6ef1000 { +@@ -854,23 +837,6 @@ + resets = <&cpg 810>; + renesas,id = <1>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin1csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&csi40vin1>; +- }; +- }; +- }; + }; + + vin2: video@e6ef2000 { +@@ -882,23 +848,6 @@ + resets = <&cpg 809>; + renesas,id = <2>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin2csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&csi40vin2>; +- }; +- }; +- }; + }; + + vin3: video@e6ef3000 { +@@ -910,23 +859,6 @@ + resets = <&cpg 808>; + renesas,id = <3>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin3csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&csi40vin3>; +- }; +- }; +- }; + }; + + dmac1: dma-controller@e7300000 { +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0302-arm64-dts-renesas-r8a77980-Convert-VIN-nodes-to-soc_.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0302-arm64-dts-renesas-r8a77980-Convert-VIN-nodes-to-soc_.patch new file mode 100644 index 00000000..42b7a6ae --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0302-arm64-dts-renesas-r8a77980-Convert-VIN-nodes-to-soc_.patch @@ -0,0 +1,212 @@ +From 614a4a2f74e8a6d14a43853c2ce134358b5e86f3 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Tue, 25 Jun 2019 23:45:40 +0300 +Subject: [PATCH 122/211] arm64: dts: renesas: r8a77980: Convert VIN nodes to + soc_camera model + +This converts VIN nodes to soc_camera model. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 136 ------------------------------ + 1 file changed, 136 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index 1b56b1f..63c49a8 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -867,23 +867,6 @@ + resets = <&cpg 811>; + renesas,id = <0>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin0csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint= <&csi40vin0>; +- }; +- }; +- }; + }; + + vin1: video@e6ef1000 { +@@ -895,23 +878,6 @@ + status = "disabled"; + renesas,id = <1>; + resets = <&cpg 810>; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin1csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint= <&csi40vin1>; +- }; +- }; +- }; + }; + + vin2: video@e6ef2000 { +@@ -923,23 +889,6 @@ + resets = <&cpg 809>; + renesas,id = <2>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin2csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint= <&csi40vin2>; +- }; +- }; +- }; + }; + + vin3: video@e6ef3000 { +@@ -951,23 +900,6 @@ + resets = <&cpg 808>; + renesas,id = <3>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin3csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint= <&csi40vin3>; +- }; +- }; +- }; + }; + + vin4: video@e6ef4000 { +@@ -979,23 +911,6 @@ + resets = <&cpg 807>; + renesas,id = <4>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin4csi41: endpoint@2 { +- reg = <2>; +- remote-endpoint= <&csi41vin4>; +- }; +- }; +- }; + }; + + vin5: video@e6ef5000 { +@@ -1007,23 +922,6 @@ + resets = <&cpg 806>; + renesas,id = <5>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin5csi41: endpoint@2 { +- reg = <2>; +- remote-endpoint= <&csi41vin5>; +- }; +- }; +- }; + }; + + vin6: video@e6ef6000 { +@@ -1035,23 +933,6 @@ + resets = <&cpg 805>; + renesas,id = <6>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin6csi41: endpoint@2 { +- reg = <2>; +- remote-endpoint= <&csi41vin6>; +- }; +- }; +- }; + }; + + vin7: video@e6ef7000 { +@@ -1063,23 +944,6 @@ + resets = <&cpg 804>; + renesas,id = <7>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin7csi41: endpoint@2 { +- reg = <2>; +- remote-endpoint= <&csi41vin7>; +- }; +- }; +- }; + }; + + vin8: video@e6ef8000 { +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0303-arm64-dts-renesas-r8a77970-Convert-SCI2-nodes-to-soc.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0303-arm64-dts-renesas-r8a77970-Convert-SCI2-nodes-to-soc.patch new file mode 100644 index 00000000..eb9c3566 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0303-arm64-dts-renesas-r8a77970-Convert-SCI2-nodes-to-soc.patch @@ -0,0 +1,56 @@ +From 85de1cf6d945c4ad380bbd65e6f5fab58a272885 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Fri, 26 Oct 2018 21:51:16 +0300 +Subject: [PATCH 123/211] arm64: dts: renesas: r8a77970: Convert SCI2 nodes to + soc_camera model + +This converts CSI2 nodes to soc_camera model. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970.dtsi | 29 ----------------------------- + 1 file changed, 29 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +index 2a35025..883d811 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +@@ -1013,35 +1013,6 @@ + power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; + resets = <&cpg 716>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- csi40vin0: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&vin0csi40>; +- }; +- csi40vin1: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&vin1csi40>; +- }; +- csi40vin2: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&vin2csi40>; +- }; +- csi40vin3: endpoint@3 { +- reg = <3>; +- remote-endpoint = <&vin3csi40>; +- }; +- }; +- }; + }; + + du: display@feb00000 { +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0304-arm64-dts-renesas-r8a77980-Convert-CSI2-nodes-to-soc.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0304-arm64-dts-renesas-r8a77980-Convert-CSI2-nodes-to-soc.patch new file mode 100644 index 00000000..190cce23 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0304-arm64-dts-renesas-r8a77980-Convert-CSI2-nodes-to-soc.patch @@ -0,0 +1,92 @@ +From 447ecfa0c2add1ff477ccf22bc27c8248738adaf Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Fri, 26 Oct 2018 21:52:31 +0300 +Subject: [PATCH 124/211] arm64: dts: renesas: r8a77980: Convert CSI2 nodes to + soc_camera model + +This converts CSI2 nodes to soc_camera model. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 58 ------------------------------- + 1 file changed, 58 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index 63c49a8..5ddff7e 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -1280,35 +1280,6 @@ + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 716>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- csi40vin0: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&vin0csi40>; +- }; +- csi40vin1: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&vin1csi40>; +- }; +- csi40vin2: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&vin2csi40>; +- }; +- csi40vin3: endpoint@3 { +- reg = <3>; +- remote-endpoint = <&vin3csi40>; +- }; +- }; +- }; + }; + + csi41: csi2@feab0000 { +@@ -1319,35 +1290,6 @@ + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 715>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- csi41vin4: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&vin4csi41>; +- }; +- csi41vin5: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&vin5csi41>; +- }; +- csi41vin6: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&vin6csi41>; +- }; +- csi41vin7: endpoint@3 { +- reg = <3>; +- remote-endpoint = <&vin7csi41>; +- }; +- }; +- }; + }; + + du: display@feb00000 { +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0305-arm64-dts-renesas-r8a77970-Add-IMR-nodes.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0305-arm64-dts-renesas-r8a77970-Add-IMR-nodes.patch new file mode 100644 index 00000000..6ec213b6 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0305-arm64-dts-renesas-r8a77970-Add-IMR-nodes.patch @@ -0,0 +1,66 @@ +From bb5909a7796b78f28c00a721dc10d694e266c410 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Fri, 26 Oct 2018 22:14:26 +0300 +Subject: [PATCH 125/211] arm64: dts: renesas: r8a77970: Add IMR nodes + +This adds IMR device nodes. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970.dtsi | 40 +++++++++++++++++++++++++++++++ + 1 file changed, 40 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +index 883d811..782c49c 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +@@ -861,6 +861,46 @@ + status = "disabled"; + }; + ++ imr-lx4@fe860000 { ++ compatible = "renesas,r8a77970-imr-lx4", ++ "renesas,imr-lx4"; ++ reg = <0 0xfe860000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 823>; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ resets = <&cpg 823>; ++ }; ++ ++ imr-lx4@fe870000 { ++ compatible = "renesas,r8a77970-imr-lx4", ++ "renesas,imr-lx4"; ++ reg = <0 0xfe870000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 822>; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ resets = <&cpg 822>; ++ }; ++ ++ imr-lx4@fe880000 { ++ compatible = "renesas,r8a77970-imr-lx4", ++ "renesas,imr-lx4"; ++ reg = <0 0xfe880000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 821>; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ resets = <&cpg 821>; ++ }; ++ ++ imr-lx4@fe890000 { ++ compatible = "renesas,r8a77970-imr-lx4", ++ "renesas,imr-lx4"; ++ reg = <0 0xfe890000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 820>; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ resets = <&cpg 820>; ++ }; ++ + dmac1: dma-controller@e7300000 { + compatible = "renesas,dmac-r8a77970", + "renesas,rcar-dmac"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0306-arm64-dts-renesas-r8a77980-Add-IMR-nodes.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0306-arm64-dts-renesas-r8a77980-Add-IMR-nodes.patch new file mode 100644 index 00000000..bc454635 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0306-arm64-dts-renesas-r8a77980-Add-IMR-nodes.patch @@ -0,0 +1,84 @@ +From 6f5248fad39c19c87ed1e88df3e59e2e7667926c Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Fri, 26 Oct 2018 22:15:26 +0300 +Subject: [PATCH 126/211] arm64: dts: renesas: r8a77980: Add IMR nodes + +This adds IMR device nodes. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 58 +++++++++++++++++++++++++++++++ + 1 file changed, 58 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index 5ddff7e..911a432 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -1034,6 +1034,64 @@ + status = "disabled"; + }; + ++ imr-lx4@fe860000 { ++ compatible = "renesas,r8a77980-imr-lx4", ++ "renesas,imr-lx4"; ++ reg = <0 0xfe860000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 823>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 823>; ++ }; ++ ++ imr-lx4@fe870000 { ++ compatible = "renesas,r8a77980-imr-lx4", ++ "renesas,imr-lx4"; ++ reg = <0 0xfe870000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 822>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 822>; ++ }; ++ ++ imr-lx4@fe880000 { ++ compatible = "renesas,r8a77980-imr-lx4", ++ "renesas,imr-lx4"; ++ reg = <0 0xfe880000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 821>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 821>; ++ }; ++ ++ imr-lx4@fe890000 { ++ compatible = "renesas,r8a77980-imr-lx4", ++ "renesas,imr-lx4"; ++ reg = <0 0xfe890000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 820>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ resets = <&cpg 820>; ++ }; ++ ++ imr4@fe8a0000 { ++ compatible = "renesas,r8a77980-imr-lx4", ++ "renesas,imr-lx4"; ++ reg = <0 0xfe8a0000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 707>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ }; ++ ++ imr5@fe8b0000 { ++ compatible = "renesas,r8a77980-imr-lx4", ++ "renesas,imr-lx4"; ++ reg = <0 0xfe8b0000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 706>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ }; ++ + dmac1: dma-controller@e7300000 { + compatible = "renesas,dmac-r8a77980", + "renesas,rcar-dmac"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0307-arm64-dts-renesas-r8a77970-Add-ISP-node.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0307-arm64-dts-renesas-r8a77970-Add-ISP-node.patch new file mode 100644 index 00000000..be3e7ac4 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0307-arm64-dts-renesas-r8a77970-Add-ISP-node.patch @@ -0,0 +1,36 @@ +From 6d44f2c02108f34b81acb2e081d274160129fcd0 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Mon, 29 Oct 2018 13:59:27 +0300 +Subject: [PATCH 127/211] arm64: dts: renesas: r8a77970: Add ISP node + +This adds ISP device node. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970.dtsi | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +index 782c49c..2585ba5 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +@@ -901,6 +901,16 @@ + resets = <&cpg 820>; + }; + ++ isp@fec00000 { ++ compatible = "renesas,isp-r8a77970"; ++ reg = <0 0xfec00000 0 0x20000>, ++ <0 0xfed00000 0 0x10000>; ++ interrupts = , ++ ; ++ clocks = <&cpg CPG_MOD 817>; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ }; ++ + dmac1: dma-controller@e7300000 { + compatible = "renesas,dmac-r8a77970", + "renesas,rcar-dmac"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0308-arm64-dts-renesas-r8a77980-Add-ISP-nodes.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0308-arm64-dts-renesas-r8a77980-Add-ISP-nodes.patch new file mode 100644 index 00000000..80bdf6ca --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0308-arm64-dts-renesas-r8a77980-Add-ISP-nodes.patch @@ -0,0 +1,46 @@ +From f35ea5b06fd411aaf351c0bc52894637efe6f0ca Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Mon, 29 Oct 2018 14:00:09 +0300 +Subject: [PATCH 128/211] arm64: dts: renesas: r8a77980: Add ISP nodes + +This adds ISP device nodes. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index 911a432..8fba9c7 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -1092,6 +1092,26 @@ + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + }; + ++ isp@fec00000 { ++ compatible = "renesas,isp-r8a77980"; ++ reg = <0 0xfec00000 0 0x20000>, ++ <0 0xfed00000 0 0x10000>; ++ interrupts = , ++ ; ++ clocks = <&cpg CPG_MOD 817>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ }; ++ ++ isp@fee00000 { ++ compatible = "renesas,isp-r8a77980"; ++ reg = <0 0xfee00000 0 0x20000>, ++ <0 0xfed20000 0 0x10000>; ++ interrupts = , ++ ; ++ clocks = <&cpg CPG_MOD 814>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ }; ++ + dmac1: dma-controller@e7300000 { + compatible = "renesas,dmac-r8a77980", + "renesas,rcar-dmac"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0309-arm64-dts-renesas-eagle-Add-video-input-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0309-arm64-dts-renesas-eagle-Add-video-input-support.patch new file mode 100644 index 00000000..e8732bf7 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0309-arm64-dts-renesas-eagle-Add-video-input-support.patch @@ -0,0 +1,326 @@ +From 8198924fb7bd1d8b26f9e148bafeecc51a249e5e Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Wed, 26 Jun 2019 00:11:17 +0300 +Subject: [PATCH 129/211] arm64: dts: renesas: eagle: Add video input support + +This adds support of MAX9286 GMSL chip connected to the CSI40. +Up to 4 video stream channels are routed to VIN[0-3] devices. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970-eagle.dts | 274 +++++++++++++++++++++++++ + 1 file changed, 274 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +index 800643b..a70337b 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +@@ -8,6 +8,7 @@ + + /dts-v1/; + #include "r8a77970.dtsi" ++#include + + / { + model = "Renesas Eagle board based on r8a77970"; +@@ -108,6 +109,40 @@ + }; + }; + ++&csi40 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ + &extal_clk { + clock-frequency = <16666666>; + }; +@@ -163,6 +198,128 @@ + }; + }; + ++&i2c3 { ++ pinctrl-0 = <&i2c3_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ clock-frequency = <400000>; ++ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_des0ep3: endpoint { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++ ++ max9286@0 { ++ compatible = "maxim,max9286"; ++ reg = <0x48>; ++ gpios = <&io_expander 0 GPIO_ACTIVE_LOW>; /* MAX9286 PWDN */ ++ maxim,gpio0 = <0>; ++ maxim,sensor_delay = <100>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ }; ++}; ++ + &pfc { + avb_pins: avb0 { + groups = "avb0_mdio", "avb0_rgmii", "avb0_txcrefclk"; +@@ -179,6 +336,11 @@ + function = "i2c0"; + }; + ++ i2c3_pins: i2c3 { ++ groups = "i2c3_a"; ++ function = "i2c3"; ++ }; ++ + scif0_pins: scif0 { + groups = "scif0_data"; + function = "scif0"; +@@ -215,3 +377,115 @@ + }; + }; + }; ++ ++&vin0 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin2_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin3_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++}; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0310-arm64-dts-renesas-condor-Add-video-input-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0310-arm64-dts-renesas-condor-Add-video-input-support.patch new file mode 100644 index 00000000..02e64bcb --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0310-arm64-dts-renesas-condor-Add-video-input-support.patch @@ -0,0 +1,587 @@ +From 8bb0bdc0fcb1a8c128e936e993d81837e5ebae95 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Wed, 26 Jun 2019 00:14:15 +0300 +Subject: [PATCH 130/211] arm64: dts: renesas: condor: Add video input support + +This adds support of two MAX9286 GMSL chips connected to the +CSI40 and CSI41 channels. Each channel provides up to 4 video +streams routed to VIN[0-3] and VIN[4-7] devices. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980-condor.dts | 534 ++++++++++++++++++++++++ + 1 file changed, 534 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +index 738edf0..330a1a1 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +@@ -8,6 +8,7 @@ + + /dts-v1/; + #include "r8a77980.dtsi" ++#include + + / { + model = "Renesas Condor board based on r8a77980"; +@@ -125,6 +126,74 @@ + }; + }; + ++&csi40 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&csi41 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi41_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ + &du { + clocks = <&cpg CPG_MOD 724>, + <&x1_clk>; +@@ -216,6 +285,242 @@ + }; + }; + ++&i2c1 { ++ pinctrl-0 = <&i2c1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ clock-frequency = <400000>; ++ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_des0ep3: endpoint { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++ ++ ov106xx@4 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x64>; ++ ++ port@0 { ++ ov106xx_in4: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@5 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x65>; ++ ++ port@0 { ++ ov106xx_in5: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin5ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@6 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x66>; ++ ++ port@0 { ++ ov106xx_in6: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin6ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@7 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x67>; ++ ++ port@0 { ++ ov106xx_in7: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin7ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_des1ep3: endpoint { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ }; ++ }; ++ ++ max9286@0 { ++ compatible = "maxim,max9286"; ++ reg = <0x48>; ++ gpios = <&io_expander0 0 GPIO_ACTIVE_LOW>; /* MAX9286 PWDN */ ++ maxim,gpio0 = <0>; ++ maxim,sensor_delay = <100>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ }; ++ ++ max9286@1 { ++ compatible = "maxim,max9286"; ++ reg = <0x4a>; ++ gpios = <&io_expander1 0 GPIO_ACTIVE_LOW>; /* MAX9286 PWDN */ ++ maxim,gpio0 = <0>; ++ maxim,sensor_delay = <100>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ port@0 { ++ max9286_des1ep0: endpoint@0 { ++ max9271-addr = <0x54>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in4>; ++ }; ++ max9286_des1ep1: endpoint@1 { ++ max9271-addr = <0x55>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ }; ++ max9286_des1ep2: endpoint@2 { ++ max9271-addr = <0x56>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in6>; ++ }; ++ max9286_des1ep3: endpoint@3 { ++ max9271-addr = <0x57>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in7>; ++ }; ++ }; ++ port@1 { ++ max9286_csi1ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ }; ++}; ++ + &lvds0 { + status = "okay"; + +@@ -275,6 +580,11 @@ + function = "i2c0"; + }; + ++ i2c1_pins: i2c1 { ++ groups = "i2c1"; ++ function = "i2c1"; ++ }; ++ + mmc_pins: mmc { + groups = "mmc_data8", "mmc_ctrl", "mmc_ds"; + function = "mmc"; +@@ -313,3 +623,227 @@ + &scif_clk { + clock-frequency = <14745600>; + }; ++ ++&vin0 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin2_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi40_ep>; ++ }; ++ }; ++ port@2 { ++ vin3_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&vin4 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin4ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in4>; ++ }; ++ }; ++ port@1 { ++ csi1ep0: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin4_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin5 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin5ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in5>; ++ }; ++ }; ++ port@1 { ++ csi1ep1: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin5_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin6 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin6ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in6>; ++ }; ++ }; ++ port@1 { ++ csi1ep2: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin6_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin7 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin7ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in7>; ++ }; ++ }; ++ port@1 { ++ csi1ep3: endpoint { ++ remote-endpoint = <&csi41_ep>; ++ }; ++ }; ++ port@2 { ++ vin7_max9286_des1ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ }; ++ }; ++}; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0311-arm64-dts-renesas-v3msk-Add-reserved-memory-nodes.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0311-arm64-dts-renesas-v3msk-Add-reserved-memory-nodes.patch new file mode 100644 index 00000000..bd55fbe1 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0311-arm64-dts-renesas-v3msk-Add-reserved-memory-nodes.patch @@ -0,0 +1,53 @@ +From 244b4bd18f4e0ee937503c8590d7bd0832fe438c Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Sat, 27 Oct 2018 00:00:15 +0300 +Subject: [PATCH 131/211] arm64: dts: renesas: v3msk: Add reserved memory nodes + +This adds reserved memory nodes. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts | 27 ++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +index 15cc9fe..8e0dbd7 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +@@ -27,6 +27,33 @@ + reg = <0x0 0x48000000 0x0 0x38000000>; + }; + ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ /* device specific region for Lossy Decompression */ ++ lossy_decompress: linux,lossy_decompress { ++ no-map; ++ reg = <0x00000000 0x6c000000 0x0 0x03000000>; ++ }; ++ ++ /* global autoconfigured region for contiguous allocations */ ++ linux,cma { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x6f000000 0x0 0x10000000>; ++ linux,cma-default; ++ }; ++ ++ /* device specific region for contiguous allocations */ ++ linux,multimedia { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x7f000000 0x0 0x01000000>; ++ }; ++ }; ++ + osc5_clk: osc5-clock { + compatible = "fixed-clock"; + #clock-cells = <0>; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0312-arm64-dts-renesas-v3hsk-Add-reserved-memory-nodes.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0312-arm64-dts-renesas-v3hsk-Add-reserved-memory-nodes.patch new file mode 100644 index 00000000..94a11f7e --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0312-arm64-dts-renesas-v3hsk-Add-reserved-memory-nodes.patch @@ -0,0 +1,53 @@ +From d5cd213aae89a74015614fb8882f8f84af13272e Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Sat, 27 Oct 2018 00:01:16 +0300 +Subject: [PATCH 132/211] arm64: dts: renesas: v3hsk: Add reserved memory nodes + +This adds reserved memory nodes. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts | 27 ++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +index dd14a41..eb7f03a 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +@@ -28,6 +28,33 @@ + reg = <0 0x48000000 0 0x78000000>; + }; + ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ /* device specific region for Lossy Decompression */ ++ lossy_decompress: linux,lossy_decompress { ++ no-map; ++ reg = <0x00000000 0x6c000000 0x0 0x03000000>; ++ }; ++ ++ /* global autoconfigured region for contiguous allocations */ ++ linux,cma { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x6f000000 0x0 0x10000000>; ++ linux,cma-default; ++ }; ++ ++ /* device specific region for contiguous allocations */ ++ linux,multimedia { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x7f000000 0x0 0x01000000>; ++ }; ++ }; ++ + hdmi-out { + compatible = "hdmi-connector"; + type = "a"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0313-arm64-dts-renesas-eagle-Add-reserved-memory-nodes.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0313-arm64-dts-renesas-eagle-Add-reserved-memory-nodes.patch new file mode 100644 index 00000000..e96842d1 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0313-arm64-dts-renesas-eagle-Add-reserved-memory-nodes.patch @@ -0,0 +1,53 @@ +From d8bc79f65b3dc567c2c56e015602467d6466ed1e Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Sat, 27 Oct 2018 00:02:28 +0300 +Subject: [PATCH 133/211] arm64: dts: renesas: eagle: Add reserved memory nodes + +This adds reserved memory nodes. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970-eagle.dts | 27 ++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +index a70337b..fcc6a83 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +@@ -30,6 +30,33 @@ + reg = <0x0 0x48000000 0x0 0x38000000>; + }; + ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ /* device specific region for Lossy Decompression */ ++ lossy_decompress: linux,lossy_decompress { ++ no-map; ++ reg = <0x00000000 0x6c000000 0x0 0x03000000>; ++ }; ++ ++ /* global autoconfigured region for contiguous allocations */ ++ linux,cma { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x6f000000 0x0 0x10000000>; ++ linux,cma-default; ++ }; ++ ++ /* device specific region for contiguous allocations */ ++ linux,multimedia { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x7f000000 0x0 0x01000000>; ++ }; ++ }; ++ + hdmi-out { + compatible = "hdmi-connector"; + type = "a"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0314-arm64-dts-renesas-condor-Add-reserved-memory-nodes.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0314-arm64-dts-renesas-condor-Add-reserved-memory-nodes.patch new file mode 100644 index 00000000..446e7dab --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0314-arm64-dts-renesas-condor-Add-reserved-memory-nodes.patch @@ -0,0 +1,54 @@ +From 2129083f43a92d53a7eeb5828f088cc4a595bba7 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Sat, 27 Oct 2018 00:03:04 +0300 +Subject: [PATCH 134/211] arm64: dts: renesas: condor: Add reserved memory + nodes + +This adds reserved memory nodes. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980-condor.dts | 27 +++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +index 330a1a1..c8bda5a 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +@@ -30,6 +30,33 @@ + reg = <0 0x48000000 0 0x78000000>; + }; + ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ /* device specific region for Lossy Decompression */ ++ lossy_decompress: linux,lossy_decompress { ++ no-map; ++ reg = <0x00000000 0x6c000000 0x0 0x03000000>; ++ }; ++ ++ /* global autoconfigured region for contiguous allocations */ ++ linux,cma { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x6f000000 0x0 0x10000000>; ++ linux,cma-default; ++ }; ++ ++ /* device specific region for contiguous allocations */ ++ linux,multimedia { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x7f000000 0x0 0x01000000>; ++ }; ++ }; ++ + d3_3v: regulator-0 { + compatible = "regulator-fixed"; + regulator-name = "D3.3V"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0315-arm64-dts-renesas-v3msk-Add-mmngr-and-mmngrbuf-nodes.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0315-arm64-dts-renesas-v3msk-Add-mmngr-and-mmngrbuf-nodes.patch new file mode 100644 index 00000000..68967ff2 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0315-arm64-dts-renesas-v3msk-Add-mmngr-and-mmngrbuf-nodes.patch @@ -0,0 +1,36 @@ +From 24aeecff3debd8fcd167979867cf6abc1e5ba329 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Sat, 27 Oct 2018 00:19:07 +0300 +Subject: [PATCH 135/211] arm64: dts: renesas: v3msk: Add mmngr and mmngrbuf + nodes + +This adds mmngr and mmngrbuf nodes. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +index 8e0dbd7..3deda9f 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +@@ -54,6 +54,15 @@ + }; + }; + ++ mmngr { ++ compatible = "renesas,mmngr"; ++ memory-region = <&lossy_decompress>; ++ }; ++ ++ mmngrbuf { ++ compatible = "renesas,mmngrbuf"; ++ }; ++ + osc5_clk: osc5-clock { + compatible = "fixed-clock"; + #clock-cells = <0>; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0316-arm64-dts-renesas-v3hsk-Add-mmngr-and-mmngrbuf-nodes.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0316-arm64-dts-renesas-v3hsk-Add-mmngr-and-mmngrbuf-nodes.patch new file mode 100644 index 00000000..d78b8f07 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0316-arm64-dts-renesas-v3hsk-Add-mmngr-and-mmngrbuf-nodes.patch @@ -0,0 +1,36 @@ +From 3a5d6b62e7d8c993e3bad5594119519e54a73e3c Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Sat, 27 Oct 2018 00:20:52 +0300 +Subject: [PATCH 136/211] arm64: dts: renesas: v3hsk: Add mmngr and mmngrbuf + nodes + +This adds mmngr and mmngrbuf nodes. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +index eb7f03a..4aa6b27 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +@@ -55,6 +55,15 @@ + }; + }; + ++ mmngr { ++ compatible = "renesas,mmngr"; ++ memory-region = <&lossy_decompress>; ++ }; ++ ++ mmngrbuf { ++ compatible = "renesas,mmngrbuf"; ++ }; ++ + hdmi-out { + compatible = "hdmi-connector"; + type = "a"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0317-arm64-dts-renesas-eagle-Add-mmngr-and-mmngrbuf-nodes.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0317-arm64-dts-renesas-eagle-Add-mmngr-and-mmngrbuf-nodes.patch new file mode 100644 index 00000000..92b60e89 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0317-arm64-dts-renesas-eagle-Add-mmngr-and-mmngrbuf-nodes.patch @@ -0,0 +1,36 @@ +From 816cc7d4c3a4cd8db18b57cc4c39d09de2277b84 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Sat, 27 Oct 2018 00:21:23 +0300 +Subject: [PATCH 137/211] arm64: dts: renesas: eagle: Add mmngr and mmngrbuf + nodes + +This adds mmngr and mmngrbuf nodes. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970-eagle.dts | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +index fcc6a83..a59fd32 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +@@ -57,6 +57,15 @@ + }; + }; + ++ mmngr { ++ compatible = "renesas,mmngr"; ++ memory-region = <&lossy_decompress>; ++ }; ++ ++ mmngrbuf { ++ compatible = "renesas,mmngrbuf"; ++ }; ++ + hdmi-out { + compatible = "hdmi-connector"; + type = "a"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0318-arm64-dts-renesas-condor-Add-mmngr-and-mmngrbuf-node.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0318-arm64-dts-renesas-condor-Add-mmngr-and-mmngrbuf-node.patch new file mode 100644 index 00000000..4fdc3f1d --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0318-arm64-dts-renesas-condor-Add-mmngr-and-mmngrbuf-node.patch @@ -0,0 +1,36 @@ +From 35eb2b4afcd348ca46c25e4c0f6fbac92193c9e9 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Sat, 27 Oct 2018 00:21:48 +0300 +Subject: [PATCH 138/211] arm64: dts: renesas: condor: Add mmngr and mmngrbuf + nodes + +This adds mmngr and mmngrbuf nodes. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980-condor.dts | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +index c8bda5a..9965b75 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +@@ -57,6 +57,15 @@ + }; + }; + ++ mmngr { ++ compatible = "renesas,mmngr"; ++ memory-region = <&lossy_decompress>; ++ }; ++ ++ mmngrbuf { ++ compatible = "renesas,mmngrbuf"; ++ }; ++ + d3_3v: regulator-0 { + compatible = "regulator-fixed"; + regulator-name = "D3.3V"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0319-arm64-dts-renesas-v3msk-Add-vspm_if-node.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0319-arm64-dts-renesas-v3msk-Add-vspm_if-node.patch new file mode 100644 index 00000000..8c7b685d --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0319-arm64-dts-renesas-v3msk-Add-vspm_if-node.patch @@ -0,0 +1,30 @@ +From 947be79b6dfaa755efa98533f790b6edcf38321e Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Sat, 27 Oct 2018 00:24:04 +0300 +Subject: [PATCH 139/211] arm64: dts: renesas: v3msk: Add vspm_if node + +This adds vspm_if node. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +index 3deda9f..6847381 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +@@ -63,6 +63,10 @@ + compatible = "renesas,mmngrbuf"; + }; + ++ vspm_if { ++ compatible = "renesas,vspm_if"; ++ }; ++ + osc5_clk: osc5-clock { + compatible = "fixed-clock"; + #clock-cells = <0>; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0320-arm64-dts-renesas-v3hsk-Add-vspm_if-node.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0320-arm64-dts-renesas-v3hsk-Add-vspm_if-node.patch new file mode 100644 index 00000000..897277c0 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0320-arm64-dts-renesas-v3hsk-Add-vspm_if-node.patch @@ -0,0 +1,30 @@ +From b643f0f2b529e074683d884fd871ee7e64b2b337 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Sat, 27 Oct 2018 00:25:29 +0300 +Subject: [PATCH 140/211] arm64: dts: renesas: v3hsk: Add vspm_if node + +This adds vspm_if node. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +index 4aa6b27..51607d4 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +@@ -64,6 +64,10 @@ + compatible = "renesas,mmngrbuf"; + }; + ++ vspm_if { ++ compatible = "renesas,vspm_if"; ++ }; ++ + hdmi-out { + compatible = "hdmi-connector"; + type = "a"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0321-arm64-dts-renesas-eagle-Add-vspm_if-node.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0321-arm64-dts-renesas-eagle-Add-vspm_if-node.patch new file mode 100644 index 00000000..bbd9270c --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0321-arm64-dts-renesas-eagle-Add-vspm_if-node.patch @@ -0,0 +1,30 @@ +From 0bacbca79cc21cfe3a48c82abc0ed0c8a22aaba0 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Sat, 27 Oct 2018 00:25:47 +0300 +Subject: [PATCH 141/211] arm64: dts: renesas: eagle: Add vspm_if node + +This adds vspm_if node. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970-eagle.dts | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +index a59fd32..38e6aea 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +@@ -66,6 +66,10 @@ + compatible = "renesas,mmngrbuf"; + }; + ++ vspm_if { ++ compatible = "renesas,vspm_if"; ++ }; ++ + hdmi-out { + compatible = "hdmi-connector"; + type = "a"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0322-arm64-dts-renesas-condor-Add-vspm_if-node.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0322-arm64-dts-renesas-condor-Add-vspm_if-node.patch new file mode 100644 index 00000000..38118f14 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0322-arm64-dts-renesas-condor-Add-vspm_if-node.patch @@ -0,0 +1,30 @@ +From 18f60135619bf95bd51d4bb98a86cd5d00bb0513 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Sat, 27 Oct 2018 00:26:01 +0300 +Subject: [PATCH 142/211] arm64: dts: renesas: condor: Add vspm_if node + +This adds vspm_if node. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980-condor.dts | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +index 9965b75..5bd0640 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +@@ -66,6 +66,10 @@ + compatible = "renesas,mmngrbuf"; + }; + ++ vspm_if { ++ compatible = "renesas,vspm_if"; ++ }; ++ + d3_3v: regulator-0 { + compatible = "regulator-fixed"; + regulator-name = "D3.3V"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0323-arm64-dts-renesas-eagle-Add-Dialog-DA9063-MFD.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0323-arm64-dts-renesas-eagle-Add-Dialog-DA9063-MFD.patch new file mode 100644 index 00000000..24277344 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0323-arm64-dts-renesas-eagle-Add-Dialog-DA9063-MFD.patch @@ -0,0 +1,56 @@ +From 7384b86794cb38745ef06493527563406898387f Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Thu, 1 Nov 2018 16:28:11 +0300 +Subject: [PATCH 143/211] arm64: dts: renesas: eagle: Add Dialog DA9063 MFD + +This adds Dialog DA9063 device nodes. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970-eagle.dts | 30 ++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +index 38e6aea..abf5470 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +@@ -236,6 +236,36 @@ + }; + }; + }; ++ ++ pmic@5A { ++ compatible = "dlg,da9063"; ++ reg = <0x5A>; ++ interrupt-parent = <&intc_ex>; ++ interrupts = <0 IRQ_TYPE_LEVEL_LOW>; ++ interrupt-controller; ++ ++ rtc { ++ compatible = "dlg,da9063-rtc"; ++ }; ++ ++ wdt { ++ compatible = "dlg,da9063-watchdog"; ++ }; ++ ++ regulators { ++ DA9063_LDO11: bmem { ++ regulator-name = "bmem"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ }; ++ ++ onkey { ++ compatible = "dlg,da9063-onkey"; ++ }; ++ }; + }; + + &i2c3 { +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0324-arm64-dts-renesas-Add-r8a77970-eagle-function-suppor.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0324-arm64-dts-renesas-Add-r8a77970-eagle-function-suppor.patch new file mode 100644 index 00000000..1dc5dbde --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0324-arm64-dts-renesas-Add-r8a77970-eagle-function-suppor.patch @@ -0,0 +1,41 @@ +From 692f5ca25d74fae4e01927a12df571227d644234 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Thu, 1 Nov 2018 17:21:09 +0300 +Subject: [PATCH 144/211] arm64: dts: renesas: Add r8a77970-eagle-function + support + +This adds r8a77970-eagle-function device tree support. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/Makefile | 1 + + arch/arm64/boot/dts/renesas/r8a77970-eagle-function.dts | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile +index 294d38a..1714f94 100644 +--- a/arch/arm64/boot/dts/renesas/Makefile ++++ b/arch/arm64/boot/dts/renesas/Makefile +@@ -33,5 +33,6 @@ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-vb2.dtb r8a7795-es1-h3ulcb-vb2.dtb + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-vb2.1.dtb r8a7795-h3ulcb-4x2g-vb2.1.dtb + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-vbm.dtb r8a7795-es1-h3ulcb-vbm.dtb r8a7795-h3ulcb-4x2g-vbm.dtb + dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-m3nulcb-kf.dtb ++dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-eagle-function.dtb + + always := $(dtb-y) +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-eagle-function.dts b/arch/arm64/boot/dts/renesas/r8a77970-eagle-function.dts +index 9043a07..dab17bf 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-eagle-function.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-eagle-function.dts +@@ -47,7 +47,7 @@ + }; + }; + +-&sdhi2 { ++&mmc0 { + /* used for on-board eMMC */ + pinctrl-0 = <&sdhi2_pins_3v3>; + pinctrl-1 = <&sdhi2_pins_1v8>; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0325-arm64-dts-renesas-Add-r8a77970-es1-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0325-arm64-dts-renesas-Add-r8a77970-es1-support.patch new file mode 100644 index 00000000..834ad7e7 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0325-arm64-dts-renesas-Add-r8a77970-es1-support.patch @@ -0,0 +1,131 @@ +From 469ecb40691eae805c28b6f821f1b6351c292008 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Thu, 1 Nov 2018 17:23:12 +0300 +Subject: [PATCH 145/211] arm64: dts: renesas: Add r8a77970-es1 support + +This adds r8a77970-es1 device tree support. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/Makefile | 2 ++ + arch/arm64/boot/dts/renesas/r8a77970-es1.dtsi | 22 +++++++++++----------- + 2 files changed, 13 insertions(+), 11 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile +index 1714f94..dad071d 100644 +--- a/arch/arm64/boot/dts/renesas/Makefile ++++ b/arch/arm64/boot/dts/renesas/Makefile +@@ -34,5 +34,7 @@ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-vb2.1.dtb r8a7795-h3ulcb-4x2g-vb2.1 + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-vbm.dtb r8a7795-es1-h3ulcb-vbm.dtb r8a7795-h3ulcb-4x2g-vbm.dtb + dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-m3nulcb-kf.dtb + dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-eagle-function.dtb ++dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-es1-eagle.dtb r8a77970-es1-eagle-function.dtb ++dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-es1-v3msk.dtb + + always := $(dtb-y) +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-es1.dtsi b/arch/arm64/boot/dts/renesas/r8a77970-es1.dtsi +index dab9adc..74a9243 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-es1.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77970-es1.dtsi +@@ -17,7 +17,7 @@ + reg = <0 0xffa00000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 830>; +- power-domains = <&sysc R8A7797_PD_A3IR>; ++ power-domains = <&sysc R8A77970_PD_A3IR>; + interrupt-controller; + #interrupt-cells = <1>; + }; +@@ -28,7 +28,7 @@ + interrupt-parent = <&imp_distributer>; + interrupts = <0>; + clocks = <&cpg CPG_MOD 827>; +- power-domains = <&sysc R8A7797_PD_A2IR0>; ++ power-domains = <&sysc R8A77970_PD_A2IR0>; + }; + + imp1 { +@@ -37,7 +37,7 @@ + interrupt-parent = <&imp_distributer>; + interrupts = <1>; + clocks = <&cpg CPG_MOD 826>; +- power-domains = <&sysc R8A7797_PD_A2IR1>; ++ power-domains = <&sysc R8A77970_PD_A2IR1>; + }; + + imp2 { +@@ -46,7 +46,7 @@ + interrupt-parent = <&imp_distributer>; + interrupts = <2>; + clocks = <&cpg CPG_MOD 825>; +- power-domains = <&sysc R8A7797_PD_A2IR2>; ++ power-domains = <&sysc R8A77970_PD_A2DP>; + }; + + imp3 { +@@ -55,7 +55,7 @@ + interrupt-parent = <&imp_distributer>; + interrupts = <3>; + clocks = <&cpg CPG_MOD 824>; +- power-domains = <&sysc R8A7797_PD_A2IR3>; ++ power-domains = <&sysc R8A77970_PD_A2CN>; + }; + + impsc0 { +@@ -64,7 +64,7 @@ + interrupt-parent = <&imp_distributer>; + interrupts = <4>; + clocks = <&cpg CPG_MOD 829>; +- power-domains = <&sysc R8A7797_PD_A2SC0>; ++ power-domains = <&sysc R8A77970_PD_A2SC0>; + }; + + impsc1 { +@@ -73,7 +73,7 @@ + interrupt-parent = <&imp_distributer>; + interrupts = <5>; + clocks = <&cpg CPG_MOD 828>; +- power-domains = <&sysc R8A7797_PD_A2SC1>; ++ power-domains = <&sysc R8A77970_PD_A2SC1>; + }; + + impdm0 { +@@ -82,7 +82,7 @@ + interrupt-parent = <&imp_distributer>; + interrupts = <16>; + clocks = <&cpg CPG_MOD 830>; +- power-domains = <&sysc R8A7797_PD_A3IR>; ++ power-domains = <&sysc R8A77970_PD_A3IR>; + }; + + impdm1 { +@@ -92,7 +92,7 @@ + interrupt-parent = <&imp_distributer>; + interrupts = <17>; + clocks = <&cpg CPG_MOD 830>; +- power-domains = <&sysc R8A7797_PD_A3IR>; ++ power-domains = <&sysc R8A77970_PD_A3IR>; + }; + + imppsc0 { +@@ -101,7 +101,7 @@ + interrupt-parent = <&imp_distributer>; + interrupts = <12>; + clocks = <&cpg CPG_MOD 830>; +- power-domains = <&sysc R8A7797_PD_A3IR>; ++ power-domains = <&sysc R8A77970_PD_A3IR>; + }; + + /delete-node/impcnn0; +@@ -110,7 +110,7 @@ + compatible = "renesas,impx4-memory"; + reg = <0 0xed000000 0 0xe0000>; + clocks = <&cpg CPG_MOD 830>; +- power-domains = <&sysc R8A7797_PD_A3IR>; ++ power-domains = <&sysc R8A77970_PD_A3IR>; + }; + }; + }; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0326-arm64-dts-renesas-Add-r8a77970-v3msk-view-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0326-arm64-dts-renesas-Add-r8a77970-v3msk-view-support.patch new file mode 100644 index 00000000..fc28259b --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0326-arm64-dts-renesas-Add-r8a77970-v3msk-view-support.patch @@ -0,0 +1,39 @@ +From 9112a9be8c58ccb96c2d261e63d1351120514588 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Thu, 1 Nov 2018 17:25:30 +0300 +Subject: [PATCH 146/211] arm64: dts: renesas: Add r8a77970-v3msk-view support + +This adds r8a77970-v3msk-view device tree support. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/Makefile | 1 + + arch/arm64/boot/dts/renesas/r8a77970-v3msk-view.dts | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile +index dad071d..3e52401 100644 +--- a/arch/arm64/boot/dts/renesas/Makefile ++++ b/arch/arm64/boot/dts/renesas/Makefile +@@ -36,5 +36,6 @@ dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-m3nulcb-kf.dtb + dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-eagle-function.dtb + dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-es1-eagle.dtb r8a77970-es1-eagle-function.dtb + dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-es1-v3msk.dtb ++dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-view.dtb r8a77970-es1-v3msk-view.dtb + + always := $(dtb-y) +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk-view.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk-view.dts +index 75631fb..2197bbe 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-v3msk-view.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk-view.dts +@@ -9,6 +9,7 @@ + */ + + #include "r8a77970-v3msk.dts" ++#include + + / { + model = "Renesas V3MSK View board based on r8a7797"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0327-arm64-dts-renesas-Add-r8a77970-v3msk-kf-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0327-arm64-dts-renesas-Add-r8a77970-v3msk-kf-support.patch new file mode 100644 index 00000000..d1b15e56 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0327-arm64-dts-renesas-Add-r8a77970-v3msk-kf-support.patch @@ -0,0 +1,39 @@ +From 960431f5ff91366a3625d4696d83617e3d8b9419 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Thu, 1 Nov 2018 17:28:40 +0300 +Subject: [PATCH 147/211] arm64: dts: renesas: Add r8a77970-v3msk-kf support + +This adds r8a77970-v3msk-kf device tree support. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/Makefile | 1 + + arch/arm64/boot/dts/renesas/r8a77970-v3msk-kf.dts | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile +index 3e52401..98d1479 100644 +--- a/arch/arm64/boot/dts/renesas/Makefile ++++ b/arch/arm64/boot/dts/renesas/Makefile +@@ -37,5 +37,6 @@ dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-eagle-function.dtb + dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-es1-eagle.dtb r8a77970-es1-eagle-function.dtb + dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-es1-v3msk.dtb + dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-view.dtb r8a77970-es1-v3msk-view.dtb ++dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-kf.dtb r8a77970-es1-v3msk-kf.dtb + + always := $(dtb-y) +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk-kf.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk-kf.dts +index 29ae871..8c001a5 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-v3msk-kf.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk-kf.dts +@@ -10,6 +10,7 @@ + */ + + #include "r8a77970-v3msk.dts" ++#include + + / { + model = "Renesas V3MSK Kingfisher board based on r8a7797"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0328-arm64-dts-renesas-Add-r8a77970-v3msk-vbm-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0328-arm64-dts-renesas-Add-r8a77970-v3msk-vbm-support.patch new file mode 100644 index 00000000..2c2015cc --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0328-arm64-dts-renesas-Add-r8a77970-v3msk-vbm-support.patch @@ -0,0 +1,44 @@ +From 7e5d40d35e34010d650be7cb9a4d6aebca14cd73 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Thu, 1 Nov 2018 17:30:38 +0300 +Subject: [PATCH 148/211] arm64: dts: renesas: Add r8a77970-v3msk-vbm support + +This adds r8a77970-v3msk-vbm device tree support. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/Makefile | 2 ++ + arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm.dts | 3 ++- + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile +index 98d1479..1679e8c 100644 +--- a/arch/arm64/boot/dts/renesas/Makefile ++++ b/arch/arm64/boot/dts/renesas/Makefile +@@ -38,5 +38,7 @@ dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-es1-eagle.dtb r8a77970-es1-eagle-functio + dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-es1-v3msk.dtb + dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-view.dtb r8a77970-es1-v3msk-view.dtb + dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-kf.dtb r8a77970-es1-v3msk-kf.dtb ++dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-vbm.dtb r8a77970-es1-v3msk-vbm.dtb ++dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-vbm-v2.dtb r8a77970-es1-v3msk-vbm-v2.dtb + + always := $(dtb-y) +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm.dts +index a37ccaa..485de2a 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm.dts +@@ -9,9 +9,10 @@ + */ + + #include "r8a77970-v3msk.dts" ++#include + + / { +- model = "Renesas V3MSK Videobox Mini board based on r8a7797"; ++ model = "Renesas V3MSK Videobox Mini board based on r8a77970"; + + aliases { + serial1 = &scif3; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0329-arm64-dts-renesas-Add-r8a77970-v3mzf-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0329-arm64-dts-renesas-Add-r8a77970-v3mzf-support.patch new file mode 100644 index 00000000..534ac343 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0329-arm64-dts-renesas-Add-r8a77970-v3mzf-support.patch @@ -0,0 +1,114 @@ +From fa7923d1b823ee09defaf2f6740955f709f0f419 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Thu, 1 Nov 2018 17:34:32 +0300 +Subject: [PATCH 149/211] arm64: dts: renesas: Add r8a77970-v3mzf support + +This adds r8a77970-v3mzf device tree support. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/Makefile | 1 + + arch/arm64/boot/dts/renesas/r8a77970-v3mzf.dts | 34 +++++++++++++++----------- + 2 files changed, 21 insertions(+), 14 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile +index 1679e8c..7698983d 100644 +--- a/arch/arm64/boot/dts/renesas/Makefile ++++ b/arch/arm64/boot/dts/renesas/Makefile +@@ -40,5 +40,6 @@ dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-view.dtb r8a77970-es1-v3msk-view.d + dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-kf.dtb r8a77970-es1-v3msk-kf.dtb + dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-vbm.dtb r8a77970-es1-v3msk-vbm.dtb + dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-vbm-v2.dtb r8a77970-es1-v3msk-vbm-v2.dtb ++dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3mzf.dtb + + always := $(dtb-y) +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3mzf.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3mzf.dts +index 2087364..71a765a 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-v3mzf.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-v3mzf.dts +@@ -13,8 +13,8 @@ + #include + + / { +- model = "Renesas V3MZF board based on r8a7797"; +- compatible = "renesas,v3mzf", "renesas,r8a7797"; ++ model = "Renesas V3MZF board based on r8a77970"; ++ compatible = "renesas,v3mzf", "renesas,r8a77970"; + + aliases { + serial0 = &scif0; +@@ -22,7 +22,6 @@ + }; + + chosen { +- bootargs = "ignore_loglevel rw root=/dev/nfs ip=dhcp"; + stdout-path = "serial0:115200n8"; + }; + +@@ -87,7 +86,7 @@ + + port { + lvds_in: endpoint { +- remote-endpoint = <&du_out_lvds0>; ++ remote-endpoint = <&lvds0_out>; + }; + }; + }; +@@ -188,15 +187,10 @@ + }; + + &du { ++ clocks = <&cpg CPG_MOD 724>, ++ <&dclkin_p0>; ++ clock-names = "du.0", "dclkin.0"; + status = "okay"; +- +- ports { +- port@0 { +- endpoint { +- remote-endpoint = <&lvds_in>; +- }; +- }; +- }; + }; + + &extal_clk { +@@ -306,6 +300,18 @@ + }; + }; + ++&lvds0 { ++ status = "okay"; ++ ++ ports { ++ port@1 { ++ lvds0_out: endpoint { ++ remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++}; ++ + &msiof2 { + pinctrl-0 = <&msiof2_pins>; + pinctrl-names = "default"; +@@ -395,7 +401,7 @@ + status = "okay"; + }; + +-&sdhi2 { ++&mmc0 { + /* used for on-board eMMC */ + pinctrl-0 = <&sdhi2_pins_3v3>; + pinctrl-names = "default"; +@@ -437,6 +443,6 @@ + }; + }; + +-&wdt0 { ++&rwdt { + status = "okay"; + }; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0330-arm64-dts-renesas-Add-r8a77980-v3hsk-vbm-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0330-arm64-dts-renesas-Add-r8a77980-v3hsk-vbm-support.patch new file mode 100644 index 00000000..d83e320f --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0330-arm64-dts-renesas-Add-r8a77980-v3hsk-vbm-support.patch @@ -0,0 +1,57 @@ +From 78e88f79266f3f8f954b308bd0274bf717a340b1 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Thu, 1 Nov 2018 17:39:35 +0300 +Subject: [PATCH 150/211] arm64: dts: renesas: Add r8a77980-v3hsk-vbm support + +This adds r8a77980-v3hsk-vbm and r8a77980-v3hsk-vbm-v2 +device tree support. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/Makefile | 2 ++ + arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm-v2.dts | 2 +- + arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm.dts | 3 ++- + 3 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile +index 7698983d..cac4b75 100644 +--- a/arch/arm64/boot/dts/renesas/Makefile ++++ b/arch/arm64/boot/dts/renesas/Makefile +@@ -41,5 +41,7 @@ dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-kf.dtb r8a77970-es1-v3msk-kf.dtb + dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-vbm.dtb r8a77970-es1-v3msk-vbm.dtb + dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-vbm-v2.dtb r8a77970-es1-v3msk-vbm-v2.dtb + dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3mzf.dtb ++dtb-$(CONFIG_ARCH_R8A77980) += r8a77980-v3hsk-vbm.dtb ++dtb-$(CONFIG_ARCH_R8A77980) += r8a77980-v3hsk-vbm-v2.dtb + + always := $(dtb-y) +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm-v2.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm-v2.dts +index 56d4253..7a3f381 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm-v2.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm-v2.dts +@@ -8,7 +8,7 @@ + * kind, whether express or implied. + */ + +-#include "r8a7798-v3hsk-vbm.dts" ++#include "r8a77980-v3hsk-vbm.dts" + + / { + model = "Renesas V3HSK Videobox Mini board V2 based on r8a7798"; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm.dts +index 9a54554..1b0649f 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm.dts +@@ -8,7 +8,8 @@ + * kind, whether express or implied. + */ + +-#include "r8a7798-v3hsk.dts" ++#include "r8a77980-v3hsk.dts" ++#include + + / { + model = "Renesas V3HSK Videobox Mini board based on r8a7798"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0331-arm64-dts-renesas-r8a779-7-8-0-Add-IMP-devices.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0331-arm64-dts-renesas-r8a779-7-8-0-Add-IMP-devices.patch new file mode 100644 index 00000000..61bb917e --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0331-arm64-dts-renesas-r8a779-7-8-0-Add-IMP-devices.patch @@ -0,0 +1,321 @@ +From 24e14fe7c9ca79f3243694288e690780d720ca66 Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Sun, 4 Nov 2018 13:27:11 +0300 +Subject: [PATCH 151/211] arm64: dts: renesas: r8a779[7|8]0: Add IMP devices. + +--- + arch/arm64/boot/dts/renesas/r8a77970.dtsi | 107 ++++++++++++++++++ + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 179 ++++++++++++++++++++++++++++++ + 2 files changed, 286 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +index 2585ba5..aa4d3d6 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +@@ -861,6 +861,113 @@ + status = "disabled"; + }; + ++ imp_distributer: impdes0 { ++ compatible = "renesas,impx5+-distributer"; ++ reg = <0 0xffa00000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 830>; ++ power-domains = <&sysc R8A77970_PD_A3IR>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ imp0 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff900000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <0>; ++ clocks = <&cpg CPG_MOD 827>; ++ power-domains = <&sysc R8A77970_PD_A2IR0>; ++ }; ++ ++ imp1 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff920000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <1>; ++ clocks = <&cpg CPG_MOD 827>; ++ power-domains = <&sysc R8A77970_PD_A2IR0>; ++ }; ++ ++ imp2 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff940000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <2>; ++ clocks = <&cpg CPG_MOD 826>; ++ power-domains = <&sysc R8A77970_PD_A2IR1>; ++ }; ++ ++ imp3 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff960000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <3>; ++ clocks = <&cpg CPG_MOD 826>; ++ power-domains = <&sysc R8A77970_PD_A2IR1>; ++ }; ++ ++ impsc0 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff980000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <4>; ++ clocks = <&cpg CPG_MOD 829>; ++ power-domains = <&sysc R8A77970_PD_A2SC0>; ++ }; ++ ++ impsc1 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff990000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <5>; ++ clocks = <&cpg CPG_MOD 828>; ++ power-domains = <&sysc R8A77970_PD_A2SC1>; ++ }; ++ ++ impdm0 { ++ compatible = "renesas,impx5-dmac"; ++ reg = <0 0xffa10000 0 0x1000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <6>; ++ clocks = <&cpg CPG_MOD 825>; ++ power-domains = <&sysc R8A77970_PD_A2DP>; ++ }; ++ ++ impdm1 { ++ compatible = "renesas,impx5-dmac"; ++ reg = <0 0xffa11000 0 0x1000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <7>; ++ clocks = <&cpg CPG_MOD 825>; ++ power-domains = <&sysc R8A77970_PD_A2DP>; ++ }; ++ ++ imppsc0 { ++ compatible = "renesas,impx5+-psc"; ++ reg = <0 0xffa20000 0 0x4000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <8>; ++ clocks = <&cpg CPG_MOD 825>; ++ power-domains = <&sysc R8A77970_PD_A2DP>; ++ }; ++ ++ impcnn0 { ++ compatible = "renesas,impx5+-cnn"; ++ reg = <0 0xff9e0000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <9>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A77970_PD_A2CN>; ++ }; ++ ++ impc0 { ++ compatible = "renesas,impx4-memory"; ++ reg = <0 0xed000000 0 0xe0000>; ++ clocks = <&cpg CPG_MOD 830>; ++ power-domains = <&sysc R8A77970_PD_A3IR>; ++ }; ++ + imr-lx4@fe860000 { + compatible = "renesas,r8a77970-imr-lx4", + "renesas,imr-lx4"; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index 8fba9c7..87490ee 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -1034,6 +1034,185 @@ + status = "disabled"; + }; + ++ imp_distributer: impdes0 { ++ compatible = "renesas,impx5+-distributer"; ++ reg = <0 0xffa00000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 830>; ++ power-domains = <&sysc R8A77980_PD_A3IR>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ imp0 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff900000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <0>; ++ clocks = <&cpg CPG_MOD 827>; ++ power-domains = <&sysc R8A77980_PD_A2IR0>; ++ }; ++ ++ imp1 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff920000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <1>; ++ clocks = <&cpg CPG_MOD 826>; ++ power-domains = <&sysc R8A77980_PD_A2IR1>; ++ }; ++ ++ imp2 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff940000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <2>; ++ clocks = <&cpg CPG_MOD 825>; ++ power-domains = <&sysc R8A77980_PD_A2IR2>; ++ }; ++ ++ imp3 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff960000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <3>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A77980_PD_A2IR3>; ++ }; ++ ++ imp4 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xffa80000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <4>; ++ clocks = <&cpg CPG_MOD 521>; ++ power-domains = <&sysc R8A77980_PD_A2IR4>; ++ }; ++ ++ impslc0 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff9c0000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <5>; ++ clocks = <&cpg CPG_MOD 500>; ++ power-domains = <&sysc R8A77980_PD_A2IR5>; ++ }; ++ ++ impsc0 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff980000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <6>; ++ clocks = <&cpg CPG_MOD 829>; ++ power-domains = <&sysc R8A77980_PD_A2SC0>; ++ }; ++ ++ impsc1 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff990000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <7>; ++ clocks = <&cpg CPG_MOD 828>; ++ power-domains = <&sysc R8A77980_PD_A2SC1>; ++ }; ++ ++ impsc2 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff9a0000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <8>; ++ clocks = <&cpg CPG_MOD 531>; ++ power-domains = <&sysc R8A77980_PD_A2SC2>; ++ }; ++ ++ impsc3 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff9b0000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <9>; ++ clocks = <&cpg CPG_MOD 529>; ++ power-domains = <&sysc R8A77980_PD_A2SC3>; ++ }; ++ ++ impsc4 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xffa40000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <10>; ++ clocks = <&cpg CPG_MOD 528>; ++ power-domains = <&sysc R8A77980_PD_A2SC4>; ++ }; ++ ++ impdm0 { ++ compatible = "renesas,impx5-dmac"; ++ reg = <0 0xffa10000 0 0x1000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <11>; ++ clocks = <&cpg CPG_MOD 527>; ++ power-domains = <&sysc R8A77980_PD_A2DP0>; ++ }; ++ ++ impdm1 { ++ compatible = "renesas,impx5-dmac"; ++ reg = <0 0xffa11000 0 0x1000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <12>; ++ clocks = <&cpg CPG_MOD 527>; ++ power-domains = <&sysc R8A77980_PD_A2DP0>; ++ }; ++ ++ impdm2 { ++ compatible = "renesas,impx5-dmac"; ++ reg = <0 0xffa14000 0 0x1000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <13>; ++ clocks = <&cpg CPG_MOD 526>; ++ power-domains = <&sysc R8A77980_PD_A2DP1>; ++ }; ++ ++ impdm3 { ++ compatible = "renesas,impx5-dmac"; ++ reg = <0 0xffa15000 0 0x1000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <14>; ++ clocks = <&cpg CPG_MOD 526>; ++ power-domains = <&sysc R8A77980_PD_A2DP1>; ++ }; ++ ++ imppsc0 { ++ compatible = "renesas,impx5+-psc"; ++ reg = <0 0xffa20000 0 0x4000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <15>; ++ clocks = <&cpg CPG_MOD 525>; ++ power-domains = <&sysc R8A77980_PD_A2DP0>; ++ }; ++ ++ imppsc1 { ++ compatible = "renesas,impx5+-psc"; ++ reg = <0 0xffa24000 0 0x4000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <16>; ++ clocks = <&cpg CPG_MOD 524>; ++ power-domains = <&sysc R8A77980_PD_A2DP1>; ++ }; ++ ++ impcnn0 { ++ compatible = "renesas,impx5+-cnn"; ++ reg = <0 0xff9e0000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <17>; ++ clocks = <&cpg CPG_MOD 831>; ++ power-domains = <&sysc R8A77980_PD_A2CN>; ++ }; ++ ++ impc0 { ++ compatible = "renesas,impx4-memory"; ++ reg = <0 0xed000000 0 0x200000>; ++ clocks = <&cpg CPG_MOD 830>; ++ power-domains = <&sysc R8A77980_PD_A3IR>; ++ }; ++ + imr-lx4@fe860000 { + compatible = "renesas,r8a77980-imr-lx4", + "renesas,imr-lx4"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0332-arm64-dts-renesas-r8a77980-Add-VIP-nodes.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0332-arm64-dts-renesas-r8a77980-Add-VIP-nodes.patch new file mode 100644 index 00000000..a6c79aa6 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0332-arm64-dts-renesas-r8a77980-Add-VIP-nodes.patch @@ -0,0 +1,183 @@ +From a85326363b5c3f0608dcef3462b598507f405c19 Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Sun, 4 Nov 2018 13:30:25 +0300 +Subject: [PATCH 152/211] arm64: dts: renesas: r8a77980: Add VIP nodes. + +--- + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 160 ++++++++++++++++++++++++++++++ + 1 file changed, 160 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index 87490ee..947cf7a 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -1271,6 +1271,166 @@ + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + }; + ++ vip_disp_status { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a00000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 101>; ++ power-domains = <&sysc R8A77980_PD_A3VIP0>; ++ }; ++ ++ vip_disp_error { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a00000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 101>; ++ power-domains = <&sysc R8A77980_PD_A3VIP0>; ++ }; ++ ++ vip_umf_status { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a10000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 102>; ++ power-domains = <&sysc R8A77980_PD_A3VIP1>; ++ }; ++ ++ vip_umf_error { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a10000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 102>; ++ power-domains = <&sysc R8A77980_PD_A3VIP1>; ++ }; ++ ++ vip_smd_ps_status { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a20000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 1102>; ++ power-domains = <&sysc R8A77980_PD_A3VIP1>; ++ }; ++ ++ vip_smd_ps_error { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a20000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 1102>; ++ power-domains = <&sysc R8A77980_PD_A3VIP1>; ++ }; ++ ++ vip_smd_est_status { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a30000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 1101>; ++ power-domains = <&sysc R8A77980_PD_A3VIP1>; ++ }; ++ ++ vip_smd_est_error { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a30000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 1101>; ++ power-domains = <&sysc R8A77980_PD_A3VIP1>; ++ }; ++ ++ vip_smd_post_status { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a40000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 1100>; ++ power-domains = <&sysc R8A77980_PD_A3VIP1>; ++ }; ++ ++ vip_smd_post_error { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a40000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 1100>; ++ power-domains = <&sysc R8A77980_PD_A3VIP1>; ++ }; ++ ++ vip_cle0_status { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a50000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 1004>; ++ power-domains = <&sysc R8A77980_PD_A3VIP2>; ++ }; ++ ++ vip_cle0_error { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a50000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 1004>; ++ power-domains = <&sysc R8A77980_PD_A3VIP2>; ++ }; ++ ++ vip_cle1_status { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a60000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 1003>; ++ power-domains = <&sysc R8A77980_PD_A3VIP2>; ++ }; ++ ++ vip_cle1_error { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a60000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 1003>; ++ power-domains = <&sysc R8A77980_PD_A3VIP2>; ++ }; ++ ++ vip_cle2_status { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a70000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 1002>; ++ power-domains = <&sysc R8A77980_PD_A3VIP2>; ++ }; ++ ++ vip_cle2_error { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a70000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 1002>; ++ power-domains = <&sysc R8A77980_PD_A3VIP2>; ++ }; ++ ++ vip_cle3_status { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a80000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 1001>; ++ power-domains = <&sysc R8A77980_PD_A3VIP2>; ++ }; ++ ++ vip_cle3_error { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a80000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 1001>; ++ power-domains = <&sysc R8A77980_PD_A3VIP2>; ++ }; ++ ++ vip_cle4_status { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a90000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 1000>; ++ power-domains = <&sysc R8A77980_PD_A3VIP2>; ++ }; ++ ++ vip_cle4_error { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a90000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 1000>; ++ power-domains = <&sysc R8A77980_PD_A3VIP2>; ++ }; ++ + isp@fec00000 { + compatible = "renesas,isp-r8a77980"; + reg = <0 0xfec00000 0 0x20000>, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0333-arm64-dts-renesas-r8a779-78-0-Add-linux-multimedia-r.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0333-arm64-dts-renesas-r8a779-78-0-Add-linux-multimedia-r.patch new file mode 100644 index 00000000..a39b0763 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0333-arm64-dts-renesas-r8a779-78-0-Add-linux-multimedia-r.patch @@ -0,0 +1,108 @@ +From 306eb2163f67cb89d492094425ec3c1e385b8b6a Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Mon, 5 Nov 2018 13:49:54 +0300 +Subject: [PATCH 153/211] arm64: dts: renesas: r8a779[78]0: Add + "linux,multimedia" region to mmngr + +This adds "linux,multimedia" reserved memory region to mmngr regions +on all R-Car V3x boards which is needed for rgnmm device registration. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970-eagle.dts | 4 ++-- + arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts | 4 ++-- + arch/arm64/boot/dts/renesas/r8a77980-condor.dts | 4 ++-- + arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts | 4 ++-- + 4 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +index abf5470..dd484d5 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +@@ -50,7 +50,7 @@ + }; + + /* device specific region for contiguous allocations */ +- linux,multimedia { ++ mmp_reserved: linux,multimedia { + compatible = "shared-dma-pool"; + reusable; + reg = <0x00000000 0x7f000000 0x0 0x01000000>; +@@ -59,7 +59,7 @@ + + mmngr { + compatible = "renesas,mmngr"; +- memory-region = <&lossy_decompress>; ++ memory-region = <&mmp_reserved>, <&lossy_decompress>; + }; + + mmngrbuf { +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +index 6847381..4cc11c9 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +@@ -47,7 +47,7 @@ + }; + + /* device specific region for contiguous allocations */ +- linux,multimedia { ++ mmp_reserved: linux,multimedia { + compatible = "shared-dma-pool"; + reusable; + reg = <0x00000000 0x7f000000 0x0 0x01000000>; +@@ -56,7 +56,7 @@ + + mmngr { + compatible = "renesas,mmngr"; +- memory-region = <&lossy_decompress>; ++ memory-region = <&mmp_reserved>, <&lossy_decompress>; + }; + + mmngrbuf { +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +index 5bd0640..f3b7ebe 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +@@ -50,7 +50,7 @@ + }; + + /* device specific region for contiguous allocations */ +- linux,multimedia { ++ mmp_reserved: linux,multimedia { + compatible = "shared-dma-pool"; + reusable; + reg = <0x00000000 0x7f000000 0x0 0x01000000>; +@@ -59,7 +59,7 @@ + + mmngr { + compatible = "renesas,mmngr"; +- memory-region = <&lossy_decompress>; ++ memory-region = <&mmp_reserved>, <&lossy_decompress>; + }; + + mmngrbuf { +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +index 51607d4..549ca5e 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +@@ -48,7 +48,7 @@ + }; + + /* device specific region for contiguous allocations */ +- linux,multimedia { ++ mmp_reserved: linux,multimedia { + compatible = "shared-dma-pool"; + reusable; + reg = <0x00000000 0x7f000000 0x0 0x01000000>; +@@ -57,7 +57,7 @@ + + mmngr { + compatible = "renesas,mmngr"; +- memory-region = <&lossy_decompress>; ++ memory-region = <&mmp_reserved>, <&lossy_decompress>; + }; + + mmngrbuf { +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0334-IMR-UIO-Driver-initial-version.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0334-IMR-UIO-Driver-initial-version.patch new file mode 100644 index 00000000..0abfefe3 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0334-IMR-UIO-Driver-initial-version.patch @@ -0,0 +1,816 @@ +From 4388b872be8d3b0d13c804d3cdb8ec9a4ddd5a97 Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Mon, 5 Nov 2018 23:01:21 +0300 +Subject: [PATCH 154/211] IMR UIO Driver initial version + +Signed-off-by: Toshiya Tamaki +--- + .../devicetree/bindings/imr/renesas,imr.txt | 55 +++ + arch/arm64/boot/dts/renesas/r8a7795.dtsi | 16 +- + arch/arm64/boot/dts/renesas/r8a7796.dtsi | 8 +- + arch/arm64/boot/dts/renesas/r8a77970.dtsi | 16 +- + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 20 +- + drivers/uio/Kconfig | 9 + + drivers/uio/Makefile | 1 + + drivers/uio/uio_imr.c | 495 +++++++++++++++++++++ + 8 files changed, 590 insertions(+), 30 deletions(-) + create mode 100644 Documentation/devicetree/bindings/imr/renesas,imr.txt + create mode 100644 drivers/uio/uio_imr.c + +diff --git a/Documentation/devicetree/bindings/imr/renesas,imr.txt b/Documentation/devicetree/bindings/imr/renesas,imr.txt +new file mode 100644 +index 0000000..4d5454a +--- /dev/null ++++ b/Documentation/devicetree/bindings/imr/renesas,imr.txt +@@ -0,0 +1,55 @@ ++* Renesas Electronics IMR ++ ++This file provides information on what the device node for the IMR ++interface contains. ++ ++Required properties: ++- compatible: "renesas,r8a7795-imr-lx4" if the device is a part of R8A7795 SoC. ++ "renesas,r8a7796-imr-lx4" if the device is a part of R8A7796 SoC. ++ "renesas,r8a77970-imr-lx4" if the device is a part of R8A7797 SoC. ++ ++ When compatible with the generic version, nodes must list the ++ SoC-specific version corresponding to the platform first ++ followed by the generic version. ++ ++- reg: offset and length of (1) the register block and (2) the stream buffer. ++- interrupts: A list of interrupt-specifiers, one for each entry in ++ interrupt-names. ++ If interrupt-names is not present, an interrupt specifier ++ for a single muxed interrupt. ++- clocks: clock phandle and specifier pair. ++- power-domains: must contain a reference to the PM domain. ++ ++Example: ++ ++ imr0{ ++ compatible = "renesas,r8a77970-imr-lx4"; ++ reg = <0 0xfe860000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 823>; ++ power-domains = <&sysc R8A7797_PD_A3VC>; ++ }; ++ ++ imr1{ ++ compatible = "renesas,r8a77970-imr-lx4"; ++ reg = <0 0xfe870000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 822>; ++ power-domains = <&sysc R8A7797_PD_A3VC>; ++ }; ++ ++ imr2{ ++ compatible = "renesas,r8a77970-imr-lx4"; ++ reg = <0 0xfe880000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 821>; ++ power-domains = <&sysc R8A7797_PD_A3VC>; ++ }; ++ ++ imr3{ ++ compatible = "renesas,r8a77970-imr-lx4"; ++ reg = <0 0xfe890000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 820>; ++ power-domains = <&sysc R8A7797_PD_A3VC>; ++ }; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi +index 536deef..e749633 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi +@@ -2785,40 +2785,40 @@ + status = "disabled"; + }; + +- imr-lx4@fe860000 { ++ imrlx4_ch0: imr0@fe860000 { + compatible = "renesas,r8a7795-imr-lx4", + "renesas,imr-lx4"; +- reg = <0 0xfe860000 0 0x2000>; ++ reg = <0 0xfe860000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 823>; + power-domains = <&sysc R8A7795_PD_A3VC>; + resets = <&cpg 823>; + }; + +- imr-lx4@fe870000 { ++ imrlx4_ch1: imr1@fe870000 { + compatible = "renesas,r8a7795-imr-lx4", + "renesas,imr-lx4"; +- reg = <0 0xfe870000 0 0x2000>; ++ reg = <0 0xfe870000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 822>; + power-domains = <&sysc R8A7795_PD_A3VC>; + resets = <&cpg 822>; + }; + +- imr-lx4@fe880000 { ++ imrlx4_ch2: imr2@fe880000 { + compatible = "renesas,r8a7795-imr-lx4", + "renesas,imr-lx4"; +- reg = <0 0xfe880000 0 0x2000>; ++ reg = <0 0xfe880000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 821>; + power-domains = <&sysc R8A7795_PD_A3VC>; + resets = <&cpg 821>; + }; + +- imr-lx4@fe890000 { ++ imrlx4_ch3: imr3@fe890000 { + compatible = "renesas,r8a7795-imr-lx4", + "renesas,imr-lx4"; +- reg = <0 0xfe890000 0 0x2000>; ++ reg = <0 0xfe890000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 820>; + power-domains = <&sysc R8A7795_PD_A3VC>; +diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi +index 383639b..49068a8 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7796.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi +@@ -2618,20 +2618,20 @@ + status = "disabled"; + }; + +- imr-lx4@fe860000 { ++ imrlx4_ch0: imr0@fe860000 { + compatible = "renesas,r8a7796-imr-lx4", + "renesas,imr-lx4"; +- reg = <0 0xfe860000 0 0x2000>; ++ reg = <0 0xfe860000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 823>; + power-domains = <&sysc R8A7796_PD_A3VC>; + resets = <&cpg 823>; + }; + +- imr-lx4@fe870000 { ++ imrlx4_ch1: imr1@fe870000 { + compatible = "renesas,r8a7796-imr-lx4", + "renesas,imr-lx4"; +- reg = <0 0xfe870000 0 0x2000>; ++ reg = <0 0xfe870000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 822>; + power-domains = <&sysc R8A7796_PD_A3VC>; +diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +index aa4d3d6..40e28338 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +@@ -968,40 +968,40 @@ + power-domains = <&sysc R8A77970_PD_A3IR>; + }; + +- imr-lx4@fe860000 { ++ imrlx4_ch0: imr0@fe860000 { + compatible = "renesas,r8a77970-imr-lx4", + "renesas,imr-lx4"; +- reg = <0 0xfe860000 0 0x2000>; ++ reg = <0 0xfe860000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 823>; + power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; + resets = <&cpg 823>; + }; + +- imr-lx4@fe870000 { ++ imrlx4_ch1: imr1@fe870000 { + compatible = "renesas,r8a77970-imr-lx4", + "renesas,imr-lx4"; +- reg = <0 0xfe870000 0 0x2000>; ++ reg = <0 0xfe870000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 822>; + power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; + resets = <&cpg 822>; + }; + +- imr-lx4@fe880000 { ++ imrlx4_ch2: imr2@fe880000 { + compatible = "renesas,r8a77970-imr-lx4", + "renesas,imr-lx4"; +- reg = <0 0xfe880000 0 0x2000>; ++ reg = <0 0xfe880000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 821>; + power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; + resets = <&cpg 821>; + }; + +- imr-lx4@fe890000 { ++ imrlx4_ch3: imr3@fe890000 { + compatible = "renesas,r8a77970-imr-lx4", + "renesas,imr-lx4"; +- reg = <0 0xfe890000 0 0x2000>; ++ reg = <0 0xfe890000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 820>; + power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index 947cf7a..302b346 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -1213,47 +1213,47 @@ + power-domains = <&sysc R8A77980_PD_A3IR>; + }; + +- imr-lx4@fe860000 { ++ imrlx4_ch0: imr0@fe860000 { + compatible = "renesas,r8a77980-imr-lx4", + "renesas,imr-lx4"; +- reg = <0 0xfe860000 0 0x2000>; ++ reg = <0 0xfe860000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 823>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 823>; + }; + +- imr-lx4@fe870000 { ++ imrlx4_ch1: imr1@fe870000 { + compatible = "renesas,r8a77980-imr-lx4", + "renesas,imr-lx4"; +- reg = <0 0xfe870000 0 0x2000>; ++ reg = <0 0xfe870000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 822>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 822>; + }; + +- imr-lx4@fe880000 { ++ imrlx4_ch2: imr2@fe880000 { + compatible = "renesas,r8a77980-imr-lx4", + "renesas,imr-lx4"; +- reg = <0 0xfe880000 0 0x2000>; ++ reg = <0 0xfe880000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 821>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 821>; + }; + +- imr-lx4@fe890000 { ++ imrlx4_ch3: imr3@fe890000 { + compatible = "renesas,r8a77980-imr-lx4", + "renesas,imr-lx4"; +- reg = <0 0xfe890000 0 0x2000>; ++ reg = <0 0xfe890000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 820>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 820>; + }; + +- imr4@fe8a0000 { ++ imrlx4_ch4: imr4@fe8a0000 { + compatible = "renesas,r8a77980-imr-lx4", + "renesas,imr-lx4"; + reg = <0 0xfe8a0000 0 0x10000>; +@@ -1262,7 +1262,7 @@ + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + }; + +- imr5@fe8b0000 { ++ imrlx4_ch5: imr5@fe8b0000 { + compatible = "renesas,r8a77980-imr-lx4", + "renesas,imr-lx4"; + reg = <0 0xfe8b0000 0 0x10000>; +diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig +index 7e8dc78..46cd4b1 100644 +--- a/drivers/uio/Kconfig ++++ b/drivers/uio/Kconfig +@@ -164,4 +164,13 @@ config UIO_HV_GENERIC + to network and storage devices from userspace. + + If you compile this as a module, it will be called uio_hv_generic. ++ ++config UIO_IMR ++ tristate "Renesas IMR support" ++ ++ help ++ Renesas IMR device driver. ++ This driver supports the following SoCs: ++ - R8A7795, R8A7796, R8A77970, R8A77980. ++ + endif +diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile +index c285dd2..4ab2039 100644 +--- a/drivers/uio/Makefile ++++ b/drivers/uio/Makefile +@@ -11,3 +11,4 @@ obj-$(CONFIG_UIO_PRUSS) += uio_pruss.o + obj-$(CONFIG_UIO_MF624) += uio_mf624.o + obj-$(CONFIG_UIO_FSL_ELBC_GPCM) += uio_fsl_elbc_gpcm.o + obj-$(CONFIG_UIO_HV_GENERIC) += uio_hv_generic.o ++obj-$(CONFIG_UIO_IMR) += uio_imr.o +diff --git a/drivers/uio/uio_imr.c b/drivers/uio/uio_imr.c +new file mode 100644 +index 0000000..a1ba788 +--- /dev/null ++++ b/drivers/uio/uio_imr.c +@@ -0,0 +1,495 @@ ++/*************************************************************************/ /* ++ IMR ++ ++ Copyright (C) 2015-2017 Renesas Electronics Corporation ++ ++ License Dual MIT/GPLv2 ++ ++ The contents of this file are subject to the MIT license as set out below. ++ ++ Permission is hereby granted, free of charge, to any person obtaining a copy ++ of this software and associated documentation files (the "Software"), to deal ++ in the Software without restriction, including without limitation the rights ++ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ copies of the Software, and to permit persons to whom the Software is ++ furnished to do so, subject to the following conditions: ++ ++ The above copyright notice and this permission notice shall be included in ++ all copies or substantial portions of the Software. ++ ++ Alternatively, the contents of this file may be used under the terms of ++ the GNU General Public License Version 2 ("GPL") in which case the provisions ++ of GPL are applicable instead of those above. ++ ++ If you wish to allow use of your version of this file only under the terms of ++ GPL, and not to allow others to use your version of this file under the terms ++ of the MIT license, indicate your decision by deleting the provisions above ++ and replace them with the notice and other provisions required by GPL as set ++ out in the file called "GPL-COPYING" included in this distribution. If you do ++ not delete the provisions above, a recipient may use your version of this file ++ under the terms of either the MIT license or GPL. ++ ++ This License is also included in this distribution in the file called ++ "MIT-COPYING". ++ ++ EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS ++ PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING ++ BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR ++ PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR ++ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER ++ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ++ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ ++ ++ GPLv2: ++ If you wish to use this file under the terms of GPL, following terms are ++ effective. ++ ++ 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; version 2 of the License. ++ ++ 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. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++*/ /*************************************************************************/ ++ ++/* PRQA S 292,2212,2214 EOF */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++/* IMR uio driver name */ ++#define DRIVER_NAME "uio_imr" ++ ++/* IMR register definition */ ++#define IMR_REG_IMR_ADDRESS (0x018U) ++#define IMR_REG_IMR_BIT_BASE (0x3U << 3) ++#define IMR_REG_IMR_BIT_INT (0x1U << 2) ++#define IMR_REG_IMR_BIT_IER (0x1U << 1) ++#define IMR_REG_IMR_BIT_TRA (0x1U << 0) ++ ++/** ++ * struct uio_platdata - the uio platform data structure ++ * @uioinfo: UIO device capabilities ++ * @lock lock flag for irq. ++ * @flags: flags for request_irq. ++ * @pdev: IMR platform device data. ++ * @base_reg: IMR base register address. ++ * @clk: clock data. ++ * ++ * the uio platform data structure. ++ */ ++struct uio_platdata { ++ struct uio_info *uioinfo; ++ spinlock_t lock; ++ unsigned long flags; ++ struct platform_device *pdev; ++ void __iomem *base_reg; ++ struct clk *clock; ++}; ++ ++static void write_register(struct uio_platdata *priv, ++ u32 reg_offs, u32 data); ++static int uio_imr_open(struct uio_info *info, ++ __attribute__((unused)) struct inode *inode); ++static int uio_imr_release(struct uio_info *info, ++ __attribute__((unused)) struct inode *inode); ++static irqreturn_t uio_imr_handler(__attribute__((unused)) int irq, ++ struct uio_info *dev_info); ++static int uio_imr_irqcontrol(struct uio_info *info, s32 irq_on); ++static int uio_imr_probe(struct platform_device *pdev); ++static int uio_imr_remove(struct platform_device *pdev); ++static int uio_runtime_imr_nop(__attribute__((unused)) struct device *dev); ++ ++/** ++ * write_register() - register setting ++ * @priv: uio platform data. ++ * @reg_offs: register offset. ++ * @data: register value. ++ * ++ * register setting. ++ * ++ * ++ * Return: none ++ */ ++static void write_register(struct uio_platdata *priv, ++ u32 reg_offs, u32 data) ++{ ++ iowrite32(data, (u8 *)priv->base_reg + reg_offs); /* PRQA S 488 */ ++} ++ ++/** ++ * uio_imr_open() - open imr module ++ * @info: UIO device capabilities. ++ * @inode: inode. ++ * ++ * Open imr module. ++ * ++ * ++ * Return: 0 normal end. ++ */ ++/* PRQA S 3206 2 */ ++static int uio_imr_open(struct uio_info *info, ++ __attribute__((unused)) struct inode *inode) ++{ ++ struct uio_platdata *pdata = info->priv; ++ /* PRQA S 3200 1 */ ++ pr_debug("uio_imr_open enter. name=%s\n", pdata->uioinfo->name); ++ ++ /* Wait until the Runtime PM code has woken up the device */ ++ (void)pm_runtime_get_sync(&pdata->pdev->dev); ++ ++ return 0; ++} ++ ++/** ++ * uio_imr_release() - close imr module ++ * @info: UIO device capabilities. ++ * @inode: inode. ++ * ++ * Close imr module. ++ * ++ * ++ * Return: 0 normal end. ++ */ ++/* PRQA S 3206 2 */ ++static int uio_imr_release(struct uio_info *info, ++ __attribute__((unused)) struct inode *inode) ++{ ++ struct uio_platdata *pdata = info->priv; ++ ++ pr_debug("uio_imr_release enter\n"); /* PRQA S 3200 */ ++ ++ /* Tell the Runtime PM code that the device has become idle */ ++ (void)pm_runtime_put_sync(&pdata->pdev->dev); ++ ++ return 0; ++} ++ ++/** ++ * uio_imr_handler() - IMR interrupt handler ++ * @irq: irq No. ++ * @dev_info: UIO device capabilities. ++ * ++ * IMR interrupt handler. ++ * ++ * ++ * Return: IRQ_HANDLED normal end. ++ */ ++/* PRQA S 3206 1*/ ++static irqreturn_t uio_imr_handler(__attribute__((unused))int irq, ++ struct uio_info *dev_info) ++{ ++ struct uio_platdata *pdata = dev_info->priv; ++ ++ ++ pr_debug("uio_imr_handler enter\n"); /* PRQA S 3200 */ ++ ++ /* Mask interrupt */ ++ write_register(pdata, IMR_REG_IMR_ADDRESS, ++ IMR_REG_IMR_BIT_BASE | (IMR_REG_IMR_BIT_INT | ++ IMR_REG_IMR_BIT_IER | IMR_REG_IMR_BIT_TRA)); ++ ++ return IRQ_HANDLED; ++} ++ ++/** ++ * uio_imr_irqcontrol() - IMR irq controller ++ * @info: UIO device capabilities. ++ * @irq_on: irq enable/disable. ++ * ++ * IMR irq controller. Enable and disable the interrupt. ++ * ++ * ++ * Return: 0 normal end. ++ */ ++static int uio_imr_irqcontrol(struct uio_info *info, s32 irq_on) ++{ ++ struct uio_platdata *pdata = info->priv; ++ u64 flag; ++ ++ pr_debug("uio_imr_irqcontrol enter\n"); /* PRQA S 3200 */ ++ ++ spin_lock_irqsave(&pdata->lock, flag); ++ if (irq_on != 0) { ++ if (test_and_clear_bit(0, &pdata->flags) != 0) ++ enable_irq((u32)info->irq); ++ } else { ++ if (test_and_set_bit(0, &pdata->flags) == 0) ++ disable_irq((u32)info->irq); ++ } ++ spin_unlock_irqrestore(&pdata->lock, flag); ++ ++ return 0; ++} ++ ++/* PRQA S 1053,1041,605 10 */ ++static const struct of_device_id rcar_imr_dt_ids[] = { ++ { .compatible = "renesas,r8a7795-imr-lx4", .data = 0 }, ++ { .compatible = "renesas,r8a7796-imr-lx4", .data = 0 }, ++ { .compatible = "renesas,r8a77970-imr-lx4", .data = 0 }, ++ { .compatible = "renesas,r8a77980-imr-lx4", .data = 0 }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rcar_imr_dt_ids); /* PRQA S 605 */ ++ ++/** ++ * uio_imr_probe() - Initialize IMR module. ++ * @pdev: platform device data. ++ * ++ * Initialize IMR module. ++ * ++ * ++ * Return: 0 normal end. ++ * -EINVAL parameter error. ++ * -ENOMEM memory error. ++ * -ENODEV system error. ++ */ ++static int uio_imr_probe(struct platform_device *pdev) ++{ ++ struct uio_info *uioinfo_data = NULL; ++ struct uio_platdata *pdata; ++ struct uio_mem *uiomem; ++ int ret = 0; ++ unsigned int i; ++ struct resource *rsc; ++ unsigned int irq_l; ++ unsigned long remap_size; ++ ++ if (pdev == NULL) { ++ pr_err("missing pdev\n"); ++ ret = -EINVAL; ++ } else { ++ if (pdev->dev.of_node == NULL) { ++ dev_err(&pdev->dev, "missing pdev->dev.of_node\n"); ++ ret = -EINVAL; ++ } ++ } ++ ++ if (ret == 0) { ++ pr_debug("uio_imr_probe enter name = %s\n", /* PRQA S 3200 */ ++ pdev->dev.of_node->name); ++ ++ uioinfo_data = devm_kzalloc(&pdev->dev, ++ sizeof(*uioinfo_data), ++ GFP_KERNEL); ++ if (uioinfo_data == NULL) ++ ret = -ENOMEM; ++ } ++ ++ if (ret == 0) { ++ uioinfo_data->name = pdev->dev.of_node->name; ++ uioinfo_data->version = "0.1"; ++ ++ /* get irq number */ ++ irq_l = irq_of_parse_and_map(pdev->dev.of_node, 0); ++ if ((int)irq_l == -ENXIO) ++ uioinfo_data->irq = platform_get_irq(pdev, 0); ++ else ++ uioinfo_data->irq = (int)irq_l; ++ ++ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); ++ if (pdata == NULL) ++ ret = -ENOMEM; ++ } ++ ++ if (ret == 0) { ++ pdata->uioinfo = uioinfo_data; ++ spin_lock_init(&pdata->lock); /* PRQA S 3200 */ ++ pdata->flags = 0; ++ pdata->pdev = pdev; ++ ++ uiomem = &uioinfo_data->mem[0]; ++ ++ for (i = 0; i < pdev->num_resources; ++i) { ++ /* PRQA S 491 1 */ ++ struct resource *r = &pdev->resource[i]; ++ ++ if (r->flags == IORESOURCE_IRQ) { ++ uioinfo_data->irq = (long)r->start; ++ } else if (r->flags != IORESOURCE_MEM) { ++ ; ++ } else { ++ if (uiomem >= ++ &uioinfo_data->mem[MAX_UIO_MAPS]) { ++ dev_warn(&pdev->dev, ++ "device has more than " ++ __stringify(MAX_UIO_MAPS) ++ " I/O memory resources.\n"); ++ break; ++ } ++ ++ uiomem->memtype = UIO_MEM_PHYS; ++ uiomem->addr = r->start; ++ uiomem->size = (r->end - r->start) + 1; ++ ++uiomem; /* PRQA S 489 */ ++ } ++ } ++ ++ while (uiomem < &uioinfo_data->mem[MAX_UIO_MAPS]) { ++ uiomem->size = 0; ++ ++uiomem; /* PRQA S 489 */ ++ } ++ ++ uioinfo_data->handler = &uio_imr_handler; ++ uioinfo_data->irqcontrol = &uio_imr_irqcontrol; ++ uioinfo_data->open = &uio_imr_open; ++ uioinfo_data->release = &uio_imr_release; ++ uioinfo_data->priv = pdata; ++ ++ pm_runtime_enable(&pdev->dev); ++ ++ ret = uio_register_device(&pdev->dev, pdata->uioinfo); ++ if (ret != 0) { ++ pm_runtime_disable(&pdev->dev); ++ dev_err(&pdev->dev, "could not register uio device\n"); ++ ret = -ENODEV; ++ } ++ } ++ ++ if (ret == 0) { ++ platform_set_drvdata(pdev, pdata); ++ pdata->clock = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(pdata->clock)) { ++ pm_runtime_disable(&pdev->dev); ++ dev_err(&pdev->dev, "could not get clock\n"); ++ ret = -ENODEV; ++ } else { ++ /* clock enable */ ++ (void)clk_prepare_enable(pdata->clock); ++ } ++ } ++ ++ if (ret == 0) { ++ rsc = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (rsc == 0) { ++ pm_runtime_disable(&pdev->dev); ++ dev_err(&pdev->dev, "could not platform_get_resource\n"); ++ ret = -ENODEV; ++ } ++ } ++ ++ if (ret == 0) { ++ remap_size = (rsc->end - rsc->start) + 1; ++ if (!request_mem_region(rsc->start, ++ remap_size, ++ uioinfo_data->name)) { ++ dev_err(&pdev->dev, "could not request IO\n"); ++ pm_runtime_disable(&pdev->dev); ++ ret = -ENOMEM; ++ } ++ } ++ ++ if (ret == 0) { ++ /* IMR Register Adderss */ ++ pdata->base_reg = devm_ioremap_nocache(&pdev->dev, ++ rsc->start, ++ remap_size); ++ if (pdata->base_reg == NULL) { ++ release_mem_region(rsc->start, resource_size(rsc)); ++ dev_err(&pdev->dev, "could not remap IMR register\n"); ++ pm_runtime_disable(&pdev->dev); ++ ret = -ENOMEM; ++ } else { ++ /* PRQA S 3200 2 */ ++ pr_debug("IMR reg_base = %x size = %x\n", ++ (uint32_t)(rsc->start), (uint32_t)remap_size); ++ } ++ } ++ ++ return ret; ++} ++ ++/** ++ * uio_imr_remove() - release IMR module. ++ * @pdev: platform device data. ++ * ++ * release IMR module. ++ * ++ * ++ * Return: 0 normal end. ++ */ ++static int uio_imr_remove(struct platform_device *pdev) ++{ ++ struct resource *rsc; ++ struct uio_platdata *pdata = platform_get_drvdata(pdev); ++ ++ /* PRQA S 3200 1 */ ++ pr_debug("uio_imr_remove enter name = %s\n", pdata->uioinfo->name); ++ ++ clk_disable_unprepare(pdata->clock); ++ ++ uio_unregister_device(pdata->uioinfo); ++ ++ pm_runtime_disable(&pdev->dev); ++ ++ irq_dispose_mapping((u32)pdata->uioinfo->irq); ++ ++ pdata->uioinfo->handler = NULL; ++ pdata->uioinfo->irqcontrol = NULL; ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ if (pdata->base_reg != NULL) ++ devm_iounmap(&pdev->dev, pdata->base_reg); ++ ++ rsc = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (rsc != 0) ++ release_mem_region(rsc->start, resource_size(rsc)); ++ ++ return 0; ++} ++ ++/** ++ * uio_runtime_imr_nop() - Runtime PM callback function. ++ * @dev: device data. ++ * ++ * Runtime PM callback function. ++ * ++ * ++ * Return: 0 normal end. ++ */ ++ /* PRQA S 3206 1 */ ++static int uio_runtime_imr_nop(__attribute__((unused)) struct device *dev) ++{ ++ pr_debug("uio_runtime_imr_nop enter\n"); /* PRQA S 3200 */ ++ return 0; ++} ++/* PRQA S 1053 4 */ ++static const struct dev_pm_ops uio_dev_pm_imr_ops = { ++ .runtime_suspend = &uio_runtime_imr_nop, ++ .runtime_resume = &uio_runtime_imr_nop, ++}; ++ ++static struct platform_driver uio_imr_platform_driver = { ++ .probe = &uio_imr_probe, ++ .remove = &uio_imr_remove, ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .pm = &uio_dev_pm_imr_ops, ++ .of_match_table = of_match_ptr(rcar_imr_dt_ids), ++ }, ++}; ++ ++module_platform_driver(uio_imr_platform_driver); ++ ++ ++MODULE_AUTHOR("Renesas Electronics Corporation"); ++MODULE_DESCRIPTION("Userspace I/O driver for IMR"); ++MODULE_LICENSE("Dual MIT/GPL"); ++MODULE_ALIAS("platform:" DRIVER_NAME); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0335-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0335-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch new file mode 100644 index 00000000..bb796eac --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0335-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch @@ -0,0 +1,538 @@ +From cf92c2d86f2eec6477c6304527c5eeccd23e290c Mon Sep 17 00:00:00 2001 +From: Konstantin Kozhevnikov +Date: Tue, 14 Nov 2017 01:47:11 -0800 +Subject: [PATCH 155/211] media: rcar-imr: IMR driver updates for raw DL + +IMR driver updates for raw DL + +Signed-off-by: Konstantin Kozhevnikov +--- + drivers/media/platform/rcar_imr.c | 209 ++++++++++++++++++++++++++++++-------- + include/uapi/linux/rcar-imr.h | 16 +-- + 2 files changed, 175 insertions(+), 50 deletions(-) + +diff --git a/drivers/media/platform/rcar_imr.c b/drivers/media/platform/rcar_imr.c +index 30c6742..9b601da 100644 +--- a/drivers/media/platform/rcar_imr.c ++++ b/drivers/media/platform/rcar_imr.c +@@ -94,6 +94,7 @@ struct imr_device { + struct v4l2_device v4l2_dev; + struct video_device video_dev; + struct v4l2_m2m_dev *m2m_dev; ++ struct device *alloc_dev; + + /* ...do we need that counter really? framework counts fh structures for us - tbd */ + int refcount; +@@ -117,6 +118,9 @@ struct imr_ctx { + /* ...cropping parameters (in pixels) */ + u16 crop[4]; + ++ /* ...solid color code */ ++ u32 color; ++ + /* ...number of active configurations (debugging) */ + u32 cfg_num; + }; +@@ -192,6 +196,7 @@ struct imr_ctx { + + #define IMR_TRICR 0x6C + #define IMR_TRIC_YCFORM (1 << 31) ++#define IMR_TRICR2 0xA0 + + #define IMR_UVDPOR 0x70 + #define IMR_SUSR 0x74 +@@ -212,6 +217,8 @@ struct imr_ctx { + #define IMR_CPDP_UBDPO_SHIFT 4 + #define IMR_CPDP_VRDPO_SHIFT 0 + ++#define IMR_TPOR 0xF0 ++ + /******************************************************************************* + * Auxiliary helpers + ******************************************************************************/ +@@ -404,11 +411,16 @@ static int imr_queue_setup(struct vb2_queue *vq, + return -EINVAL; + } + ++ /* ...specify default allocator */ ++ alloc_devs[0] = ctx->imr->alloc_dev; ++ + return 0; + } + + static int imr_buf_prepare(struct vb2_buffer *vb) + { ++ struct imr_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); ++ + /* ...unclear yet if we want to prepare a buffer somehow (cache invalidation? - tbd) */ + return 0; + } +@@ -441,9 +453,10 @@ static void imr_buf_finish(struct vb2_buffer *vb) + WARN_ON(!mutex_is_locked(&ctx->imr->mutex)); + + /* ...any special processing of completed buffer? - tbd */ +- v4l2_dbg(3, debug, &ctx->imr->v4l2_dev, "%sput buffer <0x%08llx> done\n", ++ v4l2_dbg(3, debug, &ctx->imr->v4l2_dev, "%sput buffer <0x%08llx> done (err: %d) (ctx=%p)\n", + q->is_output ? "in" : "out", +- vb2_dma_contig_plane_dma_addr(vb, 0)); ++ vb2_dma_contig_plane_dma_addr(vb, 0), ++ vb->state, ctx); + + /* ...unref configuration pointer as needed */ + if (q->is_output) +@@ -568,6 +581,11 @@ static inline u16 __imr_auto_sg_dg_tcm(u32 type) + (type & IMR_MAP_TCM ? IMR_TRIM_TCM : 0); + } + ++static inline u16 __imr_bfe_tme(u32 type) ++{ ++ return (type & IMR_MAP_TME ? IMR_TRIM_TME : 0) | (type & IMR_MAP_BFE ? IMR_TRIM_BFE : 0); ++} ++ + static inline u16 __imr_uvdp(u32 type) + { + return __IMR_MAP_UVDPOR(type) | (type & IMR_MAP_DDP ? (1 << 8) : 0); +@@ -674,15 +692,14 @@ static inline u32 * imr_tri_set_type_b(u32 *dl, void *map, struct imr_mesh *mesh + ******************************************************************************/ + + /* ...calculate length of a type "c" mapping */ +-static inline u32 imr_tri_type_c_get_length(struct imr_vbo *vbo, int item_size) ++static inline u32 imr_tri_type_c_get_length(int num, int item_size) + { +- return ((4 + 3 * item_size) * vbo->num + 4); ++ return ((4 + 3 * item_size) * num + 4); + } + + /* ...set a VBO mapping using absolute coordinates */ +-static inline u32 * imr_tri_set_type_c(u32 *dl, void *map, struct imr_vbo *vbo, int item_size) ++static inline u32 * imr_tri_set_type_c(u32 *dl, void *map, int num, int item_size) + { +- int num = vbo->num; + int i; + + /* ...prepare list of triangles to draw */ +@@ -732,6 +749,7 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg + int h = ctx->queue[0].fmt.height; + int W = ctx->queue[1].fmt.width; + int H = ctx->queue[1].fmt.height; ++ u32 tricr = ctx->color & 0xFFFFFF; + + v4l2_dbg(2, debug, &ctx->imr->v4l2_dev, "setup %u*%u -> %u*%u mapping (type=%x)\n", w, h, W, H, type); + +@@ -739,11 +757,17 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg + *dl++ = IMR_OP_WTS(IMR_TRIMCR, 0xFFFF); + + /* ...set automatic source / destination coordinates generation flags */ +- *dl++ = IMR_OP_WTS(IMR_TRIMSR, __imr_auto_sg_dg_tcm(type) | IMR_TRIM_BFE | IMR_TRIM_TME); ++ *dl++ = IMR_OP_WTS(IMR_TRIMSR, __imr_auto_sg_dg_tcm(type) | __imr_bfe_tme(type)); ++ ++ /* ...that's probably not needed? - tbd */ ++ *dl++ = IMR_OP_SYNCM; + + /* ...set source / destination coordinate precision */ + *dl++ = IMR_OP_WTS(IMR_UVDPOR, __imr_uvdp(type)); + ++ /* ...that's probably not needed? - tbd */ ++ *dl++ = IMR_OP_SYNCM; ++ + /* ...set luminance/chromacity correction parameters precision */ + *dl++ = IMR_OP_WTS(IMR_CPDPOR, __imr_cpdp(type)); + +@@ -776,14 +800,12 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg + } + } else { + u16 src_fmt = (iflags & IMR_F_UV_SWAP ? IMR_CMR2_UVFORM : 0) | (iflags & IMR_F_YUV_SWAP ? IMR_CMR2_YUV422FORM : 0); +- u32 dst_fmt = (oflags & IMR_F_YUV_SWAP ? IMR_TRIC_YCFORM : 0); + + /* ...interleaved input; output is either interleaved or planar */ + *dl++ = IMR_OP_WTS(IMR_CMRCSR2, IMR_CMR2_YUV422E | src_fmt); + + /* ...destination is always YUYV or UYVY */ +- *dl++ = IMR_OP_WTL(IMR_TRICR, 1); +- *dl++ = dst_fmt; ++ tricr |= (oflags & IMR_F_YUV_SWAP ? IMR_TRIC_YCFORM : 0); + + /* ...set precision of Y/UV planes and required correction */ + *dl++ = IMR_OP_WTS(IMR_CMRCSR, src_y_fmt | src_uv_fmt | dst_y_fmt | dst_uv_fmt | __imr_clce(type) | __imr_luce(type)); +@@ -810,6 +832,10 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg + *dl++ = ((w - 2) << 16) | (w - 1); + *dl++ = h - 1; + ++ /* ...set triangle single color */ ++ *dl++ = IMR_OP_WTL(IMR_TRICR, 1); ++ *dl++ = tricr; ++ + /* ...invoke subroutine for triangles drawing */ + *dl++ = IMR_OP_GOSUB; + *dl++ = subaddr; +@@ -852,7 +878,7 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc) + { + struct imr_device *imr = ctx->imr; + struct imr_mesh *mesh; +- struct imr_vbo *vbo; ++ int vbo_num; + struct imr_cfg *cfg; + void *buf, *map; + u32 type; +@@ -925,13 +951,6 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc) + tri_length = imr_tri_type_a_get_length(mesh, item_size); + } + } else { +- /* ...assure we have proper VBO descriptor */ +- if (length < sizeof(struct imr_vbo)) { +- v4l2_err(&imr->v4l2_dev, "invalid vbo specification size: %u\n", length); +- ret = -EINVAL; +- goto out; +- } +- + /* ...make sure there is no automatic-generation flags */ + if (type & (IMR_MAP_AUTODG | IMR_MAP_AUTOSG)) { + v4l2_err(&imr->v4l2_dev, "invalid auto-dg/sg flags: 0x%x\n", type); +@@ -939,22 +958,23 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc) + goto out; + } + +- vbo = (struct imr_vbo *)buf; +- length -= sizeof(struct imr_vbo); +- map = buf + sizeof(struct imr_vbo); ++ map = buf; + + /* ...vertex is given with absolute coordinates */ + item_size += 8; + ++ /* ...calculate total number of triangles */ ++ vbo_num = length / (3 * item_size); ++ + /* ...check the length is sane */ +- if (length != vbo->num * 3 * item_size) { +- v4l2_err(&imr->v4l2_dev, "invalid vbo size: %u*%u*3 != %u\n", vbo->num, item_size, length); ++ if (length != vbo_num * 3 * item_size) { ++ v4l2_err(&imr->v4l2_dev, "invalid vbo size: %u*%u*3 != %u\n", vbo_num, item_size, length); + ret = -EINVAL; + goto out; + } + + /* ...calculate size of trangles drawing subroutine */ +- tri_length = imr_tri_type_c_get_length(vbo, item_size); ++ tri_length = imr_tri_type_c_get_length(vbo_num, item_size); + } + + /* ...DL main program shall start with 8-byte aligned address */ +@@ -975,13 +995,16 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc) + imr_cfg_unref(ctx, ctx->cfg); + + /* ...create new configuration */ +- ctx->cfg = cfg = imr_cfg_create(ctx, dl_size, dl_start_offset); ++ cfg = imr_cfg_create(ctx, dl_size, dl_start_offset); + if (IS_ERR(cfg)) { + ret = PTR_ERR(cfg); ++ ctx->cfg = NULL; + v4l2_err(&imr->v4l2_dev, "failed to create configuration: %d\n", ret); + goto out; + } + ++ ctx->cfg = cfg; ++ + /* ...get pointer to the new display list */ + dl_vaddr = cfg->dl_vaddr; + dl_dma_addr = cfg->dl_dma_addr; +@@ -994,7 +1017,7 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc) + imr_tri_set_type_a(dl_vaddr, map, mesh, item_size); + } + } else { +- imr_tri_set_type_c(dl_vaddr, map, vbo, item_size); ++ imr_tri_set_type_c(dl_vaddr, map, vbo_num, item_size); + } + + /* ...prepare main DL-program */ +@@ -1020,6 +1043,66 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc) + return ret; + } + ++/* ...set mapping data (function called with video device lock held) */ ++static int imr_ioctl_map_raw(struct imr_ctx *ctx, struct imr_map_desc *desc) ++{ ++ struct imr_device *imr = ctx->imr; ++ u32 type = desc->type; ++ u32 length = desc->size; ++ struct imr_cfg *cfg; ++ void *dl_vaddr; ++ u32 dl_size; ++ u32 dl_start_offset; ++ dma_addr_t dl_dma_addr; ++ ++ /* ...calculate main routine length */ ++ dl_size = imr_dl_program_length(ctx); ++ if (!dl_size) { ++ v4l2_err(&imr->v4l2_dev, "format configuration error\n"); ++ return -EINVAL; ++ } ++ ++ /* ...unref current configuration (will not be used by subsequent jobs) */ ++ imr_cfg_unref(ctx, ctx->cfg); ++ ++ /* ...create new configuration (starts with zero offset) */ ++ cfg = imr_cfg_create(ctx, dl_size, 0); ++ if (IS_ERR(cfg)) { ++ ctx->cfg = NULL; ++ v4l2_err(&imr->v4l2_dev, "failed to create configuration: %ld\n", PTR_ERR(cfg)); ++ return PTR_ERR(cfg); ++ } ++ ++ ctx->cfg = cfg; ++ ++ /* ...get pointer to the new display list */ ++ dl_vaddr = cfg->dl_vaddr; ++ ++ /* ...prepare main DL-program */ ++ imr_dl_program_setup(ctx, cfg, type, dl_vaddr, (u32)(uintptr_t)desc->data); ++ ++ /* ...update cropping parameters */ ++ cfg->dst_subpixel = (type & IMR_MAP_DDP ? 2 : 0); ++ ++ /* ...display list updated successfully */ ++ v4l2_dbg(2, debug, &ctx->imr->v4l2_dev, "display-list created: #%u[%08X]:%u[%u]\n", ++ cfg->id, (u32)dl_dma_addr, dl_size, 0); ++ ++ if (debug >= 4) ++ print_hex_dump_bytes("DL-", DUMP_PREFIX_OFFSET, dl_vaddr + dl_start_offset, dl_size - dl_start_offset); ++ ++ /* ...success */ ++ return 0; ++} ++ ++/* ...set mapping data (function called with video device lock held) */ ++static int imr_ioctl_color(struct imr_ctx *ctx, u32 color) ++{ ++ ctx->color = color; ++ ++ return 0; ++} ++ + /******************************************************************************* + * V4L2 I/O controls + ******************************************************************************/ +@@ -1183,7 +1266,7 @@ static int imr_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) + WARN_ON(!mutex_is_locked(&ctx->imr->mutex)); + + /* ...verify the configuration is complete */ +- if (!V4L2_TYPE_IS_OUTPUT(buf->type) && !ctx->cfg) { ++ if (!ctx->cfg) { + v4l2_err(&ctx->imr->v4l2_dev, "stream configuration is not complete\n"); + return -EINVAL; + } +@@ -1265,6 +1348,14 @@ static long imr_default(struct file *file, void *fh, bool valid_prio, unsigned i + /* ...set mesh data */ + return imr_ioctl_map(ctx, (struct imr_map_desc *)arg); + ++ case VIDIOC_IMR_MESH_RAW: ++ /* ...set mesh data */ ++ return imr_ioctl_map_raw(ctx, (struct imr_map_desc *)arg); ++ ++ case VIDIOC_IMR_COLOR: ++ /* ...set solid color code */ ++ return imr_ioctl_color(ctx, *(u32 *)arg); ++ + default: + return -ENOIOCTLCMD; + } +@@ -1326,6 +1417,9 @@ static int imr_open(struct file *file) + /* ...set default cropping parameters */ + ctx->crop[1] = ctx->crop[3] = 0x3FF; + ++ /* ...set default color */ ++ ctx->color = 0x808080; ++ + /* ...initialize M2M processing context */ + ctx->m2m_ctx = v4l2_m2m_ctx_init(imr->m2m_dev, ctx, imr_queue_init); + if (IS_ERR(ctx->m2m_ctx)) { +@@ -1418,8 +1512,11 @@ static unsigned int imr_poll(struct file *file, struct poll_table_struct *wait) + return -ERESTARTSYS; + + res = v4l2_m2m_poll(file, ctx->m2m_ctx, wait); ++ + mutex_unlock(&imr->mutex); + ++ v4l2_dbg(3, debug, &imr->v4l2_dev, "poll result: %X (ctx=%p)\n", res, ctx); ++ + return res; + } + +@@ -1453,7 +1550,6 @@ static const struct v4l2_file_operations imr_fops = { + * M2M device interface + ******************************************************************************/ + +-#if 0 + /* ...job cleanup function */ + static void imr_cleanup(struct imr_ctx *ctx) + { +@@ -1473,17 +1569,16 @@ static void imr_cleanup(struct imr_ctx *ctx) + /* ...release lock before we mark current job as finished */ + spin_unlock_irqrestore(&imr->lock, flags); + } +-#endif + + /* ...job execution function */ + static void imr_device_run(void *priv) + { +- struct imr_ctx *ctx = priv; +- struct imr_device *imr = ctx->imr; +- struct imr_cfg *cfg; +- struct vb2_buffer *src_buf, *dst_buf; +- u32 src_addr, dst_addr; +- unsigned long flags; ++ struct imr_ctx *ctx = priv; ++ struct imr_device *imr = ctx->imr; ++ struct imr_cfg *cfg; ++ struct vb2_v4l2_buffer *src_buf, *dst_buf; ++ u32 src_addr, dst_addr; ++ unsigned long flags; + + v4l2_dbg(3, debug, &imr->v4l2_dev, "run next job...\n"); + +@@ -1494,8 +1589,11 @@ static void imr_device_run(void *priv) + src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); + dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); + ++ /* ...put source/destination buffers sequence numbers */ ++ dst_buf->sequence = src_buf->sequence = ctx->sequence++; ++ + /* ...take configuration pointer associated with input buffer */ +- cfg = to_imr_buffer(to_vb2_v4l2_buffer(src_buf))->cfg; ++ cfg = to_imr_buffer(src_buf)->cfg; + + /* ...cancel software reset state as needed */ + iowrite32(0, imr->mmio + IMR_CR); +@@ -1507,8 +1605,8 @@ static void imr_device_run(void *priv) + iowrite32(ctx->crop[3] << cfg->dst_subpixel, imr->mmio + IMR_YMAXR); + + /* ...adjust source/destination parameters of the program (interleaved / semiplanar) */ +- *cfg->src_pa_ptr[0] = src_addr = (u32)vb2_dma_contig_plane_dma_addr(src_buf, 0); +- *cfg->dst_pa_ptr[0] = dst_addr = (u32)vb2_dma_contig_plane_dma_addr(dst_buf, 0); ++ *cfg->src_pa_ptr[0] = src_addr = (u32)vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); ++ *cfg->dst_pa_ptr[0] = dst_addr = (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); + + /* ...adjust source/destination parameters of the UV-plane as needed */ + if (cfg->src_pa_ptr[1] && cfg->dst_pa_ptr[1]) { +@@ -1529,6 +1627,9 @@ static void imr_device_run(void *priv) + /* ...set display list address */ + iowrite32(cfg->dl_dma_addr + cfg->dl_start_offset, imr->mmio + IMR_DLSAR); + ++ /* ...enable texture prefetching */ ++ iowrite32(0xACCE5501, imr->mmio + IMR_TPOR); ++ + /* ...explicitly flush any pending write operations (don't need that, I guess) */ + wmb(); + +@@ -1536,7 +1637,7 @@ static void imr_device_run(void *priv) + iowrite32(IMR_CR_RS, imr->mmio + IMR_CR); + + /* ...timestamp input buffer */ +- src_buf->timestamp = ktime_get_ns(); ++ src_buf->vb2_buf.timestamp = ktime_get_ns(); + + /* ...unlock device access */ + spin_unlock_irqrestore(&imr->lock, flags); +@@ -1633,13 +1734,14 @@ static irqreturn_t imr_irq_handler(int irq, void *data) + dst_buf->timecode = src_buf->timecode; + dst_buf->flags = src_buf->flags & (V4L2_BUF_FLAG_TIMECODE | V4L2_BUF_FLAG_KEYFRAME | + V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | V4L2_BUF_FLAG_TSTAMP_SRC_MASK); +- dst_buf->sequence = src_buf->sequence = ctx->sequence++; ++ //dst_buf->sequence = src_buf->sequence = ctx->sequence++; ++ + v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); + v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); + +- v4l2_dbg(3, debug, &imr->v4l2_dev, "buffers <0x%08x,0x%08x> done\n", ++ v4l2_dbg(3, debug, &imr->v4l2_dev, "buffers <0x%08x,0x%08x> done (ctx=%p)\n", + (u32)vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0), +- (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0)); ++ (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0), ctx); + } else { + /* ...operation completed in error; no way to understand what exactly went wrong */ + v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); +@@ -1668,6 +1770,8 @@ static irqreturn_t imr_irq_handler(int irq, void *data) + * Device probing / removal interface + ******************************************************************************/ + ++static struct class *imr_alloc_class; ++ + static int imr_probe(struct platform_device *pdev) + { + struct imr_device *imr; +@@ -1727,6 +1831,26 @@ static int imr_probe(struct platform_device *pdev) + goto device_register_rollback; + } + ++ if (!imr_alloc_class) { ++ imr_alloc_class = class_create(THIS_MODULE, "imr-alloc"); ++ if (IS_ERR(imr_alloc_class)) { ++ v4l2_err(&imr->v4l2_dev, "Failed to create alloc-device class\n"); ++ ret = PTR_ERR(imr_alloc_class); ++ goto m2m_init_rollback; ++ } ++ } ++ ++ struct device *adev = device_create(imr_alloc_class, imr->dev, MKDEV(0, 0), NULL, "%s_alloc", dev_name(&pdev->dev)); ++ if (IS_ERR(adev)) { ++ v4l2_err(&imr->v4l2_dev, "Failed to create alloc-device\n"); ++ ret = PTR_ERR(adev); ++ goto m2m_init_rollback; ++ } ++ adev->dma_mask = &adev->coherent_dma_mask; ++ adev->coherent_dma_mask = DMA_BIT_MASK(32); ++ arch_setup_dma_ops(adev, 0, DMA_BIT_MASK(32) + 1, NULL, true); ++ imr->alloc_dev = adev; ++ + strlcpy(imr->video_dev.name, dev_name(&pdev->dev), sizeof(imr->video_dev.name)); + imr->video_dev.fops = &imr_fops; + imr->video_dev.ioctl_ops = &imr_ioctl_ops; +@@ -1765,6 +1889,7 @@ static int imr_remove(struct platform_device *pdev) + + //pm_runtime_disable(imr->v4l2_dev.dev); + video_unregister_device(&imr->video_dev); ++ //device_destroy(imr->alloc_dev, MKDEV(0, 0)); + v4l2_m2m_release(imr->m2m_dev); + v4l2_device_unregister(&imr->v4l2_dev); + +diff --git a/include/uapi/linux/rcar-imr.h b/include/uapi/linux/rcar-imr.h +index d02082f..7b8ed0c 100644 +--- a/include/uapi/linux/rcar-imr.h ++++ b/include/uapi/linux/rcar-imr.h +@@ -48,6 +48,12 @@ struct imr_map_desc { + /* ...vertex clockwise-mode order */ + #define IMR_MAP_TCM (1 << 5) + ++/* ...texture mapping enable flag */ ++#define IMR_MAP_TME (1 << 6) ++ ++/* ...bilinear filtration enable flag */ ++#define IMR_MAP_BFE (1 << 7) ++ + /* ...source coordinate decimal point position bit index */ + #define __IMR_MAP_UVDPOR_SHIFT 8 + #define __IMR_MAP_UVDPOR(v) (((v) >> __IMR_MAP_UVDPOR_SHIFT) & 0x7) +@@ -81,18 +87,12 @@ struct imr_mesh { + + } __attribute__((packed)); + +-/* ...VBO descriptor */ +-struct imr_vbo { +- /* ...number of triangles */ +- u16 num; +- +-} __attribute__((packed)); +- +- + /******************************************************************************* + * Private IOCTL codes + ******************************************************************************/ + + #define VIDIOC_IMR_MESH _IOW('V', BASE_VIDIOC_PRIVATE + 0, struct imr_map_desc) ++#define VIDIOC_IMR_MESH_RAW _IOW('V', BASE_VIDIOC_PRIVATE + 1, struct imr_map_desc) ++#define VIDIOC_IMR_COLOR _IOW('V', BASE_VIDIOC_PRIVATE + 2, u32) + + #endif /* RCAR_IMR_USER_H */ +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0336-media-rcar-imr-Add-RSE-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0336-media-rcar-imr-Add-RSE-support.patch new file mode 100644 index 00000000..a836dd9f --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0336-media-rcar-imr-Add-RSE-support.patch @@ -0,0 +1,348 @@ +From 4b93294c7d2ca2c6323dbb49c5447718d6503d2c Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Tue, 6 Feb 2018 13:38:34 +0300 +Subject: [PATCH 156/211] media: rcar-imr: Add RSE support + +This adds RSE support for V3H IMR + +Signed-off-by: Andrey Dolnikov +--- + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 2 + + drivers/media/platform/rcar_imr.c | 143 ++++++++++++++++++++++++++++++ + include/uapi/linux/rcar-imr.h | 22 ++++- + 3 files changed, 165 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index 302b346..fc0b008 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -1260,6 +1260,7 @@ + interrupts = ; + clocks = <&cpg CPG_MOD 707>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ rse; + }; + + imrlx4_ch5: imr5@fe8b0000 { +@@ -1269,6 +1270,7 @@ + interrupts = ; + clocks = <&cpg CPG_MOD 706>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ rse; + }; + + vip_disp_status { +diff --git a/drivers/media/platform/rcar_imr.c b/drivers/media/platform/rcar_imr.c +index 9b601da..7b16765 100644 +--- a/drivers/media/platform/rcar_imr.c ++++ b/drivers/media/platform/rcar_imr.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -38,6 +39,9 @@ MODULE_PARM_DESC(debug, "Debug level (0-4)"); + * Local types definitions + ******************************************************************************/ + ++/* Number of RSE planes on V3H (non scaled, 1/2, 1/4, 1/8) */ ++#define RSE_PLANES_NUM 4 ++ + /* ...configuration data */ + struct imr_cfg { + /* ...display-list main program data */ +@@ -49,6 +53,21 @@ struct imr_cfg { + /* ...pointers to the source/destination planes */ + u32 *src_pa_ptr[2]; + u32 *dst_pa_ptr[2]; ++ /* ...pointers to the RSE destination planes */ ++ u32 *dstn_pa_ptr[RSE_PLANES_NUM]; ++ u32 *dstr_pa_ptr[RSE_PLANES_NUM]; ++ ++ /* ...offsets to RSE destination planes */ ++ u32 dstnr_offsets[IMR_EXTDST_NUM]; ++ ++ /* ...RSE logical right shift data */ ++ u32 *rscr_ptr; ++ u8 rscr_sc8, rscr_sc4, rscr_sc2; ++ ++ /* ...RSE destination stride values */ ++ u32 dstnr_strides[IMR_EXTDST_NUM]; ++ u32 *striden_ptr[RSE_PLANES_NUM]; ++ u32 *strider_ptr[RSE_PLANES_NUM]; + + /* ...subpixel destination coordinates space */ + int dst_subpixel; +@@ -96,6 +115,8 @@ struct imr_device { + struct v4l2_m2m_dev *m2m_dev; + struct device *alloc_dev; + ++ bool rse; ++ + /* ...do we need that counter really? framework counts fh structures for us - tbd */ + int refcount; + +@@ -219,6 +240,18 @@ struct imr_ctx { + + #define IMR_TPOR 0xF0 + ++#define IMR_RSCSR 0x204 ++#define IMR_RSCCR 0x208 ++#define IMR_RSCR_RSE 31 ++#define IMR_RSCR_SC8 25 ++#define IMR_RSCR_SC4 21 ++#define IMR_RSCR_SC2 17 ++ ++#define IMR_DSANRR0 0x210 ++#define IMR_DSTNRR0 0x214 ++#define IMR_DSARR0 0x218 ++#define IMR_DSTRR0 0x21C ++ + /******************************************************************************* + * Auxiliary helpers + ******************************************************************************/ +@@ -398,6 +431,7 @@ static int imr_queue_setup(struct vb2_queue *vq, + case V4L2_PIX_FMT_YVYU: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_Y10: ++ case V4L2_PIX_FMT_Y12: + case V4L2_PIX_FMT_Y16: + sizes[0] = w * h * 2; + break; +@@ -750,6 +784,7 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg + int W = ctx->queue[1].fmt.width; + int H = ctx->queue[1].fmt.height; + u32 tricr = ctx->color & 0xFFFFFF; ++ int i; + + v4l2_dbg(2, debug, &ctx->imr->v4l2_dev, "setup %u*%u -> %u*%u mapping (type=%x)\n", w, h, W, H, type); + +@@ -775,6 +810,38 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg + *dl++ = IMR_OP_WTS(IMR_CMRCCR, 0xFFFF); + *dl++ = IMR_OP_WTS(IMR_CMRCCR2, 0xFFFF); + ++ if (type & IMR_MAP_RSE) { ++ /* ...enable RSE */ ++ *dl++ = IMR_OP_WTL(IMR_RSCCR, 1); ++ *dl++ = 0xffffffff; ++ *dl++ = IMR_OP_WTL(IMR_RSCSR, 1); ++ cfg->rscr_ptr = dl++; ++ ++ for (i = 0; i < RSE_PLANES_NUM; i++) { ++ /* ...set destination planes base address and strides */ ++ *dl++ = IMR_OP_WTL(IMR_DSANRR0 + i * 0x10, 4); ++ cfg->dstn_pa_ptr[i] = dl++; ++ cfg->striden_ptr[i] = dl++; ++ cfg->dstr_pa_ptr[i] = dl++; ++ cfg->strider_ptr[i] = dl++; ++ } ++ ++ cfg->rscr_sc8 = cfg->rscr_sc4 = cfg->rscr_sc2 = 0; ++ memset(cfg->dstnr_offsets, 0, sizeof(cfg->dstnr_offsets)); ++ memset(cfg->dstnr_strides, 0, sizeof(cfg->dstnr_strides)); ++ } else { ++ /* ...disable RSE */ ++ *dl++ = IMR_OP_WTL(IMR_RSCCR, 1); ++ *dl++ = 0xffffffff; ++ ++ for (i = 0; i < RSE_PLANES_NUM; i++) { ++ cfg->dstn_pa_ptr[i] = NULL; ++ cfg->striden_ptr[i] = NULL; ++ cfg->dstr_pa_ptr[i] = NULL; ++ cfg->strider_ptr[i] = NULL; ++ } ++ cfg->rscr_ptr = NULL; ++ } + /* ...set source/destination addresses of Y/UV plane */ + *dl++ = IMR_OP_WTL(IMR_DSAR, 2); + cfg->dst_pa_ptr[0] = dl++; +@@ -907,6 +974,12 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc) + + type = desc->type; + ++ /* ...check for RSE */ ++ if ((type & IMR_MAP_RSE) && !imr->rse) { ++ v4l2_err(&imr->v4l2_dev, "Rotator & Scaler extension not supported\n"); ++ return -EINVAL; ++ } ++ + /* ...mesh item size calculation */ + item_size = (type & IMR_MAP_LUCE ? 4 : 0) + (type & IMR_MAP_CLCE ? 4 : 0); + +@@ -1055,6 +1128,12 @@ static int imr_ioctl_map_raw(struct imr_ctx *ctx, struct imr_map_desc *desc) + u32 dl_start_offset; + dma_addr_t dl_dma_addr; + ++ /* ...check RSE */ ++ if ((type & IMR_MAP_RSE) && !imr->rse) { ++ v4l2_err(&imr->v4l2_dev, "Rotator & Scaler extension not supported\n"); ++ return -EINVAL; ++ } ++ + /* ...calculate main routine length */ + dl_size = imr_dl_program_length(ctx); + if (!dl_size) { +@@ -1103,6 +1182,46 @@ static int imr_ioctl_color(struct imr_ctx *ctx, u32 color) + return 0; + } + ++static int imr_extdst_set(struct imr_ctx *ctx, u32 *extdst) ++{ ++ struct imr_device *imr = ctx->imr; ++ struct imr_cfg *cfg = ctx->cfg; ++ ++ if (!cfg) { ++ v4l2_err(&imr->v4l2_dev, "failed to set V3H extension dst buffers: No active confguration.\n"); ++ return -EINVAL; ++ } ++ ++ if (copy_from_user((void *) cfg->dstnr_offsets, (void __user *) extdst, sizeof(cfg->dstnr_offsets))) { ++ v4l2_err(&imr->v4l2_dev, "failed to read V3H extension dst buffers\n"); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++static int imr_extstride_set(struct imr_ctx *ctx, struct imr_rse_param *param) ++{ ++ struct imr_device *imr = ctx->imr; ++ struct imr_cfg *cfg = ctx->cfg; ++ ++ if (!cfg) { ++ v4l2_err(&imr->v4l2_dev, "failed to set V3H extension buffers params: No active confguration.\n"); ++ return -EINVAL; ++ } ++ ++ cfg->rscr_sc8 = param->sc8; ++ cfg->rscr_sc4 = param->sc4; ++ cfg->rscr_sc2 = param->sc2; ++ ++ if (copy_from_user((void *) cfg->dstnr_strides, (void __user *) param->strides, sizeof(cfg->dstnr_strides))) { ++ v4l2_err(&imr->v4l2_dev, "failed to read V3H extension buffers strides\n"); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ + /******************************************************************************* + * V4L2 I/O controls + ******************************************************************************/ +@@ -1356,6 +1475,14 @@ static long imr_default(struct file *file, void *fh, bool valid_prio, unsigned i + /* ...set solid color code */ + return imr_ioctl_color(ctx, *(u32 *)arg); + ++ case VIDIOC_IMR_EXTDST: ++ /* ...set V3H extension dst buffers */ ++ return imr_extdst_set(ctx, *(u32 **)arg); ++ ++ case VIDIOC_IMR_EXTSTRIDE: ++ /* ...set V3H extension dst strides */ ++ return imr_extstride_set(ctx, (struct imr_rse_param *)arg); ++ + default: + return -ENOIOCTLCMD; + } +@@ -1579,6 +1706,7 @@ static void imr_device_run(void *priv) + struct vb2_v4l2_buffer *src_buf, *dst_buf; + u32 src_addr, dst_addr; + unsigned long flags; ++ int i; + + v4l2_dbg(3, debug, &imr->v4l2_dev, "run next job...\n"); + +@@ -1608,6 +1736,17 @@ static void imr_device_run(void *priv) + *cfg->src_pa_ptr[0] = src_addr = (u32)vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); + *cfg->dst_pa_ptr[0] = dst_addr = (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); + ++ for (i = 0; i < RSE_PLANES_NUM; i++) { ++ if (cfg->rscr_ptr) *cfg->rscr_ptr = (1 << IMR_RSCR_RSE) | (cfg->rscr_sc8 << IMR_RSCR_SC8) | ++ (cfg->rscr_sc4 << IMR_RSCR_SC4) |(cfg->rscr_sc2 << IMR_RSCR_SC2); ++ ++ if (cfg->dstn_pa_ptr[i]) *cfg->dstn_pa_ptr[i] = dst_addr + cfg->dstnr_offsets[i]; ++ if (cfg->dstr_pa_ptr[i]) *cfg->dstr_pa_ptr[i] = dst_addr + cfg->dstnr_offsets[i + RSE_PLANES_NUM]; ++ ++ if (cfg->striden_ptr[i]) *cfg->striden_ptr[i] = cfg->dstnr_strides[i]; ++ if (cfg->strider_ptr[i]) *cfg->strider_ptr[i] = cfg->dstnr_strides[i + RSE_PLANES_NUM]; ++ } ++ + /* ...adjust source/destination parameters of the UV-plane as needed */ + if (cfg->src_pa_ptr[1] && cfg->dst_pa_ptr[1]) { + *cfg->src_pa_ptr[1] = src_addr + ctx->queue[0].fmt.width * ctx->queue[0].fmt.height; +@@ -1776,6 +1915,7 @@ static int imr_probe(struct platform_device *pdev) + { + struct imr_device *imr; + struct resource *res; ++ struct device_node *np = pdev->dev.of_node; + int ret; + + imr = devm_kzalloc(&pdev->dev, sizeof(*imr), GFP_KERNEL); +@@ -1786,6 +1926,9 @@ static int imr_probe(struct platform_device *pdev) + spin_lock_init(&imr->lock); + imr->dev = &pdev->dev; + ++ /* Check RSE support */ ++ imr->rse = of_property_read_bool(np, "rse"); ++ + /* ...memory-mapped registers */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { +diff --git a/include/uapi/linux/rcar-imr.h b/include/uapi/linux/rcar-imr.h +index 7b8ed0c..93098d2 100644 +--- a/include/uapi/linux/rcar-imr.h ++++ b/include/uapi/linux/rcar-imr.h +@@ -25,8 +25,8 @@ struct imr_map_desc { + /* ...total size of the mesh structure */ + u32 size; + +- /* ...map-specific user-pointer */ +- void *data; ++ /* ...map-specific user-pointer */ ++ void *data; + + } __attribute__((packed)); + +@@ -54,6 +54,9 @@ struct imr_map_desc { + /* ...bilinear filtration enable flag */ + #define IMR_MAP_BFE (1 << 7) + ++/* ...extended functionality (rotation/scaling) enable flag */ ++#define IMR_MAP_RSE (1 << 21) ++ + /* ...source coordinate decimal point position bit index */ + #define __IMR_MAP_UVDPOR_SHIFT 8 + #define __IMR_MAP_UVDPOR(v) (((v) >> __IMR_MAP_UVDPOR_SHIFT) & 0x7) +@@ -88,11 +91,26 @@ struct imr_mesh { + } __attribute__((packed)); + + /******************************************************************************* ++ * V3H Extension destination data ++ ******************************************************************************/ ++/* ...number of V3H extension destination buffers (rotated/non-rotated, scaled 1/1, 1/2, 1/4, 1/8) */ ++#define IMR_EXTDST_NUM 8 ++ ++struct imr_rse_param { ++ /* ...logical right shift data */ ++ u8 sc8, sc4, sc2; ++ /* ...destination buffers stride */ ++ u32 *strides; ++}; ++ ++/******************************************************************************* + * Private IOCTL codes + ******************************************************************************/ + + #define VIDIOC_IMR_MESH _IOW('V', BASE_VIDIOC_PRIVATE + 0, struct imr_map_desc) + #define VIDIOC_IMR_MESH_RAW _IOW('V', BASE_VIDIOC_PRIVATE + 1, struct imr_map_desc) + #define VIDIOC_IMR_COLOR _IOW('V', BASE_VIDIOC_PRIVATE + 2, u32) ++#define VIDIOC_IMR_EXTDST _IOW('V', BASE_VIDIOC_PRIVATE + 3, u32 *) ++#define VIDIOC_IMR_EXTSTRIDE _IOW('V', BASE_VIDIOC_PRIVATE + 4, struct imr_rse_param) + + #endif /* RCAR_IMR_USER_H */ +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0337-rcar_imr-v4l2-driver-Fix-module-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0337-rcar_imr-v4l2-driver-Fix-module-support.patch new file mode 100644 index 00000000..2a5adbf0 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0337-rcar_imr-v4l2-driver-Fix-module-support.patch @@ -0,0 +1,278 @@ +From 689485ff61b8b96b180caf7ccaf19f7e3cf3c9bb Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Mon, 5 Nov 2018 23:34:53 +0300 +Subject: [PATCH 157/211] rcar_imr v4l2 driver: Fix module support. + +--- + arch/arm64/boot/dts/renesas/r8a7795.dtsi | 8 ++++++++ + arch/arm64/boot/dts/renesas/r8a7796.dtsi | 6 ++++++ + arch/arm64/boot/dts/renesas/r8a77970.dtsi | 8 ++++++++ + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 10 ++++++++++ + drivers/media/platform/rcar_imr.c | 32 ++++++++++++++++++++++++++++--- + 5 files changed, 61 insertions(+), 3 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi +index e749633..e1b57e9 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi +@@ -2785,6 +2785,10 @@ + status = "disabled"; + }; + ++ imr_v4l2_alloc: imr_alloc { ++ dma-coherent; ++ }; ++ + imrlx4_ch0: imr0@fe860000 { + compatible = "renesas,r8a7795-imr-lx4", + "renesas,imr-lx4"; +@@ -2793,6 +2797,7 @@ + clocks = <&cpg CPG_MOD 823>; + power-domains = <&sysc R8A7795_PD_A3VC>; + resets = <&cpg 823>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imrlx4_ch1: imr1@fe870000 { +@@ -2803,6 +2808,7 @@ + clocks = <&cpg CPG_MOD 822>; + power-domains = <&sysc R8A7795_PD_A3VC>; + resets = <&cpg 822>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imrlx4_ch2: imr2@fe880000 { +@@ -2813,6 +2819,7 @@ + clocks = <&cpg CPG_MOD 821>; + power-domains = <&sysc R8A7795_PD_A3VC>; + resets = <&cpg 821>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imrlx4_ch3: imr3@fe890000 { +@@ -2823,6 +2830,7 @@ + clocks = <&cpg CPG_MOD 820>; + power-domains = <&sysc R8A7795_PD_A3VC>; + resets = <&cpg 820>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + fcpcs: vcp4@fe90f000 { +diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi +index 49068a8..7fcac8f 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7796.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi +@@ -2618,6 +2618,10 @@ + status = "disabled"; + }; + ++ imr_v4l2_alloc: imr_alloc { ++ dma-coherent; ++ }; ++ + imrlx4_ch0: imr0@fe860000 { + compatible = "renesas,r8a7796-imr-lx4", + "renesas,imr-lx4"; +@@ -2626,6 +2630,7 @@ + clocks = <&cpg CPG_MOD 823>; + power-domains = <&sysc R8A7796_PD_A3VC>; + resets = <&cpg 823>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imrlx4_ch1: imr1@fe870000 { +@@ -2636,6 +2641,7 @@ + clocks = <&cpg CPG_MOD 822>; + power-domains = <&sysc R8A7796_PD_A3VC>; + resets = <&cpg 822>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imp_distributer: impdes0 { +diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +index 40e28338..77ee934 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +@@ -968,6 +968,10 @@ + power-domains = <&sysc R8A77970_PD_A3IR>; + }; + ++ imr_v4l2_alloc: imr_alloc { ++ dma-coherent; ++ }; ++ + imrlx4_ch0: imr0@fe860000 { + compatible = "renesas,r8a77970-imr-lx4", + "renesas,imr-lx4"; +@@ -976,6 +980,7 @@ + clocks = <&cpg CPG_MOD 823>; + power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; + resets = <&cpg 823>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imrlx4_ch1: imr1@fe870000 { +@@ -986,6 +991,7 @@ + clocks = <&cpg CPG_MOD 822>; + power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; + resets = <&cpg 822>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imrlx4_ch2: imr2@fe880000 { +@@ -996,6 +1002,7 @@ + clocks = <&cpg CPG_MOD 821>; + power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; + resets = <&cpg 821>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imrlx4_ch3: imr3@fe890000 { +@@ -1006,6 +1013,7 @@ + clocks = <&cpg CPG_MOD 820>; + power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; + resets = <&cpg 820>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + isp@fec00000 { +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index fc0b008..8af443d 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -1213,6 +1213,10 @@ + power-domains = <&sysc R8A77980_PD_A3IR>; + }; + ++ imr_v4l2_alloc: imr_alloc { ++ dma-coherent; ++ }; ++ + imrlx4_ch0: imr0@fe860000 { + compatible = "renesas,r8a77980-imr-lx4", + "renesas,imr-lx4"; +@@ -1221,6 +1225,7 @@ + clocks = <&cpg CPG_MOD 823>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 823>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imrlx4_ch1: imr1@fe870000 { +@@ -1231,6 +1236,7 @@ + clocks = <&cpg CPG_MOD 822>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 822>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imrlx4_ch2: imr2@fe880000 { +@@ -1241,6 +1247,7 @@ + clocks = <&cpg CPG_MOD 821>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 821>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imrlx4_ch3: imr3@fe890000 { +@@ -1251,6 +1258,7 @@ + clocks = <&cpg CPG_MOD 820>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + resets = <&cpg 820>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imrlx4_ch4: imr4@fe8a0000 { +@@ -1261,6 +1269,7 @@ + clocks = <&cpg CPG_MOD 707>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + rse; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imrlx4_ch5: imr5@fe8b0000 { +@@ -1271,6 +1280,7 @@ + clocks = <&cpg CPG_MOD 706>; + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + rse; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + vip_disp_status { +diff --git a/drivers/media/platform/rcar_imr.c b/drivers/media/platform/rcar_imr.c +index 7b16765..607778e 100644 +--- a/drivers/media/platform/rcar_imr.c ++++ b/drivers/media/platform/rcar_imr.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1917,6 +1918,8 @@ static int imr_probe(struct platform_device *pdev) + struct resource *res; + struct device_node *np = pdev->dev.of_node; + int ret; ++ phandle *prop; ++ struct device_node *node; + + imr = devm_kzalloc(&pdev->dev, sizeof(*imr), GFP_KERNEL); + if (!imr) +@@ -1989,10 +1992,15 @@ static int imr_probe(struct platform_device *pdev) + ret = PTR_ERR(adev); + goto m2m_init_rollback; + } ++ + adev->dma_mask = &adev->coherent_dma_mask; + adev->coherent_dma_mask = DMA_BIT_MASK(32); +- arch_setup_dma_ops(adev, 0, DMA_BIT_MASK(32) + 1, NULL, true); + imr->alloc_dev = adev; ++ prop = of_get_property(np, "alloc-dev", NULL); ++ if (prop) { ++ node = of_find_node_by_phandle(be32_to_cpup(prop)); ++ of_dma_configure(adev, node, true); ++ } + + strlcpy(imr->video_dev.name, dev_name(&pdev->dev), sizeof(imr->video_dev.name)); + imr->video_dev.fops = &imr_fops; +@@ -2032,7 +2040,6 @@ static int imr_remove(struct platform_device *pdev) + + //pm_runtime_disable(imr->v4l2_dev.dev); + video_unregister_device(&imr->video_dev); +- //device_destroy(imr->alloc_dev, MKDEV(0, 0)); + v4l2_m2m_release(imr->m2m_dev); + v4l2_device_unregister(&imr->v4l2_dev); + +@@ -2100,7 +2107,26 @@ static struct platform_driver imr_platform_driver = { + }, + }; + +-module_platform_driver(imr_platform_driver); ++static int __init imr_module_init(void) ++{ ++ return platform_driver_register(&imr_platform_driver); ++} ++ ++static int imr_device_destroy(struct device *dev, void *data) ++{ ++ device_destroy(imr_alloc_class, dev->devt); ++ return 0; ++} ++ ++static void __exit imr_module_exit(void) ++{ ++ class_for_each_device(imr_alloc_class, NULL, NULL, imr_device_destroy); ++ class_destroy(imr_alloc_class); ++ platform_driver_unregister(&imr_platform_driver); ++} ++ ++module_init(imr_module_init); ++module_exit(imr_module_exit); + + MODULE_ALIAS("imr"); + MODULE_AUTHOR("Cogent Embedded Inc. "); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0338-V3Hsk-Condor-and-V3Msk-Eagle-Remove-cma-default-area.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0338-V3Hsk-Condor-and-V3Msk-Eagle-Remove-cma-default-area.patch new file mode 100644 index 00000000..11b4ee62 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0338-V3Hsk-Condor-and-V3Msk-Eagle-Remove-cma-default-area.patch @@ -0,0 +1,103 @@ +From 7fb5561dd487a5fb987fd94dd016a96bf0547daf Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Tue, 6 Nov 2018 14:00:29 +0300 +Subject: [PATCH 158/211] V3Hsk/Condor and V3Msk/Eagle: Remove cma-default area + from dts. + +To be defined using 'cma' kernel command line parameter. +--- + arch/arm64/boot/dts/renesas/r8a77970-eagle.dts | 9 +-------- + arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts | 9 +-------- + arch/arm64/boot/dts/renesas/r8a77980-condor.dts | 10 +--------- + arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts | 10 +--------- + 4 files changed, 4 insertions(+), 34 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +index dd484d5..b87f418 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +@@ -38,16 +38,9 @@ + /* device specific region for Lossy Decompression */ + lossy_decompress: linux,lossy_decompress { + no-map; +- reg = <0x00000000 0x6c000000 0x0 0x03000000>; ++ reg = <0x00000000 0x7c000000 0x0 0x03000000>; + }; + +- /* global autoconfigured region for contiguous allocations */ +- linux,cma { +- compatible = "shared-dma-pool"; +- reusable; +- reg = <0x00000000 0x6f000000 0x0 0x10000000>; +- linux,cma-default; +- }; + + /* device specific region for contiguous allocations */ + mmp_reserved: linux,multimedia { +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +index 4cc11c9..af6c7b9 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +@@ -35,16 +35,9 @@ + /* device specific region for Lossy Decompression */ + lossy_decompress: linux,lossy_decompress { + no-map; +- reg = <0x00000000 0x6c000000 0x0 0x03000000>; ++ reg = <0x00000000 0x7c000000 0x0 0x03000000>; + }; + +- /* global autoconfigured region for contiguous allocations */ +- linux,cma { +- compatible = "shared-dma-pool"; +- reusable; +- reg = <0x00000000 0x6f000000 0x0 0x10000000>; +- linux,cma-default; +- }; + + /* device specific region for contiguous allocations */ + mmp_reserved: linux,multimedia { +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +index f3b7ebe..577ff3a 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +@@ -38,15 +38,7 @@ + /* device specific region for Lossy Decompression */ + lossy_decompress: linux,lossy_decompress { + no-map; +- reg = <0x00000000 0x6c000000 0x0 0x03000000>; +- }; +- +- /* global autoconfigured region for contiguous allocations */ +- linux,cma { +- compatible = "shared-dma-pool"; +- reusable; +- reg = <0x00000000 0x6f000000 0x0 0x10000000>; +- linux,cma-default; ++ reg = <0x00000000 0x7c000000 0x0 0x03000000>; + }; + + /* device specific region for contiguous allocations */ +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +index 549ca5e..cfd9c89 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +@@ -36,15 +36,7 @@ + /* device specific region for Lossy Decompression */ + lossy_decompress: linux,lossy_decompress { + no-map; +- reg = <0x00000000 0x6c000000 0x0 0x03000000>; +- }; +- +- /* global autoconfigured region for contiguous allocations */ +- linux,cma { +- compatible = "shared-dma-pool"; +- reusable; +- reg = <0x00000000 0x6f000000 0x0 0x10000000>; +- linux,cma-default; ++ reg = <0x00000000 0x7c000000 0x0 0x03000000>; + }; + + /* device specific region for contiguous allocations */ +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0339-media-rcar_imr-Enable-LUCE-for-NV16-format.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0339-media-rcar_imr-Enable-LUCE-for-NV16-format.patch new file mode 100644 index 00000000..bbd3f515 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0339-media-rcar_imr-Enable-LUCE-for-NV16-format.patch @@ -0,0 +1,49 @@ +From 0d71cf7d1b39f5a5f65efce898c1953e18a069b5 Mon Sep 17 00:00:00 2001 +From: Konstantin Kozhevnikov +Date: Thu, 30 Aug 2018 20:30:13 +0300 +Subject: [PATCH 159/211] media: rcar_imr: Enable LUCE for NV16 format + +Enable LUCE for NV16 format + +Signed-off-by: Konstantin Kozhevnikov +--- + drivers/media/platform/rcar_imr.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/media/platform/rcar_imr.c b/drivers/media/platform/rcar_imr.c +index 607778e..8864b0b 100644 +--- a/drivers/media/platform/rcar_imr.c ++++ b/drivers/media/platform/rcar_imr.c +@@ -853,14 +853,14 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg + /* ...planar input means planar output; set Y-plane precision */ + if (cflags & IMR_F_Y8) { + /* ...setup Y-plane processing: YCM=0, SY/DY=xx, SUV/DUV=0 */ +- *dl++ = IMR_OP_WTS(IMR_CMRCSR, src_y_fmt | src_uv_fmt | dst_y_fmt | dst_uv_fmt | __imr_luce(type)); ++ *dl++ = IMR_OP_WTS(IMR_CMRCSR, src_y_fmt | src_uv_fmt | dst_y_fmt | dst_uv_fmt | __imr_luce(type) | __imr_clce(type)); + + /* ...set source/destination strides basing on Y-plane precision */ + *dl++ = IMR_OP_WTS(IMR_DSTR, W << (cflags & IMR_F_Y10 ? 1 : 0)); + *dl++ = IMR_OP_WTS(IMR_SSTR, w << (iflags & IMR_F_Y10 ? 1 : 0)); + } else { + /* ...setup UV-plane processing only */ +- *dl++ = IMR_OP_WTS(IMR_CMRCSR, IMR_CMR_YCM | src_uv_fmt | dst_uv_fmt | __imr_clce(type)); ++ *dl++ = IMR_OP_WTS(IMR_CMRCSR, IMR_CMR_YCM | src_uv_fmt | dst_uv_fmt | __imr_clce(type) | __imr_luce(type)); + + /* ...set source/destination strides basing on UV-plane precision */ + *dl++ = IMR_OP_WTS(IMR_DSTR, W << (cflags & IMR_F_UV10 ? 1 : 0)); +@@ -919,10 +919,10 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg + cfg->src_pa_ptr[1] = dl++; + + /* ...select correction mode */ +- *dl++ = IMR_OP_WTS(IMR_CMRCSR, IMR_CMR_YCM | __imr_clce(type)); ++ *dl++ = IMR_OP_WTS(IMR_CMRCSR, IMR_CMR_YCM | __imr_clce(type) | __imr_luce(type)); + + /* ...luminance correction bit must be cleared (if it was set) */ +- *dl++ = IMR_OP_WTS(IMR_CMRCCR, IMR_CMR_LUCE); ++ //*dl++ = IMR_OP_WTS(IMR_CMRCCR, IMR_CMR_LUCE); + + /* ...draw triangles */ + *dl++ = IMR_OP_GOSUB; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0340-clk-cs2000-add-support-for-cs2300.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0340-clk-cs2000-add-support-for-cs2300.patch new file mode 100644 index 00000000..d700542b --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0340-clk-cs2000-add-support-for-cs2300.patch @@ -0,0 +1,256 @@ +From 1d14f9f23a8122fb286eb7c93cadd2233ac789ab Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Tue, 6 Nov 2018 16:43:06 +0300 +Subject: [PATCH 160/211] clk: cs2000 add support for cs2300 + +Signed-off-by: Andrey Gusakov +--- + drivers/clk/Kconfig | 5 ++- + drivers/clk/clk-cs2000-cp.c | 101 +++++++++++++++++++++++++++++++++----------- + 2 files changed, 79 insertions(+), 27 deletions(-) + +diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig +index 1c4e1aa..51667a3 100644 +--- a/drivers/clk/Kconfig ++++ b/drivers/clk/Kconfig +@@ -128,10 +128,11 @@ config COMMON_CLK_CDCE925 + divider to best approximate the desired output. + + config COMMON_CLK_CS2000_CP +- tristate "Clock driver for CS2000 Fractional-N Clock Synthesizer & Clock Multiplier" ++ tristate "Clock driver for CS2x00 Fractional-N Clock Synthesizer & Clock Multiplier" + depends on I2C + help +- If you say yes here you get support for the CS2000 clock multiplier. ++ If you say yes here you get support for the CS2000 and CS2300 clock ++ multiplier. + + config COMMON_CLK_GEMINI + bool "Clock driver for Cortina Systems Gemini SoC" +diff --git a/drivers/clk/clk-cs2000-cp.c b/drivers/clk/clk-cs2000-cp.c +index e8ea81c..2708e82 100644 +--- a/drivers/clk/clk-cs2000-cp.c ++++ b/drivers/clk/clk-cs2000-cp.c +@@ -28,6 +28,7 @@ + #define Val_Ratio(x, nth) ((x & 0xFF) << (24 - (8 * nth))) + #define FUNC_CFG1 0x16 + #define FUNC_CFG2 0x17 ++#define FUNC_CFG3 0x1E + + /* DEVICE_ID */ + #define REVISION_MASK (0x7) +@@ -57,8 +58,11 @@ + + /* FUNC_CFG1 */ + #define CLKSKIPEN (1 << 7) ++#define ENDEV3 (1 << 4) + #define REFCLKDIV(x) (((x) & 0x3) << 3) + #define REFCLKDIV_MASK REFCLKDIV(0x3) ++#define RMODSEL(x) (((x) & 0x7) << 5) ++#define RMODSEL_MASK RMODSEL(0x7) + + /* FUNC_CFG2 */ + #define LFRATIO_MASK (1 << 3) +@@ -74,6 +78,11 @@ + #define REF_CLK 1 + #define CLK_MAX 2 + ++enum cs2x00_type { ++ DEVICE_CS2000, ++ DEVICE_CS2300 ++}; ++ + struct cs2000_priv { + struct clk_hw hw; + struct i2c_client *client; +@@ -83,16 +92,20 @@ struct cs2000_priv { + /* suspend/resume */ + unsigned long saved_rate; + unsigned long saved_parent_rate; ++ ++ enum cs2x00_type type; + }; + + static const struct of_device_id cs2000_of_match[] = { +- { .compatible = "cirrus,cs2000-cp", }, ++ { .compatible = "cirrus,cs2000-cp", .data = (void *)DEVICE_CS2000}, ++ { .compatible = "cirrus,cs2300-cp", .data = (void *)DEVICE_CS2300}, + {}, + }; + MODULE_DEVICE_TABLE(of, cs2000_of_match); + + static const struct i2c_device_id cs2000_id[] = { +- { "cs2000-cp", }, ++ { "cs2000-cp", DEVICE_CS2000}, ++ { "cs2300-cp", DEVICE_CS2300}, + {} + }; + MODULE_DEVICE_TABLE(i2c, cs2000_id); +@@ -130,8 +143,13 @@ static int cs2000_enable_dev_config(struct cs2000_priv *priv, bool enable) + if (ret < 0) + return ret; + +- ret = cs2000_bset(priv, FUNC_CFG1, CLKSKIPEN, +- enable ? CLKSKIPEN : 0); ++ if (priv->type == DEVICE_CS2000) { ++ ret = cs2000_bset(priv, FUNC_CFG1, CLKSKIPEN, ++ enable ? CLKSKIPEN : 0); ++ } else { ++ ret = cs2000_bset(priv, FUNC_CFG1, CLKSKIPEN | ENDEV3, ++ enable ? (CLKSKIPEN | ENDEV3) : 0); ++ } + if (ret < 0) + return ret; + +@@ -163,6 +181,15 @@ static int cs2000_clk_in_bound_rate(struct cs2000_priv *priv, + REFCLKDIV(val)); + } + ++ ++static int cs2300_clk_rmod_set(struct cs2000_priv *priv, ++ u32 rmod) ++{ ++ return cs2000_bset(priv, FUNC_CFG1, ++ RMODSEL_MASK, ++ RMODSEL(rmod)); ++} ++ + static int cs2000_wait_pll_lock(struct cs2000_priv *priv) + { + struct device *dev = priv_to_dev(priv); +@@ -316,17 +343,27 @@ static int __cs2000_set_rate(struct cs2000_priv *priv, int ch, + { + int ret; + +- ret = cs2000_clk_in_bound_rate(priv, parent_rate); +- if (ret < 0) +- return ret; ++ if (priv->type == DEVICE_CS2000) { ++ ret = cs2000_clk_in_bound_rate(priv, parent_rate); ++ if (ret < 0) ++ return ret; + +- ret = cs2000_ratio_set(priv, ch, parent_rate, rate); +- if (ret < 0) +- return ret; ++ ret = cs2000_ratio_set(priv, ch, parent_rate, rate); ++ if (ret < 0) ++ return ret; + +- ret = cs2000_ratio_select(priv, ch); +- if (ret < 0) +- return ret; ++ ret = cs2000_ratio_select(priv, ch); ++ if (ret < 0) ++ return ret; ++ } else { ++ ret = cs2300_clk_rmod_set(priv, 0); ++ if (ret < 0) ++ return ret; ++ ++ ret = cs2000_ratio_set(priv, 0, parent_rate, rate); ++ if (ret < 0) ++ return ret; ++ } + + priv->saved_rate = rate; + priv->saved_parent_rate = parent_rate; +@@ -383,8 +420,12 @@ static void cs2000_disable(struct clk_hw *hw) + + static u8 cs2000_get_parent(struct clk_hw *hw) + { +- /* always return REF_CLK */ +- return REF_CLK; ++ struct cs2000_priv *priv = hw_to_priv(hw); ++ ++ if (priv->type == DEVICE_CS2000) ++ return REF_CLK; ++ else ++ return CLK_IN; + } + + static const struct clk_ops cs2000_ops = { +@@ -399,17 +440,19 @@ static const struct clk_ops cs2000_ops = { + static int cs2000_clk_get(struct cs2000_priv *priv) + { + struct device *dev = priv_to_dev(priv); +- struct clk *clk_in, *ref_clk; ++ struct clk *clk_in, *ref_clk = NULL; + + clk_in = devm_clk_get(dev, "clk_in"); + /* not yet provided */ + if (IS_ERR(clk_in)) + return -EPROBE_DEFER; + +- ref_clk = devm_clk_get(dev, "ref_clk"); +- /* not yet provided */ +- if (IS_ERR(ref_clk)) +- return -EPROBE_DEFER; ++ if (priv->type == DEVICE_CS2000) { ++ ref_clk = devm_clk_get(dev, "ref_clk"); ++ /* not yet provided */ ++ if (IS_ERR(ref_clk)) ++ return -EPROBE_DEFER; ++ } + + priv->clk_in = clk_in; + priv->ref_clk = ref_clk; +@@ -435,19 +478,26 @@ static int cs2000_clk_register(struct cs2000_priv *priv) + * otherwise .set_rate which setup ratio + * is never called if user requests 1/1 rate + */ +- rate = clk_get_rate(priv->ref_clk); ++ if (priv->type == DEVICE_CS2000) ++ rate = clk_get_rate(priv->ref_clk); ++ else ++ rate = clk_get_rate(priv->clk_in); + ret = __cs2000_set_rate(priv, ch, rate, rate); + if (ret < 0) + return ret; + + parent_names[CLK_IN] = __clk_get_name(priv->clk_in); +- parent_names[REF_CLK] = __clk_get_name(priv->ref_clk); ++ if (priv->type == DEVICE_CS2000) ++ parent_names[REF_CLK] = __clk_get_name(priv->ref_clk); + + init.name = name; + init.ops = &cs2000_ops; + init.flags = CLK_SET_RATE_GATE; + init.parent_names = parent_names; +- init.num_parents = ARRAY_SIZE(parent_names); ++ if (priv->type == DEVICE_CS2000) ++ init.num_parents = ARRAY_SIZE(parent_names); ++ else ++ init.num_parents = 1; + + priv->hw.init = &init; + +@@ -474,7 +524,7 @@ static int cs2000_version_print(struct cs2000_priv *priv) + if (val < 0) + return val; + +- /* CS2000 should be 0x0 */ ++ /* CS2000/CS2300 should be 0x0 */ + if (val >> 3) + return -EIO; + +@@ -520,6 +570,7 @@ static int cs2000_probe(struct i2c_client *client, + + priv->client = client; + i2c_set_clientdata(client, priv); ++ priv->type = (enum cs2x00_type)id->driver_data; + + ret = cs2000_clk_get(priv); + if (ret < 0) +@@ -556,7 +607,7 @@ static struct i2c_driver cs2000_driver = { + .driver = { + .name = "cs2000-cp", + .pm = &cs2000_pm_ops, +- .of_match_table = cs2000_of_match, ++ .of_match_table = of_match_ptr(cs2000_of_match), + }, + .probe = cs2000_probe, + .remove = cs2000_remove, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0341-V3H-add-support-for-8-4-channel-VideoBox-board-from-.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0341-V3H-add-support-for-8-4-channel-VideoBox-board-from-.patch new file mode 100644 index 00000000..7bd6f735 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0341-V3H-add-support-for-8-4-channel-VideoBox-board-from-.patch @@ -0,0 +1,1626 @@ +From ef57204bde1eecb536d2d321fa4a549c0d06787c Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Tue, 6 Nov 2018 16:48:39 +0300 +Subject: [PATCH 161/211] V3H: add support for 8/4 channel VideoBox board from + Cogent + +Signed-off-by: Andrey Gusakov +--- + arch/arm64/boot/dts/renesas/Makefile | 1 + + .../boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts | 661 +++++++++++++++ + .../boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts | 924 +++++++++++++++++++++ + 3 files changed, 1586 insertions(+) + create mode 100644 arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts + +diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile +index cac4b75..222df3d 100644 +--- a/arch/arm64/boot/dts/renesas/Makefile ++++ b/arch/arm64/boot/dts/renesas/Makefile +@@ -43,5 +43,6 @@ dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-vbm-v2.dtb r8a77970-es1-v3msk-vbm- + dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3mzf.dtb + dtb-$(CONFIG_ARCH_R8A77980) += r8a77980-v3hsk-vbm.dtb + dtb-$(CONFIG_ARCH_R8A77980) += r8a77980-v3hsk-vbm-v2.dtb ++dtb-$(CONFIG_ARCH_R8A77980) += r8a77980-v3hsk-vb-8ch.dtb r8a77980-v3hsk-vb-4ch.dtb + + always := $(dtb-y) +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts +new file mode 100644 +index 0000000..1dd93fd +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts +@@ -0,0 +1,661 @@ ++/* ++ * Device Tree Source for the V3HSK Videobox Mini board on r8a7798 ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a77980-v3hsk.dts" ++#include ++ ++/ { ++ model = "Renesas V3HSK 4ch Videobox board based on r8a7798"; ++ ++ aliases { ++ serial1 = &scif3; ++ ethernet1 = &avb; ++ }; ++ ++ cs2300_ref_clk: cs2300_ref_clk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <25000000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led0 { ++ label = "board:status"; ++ gpios = <&gpio2 12 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "none"; ++ }; ++ }; ++ ++ mpcie_1v8: regulator2 { ++ compatible = "regulator-fixed"; ++ regulator-name = "mPCIe 1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ mpcie_3v3: regulator3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "mPCIe 3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ common_3v3: regulator4 { ++ compatible = "regulator-fixed"; ++ regulator-name = "main 3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++}; ++ ++&canfd { ++ pinctrl-0 = <&canfd0_pins &canfd1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ channel0 { ++ status = "okay"; ++ }; ++ ++ channel1 { ++ status = "okay"; ++ }; ++}; ++ ++&avb { ++ pinctrl-0 = <&avb_pins>; ++ pinctrl-names = "default"; ++ renesas,no-ether-link; ++ phy-handle = <&avb_phy0>; ++ status = "okay"; ++ phy-int-gpio = <&gpio1 17 GPIO_ACTIVE_LOW>; ++ ++ avb_phy0: eavb-phy@0 { ++ rxc-skew-ps = <1500>; ++ rxdv-skew-ps = <420>; /* default */ ++ rxd0-skew-ps = <420>; /* default */ ++ rxd1-skew-ps = <420>; /* default */ ++ rxd2-skew-ps = <420>; /* default */ ++ rxd3-skew-ps = <420>; /* default */ ++ txc-skew-ps = <900>; /* default */ ++ txen-skew-ps = <420>; /* default */ ++ txd0-skew-ps = <420>; /* default */ ++ txd1-skew-ps = <420>; /* default */ ++ txd2-skew-ps = <420>; /* default */ ++ txd3-skew-ps = <420>; /* default */ ++ reg = <3>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <17 IRQ_TYPE_LEVEL_LOW>; ++ max-speed = <1000>; ++ }; ++}; ++ ++&csi40 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3>; ++ csi-rate = <1450>; ++ }; ++ }; ++}; ++ ++&csi41 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_41_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3>; ++ csi-rate = <1450>; ++ }; ++ }; ++}; ++ ++&i2c1 { ++ pinctrl-0 = <&i2c1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ clock-frequency = <100000>; ++ ++ i2cswitch1: i2c-switch@74 { ++ compatible = "nxp,pca9548"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x74>; ++ reset-gpios = <&gpio2 28 GPIO_ACTIVE_LOW>; ++ ++ /* DS0_SDA and DS0_SCL */ ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ ++ /* Deser #0 nodes here */ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3>; ++ remote-endpoint = <&vin6ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3>; ++ remote-endpoint = <&vin7ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; ++ }; ++ }; ++ }; ++ ++ ti9x4@0 { ++ compatible = "ti,ti9x4"; ++ clocks = <&cs2300>; ++ clock-names = "ref_clk"; ++ reg = <0x3a>; ++ ti,links = <4>; ++ ti,lanes = <3>; ++ ti,forwarding-mode = "round-robin"; ++ ti,cable-mode = "coax"; ++ gpios = <&gpio_exp_ch0 13 GPIO_ACTIVE_LOW>; ++ POC0-gpios = <&gpio_exp_ch0 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_ch0 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_ch0 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_ch0 11 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ ti9x4_des0ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ ti9x4_des0ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ ti9x4_des0ep2: endpoint@2 { ++ ti9x3-addr = <0x0e>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ ti9x4_des0ep3: endpoint@3 { ++ ti9x3-addr = <0x0f>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ ti9x4_csi0ep0: endpoint { ++ csi-rate = <1450>; ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ }; ++ }; ++ ++ /* CTL0_SDA and CTL0_SCL */ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ ++ gpio_exp_ch0: gpio_ch0@6c { ++ compatible = "maxim,max7325"; ++ reg = <0x6c>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ ch0_virq { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "CH0_VIRQ"; ++ }; ++ ch0_des_cfg0 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "CH0_CNFG0"; ++ }; ++ ch0_des_cfg1 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "CH0_CNFG1"; ++ }; ++ }; ++ }; ++ ++ /* CTL1_SDA and CTL1_SCL */ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ ++ /* CS2300 node @0x4e */ ++ cs2300: clk_multiplier@4e { ++ #clock-cells = <0>; ++ compatible = "cirrus,cs2300-cp"; ++ reg = <0x4e>; ++ clocks = <&cs2300_ref_clk>; ++ clock-names = "clk_in"; ++ ++ assigned-clocks = <&cs2300>; ++ assigned-clock-rates = <22500000>; ++ }; ++ }; ++ ++ /* CMR_SDA and CMR_SCL */ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ ++ dac_vcam: dac_vcam@60 { ++ compatible = "microchip,mcp4725"; ++ reg = <0x60>; ++ vdd-supply = <&common_3v3>; ++ }; ++ }; ++ ++ /* Disp_SDA and Disp_SCL */ ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ ++ /* fan node - lm96063 */ ++ fan_ctrl: lm96063@4c { ++ compatible = "lm96163"; ++ reg = <0x4c>; ++ }; ++ }; ++ ++ /* ESDA and ESCL */ ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ ++ /* ext connector nodes here */ ++ }; ++ ++ }; ++}; ++ ++&gpio0 { ++ fpdl_shdn { ++ gpio-hog; ++ gpios = <1 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "FPDL_SHDN"; ++ }; ++ ++ cam_pwr_en { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "VIPWR_En"; ++ }; ++ ++ wake_pin_8 { ++ gpio-hog; ++ gpios = <0 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "WAKE INPUT PIN 8"; ++ }; ++}; ++ ++&gpio1 { ++ md_buf_en { ++ gpio-hog; ++ gpios = <19 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CPLD_If_En"; ++ }; ++}; ++ ++&gpio2 { ++ m2_rst { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "M.2 RST#"; ++ }; ++ ++ can0_load { ++ gpio-hog; ++ gpios = <16 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CAN0Loff"; ++ }; ++ ++ can0_stby { ++ gpio-hog; ++ gpios = <27 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CAN0STBY"; ++ }; ++ ++ can1_load { ++ gpio-hog; ++ gpios = <29 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CAN1Loff"; ++ }; ++ ++ can1_stby { ++ gpio-hog; ++ gpios = <22 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CAN1STBY"; ++ }; ++ ++ wake_pin_7 { ++ gpio-hog; ++ gpios = <19 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "WAKE INPUT PIN 7"; ++ }; ++ ++ vi1_gpioext_rst { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "VIP1_RST"; ++ }; ++}; ++ ++&gpio3 { ++ vi0_gpioext_rst { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "VIP0_RST"; ++ }; ++}; ++ ++&pcie_bus_clk { ++ clock-frequency = <100000000>; ++ status = "okay"; ++}; ++ ++&pciec { ++ pcie3v3-supply = <&mpcie_3v3>; ++ pcie1v8-supply = <&mpcie_1v8>; ++ status = "okay"; ++}; ++ ++&pfc { ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_a"; ++ function = "canfd0"; ++ }; ++ ++ canfd1_pins: canfd1 { ++ groups = "canfd1_data"; ++ function = "canfd1"; ++ }; ++ ++ avb_pins: avb { ++ groups = "avb_mdc", "avb_mdio", ++ "avb_rx_ctrl", "avb_rxc", ++ "avb_rd4", ++ "avb_tx_ctrl", "avb_txc", ++ "avb_txcrefclk", ++ "avb_td4"; ++ function = "avb"; ++ }; ++ ++ i2c1_pins: i2c1 { ++ groups = "i2c1"; ++ function = "i2c1"; ++ }; ++ ++ scif3_pins: scif3 { ++ groups = "scif3_data"; ++ function = "scif3"; ++ }; ++}; ++ ++&scif3 { ++ pinctrl-0 = <&scif3_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&tpu { ++ status = "disabled"; ++}; ++ ++&vin0 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin6 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin6ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi1ep2: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin6_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin7 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin7ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi1ep3: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin7_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts +new file mode 100644 +index 0000000..0db52f4 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts +@@ -0,0 +1,924 @@ ++/* ++ * Device Tree Source for the V3HSK Videobox Mini board on r8a7798 ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a77980-v3hsk.dts" ++#include ++ ++/ { ++ model = "Renesas V3HSK 4ch Videobox board based on r8a7798"; ++ ++ aliases { ++ serial1 = &scif3; ++ ethernet1 = &avb; ++ }; ++ ++ cs2300_ref_clk: cs2300_ref_clk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <25000000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led0 { ++ label = "board:status"; ++ gpios = <&gpio2 12 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "none"; ++ }; ++ }; ++ ++ mpcie_1v8: regulator2 { ++ compatible = "regulator-fixed"; ++ regulator-name = "mPCIe 1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ mpcie_3v3: regulator3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "mPCIe 3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ common_3v3: regulator4 { ++ compatible = "regulator-fixed"; ++ regulator-name = "main 3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++}; ++ ++&canfd { ++ pinctrl-0 = <&canfd0_pins &canfd1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ channel0 { ++ status = "okay"; ++ }; ++ ++ channel1 { ++ status = "okay"; ++ }; ++}; ++ ++&avb { ++ pinctrl-0 = <&avb_pins>; ++ pinctrl-names = "default"; ++ renesas,no-ether-link; ++ phy-handle = <&avb_phy0>; ++ status = "okay"; ++ phy-int-gpio = <&gpio1 17 GPIO_ACTIVE_LOW>; ++ ++ avb_phy0: eavb-phy@0 { ++ rxc-skew-ps = <1500>; ++ rxdv-skew-ps = <420>; /* default */ ++ rxd0-skew-ps = <420>; /* default */ ++ rxd1-skew-ps = <420>; /* default */ ++ rxd2-skew-ps = <420>; /* default */ ++ rxd3-skew-ps = <420>; /* default */ ++ txc-skew-ps = <900>; /* default */ ++ txen-skew-ps = <420>; /* default */ ++ txd0-skew-ps = <420>; /* default */ ++ txd1-skew-ps = <420>; /* default */ ++ txd2-skew-ps = <420>; /* default */ ++ txd3-skew-ps = <420>; /* default */ ++ reg = <3>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <17 IRQ_TYPE_LEVEL_LOW>; ++ max-speed = <1000>; ++ }; ++}; ++ ++&csi40 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <1450>; ++ }; ++ }; ++}; ++ ++&csi41 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_41_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3>; ++ csi-rate = <1450>; ++ }; ++ }; ++}; ++ ++&i2c1 { ++ pinctrl-0 = <&i2c1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ clock-frequency = <100000>; ++ ++ i2cswitch1: i2c-switch@74 { ++ compatible = "nxp,pca9548"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x74>; ++ reset-gpios = <&gpio2 28 GPIO_ACTIVE_LOW>; ++ ++ /* DS0_SDA and DS0_SCL */ ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ ++ /* Deser #0 nodes here */ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; ++ }; ++ }; ++ }; ++ ++ ti9x4@0 { ++ compatible = "ti,ti9x4"; ++ reg = <0x3a>; ++ clocks = <&cs2300>; ++ clock-names = "ref_clk"; ++ ti,links = <4>; ++ ti,lanes = <4>; ++ ti,forwarding-mode = "round-robin"; ++ ti,cable-mode = "coax"; ++ gpios = <&gpio_exp_ch0 13 GPIO_ACTIVE_LOW>; ++ POC0-gpios = <&gpio_exp_ch0 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_ch0 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_ch0 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_ch0 11 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ ti9x4_des0ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ ti9x4_des0ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ ti9x4_des0ep2: endpoint@2 { ++ ti9x3-addr = <0x0e>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ ti9x4_des0ep3: endpoint@3 { ++ ti9x3-addr = <0x0f>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ ti9x4_csi0ep0: endpoint { ++ csi-rate = <1450>; ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ }; ++ }; ++ ++ /* CTL0_SDA and CTL0_SCL */ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ ++ gpio_exp_ch0: gpio_ch0@6c { ++ compatible = "maxim,max7325"; ++ reg = <0x6c>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ ch0_virq { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "CH0_VIRQ"; ++ }; ++ ch0_des_cfg0 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "CH0_CNFG0"; ++ }; ++ ch0_des_cfg1 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "CH0_CNFG1"; ++ }; ++ }; ++ }; ++ ++ /* DS1_SDA and DS1_SCL */ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ ++ /* Deser #1 nodes here */ ++ ov106xx@4 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in4: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_ti9x4_des1ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@5 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in5: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3>; ++ remote-endpoint = <&vin5ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_ti9x4_des1ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@6 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in6: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3>; ++ remote-endpoint = <&vin6ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_ti9x4_des1ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@7 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in7: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3>; ++ remote-endpoint = <&vin7ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_ti9x4_des1ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep3>; ++ }; ++ }; ++ }; ++ ++ ti9x4@1 { ++ compatible = "ti,ti9x4"; ++ clocks = <&cs2300>; ++ clock-names = "ref_clk"; ++ reg = <0x3a>; ++ ti,links = <4>; ++ ti,lanes = <3>; ++ ti,forwarding-mode = "round-robin"; ++ ti,cable-mode = "coax"; ++ gpios = <&gpio_exp_ch1 13 GPIO_ACTIVE_LOW>; ++ POC0-gpios = <&gpio_exp_ch1 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_ch1 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_ch1 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_ch1 11 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ ti9x4_des1ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in4>; ++ }; ++ ti9x4_des1ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in5>; ++ }; ++ ti9x4_des1ep2: endpoint@2 { ++ ti9x3-addr = <0x0e>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in6>; ++ }; ++ ti9x4_des1ep3: endpoint@3 { ++ ti9x3-addr = <0x0f>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in7>; ++ }; ++ }; ++ port@1 { ++ ti9x4_csi1ep0: endpoint { ++ csi-rate = <1450>; ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ }; ++ }; ++ ++ /* CTL1_SDA and CTL1_SCL */ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ ++ /* CS2300 node @0x4e */ ++ cs2300: clk_multiplier@4e { ++ #clock-cells = <0>; ++ compatible = "cirrus,cs2300-cp"; ++ reg = <0x4e>; ++ clocks = <&cs2300_ref_clk>; ++ clock-names = "clk_in"; ++ ++ assigned-clocks = <&cs2300>; ++ assigned-clock-rates = <22500000>; ++ }; ++ ++ gpio_exp_ch1: gpio_ch1@6c { ++ compatible = "maxim,max7325"; ++ reg = <0x6c>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ ch1_virq { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "CH1_VIRQ"; ++ }; ++ ch1_des_cfg0 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "CH1_CNFG0"; ++ }; ++ ch1_des_cfg1 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "CH1_CNFG1"; ++ }; ++ }; ++ }; ++ ++ /* CMR_SDA and CMR_SCL */ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ ++ dac_vcam: dac_vcam@60 { ++ compatible = "microchip,mcp4725"; ++ reg = <0x60>; ++ vdd-supply = <&common_3v3>; ++ }; ++ }; ++ ++ /* Disp_SDA and Disp_SCL */ ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ ++ /* fan node - lm96063 */ ++ fan_ctrl: lm96063@4c { ++ compatible = "lm96163"; ++ reg = <0x4c>; ++ }; ++ }; ++ ++ /* ESDA and ESCL */ ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ ++ /* ext connector nodes here */ ++ }; ++ ++ }; ++}; ++ ++&gpio0 { ++ fpdl_shdn { ++ gpio-hog; ++ gpios = <1 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "FPDL_SHDN"; ++ }; ++ ++ cam_pwr_en { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "VIPWR_En"; ++ }; ++ ++ wake_pin_8 { ++ gpio-hog; ++ gpios = <0 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "WAKE INPUT PIN 8"; ++ }; ++}; ++ ++&gpio1 { ++ md_buf_en { ++ gpio-hog; ++ gpios = <19 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CPLD_If_En"; ++ }; ++}; ++ ++&gpio2 { ++ m2_rst { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "M.2 RST#"; ++ }; ++ ++ can0_load { ++ gpio-hog; ++ gpios = <16 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CAN0Loff"; ++ }; ++ ++ can0_stby { ++ gpio-hog; ++ gpios = <27 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CAN0STBY"; ++ }; ++ ++ can1_load { ++ gpio-hog; ++ gpios = <29 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CAN1Loff"; ++ }; ++ ++ can1_stby { ++ gpio-hog; ++ gpios = <22 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CAN1STBY"; ++ }; ++ ++ wake_pin_7 { ++ gpio-hog; ++ gpios = <19 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "WAKE INPUT PIN 7"; ++ }; ++ ++ vi1_gpioext_rst { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "VIP1_RST"; ++ }; ++}; ++ ++&gpio3 { ++ vi0_gpioext_rst { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "VIP0_RST"; ++ }; ++}; ++ ++&pcie_bus_clk { ++ clock-frequency = <100000000>; ++ status = "okay"; ++}; ++ ++&pciec { ++ pcie3v3-supply = <&mpcie_3v3>; ++ pcie1v8-supply = <&mpcie_1v8>; ++ status = "okay"; ++}; ++ ++&pfc { ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_a"; ++ function = "canfd0"; ++ }; ++ ++ canfd1_pins: canfd1 { ++ groups = "canfd1_data"; ++ function = "canfd1"; ++ }; ++ ++ avb_pins: avb { ++ groups = "avb_mdc", "avb_mdio", ++ "avb_rx_ctrl", "avb_rxc", ++ "avb_rd4", ++ "avb_tx_ctrl", "avb_txc", ++ "avb_txcrefclk", ++ "avb_td4"; ++ function = "avb"; ++ }; ++ ++ i2c1_pins: i2c1 { ++ groups = "i2c1"; ++ function = "i2c1"; ++ }; ++ ++ scif3_pins: scif3 { ++ groups = "scif3_data"; ++ function = "scif3"; ++ }; ++}; ++ ++&scif3 { ++ pinctrl-0 = <&scif3_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&tpu { ++ status = "disabled"; ++}; ++ ++&vin0 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin6_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin7_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&vin4 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin4ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3>; ++ remote-endpoint = <&ov106xx_in4>; ++ }; ++ }; ++ port@1 { ++ csi1ep0: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin4_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin5 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin5ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3>; ++ remote-endpoint = <&ov106xx_in5>; ++ }; ++ }; ++ port@1 { ++ csi1ep1: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin5_ti9x4_des1ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin6 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin6ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3>; ++ remote-endpoint = <&ov106xx_in6>; ++ }; ++ }; ++ port@1 { ++ csi1ep2: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin6_ti9x4_des1ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin7 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin7ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3>; ++ remote-endpoint = <&ov106xx_in7>; ++ }; ++ }; ++ port@1 { ++ csi1ep3: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin7_ti9x4_des1ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep3>; ++ }; ++ }; ++ }; ++}; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0342-arm64-dts-r8a77970-Videobox-Mini-V3-board-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0342-arm64-dts-r8a77970-Videobox-Mini-V3-board-support.patch new file mode 100644 index 00000000..e7c1c5f0 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0342-arm64-dts-r8a77970-Videobox-Mini-V3-board-support.patch @@ -0,0 +1,95 @@ +From 3e52f48ee3314fef332d057cb0c869aec7f9ed26 Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Tue, 6 Nov 2018 18:26:49 +0300 +Subject: [PATCH 162/211] arm64: dts: r8a77970: Videobox Mini V3 board support. + +--- + arch/arm64/boot/dts/renesas/Makefile | 1 + + .../boot/dts/renesas/r8a77970-es1-v3msk-vbm-v3.dts | 17 ++++++++++ + .../boot/dts/renesas/r8a77970-v3msk-vbm-v3.dts | 38 ++++++++++++++++++++++ + 3 files changed, 56 insertions(+) + create mode 100644 arch/arm64/boot/dts/renesas/r8a77970-es1-v3msk-vbm-v3.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm-v3.dts + +diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile +index 222df3d..4ccf641 100644 +--- a/arch/arm64/boot/dts/renesas/Makefile ++++ b/arch/arm64/boot/dts/renesas/Makefile +@@ -40,6 +40,7 @@ dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-view.dtb r8a77970-es1-v3msk-view.d + dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-kf.dtb r8a77970-es1-v3msk-kf.dtb + dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-vbm.dtb r8a77970-es1-v3msk-vbm.dtb + dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-vbm-v2.dtb r8a77970-es1-v3msk-vbm-v2.dtb ++dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-vbm-v3.dtb r8a77970-es1-v3msk-vbm-v3.dtb + dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3mzf.dtb + dtb-$(CONFIG_ARCH_R8A77980) += r8a77980-v3hsk-vbm.dtb + dtb-$(CONFIG_ARCH_R8A77980) += r8a77980-v3hsk-vbm-v2.dtb +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-es1-v3msk-vbm-v3.dts b/arch/arm64/boot/dts/renesas/r8a77970-es1-v3msk-vbm-v3.dts +new file mode 100644 +index 0000000..32ace13 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a77970-es1-v3msk-vbm-v3.dts +@@ -0,0 +1,17 @@ ++/* ++ * Device Tree Source for the V3MSK Videobox Mini V2 board on r8a7797 ES1.0 ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a77970-v3msk-vbm-v3.dts" ++#include "r8a77970-es1.dtsi" ++ ++/ { ++ model = "Renesas V3MSK Videobox Mini V3 board based on r8a7797 ES1.0"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm-v3.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm-v3.dts +new file mode 100644 +index 0000000..e4d8362 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm-v3.dts +@@ -0,0 +1,38 @@ ++/* ++ * Device Tree Source for the V3MSK Videobox Mini board V3 on r8a7797 ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a77970-v3msk-vbm-v2.dts" ++ ++ ++/ { ++ model = "Renesas V3MSK Videobox Mini board V3 based on r8a7797"; ++}; ++ ++&gpio0 { ++ can0_load { ++ gpio-hog; ++ gpios = <19 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can0_120R_load"; ++ }; ++}; ++ ++&gpio1 { ++ ex_v3m { ++ gpio-hog; ++ gpios = <19 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "ExV3M"; ++ }; ++}; ++ ++&gpio2 { ++ /delete-node/can0_load; ++}; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0343-arm64-dts-renesas-r8a77970-v3msk-Add-ethernet0-alias.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0343-arm64-dts-renesas-r8a77970-v3msk-Add-ethernet0-alias.patch new file mode 100644 index 00000000..2498e966 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0343-arm64-dts-renesas-r8a77970-v3msk-Add-ethernet0-alias.patch @@ -0,0 +1,31 @@ +From 45e31ba2c9c7f8d00f4ab8837ec54c4d7ebc809b Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Sat, 29 Jun 2019 16:49:34 +0300 +Subject: [PATCH 163/211] arm64: dts: renesas: r8a77970-v3msk: Add ethernet0 + alias + +This adds ethernet0 alias to the avb. This is needed +for U-Boot to pass the MAC address via the device tree. +The MAC address registers are cleared when the device +is disabled in U-Boot before starting the kernel. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +index af6c7b9..adc2b01 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +@@ -15,6 +15,7 @@ + + aliases { + serial0 = &scif0; ++ ethernet0 = &avb; + }; + + chosen { +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0344-arm64-dts-renesas-r8a77970-Add-ISP0-alias.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0344-arm64-dts-renesas-r8a77970-Add-ISP0-alias.patch new file mode 100644 index 00000000..240082c3 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0344-arm64-dts-renesas-r8a77970-Add-ISP0-alias.patch @@ -0,0 +1,36 @@ +From fd575ad0cde7408796a8b94f72601be240d477f4 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Tue, 6 Nov 2018 21:10:13 +0300 +Subject: [PATCH 164/211] arm64: dts: renesas: r8a77970: Add ISP0 alias + +This adds ISP0 alias. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970.dtsi | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +index 77ee934..35000a7 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +@@ -22,6 +22,7 @@ + i2c2 = &i2c2; + i2c3 = &i2c3; + i2c4 = &i2c4; ++ isp0 = &isp0; + }; + + /* External CAN clock - to be overridden by boards that provide it */ +@@ -1016,7 +1017,7 @@ + alloc-dev = <&imr_v4l2_alloc>; + }; + +- isp@fec00000 { ++ isp0: isp@fec00000 { + compatible = "renesas,isp-r8a77970"; + reg = <0 0xfec00000 0 0x20000>, + <0 0xfed00000 0 0x10000>; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0345-arm64-dts-renesas-r8a77980-Add-ISP-aliases.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0345-arm64-dts-renesas-r8a77980-Add-ISP-aliases.patch new file mode 100644 index 00000000..34dc5fb6 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0345-arm64-dts-renesas-r8a77980-Add-ISP-aliases.patch @@ -0,0 +1,46 @@ +From 069bb03da39d46d50251459920f3ab95e8ff5c02 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Tue, 6 Nov 2018 21:11:09 +0300 +Subject: [PATCH 165/211] arm64: dts: renesas: r8a77980: Add ISP aliases + +This adds ISP0 and ISP1 aliases. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index 8af443d..e0d2213 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -23,6 +23,8 @@ + i2c3 = &i2c3; + i2c4 = &i2c4; + i2c5 = &i2c5; ++ isp0 = &isp0; ++ isp1 = &isp1; + }; + + /* External CAN clock - to be overridden by boards that provide it */ +@@ -1443,7 +1445,7 @@ + power-domains = <&sysc R8A77980_PD_A3VIP2>; + }; + +- isp@fec00000 { ++ isp0: isp@fec00000 { + compatible = "renesas,isp-r8a77980"; + reg = <0 0xfec00000 0 0x20000>, + <0 0xfed00000 0 0x10000>; +@@ -1453,7 +1455,7 @@ + power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; + }; + +- isp@fee00000 { ++ isp1: isp@fee00000 { + compatible = "renesas,isp-r8a77980"; + reg = <0 0xfee00000 0 0x20000>, + <0 0xfed20000 0 0x10000>; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0346-media-soc_camera-Add-soc_camera-host-preregister.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0346-media-soc_camera-Add-soc_camera-host-preregister.patch new file mode 100644 index 00000000..63ea0db0 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0346-media-soc_camera-Add-soc_camera-host-preregister.patch @@ -0,0 +1,74 @@ +From ebe2c882cf0119f9e5a81bcad9bcf4daabe6d8fe Mon Sep 17 00:00:00 2001 +From: Nikita Yushchenko +Date: Wed, 1 Aug 2018 13:06:00 +0300 +Subject: [PATCH 166/211] media: soc_camera: Add soc_camera host preregister + +This adds soc_camera host preregister + +Signed-off-by: Nikita Yushchenko +--- + drivers/media/platform/soc_camera/soc_camera.c | 20 +++++++++++++++++--- + include/media/soc_camera.h | 2 ++ + 2 files changed, 19 insertions(+), 3 deletions(-) + +diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c +index 0fa1f52..cd2a135 100644 +--- a/drivers/media/platform/soc_camera/soc_camera.c ++++ b/drivers/media/platform/soc_camera/soc_camera.c +@@ -1910,9 +1910,11 @@ int soc_camera_host_register(struct soc_camera_host *ici) + } + } + +- ret = v4l2_device_register(ici->v4l2_dev.dev, &ici->v4l2_dev); +- if (ret < 0) +- goto edevreg; ++ if (!ici->v4l2dev_preregistered) { ++ ret = v4l2_device_register(ici->v4l2_dev.dev, &ici->v4l2_dev); ++ if (ret < 0) ++ goto edevreg; ++ } + + list_add_tail(&ici->list, &hosts); + mutex_unlock(&list_lock); +@@ -1941,6 +1943,18 @@ int soc_camera_host_register(struct soc_camera_host *ici) + } + EXPORT_SYMBOL(soc_camera_host_register); + ++int soc_camera_host_preregister_v4l2_dev(struct soc_camera_host *ici) ++{ ++ int ret; ++ ++ ret = v4l2_device_register(ici->v4l2_dev.dev, &ici->v4l2_dev); ++ if (ret == 0) ++ ici->v4l2dev_preregistered = true; ++ ++ return ret; ++} ++EXPORT_SYMBOL(soc_camera_host_preregister_v4l2_dev); ++ + /* Unregister all clients! */ + void soc_camera_host_unregister(struct soc_camera_host *ici) + { +diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h +index c2a7fc2..2e44f96 100644 +--- a/include/media/soc_camera.h ++++ b/include/media/soc_camera.h +@@ -84,6 +84,7 @@ struct soc_camera_host { + struct soc_camera_host_ops *ops; + struct v4l2_async_subdev **asd; /* Flat array, arranged in groups */ + unsigned int *asd_sizes; /* 0-terminated array of asd group sizes */ ++ bool v4l2dev_preregistered; + }; + + struct soc_camera_host_ops { +@@ -275,6 +276,7 @@ static inline struct v4l2_subdev *soc_camera_to_subdev( + } + + int soc_camera_host_register(struct soc_camera_host *ici); ++int soc_camera_host_preregister_v4l2_dev(struct soc_camera_host *ici); + void soc_camera_host_unregister(struct soc_camera_host *ici); + + const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc( +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0347-arm64-renesas-r8a77980-use-CSI-4-lanes.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0347-arm64-renesas-r8a77980-use-CSI-4-lanes.patch new file mode 100644 index 00000000..6a3e4cc7 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0347-arm64-renesas-r8a77980-use-CSI-4-lanes.patch @@ -0,0 +1,339 @@ +From 64aba50a93e9a1980b291cb71bd7a62d1faa9ca7 Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Wed, 7 Nov 2018 13:06:39 +0300 +Subject: [PATCH 167/211] arm64: renesas: r8a77980: use CSI 4 lanes + +H/w must use 4 lanes +add PWM for external FSIN on deserializers + +Signed-off-by: Vladimir Barinov +--- + .../boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts | 60 ++++--------------- + .../boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts | 69 +++++++--------------- + 2 files changed, 32 insertions(+), 97 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts +index 1dd93fd..406ff2f 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts +@@ -108,32 +108,13 @@ + &csi40 { + status = "okay"; + +- virtual,channel { +- csi2_vc0 { +- data,type = "ycbcr422"; +- receive,vc = <0>; +- }; +- csi2_vc1 { +- data,type = "ycbcr422"; +- receive,vc = <1>; +- }; +- csi2_vc2 { +- data,type = "ycbcr422"; +- receive,vc = <2>; +- }; +- csi2_vc3 { +- data,type = "ycbcr422"; +- receive,vc = <3>; +- }; +- }; +- + port { + #address-cells = <1>; + #size-cells = <0>; + + csi2_40_ep: endpoint { + clock-lanes = <0>; +- data-lanes = <1 2 3>; ++ data-lanes = <1 2 3 4>; + csi-rate = <1450>; + }; + }; +@@ -142,32 +123,13 @@ + &csi41 { + status = "okay"; + +- virtual,channel { +- csi2_vc0 { +- data,type = "ycbcr422"; +- receive,vc = <0>; +- }; +- csi2_vc1 { +- data,type = "ycbcr422"; +- receive,vc = <1>; +- }; +- csi2_vc2 { +- data,type = "ycbcr422"; +- receive,vc = <2>; +- }; +- csi2_vc3 { +- data,type = "ycbcr422"; +- receive,vc = <3>; +- }; +- }; +- + port { + #address-cells = <1>; + #size-cells = <0>; + + csi2_41_ep: endpoint { + clock-lanes = <0>; +- data-lanes = <1 2 3>; ++ data-lanes = <1 2 3 4>; + csi-rate = <1450>; + }; + }; +@@ -201,7 +163,7 @@ + port@0 { + ov106xx_in0: endpoint { + clock-lanes = <0>; +- data-lanes = <1 2 3>; ++ data-lanes = <1 2 3 4>; + remote-endpoint = <&vin0ep0>; + }; + }; +@@ -219,7 +181,7 @@ + port@0 { + ov106xx_in1: endpoint { + clock-lanes = <0>; +- data-lanes = <1 2 3>; ++ data-lanes = <1 2 3 4>; + remote-endpoint = <&vin1ep0>; + }; + }; +@@ -237,7 +199,7 @@ + port@0 { + ov106xx_in2: endpoint { + clock-lanes = <0>; +- data-lanes = <1 2 3>; ++ data-lanes = <1 2 3 4>; + remote-endpoint = <&vin6ep0>; + }; + }; +@@ -255,7 +217,7 @@ + port@0 { + ov106xx_in3: endpoint { + clock-lanes = <0>; +- data-lanes = <1 2 3>; ++ data-lanes = <1 2 3 4>; + remote-endpoint = <&vin7ep0>; + }; + }; +@@ -272,7 +234,7 @@ + clock-names = "ref_clk"; + reg = <0x3a>; + ti,links = <4>; +- ti,lanes = <3>; ++ ti,lanes = <4>; + ti,forwarding-mode = "round-robin"; + ti,cable-mode = "coax"; + gpios = <&gpio_exp_ch0 13 GPIO_ACTIVE_LOW>; +@@ -559,7 +521,7 @@ + vin0ep0: endpoint { + csi,select = "csi40"; + virtual,channel = <0>; +- data-lanes = <1 2 3>; ++ data-lanes = <1 2 3 4>; + remote-endpoint = <&ov106xx_in0>; + }; + }; +@@ -587,7 +549,7 @@ + vin1ep0: endpoint { + csi,select = "csi40"; + virtual,channel = <1>; +- data-lanes = <1 2 3>; ++ data-lanes = <1 2 3 4>; + remote-endpoint = <&ov106xx_in1>; + }; + }; +@@ -615,7 +577,7 @@ + vin6ep0: endpoint { + csi,select = "csi41"; + virtual,channel = <2>; +- data-lanes = <1 2 3>; ++ data-lanes = <1 2 3 4>; + remote-endpoint = <&ov106xx_in2>; + }; + }; +@@ -643,7 +605,7 @@ + vin7ep0: endpoint { + csi,select = "csi41"; + virtual,channel = <3>; +- data-lanes = <1 2 3>; ++ data-lanes = <1 2 3 4>; + remote-endpoint = <&ov106xx_in3>; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts +index 0db52f4..f8657ed 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts +@@ -108,25 +108,6 @@ + &csi40 { + status = "okay"; + +- virtual,channel { +- csi2_vc0 { +- data,type = "ycbcr422"; +- receive,vc = <0>; +- }; +- csi2_vc1 { +- data,type = "ycbcr422"; +- receive,vc = <1>; +- }; +- csi2_vc2 { +- data,type = "ycbcr422"; +- receive,vc = <2>; +- }; +- csi2_vc3 { +- data,type = "ycbcr422"; +- receive,vc = <3>; +- }; +- }; +- + port { + #address-cells = <1>; + #size-cells = <0>; +@@ -142,32 +123,13 @@ + &csi41 { + status = "okay"; + +- virtual,channel { +- csi2_vc0 { +- data,type = "ycbcr422"; +- receive,vc = <0>; +- }; +- csi2_vc1 { +- data,type = "ycbcr422"; +- receive,vc = <1>; +- }; +- csi2_vc2 { +- data,type = "ycbcr422"; +- receive,vc = <2>; +- }; +- csi2_vc3 { +- data,type = "ycbcr422"; +- receive,vc = <3>; +- }; +- }; +- + port { + #address-cells = <1>; + #size-cells = <0>; + + csi2_41_ep: endpoint { + clock-lanes = <0>; +- data-lanes = <1 2 3>; ++ data-lanes = <1 2 3 4>; + csi-rate = <1450>; + }; + }; +@@ -359,7 +321,7 @@ + port@0 { + ov106xx_in4: endpoint { + clock-lanes = <0>; +- data-lanes = <1 2 3>; ++ data-lanes = <1 2 3 4>; + remote-endpoint = <&vin4ep0>; + }; + }; +@@ -377,7 +339,7 @@ + port@0 { + ov106xx_in5: endpoint { + clock-lanes = <0>; +- data-lanes = <1 2 3>; ++ data-lanes = <1 2 3 4>; + remote-endpoint = <&vin5ep0>; + }; + }; +@@ -395,7 +357,7 @@ + port@0 { + ov106xx_in6: endpoint { + clock-lanes = <0>; +- data-lanes = <1 2 3>; ++ data-lanes = <1 2 3 4>; + remote-endpoint = <&vin6ep0>; + }; + }; +@@ -413,7 +375,7 @@ + port@0 { + ov106xx_in7: endpoint { + clock-lanes = <0>; +- data-lanes = <1 2 3>; ++ data-lanes = <1 2 3 4>; + remote-endpoint = <&vin7ep0>; + }; + }; +@@ -430,7 +392,7 @@ + clock-names = "ref_clk"; + reg = <0x3a>; + ti,links = <4>; +- ti,lanes = <3>; ++ ti,lanes = <4>; + ti,forwarding-mode = "round-robin"; + ti,cable-mode = "coax"; + gpios = <&gpio_exp_ch1 13 GPIO_ACTIVE_LOW>; +@@ -682,12 +644,23 @@ + function = "i2c1"; + }; + ++ pwm0_pins: pwm0 { ++ groups = "pwm0_a"; ++ function = "pwm0"; ++ }; ++ + scif3_pins: scif3 { + groups = "scif3_data"; + function = "scif3"; + }; + }; + ++&pwm0 { ++ pinctrl-0 = <&pwm0_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ + &scif3 { + pinctrl-0 = <&scif3_pins>; + pinctrl-names = "default"; +@@ -822,7 +795,7 @@ + vin4ep0: endpoint { + csi,select = "csi41"; + virtual,channel = <0>; +- data-lanes = <1 2 3>; ++ data-lanes = <1 2 3 4>; + remote-endpoint = <&ov106xx_in4>; + }; + }; +@@ -850,7 +823,7 @@ + vin5ep0: endpoint { + csi,select = "csi41"; + virtual,channel = <1>; +- data-lanes = <1 2 3>; ++ data-lanes = <1 2 3 4>; + remote-endpoint = <&ov106xx_in5>; + }; + }; +@@ -878,7 +851,7 @@ + vin6ep0: endpoint { + csi,select = "csi41"; + virtual,channel = <2>; +- data-lanes = <1 2 3>; ++ data-lanes = <1 2 3 4>; + remote-endpoint = <&ov106xx_in6>; + }; + }; +@@ -906,7 +879,7 @@ + vin7ep0: endpoint { + csi,select = "csi41"; + virtual,channel = <3>; +- data-lanes = <1 2 3>; ++ data-lanes = <1 2 3 4>; + remote-endpoint = <&ov106xx_in7>; + }; + }; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0348-Bunch-update-of-r8a77980-v3hsk-vb-4ch.dts.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0348-Bunch-update-of-r8a77980-v3hsk-vb-4ch.dts.patch new file mode 100644 index 00000000..68985e0c --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0348-Bunch-update-of-r8a77980-v3hsk-vb-4ch.dts.patch @@ -0,0 +1,139 @@ +From c374786365b9051f341f9fbe1b3f6094a39b0c09 Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Wed, 7 Nov 2018 14:15:35 +0300 +Subject: [PATCH 168/211] Bunch update of r8a77980-v3hsk-vb-4ch.dts... + +...to avoid cherry-pick of patched patches... +--- + .../boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts | 30 ++++++++++++---------- + 1 file changed, 16 insertions(+), 14 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts +index 406ff2f..76855c4 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts +@@ -115,7 +115,7 @@ + csi2_40_ep: endpoint { + clock-lanes = <0>; + data-lanes = <1 2 3 4>; +- csi-rate = <1450>; ++ csi-rate = <1500>; + }; + }; + }; +@@ -130,7 +130,7 @@ + csi2_41_ep: endpoint { + clock-lanes = <0>; + data-lanes = <1 2 3 4>; +- csi-rate = <1450>; ++ csi-rate = <1500>; + }; + }; + }; +@@ -200,7 +200,7 @@ + ov106xx_in2: endpoint { + clock-lanes = <0>; + data-lanes = <1 2 3 4>; +- remote-endpoint = <&vin6ep0>; ++ remote-endpoint = <&vin4ep0>; + }; + }; + port@1 { +@@ -218,7 +218,7 @@ + ov106xx_in3: endpoint { + clock-lanes = <0>; + data-lanes = <1 2 3 4>; +- remote-endpoint = <&vin7ep0>; ++ remote-endpoint = <&vin5ep0>; + }; + }; + port@1 { +@@ -237,6 +237,8 @@ + ti,lanes = <4>; + ti,forwarding-mode = "round-robin"; + ti,cable-mode = "coax"; ++ ti,vc-map = <0x1010>; ++ ti,csi1-links = <0 1>; + gpios = <&gpio_exp_ch0 13 GPIO_ACTIVE_LOW>; + POC0-gpios = <&gpio_exp_ch0 8 GPIO_ACTIVE_HIGH>; + POC1-gpios = <&gpio_exp_ch0 9 GPIO_ACTIVE_HIGH>; +@@ -267,7 +269,7 @@ + }; + port@1 { + ti9x4_csi0ep0: endpoint { +- csi-rate = <1450>; ++ csi-rate = <1500>; + remote-endpoint = <&csi2_40_ep>; + }; + }; +@@ -322,7 +324,7 @@ + clock-names = "clk_in"; + + assigned-clocks = <&cs2300>; +- assigned-clock-rates = <22500000>; ++ assigned-clock-rates = <23500000>; + }; + }; + +@@ -566,7 +568,7 @@ + }; + }; + +-&vin6 { ++&vin4 { + status = "okay"; + + ports { +@@ -574,9 +576,9 @@ + #size-cells = <0>; + + port@0 { +- vin6ep0: endpoint { ++ vin4ep0: endpoint { + csi,select = "csi41"; +- virtual,channel = <2>; ++ virtual,channel = <0>; + data-lanes = <1 2 3 4>; + remote-endpoint = <&ov106xx_in2>; + }; +@@ -587,14 +589,14 @@ + }; + }; + port@2 { +- vin6_ti9x4_des0ep2: endpoint@1 { ++ vin4_ti9x4_des0ep2: endpoint@1 { + remote-endpoint = <&ti9x4_des0ep2>; + }; + }; + }; + }; + +-&vin7 { ++&vin5 { + status = "okay"; + + ports { +@@ -602,9 +604,9 @@ + #size-cells = <0>; + + port@0 { +- vin7ep0: endpoint { ++ vin5ep0: endpoint { + csi,select = "csi41"; +- virtual,channel = <3>; ++ virtual,channel = <1>; + data-lanes = <1 2 3 4>; + remote-endpoint = <&ov106xx_in3>; + }; +@@ -615,7 +617,7 @@ + }; + }; + port@2 { +- vin7_ti9x4_des0ep3: endpoint@1 { ++ vin5_ti9x4_des0ep3: endpoint@1 { + remote-endpoint = <&ti9x4_des0ep3>; + }; + }; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0349-arm64-dts-renesas-r8a77980-VideoBox-Mini-fix-csi-spe.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0349-arm64-dts-renesas-r8a77980-VideoBox-Mini-fix-csi-spe.patch new file mode 100644 index 00000000..0e2e9f2f --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0349-arm64-dts-renesas-r8a77980-VideoBox-Mini-fix-csi-spe.patch @@ -0,0 +1,26 @@ +From 1412299ecb8c31937e6e2db81c46cc89260ff30a Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Wed, 7 Nov 2018 14:52:34 +0300 +Subject: [PATCH 169/211] arm64: dts: renesas: r8a77980 VideoBox Mini: fix csi + speed. + +--- + arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm.dts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm.dts +index 1b0649f..e362045 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm.dts +@@ -250,7 +250,7 @@ + }; + port@1 { + ti9x4_csi0ep0: endpoint { +- csi-rate = <700>; ++ csi-rate = <1450>; + remote-endpoint = <&csi41_ep>; + }; + }; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0350-arm64-dts-renesas-r8a77980-v3hsk-vb-4ch-and-8ch-fix-.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0350-arm64-dts-renesas-r8a77980-v3hsk-vb-4ch-and-8ch-fix-.patch new file mode 100644 index 00000000..48c3ef02 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0350-arm64-dts-renesas-r8a77980-v3hsk-vb-4ch-and-8ch-fix-.patch @@ -0,0 +1,193 @@ +From 34941d2c45e323bb07c613148fbaff31b955017b Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Wed, 7 Nov 2018 15:27:06 +0300 +Subject: [PATCH 170/211] arm64: dts: renesas: r8a77980 v3hsk vb 4ch and 8ch: + fix csi labels. + +--- + .../boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts | 14 ++++++------- + .../boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts | 24 +++++++++++----------- + 2 files changed, 19 insertions(+), 19 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts +index 76855c4..d281871 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts +@@ -112,7 +112,7 @@ + #address-cells = <1>; + #size-cells = <0>; + +- csi2_40_ep: endpoint { ++ csi40_ep: endpoint { + clock-lanes = <0>; + data-lanes = <1 2 3 4>; + csi-rate = <1500>; +@@ -127,7 +127,7 @@ + #address-cells = <1>; + #size-cells = <0>; + +- csi2_41_ep: endpoint { ++ csi41_ep: endpoint { + clock-lanes = <0>; + data-lanes = <1 2 3 4>; + csi-rate = <1500>; +@@ -270,7 +270,7 @@ + port@1 { + ti9x4_csi0ep0: endpoint { + csi-rate = <1500>; +- remote-endpoint = <&csi2_40_ep>; ++ remote-endpoint = <&csi40_ep>; + }; + }; + }; +@@ -529,7 +529,7 @@ + }; + port@1 { + csi0ep0: endpoint { +- remote-endpoint = <&csi2_40_ep>; ++ remote-endpoint = <&csi40_ep>; + }; + }; + port@2 { +@@ -557,7 +557,7 @@ + }; + port@1 { + csi0ep1: endpoint { +- remote-endpoint = <&csi2_40_ep>; ++ remote-endpoint = <&csi40_ep>; + }; + }; + port@2 { +@@ -585,7 +585,7 @@ + }; + port@1 { + csi1ep2: endpoint { +- remote-endpoint = <&csi2_41_ep>; ++ remote-endpoint = <&csi41_ep>; + }; + }; + port@2 { +@@ -613,7 +613,7 @@ + }; + port@1 { + csi1ep3: endpoint { +- remote-endpoint = <&csi2_41_ep>; ++ remote-endpoint = <&csi41_ep>; + }; + }; + port@2 { +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts +index f8657ed..e5a8a18 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts +@@ -112,7 +112,7 @@ + #address-cells = <1>; + #size-cells = <0>; + +- csi2_40_ep: endpoint { ++ csi40_ep: endpoint { + clock-lanes = <0>; + data-lanes = <1 2 3 4>; + csi-rate = <1450>; +@@ -127,7 +127,7 @@ + #address-cells = <1>; + #size-cells = <0>; + +- csi2_41_ep: endpoint { ++ csi41_ep: endpoint { + clock-lanes = <0>; + data-lanes = <1 2 3 4>; + csi-rate = <1450>; +@@ -268,7 +268,7 @@ + port@1 { + ti9x4_csi0ep0: endpoint { + csi-rate = <1450>; +- remote-endpoint = <&csi2_40_ep>; ++ remote-endpoint = <&csi40_ep>; + }; + }; + }; +@@ -426,7 +426,7 @@ + port@1 { + ti9x4_csi1ep0: endpoint { + csi-rate = <1450>; +- remote-endpoint = <&csi2_41_ep>; ++ remote-endpoint = <&csi41_ep>; + }; + }; + }; +@@ -689,7 +689,7 @@ + }; + port@1 { + csi0ep0: endpoint { +- remote-endpoint = <&csi2_40_ep>; ++ remote-endpoint = <&csi40_ep>; + }; + }; + port@2 { +@@ -717,7 +717,7 @@ + }; + port@1 { + csi0ep1: endpoint { +- remote-endpoint = <&csi2_40_ep>; ++ remote-endpoint = <&csi40_ep>; + }; + }; + port@2 { +@@ -745,7 +745,7 @@ + }; + port@1 { + csi0ep2: endpoint { +- remote-endpoint = <&csi2_40_ep>; ++ remote-endpoint = <&csi40_ep>; + }; + }; + port@2 { +@@ -773,7 +773,7 @@ + }; + port@1 { + csi0ep3: endpoint { +- remote-endpoint = <&csi2_40_ep>; ++ remote-endpoint = <&csi40_ep>; + }; + }; + port@2 { +@@ -801,7 +801,7 @@ + }; + port@1 { + csi1ep0: endpoint { +- remote-endpoint = <&csi2_41_ep>; ++ remote-endpoint = <&csi41_ep>; + }; + }; + port@2 { +@@ -829,7 +829,7 @@ + }; + port@1 { + csi1ep1: endpoint { +- remote-endpoint = <&csi2_41_ep>; ++ remote-endpoint = <&csi41_ep>; + }; + }; + port@2 { +@@ -857,7 +857,7 @@ + }; + port@1 { + csi1ep2: endpoint { +- remote-endpoint = <&csi2_41_ep>; ++ remote-endpoint = <&csi41_ep>; + }; + }; + port@2 { +@@ -885,7 +885,7 @@ + }; + port@1 { + csi1ep3: endpoint { +- remote-endpoint = <&csi2_41_ep>; ++ remote-endpoint = <&csi41_ep>; + }; + }; + port@2 { +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0351-arm64-dts-renesas-r8a77980-VB-4ch-and-8ch-Add-PCIE-p.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0351-arm64-dts-renesas-r8a77980-VB-4ch-and-8ch-Add-PCIE-p.patch new file mode 100644 index 00000000..c25aa562 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0351-arm64-dts-renesas-r8a77980-VB-4ch-and-8ch-Add-PCIE-p.patch @@ -0,0 +1,44 @@ +From 75f23c3e3581eca8a5b0098943c246f64f55d406 Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Wed, 7 Nov 2018 19:09:18 +0300 +Subject: [PATCH 171/211] arm64: dts: renesas: r8a77980 VB 4ch and 8ch: Add + PCIE phy node. + +--- + arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts | 4 ++++ + arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts | 4 ++++ + 2 files changed, 8 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts +index d281871..7b35608 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts +@@ -469,6 +469,10 @@ + status = "okay"; + }; + ++&pcie_phy { ++ status = "okay"; ++}; ++ + &pfc { + canfd0_pins: canfd0 { + groups = "canfd0_data_a"; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts +index e5a8a18..84d89d2 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts +@@ -618,6 +618,10 @@ + status = "okay"; + }; + ++&pcie_phy { ++ status = "okay"; ++}; ++ + &pfc { + canfd0_pins: canfd0 { + groups = "canfd0_data_a"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0352-gpu-drm-rcar_du-Fix-physical-address-of-the-CMA-back.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0352-gpu-drm-rcar_du-Fix-physical-address-of-the-CMA-back.patch new file mode 100644 index 00000000..ac6c1c92 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0352-gpu-drm-rcar_du-Fix-physical-address-of-the-CMA-back.patch @@ -0,0 +1,30 @@ +From b31a82407090315c8bfa2c0079e2da263e66140f Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Mon, 12 Nov 2018 18:17:43 +0300 +Subject: [PATCH 172/211] gpu: drm: rcar_du: Fix physical address of the CMA + backing memory + +This fixes physical address of the frame buffer backing memory +when the frame buffer is created using DMA buffer handle. + +Signed-off-by: Valentine Barshak +--- + drivers/gpu/drm/rcar-du/rcar_du_kms.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c +index a6940e6..d66ae53 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c +@@ -208,7 +208,7 @@ struct drm_gem_object *rcar_du_gem_prime_import_sg_table(struct drm_device *dev, + goto error; + } + +- cma_obj->paddr = 0; ++ cma_obj->paddr = sg_dma_address(sgt->sgl); + cma_obj->sgt = sgt; + + return gem_obj; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0353-media-soc_camera-rcar_csi2-add-dump-module-param.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0353-media-soc_camera-rcar_csi2-add-dump-module-param.patch new file mode 100644 index 00000000..12fc8d3c --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0353-media-soc_camera-rcar_csi2-add-dump-module-param.patch @@ -0,0 +1,65 @@ +From a9bb83a2edecc903a6025cf458fec465c8886524 Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Fri, 9 Nov 2018 19:28:34 +0300 +Subject: [PATCH 173/211] media: soc_camera: rcar_csi2: add dump module param. + +Signed-off-by: Vladimir Barinov +--- + drivers/media/platform/soc_camera/rcar_csi2.c | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +diff --git a/drivers/media/platform/soc_camera/rcar_csi2.c b/drivers/media/platform/soc_camera/rcar_csi2.c +index 737a686..deee4cc 100644 +--- a/drivers/media/platform/soc_camera/rcar_csi2.c ++++ b/drivers/media/platform/soc_camera/rcar_csi2.c +@@ -40,8 +40,6 @@ + + #include + +-//#define RCAR_CSI2_DUMP +- + #define DRV_NAME "rcar_csi2" + #define VC_MAX_CHANNEL 4 + +@@ -232,6 +230,10 @@ struct rcar_csi2 { + atomic_t use_count; + }; + ++static int dump = 0; ++module_param(dump, int, 0644); ++MODULE_PARM_DESC(dump, " Dump CSI packets (default: disabled)"); ++ + #define RCAR_CSI_80MBPS 0 + #define RCAR_CSI_90MBPS 1 + #define RCAR_CSI_100MBPS 2 +@@ -295,13 +297,15 @@ struct rcar_csi2 { + + #define RCAR_CSI2_INTSTATE_ALL 0x3FFFFCDD + +-#ifdef RCAR_CSI2_DUMP + static void rcar_sci2_debug_show(struct rcar_csi2 *priv) + { + int i; + u32 reg0, reg1; + +- printk("Debug registers:\n"); ++ if (!dump) ++ return; ++ ++ dev_info(&priv->pdev->dev, "Debug registers:\n"); + printk("FCNTM : 0x%08x\n", ioread32(priv->base + RCAR_CSI2_FCNTM)); + printk("FCNTM2: 0x%08x\n", ioread32(priv->base + RCAR_CSI2_FCNTM2)); + +@@ -355,9 +359,6 @@ static void rcar_sci2_debug_show(struct rcar_csi2 *priv) + for (i = 0; i < 2; i++) + printk("LCNTM%d: 0x%08x\n", i, ioread32(priv->base + RCAR_CSI2_LCNTM(i))); + } +-#else +-#define rcar_sci2_debug_show(args) +-#endif /* RCAR_CSI2_DUMP */ + + static int rcar_csi2_set_phy_freq(struct rcar_csi2 *priv) + { +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0354-media-rcar_csi2-Disable-data-type-matching.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0354-media-rcar_csi2-Disable-data-type-matching.patch new file mode 100644 index 00000000..4f3e0e07 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0354-media-rcar_csi2-Disable-data-type-matching.patch @@ -0,0 +1,58 @@ +From 67e7f6de9a3139e12e3112119a062230b4473d3d Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Mon, 12 Nov 2018 16:29:13 +0300 +Subject: [PATCH 174/211] media: rcar_csi2: Disable data type matching. + +Signed-off-by: Vladimir Barinov +--- + drivers/media/platform/soc_camera/rcar_csi2.c | 20 +------------------- + 1 file changed, 1 insertion(+), 19 deletions(-) + +diff --git a/drivers/media/platform/soc_camera/rcar_csi2.c b/drivers/media/platform/soc_camera/rcar_csi2.c +index deee4cc..ffb28c7 100644 +--- a/drivers/media/platform/soc_camera/rcar_csi2.c ++++ b/drivers/media/platform/soc_camera/rcar_csi2.c +@@ -87,7 +87,7 @@ + + #define RCAR_CSI2_VCDT_VCDTN_EN (1 << 15) + #define RCAR_CSI2_VCDT_SEL_VCN (1 << 8) +-#define RCAR_CSI2_VCDT_SEL_DTN_ON (1 << 6) ++#define RCAR_CSI2_VCDT_SEL_DTN_ON (0 << 6) + #define RCAR_CSI2_VCDT_SEL_DTN (1 << 0) + + #define RCAR_CSI2_LINKCNT_MONITOR_EN (1 << 31) +@@ -682,15 +682,6 @@ static int rcar_csi2_parse_dt(struct device_node *np, + return ret; + + if (i < 2) { +- if (!strcmp(str, "rgb888")) +- config->vcdt |= (0x24 << (i * 16)); +- else if (!strcmp(str, "ycbcr422")) +- config->vcdt |= (0x1e << (i * 16)); +- else if (!strcmp(str, "raw8")) +- config->vcdt |= (0x2a << (i * 16)); +- else +- config->vcdt |= 0; +- + config->vcdt |= (ch << (8 + (i * 16))); + config->vcdt |= (RCAR_CSI2_VCDT_VCDTN_EN << (i * 16)) | + (RCAR_CSI2_VCDT_SEL_DTN_ON << (i * 16)); +@@ -698,15 +689,6 @@ static int rcar_csi2_parse_dt(struct device_node *np, + if (i >= 2) { + int j = (i - 2); + +- if (!strcmp(str, "rgb888")) +- config->vcdt2 |= (0x24 << (j * 16)); +- else if (!strcmp(str, "ycbcr422")) +- config->vcdt2 |= (0x1e << (j * 16)); +- else if (!strcmp(str, "raw8")) +- config->vcdt2 |= (0x2a << (j * 16)); +- else +- config->vcdt2 |= 0; +- + config->vcdt2 |= (ch << (8 + (j * 16))); + config->vcdt2 |= (RCAR_CSI2_VCDT_VCDTN_EN << (j * 16)) | + (RCAR_CSI2_VCDT_SEL_DTN_ON << (j * 16)); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0355-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0355-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch new file mode 100644 index 00000000..538ca4a6 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0355-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch @@ -0,0 +1,547 @@ +From 67a755cc6ef9d7ffc36073922610ffab9f3c8dfe Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Tue, 13 Nov 2018 20:36:36 +0300 +Subject: [PATCH 175/211] gpu: drm: rcar-du: Extend VSP1-DRM interface + +This is based on the original "Extend VSP1-DRM interface" patch +by Konstantin Kozhevnikov +which adds alpha plane and color key properties to DRM planes. + +Signed-off-by: Valentine Barshak +--- + drivers/gpu/drm/drm_fourcc.c | 1 + + drivers/gpu/drm/rcar-du/rcar_du_drv.h | 5 + + drivers/gpu/drm/rcar-du/rcar_du_kms.c | 38 ++++++ + drivers/gpu/drm/rcar-du/rcar_du_plane.c | 2 + + drivers/gpu/drm/rcar-du/rcar_du_plane.h | 5 + + drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 228 +++++++++++++++++++++++++++----- + drivers/gpu/drm/rcar-du/rcar_du_vsp.h | 7 +- + 7 files changed, 249 insertions(+), 37 deletions(-) + +diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c +index 9c0152d..5f1a175 100644 +--- a/drivers/gpu/drm/drm_fourcc.c ++++ b/drivers/gpu/drm/drm_fourcc.c +@@ -106,6 +106,7 @@ const struct drm_format_info *__drm_format_info(u32 format) + { + static const struct drm_format_info formats[] = { + { .format = DRM_FORMAT_C8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, ++ { .format = DRM_FORMAT_R8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_RGB332, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_BGR233, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_XRGB4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h +index 504a188..dc20ebb 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h ++++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h +@@ -99,6 +99,11 @@ struct rcar_du_device { + struct drm_property *alpha; + struct drm_property *colorkey; + struct drm_property *colorkey_alpha; ++ struct drm_property *alphaplane; ++ struct drm_property *blend; ++ struct drm_property *ckey; ++ struct drm_property *ckey_set0; ++ struct drm_property *ckey_set1; + } props; + + unsigned int dpad0_source; +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c +index d66ae53..f74bc6a 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c +@@ -11,6 +11,7 @@ + * (at your option) any later version. + */ + ++//#define DEBUG + #include + #include + #include +@@ -96,6 +97,12 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = { + .planes = 2, + .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC, + .edf = PnDDCR4_EDF_NONE, ++ }, { ++ .fourcc = DRM_FORMAT_R8, ++ .bpp = 8, ++ .planes = 1, ++ .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_8BPP, ++ .edf = PnDDCR4_EDF_NONE, + }, + /* + * The following formats are not supported on Gen2 and thus have no +@@ -543,6 +550,37 @@ static int rcar_du_properties_init(struct rcar_du_device *rcdu) + return -ENOMEM; + } + ++ rcdu->props.alphaplane = ++ drm_property_create(rcdu->ddev, DRM_MODE_PROP_OBJECT, "alphaplane", 1); ++ if (rcdu->props.alphaplane == NULL) ++ return -ENOMEM; ++ ++ rcdu->props.alphaplane->values[0] = DRM_MODE_OBJECT_FB; ++ ++ rcdu->props.blend = ++ drm_property_create_range(rcdu->ddev, 0, "blend", ++ 0, 0xffffffff); ++ if (rcdu->props.blend == NULL) ++ return -ENOMEM; ++ ++ rcdu->props.ckey = ++ drm_property_create_range(rcdu->ddev, 0, "ckey", ++ 0, 0xffffffff); ++ if (rcdu->props.ckey == NULL) ++ return -ENOMEM; ++ ++ rcdu->props.ckey_set0 = ++ drm_property_create_range(rcdu->ddev, 0, "ckey_set0", ++ 0, 0xffffffff); ++ if (rcdu->props.ckey_set0 == NULL) ++ return -ENOMEM; ++ ++ rcdu->props.ckey_set1 = ++ drm_property_create_range(rcdu->ddev, 0, "ckey_set1", ++ 0, 0xffffffff); ++ if (rcdu->props.ckey_set1 == NULL) ++ return -ENOMEM; ++ + return 0; + } + +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c +index 1b70db3..e934b4c 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c +@@ -11,6 +11,7 @@ + * (at your option) any later version. + */ + ++//#define DEBUG + #include + #include + #include +@@ -790,6 +791,7 @@ static const uint32_t formats[] = { + DRM_FORMAT_NV12, + DRM_FORMAT_NV21, + DRM_FORMAT_NV16, ++ DRM_FORMAT_R8, + }; + + int rcar_du_planes_init(struct rcar_du_group *rgrp) +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h +index e0ddecf..3e9dfdb 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h ++++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h +@@ -70,6 +70,11 @@ struct rcar_du_plane_state { + unsigned int alpha; + unsigned int colorkey; + unsigned int colorkey_alpha; ++ struct drm_framebuffer *alphaplane; ++ unsigned int blend; ++ unsigned int ckey; ++ unsigned int ckey_set0; ++ unsigned int ckey_set1; + }; + + static inline struct rcar_du_plane_state * +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +index c44d336..2b076cf 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +@@ -11,6 +11,7 @@ + * (at your option) any later version. + */ + ++//#define DEBUG + #include + #include + #include +@@ -96,6 +97,16 @@ void rcar_du_vsp_enable(struct rcar_du_crtc *crtc) + + void rcar_du_vsp_disable(struct rcar_du_crtc *crtc) + { ++ struct rcar_du_vsp *vsp = crtc->vsp; ++ struct rcar_du_vsp_plane *primary = &vsp->planes[0]; ++ struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(primary->plane.state); ++ ++ /* ...drop alpha-plane associated with primary plane (why only primary? - tbd) */ ++ if (rstate->alphaplane) { ++ drm_framebuffer_unreference(rstate->alphaplane); ++ rstate->alphaplane = NULL; ++ } ++ + vsp1_du_setup_lif(crtc->vsp->vsp, crtc->vsp_pipe, NULL); + } + +@@ -142,6 +153,7 @@ static const u32 formats_kms[] = { + DRM_FORMAT_YVU422, + DRM_FORMAT_YUV444, + DRM_FORMAT_YVU444, ++ DRM_FORMAT_R8, + }; + + static const u32 formats_v4l2[] = { +@@ -170,6 +182,7 @@ static const u32 formats_v4l2[] = { + V4L2_PIX_FMT_YVU422M, + V4L2_PIX_FMT_YUV444M, + V4L2_PIX_FMT_YVU444M, ++ V4L2_PIX_FMT_GREY, + }; + + static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane) +@@ -217,6 +230,28 @@ static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane) + } + } + ++ /* ...add alpha-plane as needed */ ++ if (state->alphaplane) { ++ i = state->format->planes; ++ cfg.alpha_mem = sg_dma_address(state->sg_tables[i].sgl); ++ cfg.alpha_pitch = state->alphaplane->pitches[0]; ++ pr_debug("alpha-%d: set alpha-mem address: %llx, pitch=%d\n", ++ i, (unsigned long long)cfg.alpha_mem, cfg.alpha_pitch); ++ } ++ ++ /* ...add blending formula as needed */ ++ if (state->blend) { ++ cfg.blend = state->blend; ++ pr_debug("set blending formula: %X\n", cfg.blend); ++ } ++ ++ /* ...add color key property as needed */ ++ if (state->ckey) { ++ cfg.ckey = state->ckey; ++ cfg.ckey_set0 = state->ckey_set0; ++ cfg.ckey_set1 = state->ckey_set1; ++ } ++ + vsp1_du_atomic_update(plane->vsp->vsp, crtc->vsp_pipe, + plane->index, &cfg); + } +@@ -285,6 +320,23 @@ static int rcar_du_vsp_plane_prepare_fb(struct drm_plane *plane, + if (ret) + goto fail; + ++ /* ...check if we have alpha-plane attached */ ++ if (rstate->alphaplane) { ++ struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(rstate->alphaplane, 0); ++ struct sg_table *sgt = &rstate->sg_tables[i++]; ++ ++ ret = dma_get_sgtable(rcdu->dev, sgt, gem->vaddr, gem->paddr, gem->base.size); ++ if (ret) ++ goto fail; ++ ++ ret = vsp1_du_map_sg(vsp->vsp, sgt); ++ if (!ret) { ++ sg_free_table(sgt); ++ ret = -ENOMEM; ++ goto fail; ++ } ++ } ++ + return 0; + + fail: +@@ -314,6 +366,14 @@ static void rcar_du_vsp_plane_cleanup_fb(struct drm_plane *plane, + vsp1_du_unmap_sg(vsp->vsp, sgt); + sg_free_table(sgt); + } ++ ++ if (rstate->alphaplane) { ++ struct sg_table *sgt = &rstate->sg_tables[i]; ++ ++ vsp1_du_unmap_sg(vsp->vsp, sgt); ++ sg_free_table(sgt); ++ pr_debug("unmap alpha-plane\n"); ++ } + } + + static int rcar_du_vsp_plane_atomic_check(struct drm_plane *plane, +@@ -356,6 +416,13 @@ rcar_du_vsp_plane_atomic_duplicate_state(struct drm_plane *plane) + if (copy == NULL) + return NULL; + ++ if (copy->alphaplane) { ++ drm_framebuffer_reference(copy->alphaplane); ++ pr_debug("duplicate alpha-plane '%p' (refcount=%d)\n", ++ copy->alphaplane, ++ drm_framebuffer_read_refcount(copy->alphaplane)); ++ } ++ + __drm_atomic_helper_plane_duplicate_state(plane, ©->state); + copy->alpha = to_rcar_vsp_plane_state(plane->state)->alpha; + copy->colorkey = to_rcar_vsp_plane_state(plane->state)->colorkey; +@@ -367,8 +434,17 @@ rcar_du_vsp_plane_atomic_duplicate_state(struct drm_plane *plane) + static void rcar_du_vsp_plane_atomic_destroy_state(struct drm_plane *plane, + struct drm_plane_state *state) + { ++ struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(state); ++ ++ if (rstate->alphaplane) { ++ pr_debug("unref alpha-plane '%p' (refcount=%d)\n", ++ rstate->alphaplane, ++ drm_framebuffer_read_refcount(rstate->alphaplane)); ++ drm_framebuffer_unreference(rstate->alphaplane); ++ } ++ + __drm_atomic_helper_plane_destroy_state(state); +- kfree(to_rcar_vsp_plane_state(state)); ++ kfree(rstate); + } + + static void rcar_du_vsp_plane_reset(struct drm_plane *plane) +@@ -376,6 +452,8 @@ static void rcar_du_vsp_plane_reset(struct drm_plane *plane) + struct rcar_du_vsp_plane_state *state; + + if (plane->state) { ++ pr_debug("reset plane '%p'\n", ++ to_rcar_vsp_plane_state(plane->state)->alphaplane); + rcar_du_vsp_plane_atomic_destroy_state(plane, plane->state); + plane->state = NULL; + } +@@ -403,9 +481,10 @@ int rcar_du_vsp_write_back(struct drm_device *dev, void *data, + struct rcar_du_crtc *rcrtc; + struct rcar_du_device *rcdu; + const struct drm_display_mode *mode; +- u32 pixelformat, bpp; +- unsigned int pitch; ++ struct drm_framebuffer *fb; + dma_addr_t mem[3]; ++ struct sg_table sg_tables[3]; ++ int i = 0; + + obj = drm_mode_object_find(dev, sh->crtc_id, DRM_MODE_OBJECT_CRTC); + if (!obj) +@@ -416,65 +495,89 @@ int rcar_du_vsp_write_back(struct drm_device *dev, void *data, + rcdu = rcrtc->group->dev; + mode = &rcrtc->crtc.state->adjusted_mode; + +- switch (sh->fmt) { +- case DRM_FORMAT_RGB565: +- bpp = 16; +- pixelformat = V4L2_PIX_FMT_RGB565; +- break; +- case DRM_FORMAT_ARGB1555: +- bpp = 16; +- pixelformat = V4L2_PIX_FMT_ARGB555; +- break; +- case DRM_FORMAT_ARGB8888: +- bpp = 32; +- pixelformat = V4L2_PIX_FMT_ABGR32; +- break; +- default: +- dev_err(rcdu->dev, "specified format is not supported.\n"); ++ fb = drm_framebuffer_lookup(dev, sh->buff); ++ if (!fb) { ++ dev_err(dev->dev, ++ "failed to lookup destination framebuffer '%lu'\n", ++ sh->buff); + return -EINVAL; + } + +- pitch = mode->hdisplay * bpp / 8; ++ /* ...check framebuffer is okay */ ++ if ((fb->width != (mode->hdisplay)) || ++ (fb->height != (mode->vdisplay))) { ++ dev_err(dev->dev, "wrong fb mode: %d*%d vs %d*%d\n", ++ fb->width, fb->height, mode->hdisplay, mode->vdisplay); ++ ret = -EINVAL; ++ goto done; ++ } + +- mem[0] = sh->buff; +- mem[1] = 0; +- mem[2] = 0; ++ /* ...need to verify compatibility of output format, I guess - tbd */ + +- if (sh->width != mode->hdisplay || +- sh->height != mode->vdisplay) +- return -EINVAL; ++ /* ...fill memory planes addresses */ ++ for (i = 0; i < 3; i++) { ++ struct drm_gem_cma_object *gem; ++ struct sg_table *sgt = &sg_tables[i]; + +- if ((pitch * mode->vdisplay) > sh->buff_len) +- return -EINVAL; ++ gem = drm_fb_cma_get_gem_obj(fb, i); ++ if (!gem) ++ break; ++ ++ ret = dma_get_sgtable(rcdu->dev, sgt, gem->vaddr, gem->paddr, ++ gem->base.size); ++ if (ret) ++ goto done; ++ ++ ret = vsp1_du_map_sg(rcrtc->vsp->vsp, sgt); ++ if (!ret) { ++ sg_free_table(sgt); ++ ret = -ENOMEM; ++ goto done; ++ } ++ mem[i] = sg_dma_address(sg_tables[i].sgl) + fb->offsets[i]; ++ } + +- ret = vsp1_du_setup_wb(rcrtc->vsp->vsp, pixelformat, pitch, mem, +- rcrtc->vsp_pipe); ++ dev_info(dev->dev, "setup write-back (pixfmt=%X, %u*%u, planes: %d)\n", ++ fb->format->format, fb->width, fb->height, i); ++ ++ ret = vsp1_du_setup_wb(rcrtc->vsp->vsp, fb->format->format, ++ fb->pitches[0], mem, rcrtc->vsp_pipe); + if (ret != 0) +- return ret; ++ goto done; + + ret = vsp1_du_wait_wb(rcrtc->vsp->vsp, WB_STAT_CATP_SET, + rcrtc->vsp_pipe); + if (ret != 0) +- return ret; ++ goto done; + + ret = rcar_du_async_commit(dev, crtc); + if (ret != 0) +- return ret; ++ goto done; + + ret = vsp1_du_wait_wb(rcrtc->vsp->vsp, WB_STAT_CATP_START, + rcrtc->vsp_pipe); + if (ret != 0) +- return ret; ++ goto done; + + ret = rcar_du_async_commit(dev, crtc); + if (ret != 0) +- return ret; ++ goto done; + + ret = vsp1_du_wait_wb(rcrtc->vsp->vsp, WB_STAT_CATP_DONE, + rcrtc->vsp_pipe); + if (ret != 0) +- return ret; ++ goto done; ++ ++done: ++ /* ...unmap all tables */ ++ while (i--) { ++ struct sg_table *sgt = &sg_tables[i]; ++ ++ vsp1_du_unmap_sg(rcrtc->vsp->vsp, sgt); ++ sg_free_table(sgt); ++ } + ++ drm_framebuffer_unreference(fb); + return ret; + } + +@@ -518,7 +621,38 @@ static int rcar_du_vsp_plane_atomic_set_property(struct drm_plane *plane, + rstate->colorkey = val; + else if (property == rcdu->props.colorkey_alpha) + rstate->colorkey_alpha = val; +- else ++ else if (property == rcdu->props.blend) ++ rstate->blend = val; ++ else if (property == rcdu->props.ckey) ++ rstate->ckey = val; ++ else if (property == rcdu->props.ckey_set0) ++ rstate->ckey_set0 = val; ++ else if (property == rcdu->props.ckey_set1) ++ rstate->ckey_set1 = val; ++ else if (property == rcdu->props.alphaplane) { ++ if (rstate->alphaplane) { ++ pr_debug("unref alpha-plane '%p' (refcount=%d)\n", ++ rstate->alphaplane, ++ drm_framebuffer_read_refcount(rstate->alphaplane)); ++ drm_framebuffer_unreference(rstate->alphaplane); ++ } ++ rstate->alphaplane = drm_framebuffer_lookup(plane->dev, val); ++ if (rstate->alphaplane) { ++ pr_debug("use alpha-plane '%p' (refcount=%d)\n", ++ rstate->alphaplane, ++ drm_framebuffer_read_refcount(rstate->alphaplane)); ++ /* ...the way how we handle this leads to a "loss" ++ * of plane reference (it is acquired within ++ * "drm_property_change_valid_get" but not returned ++ * in symmetric "drm_property_change_valid_put") ++ * Whether it is a bug or was done intentionally, ++ * I don't know. For a moment just drop that ++ * extra reference right here. ++ */ ++ if (0) ++ drm_framebuffer_unreference(rstate->alphaplane); ++ } ++ } else + return -EINVAL; + + return 0; +@@ -538,6 +672,16 @@ static int rcar_du_vsp_plane_atomic_get_property(struct drm_plane *plane, + *val = rstate->colorkey; + else if (property == rcdu->props.colorkey_alpha) + *val = rstate->colorkey_alpha; ++ else if (property == rcdu->props.alphaplane) ++ *val = (rstate->alphaplane ? rstate->alphaplane->base.id : 0); ++ else if (property == rcdu->props.blend) ++ *val = rstate->blend; ++ else if (property == rcdu->props.ckey) ++ *val = rstate->ckey; ++ else if (property == rcdu->props.ckey_set0) ++ *val = rstate->ckey_set0; ++ else if (property == rcdu->props.ckey_set1) ++ *val = rstate->ckey_set1; + else + return -EINVAL; + +@@ -633,8 +777,10 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp, struct device_node *np, + drm_plane_helper_add(&plane->plane, + &rcar_du_vsp_plane_helper_funcs); + ++#if 0 // ...use same set of properties for all planes + if (type == DRM_PLANE_TYPE_PRIMARY) + continue; ++#endif + + drm_object_attach_property(&plane->plane.base, + rcdu->props.alpha, 255); +@@ -647,6 +793,16 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp, struct device_node *np, + 0); + drm_plane_create_zpos_property(&plane->plane, 1, 1, + vsp->num_planes - 1); ++ drm_object_attach_property(&plane->plane.base, ++ rcdu->props.alphaplane, 0); ++ drm_object_attach_property(&plane->plane.base, ++ rcdu->props.blend, 0); ++ drm_object_attach_property(&plane->plane.base, ++ rcdu->props.ckey, 0); ++ drm_object_attach_property(&plane->plane.base, ++ rcdu->props.ckey_set0, 0); ++ drm_object_attach_property(&plane->plane.base, ++ rcdu->props.ckey_set1, 0); + } + + return 0; +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.h b/drivers/gpu/drm/rcar-du/rcar_du_vsp.h +index 93dbb9e..083d065 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.h ++++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.h +@@ -55,11 +55,16 @@ struct rcar_du_vsp_plane_state { + struct drm_plane_state state; + + const struct rcar_du_format_info *format; +- struct sg_table sg_tables[3]; ++ struct sg_table sg_tables[4]; + + unsigned int alpha; + u32 colorkey; + u32 colorkey_alpha; ++ struct drm_framebuffer *alphaplane; ++ unsigned int blend; ++ unsigned int ckey; ++ unsigned int ckey_set0; ++ unsigned int ckey_set1; + }; + + static inline struct rcar_du_vsp_plane_state * +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0356-media-platform-vsp1-Extend-DRM-VSP1-interface.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0356-media-platform-vsp1-Extend-DRM-VSP1-interface.patch new file mode 100644 index 00000000..c6abd77a --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0356-media-platform-vsp1-Extend-DRM-VSP1-interface.patch @@ -0,0 +1,374 @@ +From 918dd4d7f4cc9af593617a0bef51bfc531b74b53 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Tue, 13 Nov 2018 18:11:49 +0300 +Subject: [PATCH 176/211] media: platform: vsp1: Extend DRM-VSP1 interface + +- Extend DRM-VSP1 interface +- Add alpha-plane support for VSP1 + +This is based on the original "extend DRM-VSP1 interface" patch by +Konstantin Kozhevnikov . + +The only changes are the following: + * in vsp1_du_setup_lif() conversion back to ARGB is forced + on the pipe's output (pipe->output) instead of the first + one (vsp1->wpf[0]); + * "ckey", "ckey_set0", and "ckey_set1" properties are used only + when the conflicting "colorkey" property is disabled. + +Signed-off-by: Valentine Barshak +--- + drivers/media/platform/vsp1/vsp1_brx.c | 17 ++++++++++++++++- + drivers/media/platform/vsp1/vsp1_dl.c | 5 +++++ + drivers/media/platform/vsp1/vsp1_drm.c | 32 ++++++++++++++++++++++++++++++-- + drivers/media/platform/vsp1/vsp1_lif.c | 2 +- + drivers/media/platform/vsp1/vsp1_pipe.c | 4 ++++ + drivers/media/platform/vsp1/vsp1_rpf.c | 26 +++++++++++++++++++++++--- + drivers/media/platform/vsp1/vsp1_rwpf.c | 1 + + drivers/media/platform/vsp1/vsp1_rwpf.h | 6 ++++++ + drivers/media/platform/vsp1/vsp1_wpf.c | 4 ++++ + include/media/vsp1.h | 6 ++++++ + 10 files changed, 96 insertions(+), 7 deletions(-) + +diff --git a/drivers/media/platform/vsp1/vsp1_brx.c b/drivers/media/platform/vsp1/vsp1_brx.c +index 942ff12..7e82821 100644 +--- a/drivers/media/platform/vsp1/vsp1_brx.c ++++ b/drivers/media/platform/vsp1/vsp1_brx.c +@@ -392,6 +392,20 @@ static void brx_configure_stream(struct vsp1_entity *entity, + ctrl |= VI6_BRU_CTRL_SRCSEL_BRUIN(i); + + vsp1_brx_write(brx, dlb, VI6_BRU_CTRL(i), ctrl); ++ dev_dbg(entity->vsp1->dev, "brx#%d: ctrl=%X\n", i, ctrl); ++ ++ /* ...set blending formula as defined by the input RPF */ ++ if (brx->inputs[i].rpf) { ++ if (brx->inputs[i].rpf->blend) { ++ vsp1_brx_write(brx, dlb, VI6_BRU_BLD(i), ++ brx->inputs[i].rpf->blend); ++ dev_dbg(entity->vsp1->dev, ++ "brx#%d(#%d): setup blending formula: %X\n", ++ i, brx->inputs[i].rpf->entity.index, ++ brx->inputs[i].rpf->blend); ++ continue; ++ } ++ } + + /* + * Harcode the blending formula to +@@ -458,7 +472,8 @@ struct vsp1_brx *vsp1_brx_create(struct vsp1_device *vsp1, + v4l2_ctrl_new_std(&brx->ctrls, &brx_ctrl_ops, V4L2_CID_BG_COLOR, + 0, 0xffffff, 1, 0); + +- brx->bgcolor = 0; ++ /* ...for YUV, set black background */ ++ brx->bgcolor = 0x00800080; + + brx->entity.subdev.ctrl_handler = &brx->ctrls; + +diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c +index 48542854..f501307 100644 +--- a/drivers/media/platform/vsp1/vsp1_dl.c ++++ b/drivers/media/platform/vsp1/vsp1_dl.c +@@ -373,6 +373,7 @@ void vsp1_dl_set_addr_auto_fld(struct vsp1_dl_body *dlb, + u32 y_top_index, y_bot_index; + u32 u_top_index, u_bot_index; + u32 v_top_index, v_bot_index; ++ u32 alpha_index; + dma_addr_t y_top_addr, y_bot_addr; + dma_addr_t u_top_addr, u_bot_addr; + dma_addr_t v_top_addr, v_bot_addr; +@@ -388,6 +389,7 @@ void vsp1_dl_set_addr_auto_fld(struct vsp1_dl_body *dlb, + u_bot_index = rpf->entity.index * 8 + 3; + v_top_index = rpf->entity.index * 8 + 4; + v_bot_index = rpf->entity.index * 8 + 5; ++ alpha_index = rpf->entity.index * 8 + 6; + + switch (rpf->fmtinfo->fourcc) { + case V4L2_PIX_FMT_YUV420M: +@@ -436,6 +438,9 @@ void vsp1_dl_set_addr_auto_fld(struct vsp1_dl_body *dlb, + dlb->src_dst_addr[u_bot_index].addr = u_bot_addr; + dlb->src_dst_addr[v_top_index].addr = v_top_addr; + dlb->src_dst_addr[v_bot_index].addr = v_bot_addr; ++ ++ /* ...set alpha-plane address as needed */ ++ dlb->src_dst_addr[alpha_index].addr = rpf->mem.alpha; + } + + static struct vsp1_dl_list *vsp1_dl_list_alloc(struct vsp1_dl_manager *dlm) +diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c +index 68364d4..27aeabd 100644 +--- a/drivers/media/platform/vsp1/vsp1_drm.c ++++ b/drivers/media/platform/vsp1/vsp1_drm.c +@@ -7,6 +7,7 @@ + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) + */ + ++//#define DEBUG + #include + #include + #include +@@ -207,7 +208,12 @@ static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1, + __func__, format.format.width, format.format.height, + format.format.code, rpf->entity.index); + ++#if 0 + format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; ++#else ++ /* ...always blend in YUV colorspace; apply conversion as needed */ ++ format.format.code = MEDIA_BUS_FMT_AYUV8_1X32; ++#endif + + ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_fmt, NULL, + &format); +@@ -512,7 +518,14 @@ static int vsp1_du_pipeline_setup_output(struct vsp1_device *vsp1, + format.pad = RWPF_PAD_SINK; + format.format.width = drm_pipe->width; + format.format.height = drm_pipe->height; ++#if 0 + format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; ++#else ++ /* ...always blend in YUV colorspace; ++ * apply conversion as needed ++ */ ++ format.format.code = MEDIA_BUS_FMT_AYUV8_1X32; ++#endif + format.format.field = V4L2_FIELD_NONE; + + ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, set_fmt, NULL, +@@ -525,6 +538,13 @@ static int vsp1_du_pipeline_setup_output(struct vsp1_device *vsp1, + format.format.code, pipe->output->entity.index); + + format.pad = RWPF_PAD_SOURCE; ++ /* ...force conversion back to ARGB at the output */ ++ format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; ++ ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, set_fmt, NULL, ++ &format); ++ if (ret < 0) ++ return ret; ++ + ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, get_fmt, NULL, + &format); + if (ret < 0) +@@ -846,12 +866,14 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index, + } + + dev_dbg(vsp1->dev, +- "%s: RPF%u: (%u,%u)/%ux%u -> (%u,%u)/%ux%u (%08x), pitch %u dma { %pad, %pad, %pad } zpos %u\n", ++ "%s: RPF%u: (%u,%u)/%ux%u -> (%u,%u)/%ux%u (%08x), pitch %u " ++ "dma { %pad, %pad, %pad } zpos %u, alpha %pad, ckey %x/%x/%x\n", + __func__, rpf_index, + cfg->src.left, cfg->src.top, cfg->src.width, cfg->src.height, + cfg->dst.left, cfg->dst.top, cfg->dst.width, cfg->dst.height, + cfg->pixelformat, cfg->pitch, &cfg->mem[0], &cfg->mem[1], +- &cfg->mem[2], cfg->zpos); ++ &cfg->mem[2], cfg->zpos, &cfg->alpha_mem, cfg->ckey, ++ cfg->ckey_set0, cfg->ckey_set1); + + /* + * Store the format, stride, memory buffer address, crop and compose +@@ -879,6 +901,11 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index, + rpf->colorkey_en = cfg->colorkey_en; + rpf->colorkey_alpha = cfg->colorkey_alpha; + rpf->interlaced = cfg->interlaced; ++ rpf->alpha_pitch = cfg->alpha_pitch; ++ rpf->ckey = cfg->ckey; ++ rpf->ckey_set0 = cfg->ckey_set0; ++ rpf->ckey_set1 = cfg->ckey_set1; ++ rpf->blend = cfg->blend; + + if ((vsp1->ths_quirks & VSP1_AUTO_FLD_NOT_SUPPORT) && + rpf->interlaced) { +@@ -890,6 +917,7 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index, + rpf->mem.addr[0] = cfg->mem[0]; + rpf->mem.addr[1] = cfg->mem[1]; + rpf->mem.addr[2] = cfg->mem[2]; ++ rpf->mem.alpha = cfg->alpha_mem; + + vsp1->drm->inputs[rpf_index].crop = cfg->src; + vsp1->drm->inputs[rpf_index].compose = cfg->dst; +diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c +index eae5e6a..86dbaa4 100644 +--- a/drivers/media/platform/vsp1/vsp1_lif.c ++++ b/drivers/media/platform/vsp1/vsp1_lif.c +@@ -116,7 +116,7 @@ static void lif_configure_stream(struct vsp1_entity *entity, + + vsp1_lif_write(lif, dlb, VI6_LIF_CTRL, + (obth << VI6_LIF_CTRL_OBTH_SHIFT) | +- (format->code == 0 ? VI6_LIF_CTRL_CFMT : 0) | ++ (format->code != MEDIA_BUS_FMT_ARGB8888_1X32 ? VI6_LIF_CTRL_CFMT : 0) | + VI6_LIF_CTRL_REQSEL | VI6_LIF_CTRL_LIF_EN); + + /* +diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c +index 17b9812..5d23cfd 100644 +--- a/drivers/media/platform/vsp1/vsp1_pipe.c ++++ b/drivers/media/platform/vsp1/vsp1_pipe.c +@@ -141,6 +141,10 @@ static const struct vsp1_format_info vsp1_video_formats[] = { + VI6_FMT_Y_U_V_444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 3, { 8, 8, 8 }, false, true, 1, 1, false }, ++ { V4L2_PIX_FMT_GREY, MEDIA_BUS_FMT_Y8_1X8, ++ /*VI6_FMT_Y_U_V_444*/0xDEAD, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | ++ VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, ++ 1, { 8, 0, 0 }, false, false, 0, 0, false }, + }; + + /** +diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c +index bb24a42..9875b0b 100644 +--- a/drivers/media/platform/vsp1/vsp1_rpf.c ++++ b/drivers/media/platform/vsp1/vsp1_rpf.c +@@ -7,6 +7,7 @@ + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) + */ + ++//#define DEBUG + #include + + #include +@@ -89,8 +90,10 @@ static void rpf_configure_stream(struct vsp1_entity *entity, + if (sink_format->code != source_format->code) + infmt |= VI6_RPF_INFMT_CSC; + ++ dev_dbg(entity->vsp1->dev, "rpf#%d: infmt=%x (csc=%d)\n", ++ rpf->entity.index, infmt, !!(infmt & VI6_RPF_INFMT_CSC)); + vsp1_rpf_write(rpf, dlb, VI6_RPF_INFMT, infmt); +- vsp1_rpf_write(rpf, dlb, VI6_RPF_DSWAP, fmtinfo->swap); ++ vsp1_rpf_write(rpf, dlb, VI6_RPF_DSWAP, fmtinfo->swap | 0xF00); + + /* Output location */ + if (pipe->brx) { +@@ -113,6 +116,17 @@ static void rpf_configure_stream(struct vsp1_entity *entity, + (left << VI6_RPF_LOC_HCOORD_SHIFT) | + (top << VI6_RPF_LOC_VCOORD_SHIFT)); + ++ // ...setup alpha-plane as required ++ if (rpf->mem.alpha) { ++ vsp1_rpf_write(rpf, dlb, VI6_RPF_SRCM_ADDR_AI, rpf->mem.alpha); ++ vsp1_rpf_write(rpf, dlb, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_ASEL_8B_PLANE); ++ vsp1_rpf_write(rpf, dlb, VI6_RPF_SRCM_ASTRIDE, rpf->alpha_pitch); ++ dev_dbg(entity->vsp1->dev, ++ "rpf#%d: setup alpha-plane: buffer=%pad, stride=%u\n", ++ rpf->entity.index, &rpf->mem.alpha, rpf->alpha_pitch); ++ goto out; ++ } ++ + /* + * On Gen2 use the alpha channel (extended to 8 bits) when available or + * a fixed alpha value set through the V4L2_CID_ALPHA_COMPONENT control +@@ -168,7 +182,9 @@ static void rpf_configure_stream(struct vsp1_entity *entity, + if (entity->vsp1->info->gen == 3) { + u32 mult; + +- if (fmtinfo->alpha && ++ dev_dbg(entity->vsp1->dev, "rpf#%d: alpha=%x, fourcc=%x\n", ++ rpf->entity.index, fmtinfo->alpha, fmtinfo->fourcc); ++ if (0 && fmtinfo->alpha && + fmtinfo->fourcc != V4L2_PIX_FMT_ARGB555) { + /* + * When the input contains an alpha channel enable the +@@ -199,6 +215,7 @@ static void rpf_configure_stream(struct vsp1_entity *entity, + rpf->mult_alpha = mult; + } + ++out: + vsp1_rpf_write(rpf, dlb, VI6_RPF_MSK_CTRL, 0); + + if (rpf->colorkey_en) { +@@ -207,7 +224,10 @@ static void rpf_configure_stream(struct vsp1_entity *entity, + vsp1_rpf_write(rpf, dlb, VI6_RPF_CKEY_CTRL, + VI6_RPF_CKEY_CTRL_SAPE0); + } else { +- vsp1_rpf_write(rpf, dlb, VI6_RPF_CKEY_CTRL, 0); ++ /* ...set up color keying */ ++ vsp1_rpf_write(rpf, dlb, VI6_RPF_CKEY_CTRL, rpf->ckey); ++ vsp1_rpf_write(rpf, dlb, VI6_RPF_CKEY_SET0, rpf->ckey_set0); ++ vsp1_rpf_write(rpf, dlb, VI6_RPF_CKEY_SET1, rpf->ckey_set1); + } + } + +diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.c b/drivers/media/platform/vsp1/vsp1_rwpf.c +index 049bdd9..f763008 100644 +--- a/drivers/media/platform/vsp1/vsp1_rwpf.c ++++ b/drivers/media/platform/vsp1/vsp1_rwpf.c +@@ -7,6 +7,7 @@ + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) + */ + ++//#define DEBUG + #include + + #include "vsp1.h" +diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h +index 58d882e..793f27d 100644 +--- a/drivers/media/platform/vsp1/vsp1_rwpf.h ++++ b/drivers/media/platform/vsp1/vsp1_rwpf.h +@@ -28,6 +28,7 @@ struct vsp1_video; + + struct vsp1_rwpf_memory { + dma_addr_t addr[3]; ++ dma_addr_t alpha; + }; + + struct vsp1_rwpf { +@@ -71,6 +72,11 @@ struct vsp1_rwpf { + + int write_back; + dma_addr_t buf_addr[3]; ++ unsigned int alpha_pitch; ++ unsigned int ckey; ++ unsigned int ckey_set0; ++ unsigned int ckey_set1; ++ unsigned int blend; + }; + + static inline struct vsp1_rwpf *to_rwpf(struct v4l2_subdev *subdev) +diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c +index 75f9636..c6edeb4 100644 +--- a/drivers/media/platform/vsp1/vsp1_wpf.c ++++ b/drivers/media/platform/vsp1/vsp1_wpf.c +@@ -7,6 +7,7 @@ + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) + */ + ++//#define DEBUG + #include + + #include +@@ -245,6 +246,9 @@ static void wpf_configure_stream(struct vsp1_entity *entity, + u32 outfmt = 0; + u32 srcrpf = 0; + ++ dev_dbg(vsp1->dev, "wpf#%d: outfmt=%x (csc=%d)\n", ++ wpf->entity.index, outfmt, !!(outfmt & VI6_WPF_OUTFMT_CSC)); ++ + if (pipe->vmute_flag) + return; + +diff --git a/include/media/vsp1.h b/include/media/vsp1.h +index 08d02de..bc14dd3 100644 +--- a/include/media/vsp1.h ++++ b/include/media/vsp1.h +@@ -63,6 +63,11 @@ struct vsp1_du_atomic_config { + u32 pixelformat; + unsigned int pitch; + dma_addr_t mem[3]; ++ dma_addr_t alpha_mem; ++ unsigned int alpha_pitch; ++ unsigned int ckey; ++ unsigned int ckey_set0; ++ unsigned int ckey_set1; + struct v4l2_rect src; + struct v4l2_rect dst; + unsigned int alpha; +@@ -71,6 +76,7 @@ struct vsp1_du_atomic_config { + u32 colorkey_alpha; + bool colorkey_en; + bool interlaced; ++ unsigned int blend; + }; + + /** +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0357-gpu-drm-rcar-du-rcar_du_vsp-Check-if-gem-buffer-has-.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0357-gpu-drm-rcar-du-rcar_du_vsp-Check-if-gem-buffer-has-.patch new file mode 100644 index 00000000..2c7ae508 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0357-gpu-drm-rcar-du-rcar_du_vsp-Check-if-gem-buffer-has-.patch @@ -0,0 +1,29 @@ +From 1bf8035838734ebf1745805ae874feb491eedafa Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Thu, 27 Jun 2019 02:55:59 +0300 +Subject: [PATCH 177/211] gpu: drm: rcar-du: rcar_du_vsp: Check if gem buffer + has a physical address + +Do not copy the sg in case gem buffer does have a physical address. + +Signed-off-by: Valentine Barshak +--- + drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +index 2b076cf..a904132 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +@@ -277,7 +277,7 @@ static int rcar_du_vsp_plane_prepare_fb(struct drm_plane *plane, + drm_fb_cma_get_gem_obj(state->fb, i); + struct sg_table *sgt = &rstate->sg_tables[i]; + +- if (gem->sgt) { ++ if (gem->sgt && !gem->paddr) { + struct scatterlist *src; + struct scatterlist *dst; + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0358-media-platform-vsp1-Add-cropping-handling-to-VSP-alp.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0358-media-platform-vsp1-Add-cropping-handling-to-VSP-alp.patch new file mode 100644 index 00000000..9abaf2e3 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0358-media-platform-vsp1-Add-cropping-handling-to-VSP-alp.patch @@ -0,0 +1,56 @@ +From a96e381a1bef24b109331d55da60b9a207784815 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Tue, 13 Nov 2018 18:17:42 +0300 +Subject: [PATCH 178/211] media: platform: vsp1: Add cropping handling to VSP + alpha-planes + +This is based on the original "Add cropping handling to VSP alpha-planes" +patch by Konstantin Kozhevnikov . + +Signed-off-by: Valentine Barshak +--- + drivers/media/platform/vsp1/vsp1_dl.c | 3 ++- + drivers/media/platform/vsp1/vsp1_rpf.c | 10 +++++++--- + 2 files changed, 9 insertions(+), 4 deletions(-) + +diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c +index f501307..13da682 100644 +--- a/drivers/media/platform/vsp1/vsp1_dl.c ++++ b/drivers/media/platform/vsp1/vsp1_dl.c +@@ -440,7 +440,8 @@ void vsp1_dl_set_addr_auto_fld(struct vsp1_dl_body *dlb, + dlb->src_dst_addr[v_bot_index].addr = v_bot_addr; + + /* ...set alpha-plane address as needed */ +- dlb->src_dst_addr[alpha_index].addr = rpf->mem.alpha; ++ dlb->src_dst_addr[alpha_index].addr = rpf->mem.alpha + ++ crop->top * width + crop->left; + } + + static struct vsp1_dl_list *vsp1_dl_list_alloc(struct vsp1_dl_manager *dlm) +diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c +index 9875b0b..724655b 100644 +--- a/drivers/media/platform/vsp1/vsp1_rpf.c ++++ b/drivers/media/platform/vsp1/vsp1_rpf.c +@@ -118,12 +118,16 @@ static void rpf_configure_stream(struct vsp1_entity *entity, + + // ...setup alpha-plane as required + if (rpf->mem.alpha) { +- vsp1_rpf_write(rpf, dlb, VI6_RPF_SRCM_ADDR_AI, rpf->mem.alpha); ++ struct v4l2_rect *crop = vsp1_rwpf_get_crop(rpf, rpf->entity.config); ++ ++ vsp1_rpf_write(rpf, dlb, VI6_RPF_SRCM_ADDR_AI, ++ rpf->mem.alpha + crop->top * rpf->alpha_pitch + crop->left); + vsp1_rpf_write(rpf, dlb, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_ASEL_8B_PLANE); + vsp1_rpf_write(rpf, dlb, VI6_RPF_SRCM_ASTRIDE, rpf->alpha_pitch); + dev_dbg(entity->vsp1->dev, +- "rpf#%d: setup alpha-plane: buffer=%pad, stride=%u\n", +- rpf->entity.index, &rpf->mem.alpha, rpf->alpha_pitch); ++ "rpf#%d: setup alpha-plane: buffer=%pad, crop=%d,%d, stride=%u\n", ++ rpf->entity.index, &rpf->mem.alpha, crop->left, crop->top, ++ rpf->alpha_pitch); + goto out; + } + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0359-media-platform-rcar_imr-Clean-up-to-avoid-compiler-w.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0359-media-platform-rcar_imr-Clean-up-to-avoid-compiler-w.patch new file mode 100644 index 00000000..0d245924 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0359-media-platform-rcar_imr-Clean-up-to-avoid-compiler-w.patch @@ -0,0 +1,106 @@ +From cf65e562f773b04eb2cc07540bf0d5b3b6797790 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Tue, 13 Nov 2018 23:55:41 +0300 +Subject: [PATCH 179/211] media: platform: rcar_imr: Clean up to avoid compiler + warnings + +This is a slight driver clean-up that helps to avoid compiler warnings. + +Signed-off-by: Valentine Barshak +--- + drivers/media/platform/rcar_imr.c | 19 +++++++++++-------- + 1 file changed, 11 insertions(+), 8 deletions(-) + +diff --git a/drivers/media/platform/rcar_imr.c b/drivers/media/platform/rcar_imr.c +index 8864b0b..cdd847c 100644 +--- a/drivers/media/platform/rcar_imr.c ++++ b/drivers/media/platform/rcar_imr.c +@@ -454,7 +454,7 @@ static int imr_queue_setup(struct vb2_queue *vq, + + static int imr_buf_prepare(struct vb2_buffer *vb) + { +- struct imr_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); ++ /* struct imr_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); */ + + /* ...unclear yet if we want to prepare a buffer somehow (cache invalidation? - tbd) */ + return 0; +@@ -945,8 +945,8 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg + static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc) + { + struct imr_device *imr = ctx->imr; +- struct imr_mesh *mesh; +- int vbo_num; ++ struct imr_mesh *mesh = NULL; ++ int vbo_num = 0; + struct imr_cfg *cfg; + void *buf, *map; + u32 type; +@@ -1122,11 +1122,9 @@ static int imr_ioctl_map_raw(struct imr_ctx *ctx, struct imr_map_desc *desc) + { + struct imr_device *imr = ctx->imr; + u32 type = desc->type; +- u32 length = desc->size; + struct imr_cfg *cfg; + void *dl_vaddr; + u32 dl_size; +- u32 dl_start_offset; + dma_addr_t dl_dma_addr; + + /* ...check RSE */ +@@ -1157,6 +1155,7 @@ static int imr_ioctl_map_raw(struct imr_ctx *ctx, struct imr_map_desc *desc) + + /* ...get pointer to the new display list */ + dl_vaddr = cfg->dl_vaddr; ++ dl_dma_addr = cfg->dl_dma_addr; + + /* ...prepare main DL-program */ + imr_dl_program_setup(ctx, cfg, type, dl_vaddr, (u32)(uintptr_t)desc->data); +@@ -1169,7 +1168,7 @@ static int imr_ioctl_map_raw(struct imr_ctx *ctx, struct imr_map_desc *desc) + cfg->id, (u32)dl_dma_addr, dl_size, 0); + + if (debug >= 4) +- print_hex_dump_bytes("DL-", DUMP_PREFIX_OFFSET, dl_vaddr + dl_start_offset, dl_size - dl_start_offset); ++ print_hex_dump_bytes("DL-", DUMP_PREFIX_OFFSET, dl_vaddr, dl_size); + + /* ...success */ + return 0; +@@ -1679,6 +1678,7 @@ static const struct v4l2_file_operations imr_fops = { + ******************************************************************************/ + + /* ...job cleanup function */ ++#if 0 + static void imr_cleanup(struct imr_ctx *ctx) + { + struct imr_device *imr = ctx->imr; +@@ -1697,6 +1697,7 @@ static void imr_cleanup(struct imr_ctx *ctx) + /* ...release lock before we mark current job as finished */ + spin_unlock_irqrestore(&imr->lock, flags); + } ++#endif + + /* ...job execution function */ + static void imr_device_run(void *priv) +@@ -1918,8 +1919,9 @@ static int imr_probe(struct platform_device *pdev) + struct resource *res; + struct device_node *np = pdev->dev.of_node; + int ret; +- phandle *prop; ++ const phandle *prop; + struct device_node *node; ++ struct device *adev; + + imr = devm_kzalloc(&pdev->dev, sizeof(*imr), GFP_KERNEL); + if (!imr) +@@ -1986,7 +1988,8 @@ static int imr_probe(struct platform_device *pdev) + } + } + +- struct device *adev = device_create(imr_alloc_class, imr->dev, MKDEV(0, 0), NULL, "%s_alloc", dev_name(&pdev->dev)); ++ adev = device_create(imr_alloc_class, imr->dev, MKDEV(0, 0), NULL, ++ "%s_alloc", dev_name(&pdev->dev)); + if (IS_ERR(adev)) { + v4l2_err(&imr->v4l2_dev, "Failed to create alloc-device\n"); + ret = PTR_ERR(adev); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0360-arm64-dts-renesas-r8a77970-and-r8a77980-Add-CPU-oper.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0360-arm64-dts-renesas-r8a77970-and-r8a77980-Add-CPU-oper.patch new file mode 100644 index 00000000..40b222e8 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0360-arm64-dts-renesas-r8a77970-and-r8a77980-Add-CPU-oper.patch @@ -0,0 +1,206 @@ +From e8eee5077c2068cc04972378abcf836d08d7831d Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Tue, 13 Nov 2018 19:11:14 +0300 +Subject: [PATCH 180/211] arm64: dts: renesas: r8a77970 and r8a77980: Add CPU + operation points. + +This adds CPU operation points and enables cpufreq driver +for the V3M/V3H SoCs. This is based on the original patch +by Andrey Dolnikov . +Slight modifications have been done to the Z2 CPG quirk +definitions. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970.dtsi | 13 +++++++++++++ + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 15 +++++++++++++++ + drivers/clk/renesas/r8a77970-cpg-mssr.c | 1 + + drivers/clk/renesas/r8a77980-cpg-mssr.c | 1 + + drivers/clk/renesas/rcar-gen3-cpg.c | 27 +++++++++++++++++++++++++-- + drivers/cpufreq/cpufreq-dt-platdev.c | 2 ++ + 6 files changed, 57 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +index 35000a7..090122c 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +@@ -44,6 +44,7 @@ + power-domains = <&sysc R8A77970_PD_CA53_CPU0>; + next-level-cache = <&L2_CA53>; + enable-method = "psci"; ++ operating-points-v2 = <&cluster0_opp_tb0>; + }; + + a53_1: cpu@1 { +@@ -54,6 +55,7 @@ + power-domains = <&sysc R8A77970_PD_CA53_CPU1>; + next-level-cache = <&L2_CA53>; + enable-method = "psci"; ++ operating-points-v2 = <&cluster0_opp_tb0>; + }; + + L2_CA53: cache-controller { +@@ -64,6 +66,17 @@ + }; + }; + ++ cluster0_opp_tb0: opp_table0 { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp@800000000 { ++ opp-hz = /bits/ 64 <800000000>; ++ opp-microvolt = <850000>; ++ clock-latency-ns = <300000>; ++ }; ++ }; ++ + extal_clk: extal { + compatible = "fixed-clock"; + #clock-cells = <0>; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index e0d2213..24edddb 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -46,6 +46,7 @@ + power-domains = <&sysc R8A77980_PD_CA53_CPU0>; + next-level-cache = <&L2_CA53>; + enable-method = "psci"; ++ operating-points-v2 = <&cluster0_opp_tb0>; + }; + + a53_1: cpu@1 { +@@ -56,6 +57,7 @@ + power-domains = <&sysc R8A77980_PD_CA53_CPU1>; + next-level-cache = <&L2_CA53>; + enable-method = "psci"; ++ operating-points-v2 = <&cluster0_opp_tb0>; + }; + + a53_2: cpu@2 { +@@ -66,6 +68,7 @@ + power-domains = <&sysc R8A77980_PD_CA53_CPU2>; + next-level-cache = <&L2_CA53>; + enable-method = "psci"; ++ operating-points-v2 = <&cluster0_opp_tb0>; + }; + + a53_3: cpu@3 { +@@ -76,6 +79,7 @@ + power-domains = <&sysc R8A77980_PD_CA53_CPU3>; + next-level-cache = <&L2_CA53>; + enable-method = "psci"; ++ operating-points-v2 = <&cluster0_opp_tb0>; + }; + + L2_CA53: cache-controller { +@@ -86,6 +90,17 @@ + }; + }; + ++ cluster0_opp_tb0: opp_table0 { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp@1000000000 { ++ opp-hz = /bits/ 64 <1000000000>; ++ opp-microvolt = <850000>; /* TBD; section 87.2 */ ++ clock-latency-ns = <300000>; ++ }; ++ }; ++ + extal_clk: extal { + compatible = "fixed-clock"; + #clock-cells = <0>; +diff --git a/drivers/clk/renesas/r8a77970-cpg-mssr.c b/drivers/clk/renesas/r8a77970-cpg-mssr.c +index 29833b6..1e3f6f8 100644 +--- a/drivers/clk/renesas/r8a77970-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a77970-cpg-mssr.c +@@ -79,6 +79,7 @@ static const struct cpg_core_clk r8a77970_core_clks[] __initconst = { + DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4, CLK_PLL1_DIV2, 2, 1), + + /* Core Clock Outputs */ ++ DEF_GEN3_Z("z2", R8A77970_CLK_Z2, CLK_TYPE_GEN3_Z2, CLK_PLL1_DIV4, 1), + DEF_FIXED("ztr", R8A77970_CLK_ZTR, CLK_PLL1_DIV2, 6, 1), + DEF_FIXED("ztrd2", R8A77970_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1), + DEF_FIXED("zt", R8A77970_CLK_ZT, CLK_PLL1_DIV2, 4, 1), +diff --git a/drivers/clk/renesas/r8a77980-cpg-mssr.c b/drivers/clk/renesas/r8a77980-cpg-mssr.c +index 5371c27..4a61b585 100644 +--- a/drivers/clk/renesas/r8a77980-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a77980-cpg-mssr.c +@@ -75,6 +75,7 @@ static const struct cpg_core_clk r8a77980_core_clks[] __initconst = { + R8A77980_CLK_RPC), + + /* Core Clock Outputs */ ++ DEF_GEN3_Z("z2", R8A77980_CLK_Z2, CLK_TYPE_GEN3_Z2, CLK_PLL2, 2), + DEF_FIXED("ztr", R8A77980_CLK_ZTR, CLK_PLL1_DIV2, 6, 1), + DEF_FIXED("ztrd2", R8A77980_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1), + DEF_FIXED("zt", R8A77980_CLK_ZT, CLK_PLL1_DIV2, 4, 1), +diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c +index c73b269..5993dbd 100644 +--- a/drivers/clk/renesas/rcar-gen3-cpg.c ++++ b/drivers/clk/renesas/rcar-gen3-cpg.c +@@ -45,6 +45,13 @@ static u32 cpg_quirks; + #define RCKCR_CKSEL BIT(1) /* Resverd RCLK clock soruce select */ + #define Z2FC_BIT_MASK_SFT_8 BIT(2) /* Use Z2FC bit mask range to [12:8] */ + #define ZG_PARENT_PLL0 BIT(3) /* Use PLL0 as ZG clock parent */ ++/* ++ * Z2: SYS-CPU divider 2 on V3H seems to be fixed to 1/2 and 1 on V3M. ++ * It is not 100% clear from the User's Manual but at least ++ * FRQCRC register is missed on V3x. ++ */ ++#define Z2_SYSCPU_1 BIT(4) /* Z2 is fixed with SYS-CPU divider 2 set to 1 - V3M */ ++#define Z2_SYSCPU_2 BIT(5) /* Z2 is fixed with SYS-CPU divider 2 set to 1/2 - V3H */ + + static spinlock_t cpg_lock; + +@@ -247,8 +254,16 @@ static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw, + unsigned int mult; + u32 val; + +- val = readl(zclk->reg) & zclk->mask; +- mult = 32 - (val >> __ffs(zclk->mask)); ++ if (cpg_quirks & Z2_SYSCPU_1) { ++ /* SYS-CPU divider 2 is 1 == 32/32) */ ++ mult = 32; ++ } else if (cpg_quirks & Z2_SYSCPU_2) { ++ /* SYS-CPU divider 2 is 1/2 == 16/32) */ ++ mult = 16; ++ } else { ++ val = readl(zclk->reg) & zclk->mask; ++ mult = 32 - (val >> __ffs(zclk->mask)); ++ } + + return Z_CLK_ROUND(prate * mult / 32); + } +@@ -827,6 +842,14 @@ static const struct soc_device_attribute cpg_quirks_match[] __initconst = { + .soc_id = "r8a77990", + .data = (void *)(Z2FC_BIT_MASK_SFT_8 | ZG_PARENT_PLL0), + }, ++ { ++ .soc_id = "r8a77970", ++ .data = (void *)(Z2_SYSCPU_1), ++ }, ++ { ++ .soc_id = "r8a77980", ++ .data = (void *)(Z2_SYSCPU_2), ++ }, + { /* sentinel */ } + }; + +diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c +index 9e0aa76..6adb4a1 100644 +--- a/drivers/cpufreq/cpufreq-dt-platdev.c ++++ b/drivers/cpufreq/cpufreq-dt-platdev.c +@@ -69,6 +69,8 @@ static const struct of_device_id whitelist[] __initconst = { + { .compatible = "renesas,r8a7794", }, + { .compatible = "renesas,r8a7795", }, + { .compatible = "renesas,r8a7796", }, ++ { .compatible = "renesas,r8a77970", }, ++ { .compatible = "renesas,r8a77980", }, + { .compatible = "renesas,sh73a0", }, + + { .compatible = "rockchip,rk2928", }, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0361-V3H-DTS-Add-FCPR-devices.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0361-V3H-DTS-Add-FCPR-devices.patch new file mode 100644 index 00000000..91c32840 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0361-V3H-DTS-Add-FCPR-devices.patch @@ -0,0 +1,70 @@ +From 3ba4e9c2cf6d744f6f15a7c2f7b71802f967e038 Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Fri, 26 Oct 2018 18:38:42 +0300 +Subject: [PATCH 181/211] V3H DTS: Add FCPR devices. + +--- + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 47 +++++++++++++++++++++++++++++++ + 1 file changed, 47 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index 24edddb..c599814 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -1460,6 +1460,53 @@ + power-domains = <&sysc R8A77980_PD_A3VIP2>; + }; + ++ fcpr_vip { ++ compatible = "generic-uio"; ++ reg = <0 0xe7aa0000 0 0x20000>; ++ }; ++ ++ fcpr_ir { ++ compatible = "generic-uio"; ++ reg = <0 0xff8d8000 0 0x10000>; ++ }; ++ ++ fcpr_vio0 { ++ compatible = "generic-uio"; ++ reg = <0 0xfe9c0000 0 0x10000>; ++ }; ++ ++ fcpr_vio1 { ++ compatible = "generic-uio"; ++ reg = <0 0xfea90000 0 0x10000>; ++ }; ++ ++ fcpr_rt { ++ compatible = "generic-uio"; ++ reg = <0 0xffc70000 0 0x10000>; ++ }; ++ ++ fcpr_peri { ++ compatible = "generic-uio"; ++ reg = <0 0xe7320000 0 0x10000>; ++ }; ++ ++ fcpra_peri { ++ compatible = "generic-uio"; ++ reg = <0 0xe7410000 0 0x10000>; ++ }; ++ ++ ++ fcpr_c53 { ++ compatible = "generic-uio"; ++ reg = <0 0xf12a0000 0 0x10000>; ++ }; ++ ++ fcpra_c53 { ++ compatible = "generic-uio"; ++ reg = <0 0xf12f0000 0 0x10000>; ++ }; ++ ++ + isp0: isp@fec00000 { + compatible = "renesas,isp-r8a77980"; + reg = <0 0xfec00000 0 0x20000>, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0362-arm64-dts-r8a77980-v3hsk-Enable-onboard-eMMC.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0362-arm64-dts-r8a77980-v3hsk-Enable-onboard-eMMC.patch new file mode 100644 index 00000000..e74c3f3d --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0362-arm64-dts-r8a77980-v3hsk-Enable-onboard-eMMC.patch @@ -0,0 +1,69 @@ +From b1c0fc5cec81edb5be704011f9fd07c343e47286 Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Thu, 15 Nov 2018 23:18:48 +0300 +Subject: [PATCH 182/211] arm64: dts: r8a77980-v3hsk: Enable onboard eMMC. + +--- + arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts | 35 ++++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +index cfd9c89..0e0aed7 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +@@ -118,6 +118,15 @@ + regulator-boot-on; + regulator-always-on; + }; ++ ++ vddq_vin01: regulator-2 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VDDQ_VIN01"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; + }; + + &du { +@@ -230,6 +239,18 @@ + groups = "scif_clk_b"; + function = "scif_clk"; + }; ++ ++ mmc_pins_uhs: mmc_uhs { ++ groups = "mmc_data8", "mmc_ctrl", "mmc_ds"; ++ function = "mmc"; ++ power-source = <1800>; ++ }; ++ ++ mmc_pins: mmc { ++ groups = "mmc_data8", "mmc_ctrl", "mmc_ds"; ++ function = "mmc"; ++ power-source = <3300>; ++ }; + }; + + &rwdt { +@@ -247,3 +268,17 @@ + &scif_clk { + clock-frequency = <14745600>; + }; ++ ++&mmc0 { ++ /* used for on-board eMMC */ ++ pinctrl-0 = <&mmc_pins>; ++ pinctrl-1 = <&mmc_pins_uhs>; ++ pinctrl-names = "default", "state_uhs"; ++ ++ vmmc-supply = <&vcc3v3_d5>; ++ vqmmc-supply = <&vddq_vin01>; ++ mmc-hs200-1_8v; ++ bus-width = <8>; ++ non-removable; ++ status = "okay"; ++}; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0363-arm64-dts-renesas-r8a77980-v3hsk-vb-Xch-Fix-Ethernet.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0363-arm64-dts-renesas-r8a77980-v3hsk-vb-Xch-Fix-Ethernet.patch new file mode 100644 index 00000000..fc05d622 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0363-arm64-dts-renesas-r8a77980-v3hsk-vb-Xch-Fix-Ethernet.patch @@ -0,0 +1,50 @@ +From 9b1ace6d26cd3234c87bd3f43ec0360485882f74 Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Fri, 16 Nov 2018 12:59:24 +0300 +Subject: [PATCH 183/211] arm64: dts: renesas: r8a77980-v3hsk-vb-Xch: Fix + Ethernet AVB pins. + +--- + arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts | 7 +------ + arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts | 7 +------ + 2 files changed, 2 insertions(+), 12 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts +index 7b35608..cb9cd54 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts +@@ -485,12 +485,7 @@ + }; + + avb_pins: avb { +- groups = "avb_mdc", "avb_mdio", +- "avb_rx_ctrl", "avb_rxc", +- "avb_rd4", +- "avb_tx_ctrl", "avb_txc", +- "avb_txcrefclk", +- "avb_td4"; ++ groups = "avb_mdio", "avb_rgmii"; + function = "avb"; + }; + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts +index 84d89d2..f23f2d0 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts +@@ -634,12 +634,7 @@ + }; + + avb_pins: avb { +- groups = "avb_mdc", "avb_mdio", +- "avb_rx_ctrl", "avb_rxc", +- "avb_rd4", +- "avb_tx_ctrl", "avb_txc", +- "avb_txcrefclk", +- "avb_td4"; ++ groups = "avb_mdio", "avb_rgmii"; + function = "avb"; + }; + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0364-clocksource-drivers-sh_cmt-Add-R-Car-gen3-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0364-clocksource-drivers-sh_cmt-Add-R-Car-gen3-support.patch new file mode 100644 index 00000000..5281aa09 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0364-clocksource-drivers-sh_cmt-Add-R-Car-gen3-support.patch @@ -0,0 +1,37 @@ +From d6dae604dcb5ebf73e1b0adfdd7773fd9476c7c3 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Wed, 12 Sep 2018 23:17:37 +0300 +Subject: [PATCH 184/211] clocksource/drivers/sh_cmt: Add R-Car gen3 support + +Add support for the R-Car gen3 CMT types 0/1 -- they seem to be the same +CMT types 0/1 as in R-Car gen2 SoCs. + +Signed-off-by: Sergei Shtylyov +Reviewed-by: Geert Uytterhoeven +Signed-off-by: Daniel Lezcano +--- + drivers/clocksource/sh_cmt.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c +index 70b3cf8..30f18ea 100644 +--- a/drivers/clocksource/sh_cmt.c ++++ b/drivers/clocksource/sh_cmt.c +@@ -943,6 +943,14 @@ static const struct of_device_id sh_cmt_of_table[] __maybe_unused = { + }, + { .compatible = "renesas,rcar-gen2-cmt0", .data = &sh_cmt_info[SH_CMT0_RCAR_GEN2] }, + { .compatible = "renesas,rcar-gen2-cmt1", .data = &sh_cmt_info[SH_CMT1_RCAR_GEN2] }, ++ { ++ .compatible = "renesas,rcar-gen3-cmt0", ++ .data = &sh_cmt_info[SH_CMT0_RCAR_GEN2] ++ }, ++ { ++ .compatible = "renesas,rcar-gen3-cmt1", ++ .data = &sh_cmt_info[SH_CMT1_RCAR_GEN2] ++ }, + { } + }; + MODULE_DEVICE_TABLE(of, sh_cmt_of_table); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0365-mtd-spi-nor-Add-R-Car-Gen3-RPC-QSPI-driver.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0365-mtd-spi-nor-Add-R-Car-Gen3-RPC-QSPI-driver.patch new file mode 100644 index 00000000..b0149ee8 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0365-mtd-spi-nor-Add-R-Car-Gen3-RPC-QSPI-driver.patch @@ -0,0 +1,1334 @@ +From bb7780ccca449ad284a96789d38913d844e1f985 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Thu, 15 Nov 2018 23:55:17 +0300 +Subject: [PATCH 185/211] mtd: spi-nor: Add R-Car Gen3 RPC QSPI driver + +This is preliminary Renesas R-Car Gen3 RPC QSPI flash driver. +The driver should support single and dual mode. Dual mode means +that there are two SPI-NOR flash chips connected. + +This is based on the original patch by patch by Dmitry Shifrin. +The only change is dual mode support done before calling +mtd_device_register() instead of implementing spi-nor array +size support in the generic spi-nor layer. + +Signed-off-by: Dmitry Shifrin +Signed-off-by: Valentine Barshak +--- + drivers/mtd/spi-nor/Kconfig | 8 + + drivers/mtd/spi-nor/Makefile | 1 + + drivers/mtd/spi-nor/renesas-rpc.c | 1271 +++++++++++++++++++++++++++++++++++++ + 3 files changed, 1280 insertions(+) + create mode 100644 drivers/mtd/spi-nor/renesas-rpc.c + +diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig +index 69c638d..2c73adb 100644 +--- a/drivers/mtd/spi-nor/Kconfig ++++ b/drivers/mtd/spi-nor/Kconfig +@@ -7,6 +7,14 @@ menuconfig MTD_SPI_NOR + + if MTD_SPI_NOR + ++ ++config SPI_RENESAS_RPC ++ tristate "Renesas RPC controller" ++ depends on ARCH_R8A7795 || ARCH_R8A7796 || ARCH_R8A77970 || ARCH_R8A77980 || COMPILE_TEST ++ help ++ QSPI driver for Renesas SPI Multi I/O Bus controller. This controller ++ supports normal, dual and quad spi for one or two SPI NOR Flashes. ++ + config MTD_MT81xx_NOR + tristate "Mediatek MT81xx SPI NOR flash controller" + depends on HAS_IOMEM +diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile +index f4c61d2..0c46c9c 100644 +--- a/drivers/mtd/spi-nor/Makefile ++++ b/drivers/mtd/spi-nor/Makefile +@@ -7,6 +7,7 @@ obj-$(CONFIG_SPI_FSL_QUADSPI) += fsl-quadspi.o + obj-$(CONFIG_SPI_HISI_SFC) += hisi-sfc.o + obj-$(CONFIG_MTD_MT81xx_NOR) += mtk-quadspi.o + obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o ++obj-$(CONFIG_SPI_RENESAS_RPC) += renesas-rpc.o + obj-$(CONFIG_SPI_INTEL_SPI) += intel-spi.o + obj-$(CONFIG_SPI_INTEL_SPI_PCI) += intel-spi-pci.o + obj-$(CONFIG_SPI_INTEL_SPI_PLATFORM) += intel-spi-platform.o +diff --git a/drivers/mtd/spi-nor/renesas-rpc.c b/drivers/mtd/spi-nor/renesas-rpc.c +new file mode 100644 +index 0000000..b619a7e +--- /dev/null ++++ b/drivers/mtd/spi-nor/renesas-rpc.c +@@ -0,0 +1,1271 @@ ++/* ++ * Renesas RPC driver ++ * ++ * Copyright (C) 2018, Cogent Embedded Inc. ++ * ++ * 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; version 2 of the License. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* regs offsets */ ++#define CMNCR 0x0000 ++#define SSLDR 0x0004 ++#define DRCR 0x000C ++#define DRCMR 0x0010 ++#define DREAR 0x0014 ++#define DROPR 0x0018 ++#define DRENR 0x001C ++#define SMCR 0x0020 ++#define SMCMR 0x0024 ++#define SMADR 0x0028 ++#define SMOPR 0x002C ++#define SMENR 0x0030 ++#define SMRDR0 0x0038 ++#define SMRDR1 0x003C ++#define SMWDR0 0x0040 ++#define SMWDR1 0x0044 ++#define CMNSR 0x0048 ++#define DRDMCR 0x0058 ++#define DRDRENR 0x005C ++#define SMDMCR 0x0060 ++#define SMDRENR 0x0064 ++#define PHYCNT 0x007C ++#define PHYOFFSET1 0x0080 ++#define PHYOFFSET2 0x0084 ++#define PHYINT 0x0088 ++#define DIV_REG 0x00A8 ++ ++/* CMNCR */ ++#define CMNCR_BSZ_MASK (0x03) ++#define CMNCR_BSZ_4x1 (0x0) ++#define CMNCR_BSZ_8x1 (0x1) ++#define CMNCR_BSZ_4x2 (0x1) ++#define CMNCR_MD (0x1 << 31) ++#define CMNCR_MOIIO3_MASK (0x3 << 22) ++#define CMNCR_MOIIO3_HIZ (0x3 << 22) ++#define CMNCR_MOIIO2_MASK (0x3 << 20) ++#define CMNCR_MOIIO2_HIZ (0x3 << 20) ++#define CMNCR_MOIIO1_MASK (0x3 << 18) ++#define CMNCR_MOIIO1_HIZ (0x3 << 18) ++#define CMNCR_MOIIO0_MASK (0x3 << 16) ++#define CMNCR_MOIIO0_HIZ (0x3 << 16) ++#define CMNCR_IO0FV_MASK (0x3 << 8) ++#define CMNCR_IO0FV_HIZ (0x3 << 8) ++ ++/* DRCR */ ++#define DRCR_RBURST_MASK (0x1f << 16) ++#define DRCR_RBURST(v) (((v) & 0x1f) << 16) ++#define DRCR_SSLE (0x1) ++#define DRCR_RBE (0x1 << 8) ++#define DRCR_RCF (0x1 << 9) ++#define DRCR_RBURST_32 (0x1f << 16) ++ ++/* SMENR */ ++#define SMENR_CDB_MASK (0x03 << 30) ++#define SMENR_CDB(v) (((v) & 0x03) << 30) ++#define SMENR_CDB_1B (0) ++#define SMENR_CDB_2B (0x1 << 30) ++#define SMENR_CDB_4B (0x2 << 30) ++#define SMENR_OCDB_MASK (0x03 << 28) ++#define SMENR_OCDB_1B (0) ++#define SMENR_OCDB_2B (0x1 << 28) ++#define SMENR_OCDB_4B (0x2 << 28) ++#define SMENR_ADB_MASK (0x03 << 24) ++#define SMENR_ADB(v) (((v) & 0x03) << 24) ++#define SMENR_ADB_1B (0) ++#define SMENR_ADB_2B (0x1 << 24) ++#define SMENR_ADB_4B (0x2 << 24) ++#define SMENR_OPDB_MASK (0x03 << 20) ++#define SMENR_OPDB_1B (0) ++#define SMENR_OPDB_2B (0x1 << 20) ++#define SMENR_OPDB_4B (0x2 << 20) ++#define SMENR_SPIDB_MASK (0x03 << 16) ++#define SMENR_SPIDB(v) (((v) & 0x03) << 16) ++#define SMENR_SPIDB_1B (0) ++#define SMENR_SPIDB_2B (0x1 << 16) ++#define SMENR_SPIDB_4B (0x2 << 16) ++#define SMENR_OPDE_MASK (0xf << 4) ++#define SMENR_OPDE_DISABLE (0) ++#define SMENR_OPDE3 (0x8 << 4) ++#define SMENR_OPDE32 (0xC << 4) ++#define SMENR_OPDE321 (0xE << 4) ++#define SMENR_OPDE3210 (0xF << 4) ++#define SMENR_SPIDE_MASK (0x0F) ++#define SMENR_SPIDE_DISABLE (0) ++#define SMENR_SPIDE_8B (0x08) ++#define SMENR_SPIDE_16B (0x0C) ++#define SMENR_SPIDE_32B (0x0F) ++#define SMENR_DME (1<<15) ++#define SMENR_CDE (1<<14) ++#define SMENR_OCDE (1<<12) ++#define SMENR_ADE_MASK (0xf << 8) ++#define SMENR_ADE_DISABLE (0) ++#define SMENR_ADE_23_16 (0x4 << 8) ++#define SMENR_ADE_23_8 (0x6 << 8) ++#define SMENR_ADE_23_0 (0x7 << 8) ++#define SMENR_ADE_31_0 (0xf << 8) ++ ++/* SMCMR */ ++#define SMCMR_CMD(cmd) (((cmd) & 0xff) << 16) ++#define SMCMR_CMD_MASK (0xff << 16) ++#define SMCMR_OCMD(cmd) (((cmd) & 0xff)) ++#define SMCMR_OCMD_MASK (0xff) ++ ++/* SMDRENR */ ++#define SMDRENR_HYPE_MASK (0x7 << 12) ++#define SMDRENR_HYPE_SPI_FLASH (0x0) ++#define SMDRENR_ADDRE (0x1 << 8) ++#define SMDRENR_OPDRE (0x1 << 4) ++#define SMDRENR_SPIDRE (0x1) ++ ++/* PHYCNT */ ++#define PHYCNT_CAL (0x1 << 31) ++#define PHYCNT_OCTA_MASK (0x3 << 22) ++#define PHYCNT_EXDS (0x1 << 21) ++#define PHYCNT_OCT (0x1 << 20) ++#define PHYCNT_DDRCAL (0x1 << 19) ++#define PHYCNT_HS (0x1 << 18) ++#define PHYCNT_STREAM_MASK (0x7 << 15) ++#define PHYCNT_STREAM(o) (((o) & 0x7) << 15) ++#define PHYCNT_WBUF2 (0x1 << 4) ++#define PHYCNT_WBUF (0x1 << 2) ++#define PHYCNT_PHYMEM_MASK (0x3) ++ ++/* SMCR */ ++#define SMCR_SSLKP (0x1 << 8) ++#define SMCR_SPIRE (0x1 << 2) ++#define SMCR_SPIWE (0x1 << 1) ++#define SMCR_SPIE (0x1) ++ ++/* CMNSR */ ++#define CMNSR_TEND (0x1 << 0) ++ ++/* SSLDR */ ++#define SSLDR_SPNDL(v) (((v) & 0x7) << 16) ++#define SSLDR_SLNDL(v) ((((v) | 0x4) & 0x7) << 8) ++#define SSLDR_SCKDL(v) ((v) & 0x7) ++ ++/* DREAR */ ++#define DREAR_EAV_MASK (0xff << 16) ++#define DREAR_EAV(v) (((v) & 0xff) << 16) ++#define DREAR_EAC_MASK (0x7) ++#define DREAR_24B (0) ++#define DREAR_25B (1) ++ ++/* DRENR */ ++#define DRENR_CDB_MASK (0x03 << 30) ++#define DRENR_CDB(v) (((v) & 0x3) << 30) ++#define DRENR_CDB_1B (0) ++#define DRENR_CDB_2B (0x1 << 30) ++#define DRENR_CDB_4B (0x2 << 30) ++#define DRENR_OCDB_MASK (0x03 << 28) ++#define DRENR_OCDB_1B (0) ++#define DRENR_OCDB_2B (0x1 << 28) ++#define DRENR_OCDB_4B (0x2 << 28) ++#define DRENR_ADB_MASK (0x03 << 24) ++#define DRENR_ADB(v) (((v) & 0x3) << 24) ++#define DRENR_ADB_1B (0) ++#define DRENR_ADB_2B (0x1 << 24) ++#define DRENR_ADB_4B (0x2 << 24) ++#define DRENR_OPDB_MASK (0x03 << 20) ++#define DRENR_OPDB_1B (0) ++#define DRENR_OPDB_2B (0x1 << 20) ++#define DRENR_OPDB_4B (0x2 << 20) ++#define DRENR_DRDB_MASK (0x03 << 16) ++#define DRENR_DRDB(v) (((v) & 0x3) << 16) ++#define DRENR_DRDB_1B (0) ++#define DRENR_DRDB_2B (0x1 << 16) ++#define DRENR_DRDB_4B (0x2 << 16) ++#define DRENR_OPDE_MASK (0xf << 4) ++#define DRENR_OPDE_DISABLE (0) ++#define DRENR_OPDE3 (0x8 << 4) ++#define DRENR_OPDE32 (0xC << 4) ++#define DRENR_OPDE321 (0xE << 4) ++#define DRENR_OPDE3210 (0xF << 4) ++#define DRENR_DME (1<<15) ++#define DRENR_CDE (1<<14) ++#define DRENR_OCDE (1<<12) ++#define DRENR_ADE_MASK (0xf << 8) ++#define DRENR_ADE_DISABLE (0) ++#define DRENR_ADE_23_0 (0x7 << 8) ++#define DRENR_ADE_31_0 (0xf << 8) ++ ++/* DRCMR */ ++#define DRCMR_CMD(cmd) (((cmd) & 0xff) << 16) ++#define DRCMR_CMD_MASK (0xff << 16) ++#define DRCMR_OCMD(cmd) (((cmd) & 0xff)) ++#define DRCMR_OCMD_MASK (0xff) ++ ++/* DRCMR */ ++#define DRDMCR_DMCYC(v) ((v) & 0x1f) ++#define DRDMCR_DMCYC_MASK (0x1f) ++ ++/* SMDMCR */ ++#define SMDMCR_DMCYC(v) ((v) & 0x0f) ++#define SMDMCR_DMCYC_MASK (0x0f) ++ ++/* PHYOFFSET1 */ ++#define PHYOFFSET1_DDRTMG (1 << 28) ++ ++/* DIVREG */ ++#define DIVREG_RATIO_MASK (0x03) ++#define DIVREG_RATIO(v) ((v) & 0x03) ++#define DIVREG_RATIO_MAX (0x2) ++ ++ ++#define DEFAULT_TO (100) ++#define WRITE_BUF_SIZE (0x100) ++#define WRITE_BUF_ADR_MASK (0xff) ++ ++#define REPEAT_MAX (20) ++#define REPEAT_TIME (10) ++ ++struct rpc_spi { ++ struct platform_device *pdev; ++ void __iomem *base; ++ void __iomem *read_area; ++ void __iomem *write_area; ++ struct clk *clk; ++ unsigned int irq; ++ struct spi_nor spi_nor; ++ ++#define MTD_QSPI_1x 0 ++#define MTD_QSPI_2x 1 ++ ++ u32 mtdtype; ++}; ++ ++/* IP block use it's own clock divigion register */ ++#define OWN_CLOCK_DIVIDER BIT(0) ++ ++/* debug */ ++static void __maybe_unused regs_dump(struct rpc_spi *rpc) ++{ ++ static u32 regs[] = { ++ CMNCR, SSLDR, DRCR, DRCMR, DREAR, ++ DROPR, DRENR, SMCR, SMCMR, SMADR, ++ SMOPR, SMENR, SMRDR0, SMRDR1, SMWDR0, ++ SMWDR1, CMNSR, DRDMCR, DRDRENR, SMDMCR, ++ SMDRENR, PHYCNT, PHYOFFSET1, PHYOFFSET2, ++ PHYINT ++ }; ++ ++ static const char *const names[] = { ++ "CMNCR", "SSLDR", "DRCR", "DRCMR", "DREAR", ++ "DROPR", "DRENR", "SMCR", "SMCMR", "SMADR", ++ "SMOPR", "SMENR", "SMRDR0", "SMRDR1", "SMWDR0", ++ "SMWDR1", "CMNSR", "DRDMCR", "DRDRENR", "SMDMCR", ++ "SMDRENR", "PHYCNT", "PHYOFFSET1", "PHYOFFSET2", ++ "PHYINT" ++ }; ++ ++ int i; ++ ++ dev_dbg(&rpc->pdev->dev, "RPC regs dump:\n"); ++ for (i = 0; i < ARRAY_SIZE(regs); i++) ++ dev_dbg(&rpc->pdev->dev, "%s = 0x%08x\n", names[i], ++ readl(rpc->base + regs[i])); ++} ++ ++/* register acces */ ++static u32 rpc_read(struct rpc_spi *rpc, unsigned int reg) ++{ ++ u32 val; ++ ++ val = readl(rpc->base + reg); ++ return val; ++} ++ ++static void rpc_write(struct rpc_spi *rpc, unsigned int reg, u32 val) ++{ ++ writel(val, rpc->base + reg); ++} ++ ++static int rpc_wait(struct rpc_spi *rpc, u32 to) ++{ ++ u32 val; ++ int i; ++ ++ for (i = 0; i < to; i++) { ++ val = rpc_read(rpc, CMNSR); ++ val &= CMNSR_TEND; ++ if (val) ++ break; ++ ++ udelay(100); ++ } ++ ++ if (i == to) { ++ dev_err(&rpc->pdev->dev, "timeout waiting for operation end %d\n", ++ rpc_read(rpc, CMNSR)); ++ return -ETIMEDOUT; ++ } ++ ++ return 0; ++} ++ ++static int rpc_setup_clk_ratio(struct rpc_spi *rpc, u32 max_clk_rate) ++{ ++ unsigned long rate = clk_get_rate(rpc->clk); ++ u32 ratio; ++ u32 val; ++ ++ ratio = DIV_ROUND_UP(rate, max_clk_rate * 2) >> 1; ++ if (ratio > DIVREG_RATIO_MAX) ++ ratio = DIVREG_RATIO_MAX; ++ ++ val = rpc_read(rpc, DIV_REG); ++ val &= DIVREG_RATIO_MASK; ++ val |= DIVREG_RATIO(ratio); ++ rpc_write(rpc, DIV_REG, val); ++ ++ return 0; ++} ++ ++static int rpc_endisable_write_buf(struct rpc_spi *rpc, bool en) ++{ ++ u32 val; ++ ++ val = rpc_read(rpc, PHYCNT); ++ ++ if (en) ++ val |= PHYCNT_WBUF | PHYCNT_WBUF2; ++ else ++ val &= ~(PHYCNT_WBUF | PHYCNT_WBUF2); ++ ++ rpc_write(rpc, PHYCNT, val); ++ ++ return 0; ++} ++ ++static int rpc_begin(struct rpc_spi *rpc, ++ bool rx, bool tx, bool last) ++{ ++ u32 val = SMCR_SPIE; ++ ++ if (rx) ++ val |= SMCR_SPIRE; ++ ++ if (tx) ++ val |= SMCR_SPIWE; ++ ++ if (!last) ++ val |= SMCR_SSLKP; ++ ++ rpc_write(rpc, SMCR, val); ++ ++ return 0; ++} ++ ++static int rpc_setup_reg_mode(struct rpc_spi *rpc) ++{ ++ u32 val; ++ ++ rpc_wait(rpc, DEFAULT_TO); ++ ++ rpc_endisable_write_buf(rpc, false); ++ ++ /* ...setup manual mode */ ++ val = rpc_read(rpc, CMNCR); ++ val |= CMNCR_MD; ++ rpc_write(rpc, CMNCR, val); ++ ++ /* disable ddr */ ++ val = rpc_read(rpc, SMDRENR); ++ val &= ~(SMDRENR_ADDRE | SMDRENR_OPDRE | SMDRENR_SPIDRE); ++ rpc_write(rpc, SMDRENR, val); ++ ++ /* enable 1bit command */ ++ val = rpc_read(rpc, SMENR); ++ val &= ~(SMENR_CDB_MASK | SMENR_OCDB_MASK | SMENR_DME ++ | SMENR_OCDE | SMENR_SPIDB_MASK ++ | SMENR_ADE_MASK | SMENR_ADB_MASK ++ | SMENR_OPDE_MASK | SMENR_SPIDE_MASK); ++ val |= SMENR_CDB_1B | SMENR_CDE | SMENR_SPIDE_32B; ++ rpc_write(rpc, SMENR, val); ++ ++ ++ return 0; ++} ++ ++static void rpc_flush_cache(struct rpc_spi *rpc) ++{ ++ u32 val; ++ ++ val = rpc_read(rpc, DRCR); ++ val |= DRCR_RCF; ++ rpc_write(rpc, DRCR, val); ++} ++ ++static int rpc_setup_ext_mode(struct rpc_spi *rpc) ++{ ++ u32 val; ++ u32 cmncr; ++ ++ rpc_wait(rpc, DEFAULT_TO); ++ ++ rpc_endisable_write_buf(rpc, false); ++ ++ /* ...setup ext mode */ ++ val = rpc_read(rpc, CMNCR); ++ cmncr = val; ++ val &= ~(CMNCR_MD); ++ rpc_write(rpc, CMNCR, val); ++ ++ /* ...enable burst and clear cache */ ++ val = rpc_read(rpc, DRCR); ++ val &= ~(DRCR_RBURST_MASK | DRCR_RBE | DRCR_SSLE); ++ val |= DRCR_RBURST(0x1f) | DRCR_RBE; ++ ++ if (cmncr & CMNCR_MD) ++ val |= DRCR_RCF; ++ ++ rpc_write(rpc, DRCR, val); ++ ++ return 0; ++} ++ ++static int rpc_setup_data_size(struct rpc_spi *rpc, u32 size, bool copy) ++{ ++ u32 val; ++ ++ val = rpc_read(rpc, SMENR); ++ val &= ~(SMENR_SPIDE_MASK); ++ ++ if (rpc->mtdtype == MTD_QSPI_2x && !copy) ++ size >>= 1; ++ ++ switch (size) { ++ case 0: ++ break; ++ case 1: ++ val |= SMENR_SPIDE_8B; ++ break; ++ case 2: ++ val |= SMENR_SPIDE_16B; ++ break; ++ case 4: ++ val |= SMENR_SPIDE_32B; ++ break; ++ default: ++ dev_err(&rpc->pdev->dev, "Unsupported data width %d\n", size); ++ return -EINVAL; ++ } ++ rpc_write(rpc, SMENR, val); ++ ++ return 0; ++} ++ ++static int rpc_setup_extmode_read_addr(struct rpc_spi *rpc, ++ int adr_width, loff_t adr) ++{ ++ u32 val; ++ u32 v; ++ ++ val = rpc_read(rpc, DREAR); ++ val &= ~(DREAR_EAV_MASK | DREAR_EAC_MASK); ++ ++ if (adr_width == 4) { ++ v = adr >> 25; ++ val |= DREAR_EAV(v) | DREAR_25B; ++ } ++ rpc_write(rpc, DREAR, val); ++ ++ val = rpc_read(rpc, DRENR); ++ val &= ~(DRENR_ADE_MASK); ++ if (adr_width == 4) ++ val |= DRENR_ADE_31_0; ++ else ++ val |= DRENR_ADE_23_0; ++ rpc_write(rpc, DRENR, val); ++ ++ return 0; ++} ++ ++static inline int rpc_get_read_addr_nbits(u8 opcode) ++{ ++ if (opcode == SPINOR_OP_READ_1_4_4_4B) ++ return 4; ++ return 1; ++} ++ ++#define NBITS_TO_VAL(v) ((v >> 1) & 3) ++static int rpc_setup_extmode_nbits(struct rpc_spi *rpc, int cnb, ++ int anb, int dnb) ++{ ++ u32 val; ++ ++ val = rpc_read(rpc, DRENR); ++ val &= ~(DRENR_CDB_MASK | DRENR_ADB_MASK | DRENR_DRDB_MASK); ++ val |= DRENR_CDB(NBITS_TO_VAL(cnb)) ++ | DRENR_ADB(NBITS_TO_VAL(anb)) ++ | DRENR_DRDB(NBITS_TO_VAL(dnb)); ++ rpc_write(rpc, DRENR, val); ++ ++ return 0; ++} ++ ++static int rpc_setup_writemode_nbits(struct rpc_spi *rpc, int cnb, ++ int anb, int dnb) ++{ ++ u32 val; ++ ++ val = rpc_read(rpc, SMENR); ++ val &= ~(SMENR_CDB_MASK | SMENR_ADB_MASK | SMENR_SPIDB_MASK); ++ val |= SMENR_CDB(NBITS_TO_VAL(cnb)) ++ | SMENR_ADB(NBITS_TO_VAL(anb)) ++ | SMENR_SPIDB(NBITS_TO_VAL(dnb)); ++ rpc_write(rpc, SMENR, val); ++ ++ return 0; ++} ++ ++static void rpc_setup_write_mode_command_and_adr(struct rpc_spi *rpc, ++ int adr_width, bool ena) ++{ ++ u32 val; ++ ++ val = rpc_read(rpc, SMENR); ++ val &= ~(SMENR_CDB_MASK | SMENR_CDE | SMENR_ADE_MASK); ++ ++ if (ena) { ++ /* enable 1bit command */ ++ val |= SMENR_CDB_1B | SMENR_CDE; ++ ++ if (adr_width == 4) ++ val |= SMENR_ADE_31_0; ++ else ++ val |= SMENR_ADE_23_0; ++ } ++ rpc_write(rpc, SMENR, val); ++} ++ ++static int rpc_setup_write_mode(struct rpc_spi *rpc) ++{ ++ u32 val; ++ ++ rpc_wait(rpc, DEFAULT_TO); ++ ++ rpc_endisable_write_buf(rpc, true); ++ ++ /* ...setup manual mode */ ++ val = rpc_read(rpc, CMNCR); ++ val |= CMNCR_MD; ++ rpc_write(rpc, CMNCR, val); ++ ++ /* disable ddr */ ++ val = rpc_read(rpc, SMDRENR); ++ val &= ~(SMDRENR_ADDRE | SMDRENR_OPDRE | SMDRENR_SPIDRE); ++ rpc_write(rpc, SMDRENR, val); ++ ++ val = rpc_read(rpc, SMENR); ++ val &= ~(SMENR_OCDB_MASK | SMENR_DME | SMENR_OCDE | SMENR_SPIDB_MASK ++ | SMENR_ADB_MASK | SMENR_OPDE_MASK | SMENR_SPIDE_MASK); ++ val |= SMENR_SPIDE_32B; ++ rpc_write(rpc, SMENR, val); ++ ++ return 0; ++} ++ ++static void rpc_read_manual_data(struct rpc_spi *rpc, u32 *pv0, u32 *pv1) ++{ ++ u32 val0, val1, rd0, rd1; ++ ++ val0 = rpc_read(rpc, SMRDR0); ++ val1 = rpc_read(rpc, SMRDR1); ++ ++ if (rpc->mtdtype == MTD_QSPI_2x) { ++ rd1 = (val0 & 0xff000000) | ((val0 << 8) & 0xff0000) | ++ ((val1 >> 16) & 0xff00) | ((val1 >> 8) & 0xff); ++ rd0 = ((val0 & 0xff0000) << 8) | ((val0 << 16) & 0xff0000) | ++ ((val1 >> 8) & 0xff00) | (val1 & 0xff); ++ } else ++ rd0 = val0; ++ ++ if (pv0) ++ *pv0 = rd0; ++ ++ if (pv1 && rpc->mtdtype == MTD_QSPI_2x) ++ *pv1 = rd1; ++} ++ ++static int rpc_datalen2trancfersize(struct rpc_spi *rpc, int len, bool copy) ++{ ++ int sz = len; ++ ++ if (len >= 2) ++ sz = 2; ++ ++ if (len >= 4) ++ sz = 4; ++ ++ if (rpc->mtdtype == MTD_QSPI_2x && len >= 8 && !copy) ++ sz = 8; ++ ++ return sz; ++} ++ ++static int __rpc_write_data2reg(struct rpc_spi *rpc, int off, ++ const u8 *buf, int sz) ++{ ++ const u32 *b32 = (const u32 *)buf; ++ const u16 *b16 = (const u16 *)buf; ++ ++ if (sz == 4) ++ rpc_write(rpc, off, *b32); ++ else if (sz == 2) ++ writew(*b16, rpc->base + off); ++ else if (sz == 1) ++ writeb(*buf, rpc->base + off); ++ else if (sz != 0) { ++ dev_err(&rpc->pdev->dev, "incorrect data size %d\n", sz); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++#define __SETVAL(x) ((((x) & 0xff) << 8) | ((x) & 0xff)) ++static int rpc_write_data2reg(struct rpc_spi *rpc, const u8 *buf, ++ int sz, bool copy) ++{ ++ int i, ret; ++ u32 v = 0; ++ ++ if (rpc->mtdtype == MTD_QSPI_2x) { ++ if (copy) { ++ for (i = 0; i < sz && i < 2; i++) ++ v |= (__SETVAL(buf[i]) << 16*i); ++ ++ ret = __rpc_write_data2reg(rpc, ++ sz == 4 ? SMWDR1 : SMWDR0, ++ (u8 *)&v, ++ sz == 4 ? sz : sz * 2); ++ if (ret) ++ return ret; ++ ++ v = 0; ++ for (; i < sz; i++) ++ v |= (__SETVAL(buf[i]) << 16*i); ++ ++ ++ ret = __rpc_write_data2reg(rpc, ++ sz == 4 ? SMWDR0 : SMWDR1, ++ (u8 *)&v, ++ sz == 4 ? sz : sz * 2); ++ if (ret) ++ return ret; ++ ++ return 0; ++ } ++ ++ sz >>= 1; ++ ret = __rpc_write_data2reg(rpc, ++ sz == 4 ? SMWDR1 : SMWDR0, ++ buf, ++ sz == 4 ? sz : sz * 2); ++ if (ret) ++ return ret; ++ buf += sz; ++ ++ return __rpc_write_data2reg(rpc, ++ sz == 4 ? SMWDR0 : SMWDR1, ++ buf, sz == 4 ? sz : sz * 2); ++ } ++ ++ return __rpc_write_data2reg(rpc, SMWDR0, buf, sz); ++} ++ ++static ssize_t rpc_write_unaligned(struct spi_nor *nor, loff_t to, size_t len, ++ const u_char *buf, size_t fullen) ++{ ++ int ret = len, dsize; ++ struct rpc_spi *rpc = nor->priv; ++ bool copy = false, last; ++ loff_t _to; ++ ++ rpc_endisable_write_buf(rpc, false); ++ ++ while (len > 0) { ++ _to = to; ++ if (rpc->mtdtype == MTD_QSPI_2x) ++ _to >>= 1; ++ rpc_write(rpc, SMADR, _to); ++ dsize = rpc_datalen2trancfersize(rpc, len, copy); ++ ++ if (rpc_setup_data_size(rpc, dsize, copy)) ++ return -EINVAL; ++ ++ rpc_write_data2reg(rpc, buf, dsize, copy); ++ ++ last = (len <= dsize && fullen <= ret); ++ rpc_begin(rpc, false, true, last); ++ if (rpc_wait(rpc, DEFAULT_TO)) ++ return -ETIMEDOUT; ++ ++ /* ...disable command */ ++ rpc_setup_write_mode_command_and_adr(rpc, ++ nor->addr_width, false); ++ ++ buf += dsize; ++ len -= dsize; ++ to += dsize; ++ } ++ ++ return ret; ++} ++ ++static ssize_t rpc_write_flash(struct spi_nor *nor, loff_t to, size_t len, ++ const u_char *buf) ++{ ++ ssize_t res = len, full = len; ++ u32 val; ++ u8 rval[2]; ++ struct rpc_spi *rpc = nor->priv; ++ loff_t bo; ++ loff_t offset; ++ bool is_rounded = false; ++ ++ /* ...len should be rounded to 2 bytes */ ++ if (rpc->mtdtype == MTD_QSPI_2x && (len & 1)) { ++ is_rounded = true; ++ len &= ~(1); ++ } ++ ++ bo = to & (WRITE_BUF_ADR_MASK); ++ ++ rpc_flush_cache(rpc); ++ rpc_setup_write_mode(rpc); ++ rpc_setup_write_mode_command_and_adr(rpc, nor->addr_width, true); ++ rpc_setup_writemode_nbits(rpc, 1, 1, 1); ++ ++ /* ...setup command */ ++ val = rpc_read(rpc, SMCMR); ++ val &= ~(SMCMR_CMD_MASK); ++ val |= SMCMR_CMD(nor->program_opcode); ++ rpc_write(rpc, SMCMR, val); ++ ++ offset = (to & (~WRITE_BUF_ADR_MASK)); ++ ++ /* ...write unaligned first bytes */ ++ if (bo) { ++ size_t min = (len < (WRITE_BUF_SIZE - bo)) ? len : (WRITE_BUF_SIZE - bo); ++ ++ rpc_write_unaligned(nor, to, min, buf, full); ++ rpc_setup_write_mode(rpc); ++ ++ len -= min; ++ buf += min; ++ to += min; ++ full -= min; ++ } ++ ++ /* ++ * TODO: Unfortunately RPC does not write properly in write buf mode ++ * without transferring command. Investigate this. ++ */ ++ ++ if (len) { ++ rpc_write_unaligned(nor, to, len, buf, full); ++ buf += len; ++ to += len; ++ full -= len; ++ len = 0; ++ } ++ ++ if (is_rounded) { ++ rval[0] = *buf; ++ rval[1] = 0xFF; ++ rpc_write_unaligned(nor, to, 2, rval, full); ++ } ++ ++ rpc_flush_cache(rpc); ++ ++ return res; ++} ++ ++static inline unsigned int rpc_rx_nbits(struct spi_nor *nor) ++{ ++ return spi_nor_get_protocol_data_nbits(nor->read_proto); ++} ++ ++#define READ_ADR_MASK (BIT(26) - 1) ++static ssize_t rpc_read_flash(struct spi_nor *nor, loff_t from, size_t len, ++ u_char *buf) ++{ ++ u32 val; ++ struct rpc_spi *rpc = nor->priv; ++ int adr_width = nor->addr_width; ++ int opcode_nbits = 1; ++ int addr_nbits = rpc_get_read_addr_nbits(nor->read_opcode); ++ int data_nbits = rpc_rx_nbits(nor); ++ int dummy = nor->read_dummy - 1; ++ ssize_t ret = len; ++ ssize_t readlen; ++ loff_t _from; ++ ++ rpc_setup_ext_mode(rpc); ++ /* ...setup n bits */ ++ rpc_setup_extmode_nbits(rpc, opcode_nbits, addr_nbits, data_nbits); ++ ++ /* TODO: setup DDR */ ++ ++ /* ...setup command */ ++ val = rpc_read(rpc, DRCMR); ++ val &= ~(DRCMR_CMD_MASK); ++ val |= DRCMR_CMD(nor->read_opcode); ++ rpc_write(rpc, DRCMR, val); ++ ++ /* ...setup dummy cycles */ ++ val = rpc_read(rpc, DRDMCR); ++ val &= ~(DRDMCR_DMCYC_MASK); ++ val |= DRDMCR_DMCYC(dummy); ++ rpc_write(rpc, DRDMCR, val); ++ ++ /* ...setup read sequence */ ++ val = rpc_read(rpc, DRENR); ++ val |= DRENR_DME | DRENR_CDE; ++ rpc_write(rpc, DRENR, val); ++ ++ while (len > 0) { ++ /* ...setup address */ ++ rpc_setup_extmode_read_addr(rpc, adr_width, from); ++ /* ...use adr [25...0] */ ++ _from = from & READ_ADR_MASK; ++ ++ readlen = READ_ADR_MASK - _from + 1; ++ readlen = readlen > len ? len : readlen; ++ ++ memcpy_fromio(buf, rpc->read_area + _from, readlen); ++ buf += readlen; ++ from += readlen; ++ len -= readlen; ++ } ++ ++ return ret; ++} ++ ++static int __rpc_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) ++{ ++ u32 val; ++ u32 val2 = 0; ++ u32 *buf32; ++ int i; ++ u32 mask = 0, type; ++ struct rpc_spi *rpc = nor->priv; ++ ++ type = rpc->mtdtype; ++ ++ rpc_setup_reg_mode(rpc); ++ val = rpc_read(rpc, SMCMR); ++ val &= ~(SMCMR_CMD_MASK); ++ val |= SMCMR_CMD(opcode); ++ rpc_write(rpc, SMCMR, val); ++ ++ rpc_begin(rpc, true, false, len <= 4); ++ if (rpc_wait(rpc, DEFAULT_TO)) ++ return -ETIMEDOUT; ++ ++ /* ...disable command */ ++ val = rpc_read(rpc, SMENR); ++ val &= ~(SMENR_CDE); ++ rpc_write(rpc, SMENR, val); ++ ++ buf32 = (u32 *)buf; ++ ++ while (len > 0) { ++ rpc_read_manual_data(rpc, &val, &val2); ++ ++ if (mask) { ++ dev_warn(&rpc->pdev->dev, ++ "Using mask workaround (0x%x)\n", mask); ++ val &= ~(mask); ++ val2 &= ~(mask); ++ } ++ ++ /* ... spi flashes should be the same */ ++ if (type == MTD_QSPI_2x && val != val2) { ++ /* clear cs */ ++ rpc_begin(rpc, true, false, true); ++ return -EAGAIN; ++ } ++ ++ if (len > 4) { ++ *buf32 = val; ++ buf32++; ++ len -= 4; ++ } else { ++ buf = (u8 *)buf32; ++ for (i = 0; i < len; i++) { ++ *buf = (val >> (8 * i)) & 0x000000ff; ++ buf++; ++ } ++ len = 0; ++ } ++ ++ if (!len) ++ break; ++ ++ mask = 0xff; ++ ++ rpc_begin(rpc, true, false, len <= 4); ++ if (rpc_wait(rpc, DEFAULT_TO)) ++ return -ETIMEDOUT; ++ ++ } ++ ++ return 0; ++} ++ ++static int rpc_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) ++{ ++ int i, ret; ++ ++ /* A few read commands like read status can ++ * generate different answers. We repeat reading ++ * in that case ++ */ ++ for (i = 0; i < REPEAT_MAX; i++) { ++ ret = __rpc_read_reg(nor, opcode, buf, len); ++ if (!ret || ret != -EAGAIN) ++ break; ++ mdelay(REPEAT_TIME); ++ } ++ ++ return ret; ++} ++ ++static int rpc_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) ++{ ++ struct rpc_spi *rpc = nor->priv; ++ u32 val; ++ int dsize; ++ bool copy = true; ++ ++ rpc_setup_reg_mode(rpc); ++ ++ val = rpc_read(rpc, SMCMR); ++ val &= ~(SMCMR_CMD_MASK); ++ val |= SMCMR_CMD(opcode); ++ rpc_write(rpc, SMCMR, val); ++ ++ dsize = rpc_datalen2trancfersize(rpc, len, copy); ++ ++ if (rpc_setup_data_size(rpc, dsize, copy)) ++ return -EINVAL; ++ ++ if (rpc_write_data2reg(rpc, buf, dsize, copy)) ++ return -EINVAL; ++ buf += dsize; ++ len -= dsize; ++ rpc_begin(rpc, false, dsize > 0, len == 0); ++ ++ if (rpc_wait(rpc, DEFAULT_TO)) ++ return -ETIMEDOUT; ++ ++ /* ...disable command */ ++ val = rpc_read(rpc, SMENR); ++ val &= ~(SMENR_CDE); ++ rpc_write(rpc, SMENR, val); ++ ++ while (len > 0) { ++ dsize = rpc_datalen2trancfersize(rpc, len, copy); ++ if (rpc_setup_data_size(rpc, dsize, copy)) ++ return -EINVAL; ++ rpc_write_data2reg(rpc, buf, dsize, copy); ++ buf += dsize; ++ len -= dsize; ++ ++ rpc_begin(rpc, false, dsize, len == 0); ++ ++ if (rpc_wait(rpc, DEFAULT_TO)) ++ return -ETIMEDOUT; ++ ++ } ++ ++ return 0; ++} ++ ++/* hw init for spi-nor flashes */ ++static int rpc_hw_init_1x2x(struct rpc_spi *rpc) ++{ ++ u32 val; ++ ++ /* Exec calibration */ ++ val = rpc_read(rpc, PHYCNT); ++ val &= ~(PHYCNT_OCTA_MASK | PHYCNT_EXDS | PHYCNT_OCT ++ | PHYCNT_DDRCAL | PHYCNT_HS | PHYCNT_STREAM_MASK ++ | PHYCNT_WBUF2 | PHYCNT_WBUF | PHYCNT_PHYMEM_MASK); ++ val |= (PHYCNT_CAL) | PHYCNT_STREAM(6); ++ rpc_write(rpc, PHYCNT, val); ++ ++ /* disable rpc_* pins */ ++ val = rpc_read(rpc, PHYINT); ++ val &= ~((1<<24) | (7<<16)); ++ rpc_write(rpc, PHYINT, val); ++ ++ val = rpc_read(rpc, SMDRENR); ++ val &= ~(SMDRENR_HYPE_MASK); ++ val |= SMDRENR_HYPE_SPI_FLASH; ++ rpc_write(rpc, SMDRENR, val); ++ ++ val = rpc_read(rpc, CMNCR); ++ val &= ~(CMNCR_BSZ_MASK); ++ if (rpc->mtdtype != MTD_QSPI_1x) ++ val |= CMNCR_BSZ_4x2; ++ rpc_write(rpc, CMNCR, val); ++ ++ val = rpc_read(rpc, PHYOFFSET1); ++ val |= PHYOFFSET1_DDRTMG; ++ rpc_write(rpc, PHYOFFSET1, val); ++ ++ val = SSLDR_SPNDL(0) | SSLDR_SLNDL(4) | SSLDR_SCKDL(0); ++ rpc_write(rpc, SSLDR, val); ++ ++ return 0; ++} ++ ++static int rpc_hw_init(struct rpc_spi *rpc) ++{ ++ switch (rpc->mtdtype) { ++ case MTD_QSPI_1x: ++ case MTD_QSPI_2x: ++ return rpc_hw_init_1x2x(rpc); ++ ++ default: ++ dev_err(&rpc->pdev->dev, "Unsupported connection mode\n"); ++ return -ENODEV; ++ } ++} ++ ++static int rpc_erase_sector(struct spi_nor *nor, loff_t addr) ++{ ++ struct rpc_spi *rpc = nor->priv; ++ u8 buf[6]; ++ int i; ++ ++ if (rpc->mtdtype == MTD_QSPI_2x) ++ addr >>= 1; ++ ++ for (i = nor->addr_width - 1; i >= 0; i--) { ++ buf[i] = addr & 0xff; ++ addr >>= 8; ++ } ++ ++ return nor->write_reg(nor, nor->erase_opcode, buf, nor->addr_width); ++} ++ ++static const struct of_device_id rpc_of_match[] = { ++ { .compatible = "renesas,qspi-rpc-r8a77980" }, ++ { .compatible = "renesas,qspi-rpc-r8a77970", .data = (void *)OWN_CLOCK_DIVIDER }, ++ { }, ++}; ++ ++MODULE_DEVICE_TABLE(of, rpc_of_match); ++ ++static int rpc_spi_probe(struct platform_device *pdev) ++{ ++ struct device_node *flash_np; ++ struct spi_nor *nor; ++ struct rpc_spi *rpc; ++ struct resource *res; ++ struct spi_nor_hwcaps hwcaps = { ++ .mask = SNOR_HWCAPS_READ | ++ SNOR_HWCAPS_READ_FAST | ++ SNOR_HWCAPS_PP, ++ }; ++ u32 max_clk_rate = 50000000; ++ u32 property; ++ int ret; ++ int own_clk; ++ ++ ++ flash_np = of_get_next_available_child(pdev->dev.of_node, NULL); ++ if (!flash_np) { ++ dev_err(&pdev->dev, "no SPI flash device to configure\n"); ++ return -ENODEV; ++ } ++ ++ if (!of_property_read_u32(flash_np, "spi-rx-bus-width", &property)) { ++ switch (property) { ++ case 1: ++ break; ++ case 2: ++ hwcaps.mask |= SNOR_HWCAPS_READ_DUAL; ++ break; ++ case 4: ++ hwcaps.mask |= SNOR_HWCAPS_READ_QUAD; ++ break; ++ default: ++ dev_err(&pdev->dev, "unsupported rx-bus-width\n"); ++ return -EINVAL; ++ } ++ } ++ ++ of_property_read_u32(flash_np, "spi-max-frequency", &max_clk_rate); ++ own_clk = (of_device_get_match_data(&pdev->dev) == (void *)OWN_CLOCK_DIVIDER); ++ ++ rpc = devm_kzalloc(&pdev->dev, sizeof(*rpc), GFP_KERNEL); ++ if (!rpc) ++ return -ENOMEM; ++ ++ rpc->pdev = pdev; ++ ++ /* ... setup nor hooks */ ++ nor = &rpc->spi_nor; ++ nor->dev = &pdev->dev; ++ spi_nor_set_flash_node(nor, flash_np); ++ nor->read = rpc_read_flash; ++ nor->write = rpc_write_flash; ++ nor->read_reg = rpc_read_reg; ++ nor->write_reg = rpc_write_reg; ++ nor->priv = rpc; ++ rpc->mtdtype = MTD_QSPI_1x; ++ ++ if (of_find_property(pdev->dev.of_node, "dual", NULL)) { ++ rpc->mtdtype = MTD_QSPI_2x; ++ nor->erase = rpc_erase_sector; ++ } ++ ++ /* ...get memory */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ rpc->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(rpc->base)) { ++ dev_err(&pdev->dev, "cannot get resources\n"); ++ ret = PTR_ERR(rpc->base); ++ goto error; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ ++ rpc->read_area = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(rpc->base)) { ++ dev_err(&pdev->dev, "cannot get resources\n"); ++ ret = PTR_ERR(rpc->base); ++ goto error; ++ } ++ ++ /* ...get memory */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 2); ++ rpc->write_area = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(rpc->base)) { ++ dev_err(&pdev->dev, "cannot get resources\n"); ++ ret = PTR_ERR(rpc->base); ++ goto error; ++ } ++ ++ /* ...get clk */ ++ rpc->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(rpc->clk)) { ++ dev_err(&pdev->dev, "cannot get clock\n"); ++ ret = PTR_ERR(rpc->clk); ++ goto error; ++ } ++ ++ /* ...set max clk rate */ ++ if (!own_clk) { ++ ret = clk_set_rate(rpc->clk, max_clk_rate); ++ if (ret) { ++ dev_err(&pdev->dev, "cannot set clock rate\n"); ++ goto error; ++ } ++ } ++ ++ /* ... enable clk */ ++ ret = clk_prepare_enable(rpc->clk); ++ if (ret) { ++ dev_err(&pdev->dev, "cannot prepare clock\n"); ++ goto error; ++ } ++ ++ /* ...init device */ ++ ret = rpc_hw_init(rpc); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "rpc_hw_init error.\n"); ++ goto error_clk_disable; ++ } ++ ++ /* ...set clk ratio */ ++ if (own_clk) { ++ ret = rpc_setup_clk_ratio(rpc, max_clk_rate); ++ if (ret) { ++ dev_err(&pdev->dev, "cannot set clock ratio\n"); ++ goto error; ++ } ++ } ++ ++ platform_set_drvdata(pdev, rpc); ++ ++ ret = spi_nor_scan(nor, NULL, &hwcaps); ++ if (ret) { ++ dev_err(&pdev->dev, "spi_nor_scan error.\n"); ++ goto error_clk_disable; ++ } ++ ++ /* Dual mode support */ ++ if (rpc->mtdtype == MTD_QSPI_2x) { ++ nor->page_size <<= 1; ++ nor->mtd.erasesize <<= 1; ++ nor->mtd.size <<= 1; ++ nor->mtd.writebufsize <<= 1; ++ } ++ ++ ret = mtd_device_register(&nor->mtd, NULL, 0); ++ if (ret) { ++ dev_err(&pdev->dev, "mtd_device_register error.\n"); ++ goto error_clk_disable; ++ } ++ ++ dev_info(&pdev->dev, "probed as %s\n", ++ rpc->mtdtype == MTD_QSPI_1x ? "single" : "dual"); ++ ++ return 0; ++ ++error_clk_disable: ++ clk_disable_unprepare(rpc->clk); ++error: ++ return ret; ++} ++ ++static int rpc_spi_remove(struct platform_device *pdev) ++{ ++ struct rpc_spi *rpc = platform_get_drvdata(pdev); ++ ++ /* HW shutdown */ ++ clk_disable_unprepare(rpc->clk); ++ mtd_device_unregister(&rpc->spi_nor.mtd); ++ return 0; ++} ++ ++/* platform driver interface */ ++static struct platform_driver rpc_platform_driver = { ++ .probe = rpc_spi_probe, ++ .remove = rpc_spi_remove, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "rpc", ++ .of_match_table = of_match_ptr(rpc_of_match), ++ }, ++}; ++ ++module_platform_driver(rpc_platform_driver); ++ ++MODULE_ALIAS("rpc"); ++MODULE_AUTHOR("Cogent Embedded Inc. "); ++MODULE_DESCRIPTION("Renesas RPC Driver"); ++MODULE_LICENSE("GPL"); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0366-mtd-spi-nor-renesas-rpc-Workaround-256-byte-data-siz.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0366-mtd-spi-nor-renesas-rpc-Workaround-256-byte-data-siz.patch new file mode 100644 index 00000000..e132f64f --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0366-mtd-spi-nor-renesas-rpc-Workaround-256-byte-data-siz.patch @@ -0,0 +1,35 @@ +From bc75cae7624f73ff866668793b4addd57228f5c2 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Thu, 15 Nov 2018 23:58:54 +0300 +Subject: [PATCH 186/211] mtd: spi-nor: renesas-rpc: Workaround 256-byte data + size limitation + +Looks like QSPI controller does not support page sizes more +than write buffer size. This limits maximum page size detected +by the spi_nor_scan() callback at the RPC write buffer size. + +Signed-off-by: Valentine Barshak +--- + drivers/mtd/spi-nor/renesas-rpc.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/mtd/spi-nor/renesas-rpc.c b/drivers/mtd/spi-nor/renesas-rpc.c +index b619a7e..af99762 100644 +--- a/drivers/mtd/spi-nor/renesas-rpc.c ++++ b/drivers/mtd/spi-nor/renesas-rpc.c +@@ -1225,6 +1225,12 @@ static int rpc_spi_probe(struct platform_device *pdev) + nor->mtd.writebufsize <<= 1; + } + ++ /* Workaround data size limitation */ ++ if (nor->page_size > WRITE_BUF_SIZE) { ++ nor->page_size = WRITE_BUF_SIZE; ++ nor->mtd.writebufsize = WRITE_BUF_SIZE; ++ } ++ + ret = mtd_device_register(&nor->mtd, NULL, 0); + if (ret) { + dev_err(&pdev->dev, "mtd_device_register error.\n"); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0367-mtd-spi-nor-Add-s25fs512s-and-s25fs128s-01-SPI-NOR-f.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0367-mtd-spi-nor-Add-s25fs512s-and-s25fs128s-01-SPI-NOR-f.patch new file mode 100644 index 00000000..e0e9bf29 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0367-mtd-spi-nor-Add-s25fs512s-and-s25fs128s-01-SPI-NOR-f.patch @@ -0,0 +1,37 @@ +From 30f4055ad0dd5f3331def3131405fdc20879b828 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Fri, 16 Nov 2018 00:01:22 +0300 +Subject: [PATCH 187/211] mtd: spi-nor: Add s25fs512s and s25fs128s[01] SPI NOR + flash support + +Add support for the "s25fs512s", "s25fs128s0", and "s25fs128s1" +SPI NOR flash chips. Update "s25fl512s" device info as well because +the difference between FS and FL devices is at JEDEC byte 5. + +This is based on the original patch by Dmitry Shifrin. + +Signed-off-by: Dmitry Shifrin +Signed-off-by: Valentine Barshak +--- + drivers/mtd/spi-nor/spi-nor.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c +index d458523..49ffc9a 100644 +--- a/drivers/mtd/spi-nor/spi-nor.c ++++ b/drivers/mtd/spi-nor/spi-nor.c +@@ -1057,7 +1057,10 @@ static const struct flash_info spi_nor_ids[] = { + { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, USE_CLSR) }, + { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, +- { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, ++ { "s25fl512s", INFO6(0x010220, 0x4d0080, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { "s25fs512s", INFO6(0x010220, 0x4d0081, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR | SECT_4K) }, ++ { "s25fs128s0", INFO6(0x012018, 0x4d0381, 256 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR | SECT_4K) }, ++ { "s25fs128s1", INFO6(0x012018, 0x4d0181, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR | SECT_4K) }, + { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, + { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, + { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0368-arm64-dts-renesas-r8a77970-Add-RPC-QSPI-node.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0368-arm64-dts-renesas-r8a77970-Add-RPC-QSPI-node.patch new file mode 100644 index 00000000..917875a3 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0368-arm64-dts-renesas-r8a77970-Add-RPC-QSPI-node.patch @@ -0,0 +1,41 @@ +From aa31c93e29d6e4dca93e167a97875cb225b062e4 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Fri, 16 Nov 2018 00:01:48 +0300 +Subject: [PATCH 188/211] arm64: dts: renesas: r8a77970: Add RPC QSPI node + +Add RPC QSPI device node. This is based +on the original patch by Dmitry Shifrin. + +Signed-off-by: Dmitry Shifrin +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970.dtsi | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +index 090122c..23422c7 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +@@ -767,6 +767,19 @@ + status = "disabled"; + }; + ++ qspi0: qspi@ee200000 { ++ compatible = "renesas,qspi-rpc-r8a77970"; ++ reg = <0 0xee200000 0 0x1f0>, ++ <0 0x08000000 0 0x04000000>, ++ <0 0xee208000 0 0x100>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 917>; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ + msiof0: spi@e6e90000 { + compatible = "renesas,msiof-r8a77970", + "renesas,rcar-gen3-msiof"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0369-arm64-dts-renesas-r8a77980-Add-RPC-QSPI-node.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0369-arm64-dts-renesas-r8a77980-Add-RPC-QSPI-node.patch new file mode 100644 index 00000000..ba242de3 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0369-arm64-dts-renesas-r8a77980-Add-RPC-QSPI-node.patch @@ -0,0 +1,41 @@ +From aaf5960d267e42b7bc1699e8e614c806723e263b Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Fri, 16 Nov 2018 00:02:16 +0300 +Subject: [PATCH 189/211] arm64: dts: renesas: r8a77980: Add RPC QSPI node + +Add RPC QSPI device node. This is based +on the original patch by Dmitry Shifrin. + +Signed-off-by: Dmitry Shifrin +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index c599814..688bc09 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -823,6 +823,19 @@ + status = "disabled"; + }; + ++ qspi0: qspi@ee200000 { ++ compatible = "renesas,qspi-rpc-r8a77980"; ++ reg = <0 0xee200000 0 0x1f0>, ++ <0 0x08000000 0 0x04000000>, ++ <0 0xee208000 0 0x100>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 917>; ++ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ + msiof0: spi@e6e90000 { + compatible = "renesas,msiof-r8a77980", + "renesas,rcar-gen3-msiof"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0370-arm64-dts-renesas-v3msk-Add-s25fs512s-QSPI-flash-nod.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0370-arm64-dts-renesas-v3msk-Add-s25fs512s-QSPI-flash-nod.patch new file mode 100644 index 00000000..4753e389 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0370-arm64-dts-renesas-v3msk-Add-s25fs512s-QSPI-flash-nod.patch @@ -0,0 +1,107 @@ +From d9c1db5efa52e0febebfdc351905501760d37454 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Fri, 16 Nov 2018 00:02:40 +0300 +Subject: [PATCH 190/211] arm64: dts: renesas: v3msk: Add s25fs512s QSPI flash + node + +Add s25fs512s QSPI flash node. This is based +on the original patch by Dmitry Shifrin. + +Signed-off-by: Dmitry Shifrin +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts | 72 ++++++++++++++++++++++++++ + 1 file changed, 72 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +index adc2b01..ef9a2c5 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +@@ -179,12 +179,84 @@ + power-source = <3300>; + }; + ++ qspi0_pins: qspi0 { ++ groups = "qspi0_ctrl", "qspi0_data4"; ++ function = "qspi0"; ++ }; ++ ++ qspi1_pins: qspi1 { ++ groups = "qspi1_ctrl", "qspi1_data4"; ++ function = "qspi1"; ++ }; ++ + scif0_pins: scif0 { + groups = "scif0_data"; + function = "scif0"; + }; + }; + ++&qspi0 { ++ pinctrl-0 = <&qspi0_pins &qspi1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ ++ flash@0 { ++ compatible = "spansion,s25fs512s", "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <50000000>; ++ spi-rx-bus-width = <4>; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ bootparam@0 { ++ reg = <0x00000000 0x040000>; ++ read-only; ++ }; ++ cr7@00040000 { ++ reg = <0x00040000 0x080000>; ++ read-only; ++ }; ++ cert_header_sa3@000C0000 { ++ reg = <0x000C0000 0x080000>; ++ read-only; ++ }; ++ bl2@00140000 { ++ reg = <0x00140000 0x040000>; ++ read-only; ++ }; ++ cert_header_sa6@00180000 { ++ reg = <0x00180000 0x040000>; ++ read-only; ++ }; ++ bl31@001C0000 { ++ reg = <0x001C0000 0x480000>; ++ read-only; ++ }; ++ uboot@00640000 { ++ reg = <0x00640000 0x0C0000>; ++ read-only; ++ }; ++ uboot-env@00700000 { ++ reg = <0x00700000 0x040000>; ++ read-only; ++ }; ++ dtb@00740000 { ++ reg = <0x00740000 0x080000>; ++ }; ++ kernel@007C0000 { ++ reg = <0x007C0000 0x1400000>; ++ }; ++ user@01BC0000 { ++ reg = <0x01BC0000 0x2440000>; ++ }; ++ }; ++ }; ++}; ++ + &i2c0 { + pinctrl-0 = <&i2c0_pins>; + pinctrl-names = "default"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0371-arm64-dts-renesas-v3mzf-Add-s25fs512s-QSPI-flash-nod.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0371-arm64-dts-renesas-v3mzf-Add-s25fs512s-QSPI-flash-nod.patch new file mode 100644 index 00000000..7eb94366 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0371-arm64-dts-renesas-v3mzf-Add-s25fs512s-QSPI-flash-nod.patch @@ -0,0 +1,104 @@ +From bad00e588837b41775c80fe9fa6ee999e398f462 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Fri, 16 Nov 2018 00:03:02 +0300 +Subject: [PATCH 191/211] arm64: dts: renesas: v3mzf: Add s25fs512s QSPI flash + node + +Add s25fs512s QSPI flash node. This is based +on the original patch by Dmitry Shifrin. + +Signed-off-by: Dmitry Shifrin +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970-v3mzf.dts | 68 ++++++++++++++++++++++++++ + 1 file changed, 68 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3mzf.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3mzf.dts +index 71a765a..caecf8c 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-v3mzf.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-v3mzf.dts +@@ -372,6 +372,16 @@ + function = "msiof3"; + }; + ++ qspi0_pins: qspi0 { ++ groups = "qspi0_ctrl", "qspi0_data4"; ++ function = "qspi0"; ++ }; ++ ++ qspi1_pins: qspi1 { ++ groups = "qspi1_ctrl", "qspi1_data4"; ++ function = "qspi1"; ++ }; ++ + scif0_pins: scif0 { + groups = "scif0_data"; + function = "scif0"; +@@ -389,6 +399,64 @@ + }; + }; + ++&qspi0 { ++ pinctrl-0 = <&qspi0_pins &qspi1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ ++ flash@0 { ++ compatible = "spansion,s25fs512s", "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <50000000>; ++ spi-rx-bus-width = <4>; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ bootparam@0 { ++ reg = <0x00000000 0x040000>; ++ read-only; ++ }; ++ cr7@00040000 { ++ reg = <0x00040000 0x080000>; ++ read-only; ++ }; ++ cert_header_sa3@000C0000 { ++ reg = <0x000C0000 0x080000>; ++ read-only; ++ }; ++ bl2@00140000 { ++ reg = <0x00140000 0x040000>; ++ read-only; ++ }; ++ cert_header_sa6@00180000 { ++ reg = <0x00180000 0x040000>; ++ read-only; ++ }; ++ bl31@001C0000 { ++ reg = <0x001C0000 0x480000>; ++ read-only; ++ }; ++ uboot@00640000 { ++ reg = <0x00640000 0x100000>; ++ read-only; ++ }; ++ dtb@00740000 { ++ reg = <0x00740000 0x080000>; ++ }; ++ kernel@007C0000 { ++ reg = <0x007C0000 0x1400000>; ++ }; ++ user@01BC0000 { ++ reg = <0x01BC0000 0x2440000>; ++ }; ++ }; ++ }; ++}; ++ + &scif0 { + pinctrl-0 = <&scif0_pins>; + pinctrl-names = "default"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0372-arm64-dts-renesas-eagle-Add-s25fs512s-QSPI-flash-nod.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0372-arm64-dts-renesas-eagle-Add-s25fs512s-QSPI-flash-nod.patch new file mode 100644 index 00000000..442aac6f --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0372-arm64-dts-renesas-eagle-Add-s25fs512s-QSPI-flash-nod.patch @@ -0,0 +1,107 @@ +From 7f2e7da3e400e1cccbe5886e4e3e22f16ed539c3 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Fri, 16 Nov 2018 00:03:20 +0300 +Subject: [PATCH 192/211] arm64: dts: renesas: eagle: Add s25fs512s QSPI flash + node + +Add s25fs512s QSPI flash node. This is based +on the original patch by Dmitry Shifrin. + +Signed-off-by: Dmitry Shifrin +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970-eagle.dts | 72 ++++++++++++++++++++++++++ + 1 file changed, 72 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +index b87f418..7d93834 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +@@ -404,12 +404,84 @@ + function = "i2c3"; + }; + ++ qspi0_pins: qspi0 { ++ groups = "qspi0_ctrl", "qspi0_data4"; ++ function = "qspi0"; ++ }; ++ ++ qspi1_pins: qspi1 { ++ groups = "qspi1_ctrl", "qspi1_data4"; ++ function = "qspi1"; ++ }; ++ + scif0_pins: scif0 { + groups = "scif0_data"; + function = "scif0"; + }; + }; + ++&qspi0 { ++ pinctrl-0 = <&qspi0_pins &qspi1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ ++ flash@0 { ++ compatible = "spansion,s25fs512s", "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <50000000>; ++ spi-rx-bus-width = <4>; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ bootparam@0 { ++ reg = <0x00000000 0x040000>; ++ read-only; ++ }; ++ cr7@00040000 { ++ reg = <0x00040000 0x080000>; ++ read-only; ++ }; ++ cert_header_sa3@000C0000 { ++ reg = <0x000C0000 0x080000>; ++ read-only; ++ }; ++ bl2@00140000 { ++ reg = <0x00140000 0x040000>; ++ read-only; ++ }; ++ cert_header_sa6@00180000 { ++ reg = <0x00180000 0x040000>; ++ read-only; ++ }; ++ bl31@001C0000 { ++ reg = <0x001C0000 0x480000>; ++ read-only; ++ }; ++ uboot@00640000 { ++ reg = <0x00640000 0x0C0000>; ++ read-only; ++ }; ++ uboot-env@00700000 { ++ reg = <0x00700000 0x040000>; ++ read-only; ++ }; ++ dtb@00740000 { ++ reg = <0x00740000 0x080000>; ++ }; ++ kernel@007C0000 { ++ reg = <0x007C0000 0x1400000>; ++ }; ++ user@01BC0000 { ++ reg = <0x01BC0000 0x2440000>; ++ }; ++ }; ++ }; ++}; ++ + &rwdt { + timeout-sec = <60>; + status = "okay"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0373-arm64-dts-renesas-v3hsk-Add-s25fs512s-QSPI-flash-nod.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0373-arm64-dts-renesas-v3hsk-Add-s25fs512s-QSPI-flash-nod.patch new file mode 100644 index 00000000..4c3fe0a9 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0373-arm64-dts-renesas-v3hsk-Add-s25fs512s-QSPI-flash-nod.patch @@ -0,0 +1,101 @@ +From 44f30278153ce5dc1de882117ebff3526a997d95 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Fri, 16 Nov 2018 00:03:36 +0300 +Subject: [PATCH 193/211] arm64: dts: renesas: v3hsk: Add s25fs512s QSPI flash + node + +Add s25fs512s QSPI flash node. This is based +on the original patch by Dmitry Shifrin. + +Signed-off-by: Dmitry Shifrin +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts | 72 ++++++++++++++++++++++++++ + 1 file changed, 72 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +index 0e0aed7..cfbfd98 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +@@ -251,6 +251,78 @@ + function = "mmc"; + power-source = <3300>; + }; ++ ++ qspi0_pins: qspi0 { ++ groups = "qspi0_ctrl", "qspi0_data4"; ++ function = "qspi0"; ++ }; ++ ++ qspi1_pins: qspi1 { ++ groups = "qspi1_ctrl", "qspi1_data4"; ++ function = "qspi1"; ++ }; ++}; ++ ++&qspi0 { ++ pinctrl-0 = <&qspi0_pins &qspi1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ ++ flash@0 { ++ compatible = "spansion,s25fs512s", "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <50000000>; ++ spi-rx-bus-width = <4>; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ bootparam@0 { ++ reg = <0x00000000 0x040000>; ++ read-only; ++ }; ++ cr7@00040000 { ++ reg = <0x00040000 0x080000>; ++ read-only; ++ }; ++ cert_header_sa3@000C0000 { ++ reg = <0x000C0000 0x080000>; ++ read-only; ++ }; ++ bl2@00140000 { ++ reg = <0x00140000 0x040000>; ++ read-only; ++ }; ++ cert_header_sa6@00180000 { ++ reg = <0x00180000 0x040000>; ++ read-only; ++ }; ++ bl31@001C0000 { ++ reg = <0x001C0000 0x480000>; ++ read-only; ++ }; ++ uboot@00640000 { ++ reg = <0x00640000 0x0C0000>; ++ read-only; ++ }; ++ uboot-env@00700000 { ++ reg = <0x00700000 0x040000>; ++ read-only; ++ }; ++ dtb@00740000 { ++ reg = <0x00740000 0x080000>; ++ }; ++ kernel@007C0000 { ++ reg = <0x007C0000 0x1400000>; ++ }; ++ user@01BC0000 { ++ reg = <0x01BC0000 0x2440000>; ++ }; ++ }; ++ }; + }; + + &rwdt { +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0374-arm64-dts-renesas-condor-Add-s25fs512s-QSPI-flash-no.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0374-arm64-dts-renesas-condor-Add-s25fs512s-QSPI-flash-no.patch new file mode 100644 index 00000000..22d2fcf6 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0374-arm64-dts-renesas-condor-Add-s25fs512s-QSPI-flash-no.patch @@ -0,0 +1,108 @@ +From 8ba13604f545465951c92f5f1d677eb10ff71dec Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Fri, 16 Nov 2018 00:03:54 +0300 +Subject: [PATCH 194/211] arm64: dts: renesas: condor: Add s25fs512s QSPI flash + node + +Add s25fs512s QSPI flash node. This is based +on the original patch by Dmitry Shifrin. + +Signed-off-by: Dmitry Shifrin +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980-condor.dts | 72 +++++++++++++++++++++++++ + 1 file changed, 72 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +index 577ff3a..6b5f574 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +@@ -629,6 +629,16 @@ + power-source = <1800>; + }; + ++ qspi0_pins: qspi0 { ++ groups = "qspi0_ctrl", "qspi0_data4"; ++ function = "qspi0"; ++ }; ++ ++ qspi1_pins: qspi1 { ++ groups = "qspi1_ctrl", "qspi1_data4"; ++ function = "qspi1"; ++ }; ++ + scif0_pins: scif0 { + groups = "scif0_data"; + function = "scif0"; +@@ -640,6 +650,68 @@ + }; + }; + ++&qspi0 { ++ pinctrl-0 = <&qspi0_pins &qspi1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ ++ flash@0 { ++ compatible = "spansion,s25fs512s", "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <50000000>; ++ spi-rx-bus-width = <4>; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ bootparam@0 { ++ reg = <0x00000000 0x040000>; ++ read-only; ++ }; ++ cr7@00040000 { ++ reg = <0x00040000 0x080000>; ++ read-only; ++ }; ++ cert_header_sa3@000C0000 { ++ reg = <0x000C0000 0x080000>; ++ read-only; ++ }; ++ bl2@00140000 { ++ reg = <0x00140000 0x040000>; ++ read-only; ++ }; ++ cert_header_sa6@00180000 { ++ reg = <0x00180000 0x040000>; ++ read-only; ++ }; ++ bl31@001C0000 { ++ reg = <0x001C0000 0x480000>; ++ read-only; ++ }; ++ uboot@00640000 { ++ reg = <0x00640000 0x0C0000>; ++ read-only; ++ }; ++ uboot-env@00700000 { ++ reg = <0x00700000 0x040000>; ++ read-only; ++ }; ++ dtb@00740000 { ++ reg = <0x00740000 0x080000>; ++ }; ++ kernel@007C0000 { ++ reg = <0x007C0000 0x1400000>; ++ }; ++ user@01BC0000 { ++ reg = <0x01BC0000 0x2440000>; ++ }; ++ }; ++ }; ++}; ++ + &rwdt { + timeout-sec = <60>; + status = "okay"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0375-mtd-spi-nor-renesas-rpc-Support-single-mode-write-co.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0375-mtd-spi-nor-renesas-rpc-Support-single-mode-write-co.patch new file mode 100644 index 00000000..6f0454ab --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0375-mtd-spi-nor-renesas-rpc-Support-single-mode-write-co.patch @@ -0,0 +1,61 @@ +From cfdd31e5cef09e255d42a39fe1171db7dfa9bd55 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Fri, 16 Nov 2018 00:04:14 +0300 +Subject: [PATCH 195/211] mtd: spi-nor: renesas: rpc: Support single mode write + command + +This adds single mode write command support. + +Signed-off-by: Andrey Gusakov +Signed-off-by: Valentine Barshak +--- + drivers/mtd/spi-nor/renesas-rpc.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/drivers/mtd/spi-nor/renesas-rpc.c b/drivers/mtd/spi-nor/renesas-rpc.c +index af99762..4cd50b1 100644 +--- a/drivers/mtd/spi-nor/renesas-rpc.c ++++ b/drivers/mtd/spi-nor/renesas-rpc.c +@@ -555,7 +555,7 @@ static void rpc_setup_write_mode_command_and_adr(struct rpc_spi *rpc, + rpc_write(rpc, SMENR, val); + } + +-static int rpc_setup_write_mode(struct rpc_spi *rpc) ++static int rpc_setup_write_mode(struct rpc_spi *rpc, u8 opcode) + { + u32 val; + +@@ -576,7 +576,11 @@ static int rpc_setup_write_mode(struct rpc_spi *rpc) + val = rpc_read(rpc, SMENR); + val &= ~(SMENR_OCDB_MASK | SMENR_DME | SMENR_OCDE | SMENR_SPIDB_MASK + | SMENR_ADB_MASK | SMENR_OPDE_MASK | SMENR_SPIDE_MASK); +- val |= SMENR_SPIDE_32B; ++ if (opcode != SPINOR_OP_PP) ++ val |= SMENR_SPIDE_32B; ++ else ++ val |= SMENR_SPIDE_8B; ++ + rpc_write(rpc, SMENR, val); + + return 0; +@@ -750,7 +754,7 @@ static ssize_t rpc_write_flash(struct spi_nor *nor, loff_t to, size_t len, + bo = to & (WRITE_BUF_ADR_MASK); + + rpc_flush_cache(rpc); +- rpc_setup_write_mode(rpc); ++ rpc_setup_write_mode(rpc, nor->program_opcode); + rpc_setup_write_mode_command_and_adr(rpc, nor->addr_width, true); + rpc_setup_writemode_nbits(rpc, 1, 1, 1); + +@@ -767,7 +771,7 @@ static ssize_t rpc_write_flash(struct spi_nor *nor, loff_t to, size_t len, + size_t min = (len < (WRITE_BUF_SIZE - bo)) ? len : (WRITE_BUF_SIZE - bo); + + rpc_write_unaligned(nor, to, min, buf, full); +- rpc_setup_write_mode(rpc); ++ rpc_setup_write_mode(rpc, nor->program_opcode); + + len -= min; + buf += min; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0376-mtd-spi-nor-renesas-rpc-Add-DMA-read-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0376-mtd-spi-nor-renesas-rpc-Add-DMA-read-support.patch new file mode 100644 index 00000000..4b17f99d --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0376-mtd-spi-nor-renesas-rpc-Add-DMA-read-support.patch @@ -0,0 +1,219 @@ +From 094ab0a4aaf8e0797ae51ea4cf7b84bb0b95dadf Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Fri, 16 Nov 2018 10:04:14 +0300 +Subject: [PATCH 196/211] mtd: spi-nor: renesas-rpc: Add DMA read support + +This adds DMA read support which can be disabled +by the "use_dma=0" module parameter. +Minimum DMA transfer size equals 8 RBURST chunks. +DMA transfer size is truncated to a multiple of +RBURST size. The remainder is left for the next +transfer iteration. + +Signed-off-by: Valentine Barshak +--- + drivers/mtd/spi-nor/renesas-rpc.c | 108 ++++++++++++++++++++++++++++++++++++-- + 1 file changed, 104 insertions(+), 4 deletions(-) + +diff --git a/drivers/mtd/spi-nor/renesas-rpc.c b/drivers/mtd/spi-nor/renesas-rpc.c +index 4cd50b1..0026b99 100644 +--- a/drivers/mtd/spi-nor/renesas-rpc.c ++++ b/drivers/mtd/spi-nor/renesas-rpc.c +@@ -14,6 +14,8 @@ + */ + + #include ++#include ++#include + #include + #include + #include +@@ -73,7 +75,7 @@ + #define DRCR_SSLE (0x1) + #define DRCR_RBE (0x1 << 8) + #define DRCR_RCF (0x1 << 9) +-#define DRCR_RBURST_32 (0x1f << 16) ++#define DRCR_RBURST_32 (0x1f) + + /* SMENR */ + #define SMENR_CDB_MASK (0x03 << 30) +@@ -240,6 +242,9 @@ struct rpc_spi { + void __iomem *base; + void __iomem *read_area; + void __iomem *write_area; ++ dma_addr_t read_area_dma; ++ struct completion comp; ++ struct dma_chan *dma_chan; + struct clk *clk; + unsigned int irq; + struct spi_nor spi_nor; +@@ -253,6 +258,13 @@ struct rpc_spi { + /* IP block use it's own clock divigion register */ + #define OWN_CLOCK_DIVIDER BIT(0) + ++#define RPC_DMA_BURST ((DRCR_RBURST_32 + 1) << 3) ++#define RPC_DMA_SIZE_MIN (RPC_DMA_BURST << 3) ++ ++static bool use_dma = true; ++module_param(use_dma, bool, 0); ++MODULE_PARM_DESC(use_dma, "DMA support. 0 = Disable, 1 = Enable"); ++ + /* debug */ + static void __maybe_unused regs_dump(struct rpc_spi *rpc) + { +@@ -282,6 +294,70 @@ static void __maybe_unused regs_dump(struct rpc_spi *rpc) + readl(rpc->base + regs[i])); + } + ++static void rpc_dma_complete_func(void *completion) ++{ ++ complete(completion); ++} ++ ++static int rpc_dma_read(struct rpc_spi *rpc, void *buf, ++ loff_t from, ssize_t *plen) ++{ ++ struct dma_device *dma_dev; ++ enum dma_ctrl_flags flags; ++ dma_addr_t dma_dst_addr; ++ struct dma_async_tx_descriptor *tx = NULL; ++ dma_cookie_t cookie; ++ int retval = 0; ++ ssize_t len; ++ ++ len = *plen; ++ ++ if (!rpc->dma_chan || len < RPC_DMA_SIZE_MIN) ++ return -ENODEV; ++ ++ dma_dev = rpc->dma_chan->device; ++ ++ /* Align size to RBURST */ ++ len -= len % RPC_DMA_BURST; ++ ++ dma_dst_addr = dma_map_single(dma_dev->dev, buf, len, DMA_FROM_DEVICE); ++ if (dma_mapping_error(dma_dev->dev, dma_dst_addr)) { ++ dev_err(&rpc->pdev->dev, "Failed to dma_map_single\n"); ++ return -ENXIO; ++ } ++ ++ flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT; ++ tx = dma_dev->device_prep_dma_memcpy(rpc->dma_chan, dma_dst_addr, ++ rpc->read_area_dma + from, ++ len, flags); ++ if (!tx) { ++ dev_err(&rpc->pdev->dev, "Failed to prepare DMA memcpy\n"); ++ retval = -EIO; ++ goto out_dma; ++ } ++ ++ init_completion(&rpc->comp); ++ tx->callback = rpc_dma_complete_func; ++ tx->callback_param = &rpc->comp; ++ ++ cookie = tx->tx_submit(tx); ++ retval = dma_submit_error(cookie); ++ if (retval) { ++ dev_err(&rpc->pdev->dev, "Failed to do DMA tx_submit\n"); ++ goto out_dma; ++ } ++ ++ dma_async_issue_pending(rpc->dma_chan); ++ wait_for_completion(&rpc->comp); ++ ++ /* Update length with actual transfer size */ ++ *plen = len; ++ ++out_dma: ++ dma_unmap_single(dma_dev->dev, dma_dst_addr, len, DMA_FROM_DEVICE); ++ return retval; ++} ++ + /* register acces */ + static u32 rpc_read(struct rpc_spi *rpc, unsigned int reg) + { +@@ -430,7 +506,7 @@ static int rpc_setup_ext_mode(struct rpc_spi *rpc) + /* ...enable burst and clear cache */ + val = rpc_read(rpc, DRCR); + val &= ~(DRCR_RBURST_MASK | DRCR_RBE | DRCR_SSLE); +- val |= DRCR_RBURST(0x1f) | DRCR_RBE; ++ val |= DRCR_RBURST(DRCR_RBURST_32) | DRCR_RBE; + + if (cmncr & CMNCR_MD) + val |= DRCR_RCF; +@@ -847,6 +923,8 @@ static ssize_t rpc_read_flash(struct spi_nor *nor, loff_t from, size_t len, + rpc_write(rpc, DRENR, val); + + while (len > 0) { ++ int retval; ++ + /* ...setup address */ + rpc_setup_extmode_read_addr(rpc, adr_width, from); + /* ...use adr [25...0] */ +@@ -855,7 +933,10 @@ static ssize_t rpc_read_flash(struct spi_nor *nor, loff_t from, size_t len, + readlen = READ_ADR_MASK - _from + 1; + readlen = readlen > len ? len : readlen; + +- memcpy_fromio(buf, rpc->read_area + _from, readlen); ++ retval = rpc_dma_read(rpc, buf, _from, &readlen); ++ if (retval) ++ memcpy_fromio(buf, rpc->read_area + _from, readlen); ++ + buf += readlen; + from += readlen; + len -= readlen; +@@ -1157,6 +1238,7 @@ static int rpc_spi_probe(struct platform_device *pdev) + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + ++ rpc->read_area_dma = res->start; + rpc->read_area = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(rpc->base)) { + dev_err(&pdev->dev, "cannot get resources\n"); +@@ -1235,10 +1317,23 @@ static int rpc_spi_probe(struct platform_device *pdev) + nor->mtd.writebufsize = WRITE_BUF_SIZE; + } + ++ if (use_dma) { ++ dma_cap_mask_t mask; ++ ++ dma_cap_zero(mask); ++ dma_cap_set(DMA_MEMCPY, mask); ++ rpc->dma_chan = dma_request_channel(mask, NULL, NULL); ++ if (!rpc->dma_chan) ++ dev_warn(&pdev->dev, "Failed to request DMA channel\n"); ++ else ++ dev_info(&pdev->dev, "Using DMA read (%s)\n", ++ dma_chan_name(rpc->dma_chan)); ++ } ++ + ret = mtd_device_register(&nor->mtd, NULL, 0); + if (ret) { + dev_err(&pdev->dev, "mtd_device_register error.\n"); +- goto error_clk_disable; ++ goto error_dma; + } + + dev_info(&pdev->dev, "probed as %s\n", +@@ -1246,6 +1341,9 @@ static int rpc_spi_probe(struct platform_device *pdev) + + return 0; + ++error_dma: ++ if (rpc->dma_chan) ++ dma_release_channel(rpc->dma_chan); + error_clk_disable: + clk_disable_unprepare(rpc->clk); + error: +@@ -1259,6 +1357,8 @@ static int rpc_spi_remove(struct platform_device *pdev) + /* HW shutdown */ + clk_disable_unprepare(rpc->clk); + mtd_device_unregister(&rpc->spi_nor.mtd); ++ if (rpc->dma_chan) ++ dma_release_channel(rpc->dma_chan); + return 0; + } + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0377-r8a779-78-dtsi-Add-iccom-nodes.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0377-r8a779-78-dtsi-Add-iccom-nodes.patch new file mode 100644 index 00000000..0c13d879 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0377-r8a779-78-dtsi-Add-iccom-nodes.patch @@ -0,0 +1,196 @@ +From 92a155910d8ccf5aa72c6e0c8b4307e6f6f08aba Mon Sep 17 00:00:00 2001 +From: Nikita Yushchenko +Date: Wed, 20 Jun 2018 13:18:02 +0300 +Subject: [PATCH 197/211] r8a779[78]: dtsi: Add iccom nodes + +Signed-off-by: Nikita Yushchenko +--- + arch/arm64/boot/dts/renesas/r8a77970.dtsi | 80 +++++++++++++++++++++++++++++++ + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 80 +++++++++++++++++++++++++++++++ + 2 files changed, 160 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +index 23422c7..08b4a05 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +@@ -1268,6 +1268,86 @@ + compatible = "renesas,prr"; + reg = <0 0xfff00044 0 4>; + }; ++ ++ iccom0 { ++ compatible = "renesas,iccom-rcar"; ++ interrupts = <0 224 4>; ++ reg = <0x0 0xe6260000 0x0 0x1000>; ++ iccom,reg-offset = <0x400 0x404 0x440 0x460>; ++ iccom,cta-memory = <0x0 0x47fc7000 0x0 0x2000>; ++ iccom,ack-timeout = <100>; ++ iccom,trg-timeout = <100>; ++ }; ++ ++ iccom1 { ++ compatible = "renesas,iccom-rcar"; ++ interrupts = <0 225 4>; ++ reg = <0x0 0xe6260000 0x0 0x1000>; ++ iccom,reg-offset = <0x408 0x40c 0x444 0x464>; ++ iccom,cta-memory = <0x0 0x47fc9000 0x0 0x2000>; ++ iccom,ack-timeout = <100>; ++ iccom,trg-timeout = <100>; ++ }; ++ ++ iccom2 { ++ compatible = "renesas,iccom-rcar"; ++ interrupts = <0 226 4>; ++ reg = <0x0 0xe6260000 0x0 0x1000>; ++ iccom,reg-offset = <0x410 0x414 0x448 0x468>; ++ iccom,cta-memory = <0x0 0x47fcb000 0x0 0x2000>; ++ iccom,ack-timeout = <100>; ++ iccom,trg-timeout = <100>; ++ }; ++ ++ iccom3 { ++ compatible = "renesas,iccom-rcar"; ++ interrupts = <0 227 4>; ++ reg = <0x0 0xe6260000 0x0 0x1000>; ++ iccom,reg-offset = <0x418 0x41c 0x44c 0x46c>; ++ iccom,cta-memory = <0x0 0x47fcd000 0x0 0x2000>; ++ iccom,ack-timeout = <100>; ++ iccom,trg-timeout = <100>; ++ }; ++ ++ iccom4 { ++ compatible = "renesas,iccom-rcar"; ++ interrupts = <0 228 4>; ++ reg = <0x0 0xe6260000 0x0 0x1000>; ++ iccom,reg-offset = <0x420 0x424 0x450 0x470>; ++ iccom,cta-memory = <0x0 0x47fcf000 0x0 0x2000>; ++ iccom,ack-timeout = <100>; ++ iccom,trg-timeout = <100>; ++ }; ++ ++ iccom5 { ++ compatible = "renesas,iccom-rcar"; ++ interrupts = <0 229 4>; ++ reg = <0x0 0xe6260000 0x0 0x1000>; ++ iccom,reg-offset = <0x428 0x42c 0x454 0x474>; ++ iccom,cta-memory = <0x0 0x47fd1000 0x0 0x2000>; ++ iccom,ack-timeout = <100>; ++ iccom,trg-timeout = <100>; ++ }; ++ ++ iccom6 { ++ compatible = "renesas,iccom-rcar"; ++ interrupts = <0 230 4>; ++ reg = <0x0 0xe6260000 0x0 0x1000>; ++ iccom,reg-offset = <0x430 0x434 0x458 0x478>; ++ iccom,cta-memory = <0x0 0x47fd3000 0x0 0x2000>; ++ iccom,ack-timeout = <100>; ++ iccom,trg-timeout = <100>; ++ }; ++ ++ iccom7 { ++ compatible = "renesas,iccom-rcar"; ++ interrupts = <0 231 4>; ++ reg = <0x0 0xe6260000 0x0 0x1000>; ++ iccom,reg-offset = <0x438 0x43c 0x45c 0x47c>; ++ iccom,cta-memory = <0x0 0x47fd5000 0x0 0x2000>; ++ iccom,ack-timeout = <100>; ++ iccom,trg-timeout = <100>; ++ }; + }; + + thermal-zones { +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index 688bc09..f649bbdc 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -1861,6 +1861,86 @@ + compatible = "renesas,prr"; + reg = <0 0xfff00044 0 4>; + }; ++ ++ iccom0 { ++ compatible = "renesas,iccom-rcar"; ++ interrupts = <0 224 4>; ++ reg = <0x0 0xe6260000 0x0 0x1000>; ++ iccom,reg-offset = <0x400 0x404 0x440 0x460>; ++ iccom,cta-memory = <0x0 0x47fc7000 0x0 0x2000>; ++ iccom,ack-timeout = <100>; ++ iccom,trg-timeout = <100>; ++ }; ++ ++ iccom1 { ++ compatible = "renesas,iccom-rcar"; ++ interrupts = <0 225 4>; ++ reg = <0x0 0xe6260000 0x0 0x1000>; ++ iccom,reg-offset = <0x408 0x40c 0x444 0x464>; ++ iccom,cta-memory = <0x0 0x47fc9000 0x0 0x2000>; ++ iccom,ack-timeout = <100>; ++ iccom,trg-timeout = <100>; ++ }; ++ ++ iccom2 { ++ compatible = "renesas,iccom-rcar"; ++ interrupts = <0 226 4>; ++ reg = <0x0 0xe6260000 0x0 0x1000>; ++ iccom,reg-offset = <0x410 0x414 0x448 0x468>; ++ iccom,cta-memory = <0x0 0x47fcb000 0x0 0x2000>; ++ iccom,ack-timeout = <100>; ++ iccom,trg-timeout = <100>; ++ }; ++ ++ iccom3 { ++ compatible = "renesas,iccom-rcar"; ++ interrupts = <0 227 4>; ++ reg = <0x0 0xe6260000 0x0 0x1000>; ++ iccom,reg-offset = <0x418 0x41c 0x44c 0x46c>; ++ iccom,cta-memory = <0x0 0x47fcd000 0x0 0x2000>; ++ iccom,ack-timeout = <100>; ++ iccom,trg-timeout = <100>; ++ }; ++ ++ iccom4 { ++ compatible = "renesas,iccom-rcar"; ++ interrupts = <0 228 4>; ++ reg = <0x0 0xe6260000 0x0 0x1000>; ++ iccom,reg-offset = <0x420 0x424 0x450 0x470>; ++ iccom,cta-memory = <0x0 0x47fcf000 0x0 0x2000>; ++ iccom,ack-timeout = <100>; ++ iccom,trg-timeout = <100>; ++ }; ++ ++ iccom5 { ++ compatible = "renesas,iccom-rcar"; ++ interrupts = <0 229 4>; ++ reg = <0x0 0xe6260000 0x0 0x1000>; ++ iccom,reg-offset = <0x428 0x42c 0x454 0x474>; ++ iccom,cta-memory = <0x0 0x47fd1000 0x0 0x2000>; ++ iccom,ack-timeout = <100>; ++ iccom,trg-timeout = <100>; ++ }; ++ ++ iccom6 { ++ compatible = "renesas,iccom-rcar"; ++ interrupts = <0 230 4>; ++ reg = <0x0 0xe6260000 0x0 0x1000>; ++ iccom,reg-offset = <0x430 0x434 0x458 0x478>; ++ iccom,cta-memory = <0x0 0x47fd3000 0x0 0x2000>; ++ iccom,ack-timeout = <100>; ++ iccom,trg-timeout = <100>; ++ }; ++ ++ iccom7 { ++ compatible = "renesas,iccom-rcar"; ++ interrupts = <0 231 4>; ++ reg = <0x0 0xe6260000 0x0 0x1000>; ++ iccom,reg-offset = <0x438 0x43c 0x45c 0x47c>; ++ iccom,cta-memory = <0x0 0x47fd5000 0x0 0x2000>; ++ iccom,ack-timeout = <100>; ++ iccom,trg-timeout = <100>; ++ }; + }; + + thermal-zones { +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0378-arm64-dts-renesas-Add-temperature-emergency-levels.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0378-arm64-dts-renesas-Add-temperature-emergency-levels.patch new file mode 100644 index 00000000..43646810 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0378-arm64-dts-renesas-Add-temperature-emergency-levels.patch @@ -0,0 +1,52 @@ +From 96f731ef74970d67cf8126667149cea09d12dacc Mon Sep 17 00:00:00 2001 +From: Dmitry Shifrin +Date: Sat, 17 Nov 2018 19:02:31 +0300 +Subject: [PATCH 198/211] arm64: dts: renesas: Add temperature emergency levels + +Add temperature emergency levels for SoCs r8a77970 and r8a77980 +--- + arch/arm64/boot/dts/renesas/r8a77970.dtsi | 7 +++++++ + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 9 +++++++++ + 2 files changed, 16 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +index 08b4a05..dd0a814 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +@@ -1351,6 +1351,13 @@ + }; + + thermal-zones { ++ emergency { ++ polling-delay = <1000>; ++ on-temperature = <110000>; ++ off-temperature = <95000>; ++ target_cpus = <&a53_1>; ++ status = "disabled"; ++ }; + cpu-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index f649bbdc..cdbdebc 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -1944,6 +1944,15 @@ + }; + + thermal-zones { ++ emergency { ++ polling-delay = <1000>; ++ on-temperature = <110000>; ++ off-temperature = <95000>; ++ target_cpus = <&a53_1>, ++ <&a53_2>, ++ <&a53_3>; ++ status = "disabled"; ++ }; + thermal-sensor-1 { + polling-delay-passive = <250>; + polling-delay = <1000>; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0379-r8a77980-dts-Add-vbm-v3-on-r8a77980-SoC.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0379-r8a77980-dts-Add-vbm-v3-on-r8a77980-SoC.patch new file mode 100644 index 00000000..dd27a6e6 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0379-r8a77980-dts-Add-vbm-v3-on-r8a77980-SoC.patch @@ -0,0 +1,70 @@ +From 9a278cdb4fe860d80fe95f576f685c78ec7a4113 Mon Sep 17 00:00:00 2001 +From: Roman Meshkevich +Date: Mon, 19 Nov 2018 13:27:06 +0300 +Subject: [PATCH 199/211] r8a77980: dts: Add vbm-v3 on r8a77980 SoC. + +--- + arch/arm64/boot/dts/renesas/Makefile | 1 + + .../boot/dts/renesas/r8a77980-v3hsk-vbm-v3.dts | 38 ++++++++++++++++++++++ + 2 files changed, 39 insertions(+) + create mode 100644 arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm-v3.dts + +diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile +index 4ccf641..563e390 100644 +--- a/arch/arm64/boot/dts/renesas/Makefile ++++ b/arch/arm64/boot/dts/renesas/Makefile +@@ -44,6 +44,7 @@ dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3msk-vbm-v3.dtb r8a77970-es1-v3msk-vbm- + dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-v3mzf.dtb + dtb-$(CONFIG_ARCH_R8A77980) += r8a77980-v3hsk-vbm.dtb + dtb-$(CONFIG_ARCH_R8A77980) += r8a77980-v3hsk-vbm-v2.dtb ++dtb-$(CONFIG_ARCH_R8A77980) += r8a77980-v3hsk-vbm-v3.dtb + dtb-$(CONFIG_ARCH_R8A77980) += r8a77980-v3hsk-vb-8ch.dtb r8a77980-v3hsk-vb-4ch.dtb + + always := $(dtb-y) +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm-v3.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm-v3.dts +new file mode 100644 +index 0000000..32a1805 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm-v3.dts +@@ -0,0 +1,38 @@ ++/* ++ * Device Tree Source for the V3MSK Videobox Mini board V3 on r8a7797 ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a77980-v3hsk-vbm-v2.dts" ++ ++ ++/ { ++ model = "Renesas V3HSK Videobox Mini board V3 based on r8a7798"; ++}; ++ ++&gpio0 { ++ can0_load { ++ gpio-hog; ++ gpios = <19 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can0_120R_load"; ++ }; ++}; ++ ++&gpio1 { ++ ex_v3m { ++ gpio-hog; ++ gpios = <19 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "ExV3M"; ++ }; ++}; ++ ++&gpio2 { ++ /delete-node/can0_load; ++}; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0380-arm64-dts-r8a77970-Enable-TMU-and-CMT.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0380-arm64-dts-r8a77970-Enable-TMU-and-CMT.patch new file mode 100644 index 00000000..8a0fa92a --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0380-arm64-dts-r8a77970-Enable-TMU-and-CMT.patch @@ -0,0 +1,101 @@ +From 6ad86a46afeebe56b69cd5618d416dff58d34168 Mon Sep 17 00:00:00 2001 +From: Dmitry Shifrin +Date: Fri, 16 Nov 2018 13:13:38 +0300 +Subject: [PATCH 200/211] arm64: dts: r8a77970: Enable TMU and CMT + +--- + arch/arm64/boot/dts/renesas/r8a77970-eagle.dts | 36 ++++++++++++++++++++++++++ + arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts | 36 ++++++++++++++++++++++++++ + 2 files changed, 72 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +index 7d93834..642efc7 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +@@ -624,3 +624,39 @@ + }; + }; + }; ++ ++&tmu0 { ++ status = "okay"; ++}; ++ ++&tmu1 { ++ status = "okay"; ++}; ++ ++&tmu2 { ++ status = "okay"; ++}; ++ ++&tmu3 { ++ status = "okay"; ++}; ++ ++&tmu4 { ++ status = "okay"; ++}; ++ ++&cmt0 { ++ status = "okay"; ++}; ++ ++&cmt1 { ++ status = "okay"; ++}; ++ ++&cmt2 { ++ status = "okay"; ++}; ++ ++&cmt3 { ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +index ef9a2c5..107d041 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +@@ -332,3 +332,39 @@ + + status = "okay"; + }; ++ ++&tmu0 { ++ status = "okay"; ++}; ++ ++&tmu1 { ++ status = "okay"; ++}; ++ ++&tmu2 { ++ status = "okay"; ++}; ++ ++&tmu3 { ++ status = "okay"; ++}; ++ ++&tmu4 { ++ status = "okay"; ++}; ++ ++&cmt0 { ++ status = "okay"; ++}; ++ ++&cmt1 { ++ status = "okay"; ++}; ++ ++&cmt2 { ++ status = "okay"; ++}; ++ ++&cmt3 { ++ status = "okay"; ++}; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0381-arm64-dts-r8a77980-Enable-TMU-and-CMT.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0381-arm64-dts-r8a77980-Enable-TMU-and-CMT.patch new file mode 100644 index 00000000..b09ab317 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0381-arm64-dts-r8a77980-Enable-TMU-and-CMT.patch @@ -0,0 +1,101 @@ +From 6255d98e794cabafdfd3683bdfadb7468e5251d1 Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Mon, 19 Nov 2018 18:59:08 +0300 +Subject: [PATCH 201/211] arm64: dts: r8a77980: Enable TMU and CMT + +--- + arch/arm64/boot/dts/renesas/r8a77980-condor.dts | 36 +++++++++++++++++++++++++ + arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts | 36 +++++++++++++++++++++++++ + 2 files changed, 72 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +index 6b5f574..45e4ada 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +@@ -951,3 +951,39 @@ + }; + }; + }; ++ ++&tmu0 { ++ status = "okay"; ++}; ++ ++&tmu1 { ++ status = "okay"; ++}; ++ ++&tmu2 { ++ status = "okay"; ++}; ++ ++&tmu3 { ++ status = "okay"; ++}; ++ ++&tmu4 { ++ status = "okay"; ++}; ++ ++&cmt0 { ++ status = "okay"; ++}; ++ ++&cmt1 { ++ status = "okay"; ++}; ++ ++&cmt2 { ++ status = "okay"; ++}; ++ ++&cmt3 { ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +index cfbfd98..7a07120 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +@@ -354,3 +354,39 @@ + non-removable; + status = "okay"; + }; ++ ++&tmu0 { ++ status = "okay"; ++}; ++ ++&tmu1 { ++ status = "okay"; ++}; ++ ++&tmu2 { ++ status = "okay"; ++}; ++ ++&tmu3 { ++ status = "okay"; ++}; ++ ++&tmu4 { ++ status = "okay"; ++}; ++ ++&cmt0 { ++ status = "okay"; ++}; ++ ++&cmt1 { ++ status = "okay"; ++}; ++ ++&cmt2 { ++ status = "okay"; ++}; ++ ++&cmt3 { ++ status = "okay"; ++}; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0382-arm64-dts-renesas-r8a77970-and-r8a77980-Add-QoS-node.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0382-arm64-dts-renesas-r8a77970-and-r8a77980-Add-QoS-node.patch new file mode 100644 index 00000000..cc9f9925 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0382-arm64-dts-renesas-r8a77970-and-r8a77980-Add-QoS-node.patch @@ -0,0 +1,46 @@ +From 5afe6a9d9e087dee62d593c09e71da800b5f6e88 Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Wed, 21 Nov 2018 15:22:45 +0300 +Subject: [PATCH 202/211] arm64: dts: renesas: r8a77970 and r8a77980: Add QoS + nodes + +--- + arch/arm64/boot/dts/renesas/r8a77970.dtsi | 5 +++++ + arch/arm64/boot/dts/renesas/r8a77980.dtsi | 5 +++++ + 2 files changed, 10 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +index dd0a814..be793ff 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +@@ -1348,6 +1348,11 @@ + iccom,ack-timeout = <100>; + iccom,trg-timeout = <100>; + }; ++ ++ qos@e67e0000 { ++ compatible = "renesas,qos"; ++ reg = <0 0xe67e0000 0 0x10090>; ++ }; + }; + + thermal-zones { +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index cdbdebc..045b517 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -1941,6 +1941,11 @@ + iccom,ack-timeout = <100>; + iccom,trg-timeout = <100>; + }; ++ ++ qos@e67e0000 { ++ compatible = "renesas,qos"; ++ reg = <0 0xe67e0000 0 0x10090>; ++ }; + }; + + thermal-zones { +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0383-clk-renesas-r8a77970-cpg-mssr-Add-sadc-clock.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0383-clk-renesas-r8a77970-cpg-mssr-Add-sadc-clock.patch new file mode 100644 index 00000000..0a9f94b4 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0383-clk-renesas-r8a77970-cpg-mssr-Add-sadc-clock.patch @@ -0,0 +1,26 @@ +From 76384a2aa1e57174bfa97a2d01b588c49a8cce80 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Tue, 10 Jul 2018 15:28:03 +0300 +Subject: [PATCH 203/211] clk: renesas: r8a77970: cpg-mssr: Add sadc clock + +Signed-off-by: Andrey Gusakov +Signed-off-by: Valentine Barshak +--- + drivers/clk/renesas/r8a77970-cpg-mssr.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/clk/renesas/r8a77970-cpg-mssr.c b/drivers/clk/renesas/r8a77970-cpg-mssr.c +index 1e3f6f8..dc70a36 100644 +--- a/drivers/clk/renesas/r8a77970-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a77970-cpg-mssr.c +@@ -137,6 +137,7 @@ static const struct mssr_mod_clk r8a77970_mod_clks[] __initconst = { + DEF_MOD("rwdt", 402, R8A77970_CLK_R), + DEF_MOD("intc-ex", 407, R8A77970_CLK_CP), + DEF_MOD("intc-ap", 408, R8A77970_CLK_S2D1), ++ DEF_MOD("sadc", 503, R8A77970_CLK_S2D1), /* @@ H3=S3D1 */ + DEF_MOD("hscif3", 517, R8A77970_CLK_S2D1), + DEF_MOD("hscif2", 518, R8A77970_CLK_S2D1), + DEF_MOD("hscif1", 519, R8A77970_CLK_S2D1), +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0384-arm64-dts-renesas-r8a77970-Add-sadc-node.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0384-arm64-dts-renesas-r8a77970-Add-sadc-node.patch new file mode 100644 index 00000000..62629ba7 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0384-arm64-dts-renesas-r8a77970-Add-sadc-node.patch @@ -0,0 +1,37 @@ +From 25e00c6c4bd5be1ba742b0d75b7e02f052489d38 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Tue, 10 Jul 2018 15:27:33 +0300 +Subject: [PATCH 204/211] arm64: dts: renesas: r8a77970: Add sadc node + +Signed-off-by: Andrey Gusakov +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970.dtsi | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +index be793ff..7ecbc01 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi +@@ -1053,6 +1053,18 @@ + power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; + }; + ++ sadc0: adc@ffce0000 { ++ compatible = "renesas,sadc-r8a77970"; ++ reg = <0 0xffce0000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_CORE R8A77970_CLK_S2D4>, ++ <&cpg CPG_CORE R8A77970_CLK_S2D2>, ++ <&cpg CPG_MOD 503>; /* RMSTPCR5/bit3:ADC */ ++ clock-names = "phy_clk", "ip_clk", "adc"; ++ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ + dmac1: dma-controller@e7300000 { + compatible = "renesas,dmac-r8a77970", + "renesas,rcar-dmac"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0385-iio-adc-Add-R-Car-SADC-driver.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0385-iio-adc-Add-R-Car-SADC-driver.patch new file mode 100644 index 00000000..0ed90c24 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0385-iio-adc-Add-R-Car-SADC-driver.patch @@ -0,0 +1,456 @@ +From 7793b9dcbfd9795853b27f758b93f18e1c90a9c5 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Tue, 10 Jul 2018 15:25:58 +0300 +Subject: [PATCH 205/211] iio: adc: Add R-Car SADC driver + +Signed-off-by: Andrey Gusakov +Signed-off-by: Valentine Barshak +--- + drivers/iio/adc/Kconfig | 11 ++ + drivers/iio/adc/Makefile | 1 + + drivers/iio/adc/rcar-sadc.c | 399 ++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 411 insertions(+) + create mode 100644 drivers/iio/adc/rcar-sadc.c + +diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig +index 369a2c6..a715cdc 100644 +--- a/drivers/iio/adc/Kconfig ++++ b/drivers/iio/adc/Kconfig +@@ -607,6 +607,17 @@ config RCAR_GYRO_ADC + To compile this driver as a module, choose M here: the + module will be called rcar-gyroadc. + ++config RCAR_SADC ++ tristate "Renesas R-Car SADC driver" ++ depends on ARCH_R8A77970 ++ depends on OF ++ depends on HAS_IOMEM ++ select IIO_BUFFER ++ select IIO_TRIGGERED_BUFFER ++ help ++ Say yes here to build support for the SADC found in SoCs from ++ Renesas (currently V3M has this ADC). ++ + config ROCKCHIP_SARADC + tristate "Rockchip SARADC driver" + depends on ARCH_ROCKCHIP || (ARM && COMPILE_TEST) +diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile +index 9572c10..6ee0f32 100644 +--- a/drivers/iio/adc/Makefile ++++ b/drivers/iio/adc/Makefile +@@ -58,6 +58,7 @@ obj-$(CONFIG_QCOM_VADC_COMMON) += qcom-vadc-common.o + obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o + obj-$(CONFIG_QCOM_PM8XXX_XOADC) += qcom-pm8xxx-xoadc.o + obj-$(CONFIG_RCAR_GYRO_ADC) += rcar-gyroadc.o ++obj-$(CONFIG_RCAR_SADC) += rcar-sadc.o + obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o + obj-$(CONFIG_SPEAR_ADC) += spear_adc.o + obj-$(CONFIG_STX104) += stx104.o +diff --git a/drivers/iio/adc/rcar-sadc.c b/drivers/iio/adc/rcar-sadc.c +new file mode 100644 +index 0000000..724ea21 +--- /dev/null ++++ b/drivers/iio/adc/rcar-sadc.c +@@ -0,0 +1,399 @@ ++/* ++ * Renesas R-Car 3 ADC ++ * ++ * Copyright 2018 CogentEmbedded, Inc. ++ * ++ * based on linux/drivers/iio/vf610_adc.c ++ * Copyright 2013 Freescale Semiconductor, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* This will be the driver name the kernel reports */ ++#define DRIVER_NAME "rcar-sadc" ++ ++#define RCAR_ADPHYS 0x00 ++#define RCAR_ADFLAG 0x04 ++#define RCAR_ADEMSK 0x08 ++#define RCAR_ADECLR 0x0c ++#define RCAR_ADFIFOEN 0x10 ++#define RCAR_ADFIFORST 0x14 ++#define RCAR_ADFIFOSTS 0x18 ++#define RCAR_ADFIFORC 0x1c ++#define RCAR_ADCHSELP 0x20 ++#define RCAR_ADMON(x) (0x24 + 0x4 * (x)) ++#define ADMONSET(x) (0x4c + 0x4 * (x)) ++#define RCAR_ADCTRANS(x) (0x74 + 0x4 * (x)) ++#define RCAR_ADCLASTREG 0x98 ++ ++#define RCAR_ALL_CHANS 0x3ff ++ ++#define RCAR_ADC_TIMEOUT msecs_to_jiffies(100) ++ ++struct rcar_adc { ++ struct device *dev; ++ void __iomem *regs; ++ struct clk *clk; ++ ++ u32 vref_uv; ++ struct regulator *vref; ++ ++ struct completion completion; ++}; ++ ++static int rcar_chan_to_idx(int ch) ++{ ++ /* regular channels starts from 1 */ ++ if ((ch >= 0) && (ch <= 7)) ++ return ch + 1; ++ else if (ch == 8) ++ return 0; /* VDD1 */ ++ else ++ return 9; /* VDD2 */ ++} ++ ++static void rcar_adc_hw_init(struct rcar_adc *info) ++{ ++ uint32_t reg; ++ ++ /* ADCHSELP register should be set 32'H0000 0030 before measuring */ ++ writel(0x30, info->regs + RCAR_ADCHSELP); ++ /* reset all fifo */ ++ writel(RCAR_ALL_CHANS, info->regs + RCAR_ADFIFORST); ++ /* enable all channels */ ++ writel(RCAR_ALL_CHANS, info->regs + RCAR_ADFIFOEN); ++ /* AD FIFO read command register */ ++ writel(RCAR_ALL_CHANS, info->regs + RCAR_ADFIFORC); ++ ++ reg = readl(info->regs + RCAR_ADPHYS); ++ writel(reg | (1 << 28) | (1 << 24), info->regs + RCAR_ADPHYS); ++} ++ ++#define RCAR_ADC_CHAN(_idx, _chan_type) { \ ++ .type = (_chan_type), \ ++ .indexed = 1, \ ++ .channel = (_idx), \ ++ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ ++ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ ++ .scan_index = (_idx), \ ++ .scan_type = { \ ++ .sign = 'u', \ ++ .realbits = 12, \ ++ .storagebits = 16, \ ++ }, \ ++} ++ ++static const struct iio_chan_spec rcar_adc_iio_channels[] = { ++ /* external */ ++ RCAR_ADC_CHAN(0, IIO_VOLTAGE), ++ RCAR_ADC_CHAN(1, IIO_VOLTAGE), ++ RCAR_ADC_CHAN(2, IIO_VOLTAGE), ++ RCAR_ADC_CHAN(3, IIO_VOLTAGE), ++ RCAR_ADC_CHAN(4, IIO_VOLTAGE), ++ RCAR_ADC_CHAN(5, IIO_VOLTAGE), ++ RCAR_ADC_CHAN(6, IIO_VOLTAGE), ++ RCAR_ADC_CHAN(7, IIO_VOLTAGE), ++ /* internal */ ++ RCAR_ADC_CHAN(8, IIO_VOLTAGE), /* VDD1 */ ++ RCAR_ADC_CHAN(9, IIO_VOLTAGE), /* VDD2 */ ++ /* sentinel */ ++}; ++ ++static irqreturn_t rcar_adc_isr(int irq, void *dev_id) ++{ ++ struct iio_dev *indio_dev = (struct iio_dev *)dev_id; ++ struct rcar_adc *info = iio_priv(indio_dev); ++ ++ writel(RCAR_ALL_CHANS, info->regs + RCAR_ADECLR); ++ ++ return IRQ_HANDLED; ++} ++ ++static int rcar_adc_read_raw(struct iio_dev *indio_dev, ++ struct iio_chan_spec const *chan, ++ int *val, ++ int *val2, ++ long mask) ++{ ++ u32 value; ++ struct rcar_adc *info = iio_priv(indio_dev); ++ ++ switch (mask) { ++ case IIO_CHAN_INFO_RAW: ++ case IIO_CHAN_INFO_PROCESSED: ++ value = readl(info->regs + ++ RCAR_ADMON(rcar_chan_to_idx(chan->channel))) ++ & 0x0fff; ++ switch (chan->type) { ++ case IIO_VOLTAGE: ++ *val = value; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return IIO_VAL_INT; ++ ++ case IIO_CHAN_INFO_SCALE: ++ *val = info->vref_uv / 1000; ++ *val2 = 12; /* 12 bit mode */ ++ return IIO_VAL_FRACTIONAL_LOG2; ++ ++ default: ++ break; ++ } ++ ++ return -EINVAL; ++} ++ ++static int rcar_adc_buffer_postenable(struct iio_dev *indio_dev) ++{ ++ return 0; ++} ++ ++static int rcar_adc_buffer_predisable(struct iio_dev *indio_dev) ++{ ++ return iio_triggered_buffer_predisable(indio_dev); ++} ++ ++static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = { ++ .postenable = &rcar_adc_buffer_postenable, ++ .predisable = &rcar_adc_buffer_predisable, ++ .validate_scan_mask = &iio_validate_scan_mask_onehot, ++}; ++ ++static int rcar_adc_reg_access(struct iio_dev *indio_dev, ++ unsigned reg, unsigned writeval, ++ unsigned *readval) ++{ ++ struct rcar_adc *info = iio_priv(indio_dev); ++ ++ if ((readval == NULL) || ++ ((reg % 4) || (reg > RCAR_ADCLASTREG))) ++ return -EINVAL; ++ ++ *readval = readl(info->regs + reg); ++ ++ return 0; ++} ++ ++static const struct iio_info rcar_adc_iio_info = { ++ .driver_module = THIS_MODULE, ++ .read_raw = &rcar_adc_read_raw, ++ .debugfs_reg_access = &rcar_adc_reg_access, ++}; ++ ++static const struct of_device_id rcar_adc_match[] = { ++ { .compatible = "renesas,sadc-r8a77970", }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, rcar_adc_match); ++ ++static int rcar_adc_probe(struct platform_device *pdev) ++{ ++ struct rcar_adc *info; ++ struct iio_dev *indio_dev; ++ struct resource *mem; ++ int irq; ++ int ret; ++ ++ indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct rcar_adc)); ++ if (!indio_dev) { ++ dev_err(&pdev->dev, "Failed allocating iio device\n"); ++ return -ENOMEM; ++ } ++ ++ info = iio_priv(indio_dev); ++ info->dev = &pdev->dev; ++ ++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ info->regs = devm_ioremap_resource(&pdev->dev, mem); ++ if (IS_ERR(info->regs)) ++ return PTR_ERR(info->regs); ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ dev_err(&pdev->dev, "no irq resource?\n"); ++ return irq; ++ } ++ ++ ret = devm_request_irq(info->dev, irq, ++ rcar_adc_isr, 0, ++ dev_name(&pdev->dev), indio_dev); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "failed requesting irq: %d\n", irq); ++ return ret; ++ } ++ ++ info->clk = devm_clk_get(&pdev->dev, "adc"); ++ if (IS_ERR(info->clk)) { ++ dev_err(&pdev->dev, "failed getting clock: %ld\n", ++ PTR_ERR(info->clk)); ++ return PTR_ERR(info->clk); ++ } ++ ++ info->vref = devm_regulator_get(&pdev->dev, "vref"); ++ if (IS_ERR(info->vref)) { ++ dev_err(&pdev->dev, "failed getting regulator: %ld\n", ++ PTR_ERR(info->vref)); ++ return PTR_ERR(info->vref); ++ } ++ ++ ret = regulator_enable(info->vref); ++ if (ret) { ++ dev_err(&pdev->dev, "failed enabling regulator: %d\n", ++ ret); ++ return ret; ++ } ++ ++ ret = regulator_get_voltage(info->vref); ++ if (ret <= 0) { ++ dev_err(&pdev->dev, "failed getting regulator voltage: %d\n", ++ ret); ++ return ret; ++ } ++ info->vref_uv = ret; ++ ++ platform_set_drvdata(pdev, indio_dev); ++ ++ init_completion(&info->completion); ++ ++ indio_dev->name = dev_name(&pdev->dev); ++ indio_dev->dev.parent = &pdev->dev; ++ indio_dev->dev.of_node = pdev->dev.of_node; ++ indio_dev->info = &rcar_adc_iio_info; ++ indio_dev->modes = INDIO_DIRECT_MODE; ++ indio_dev->channels = rcar_adc_iio_channels; ++ indio_dev->num_channels = ARRAY_SIZE(rcar_adc_iio_channels); ++ ++ ret = clk_prepare_enable(info->clk); ++ if (ret) { ++ dev_err(&pdev->dev, ++ "Could not prepare or enable the clock: %d\n", ++ ret); ++ goto error_adc_clk_enable; ++ } ++ ++ rcar_adc_hw_init(info); ++ ++ ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, ++ NULL, &iio_triggered_buffer_setup_ops); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "Couldn't initialise the buffer\n"); ++ goto error_iio_device_register; ++ } ++ ++ ret = iio_device_register(indio_dev); ++ if (ret) { ++ dev_err(&pdev->dev, "Couldn't register the device.\n"); ++ goto error_adc_buffer_init; ++ } ++ ++ return 0; ++ ++error_adc_buffer_init: ++ iio_triggered_buffer_cleanup(indio_dev); ++error_iio_device_register: ++ clk_disable_unprepare(info->clk); ++error_adc_clk_enable: ++ regulator_disable(info->vref); ++ ++ return ret; ++} ++ ++static int rcar_adc_remove(struct platform_device *pdev) ++{ ++ struct iio_dev *indio_dev = platform_get_drvdata(pdev); ++ struct rcar_adc *info = iio_priv(indio_dev); ++ ++ iio_device_unregister(indio_dev); ++ iio_triggered_buffer_cleanup(indio_dev); ++ regulator_disable(info->vref); ++ clk_disable_unprepare(info->clk); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int rcar_adc_suspend(struct device *dev) ++{ ++ struct iio_dev *indio_dev = dev_get_drvdata(dev); ++ struct rcar_adc *info = iio_priv(indio_dev); ++ ++ clk_disable_unprepare(info->clk); ++ regulator_disable(info->vref); ++ ++ return 0; ++} ++ ++static int rcar_adc_resume(struct device *dev) ++{ ++ struct iio_dev *indio_dev = dev_get_drvdata(dev); ++ struct rcar_adc *info = iio_priv(indio_dev); ++ int ret; ++ ++ ret = regulator_enable(info->vref); ++ if (ret) ++ return ret; ++ ++ ret = clk_prepare_enable(info->clk); ++ if (ret) ++ goto disable_reg; ++ ++ rcar_adc_hw_init(info); ++ ++ return 0; ++ ++disable_reg: ++ regulator_disable(info->vref); ++ return ret; ++} ++#endif ++ ++static SIMPLE_DEV_PM_OPS(rcar_adc_pm_ops, rcar_adc_suspend, rcar_adc_resume); ++ ++static struct platform_driver rcar_adc_driver = { ++ .probe = rcar_adc_probe, ++ .remove = rcar_adc_remove, ++ .driver = { ++ .name = DRIVER_NAME, ++ .of_match_table = rcar_adc_match, ++ .pm = &rcar_adc_pm_ops, ++ }, ++}; ++ ++module_platform_driver(rcar_adc_driver); ++ ++MODULE_AUTHOR("Andrey Gusakov "); ++MODULE_DESCRIPTION("Renesas R-Car V3M SADC driver"); ++MODULE_LICENSE("GPL v2"); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0386-rcar-vin-add-ISP-source-enable.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0386-rcar-vin-add-ISP-source-enable.patch new file mode 100644 index 00000000..0d334bfa --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0386-rcar-vin-add-ISP-source-enable.patch @@ -0,0 +1,66 @@ +From 0c86a96a5d552d5f7ddd9004b4639821ab2c3083 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Tue, 18 Dec 2018 14:34:58 +0300 +Subject: [PATCH 206/211] rcar-vin: add ISP source enable + +This adds possbility to use ISP as a source for VIN8-VIN15 +on V3H + +Signed-off-by: Vladimir Barinov +--- + drivers/media/platform/soc_camera/rcar_vin.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c +index 6ba94c3..bcc1cfd 100644 +--- a/drivers/media/platform/soc_camera/rcar_vin.c ++++ b/drivers/media/platform/soc_camera/rcar_vin.c +@@ -102,6 +102,7 @@ + + /* Register bit fields for R-Car VIN */ + /* Video n Main Control Register bits */ ++#define VNMC_ISPE (1 << 30) + #define VNMC_DPINE (1 << 27) + #define VNMC_SCLE (1 << 26) + #define VNMC_FOC (1 << 21) +@@ -188,6 +189,7 @@ + #define RCAR_VIN_BT601 (1 << 2) + #define RCAR_VIN_BT656 (1 << 3) + #define RCAR_VIN_CSI2 (1 << 4) ++#define RCAR_VIN_ISP (1 << 5) + + static int lut_reverse; + module_param(lut_reverse, int, 0644); +@@ -1238,6 +1240,9 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + vnmc |= VNMC_SCLE; + } + ++ if (priv->pdata_flags & RCAR_VIN_ISP) ++ vnmc |= VNMC_ISPE; ++ + /* progressive or interlaced mode */ + interrupts = progressive ? VNIE_FIE : VNIE_EFE; + +@@ -2042,6 +2047,9 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd) + vnmc |= VNMC_DPINE; + } + ++ if (priv->pdata_flags & RCAR_VIN_ISP) ++ vnmc |= VNMC_ISPE; ++ + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || + priv->chip == RCAR_M3N || priv->chip == RCAR_V3M || + priv->chip == RCAR_V3H) +@@ -3124,6 +3132,9 @@ static int rcar_vin_probe(struct platform_device *pdev) + + of_node_put(np); + ++ if (of_property_read_bool(np, "isp,enable")) ++ pdata_flags = RCAR_VIN_ISP; ++ + dev_dbg(&pdev->dev, "pdata_flags = %08x\n", pdata_flags); + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0387-media-soc_camera-Add-events-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0387-media-soc_camera-Add-events-support.patch new file mode 100644 index 00000000..bb2ab7de --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0387-media-soc_camera-Add-events-support.patch @@ -0,0 +1,426 @@ +From 6e47c1eba7112dfcd5f7c07103a99e1e09a150bd Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Thu, 17 Jan 2019 17:48:53 +0300 +Subject: [PATCH 207/211] media: soc_camera: Add events support + +--- + drivers/media/platform/soc_camera/rcar_isp.c | 2 +- + drivers/media/platform/soc_camera/rcar_vin.c | 2 +- + .../platform/soc_camera/sh_mobile_ceu_camera.c | 2 +- + drivers/media/platform/soc_camera/soc_camera.c | 88 ++++++++++++++-------- + include/media/soc_camera.h | 4 + + 5 files changed, 65 insertions(+), 33 deletions(-) + +diff --git a/drivers/media/platform/soc_camera/rcar_isp.c b/drivers/media/platform/soc_camera/rcar_isp.c +index 1127c7d..e7c2801 100644 +--- a/drivers/media/platform/soc_camera/rcar_isp.c ++++ b/drivers/media/platform/soc_camera/rcar_isp.c +@@ -1549,7 +1549,7 @@ static int rcar_isp_try_fmt(struct soc_camera_device *icd, + + static unsigned int rcar_isp_poll(struct file *file, poll_table *pt) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + + return vb2_poll(&icd->vb2_vidq, file, pt); + } +diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c +index bcc1cfd..9051590 100644 +--- a/drivers/media/platform/soc_camera/rcar_vin.c ++++ b/drivers/media/platform/soc_camera/rcar_vin.c +@@ -2723,7 +2723,7 @@ static int rcar_vin_try_fmt(struct soc_camera_device *icd, + + static unsigned int rcar_vin_poll(struct file *file, poll_table *pt) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + + return vb2_poll(&icd->vb2_vidq, file, pt); + } +diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c +index 9180a1d..564d7e8 100644 +--- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c ++++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c +@@ -1560,7 +1560,7 @@ static int sh_mobile_ceu_set_liveselection(struct soc_camera_device *icd, + + static unsigned int sh_mobile_ceu_poll(struct file *file, poll_table *pt) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + + return vb2_poll(&icd->vb2_vidq, file, pt); + } +diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c +index cd2a135..7e5ca15 100644 +--- a/drivers/media/platform/soc_camera/soc_camera.c ++++ b/drivers/media/platform/soc_camera/soc_camera.c +@@ -289,7 +289,7 @@ static int soc_camera_try_fmt(struct soc_camera_device *icd, + static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + + WARN_ON(priv != file->private_data); + +@@ -304,7 +304,7 @@ static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv, + static int soc_camera_enum_input(struct file *file, void *priv, + struct v4l2_input *inp) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + + if (inp->index != 0) + return -EINVAL; +@@ -334,7 +334,7 @@ static int soc_camera_s_input(struct file *file, void *priv, unsigned int i) + + static int soc_camera_s_std(struct file *file, void *priv, v4l2_std_id a) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + + return v4l2_subdev_call(sd, video, s_std, a); +@@ -342,7 +342,7 @@ static int soc_camera_s_std(struct file *file, void *priv, v4l2_std_id a) + + static int soc_camera_g_std(struct file *file, void *priv, v4l2_std_id *a) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + + return v4l2_subdev_call(sd, video, g_std, a); +@@ -351,7 +351,7 @@ static int soc_camera_g_std(struct file *file, void *priv, v4l2_std_id *a) + static int soc_camera_enum_framesizes(struct file *file, void *fh, + struct v4l2_frmsizeenum *fsize) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + + return ici->ops->enum_framesizes(icd, fsize); +@@ -361,7 +361,7 @@ static int soc_camera_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *p) + { + int ret; +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + + WARN_ON(priv != file->private_data); + +@@ -377,7 +377,7 @@ static int soc_camera_reqbufs(struct file *file, void *priv, + static int soc_camera_querybuf(struct file *file, void *priv, + struct v4l2_buffer *p) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + + WARN_ON(priv != file->private_data); + +@@ -387,7 +387,7 @@ static int soc_camera_querybuf(struct file *file, void *priv, + static int soc_camera_qbuf(struct file *file, void *priv, + struct v4l2_buffer *p) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + + WARN_ON(priv != file->private_data); + +@@ -400,7 +400,7 @@ static int soc_camera_qbuf(struct file *file, void *priv, + static int soc_camera_dqbuf(struct file *file, void *priv, + struct v4l2_buffer *p) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + + WARN_ON(priv != file->private_data); + +@@ -413,7 +413,7 @@ static int soc_camera_dqbuf(struct file *file, void *priv, + static int soc_camera_create_bufs(struct file *file, void *priv, + struct v4l2_create_buffers *create) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + int ret; + + if (icd->streamer && icd->streamer != file) +@@ -428,7 +428,7 @@ static int soc_camera_create_bufs(struct file *file, void *priv, + static int soc_camera_prepare_buf(struct file *file, void *priv, + struct v4l2_buffer *b) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + + return vb2_prepare_buf(&icd->vb2_vidq, b); + } +@@ -436,7 +436,7 @@ static int soc_camera_prepare_buf(struct file *file, void *priv, + static int soc_camera_expbuf(struct file *file, void *priv, + struct v4l2_exportbuffer *p) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + + if (icd->streamer && icd->streamer != file) + return -EBUSY; +@@ -632,6 +632,7 @@ static int soc_camera_open(struct file *file) + return -ENODEV; + } + ++ v4l2_fh_open(file); + icd = video_get_drvdata(vdev); + ici = to_soc_camera_host(icd->parent); + +@@ -708,7 +709,6 @@ static int soc_camera_open(struct file *file) + } + mutex_unlock(&ici->host_lock); + +- file->private_data = icd; + dev_dbg(icd->pdev, "camera device open\n"); + + return 0; +@@ -736,14 +736,19 @@ static int soc_camera_open(struct file *file) + + static int soc_camera_close(struct file *file) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct v4l2_event ev; + + mutex_lock(&ici->host_lock); + if (icd->streamer == file) { + if (ici->ops->init_videobuf2) + vb2_queue_release(&icd->vb2_vidq); + icd->streamer = NULL; ++ ++ memset(&ev, 0, sizeof(ev)); ++ ev.type = V4L2_EVENT_EOS; ++ v4l2_event_queue(icd->vdev, &ev); + } + icd->use_count--; + if (!icd->use_count) { +@@ -755,6 +760,8 @@ static int soc_camera_close(struct file *file) + soc_camera_remove_device(icd); + } + ++ v4l2_fh_release(file); ++ + mutex_unlock(&ici->host_lock); + + module_put(ici->ops->owner); +@@ -767,7 +774,7 @@ static int soc_camera_close(struct file *file) + static ssize_t soc_camera_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + + dev_dbg(icd->pdev, "read called, buf %p\n", buf); +@@ -783,7 +790,7 @@ static ssize_t soc_camera_read(struct file *file, char __user *buf, + + static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + int err; + +@@ -807,12 +814,14 @@ static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma) + + static unsigned int soc_camera_poll(struct file *file, poll_table *pt) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + unsigned res = POLLERR; + ++/* + if (icd->streamer != file) + return POLLERR; ++*/ + + mutex_lock(&ici->host_lock); + res = ici->ops->poll(file, pt); +@@ -833,7 +842,7 @@ static const struct v4l2_file_operations soc_camera_fops = { + static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + int ret; + + WARN_ON(priv != file->private_data); +@@ -862,7 +871,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, + static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + const struct soc_mbus_pixelfmt *format; + + WARN_ON(priv != file->private_data); +@@ -881,7 +890,7 @@ static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv, + static int soc_camera_g_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + struct v4l2_pix_format *pix = &f->fmt.pix; + + WARN_ON(priv != file->private_data); +@@ -904,7 +913,7 @@ static int soc_camera_g_fmt_vid_cap(struct file *file, void *priv, + static int soc_camera_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + + WARN_ON(priv != file->private_data); +@@ -916,8 +925,9 @@ static int soc_camera_querycap(struct file *file, void *priv, + static int soc_camera_streamon(struct file *file, void *priv, + enum v4l2_buf_type i) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ struct v4l2_event ev; + int ret; + + WARN_ON(priv != file->private_data); +@@ -933,14 +943,19 @@ static int soc_camera_streamon(struct file *file, void *priv, + if (!ret) + v4l2_subdev_call(sd, video, s_stream, 1); + ++ memset(&ev, 0, sizeof(ev)); ++ ev.type = V4L2_EVENT_SOC_START_STREAM; ++ v4l2_event_queue(icd->vdev, &ev); ++ + return ret; + } + + static int soc_camera_streamoff(struct file *file, void *priv, + enum v4l2_buf_type i) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ struct v4l2_event ev; + int ret; + + WARN_ON(priv != file->private_data); +@@ -959,13 +974,17 @@ static int soc_camera_streamoff(struct file *file, void *priv, + + v4l2_subdev_call(sd, video, s_stream, 0); + ++ memset(&ev, 0, sizeof(ev)); ++ ev.type = V4L2_EVENT_EOS; ++ v4l2_event_queue(icd->vdev, &ev); ++ + return ret; + } + + static int soc_camera_g_selection(struct file *file, void *fh, + struct v4l2_selection *s) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + + /* With a wrong type no need to try to fall back to cropping */ +@@ -978,7 +997,7 @@ static int soc_camera_g_selection(struct file *file, void *fh, + static int soc_camera_s_selection(struct file *file, void *fh, + struct v4l2_selection *s) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + int ret; + +@@ -1023,7 +1042,7 @@ static int soc_camera_s_selection(struct file *file, void *fh, + static int soc_camera_g_parm(struct file *file, void *fh, + struct v4l2_streamparm *a) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + + if (ici->ops->get_parm) +@@ -1035,7 +1054,7 @@ static int soc_camera_g_parm(struct file *file, void *fh, + static int soc_camera_s_parm(struct file *file, void *fh, + struct v4l2_streamparm *a) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + + if (ici->ops->set_parm) +@@ -1047,7 +1066,7 @@ static int soc_camera_s_parm(struct file *file, void *fh, + static int soc_camera_g_edid(struct file *file, void *fh, + struct v4l2_edid *edid) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + + if (ici->ops->get_edid) +@@ -1060,7 +1079,7 @@ static int soc_camera_g_edid(struct file *file, void *fh, + static int soc_camera_g_register(struct file *file, void *priv, + struct v4l2_dbg_register *reg) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + + if (ici->ops->get_register) +@@ -1072,7 +1091,7 @@ static int soc_camera_g_register(struct file *file, void *priv, + static int soc_camera_s_register(struct file *file, void *priv, + const struct v4l2_dbg_register *reg) + { +- struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_device *icd = video_drvdata(file); + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + + if (ici->ops->set_register) +@@ -2040,6 +2059,13 @@ static int soc_camera_device_register(struct soc_camera_device *icd) + return 0; + } + ++static int soc_camera_subscribe_event(struct v4l2_fh *fh, ++ const struct v4l2_event_subscription *sub) ++{ ++ /* Just subscribe any event */ ++ return v4l2_event_subscribe(fh, sub, 16, NULL); ++} ++ + static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = { + .vidioc_querycap = soc_camera_querycap, + .vidioc_try_fmt_vid_cap = soc_camera_try_fmt_vid_cap, +@@ -2070,6 +2096,8 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = { + .vidioc_g_register = soc_camera_g_register, + .vidioc_s_register = soc_camera_s_register, + #endif ++ .vidioc_subscribe_event = soc_camera_subscribe_event, ++ .vidioc_unsubscribe_event = v4l2_event_unsubscribe, + }; + + static int video_dev_create(struct soc_camera_device *icd) +diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h +index 2e44f96..53c650d 100644 +--- a/include/media/soc_camera.h ++++ b/include/media/soc_camera.h +@@ -21,6 +21,10 @@ + #include + #include + #include ++#include ++ ++#define V4L2_EVENT_SOC_START_STREAM (V4L2_EVENT_PRIVATE_START + 1) ++#define V4L2_EVENT_SOC_PRIVATE_START (V4L2_EVENT_PRIVATE_START + 1) + + struct file; + struct soc_camera_desc; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0388-media-rcar-imr-Add-stride-support-to-IMR.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0388-media-rcar-imr-Add-stride-support-to-IMR.patch new file mode 100644 index 00000000..ba522ddb --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0388-media-rcar-imr-Add-stride-support-to-IMR.patch @@ -0,0 +1,216 @@ +From 48485fd8cc4049745e286d8a4d3617327e5551e8 Mon Sep 17 00:00:00 2001 +From: Konstantin Kozhevnikov +Date: Wed, 23 Jan 2019 08:07:38 -0800 +Subject: [PATCH 208/211] media: rcar-imr: Add stride support to IMR + +Add stride support to IMR + +Signed-off-by: Konstantin Kozhevnikov +--- + drivers/media/platform/rcar_imr.c | 96 ++++++++++++++++++++++++++++++--------- + 1 file changed, 74 insertions(+), 22 deletions(-) + +diff --git a/drivers/media/platform/rcar_imr.c b/drivers/media/platform/rcar_imr.c +index cdd847c..cb982b8 100644 +--- a/drivers/media/platform/rcar_imr.c ++++ b/drivers/media/platform/rcar_imr.c +@@ -418,28 +418,33 @@ static int imr_queue_setup(struct vb2_queue *vq, + { + struct imr_ctx *ctx = vb2_get_drv_priv(vq); + struct imr_q_data *q_data = &ctx->queue[V4L2_TYPE_IS_OUTPUT(vq->type) ? 0 : 1]; +- int w = q_data->fmt.width; ++ int s = q_data->fmt.bytesperline; + int h = q_data->fmt.height; + + /* ...we use only single-plane formats */ + *nplanes = 1; + ++ v4l2_dbg(1, debug, &ctx->imr->v4l2_dev, "format: %c%c%c%c, s=%d, h=%d\n", ++ (q_data->fmt.pixelformat >> 0) & 0xff, (q_data->fmt.pixelformat >> 8) & 0xff, ++ (q_data->fmt.pixelformat >> 16) & 0xff, (q_data->fmt.pixelformat >> 24) & 0xff, ++ s, h); ++ + /* ...specify plane size */ + switch (q_data->fmt.pixelformat) { + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_VYUY: + case V4L2_PIX_FMT_YVYU: +- case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_Y10: + case V4L2_PIX_FMT_Y12: + case V4L2_PIX_FMT_Y16: +- sizes[0] = w * h * 2; +- break; +- + case V4L2_PIX_FMT_UV8: + case V4L2_PIX_FMT_GREY: +- sizes[0] = w * h; ++ sizes[0] = s * h; ++ break; ++ ++ case V4L2_PIX_FMT_NV16: ++ sizes[0] = s * h * 2; + break; + + default: +@@ -782,8 +787,10 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg + u16 dst_uv_fmt = (cflags & IMR_F_UV12 ? 2 : (cflags & IMR_F_UV10 ? 1 : 0)) << IMR_CMR_DUV_SHIFT; + int w = ctx->queue[0].fmt.width; + int h = ctx->queue[0].fmt.height; ++ int s = ctx->queue[0].fmt.bytesperline; + int W = ctx->queue[1].fmt.width; + int H = ctx->queue[1].fmt.height; ++ int S = ctx->queue[1].fmt.bytesperline; + u32 tricr = ctx->color & 0xFFFFFF; + int i; + +@@ -856,15 +863,15 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg + *dl++ = IMR_OP_WTS(IMR_CMRCSR, src_y_fmt | src_uv_fmt | dst_y_fmt | dst_uv_fmt | __imr_luce(type) | __imr_clce(type)); + + /* ...set source/destination strides basing on Y-plane precision */ +- *dl++ = IMR_OP_WTS(IMR_DSTR, W << (cflags & IMR_F_Y10 ? 1 : 0)); +- *dl++ = IMR_OP_WTS(IMR_SSTR, w << (iflags & IMR_F_Y10 ? 1 : 0)); ++ *dl++ = IMR_OP_WTS(IMR_DSTR, S); ++ *dl++ = IMR_OP_WTS(IMR_SSTR, s); + } else { + /* ...setup UV-plane processing only */ + *dl++ = IMR_OP_WTS(IMR_CMRCSR, IMR_CMR_YCM | src_uv_fmt | dst_uv_fmt | __imr_clce(type) | __imr_luce(type)); + + /* ...set source/destination strides basing on UV-plane precision */ +- *dl++ = IMR_OP_WTS(IMR_DSTR, W << (cflags & IMR_F_UV10 ? 1 : 0)); +- *dl++ = IMR_OP_WTS(IMR_SSTR, w << (iflags & IMR_F_UV10 ? 1 : 0)); ++ *dl++ = IMR_OP_WTS(IMR_DSTR, S); ++ *dl++ = IMR_OP_WTS(IMR_SSTR, s); + } + } else { + u16 src_fmt = (iflags & IMR_F_UV_SWAP ? IMR_CMR2_UVFORM : 0) | (iflags & IMR_F_YUV_SWAP ? IMR_CMR2_YUV422FORM : 0); +@@ -879,19 +886,22 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg + *dl++ = IMR_OP_WTS(IMR_CMRCSR, src_y_fmt | src_uv_fmt | dst_y_fmt | dst_uv_fmt | __imr_clce(type) | __imr_luce(type)); + + /* ...set source stride basing on precision (2 or 4 bytes/pixel) */ +- *dl++ = IMR_OP_WTS(IMR_SSTR, w << (iflags & IMR_F_Y10 ? 2 : 1)); ++ *dl++ = IMR_OP_WTS(IMR_SSTR, s/* << (iflags & IMR_F_Y10 ? 2 : 1)*/); + + /* ...if output is planar, put the offset value */ + if (oflags & IMR_F_PLANAR) { + /* ...specify offset of a destination UV plane */ + *dl++ = IMR_OP_WTL(IMR_DSOR, 1); +- *dl++ = W * H; ++ *dl++ = S * H; ++ ++ /* ...force planar output */ ++ *dl++ = IMR_OP_WTS(IMR_CMRCSR, IMR_CMR_YISM); + + /* ...destination stride is 1 or 2 bytes/pixel (same for both Y and UV planes) */ +- *dl++ = IMR_OP_WTS(IMR_DSTR, W << (cflags & IMR_F_Y10 ? 1 : 0)); ++ *dl++ = IMR_OP_WTS(IMR_DSTR, S); + } else { + /* ...destination stride if 2 or 4 bytes/pixel (Y and UV planes interleaved) */ +- *dl++ = IMR_OP_WTS(IMR_DSTR, W << (cflags & IMR_F_Y10 ? 2 : 1)); ++ *dl++ = IMR_OP_WTS(IMR_DSTR, S); + } + } + +@@ -921,9 +931,6 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg + /* ...select correction mode */ + *dl++ = IMR_OP_WTS(IMR_CMRCSR, IMR_CMR_YCM | __imr_clce(type) | __imr_luce(type)); + +- /* ...luminance correction bit must be cleared (if it was set) */ +- //*dl++ = IMR_OP_WTS(IMR_CMRCCR, IMR_CMR_LUCE); +- + /* ...draw triangles */ + *dl++ = IMR_OP_GOSUB; + *dl++ = subaddr; +@@ -1226,6 +1233,43 @@ static int imr_extstride_set(struct imr_ctx *ctx, struct imr_rse_param *param) + * V4L2 I/O controls + ******************************************************************************/ + ++/* ...check the format stride */ ++static inline int __imr_verify_fmt_stride(struct v4l2_pix_format *pix) ++{ ++ int stride; ++ ++ switch (pix->pixelformat) { ++ case V4L2_PIX_FMT_NV16: ++ case V4L2_PIX_FMT_GREY: ++ case V4L2_PIX_FMT_UV8: ++ /* ...single byte per pixel */ ++ stride = pix->width; ++ break; ++ ++ case V4L2_PIX_FMT_UYVY: ++ case V4L2_PIX_FMT_VYUY: ++ case V4L2_PIX_FMT_YUYV: ++ case V4L2_PIX_FMT_YVYU: ++ case V4L2_PIX_FMT_Y10: ++ case V4L2_PIX_FMT_Y12: ++ /* ...two bytes per pixel */ ++ stride = pix->width * 2; ++ break; ++ ++ default: ++ /* ...unsupported format */ ++ return -1; ++ } ++ ++ if (pix->bytesperline) ++ return (pix->bytesperline >= stride ? 0 : -1); ++ ++ /* ...no stride is specified; use default one */ ++ pix->bytesperline = stride; ++ ++ return 0; ++} ++ + /* ...test for a format supported */ + static int __imr_try_fmt(struct imr_ctx *ctx, struct v4l2_format *f) + { +@@ -1233,22 +1277,30 @@ static int __imr_try_fmt(struct imr_ctx *ctx, struct v4l2_format *f) + u32 fourcc = pix->pixelformat; + int i; + ++ /* ...fix-up format stride if needed */ ++ if (__imr_verify_fmt_stride(pix) < 0) ++ return -EINVAL; ++ + /* ...both output and capture interface have the same set of supported formats */ + for (i = 0; i < ARRAY_SIZE(imr_lx4_formats); i++) { + if (fourcc == imr_lx4_formats[i].fourcc) { + /* ...fix-up format specification as needed */ + pix->field = V4L2_FIELD_NONE; + +- v4l2_dbg(1, debug, &ctx->imr->v4l2_dev, "format request: '%c%c%c%c', %d*%d\n", ++ v4l2_dbg(1, debug, &ctx->imr->v4l2_dev, "%s-format request: '%c%c%c%c', %d*%d\n", ++ (V4L2_TYPE_IS_OUTPUT(f->type) ? "output" : "capture"), + (fourcc >> 0) & 0xff, (fourcc >> 8) & 0xff, + (fourcc >> 16) & 0xff, (fourcc >> 24) & 0xff, + pix->width, pix->height); + + /* ...verify source/destination image dimensions */ + if (V4L2_TYPE_IS_OUTPUT(f->type)) +- v4l_bound_align_image(&pix->width, 128, 2048, 7, &pix->height, 1, 2048, 0, 0); ++ v4l_bound_align_image(&pix->bytesperline, 256, 8192, 8, &pix->height, 1, 2048, 0, 0); + else +- v4l_bound_align_image(&pix->width, 64, 2048, 6, &pix->height, 1, 2048, 0, 0); ++ v4l_bound_align_image(&pix->bytesperline, 64, 8192, 6, &pix->height, 1, 2048, 0, 0); ++ ++ /* ...verify width is not exceeding the maximal value */ ++ (pix->width > 2048 ? pix->width = 2048 : 0); + + return i; + } +@@ -1751,8 +1803,8 @@ static void imr_device_run(void *priv) + + /* ...adjust source/destination parameters of the UV-plane as needed */ + if (cfg->src_pa_ptr[1] && cfg->dst_pa_ptr[1]) { +- *cfg->src_pa_ptr[1] = src_addr + ctx->queue[0].fmt.width * ctx->queue[0].fmt.height; +- *cfg->dst_pa_ptr[1] = dst_addr + ctx->queue[1].fmt.width * ctx->queue[1].fmt.height; ++ *cfg->src_pa_ptr[1] = src_addr + ctx->queue[0].fmt.bytesperline * ctx->queue[0].fmt.height; ++ *cfg->dst_pa_ptr[1] = dst_addr + ctx->queue[1].fmt.bytesperline * ctx->queue[1].fmt.height; + } + + v4l2_dbg(3, debug, &imr->v4l2_dev, "process buffer-pair 0x%08x:0x%08x\n", +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0389-arm64-renesas-r8a77980-VB-use-REFCLK-23.0MHZ.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0389-arm64-renesas-r8a77980-VB-use-REFCLK-23.0MHZ.patch new file mode 100644 index 00000000..31536c8e --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0389-arm64-renesas-r8a77980-VB-use-REFCLK-23.0MHZ.patch @@ -0,0 +1,78 @@ +From 0e76e0d714d4da7b4572c915fc588d111ac659e6 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Thu, 7 Feb 2019 11:44:37 +0300 +Subject: [PATCH 209/211] arm64: renesas: r8a77980: VB: use REFCLK=23.0MHZ + +This fixes data integrity on FPDLink + +Signed-off-by: Vladimir Barinov +--- + arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts | 2 +- + arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts | 10 +++++----- + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts +index cb9cd54..81f9edb 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts +@@ -324,7 +324,7 @@ + clock-names = "clk_in"; + + assigned-clocks = <&cs2300>; +- assigned-clock-rates = <23500000>; ++ assigned-clock-rates = <23000000>; + }; + }; + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts +index f23f2d0..8749c94 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts +@@ -115,7 +115,7 @@ + csi40_ep: endpoint { + clock-lanes = <0>; + data-lanes = <1 2 3 4>; +- csi-rate = <1450>; ++ csi-rate = <1500>; + }; + }; + }; +@@ -130,7 +130,7 @@ + csi41_ep: endpoint { + clock-lanes = <0>; + data-lanes = <1 2 3 4>; +- csi-rate = <1450>; ++ csi-rate = <1500>; + }; + }; + }; +@@ -267,7 +267,7 @@ + }; + port@1 { + ti9x4_csi0ep0: endpoint { +- csi-rate = <1450>; ++ csi-rate = <1500>; + remote-endpoint = <&csi40_ep>; + }; + }; +@@ -425,7 +425,7 @@ + }; + port@1 { + ti9x4_csi1ep0: endpoint { +- csi-rate = <1450>; ++ csi-rate = <1500>; + remote-endpoint = <&csi41_ep>; + }; + }; +@@ -447,7 +447,7 @@ + clock-names = "clk_in"; + + assigned-clocks = <&cs2300>; +- assigned-clock-rates = <22500000>; ++ assigned-clock-rates = <23000000>; + }; + + gpio_exp_ch1: gpio_ch1@6c { +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0390-arm64-dts-renesas-Add-V3x-VideoBox-FDPLink-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0390-arm64-dts-renesas-Add-V3x-VideoBox-FDPLink-support.patch new file mode 100644 index 00000000..f732d366 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0390-arm64-dts-renesas-Add-V3x-VideoBox-FDPLink-support.patch @@ -0,0 +1,123 @@ +From 902c01c2b4f805de45d93e7551ee7204576aadf9 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Wed, 17 Apr 2019 23:19:53 +0300 +Subject: [PATCH 210/211] arm64: dts: renesas: Add V3x VideoBox FDPLink support + +This adds "vb-fdplink-output.dtsi" and includes it +in the V3x VideoBox device trees. FDPLink is disabled +by default. Uncomment the include directive in order +to enable it. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm.dts | 2 ++ + .../boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts | 2 ++ + .../boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts | 2 ++ + arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm.dts | 2 ++ + arch/arm64/boot/dts/renesas/vb-fdplink-output.dtsi | 42 ++++++++++++++++++++++ + 5 files changed, 50 insertions(+) + create mode 100644 arch/arm64/boot/dts/renesas/vb-fdplink-output.dtsi + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm.dts +index 485de2a..f65ebeb 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm.dts +@@ -10,6 +10,8 @@ + + #include "r8a77970-v3msk.dts" + #include ++/* FDPLink output */ ++//#include "vb-fdplink-output.dtsi" + + / { + model = "Renesas V3MSK Videobox Mini board based on r8a77970"; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts +index 81f9edb..12ef357 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts +@@ -10,6 +10,8 @@ + + #include "r8a77980-v3hsk.dts" + #include ++/* FDPLink output */ ++//#include "vb-fdplink-output.dtsi" + + / { + model = "Renesas V3HSK 4ch Videobox board based on r8a7798"; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts +index 8749c94..861b90f 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts +@@ -10,6 +10,8 @@ + + #include "r8a77980-v3hsk.dts" + #include ++/* FDPLink output */ ++//#include "vb-fdplink-output.dtsi" + + / { + model = "Renesas V3HSK 4ch Videobox board based on r8a7798"; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm.dts +index e362045..f5eb597 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm.dts +@@ -10,6 +10,8 @@ + + #include "r8a77980-v3hsk.dts" + #include ++/* FDPLink output */ ++//#include "vb-fdplink-output.dtsi" + + / { + model = "Renesas V3HSK Videobox Mini board based on r8a7798"; +diff --git a/arch/arm64/boot/dts/renesas/vb-fdplink-output.dtsi b/arch/arm64/boot/dts/renesas/vb-fdplink-output.dtsi +new file mode 100644 +index 0000000..b166843 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/vb-fdplink-output.dtsi +@@ -0,0 +1,42 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Device Tree Source for VideoBox FDPLink output. ++ * ++ * Copyright (C) 2019 Renesas Electronics Corp. ++ * Copyright (C) 2019 Cogent Embedded, Inc. ++ */ ++ ++/ { ++ lvds: lvds { ++ compatible = "panel-lvds"; ++ ++ data-mapping = "jeida-24"; ++ ++ width-mm = <210>; ++ height-mm = <158>; ++ ++ panel-timing { ++ /* 1280x800 @60Hz */ ++ clock-frequency = <65000000>; ++ hactive = <1280>; ++ vactive = <800>; ++ hsync-len = <40>; ++ hfront-porch = <80>; ++ hback-porch = <40>; ++ vfront-porch = <14>; ++ vback-porch = <14>; ++ vsync-len = <4>; ++ }; ++ ++ port { ++ lvds_in: endpoint { ++ remote-endpoint = <&du_out_lvds0>; ++ }; ++ }; ++ }; ++}; ++ ++&lvds0_out { ++ /* FDPLink output */ ++ remote-endpoint = <&lvds_in>; ++}; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0391-arm64-dts-renesas-Enable-FDPLink-output-on-V3x-Video.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0391-arm64-dts-renesas-Enable-FDPLink-output-on-V3x-Video.patch new file mode 100644 index 00000000..d09c9875 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0391-arm64-dts-renesas-Enable-FDPLink-output-on-V3x-Video.patch @@ -0,0 +1,71 @@ +From c474a429fcdbe8c68cf87e4c2410840b85cb3627 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Wed, 17 Apr 2019 23:28:56 +0300 +Subject: [PATCH 211/211] arm64: dts: renesas: Enable FDPLink output on V3x + VideoBox + +This enables FDPLink output on all V3x VideoBox boards. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm.dts | 2 +- + arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts | 2 +- + arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts | 2 +- + arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm.dts | 2 +- + 4 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm.dts +index f65ebeb..8d7ec04 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk-vbm.dts +@@ -11,7 +11,7 @@ + #include "r8a77970-v3msk.dts" + #include + /* FDPLink output */ +-//#include "vb-fdplink-output.dtsi" ++#include "vb-fdplink-output.dtsi" + + / { + model = "Renesas V3MSK Videobox Mini board based on r8a77970"; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts +index 12ef357..bca9014 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-4ch.dts +@@ -11,7 +11,7 @@ + #include "r8a77980-v3hsk.dts" + #include + /* FDPLink output */ +-//#include "vb-fdplink-output.dtsi" ++#include "vb-fdplink-output.dtsi" + + / { + model = "Renesas V3HSK 4ch Videobox board based on r8a7798"; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts +index 861b90f..1ef6b11 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vb-8ch.dts +@@ -11,7 +11,7 @@ + #include "r8a77980-v3hsk.dts" + #include + /* FDPLink output */ +-//#include "vb-fdplink-output.dtsi" ++#include "vb-fdplink-output.dtsi" + + / { + model = "Renesas V3HSK 4ch Videobox board based on r8a7798"; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm.dts +index f5eb597..ea3d9e9 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk-vbm.dts +@@ -11,7 +11,7 @@ + #include "r8a77980-v3hsk.dts" + #include + /* FDPLink output */ +-//#include "vb-fdplink-output.dtsi" ++#include "vb-fdplink-output.dtsi" + + / { + model = "Renesas V3HSK Videobox Mini board based on r8a7798"; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0392-gpu-drm-bridge-thc63-Set-upper-clock-limit-to-150-MH.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0392-gpu-drm-bridge-thc63-Set-upper-clock-limit-to-150-MH.patch new file mode 100644 index 00000000..4160402a --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0392-gpu-drm-bridge-thc63-Set-upper-clock-limit-to-150-MH.patch @@ -0,0 +1,32 @@ +From e97955f52cf6d797ce4a4e6c9c27f96ecac77798 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Wed, 3 Jul 2019 17:24:01 +0300 +Subject: [PATCH] gpu: drm: bridge: thc63: Set upper clock limit to 150 MHz + +Commit "drm: bridge: thc63: Restrict modes based on hardware +operating frequency" limits the maximum resolution to 1280x1024 +on the V3[HM] boards. Clock frequency is set to 138-148.5 MHz +for the FullHD resolution. This sets maximum clock frequency +to 150MHz to allow FullHD modes. + +Signed-off-by: Valentine Barshak +--- + drivers/gpu/drm/bridge/thc63lvd1024.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/bridge/thc63lvd1024.c b/drivers/gpu/drm/bridge/thc63lvd1024.c +index cc44f37..0f3ad8b 100644 +--- a/drivers/gpu/drm/bridge/thc63lvd1024.c ++++ b/drivers/gpu/drm/bridge/thc63lvd1024.c +@@ -55,7 +55,7 @@ static enum drm_mode_status thc63_mode_valid(struct drm_bridge *bridge, + if (mode->clock < 8000) + return MODE_CLOCK_LOW; + +- if (mode->clock > 135000) ++ if (mode->clock > 150000) + return MODE_CLOCK_HIGH; + + /* Refresh rate 30 or less of full HD is basically not used, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0393-media-soc_camera-dummy-add-mbus-controls-ids.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0393-media-soc_camera-dummy-add-mbus-controls-ids.patch new file mode 100644 index 00000000..7f72578d --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0393-media-soc_camera-dummy-add-mbus-controls-ids.patch @@ -0,0 +1,338 @@ +From e0b7cbaad7f2cea64239929ac96af234027bd19f Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Mon, 17 Jun 2019 23:19:20 +0300 +Subject: [PATCH] media: soc_camera: dummy: add mbus, controls, ids + +This add different media buses, controls, otp ids and +module params + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/dummy.c | 216 +++++++++++++++++++++++++++++++---- + 1 file changed, 195 insertions(+), 21 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/dummy.c b/drivers/media/i2c/soc_camera/dummy.c +index a38d7c4..d213fff 100644 +--- a/drivers/media/i2c/soc_camera/dummy.c ++++ b/drivers/media/i2c/soc_camera/dummy.c +@@ -20,17 +20,30 @@ + #include + #include + +-#define MEDIA_BUS_FORMAT MEDIA_BUS_FMT_YUYV8_2X8 +- + struct dummy_priv { + struct v4l2_subdev sd; + struct v4l2_ctrl_handler hdl; + struct media_pad pad; + struct v4l2_rect rect; ++ u8 id[6]; + int max_width; + int max_height; ++ const char * media_bus_format; ++ int mbus_format; + }; + ++static int width = 1920; ++module_param(width, int, 0644); ++MODULE_PARM_DESC(width, " width (default: 1920)"); ++ ++static int height = 1080; ++module_param(height, int, 0644); ++MODULE_PARM_DESC(height, " height (default: 1080)"); ++ ++static char *mbus = "yuyv"; ++module_param(mbus, charp, 0644); ++MODULE_PARM_DESC(mbus, " MEDIA_BUS_FORMAT (default: YUYV)"); ++ + static inline struct dummy_priv *to_dummy(const struct i2c_client *client) + { + return container_of(i2c_get_clientdata(client), struct dummy_priv, sd); +@@ -59,7 +72,7 @@ static int dummy_get_fmt(struct v4l2_subdev *sd, + + mf->width = priv->rect.width; + mf->height = priv->rect.height; +- mf->code = MEDIA_BUS_FORMAT; ++ mf->code = priv->mbus_format; + mf->colorspace = V4L2_COLORSPACE_SMPTE170M; + mf->field = V4L2_FIELD_NONE; + +@@ -71,8 +84,10 @@ static int dummy_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_format *format) + { + struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct dummy_priv *priv = to_dummy(client); + +- mf->code = MEDIA_BUS_FORMAT; ++ mf->code = priv->mbus_format; + mf->colorspace = V4L2_COLORSPACE_SMPTE170M; + mf->field = V4L2_FIELD_NONE; + +@@ -86,10 +101,28 @@ static int dummy_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *code) + { ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct dummy_priv *priv = to_dummy(client); ++ + if (code->pad || code->index > 0) + return -EINVAL; + +- code->code = MEDIA_BUS_FORMAT; ++ code->code = priv->mbus_format; ++ ++ return 0; ++} ++ ++static int dummy_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct dummy_priv *priv = to_dummy(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = 'D' >> 8; ++ edid->edid[9] = 'Y' & 0xff; + + return 0; + } +@@ -164,9 +197,50 @@ static int dummy_g_mbus_config(struct v4l2_subdev *sd, + return 0; + } + ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int dummy_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ reg->val = 0; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int dummy_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ return 0; ++} ++#endif ++ ++static struct v4l2_subdev_core_ops dummy_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = dummy_g_register, ++ .s_register = dummy_s_register, ++#endif ++}; ++ + static int dummy_s_ctrl(struct v4l2_ctrl *ctrl) + { +- return -EINVAL; ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ case V4L2_CID_CONTRAST: ++ case V4L2_CID_SATURATION: ++ case V4L2_CID_HUE: ++ case V4L2_CID_GAMMA: ++ case V4L2_CID_SHARPNESS: ++ case V4L2_CID_AUTOGAIN: ++ case V4L2_CID_GAIN: ++ case V4L2_CID_ANALOGUE_GAIN: ++ case V4L2_CID_EXPOSURE: ++ case V4L2_CID_HFLIP: ++ case V4L2_CID_VFLIP: ++ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: ++ break; ++ } ++ ++ return 0; + } + + static const struct v4l2_ctrl_ops dummy_ctrl_ops = { +@@ -179,6 +253,7 @@ static struct v4l2_subdev_video_ops dummy_video_ops = { + }; + + static const struct v4l2_subdev_pad_ops dummy_subdev_pad_ops = { ++ .get_edid = dummy_get_edid, + .enum_mbus_code = dummy_enum_mbus_code, + .get_selection = dummy_get_selection, + .set_selection = dummy_set_selection, +@@ -187,38 +262,107 @@ static const struct v4l2_subdev_pad_ops dummy_subdev_pad_ops = { + }; + + static struct v4l2_subdev_ops dummy_subdev_ops = { ++ .core = &dummy_core_ops, + .video = &dummy_video_ops, + .pad = &dummy_subdev_pad_ops, + }; + ++static void dummy_otp_id_read(struct i2c_client *client) ++{ ++ struct dummy_priv *priv = to_dummy(client); ++ ++ /* dummy camera id */ ++ priv->id[0] = 'd'; ++ priv->id[1] = 'u'; ++ priv->id[2] = 'm'; ++ priv->id[3] = 'm'; ++ priv->id[4] = 'y'; ++ priv->id[5] = '.'; ++} ++ ++static ssize_t dummy_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct dummy_priv *priv = to_dummy(client); ++ ++ dummy_otp_id_read(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_dummy, S_IRUGO, dummy_otp_id_show, NULL); ++ + static int dummy_initialize(struct i2c_client *client) + { + struct dummy_priv *priv = to_dummy(client); + +- dev_info(&client->dev, "Dummy sensor res %dx%d\n", priv->max_width, priv->max_height); ++ if (strcmp(priv->media_bus_format, "yuyv") == 0) ++ priv->mbus_format = MEDIA_BUS_FMT_YUYV8_2X8; ++ else if (strcmp(priv->media_bus_format, "uyvy") == 0) ++ priv->mbus_format = MEDIA_BUS_FMT_UYVY8_2X8; ++ else if (strcmp(priv->media_bus_format, "grey") == 0) ++ priv->mbus_format = MEDIA_BUS_FMT_Y8_1X8; ++ else if (strcmp(priv->media_bus_format, "rggb8") == 0) ++ priv->mbus_format = MEDIA_BUS_FMT_SRGGB8_1X8; ++ else if (strcmp(priv->media_bus_format, "bggr8") == 0) ++ priv->mbus_format = MEDIA_BUS_FMT_SBGGR8_1X8; ++ else if (strcmp(priv->media_bus_format, "grbg8") == 0) ++ priv->mbus_format = MEDIA_BUS_FMT_SGRBG8_1X8; ++ else if (strcmp(priv->media_bus_format, "rggb12") == 0) ++ priv->mbus_format = MEDIA_BUS_FMT_SRGGB12_1X12; ++ else if (strcmp(priv->media_bus_format, "bggr12") == 0) ++ priv->mbus_format = MEDIA_BUS_FMT_SBGGR12_1X12; ++ else if (strcmp(priv->media_bus_format, "grbg12") == 0) ++ priv->mbus_format = MEDIA_BUS_FMT_SGRBG12_1X12; ++ else if (strcmp(priv->media_bus_format, "rggb14") == 0) ++ priv->mbus_format = MEDIA_BUS_FMT_SRGGB14_1X14; ++ else if (strcmp(priv->media_bus_format, "bggr14") == 0) ++ priv->mbus_format = MEDIA_BUS_FMT_SBGGR14_1X14; ++ else if (strcmp(priv->media_bus_format, "grbg14") == 0) ++ priv->mbus_format = MEDIA_BUS_FMT_SGRBG14_1X14; ++ else if (strcmp(priv->media_bus_format, "rggb16") == 0) ++ priv->mbus_format = MEDIA_BUS_FMT_SRGGB16_1X16; ++ else if (strcmp(priv->media_bus_format, "bggr16") == 0) ++ priv->mbus_format = MEDIA_BUS_FMT_SBGGR16_1X16; ++ else if (strcmp(priv->media_bus_format, "grbg16") == 0) ++ priv->mbus_format = MEDIA_BUS_FMT_SGRBG16_1X16; ++ else { ++ v4l_err(client, "failed to parse mbus format (%s)\n", priv->media_bus_format); ++ return -EINVAL; ++ } ++ ++ /* Read OTP IDs */ ++ dummy_otp_id_read(client); ++ ++ dev_info(&client->dev, "Dummy camera sensor, res %dx%d, mbus %s, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->max_width, priv->max_height, priv->media_bus_format, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); + + return 0; + } + + static int dummy_parse_dt(struct device_node *np, struct dummy_priv *priv) + { +- struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); +- int err; ++ if (of_property_read_u32(np, "dummy,width", &priv->max_width)) ++ priv->max_width = width; + +- err = of_property_read_u32(np, "dummy,width", &priv->max_width); +- if (err) { +- dev_err(&client->dev, "dummy,width must be defined\n"); +- goto out; +- } ++ if (of_property_read_u32(np, "dummy,height", &priv->max_height)) ++ priv->max_height = height; + +- err = of_property_read_u32(np, "dummy,height", &priv->max_height); +- if (err) { +- dev_err(&client->dev, "dummy,height must be defined\n"); +- goto out; +- } ++ if (of_property_read_string(np, "dummy,mbus", &priv->media_bus_format)) ++ priv->media_bus_format = mbus; + +-out: +- return err; ++ /* module params override dts */ ++ if (strcmp(mbus, "yuyv")) ++ priv->media_bus_format = mbus; ++ if (width != 1920) ++ priv->max_width = width; ++ if (height != 1080) ++ priv->max_height = height; ++ ++ return 0; + } + + static int dummy_probe(struct i2c_client *client, +@@ -235,6 +379,30 @@ static int dummy_probe(struct i2c_client *client, + priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; + + v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &dummy_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &dummy_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &dummy_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &dummy_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &dummy_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &dummy_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &dummy_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &dummy_ctrl_ops, ++ V4L2_CID_GAIN, 1, 0x7ff, 1, 0x200); ++ v4l2_ctrl_new_std(&priv->hdl, &dummy_ctrl_ops, ++ V4L2_CID_ANALOGUE_GAIN, 1, 0xe, 1, 0xa); ++ v4l2_ctrl_new_std(&priv->hdl, &dummy_ctrl_ops, ++ V4L2_CID_EXPOSURE, 1, 0x600, 1, 0x144); ++ v4l2_ctrl_new_std(&priv->hdl, &dummy_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &dummy_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); + priv->sd.ctrl_handler = &priv->hdl; + + ret = priv->hdl.error; +@@ -266,6 +434,11 @@ static int dummy_probe(struct i2c_client *client, + if (ret) + goto cleanup; + ++ if (device_create_file(&client->dev, &dev_attr_otp_id_dummy) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ + return 0; + + cleanup: +@@ -281,6 +454,7 @@ static int dummy_remove(struct i2c_client *client) + { + struct dummy_priv *priv = i2c_get_clientdata(client); + ++ device_remove_file(&client->dev, &dev_attr_otp_id_dummy); + v4l2_async_unregister_subdev(&priv->sd); + media_entity_cleanup(&priv->sd.entity); + v4l2_ctrl_handler_free(&priv->hdl); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0394-media-i2c-ar0233-fix-superexposure.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0394-media-i2c-ar0233-fix-superexposure.patch new file mode 100644 index 00000000..aafe1f83 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0394-media-i2c-ar0233-fix-superexposure.patch @@ -0,0 +1,31 @@ +From 97424dd7f393ad1d44827062b59c3957369d60a0 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Mon, 1 Jul 2019 15:29:47 +0300 +Subject: [PATCH] media: i2c: ar0233: fix superexposure + +This fixes superexposure mode for imager 27Mhz REFCLK + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ar0233.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/i2c/soc_camera/ar0233.c b/drivers/media/i2c/soc_camera/ar0233.c +index f3b899e..1b7ba22 100644 +--- a/drivers/media/i2c/soc_camera/ar0233.c ++++ b/drivers/media/i2c/soc_camera/ar0233.c +@@ -436,8 +436,10 @@ static int ar0233_initialize(struct i2c_client *client) + ar0233_set_regs(client, ar0233_regs_hdr_mipi_12bit_30fps_rev1); + break; + case 0x2: +- if (extclk == 27) ++ if (extclk == 27) { + ar0233_regs_hdr_mipi_12bit_30fps_rev2[4] = ar0233_rev2_pll_27_102_4lane_12b; ++ ar0233_regs_seplus_mipi_12bit_30fps_rev2[2] = ar0233_rev2_pll_27_102_4lane_12b; ++ } + + if (strcmp(mode, "hdr") == 0) + ar0233_set_regs(client, ar0233_regs_hdr_mipi_12bit_30fps_rev2); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0395-media-i2c-ap0101-add-V-H-flip.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0395-media-i2c-ap0101-add-V-H-flip.patch new file mode 100644 index 00000000..eb2f9739 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0395-media-i2c-ap0101-add-V-H-flip.patch @@ -0,0 +1,63 @@ +From 2fa25532f64b6c7706b523476316490c60384db2 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Tue, 2 Jul 2019 15:49:39 +0300 +Subject: [PATCH] media: i2c: ap0101: add V/H flip + +This adds image mirror and flip + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ap0101_ar014x.c | 21 ++++++++++++++++++++- + 1 file changed, 20 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/i2c/soc_camera/ap0101_ar014x.c b/drivers/media/i2c/soc_camera/ap0101_ar014x.c +index e4f2bda..03b50e9 100644 +--- a/drivers/media/i2c/soc_camera/ap0101_ar014x.c ++++ b/drivers/media/i2c/soc_camera/ap0101_ar014x.c +@@ -306,6 +306,7 @@ static int ap0101_s_ctrl(struct v4l2_ctrl *ctrl) + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ap0101_priv *priv = to_ap0101(client); + int ret = -EINVAL; ++ u16 val = 0; + + if (!priv->init_complete) + return 0; +@@ -320,8 +321,26 @@ static int ap0101_s_ctrl(struct v4l2_ctrl *ctrl) + case V4L2_CID_AUTOGAIN: + case V4L2_CID_GAIN: + case V4L2_CID_EXPOSURE: ++ break; + case V4L2_CID_HFLIP: ++ reg16_read16(client, 0xc846, &val); ++ if (ctrl->val) ++ val |= 0x01; ++ else ++ val &= ~0x01; ++ reg16_write16(client, 0xc846, val); ++ reg16_write16(client, 0xfc00, 0x2800); ++ ret = reg16_write16(client, 0x0040, 0x8100); ++ break; + case V4L2_CID_VFLIP: ++ reg16_read16(client, 0xc846, &val); ++ if (ctrl->val) ++ val |= 0x02; ++ else ++ val &= ~0x02; ++ reg16_write16(client, 0xc846, val); ++ reg16_write16(client, 0xfc00, 0x2800); ++ ret = reg16_write16(client, 0x0040, 0x8100); + break; + } + +@@ -558,7 +577,7 @@ static int ap0101_probe(struct i2c_client *client, + v4l2_ctrl_new_std(&priv->hdl, &ap0101_ctrl_ops, + V4L2_CID_HFLIP, 0, 1, 1, 1); + v4l2_ctrl_new_std(&priv->hdl, &ap0101_ctrl_ops, +- V4L2_CID_VFLIP, 0, 1, 1, 0); ++ V4L2_CID_VFLIP, 0, 1, 1, 1); + priv->sd.ctrl_handler = &priv->hdl; + + ret = priv->hdl.error; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0396-media-i2c-ap0101-ar014x-get-OTP-more-complex.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0396-media-i2c-ap0101-ar014x-get-OTP-more-complex.patch new file mode 100644 index 00000000..a7be90d8 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0396-media-i2c-ap0101-ar014x-get-OTP-more-complex.patch @@ -0,0 +1,72 @@ +From bb5a3717068ec667d316a051354b4edff069bf33 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Fri, 5 Jul 2019 14:04:11 +0300 +Subject: [PATCH] media: i2c: ap0101-ar014x: get OTP more complex + +Involve more OTP bytes for ID to reduce the chance of similar OTP_IDs + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ap0101_ar014x.c | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ap0101_ar014x.c b/drivers/media/i2c/soc_camera/ap0101_ar014x.c +index 03b50e9..74e6e51 100644 +--- a/drivers/media/i2c/soc_camera/ap0101_ar014x.c ++++ b/drivers/media/i2c/soc_camera/ap0101_ar014x.c +@@ -97,16 +97,16 @@ static u16 ap0101_ar014x_read(struct i2c_client *client, u16 addr) + u16 reg_val = 0; + + reg16_write16(client, 0x0040, 0x8d00); +- usleep_range(100, 150); /* wait 100 us */ ++ usleep_range(1000, 1500); /* wait 1000 us */ + reg16_write16(client, 0xfc00, addr); + reg16_write16(client, 0xfc02, 0x0200); /* 2 bytes */ + reg16_write16(client, 0x0040, 0x8d05); +- usleep_range(100, 150); /* wait 100 us */ ++ usleep_range(1000, 1500); /* wait 1000 us */ + reg16_write16(client, 0x0040, 0x8d08); +- usleep_range(100, 150); /* wait 100 us */ ++ usleep_range(1000, 1500); /* wait 1000 us */ + reg16_read16(client, 0xfc00, ®_val); + reg16_write16(client, 0x0040, 0x8d02); +- usleep_range(100, 150); /* wait 100 us */ ++ usleep_range(1000, 1500); /* wait 1000 us */ + + return reg_val; + } +@@ -114,16 +114,16 @@ static u16 ap0101_ar014x_read(struct i2c_client *client, u16 addr) + static void ap0101_ar014x_write(struct i2c_client *client, u16 addr, u16 val) + { + reg16_write16(client, 0x0040, 0x8d00); +- usleep_range(100, 150); /* wait 100 us */ ++ usleep_range(1000, 1500); /* wait 1000 us */ + reg16_write16(client, 0xfc00, addr); + reg16_write16(client, 0xfc02, 0x0200 | (val >> 8)); /* 2 bytes */ + reg16_write16(client, 0xfc04, (val & 0xff) << 8); + reg16_write16(client, 0x0040, 0x8d06); +- usleep_range(100, 150); /* wait 100 us */ ++ usleep_range(1000, 1500); /* wait 1000 us */ + reg16_write16(client, 0x0040, 0x8d08); +- usleep_range(100, 150); /* wait 100 us */ ++ usleep_range(1000, 1500); /* wait 1000 us */ + reg16_write16(client, 0x0040, 0x8d02); +- usleep_range(100, 150); /* wait 100 us */ ++ usleep_range(1000, 1500); /* wait 1000 us */ + } + + static int ap0101_s_stream(struct v4l2_subdev *sd, int enable) +@@ -383,8 +383,8 @@ static void ap0101_otp_id_read(struct i2c_client *client) + + for (i = 0; i < 6; i += 2) { + /* first 4 bytes are equal on all ar014x */ +- priv->id[i] = ap0101_ar014x_read(client, 0x3800 + i + 4) >> 8; +- priv->id[i + 1] = ap0101_ar014x_read(client, 0x3800 + i + 4) & 0xff; ++ priv->id[i] = (ap0101_ar014x_read(client, 0x3800 + i + 4) >> 8) ^ (ap0101_ar014x_read(client, 0x3800 + i + 16) >> 8); ++ priv->id[i + 1] = (ap0101_ar014x_read(client, 0x3800 + i + 4) & 0xff) ^ (ap0101_ar014x_read(client, 0x3800 + i + 16) & 0xff); + } + } + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0397-media-i2c-ar0147-add-mipi-rev3-lvds-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0397-media-i2c-ar0147-add-mipi-rev3-lvds-support.patch new file mode 100644 index 00000000..c0d55d98 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0397-media-i2c-ar0147-add-mipi-rev3-lvds-support.patch @@ -0,0 +1,1083 @@ +From 04fdc5dcea8695045c7c00d6ea1f6d9594afbd89 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Wed, 10 Jul 2019 00:08:47 +0300 +Subject: [PATCH] media: i2c: ar0147: add mipi, rev3, lvds support + +This adds DVP/MIPI interfaces, silicon rev3 and +possibility to use serializers with this imager + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ar0147.c | 53 +- + drivers/media/i2c/soc_camera/ar0147.h | 1 + + drivers/media/i2c/soc_camera/ar0147_rev3.h | 886 +++++++++++++++++++++++++++++ + drivers/media/i2c/soc_camera/ov106xx.c | 11 + + 4 files changed, 948 insertions(+), 3 deletions(-) + create mode 100644 drivers/media/i2c/soc_camera/ar0147_rev3.h + +diff --git a/drivers/media/i2c/soc_camera/ar0147.c b/drivers/media/i2c/soc_camera/ar0147.c +index cc4e761..563708c 100644 +--- a/drivers/media/i2c/soc_camera/ar0147.c ++++ b/drivers/media/i2c/soc_camera/ar0147.c +@@ -49,21 +49,33 @@ struct ar0147_priv { + int hts; + int vts; + int frame_preamble; ++ int trigger; + }; + ++#ifdef CONFIG_SOC_CAMERA_AR0147 ++static int trigger = 0; ++module_param(trigger, int, 0644); ++MODULE_PARM_DESC(trigger, " Trigger gpio number (default: 0 - GPIO0) "); ++ + static char *mode = "hdr"; + module_param(mode, charp, 0644); + MODULE_PARM_DESC(mode, " Modes linear,hdr,se,seplus (default: hdr)"); ++#endif ++static char *mbus = "mipi"; ++module_param(mbus, charp, 0644); ++MODULE_PARM_DESC(mbus, " Interfaces mipi,dvp (default: mipi)"); + + static inline struct ar0147_priv *to_ar0147(const struct i2c_client *client) + { + return container_of(i2c_get_clientdata(client), struct ar0147_priv, sd); + } + ++#ifdef CONFIG_SOC_CAMERA_AR0147 + static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) + { + return &container_of(ctrl->handler, struct ar0147_priv, hdl)->sd; + } ++#endif + + static void ar0147_s_port(struct i2c_client *client, int fwd_en) + { +@@ -463,7 +475,7 @@ static int ar0147_initialize(struct i2c_client *client) + reg16_read16(client, AR0147_PID, &pid); + + if (pid != AR0147_VERSION_REG) { +- dev_dbg(&client->dev, "Product ID error %x\n\n\n", pid); ++ dev_dbg(&client->dev, "Product ID error %x\n", pid); + ret = -ENODEV; + goto err; + } +@@ -485,6 +497,16 @@ static int ar0147_initialize(struct i2c_client *client) + else + dev_err(&client->dev, "Unsupported mode %s\n", mode); + break; ++ case 0x3: ++ if (strcmp(mode, "hdr") == 0) ++ ar0147_set_regs(client, ar0147_regs_hdr_mipi450mbps_12bit_30fps_rev3); ++ else if (strcmp(mode, "seplus1") == 0) ++ ar0147_set_regs(client, ar0147_regs_seplus1_mipi450mbps_12bit_30fps_rev3); ++ else if (strcmp(mode, "seplus2") == 0) ++ ar0147_set_regs(client, ar0147_regs_seplus2_mipi450mbps_12bit_30fps_rev3); ++ else ++ dev_err(&client->dev, "Unsupported mode %s\n", mode); ++ break; + default: + dev_err(&client->dev, "Unsupported chip revision\n"); + } +@@ -505,13 +527,31 @@ static int ar0147_initialize(struct i2c_client *client) + } + client->addr = tmp_addr; + ++ /* Enable trigger */ ++ if (priv->trigger < 4) { ++ reg16_write16(client, 0x340A, (~(BIT(priv->trigger) << 4)) & 0xf0);/* GPIO_CONTROL1: GPIOn input enable */ ++ reg16_write16(client, 0x340C, (0x2 << 2*priv->trigger)); /* GPIO_CONTROL2: GPIOn is trigger */ ++ reg16_write16(client, 0x30CE, 0x0120); /* TRIGGER_MODE */ ++ //reg16_write16(client, 0x30DC, 0x0120); /* TRIGGER_DELAY */ ++ } ++ + /* Enable stream */ + reg16_read16(client, 0x301a, &val); ++ val |= (1 << 8); /* GPI pins enable */ + val |= (1 << 2); ++ if (strcmp(mbus, "mipi") == 0) { ++ val &= ~(1 << 12); /* HISPI interface enable */ ++ val &= ~(1 << 7); /* Parallel interface disable */ ++ val &= ~(1 << 6); /* Parallel pins high-impedance state */ ++ } else if (strcmp(mbus, "dvp") == 0) { ++ val |= (1 << 12); /* HISPI interface disable */ ++ val |= (1 << 7); /* Parallel interface enable */ ++ val |= (1 << 6); /* Parallel pins drive */ ++ } + reg16_write16(client, 0x301a, val); + +- dev_info(&client->dev, "ar0147 PID %x (rev %x), res %dx%d, mode=%s, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", +- pid, rev, AR0147_MAX_WIDTH, AR0147_MAX_HEIGHT, mode, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++ dev_info(&client->dev, "ar0147 PID %x (rev %x), res %dx%d, mode=%s, mbus=%s, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, rev, AR0147_MAX_WIDTH, AR0147_MAX_HEIGHT, mode, mbus, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); + err: + ar0147_s_port(client, 0); + +@@ -530,6 +570,9 @@ static int ar0147_parse_dt(struct device_node *np, struct ar0147_priv *priv) + if (!endpoint) + break; + ++ if (of_property_read_u32(endpoint, "trigger", &priv->trigger)) ++ priv->trigger = 0; ++ + rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); + if (!rendpoint) + continue; +@@ -576,6 +619,10 @@ static int ar0147_parse_dt(struct device_node *np, struct ar0147_priv *priv) + } + client->addr = tmp_addr; + ++ /* module params override dts */ ++ if (trigger) ++ priv->trigger = trigger; ++ + mdelay(10); + + return 0; +diff --git a/drivers/media/i2c/soc_camera/ar0147.h b/drivers/media/i2c/soc_camera/ar0147.h +index 0f7ce31..2963708 100644 +--- a/drivers/media/i2c/soc_camera/ar0147.h ++++ b/drivers/media/i2c/soc_camera/ar0147.h +@@ -34,3 +34,4 @@ struct ar0147_reg { + + #include "ar0147_rev1.h" + #include "ar0147_rev2.h" ++#include "ar0147_rev3.h" +diff --git a/drivers/media/i2c/soc_camera/ar0147_rev3.h b/drivers/media/i2c/soc_camera/ar0147_rev3.h +new file mode 100644 +index 0000000..89b58da +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0147_rev3.h +@@ -0,0 +1,886 @@ ++/* ++ * ON Semiconductor AR0147 sensor camera wizard 1344x968@30/BGGR/BT601/RAW12 ++ * ++ * Copyright (C) 2019 Cogent Embedded, Inc. ++ * ++ * 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. ++ */ ++ ++static const struct ar0147_reg ar0147_rev3_Reset[] = { ++{0x301A, 0x0001}, // reset ++{AR0147_DELAY, 100}, ++{0x301A, 0x10D8}, // Stream off and setup parallel ++{0x3070, 0x0001}, ++{0x3070, 0x0000}, // 1: Solid color test pattern, ++ // 2: Full color bar test pattern, ++ // 3: Fade to grey color bar test pattern, ++ //256: Walking 1 test pattern (12 bit) ++#ifdef AR0147_DISPLAY_PATTERN_FIXED ++{0x3070, 0x0001}, ++#endif ++{0x3072, 0x0fff}, // R ++{0x3074, 0x0fff}, // G(GR row) ++{0x3076, 0x0fff}, // B ++{0x3078, 0x0fff}, // G(GB row) ++#ifdef AR0147_DISPLAY_PATTERN_COLOR_BAR ++{0x3070, 0x0002}, ++#endif ++{AR0147_DELAY, 250}, ++{ } ++}; /* Reset */ ++ ++static const struct ar0147_reg ar0147_rev3_Sensor_Setup[] = { ++/* Recommended_Settings */ ++{0x3500, 0x0100}, ++{AR0147_DELAY, 1}, ++{0x30B0, 0x980E}, // DIGITAL_TEST ++{0x3C08, 0x0000}, ++{0x3C0C, 0x0518}, // DELAY_BUFFER_LLPCK_RD_WR_OVERLAP ++{0x3092, 0x1A24}, ++{0x30B4, 0x01C7}, // TEMPSENS0_CTRL_REG ++{0x3372, 0x700F}, // DBLC_FS0_CONTROL ++{0x33EE, 0x0344}, ++{0x350C, 0x035A}, ++{0x350E, 0x0514}, ++{0x3518, 0x14FE}, ++{0x351A, 0x6000}, ++{0x3520, 0x08CC}, ++{0x3522, 0xCC08}, ++{0x3524, 0x0C00}, ++{0x3526, 0x0F00}, ++{0x3528, 0xEEEE}, ++{0x352A, 0x089F}, ++{0x352C, 0x0012}, ++{0x352E, 0x00EE}, ++{0x3530, 0xEE00}, ++{0x3536, 0xFF20}, ++{0x3538, 0x3CFF}, ++{0x353A, 0x9000}, ++{0x353C, 0x7F00}, ++{0x3540, 0xC62C}, ++{0x3542, 0x4B4B}, ++{0x3544, 0x3C46}, ++{0x3546, 0x5A5A}, ++{0x3548, 0x6400}, ++{0x354A, 0x007F}, ++{0x3556, 0x1010}, ++{0x3566, 0x7328}, ++{0x3F90, 0x0800}, // TEMPVSENS0_TMG_CTRL ++{0x3510, 0x011F}, ++{0x353E, 0x801F}, ++{0x3F9A, 0x0001}, // TEMPVSENS0_BOOST_SAMP_CTRL ++{0x3116, 0x0001}, // HDR_CONTROL3 ++{0x3102, 0x60A0}, ++{0x3104, 0x60A0}, ++{0x3106, 0x60A0}, ++{0x3362, 0x0000}, // DC_GAIN ++{0x3366, 0xCCCC}, // ANALOG_GAIN ++ ++// Corrects defect tagged pixels ++{0x31E0, 0x0003}, ++ ++// Writes to bitfield R0x3552[5:4]. ++// Be sure not to overwrite the other bitfields in this register. ++{0x3552, 0x0FB0}, ++/* Recommended_Settings */ ++ ++/* Sequencer_Update */ ++{0x2512, 0x8000}, ++{0x2510, 0x0901}, ++{0x2510, 0x3350}, ++{0x2510, 0x2004}, ++{0x2510, 0x1420}, ++{0x2510, 0x1578}, ++{0x2510, 0x087B}, ++{0x2510, 0x24FF}, ++{0x2510, 0x24FF}, ++{0x2510, 0x24EA}, ++{0x2510, 0x2410}, ++{0x2510, 0x2224}, ++{0x2510, 0x1015}, ++{0x2510, 0xD813}, ++{0x2510, 0x0214}, ++{0x2510, 0x0024}, ++{0x2510, 0xFF24}, ++{0x2510, 0xFF24}, ++{0x2510, 0xEA23}, ++{0x2510, 0x2464}, ++{0x2510, 0x7A24}, ++{0x2510, 0x0405}, ++{0x2510, 0x2C40}, ++{0x2510, 0x0AFF}, ++{0x2510, 0x0A78}, ++{0x2510, 0x3851}, ++{0x2510, 0x2A54}, ++{0x2510, 0x1440}, ++{0x2510, 0x0015}, ++{0x2510, 0x0804}, ++{0x2510, 0x0801}, ++{0x2510, 0x0408}, ++{0x2510, 0x2652}, ++{0x2510, 0x0813}, ++{0x2510, 0xC810}, ++{0x2510, 0x0210}, ++{0x2510, 0x1611}, ++{0x2510, 0x8111}, ++{0x2510, 0x8910}, ++{0x2510, 0x5612}, ++{0x2510, 0x1009}, ++{0x2510, 0x020D}, ++{0x2510, 0x0903}, ++{0x2510, 0x1402}, ++{0x2510, 0x15A8}, ++{0x2510, 0x1388}, ++{0x2510, 0x0938}, ++{0x2510, 0x1199}, ++{0x2510, 0x11D9}, ++{0x2510, 0x091E}, ++{0x2510, 0x1214}, ++{0x2510, 0x10D6}, ++{0x2510, 0x0901}, ++{0x2510, 0x1210}, ++{0x2510, 0x1212}, ++{0x2510, 0x1210}, ++{0x2510, 0x11DD}, ++{0x2510, 0x11D9}, ++{0x2510, 0x0901}, ++{0x2510, 0x1441}, ++{0x2510, 0x0904}, ++{0x2510, 0x1056}, ++{0x2510, 0x0811}, ++{0x2510, 0xDB09}, ++{0x2510, 0x0311}, ++{0x2510, 0xFB11}, ++{0x2510, 0xBB12}, ++{0x2510, 0x1A12}, ++{0x2510, 0x1008}, ++{0x2510, 0x1250}, ++{0x2510, 0x0B10}, ++{0x2510, 0x7610}, ++{0x2510, 0xE614}, ++{0x2510, 0x6109}, ++{0x2510, 0x0612}, ++{0x2510, 0x4012}, ++{0x2510, 0x6009}, ++{0x2510, 0x1C14}, ++{0x2510, 0x6009}, ++{0x2510, 0x1215}, ++{0x2510, 0xC813}, ++{0x2510, 0xC808}, ++{0x2510, 0x1066}, ++{0x2510, 0x090B}, ++{0x2510, 0x1588}, ++{0x2510, 0x1388}, ++{0x2510, 0x0913}, ++{0x2510, 0x0C14}, ++{0x2510, 0x4009}, ++{0x2510, 0x0310}, ++{0x2510, 0xE611}, ++{0x2510, 0xFB12}, ++{0x2510, 0x6212}, ++{0x2510, 0x6011}, ++{0x2510, 0xFF11}, ++{0x2510, 0xFB14}, ++{0x2510, 0x4109}, ++{0x2510, 0x0210}, ++{0x2510, 0x6609}, ++{0x2510, 0x1211}, ++{0x2510, 0xBB12}, ++{0x2510, 0x6312}, ++{0x2510, 0x6014}, ++{0x2510, 0x0015}, ++{0x2510, 0x1811}, ++{0x2510, 0xB812}, ++{0x2510, 0xA012}, ++{0x2510, 0x0010}, ++{0x2510, 0x2610}, ++{0x2510, 0x0013}, ++{0x2510, 0x0011}, ++{0x2510, 0x0030}, ++{0x2510, 0x5342}, ++{0x2510, 0x1100}, ++{0x2510, 0x1002}, ++{0x2510, 0x1016}, ++{0x2510, 0x1101}, ++{0x2510, 0x1109}, ++{0x2510, 0x1056}, ++{0x2510, 0x1210}, ++{0x2510, 0x0D09}, ++{0x2510, 0x0314}, ++{0x2510, 0x0214}, ++{0x2510, 0x4309}, ++{0x2510, 0x0514}, ++{0x2510, 0x4009}, ++{0x2510, 0x0115}, ++{0x2510, 0xC813}, ++{0x2510, 0xC809}, ++{0x2510, 0x1A11}, ++{0x2510, 0x4909}, ++{0x2510, 0x0815}, ++{0x2510, 0x8813}, ++{0x2510, 0x8809}, ++{0x2510, 0x1B11}, ++{0x2510, 0x5909}, ++{0x2510, 0x0B12}, ++{0x2510, 0x1409}, ++{0x2510, 0x0112}, ++{0x2510, 0x1010}, ++{0x2510, 0xD612}, ++{0x2510, 0x1212}, ++{0x2510, 0x1011}, ++{0x2510, 0x5D11}, ++{0x2510, 0x5910}, ++{0x2510, 0x5609}, ++{0x2510, 0x0311}, ++{0x2510, 0x5B08}, ++{0x2510, 0x1441}, ++{0x2510, 0x0901}, ++{0x2510, 0x1440}, ++{0x2510, 0x090C}, ++{0x2510, 0x117B}, ++{0x2510, 0x113B}, ++{0x2510, 0x121A}, ++{0x2510, 0x1210}, ++{0x2510, 0x0901}, ++{0x2510, 0x1250}, ++{0x2510, 0x10F6}, ++{0x2510, 0x10E6}, ++{0x2510, 0x1460}, ++{0x2510, 0x0901}, ++{0x2510, 0x15A8}, ++{0x2510, 0x13A8}, ++{0x2510, 0x1240}, ++{0x2510, 0x1260}, ++{0x2510, 0x0924}, ++{0x2510, 0x1588}, ++{0x2510, 0x0901}, ++{0x2510, 0x1066}, ++{0x2510, 0x0B08}, ++{0x2510, 0x1388}, ++{0x2510, 0x0925}, ++{0x2510, 0x0C09}, ++{0x2510, 0x0214}, ++{0x2510, 0x4009}, ++{0x2510, 0x0710}, ++{0x2510, 0xE612}, ++{0x2510, 0x6212}, ++{0x2510, 0x6011}, ++{0x2510, 0x7F11}, ++{0x2510, 0x7B10}, ++{0x2510, 0x6609}, ++{0x2510, 0x0614}, ++{0x2510, 0x4109}, ++{0x2510, 0x0114}, ++{0x2510, 0x4009}, ++{0x2510, 0x0D11}, ++{0x2510, 0x3B12}, ++{0x2510, 0x6312}, ++{0x2510, 0x6014}, ++{0x2510, 0x0015}, ++{0x2510, 0x1811}, ++{0x2510, 0x3812}, ++{0x2510, 0xA012}, ++{0x2510, 0x0010}, ++{0x2510, 0x2610}, ++{0x2510, 0x0013}, ++{0x2510, 0x0011}, ++{0x2510, 0x0043}, ++{0x2510, 0x7A06}, ++{0x2510, 0x0507}, ++{0x2510, 0x410E}, ++{0x2510, 0x0237}, ++{0x2510, 0x502C}, ++{0x2510, 0x4414}, ++{0x2510, 0x4000}, ++{0x2510, 0x1508}, ++{0x2510, 0x0408}, ++{0x2510, 0x0104}, ++{0x2510, 0x0826}, ++{0x2510, 0x5508}, ++{0x2510, 0x13C8}, ++{0x2510, 0x1002}, ++{0x2510, 0x1016}, ++{0x2510, 0x1181}, ++{0x2510, 0x1189}, ++{0x2510, 0x1056}, ++{0x2510, 0x1210}, ++{0x2510, 0x0902}, ++{0x2510, 0x0D09}, ++{0x2510, 0x0314}, ++{0x2510, 0x0215}, ++{0x2510, 0xA813}, ++{0x2510, 0xA814}, ++{0x2510, 0x0309}, ++{0x2510, 0x0614}, ++{0x2510, 0x0209}, ++{0x2510, 0x1F15}, ++{0x2510, 0x8813}, ++{0x2510, 0x8809}, ++{0x2510, 0x0B11}, ++{0x2510, 0x9911}, ++{0x2510, 0xD909}, ++{0x2510, 0x1E12}, ++{0x2510, 0x1409}, ++{0x2510, 0x0312}, ++{0x2510, 0x1012}, ++{0x2510, 0x1212}, ++{0x2510, 0x1011}, ++{0x2510, 0xDD11}, ++{0x2510, 0xD909}, ++{0x2510, 0x0114}, ++{0x2510, 0x4009}, ++{0x2510, 0x0711}, ++{0x2510, 0xDB09}, ++{0x2510, 0x0311}, ++{0x2510, 0xFB11}, ++{0x2510, 0xBB12}, ++{0x2510, 0x1A12}, ++{0x2510, 0x1009}, ++{0x2510, 0x0112}, ++{0x2510, 0x500B}, ++{0x2510, 0x1076}, ++{0x2510, 0x1066}, ++{0x2510, 0x1460}, ++{0x2510, 0x0901}, ++{0x2510, 0x15C8}, ++{0x2510, 0x0901}, ++{0x2510, 0x1240}, ++{0x2510, 0x1260}, ++{0x2510, 0x0901}, ++{0x2510, 0x13C8}, ++{0x2510, 0x0956}, ++{0x2510, 0x1588}, ++{0x2510, 0x0901}, ++{0x2510, 0x0C14}, ++{0x2510, 0x4009}, ++{0x2510, 0x0511}, ++{0x2510, 0xFB12}, ++{0x2510, 0x6212}, ++{0x2510, 0x6011}, ++{0x2510, 0xFF11}, ++{0x2510, 0xFB09}, ++{0x2510, 0x1911}, ++{0x2510, 0xBB12}, ++{0x2510, 0x6312}, ++{0x2510, 0x6014}, ++{0x2510, 0x0015}, ++{0x2510, 0x1811}, ++{0x2510, 0xB812}, ++{0x2510, 0xA012}, ++{0x2510, 0x0010}, ++{0x2510, 0x2610}, ++{0x2510, 0x0013}, ++{0x2510, 0x0011}, ++{0x2510, 0x0030}, ++{0x2510, 0x5345}, ++{0x2510, 0x1444}, ++{0x2510, 0x1002}, ++{0x2510, 0x1016}, ++{0x2510, 0x1101}, ++{0x2510, 0x1109}, ++{0x2510, 0x1056}, ++{0x2510, 0x1210}, ++{0x2510, 0x0D09}, ++{0x2510, 0x0314}, ++{0x2510, 0x0614}, ++{0x2510, 0x4709}, ++{0x2510, 0x0514}, ++{0x2510, 0x4409}, ++{0x2510, 0x0115}, ++{0x2510, 0x9813}, ++{0x2510, 0x9809}, ++{0x2510, 0x1A11}, ++{0x2510, 0x4909}, ++{0x2510, 0x0815}, ++{0x2510, 0x8813}, ++{0x2510, 0x8809}, ++{0x2510, 0x1B11}, ++{0x2510, 0x5909}, ++{0x2510, 0x0B12}, ++{0x2510, 0x1409}, ++{0x2510, 0x0112}, ++{0x2510, 0x1009}, ++{0x2510, 0x0112}, ++{0x2510, 0x1212}, ++{0x2510, 0x1011}, ++{0x2510, 0x5D11}, ++{0x2510, 0x5909}, ++{0x2510, 0x0511}, ++{0x2510, 0x5B09}, ++{0x2510, 0x1311}, ++{0x2510, 0x7B11}, ++{0x2510, 0x3B12}, ++{0x2510, 0x1A12}, ++{0x2510, 0x1009}, ++{0x2510, 0x0112}, ++{0x2510, 0x5010}, ++{0x2510, 0x7610}, ++{0x2510, 0x6614}, ++{0x2510, 0x6409}, ++{0x2510, 0x0115}, ++{0x2510, 0xA813}, ++{0x2510, 0xA812}, ++{0x2510, 0x4012}, ++{0x2510, 0x6009}, ++{0x2510, 0x2015}, ++{0x2510, 0x8809}, ++{0x2510, 0x020B}, ++{0x2510, 0x0901}, ++{0x2510, 0x1388}, ++{0x2510, 0x0925}, ++{0x2510, 0x0C09}, ++{0x2510, 0x0214}, ++{0x2510, 0x4409}, ++{0x2510, 0x0912}, ++{0x2510, 0x6212}, ++{0x2510, 0x6011}, ++{0x2510, 0x7F11}, ++{0x2510, 0x7B09}, ++{0x2510, 0x1C11}, ++{0x2510, 0x3B12}, ++{0x2510, 0x6312}, ++{0x2510, 0x6014}, ++{0x2510, 0x0015}, ++{0x2510, 0x1811}, ++{0x2510, 0x3812}, ++{0x2510, 0xA012}, ++{0x2510, 0x0010}, ++{0x2510, 0x2610}, ++{0x2510, 0x0013}, ++{0x2510, 0x0011}, ++{0x2510, 0x0008}, ++{0x2510, 0x7A06}, ++{0x2510, 0x0508}, ++{0x2510, 0x070E}, ++{0x2510, 0x0237}, ++{0x2510, 0x502C}, ++{0x2510, 0xFE32}, ++{0x2510, 0xFE06}, ++{0x2510, 0x2C2C}, ++ ++{AR0147_DELAY, 200}, ++ ++{0x32e6, 0x009a}, //min_subrow ++{0x322e, 0x258c}, //clks_per_sample 396 ++/* Sequencer_Update */ ++ ++{0x32D0, 0x3A02}, ++{0x32D2, 0x3508}, ++{0x32D4, 0x3702}, ++{0x32D6, 0x3C04}, ++{0x32DC, 0x370A}, ++{0x32EA, 0x3CA8}, ++{0x351E, 0x0000}, ++{0x3510, 0x811F}, ++ ++//settings to rev1 default for non-Super Exposure mode settings ++//Super Exposure mode settings have additional settings ++{0x1010, 0x0155}, // FINE_INTEGRATION_TIME4_MIN ++{0x3236, 0x00B2}, // FINE_CORRECTION4 ++{0x32EA, 0x3C0E}, ++{0x32EC, 0x7151}, ++{0x3116, 0x0001}, // HDR_CONTROL3 ++{0x33E2, 0x0000}, // SAMPLE_CTRL ++{0x3088, 0x0400}, // LFM_CTRL ++{0x322A, 0x0039}, // FINE_INTEGRATION_CTRL ++{0x3238, 0x0333}, // EXPOSURE_RATIO ++{ } ++}; /* Sensor_Setup */ ++ ++static const struct ar0147_reg ar0147_rev3_Super_Exposure_Plus_T2_Mode_1_Setup[] = { ++{0x3C06, 0x2024}, // CONFIGURE_BUFFERS1 ++{0x3C08, 0x2100}, // CONFIGURE_BUFFERS2 ++{0x3088, 0x0400}, ++{0x32EC, 0x7281}, ++{0x33E2, 0x0A10}, ++{0x322A, 0x0539}, // FINE_INTEGRATION_CTRL ++{0x1008, 0x0137}, // FINE_INTEGRATION_TIME_MIN ++{0x100E, 0x044F}, // FINE_INTEGRATION_TIME3_MIN ++{0x3230, 0x00DB}, // FINE_CORRECTION ++{0x3234, 0x03F3}, // FINE_CORRECTION3 ++{0x30FE, 0x0040}, // NOISE_PEDESTAL ++{0x3372, 0xF40F}, // DBLC_FS0_CONTROL ++{0x3180, 0x0188}, ++{0x3108, 0x0CB1}, ++{0x3280, 0x0CB2}, // T1_BARRIER_C0 ++{0x3282, 0x0CB2}, // T1_BARRIER_C1 ++{0x3284, 0x0CB2}, // T1_BARRIER_C2 ++{0x3286, 0x0CB2}, // T1_BARRIER_C3 ++{0x3288, 0x0CB2}, // T2_BARRIER_C0 ++{0x328A, 0x0CB2}, // T2_BARRIER_C1 ++{0x328C, 0x0CB2}, // T2_BARRIER_C2 ++{0x328E, 0x0CB2}, // T2_BARRIER_C3 ++{0x3290, 0x0CB2}, // T3_BARRIER_C0 ++{0x3292, 0x0CB2}, // T3_BARRIER_C1 ++{0x3294, 0x0CB2}, // T3_BARRIER_C2 ++{0x3296, 0x0CB2}, // T3_BARRIER_C3 ++{0x3298, 0x0ED8}, // T4_BARRIER_C0 ++{0x329A, 0x0ED8}, // T4_BARRIER_C1 ++{0x329C, 0x0ED8}, // T4_BARRIER_C2 ++{0x329E, 0x0ED8}, // T4_BARRIER_C3 ++{0x32F6, 0x3A01}, ++{0x32D2, 0x200A}, ++{0x32D0, 0x3005}, ++{0x32D4, 0x3505}, ++{0x32F8, 0x3C03}, ++{0x32DC, 0x220C}, ++{0x32D6, 0x3207}, ++{0x32E2, 0x3707}, ++{0x3260, 0x00FF}, ++{0x3262, 0x00FF}, ++{0x32EA, 0x3CA9}, ++{0x3250, 0x0005}, ++{0x3256, 0x03E8}, ++{0x3258, 0x0300}, ++{0x325A, 0x0A13}, ++{0x325E, 0x0186}, ++{0x3252, 0x0107}, ++{0x325E, 0x0186}, ++{0x3096, 0x0000}, ++{0x3372, 0xF50F}, // DBLC_FS0_CONTROL ++{0x337A, 0x100E}, // DBLC_SCALE0 ++{0x3504, 0x9100}, ++{0x350C, 0x034A}, ++{0x350E, 0x051C}, ++{0x3510, 0x9753}, ++{0x351E, 0x0100}, ++{0x3520, 0x0800}, ++{0x3522, 0x0008}, ++{0x3524, 0x0C00}, ++{0x3526, 0x0F00}, ++{0x3528, 0xDDDD}, ++{0x352A, 0x089F}, ++{0x352C, 0x0012}, ++{0x352E, 0x00FF}, ++{0x3530, 0xFF00}, ++{0x3532, 0x8F48}, ++{0x3536, 0xFF38}, ++{0x3538, 0x24FF}, ++{0x353A, 0x9000}, ++{0x353C, 0x7F00}, ++{0x353E, 0x801F}, ++{0x3540, 0xC62C}, ++{0x3542, 0x4B4B}, ++{0x3544, 0x4B46}, ++{0x3546, 0x5A5A}, ++{0x3548, 0x6400}, ++{0x354A, 0x007F}, ++{0x354E, 0x1480}, ++{0x3554, 0x1599}, ++{0x355A, 0x0B0E}, ++ ++/* Digital Lateral Overflow for SE Mode 1 */ ++{0x3116, 0x0001}, ++{0x3100, 0xC001}, // FIELD_WR= DLO_CONTROL0, 0xE001 ++{0x3102, 0x6100}, ++{0x3104, 0x6100}, ++{0x3106, 0x6100}, ++{0x3108, 0x0CB1}, ++{0x312A, 0x83E8}, ++{0x3C82, 0x0FFF}, ++/* Digital Lateral Overflow for SE Mode 1 */ ++{ } ++}; /* Super_Exposure_Plus_T2_Mode_1_Setup */ ++ ++static const struct ar0147_reg ar0147_rev3_Super_Exposure_Plus_T2_Mode_2_Setup[] = { ++{0x3C06, 0x141C}, ++{0x3C08, 0x2114}, ++{0x3088, 0x0400}, ++{0x32EC, 0x7101}, ++{0x33E2, 0x0530}, ++{0x322A, 0x0939}, // FINE_INTEGRATION_CTRL ++{0x1008, 0x0271}, // FINE_INTEGRATION_TIME_MIN ++{0x1010, 0x0129}, // FINE_INTEGRATION_TIME4_MIN ++{0x3230, 0x020F}, // FINE_CORRECTION ++{0x3236, 0x00C7}, // FINE_CORRECTION4 ++{0x30FE, 0x0040}, // NOISE_PEDESTAL ++{0x3372, 0xF40F}, // DBLC_FS0_CONTROL ++{0x3180, 0x0188}, ++{0x3108, 0x0CB1}, ++{0x3280, 0x0CB2}, // T1_BARRIER_C0 ++{0x3282, 0x0CB2}, // T1_BARRIER_C1 ++{0x3284, 0x0CB2}, // T1_BARRIER_C2 ++{0x3286, 0x0CB2}, // T1_BARRIER_C3 ++{0x3288, 0x0226}, // T2_BARRIER_C0 ++{0x328A, 0x0226}, // T2_BARRIER_C1 ++{0x328C, 0x0226}, // T2_BARRIER_C2 ++{0x328E, 0x0226}, // T2_BARRIER_C3 ++{0x3290, 0x0CB2}, // T3_BARRIER_C0 ++{0x3292, 0x0CB2}, // T3_BARRIER_C1 ++{0x3294, 0x0CB2}, // T3_BARRIER_C2 ++{0x3296, 0x0CB2}, // T3_BARRIER_C3 ++{0x3298, 0x0ED8}, // T4_BARRIER_C0 ++{0x329A, 0x0ED8}, // T4_BARRIER_C1 ++{0x329C, 0x0ED8}, // T4_BARRIER_C2 ++{0x329E, 0x0ED8}, // T4_BARRIER_C3 ++{0x32F6, 0x3A01}, ++{0x32D2, 0x200A}, ++{0x32D0, 0x3005}, ++{0x32D4, 0x3505}, ++{0x32F8, 0x3C03}, ++{0x32DC, 0x220C}, ++{0x32D6, 0x3207}, ++{0x32E2, 0x3707}, ++{0x3260, 0x00FF}, ++{0x3262, 0x00FF}, ++{0x32EA, 0x3C69}, ++{0x3250, 0x0005}, ++{0x3256, 0x03E8}, ++{0x3258, 0x0300}, ++{0x325A, 0x0A13}, ++{0x325E, 0x0186}, ++{0x3252, 0x0107}, ++{0x325E, 0x0186}, ++{0x3752, 0x0000}, ++{0x3372, 0xF50F}, // DBLC_FS0_CONTROL ++{0x337A, 0x100E}, // DBLC_SCALE0 ++{0x3504, 0x9100}, ++{0x350C, 0x034A}, ++{0x350E, 0x051C}, ++{0x3510, 0x9753}, ++{0x351E, 0x0100}, ++{0x3520, 0x0800}, ++{0x3522, 0x0008}, ++{0x3524, 0x0C00}, ++{0x3526, 0x0F00}, ++{0x3528, 0xDDDD}, ++{0x352A, 0x089F}, ++{0x352C, 0x0012}, ++{0x352E, 0x00FF}, ++{0x3530, 0xFF00}, ++{0x3532, 0x8F08}, ++{0x3536, 0xFF38}, ++{0x3538, 0x24FF}, ++{0x353A, 0x9000}, ++{0x353C, 0x7F00}, ++{0x353E, 0x801F}, ++{0x3540, 0xC62C}, ++{0x3542, 0x4B4B}, ++{0x3544, 0x4B46}, ++{0x3546, 0x5A5A}, ++{0x3548, 0x6400}, ++{0x354A, 0x007F}, ++{0x354E, 0x1480}, ++{0x3554, 0x1599}, ++{0x355A, 0x0B0E}, ++{0x3364, 0x0004}, ++{0x3F72, 0x0A08}, // GCF_TRIM_0 ++{0x3F74, 0x40E8}, // GCF_TRIM_1 ++{0x3F76, 0x0E09}, // GCF_TRIM_2 ++{0x3F78, 0x0210}, // GCF_TRIM_3 ++ ++/* Digital Lateral Overflow for SE Mode 2 */ ++{0x3116, 0x0001}, ++{0x3100, 0xC003}, // DLO_CONTROL0 ++{0x3102, 0x8FA0}, // DLO_CONTROL1 ++{0x3104, 0x8FA0}, // DLO_CONTROL2 ++{0x3106, 0x8FA0}, // DLO_CONTROL3 ++{0x312A, 0x83E8}, // HDR_SE_CONTROL0 ++{0x3C82, 0x4FFF}, // HDR_SE_CONTROL1[] ++/* Digital Lateral Overflow for SE Mode 2 */ ++{ } ++}; /* Super_Exposure_Plus_T2_Mode_2_Setup */ ++ ++static const struct ar0147_reg ar0147_rev3_Serial_12_bit_Timing_Setup[] = { ++#if 0 ++/* PCLK=24Mhz/3 *50 /1/8 = 50MHz */ ++{0x302A, 8}, // VT_PIX_CLK_DIV ++{0x302C, 1}, // VT_SYS_CLK_DIV ++{0x302E, 3}, // PRE_PLL_CLK_DIV ++{0x3030, 50}, // PLL_MULTIPLIER ++{0x3036, 8}, // OP_WORD_CLK_DIV ++{0x3038, 1}, // OP_SYS_CLK_DIV ++#else ++/* PCLK=24Mhz/4 *75 /1/9 = 50MHz */ ++{0x302A, 9}, // VT_PIX_CLK_DIV ++{0x302C, 1}, // VT_SYS_CLK_DIV ++{0x302E, 4}, // PRE_PLL_CLK_DIV ++{0x3030, 75}, // PLL_MULTIPLIER ++{0x3036, 12}, // OP_WORD_CLK_DIV ++{0x3038, 1}, // OP_SYS_CLK_DIV ++#endif ++{0x30B0, 0x980C}, // DIGITAL_TEST ++{0x31DC, 0x1FB0}, ++{ } ++}; /* Serial_12_bit_Timing_Setup */ ++ ++static const struct ar0147_reg ar0147_rev3_Readout_Mode_Configuration[] = { ++{0x30A2, 0x0001}, // X_ODD_INC_ ++{0x30A6, 0x0001}, // Y_ODD_INC_ ++{0x3040, 0x0000}, // READ_MODE ++{0x3082, 0x0008}, // OPERATION_MODE_CTRL: 3exp ++{0x3044, 0x0400}, // DARK_CONTROL ++{0x3064, 0x0000}, // SMIA_TEST: disable emb data and stats ++{0x33E0, 0x0C80}, // TEST_ASIL_ROWS ++{0x3180, 0x0080}, // RESERVED_MFR_3180 ++{0x33E4, 0x0080}, // RESERVED_MFR_33E4 ++#ifdef AR0147_EMBEDDED_LINE ++{0x3064, 0x0180}, // SMIA_TEST: enable emb data and stats ++#endif ++{ } ++}; /* Readout_Mode_Configuration */ ++ ++static const struct ar0147_reg ar0147_rev3_Full_Res_FOV[] = { ++{0x31B0, 0x0056}, // FRAME_PREAMBLE ++{0x31B2, 0x0045}, // LINE_PREAMBLE ++{0x3004, AR0147_X_START}, // X_ADDR_START_ ++{0x3008, AR0147_X_END}, // X_ADDR_END_ ++{0x3002, AR0147_Y_START}, // Y_ADDR_START_ ++{0x3006, AR0147_Y_END}, // Y_ADDR_END_ ++{0x3400, 0x10}, ++{0x3402, (0x8000 & 0) | AR0147_MAX_WIDTH}, // X_OUTPUT_CONTROL ++{0x3404, (0x8000 & 0) | AR0147_MAX_HEIGHT}, // Y_OUTPUT_CONTROL ++{ } ++}; /* Full_Res_FOV */ ++ ++static const struct ar0147_reg ar0147_rev3_3exp_30FPS_Timing_and_Exposure[] = { ++{0x3082, 0x0008}, // OPERATION_MODE_CTRL: 3exp ++{0x30BA, 0x1002}, // DIGITAL_CTRL: 3exp max ++ ++/* Row and Pixel Timing */ ++{0x300C, AR0147_SENSOR_WIDTH + 52}, // LINE_LENGTH_PCK_ (1396) ++{0x300A, AR0147_SENSOR_HEIGHT + 226}, // FRAME_LENGTH_LINES_ ++{0x3042, 0x0000}, // EXTRA_DELAY ++ ++/* Exposure Settings */ ++{0x3238, 0x0222}, // EXPOSURE_RATIO ++{0x3012, 0x0300}, // COARSE_INTEGRATION_TIME_ ++ ++{0x3014, 1550}, // FINE_INTEGRATION_TIME_ ++{0x321E, 1550}, // FINE_INTEGRATION_TIME2 ++{0x3222, 1550}, // FINE_INTEGRATION_TIME3 ++{0x30B0, 0x980C}, // DIGITAL_TEST (MIPI ...) ++{0x32EA, 0x3C0E}, ++{0x32EC, 0x72A1}, ++{0x3362, 0x0000}, // DC_GAIN ++{0x3366, 0xCCCC}, // ANALOG_GAIN ++{0x3364, 0x01CF}, // DCG_TRIM ++{0x3C06, 0x083C}, ++{0x3C08, 0x0100}, ++{ } ++}; /* 3exp_30FPS_Timing_and_Exposure */ ++ ++static const struct ar0147_reg ar0147_rev3_SE_Plus_T2_Mode_1_30FPS_Timing_and_Exposure[] = { ++{0x3082, 0x0008}, // OPERATION_MODE_CTRL: 3exp ++{0x30BA, 0x1003}, // DIGITAL_CTRL: 4exp max ++ ++/* Row and Pixel Timing */ ++{0x300C, AR0147_SENSOR_WIDTH + 52}, // LINE_LENGTH_PCK_ (1396) ++{0x300A, AR0147_SENSOR_HEIGHT + 226}, // FRAME_LENGTH_LINES_ ++{0x3042, 0x0000}, // EXTRA_DELAY ++ ++/* Exposure Settings */ ++{0x3238, 0x8222}, // EXPOSURE_RATIO: separate integartion time!? ++{0x3012, 0x0300}, // COARSE_INTEGRATION_TIME_ ++ ++{0x322A, 0x0539}, // FINE_INTEGRATION_CTRL ++{0x3014, 0x0137}, // FINE_INTEGRATION_TIME_ ++{0x3222, 0x0926}, // FINE_INTEGRATION_TIME3 ++{0x3362, 0x0001}, // DC_GAIN ++{0x3366, 0xFDF7}, // ANALOG_GAIN ++ ++{0x30B0, 0x980C}, // DIGITAL_TEST (MIPI ...) ++{0x32EC, 0x7281}, ++{ } ++}; /* SE_Plus_T2_Mode_1_30FPS_Timing_and_Exposure */ ++ ++static const struct ar0147_reg ar0147_rev3_SE_Plus_T2_Mode_2_50MHz_29FPS_Timing_and_Exposure[] = { ++{0x3082, 0x000C}, // OPERATION_MODE_CTRL: 3exp ++{0x30BA, 0x1003}, // DIGITAL_CTRL: 4exp max ++ ++/* Row and Pixel Timing */ ++{0x300C, AR0147_SENSOR_WIDTH + 326}, // LINE_LENGTH_PCK_ (1670) ++{0x300A, AR0147_SENSOR_HEIGHT + 30}, // FRAME_LENGTH_LINES_ ++{0x3042, 0x0000}, // EXTRA_DELAY ++ ++/* Exposure Settings */ ++{0x3012, 0x0300}, // COARSE_INTEGRATION_TIME_ ++{0x321A, 12}, // COARSE_INTEGRATION_TIME4_ ++{0x3238, 0x8222}, // EXPOSURE_RATIO: separate integartion time!? ++ ++{0x322A, 0x0939}, // FINE_INTEGRATION_CTRL ++{0x3014, 0x0271}, // FINE_INTEGRATION_TIME_ ++{0x3226, 0x0594}, // FINE_INTEGRATION_TIME4 ++{0x3362, 0x0D02}, // DC_GAIN ++{0x3366, 0xDE79}, // ANALOG_GAIN ++ ++{0x30B0, 0x980C}, // DIGITAL_TEST (MIPI ...) ++{0x32EC, 0x7101}, ++{0x33E0, 0x0080}, // TEST_ASIL_ROWS ++{ } ++}; /* SE_Plus_T2_Mode_2_30FPS_Timing_and_Exposure */ ++ ++static const struct ar0147_reg ar0147_rev3_Serial_4_Lane_20_to_12_bit_Output[] = { ++{0x31D0, 0x0001}, // COMPANDING ++{0x31AE, 0x0304}, // SERIAL_FORMAT: HISPI 4-lanes ++{0x31AC, 0x140C}, // DATA_FORMAT_BITS: ADC20, RAW12 ++//{0x301A, 0x0118}, // RESET_REGISTER ++{0x301A, 0x0018}, // RESET_REGISTER (MIPI) ++//{0x301A, 0x11d8}, // RESET_REGISTER (DVP) ++{ } ++}; /* Serial_4_Lane_20_to_12_bit_Output */ ++ ++static const struct ar0147_reg ar0147_rev3_MIPI_12_bit_450MBps_Settings[] = { ++{0x31AE, 0x0204}, // SERIAL_FORMAT: MIPI 4-lanes ++{0x3342, 0x122C}, // exposure1 DT=0x2c emb=0x12 ++{0x3346, 0x122C}, // exposure2 DT=0x2c emb=0x12 ++{0x334A, 0x122C}, // exposure3 DT=0x2c emb=0x12 ++{0x334E, 0x122C}, // exposure4 DT=0x2c emb=0x12 ++{0x3344, 0x0011}, // exposure1 VC=0 ++{0x3348, 0x0111}, // exposure1 VC=1 ++{0x334C, 0x0211}, // exposure1 VC=2 ++{0x3350, 0x0311}, // exposure1 VC=3 ++{0x31B0, 0x41}, // frame_preamble ++{0x31B2, 0x2e}, // line_preamble ++ ++{0x31B4, 0x2185}, ++{0x31B6, 0x1105}, ++{0x31B8, 0x2047}, ++{0x31BA, 0x105}, ++{0x31BC, 0x704}, ++{ } ++}; /* MIPI_12_bit_450MBps_Settings */ ++ ++/* 3 Exp HDR, Full Resolution, MIPI 450MBPS 4 lane 12-bit, 30FPS, XMCLK=24MHz */ ++static const struct ar0147_reg *ar0147_regs_hdr_mipi450mbps_12bit_30fps_rev3[] = { ++ ar0147_rev3_Reset, ++ ar0147_rev3_Sensor_Setup, ++ ar0147_rev3_Serial_12_bit_Timing_Setup, ++ ar0147_rev3_Readout_Mode_Configuration, ++ ar0147_rev3_Full_Res_FOV, ++ ar0147_rev3_3exp_30FPS_Timing_and_Exposure, ++ ar0147_rev3_Serial_4_Lane_20_to_12_bit_Output, ++ ar0147_rev3_MIPI_12_bit_450MBps_Settings, ++ NULL ++}; ++ ++/* Super-Exposure Plus T2 Mode 1, Full Resolution, MIPI 450MBPS 4 lane 12-bit, 30FPS, XMCLK=24MHz */ ++static const struct ar0147_reg *ar0147_regs_seplus1_mipi450mbps_12bit_30fps_rev3[] = { ++ ar0147_rev3_Reset, ++ ar0147_rev3_Sensor_Setup, ++ ar0147_rev3_Super_Exposure_Plus_T2_Mode_1_Setup, ++ ar0147_rev3_Serial_12_bit_Timing_Setup, ++ ar0147_rev3_Readout_Mode_Configuration, ++ ar0147_rev3_Full_Res_FOV, ++ ar0147_rev3_SE_Plus_T2_Mode_1_30FPS_Timing_and_Exposure, ++ ar0147_rev3_Serial_4_Lane_20_to_12_bit_Output, ++ ar0147_rev3_MIPI_12_bit_450MBps_Settings, ++ NULL ++}; ++ ++/* Super-Exposure Plus T2 Mode 2, Full Resolution, MIPI 450MBPS 4 lane 12-bit, 30FPS, XMCLK=24MHz */ ++static const struct ar0147_reg *ar0147_regs_seplus2_mipi450mbps_12bit_30fps_rev3[] = { ++ ar0147_rev3_Reset, ++ ar0147_rev3_Sensor_Setup, ++ ar0147_rev3_Super_Exposure_Plus_T2_Mode_2_Setup, ++ ar0147_rev3_Serial_12_bit_Timing_Setup, ++ ar0147_rev3_Readout_Mode_Configuration, ++ ar0147_rev3_Full_Res_FOV, ++ ar0147_rev3_SE_Plus_T2_Mode_2_50MHz_29FPS_Timing_and_Exposure, ++ ar0147_rev3_Serial_4_Lane_20_to_12_bit_Output, ++ ar0147_rev3_MIPI_12_bit_450MBps_Settings, ++ NULL ++}; +diff --git a/drivers/media/i2c/soc_camera/ov106xx.c b/drivers/media/i2c/soc_camera/ov106xx.c +index 70067d7..21dffcd8 100644 +--- a/drivers/media/i2c/soc_camera/ov106xx.c ++++ b/drivers/media/i2c/soc_camera/ov106xx.c +@@ -29,6 +29,7 @@ + #include "isx016.c" + #include "isx019.c" + #include "ov2311.c" ++#include "ar0147.c" + + static enum { + ID_OV10635, +@@ -38,6 +39,7 @@ static enum { + ID_AR0132, + ID_AR0140, + ID_AR0143, ++ ID_AR0147, + ID_AR0220, + ID_AR0231, + ID_AR0233, +@@ -119,6 +121,12 @@ static int ov106xx_probe(struct i2c_client *client, + goto out; + } + ++ ret = ar0147_probe(client, did); ++ if (!ret) { ++ chip_id = ID_AR0147; ++ goto out; ++ } ++ + ret = ar0220_probe(client, did); + if (!ret) { + chip_id = ID_AR0220; +@@ -209,6 +217,9 @@ static int ov106xx_remove(struct i2c_client *client) + case ID_AR0143: + ar0143_remove(client); + break; ++ case ID_AR0147: ++ ar0147_remove(client); ++ break; + case ID_AR0220: + ar0220_remove(client); + break; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0398-media-i2c-ar0147-add-SE-mode.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0398-media-i2c-ar0147-add-SE-mode.patch new file mode 100644 index 00000000..4a003f71 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0398-media-i2c-ar0147-add-SE-mode.patch @@ -0,0 +1,284 @@ +From f424f98ee6a4fd3b8add8d126b340914e0643929 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Tue, 16 Jul 2019 12:29:00 +0300 +Subject: [PATCH] media: i2c: ar0147: add SE mode + +This adds super-exposure default mode + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ar0147.c | 4 ++ + drivers/media/i2c/soc_camera/ar0147_rev2.h | 111 +++++++++++++++++++++++++++++ + drivers/media/i2c/soc_camera/ar0147_rev3.h | 77 ++++++++++++++++++++ + 3 files changed, 192 insertions(+) + +diff --git a/drivers/media/i2c/soc_camera/ar0147.c b/drivers/media/i2c/soc_camera/ar0147.c +index 563708c..53be588 100644 +--- a/drivers/media/i2c/soc_camera/ar0147.c ++++ b/drivers/media/i2c/soc_camera/ar0147.c +@@ -492,6 +492,8 @@ static int ar0147_initialize(struct i2c_client *client) + case 0x2: + if (strcmp(mode, "hdr") == 0) + ar0147_set_regs(client, ar0147_regs_hdr_mipi450mbps_12bit_30fps_rev2); ++ else if (strcmp(mode, "se") == 0) ++ ar0147_set_regs(client, ar0147_regs_se_mipi450mbps_12bit_30fps_rev2); + else if (strcmp(mode, "seplus") == 0) + ar0147_set_regs(client, ar0147_regs_seplus_mipi450mbps_12bit_30fps_rev2); + else +@@ -500,6 +502,8 @@ static int ar0147_initialize(struct i2c_client *client) + case 0x3: + if (strcmp(mode, "hdr") == 0) + ar0147_set_regs(client, ar0147_regs_hdr_mipi450mbps_12bit_30fps_rev3); ++ else if (strcmp(mode, "se") == 0) ++ ar0147_set_regs(client, ar0147_regs_se_mipi450mbps_12bit_30fps_rev3); + else if (strcmp(mode, "seplus1") == 0) + ar0147_set_regs(client, ar0147_regs_seplus1_mipi450mbps_12bit_30fps_rev3); + else if (strcmp(mode, "seplus2") == 0) +diff --git a/drivers/media/i2c/soc_camera/ar0147_rev2.h b/drivers/media/i2c/soc_camera/ar0147_rev2.h +index 04d8e5e..c7a643e 100644 +--- a/drivers/media/i2c/soc_camera/ar0147_rev2.h ++++ b/drivers/media/i2c/soc_camera/ar0147_rev2.h +@@ -485,6 +485,78 @@ static const struct ar0147_reg ar0147_rev2_Sensor_Setup[] = { + { } + }; /* Sensor_Setup */ + ++static const struct ar0147_reg ar0147_rev2_Super_Exposure_Default_Setup[] = { ++{0x3082, 0x0004}, // OPERATION_MODE_CTRL ++{0x30BA, 0x1002}, // DIGITAL_CTRL ++{0x3C06, 0x000C}, ++{0x3C08, 0x1100}, ++{0x3116, 0x0000}, // HDR_CONTROL3 ++{0x3088, 0x0480}, ++{0x3510, 0x814F}, ++{0x351E, 0x0100}, ++{0x32EA, 0x3CA9}, ++{0x32EC, 0x7281}, ++{0x3212, 0x0000}, // COARSE_INTEGRATION_TIME2 ++{0x3238, 0x8222}, // EXPOSURE_RATIO ++{0x33E2, 0x0910}, // SAMPLE_CTRL ++{0x3362, 0x0001}, // DC_GAIN ++{0x322A, 0x0539}, // FINE_INTEGRATION_CTRL ++{0x3014, 0x0123}, // FINE_INTEGRATION_TIME_ ++{0x1008, 0x0123}, // FINE_INTEGRATION_TIME_MIN ++{0x3230, 0x00C7}, // FINE_CORRECTION ++{0x32D0, 0x3A02}, ++{0x32D2, 0x3508}, ++{0x32D4, 0x3702}, ++{0x32D6, 0x3C04}, ++{0x32DC, 0x370A}, ++{0x3528, 0x99EE}, ++{0x30FE, 0x0040}, // NOISE_PEDESTAL ++{0x3782, 0x0000}, ++ ++/* Other_Super_Exposure_Setup */ ++{0x3536, 0xFF20}, ++{0x3520, 0x0800}, ++{0x3522, 0x0008}, ++{0x3536, 0xFF20}, ++{0x350C, 0x034A}, ++{0x350E, 0x051C}, ++{0x3540, 0xC62C}, ++{0x3542, 0x4B4B}, ++{0x3544, 0x4B46}, ++{0x3546, 0x5A5A}, ++{0x3548, 0x6400}, ++{0x354A, 0x007F}, ++{0x3524, 0x0600}, ++{0x3372, 0xF40F}, // DBLC_FS0_CONTROL ++{0x3180, 0x0188}, ++{0x3280, 0x0CB2}, // T1_BARRIER_C0 ++{0x3282, 0x0CB2}, // T1_BARRIER_C1 ++{0x3284, 0x0CB2}, // T1_BARRIER_C2 ++{0x3286, 0x0CB2}, // T1_BARRIER_C3 ++{0x3288, 0x0CB2}, // T2_BARRIER_C0 ++{0x328A, 0x0CB2}, // T2_BARRIER_C1 ++{0x328C, 0x0CB2}, // T2_BARRIER_C2 ++{0x328E, 0x0CB2}, // T2_BARRIER_C3 ++{0x3290, 0x0CB2}, // T3_BARRIER_C0 ++{0x3292, 0x0CB2}, // T3_BARRIER_C1 ++{0x3294, 0x0CB2}, // T3_BARRIER_C2 ++{0x3296, 0x0CB2}, // T3_BARRIER_C3 ++{0x3298, 0x0CB2}, // T4_BARRIER_C0 ++{0x329A, 0x0CB2}, // T4_BARRIER_C1 ++{0x329C, 0x0CB2}, // T4_BARRIER_C2 ++{0x329E, 0x0CB2}, // T4_BARRIER_C3 ++{0x3108, 0x0CB1}, ++{0x312A, 0x83E8}, ++{0x3C82, 0x0FFF}, ++{0x3102, 0x6100}, ++{0x3104, 0x6100}, ++{0x3106, 0x6100}, ++{0x3120, 0x0AF0}, ++{0x3122, 0x0CB2}, ++/* Other_Super_Exposure_Setup */ ++{ } ++}; /* Super_Exposure_Default_Setup */ ++ + static const struct ar0147_reg ar0147_rev2_Super_Exposure_Default_Plus_T2_Setup[] = { + {0x3082, 0x0008}, // OPERATION_MODE_CTRL + {0x30BA, 0x1003}, // DIGITAL_CTRL +@@ -651,6 +723,30 @@ static const struct ar0147_reg ar0147_rev2_3exp_30FPS_Timing_and_Exposure[] = { + { } + }; /* 3exp_30FPS_Timing_and_Exposure */ + ++static const struct ar0147_reg ar0147_rev2_SE_Default_Mode_30FPS_Timing_and_Exposure[] = { ++{0x3082, 0x0004}, // OPERATION_MODE_CTRL: 2exp ++{0x30BA, 0x1002}, // DIGITAL_CTRL: 3exp max ++ ++/* Row and Pixel Timing */ ++{0x300C, AR0147_SENSOR_WIDTH + 52}, // LINE_LENGTH_PCK_ (1396) ++{0x300A, AR0147_SENSOR_HEIGHT + 226}, // FRAME_LENGTH_LINES_ ++{0x3042, 0x0000}, // EXTRA_DELAY ++ ++/* Exposure Settings */ ++{0x3238, 0x8222}, // EXPOSURE_RATIO: separate integartion time!? ++{0x3012, 0x0300}, // COARSE_INTEGRATION_TIME_ ++ ++{0x322A, 0x0139}, // FINE_INTEGRATION_CTRL ++{0x3014, 0x0123}, // FINE_INTEGRATION_TIME_ ++{0x3362, 0x0001}, // DC_GAIN ++{0x3366, 0xFFF7}, // ANALOG_GAIN ++{0x3364, 0x01CF}, // DCG_TRIM ++ ++{0x30B0, 0x980C}, // DIGITAL_TEST (MIPI ...) ++{0x32EC, 0x7281}, ++{ } ++}; /* SE_Default_Mode_30FPS_Timing_and_Exposure */ ++ + static const struct ar0147_reg ar0147_rev2_SE_Plus_T2_Default_Mode_30FPS_Timing_and_Exposure[] = { + {0x3082, 0x0008}, // OPERATION_MODE_CTRL: 3exp + {0x30BA, 0x1003}, // DIGITAL_CTRL: 4exp max +@@ -780,6 +876,21 @@ static const struct ar0147_reg *ar0147_regs_hdr_mipi450mbps_12bit_30fps_rev2[] = + NULL + }; + ++/* Super-Exposure, Full Resolution, MIPI 450MBPS 4 lane 12-bit, 30FPS, XMCLK=24MHz */ ++static const struct ar0147_reg *ar0147_regs_se_mipi450mbps_12bit_30fps_rev2[] = { ++ ar0147_rev2_Reset, ++ ar0147_rev2_Sensor_Setup, ++ ar0147_rev2_Super_Exposure_Default_Setup, ++ ar0147_rev2_Serial_12_bit_Timing_Setup, ++ ar0147_rev2_Readout_Mode_Configuration, ++ ar0147_rev2_Full_Res_FOV, ++ ar0147_rev2_SE_Default_Mode_30FPS_Timing_and_Exposure, ++ ar0147_rev2_Serial_4_Lane_20_to_12_bit_Output, ++ ar0147_rev2_MIPI_12_bit_450MBps_Settings, ++ ar0147_rev2_shutter_and_booster_settings, ++ NULL ++}; ++ + /* Super-Exposure Plus T2, Full Resolution, MIPI 450MBPS 4 lane 12-bit, 30FPS, XMCLK=24MHz */ + static const struct ar0147_reg *ar0147_regs_seplus_mipi450mbps_12bit_30fps_rev2[] = { + ar0147_rev2_Reset, +diff --git a/drivers/media/i2c/soc_camera/ar0147_rev3.h b/drivers/media/i2c/soc_camera/ar0147_rev3.h +index 89b58da..02acf1a 100644 +--- a/drivers/media/i2c/soc_camera/ar0147_rev3.h ++++ b/drivers/media/i2c/soc_camera/ar0147_rev3.h +@@ -490,6 +490,36 @@ static const struct ar0147_reg ar0147_rev3_Sensor_Setup[] = { + { } + }; /* Sensor_Setup */ + ++static const struct ar0147_reg ar0147_rev3_Super_Exposure_Mode_1_Setup[] = { ++{0x3082, 0x0004}, // OPERATION_MODE_CTRL ++{0x30BA, 0x1002}, // DIGITAL_CTRL ++{0x3C06, 0x000C}, // ++{0x3C08, 0x1100}, // ++{0x3116, 0x0000}, // HDR_CONTROL3 ++{0x3088, 0x0480}, // ++{0x3510, 0x814F}, // ++{0x351E, 0x0100}, // ++{0x32EA, 0x3CA9}, // ++{0x32EC, 0x7281}, // ++{0x3212, 0x0000}, // COARSE_INTEGRATION_TIME2 ++{0x3238, 0x8222}, // EXPOSURE_RATIO ++{0x33E2, 0x0910}, // SAMPLE_CTRL ++{0x3362, 0x0001}, // DC_GAIN ++{0x322A, 0x0539}, // FINE_INTEGRATION_CTRL ++{0x3014, 0x0137}, // FINE_INTEGRATION_TIME_ ++{0x1008, 0x0137}, // FINE_INTEGRATION_TIME_MIN ++{0x3230, 0x00DB}, // FINE_CORRECTION ++{0x32D0, 0x3A02}, // ++{0x32D2, 0x3508}, // ++{0x32D4, 0x3702}, // ++{0x32D6, 0x3C04}, // ++{0x32DC, 0x370A}, // ++{0x3528, 0x99EE}, // ++{0x30FE, 0x0040}, // NOISE_PEDESTAL ++{0x3782, 0x0000}, // ++{ } ++}; /* Super_Exposure_Mode_1_Setup */ ++ + static const struct ar0147_reg ar0147_rev3_Super_Exposure_Plus_T2_Mode_1_Setup[] = { + {0x3C06, 0x2024}, // CONFIGURE_BUFFERS1 + {0x3C08, 0x2100}, // CONFIGURE_BUFFERS2 +@@ -763,6 +793,29 @@ static const struct ar0147_reg ar0147_rev3_3exp_30FPS_Timing_and_Exposure[] = { + { } + }; /* 3exp_30FPS_Timing_and_Exposure */ + ++static const struct ar0147_reg ar0147_rev3_SE_Mode_1_30FPS_Timing_and_Exposure[] = { ++{0x3082, 0x0004}, // OPERATION_MODE_CTRL: 2exp ++{0x30BA, 0x1002}, // DIGITAL_CTRL: 3exp max ++ ++/* Row and Pixel Timing */ ++{0x300C, AR0147_SENSOR_WIDTH + 52}, // LINE_LENGTH_PCK_ (1396) ++{0x300A, AR0147_SENSOR_HEIGHT + 226}, // FRAME_LENGTH_LINES_ ++{0x3042, 0x0000}, // EXTRA_DELAY ++ ++/* Exposure Settings */ ++{0x3238, 0x8222}, // EXPOSURE_RATIO: separate integartion time!? ++{0x3012, 0x0300}, // COARSE_INTEGRATION_TIME_ ++ ++{0x322A, 0x0139}, // FINE_INTEGRATION_CTRL ++{0x3014, 0x0123}, // FINE_INTEGRATION_TIME_ ++{0x3362, 0x0001}, // DC_GAIN ++{0x3366, 0xFFF7}, // ANALOG_GAIN ++ ++{0x30B0, 0x980C}, // DIGITAL_TEST (MIPI ...) ++{0x32EC, 0x7281}, ++{ } ++}; /* SE_Mode_1_30FPS_Timing_and_Exposure */ ++ + static const struct ar0147_reg ar0147_rev3_SE_Plus_T2_Mode_1_30FPS_Timing_and_Exposure[] = { + {0x3082, 0x0008}, // OPERATION_MODE_CTRL: 3exp + {0x30BA, 0x1003}, // DIGITAL_CTRL: 4exp max +@@ -813,6 +866,16 @@ static const struct ar0147_reg ar0147_rev3_SE_Plus_T2_Mode_2_50MHz_29FPS_Timing_ + { } + }; /* SE_Plus_T2_Mode_2_30FPS_Timing_and_Exposure */ + ++static const struct ar0147_reg ar0147_rev3_Serial_4_Lane_16_to_12_bit_Output[] = { ++{0x31D0, 0x0001}, // COMPANDING ++{0x31AE, 0x0304}, // SERIAL_FORMAT: HISPI 4-lanes ++{0x31AC, 0x100C}, // DATA_FORMAT_BITS: ADC16, RAW12 ++//{0x301A, 0x0118}, // RESET_REGISTER ++{0x301A, 0x0018}, // RESET_REGISTER (MIPI) ++//{0x301A, 0x11d8}, // RESET_REGISTER (DVP) ++{ } ++}; /* Serial_4_Lane_16_to_12_bit_Output */ ++ + static const struct ar0147_reg ar0147_rev3_Serial_4_Lane_20_to_12_bit_Output[] = { + {0x31D0, 0x0001}, // COMPANDING + {0x31AE, 0x0304}, // SERIAL_FORMAT: HISPI 4-lanes +@@ -857,6 +920,20 @@ static const struct ar0147_reg *ar0147_regs_hdr_mipi450mbps_12bit_30fps_rev3[] = + NULL + }; + ++/* Super-Exposure Mode 1, Full Resolution, MIPI 450MBPS 4 lane 12-bit, 30FPS, XMCLK=24MHz */ ++static const struct ar0147_reg *ar0147_regs_se_mipi450mbps_12bit_30fps_rev3[] = { ++ ar0147_rev3_Reset, ++ ar0147_rev3_Sensor_Setup, ++ ar0147_rev3_Super_Exposure_Mode_1_Setup, ++ ar0147_rev3_Serial_12_bit_Timing_Setup, ++ ar0147_rev3_Readout_Mode_Configuration, ++ ar0147_rev3_Full_Res_FOV, ++ ar0147_rev3_SE_Mode_1_30FPS_Timing_and_Exposure, ++ ar0147_rev3_Serial_4_Lane_16_to_12_bit_Output, ++ ar0147_rev3_MIPI_12_bit_450MBps_Settings, ++ NULL ++}; ++ + /* Super-Exposure Plus T2 Mode 1, Full Resolution, MIPI 450MBPS 4 lane 12-bit, 30FPS, XMCLK=24MHz */ + static const struct ar0147_reg *ar0147_regs_seplus1_mipi450mbps_12bit_30fps_rev3[] = { + ar0147_rev3_Reset, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0399-media-i2c-ar0233-fix-artifact-line-at-vflip.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0399-media-i2c-ar0233-fix-artifact-line-at-vflip.patch new file mode 100644 index 00000000..bca65f39 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0399-media-i2c-ar0233-fix-artifact-line-at-vflip.patch @@ -0,0 +1,59 @@ +From f64967aaa784f0c9bebf0f58ac3b239a093dee00 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Fri, 19 Jul 2019 14:05:43 +0300 +Subject: [PATCH] media: i2c: ar0233: fix artifact line at vflip + +This fixes artifact line in super-exposure mode at vflip=1 + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ar0231.c | 2 +- + drivers/media/i2c/soc_camera/ar0233.c | 6 ++++++ + drivers/media/i2c/soc_camera/ar0233_rev2.h | 1 + + 3 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/i2c/soc_camera/ar0231.c b/drivers/media/i2c/soc_camera/ar0231.c +index b239f56..dfca9e2 100644 +--- a/drivers/media/i2c/soc_camera/ar0231.c ++++ b/drivers/media/i2c/soc_camera/ar0231.c +@@ -93,7 +93,7 @@ static int ar0231_set_window(struct v4l2_subdev *sd) + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ar0231_priv *priv = to_ar0231(client); + +- dev_err(&client->dev, "L=%d T=%d %dx%d\n", priv->rect.left, priv->rect.top, priv->rect.width, priv->rect.height); ++ dev_dbg(&client->dev, "L=%d T=%d %dx%d\n", priv->rect.left, priv->rect.top, priv->rect.width, priv->rect.height); + + /* horiz crop start */ + reg16_write16(client, 0x3004, priv->rect.left + AR0231_X_START); +diff --git a/drivers/media/i2c/soc_camera/ar0233.c b/drivers/media/i2c/soc_camera/ar0233.c +index 1b7ba22..71bff3f 100644 +--- a/drivers/media/i2c/soc_camera/ar0233.c ++++ b/drivers/media/i2c/soc_camera/ar0233.c +@@ -328,6 +328,12 @@ static int ar0233_s_ctrl(struct v4l2_ctrl *ctrl) + else + val &= ~(1 << 15); + ret |= reg16_write16(client, 0x3040, val); ++ ret = reg16_read16(client, 0x350e, &val); ++ if (ctrl->val) ++ val |= (1 << 0); ++ else ++ val &= ~(1 << 0); ++ ret |= reg16_write16(client, 0x350e, val); + break; + case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: + ret = 0; +diff --git a/drivers/media/i2c/soc_camera/ar0233_rev2.h b/drivers/media/i2c/soc_camera/ar0233_rev2.h +index 66c79ca..7085fbc 100644 +--- a/drivers/media/i2c/soc_camera/ar0233_rev2.h ++++ b/drivers/media/i2c/soc_camera/ar0233_rev2.h +@@ -2266,6 +2266,7 @@ static const struct ar0233_reg ar0233_rev2_O1_Recommended_Defaults_SE_T1_LIN_T2[ + + static const struct ar0233_reg ar0233_rev2_disable_embed_data_stat[] = { + {0x3040, 0xC000}, //Embedded stat2 and data2 rows, hflip/vflip=1 ++{0x350e, 0x2089}, // bit0 must be set for vflip=1 + #ifdef AR0233_EMBEDDED_LINE + {0x3064, 0x0180}, // SMIA_TEST: enable emb data and stats + #else +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0400-media-platform-soc_mediabus-add-Bayer-16bit-format.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0400-media-platform-soc_mediabus-add-Bayer-16bit-format.patch new file mode 100644 index 00000000..a5007fc0 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0400-media-platform-soc_mediabus-add-Bayer-16bit-format.patch @@ -0,0 +1,36 @@ +From c735a6b07b3fdb830cf0655c7c3aa447be8d62d6 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Mon, 29 Jul 2019 16:01:38 +0300 +Subject: [PATCH] media: platform: soc_mediabus: add Bayer 16bit format + +This adds MBUS format SBGGR16 + +Signed-off-by: Vladimir Barinov +--- + drivers/media/platform/soc_camera/soc_mediabus.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/media/platform/soc_camera/soc_mediabus.c b/drivers/media/platform/soc_camera/soc_mediabus.c +index d4e5c1e..768918e 100644 +--- a/drivers/media/platform/soc_camera/soc_mediabus.c ++++ b/drivers/media/platform/soc_camera/soc_mediabus.c +@@ -392,6 +392,16 @@ static const struct soc_mbus_lookup mbus_fmt[] = { + .order = SOC_MBUS_ORDER_LE, + .layout = SOC_MBUS_LAYOUT_PACKED, + }, ++}, { ++ .code = MEDIA_BUS_FMT_SBGGR16_1X16, ++ .fmt = { ++ .fourcc = V4L2_PIX_FMT_SBGGR16, ++ .name = "Bayer 16 RGGB", ++ .bits_per_sample = 16, ++ .packing = SOC_MBUS_PACKING_NONE, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, + }, + }; + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0401-media-i2c-ov490_ov10640-add-group-switch.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0401-media-i2c-ov490_ov10640-add-group-switch.patch new file mode 100644 index 00000000..184ff719 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0401-media-i2c-ov490_ov10640-add-group-switch.patch @@ -0,0 +1,103 @@ +From 2e0f2e9bd61f8a76b2cb6b9022a4787c6e6768ff Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Wed, 31 Jul 2019 13:46:17 +0300 +Subject: [PATCH] media: i2c: ov490_ov10640: add group switch + +This adds possible to use group switch. +By default vendors use group#1 in firmware. +Some vendors start with different group# + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ov490_ov10640.c | 21 +++++++++++++++++++++ + drivers/media/i2c/soc_camera/ov490_ov10640.h | 9 --------- + 2 files changed, 21 insertions(+), 9 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ov490_ov10640.c b/drivers/media/i2c/soc_camera/ov490_ov10640.c +index 0f1a0d4..49f373c 100644 +--- a/drivers/media/i2c/soc_camera/ov490_ov10640.c ++++ b/drivers/media/i2c/soc_camera/ov490_ov10640.c +@@ -54,6 +54,7 @@ struct ov490_priv { + int blue; + int awb; + int dvp_order; ++ int group; + /* serializers */ + int max9286_addr; + int max9271_addr; +@@ -77,6 +78,10 @@ static int max_height; + module_param(max_height, int, 0644); + MODULE_PARM_DESC(max_height, " Fixed sensor height"); + ++static int group = 0; ++module_param(group, int, 0644); ++MODULE_PARM_DESC(group, " group number (0 - does not apply)"); ++ + static inline struct ov490_priv *to_ov490(const struct i2c_client *client) + { + return container_of(i2c_get_clientdata(client), struct ov490_priv, sd); +@@ -858,6 +863,19 @@ static int ov490_initialize(struct i2c_client *client) + goto again; + } + ++ if (priv->group) { ++ /* switch to group# */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x5000, priv->group); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0xc0, 0x3f); ++ ++ mdelay(30); ++ } ++ + /* read resolution used by current firmware */ + reg16_write(client, 0xFFFD, 0x80); + reg16_write(client, 0xFFFE, 0x82); +@@ -903,6 +921,7 @@ static int ov490_parse_dt(struct device_node *np, struct ov490_priv *priv) + break; + + of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order); ++ of_property_read_u32(endpoint, "group", &priv->group); + + rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); + if (!rendpoint) +@@ -978,6 +997,8 @@ static int ov490_parse_dt(struct device_node *np, struct ov490_priv *priv) + priv->max_height = max_height; + priv->is_fixed_sensor = true; + } ++ if (group) ++ priv->group = group; + + return 0; + } +diff --git a/drivers/media/i2c/soc_camera/ov490_ov10640.h b/drivers/media/i2c/soc_camera/ov490_ov10640.h +index b00dc3ade..8ce8611 100644 +--- a/drivers/media/i2c/soc_camera/ov490_ov10640.h ++++ b/drivers/media/i2c/soc_camera/ov490_ov10640.h +@@ -17,12 +17,6 @@ struct ov490_reg { + }; + + static const struct ov490_reg ov490_regs_wizard[] = { +-/* Firmware start (some firmwares need this to kick processing) */ +-{0xfffd, 0x80}, +-{0xfffe, 0x19}, +-{0x5000, 0x05}, +-{0xfffe, 0x80}, +-{0x00c0, 0x3f}, + /* The following registers should match firmware */ + {0xfffd, 0x80}, + {0xfffe, 0x82}, +@@ -104,7 +98,4 @@ static const struct ov490_reg ov490_regs_wizard[] = { + {0xfffe, 0x80}, + {0x00c0, 0xd6}, + #endif +-/* respin register 0x6010 due to added firmware start HOST command */ +-{0xfffe, 0x29}, +-{0x6010, 0x01}, + }; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0402-media-i2c-gw5200-detection-workaround.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0402-media-i2c-gw5200-detection-workaround.patch new file mode 100644 index 00000000..f9d063d0 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0402-media-i2c-gw5200-detection-workaround.patch @@ -0,0 +1,118 @@ +From 78f7140c81532ad42eb3a167d7b4f83eee13701e Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Fri, 2 Aug 2019 21:20:00 +0300 +Subject: [PATCH] media: i2c: gw5200: detection workaround + +This adds detection of GW5200 workaround: +ISP starts for more then 1 second. Force detect gw5200 +if enabled in dts/cmdline and the serizlier presents +--- + drivers/media/i2c/soc_camera/gw5200_imx390.c | 39 +++++++++++++++++++++++++--- + 1 file changed, 35 insertions(+), 4 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/gw5200_imx390.c b/drivers/media/i2c/soc_camera/gw5200_imx390.c +index 90de41f..98352a9 100644 +--- a/drivers/media/i2c/soc_camera/gw5200_imx390.c ++++ b/drivers/media/i2c/soc_camera/gw5200_imx390.c +@@ -22,10 +22,10 @@ + + #include "gw5200_imx390.h" + +-static const int gw5200_i2c_addr[] = {0x18}; ++static const int gw5200_i2c_addr[] = {0x6d}; + + #define GW5200_PID 0x00 +-#define GW5200_VERSION_REG 0x30 ++#define GW5200_VERSION_REG 0x00 + + #define GW5200_MEDIA_BUS_FMT MEDIA_BUS_FMT_YUYV8_2X8 + +@@ -41,6 +41,7 @@ struct gw5200_priv { + int exposure; + int gain; + int autogain; ++ int gw5200; + /* serializers */ + int max9286_addr; + int max9271_addr; +@@ -51,6 +52,10 @@ struct gw5200_priv { + int gpio_fsin; + }; + ++static int gw5200 = 0; ++module_param(gw5200, int, 0644); ++MODULE_PARM_DESC(gw5200, " gw5200 force (0 - imager disabled)"); ++ + static inline struct gw5200_priv *to_gw5200(const struct i2c_client *client) + { + return container_of(i2c_get_clientdata(client), struct gw5200_priv, sd); +@@ -337,9 +342,10 @@ static DEVICE_ATTR(otp_id_gw5200, S_IRUGO, gw5200_otp_id_show, NULL); + static int gw5200_initialize(struct i2c_client *client) + { + struct gw5200_priv *priv = to_gw5200(client); +- u8 pid = 0; ++ u8 pid = 0xff; + int ret = 0; + int tmp_addr; ++#if 0 + int i; + + for (i = 0; i < ARRAY_SIZE(gw5200_i2c_addr); i++) { +@@ -357,7 +363,7 @@ static int gw5200_initialize(struct i2c_client *client) + client->addr = tmp_addr; + + /* check model ID */ +- reg8_read(client, GW5200_PID, &pid); ++ ret = reg8_read(client, GW5200_PID, &pid); + + if (pid == GW5200_VERSION_REG) + break; +@@ -368,6 +374,23 @@ static int gw5200_initialize(struct i2c_client *client) + ret = -ENODEV; + goto err; + } ++#else ++ // Workaround: GW5200 has some hidden protocol to access it's registers, hence check serializer and dts ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x3_addr; /* Serializer I2C address */ ++ /* check UB953 ID */ ++ reg8_read(client, 0xf1, &pid); ++ } ++ client->addr = tmp_addr; ++ ++ if (pid != 'U') { ++ dev_dbg(&client->dev, "Product ID error %x\n", pid); ++ ret = -ENODEV; ++ goto err; ++ } ++#endif ++ + #if 0 + /* Program wizard registers */ + gw5200_set_regs(client, gw5200_regs_wizard, ARRAY_SIZE(gw5200_regs_wizard)); +@@ -393,6 +416,8 @@ static int gw5200_parse_dt(struct device_node *np, struct gw5200_priv *priv) + if (!endpoint) + break; + ++ of_property_read_u32(endpoint, "gw5200", &priv->gw5200); ++ + rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); + if (!rendpoint) + continue; +@@ -437,6 +462,12 @@ static int gw5200_parse_dt(struct device_node *np, struct gw5200_priv *priv) + + mdelay(10); + ++ if (gw5200) ++ priv->gw5200 = gw5200; ++ ++ if (!priv->gw5200) ++ return -ENODEV; ++ + return 0; + } + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0403-media-i2c-ov2311-put-to-autodetect-head.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0403-media-i2c-ov2311-put-to-autodetect-head.patch new file mode 100644 index 00000000..460474a3 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0403-media-i2c-ov2311-put-to-autodetect-head.patch @@ -0,0 +1,48 @@ +From 724e16aa8fbc060167beeb3faeb375537616fa2c Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Fri, 2 Aug 2019 23:12:13 +0300 +Subject: [PATCH] media: i2c: ov2311: put to autodetect head + +This puts OV2311 in autodetect head becase the serializer +remote gpio is controlled from command line only + +Imagers that have remote gpios in glue must be in tail + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ov106xx.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ov106xx.c b/drivers/media/i2c/soc_camera/ov106xx.c +index 21dffcd8..eaa492e 100644 +--- a/drivers/media/i2c/soc_camera/ov106xx.c ++++ b/drivers/media/i2c/soc_camera/ov106xx.c +@@ -91,6 +91,12 @@ static int ov106xx_probe(struct i2c_client *client, + goto out; + } + ++ ret = ov2311_probe(client, did); ++ if (!ret) { ++ chip_id = ID_OV2311; ++ goto out; ++ } ++ + ret = ov10635_probe(client, did); + if (!ret) { + chip_id = ID_OV10635; +@@ -145,12 +151,6 @@ static int ov106xx_probe(struct i2c_client *client, + goto out; + } + +- ret = ov2311_probe(client, did); +- if (!ret) { +- chip_id = ID_OV2311; +- goto out; +- } +- + ret = imx390_probe(client, did); + if (!ret) { + chip_id = ID_IMX390; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0404-media-i2c-onsemi-imager-correct-trigger-handling.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0404-media-i2c-onsemi-imager-correct-trigger-handling.patch new file mode 100644 index 00000000..79b12c5a --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0404-media-i2c-onsemi-imager-correct-trigger-handling.patch @@ -0,0 +1,165 @@ +From 783eb39cdc3a26582dbe6031f7d112441a7cccd1 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Sat, 3 Aug 2019 00:24:36 +0300 +Subject: [PATCH] media: i2c: onsemi imager correct trigger handling + +This add trigger enablement from dts/bootargs + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ar0147.c | 6 +++--- + drivers/media/i2c/soc_camera/ar0231.c | 24 ++++++++++++++++++++++-- + drivers/media/i2c/soc_camera/ar0231_rev7.h | 6 +++--- + drivers/media/i2c/soc_camera/ar0233.c | 18 ++++++++---------- + 4 files changed, 36 insertions(+), 18 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ar0147.c b/drivers/media/i2c/soc_camera/ar0147.c +index 53be588..08fd136 100644 +--- a/drivers/media/i2c/soc_camera/ar0147.c ++++ b/drivers/media/i2c/soc_camera/ar0147.c +@@ -532,7 +532,7 @@ static int ar0147_initialize(struct i2c_client *client) + client->addr = tmp_addr; + + /* Enable trigger */ +- if (priv->trigger < 4) { ++ if (priv->trigger >= 0 && priv->trigger < 4) { + reg16_write16(client, 0x340A, (~(BIT(priv->trigger) << 4)) & 0xf0);/* GPIO_CONTROL1: GPIOn input enable */ + reg16_write16(client, 0x340C, (0x2 << 2*priv->trigger)); /* GPIO_CONTROL2: GPIOn is trigger */ + reg16_write16(client, 0x30CE, 0x0120); /* TRIGGER_MODE */ +@@ -554,8 +554,8 @@ static int ar0147_initialize(struct i2c_client *client) + } + reg16_write16(client, 0x301a, val); + +- dev_info(&client->dev, "ar0147 PID %x (rev %x), res %dx%d, mode=%s, mbus=%s, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", +- pid, rev, AR0147_MAX_WIDTH, AR0147_MAX_HEIGHT, mode, mbus, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++ dev_info(&client->dev, "ar0147 PID %x (rev%x), res %dx%d, mode=%s, mbus=%s, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, rev & 0xf, AR0147_MAX_WIDTH, AR0147_MAX_HEIGHT, mode, mbus, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); + err: + ar0147_s_port(client, 0); + +diff --git a/drivers/media/i2c/soc_camera/ar0231.c b/drivers/media/i2c/soc_camera/ar0231.c +index dfca9e2..36b5657 100644 +--- a/drivers/media/i2c/soc_camera/ar0231.c ++++ b/drivers/media/i2c/soc_camera/ar0231.c +@@ -45,8 +45,13 @@ struct ar0231_priv { + int port; + int gpio_resetb; + int gpio_fsin; ++ int trigger; + }; + ++static int trigger = 0; ++module_param(trigger, int, 0644); ++MODULE_PARM_DESC(trigger, " Trigger gpio number (default: 0 - GPIO0) "); ++ + static inline struct ar0231_priv *to_ar0231(const struct i2c_client *client) + { + return container_of(i2c_get_clientdata(client), struct ar0231_priv, sd); +@@ -436,13 +441,21 @@ static int ar0231_initialize(struct i2c_client *client) + if (priv->max9286_addr) + ar0231_set_regs(client, ar0231_regs_wizard_rev6_dvp, ARRAY_SIZE(ar0231_regs_wizard_rev6_dvp)); + ++ /* Enable trigger */ ++ if (priv->trigger >= 0 && priv->trigger < 4) { ++ reg16_write16(client, 0x340A, (~(BIT(priv->trigger) << 4)) & 0xf0);/* GPIO_CONTROL1: GPIOn input enable */ ++ reg16_write16(client, 0x340C, (0x2 << 2*priv->trigger)); /* GPIO_CONTROL2: GPIOn is trigger */ ++ reg16_write16(client, 0x30CE, 0x0120); /* TRIGGER_MODE */ ++ //reg16_write16(client, 0x30DC, 0x0120); /* TRIGGER_DELAY */ ++ } ++ + /* Enable stream */ + reg16_read16(client, 0x301a, &val); + val |= (1 << 2); + reg16_write16(client, 0x301a, val); + +- dev_info(&client->dev, "ar0231 PID %x (rev %x), res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", +- pid, rev, AR0231_MAX_WIDTH, AR0231_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++ dev_info(&client->dev, "ar0231 PID %x (rev%x), res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, rev & 0xf, AR0231_MAX_WIDTH, AR0231_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); + err: + ar0231_s_port(client, 0); + return ret; +@@ -460,6 +473,9 @@ static int ar0231_parse_dt(struct device_node *np, struct ar0231_priv *priv) + if (!endpoint) + break; + ++ if (of_property_read_u32(endpoint, "trigger", &priv->trigger)) ++ priv->trigger = 0; ++ + rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); + if (!rendpoint) + continue; +@@ -502,6 +518,10 @@ static int ar0231_parse_dt(struct device_node *np, struct ar0231_priv *priv) + } + client->addr = tmp_addr; + ++ /* module params override dts */ ++ if (trigger) ++ priv->trigger = trigger; ++ + return 0; + } + +diff --git a/drivers/media/i2c/soc_camera/ar0231_rev7.h b/drivers/media/i2c/soc_camera/ar0231_rev7.h +index 5f196e8..704024a 100644 +--- a/drivers/media/i2c/soc_camera/ar0231_rev7.h ++++ b/drivers/media/i2c/soc_camera/ar0231_rev7.h +@@ -389,9 +389,9 @@ static const struct ar0231_reg ar0231_regs_wizard_rev7[] = { + {0x300C, AR0231_SENSOR_WIDTH + 550}, // Line_length_pck + {0x3012, 0x144}, //Integration_time + +-#if 1 /* Enable trigger input */ +-{0x340A, 0x00E0}, // GPIO_CONTROL1: GPIO1 is trigger +-{0x340C, 0x0002}, // GPIO_CONTROL2: GPIO1 is trigger ++#if 0 /* Enable trigger input */ ++{0x340A, 0x00E0}, // GPIO_CONTROL1: GPIO0 is trigger ++{0x340C, 0x0002}, // GPIO_CONTROL2: GPIO0 is trigger + {0x30CE, 0x0120}, // TRIGGER_MODE + //{0x30DC, 0x0120}, // TRIGGER_DELAY + {0x301A, 0x0118}, // GPI pins enable +diff --git a/drivers/media/i2c/soc_camera/ar0233.c b/drivers/media/i2c/soc_camera/ar0233.c +index 71bff3f..9294267 100644 +--- a/drivers/media/i2c/soc_camera/ar0233.c ++++ b/drivers/media/i2c/soc_camera/ar0233.c +@@ -44,10 +44,6 @@ struct ar0233_priv { + int trigger; + }; + +-static int trigger = 0; +-module_param(trigger, int, 0644); +-MODULE_PARM_DESC(trigger, " Trigger gpio number (default: 0 - GPIO0) "); +- + static int extclk = 23; + module_param(extclk, int, 0644); + MODULE_PARM_DESC(extclk, " EXTCLK value in MHz (default: 23) "); +@@ -459,10 +455,12 @@ static int ar0233_initialize(struct i2c_client *client) + } + + /* Enable trigger */ +- reg16_write16(client, 0x340A, (~(BIT(priv->trigger) << 4)) & 0xf0); /* GPIO_CONTROL1: GPIOn input enable */ +- reg16_write16(client, 0x340C, (0x2 << 2*priv->trigger)); /* GPIO_CONTROL2: GPIOn is trigger */ +- reg16_write16(client, 0x30CE, 0x0120); /* TRIGGER_MODE */ +- //reg16_write16(client, 0x30DC, 0x0120); /* TRIGGER_DELAY */ ++ if (priv->trigger >= 0 && priv->trigger < 4) { ++ reg16_write16(client, 0x340A, (~(BIT(priv->trigger) << 4)) & 0xf0); /* GPIO_CONTROL1: GPIOn input enable */ ++ reg16_write16(client, 0x340C, (0x2 << 2*priv->trigger)); /* GPIO_CONTROL2: GPIOn is trigger */ ++ reg16_write16(client, 0x30CE, 0x0120); /* TRIGGER_MODE */ ++ //reg16_write16(client, 0x30DC, 0x0120); /* TRIGGER_DELAY */ ++ } + + /* Enable stream */ + reg16_read16(client, 0x301a, &val); // read inital reset_register value +@@ -470,8 +468,8 @@ static int ar0233_initialize(struct i2c_client *client) + val |= (1 << 2); // Set streamOn bit + reg16_write16(client, 0x301a, val); // Start Streaming + +- dev_info(&client->dev, "ar0233 PID %x (rev %x), res %dx%d, mode=%s, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", +- pid, rev, AR0233_MAX_WIDTH, AR0233_MAX_HEIGHT, mode, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++ dev_info(&client->dev, "ar0233 PID %x (rev%x), res %dx%d, mode=%s, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, rev & 0xf, AR0233_MAX_WIDTH, AR0233_MAX_HEIGHT, mode, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); + err: + return ret; + } +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0405-media-i2c-ov10640-fix-controls.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0405-media-i2c-ov10640-fix-controls.patch new file mode 100644 index 00000000..179e28c7 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0405-media-i2c-ov10640-fix-controls.patch @@ -0,0 +1,70 @@ +From 9a56fad72e10479fb7ec44a9e871261daba75a18 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Sat, 3 Aug 2019 01:34:49 +0300 +Subject: [PATCH] media: i2c: ov10640: fix controls + +This fixes v4l2 controls + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ov10640.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ov10640.c b/drivers/media/i2c/soc_camera/ov10640.c +index 31117e5..4ce6e15 100644 +--- a/drivers/media/i2c/soc_camera/ov10640.c ++++ b/drivers/media/i2c/soc_camera/ov10640.c +@@ -320,7 +320,7 @@ static int ov10640_s_ctrl(struct v4l2_ctrl *ctrl) + case V4L2_CID_GAIN: + reg16_write(client, 0x30EC, ctrl->val); // L + reg16_write(client, 0x30EE, ctrl->val); // S +- reg16_write(client, 0x30F0, ctrl->val); // VS ++ ret = reg16_write(client, 0x30F0, ctrl->val); // VS + break; + case V4L2_CID_ANALOGUE_GAIN: + reg16_read(client, 0x30EB, &val); +@@ -328,7 +328,7 @@ static int ov10640_s_ctrl(struct v4l2_ctrl *ctrl) + val |= ((ctrl->val / 2) << 0); // L + val |= (ctrl->val << 2); // S + val |= ((ctrl->val / 2) << 4); // VS +- reg16_write(client, 0x30EB, val); ++ ret = reg16_write(client, 0x30EB, val); + break; + case V4L2_CID_EXPOSURE: + val16 = 0xfff - ctrl->val; +@@ -337,16 +337,18 @@ static int ov10640_s_ctrl(struct v4l2_ctrl *ctrl) + reg16_write(client, 0x30E7, val16 & 0xff); // L + + reg16_write(client, 0x30E8, val16 >> 8); // S +- reg16_write(client, 0x30E9, val16 & 0xff); // S ++ ret = reg16_write(client, 0x30E9, val16 & 0xff);// S + +-// reg16_write(client, 0x30EA, val >> 8); // VS - fractional ... ++// ret = reg16_write(client, 0x30EA, val >> 8); // VS - fractional ... + break; ++#if 0 + case V4L2_CID_EXPOSURE_AUTO: + reg16_read(client, 0x30FA, &val); + val &= ~(0x1 << 6); + val |= (ctrl->val << 6); +- reg16_write(client, 0x30FA, val); ++ ret = reg16_write(client, 0x30FA, val); + break; ++#endif + case V4L2_CID_HFLIP: + reg16_read(client, 0x3128, &val); + val &= ~(0x1 << 0); +@@ -585,8 +587,10 @@ static int ov10640_probe(struct i2c_client *client, + V4L2_CID_ANALOGUE_GAIN, 0, 3, 1, 1); + v4l2_ctrl_new_std(&priv->hdl, &ov10640_ctrl_ops, + V4L2_CID_EXPOSURE, 0, 0xfff, 1, 0x448); ++#if 0 + v4l2_ctrl_new_std(&priv->hdl, &ov10640_ctrl_ops, + V4L2_CID_EXPOSURE_AUTO, 0, 1, 1, 0); ++#endif + v4l2_ctrl_new_std(&priv->hdl, &ov10640_ctrl_ops, + V4L2_CID_HFLIP, 0, 1, 1, 1); + v4l2_ctrl_new_std(&priv->hdl, &ov10640_ctrl_ops, +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0406-Add-new-custom_ioctl-ops-for-soc-camera.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0406-Add-new-custom_ioctl-ops-for-soc-camera.patch new file mode 100644 index 00000000..599b8a42 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0406-Add-new-custom_ioctl-ops-for-soc-camera.patch @@ -0,0 +1,58 @@ +From cf252d28e6db8fdcc6e21ae456835cdd3920b3ce Mon Sep 17 00:00:00 2001 +From: Petr Nechaev +Date: Sat, 3 Aug 2019 00:39:57 +0300 +Subject: [PATCH] Add new custom_ioctl ops for soc camera + +It allows to implement custom ioctls in soc_camera host drivers. +--- + drivers/media/platform/soc_camera/soc_camera.c | 13 +++++++++++++ + include/media/soc_camera.h | 2 ++ + 2 files changed, 15 insertions(+) + +diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c +index 7e5ca15adb2b..80846832dd61 100644 +--- a/drivers/media/platform/soc_camera/soc_camera.c ++++ b/drivers/media/platform/soc_camera/soc_camera.c +@@ -1075,6 +1075,18 @@ static int soc_camera_g_edid(struct file *file, void *fh, + return -ENOIOCTLCMD; + } + ++static long soc_camera_default(struct file *file, void *fh, ++ bool valid_prio, unsigned int cmd, void *arg) ++{ ++ struct soc_camera_device *icd = video_drvdata(file); ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ ++ if (ici->ops->custom_ioctl) ++ return ici->ops->custom_ioctl(icd, valid_prio, cmd, arg); ++ ++ return -ENOIOCTLCMD; ++} ++ + #ifdef CONFIG_VIDEO_ADV_DEBUG + static int soc_camera_g_register(struct file *file, void *priv, + struct v4l2_dbg_register *reg) +@@ -2092,6 +2104,7 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = { + .vidioc_g_parm = soc_camera_g_parm, + .vidioc_s_parm = soc_camera_s_parm, + .vidioc_g_edid = soc_camera_g_edid, ++ .vidioc_default = soc_camera_default, + #ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = soc_camera_g_register, + .vidioc_s_register = soc_camera_s_register, +diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h +index 53c650d82b57..adcfadabcdc5 100644 +--- a/include/media/soc_camera.h ++++ b/include/media/soc_camera.h +@@ -124,6 +124,8 @@ struct soc_camera_host_ops { + int (*enum_framesizes)(struct soc_camera_device *, struct v4l2_frmsizeenum *); + unsigned int (*poll)(struct file *, poll_table *); + int (*get_edid)(struct soc_camera_device *, struct v4l2_edid *); ++ long (*custom_ioctl)(struct soc_camera_device *, bool valid_prio, ++ unsigned int cmd, void *arg); + #ifdef CONFIG_VIDEO_ADV_DEBUG + int (*get_register)(struct soc_camera_device *, struct v4l2_dbg_register *reg); + int (*set_register)(struct soc_camera_device *, const struct v4l2_dbg_register *reg); +-- +2.20.1 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0407-arm64-dts-renesas-r8a77970-v3msk-Fix-memory-size.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0407-arm64-dts-renesas-r8a77970-v3msk-Fix-memory-size.patch new file mode 100644 index 00000000..d193d6e2 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0407-arm64-dts-renesas-r8a77970-v3msk-Fix-memory-size.patch @@ -0,0 +1,28 @@ +From 0eaccc1648824c2059d93d0395552efe5c057e38 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Fri, 9 Aug 2019 01:36:33 +0300 +Subject: [PATCH] arm64: dts: renesas: r8a77970-v3msk: Fix memory size + +The V3MSK board has 2GB RAM according to the datasheet. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +index 107d041..d6deffe 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +@@ -25,7 +25,7 @@ + memory@48000000 { + device_type = "memory"; + /* first 128MB is reserved for secure area. */ +- reg = <0x0 0x48000000 0x0 0x38000000>; ++ reg = <0x0 0x48000000 0x0 0x78000000>; + }; + + reserved-memory { +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0408-arm64-dts-renesas-v3hsk-Add-GEther-PHY-GPIO-reset-pi.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0408-arm64-dts-renesas-v3hsk-Add-GEther-PHY-GPIO-reset-pi.patch new file mode 100644 index 00000000..54e4762c --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0408-arm64-dts-renesas-v3hsk-Add-GEther-PHY-GPIO-reset-pi.patch @@ -0,0 +1,36 @@ +From 94eabe59e8f83cdd68ce763f3ce8a9e2533cc737 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Tue, 13 Aug 2019 23:02:19 +0300 +Subject: [PATCH 1/3] arm64: dts: renesas: v3hsk: Add GEther PHY GPIO reset pin + support + +This adds "reset-gpios" property to the GEther PHY device tree node. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +index f52dc2d..9e907b9 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts +@@ -8,6 +8,7 @@ + + /dts-v1/; + #include "r8a77980.dtsi" ++#include + + / { + model = "Renesas V3H Starter Kit board"; +@@ -150,6 +151,7 @@ + reg = <0>; + interrupt-parent = <&gpio4>; + interrupts = <23 IRQ_TYPE_LEVEL_LOW>; ++ reset-gpios = <&gpio4 22 GPIO_ACTIVE_LOW>; + }; + }; + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0409-arm64-dts-renesas-condor-Add-GEther-PHY-GPIO-reset-p.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0409-arm64-dts-renesas-condor-Add-GEther-PHY-GPIO-reset-p.patch new file mode 100644 index 00000000..a3baca8e --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0409-arm64-dts-renesas-condor-Add-GEther-PHY-GPIO-reset-p.patch @@ -0,0 +1,28 @@ +From 96c4aea87df924d7430957b9c37eac5f200e382a Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Tue, 13 Aug 2019 23:04:03 +0300 +Subject: [PATCH 2/3] arm64: dts: renesas: condor: Add GEther PHY GPIO reset + pin support + +This adds "reset-gpios" property to the GEther PHY device tree node. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77980-condor.dts | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +index e21dadd..f98a25e 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts +@@ -145,6 +145,7 @@ + reg = <0>; + interrupt-parent = <&gpio1>; + interrupts = <17 IRQ_TYPE_LEVEL_LOW>; ++ reset-gpios = <&gpio4 22 GPIO_ACTIVE_LOW>; + }; + }; + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0410-arm64-dts-renesas-eagle-Add-RAVB-PHY-GPIO-reset-pin-.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0410-arm64-dts-renesas-eagle-Add-RAVB-PHY-GPIO-reset-pin-.patch new file mode 100644 index 00000000..c4c3b018 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0410-arm64-dts-renesas-eagle-Add-RAVB-PHY-GPIO-reset-pin-.patch @@ -0,0 +1,28 @@ +From 587b37dfb949accafc981f9c6f6b1a245f940ab6 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Tue, 13 Aug 2019 23:05:00 +0300 +Subject: [PATCH 3/3] arm64: dts: renesas: eagle: Add RAVB PHY GPIO reset pin + support + +This adds "gpio-resets" property to the RAVB PHY device tree node. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a77970-eagle.dts | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +index 7525bc9..706d75e 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts ++++ b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts +@@ -132,6 +132,7 @@ + reg = <0>; + interrupt-parent = <&gpio1>; + interrupts = <17 IRQ_TYPE_LEVEL_LOW>; ++ reset-gpios = <&gpio1 16 GPIO_ACTIVE_LOW>; + }; + }; + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0411-media-soc_camera-add-MAX9288-support.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0411-media-soc_camera-add-MAX9288-support.patch new file mode 100644 index 00000000..78712a42 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0411-media-soc_camera-add-MAX9288-support.patch @@ -0,0 +1,956 @@ +From 21d57c5af828faddf2bea88a1dc3715a936ffe5d Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Wed, 14 Aug 2019 14:15:02 +0300 +Subject: [PATCH 1/3] media: soc_camera: add MAX9288 support + +This adds MAX9288 deserializer support + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/Kconfig | 6 + + drivers/media/i2c/soc_camera/Makefile | 1 + + drivers/media/i2c/soc_camera/max9286.h | 57 +- + drivers/media/i2c/soc_camera/max9288.c | 747 +++++++++++++++++++++++++++ + drivers/media/platform/soc_camera/rcar_vin.c | 19 +- + 5 files changed, 779 insertions(+), 51 deletions(-) + create mode 100644 drivers/media/i2c/soc_camera/max9288.c + +diff --git a/drivers/media/i2c/soc_camera/Kconfig b/drivers/media/i2c/soc_camera/Kconfig +index edff0b0..729b5af 100644 +--- a/drivers/media/i2c/soc_camera/Kconfig ++++ b/drivers/media/i2c/soc_camera/Kconfig +@@ -89,6 +89,12 @@ config SOC_CAMERA_MAX9286 + help + This is a MAXIM max9286 GMSL driver + ++config SOC_CAMERA_MAX9288 ++ tristate "max9288 GMSL support" ++ depends on SOC_CAMERA && I2C ++ help ++ This is a MAXIM max9288 GMSL driver ++ + config SOC_CAMERA_TI9X4 + tristate "ti9x4 FPDLink3 support" + depends on SOC_CAMERA && I2C +diff --git a/drivers/media/i2c/soc_camera/Makefile b/drivers/media/i2c/soc_camera/Makefile +index 367674b..7bbcaaa 100644 +--- a/drivers/media/i2c/soc_camera/Makefile ++++ b/drivers/media/i2c/soc_camera/Makefile +@@ -12,6 +12,7 @@ obj-$(CONFIG_SOC_CAMERA_OV9740) += ov9740.o + obj-$(CONFIG_SOC_CAMERA_RJ54N1) += rj54n1cb0c.o + obj-$(CONFIG_SOC_CAMERA_TW9910) += tw9910.o + obj-$(CONFIG_SOC_CAMERA_MAX9286) += max9286.o ++obj-$(CONFIG_SOC_CAMERA_MAX9288) += max9288.o + obj-$(CONFIG_SOC_CAMERA_TI9X4) += ti9x4.o + obj-$(CONFIG_SOC_CAMERA_OV106XX) += ov106xx.o + obj-$(CONFIG_SOC_CAMERA_IMX219) += imx219.o +diff --git a/drivers/media/i2c/soc_camera/max9286.h b/drivers/media/i2c/soc_camera/max9286.h +index 2875b3c..23ed035 100644 +--- a/drivers/media/i2c/soc_camera/max9286.h ++++ b/drivers/media/i2c/soc_camera/max9286.h +@@ -1,7 +1,7 @@ + /* +- * MAXIM max9286-max9271 GMSL driver include file ++ * MAXIM max9286/max9288 GMSL driver include file + * +- * Copyright (C) 2015-2017 Cogent Embedded, Inc. ++ * Copyright (C) 2015-2019 Cogent Embedded, Inc. + * + * 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 +@@ -9,8 +9,8 @@ + * option) any later version. + */ + +-#ifndef _MAX9286_MAX9271_H +-#define _MAX9286_MAX9271_H ++#ifndef _MAX92XX_H ++#define _MAX92XX_H + + //#define DEBUG + #ifdef DEBUG +@@ -26,6 +26,8 @@ + #define MAX96705_ID 0x41 + #define MAX96707_ID 0x45 /* MAX96715: there is no HS pin */ + #define MAX9286_ID 0x40 ++#define MAX9288_ID 0x2A ++#define MAX9290_ID 0x2C + #define BROADCAST 0x6f + + static inline int reg8_read(struct i2c_client *client, u8 reg, u8 *val) +@@ -177,52 +179,7 @@ static inline int reg16_write16(struct i2c_client *client, u16 reg, u16 val) + return ret < 0 ? ret : 0; + } + +- + #ifdef MAXIM_DUMP +-static void maxim_ovsensor_dump_regs(struct i2c_client *client) +-{ +- int ret, i; +- u8 val = 0; +- u16 regs[] = {0x300a, 0x300b, 0x300c}; +- +- dev_dbg(&client->dev, "dump regs 0x%x\n", client->addr); +- +- for (i = 0; i < sizeof(regs) / 2; i++) { +- ret = reg16_read(client, regs[i], &val); +- if (ret < 0) +- dev_err(&client->dev, +- "read fail: chip 0x%x register 0x%02x: %d\n", +- client->addr, regs[i], ret); +- printk("0x%02x -> 0x%x\n", regs[i], val); +- } +-} +- +-static void maxim_ov10635_dump_format_regs(struct i2c_client *client) +-{ +- int ret, i; +- u8 val; +- u16 regs[] = {0x3003, 0x3004, 0x4300, +- 0x4605, 0x3621, 0x3702, 0x3703, 0x3704, +- 0x3802, 0x3803, 0x3806, 0x3807, 0x3808, 0x3809, 0x380a, +- 0x380b, 0x380c, 0x380d, 0x380e, 0x380f, +- 0x4606, 0x4607, 0x460a, 0x460b, +- 0xc488, 0xc489, 0xc48a, 0xc48b, +- 0xc4cc, 0xc4cd, 0xc4ce, 0xc4cf, 0xc512, 0xc513, +- 0xc518, 0xc519, 0xc51a, 0xc51b, +- }; +- +- dev_dbg(&client->dev, "dump regs 0x%x\n", client->addr); +- +- for (i = 0; i < sizeof(regs) / 2; i++) { +- ret = reg16_read(client, regs[i], &val); +- if (ret < 0) +- dev_err(&client->dev, +- "read fail: chip 0x%x register 0x%02x: %d\n", +- client->addr, regs[i], ret); +- printk("0x%02x -> 0x%x\n", regs[i], val); +- } +-} +- + static void maxim_max927x_dump_regs(struct i2c_client *client) + { + int ret; +@@ -242,4 +199,4 @@ static void maxim_max927x_dump_regs(struct i2c_client *client) + } + } + #endif /* MAXIM_DUMP */ +-#endif /* _MAX9286_MAX9271_H */ ++#endif /* _MAX92XX_H */ +diff --git a/drivers/media/i2c/soc_camera/max9288.c b/drivers/media/i2c/soc_camera/max9288.c +new file mode 100644 +index 0000000..dd57074 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/max9288.c +@@ -0,0 +1,747 @@ ++/* ++ * MAXIM max9288 GMSL driver ++ * ++ * Copyright (C) 2019 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "max9286.h" ++ ++#define MAXIM_I2C_I2C_SPEED_837KHZ (0x7 << 2) /* 837kbps */ ++#define MAXIM_I2C_I2C_SPEED_533KHZ (0x6 << 2) /* 533kbps */ ++#define MAXIM_I2C_I2C_SPEED_339KHZ (0x5 << 2) /* 339 kbps */ ++#define MAXIM_I2C_I2C_SPEED_173KHZ (0x4 << 2) /* 174kbps */ ++#define MAXIM_I2C_I2C_SPEED_105KHZ (0x3 << 2) /* 105 kbps */ ++#define MAXIM_I2C_I2C_SPEED_085KHZ (0x2 << 2) /* 84.7 kbps */ ++#define MAXIM_I2C_I2C_SPEED_028KHZ (0x1 << 2) /* 28.3 kbps */ ++#define MAXIM_I2C_I2C_SPEED MAXIM_I2C_I2C_SPEED_339KHZ ++ ++struct max9288_priv { ++ struct v4l2_subdev sd; ++ struct fwnode_handle *sd_fwnode; ++ int des_addr; ++ int lanes; ++ int csi_rate; ++ int pclk; ++ char pclk_rising_edge; ++ int gpio_resetb; ++ int active_low_resetb; ++ int him; ++ int hsync; ++ int vsync; ++ int timeout; ++ int poc_delay; ++ int bws; ++ int dbl; ++ int dt; ++ int hsgen; ++ int hts; ++ int vts; ++ int hts_delay; ++ struct i2c_client *client; ++ int max9271_addr; ++ int ser_id; ++ struct gpio_desc *poc_gpio; /* PoC power supply */ ++}; ++ ++static int conf_link; ++module_param(conf_link, int, 0644); ++MODULE_PARM_DESC(conf_link, " Force configuration link. Used only if robust firmware flashing required (f.e. recovery)"); ++ ++static int poc_trig; ++module_param(poc_trig, int, 0644); ++MODULE_PARM_DESC(poc_trig, " Use PoC triggering during reverse channel setup. Useful on systems with dedicated PoC and unstable ser-des lock"); ++ ++static int him = 0; ++module_param(him, int, 0644); ++MODULE_PARM_DESC(him, " Use High-Immunity mode (default: leagacy mode)"); ++ ++static int hsync; ++module_param(hsync, int, 0644); ++MODULE_PARM_DESC(hsync, " HSYNC invertion (default: 0 - not inverted)"); ++ ++static int vsync = 1; ++module_param(vsync, int, 0644); ++MODULE_PARM_DESC(vsync, " VSYNC invertion (default: 1 - inverted)"); ++ ++static int gpio_resetb; ++module_param(gpio_resetb, int, 0644); ++MODULE_PARM_DESC(gpio_resetb, " Serializer GPIO reset (default: 0 - not used)"); ++ ++static int active_low_resetb; ++module_param(active_low_resetb, int, 0644); ++MODULE_PARM_DESC(active_low_resetb, " Serializer GPIO reset level (default: 0 - active high)"); ++ ++static int timeout_n = 100; ++module_param(timeout_n, int, 0644); ++MODULE_PARM_DESC(timeout_n, " Timeout of link detection (default: 100 retries)"); ++ ++static int poc_delay = 50; ++module_param(poc_delay, int, 0644); ++MODULE_PARM_DESC(poc_delay, " Delay in ms after POC enable (default: 50 ms)"); ++ ++static int bws = 0; ++module_param(bws, int, 0644); ++MODULE_PARM_DESC(bws, " BWS mode (default: 0 - 24-bit gmsl packets)"); ++ ++static int dbl = 1; ++module_param(dbl, int, 0644); ++MODULE_PARM_DESC(dbl, " DBL mode (default: 1 - DBL mode enabled)"); ++ ++static int dt = 3; ++module_param(dt, int, 0644); ++MODULE_PARM_DESC(dt, " DataType (default: 3 - YUV8), 0 - RGB888, 5 - RAW8, 6 - RAW10, 7 - RAW12, 8 - RAW14"); ++ ++static int hsgen; ++module_param(hsgen, int, 0644); ++MODULE_PARM_DESC(hsgen, " Enable HS embedded generator (default: 0 - disabled)"); ++ ++static int pclk = 100; ++module_param(pclk, int, 0644); ++MODULE_PARM_DESC(pclk, " PCLK rate (default: 100MHz)"); ++ ++enum { ++ RGB888_DT = 0, ++ RGB565_DT, ++ RGB666_DT, ++ YUV8_DT, /* default */ ++ YUV10_DT, ++ RAW8_DT, ++ RAW10_DT, ++ RAW12_DT, ++ RAW14_DT, ++}; ++ ++static int dt2bpp [9] = { ++ 24, /* RGB888 */ ++ 16, /* RGB565 */ ++ 18, /* RGB666 */ ++ 8, /* YUV8 - default */ ++ 10, /* YUV10 */ ++ 8, /* RAW8/RAW16 */ ++ 10, /* RAW10 */ ++ 12, /* RAW12 */ ++ 14, /* RAW14 */ ++}; ++ ++static char* ser_name(int id) ++{ ++ switch (id) { ++ case MAX9271_ID: ++ return "MAX9271"; ++ case MAX96705_ID: ++ return "MAX96705"; ++ case MAX96707_ID: ++ return "MAX96707"; ++ default: ++ return "unknown"; ++ } ++} ++ ++static void max9288_preinit(struct i2c_client *client, int addr) ++{ ++ ++ struct max9288_priv *priv = i2c_get_clientdata(client); ++ ++ client->addr = addr; /* MAX9288-CAMx I2C */ ++ reg8_write(client, 0x04, 0x00); /* disable reverse control */ ++ reg8_write(client, 0x16, (priv->him ? 0x80 : 0x00) | ++ 0x5a); /* high-immunity/legacy mode */ ++} ++ ++static void max9288_sensor_reset(struct i2c_client *client, int addr, int reset_on) ++{ ++ struct max9288_priv *priv = i2c_get_clientdata(client); ++ ++ if (priv->gpio_resetb < 1 || priv->gpio_resetb > 5) ++ return; ++ ++ /* sensor reset/unreset */ ++ client->addr = addr; /* MAX9271-CAMx I2C */ ++ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | /* set GPIOn value to reset/unreset */ ++ ((priv->active_low_resetb ? BIT(priv->gpio_resetb) : 0) ^ reset_on)); ++ reg8_write(client, 0x0e, 0x42 | BIT(priv->gpio_resetb)); /* set GPIOn direction output */ ++} ++ ++static int max9288_reverse_channel_setup(struct i2c_client *client) ++{ ++ struct max9288_priv *priv = i2c_get_clientdata(client); ++ u8 val = 0, lock_sts = 0; ++ int timeout = priv->timeout; ++ char timeout_str[40]; ++ int ret = 0; ++ ++ /* Reverse channel enable */ ++ client->addr = priv->des_addr; /* MAX9288-CAMx I2C */ ++ reg8_write(client, 0x1c, 0xa2 | MAXIM_I2C_I2C_SPEED); /* enable artificial ACKs, I2C speed set */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ reg8_write(client, 0x04, 0x03); /* enable reverse control */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ ++ for (;;) { ++ if (priv->him) { ++ /* HIM mode setup */ ++ client->addr = 0x40; /* MAX9271-CAMx I2C */ ++ reg8_write(client, 0x4d, 0xc0); ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ reg8_write(client, 0x04, 0x43); /* wake-up, enable reverse_control/conf_link */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ if (priv->bws) { ++ reg8_write(client, 0x07, (priv->pclk_rising_edge ? 0 : 0x10) | ++ (priv->dbl ? 0x80 : 0) | ++ (priv->bws ? 0x20 : 0)); /* RAW/YUV, PCLK edge, HS/VS disabled enabled, DBL mode, BWS 24/32-bit */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ } ++ } else { ++ /* Legacy mode setup */ ++ client->addr = priv->des_addr; /* MAX9288-CAMx I2C */ ++ reg8_write(client, 0x13, 0x00); ++ reg8_write(client, 0x11, 0x42); /* enable custom reverse channel & first pulse length */ ++ reg8_write(client, 0x0a, 0x0f); /* first pulse length rise time changed from 300ns to 200ns, amplitude 100mV */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ ++ client->addr = 0x40; /* MAX9271-CAMx I2C */ ++ reg8_write(client, 0x04, 0x43); /* wake-up, enable reverse_control/conf_link */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ reg8_write(client, 0x08, 0x01); /* reverse channel receiver high threshold enable */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ if (priv->bws) { ++ reg8_write(client, 0x07, (priv->pclk_rising_edge ? 0 : 0x10) | ++ (priv->dbl ? 0x80 : 0) | ++ (priv->bws ? 0x20 : 0)); /* RAW/YUV, PCLK edge, HS/VS encoding disabled, DBL mode, BWS 24/32-bit */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ } ++ reg8_write(client, 0x97, 0x5f); /* enable reverse control channel programming (MAX96705-MAX96711 only) */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ ++ client->addr = priv->des_addr; /* MAX9288-CAMx I2C */ ++ reg8_write(client, 0x0a, 0x0c); /* first pulse length rise time changed from 300ns to 200ns, amplitude 100mV */ ++ reg8_write(client, 0x13, 0x20); /* reverse channel increase amplitude 170mV to compensate high threshold enabled */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ } ++ ++ client->addr = 0x40; /* MAX9271-CAMx I2C */ ++ reg8_read(client, 0x1e, &val); /* read max9271 ID */ ++ if (val == MAX9271_ID || val == MAX96705_ID || val == MAX96707_ID || --timeout == 0) { ++ priv->ser_id = val; ++ break; ++ } ++ ++ /* Check if already initialized (after reboot/reset ?) */ ++ client->addr = priv->max9271_addr; /* MAX9271-CAMx I2C */ ++ reg8_read(client, 0x1e, &val); /* read max9271 ID */ ++ if (val == MAX9271_ID || val == MAX96705_ID || val == MAX96707_ID) { ++ priv->ser_id = val; ++ reg8_write(client, 0x04, 0x43); /* enable reverse_control/conf_link */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ ret = -EADDRINUSE; ++ break; ++ } ++ ++ if (poc_trig) { ++ if (!IS_ERR(priv->poc_gpio) && (timeout % poc_trig == 0)) { ++ gpiod_direction_output(priv->poc_gpio, 0); /* POC power off */ ++ mdelay(200); ++ gpiod_direction_output(priv->poc_gpio, 1); /* POC power on */ ++ mdelay(priv->poc_delay); ++ } ++ } ++ } ++ ++ max9288_sensor_reset(client, client->addr, 1); /* sensor reset */ ++ ++ client->addr = priv->des_addr; /* MAX9288-CAMx I2C */ ++ reg8_read(client, 0x04, &lock_sts); /* LOCK status */ ++ ++ if (!timeout) { ++ ret = -ETIMEDOUT; ++ goto out; ++ } ++ ++out: ++ sprintf(timeout_str, "retries=%d lock_sts=%d", priv->timeout - timeout, !!(lock_sts & 0x80)); ++ dev_info(&client->dev, "link %s %sat 0x%x %s %s\n", ser_name(priv->ser_id), ++ ret == -EADDRINUSE ? "already " : "", priv->max9271_addr, ++ ret == -ETIMEDOUT ? "not found: timeout GMSL link establish" : "", ++ priv->timeout - timeout ? timeout_str : ""); ++ ++ return ret; ++} ++ ++static void max9288_initial_setup(struct i2c_client *client) ++{ ++ struct max9288_priv *priv = i2c_get_clientdata(client); ++ ++ /* Initial setup */ ++ client->addr = priv->des_addr; /* MAX9288-CAMx I2C */ ++ reg8_write(client, 0x09, 0x40); /* Automatic pixel count enable */ ++ reg8_write(client, 0x15, 0x70); /* Enable HV and DE tracking by register 0x69 */ ++ reg8_write(client, 0x60, (priv->dbl ? 0x20 : 0) | ++ (priv->dt & 0xf)); /* VC=0, DBL mode, DataType */ ++ reg8_write(client, 0x65, 0x47 | ((priv->lanes - 1) << 4)); /* setup CSI lanes, DE input is HS */ ++ ++ reg8_write(client, 0x08, 0x20); /* use D18/19 for HS/VS */ ++ reg8_write(client, 0x14, (priv->vsync ? 0x80 : 0) | (priv->hsync ? 0x40 : 0)); /* setup HS/VS inversion */ ++ reg8_write(client, 0x64, 0x0c); /* Drive HSTRAIL state for 120ns after the last payload bit */ ++} ++ ++static void max9288_gmsl_link_setup(struct i2c_client *client) ++{ ++ struct max9288_priv *priv = i2c_get_clientdata(client); ++ ++ /* GMSL setup */ ++ client->addr = 0x40; /* MAX9271-CAMx I2C */ ++ reg8_write(client, 0x0d, 0x22 | MAXIM_I2C_I2C_SPEED); /* disable artificial ACK, I2C speed set */ ++ reg8_write(client, 0x07, (priv->pclk_rising_edge ? 0 : 0x10) | ++ (priv->dbl ? 0x80 : 0) | ++ (priv->bws ? 0x20 : 0)); /* RAW/YUV, PCLK edge, HS/VS encoding disabled, DBL mode, BWS 24/32-bit */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x02, 0xff); /* spread spectrum +-4%, pclk range automatic, Gbps automatic */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ ++ if (priv->ser_id == MAX96705_ID || priv->ser_id == MAX96707_ID) { ++ switch (priv->dt) { ++ case YUV8_DT: ++ /* setup crossbar for YUV8/RAW8: reverse DVP bus */ ++ reg8_write(client, 0x20, 3); ++ reg8_write(client, 0x21, 4); ++ reg8_write(client, 0x22, 5); ++ reg8_write(client, 0x23, 6); ++ reg8_write(client, 0x24, 7); ++ reg8_write(client, 0x25, 0x40); ++ reg8_write(client, 0x26, 0x40); ++ if (priv->ser_id == MAX96705_ID) { ++ reg8_write(client, 0x27, 14); /* HS: D14->D18 */ ++ reg8_write(client, 0x28, 15); /* VS: D15->D19 */ ++ } ++ if (priv->ser_id == MAX96707_ID) { ++ reg8_write(client, 0x27, 14); /* HS: D14->D18, this is a virtual NC pin, hence it is D14 at HS */ ++ reg8_write(client, 0x28, 13); /* VS: D13->D19 */ ++ } ++ reg8_write(client, 0x29, 0x40); ++ reg8_write(client, 0x2A, 0x40); ++ ++ /* this is second byte if DBL=1 */ ++ reg8_write(client, 0x30, 0x10 + 0); ++ reg8_write(client, 0x31, 0x10 + 1); ++ reg8_write(client, 0x32, 0x10 + 2); ++ reg8_write(client, 0x33, 0x10 + 3); ++ reg8_write(client, 0x34, 0x10 + 4); ++ reg8_write(client, 0x35, 0x10 + 5); ++ reg8_write(client, 0x36, 0x10 + 6); ++ reg8_write(client, 0x37, 0x10 + 7); ++ reg8_write(client, 0x38, 0); ++ reg8_write(client, 0x39, 1); ++ reg8_write(client, 0x3A, 2); ++ ++ reg8_write(client, 0x67, 0xC4); /* DBL_ALIGN_TO = 100b */ ++ ++ break; ++ case RAW12_DT: ++#if 0 /* Not supported yet */ ++ /* setup crossbar for RAW12: reverse DVP bus */ ++ reg8_write(client, 0x20, 11); ++ reg8_write(client, 0x21, 10); ++ reg8_write(client, 0x22, 9); ++ reg8_write(client, 0x23, 8); ++ reg8_write(client, 0x24, 7); ++ reg8_write(client, 0x25, 6); ++ reg8_write(client, 0x26, 5); ++ reg8_write(client, 0x27, 4); ++ reg8_write(client, 0x28, 3); ++ reg8_write(client, 0x29, 2); ++ reg8_write(client, 0x2a, 1); ++ reg8_write(client, 0x2b, 0); ++ ++ /* this is second byte if DBL=1 */ ++ reg8_write(client, 0x30, 27); ++ reg8_write(client, 0x31, 26); ++ reg8_write(client, 0x32, 25); ++ reg8_write(client, 0x33, 24); ++ reg8_write(client, 0x34, 23); ++ reg8_write(client, 0x35, 22); ++ reg8_write(client, 0x36, 21); ++ reg8_write(client, 0x37, 20); ++ reg8_write(client, 0x38, 19); ++ reg8_write(client, 0x39, 18); ++ reg8_write(client, 0x3a, 17); ++ reg8_write(client, 0x3b, 16); ++ ++ if (!priv->bws && priv->dbl) ++ dev_err(&client->dev, " BWS must be 27/32-bit for RAW12 in DBL mode\n"); ++#endif ++ break; ++ } ++ ++ if (priv->hsgen) { ++ /* HS/VS pins map */ ++ reg8_write(client, 0x3f, 0x10); /* HS (NC) */ ++ reg8_write(client, 0x41, 0x10); /* DE (NC) */ ++ if (priv->ser_id == MAX96705_ID) ++ reg8_write(client, 0x40, 15); /* VS (DIN13) */ ++ if (priv->ser_id == MAX96707_ID) ++ reg8_write(client, 0x40, 13); /* VS (DIN13) */ ++#if 0 ++ /* following must come from imager */ ++#define SENSOR_WIDTH (1280*2) ++#define HTS (1288*2) ++#define VTS 960 ++#define HTS_DELAY 0x9 ++ reg8_write(client, 0x4e, HTS_DELAY >> 16); /* HS delay */ ++ reg8_write(client, 0x4f, (HTS_DELAY >> 8) & 0xff); ++ reg8_write(client, 0x50, HTS_DELAY & 0xff); ++ reg8_write(client, 0x54, SENSOR_WIDTH >> 8); /* HS high period */ ++ reg8_write(client, 0x55, SENSOR_WIDTH & 0xff); ++ reg8_write(client, 0x56, (HTS - SENSOR_WIDTH) >> 8); /* HS low period */ ++ reg8_write(client, 0x57, (HTS - SENSOR_WIDTH) & 0xff); ++ reg8_write(client, 0x58, VTS >> 8); /* HS count */ ++ reg8_write(client, 0x59, VTS & 0xff ); ++#endif ++ reg8_write(client, 0x43, 0x15); /* enable HS generator */ ++ } ++ } ++ ++ client->addr = priv->des_addr; /* MAX9288-CAMx I2C */ ++ reg8_write(client, 0x1c, 0x22 | MAXIM_I2C_I2C_SPEED); /* disable artificial ACK, I2C speed set */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ ++ /* I2C translator setup */ ++ client->addr = 0x40; /* MAX9271-CAMx I2C */ ++// reg8_write(client, 0x09, maxim_map[2][idx] << 1); /* SENSOR I2C translated - must be set by sensor driver */ ++// reg8_write(client, 0x0A, 0x30 << 1); /* SENSOR I2C native - must be set by sensor driver */ ++ reg8_write(client, 0x0B, BROADCAST << 1); /* broadcast I2C */ ++ reg8_write(client, 0x0C, priv->max9271_addr << 1); /* MAX9271-CAMx I2C new */ ++ /* I2C addresse change */ ++ reg8_write(client, 0x01, priv->des_addr << 1); /* MAX9288 I2C */ ++ reg8_write(client, 0x00, priv->max9271_addr << 1); /* MAX9271-CAM0 I2C new */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ /* put MAX9271 in configuration link state */ ++ client->addr = priv->max9271_addr; /* MAX9271-CAMx I2C new */ ++ reg8_write(client, 0x04, 0x43); /* enable reverse_control/conf_link */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++#ifdef MAXIM_DUMP ++ client->addr = priv->des_addr; /* MAX9288-CAMx I2C */ ++ maxim_max927x_dump_regs(client); ++ client->addr = priv->max9271_addr; /* MAX9271-CAMx I2C new */ ++ maxim_max927x_dump_regs(client); ++#endif ++} ++ ++static int max9288_initialize(struct i2c_client *client) ++{ ++ struct max9288_priv *priv = i2c_get_clientdata(client); ++ ++ dev_info(&client->dev, "LANES=%d, PCLK edge=%s\n", ++ priv->lanes, priv->pclk_rising_edge ? "rising" : "falling"); ++ ++ max9288_preinit(client, priv->des_addr); ++ max9288_initial_setup(client); ++ ++ if (!IS_ERR(priv->poc_gpio)) { ++ gpiod_direction_output(priv->poc_gpio, 1); /* POC power on */ ++ mdelay(priv->poc_delay); ++ } ++ ++ max9288_reverse_channel_setup(client); ++ max9288_gmsl_link_setup(client); ++ ++ client->addr = priv->des_addr; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int max9288_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct max9288_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ int ret; ++ u8 val = 0; ++ ++ ret = reg8_read(client, (u8)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u8); ++ ++ return 0; ++} ++ ++static int max9288_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct max9288_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ ++ return reg8_write(client, (u8)reg->reg, (u8)reg->val); ++} ++#endif ++ ++static int max9288_s_power(struct v4l2_subdev *sd, int on) ++{ ++ struct max9288_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ ++ client->addr = priv->max9271_addr; /* MAX9271-CAMx I2C new */ ++ reg8_write(client, 0x04, on ? (conf_link ? 0x43 : 0x83) : 0x43); /* enable serial_link or conf_link */ ++ usleep_range(2000, 2500); /* wait 2ms after changing reverse_control */ ++ client->addr = priv->des_addr; /* MAX9288-CAMx I2C */ ++ ++ return 0; ++} ++ ++static struct v4l2_subdev_core_ops max9288_subdev_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = max9288_g_register, ++ .s_register = max9288_s_register, ++#endif ++ .s_power = max9288_s_power, ++}; ++ ++static struct v4l2_subdev_ops max9288_subdev_ops = { ++ .core = &max9288_subdev_core_ops, ++}; ++ ++static int max9288_parse_dt(struct i2c_client *client) ++{ ++ struct max9288_priv *priv = i2c_get_clientdata(client); ++ struct device_node *np = client->dev.of_node; ++ struct device_node *endpoint = NULL; ++ struct property *prop; ++ int err, pwen; ++ int sensor_delay, gpio0 = 1, gpio1 = 1; ++ u8 val = 0; ++ char poc_name[10]; ++ ++ if (of_property_read_u32(np, "maxim,lanes", &priv->lanes)) ++ priv->lanes = 4; ++ ++ pwen = of_get_gpio(np, 0); ++ if (pwen > 0) { ++ err = gpio_request_one(pwen, GPIOF_OUT_INIT_HIGH, dev_name(&client->dev)); ++ if (err) ++ dev_err(&client->dev, "cannot request PWEN gpio %d: %d\n", pwen, err); ++ } ++ ++ mdelay(250); ++ ++ sprintf(poc_name, "POC%d", 0); ++ priv->poc_gpio = devm_gpiod_get_optional(&client->dev, kstrdup(poc_name, GFP_KERNEL), 0); ++ ++ reg8_read(client, 0x1e, &val); /* read max9288 ID */ ++ if (val != MAX9288_ID) { ++ prop = of_find_property(np, "reg", NULL); ++ if (prop) ++ of_remove_property(np, prop); ++ return -ENODEV; ++ } ++ ++ if (!of_property_read_u32(np, "maxim,gpio0", &gpio0) || ++ !of_property_read_u32(np, "maxim,gpio1", &gpio1)) ++ reg8_write(client, 0x06, (gpio1 << 3) | (gpio0 << 1)); ++ ++ if (of_property_read_u32(np, "maxim,resetb-gpio", &priv->gpio_resetb)) { ++ priv->gpio_resetb = -1; ++ } else { ++ if (of_property_read_bool(np, "maxim,resetb-active-high")) ++ priv->active_low_resetb = 0; ++ else ++ priv->active_low_resetb = 1; ++ } ++ ++ if (!of_property_read_u32(np, "maxim,sensor_delay", &sensor_delay)) ++ mdelay(sensor_delay); ++ priv->pclk_rising_edge = true; ++ if (of_property_read_bool(np, "maxim,pclk-falling-edge")) ++ priv->pclk_rising_edge = false; ++ if (of_property_read_u32(np, "maxim,timeout", &priv->timeout)) ++ priv->timeout = 100; ++ if (of_property_read_u32(np, "maxim,him", &priv->him)) ++ priv->him = 0; ++ if (of_property_read_u32(np, "maxim,hsync", &priv->hsync)) ++ priv->hsync = 0; ++ if (of_property_read_u32(np, "maxim,vsync", &priv->vsync)) ++ priv->vsync = 1; ++ if (of_property_read_u32(np, "maxim,poc-delay", &priv->poc_delay)) ++ priv->poc_delay = 50; ++ if (of_property_read_u32(np, "maxim,bws", &priv->bws)) ++ priv->bws = 0; ++ if (of_property_read_u32(np, "maxim,dbl", &priv->dbl)) ++ priv->dbl = 1; ++ if (of_property_read_u32(np, "maxim,dt", &priv->dt)) ++ priv->dt = 3; ++ if (of_property_read_u32(np, "maxim,hsgen", &priv->hsgen)) ++ priv->hsgen = 0; ++ if (of_property_read_u32(np, "maxim,pclk", &priv->pclk)) ++ priv->pclk = pclk; ++ ++ /* module params override dts */ ++ if (him) ++ priv->him = him; ++ if (hsync) ++ priv->hsync = hsync; ++ if (!vsync) ++ priv->vsync = vsync; ++ if (gpio_resetb) ++ priv->gpio_resetb = gpio_resetb; ++ if (active_low_resetb) ++ priv->active_low_resetb = active_low_resetb; ++ if (timeout_n) ++ priv->timeout = timeout_n; ++ if (poc_delay) ++ priv->poc_delay = poc_delay; ++ if (bws) ++ priv->bws = bws; ++ if (!dbl) ++ priv->dbl = dbl; ++ if (dt != 3) ++ priv->dt = dt; ++ if (hsgen) ++ priv->hsgen = hsgen; ++ if (pclk != 100) ++ priv->pclk = pclk; ++ ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (endpoint) { ++ if (of_property_read_u32(endpoint, "max9271-addr", &priv->max9271_addr)) { ++ of_node_put(endpoint); ++ dev_err(&client->dev, "max9271-addr not set\n"); ++ return -EINVAL; ++ } ++ ++ priv->sd_fwnode = of_fwnode_handle(endpoint); ++ } ++ ++ of_node_put(endpoint); ++ return 0; ++} ++ ++static void max9288_setup_remote_endpoint(struct i2c_client *client) ++{ ++ struct max9288_priv *priv = i2c_get_clientdata(client); ++ struct device_node *np = client->dev.of_node; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int i; ++ struct property *csi_rate_prop, *dvp_order_prop; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ csi_rate_prop = of_find_property(endpoint, "csi-rate", NULL); ++ if (csi_rate_prop) { ++ /* CSI2_RATE = PCLK*bpp/lanes */ ++ priv->csi_rate = cpu_to_be32(priv->pclk * dt2bpp[priv->dt] / priv->lanes); ++ csi_rate_prop->value = &priv->csi_rate; ++ of_update_property(rendpoint, csi_rate_prop); ++ } ++ ++ dvp_order_prop = of_find_property(endpoint, "dvp-order", NULL); ++ if (dvp_order_prop) ++ of_update_property(rendpoint, dvp_order_prop); ++ } ++ ++ of_node_put(endpoint); ++} ++ ++static int max9288_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct max9288_priv *priv; ++ int err; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ i2c_set_clientdata(client, priv); ++ priv->des_addr = client->addr; ++ priv->client = client; ++ ++ err = max9288_parse_dt(client); ++ if (err) ++ goto out; ++ ++ err = max9288_initialize(client); ++ if (err < 0) ++ goto out; ++ ++ max9288_setup_remote_endpoint(client); ++ ++ v4l2_subdev_init(&priv->sd, &max9288_subdev_ops); ++ priv->sd.owner = client->dev.driver->owner; ++ priv->sd.dev = &client->dev; ++ v4l2_set_subdevdata(&priv->sd, priv); ++ priv->sd.fwnode = priv->sd_fwnode; ++ ++ snprintf(priv->sd.name, V4L2_SUBDEV_NAME_SIZE, "%s %d-%04x", ++ client->dev.driver->name, i2c_adapter_id(client->adapter), ++ client->addr); ++ ++ err = v4l2_async_register_subdev(&priv->sd); ++ if (err < 0) ++ goto out; ++out: ++ return err; ++} ++ ++static int max9288_remove(struct i2c_client *client) ++{ ++ struct max9288_priv *priv = i2c_get_clientdata(client); ++ ++ v4l2_async_unregister_subdev(&priv->sd); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++static const struct of_device_id max9288_dt_ids[] = { ++ { .compatible = "maxim,max9288" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, max9288_dt_ids); ++ ++static const struct i2c_device_id max9288_id[] = { ++ { "max9288", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, max9288_id); ++ ++static struct i2c_driver max9288_i2c_driver = { ++ .driver = { ++ .name = "max9288", ++ .of_match_table = of_match_ptr(max9288_dt_ids), ++ }, ++ .probe = max9288_probe, ++ .remove = max9288_remove, ++ .id_table = max9288_id, ++}; ++ ++module_i2c_driver(max9288_i2c_driver); ++ ++MODULE_DESCRIPTION("GMSL driver for MAX9288"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c +index 9051590..501598c 100644 +--- a/drivers/media/platform/soc_camera/rcar_vin.c ++++ b/drivers/media/platform/soc_camera/rcar_vin.c +@@ -1587,6 +1587,7 @@ static struct v4l2_subdev *find_deser(struct rcar_vin_priv *pcdev) + struct v4l2_subdev *sd; + char name[] = "max9286"; + char name2[] = "ti9x4"; ++ char name3[] = "max9288"; + + v4l2_device_for_each_subdev(sd, &pcdev->ici.v4l2_dev) { + if (!strncmp(name, sd->name, sizeof(name) - 1)) { +@@ -1597,6 +1598,10 @@ static struct v4l2_subdev *find_deser(struct rcar_vin_priv *pcdev) + pcdev->deser_sd = sd; + return sd; + } ++ if (!strncmp(name3, sd->name, sizeof(name3) - 1)) { ++ pcdev->deser_sd = sd; ++ return sd; ++ } + } + + return NULL; +@@ -3064,10 +3069,11 @@ static int rcar_vin_probe(struct platform_device *pdev) + const char *str; + unsigned int i; + struct device_node *epn = NULL, *ren = NULL; +- struct device_node *csi2_ren = NULL, *max9286_ren = NULL, *ti9x4_ren = NULL; ++ struct device_node *csi2_ren = NULL, *max9286_ren = NULL, *ti9x4_ren = NULL, *max9288_ren = NULL; + bool csi_use = false; + bool max9286_use = false; + bool ti9x4_use = false; ++ bool max9288_use = false; + + match = of_match_device(of_match_ptr(rcar_vin_of_table), &pdev->dev); + +@@ -3109,6 +3115,11 @@ static int rcar_vin_probe(struct platform_device *pdev) + ti9x4_use = true; + } + ++ if (strcmp(ren->parent->name, "max9288") == 0) { ++ max9288_ren = of_parse_phandle(epn, "remote-endpoint", 0); ++ max9288_use = true; ++ } ++ + of_node_put(ren); + } + +@@ -3385,6 +3396,12 @@ static int rcar_vin_probe(struct platform_device *pdev) + goto cleanup; + } + ++ if (max9288_use) { ++ ret = rcar_vin_soc_of_bind(priv, &priv->ici, epn, max9288_ren); ++ if (ret) ++ goto cleanup; ++ } ++ + vin_debug = 0; + + return 0; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0412-media-i2c-soc_camera-differenciate-max9286-and-max92.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0412-media-i2c-soc_camera-differenciate-max9286-and-max92.patch new file mode 100644 index 00000000..68e569e2 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0412-media-i2c-soc_camera-differenciate-max9286-and-max92.patch @@ -0,0 +1,351 @@ +From 3fea12b6dfa46dc30dc2cdbd1f27dc3f5a07d003 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Wed, 14 Aug 2019 15:06:18 +0300 +Subject: [PATCH 2/3] media: i2c: soc_camera: differenciate max9286 and max9288 + +The max9288 needs to be differenciated from max9286, because +it does not have the link control block + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/ap0101_ar014x.c | 8 ++++++-- + drivers/media/i2c/soc_camera/ar0132.c | 8 ++++++-- + drivers/media/i2c/soc_camera/ar0140.c | 8 ++++++-- + drivers/media/i2c/soc_camera/ar0143.c | 8 ++++++-- + drivers/media/i2c/soc_camera/ar0147.c | 8 ++++++-- + drivers/media/i2c/soc_camera/ar0231.c | 8 ++++++-- + drivers/media/i2c/soc_camera/gw4200_ar014x.c | 8 ++++++-- + drivers/media/i2c/soc_camera/gw5200_imx390.c | 8 ++++++-- + drivers/media/i2c/soc_camera/isx016.c | 8 ++++++-- + drivers/media/i2c/soc_camera/isx019.c | 8 ++++++-- + drivers/media/i2c/soc_camera/ov10635.c | 8 ++++++-- + drivers/media/i2c/soc_camera/ov10640.c | 8 ++++++-- + drivers/media/i2c/soc_camera/ov2311.c | 8 ++++++-- + drivers/media/i2c/soc_camera/ov490_ov10640.c | 8 ++++++-- + 14 files changed, 84 insertions(+), 28 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ap0101_ar014x.c b/drivers/media/i2c/soc_camera/ap0101_ar014x.c +index 74e6e51..c35e5a0 100644 +--- a/drivers/media/i2c/soc_camera/ap0101_ar014x.c ++++ b/drivers/media/i2c/soc_camera/ap0101_ar014x.c +@@ -65,12 +65,16 @@ static void ap0101_s_port(struct i2c_client *client, int fwd_en) + { + struct ap0101_priv *priv = to_ap0101(client); + int tmp_addr; ++ u8 val = 0; + + if (priv->max9286_addr) { + tmp_addr = client->addr; + client->addr = priv->max9286_addr; /* Deserializer I2C address */ +- reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ +- usleep_range(5000, 5500); /* wait 5ms */ ++ reg8_read(client, 0x1e, &val); /* read max928X ID */ ++ if (val == MAX9286_ID) { ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ } + client->addr = tmp_addr; + }; + } +diff --git a/drivers/media/i2c/soc_camera/ar0132.c b/drivers/media/i2c/soc_camera/ar0132.c +index 18bc5dc..e4926e8 100644 +--- a/drivers/media/i2c/soc_camera/ar0132.c ++++ b/drivers/media/i2c/soc_camera/ar0132.c +@@ -61,12 +61,16 @@ static void ar0132_s_port(struct i2c_client *client, int fwd_en) + { + struct ar0132_priv *priv = to_ar0132(client); + int tmp_addr; ++ u8 val = 0; + + if (priv->max9286_addr) { + tmp_addr = client->addr; + client->addr = priv->max9286_addr; /* Deserializer I2C address */ +- reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ +- usleep_range(5000, 5500); /* wait 5ms */ ++ reg8_read(client, 0x1e, &val); /* read max928X ID */ ++ if (val == MAX9286_ID) { ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ } + client->addr = tmp_addr; + }; + } +diff --git a/drivers/media/i2c/soc_camera/ar0140.c b/drivers/media/i2c/soc_camera/ar0140.c +index c52ca4e..b156fc5 100644 +--- a/drivers/media/i2c/soc_camera/ar0140.c ++++ b/drivers/media/i2c/soc_camera/ar0140.c +@@ -58,12 +58,16 @@ static void ar0140_s_port(struct i2c_client *client, int fwd_en) + { + struct ar0140_priv *priv = to_ar0140(client); + int tmp_addr; ++ u8 val = 0; + + if (priv->max9286_addr) { + tmp_addr = client->addr; + client->addr = priv->max9286_addr; /* Deserializer I2C address */ +- reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ +- usleep_range(5000, 5500); /* wait 5ms */ ++ reg8_read(client, 0x1e, &val); /* read max928X ID */ ++ if (val == MAX9286_ID) { ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0);/* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ } + client->addr = tmp_addr; + }; + } +diff --git a/drivers/media/i2c/soc_camera/ar0143.c b/drivers/media/i2c/soc_camera/ar0143.c +index b61c7eb..0c4b970 100644 +--- a/drivers/media/i2c/soc_camera/ar0143.c ++++ b/drivers/media/i2c/soc_camera/ar0143.c +@@ -64,12 +64,16 @@ static void ar0143_s_port(struct i2c_client *client, int fwd_en) + { + struct ar0143_priv *priv = to_ar0143(client); + int tmp_addr; ++ u8 val = 0; + + if (priv->max9286_addr) { + tmp_addr = client->addr; + client->addr = priv->max9286_addr; /* Deserializer I2C address */ +- reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ +- usleep_range(5000, 5500); /* wait 5ms */ ++ reg8_read(client, 0x1e, &val); /* read max928X ID */ ++ if (val == MAX9286_ID) { ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ } + client->addr = tmp_addr; + }; + } +diff --git a/drivers/media/i2c/soc_camera/ar0147.c b/drivers/media/i2c/soc_camera/ar0147.c +index 08fd136..fc2a09e 100644 +--- a/drivers/media/i2c/soc_camera/ar0147.c ++++ b/drivers/media/i2c/soc_camera/ar0147.c +@@ -81,12 +81,16 @@ static void ar0147_s_port(struct i2c_client *client, int fwd_en) + { + struct ar0147_priv *priv = to_ar0147(client); + int tmp_addr; ++ u8 val = 0; + + if (priv->max9286_addr) { + tmp_addr = client->addr; + client->addr = priv->max9286_addr; /* Deserializer I2C address */ +- reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ +- usleep_range(5000, 5500); /* wait 5ms */ ++ reg8_read(client, 0x1e, &val); /* read max928X ID */ ++ if (val == MAX9286_ID) { ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ } + client->addr = tmp_addr; + }; + } +diff --git a/drivers/media/i2c/soc_camera/ar0231.c b/drivers/media/i2c/soc_camera/ar0231.c +index 36b5657..c51ae9ad 100644 +--- a/drivers/media/i2c/soc_camera/ar0231.c ++++ b/drivers/media/i2c/soc_camera/ar0231.c +@@ -61,12 +61,16 @@ static void ar0231_s_port(struct i2c_client *client, int fwd_en) + { + struct ar0231_priv *priv = to_ar0231(client); + int tmp_addr; ++ u8 val = 0; + + if (priv->max9286_addr) { + tmp_addr = client->addr; + client->addr = priv->max9286_addr; /* Deserializer I2C address */ +- reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ +- usleep_range(5000, 5500); /* wait 5ms */ ++ reg8_read(client, 0x1e, &val); /* read max928X ID */ ++ if (val == MAX9286_ID) { ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ } + client->addr = tmp_addr; + }; + } +diff --git a/drivers/media/i2c/soc_camera/gw4200_ar014x.c b/drivers/media/i2c/soc_camera/gw4200_ar014x.c +index 45123ae..71c34f9 100644 +--- a/drivers/media/i2c/soc_camera/gw4200_ar014x.c ++++ b/drivers/media/i2c/soc_camera/gw4200_ar014x.c +@@ -58,12 +58,16 @@ static void gw4200_s_port(struct i2c_client *client, int fwd_en) + { + struct gw4200_priv *priv = to_gw4200(client); + int tmp_addr; ++ u8 val = 0; + + if (priv->max9286_addr) { + tmp_addr = client->addr; + client->addr = priv->max9286_addr; /* Deserializer I2C address */ +- reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ +- usleep_range(5000, 5500); /* wait 5ms */ ++ reg8_read(client, 0x1e, &val); /* read max928X ID */ ++ if (val == MAX9286_ID) { ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ } + client->addr = tmp_addr; + }; + } +diff --git a/drivers/media/i2c/soc_camera/gw5200_imx390.c b/drivers/media/i2c/soc_camera/gw5200_imx390.c +index 98352a9..e750a85 100644 +--- a/drivers/media/i2c/soc_camera/gw5200_imx390.c ++++ b/drivers/media/i2c/soc_camera/gw5200_imx390.c +@@ -65,12 +65,16 @@ static void gw5200_s_port(struct i2c_client *client, int fwd_en) + { + struct gw5200_priv *priv = to_gw5200(client); + int tmp_addr; ++ u8 val = 0; + + if (priv->max9286_addr) { + tmp_addr = client->addr; + client->addr = priv->max9286_addr; /* Deserializer I2C address */ +- reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ +- usleep_range(5000, 5500); /* wait 5ms */ ++ reg8_read(client, 0x1e, &val); /* read max928X ID */ ++ if (val == MAX9286_ID) { ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ } + client->addr = tmp_addr; + }; + } +diff --git a/drivers/media/i2c/soc_camera/isx016.c b/drivers/media/i2c/soc_camera/isx016.c +index ab85b7d..9465c8f 100644 +--- a/drivers/media/i2c/soc_camera/isx016.c ++++ b/drivers/media/i2c/soc_camera/isx016.c +@@ -62,12 +62,16 @@ static void isx016_s_port(struct i2c_client *client, int fwd_en) + { + struct isx016_priv *priv = to_isx016(client); + int tmp_addr; ++ u8 val = 0; + + if (priv->max9286_addr) { + tmp_addr = client->addr; + client->addr = priv->max9286_addr; /* Deserializer I2C address */ +- reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ +- usleep_range(5000, 5500); /* wait 5ms */ ++ reg8_read(client, 0x1e, &val); /* read max928X ID */ ++ if (val == MAX9286_ID) { ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ } + client->addr = tmp_addr; + }; + } +diff --git a/drivers/media/i2c/soc_camera/isx019.c b/drivers/media/i2c/soc_camera/isx019.c +index 188fd28..d75d8f3 100644 +--- a/drivers/media/i2c/soc_camera/isx019.c ++++ b/drivers/media/i2c/soc_camera/isx019.c +@@ -64,12 +64,16 @@ static void isx019_s_port(struct i2c_client *client, int fwd_en) + { + struct isx019_priv *priv = to_isx019(client); + int tmp_addr; ++ u8 val = 0; + + if (priv->max9286_addr) { + tmp_addr = client->addr; + client->addr = priv->max9286_addr; /* Deserializer I2C address */ +- reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ +- usleep_range(5000, 5500); /* wait 5ms */ ++ reg8_read(client, 0x1e, &val); /* read max928X ID */ ++ if (val == MAX9286_ID) { ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ } + client->addr = tmp_addr; + }; + } +diff --git a/drivers/media/i2c/soc_camera/ov10635.c b/drivers/media/i2c/soc_camera/ov10635.c +index 1bbde91..14bb339 100644 +--- a/drivers/media/i2c/soc_camera/ov10635.c ++++ b/drivers/media/i2c/soc_camera/ov10635.c +@@ -69,12 +69,16 @@ static void ov10635_s_port(struct i2c_client *client, int fwd_en) + { + struct ov10635_priv *priv = to_ov10635(client); + int tmp_addr; ++ u8 val = 0; + + if (priv->max9286_addr) { + tmp_addr = client->addr; + client->addr = priv->max9286_addr; /* Deserializer I2C address */ +- reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ +- usleep_range(5000, 5500); /* wait 5ms */ ++ reg8_read(client, 0x1e, &val); /* read max928X ID */ ++ if (val == MAX9286_ID) { ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ } + client->addr = tmp_addr; + }; + } +diff --git a/drivers/media/i2c/soc_camera/ov10640.c b/drivers/media/i2c/soc_camera/ov10640.c +index 4ce6e15..89dac1b 100644 +--- a/drivers/media/i2c/soc_camera/ov10640.c ++++ b/drivers/media/i2c/soc_camera/ov10640.c +@@ -65,12 +65,16 @@ static void ov10640_s_port(struct i2c_client *client, int fwd_en) + { + struct ov10640_priv *priv = to_ov10640(client); + int tmp_addr; ++ u8 val = 0; + + if (priv->max9286_addr) { + tmp_addr = client->addr; + client->addr = priv->max9286_addr; /* Deserializer I2C address */ +- reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ +- usleep_range(5000, 5500); /* wait 5ms */ ++ reg8_read(client, 0x1e, &val); /* read max928X ID */ ++ if (val == MAX9286_ID) { ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ } + client->addr = tmp_addr; + }; + } +diff --git a/drivers/media/i2c/soc_camera/ov2311.c b/drivers/media/i2c/soc_camera/ov2311.c +index c8d260c..f04f271 100644 +--- a/drivers/media/i2c/soc_camera/ov2311.c ++++ b/drivers/media/i2c/soc_camera/ov2311.c +@@ -66,12 +66,16 @@ static void ov2311_s_port(struct i2c_client *client, int fwd_en) + { + struct ov2311_priv *priv = to_ov2311(client); + int tmp_addr; ++ u8 val = 0; + + if (priv->max9286_addr) { + tmp_addr = client->addr; + client->addr = priv->max9286_addr; /* Deserializer I2C address */ +- reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ +- usleep_range(5000, 5500); /* wait 5ms */ ++ reg8_read(client, 0x1e, &val); /* read max928X ID */ ++ if (val == MAX9286_ID) { ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ } + client->addr = tmp_addr; + }; + } +diff --git a/drivers/media/i2c/soc_camera/ov490_ov10640.c b/drivers/media/i2c/soc_camera/ov490_ov10640.c +index c492792..b85f871 100644 +--- a/drivers/media/i2c/soc_camera/ov490_ov10640.c ++++ b/drivers/media/i2c/soc_camera/ov490_ov10640.c +@@ -91,12 +91,16 @@ static void ov490_s_port(struct i2c_client *client, int fwd_en) + { + struct ov490_priv *priv = to_ov490(client); + int tmp_addr; ++ u8 val = 0; + + if (priv->max9286_addr) { + tmp_addr = client->addr; + client->addr = priv->max9286_addr; /* Deserializer I2C address */ +- reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ +- usleep_range(5000, 5500); /* wait 5ms */ ++ reg8_read(client, 0x1e, &val); /* read max928X ID */ ++ if (val == MAX9286_ID) { ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ } + client->addr = tmp_addr; + }; + } +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0413-media-i2c-max9288-fix-stream-on-off.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0413-media-i2c-max9288-fix-stream-on-off.patch new file mode 100644 index 00000000..f45837a2 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0413-media-i2c-max9288-fix-stream-on-off.patch @@ -0,0 +1,57 @@ +From 0bd5979e4ae470c914a941c97e178d71ecb8d7f9 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Thu, 15 Aug 2019 14:18:51 +0300 +Subject: [PATCH 3/3] media: i2c: max9288: fix stream on/off + +The remote i2c write can fail seldom. +Implement write_verify. + +Signed-off-by: Vladimir Barinov +--- + drivers/media/i2c/soc_camera/max9288.c | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/i2c/soc_camera/max9288.c b/drivers/media/i2c/soc_camera/max9288.c +index dd57074..4840795 100644 +--- a/drivers/media/i2c/soc_camera/max9288.c ++++ b/drivers/media/i2c/soc_camera/max9288.c +@@ -154,6 +154,27 @@ static char* ser_name(int id) + } + } + ++static void max9288_write_remote_verify(struct i2c_client *client, u8 reg, u8 val) ++{ ++ struct max9288_priv *priv = i2c_get_clientdata(client); ++ int timeout; ++ ++ for (timeout = 0; timeout < 10; timeout++) { ++ u8 val2 = 0; ++ ++ reg8_write(client, reg, val); ++ reg8_read(client, reg, &val2); ++ if (val2 == val) ++ break; ++ ++ usleep_range(1000, 1500); ++ } ++ ++ if (timeout >= 10) ++ dev_err(&client->dev, "timeout remote write acked\n"); ++} ++ ++ + static void max9288_preinit(struct i2c_client *client, int addr) + { + +@@ -501,7 +522,7 @@ static int max9288_s_power(struct v4l2_subdev *sd, int on) + struct i2c_client *client = priv->client; + + client->addr = priv->max9271_addr; /* MAX9271-CAMx I2C new */ +- reg8_write(client, 0x04, on ? (conf_link ? 0x43 : 0x83) : 0x43); /* enable serial_link or conf_link */ ++ max9288_write_remote_verify(client, 0x04, on ? (conf_link ? 0x43 : 0x83) : 0x43); /* enable serial_link or conf_link */ + usleep_range(2000, 2500); /* wait 2ms after changing reverse_control */ + client->addr = priv->des_addr; /* MAX9288-CAMx I2C */ + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0414-gpio-pca953x-do-not-ignore-i2c-errors.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0414-gpio-pca953x-do-not-ignore-i2c-errors.patch new file mode 100644 index 00000000..ca7a2493 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0414-gpio-pca953x-do-not-ignore-i2c-errors.patch @@ -0,0 +1,33 @@ +From cb6211b6dc99e19b5c45f9714478a085d180266c Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Tue, 27 Aug 2019 13:08:42 +0300 +Subject: [PATCH 1/6] gpio: pca953x: do not ignore i2c errors + +Signed-off-by: Andrey Gusakov +--- + drivers/gpio/gpio-pca953x.c | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c +index 587bb3e..9ad0720 100644 +--- a/drivers/gpio/gpio-pca953x.c ++++ b/drivers/gpio/gpio-pca953x.c +@@ -349,13 +349,8 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) + mutex_lock(&chip->i2c_lock); + ret = pca953x_read_single(chip, chip->regs->input, ®_val, off); + mutex_unlock(&chip->i2c_lock); +- if (ret < 0) { +- /* NOTE: diagnostic already emitted; that's all we should +- * do unless gpio_*_value_cansleep() calls become different +- * from their nonsleeping siblings (and report faults). +- */ +- return 0; +- } ++ if (ret < 0) ++ return ret; + + return (reg_val & (1u << (off % BANK_SZ))) ? 1 : 0; + } +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0415-usb-host-xhci-rcar-Add-XHCI_TRUST_TX_LENGTH-quirk.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0415-usb-host-xhci-rcar-Add-XHCI_TRUST_TX_LENGTH-quirk.patch new file mode 100644 index 00000000..889a3729 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0415-usb-host-xhci-rcar-Add-XHCI_TRUST_TX_LENGTH-quirk.patch @@ -0,0 +1,37 @@ +From 1e82360f4dd318a8ca4bd2e0d0b75a1780c158d7 Mon Sep 17 00:00:00 2001 +From: Yasushi Asano +Date: Mon, 18 Feb 2019 11:26:34 +0100 +Subject: [PATCH 2/6] usb: host: xhci-rcar: Add XHCI_TRUST_TX_LENGTH quirk + +When plugging BUFFALO LUA4-U3-AGT USB3.0 to Gigabit Ethernet LAN +Adapter, warning messages filled up dmesg. + +[ 101.098287] xhci-hcd ee000000.usb: WARN Successful completion on short TX for slot 1 ep 4: needs XHCI_TRUST_TX_LENGTH quirk? +[ 101.117463] xhci-hcd ee000000.usb: WARN Successful completion on short TX for slot 1 ep 4: needs XHCI_TRUST_TX_LENGTH quirk? +[ 101.136513] xhci-hcd ee000000.usb: WARN Successful completion on short TX for slot 1 ep 4: needs XHCI_TRUST_TX_LENGTH quirk? + +Adding the XHCI_TRUST_TX_LENGTH quirk resolves the issue. + +Signed-off-by: Yasushi Asano +Signed-off-by: Spyridon Papageorgiou +Acked-by: Yoshihiro Shimoda +Signed-off-by: Andrey Gusakov +--- + drivers/usb/host/xhci-rcar.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c +index b05c937..1f31f84 100644 +--- a/drivers/usb/host/xhci-rcar.c ++++ b/drivers/usb/host/xhci-rcar.c +@@ -264,6 +264,7 @@ int xhci_rcar_init_quirk(struct usb_hcd *hcd) + return -ETIMEDOUT; + + xhci->quirks |= XHCI_SLOW_SUSPEND; ++ xhci->quirks |= XHCI_TRUST_TX_LENGTH; + return xhci_rcar_download_firmware(hcd); + } + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0416-arm64-dtb-renesas-vb2.1-enable-usb2-channel-3.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0416-arm64-dtb-renesas-vb2.1-enable-usb2-channel-3.patch new file mode 100644 index 00000000..609f7f54 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0416-arm64-dtb-renesas-vb2.1-enable-usb2-channel-3.patch @@ -0,0 +1,55 @@ +From 2bda1ee68a17dcc3774073dd2b35d2525a079a7d Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Tue, 27 Aug 2019 17:26:13 +0300 +Subject: [PATCH 3/6] arm64: dtb: renesas: vb2.1: enable usb2 channel 3 + +Signed-off-by: Andrey Gusakov +--- + arch/arm64/boot/dts/renesas/ulcb-vb2.1.dtsi | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/ulcb-vb2.1.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vb2.1.dtsi +index 0df720d..f77b4c3 100644 +--- a/arch/arm64/boot/dts/renesas/ulcb-vb2.1.dtsi ++++ b/arch/arm64/boot/dts/renesas/ulcb-vb2.1.dtsi +@@ -72,6 +72,11 @@ + groups = "usb1"; + function = "usb1"; + }; ++ ++ usb3_pins: usb3 { ++ groups = "usb2_ch3"; ++ function = "usb2_ch3"; ++ }; + }; + + &usb2_phy1 { +@@ -81,6 +86,13 @@ + status = "okay"; + }; + ++&usb2_phy3 { ++ pinctrl-0 = <&usb3_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ + &ehci1 { + status = "okay"; + }; +@@ -88,3 +100,11 @@ + &ohci1 { + status = "okay"; + }; ++ ++&ehci3 { ++ status = "okay"; ++}; ++ ++&ohci3 { ++ status = "okay"; ++}; +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0417-USB-tusb8041-add-simple-driver-to-start-device-over-.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0417-USB-tusb8041-add-simple-driver-to-start-device-over-.patch new file mode 100644 index 00000000..2e889b43 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0417-USB-tusb8041-add-simple-driver-to-start-device-over-.patch @@ -0,0 +1,288 @@ +From 542ce2e546efc78892b0d81b7b012424d153d2b5 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Wed, 30 May 2018 17:59:22 +0300 +Subject: [PATCH 4/6] USB: tusb8041: add simple driver to start device over + smbus + +Signed-off-by: Andrey Gusakov +--- + drivers/usb/misc/Kconfig | 7 ++ + drivers/usb/misc/Makefile | 1 + + drivers/usb/misc/tusb8041.c | 235 ++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 243 insertions(+) + create mode 100644 drivers/usb/misc/tusb8041.c + +diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig +index 0f9f25d..0476717 100644 +--- a/drivers/usb/misc/Kconfig ++++ b/drivers/usb/misc/Kconfig +@@ -255,6 +255,13 @@ config USB_HSIC_USB4604 + help + This option enables support for SMSC USB4604 HSIC to USB 2.0 Driver. + ++config USB_TUSB8041 ++ tristate "TUSB8041 HUB" ++ depends on I2C ++ help ++ This option enables support for TI TUSB8041 3.0 HUB configuration ++ over SMBUS. ++ + config USB_LINK_LAYER_TEST + tristate "USB Link Layer Test driver" + help +diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile +index 109f54f..9ae89e5 100644 +--- a/drivers/usb/misc/Makefile ++++ b/drivers/usb/misc/Makefile +@@ -27,6 +27,7 @@ obj-$(CONFIG_USB_YUREX) += yurex.o + obj-$(CONFIG_USB_HUB_USB251XB) += usb251xb.o + obj-$(CONFIG_USB_HSIC_USB3503) += usb3503.o + obj-$(CONFIG_USB_HSIC_USB4604) += usb4604.o ++obj-$(CONFIG_USB_TUSB8041) += tusb8041.o + obj-$(CONFIG_USB_CHAOSKEY) += chaoskey.o + + obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/ +diff --git a/drivers/usb/misc/tusb8041.c b/drivers/usb/misc/tusb8041.c +new file mode 100644 +index 0000000..7405ace +--- /dev/null ++++ b/drivers/usb/misc/tusb8041.c +@@ -0,0 +1,235 @@ ++/* ++ * Driver for TI TUSB8041 USB SSIC 4-port 3.0 hub controller driver ++ * Based on tusb8041 and usb3503 drivers ++ * ++ * Copyright (c) 2012-2013 Dongjin Kim (tobetter@gmail.com) ++ * Copyright (c) 2016 Linaro Ltd. ++ * Copyright (c) 2018 Andrey Gusakov (andrey.gusakov@cogentembedded.com) ++ * ++ * 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 ++#include ++#include ++#include ++#include ++ ++enum tusb8041_mode { ++ TUSB8041_MODE_UNKNOWN, ++ TUSB8041_MODE_HUB, ++ TUSB8041_MODE_STANDBY, ++}; ++ ++struct tusb8041 { ++ enum tusb8041_mode mode; ++ u8 *regs; ++ int regs_sz; ++ struct device *dev; ++ struct gpio_desc *gpio_reset; ++}; ++ ++static void tusb8041_reset(struct tusb8041 *hub, int state) ++{ ++ gpiod_set_value_cansleep(hub->gpio_reset, state); ++} ++ ++static int tusb8041_connect(struct tusb8041 *hub) ++{ ++ struct device *dev = hub->dev; ++ struct i2c_client *client = to_i2c_client(dev); ++ int ret; ++ int retry = 100; ++ ++ tusb8041_reset(hub, 1); ++ ++ /* reset and load defaults */ ++ ret = i2c_smbus_write_byte_data(client, 0xf8, 0x03); ++ if (ret < 0) ++ goto err; ++ ++ /* wait reset finished */ ++ do { ++ /* check reset bit cleared */ ++ ret = i2c_smbus_read_byte_data(client, 0xf8); ++ if (ret >= 0) { ++ if (ret & 0x02) ++ ret = -EIO; ++ else ++ ret = 0; ++ } ++ } while ((retry--) && (ret < 0)); ++ if (ret < 0) ++ goto err; ++ ++ /* write settings */ ++ if ((hub->regs) && (hub->regs_sz)) { ++ int i; ++ ++ for (i = 0; i < hub->regs_sz; i += 2) { ++ do { ++ ret = i2c_master_send(client, &(hub->regs[i]), 2); ++ } while ((retry--) && (ret < 0)); ++ } ++ if (ret < 0) ++ goto err; ++ } ++ ++ /* attach */ ++ do { ++ ret = i2c_smbus_write_byte_data(client, 0xf8, 0x01); ++ if (ret >= 0) { ++ /* check bit cleared */ ++ ret = i2c_smbus_read_byte_data(client, 0xf8); ++ if (ret >= 0) { ++ if (ret & 0x01) ++ ret = -EIO; ++ else ++ ret = 0; ++ } ++ } ++ } while ((retry--) && (ret < 0)); ++ ++ if (ret < 0) ++ goto err; ++ ++ hub->mode = TUSB8041_MODE_HUB; ++ dev_dbg(dev, "switched to HUB mode\n"); ++ return 0; ++ ++err: ++ dev_err(dev, "Failed to write settings: %d\n", ret); ++ tusb8041_reset(hub, 0); ++ return ret; ++} ++ ++static int tusb8041_switch_mode(struct tusb8041 *hub, enum tusb8041_mode mode) ++{ ++ struct device *dev = hub->dev; ++ int err = 0; ++ ++ switch (mode) { ++ case TUSB8041_MODE_HUB: ++ err = tusb8041_connect(hub); ++ break; ++ ++ case TUSB8041_MODE_STANDBY: ++ tusb8041_reset(hub, 0); ++ dev_dbg(dev, "switched to STANDBY mode\n"); ++ break; ++ ++ default: ++ dev_err(dev, "unknown mode is requested\n"); ++ err = -EINVAL; ++ break; ++ } ++ ++ return err; ++} ++ ++static int tusb8041_probe(struct tusb8041 *hub) ++{ ++ struct device *dev = hub->dev; ++ struct device_node *np = dev->of_node; ++ struct gpio_desc *gpio; ++ int ret; ++ u32 mode = TUSB8041_MODE_HUB; ++ int sz; ++ ++ gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); ++ if (IS_ERR(gpio)) ++ return PTR_ERR(gpio); ++ hub->gpio_reset = gpio; ++ ++ if (of_property_read_u32(np, "initial-mode", &hub->mode)) ++ hub->mode = mode; ++ ++ if (of_find_property(np, "ti,registers", &sz) && ((sz & 0x01) == 0)) { ++ hub->regs = devm_kzalloc(hub->dev, sz, GFP_KERNEL); ++ ret = of_property_read_u8_array(np, "ti,registers", hub->regs, sz); ++ if (ret == 0) ++ hub->regs_sz = sz; ++ } ++ ++ /* reset */ ++ tusb8041_reset(hub, 0); ++ msleep(250); ++ ++ return tusb8041_switch_mode(hub, hub->mode); ++} ++ ++static int tusb8041_i2c_probe(struct i2c_client *i2c, ++ const struct i2c_device_id *id) ++{ ++ struct tusb8041 *hub; ++ ++ hub = devm_kzalloc(&i2c->dev, sizeof(*hub), GFP_KERNEL); ++ if (!hub) ++ return -ENOMEM; ++ ++ i2c_set_clientdata(i2c, hub); ++ hub->dev = &i2c->dev; ++ ++ return tusb8041_probe(hub); ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int tusb8041_i2c_suspend(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct tusb8041 *hub = i2c_get_clientdata(client); ++ ++ tusb8041_switch_mode(hub, TUSB8041_MODE_STANDBY); ++ ++ return 0; ++} ++ ++static int tusb8041_i2c_resume(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct tusb8041 *hub = i2c_get_clientdata(client); ++ ++ tusb8041_switch_mode(hub, hub->mode); ++ ++ return 0; ++} ++#endif ++ ++static SIMPLE_DEV_PM_OPS(tusb8041_i2c_pm_ops, tusb8041_i2c_suspend, ++ tusb8041_i2c_resume); ++ ++static const struct i2c_device_id tusb8041_id[] = { ++ { "tusb8041", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, tusb8041_id); ++ ++#ifdef CONFIG_OF ++static const struct of_device_id tusb8041_of_match[] = { ++ { .compatible = "ti,tusb8041" }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, tusb8041_of_match); ++#endif ++ ++static struct i2c_driver tusb8041_i2c_driver = { ++ .driver = { ++ .name = "tusb8041", ++ .pm = &tusb8041_i2c_pm_ops, ++ .of_match_table = of_match_ptr(tusb8041_of_match), ++ }, ++ .probe = tusb8041_i2c_probe, ++ .id_table = tusb8041_id, ++}; ++module_i2c_driver(tusb8041_i2c_driver); ++ ++MODULE_DESCRIPTION("TUSB8041 USB HUB driver"); ++MODULE_LICENSE("GPL v2"); +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0418-arm64-dts-renesas-ulcb-vb2-fix-USB30-and-HUB.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0418-arm64-dts-renesas-ulcb-vb2-fix-USB30-and-HUB.patch new file mode 100644 index 00000000..b39c51fb --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0418-arm64-dts-renesas-ulcb-vb2-fix-USB30-and-HUB.patch @@ -0,0 +1,116 @@ +From ef159033e2ef9917c15335ba89bcbeb4270773c6 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Tue, 11 Jun 2019 16:21:41 +0300 +Subject: [PATCH 5/6] arm64: dts: renesas: ulcb-vb2: fix USB30 and HUB + +- add two HUB nodes as HUB can populate one of two i2c addresses +depending on power supply start order. Driver just fixes few +registers values over i2c for proper operation. +- same driver handles reset gpio, so remove regulator. +- add pinctl for XHCI and remove PWEN regulator. + +Signed-off-by: Andrey Gusakov +--- + arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 58 +++++++++++++++++++------------ + 1 file changed, 35 insertions(+), 23 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi +index 5831d12..50cdfd8 100644 +--- a/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi ++++ b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi +@@ -74,27 +74,7 @@ + regulator-always-on; + }; + +- hub_reset: regulator@9 { +- compatible = "regulator-fixed"; +- regulator-name = "hub_reset"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- gpio = <&gpio5 5 0>; +- enable-active-high; +- regulator-always-on; +- }; +- +- hub_power: regulator@10 { +- compatible = "regulator-fixed"; +- regulator-name = "hub_power"; +- regulator-min-microvolt = <5000000>; +- regulator-max-microvolt = <5000000>; +- gpio = <&gpio6 28 0>; +- enable-active-high; +- regulator-always-on; +- }; +- +- can2_power: regulator@11 { ++ can2_power: regulator@9 { + compatible = "regulator-fixed"; + regulator-name = "can2_power"; + regulator-min-microvolt = <3300000>; +@@ -103,7 +83,7 @@ + enable-active-high; + }; + +- can3_power: regulator@12 { ++ can3_power: regulator@10 { + compatible = "regulator-fixed"; + regulator-name = "can3_power"; + regulator-min-microvolt = <3300000>; +@@ -242,6 +222,12 @@ + function = "usb2"; + }; + ++ usb30_pins: usb30 { ++ groups = "usb30"; ++ function = "usb30"; ++ }; ++ ++ + can0_pins: can0 { + groups = "can0_data_a"; + function = "can0"; +@@ -449,7 +435,30 @@ + #size-cells = <0>; + reg = <4>; + /* USB3.0 HUB node(s) */ +- /* addr of TUSB8041 is 100.0100 = 0x44 */ ++ tusb8041_44@44 { ++ compatible = "ti,tusb8041"; ++ reg = <0x44>; ++ reset-gpios = <&gpio5 5 0>; ++ ti,registers = /bits/ 8 < ++ 0x05 0x10 ++ 0x06 0x0f ++ 0x07 0x8f ++ 0x08 0x0f ++ 0x0a 0x20 ++ 0x0b 0x80>; ++ }; ++ tusb8041_45@45 { ++ compatible = "ti,tusb8041"; ++ reg = <0x45>; ++ reset-gpios = <&gpio5 5 0>; ++ ti,registers = /bits/ 8 < ++ 0x05 0x10 ++ 0x06 0x0f ++ 0x07 0x8f ++ 0x08 0x0f ++ 0x0a 0x20 ++ 0x0b 0x80>; ++ }; + }; + + i2c@1 { +@@ -1594,6 +1603,9 @@ + }; + + &xhci0 { ++ pinctrl-0 = <&usb30_pins>; ++ pinctrl-names = "default"; ++ + status = "okay"; + }; + +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0419-phy-rcar-gen3-usb2-power-on-port-in-host-mode-to.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0419-phy-rcar-gen3-usb2-power-on-port-in-host-mode-to.patch new file mode 100644 index 00000000..4987d79b --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0419-phy-rcar-gen3-usb2-power-on-port-in-host-mode-to.patch @@ -0,0 +1,62 @@ +From 47f3896e8938401a641d5c48c8b1dc9389fcb7b1 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Wed, 28 Aug 2019 17:16:35 +0300 +Subject: [PATCH 6/6] phy: rcar-gen3-usb2: power-on port in host mode to + +Signed-off-by: Andrey Gusakov +--- + drivers/phy/renesas/phy-rcar-gen3-usb2.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c +index 0d03c5d..c35f1a1 100644 +--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c ++++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c +@@ -156,7 +156,8 @@ static void rcar_gen3_init_for_host(struct rcar_gen3_chan *ch) + rcar_gen3_enable_vbus_ctrl(ch, 1); + + ch->extcon_host = true; +- schedule_work(&ch->work); ++ if (ch->extcon) ++ schedule_work(&ch->work); + } + + static void rcar_gen3_init_for_peri(struct rcar_gen3_chan *ch) +@@ -166,7 +167,8 @@ static void rcar_gen3_init_for_peri(struct rcar_gen3_chan *ch) + rcar_gen3_enable_vbus_ctrl(ch, 0); + + ch->extcon_host = false; +- schedule_work(&ch->work); ++ if (ch->extcon) ++ schedule_work(&ch->work); + } + + static void rcar_gen3_init_for_b_host(struct rcar_gen3_chan *ch) +@@ -290,8 +292,6 @@ static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch) + void __iomem *usb2_base = ch->base; + u32 val; + +- val = readl(usb2_base + USB2_VBCTRL); +- writel(val | USB2_VBCTRL_DRVVBUSSEL, usb2_base + USB2_VBCTRL); + writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA); + val = readl(usb2_base + USB2_OBINTEN); + writel(val | USB2_OBINT_BITS, usb2_base + USB2_OBINTEN); +@@ -321,11 +321,15 @@ static int rcar_gen3_phy_usb2_init(struct phy *p) + writel(USB2_OC_TIMSET_INIT, usb2_base + USB2_OC_TIMSET); + val = readl(usb2_base + USB2_VBCTRL); + val &= ~USB2_VBCTRL_OCCLREN; ++ /* setup Vbus control pin */ ++ val |= USB2_VBCTRL_DRVVBUSSEL; + writel(val, usb2_base + USB2_VBCTRL); + + /* Initialize otg part */ + if (channel->has_otg_pins) + rcar_gen3_init_otg(channel); ++ else ++ rcar_gen3_init_for_host(channel); + + return 0; + } +-- +2.7.4 + diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/cma.cfg b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/cma.cfg new file mode 100644 index 00000000..e5b5e83f --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/cma.cfg @@ -0,0 +1,2 @@ +CONFIG_CMA_SIZE_MBYTES=256 +CONFIG_CMA_SIZE_SEL_MBYTES=y diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg new file mode 100644 index 00000000..015a94a4 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg @@ -0,0 +1,34 @@ +CONFIG_ARCH_R8A77980=y +CONFIG_CAN=y +CONFIG_CAN_BCM=y +CONFIG_CAN_RAW=y +CONFIG_CAN_DEV=y +CONFIG_CAN_CALC_BITTIMING=y +CONFIG_CAN_RCAR=y +CONFIG_CAN_RCAR_CANFD=y +CONFIG_DUMMY=y +CONFIG_DRM_I2C_ADV7511=y +CONFIG_GPIO_PCA953X=y +CONFIG_GPIO_PCA953X_IRQ=y +CONFIG_VIDEO_ADV_DEBUG=y +CONFIG_VIDEO_RCAR_VIN_LEGACY=y +CONFIG_VIDEO_RCAR_CSI2_LEGACY=y +# CONFIG_VIDEO_RCAR_VIN is not set +# CONFIG_VIDEO_RCAR_CSI2 is not set +CONFIG_SOC_CAMERA=y +CONFIG_SOC_CAMERA_SCALE_CROP=y +CONFIG_SOC_CAMERA_PLATFORM=y +CONFIG_SOC_CAMERA_MAX9286=y +CONFIG_SOC_CAMERA_OV106XX=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_INPUT_UINPUT=y +CONFIG_TOUCHSCREEN_PROPERTIES=y +CONFIG_HID_MULTITOUCH=y +CONFIG_SERIAL_SH_SCI_DMA=y +CONFIG_UIO=y +CONFIG_UIO_PDRV_GENIRQ=m +CONFIG_SH_ETH=y +CONFIG_SATA_ACARD_AHCI=y +CONFIG_GPIO_SYSFS=y +CONFIG_DRM_THINE_THC63LVD1024=y +CONFIG_PHY_RCAR_GEN3_PCIE=y diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/disable-unused.cfg b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/disable-unused.cfg new file mode 100644 index 00000000..ea050a8e --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/disable-unused.cfg @@ -0,0 +1,33 @@ +# CONFIG_ARCH_SUNXI is not set +# CONFIG_ARCH_ALPINE is not set +# CONFIG_ARCH_BCM2835 is not set +# CONFIG_ARCH_BCM_IPROC is not set +# CONFIG_ARCH_BERLIN is not set +# CONFIG_ARCH_BRCMSTB is not set +# CONFIG_ARCH_EXYNOS is not set +# CONFIG_ARCH_LAYERSCAPE is not set +# CONFIG_ARCH_LG1K is not set +# CONFIG_ARCH_HISI is not set +# CONFIG_ARCH_MEDIATEK is not set +# CONFIG_ARCH_MESON is not set +# CONFIG_ARCH_MVEBU is not set +# CONFIG_ARCH_QCOM is not set +# CONFIG_ARCH_ROCKCHIP is not set +# CONFIG_ARCH_SEATTLE is not set +# CONFIG_ARCH_STRATIX10 is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_SPRD is not set +# CONFIG_ARCH_THUNDER is not set +# CONFIG_ARCH_THUNDER2 is not set +# CONFIG_ARCH_UNIPHIER is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_XGENE is not set +# CONFIG_ARCH_ZX is not set +# CONFIG_ARCH_ZYNQMP is not set +# CONFIG_SUNXI_SRAM is not set +# CONFIG_RESET_BERLIN is not set +# CONFIG_RESET_MESON is not set +# CONFIG_RESET_SOCFPGA is not set +# CONFIG_RESET_SUNXI is not set +# CONFIG_RESET_TEGRA_BPMP is not set +# CONFIG_MESON_SM is not set diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg new file mode 100644 index 00000000..d6ee9177 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg @@ -0,0 +1,35 @@ +CONFIG_ARCH_R8A77970=y +CONFIG_CAN=y +CONFIG_CAN_BCM=y +CONFIG_CAN_RAW=y +CONFIG_CAN_DEV=y +CONFIG_CAN_CALC_BITTIMING=y +CONFIG_CAN_RCAR=y +CONFIG_CAN_RCAR_CANFD=y +CONFIG_DUMMY=y +CONFIG_DRM_I2C_ADV7511=y +CONFIG_GPIO_PCA953X=y +CONFIG_GPIO_PCA953X_IRQ=y +CONFIG_VIDEO_ADV_DEBUG=y +CONFIG_VIDEO_RCAR_VIN_LEGACY=y +CONFIG_VIDEO_RCAR_CSI2_LEGACY=y +# CONFIG_VIDEO_RCAR_VIN is not set +# CONFIG_VIDEO_RCAR_CSI2 is not set +CONFIG_SOC_CAMERA=y +CONFIG_SOC_CAMERA_SCALE_CROP=y +CONFIG_SOC_CAMERA_PLATFORM=y +CONFIG_SOC_CAMERA_MAX9286=y +CONFIG_SOC_CAMERA_OV106XX=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_INPUT_UINPUT=y +CONFIG_TOUCHSCREEN_PROPERTIES=y +CONFIG_HID_MULTITOUCH=y +CONFIG_SERIAL_SH_SCI_DMA=y +CONFIG_UIO=y +CONFIG_MFD_DA9063=y +CONFIG_INPUT_DA9063_ONKEY=y +CONFIG_DA9063_WATCHDOG=y +CONFIG_REGULATOR_DA9063=y +CONFIG_RCAR_THERMAL=y +CONFIG_GPIO_SYSFS=y +CONFIG_DRM_THINE_THC63LVD1024=y diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/hyperflash.cfg b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/hyperflash.cfg new file mode 100644 index 00000000..df45d5e9 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/hyperflash.cfg @@ -0,0 +1,2 @@ +CONFIG_MTD=y +CONFIG_MTD_RPC_HYPERFLASH=y diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/imr.cfg b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/imr.cfg new file mode 100644 index 00000000..cc7f69e9 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/imr.cfg @@ -0,0 +1,3 @@ +CONFIG_VIDEO_RENESAS_IMR=m +CONFIG_UIO=y +CONFIG_UIO_IMR=m diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/nvme.cfg b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/nvme.cfg new file mode 100644 index 00000000..740a25e4 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/nvme.cfg @@ -0,0 +1,2 @@ +CONFIG_NVME_CORE=y +CONFIG_BLK_DEV_NVME=y diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/qspi.cfg b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/qspi.cfg new file mode 100644 index 00000000..9a1c695e --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/qspi.cfg @@ -0,0 +1,3 @@ +CONFIG_SPI_RENESAS_RPC=y +CONFIG_MTD_BLOCK=y +CONFIG_JFFS2_FS=y diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/renesas-not-applied.scc b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/renesas-not-applied.scc new file mode 100644 index 00000000..6d542846 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/renesas-not-applied.scc @@ -0,0 +1,16 @@ +0014-lib-swiotlb-reduce-verbosity.patch +0018-arm64-renesas-r8a7797-Add-Renesas-R8A7797-SoC-suppor.patch +0026-drm-adv7511-add-polling-mode-when-no-irq-available.patch +0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch +0052-soc-renesas-rcar-sysc-Add-workaround-for-A3-PD-issue.patch +0079-Revert-dmaengine-rcar-dmac-use-TCRB-instead-of-TCR-f.patch +0082-gpio-pca953x-fix-interrupt-trigger.patch +0090-ASoC-rsnd-fixup-rsnd_ssi_master_clk_start-user-count.patch +0100-LVDS-ar0132-use-raw12.patch +0101-LVDS-ar0132-use-context-swwitch.patch +0103-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch +0104-media-vsp1-extend-DRM-VSP1-interface.patch +0105-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch +0106-media-rcar-imr-Add-RSE-support.patch +0110-mmc-tmio-Add-SDHI-SEQUENCER-support.patch +0111-mmc-renesas_sdhi-Add-SDHI-SEQUENCER-support.patch diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/renesas.scc b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/renesas.scc new file mode 100644 index 00000000..31146743 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/renesas.scc @@ -0,0 +1,357 @@ +patch 0001-spi-sh-msiof-fixes.patch +patch 0002-spi-spidev-add-spi-gpio-into-spidev.patch +patch 0003-spi-spi-gpio-fix-CPOL-mode.patch +patch 0006-spi-spi-gpio-fix-set-CPOL-default-inverted.patch +patch 0008-Revert-PCI-rcar-pcie-Add-bus-notifier-so-we-can-limi.patch +patch 0009-arm64-dma-check-parent-bus-restrictions-in-dma_capab.patch +patch 0010-can-rcar_can-add-enable-and-standby-control-pins.patch +patch 0011-can-rcar_canfd-add-enable-and-standby-control-pins.patch +patch 0012-mtd-Add-RPC-HyperFlash-driver.patch +patch 0013-IMR-driver-interim-patch.patch +patch 0015-gpio-max732x-fix-gpio-set.patch +patch 0016-gpio-gpiolib-suppress-gpiod-warning.patch +patch 0017-media-soc_camera-add-legacy-VIN-CSI2.patch +patch 0019-Revert-media-v4l2-async-remove-unneeded-.registered_.patch +patch 0020-ti-st-add-device-tree-support.patch +patch 0021-btwilink-add-minimal-device-tree-support.patch +patch 0022-ASoC-Modify-check-condition-of-multiple-bindings-of-.patch +patch 0023-ASoC-add-dummy-Si468x-driver.patch +patch 0024-wl18xx-do-not-invert-IRQ-on-WLxxxx-side.patch +patch 0025-drm-adv7511-Enable-HPD-interrupts-to-support-hotplug.patch +patch 0027-gpu-drm-bridge-adv7511-Add-interlaced-mode-support.patch +patch 0030-Gen3-LVDS-cameras.patch +patch 0031-media-i2c-Add-ov5647-sensor.patch +patch 0032-media-i2c-Add-ov5642-sensor.patch +patch 0033-media-soc-camera-fix-parallel-i-f-in-VIN.patch +patch 0034-media-soc_camera-Fix-VIDIOC_S_SELECTION-ioctl-miscal.patch +patch 0036-Add-MOST-support-for-r8a77965.patch +patch 0037-media-soc_camera-rcar_vin-Fix-VnCSI_IFMD-settings.patch +patch 0038-media-soc_camera-rcar_vin-Add-R-Car-M3N-support.patch +patch 0039-media-soc_camera-rcar_csi2-Add-R-Car-M3N-support.patch +patch 0040-arm64-dts-renesas-add-ADAS-boards.patch +patch 0041-arm64-dts-renesas-ulcb-kf-Move-panel-configuration-t.patch +patch 0042-arm64-dts-renesas-r8a7795-es1-h3ulcb-disable-eMMC.patch +patch 0043-pinctrl-sh-pfc-pfc-r8a77965-Add-missing-avb_mii-pin-.patch +patch 0045-clk-r8a779x-add-mlp-clock.patch +patch 0046-arm64-dts-renesas-r8a779x-add-mlp-nodes.patch +patch 0049-clk-r8a779x-add-IMP-clock.patch +patch 0050-arm64-dts-renesas-r8a779x-add-IMP-nodes.patch +patch 0062-IIO-lsm9ds0-add-IMU-driver.patch +patch 0063-ASoC-PCM3168A-add-TDM-modes-merge-ADC-and-DAC.patch +patch 0064-drm-bridge-adv7511-Add-frequency-and-vrefresh-limita.patch +patch 0066-pci-pcie-rcar-add-regulators-support.patch +patch 0067-ti-st-use-proper-way-to-get-shutdown-gpio.patch +patch 0068-drm-adv7511-use-smbus-to-retrieve-edid.patch +patch 0071-ASoC-add-dummy-device-for-WL18xx-PCM-audio.patch +patch 0072-usb-hub-disable-autosuspend-for-SMSC-hubs.patch +patch 0073-MOST-dim2-add-device-tree-support.patch +patch 0074-MOST-dim2-add-R-Car3-related-initialization.patch +patch 0075-MOST-core-fix-memory-allocation-at-arm64.patch +patch 0076-MOST-dim2-Renesas-R-Car3-variant.patch +patch 0077-MOST-dim2-add-timeouts.patch +patch 0078-MOST-aim-fix-null-pointer-crash.patch +patch 0109-serial-sh-sci-Fix-minimal-rx_timeout-value.patch +patch 0112-ARM64-dts-renesas-ulcb-Make-AK4613-sound-device-name.patch +patch 0113-arm64-dts-ulcb-kf-increase-SDIO-frequency-for-WLAN-c.patch +patch 0114-Sony-IMX219-driver.patch +patch 0116-media-i2c-soc_camera-Fix-Bad-of_node_put-error.patch +patch 0117-rcar-vin-fix-get_selection-use.patch +patch 0118-clk-clk-gpio-Allow-GPIO-to-sleep-in-set-get_parent.patch +patch 0119-i2c-mix-pca954x-reset-mux-in-case-of-error-during-bu.patch +patch 0120-arm64-dts-ulcb-kf-pcm3168a-reset-earlier-i2c-mux-dis.patch +patch 0122-block-blk-mq-Fix-IO-hang.patch +patch 0123-nvme-Workaround-Samsung-970-Pro-power-state-issues.patch +patch 0124-nvme-pci-add-SGL-support.patch +patch 0125-nvme-pci-don-t-open-code-nvme_reset_ctrl.patch +patch 0126-nvme-pci-limit-max-IO-size-and-segments-to-avoid-hig.patch +patch 0127-swiotlb-Respect-DMA_ATTR_NO_WARN-in-swiotlb_map_sg_a.patch +patch 0128-arm64-dts-Add-H3ULCB-VideoBox-2.1-support.patch +patch 0129-can-rcar_canfd-fix-possible-IRQ-storm-on-high-load.patch +patch 0130-LVDS-ar0132-use-context-swwitch.patch +patch 0131-media-i2c-soc_camera-Bunch-update-from-2.23.1.patch +patch 0132-lvds-ti960-fix-frame-sync-time-for-different-ref-clo.patch +patch 0133-lvds-add-AR0323-imager.patch +patch 0134-lvds-add-ISX016-imager.patch +patch 0135-LVDS-ar0233-set-frame-size-1920x1200.patch +patch 0136-lvds-AR0233-add-different-vendor.patch +patch 0137-lvds-poll-ub960-deserializer-lock-status.patch +patch 0138-lvds-AR0231-modify-with-rev7-silicon.patch +patch 0139-lvds-AR0233-modify-with-rev2-silicon.patch +patch 0140-lvds-ti9x4-fix-remote-gpio-enablement-for-4-cams.patch +patch 0141-media-soc_camera-imx390-Add-new-V4L-controls.patch +patch 0142-lvds-AR233-add-rev1-silion-setup.patch +patch 0143-LVDS-AR0231-add-rev6-rev4-on-max9286.patch +patch 0144-lvds-add-OV10640-imager.patch +patch 0145-lvds-ti9x4-fix-remote-gpio-enablement-on-UB913.patch +patch 0146-lvds-add-dummy-imager-driver.patch +patch 0147-lvds-ti9x4-use-REFCLK-23.0MHz.patch +patch 0148-lvds-ar0231-fix-comments.patch +patch 0149-lvds-ISX019-rename-isx016-to-isx019.patch +patch 0150-lvds-add-ISX016-imager.patch +patch 0151-lvds-ti9x4-add-DVP-LSB-MSB-selection.patch +patch 0152-lvds-AR323-fix-reset-gpio-nadling.patch +patch 0153-lvds-OV495-fix-reset-gpio-handling.patch +patch 0154-lvds-AR0323-replace-with-REV2-setup-table.patch +patch 0155-AR0143-add-original-ONSEMI-setup.patch +patch 0156-AR0143-enable-3exp-in-custom-setup.patch +patch 0157-AR0143-add-choose-of-imager-setup.patch +patch 0158-MAX9286-fix-BWS-setup-to-reserve-reboot.patch +patch 0159-MAX9286-adjust-POC-trigger-for-unstable-link.patch +patch 0160-lvds-onsemi-fix-revsion-parsing.patch +patch 0161-lvds-AR0233-add-module-trigger-parameter.patch +patch 0162-lvds-AR0233-migrate-to-composed-tables.patch +patch 0163-lvds-AP0101-AR014X-add-TI-serializers.patch +patch 0164-lvds-fix-vendor-names.patch +patch 0165-LVDS-add-GW5200-IMX390-camera.patch +patch 0166-lvds-AR0233-add-superexposure-plus.patch +patch 0167-lvds-AR0233-fix-matrix-size-set-default-h-vflip.patch +patch 0168-lvds-ISX019-fix-add-address-intf-fix-read-write.patch +patch 0169-lvds-OVT-add-dvp_order-parameter-for-ov10635.patch +patch 0170-media-i2c-add-AR0147-imager.patch +patch 0171-lvds-ONSEMI-fix-matrix-position-during-crop.patch +patch 0172-media-i2c-ar0147-fix-super-exposure-artifact-line.patch +patch 0173-lvds-ti9x4-fix-remote-gpio-setup.patch +patch 0174-arm64-dts-renesas-ulcb-vb2-Drive-CAN-controller-rese.patch +patch 0175-lvds-ov2775-add-exposure-gain.patch +patch 0177-media-rcar_vin-add-GREY-Y8-bypass.patch +patch 0178-lvds-add-OV2311-imager.patch +patch 0179-media-i2c-soc_camera-Fix-more-Bad-of_node_put-errors.patch +patch 0180-media-i2c-ov490-add-LI-cameras.patch +patch 0181-ARM64-dts-Remove-conflicting-with-mainline-V3M-and-V.patch +patch 0182-iommu-msm-Claim-bus-ops-on-probe.patch +patch 0183-iommu-Clean-up-of_iommu_init_fn.patch +patch 0184-iommu-ipmmu-vmsa-Hook-up-r8a779-70-95-DT-matching-co.patch +patch 0185-dt-bindings-display-bridge-Document-THC63LVD1024-LVD.patch +patch 0186-gpio-rcar-document-R8A77980-bindings.patch +patch 0187-arm64-dts-renesas-r8a77980-add-SMP-support.patch +patch 0188-arm64-dts-renesas-r8a77980-add-GEther-support.patch +patch 0189-arm64-dts-renesas-v3hsk-add-GEther-support.patch +patch 0190-arm64-dts-renesas-r8a77980-add-I2C-support.patch +patch 0191-arm64-dts-renesas-condor-add-I2C0-support.patch +patch 0192-arm64-dts-renesas-r8a77980-add-GPIO-support.patch +patch 0193-arm64-dts-renesas-condor-v3hsk-specify-Ethernet-PHY-.patch +patch 0194-arm64-dts-renesas-r8a77980-add-FCPVD-VSPD-DU-LVDS-su.patch +patch 0195-sh_eth-fix-enum-RPADIR_BIT.patch +patch 0196-sh_eth-remove-sh_eth_cpu_data-rpadir_value.patch +patch 0197-sh_eth-fix-enum-A-M-PR_BIT.patch +patch 0198-iommu-ipmmu-vmsa-Document-R-Car-V3H-and-E3-IPMMU-DT-.patch +patch 0199-dt-bindings-phy-Renesas-R-Car-Gen3-PCIe-PHY-bindings.patch +patch 0200-phy-Renesas-R-Car-gen3-PCIe-PHY-driver.patch +patch 0201-dt-bindings-irqchip-renesas-irqc-Document-r8a77980-s.patch +patch 0202-arm64-dts-renesas-r8a77980-add-INTC-EX-support.patch +patch 0203-net-phy-allow-scanning-busses-with-missing-phys.patch +patch 0204-arm64-dts-renesas-r8a77980-add-RWDT-support.patch +patch 0205-arm64-enable-CMT-TMU-support-for-Renesas-SoC.patch +patch 0206-arm64-dts-renesas-r8a77980-add-Cortex-A53-PMU-suppor.patch +patch 0207-arm64-dts-renesas-r8a77980-move-IPMMU-nodes.patch +patch 0208-arm64-dts-renesas-r8a779-7-8-0-move-CAN-clock-node.patch +patch 0209-arm64-dts-renesas-r8a77980-add-CSI2-VIN-support.patch +patch 0210-arm64-dts-renesas-r8a77970-add-MMC-support.patch +patch 0211-arm64-dts-renesas-v3msk-add-eMMC-support.patch +patch 0212-arm64-dts-renesas-condor-v3hsk-add-DU-LVDS-HDMI-supp.patch +patch 0213-arm64-dts-renesas-r8a77980-add-PCIe-support.patch +patch 0214-arm64-dts-renesas-condor-add-PCIe-support.patch +patch 0215-arm64-dts-renesas-v3hsk-Move-lvds0-node.patch +patch 0216-arm64-dts-renesas-r8a77980-Attach-the-SYS-DMAC-to-th.patch +patch 0217-arm64-dts-renesas-r8a779-7-8-0-add-CMT-support.patch +patch 0218-dt-bindings-timer-renesas-tmu-document-R8A779-7-8-0-.patch +patch 0219-arm64-dts-renesas-r8a779-7-8-0-add-TPU-support.patch +patch 0220-arm64-dts-renesas-r8a779-7-8-0-add-PWM-support.patch +patch 0221-media-vsp1-Use-header-display-lists-for-all-WPF-outp.patch +patch 0222-arm64-dts-renesas-r8a77970-add-thermal-support.patch +patch 0223-arm64-dts-renesas-r8a77980-add-thermal-support.patch +patch 0224-arm64-dts-renesas-r8a779-7-8-0-add-TMU-support.patch +patch 0225-arm64-dts-renesas-r8a779-7-8-0-add-MSIOF-support.patch +patch 0226-arm64-dts-renesas-r8a77980-Connect-R-Car-V3H-AVB-to-.patch +patch 0227-clk-renesas-r8a77980-Add-OSC-predivider-configuratio.patch +patch 0228-clk-renesas-r8a77980-Add-RCLK-for-watchdog-timer.patch +patch 0229-drm-rcar-du-lvds-add-R8A77980-support.patch +patch 0230-drivers-flag-buses-which-demand-DMA-configuration.patch +patch 0231-gpu-host1x-Call-of_dma_configure-after-setting-bus.patch +patch 0232-gpu-host1x-Cleanup-on-initialization-failure.patch +patch 0233-dma-mapping-move-dma-configuration-to-bus-infrastruc.patch +patch 0234-drivers-remove-force-dma-flag-from-buses.patch +patch 0235-clk-renesas-r8a77980-Add-CMT-clocks.patch +patch 0236-clk-renesas-r8a77970-Add-SD0H-SD0-clocks-for-SDHI.patch +patch 0237-clk-renesas-r8a77970-Add-CMT-clocks.patch +patch 0238-clk-renesas-r8a77970-Add-TMU-clocks.patch +patch 0239-dt-bindings-display-renesas-du-document-R8A77980-bin.patch +patch 0240-dt-bindings-display-renesas-lvds-document-R8A77980-b.patch +patch 0241-clk-renesas-r8a77970-Add-TPU-clock.patch +patch 0242-mmc-renesas_sdhi_internal_dmac-add-R8A77970-to-white.patch +patch 0243-dt-bindings-mmc-tmio_mmc-document-Renesas-R8A77970-b.patch +patch 0244-dt-bindings-thermal-rcar-gen3-thermal-document-R8A77.patch +patch 0245-thermal-rcar_gen3_thermal-add-R8A77980-support.patch +patch 0246-dt-bindings-thermal-rcar-thermal-document-R8A77970-b.patch +patch 0247-thermal-rcar_thermal-add-R8A77970-support.patch +patch 0248-clk-renesas-r8a77970-Add-RPC-clocks.patch +patch 0249-pinctrl-sh-pfc-r8a77970-Add-QSPI-pins-groups-and-fun.patch +patch 0250-pinctrl-sh-pfc-r8a77980-Add-QSPI-pins-groups-and-fun.patch +patch 0251-media-rcar-rcar-csi2-Update-V3M-E3-PHTW-tables.patch +patch 0252-soc-renesas-r8a77970-sysc-Remove-non-existent-CR7-po.patch +patch 0253-soc-renesas-r8a77970-sysc-Correct-names-of-A2DP-A2CN.patch +patch 0254-soc-renesas-r8a77980-sysc-Correct-names-of-A2DP-01-p.patch +patch 0255-soc-renesas-r8a77980-sysc-Correct-A3VIP-012-power-do.patch +patch 0256-clk-renesas-r8a77970-Add-CPEX-clock.patch +patch 0257-media-rcar-csi2-add-R8A77980-support.patch +patch 0258-media-rcar-vin-add-R8A77980-support.patch +patch 0259-pinctrl-sh-pfc-r8a77970-Add-missing-MOD_SEL0-field.patch +patch 0260-pinctrl-sh-pfc-r8a77980-Add-missing-MOD_SEL0-field.patch +patch 0261-media-rcar-csi2-Fix-PHTW-table-values-for-E3-V3M.patch +patch 0262-pinctrl-sh-pfc-Reduce-kernel-size-for-narrow-VIN-cha.patch +patch 0263-pinctrl-sh-pfc-r8a77970-Deduplicate-VIN-01-pin-defin.patch +patch 0264-pinctrl-sh-pfc-r8a77980-Deduplicate-VIN1-pin-definit.patch +patch 0265-arm64-dts-renesas-v3msk-specify-EtherAVB-PHY-IRQ.patch +patch 0266-sh_eth-rename-sh_eth_cpu_data-hw_checksum.patch +patch 0267-sh_eth-RX-checksum-offload-support.patch +patch 0268-sh_eth-offload-RX-checksum-on-R7S72100.patch +patch 0269-sh_eth-offload-RX-checksum-on-R8A7740.patch +patch 0270-sh_eth-offload-RX-checksum-on-R8A77980.patch +patch 0271-sh_eth-offload-RX-checksum-on-SH7734.patch +patch 0272-sh_eth-offload-RX-checksum-on-SH7763.patch +patch 0273-clk-renesas-rcar-gen3-Factor-out-cpg_reg_modify.patch +patch 0274-clk-renesas-rcar-gen3-Add-spinlock.patch +patch 0275-clk-renesas-rcar-gen3-Add-RPC-clocks.patch +patch 0276-clk-renesas-r8a77980-Add-RPC-clocks.patch +patch 0277-pinctrl-sh-pfc-r8a77970-Rename-IOCTRLx-registers.patch +patch 0278-pinctrl-sh-pfc-r8a77980-Rename-IOCTRLx-registers.patch +patch 0279-clk-renesas-r8a77980-Fix-RPC-IF-module-clock-s-paren.patch +patch 0280-arm64-dts-renesas-r8a77980-Add-renesas-id-to-VIN.patch +patch 0281-arm64-dts-renesas-eagle-Add-x1-clock.patch +patch 0282-arm64-dts-renesas-r8a77980-condor-Add-GEther-support.patch +patch 0283-iommu-ipmmu-vmsa-Add-r8a77980-support.patch +patch 0284-iommu-ipmmu-vmsa-Fix-NULL-pointer-dereference.patch +patch 0285-iommu-ipmmu-vmsa-Add-r8a779-7-8-0-whitelist.patch +patch 0286-clk-renesas-r8a77980-cpg-mssr-Add-VIN-clocks.patch +patch 0287-clk-renesas-r8a77970-cpg-mssr-Add-IMR-clocks.patch +patch 0288-clk-renesas-r8a77980-cpg-mssr-Add-IMR-clocks.patch +patch 0289-clk-renesas-r8a77970-cpg-mssr-Add-ISP-clock.patch +patch 0290-clk-renesas-r8a77980-cpg-mssr-Add-ISP-clocks.patch +patch 0291-clk-renesas-r8a77980-cpg-mssr-Add-IMP-clocks.patch +patch 0292-clk-renesas-r8a77980-cpg-mssr-Add-VIP-clocks.patch +patch 0293-clk-renesas-r8a77970-cpg-mssr-Add-IMP-clocks.patch +patch 0294-media-soc_camera-Add-CONFIG_VIDEO_ADV_DEBUG-support.patch +patch 0295-media-platform-soc_camera-Add-V4L2-R-Car-ISP-driver.patch +patch 0296-media-platform-soc_camera-rcar_isp-Fix-unused-variab.patch +patch 0297-media-platform-soc_camera-rcar_vin-Update-R-Car-V3M-.patch +patch 0298-media-platform-soc_camera-rcar_vin-Add-r8a77980-supp.patch +patch 0299-media-platform-soc_camera-rcar_csi2-r8a77970-Update-.patch +patch 0300-media-platform-soc_camera-rcar_csi2-Add-r8a77980-sup.patch +patch 0301-arm64-dts-renesas-r8a77970-Convert-VIN-nodes-to-soc_.patch +patch 0302-arm64-dts-renesas-r8a77980-Convert-VIN-nodes-to-soc_.patch +patch 0303-arm64-dts-renesas-r8a77970-Convert-SCI2-nodes-to-soc.patch +patch 0304-arm64-dts-renesas-r8a77980-Convert-CSI2-nodes-to-soc.patch +patch 0305-arm64-dts-renesas-r8a77970-Add-IMR-nodes.patch +patch 0306-arm64-dts-renesas-r8a77980-Add-IMR-nodes.patch +patch 0307-arm64-dts-renesas-r8a77970-Add-ISP-node.patch +patch 0308-arm64-dts-renesas-r8a77980-Add-ISP-nodes.patch +patch 0309-arm64-dts-renesas-eagle-Add-video-input-support.patch +patch 0310-arm64-dts-renesas-condor-Add-video-input-support.patch +patch 0311-arm64-dts-renesas-v3msk-Add-reserved-memory-nodes.patch +patch 0312-arm64-dts-renesas-v3hsk-Add-reserved-memory-nodes.patch +patch 0313-arm64-dts-renesas-eagle-Add-reserved-memory-nodes.patch +patch 0314-arm64-dts-renesas-condor-Add-reserved-memory-nodes.patch +patch 0315-arm64-dts-renesas-v3msk-Add-mmngr-and-mmngrbuf-nodes.patch +patch 0316-arm64-dts-renesas-v3hsk-Add-mmngr-and-mmngrbuf-nodes.patch +patch 0317-arm64-dts-renesas-eagle-Add-mmngr-and-mmngrbuf-nodes.patch +patch 0318-arm64-dts-renesas-condor-Add-mmngr-and-mmngrbuf-node.patch +patch 0319-arm64-dts-renesas-v3msk-Add-vspm_if-node.patch +patch 0320-arm64-dts-renesas-v3hsk-Add-vspm_if-node.patch +patch 0321-arm64-dts-renesas-eagle-Add-vspm_if-node.patch +patch 0322-arm64-dts-renesas-condor-Add-vspm_if-node.patch +patch 0323-arm64-dts-renesas-eagle-Add-Dialog-DA9063-MFD.patch +patch 0324-arm64-dts-renesas-Add-r8a77970-eagle-function-suppor.patch +patch 0325-arm64-dts-renesas-Add-r8a77970-es1-support.patch +patch 0326-arm64-dts-renesas-Add-r8a77970-v3msk-view-support.patch +patch 0327-arm64-dts-renesas-Add-r8a77970-v3msk-kf-support.patch +patch 0328-arm64-dts-renesas-Add-r8a77970-v3msk-vbm-support.patch +patch 0329-arm64-dts-renesas-Add-r8a77970-v3mzf-support.patch +patch 0330-arm64-dts-renesas-Add-r8a77980-v3hsk-vbm-support.patch +patch 0331-arm64-dts-renesas-r8a779-7-8-0-Add-IMP-devices.patch +patch 0332-arm64-dts-renesas-r8a77980-Add-VIP-nodes.patch +patch 0333-arm64-dts-renesas-r8a779-78-0-Add-linux-multimedia-r.patch +patch 0334-IMR-UIO-Driver-initial-version.patch +patch 0335-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch +patch 0336-media-rcar-imr-Add-RSE-support.patch +patch 0337-rcar_imr-v4l2-driver-Fix-module-support.patch +patch 0338-V3Hsk-Condor-and-V3Msk-Eagle-Remove-cma-default-area.patch +patch 0339-media-rcar_imr-Enable-LUCE-for-NV16-format.patch +patch 0340-clk-cs2000-add-support-for-cs2300.patch +patch 0341-V3H-add-support-for-8-4-channel-VideoBox-board-from-.patch +patch 0342-arm64-dts-r8a77970-Videobox-Mini-V3-board-support.patch +patch 0343-arm64-dts-renesas-r8a77970-v3msk-Add-ethernet0-alias.patch +patch 0344-arm64-dts-renesas-r8a77970-Add-ISP0-alias.patch +patch 0345-arm64-dts-renesas-r8a77980-Add-ISP-aliases.patch +patch 0346-media-soc_camera-Add-soc_camera-host-preregister.patch +patch 0347-arm64-renesas-r8a77980-use-CSI-4-lanes.patch +patch 0348-Bunch-update-of-r8a77980-v3hsk-vb-4ch.dts.patch +patch 0349-arm64-dts-renesas-r8a77980-VideoBox-Mini-fix-csi-spe.patch +patch 0350-arm64-dts-renesas-r8a77980-v3hsk-vb-4ch-and-8ch-fix-.patch +patch 0351-arm64-dts-renesas-r8a77980-VB-4ch-and-8ch-Add-PCIE-p.patch +patch 0352-gpu-drm-rcar_du-Fix-physical-address-of-the-CMA-back.patch +patch 0353-media-soc_camera-rcar_csi2-add-dump-module-param.patch +patch 0354-media-rcar_csi2-Disable-data-type-matching.patch +patch 0355-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch +patch 0356-media-platform-vsp1-Extend-DRM-VSP1-interface.patch +patch 0357-gpu-drm-rcar-du-rcar_du_vsp-Check-if-gem-buffer-has-.patch +patch 0358-media-platform-vsp1-Add-cropping-handling-to-VSP-alp.patch +patch 0359-media-platform-rcar_imr-Clean-up-to-avoid-compiler-w.patch +patch 0360-arm64-dts-renesas-r8a77970-and-r8a77980-Add-CPU-oper.patch +patch 0361-V3H-DTS-Add-FCPR-devices.patch +patch 0362-arm64-dts-r8a77980-v3hsk-Enable-onboard-eMMC.patch +patch 0363-arm64-dts-renesas-r8a77980-v3hsk-vb-Xch-Fix-Ethernet.patch +patch 0364-clocksource-drivers-sh_cmt-Add-R-Car-gen3-support.patch +patch 0365-mtd-spi-nor-Add-R-Car-Gen3-RPC-QSPI-driver.patch +patch 0366-mtd-spi-nor-renesas-rpc-Workaround-256-byte-data-siz.patch +patch 0367-mtd-spi-nor-Add-s25fs512s-and-s25fs128s-01-SPI-NOR-f.patch +patch 0368-arm64-dts-renesas-r8a77970-Add-RPC-QSPI-node.patch +patch 0369-arm64-dts-renesas-r8a77980-Add-RPC-QSPI-node.patch +patch 0370-arm64-dts-renesas-v3msk-Add-s25fs512s-QSPI-flash-nod.patch +patch 0371-arm64-dts-renesas-v3mzf-Add-s25fs512s-QSPI-flash-nod.patch +patch 0372-arm64-dts-renesas-eagle-Add-s25fs512s-QSPI-flash-nod.patch +patch 0373-arm64-dts-renesas-v3hsk-Add-s25fs512s-QSPI-flash-nod.patch +patch 0374-arm64-dts-renesas-condor-Add-s25fs512s-QSPI-flash-no.patch +patch 0375-mtd-spi-nor-renesas-rpc-Support-single-mode-write-co.patch +patch 0376-mtd-spi-nor-renesas-rpc-Add-DMA-read-support.patch +patch 0377-r8a779-78-dtsi-Add-iccom-nodes.patch +patch 0378-arm64-dts-renesas-Add-temperature-emergency-levels.patch +patch 0379-r8a77980-dts-Add-vbm-v3-on-r8a77980-SoC.patch +patch 0380-arm64-dts-r8a77970-Enable-TMU-and-CMT.patch +patch 0381-arm64-dts-r8a77980-Enable-TMU-and-CMT.patch +patch 0382-arm64-dts-renesas-r8a77970-and-r8a77980-Add-QoS-node.patch +patch 0383-clk-renesas-r8a77970-cpg-mssr-Add-sadc-clock.patch +patch 0384-arm64-dts-renesas-r8a77970-Add-sadc-node.patch +patch 0385-iio-adc-Add-R-Car-SADC-driver.patch +patch 0386-rcar-vin-add-ISP-source-enable.patch +patch 0387-media-soc_camera-Add-events-support.patch +patch 0388-media-rcar-imr-Add-stride-support-to-IMR.patch +patch 0389-arm64-renesas-r8a77980-VB-use-REFCLK-23.0MHZ.patch +patch 0390-arm64-dts-renesas-Add-V3x-VideoBox-FDPLink-support.patch +patch 0392-gpu-drm-bridge-thc63-Set-upper-clock-limit-to-150-MH.patch +patch 0393-media-soc_camera-dummy-add-mbus-controls-ids.patch +patch 0394-media-i2c-ar0233-fix-superexposure.patch +patch 0395-media-i2c-ap0101-add-V-H-flip.patch +patch 0396-media-i2c-ap0101-ar014x-get-OTP-more-complex.patch +patch 0397-media-i2c-ar0147-add-mipi-rev3-lvds-support.patch +patch 0398-media-i2c-ar0147-add-SE-mode.patch +patch 0399-media-i2c-ar0233-fix-artifact-line-at-vflip.patch +patch 0400-media-platform-soc_mediabus-add-Bayer-16bit-format.patch +patch 0401-media-i2c-ov490_ov10640-add-group-switch.patch +patch 0402-media-i2c-gw5200-detection-workaround.patch +patch 0403-media-i2c-ov2311-put-to-autodetect-head.patch +patch 0404-media-i2c-onsemi-imager-correct-trigger-handling.patch +patch 0405-media-i2c-ov10640-fix-controls.patch +patch 0406-Add-new-custom_ioctl-ops-for-soc-camera.patch +patch 0407-arm64-dts-renesas-r8a77970-v3msk-Fix-memory-size.patch +patch 0408-arm64-dts-renesas-v3hsk-Add-GEther-PHY-GPIO-reset-pi.patch +patch 0409-arm64-dts-renesas-condor-Add-GEther-PHY-GPIO-reset-p.patch +patch 0410-arm64-dts-renesas-eagle-Add-RAVB-PHY-GPIO-reset-pin-.patch +patch 0411-media-soc_camera-add-MAX9288-support.patch +patch 0412-media-i2c-soc_camera-differenciate-max9286-and-max92.patch +patch 0413-media-i2c-max9288-fix-stream-on-off.patch +patch 0414-gpio-pca953x-do-not-ignore-i2c-errors.patch +patch 0415-usb-host-xhci-rcar-Add-XHCI_TRUST_TX_LENGTH-quirk.patch +patch 0416-arm64-dtb-renesas-vb2.1-enable-usb2-channel-3.patch +patch 0417-USB-tusb8041-add-simple-driver-to-start-device-over-.patch +patch 0418-arm64-dts-renesas-ulcb-vb2-fix-USB30-and-HUB.patch +patch 0419-phy-rcar-gen3-usb2-power-on-port-in-host-mode-to.patch diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/salvator-x.cfg b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/salvator-x.cfg new file mode 100644 index 00000000..b43866d8 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/salvator-x.cfg @@ -0,0 +1,27 @@ +CONFIG_CAN=y +CONFIG_CAN_PEAK_USB=y +CONFIG_CAN_BCM=y +CONFIG_CAN_RAW=y +CONFIG_CAN_DEV=y +CONFIG_CAN_CALC_BITTIMING=y +CONFIG_CAN_RCAR=y +CONFIG_CAN_RCAR_CANFD=y +CONFIG_DUMMY=y +CONFIG_VIDEO_ADV_DEBUG=y +CONFIG_VIDEO_RCAR_VIN_LEGACY=y +CONFIG_VIDEO_RCAR_CSI2_LEGACY=y +# CONFIG_VIDEO_RCAR_VIN is not set +# CONFIG_VIDEO_RCAR_CSI2 is not set +CONFIG_SOC_CAMERA=y +CONFIG_SOC_CAMERA_SCALE_CROP=y +CONFIG_SOC_CAMERA_PLATFORM=y +CONFIG_SOC_CAMERA_MAX9286=y +CONFIG_SOC_CAMERA_OV106XX=y +CONFIG_MMC_SDHI_PRE_REQ=y +CONFIG_MMC_SDHI_SEQ=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_PROPERTIES=y +CONFIG_HID_MULTITOUCH=y +CONFIG_SERIAL_SH_SCI_DMA=y +CONFIG_UIO=y +CONFIG_GPIO_SYSFS=y diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/sdhi_seq.cfg b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/sdhi_seq.cfg new file mode 100644 index 00000000..9c43599c --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/sdhi_seq.cfg @@ -0,0 +1,2 @@ +CONFIG_MMC_SDHI_PRE_REQ=y +CONFIG_MMC_SDHI_SEQ=y diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg new file mode 100644 index 00000000..e053969e --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg @@ -0,0 +1,87 @@ +CONFIG_CAN=y +CONFIG_CAN_PEAK_USB=y +CONFIG_CAN_BCM=y +CONFIG_CAN_RAW=y +CONFIG_CAN_DEV=y +CONFIG_CAN_CALC_BITTIMING=y +CONFIG_CAN_RCAR=y +CONFIG_CAN_RCAR_CANFD=y +CONFIG_CAN_MCP251X=y +CONFIG_DUMMY=y +CONFIG_EXTRA_FIRMWARE="r8a779x_usb3_v2.dlmem r8a779x_usb3_v3.dlmem" +CONFIG_EXTRA_FIRMWARE_DIR="firmware" +CONFIG_SATA_ACARD_AHCI=y +CONFIG_FIXED_PHY=y +CONFIG_SPI_BITBANG=y +CONFIG_SPI_GPIO=y +CONFIG_GPIO_MAX732X=y +CONFIG_GPIO_MAX732X_IRQ=y +CONFIG_GPIO_PCA953X=y +CONFIG_GPIO_PCA953X_IRQ=y +CONFIG_VIDEO_ADV_DEBUG=y +CONFIG_VIDEO_RCAR_VIN_LEGACY=y +CONFIG_VIDEO_RCAR_CSI2_LEGACY=y +# CONFIG_VIDEO_RCAR_VIN is not set +# CONFIG_VIDEO_RCAR_CSI2 is not set +CONFIG_SOC_CAMERA=y +CONFIG_SOC_CAMERA_SCALE_CROP=y +CONFIG_SOC_CAMERA_PLATFORM=y +CONFIG_SOC_CAMERA_MAX9286=y +CONFIG_SOC_CAMERA_TI9X4=y +CONFIG_SOC_CAMERA_OV106XX=y +CONFIG_SOC_CAMERA_OV5647=y +CONFIG_SOC_CAMERA_OV5642=y +CONFIG_SOC_CAMERA_IMX219=y +CONFIG_VIRTIO_RCAR_PCIE=y +CONFIG_BT=y +CONFIG_BT_BNEP=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_HIDP=m +CONFIG_TI_ST=m +CONFIG_BT_WILINK=m +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_CFG80211_WEXT=y +CONFIG_MAC80211=y +CONFIG_WLAN=y +CONFIG_WL18XX=m +CONFIG_WLCORE=m +CONFIG_WLCORE_SDIO=m +CONFIG_SND_SOC_SI468X=y +CONFIG_SND_SOC_PCM3168A=y +CONFIG_SND_SOC_PCM3168A_I2C=y +CONFIG_SND_SOC_WL18XX=y +CONFIG_INPUT_POLLDEV=y +CONFIG_KEYBOARD_GPIO_POLLED=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_PROPERTIES=y +CONFIG_HID_MULTITOUCH=y +CONFIG_IIO=y +CONFIG_IIO_BUFFER=y +CONFIG_IIO_BUFFER_CB=y +CONFIG_IIO_KFIFO_BUF=y +CONFIG_IIO_TRIGGERED_BUFFER=y +CONFIG_IIO_TRIGGER=y +CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 +CONFIG_LSM9DS0=m +CONFIG_DRM_I2C_ADV7511=y +CONFIG_TOUCHSCREEN_EDT_FT5X06=y +CONFIG_SERIAL_SH_SCI_DMA=y +CONFIG_STAGING=y +CONFIG_MOST=y +CONFIG_MOSTCORE=y +CONFIG_AIM_CDEV=y +CONFIG_AIM_NETWORK=y +CONFIG_AIM_SOUND=y +CONFIG_AIM_V4L2=y +CONFIG_HDM_DIM2=y +CONFIG_UIO=y +CONFIG_SENSORS_EMC2103=y +CONFIG_PMBUS=y +CONFIG_RTC_DRV_DS1307=y +CONFIG_RTC_DRV_DS1307_HWMON=y +CONFIG_SENSORS_LM63=y +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_RAID0=y +CONFIG_GPIO_SYSFS=y diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3hsk.cfg b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3hsk.cfg new file mode 100644 index 00000000..c633e9ed --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3hsk.cfg @@ -0,0 +1,43 @@ +CONFIG_ARCH_R8A77980=y +CONFIG_CAN=y +CONFIG_CAN_PEAK_USB=y +CONFIG_CAN_BCM=y +CONFIG_CAN_RAW=y +CONFIG_CAN_DEV=y +CONFIG_CAN_CALC_BITTIMING=y +CONFIG_CAN_RCAR=y +CONFIG_CAN_RCAR_CANFD=y +CONFIG_DUMMY=y +CONFIG_DRM_I2C_ADV7511=y +CONFIG_GPIO_MAX732X=y +CONFIG_GPIO_MAX732X_IRQ=y +CONFIG_GPIO_PCA953X=y +CONFIG_GPIO_PCA953X_IRQ=y +CONFIG_VIDEO_ADV_DEBUG=y +CONFIG_VIDEO_RCAR_VIN_LEGACY=y +CONFIG_VIDEO_RCAR_CSI2_LEGACY=y +# CONFIG_VIDEO_RCAR_VIN is not set +# CONFIG_VIDEO_RCAR_CSI2 is not set +CONFIG_SOC_CAMERA=y +CONFIG_SOC_CAMERA_SCALE_CROP=y +CONFIG_SOC_CAMERA_PLATFORM=y +CONFIG_SOC_CAMERA_MAX9286=y +CONFIG_SOC_CAMERA_TI9X4=y +CONFIG_SOC_CAMERA_OV106XX=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_INPUT_UINPUT=y +CONFIG_TOUCHSCREEN_PROPERTIES=y +CONFIG_HID_MULTITOUCH=y +CONFIG_SERIAL_SH_SCI_DMA=y +CONFIG_UIO=y +CONFIG_UIO_PDRV_GENIRQ=m +CONFIG_SPI_SLAVE=y +CONFIG_SPI_SLAVE_TIME=y +CONFIG_SPI_SLAVE_SYSTEM_CONTROL=y +CONFIG_SENSORS_LM63=y +CONFIG_SH_ETH=y +CONFIG_SATA_ACARD_AHCI=y +CONFIG_GPIO_SYSFS=y +CONFIG_DRM_THINE_THC63LVD1024=y +CONFIG_MCP4725=y +CONFIG_PHY_RCAR_GEN3_PCIE=y diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg new file mode 100644 index 00000000..3a4e283b --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg @@ -0,0 +1,39 @@ +CONFIG_ARCH_R8A77970=y +CONFIG_CAN=y +CONFIG_CAN_PEAK_USB=y +CONFIG_CAN_BCM=y +CONFIG_CAN_RAW=y +CONFIG_CAN_DEV=y +CONFIG_CAN_CALC_BITTIMING=y +CONFIG_CAN_RCAR=y +CONFIG_CAN_RCAR_CANFD=y +CONFIG_DUMMY=y +CONFIG_DRM_I2C_ADV7511=y +CONFIG_GPIO_MAX732X=y +CONFIG_GPIO_MAX732X_IRQ=y +CONFIG_GPIO_PCA953X=y +CONFIG_GPIO_PCA953X_IRQ=y +CONFIG_VIDEO_ADV_DEBUG=y +CONFIG_VIDEO_RCAR_VIN_LEGACY=y +CONFIG_VIDEO_RCAR_CSI2_LEGACY=y +# CONFIG_VIDEO_RCAR_VIN is not set +# CONFIG_VIDEO_RCAR_CSI2 is not set +CONFIG_SOC_CAMERA=y +CONFIG_SOC_CAMERA_SCALE_CROP=y +CONFIG_SOC_CAMERA_PLATFORM=y +CONFIG_SOC_CAMERA_MAX9286=y +CONFIG_SOC_CAMERA_TI9X4=y +CONFIG_SOC_CAMERA_OV106XX=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_INPUT_UINPUT=y +CONFIG_TOUCHSCREEN_PROPERTIES=y +CONFIG_HID_MULTITOUCH=y +CONFIG_SERIAL_SH_SCI_DMA=y +CONFIG_UIO=y +CONFIG_SPI_SLAVE=y +CONFIG_SPI_SLAVE_TIME=y +CONFIG_SPI_SLAVE_SYSTEM_CONTROL=y +CONFIG_SENSORS_LM63=y +CONFIG_RCAR_THERMAL=y +CONFIG_GPIO_SYSFS=y +CONFIG_DRM_THINE_THC63LVD1024=y diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3mzf.cfg b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3mzf.cfg new file mode 100644 index 00000000..84efece5 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3mzf.cfg @@ -0,0 +1,25 @@ +CONFIG_ARCH_R8A77970=y +CONFIG_CAN=y +CONFIG_CAN_BCM=y +CONFIG_CAN_RAW=y +CONFIG_CAN_DEV=y +CONFIG_CAN_CALC_BITTIMING=y +CONFIG_CAN_RCAR=y +CONFIG_CAN_RCAR_CANFD=y +CONFIG_DUMMY=y +CONFIG_VIDEO_ADV_DEBUG=y +CONFIG_VIDEO_RCAR_VIN_LEGACY=y +CONFIG_VIDEO_RCAR_CSI2_LEGACY=y +# CONFIG_VIDEO_RCAR_VIN is not set +# CONFIG_VIDEO_RCAR_CSI2 is not set +CONFIG_SOC_CAMERA=y +CONFIG_SOC_CAMERA_SCALE_CROP=y +CONFIG_SOC_CAMERA_PLATFORM=y +CONFIG_SOC_CAMERA_TI9X4=y +CONFIG_SOC_CAMERA_OV106XX=y +CONFIG_SERIAL_SH_SCI_DMA=y +CONFIG_SPI_SLAVE=y +CONFIG_SPI_SLAVE_TIME=y +CONFIG_SPI_SLAVE_SYSTEM_CONTROL=y +CONFIG_RCAR_THERMAL=y +CONFIG_GPIO_SYSFS=y diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.14.bbappend b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.14.bbappend new file mode 100644 index 00000000..5473336d --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.14.bbappend @@ -0,0 +1,134 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" + +COMPATIBLE_MACHINE_eagle = "eagle" +COMPATIBLE_MACHINE_v3msk = "v3msk" +COMPATIBLE_MACHINE_condor = "condor" +COMPATIBLE_MACHINE_v3mzf = "v3mzf" +COMPATIBLE_MACHINE_v3hsk = "v3hsk" + +SRC_URI_append = " \ + ${@bb.utils.contains('MACHINE_FEATURES', 'h3ulcb-had', ' file://hyperflash.cfg', '', d)} \ + ${@oe.utils.conditional("SDHI_SEQ", "1", " file://sdhi_seq.cfg", "", d)} \ + file://nvme.cfg \ + file://imr.cfg \ + file://disable-unused.cfg \ + file://renesas.scc \ + ${@oe.utils.conditional("KF_ENABLE_SD3", "1", " file://0047-arm64-dts-renesas-ulcb-kf-enable-sd3.patch", "", d)} \ + ${@oe.utils.conditional("KF_ENABLE_MOST", "1", " file://0048-arm64-dts-renesas-ulcb-kf-enable-most.patch", "", d)} \ + ${@oe.utils.conditional("KF_ENABLE_IMX219", "1", " file://0115-arm64-dts-renesas-ulcb-kf-enable-enable-IMX219.patch", "", d)} \ + ${@oe.utils.conditional("KF_PANEL_MODEL", "TX31D200VM0BAA", " file://0121-arm64-dts-renesas-ulcb-kf-Set-KOE-TX31D200VM0BAA-128.patch", "", d)} \ + ${@oe.utils.conditional("KF_PANEL_MODEL", "AA104XD12", " file://0121-arm64-dts-renesas-ulcb-kf-Set-Mitsubishi-AA104XD12-1.patch", "", d)} \ + ${@oe.utils.conditional("KF_PANEL_MODEL", "AA121TD01", " file://0121-arm64-dts-renesas-ulcb-kf-Set-Mitsubishi-AA121TD01-1.patch", "", d)} \ + ${@oe.utils.conditional("VB_ENABLE_FDPLINK", "1", " file://0391-arm64-dts-renesas-Enable-FDPLink-output-on-V3x-Video.patch", "", d)} \ +" + +SRC_URI_append_h3ulcb = " file://ulcb.cfg" +SRC_URI_append_m3ulcb = " file://ulcb.cfg" +SRC_URI_append_m3nulcb = " file://ulcb.cfg" +SRC_URI_append_salvator-x = " file://salvator-x.cfg" +SRC_URI_append_eagle = " file://eagle.cfg" +SRC_URI_append_v3msk = " file://v3msk.cfg" +SRC_URI_append_condor = " file://condor.cfg" +SRC_URI_append_v3mzf = " file://v3mzf.cfg" +SRC_URI_append_v3hsk = " file://v3hsk.cfg" + +SRC_URI_append_rcar-gen3-v3x = " \ + file://cma.cfg \ + file://qspi.cfg \ +" + +KERNEL_DEVICETREE_append_h3ulcb = " \ + renesas/r8a7795-es1-h3ulcb-view.dtb \ + renesas/r8a7795-es1-h3ulcb-had-alfa.dtb \ + renesas/r8a7795-es1-h3ulcb-had-beta.dtb \ + renesas/r8a7795-es1-h3ulcb-kf.dtb \ + renesas/r8a7795-es1-h3ulcb-vb.dtb \ + renesas/r8a7795-es1-h3ulcb-vb2.dtb \ + renesas/r8a7795-es1-h3ulcb-vbm.dtb \ + renesas/r8a7795-h3ulcb-view.dtb \ + renesas/r8a7795-h3ulcb-had-alfa.dtb \ + renesas/r8a7795-h3ulcb-had-beta.dtb \ + renesas/r8a7795-h3ulcb-kf.dtb \ + renesas/r8a7795-h3ulcb-4x2g-kf.dtb \ + renesas/r8a7795-h3ulcb-vb.dtb \ + renesas/r8a7795-h3ulcb-vb2.dtb \ + renesas/r8a7795-h3ulcb-vb2.1.dtb \ + renesas/r8a7795-h3ulcb-vbm.dtb \ + renesas/r8a7795-h3ulcb-4x2g-vb.dtb \ + renesas/r8a7795-h3ulcb-4x2g-vb2.dtb \ + renesas/r8a7795-h3ulcb-4x2g-vb2.1.dtb \ + renesas/r8a7795-h3ulcb-4x2g-vbm.dtb \ +" + +KERNEL_DEVICETREE_append_m3ulcb = " \ + renesas/r8a7796-m3ulcb-view.dtb \ + renesas/r8a7796-m3ulcb-kf.dtb \ +" + +KERNEL_DEVICETREE_append_m3nulcb = " \ + renesas/r8a77965-m3nulcb-kf.dtb \ +" + +KERNEL_DEVICETREE_append_salvator-x = " \ + renesas/r8a7795-es1-salvator-x-view.dtb \ + renesas/r8a7795-salvator-x-view.dtb \ + renesas/r8a7796-salvator-x-view.dtb \ +" + +KERNEL_DEVICETREE_append_eagle = " \ + renesas/r8a77970-es1-eagle.dtb \ + renesas/r8a77970-es1-eagle-function.dtb \ + renesas/r8a77970-eagle.dtb \ + renesas/r8a77970-eagle-function.dtb \ +" + +KERNEL_DEVICETREE_append_v3msk = " \ + renesas/r8a77970-es1-v3msk.dtb \ + renesas/r8a77970-es1-v3msk-kf.dtb \ + renesas/r8a77970-es1-v3msk-vbm.dtb \ + renesas/r8a77970-es1-v3msk-vbm-v2.dtb \ + renesas/r8a77970-es1-v3msk-vbm-v3.dtb \ + renesas/r8a77970-es1-v3msk-view.dtb \ + renesas/r8a77970-v3msk.dtb \ + renesas/r8a77970-v3msk-kf.dtb \ + renesas/r8a77970-v3msk-vbm.dtb \ + renesas/r8a77970-v3msk-vbm-v2.dtb \ + renesas/r8a77970-v3msk-vbm-v3.dtb \ + renesas/r8a77970-v3msk-view.dtb \ +" + +KERNEL_DEVICETREE_append_v3mzf = " \ + renesas/r8a77970-v3mzf.dtb \ +" + +KERNEL_DEVICETREE_append_condor = " \ + renesas/r8a77980-condor.dtb \ +" + +KERNEL_DEVICETREE_append_v3hsk = " \ + renesas/r8a77980-v3hsk.dtb \ + renesas/r8a77980-v3hsk-vbm.dtb \ + renesas/r8a77980-v3hsk-vbm-v2.dtb \ + renesas/r8a77980-v3hsk-vbm-v3.dtb \ + renesas/r8a77980-v3hsk-vb-4ch.dtb \ + renesas/r8a77980-v3hsk-vb-8ch.dtb \ +" +# Prefer V4L2 rcar_imr driver over UIO uio_imr +KERNEL_MODULE_AUTOLOAD_append = " rcar_imr" +KERNEL_MODULE_PROBECONF_append = " rcar_imr" +KERNEL_MODULE_PROBECONF_append = " uio_imr" +module_conf_uio_imr = 'blacklist uio_imr' + +# V3H VIP devices +KERNEL_MODULE_AUTOLOAD_append_r8a77980 = " uio_pdrv_genirq" +KERNEL_MODULE_PROBECONF_append_r8a77980 = " uio_pdrv_genirq" +module_conf_uio_pdrv_genirq_r8a77980 = 'options uio_pdrv_genirq of_id="generic-uio"' + +# Install RCAR Gen3 specific UAPI headers +do_install_append_rcar-gen3() { + install -d ${D}/usr/include/linux/ + install -m 0644 ${STAGING_KERNEL_DIR}/include/uapi/linux/rcar-imr.h ${D}/usr/include/linux/ +} + +PACKAGES += "${PN}-uapi" +FILES_${PN}-uapi = "/usr/include" -- cgit 1.2.3-korg