mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-11 13:27:06 +09:00
Merge commit '116680b9cb8013a29acdd4589e8c3260eef0dee9'
* commit '116680b9cb8013a29acdd4589e8c3260eef0dee9': (55 commits) video: rockchip: mpp: fix JPEG Enc dma sync problem arm64: rockchip_gki.config: enable icm4260x sensor. arm64: rockchip_defconfig: enable icm4260x sensor. video: rockchip: vtunnel: fix compile errors on android 14 fiq_debugger: set uart irq no balancing PCI: rockchip: dw: remove .link_up() hook from struct dw_pcie_ops media: i2c: add cam-tb-setup input: sensors: add icm4260x driver. arm64: dts: rockchip: rk3588s-evb3: disable gt1x in bt1120 display board dmaengine: pl330: Add support for interleaved transfer arm64: dts: rockchip: rk3568-evb: fix gc8034 power domain config media: i2c: lt6911uxc: add 4K60 dual mipi port support PCI: rockchip: dw: remove .link_up() hook from struct dw_pcie_ops regulator: rk806: delete the PLDO6 enable/disable interface mfd: rkx110_x120: change panel device and driver name arm64: dts: rockchip: remove androidboot bootargs for px30/rk3326 boards video: rockchip: rga2: add hardware time-consuming printing media: i2c: gc2093: get camera param from cam-tb-setup media: i2c: add cam-tb-setup input: sensors: add icm4260x driver. ... Change-Id: I7267d5874c2c6edfb0e7a55db19905270f08c9cc
This commit is contained in:
@@ -222,6 +222,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb1-lp4-v10-linux.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb1-lp4-v10-linux-amp.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb1-lp4-v10-linux-ipc.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb1-lp4-v10-lt6911uxe.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb1-lp4-v10-lt6911uxc-dual-mipi.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb1-lp4-v10-rk628-hdmi2csi.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb2-lp4-v10.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb2-lp4-v10-edp.dtb
|
||||
|
||||
@@ -13,10 +13,6 @@
|
||||
compatible = "rockchip,px30-evb-ddr3-v10-avb", "rockchip,px30";
|
||||
};
|
||||
|
||||
&chosen {
|
||||
bootargs_ext = "androidboot.boot_devices=ff390000.dwmmc,ff3b0000.nandc";
|
||||
};
|
||||
|
||||
&dsi {
|
||||
status = "okay";
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart1_xfer>;
|
||||
status = "okay";
|
||||
amp-cpu-aff-maskbits = <0x0 0x1 0x1 0x2 0x2 0x4 0x3 0x8>;
|
||||
amp-irqs = <GIC_AMP_IRQ_CFG_ROUTE(51, 0xd0, CPU_GET_AFFINITY(3, 0))>;
|
||||
amp-cpu-aff-maskbits = /bits/ 64 <0x0 0x1 0x1 0x2 0x2 0x4 0x3 0x8>;
|
||||
amp-irqs = /bits/ 64 <GIC_AMP_IRQ_CFG_ROUTE(51, 0xd0, CPU_GET_AFFINITY(3, 0))>;
|
||||
};
|
||||
|
||||
reserved-memory {
|
||||
|
||||
@@ -11,10 +11,6 @@
|
||||
compatible = "rockchip,rk3326-863-lp3-v10-rkisp1", "rockchip,rk3326";
|
||||
};
|
||||
|
||||
&chosen {
|
||||
bootargs_ext = "androidboot.boot_devices=ff390000.dwmmc,ff3b0000.nandc";
|
||||
};
|
||||
|
||||
&i2c2 {
|
||||
status = "okay";
|
||||
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart7m1_xfer>;
|
||||
|
||||
amp-cpu-aff-maskbits = <0x0 0x1 0x1 0x2 0x2 0x4 0x3 0x8>;
|
||||
amp-irqs = <GIC_AMP_IRQ_CFG_ROUTE(81, 0xd0, CPU_GET_AFFINITY(3, 0))>;
|
||||
amp-cpu-aff-maskbits = /bits/ 64 <0x0 0x1 0x1 0x2 0x2 0x4 0x3 0x8>;
|
||||
amp-irqs = /bits/ 64 <GIC_AMP_IRQ_CFG_ROUTE(81, 0xd0, CPU_GET_AFFINITY(3, 0))>;
|
||||
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@@ -273,6 +273,7 @@
|
||||
clock-names = "xvclk";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&cif_clk>;
|
||||
power-domains = <&power RK3568_PD_VI>;
|
||||
reset-gpios = <&gpio3 RK_PB6 GPIO_ACTIVE_LOW>;
|
||||
pwdn-gpios = <&gpio4 RK_PB4 GPIO_ACTIVE_LOW>;
|
||||
rockchip,grf = <&grf>;
|
||||
|
||||
@@ -304,6 +304,7 @@
|
||||
clock-names = "xvclk";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&cif_clk>;
|
||||
power-domains = <&power RK3568_PD_VI>;
|
||||
reset-gpios = <&gpio3 RK_PB6 GPIO_ACTIVE_LOW>;
|
||||
pwdn-gpios = <&gpio4 RK_PB4 GPIO_ACTIVE_LOW>;
|
||||
rockchip,grf = <&grf>;
|
||||
|
||||
@@ -0,0 +1,326 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2022 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
*/
|
||||
/dts-v1/;
|
||||
|
||||
#include "rk3588-evb1-lp4.dtsi"
|
||||
#include "rk3588-android.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Rockchip RK3588 EVB1 LP4 V10 Board + Rockchip RK3588 EVB V10 Extboard";
|
||||
compatible = "rockchip,rk3588-evb1-lp4-lt6911uxc-dual-mipi", "rockchip,rk3588";
|
||||
|
||||
vcc_mipicsi0: vcc-mipicsi0-regulator {
|
||||
compatible = "regulator-fixed";
|
||||
gpio = <&gpio1 RK_PB1 GPIO_ACTIVE_HIGH>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&mipicsi0_pwr>;
|
||||
regulator-name = "vcc_mipicsi0";
|
||||
enable-active-high;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
vcc_mipidcphy0: vcc-mipidcphy0-regulator {
|
||||
compatible = "regulator-fixed";
|
||||
gpio = <&gpio2 RK_PC4 GPIO_ACTIVE_HIGH>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&mipidcphy0_pwr>;
|
||||
regulator-name = "vcc_mipidcphy0";
|
||||
enable-active-high;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
ext_cam_clk: external-camera-clock {
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <24000000>;
|
||||
clock-output-names = "CLK_CAMERA_24MHZ";
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
&csi2_dphy0_hw {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&csi2_dphy1_hw {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&csi2_dphy0 {
|
||||
status = "okay";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
hdmi_mipi_in: endpoint@1 {
|
||||
reg = <1>;
|
||||
remote-endpoint = <<6911uxc_out0>;
|
||||
data-lanes = <1 2 3 4>;
|
||||
};
|
||||
};
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
csidphy0_out: endpoint@0 {
|
||||
reg = <0>;
|
||||
remote-endpoint = <&mipi2_csi2_input>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&csi2_dphy1 {
|
||||
status = "okay";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
hdmi_mipi_in1: endpoint@1 {
|
||||
reg = <1>;
|
||||
remote-endpoint = <<6911uxc_out1>;
|
||||
data-lanes = <1 2 3 4>;
|
||||
};
|
||||
};
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
csidphy1_out: endpoint@0 {
|
||||
reg = <0>;
|
||||
remote-endpoint = <&mipi0_csi2_input>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&i2c3 {
|
||||
status = "okay";
|
||||
|
||||
lt6911uxc: lt6911uxc@2b {
|
||||
compatible = "lontium,lt6911uxc";
|
||||
status = "okay";
|
||||
reg = <0x2b>;
|
||||
clocks = <&ext_cam_clk>;
|
||||
clock-names = "xvclk";
|
||||
power-domains = <&power RK3588_PD_VI>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <<6911uxc_pin_1>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <RK_PB3 IRQ_TYPE_LEVEL_LOW>;
|
||||
// reset-gpios = <&gpio1 RK_PB1 GPIO_ACTIVE_LOW>;
|
||||
// power-gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_HIGH>;
|
||||
plugin-det-gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_HIGH>;
|
||||
rockchip,camera-module-index = <0>;
|
||||
rockchip,camera-module-facing = "back";
|
||||
rockchip,camera-module-name = "HDMI-MIPI2";
|
||||
rockchip,camera-module-lens-name = "LT6911UXC-2";
|
||||
|
||||
multi-dev-info {
|
||||
dev-idx-l = <4>;
|
||||
dev-idx-r = <2>;
|
||||
combine-idx = <2>;
|
||||
pixel-offset = <0>;
|
||||
dev-num = <2>;
|
||||
};
|
||||
|
||||
port {
|
||||
lt6911uxc_out0: endpoint {
|
||||
remote-endpoint = <&hdmi_mipi_in>;
|
||||
data-lanes = <1 2 3 4>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&i2c5 {
|
||||
status = "okay";
|
||||
|
||||
lt6911uxc_1: lt6911uxc_1@2b {
|
||||
compatible = "lontium,lt6911uxc";
|
||||
status = "okay";
|
||||
reg = <0x2b>;
|
||||
clocks = <&ext_cam_clk>;
|
||||
clock-names = "xvclk";
|
||||
power-domains = <&power RK3588_PD_VI>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <<6911uxc_pin>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <RK_PA0 IRQ_TYPE_LEVEL_LOW>;
|
||||
// reset-gpios = <&gpio1 RK_PB1 GPIO_ACTIVE_LOW>;
|
||||
// power-gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_HIGH>;
|
||||
// plugin-det-gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>;
|
||||
plugin-det-gpios = <&gpio1 RK_PA1 GPIO_ACTIVE_HIGH>;
|
||||
rockchip,camera-module-index = <1>;
|
||||
rockchip,camera-module-facing = "front";
|
||||
rockchip,camera-module-name = "HDMI-MIPI0";
|
||||
rockchip,camera-module-lens-name = "LT6911UXC-1";
|
||||
|
||||
multi-dev-info {
|
||||
dev-idx-l = <1>;
|
||||
dev-idx-r = <0>;
|
||||
combine-idx = <0>;
|
||||
pixel-offset = <0>;
|
||||
dev-num = <2>;
|
||||
};
|
||||
|
||||
port {
|
||||
lt6911uxc_out1: endpoint {
|
||||
remote-endpoint = <&hdmi_mipi_in1>;
|
||||
data-lanes = <1 2 3 4>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&mipi_dcphy0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mipi_dcphy1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mipi0_csi2_hw {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mipi1_csi2_hw {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mipi2_csi2_hw {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mipi3_csi2_hw {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mipi4_csi2_hw {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mipi5_csi2_hw {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mipi0_csi2 {
|
||||
status = "okay";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
mipi0_csi2_input: endpoint@1 {
|
||||
reg = <1>;
|
||||
remote-endpoint = <&csidphy1_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
mipi0_csi2_output: endpoint@0 {
|
||||
reg = <0>;
|
||||
remote-endpoint = <&cif_mipi_in0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&mipi2_csi2 {
|
||||
status = "okay";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
mipi2_csi2_input: endpoint@1 {
|
||||
reg = <1>;
|
||||
remote-endpoint = <&csidphy0_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
mipi2_csi2_output: endpoint@0 {
|
||||
reg = <0>;
|
||||
remote-endpoint = <&cif_mipi_in2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&rkcif_mipi_lvds {
|
||||
status = "okay";
|
||||
|
||||
port {
|
||||
cif_mipi_in0: endpoint {
|
||||
remote-endpoint = <&mipi0_csi2_output>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&rkcif_mipi_lvds2 {
|
||||
status = "okay";
|
||||
|
||||
port {
|
||||
cif_mipi_in2: endpoint {
|
||||
remote-endpoint = <&mipi2_csi2_output>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&rkcif {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&rkcif_mmu {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&pinctrl {
|
||||
hdmiin {
|
||||
lt6911uxc_pin: lt6911uxc-pin {
|
||||
rockchip,pins = <1 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>,
|
||||
<1 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
};
|
||||
|
||||
lt6911uxc_pin_1: lt6911uxc-pin-1 {
|
||||
rockchip,pins = <1 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>,
|
||||
<1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -12,6 +12,42 @@
|
||||
clock-frequency = <25000000>;
|
||||
clock-output-names = "max96712-dcphy0-osc";
|
||||
};
|
||||
|
||||
max96712_dcphy0_vcc1v2: max96712-dcphy0-vcc1v2 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "max96712_dcphy0_vcc1v2";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <1200000>;
|
||||
startup-delay-us = <850>;
|
||||
vin-supply = <&vcc5v0_sys>;
|
||||
};
|
||||
|
||||
max96712_dcphy0_vcc1v8: max96712-dcphy0-vcc1v8 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "max96712_dcphy0_vcc1v8";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
startup-delay-us = <200>;
|
||||
vin-supply = <&vcc_3v3_s3>;
|
||||
};
|
||||
|
||||
max96712_dcphy0_poc: max96712-dcphy0-poc {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "max96712_dcphy0_poc";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-min-microvolt = <12000000>;
|
||||
regulator-max-microvolt = <12000000>;
|
||||
enable-active-high;
|
||||
gpio = <&gpio3 RK_PA6 GPIO_ACTIVE_HIGH>;
|
||||
startup-delay-us = <1050>;
|
||||
off-on-delay-us = <515000>;
|
||||
vin-supply = <&vcc12v_dcin>;
|
||||
};
|
||||
};
|
||||
|
||||
&mipi_dcphy0 {
|
||||
@@ -64,8 +100,10 @@
|
||||
power-domains = <&power RK3588_PD_VI>;
|
||||
rockchip,grf = <&sys_grf>;
|
||||
pwdn-gpios = <&gpio4 RK_PA4 GPIO_ACTIVE_HIGH>;
|
||||
pocen-gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_HIGH>;
|
||||
lock-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>;
|
||||
vcc1v2-supply = <&max96712_dcphy0_vcc1v2>;
|
||||
vcc1v8-supply = <&max96712_dcphy0_vcc1v8>;
|
||||
poc-supply = <&max96712_dcphy0_poc>;
|
||||
|
||||
rockchip,camera-module-index = <0>;
|
||||
rockchip,camera-module-facing = "back";
|
||||
|
||||
@@ -12,6 +12,42 @@
|
||||
clock-frequency = <25000000>;
|
||||
clock-output-names = "max96712-dcphy1-osc";
|
||||
};
|
||||
|
||||
max96712_dcphy1_vcc1v2: max96712-dcphy1-vcc1v2 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "max96712_dcphy1_vcc1v2";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <1200000>;
|
||||
startup-delay-us = <850>;
|
||||
vin-supply = <&vcc5v0_sys>;
|
||||
};
|
||||
|
||||
max96712_dcphy1_vcc1v8: max96712-dcphy1-vcc1v8 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "max96712_dcphy1_vcc1v8";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
startup-delay-us = <200>;
|
||||
vin-supply = <&vcc_3v3_s3>;
|
||||
};
|
||||
|
||||
max96712_dcphy1_poc: max96712-dcphy1-poc {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "max96712_dcphy1_poc";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-min-microvolt = <12000000>;
|
||||
regulator-max-microvolt = <12000000>;
|
||||
enable-active-high;
|
||||
gpio = <&gpio3 RK_PA7 GPIO_ACTIVE_HIGH>;
|
||||
startup-delay-us = <1050>;
|
||||
off-on-delay-us = <515000>;
|
||||
vin-supply = <&vcc12v_dcin>;
|
||||
};
|
||||
};
|
||||
|
||||
&mipi_dcphy1 {
|
||||
@@ -64,8 +100,10 @@
|
||||
power-domains = <&power RK3588_PD_VI>;
|
||||
rockchip,grf = <&sys_grf>;
|
||||
pwdn-gpios = <&gpio4 RK_PD1 GPIO_ACTIVE_HIGH>;
|
||||
pocen-gpios = <&gpio3 RK_PA7 GPIO_ACTIVE_HIGH>;
|
||||
lock-gpios = <&gpio4 RK_PD3 GPIO_ACTIVE_HIGH>;
|
||||
vcc1v2-supply = <&max96712_dcphy1_vcc1v2>;
|
||||
vcc1v8-supply = <&max96712_dcphy1_vcc1v8>;
|
||||
poc-supply = <&max96712_dcphy1_poc>;
|
||||
|
||||
rockchip,camera-module-index = <0>;
|
||||
rockchip,camera-module-facing = "back";
|
||||
|
||||
@@ -12,6 +12,42 @@
|
||||
clock-frequency = <25000000>;
|
||||
clock-output-names = "max96712-dphy0-osc0";
|
||||
};
|
||||
|
||||
max96712_dphy0_vcc1v2: max96712-dphy0-vcc1v2 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "max96712_dphy0_vcc1v2";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <1200000>;
|
||||
startup-delay-us = <850>;
|
||||
vin-supply = <&vcc5v0_sys>;
|
||||
};
|
||||
|
||||
max96712_dphy0_vcc1v8: max96712-dphy0-vcc1v8 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "max96712_dphy0_vcc1v8";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
startup-delay-us = <200>;
|
||||
vin-supply = <&vcc_3v3_s3>;
|
||||
};
|
||||
|
||||
max96712_dphy0_poc: max96712-dphy0-poc {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "max96712_dphy0_poc";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-min-microvolt = <12000000>;
|
||||
regulator-max-microvolt = <12000000>;
|
||||
enable-active-high;
|
||||
gpio = <&gpio3 RK_PB0 GPIO_ACTIVE_HIGH>;
|
||||
startup-delay-us = <1050>;
|
||||
off-on-delay-us = <515000>;
|
||||
vin-supply = <&vcc12v_dcin>;
|
||||
};
|
||||
};
|
||||
|
||||
&csi2_dphy0_hw {
|
||||
@@ -64,8 +100,10 @@
|
||||
power-domains = <&power RK3588_PD_VI>;
|
||||
rockchip,grf = <&sys_grf>;
|
||||
pwdn-gpios = <&gpio1 RK_PB2 GPIO_ACTIVE_HIGH>;
|
||||
pocen-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_HIGH>;
|
||||
lock-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_HIGH>;
|
||||
vcc1v2-supply = <&max96712_dphy0_vcc1v2>;
|
||||
vcc1v8-supply = <&max96712_dphy0_vcc1v8>;
|
||||
poc-supply = <&max96712_dphy0_poc>;
|
||||
|
||||
rockchip,camera-module-index = <0>;
|
||||
rockchip,camera-module-facing = "back";
|
||||
|
||||
@@ -12,6 +12,41 @@
|
||||
clock-frequency = <25000000>;
|
||||
clock-output-names = "max96712-dphy3-osc0";
|
||||
};
|
||||
|
||||
max96712_dphy3_vcc1v2: max96712-dphy3-vcc1v2 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "max96712_dphy3_vcc1v2";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <1200000>;
|
||||
startup-delay-us = <850>;
|
||||
vin-supply = <&vcc5v0_sys>;
|
||||
};
|
||||
|
||||
max96712_dphy3_vcc1v8: max96712-dphy3-vcc1v8 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "max96712_dphy3_vcc1v8";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
startup-delay-us = <200>;
|
||||
vin-supply = <&vcc_3v3_s3>;
|
||||
};
|
||||
|
||||
max96712_dphy3_poc: max96712-dphy3-poc {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "max96712_dphy3_poc";
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <12000000>;
|
||||
regulator-max-microvolt = <12000000>;
|
||||
enable-active-high;
|
||||
gpio = <&gpio3 RK_PB1 GPIO_ACTIVE_HIGH>;
|
||||
startup-delay-us = <1050>;
|
||||
off-on-delay-us = <515000>;
|
||||
vin-supply = <&vcc12v_dcin>;
|
||||
};
|
||||
};
|
||||
|
||||
&csi2_dphy1_hw {
|
||||
@@ -64,8 +99,10 @@
|
||||
power-domains = <&power RK3588_PD_VI>;
|
||||
rockchip,grf = <&sys_grf>;
|
||||
pwdn-gpios = <&gpio4 RK_PA6 GPIO_ACTIVE_HIGH>;
|
||||
pocen-gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_HIGH>;
|
||||
lock-gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_HIGH>;
|
||||
vcc1v2-supply = <&max96712_dphy3_vcc1v2>;
|
||||
vcc1v8-supply = <&max96712_dphy3_vcc1v8>;
|
||||
poc-supply = <&max96712_dphy3_poc>;
|
||||
|
||||
rockchip,camera-module-index = <0>;
|
||||
rockchip,camera-module-facing = "back";
|
||||
|
||||
@@ -12,6 +12,42 @@
|
||||
clock-frequency = <25000000>;
|
||||
clock-output-names = "max96722-dphy0-osc0";
|
||||
};
|
||||
|
||||
max96722_dphy0_vcc1v2: max96722-dphy0-vcc1v2 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "max96722_dphy0_vcc1v2";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <1200000>;
|
||||
startup-delay-us = <850>;
|
||||
vin-supply = <&vcc5v0_sys>;
|
||||
};
|
||||
|
||||
max96722_dphy0_vcc1v8: max96722-dphy0-vcc1v8 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "max96722_dphy0_vcc1v8";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
startup-delay-us = <200>;
|
||||
vin-supply = <&vcc_3v3_s3>;
|
||||
};
|
||||
|
||||
max96722_dphy0_poc: max96722-dphy0-poc {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "max96722_dphy0_poc";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-min-microvolt = <12000000>;
|
||||
regulator-max-microvolt = <12000000>;
|
||||
enable-active-high;
|
||||
gpio = <&gpio3 RK_PB0 GPIO_ACTIVE_HIGH>;
|
||||
startup-delay-us = <1050>;
|
||||
off-on-delay-us = <515000>;
|
||||
vin-supply = <&vcc12v_dcin>;
|
||||
};
|
||||
};
|
||||
|
||||
&csi2_dphy0_hw {
|
||||
@@ -64,8 +100,10 @@
|
||||
power-domains = <&power RK3588_PD_VI>;
|
||||
rockchip,grf = <&sys_grf>;
|
||||
pwdn-gpios = <&gpio1 RK_PB2 GPIO_ACTIVE_HIGH>;
|
||||
pocen-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_HIGH>;
|
||||
lock-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_HIGH>;
|
||||
vcc1v2-supply = <&max96722_dphy0_vcc1v2>;
|
||||
vcc1v8-supply = <&max96722_dphy0_vcc1v8>;
|
||||
poc-supply = <&max96722_dphy0_poc>;
|
||||
|
||||
rockchip,camera-module-index = <0>;
|
||||
rockchip,camera-module-facing = "back";
|
||||
|
||||
@@ -12,6 +12,42 @@
|
||||
clock-frequency = <25000000>;
|
||||
clock-output-names = "max96722-dphy3-osc0";
|
||||
};
|
||||
|
||||
max96722_dphy3_vcc1v2: max96722-dphy3-vcc1v2 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "max96722_dphy3_vcc1v2";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <1200000>;
|
||||
startup-delay-us = <850>;
|
||||
vin-supply = <&vcc5v0_sys>;
|
||||
};
|
||||
|
||||
max96722_dphy3_vcc1v8: max96722-dphy3-vcc1v8 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "max96722_dphy3_vcc1v8";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
startup-delay-us = <200>;
|
||||
vin-supply = <&vcc_3v3_s3>;
|
||||
};
|
||||
|
||||
max96722_dphy3_poc: max96722-dphy3-poc {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "max96722_dphy3_poc";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-min-microvolt = <12000000>;
|
||||
regulator-max-microvolt = <12000000>;
|
||||
enable-active-high;
|
||||
gpio = <&gpio3 RK_PB1 GPIO_ACTIVE_HIGH>;
|
||||
startup-delay-us = <1050>;
|
||||
off-on-delay-us = <515000>;
|
||||
vin-supply = <&vcc12v_dcin>;
|
||||
};
|
||||
};
|
||||
|
||||
&csi2_dphy1_hw {
|
||||
@@ -64,8 +100,10 @@
|
||||
power-domains = <&power RK3588_PD_VI>;
|
||||
rockchip,grf = <&sys_grf>;
|
||||
pwdn-gpios = <&gpio4 RK_PA6 GPIO_ACTIVE_HIGH>;
|
||||
pocen-gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_HIGH>;
|
||||
lock-gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_HIGH>;
|
||||
vcc1v2-supply = <&max96722_dphy3_vcc1v2>;
|
||||
vcc1v8-supply = <&max96722_dphy3_vcc1v8>;
|
||||
poc-supply = <&max96722_dphy3_poc>;
|
||||
|
||||
rockchip,camera-module-index = <0>;
|
||||
rockchip,camera-module-facing = "back";
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
vin-supply = <&vcc12v_dcin>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&vcc5v0_buck_en>;
|
||||
startup-delay-us = <2500>;
|
||||
off-on-delay-us = <1500>;
|
||||
regulator-state-mem {
|
||||
regulator-on-in-suspend;
|
||||
regulator-suspend-microvolt = <5000000>;
|
||||
@@ -156,6 +158,8 @@
|
||||
regulator-max-microvolt = <12000000>;
|
||||
enable-active-high;
|
||||
gpio = <&i2c5_nca9539_gpio 6 GPIO_ACTIVE_HIGH>;
|
||||
startup-delay-us = <2000>;
|
||||
off-on-delay-us = <16000>;
|
||||
vin-supply = <&vcc12v_dcin>;
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
@@ -172,6 +176,8 @@
|
||||
regulator-max-microvolt = <12000000>;
|
||||
enable-active-high;
|
||||
gpio = <&i2c5_nca9539_gpio 7 GPIO_ACTIVE_HIGH>;
|
||||
startup-delay-us = <2000>;
|
||||
off-on-delay-us = <16000>;
|
||||
vin-supply = <&vcc12v_dcin>;
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
@@ -188,6 +194,8 @@
|
||||
regulator-max-microvolt = <12000000>;
|
||||
enable-active-high;
|
||||
gpio = <&i2c5_nca9539_gpio 8 GPIO_ACTIVE_HIGH>;
|
||||
startup-delay-us = <2000>;
|
||||
off-on-delay-us = <16000>;
|
||||
vin-supply = <&vcc12v_dcin>;
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
@@ -204,6 +212,8 @@
|
||||
regulator-max-microvolt = <12000000>;
|
||||
enable-active-high;
|
||||
gpio = <&i2c5_nca9539_gpio 9 GPIO_ACTIVE_HIGH>;
|
||||
startup-delay-us = <2000>;
|
||||
off-on-delay-us = <16000>;
|
||||
vin-supply = <&vcc12v_dcin>;
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
@@ -220,6 +230,8 @@
|
||||
regulator-max-microvolt = <5000000>;
|
||||
enable-active-high;
|
||||
gpio = <&i2c5_nca9539_gpio 10 GPIO_ACTIVE_HIGH>;
|
||||
startup-delay-us = <2000>;
|
||||
off-on-delay-us = <16000>;
|
||||
vin-supply = <&vcc5v0_usb>;
|
||||
};
|
||||
|
||||
@@ -232,6 +244,8 @@
|
||||
regulator-max-microvolt = <5000000>;
|
||||
enable-active-high;
|
||||
gpio = <&i2c5_nca9539_gpio 11 GPIO_ACTIVE_HIGH>;
|
||||
startup-delay-us = <2000>;
|
||||
off-on-delay-us = <16000>;
|
||||
vin-supply = <&vcc5v0_usb>;
|
||||
};
|
||||
|
||||
@@ -329,6 +343,14 @@
|
||||
};
|
||||
};
|
||||
|
||||
&max96712_dphy3_vcc1v2 {
|
||||
vin-supply = <&vcc5v0_buck>;
|
||||
};
|
||||
|
||||
&max96712_dphy3_poc {
|
||||
vin-supply = <&camera1_vcc12v_buck>;
|
||||
};
|
||||
|
||||
&avdd1v8_ddr_pll_s0 {
|
||||
regulator-state-mem {
|
||||
regulator-on-in-suspend;
|
||||
|
||||
@@ -19,6 +19,13 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
/*
|
||||
* The pins of gt1x and sii9022 are multiplexed
|
||||
*/
|
||||
>1x {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&i2c4 {
|
||||
clock-frequency = <400000>;
|
||||
status = "okay";
|
||||
@@ -32,6 +39,10 @@
|
||||
interrupts = <RK_PC0 IRQ_TYPE_LEVEL_HIGH>;
|
||||
reset-gpio = <&gpio1 RK_PA7 GPIO_ACTIVE_LOW>;
|
||||
enable-gpio = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>;
|
||||
/*
|
||||
* MEDIA_BUS_FMT_UYVY8_1X16 for bt1120
|
||||
* MEDIA_BUS_FMT_UYVY8_2X8 for bt656
|
||||
*/
|
||||
bus-format = <MEDIA_BUS_FMT_UYVY8_1X16>;
|
||||
|
||||
ports {
|
||||
@@ -60,6 +71,10 @@
|
||||
&rgb {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
/*
|
||||
* <&bt1120_pins> for bt1120
|
||||
* <&bt656_pins> for bt656
|
||||
*/
|
||||
pinctrl-0 = <&bt1120_pins>;
|
||||
|
||||
ports {
|
||||
|
||||
@@ -3019,6 +3019,8 @@
|
||||
interrupts = <GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c0m0_xfer>;
|
||||
resets = <&cru SRST_I2C0>, <&cru SRST_P_I2C0>;
|
||||
reset-names = "i2c", "apb";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
@@ -6004,6 +6006,8 @@
|
||||
interrupts = <GIC_SPI 318 IRQ_TYPE_LEVEL_HIGH>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c1m0_xfer>;
|
||||
resets = <&cru SRST_I2C1>, <&cru SRST_P_I2C1>;
|
||||
reset-names = "i2c", "apb";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
@@ -6017,6 +6021,8 @@
|
||||
interrupts = <GIC_SPI 319 IRQ_TYPE_LEVEL_HIGH>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c2m0_xfer>;
|
||||
resets = <&cru SRST_I2C2>, <&cru SRST_P_I2C2>;
|
||||
reset-names = "i2c", "apb";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
@@ -6030,6 +6036,8 @@
|
||||
interrupts = <GIC_SPI 320 IRQ_TYPE_LEVEL_HIGH>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c3m0_xfer>;
|
||||
resets = <&cru SRST_I2C3>, <&cru SRST_P_I2C3>;
|
||||
reset-names = "i2c", "apb";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
@@ -6043,6 +6051,8 @@
|
||||
interrupts = <GIC_SPI 321 IRQ_TYPE_LEVEL_HIGH>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c4m0_xfer>;
|
||||
resets = <&cru SRST_I2C4>, <&cru SRST_P_I2C4>;
|
||||
reset-names = "i2c", "apb";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
@@ -6056,6 +6066,8 @@
|
||||
interrupts = <GIC_SPI 322 IRQ_TYPE_LEVEL_HIGH>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c5m0_xfer>;
|
||||
resets = <&cru SRST_I2C5>, <&cru SRST_P_I2C5>;
|
||||
reset-names = "i2c", "apb";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
@@ -6483,6 +6495,8 @@
|
||||
interrupts = <GIC_SPI 323 IRQ_TYPE_LEVEL_HIGH>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c6m0_xfer>;
|
||||
resets = <&cru SRST_I2C6>, <&cru SRST_P_I2C6>;
|
||||
reset-names = "i2c", "apb";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
@@ -6496,6 +6510,8 @@
|
||||
interrupts = <GIC_SPI 324 IRQ_TYPE_LEVEL_HIGH>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c7m0_xfer>;
|
||||
resets = <&cru SRST_I2C7>, <&cru SRST_P_I2C7>;
|
||||
reset-names = "i2c", "apb";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
@@ -6509,6 +6525,8 @@
|
||||
interrupts = <GIC_SPI 325 IRQ_TYPE_LEVEL_HIGH>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c8m0_xfer>;
|
||||
resets = <&cru SRST_I2C8>, <&cru SRST_P_I2C8>;
|
||||
reset-names = "i2c", "apb";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
|
||||
@@ -476,6 +476,7 @@ CONFIG_GS_LSM303D=y
|
||||
CONFIG_LSM330_ACC=y
|
||||
CONFIG_BMA2XX_ACC=y
|
||||
CONFIG_GS_DA223=y
|
||||
CONFIG_ICM4260X_ACC=y
|
||||
CONFIG_COMPASS_DEVICE=y
|
||||
CONFIG_COMPASS_AK8975=y
|
||||
CONFIG_COMPASS_AK8963=y
|
||||
@@ -486,6 +487,7 @@ CONFIG_GYRO_EWTSA=y
|
||||
CONFIG_GYRO_MPU6500=y
|
||||
CONFIG_GYRO_MPU6880=y
|
||||
CONFIG_GYRO_LSM330=y
|
||||
CONFIG_GYRO_ICM4260X=y
|
||||
CONFIG_LIGHT_DEVICE=y
|
||||
CONFIG_LS_CM3217=y
|
||||
CONFIG_LS_CM3218=y
|
||||
@@ -521,6 +523,7 @@ CONFIG_SPI_SPIDEV=y
|
||||
CONFIG_PINCTRL_RK805=y
|
||||
CONFIG_PINCTRL_RK806=y
|
||||
CONFIG_GPIO_SYSFS=y
|
||||
CONFIG_GPIO_SYSCON=y
|
||||
CONFIG_POWER_RESET_GPIO=y
|
||||
CONFIG_SYSCON_REBOOT_MODE=y
|
||||
CONFIG_TEST_POWER=y
|
||||
|
||||
@@ -83,6 +83,7 @@ CONFIG_GS_SC7A20=m
|
||||
CONFIG_GS_SC7A30=m
|
||||
CONFIG_GYROSCOPE_DEVICE=m
|
||||
CONFIG_GYRO_EWTSA=m
|
||||
CONFIG_GYRO_ICM4260X=m
|
||||
CONFIG_GYRO_L3G20D=m
|
||||
CONFIG_GYRO_L3G4200D=m
|
||||
CONFIG_GYRO_LSM330=m
|
||||
@@ -137,6 +138,7 @@ CONFIG_I2C_CHARDEV=m
|
||||
CONFIG_I2C_GPIO=m
|
||||
CONFIG_I2C_HID_OF=m
|
||||
CONFIG_I2C_RK3X=m
|
||||
CONFIG_ICM4260X_ACC=m
|
||||
CONFIG_IEP=m
|
||||
CONFIG_IIO_BUFFER_CB=m
|
||||
CONFIG_INPUT_RK805_PWRKEY=m
|
||||
|
||||
@@ -254,6 +254,7 @@ CONFIG_PINCTRL_RK805=y
|
||||
CONFIG_PINCTRL_RK806=y
|
||||
CONFIG_GPIO_SYSFS=y
|
||||
CONFIG_GPIO_GENERIC_PLATFORM=y
|
||||
CONFIG_GPIO_SYSCON=y
|
||||
CONFIG_POWER_RESET_GPIO=y
|
||||
CONFIG_POWER_RESET_GPIO_RESTART=y
|
||||
CONFIG_SYSCON_REBOOT_MODE=y
|
||||
|
||||
@@ -541,11 +541,9 @@ struct dma_pl330_desc {
|
||||
/* For cyclic capability */
|
||||
bool cyclic;
|
||||
size_t num_periods;
|
||||
#ifdef CONFIG_NO_GKI
|
||||
/* interlace size */
|
||||
unsigned int src_interlace_size;
|
||||
unsigned int dst_interlace_size;
|
||||
#endif
|
||||
|
||||
/* interleaved size */
|
||||
struct data_chunk sgl;
|
||||
};
|
||||
|
||||
struct _xfer_spec {
|
||||
@@ -1204,7 +1202,7 @@ static inline int _ldst_peripheral(struct pl330_dmac *pl330,
|
||||
const struct _xfer_spec *pxs, int cyc,
|
||||
enum pl330_cond cond)
|
||||
{
|
||||
int off = 0;
|
||||
int off = 0, i = 0, burstn = 1;
|
||||
|
||||
/*
|
||||
* do FLUSHP at beginning to clear any stale dma requests before the
|
||||
@@ -1212,30 +1210,36 @@ static inline int _ldst_peripheral(struct pl330_dmac *pl330,
|
||||
*/
|
||||
if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP))
|
||||
off += _emit_FLUSHP(dry_run, &buf[off], pxs->desc->peri);
|
||||
|
||||
if (pxs->desc->sgl.size) {
|
||||
WARN_ON(BYTE_MOD_BURST_LEN(pxs->desc->sgl.size, pxs->ccr));
|
||||
burstn = BYTE_TO_BURST(pxs->desc->sgl.size, pxs->ccr);
|
||||
}
|
||||
|
||||
while (cyc--) {
|
||||
off += _emit_WFP(dry_run, &buf[off], cond, pxs->desc->peri);
|
||||
off += _emit_load(dry_run, &buf[off], cond, pxs->desc->rqtype,
|
||||
pxs->desc->peri);
|
||||
off += _emit_store(dry_run, &buf[off], cond, pxs->desc->rqtype,
|
||||
pxs->desc->peri);
|
||||
#ifdef CONFIG_NO_GKI
|
||||
for (i = 0; i < burstn; i++) {
|
||||
off += _emit_WFP(dry_run, &buf[off], cond, pxs->desc->peri);
|
||||
off += _emit_load(dry_run, &buf[off], cond, pxs->desc->rqtype,
|
||||
pxs->desc->peri);
|
||||
off += _emit_store(dry_run, &buf[off], cond, pxs->desc->rqtype,
|
||||
pxs->desc->peri);
|
||||
}
|
||||
|
||||
switch (pxs->desc->rqtype) {
|
||||
case DMA_DEV_TO_MEM:
|
||||
|
||||
if (pxs->desc->dst_interlace_size)
|
||||
if (pxs->desc->sgl.dst_icg)
|
||||
off += _emit_ADDH(dry_run, &buf[off], DST,
|
||||
pxs->desc->dst_interlace_size);
|
||||
pxs->desc->sgl.dst_icg);
|
||||
break;
|
||||
case DMA_MEM_TO_DEV:
|
||||
if (pxs->desc->src_interlace_size)
|
||||
if (pxs->desc->sgl.src_icg)
|
||||
off += _emit_ADDH(dry_run, &buf[off], SRC,
|
||||
pxs->desc->src_interlace_size);
|
||||
pxs->desc->sgl.src_icg);
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return off;
|
||||
@@ -1450,9 +1454,7 @@ static int _period(struct pl330_dmac *pl330, unsigned int dry_run, u8 buf[],
|
||||
off += _emit_LPEND(dry_run, &buf[off], &lpend);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NO_GKI
|
||||
if (!pxs->desc->src_interlace_size &&
|
||||
!pxs->desc->dst_interlace_size) {
|
||||
if (!pxs->desc->sgl.src_icg && !pxs->desc->sgl.dst_icg) {
|
||||
num_dregs = BYTE_MOD_BURST_LEN(x->bytes, pxs->ccr);
|
||||
|
||||
if (num_dregs) {
|
||||
@@ -1460,14 +1462,6 @@ static int _period(struct pl330_dmac *pl330, unsigned int dry_run, u8 buf[],
|
||||
off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr);
|
||||
}
|
||||
}
|
||||
#else
|
||||
num_dregs = BYTE_MOD_BURST_LEN(x->bytes, pxs->ccr);
|
||||
|
||||
if (num_dregs) {
|
||||
off += _dregs(pl330, dry_run, &buf[off], pxs, num_dregs);
|
||||
off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr);
|
||||
}
|
||||
#endif
|
||||
|
||||
off += _emit_SEV(dry_run, &buf[off], ev);
|
||||
|
||||
@@ -1535,26 +1529,18 @@ static inline int _setup_loops(struct pl330_dmac *pl330,
|
||||
BRST_SIZE(ccr);
|
||||
int off = 0;
|
||||
|
||||
#ifdef CONFIG_NO_GKI
|
||||
if (pxs->desc->rqtype == DMA_DEV_TO_MEM)
|
||||
bursts = x->bytes / (BRST_SIZE(ccr) * BRST_LEN(ccr) +
|
||||
pxs->desc->dst_interlace_size);
|
||||
else if (pxs->desc->rqtype == DMA_MEM_TO_DEV)
|
||||
bursts = x->bytes / (BRST_SIZE(ccr) * BRST_LEN(ccr) +
|
||||
pxs->desc->src_interlace_size);
|
||||
#endif
|
||||
if (pxs->desc->sgl.size)
|
||||
bursts = x->bytes / pxs->desc->sgl.size;
|
||||
|
||||
while (bursts) {
|
||||
c = bursts;
|
||||
off += _loop(pl330, dry_run, &buf[off], &c, pxs);
|
||||
bursts -= c;
|
||||
}
|
||||
#ifdef CONFIG_NO_GKI
|
||||
if (!pxs->desc->src_interlace_size &&
|
||||
!pxs->desc->dst_interlace_size)
|
||||
|
||||
if (!pxs->desc->sgl.src_icg && !pxs->desc->sgl.dst_icg)
|
||||
off += _dregs(pl330, dry_run, &buf[off], pxs, num_dregs);
|
||||
#else
|
||||
off += _dregs(pl330, dry_run, &buf[off], pxs, num_dregs);
|
||||
#endif
|
||||
|
||||
return off;
|
||||
}
|
||||
|
||||
@@ -1585,14 +1571,9 @@ static inline int _setup_xfer_cyclic(struct pl330_dmac *pl330,
|
||||
unsigned long bursts = BYTE_TO_BURST(x->bytes, ccr);
|
||||
int off = 0;
|
||||
|
||||
#ifdef CONFIG_NO_GKI
|
||||
if (pxs->desc->rqtype == DMA_DEV_TO_MEM)
|
||||
bursts = x->bytes / (BRST_SIZE(ccr) * BRST_LEN(ccr)
|
||||
+ pxs->desc->dst_interlace_size);
|
||||
else if (pxs->desc->rqtype == DMA_MEM_TO_DEV)
|
||||
bursts = x->bytes / (BRST_SIZE(ccr) * BRST_LEN(ccr)
|
||||
+ pxs->desc->src_interlace_size);
|
||||
#endif
|
||||
if (pxs->desc->sgl.size)
|
||||
bursts = x->bytes / pxs->desc->sgl.size;
|
||||
|
||||
/* Setup Loop(s) */
|
||||
off += _loop_cyclic(pl330, dry_run, &buf[off], bursts, pxs, ev);
|
||||
|
||||
@@ -2452,10 +2433,6 @@ static int pl330_config_write(struct dma_chan *chan,
|
||||
pch->fifo_addr = slave_config->dst_addr;
|
||||
if (slave_config->dst_addr_width)
|
||||
pch->burst_sz = __ffs(slave_config->dst_addr_width);
|
||||
#ifdef CONFIG_NO_GKI
|
||||
if (slave_config->src_interlace_size)
|
||||
pch->slave_config.src_interlace_size = slave_config->src_interlace_size;
|
||||
#endif
|
||||
pch->burst_len = fixup_burst_len(slave_config->dst_maxburst,
|
||||
pch->dmac->quirks);
|
||||
} else if (direction == DMA_DEV_TO_MEM) {
|
||||
@@ -2463,10 +2440,6 @@ static int pl330_config_write(struct dma_chan *chan,
|
||||
pch->fifo_addr = slave_config->src_addr;
|
||||
if (slave_config->src_addr_width)
|
||||
pch->burst_sz = __ffs(slave_config->src_addr_width);
|
||||
#ifdef CONFIG_NO_GKI
|
||||
if (slave_config->dst_interlace_size)
|
||||
pch->slave_config.dst_interlace_size = slave_config->dst_interlace_size;
|
||||
#endif
|
||||
pch->burst_len = fixup_burst_len(slave_config->src_maxburst,
|
||||
pch->dmac->quirks);
|
||||
}
|
||||
@@ -2819,6 +2792,10 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
|
||||
desc->cyclic = false;
|
||||
desc->num_periods = 1;
|
||||
|
||||
desc->sgl.size = 0;
|
||||
desc->sgl.src_icg = 0;
|
||||
desc->sgl.dst_icg = 0;
|
||||
|
||||
dma_async_tx_descriptor_init(&desc->txd, &pch->chan);
|
||||
|
||||
return desc;
|
||||
@@ -2933,10 +2910,78 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
|
||||
|
||||
desc->cyclic = true;
|
||||
desc->num_periods = len / period_len;
|
||||
|
||||
return &desc->txd;
|
||||
}
|
||||
|
||||
static struct dma_async_tx_descriptor *pl330_prep_interleaved_dma(
|
||||
struct dma_chan *chan, struct dma_interleaved_template *xt,
|
||||
unsigned long flags)
|
||||
{
|
||||
struct dma_pl330_desc *desc = NULL;
|
||||
struct dma_pl330_chan *pch = to_pchan(chan);
|
||||
dma_addr_t dst = 0, src = 0;
|
||||
size_t size, src_icg, dst_icg, period_bytes, buffer_bytes;
|
||||
size_t nump = 0, numf = 0;
|
||||
|
||||
if (!xt->numf || !xt->sgl[0].size || xt->frame_size != 1)
|
||||
return NULL;
|
||||
|
||||
#ifdef CONFIG_NO_GKI
|
||||
desc->src_interlace_size = pch->slave_config.src_interlace_size;
|
||||
desc->dst_interlace_size = pch->slave_config.dst_interlace_size;
|
||||
nump = xt->nump;
|
||||
#endif
|
||||
numf = xt->numf;
|
||||
size = xt->sgl[0].size;
|
||||
period_bytes = size * nump;
|
||||
buffer_bytes = size * numf;
|
||||
|
||||
if (flags & DMA_PREP_REPEAT && (!nump || (numf % nump)))
|
||||
return NULL;
|
||||
|
||||
src_icg = dmaengine_get_src_icg(xt, &xt->sgl[0]);
|
||||
dst_icg = dmaengine_get_dst_icg(xt, &xt->sgl[0]);
|
||||
|
||||
pl330_config_write(chan, &pch->slave_config, xt->dir);
|
||||
|
||||
if (!pl330_prep_slave_fifo(pch, xt->dir))
|
||||
return NULL;
|
||||
|
||||
desc = pl330_get_desc(pch);
|
||||
if (!desc) {
|
||||
dev_err(chan->device->dev, "Failed to get desc\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (xt->dir == DMA_MEM_TO_DEV) {
|
||||
desc->rqcfg.src_inc = 1;
|
||||
desc->rqcfg.dst_inc = 0;
|
||||
src = xt->src_start;
|
||||
dst = pch->fifo_dma;
|
||||
} else {
|
||||
desc->rqcfg.src_inc = 0;
|
||||
desc->rqcfg.dst_inc = 1;
|
||||
src = pch->fifo_dma;
|
||||
dst = xt->dst_start;
|
||||
}
|
||||
|
||||
desc->rqtype = xt->dir;
|
||||
desc->rqcfg.brst_size = pch->burst_sz;
|
||||
desc->rqcfg.brst_len = pch->burst_len;
|
||||
desc->bytes_requested = buffer_bytes;
|
||||
desc->sgl.size = size;
|
||||
desc->sgl.src_icg = src_icg;
|
||||
desc->sgl.dst_icg = dst_icg;
|
||||
|
||||
if (flags & DMA_PREP_REPEAT) {
|
||||
desc->cyclic = true;
|
||||
desc->num_periods = numf / nump;
|
||||
fill_px(&desc->px, dst, src, period_bytes);
|
||||
} else {
|
||||
fill_px(&desc->px, dst, src, buffer_bytes);
|
||||
}
|
||||
|
||||
dev_dbg(chan->device->dev, "size: %zu, src_icg: %zu, dst_icg: %zu, nump: %zu, numf: %zu\n",
|
||||
size, src_icg, dst_icg, nump, numf);
|
||||
|
||||
return &desc->txd;
|
||||
}
|
||||
@@ -3068,10 +3113,6 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
|
||||
desc->rqcfg.brst_len = pch->burst_len;
|
||||
desc->rqtype = direction;
|
||||
desc->bytes_requested = sg_dma_len(sg);
|
||||
#ifdef CONFIG_NO_GKI
|
||||
desc->src_interlace_size = pch->slave_config.src_interlace_size;
|
||||
desc->dst_interlace_size = pch->slave_config.dst_interlace_size;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return the last desc in the chain */
|
||||
@@ -3306,12 +3347,16 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
dma_cap_set(DMA_SLAVE, pd->cap_mask);
|
||||
dma_cap_set(DMA_CYCLIC, pd->cap_mask);
|
||||
dma_cap_set(DMA_PRIVATE, pd->cap_mask);
|
||||
dma_cap_set(DMA_INTERLEAVE, pd->cap_mask);
|
||||
dma_cap_set(DMA_REPEAT, pd->cap_mask);
|
||||
dma_cap_set(DMA_LOAD_EOT, pd->cap_mask);
|
||||
}
|
||||
|
||||
pd->device_alloc_chan_resources = pl330_alloc_chan_resources;
|
||||
pd->device_free_chan_resources = pl330_free_chan_resources;
|
||||
pd->device_prep_dma_memcpy = pl330_prep_dma_memcpy;
|
||||
pd->device_prep_dma_cyclic = pl330_prep_dma_cyclic;
|
||||
pd->device_prep_interleaved_dma = pl330_prep_interleaved_dma;
|
||||
pd->device_tx_status = pl330_tx_status;
|
||||
pd->device_prep_slave_sg = pl330_prep_slave_sg;
|
||||
pd->device_config = pl330_config;
|
||||
|
||||
@@ -2554,9 +2554,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
|
||||
|
||||
vmode->previous_pixelclock = vmode->mpixelclock;
|
||||
vmode->mpixelclock = mode->crtc_clock * 1000;
|
||||
if ((mode->flags & DRM_MODE_FLAG_3D_MASK) ==
|
||||
DRM_MODE_FLAG_3D_FRAME_PACKING)
|
||||
vmode->mpixelclock *= 2;
|
||||
dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock);
|
||||
|
||||
vmode->previous_tmdsclock = vmode->mtmdsclock;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/wait.h>
|
||||
@@ -39,6 +40,7 @@
|
||||
#define REG_IEN 0x18 /* interrupt enable */
|
||||
#define REG_IPD 0x1c /* interrupt pending */
|
||||
#define REG_FCNT 0x20 /* finished count */
|
||||
#define REG_SCL_OE_DB 0x24 /* Slave hold scl debounce */
|
||||
#define REG_CON1 0x228 /* control register1 */
|
||||
|
||||
/* Data buffer offsets */
|
||||
@@ -87,6 +89,7 @@ enum {
|
||||
#define REG_INT_START BIT(4) /* START condition generated */
|
||||
#define REG_INT_STOP BIT(5) /* STOP condition generated */
|
||||
#define REG_INT_NAKRCV BIT(6) /* NACK received */
|
||||
#define REG_INT_SLV_HDSCL BIT(7) /* slave hold scl */
|
||||
#define REG_INT_ALL 0xff
|
||||
|
||||
/* Disable i2c all irqs */
|
||||
@@ -97,7 +100,7 @@ enum {
|
||||
#define REG_CON1_NACK_AUTO_STOP BIT(2)
|
||||
|
||||
/* Constants */
|
||||
#define WAIT_TIMEOUT 1000 /* ms */
|
||||
#define WAIT_TIMEOUT 200 /* ms */
|
||||
#define DEFAULT_SCL_RATE (100 * 1000) /* Hz */
|
||||
|
||||
/**
|
||||
@@ -225,6 +228,9 @@ struct rk3x_i2c {
|
||||
struct notifier_block clk_rate_nb;
|
||||
bool autostop_supported;
|
||||
|
||||
struct reset_control *reset;
|
||||
struct reset_control *reset_apb;
|
||||
|
||||
/* Settings */
|
||||
struct i2c_timings t;
|
||||
|
||||
@@ -307,6 +313,13 @@ static bool rk3x_i2c_auto_stop(struct rk3x_i2c *i2c)
|
||||
if (len > 32)
|
||||
goto out;
|
||||
|
||||
/* For tx mode, one byte of the device address also needs to be counted,
|
||||
* if the data length is equal to 32, which is actually 33 bytes, it would
|
||||
* need to be divided into two parts, and needs to jump out of autostop.
|
||||
*/
|
||||
if (i2c->msg->len == 32 && i2c->mode == REG_CON_MOD_TX && !i2c->processed)
|
||||
goto out;
|
||||
|
||||
i2c->state = STATE_STOP;
|
||||
|
||||
con1 |= REG_CON1_TRANSFER_AUTO_STOP | REG_CON1_AUTO_STOP;
|
||||
@@ -983,9 +996,10 @@ static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
|
||||
{
|
||||
struct i2c_timings *t = &i2c->t;
|
||||
struct rk3x_i2c_calced_timings calc;
|
||||
unsigned long period, time_hold = (WAIT_TIMEOUT / 2) * 1000000;
|
||||
u64 t_low_ns, t_high_ns;
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
u32 val, cnt;
|
||||
int ret;
|
||||
|
||||
ret = i2c->soc_data->calc_timings(clk_rate, t, &calc);
|
||||
@@ -1000,6 +1014,10 @@ static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
|
||||
i2c_writel(i2c, val, REG_CON);
|
||||
i2c_writel(i2c, (calc.div_high << 16) | (calc.div_low & 0xffff),
|
||||
REG_CLKDIV);
|
||||
|
||||
period = DIV_ROUND_UP(1000000000, clk_rate);
|
||||
cnt = DIV_ROUND_UP(time_hold, period);
|
||||
i2c_writel(i2c, cnt, REG_SCL_OE_DB);
|
||||
spin_unlock_irqrestore(&i2c->lock, flags);
|
||||
|
||||
clk_disable(i2c->pclk);
|
||||
@@ -1165,12 +1183,30 @@ static int rk3x_i2c_wait_xfer_poll(struct rk3x_i2c *i2c, unsigned long xfer_time
|
||||
return !i2c->busy;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset i2c controller, reset all i2c registers.
|
||||
*/
|
||||
static void rk3x_i2c_reset_controller(struct rk3x_i2c *i2c)
|
||||
{
|
||||
if (!IS_ERR_OR_NULL(i2c->reset)) {
|
||||
reset_control_assert(i2c->reset);
|
||||
udelay(10);
|
||||
reset_control_deassert(i2c->reset);
|
||||
}
|
||||
|
||||
if (!IS_ERR_OR_NULL(i2c->reset_apb)) {
|
||||
reset_control_assert(i2c->reset_apb);
|
||||
udelay(10);
|
||||
reset_control_deassert(i2c->reset_apb);
|
||||
}
|
||||
}
|
||||
|
||||
static int rk3x_i2c_xfer_common(struct i2c_adapter *adap,
|
||||
struct i2c_msg *msgs, int num, bool polling)
|
||||
{
|
||||
struct rk3x_i2c *i2c = (struct rk3x_i2c *)adap->algo_data;
|
||||
unsigned long timeout, flags;
|
||||
u32 val;
|
||||
u32 val, ipd = 0;
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
@@ -1189,7 +1225,7 @@ static int rk3x_i2c_xfer_common(struct i2c_adapter *adap,
|
||||
* rk3x_i2c_setup()).
|
||||
*/
|
||||
for (i = 0; i < num; i += ret) {
|
||||
unsigned long xfer_time = 100;
|
||||
unsigned long xfer_time = WAIT_TIMEOUT;
|
||||
int len;
|
||||
|
||||
ret = rk3x_i2c_setup(i2c, msgs + i, num - i);
|
||||
@@ -1227,8 +1263,9 @@ static int rk3x_i2c_xfer_common(struct i2c_adapter *adap,
|
||||
spin_lock_irqsave(&i2c->lock, flags);
|
||||
|
||||
if (timeout == 0) {
|
||||
ipd = i2c_readl(i2c, REG_IPD);
|
||||
dev_err(i2c->dev, "timeout, ipd: 0x%02x, state: %d\n",
|
||||
i2c_readl(i2c, REG_IPD), i2c->state);
|
||||
ipd, i2c->state);
|
||||
|
||||
/* Force a STOP condition without interrupt */
|
||||
rk3x_i2c_disable_irq(i2c);
|
||||
@@ -1256,6 +1293,12 @@ static int rk3x_i2c_xfer_common(struct i2c_adapter *adap,
|
||||
|
||||
spin_unlock_irqrestore(&i2c->lock, flags);
|
||||
|
||||
if ((ret == -ETIMEDOUT) && (ipd & REG_INT_SLV_HDSCL)) {
|
||||
rk3x_i2c_reset_controller(i2c);
|
||||
dev_err(i2c->dev, "SCL hold by slave, check your device.\n");
|
||||
rk3x_i2c_adapt_div(i2c, clk_get_rate(i2c->clk));
|
||||
}
|
||||
|
||||
return ret < 0 ? ret : num;
|
||||
}
|
||||
|
||||
@@ -1602,6 +1645,7 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
|
||||
|
||||
platform_set_drvdata(pdev, i2c);
|
||||
|
||||
i2c->reset = devm_reset_control_get(&pdev->dev, "i2c");
|
||||
if (!has_acpi_companion(&pdev->dev)) {
|
||||
if (i2c->soc_data->calc_timings == rk3x_i2c_v0_calc_timings) {
|
||||
/* Only one clock to use for bus clock and peripheral clock */
|
||||
@@ -1610,6 +1654,7 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
|
||||
} else {
|
||||
i2c->clk = devm_clk_get(&pdev->dev, "i2c");
|
||||
i2c->pclk = devm_clk_get(&pdev->dev, "pclk");
|
||||
i2c->reset_apb = devm_reset_control_get(&pdev->dev, "apb");
|
||||
}
|
||||
|
||||
if (IS_ERR(i2c->clk))
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
@@ -68,6 +69,8 @@ struct rockchip_saradc {
|
||||
struct clk *clk;
|
||||
struct completion completion;
|
||||
struct regulator *vref;
|
||||
/* lock to protect against multiple access to the device */
|
||||
struct mutex lock;
|
||||
int uv_vref;
|
||||
struct reset_control *reset;
|
||||
const struct rockchip_saradc_data *data;
|
||||
@@ -189,22 +192,22 @@ static int rockchip_saradc_read_raw(struct iio_dev *indio_dev,
|
||||
#endif
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
mutex_lock(&info->lock);
|
||||
|
||||
if (info->suspended) {
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
mutex_unlock(&info->lock);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
ret = rockchip_saradc_conversion(info, chan);
|
||||
if (ret) {
|
||||
rockchip_saradc_power_down(info);
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
mutex_unlock(&info->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
*val = info->last_val;
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
mutex_unlock(&info->lock);
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
/* It is a dummy regulator */
|
||||
@@ -476,7 +479,7 @@ static irqreturn_t rockchip_saradc_trigger_handler(int irq, void *p)
|
||||
int ret;
|
||||
int i, j = 0;
|
||||
|
||||
mutex_lock(&i_dev->mlock);
|
||||
mutex_lock(&info->lock);
|
||||
|
||||
for_each_set_bit(i, i_dev->active_scan_mask, i_dev->masklength) {
|
||||
const struct iio_chan_spec *chan = &i_dev->channels[i];
|
||||
@@ -493,7 +496,7 @@ static irqreturn_t rockchip_saradc_trigger_handler(int irq, void *p)
|
||||
|
||||
iio_push_to_buffers_with_timestamp(i_dev, &data, iio_get_time_ns(i_dev));
|
||||
out:
|
||||
mutex_unlock(&i_dev->mlock);
|
||||
mutex_unlock(&info->lock);
|
||||
|
||||
iio_trigger_notify_done(i_dev->trig);
|
||||
|
||||
@@ -779,6 +782,8 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
mutex_init(&info->lock);
|
||||
|
||||
return devm_iio_device_register(&pdev->dev, indio_dev);
|
||||
}
|
||||
|
||||
@@ -788,14 +793,14 @@ static int rockchip_saradc_suspend(struct device *dev)
|
||||
struct rockchip_saradc *info = iio_priv(indio_dev);
|
||||
|
||||
/* Avoid reading saradc when suspending */
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
mutex_lock(&info->lock);
|
||||
|
||||
clk_disable_unprepare(info->clk);
|
||||
clk_disable_unprepare(info->pclk);
|
||||
regulator_disable(info->vref);
|
||||
|
||||
info->suspended = true;
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
mutex_unlock(&info->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -158,6 +158,12 @@ config ICM2060X_ACC
|
||||
To have support for your specific gsesnor you will have to
|
||||
select the proper drivers which depend on this option.
|
||||
|
||||
config ICM4260X_ACC
|
||||
tristate "gsensor icm4260x"
|
||||
help
|
||||
To have support for your specific gsesnor you will have to
|
||||
select the proper drivers which depend on this option.
|
||||
|
||||
config IAM20680_ACC
|
||||
tristate "gsensor iam20680"
|
||||
default n
|
||||
|
||||
@@ -21,5 +21,6 @@ obj-$(CONFIG_GS_DA215S) += da215s/
|
||||
obj-$(CONFIG_GS_DA223) += da223.o
|
||||
obj-$(CONFIG_GS_DA228E) += da228e/
|
||||
obj-$(CONFIG_ICM2060X_ACC) += icm2060x_acc.o
|
||||
obj-$(CONFIG_ICM4260X_ACC) += icm4260x_acc.o
|
||||
da223-y := da223_cust.o da223_core.o
|
||||
obj-$(CONFIG_IAM20680_ACC) += iam20680_acc.o
|
||||
|
||||
470
drivers/input/sensors/accel/icm4260x_acc.c
Normal file
470
drivers/input/sensors/accel/icm4260x_acc.c
Normal file
@@ -0,0 +1,470 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2023 Rockchip Co.,Ltd.
|
||||
* Author: Wangqiang Guo <kay.guo@rock-chips.com>
|
||||
*/
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
#include <linux/icm4260x.h>
|
||||
|
||||
/**
|
||||
* icm4260x_set_idle() - Set Idle bit in PWR_MGMT_0 register
|
||||
* @client: struct i2c_client..
|
||||
*
|
||||
* Set ACCEL_LP_CLK_SEL as well when necessary with a proper wait
|
||||
*
|
||||
* Return: 0 when successful.
|
||||
*/
|
||||
static int icm4260x_set_idle(struct i2c_client *client)
|
||||
{
|
||||
u8 reg_pwr_mgmt_0;
|
||||
u8 d;
|
||||
int ret = 0;
|
||||
|
||||
reg_pwr_mgmt_0 = sensor_read_reg(client, ICM4260X_PWR_MGMT_0);
|
||||
/* set Idle bit.
|
||||
* when accel LPM is already enabled, set ACCEL_LP_CLK_SEL bit as well.
|
||||
*/
|
||||
d = reg_pwr_mgmt_0;
|
||||
d |= BIT_IDLE;
|
||||
if ((d & BIT_ACCEL_MODE_MASK) == BIT_ACCEL_MODE_LPM)
|
||||
d |= BIT_ACCEL_LP_CLK_SEL;
|
||||
|
||||
ret = sensor_write_reg(client, ICM4260X_PWR_MGMT_0, d);
|
||||
usleep_range(20, 21);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* icm4260x_mreg_read() - Multiple byte read from MREG area.
|
||||
* @client: struct i2c_client.
|
||||
* @addr: MREG register start address including bank in upper byte.
|
||||
* @len: length to read in byte.
|
||||
* @data: pointer to store read data.
|
||||
*
|
||||
* Return: 0 when successful.
|
||||
*/
|
||||
static int icm4260x_mreg_read(struct i2c_client *client, int addr, int len, u8 *data)
|
||||
{
|
||||
int ret;
|
||||
u8 reg_pwr_mgmt_0;
|
||||
|
||||
reg_pwr_mgmt_0 = sensor_read_reg(client, ICM4260X_PWR_MGMT_0);
|
||||
|
||||
ret = icm4260x_set_idle(client);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = sensor_write_reg(client, ICM4260X_BLK_SEL_R, (addr >> 8) & 0xff);
|
||||
usleep_range(INV_ICM42607_BLK_SEL_WAIT_US,
|
||||
INV_ICM42607_BLK_SEL_WAIT_US + 1);
|
||||
if (ret)
|
||||
goto restore_bank;
|
||||
|
||||
ret = sensor_write_reg(client, ICM4260X_MADDR_R, addr & 0xff);
|
||||
usleep_range(INV_ICM42607_MADDR_WAIT_US,
|
||||
INV_ICM42607_MADDR_WAIT_US + 1);
|
||||
if (ret)
|
||||
goto restore_bank;
|
||||
|
||||
*data = ICM4260X_M_R;
|
||||
ret = sensor_rx_data(client, data, len);
|
||||
usleep_range(INV_ICM42607_M_RW_WAIT_US,
|
||||
INV_ICM42607_M_RW_WAIT_US + 1);
|
||||
if (ret)
|
||||
goto restore_bank;
|
||||
|
||||
restore_bank:
|
||||
ret |= sensor_write_reg(client, ICM4260X_BLK_SEL_R, 0);
|
||||
usleep_range(INV_ICM42607_BLK_SEL_WAIT_US,
|
||||
INV_ICM42607_BLK_SEL_WAIT_US + 1);
|
||||
|
||||
ret |= sensor_write_reg(client, ICM4260X_PWR_MGMT_0, reg_pwr_mgmt_0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* icm4260x_mreg_single_write() - Single byte write to MREG area.
|
||||
* @client: struct i2c_client.
|
||||
* @addr: MREG register address including bank in upper byte.
|
||||
* @data: data to write.
|
||||
*
|
||||
* Return: 0 when successful.
|
||||
*/
|
||||
static int icm4260x_mreg_single_write(struct i2c_client *client, int addr, u8 data)
|
||||
{
|
||||
int ret;
|
||||
u8 reg_pwr_mgmt_0;
|
||||
|
||||
reg_pwr_mgmt_0 = sensor_read_reg(client, ICM4260X_PWR_MGMT_0);
|
||||
|
||||
ret = icm4260x_set_idle(client);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = sensor_write_reg(client, ICM4260X_BLK_SEL_W, (addr >> 8) & 0xff);
|
||||
usleep_range(INV_ICM42607_BLK_SEL_WAIT_US,
|
||||
INV_ICM42607_BLK_SEL_WAIT_US + 1);
|
||||
if (ret)
|
||||
goto restore_bank;
|
||||
|
||||
ret = sensor_write_reg(client, ICM4260X_MADDR_W, addr & 0xff);
|
||||
usleep_range(INV_ICM42607_MADDR_WAIT_US,
|
||||
INV_ICM42607_MADDR_WAIT_US + 1);
|
||||
if (ret)
|
||||
goto restore_bank;
|
||||
|
||||
ret = sensor_write_reg(client, ICM4260X_M_W, data);
|
||||
usleep_range(INV_ICM42607_M_RW_WAIT_US,
|
||||
INV_ICM42607_M_RW_WAIT_US + 1);
|
||||
if (ret)
|
||||
goto restore_bank;
|
||||
|
||||
restore_bank:
|
||||
ret |= sensor_write_reg(client, ICM4260X_BLK_SEL_W, 0);
|
||||
usleep_range(INV_ICM42607_BLK_SEL_WAIT_US,
|
||||
INV_ICM42607_BLK_SEL_WAIT_US + 1);
|
||||
|
||||
ret |= sensor_write_reg(client, ICM4260X_PWR_MGMT_0, reg_pwr_mgmt_0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* OTP reload procedure.
|
||||
*/
|
||||
static int icm4260x_otp_reload(struct i2c_client *client)
|
||||
{
|
||||
int ret;
|
||||
u8 rb = 0;
|
||||
|
||||
/* set idle bit */
|
||||
ret = icm4260x_set_idle(client);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Set OTP_COPY_MODE to 2'b01 */
|
||||
ret = icm4260x_mreg_read(client, ICM4260X_OTP_CONFIG_MREG_TOP1, 1, &rb);
|
||||
if (ret)
|
||||
return ret;
|
||||
rb &= ~OTP_COPY_MODE_MASK;
|
||||
rb |= BIT_OTP_COPY_NORMAL;
|
||||
ret = icm4260x_mreg_single_write(client, ICM4260X_OTP_CONFIG_MREG_TOP1, rb);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* set OTP_PWR_DOWN to 1'b0 and wait for 300us */
|
||||
ret = icm4260x_mreg_read(client, ICM4260X_OTP_CTRL7_MREG_OTP, 1, &rb);
|
||||
if (ret)
|
||||
return ret;
|
||||
rb &= ~BIT_OTP_PWR_DOWN;
|
||||
ret = icm4260x_mreg_single_write(client, ICM4260X_OTP_CTRL7_MREG_OTP, rb);
|
||||
if (ret)
|
||||
return ret;
|
||||
usleep_range(300, 400);
|
||||
|
||||
/* set OTP_RELOAD to 1'b1 and wait for 280us */
|
||||
ret = icm4260x_mreg_read(client, ICM4260X_OTP_CTRL7_MREG_OTP, 1, &rb);
|
||||
if (ret)
|
||||
return ret;
|
||||
rb |= BIT_OTP_RELOAD;
|
||||
ret = icm4260x_mreg_single_write(client, ICM4260X_OTP_CTRL7_MREG_OTP, rb);
|
||||
if (ret)
|
||||
return ret;
|
||||
usleep_range(280, 380);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sensor_active(struct i2c_client *client, int enable, int rate)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int result = 0;
|
||||
u8 status = 0;
|
||||
|
||||
sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);
|
||||
|
||||
if (!enable) {
|
||||
status = (0xff & ~BIT_ACCEL_MODE_MASK);
|
||||
sensor->ops->ctrl_data &= status;
|
||||
} else {
|
||||
status = BIT_ACCEL_MODE_LNM;
|
||||
sensor->ops->ctrl_data |= status;
|
||||
sensor->ops->ctrl_data &= ~BIT_IDLE;
|
||||
}
|
||||
|
||||
result = sensor_write_reg(client, sensor->ops->ctrl_reg,
|
||||
sensor->ops->ctrl_data);
|
||||
if (result) {
|
||||
dev_err(&client->dev,
|
||||
"%s: fail to set pwr_mgmt0(%d)\n", __func__, result);
|
||||
return result;
|
||||
}
|
||||
usleep_range(250, 260);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* write POR value
|
||||
*/
|
||||
|
||||
static int icm4260x_set_default_register(struct i2c_client *client)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
status |= sensor_write_reg(client, ICM4260X_GYRO_CONFIG0, 0x06);
|
||||
status |= sensor_write_reg(client, ICM4260X_ACCEL_CONFIG0, 0x06);
|
||||
status |= sensor_write_reg(client, ICM4260X_APEX_CONFIG0, 0x08);
|
||||
status |= sensor_write_reg(client, ICM4260X_APEX_CONFIG1, 0x02);
|
||||
status |= sensor_write_reg(client, ICM4260X_WOM_CONFIG, 0);
|
||||
status |= sensor_write_reg(client, ICM4260X_FIFO_CONFIG1, 0x01);
|
||||
status |= sensor_write_reg(client, ICM4260X_FIFO_CONFIG2, 0);
|
||||
status |= sensor_write_reg(client, ICM4260X_FIFO_CONFIG3, 0);
|
||||
status |= icm4260x_mreg_single_write(client, ICM4260X_FIFO_CONFIG5_MREG_TOP1, 0x20);
|
||||
status |= icm4260x_mreg_single_write(client, ICM4260X_ST_CONFIG_MREG_TOP1, 0);
|
||||
status |= icm4260x_mreg_single_write(client, ICM4260X_INT_SOURCE7_MREG_TOP1, 0);
|
||||
status |= icm4260x_mreg_single_write(client, ICM4260X_INT_SOURCE8_MREG_TOP1, 0);
|
||||
status |= icm4260x_mreg_single_write(client, ICM4260X_INT_SOURCE9_MREG_TOP1, 0);
|
||||
status |= icm4260x_mreg_single_write(client, ICM4260X_INT_SOURCE10_MREG_TOP1, 0);
|
||||
status |= icm4260x_mreg_single_write(client, ICM4260X_APEX_CONFIG2_MREG_TOP1, 0xA2);
|
||||
status |= icm4260x_mreg_single_write(client, ICM4260X_APEX_CONFIG3_MREG_TOP1, 0x85);
|
||||
status |= icm4260x_mreg_single_write(client, ICM4260X_APEX_CONFIG4_MREG_TOP1, 0x51);
|
||||
status |= icm4260x_mreg_single_write(client, ICM4260X_APEX_CONFIG5_MREG_TOP1, 0x80);
|
||||
status |= icm4260x_mreg_single_write(client, ICM4260X_APEX_CONFIG9_MREG_TOP1, 0);
|
||||
status |= icm4260x_mreg_single_write(client, ICM4260X_APEX_CONFIG10_MREG_TOP1, 0);
|
||||
status |= icm4260x_mreg_single_write(client, ICM4260X_APEX_CONFIG11_MREG_TOP1, 0);
|
||||
status |= icm4260x_mreg_single_write(client, ICM4260X_ACCEL_WOM_X_THR_MREG_TOP1, 0);
|
||||
status |= icm4260x_mreg_single_write(client, ICM4260X_ACCEL_WOM_Y_THR_MREG_TOP1, 0);
|
||||
status |= icm4260x_mreg_single_write(client, ICM4260X_ACCEL_WOM_Z_THR_MREG_TOP1, 0);
|
||||
status |= icm4260x_mreg_single_write(client, ICM4260X_GOS_USER0_MREG_TOP1, 0);
|
||||
status |= icm4260x_mreg_single_write(client, ICM4260X_GOS_USER1_MREG_TOP1, 0);
|
||||
status |= icm4260x_mreg_single_write(client, ICM4260X_GOS_USER2_MREG_TOP1, 0);
|
||||
status |= icm4260x_mreg_single_write(client, ICM4260X_GOS_USER3_MREG_TOP1, 0);
|
||||
status |= icm4260x_mreg_single_write(client, ICM4260X_GOS_USER4_MREG_TOP1, 0);
|
||||
status |= icm4260x_mreg_single_write(client, ICM4260X_GOS_USER5_MREG_TOP1, 0);
|
||||
status |= icm4260x_mreg_single_write(client, ICM4260X_GOS_USER6_MREG_TOP1, 0);
|
||||
status |= icm4260x_mreg_single_write(client, ICM4260X_GOS_USER7_MREG_TOP1, 0);
|
||||
status |= icm4260x_mreg_single_write(client, ICM4260X_GOS_USER8_MREG_TOP1, 0);
|
||||
status |= icm4260x_mreg_single_write(client, ICM4260X_APEX_CONFIG12_MREG_TOP1, 0);
|
||||
|
||||
if (status)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sensor_init(struct i2c_client *client)
|
||||
{
|
||||
int ret = 0;
|
||||
u8 device_id = 0, value = 0;
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
|
||||
device_id = sensor_read_reg(client, ICM4260X_WHO_AM_I);
|
||||
if (device_id != ICM42607_DEVICE_ID) {
|
||||
dev_err(&client->dev, "%s: check id err, read_id: %d\n",
|
||||
__func__, device_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = icm4260x_otp_reload(client);
|
||||
if (ret) {
|
||||
dev_err(&client->dev,
|
||||
"ICM4260X OTP reload error,ret: %d!\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
ret = icm4260x_set_default_register(client);
|
||||
if (ret) {
|
||||
dev_err(&client->dev,
|
||||
"set ICM4260X default_register error,ret: %d!\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* SPI or I2C only
|
||||
* FIFO count : byte mode, big endian
|
||||
* sensor data : big endian
|
||||
*/
|
||||
value |= BIT_FIFO_COUNT_ENDIAN;
|
||||
value |= BIT_SENSOR_DATA_ENDIAN;
|
||||
ret = sensor_write_reg(client, ICM4260X_INTF_CONFIG0, value);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* configure clock */
|
||||
value = BIT_CLK_SEL_PLL | BIT_I3C_SDR_EN | BIT_I3C_DDR_EN;
|
||||
ret = sensor_write_reg(client, ICM4260X_INTF_CONFIG1, value);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* INT pin configuration */
|
||||
/*
|
||||
* value = (INT_POLARITY << SHIFT_INT1_POLARITY) |
|
||||
* (INT_DRIVE_CIRCUIT << SHIFT_INT1_DRIVE_CIRCUIT) |
|
||||
* (INT_MODE << SHIFT_INT1_MODE);
|
||||
* ret = sensor_write_reg(client, ICM4260X_INT_CONFIG_REG, value);
|
||||
* if (ret)
|
||||
* return ret;
|
||||
*/
|
||||
|
||||
/* disable sensors */
|
||||
ret = sensor_write_reg(client, ICM4260X_PWR_MGMT_0, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* set Full scale select for accelerometer UI interface output*/
|
||||
value = sensor_read_reg(client, ICM4260X_ACCEL_CONFIG0);
|
||||
value &= ~BIT_ACCEL_FSR;
|
||||
value |= ACCEL_FS_SEL << SHIFT_ACCEL_FS_SEL;
|
||||
ret = sensor_write_reg(client, ICM4260X_ACCEL_CONFIG0, value);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* turn on accelerometer*/
|
||||
ret = sensor->ops->active(client, 0, sensor->pdata->poll_delay_ms);
|
||||
if (ret) {
|
||||
dev_err(&client->dev,
|
||||
"%s: fail to active sensor(%d)\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int gsensor_report_value(struct i2c_client *client,
|
||||
struct sensor_axis *axis)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
|
||||
if (sensor->status_cur == SENSOR_ON) {
|
||||
/* Report acceleration sensor information */
|
||||
input_report_abs(sensor->input_dev, ABS_X, axis->x);
|
||||
input_report_abs(sensor->input_dev, ABS_Y, axis->y);
|
||||
input_report_abs(sensor->input_dev, ABS_Z, axis->z);
|
||||
input_sync(sensor->input_dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sensor_report_value(struct i2c_client *client)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
struct sensor_platform_data *pdata = sensor->pdata;
|
||||
int ret = 0;
|
||||
short x, y, z;
|
||||
struct sensor_axis axis;
|
||||
u8 buffer[6] = {0};
|
||||
|
||||
if (sensor->ops->read_len < 6) {
|
||||
dev_err(&client->dev, "%s: length is error, len = %d\n",
|
||||
__func__, sensor->ops->read_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Data bytes from hardware xH, xL, yH, yL, zH, zL */
|
||||
*buffer = sensor->ops->read_reg;
|
||||
ret = sensor_rx_data(client, buffer, sensor->ops->read_len);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev,
|
||||
"%s: read data failed, ret = %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
x = ((buffer[0] << 8) & 0xff00) + (buffer[1] & 0xFF);
|
||||
y = ((buffer[2] << 8) & 0xff00) + (buffer[3] & 0xFF);
|
||||
z = ((buffer[4] << 8) & 0xff00) + (buffer[5] & 0xFF);
|
||||
|
||||
//printk("%s,x:%d, y:%d, z:%d\n", __func__, x, y, z);
|
||||
axis.x = (pdata->orientation[0]) * x + (pdata->orientation[1]) * y +
|
||||
(pdata->orientation[2]) * z;
|
||||
axis.y = (pdata->orientation[3]) * x + (pdata->orientation[4]) * y +
|
||||
(pdata->orientation[5]) * z;
|
||||
axis.z = (pdata->orientation[6]) * x + (pdata->orientation[7]) * y +
|
||||
(pdata->orientation[8]) * z;
|
||||
|
||||
gsensor_report_value(client, &axis);
|
||||
|
||||
mutex_lock(&(sensor->data_mutex));
|
||||
sensor->axis = axis;
|
||||
mutex_unlock(&(sensor->data_mutex));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct sensor_operate gsensor_icm4260x_ops = {
|
||||
.name = "icm4260x_acc",
|
||||
.type = SENSOR_TYPE_ACCEL,
|
||||
.id_i2c = ACCEL_ID_ICM4260X,
|
||||
.read_reg = ICM4260X_ACCEL_DATA_X0,
|
||||
.read_len = 6,
|
||||
.id_reg = SENSOR_UNKNOW_DATA,
|
||||
.id_data = SENSOR_UNKNOW_DATA,
|
||||
.precision = ICM4260X_PRECISION,
|
||||
.ctrl_reg = ICM4260X_PWR_MGMT_0,
|
||||
.int_status_reg = ICM4260X_INT_STATUS,
|
||||
.range = {-32768, 32768},
|
||||
.trig = IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
|
||||
.active = sensor_active,
|
||||
.init = sensor_init,
|
||||
.report = sensor_report_value,
|
||||
};
|
||||
|
||||
/****************operate according to sensor chip:end************/
|
||||
static int gsensor_icm4260x_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *devid)
|
||||
{
|
||||
client->addr = ICM42607_ADDR;
|
||||
return sensor_register_device(client, NULL, devid, &gsensor_icm4260x_ops);
|
||||
}
|
||||
|
||||
static void gsensor_icm4260x_remove(struct i2c_client *client)
|
||||
{
|
||||
sensor_unregister_device(client, NULL, &gsensor_icm4260x_ops);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id gsensor_icm4260x_id[] = {
|
||||
{"icm42607_acc", ACCEL_ID_ICM4260X},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct i2c_driver gsensor_icm4260x_driver = {
|
||||
.probe = gsensor_icm4260x_probe,
|
||||
.remove = gsensor_icm4260x_remove,
|
||||
.shutdown = sensor_shutdown,
|
||||
.id_table = gsensor_icm4260x_id,
|
||||
.driver = {
|
||||
.name = "gsensor_icm4260x",
|
||||
#ifdef CONFIG_PM
|
||||
.pm = &sensor_pm_ops,
|
||||
#endif
|
||||
},
|
||||
};
|
||||
|
||||
module_i2c_driver(gsensor_icm4260x_driver);
|
||||
|
||||
MODULE_AUTHOR("Wangqiang Guo <dave.wang@rock-chips.com>");
|
||||
MODULE_DESCRIPTION("icm4260x_acc 3-Axis accelerometer driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -40,6 +40,12 @@ config GYRO_LSM330
|
||||
config GYRO_ICM2060X
|
||||
tristate "gyroscope icm2060x_gyro"
|
||||
|
||||
config GYRO_ICM4260X
|
||||
tristate "gyroscope icm4260x_gyro"
|
||||
help
|
||||
To have support for your specific gyro you will have to
|
||||
select the proper drivers which depend on this option.
|
||||
|
||||
config GYRO_IAM20680
|
||||
tristate "gyroscope iam20680_gyro"
|
||||
default n
|
||||
|
||||
@@ -9,4 +9,5 @@ obj-$(CONFIG_GYRO_MPU6500) += mpu6500_gyro.o
|
||||
obj-$(CONFIG_GYRO_MPU6880) += mpu6880_gyro.o
|
||||
obj-$(CONFIG_GYRO_LSM330) += lsm330_gyro.o
|
||||
obj-$(CONFIG_GYRO_ICM2060X) += icm2060x_gyro.o
|
||||
obj-$(CONFIG_GYRO_ICM4260X) += icm4260x_gyro.o
|
||||
obj-$(CONFIG_GYRO_IAM20680) += iam20680_gyro.o
|
||||
|
||||
211
drivers/input/sensors/gyro/icm4260x_gyro.c
Normal file
211
drivers/input/sensors/gyro/icm4260x_gyro.c
Normal file
@@ -0,0 +1,211 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2023 Rockchip Co.,Ltd.
|
||||
* Author: Wangqiang Guo <kay.guo@rock-chips.com>
|
||||
*/
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include <linux/sensor-dev.h>
|
||||
#include <linux/icm4260x.h>
|
||||
|
||||
static int sensor_active(struct i2c_client *client, int enable, int rate)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
int result = 0;
|
||||
int status = 0;
|
||||
|
||||
sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);
|
||||
|
||||
if (!enable) {
|
||||
status = (0xff & ~BIT_GYRO_MODE_MASK);
|
||||
sensor->ops->ctrl_data &= status;
|
||||
} else {
|
||||
status = BIT_GYRO_MODE_LNM;
|
||||
sensor->ops->ctrl_data |= status;
|
||||
sensor->ops->ctrl_data &= ~BIT_IDLE;
|
||||
}
|
||||
|
||||
result = sensor_write_reg(client, sensor->ops->ctrl_reg,
|
||||
sensor->ops->ctrl_data);
|
||||
if (result) {
|
||||
dev_err(&client->dev,
|
||||
"%s: fail to set pwr_mgmt0(%d)\n", __func__, result);
|
||||
return result;
|
||||
}
|
||||
/* Gyroscope needs to be kept ON for a minimum of 45ms */
|
||||
usleep_range(45*1000, 45*1010);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int sensor_init(struct i2c_client *client)
|
||||
{
|
||||
int ret = 0;
|
||||
u8 value;
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
|
||||
/*
|
||||
* init on icm42607_acc.c
|
||||
*/
|
||||
|
||||
/* set Full scale select for accelerometer UI interface output*/
|
||||
value = sensor_read_reg(client, ICM4260X_GYRO_CONFIG0);
|
||||
value &= ~BIT_GYRO_FSR;
|
||||
value |= GYRO_FS_SEL << SHIFT_GYRO_FS_SEL;
|
||||
ret = sensor_write_reg(client, ICM4260X_GYRO_CONFIG0, value);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* turn on accelerometer*/
|
||||
ret = sensor->ops->active(client, 0, sensor->pdata->poll_delay_ms);
|
||||
if (ret) {
|
||||
dev_err(&client->dev,
|
||||
"%s: fail to active sensor(%d)\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int gyro_report_value(struct i2c_client *client,
|
||||
struct sensor_axis *axis)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
|
||||
if (sensor->status_cur == SENSOR_ON) {
|
||||
/* Report acceleration sensor information */
|
||||
input_report_abs(sensor->input_dev, ABS_RX, axis->x);
|
||||
input_report_abs(sensor->input_dev, ABS_RY, axis->y);
|
||||
input_report_abs(sensor->input_dev, ABS_RZ, axis->z);
|
||||
input_sync(sensor->input_dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sensor_report_value(struct i2c_client *client)
|
||||
{
|
||||
struct sensor_private_data *sensor =
|
||||
(struct sensor_private_data *) i2c_get_clientdata(client);
|
||||
struct sensor_platform_data *pdata = sensor->pdata;
|
||||
int ret = 0;
|
||||
short x, y, z;
|
||||
struct sensor_axis axis;
|
||||
u8 buffer[6] = {0};
|
||||
|
||||
if (sensor->ops->read_len < 6) {
|
||||
dev_err(&client->dev, "%s: length is error, len = %d\n",
|
||||
__func__, sensor->ops->read_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*buffer = sensor->ops->read_reg;
|
||||
ret = sensor_rx_data(client, buffer, sensor->ops->read_len);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev,
|
||||
"%s: read data failed, ret = %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
x = ((buffer[0] << 8) & 0xff00) + (buffer[1] & 0xFF);
|
||||
y = ((buffer[2] << 8) & 0xff00) + (buffer[3] & 0xFF);
|
||||
z = ((buffer[4] << 8) & 0xff00) + (buffer[5] & 0xFF);
|
||||
|
||||
axis.x = (pdata->orientation[0]) * x + (pdata->orientation[1]) * y +
|
||||
(pdata->orientation[2]) * z;
|
||||
axis.y = (pdata->orientation[3]) * x + (pdata->orientation[4]) * y +
|
||||
(pdata->orientation[5]) * z;
|
||||
axis.z = (pdata->orientation[6]) * x + (pdata->orientation[7]) * y +
|
||||
(pdata->orientation[8]) * z;
|
||||
|
||||
gyro_report_value(client, &axis);
|
||||
|
||||
mutex_lock(&(sensor->data_mutex));
|
||||
sensor->axis = axis;
|
||||
mutex_unlock(&(sensor->data_mutex));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct sensor_operate gyro_icm4260x_ops = {
|
||||
.name = "icm4260x_gyro",
|
||||
.type = SENSOR_TYPE_GYROSCOPE,
|
||||
.id_i2c = GYRO_ID_ICM4260X,
|
||||
.read_reg = ICM4260X_GYRO_DATA_X0,
|
||||
.read_len = 6,
|
||||
.id_reg = SENSOR_UNKNOW_DATA,
|
||||
.id_data = SENSOR_UNKNOW_DATA,
|
||||
.precision = ICM4260X_PRECISION,
|
||||
.ctrl_reg = ICM4260X_PWR_MGMT_0,
|
||||
.int_status_reg = ICM4260X_INT_STATUS,
|
||||
.range = {-32768, 32768},
|
||||
.trig = IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
|
||||
.active = sensor_active,
|
||||
.init = sensor_init,
|
||||
.report = sensor_report_value,
|
||||
};
|
||||
|
||||
/****************operate according to sensor chip:end************/
|
||||
static int gyro_icm4260x_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *devid)
|
||||
{
|
||||
client->addr = ICM42607_ADDR;
|
||||
return sensor_register_device(client, NULL, devid, &gyro_icm4260x_ops);
|
||||
}
|
||||
|
||||
static void gyro_icm4260x_remove(struct i2c_client *client)
|
||||
{
|
||||
sensor_unregister_device(client, NULL, &gyro_icm4260x_ops);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id gyro_icm4260x_id[] = {
|
||||
{"icm42607_gyro", GYRO_ID_ICM4260X},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct i2c_driver gyro_icm4260x_driver = {
|
||||
.probe = gyro_icm4260x_probe,
|
||||
.remove = gyro_icm4260x_remove,
|
||||
.shutdown = sensor_shutdown,
|
||||
.id_table = gyro_icm4260x_id,
|
||||
.driver = {
|
||||
.name = "gyro_icm4260x",
|
||||
#ifdef CONFIG_PM
|
||||
.pm = &sensor_pm_ops,
|
||||
#endif
|
||||
},
|
||||
};
|
||||
|
||||
static int __init gyro_icm4260x_init(void)
|
||||
{
|
||||
return i2c_add_driver(&gyro_icm4260x_driver);
|
||||
}
|
||||
|
||||
static void __exit gyro_icm4260x_exit(void)
|
||||
{
|
||||
i2c_del_driver(&gyro_icm4260x_driver);
|
||||
}
|
||||
/* must register after icm4260x_acc */
|
||||
device_initcall_sync(gyro_icm4260x_init);
|
||||
module_exit(gyro_icm4260x_exit);
|
||||
|
||||
MODULE_AUTHOR("Wangqiang Guo <dave.wang@rock-chips.com>");
|
||||
MODULE_DESCRIPTION("icm4260x_gyro 3-Axis accelerometer driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -109,7 +109,7 @@ void gic_dist_config(void __iomem *base, int gic_irqs,
|
||||
|
||||
amp_pri = 0;
|
||||
for (j = 0; j < 4; j++) {
|
||||
if (rockchip_amp_check_amp_irq(i + j)) {
|
||||
if (rockchip_amp_need_init_amp_irq(i + j)) {
|
||||
amp_pri |= rockchip_amp_get_irq_prio(i + j) <<
|
||||
(j * 8);
|
||||
} else {
|
||||
|
||||
@@ -272,7 +272,8 @@ static int gic_irq_set_irqchip_state(struct irq_data *d,
|
||||
u32 reg;
|
||||
|
||||
#ifdef CONFIG_ROCKCHIP_AMP
|
||||
if (rockchip_amp_check_amp_irq(gic_irq(d)))
|
||||
if (which != IRQCHIP_STATE_PENDING &&
|
||||
rockchip_amp_check_amp_irq(gic_irq(d)))
|
||||
return -EINVAL;
|
||||
#endif
|
||||
switch (which) {
|
||||
@@ -528,7 +529,7 @@ static void gic_dist_init(struct gic_chip_data *gic)
|
||||
|
||||
maskval = 0;
|
||||
for (j = 0; j < 4; j++) {
|
||||
if (rockchip_amp_check_amp_irq(i + j)) {
|
||||
if (rockchip_amp_need_init_amp_irq(i + j)) {
|
||||
maskval |= rockchip_amp_get_irq_cpumask(i + j) <<
|
||||
(j * 8);
|
||||
} else {
|
||||
@@ -1362,6 +1363,9 @@ static int gic_init_bases(struct gic_chip_data *gic,
|
||||
goto error;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ROCKCHIP_AMP
|
||||
rockchip_amp_get_gic_info(gic->gic_irqs, GIC_V2);
|
||||
#endif
|
||||
gic_dist_init(gic);
|
||||
ret = gic_cpu_init(gic);
|
||||
if (ret)
|
||||
@@ -1569,10 +1573,6 @@ static int gic_of_setup(struct gic_chip_data *gic, struct device_node *node)
|
||||
|
||||
gic_enable_of_quirks(node, gic_quirks, gic);
|
||||
|
||||
#ifdef CONFIG_ROCKCHIP_AMP
|
||||
rockchip_amp_get_gic_info();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
|
||||
@@ -190,6 +190,7 @@ obj-$(CONFIG_VIDEO_RDACM21) += rdacm21.o
|
||||
obj-$(CONFIG_VIDEO_RJ54N1) += rj54n1cb0c.o
|
||||
obj-$(CONFIG_VIDEO_RK628) += rk628/
|
||||
obj-$(CONFIG_VIDEO_RK_IRCUT) += rk_ircut.o
|
||||
obj-$(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) += cam-tb-setup.o
|
||||
obj-$(CONFIG_VIDEO_S5C73M3) += s5c73m3/
|
||||
obj-$(CONFIG_VIDEO_S5K3L6XX) += s5k3l6xx.o
|
||||
obj-$(CONFIG_VIDEO_S5K4ECGX) += s5k4ecgx.o
|
||||
|
||||
97
drivers/media/i2c/cam-tb-setup.c
Normal file
97
drivers/media/i2c/cam-tb-setup.c
Normal file
@@ -0,0 +1,97 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (c) 2023 Rockchip Electronics Co., Ltd
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include "cam-tb-setup.h"
|
||||
|
||||
static u32 rk_cam_w;
|
||||
static u32 rk_cam_h;
|
||||
static u32 rk_cam_hdr;
|
||||
static u32 rk_cam_fps;
|
||||
|
||||
static int __init rk_cam_w_setup(char *str)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long val = 0;
|
||||
|
||||
ret = kstrtoul(str, 0, &val);
|
||||
if (!ret)
|
||||
rk_cam_w = (u32)val;
|
||||
else
|
||||
pr_err("get rk_cam_w fail\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 get_rk_cam_w(void)
|
||||
{
|
||||
return rk_cam_w;
|
||||
}
|
||||
EXPORT_SYMBOL(get_rk_cam_w);
|
||||
|
||||
static int __init rk_cam_h_setup(char *str)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long val = 0;
|
||||
|
||||
ret = kstrtoul(str, 0, &val);
|
||||
if (!ret)
|
||||
rk_cam_h = (u32)val;
|
||||
else
|
||||
pr_err("get rk_cam_h fail\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 get_rk_cam_h(void)
|
||||
{
|
||||
return rk_cam_h;
|
||||
}
|
||||
EXPORT_SYMBOL(get_rk_cam_h);
|
||||
|
||||
static int __init rk_cam_hdr_setup(char *str)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long val = 0;
|
||||
|
||||
ret = kstrtoul(str, 0, &val);
|
||||
if (!ret)
|
||||
rk_cam_hdr = (u32)val;
|
||||
else
|
||||
pr_err("get rk_cam_hdr fail\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 get_rk_cam_hdr(void)
|
||||
{
|
||||
return rk_cam_hdr;
|
||||
}
|
||||
EXPORT_SYMBOL(get_rk_cam_hdr);
|
||||
|
||||
static int __init __maybe_unused rk_cam_fps_setup(char *str)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long val = 0;
|
||||
|
||||
ret = kstrtoul(str, 0, &val);
|
||||
if (!ret)
|
||||
rk_cam_fps = (u32)val;
|
||||
else
|
||||
pr_err("get rk_cam_fps fail\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 get_rk_cam_fps(void)
|
||||
{
|
||||
return rk_cam_fps;
|
||||
}
|
||||
EXPORT_SYMBOL(get_rk_cam_fps);
|
||||
|
||||
__setup("rk_cam_w=", rk_cam_w_setup);
|
||||
__setup("rk_cam_h=", rk_cam_h_setup);
|
||||
__setup("rk_cam_hdr=", rk_cam_hdr_setup);
|
||||
__setup("rk_cam_fps=", rk_cam_fps_setup);
|
||||
33
drivers/media/i2c/cam-tb-setup.h
Normal file
33
drivers/media/i2c/cam-tb-setup.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (C) 2023 Rockchip Electronics Co., Ltd. */
|
||||
|
||||
#ifndef CAM_TB_SETUP_H
|
||||
#define CAM_TB_SETUP_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#ifdef CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP
|
||||
u32 get_rk_cam_w(void);
|
||||
u32 get_rk_cam_h(void);
|
||||
u32 get_rk_cam_hdr(void);
|
||||
u32 get_rk_cam_fps(void);
|
||||
#else
|
||||
static inline u32 get_rk_cam_w(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline u32 get_rk_cam_h(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline u32 get_rk_cam_hdr(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline u32 get_rk_cam_fps(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <media/v4l2-fwnode.h>
|
||||
#include <media/v4l2-subdev.h>
|
||||
#include "../platform/rockchip/isp/rkisp_tb_helper.h"
|
||||
#include "cam-tb-setup.h"
|
||||
|
||||
#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02)
|
||||
#define GC2093_NAME "gc2093"
|
||||
@@ -1607,68 +1608,6 @@ static const struct dev_pm_ops gc2093_pm_ops = {
|
||||
|
||||
|
||||
#ifdef CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP
|
||||
static u32 rk_cam_hdr;
|
||||
static u32 rk_cam_w;
|
||||
static u32 rk_cam_h;
|
||||
static u32 rk_cam_fps;
|
||||
|
||||
static int __init __maybe_unused rk_cam_hdr_setup(char *str)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long val = 0;
|
||||
|
||||
ret = kstrtoul(str, 0, &val);
|
||||
if (!ret)
|
||||
rk_cam_hdr = (u32)val;
|
||||
else
|
||||
pr_err("get rk_cam_hdr fail\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __init __maybe_unused rk_cam_w_setup(char *str)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long val = 0;
|
||||
|
||||
ret = kstrtoul(str, 0, &val);
|
||||
if (!ret)
|
||||
rk_cam_w = (u32)val;
|
||||
else
|
||||
pr_err("get rk_cam_w fail\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __init __maybe_unused rk_cam_h_setup(char *str)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long val = 0;
|
||||
|
||||
ret = kstrtoul(str, 0, &val);
|
||||
if (!ret)
|
||||
rk_cam_h = (u32)val;
|
||||
else
|
||||
pr_err("get rk_cam_h fail\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __init __maybe_unused rk_cam_fps_setup(char *str)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long val = 0;
|
||||
|
||||
ret = kstrtoul(str, 0, &val);
|
||||
if (!ret)
|
||||
rk_cam_fps = (u32)val;
|
||||
else
|
||||
pr_err("get rk_cam_fps fail\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
__setup("rk_cam_hdr=", rk_cam_hdr_setup);
|
||||
__setup("rk_cam_w=", rk_cam_w_setup);
|
||||
__setup("rk_cam_h=", rk_cam_h_setup);
|
||||
__setup("rk_cam_fps=", rk_cam_fps_setup);
|
||||
|
||||
static void find_terminal_resolution(struct gc2093 *gc2093)
|
||||
{
|
||||
int i = 0;
|
||||
@@ -1677,6 +1616,10 @@ static void find_terminal_resolution(struct gc2093 *gc2093)
|
||||
u32 cur_fps = 0;
|
||||
u32 dst_fps = 0;
|
||||
u32 tmp_fps = 0;
|
||||
u32 rk_cam_hdr = get_rk_cam_hdr();
|
||||
u32 rk_cam_w = get_rk_cam_w();
|
||||
u32 rk_cam_h = get_rk_cam_h();
|
||||
u32 rk_cam_fps = get_rk_cam_fps();
|
||||
|
||||
if (rk_cam_w == 0 || rk_cam_h == 0 ||
|
||||
rk_cam_fps == 0)
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
* V0.0X01.0X00 first version.
|
||||
* V0.0X01.0X01 fix if plugin_gpio was not used.
|
||||
* V0.0X01.0X02 modify driver init level to late_initcall.
|
||||
* V0.0X01.0X03 add 4K60 dual mipi support
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
@@ -34,12 +36,16 @@
|
||||
#include <media/v4l2-fwnode.h>
|
||||
#include "lt6911uxc.h"
|
||||
|
||||
#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x2)
|
||||
#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x3)
|
||||
#define LT6911UXC_NAME "LT6911UXC"
|
||||
|
||||
#define LT6911UXC_LINK_FREQ_HIGH 400000000
|
||||
#define LT6911UXC_LINK_FREQ_LOW 200000000
|
||||
#define LT6911UXC_PIXEL_RATE 400000000
|
||||
#define LT6911UXC_LINK_FREQ_650M 650000000
|
||||
#define LT6911UXC_LINK_FREQ_400M 400000000
|
||||
#define LT6911UXC_LINK_FREQ_300M 300000000
|
||||
#define LT6911UXC_LINK_FREQ_200M 200000000
|
||||
#define LT6911UXC_LINK_FREQ_100M 100000000
|
||||
#define LT6911UXC_LINK_FREQ_60M 60000000
|
||||
#define LT6911UXC_PIXEL_RATE 600000000
|
||||
|
||||
#define I2C_MAX_XFER_SIZE 128
|
||||
|
||||
@@ -54,8 +60,12 @@ module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "debug level (0-2)");
|
||||
|
||||
static const s64 link_freq_menu_items[] = {
|
||||
LT6911UXC_LINK_FREQ_HIGH,
|
||||
LT6911UXC_LINK_FREQ_LOW,
|
||||
LT6911UXC_LINK_FREQ_650M,
|
||||
LT6911UXC_LINK_FREQ_400M,
|
||||
LT6911UXC_LINK_FREQ_300M,
|
||||
LT6911UXC_LINK_FREQ_200M,
|
||||
LT6911UXC_LINK_FREQ_100M,
|
||||
LT6911UXC_LINK_FREQ_60M,
|
||||
};
|
||||
|
||||
struct lt6911uxc {
|
||||
@@ -78,6 +88,7 @@ struct lt6911uxc {
|
||||
struct v4l2_dv_timings timings;
|
||||
struct v4l2_mbus_config_mipi_csi2 bus;
|
||||
struct v4l2_subdev sd;
|
||||
struct rkmodule_multi_dev_info multi_dev_info;
|
||||
const char *len_name;
|
||||
const char *module_facing;
|
||||
const char *module_name;
|
||||
@@ -100,13 +111,25 @@ struct lt6911uxc_mode {
|
||||
u32 hts_def;
|
||||
u32 vts_def;
|
||||
u32 exp_def;
|
||||
u32 mipi_freq_idx;
|
||||
};
|
||||
|
||||
static struct rkmodule_csi_dphy_param rk3588_dcphy_param = {
|
||||
.vendor = PHY_VENDOR_SAMSUNG,
|
||||
.lp_vol_ref = 3,
|
||||
.lp_hys_sw = {3, 0, 3, 0},
|
||||
.lp_escclk_pol_sel = {1, 1, 0, 0},
|
||||
.skew_data_cal_clk = {0, 0, 0, 0},
|
||||
.clk_hs_term_sel = 2,
|
||||
.data_hs_term_sel = {2, 2, 2, 2},
|
||||
.reserved = {0},
|
||||
};
|
||||
|
||||
static const struct v4l2_dv_timings_cap lt6911uxc_timings_cap = {
|
||||
.type = V4L2_DV_BT_656_1120,
|
||||
/* keep this initialization for compatibility with GCC < 4.4.6 */
|
||||
.reserved = { 0 },
|
||||
V4L2_INIT_BT_TIMINGS(1, 10000, 1, 10000, 0, 400000000,
|
||||
V4L2_INIT_BT_TIMINGS(1, 10000, 1, 10000, 0, 600000000,
|
||||
V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
|
||||
V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
|
||||
V4L2_DV_BT_CAP_PROGRESSIVE |
|
||||
@@ -117,6 +140,16 @@ static const struct v4l2_dv_timings_cap lt6911uxc_timings_cap = {
|
||||
|
||||
static const struct lt6911uxc_mode supported_modes[] = {
|
||||
{
|
||||
.width = 3840,
|
||||
.height = 2160,
|
||||
.max_fps = {
|
||||
.numerator = 10000,
|
||||
.denominator = 600000,
|
||||
},
|
||||
.hts_def = 4400,
|
||||
.vts_def = 2250,
|
||||
.mipi_freq_idx = 0,
|
||||
}, {
|
||||
.width = 3840,
|
||||
.height = 2160,
|
||||
.max_fps = {
|
||||
@@ -125,6 +158,7 @@ static const struct lt6911uxc_mode supported_modes[] = {
|
||||
},
|
||||
.hts_def = 4400,
|
||||
.vts_def = 2250,
|
||||
.mipi_freq_idx = 0,
|
||||
}, {
|
||||
.width = 1920,
|
||||
.height = 1080,
|
||||
@@ -134,6 +168,7 @@ static const struct lt6911uxc_mode supported_modes[] = {
|
||||
},
|
||||
.hts_def = 2200,
|
||||
.vts_def = 1125,
|
||||
.mipi_freq_idx = 2,
|
||||
}, {
|
||||
.width = 1920,
|
||||
.height = 540,
|
||||
@@ -141,6 +176,7 @@ static const struct lt6911uxc_mode supported_modes[] = {
|
||||
.numerator = 10000,
|
||||
.denominator = 600000,
|
||||
},
|
||||
.mipi_freq_idx = 3,
|
||||
}, {
|
||||
.width = 1440,
|
||||
.height = 240,
|
||||
@@ -148,6 +184,7 @@ static const struct lt6911uxc_mode supported_modes[] = {
|
||||
.numerator = 10000,
|
||||
.denominator = 600000,
|
||||
},
|
||||
.mipi_freq_idx = 4,
|
||||
}, {
|
||||
.width = 1440,
|
||||
.height = 288,
|
||||
@@ -155,6 +192,7 @@ static const struct lt6911uxc_mode supported_modes[] = {
|
||||
.numerator = 10000,
|
||||
.denominator = 500000,
|
||||
},
|
||||
.mipi_freq_idx = 4,
|
||||
}, {
|
||||
.width = 1280,
|
||||
.height = 720,
|
||||
@@ -164,6 +202,7 @@ static const struct lt6911uxc_mode supported_modes[] = {
|
||||
},
|
||||
.hts_def = 1650,
|
||||
.vts_def = 750,
|
||||
.mipi_freq_idx = 3,
|
||||
}, {
|
||||
.width = 720,
|
||||
.height = 576,
|
||||
@@ -173,6 +212,7 @@ static const struct lt6911uxc_mode supported_modes[] = {
|
||||
},
|
||||
.hts_def = 864,
|
||||
.vts_def = 625,
|
||||
.mipi_freq_idx = 5,
|
||||
}, {
|
||||
.width = 720,
|
||||
.height = 480,
|
||||
@@ -182,6 +222,7 @@ static const struct lt6911uxc_mode supported_modes[] = {
|
||||
},
|
||||
.hts_def = 858,
|
||||
.vts_def = 525,
|
||||
.mipi_freq_idx = 5,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -390,6 +431,7 @@ static int lt6911uxc_get_detected_timings(struct v4l2_subdev *sd,
|
||||
u8 value, val_h, val_l;
|
||||
u32 fw_ver, mipi_byte_clk, mipi_bitrate;
|
||||
u8 fw_a, fw_b, fw_c, fw_d, lanes;
|
||||
u8 video_fmt;
|
||||
int ret;
|
||||
|
||||
memset(timings, 0, sizeof(struct v4l2_dv_timings));
|
||||
@@ -421,13 +463,15 @@ static int lt6911uxc_get_detected_timings(struct v4l2_subdev *sd,
|
||||
|
||||
i2c_rd8(sd, MIPI_LANES, &lanes);
|
||||
lt6911uxc->csi_lanes_in_use = lanes;
|
||||
if (lt6911uxc->csi_lanes_in_use == 8)
|
||||
v4l2_info(sd, "get 8 lane in use, set dual mipi mode\n");
|
||||
i2c_wr8(sd, FM1_DET_CLK_SRC_SEL, AD_LMTX_WRITE_CLK);
|
||||
i2c_rd8(sd, FREQ_METER_H, &clk_h);
|
||||
i2c_rd8(sd, FREQ_METER_M, &clk_m);
|
||||
i2c_rd8(sd, FREQ_METER_L, &clk_l);
|
||||
mipi_byte_clk = (((clk_h & 0xf) << 16) | (clk_m << 8) | clk_l);
|
||||
mipi_bitrate = mipi_byte_clk * 8 / 1000;
|
||||
v4l2_info(sd, "MIPI Byte clk: %dKHz, MIPI bitrate: %dMbps, lanes:%d\n",
|
||||
v4l2_info(sd, "MIPI Byte clk: %uKHz, MIPI bitrate: %uMbps, lanes:%d\n",
|
||||
mipi_byte_clk, mipi_bitrate, lanes);
|
||||
|
||||
i2c_rd8(sd, HTOTAL_H, &val_h);
|
||||
@@ -457,8 +501,16 @@ static int lt6911uxc_get_detected_timings(struct v4l2_subdev *sd,
|
||||
hbp = ((val_h << 8) | val_l) * 2;
|
||||
i2c_rd8(sd, VBP, &value);
|
||||
vbp = value;
|
||||
i2c_rd8(sd, COLOR_FMT_STATUS, &video_fmt);
|
||||
video_fmt = (video_fmt & GENMASK(6, 5)) >> 5;
|
||||
lt6911uxc_i2c_disable(sd);
|
||||
|
||||
if (video_fmt == 0x3) {
|
||||
lt6911uxc->nosignal = true;
|
||||
v4l2_err(sd, "%s ERROR: HDMI input YUV420, don't support YUV420!\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!lt6911uxc_rcv_supported_res(sd, hact, vact)) {
|
||||
lt6911uxc->nosignal = true;
|
||||
v4l2_err(sd, "%s: rcv err res, return no signal!\n", __func__);
|
||||
@@ -694,7 +746,6 @@ static int lt6911uxc_s_dv_timings(struct v4l2_subdev *sd,
|
||||
}
|
||||
|
||||
lt6911uxc->timings = *timings;
|
||||
|
||||
enable_stream(sd, false);
|
||||
|
||||
return 0;
|
||||
@@ -818,11 +869,50 @@ static int lt6911uxc_enum_frame_interval(struct v4l2_subdev *sd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lt6911uxc_get_reso_dist(const struct lt6911uxc_mode *mode,
|
||||
struct v4l2_dv_timings *timings)
|
||||
{
|
||||
struct v4l2_bt_timings *bt = &timings->bt;
|
||||
u32 cur_fps, dist_fps;
|
||||
|
||||
cur_fps = fps_calc(bt);
|
||||
dist_fps = DIV_ROUND_CLOSEST(mode->max_fps.denominator, mode->max_fps.numerator);
|
||||
|
||||
return abs(mode->width - bt->width) +
|
||||
abs(mode->height - bt->height) + abs(dist_fps - cur_fps);
|
||||
}
|
||||
|
||||
static const struct lt6911uxc_mode *
|
||||
lt6911uxc_find_best_fit(struct lt6911uxc *lt6911uxc)
|
||||
{
|
||||
int dist;
|
||||
int cur_best_fit = 0;
|
||||
int cur_best_fit_dist = -1;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
|
||||
dist = lt6911uxc_get_reso_dist(&supported_modes[i], <6911uxc->timings);
|
||||
if (cur_best_fit_dist == -1 || dist < cur_best_fit_dist) {
|
||||
cur_best_fit_dist = dist;
|
||||
cur_best_fit = i;
|
||||
}
|
||||
}
|
||||
dev_info(<6911uxc->i2c_client->dev,
|
||||
"find current mode: support_mode[%d], %dx%d@%dfps\n",
|
||||
cur_best_fit, supported_modes[cur_best_fit].width,
|
||||
supported_modes[cur_best_fit].height,
|
||||
DIV_ROUND_CLOSEST(supported_modes[cur_best_fit].max_fps.denominator,
|
||||
supported_modes[cur_best_fit].max_fps.numerator));
|
||||
|
||||
return &supported_modes[cur_best_fit];
|
||||
}
|
||||
|
||||
static int lt6911uxc_get_fmt(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_state *sd_state,
|
||||
struct v4l2_subdev_format *format)
|
||||
{
|
||||
struct lt6911uxc *lt6911uxc = to_state(sd);
|
||||
const struct lt6911uxc_mode *mode;
|
||||
|
||||
mutex_lock(<6911uxc->confctl_mutex);
|
||||
format->format.code = lt6911uxc->mbus_fmt_code;
|
||||
@@ -832,6 +922,14 @@ static int lt6911uxc_get_fmt(struct v4l2_subdev *sd,
|
||||
lt6911uxc->timings.bt.interlaced ?
|
||||
V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE;
|
||||
format->format.colorspace = V4L2_COLORSPACE_SRGB;
|
||||
|
||||
mode = lt6911uxc_find_best_fit(lt6911uxc);
|
||||
lt6911uxc->cur_mode = mode;
|
||||
__v4l2_ctrl_s_ctrl_int64(lt6911uxc->pixel_rate,
|
||||
LT6911UXC_PIXEL_RATE);
|
||||
__v4l2_ctrl_s_ctrl(lt6911uxc->link_freq,
|
||||
mode->mipi_freq_idx);
|
||||
|
||||
mutex_unlock(<6911uxc->confctl_mutex);
|
||||
|
||||
v4l2_dbg(1, debug, sd, "%s: fmt code:%d, w:%d, h:%d, field mode:%s\n",
|
||||
@@ -841,40 +939,12 @@ static int lt6911uxc_get_fmt(struct v4l2_subdev *sd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lt6911uxc_get_reso_dist(const struct lt6911uxc_mode *mode,
|
||||
struct v4l2_mbus_framefmt *framefmt)
|
||||
{
|
||||
return abs(mode->width - framefmt->width) +
|
||||
abs(mode->height - framefmt->height);
|
||||
}
|
||||
|
||||
static const struct lt6911uxc_mode *
|
||||
lt6911uxc_find_best_fit(struct v4l2_subdev_format *fmt)
|
||||
{
|
||||
struct v4l2_mbus_framefmt *framefmt = &fmt->format;
|
||||
int dist;
|
||||
int cur_best_fit = 0;
|
||||
int cur_best_fit_dist = -1;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
|
||||
dist = lt6911uxc_get_reso_dist(&supported_modes[i], framefmt);
|
||||
if (cur_best_fit_dist == -1 || dist < cur_best_fit_dist) {
|
||||
cur_best_fit_dist = dist;
|
||||
cur_best_fit = i;
|
||||
}
|
||||
}
|
||||
|
||||
return &supported_modes[cur_best_fit];
|
||||
}
|
||||
|
||||
static int lt6911uxc_set_fmt(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_state *sd_state,
|
||||
struct v4l2_subdev_format *format)
|
||||
{
|
||||
struct lt6911uxc *lt6911uxc = to_state(sd);
|
||||
const struct lt6911uxc_mode *mode;
|
||||
int index;
|
||||
|
||||
/* is overwritten by get_fmt */
|
||||
u32 code = format->format.code;
|
||||
@@ -897,20 +967,10 @@ static int lt6911uxc_set_fmt(struct v4l2_subdev *sd,
|
||||
return 0;
|
||||
|
||||
lt6911uxc->mbus_fmt_code = format->format.code;
|
||||
mode = lt6911uxc_find_best_fit(format);
|
||||
mode = lt6911uxc_find_best_fit(lt6911uxc);
|
||||
lt6911uxc->cur_mode = mode;
|
||||
enable_stream(sd, false);
|
||||
|
||||
if (((mode->width == 720) && (mode->height == 576)) ||
|
||||
((mode->width == 720) && (mode->height == 480)))
|
||||
index = 1;
|
||||
else
|
||||
index = 0;
|
||||
|
||||
__v4l2_ctrl_s_ctrl(lt6911uxc->link_freq, index);
|
||||
v4l2_dbg(1, debug, sd, "%s res wxh:%dx%d, link freq:%llu", __func__,
|
||||
mode->width, mode->height, link_freq_menu_items[index]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -939,7 +999,10 @@ static void lt6911uxc_get_module_inf(struct lt6911uxc *lt6911uxc,
|
||||
static long lt6911uxc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
|
||||
{
|
||||
struct lt6911uxc *lt6911uxc = to_state(sd);
|
||||
struct device *dev = <6911uxc->i2c_client->dev;
|
||||
long ret = 0;
|
||||
struct rkmodule_csi_dphy_param *dphy_param;
|
||||
struct rkmodule_capture_info *capture_info;
|
||||
|
||||
switch (cmd) {
|
||||
case RKMODULE_GET_MODULE_INFO:
|
||||
@@ -948,6 +1011,29 @@ static long lt6911uxc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
|
||||
case RKMODULE_GET_HDMI_MODE:
|
||||
*(int *)arg = RKMODULE_HDMIIN_MODE;
|
||||
break;
|
||||
case RKMODULE_SET_CSI_DPHY_PARAM:
|
||||
dphy_param = (struct rkmodule_csi_dphy_param *)arg;
|
||||
if (dphy_param->vendor == PHY_VENDOR_SAMSUNG)
|
||||
rk3588_dcphy_param = *dphy_param;
|
||||
dev_dbg(<6911uxc->i2c_client->dev,
|
||||
"sensor set dphy param\n");
|
||||
break;
|
||||
case RKMODULE_GET_CSI_DPHY_PARAM:
|
||||
dphy_param = (struct rkmodule_csi_dphy_param *)arg;
|
||||
*dphy_param = rk3588_dcphy_param;
|
||||
dev_dbg(<6911uxc->i2c_client->dev,
|
||||
"sensor get dphy param\n");
|
||||
break;
|
||||
case RKMODULE_GET_CAPTURE_MODE:
|
||||
capture_info = (struct rkmodule_capture_info *)arg;
|
||||
if (lt6911uxc->csi_lanes_in_use == 8) {
|
||||
dev_info(dev, "8 lanes in use, set dual mipi mode\n");
|
||||
capture_info->mode = RKMODULE_MULTI_DEV_COMBINE_ONE;
|
||||
capture_info->multi_dev = lt6911uxc->multi_dev_info;
|
||||
} else {
|
||||
capture_info->mode = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = -ENOIOCTLCMD;
|
||||
break;
|
||||
@@ -964,6 +1050,8 @@ static long lt6911uxc_compat_ioctl32(struct v4l2_subdev *sd,
|
||||
struct rkmodule_inf *inf;
|
||||
long ret;
|
||||
int *seq;
|
||||
struct rkmodule_csi_dphy_param *dphy_param;
|
||||
struct rkmodule_capture_info *capture_info;
|
||||
|
||||
switch (cmd) {
|
||||
case RKMODULE_GET_MODULE_INFO:
|
||||
@@ -996,6 +1084,50 @@ static long lt6911uxc_compat_ioctl32(struct v4l2_subdev *sd,
|
||||
}
|
||||
kfree(seq);
|
||||
break;
|
||||
case RKMODULE_SET_CSI_DPHY_PARAM:
|
||||
dphy_param = kzalloc(sizeof(*dphy_param), GFP_KERNEL);
|
||||
if (!dphy_param) {
|
||||
ret = -ENOMEM;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = copy_from_user(dphy_param, up, sizeof(*dphy_param));
|
||||
if (!ret)
|
||||
ret = lt6911uxc_ioctl(sd, cmd, dphy_param);
|
||||
else
|
||||
ret = -EFAULT;
|
||||
kfree(dphy_param);
|
||||
break;
|
||||
case RKMODULE_GET_CSI_DPHY_PARAM:
|
||||
dphy_param = kzalloc(sizeof(*dphy_param), GFP_KERNEL);
|
||||
if (!dphy_param) {
|
||||
ret = -ENOMEM;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = lt6911uxc_ioctl(sd, cmd, dphy_param);
|
||||
if (!ret) {
|
||||
ret = copy_to_user(up, dphy_param, sizeof(*dphy_param));
|
||||
if (ret)
|
||||
ret = -EFAULT;
|
||||
}
|
||||
kfree(dphy_param);
|
||||
break;
|
||||
case RKMODULE_GET_CAPTURE_MODE:
|
||||
capture_info = kzalloc(sizeof(*capture_info), GFP_KERNEL);
|
||||
if (!capture_info) {
|
||||
ret = -ENOMEM;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = lt6911uxc_ioctl(sd, cmd, capture_info);
|
||||
if (!ret) {
|
||||
ret = copy_to_user(up, capture_info, sizeof(*capture_info));
|
||||
if (ret)
|
||||
ret = -EFAULT;
|
||||
}
|
||||
kfree(capture_info);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOIOCTLCMD;
|
||||
break;
|
||||
@@ -1075,9 +1207,11 @@ static void lt6911uxc_reset(struct lt6911uxc *lt6911uxc)
|
||||
|
||||
static int lt6911uxc_init_v4l2_ctrls(struct lt6911uxc *lt6911uxc)
|
||||
{
|
||||
const struct lt6911uxc_mode *mode;
|
||||
struct v4l2_subdev *sd;
|
||||
int ret;
|
||||
|
||||
mode = lt6911uxc->cur_mode;
|
||||
sd = <6911uxc->sd;
|
||||
ret = v4l2_ctrl_handler_init(<6911uxc->hdl, 5);
|
||||
if (ret)
|
||||
@@ -1087,8 +1221,9 @@ static int lt6911uxc_init_v4l2_ctrls(struct lt6911uxc *lt6911uxc)
|
||||
V4L2_CID_LINK_FREQ,
|
||||
ARRAY_SIZE(link_freq_menu_items) - 1, 0,
|
||||
link_freq_menu_items);
|
||||
v4l2_ctrl_new_std(<6911uxc->hdl, NULL, V4L2_CID_PIXEL_RATE,
|
||||
0, LT6911UXC_PIXEL_RATE, 1, LT6911UXC_PIXEL_RATE);
|
||||
lt6911uxc->pixel_rate = v4l2_ctrl_new_std(<6911uxc->hdl, NULL,
|
||||
V4L2_CID_PIXEL_RATE,
|
||||
0, LT6911UXC_PIXEL_RATE, 1, LT6911UXC_PIXEL_RATE);
|
||||
|
||||
lt6911uxc->detect_tx_5v_ctrl = v4l2_ctrl_new_std(<6911uxc->hdl,
|
||||
NULL, V4L2_CID_DV_RX_POWER_PRESENT,
|
||||
@@ -1107,6 +1242,9 @@ static int lt6911uxc_init_v4l2_ctrls(struct lt6911uxc *lt6911uxc)
|
||||
return ret;
|
||||
}
|
||||
|
||||
__v4l2_ctrl_s_ctrl(lt6911uxc->link_freq, mode->mipi_freq_idx);
|
||||
__v4l2_ctrl_s_ctrl_int64(lt6911uxc->pixel_rate, LT6911UXC_PIXEL_RATE);
|
||||
|
||||
if (lt6911uxc_update_controls(sd)) {
|
||||
ret = -ENODEV;
|
||||
v4l2_err(sd, "update v4l2 ctrls failed! ret:%d\n", ret);
|
||||
@@ -1291,6 +1429,36 @@ static struct attribute *lt6911_attrs[] = {
|
||||
};
|
||||
ATTRIBUTE_GROUPS(lt6911);
|
||||
|
||||
static int lt6911uxc_get_multi_dev_info(struct lt6911uxc *lt6911uxc)
|
||||
{
|
||||
struct device *dev = <6911uxc->i2c_client->dev;
|
||||
struct device_node *node = dev->of_node;
|
||||
struct device_node *multi_info_np;
|
||||
|
||||
multi_info_np = of_get_child_by_name(node, "multi-dev-info");
|
||||
if (!multi_info_np) {
|
||||
dev_info(dev, "failed to get multi dev info\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
of_property_read_u32(multi_info_np, "dev-idx-l",
|
||||
<6911uxc->multi_dev_info.dev_idx[0]);
|
||||
of_property_read_u32(multi_info_np, "dev-idx-r",
|
||||
<6911uxc->multi_dev_info.dev_idx[1]);
|
||||
of_property_read_u32(multi_info_np, "combine-idx",
|
||||
<6911uxc->multi_dev_info.combine_idx[0]);
|
||||
of_property_read_u32(multi_info_np, "pixel-offset",
|
||||
<6911uxc->multi_dev_info.pixel_offset);
|
||||
of_property_read_u32(multi_info_np, "dev-num",
|
||||
<6911uxc->multi_dev_info.dev_num);
|
||||
dev_info(dev,
|
||||
"multi dev left: mipi%d, multi dev right: mipi%d, combile mipi%d, dev num: %d\n",
|
||||
lt6911uxc->multi_dev_info.dev_idx[0], lt6911uxc->multi_dev_info.dev_idx[1],
|
||||
lt6911uxc->multi_dev_info.combine_idx[0], lt6911uxc->multi_dev_info.dev_num);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lt6911uxc_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
@@ -1323,6 +1491,10 @@ static int lt6911uxc_probe(struct i2c_client *client,
|
||||
return err;
|
||||
}
|
||||
|
||||
err = lt6911uxc_get_multi_dev_info(lt6911uxc);
|
||||
if (err)
|
||||
v4l2_info(sd, "get multi dev info failed, not use dual mipi mode\n");
|
||||
|
||||
err = lt6911uxc_check_chip_id(lt6911uxc);
|
||||
if (err < 0)
|
||||
return err;
|
||||
@@ -1477,9 +1649,10 @@ static void __exit lt6911uxc_driver_exit(void)
|
||||
i2c_del_driver(<6911uxc_driver);
|
||||
}
|
||||
|
||||
late_initcall(lt6911uxc_driver_init);
|
||||
device_initcall_sync(lt6911uxc_driver_init);
|
||||
module_exit(lt6911uxc_driver_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Lontium LT6911UXC HDMI to MIPI CSI-2 bridge driver");
|
||||
MODULE_AUTHOR("Dingxian Wen <shawn.wen@rock-chips.com>");
|
||||
MODULE_AUTHOR("Jianwei Fan <jianwei.fan@rock-chips.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
@@ -65,4 +65,9 @@
|
||||
#define AUDIO_SAMPLE_RATAE_H 0xb0aa
|
||||
#define AUDIO_SAMPLE_RATAE_L 0xb0ab
|
||||
|
||||
#define COLOR_FMT_STATUS 0xb092
|
||||
#define STREAM_CTRL 0x811d
|
||||
#define STREAM_ENABLE 0xFB
|
||||
#define STREAM_DISABLE 0xBB
|
||||
|
||||
#endif
|
||||
|
||||
@@ -7,7 +7,8 @@ maxim4c-objs += maxim4c_i2c.o \
|
||||
maxim4c_remote.o \
|
||||
maxim4c_pattern.o \
|
||||
maxim4c_v4l2.o \
|
||||
maxim4c_drv.o
|
||||
maxim4c_drv.o \
|
||||
maxim4c_debugfs.o
|
||||
|
||||
obj-$(CONFIG_MAXIM4C_SER_MAX9295) += remote_max9295.o
|
||||
obj-$(CONFIG_MAXIM4C_SER_MAX96715) += remote_max96715.o
|
||||
|
||||
@@ -98,4 +98,7 @@ int maxim4c_pattern_support_mode_init(maxim4c_t *maxim4c);
|
||||
int maxim4c_pattern_data_init(maxim4c_t *maxim4c);
|
||||
int maxim4c_pattern_enable(maxim4c_t *maxim4c, bool enable);
|
||||
|
||||
int maxim4c_dbgfs_init(maxim4c_t *maxim4c);
|
||||
void maxim4c_dbgfs_deinit(maxim4c_t *maxim4c);
|
||||
|
||||
#endif /* __MAXIM4C_API_H__ */
|
||||
|
||||
60
drivers/media/i2c/maxim4c/maxim4c_debugfs.c
Normal file
60
drivers/media/i2c/maxim4c/maxim4c_debugfs.c
Normal file
@@ -0,0 +1,60 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Maxim Quad GMSL Deserializer debugfs helper functions
|
||||
*
|
||||
* Copyright (C) 2023 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
* Author: Cai Wenzhong <cwz@rock-chips.com>
|
||||
*
|
||||
*/
|
||||
#include <linux/export.h>
|
||||
#include <linux/debugfs.h>
|
||||
|
||||
#include "maxim4c_api.h"
|
||||
|
||||
int maxim4c_dbgfs_init(maxim4c_t *maxim4c)
|
||||
{
|
||||
struct dentry *entry;
|
||||
|
||||
entry = debugfs_create_dir("maxim4c", NULL);
|
||||
|
||||
debugfs_create_u8("timing_override_en", 0600, entry,
|
||||
&maxim4c->mipi_txphy.timing_override_en);
|
||||
|
||||
debugfs_create_u8("t_hs_przero", 0600, entry,
|
||||
&maxim4c->mipi_txphy.timing.t_hs_przero);
|
||||
debugfs_create_u8("t_hs_prep", 0600, entry,
|
||||
&maxim4c->mipi_txphy.timing.t_hs_prep);
|
||||
debugfs_create_u8("t_clk_trail", 0600, entry,
|
||||
&maxim4c->mipi_txphy.timing.t_clk_trail);
|
||||
debugfs_create_u8("t_clk_przero", 0600, entry,
|
||||
&maxim4c->mipi_txphy.timing.t_clk_przero);
|
||||
debugfs_create_u8("t_lpx", 0600, entry, &maxim4c->mipi_txphy.timing.t_lpx);
|
||||
debugfs_create_u8("t_hs_trail", 0600, entry,
|
||||
&maxim4c->mipi_txphy.timing.t_hs_trail);
|
||||
|
||||
debugfs_create_u8("t_clk_prep", 0600, entry,
|
||||
&maxim4c->mipi_txphy.timing.t_clk_prep);
|
||||
debugfs_create_u8("t_lpxesc", 0600, entry,
|
||||
&maxim4c->mipi_txphy.timing.t_lpxesc);
|
||||
|
||||
debugfs_create_u8("csi2_t_pre", 0600, entry,
|
||||
&maxim4c->mipi_txphy.timing.csi2_t_pre);
|
||||
debugfs_create_u8("csi2_t_post", 0600, entry,
|
||||
&maxim4c->mipi_txphy.timing.csi2_t_post);
|
||||
debugfs_create_u8("csi2_tx_gap", 0600, entry,
|
||||
&maxim4c->mipi_txphy.timing.csi2_tx_gap);
|
||||
debugfs_create_u32("csi2_twakeup", 0600, entry,
|
||||
&maxim4c->mipi_txphy.timing.csi2_twakeup);
|
||||
|
||||
maxim4c->dbgfs_root = entry;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(maxim4c_dbgfs_init);
|
||||
|
||||
void maxim4c_dbgfs_deinit(maxim4c_t *maxim4c)
|
||||
{
|
||||
debugfs_remove_recursive(maxim4c->dbgfs_root);
|
||||
}
|
||||
EXPORT_SYMBOL(maxim4c_dbgfs_deinit);
|
||||
@@ -29,6 +29,11 @@
|
||||
* V2.03.00
|
||||
* 1. remote device add the maxim4c prefix to driver name.
|
||||
*
|
||||
* V2.04.02
|
||||
* 1. Add regulator supplier dependencies.
|
||||
* 2. Add config ssc-ratio property
|
||||
* 3. Add debugfs entry to change MIPI timing
|
||||
*
|
||||
*/
|
||||
#include <linux/clk.h>
|
||||
#include <linux/i2c.h>
|
||||
@@ -58,10 +63,15 @@
|
||||
|
||||
#include "maxim4c_api.h"
|
||||
|
||||
#define DRIVER_VERSION KERNEL_VERSION(2, 0x03, 0x00)
|
||||
#define DRIVER_VERSION KERNEL_VERSION(2, 0x04, 0x02)
|
||||
|
||||
#define MAXIM4C_XVCLK_FREQ 25000000
|
||||
|
||||
static const char *const maxim4c_supply_names[MAXIM4C_NUM_SUPPLIES] = {
|
||||
"vcc1v2",
|
||||
"vcc1v8",
|
||||
};
|
||||
|
||||
static int maxim4c_check_local_chipid(maxim4c_t *maxim4c)
|
||||
{
|
||||
struct i2c_client *client = maxim4c->client;
|
||||
@@ -302,6 +312,13 @@ static inline u32 maxim4c_cal_delay(u32 cycles)
|
||||
static int maxim4c_local_device_power_on(maxim4c_t *maxim4c)
|
||||
{
|
||||
struct device *dev = &maxim4c->client->dev;
|
||||
int ret;
|
||||
|
||||
ret = regulator_bulk_enable(MAXIM4C_NUM_SUPPLIES, maxim4c->supplies);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enable regulators\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!IS_ERR(maxim4c->pwdn_gpio)) {
|
||||
dev_info(dev, "local device pwdn gpio on\n");
|
||||
@@ -317,24 +334,30 @@ static int maxim4c_local_device_power_on(maxim4c_t *maxim4c)
|
||||
static void maxim4c_local_device_power_off(maxim4c_t *maxim4c)
|
||||
{
|
||||
struct device *dev = &maxim4c->client->dev;
|
||||
int ret;
|
||||
|
||||
if (!IS_ERR(maxim4c->pwdn_gpio)) {
|
||||
dev_info(dev, "local device pwdn gpio off\n");
|
||||
|
||||
gpiod_set_value_cansleep(maxim4c->pwdn_gpio, 0);
|
||||
}
|
||||
|
||||
ret = regulator_bulk_disable(MAXIM4C_NUM_SUPPLIES, maxim4c->supplies);
|
||||
if (ret < 0) {
|
||||
dev_warn(dev, "Failed to disable regulators\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int maxim4c_remote_device_power_on(maxim4c_t *maxim4c)
|
||||
{
|
||||
struct device *dev = &maxim4c->client->dev;
|
||||
int ret;
|
||||
|
||||
// remote PoC enable
|
||||
if (!IS_ERR(maxim4c->pocen_gpio)) {
|
||||
dev_info(dev, "remote device pocen gpio on\n");
|
||||
|
||||
gpiod_set_value_cansleep(maxim4c->pocen_gpio, 1);
|
||||
usleep_range(5000, 10000);
|
||||
dev_dbg(dev, "Turn PoC on\n");
|
||||
ret = regulator_enable(maxim4c->poc_regulator);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Unable to turn PoC on\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -343,13 +366,12 @@ static int maxim4c_remote_device_power_on(maxim4c_t *maxim4c)
|
||||
static int maxim4c_remote_device_power_off(maxim4c_t *maxim4c)
|
||||
{
|
||||
struct device *dev = &maxim4c->client->dev;
|
||||
int ret;
|
||||
|
||||
// remote PoC enable
|
||||
if (!IS_ERR(maxim4c->pocen_gpio)) {
|
||||
dev_info(dev, "remote device pocen gpio off\n");
|
||||
|
||||
gpiod_set_value_cansleep(maxim4c->pocen_gpio, 0);
|
||||
}
|
||||
dev_dbg(dev, "Turn PoC off\n");
|
||||
ret = regulator_disable(maxim4c->poc_regulator);
|
||||
if (ret < 0)
|
||||
dev_warn(dev, "Unable to turn PoC off\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -581,6 +603,7 @@ static int maxim4c_probe(struct i2c_client *client,
|
||||
maxim4c_t *maxim4c = NULL;
|
||||
u32 chip_id;
|
||||
int ret = 0;
|
||||
unsigned int i;
|
||||
|
||||
dev_info(dev, "driver version: %02x.%02x.%02x", DRIVER_VERSION >> 16,
|
||||
(DRIVER_VERSION & 0xff00) >> 8, DRIVER_VERSION & 0x00ff);
|
||||
@@ -621,14 +644,37 @@ static int maxim4c_probe(struct i2c_client *client,
|
||||
if (IS_ERR(maxim4c->pwdn_gpio))
|
||||
dev_warn(dev, "Failed to get pwdn-gpios, maybe no use\n");
|
||||
|
||||
maxim4c->pocen_gpio = devm_gpiod_get(dev, "pocen", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(maxim4c->pocen_gpio))
|
||||
dev_warn(dev, "Failed to get pocen-gpios\n");
|
||||
|
||||
maxim4c->lock_gpio = devm_gpiod_get(dev, "lock", GPIOD_IN);
|
||||
if (IS_ERR(maxim4c->lock_gpio))
|
||||
dev_warn(dev, "Failed to get lock-gpios\n");
|
||||
|
||||
for (i = 0; i < MAXIM4C_NUM_SUPPLIES; i++)
|
||||
maxim4c->supplies[i].supply = maxim4c_supply_names[i];
|
||||
|
||||
ret = devm_regulator_bulk_get(dev, MAXIM4C_NUM_SUPPLIES,
|
||||
maxim4c->supplies);
|
||||
if (ret < 0) {
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "Unable to get supply regulators\n");
|
||||
else
|
||||
dev_warn(dev, "Get PoC regulator deferred\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
maxim4c->poc_regulator = devm_regulator_get(dev, "poc");
|
||||
if (IS_ERR(maxim4c->poc_regulator)) {
|
||||
if (PTR_ERR(maxim4c->poc_regulator) != -EPROBE_DEFER)
|
||||
dev_err(dev, "Unable to get PoC regulator (%ld)\n",
|
||||
PTR_ERR(maxim4c->poc_regulator));
|
||||
else
|
||||
dev_err(dev, "Get PoC regulator deferred\n");
|
||||
|
||||
ret = PTR_ERR(maxim4c->poc_regulator);
|
||||
#if !MAXIM4C_TEST_PATTERN
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
mutex_init(&maxim4c->mutex);
|
||||
|
||||
ret = maxim4c_local_device_power_on(maxim4c);
|
||||
@@ -668,15 +714,19 @@ static int maxim4c_probe(struct i2c_client *client,
|
||||
maxim4c_module_data_init(maxim4c);
|
||||
maxim4c_module_parse_dt(maxim4c);
|
||||
|
||||
ret = maxim4c_dbgfs_init(maxim4c);
|
||||
if (ret)
|
||||
goto err_subdev_deinit;
|
||||
|
||||
#if (MAXIM4C_LOCAL_DES_ON_OFF_EN == 0)
|
||||
ret = maxim4c_module_hw_init(maxim4c);
|
||||
if (ret)
|
||||
goto err_subdev_deinit;
|
||||
goto err_dbgfs_deinit;
|
||||
#endif /* MAXIM4C_LOCAL_DES_ON_OFF_EN */
|
||||
|
||||
ret = maxim4c_remote_mfd_add_devices(maxim4c);
|
||||
if (ret)
|
||||
goto err_subdev_deinit;
|
||||
goto err_dbgfs_deinit;
|
||||
|
||||
maxim4c_lock_irq_init(maxim4c);
|
||||
maxim4c_lock_state_work_init(maxim4c);
|
||||
@@ -687,6 +737,8 @@ static int maxim4c_probe(struct i2c_client *client,
|
||||
|
||||
return 0;
|
||||
|
||||
err_dbgfs_deinit:
|
||||
maxim4c_dbgfs_deinit(maxim4c);
|
||||
err_subdev_deinit:
|
||||
maxim4c_v4l2_subdev_deinit(maxim4c);
|
||||
err_power_off:
|
||||
@@ -703,6 +755,8 @@ static int maxim4c_remove(struct i2c_client *client)
|
||||
|
||||
maxim4c_lock_state_work_deinit(maxim4c);
|
||||
|
||||
maxim4c_dbgfs_deinit(maxim4c);
|
||||
|
||||
maxim4c_v4l2_subdev_deinit(maxim4c);
|
||||
|
||||
mutex_destroy(&maxim4c->mutex);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/rk-camera-module.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <media/media-entity.h>
|
||||
#include <media/v4l2-async.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
@@ -28,6 +29,8 @@
|
||||
#define MAX96712_CHIP_ID 0xA0
|
||||
#define MAX96722_CHIP_ID 0xA1
|
||||
|
||||
#define MAXIM4C_NUM_SUPPLIES 2
|
||||
|
||||
enum {
|
||||
MAXIM4C_HOT_PLUG_OUT = 0,
|
||||
MAXIM4C_HOT_PLUG_IN,
|
||||
@@ -57,8 +60,9 @@ typedef struct maxim4c {
|
||||
struct i2c_client *client;
|
||||
struct clk *xvclk;
|
||||
struct gpio_desc *pwdn_gpio;
|
||||
struct gpio_desc *pocen_gpio;
|
||||
struct gpio_desc *lock_gpio;
|
||||
struct regulator_bulk_data supplies[MAXIM4C_NUM_SUPPLIES];
|
||||
struct regulator *poc_regulator;
|
||||
|
||||
struct mutex mutex;
|
||||
|
||||
@@ -104,6 +108,8 @@ typedef struct maxim4c {
|
||||
|
||||
struct mfd_cell remote_mfd_devs[MAXIM4C_LINK_ID_MAX];
|
||||
maxim4c_remote_t *remote_device[MAXIM4C_LINK_ID_MAX];
|
||||
|
||||
struct dentry *dbgfs_root;
|
||||
} maxim4c_t;
|
||||
|
||||
#endif /* __MAXIM4C_DRV_H__ */
|
||||
|
||||
@@ -11,6 +11,82 @@
|
||||
|
||||
#include "maxim4c_api.h"
|
||||
|
||||
static int maxim4c_txphy_init_timing(maxim4c_t *maxim4c)
|
||||
{
|
||||
struct i2c_client *client = maxim4c->client;
|
||||
int ret = 0;
|
||||
u16 reg_addr = 0;
|
||||
u8 reg_mask;
|
||||
u8 timing;
|
||||
u8 phy_idx = 0;
|
||||
|
||||
if (!maxim4c->mipi_txphy.timing_override_en)
|
||||
return 0;
|
||||
|
||||
timing = ((maxim4c->mipi_txphy.timing.t_hs_przero & 0x3) << 6 |
|
||||
(maxim4c->mipi_txphy.timing.t_hs_prep & 0x3) << 4 |
|
||||
(maxim4c->mipi_txphy.timing.t_clk_trail & 0x3) << 2 |
|
||||
(maxim4c->mipi_txphy.timing.t_clk_przero & 0x3) << 0);
|
||||
|
||||
ret |= maxim4c_i2c_write_byte(client, 0x08A1,
|
||||
MAXIM4C_I2C_REG_ADDR_16BITS, timing);
|
||||
|
||||
reg_mask = 0x0F;
|
||||
timing = ((maxim4c->mipi_txphy.timing.t_lpx & 0x3) << 2 |
|
||||
(maxim4c->mipi_txphy.timing.t_hs_trail & 0x3) << 0);
|
||||
|
||||
ret |= maxim4c_i2c_update_byte(
|
||||
client, 0x08A2, MAXIM4C_I2C_REG_ADDR_16BITS, reg_mask, timing);
|
||||
|
||||
reg_mask = (0x3 << 6);
|
||||
timing = (maxim4c->mipi_txphy.timing.t_lpxesc & 0x3) << 6;
|
||||
ret |= maxim4c_i2c_update_byte(
|
||||
client, 0x08A5, MAXIM4C_I2C_REG_ADDR_16BITS, reg_mask, timing);
|
||||
|
||||
reg_mask = (0x7 << 5);
|
||||
timing = (maxim4c->mipi_txphy.timing.t_lpxesc & 0x7) << 5;
|
||||
ret |= maxim4c_i2c_update_byte(
|
||||
client, 0x08A8, MAXIM4C_I2C_REG_ADDR_16BITS, reg_mask, timing);
|
||||
|
||||
for (phy_idx = 0; phy_idx < MAXIM4C_TXPHY_ID_MAX; phy_idx++) {
|
||||
reg_mask = 0xFF;
|
||||
reg_addr = 0x0905 + 0x40 * phy_idx;
|
||||
timing = maxim4c->mipi_txphy.timing.csi2_t_pre;
|
||||
ret |= maxim4c_i2c_update_byte(client, reg_addr,
|
||||
MAXIM4C_I2C_REG_ADDR_16BITS,
|
||||
reg_mask, timing);
|
||||
|
||||
reg_addr = 0x0906 + 0x40 * phy_idx;
|
||||
timing = maxim4c->mipi_txphy.timing.csi2_t_post;
|
||||
ret |= maxim4c_i2c_update_byte(client, reg_addr,
|
||||
MAXIM4C_I2C_REG_ADDR_16BITS,
|
||||
reg_mask, timing);
|
||||
|
||||
reg_addr = 0x0907 + 0x40 * phy_idx;
|
||||
timing = maxim4c->mipi_txphy.timing.csi2_tx_gap;
|
||||
ret |= maxim4c_i2c_update_byte(client, reg_addr,
|
||||
MAXIM4C_I2C_REG_ADDR_16BITS,
|
||||
reg_mask, timing);
|
||||
|
||||
reg_addr = 0x0908 + 0x40 * phy_idx;
|
||||
timing = maxim4c->mipi_txphy.timing.csi2_twakeup & 0xFF;
|
||||
ret |= maxim4c_i2c_update_byte(client, reg_addr,
|
||||
MAXIM4C_I2C_REG_ADDR_16BITS,
|
||||
reg_mask, timing);
|
||||
timing = (maxim4c->mipi_txphy.timing.csi2_twakeup >> 8) & 0xFF;
|
||||
ret |= maxim4c_i2c_update_byte(client, reg_addr + 1,
|
||||
MAXIM4C_I2C_REG_ADDR_16BITS,
|
||||
reg_mask, timing);
|
||||
reg_mask = 0x7;
|
||||
timing = (maxim4c->mipi_txphy.timing.csi2_twakeup >> 16) & 0x7;
|
||||
ret |= maxim4c_i2c_update_byte(client, reg_addr + 2,
|
||||
MAXIM4C_I2C_REG_ADDR_16BITS,
|
||||
reg_mask, timing);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int maxim4c_txphy_auto_init_deskew(maxim4c_t *maxim4c)
|
||||
{
|
||||
struct i2c_client *client = maxim4c->client;
|
||||
@@ -182,6 +258,11 @@ int maxim4c_dphy_dpll_predef_set(maxim4c_t *maxim4c, s64 link_freq_hz)
|
||||
reg_addr, MAXIM4C_I2C_REG_ADDR_16BITS,
|
||||
0xf4);
|
||||
|
||||
reg_addr = 0x1C03 + 0x100 * phy_idx;
|
||||
ret |= maxim4c_i2c_update_byte(client, reg_addr,
|
||||
MAXIM4C_I2C_REG_ADDR_16BITS,
|
||||
0x07, phy_cfg->ssc_ratio);
|
||||
|
||||
// Set dpll data rate
|
||||
reg_addr = 0x0415 + 0x03 * phy_idx;
|
||||
ret |= maxim4c_i2c_update_byte(client,
|
||||
@@ -349,6 +430,12 @@ static int maxim4c_mipi_txphy_config_parse_dt(struct device *dev,
|
||||
phy_cfg->clock_mode = value;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(node, "ssc-ratio", &value);
|
||||
if (ret == 0) {
|
||||
dev_info(dev, "ssc-ratio property: %d", value);
|
||||
phy_cfg->ssc_ratio = value;
|
||||
}
|
||||
|
||||
sub_idx++;
|
||||
}
|
||||
}
|
||||
@@ -510,6 +597,9 @@ int maxim4c_mipi_txphy_hw_init(maxim4c_t *maxim4c)
|
||||
// mipi txphy auto init deskew
|
||||
ret |= maxim4c_txphy_auto_init_deskew(maxim4c);
|
||||
|
||||
// mipi txphy timing init
|
||||
ret |= maxim4c_txphy_init_timing(maxim4c);
|
||||
|
||||
if (ret) {
|
||||
dev_err(dev, "%s: txphy hw init error\n", __func__);
|
||||
return ret;
|
||||
@@ -529,6 +619,11 @@ void maxim4c_mipi_txphy_data_init(maxim4c_t *maxim4c)
|
||||
mipi_txphy->force_clock_out_en = 1;
|
||||
mipi_txphy->force_clk0_en = 0;
|
||||
mipi_txphy->force_clk3_en = 0;
|
||||
mipi_txphy->timing.t_lpx = 1;
|
||||
mipi_txphy->timing.csi2_t_pre = 0x71;
|
||||
mipi_txphy->timing.csi2_t_post = 0x19;
|
||||
mipi_txphy->timing.csi2_tx_gap = 0x1C;
|
||||
mipi_txphy->timing.csi2_twakeup = 0x100;
|
||||
|
||||
for (i = 0; i < MAXIM4C_TXPHY_ID_MAX; i++) {
|
||||
phy_cfg = &mipi_txphy->phy_cfg[i];
|
||||
@@ -541,6 +636,7 @@ void maxim4c_mipi_txphy_data_init(maxim4c_t *maxim4c)
|
||||
phy_cfg->vc_ext_en = 0;
|
||||
phy_cfg->clock_master = 0;
|
||||
phy_cfg->clock_mode = MAXIM4C_TXPHY_DPLL_PREDEF;
|
||||
phy_cfg->ssc_ratio = 0;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(maxim4c_mipi_txphy_data_init);
|
||||
|
||||
@@ -53,6 +53,38 @@ struct maxim4c_txphy_cfg {
|
||||
u8 vc_ext_en;
|
||||
u8 clock_master;
|
||||
u8 clock_mode;
|
||||
u8 ssc_ratio;
|
||||
};
|
||||
|
||||
struct maxim4c_txphy_timing {
|
||||
/* 0x8A1 */
|
||||
u8 t_hs_przero;
|
||||
u8 t_hs_prep;
|
||||
u8 t_clk_trail;
|
||||
u8 t_clk_przero;
|
||||
|
||||
/* 0x8A2 */
|
||||
u8 t_lpx;
|
||||
u8 t_hs_trail;
|
||||
|
||||
/* 0x8A5 */
|
||||
u8 t_clk_prep;
|
||||
|
||||
/* 0x8A8 */
|
||||
u8 t_lpxesc;
|
||||
|
||||
/* 0x8AE */
|
||||
u8 t_t3_post;
|
||||
u8 t_t3_prep;
|
||||
|
||||
/* 0x905 */
|
||||
u8 csi2_t_pre;
|
||||
/* 0x906 */
|
||||
u8 csi2_t_post;
|
||||
/* 0x907 */
|
||||
u8 csi2_tx_gap;
|
||||
/* 0x908,0x909,0x90A */
|
||||
u32 csi2_twakeup;
|
||||
};
|
||||
|
||||
typedef struct maxim4c_mipi_txphy {
|
||||
@@ -61,6 +93,9 @@ typedef struct maxim4c_mipi_txphy {
|
||||
u8 force_clk0_en; /* DPHY0 enabled as clock */
|
||||
u8 force_clk3_en; /* DPHY3 enabled as clock */
|
||||
|
||||
u8 timing_override_en;
|
||||
struct maxim4c_txphy_timing timing;
|
||||
|
||||
struct maxim4c_txphy_cfg phy_cfg[MAXIM4C_TXPHY_ID_MAX];
|
||||
} maxim4c_mipi_txphy_t;
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
* V0.0X01.0X03 fix gain range.
|
||||
* V0.0X01.0X04 add enum_frame_interval function.
|
||||
* V0.0X01.0X05 add quick stream on/off
|
||||
* V0.0X01.0X06 support thunder boot function.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
@@ -31,8 +32,9 @@
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-subdev.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include "../platform/rockchip/isp/rkisp_tb_helper.h"
|
||||
|
||||
#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x05)
|
||||
#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x06)
|
||||
|
||||
#ifndef V4L2_CID_DIGITAL_GAIN
|
||||
#define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN
|
||||
@@ -173,6 +175,8 @@ struct sc401ai {
|
||||
const char *module_name;
|
||||
const char *len_name;
|
||||
u32 cur_vts;
|
||||
bool is_thunderboot;
|
||||
bool is_first_streamoff;
|
||||
struct preisp_hdrae_exp_s init_hdrae_exp;
|
||||
};
|
||||
|
||||
@@ -447,6 +451,8 @@ static const s64 link_freq_menu_items[] = {
|
||||
SC401AI_LINK_FREQ_630,
|
||||
};
|
||||
|
||||
static int __sc401ai_power_on(struct sc401ai *sc401ai);
|
||||
|
||||
/* Write registers up to 4 at a time */
|
||||
static int sc401ai_write_reg(struct i2c_client *client, u16 reg,
|
||||
u32 len, u32 val)
|
||||
@@ -624,6 +630,11 @@ static int sc401ai_set_gain_reg(struct sc401ai *sc401ai, u32 gain)
|
||||
DIG_Fine_gain_reg = abs(800 * gain / (Dcg_gainx100 * Coarse_gain *
|
||||
DIG_gain) / ANA_Fine_gainx64);
|
||||
|
||||
if (sc401ai->is_thunderboot && rkisp_tb_get_state() == RKISP_TB_NG) {
|
||||
sc401ai->is_thunderboot = false;
|
||||
__sc401ai_power_on(sc401ai);
|
||||
}
|
||||
|
||||
ret = sc401ai_write_reg(sc401ai->client,
|
||||
SC401AI_REG_DIG_GAIN,
|
||||
SC401AI_REG_VALUE_08BIT,
|
||||
@@ -978,23 +989,31 @@ static int __sc401ai_start_stream(struct sc401ai *sc401ai)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = sc401ai_write_array(sc401ai->client, sc401ai->cur_mode->reg_list);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!sc401ai->is_thunderboot) {
|
||||
ret = sc401ai_write_array(sc401ai->client, sc401ai->cur_mode->reg_list);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* In case these controls are set before streaming */
|
||||
ret = __v4l2_ctrl_handler_setup(&sc401ai->ctrl_handler);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* In case these controls are set before streaming */
|
||||
ret = __v4l2_ctrl_handler_setup(&sc401ai->ctrl_handler);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return sc401ai_write_reg(sc401ai->client,
|
||||
SC401AI_REG_CTRL_MODE,
|
||||
SC401AI_REG_VALUE_08BIT,
|
||||
SC401AI_MODE_STREAMING);
|
||||
SC401AI_REG_CTRL_MODE,
|
||||
SC401AI_REG_VALUE_08BIT,
|
||||
SC401AI_MODE_STREAMING);
|
||||
|
||||
}
|
||||
|
||||
static int __sc401ai_stop_stream(struct sc401ai *sc401ai)
|
||||
{
|
||||
if (sc401ai->is_thunderboot) {
|
||||
sc401ai->is_first_streamoff = true;
|
||||
pm_runtime_put(&sc401ai->client->dev);
|
||||
}
|
||||
|
||||
return sc401ai_write_reg(sc401ai->client,
|
||||
SC401AI_REG_CTRL_MODE,
|
||||
SC401AI_REG_VALUE_08BIT,
|
||||
@@ -1013,6 +1032,10 @@ static int sc401ai_s_stream(struct v4l2_subdev *sd, int on)
|
||||
goto unlock_and_return;
|
||||
|
||||
if (on) {
|
||||
if (sc401ai->is_thunderboot && rkisp_tb_get_state() == RKISP_TB_NG) {
|
||||
sc401ai->is_thunderboot = false;
|
||||
__sc401ai_power_on(sc401ai);
|
||||
}
|
||||
ret = pm_runtime_get_sync(&client->dev);
|
||||
if (ret < 0) {
|
||||
pm_runtime_put_noidle(&client->dev);
|
||||
@@ -1104,6 +1127,10 @@ static int __sc401ai_power_on(struct sc401ai *sc401ai)
|
||||
dev_err(dev, "Failed to enable xvclk\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (sc401ai->is_thunderboot)
|
||||
return 0;
|
||||
|
||||
if (!IS_ERR(sc401ai->reset_gpio))
|
||||
gpiod_set_value_cansleep(sc401ai->reset_gpio, 0);
|
||||
|
||||
@@ -1142,6 +1169,15 @@ static void __sc401ai_power_off(struct sc401ai *sc401ai)
|
||||
int ret;
|
||||
struct device *dev = &sc401ai->client->dev;
|
||||
|
||||
if (sc401ai->is_thunderboot) {
|
||||
if (sc401ai->is_first_streamoff) {
|
||||
sc401ai->is_thunderboot = false;
|
||||
sc401ai->is_first_streamoff = false;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!IS_ERR(sc401ai->pwdn_gpio))
|
||||
gpiod_set_value_cansleep(sc401ai->pwdn_gpio, 0);
|
||||
clk_disable_unprepare(sc401ai->xvclk);
|
||||
@@ -1480,6 +1516,11 @@ static int sc401ai_check_sensor_id(struct sc401ai *sc401ai,
|
||||
u32 id = 0;
|
||||
int ret;
|
||||
|
||||
if (sc401ai->is_thunderboot) {
|
||||
dev_info(dev, "Enable thunderboot mode, skip sensor id check\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = sc401ai_read_reg(client, SC401AI_REG_CHIP_ID,
|
||||
SC401AI_REG_VALUE_16BIT, &id);
|
||||
if (id != CHIP_ID) {
|
||||
@@ -1538,6 +1579,8 @@ static int sc401ai_probe(struct i2c_client *client,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sc401ai->is_thunderboot = IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP);
|
||||
|
||||
sc401ai->client = client;
|
||||
for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
|
||||
if (hdr_mode == supported_modes[i].hdr_mode) {
|
||||
@@ -1554,13 +1597,23 @@ static int sc401ai_probe(struct i2c_client *client,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sc401ai->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(sc401ai->reset_gpio))
|
||||
dev_warn(dev, "Failed to get reset-gpios\n");
|
||||
if (sc401ai->is_thunderboot) {
|
||||
sc401ai->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_ASIS);
|
||||
if (IS_ERR(sc401ai->reset_gpio))
|
||||
dev_warn(dev, "Failed to get reset-gpios\n");
|
||||
|
||||
sc401ai->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(sc401ai->pwdn_gpio))
|
||||
dev_warn(dev, "Failed to get pwdn-gpios\n");
|
||||
sc401ai->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_ASIS);
|
||||
if (IS_ERR(sc401ai->pwdn_gpio))
|
||||
dev_warn(dev, "Failed to get pwdn-gpios\n");
|
||||
} else {
|
||||
sc401ai->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(sc401ai->reset_gpio))
|
||||
dev_warn(dev, "Failed to get reset-gpios\n");
|
||||
|
||||
sc401ai->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(sc401ai->pwdn_gpio))
|
||||
dev_warn(dev, "Failed to get pwdn-gpios\n");
|
||||
}
|
||||
|
||||
sc401ai->pinctrl = devm_pinctrl_get(dev);
|
||||
if (!IS_ERR(sc401ai->pinctrl)) {
|
||||
@@ -1635,7 +1688,10 @@ static int sc401ai_probe(struct i2c_client *client,
|
||||
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_idle(dev);
|
||||
if (sc401ai->is_thunderboot)
|
||||
pm_runtime_get_sync(dev);
|
||||
else
|
||||
pm_runtime_idle(dev);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1705,7 +1761,12 @@ static void __exit sensor_mod_exit(void)
|
||||
i2c_del_driver(&sc401ai_i2c_driver);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC)
|
||||
subsys_initcall(sensor_mod_init);
|
||||
#else
|
||||
device_initcall_sync(sensor_mod_init);
|
||||
#endif
|
||||
|
||||
module_exit(sensor_mod_exit);
|
||||
|
||||
MODULE_DESCRIPTION("smartsens sc401ai sensor driver");
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <media/cec.h>
|
||||
#include <media/cec-notifier.h>
|
||||
#include <media/v4l2-common.h>
|
||||
#include <media/v4l2-controls_rockchip.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-dv-timings.h>
|
||||
@@ -188,6 +189,8 @@ struct rk_hdmirx_dev {
|
||||
struct v4l2_device v4l2_dev;
|
||||
struct v4l2_ctrl_handler hdl;
|
||||
struct v4l2_ctrl *detect_tx_5v_ctrl;
|
||||
struct v4l2_ctrl *audio_sampling_rate_ctrl;
|
||||
struct v4l2_ctrl *audio_present_ctrl;
|
||||
struct v4l2_dv_timings timings;
|
||||
struct gpio_desc *hdmirx_det_gpio;
|
||||
struct work_struct work_wdt_config;
|
||||
@@ -471,6 +474,7 @@ static int hdmirx_subscribe_event(struct v4l2_fh *fh,
|
||||
case V4L2_EVENT_CTRL:
|
||||
return v4l2_ctrl_subscribe_event(fh, sub);
|
||||
case RK_HDMIRX_V4L2_EVENT_SIGNAL_LOST:
|
||||
case RK_HDMIRX_V4L2_EVENT_AUDIOINFO:
|
||||
return v4l2_event_subscribe(fh, sub, 0, NULL);
|
||||
|
||||
default:
|
||||
@@ -2353,6 +2357,15 @@ static int hdmirx_register_stream_vdev(struct hdmirx_stream *stream)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void process_audio_change(struct rk_hdmirx_dev *hdmirx_dev)
|
||||
{
|
||||
struct hdmirx_stream *stream = &hdmirx_dev->stream;
|
||||
const struct v4l2_event evt_audio_info = {
|
||||
.type = RK_HDMIRX_V4L2_EVENT_AUDIOINFO,
|
||||
};
|
||||
v4l2_event_queue(&stream->vdev, &evt_audio_info);
|
||||
}
|
||||
|
||||
static void process_signal_change(struct rk_hdmirx_dev *hdmirx_dev)
|
||||
{
|
||||
struct hdmirx_stream *stream = &hdmirx_dev->stream;
|
||||
@@ -3248,6 +3261,7 @@ static void hdmirx_delayed_work_audio(struct work_struct *work)
|
||||
if (!hdmirx_dev->audio_present) {
|
||||
dev_info(hdmirx_dev->dev, "audio on");
|
||||
hdmirx_audio_handle_plugged_change(hdmirx_dev, 1);
|
||||
process_audio_change(hdmirx_dev);
|
||||
hdmirx_dev->audio_present = true;
|
||||
}
|
||||
if (cur_state - init_state > 16 && cur_state - pre_state > 0)
|
||||
@@ -3258,6 +3272,7 @@ static void hdmirx_delayed_work_audio(struct work_struct *work)
|
||||
if (hdmirx_dev->audio_present) {
|
||||
dev_info(hdmirx_dev->dev, "audio off");
|
||||
hdmirx_audio_handle_plugged_change(hdmirx_dev, 0);
|
||||
process_audio_change(hdmirx_dev);
|
||||
hdmirx_dev->audio_present = false;
|
||||
}
|
||||
}
|
||||
@@ -4175,6 +4190,50 @@ static void hdmirx_cancel_cpu_limit_freq(struct rk_hdmirx_dev *hdmirx_dev)
|
||||
dev_err(hdmirx_dev->dev, "%s freq qos nod add\n", __func__);
|
||||
}
|
||||
|
||||
static int hdmirx_get_custom_ctrl(struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
struct rk_hdmirx_dev *hdmirx_dev = container_of(ctrl->handler, struct rk_hdmirx_dev, hdl);
|
||||
int ret = 0;
|
||||
|
||||
if (ctrl->id == RK_V4L2_CID_AUDIO_SAMPLING_RATE) {
|
||||
*ctrl->p_new.p_s32 = hdmirx_dev->audio_state.fs_audio;
|
||||
} else if (ctrl->id == RK_V4L2_CID_AUDIO_PRESENT) {
|
||||
*ctrl->p_new.p_s32 = tx_5v_power_present(hdmirx_dev) ?
|
||||
hdmirx_dev->audio_present : 0;
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct v4l2_ctrl_ops hdmirx_custom_ctrl_ops = {
|
||||
.g_volatile_ctrl = hdmirx_get_custom_ctrl,
|
||||
};
|
||||
|
||||
static const struct v4l2_ctrl_config hdmirx_ctrl_audio_sampling_rate = {
|
||||
.ops = &hdmirx_custom_ctrl_ops,
|
||||
.id = RK_V4L2_CID_AUDIO_SAMPLING_RATE,
|
||||
.name = "Audio sampling rate",
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.min = 0,
|
||||
.max = 768000,
|
||||
.step = 1,
|
||||
.def = 0,
|
||||
.flags = V4L2_CTRL_FLAG_READ_ONLY,
|
||||
};
|
||||
|
||||
static const struct v4l2_ctrl_config hdmirx_ctrl_audio_present = {
|
||||
.ops = &hdmirx_custom_ctrl_ops,
|
||||
.id = RK_V4L2_CID_AUDIO_PRESENT,
|
||||
.name = "Audio present",
|
||||
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
||||
.min = 0,
|
||||
.max = 1,
|
||||
.step = 1,
|
||||
.def = 0,
|
||||
.flags = V4L2_CTRL_FLAG_READ_ONLY,
|
||||
};
|
||||
|
||||
static int hdmirx_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct v4l2_dv_timings timings_def = HDMIRX_DEFAULT_TIMING;
|
||||
@@ -4288,10 +4347,19 @@ static int hdmirx_probe(struct platform_device *pdev)
|
||||
strscpy(v4l2_dev->name, dev_name(dev), sizeof(v4l2_dev->name));
|
||||
|
||||
hdl = &hdmirx_dev->hdl;
|
||||
v4l2_ctrl_handler_init(hdl, 1);
|
||||
v4l2_ctrl_handler_init(hdl, 3);
|
||||
hdmirx_dev->detect_tx_5v_ctrl = v4l2_ctrl_new_std(hdl,
|
||||
NULL, V4L2_CID_DV_RX_POWER_PRESENT,
|
||||
0, 1, 0, 0);
|
||||
/* custom controls */
|
||||
hdmirx_dev->audio_sampling_rate_ctrl = v4l2_ctrl_new_custom(hdl,
|
||||
&hdmirx_ctrl_audio_sampling_rate, NULL);
|
||||
if (hdmirx_dev->audio_sampling_rate_ctrl)
|
||||
hdmirx_dev->audio_sampling_rate_ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
|
||||
hdmirx_dev->audio_present_ctrl = v4l2_ctrl_new_custom(hdl,
|
||||
&hdmirx_ctrl_audio_present, NULL);
|
||||
if (hdmirx_dev->audio_present_ctrl)
|
||||
hdmirx_dev->audio_present_ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
|
||||
if (hdl->error) {
|
||||
dev_err(dev, "v4l2 ctrl handler init failed!\n");
|
||||
ret = hdl->error;
|
||||
|
||||
@@ -169,8 +169,10 @@ void rkisp_update_regs(struct rkisp_device *dev, u32 start, u32 end)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hw->unite == ISP_UNITE_ONE && dev->unite_index == ISP_UNITE_RIGHT)
|
||||
if (hw->unite == ISP_UNITE_ONE && dev->unite_index == ISP_UNITE_RIGHT) {
|
||||
val = dev->sw_base_addr + i + RKISP_ISP_SW_MAX_SIZE;
|
||||
flag = dev->sw_base_addr + i + RKISP_ISP_SW_MAX_SIZE + RKISP_ISP_SW_REG_SIZE;
|
||||
}
|
||||
|
||||
if (*flag == SW_REG_CACHE) {
|
||||
if ((i == ISP3X_MAIN_RESIZE_CTRL ||
|
||||
|
||||
@@ -1557,6 +1557,7 @@ static void rkisp_config_cmsk_dual(struct rkisp_device *dev,
|
||||
left.win[0].win_en &= ~BIT(i);
|
||||
left.win[1].win_en &= ~BIT(i);
|
||||
left.win[2].win_en &= ~BIT(i);
|
||||
right.win[i].h_offs = right.win[i].h_offs - w;
|
||||
} else {
|
||||
/* cmsk window at dual isp */
|
||||
left.win[i].h_size = ALIGN(w - h_offs, 8);
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
static const struct mfd_cell rkx110_x120_devs[] = {
|
||||
/* 2 panel device for rkx110_x120 drm panel */
|
||||
{
|
||||
.name = "serdes-panel",
|
||||
.name = "rockchip-serdes-panel",
|
||||
.of_compatible = "rockchip,serdes-panel",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -630,7 +630,7 @@ static struct platform_driver serdes_panel_driver = {
|
||||
.probe = serdes_panel_probe,
|
||||
.remove = serdes_panel_remove,
|
||||
.driver = {
|
||||
.name = "serdes-panel",
|
||||
.name = "rockchip-serdes-panel",
|
||||
.of_match_table = serdes_panel_of_table,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -815,7 +815,12 @@ static void pcie_rkep_remove(struct pci_dev *pdev)
|
||||
#if IS_ENABLED(CONFIG_PCIE_FUNC_RKEP_USERPAGES)
|
||||
free_contig_range(page_to_pfn(pcie_rkep->user_pages), RKEP_USER_MEM_SIZE >> PAGE_SHIFT);
|
||||
#endif
|
||||
pci_iounmap(pdev, pcie_rkep->bar0);
|
||||
if (pcie_rkep->bar0)
|
||||
pci_iounmap(pdev, pcie_rkep->bar0);
|
||||
if (pcie_rkep->bar2)
|
||||
pci_iounmap(pdev, pcie_rkep->bar2);
|
||||
if (pcie_rkep->bar4)
|
||||
pci_iounmap(pdev, pcie_rkep->bar4);
|
||||
pci_release_regions(pdev);
|
||||
pci_disable_device(pdev);
|
||||
misc_deregister(&pcie_rkep->dev);
|
||||
|
||||
@@ -658,18 +658,6 @@ static inline void rk_pcie_enable_ltssm(struct rk_pcie *rk_pcie)
|
||||
rk_pcie_writel_apb(rk_pcie, 0x0, 0xC000C);
|
||||
}
|
||||
|
||||
static int rk_pcie_link_up(struct dw_pcie *pci)
|
||||
{
|
||||
struct rk_pcie *rk_pcie = to_rk_pcie(pci);
|
||||
u32 val;
|
||||
|
||||
val = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS);
|
||||
if ((val & (RDLH_LINKUP | SMLH_LINKUP)) == 0x30000)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rk_pcie_enable_debug(struct rk_pcie *rk_pcie)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_DEBUG_FS))
|
||||
@@ -1489,7 +1477,6 @@ MODULE_DEVICE_TABLE(of, rk_pcie_of_match);
|
||||
|
||||
static const struct dw_pcie_ops dw_pcie_ops = {
|
||||
.start_link = rk_pcie_establish_link,
|
||||
.link_up = rk_pcie_link_up,
|
||||
};
|
||||
|
||||
static void rk_pcie_fast_link_setup(struct rk_pcie *rk_pcie)
|
||||
|
||||
@@ -942,6 +942,20 @@ static const struct regulator_ops rk806_ops_ldo = {
|
||||
.set_suspend_disable = rk806_set_suspend_disable,
|
||||
};
|
||||
|
||||
static const struct regulator_ops rk806_ops_ldo6 = {
|
||||
.list_voltage = regulator_list_voltage_linear_range,
|
||||
.map_voltage = regulator_map_voltage_linear_range,
|
||||
|
||||
.get_voltage_sel = rk806_get_voltage_sel_regmap,
|
||||
.set_voltage = rk806_set_voltage,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
|
||||
.set_ramp_delay = rk806_set_ramp_delay,
|
||||
|
||||
.set_suspend_voltage = rk806_set_suspend_voltage_range,
|
||||
.resume = rk806_regulator_resume,
|
||||
};
|
||||
|
||||
#define RK806_REGULATOR(_name, _supply_name, _id, _ops,\
|
||||
_n_voltages, _vr, _er, _lr, ctrl_bit)\
|
||||
[_id] = {\
|
||||
@@ -1033,7 +1047,7 @@ static const struct regulator_desc rk806_regulators[] = {
|
||||
RK806_LDO_SEL_CNT, RK806_PLDO5_ON_VSEL,
|
||||
RK806_POWER_EN5, rk806_ldo_voltage_ranges, 1),
|
||||
|
||||
RK806_REGULATOR("PLDO_REG6", "vcca", RK806_ID_PLDO6, rk806_ops_ldo,
|
||||
RK806_REGULATOR("PLDO_REG6", "vcca", RK806_ID_PLDO6, rk806_ops_ldo6,
|
||||
RK806_LDO_SEL_CNT, RK806_PLDO6_ON_VSEL,
|
||||
RK806_POWER_EN4, rk806_ldo_voltage_ranges, 0),
|
||||
};
|
||||
|
||||
@@ -1555,7 +1555,7 @@ static int fiq_debugger_probe(struct platform_device *pdev)
|
||||
pr_err("%s: could not install nmi irq handler\n", __func__);
|
||||
irq_clear_status_flags(state->uart_irq, IRQ_NOAUTOEN);
|
||||
ret = request_irq(state->uart_irq, fiq_debugger_uart_irq,
|
||||
IRQF_NO_SUSPEND, "debug", state);
|
||||
IRQF_NO_SUSPEND | IRQF_NOBALANCING, "debug", state);
|
||||
} else {
|
||||
enable_nmi(state->uart_irq);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/rockchip/rockchip_sip.h>
|
||||
#include <soc/rockchip/rockchip_amp.h>
|
||||
#include <linux/irqchip/arm-gic-common.h>
|
||||
|
||||
#define RK_CPU_STATUS_OFF 0
|
||||
#define RK_CPU_STATUS_ON 1
|
||||
@@ -24,6 +25,7 @@
|
||||
#define GPIO_BANK_NUM 16
|
||||
#define GPIO_GROUP_PRIO_MAX 3
|
||||
|
||||
#define MAX_GIC_SPI_NUM (1020)
|
||||
#define AMP_GIC_DBG(fmt, arg...) do { if (0) { pr_warn(fmt, ##arg); } } while (0)
|
||||
|
||||
enum amp_cpu_ctrl_status {
|
||||
@@ -55,26 +57,27 @@ static struct {
|
||||
struct amp_gpio_group_s {
|
||||
u32 bank_id;
|
||||
u32 prio;
|
||||
u32 irq_aff[AMP_AFF_MAX_CPU];
|
||||
u64 irq_aff[AMP_AFF_MAX_CPU];
|
||||
u32 irq_id[AMP_AFF_MAX_CPU];
|
||||
u32 en[AMP_AFF_MAX_CPU];
|
||||
};
|
||||
|
||||
struct amp_irq_cfg_s {
|
||||
u64 aff;
|
||||
u32 prio;
|
||||
u32 cpumask;
|
||||
u32 aff;
|
||||
int amp_flag;
|
||||
} irqs_cfg[1024];
|
||||
} irqs_cfg[MAX_GIC_SPI_NUM];
|
||||
|
||||
static struct amp_gic_ctrl_s {
|
||||
enum gic_type gic_version;
|
||||
u32 spis_num;
|
||||
struct {
|
||||
u32 aff;
|
||||
u32 cpumask;
|
||||
u32 flag;
|
||||
} aff_to_cpumask[AMP_AFF_MAX_CLUSTER][AMP_AFF_MAX_CPU];
|
||||
struct amp_irq_cfg_s irqs_cfg[1024];
|
||||
u32 validmask[1020 / 32 + 1];
|
||||
struct amp_irq_cfg_s irqs_cfg[MAX_GIC_SPI_NUM];
|
||||
struct amp_gpio_group_s gpio_grp[GPIO_BANK_NUM][GPIO_GROUP_PRIO_MAX];
|
||||
u32 gpio_banks;
|
||||
} amp_ctrl;
|
||||
@@ -275,7 +278,12 @@ u32 rockchip_amp_get_irq_cpumask(u32 irq)
|
||||
return amp_ctrl.irqs_cfg[irq].cpumask;
|
||||
}
|
||||
|
||||
static u32 amp_get_cpumask_bit(u32 aff)
|
||||
int rockchip_amp_need_init_amp_irq(u32 irq)
|
||||
{
|
||||
return amp_ctrl.irqs_cfg[irq].amp_flag;
|
||||
}
|
||||
|
||||
static u32 amp_get_cpumask_bit(u64 aff)
|
||||
{
|
||||
u32 aff_cluster, aff_cpu;
|
||||
|
||||
@@ -285,18 +293,24 @@ static u32 amp_get_cpumask_bit(u32 aff)
|
||||
if (aff_cpu >= AMP_AFF_MAX_CPU || aff_cluster >= AMP_AFF_MAX_CLUSTER)
|
||||
return 0;
|
||||
|
||||
AMP_GIC_DBG("%s: aff:%d-%d: %x\n", __func__, aff_cluster, aff_cpu,
|
||||
AMP_GIC_DBG(" %s: aff:%d-%d: %x\n", __func__, aff_cluster, aff_cpu,
|
||||
amp_ctrl.aff_to_cpumask[aff_cluster][aff_cpu].cpumask);
|
||||
|
||||
return amp_ctrl.aff_to_cpumask[aff_cluster][aff_cpu].cpumask;
|
||||
}
|
||||
|
||||
u64 rockchip_amp_get_irq_aff(u32 irq)
|
||||
{
|
||||
return amp_ctrl.irqs_cfg[irq].aff;
|
||||
}
|
||||
|
||||
static int gic_amp_get_gpio_prio_group_info(struct device_node *np,
|
||||
struct amp_gic_ctrl_s *amp_ctrl,
|
||||
int prio_id)
|
||||
{
|
||||
u32 gpio_bank, count0, count1, prio, irq_id, irq_aff;
|
||||
int i;
|
||||
u32 gpio_bank, prio, irq_id;
|
||||
u64 irq_aff;
|
||||
int i, count0, count1;
|
||||
struct amp_gpio_group_s *gpio_grp;
|
||||
struct amp_irq_cfg_s *irqs_cfg;
|
||||
|
||||
@@ -320,7 +334,7 @@ static int gic_amp_get_gpio_prio_group_info(struct device_node *np,
|
||||
__func__, gpio_bank, prio_id, prio);
|
||||
|
||||
count0 = of_property_count_u32_elems(np, "girq-id");
|
||||
count1 = of_property_count_u32_elems(np, "girq-aff");
|
||||
count1 = of_property_count_u64_elems(np, "girq-aff");
|
||||
|
||||
if (count0 != count1)
|
||||
return -EINVAL;
|
||||
@@ -330,7 +344,7 @@ static int gic_amp_get_gpio_prio_group_info(struct device_node *np,
|
||||
for (i = 0; i < count0; i++) {
|
||||
of_property_read_u32_index(np, "girq-id", i, &irq_id);
|
||||
gpio_grp->irq_id[i] = irq_id;
|
||||
of_property_read_u32_index(np, "girq-aff", i, &irq_aff);
|
||||
of_property_read_u64_index(np, "girq-aff", i, &irq_aff);
|
||||
|
||||
gpio_grp->irq_aff[i] = irq_aff;
|
||||
|
||||
@@ -338,18 +352,24 @@ static int gic_amp_get_gpio_prio_group_info(struct device_node *np,
|
||||
|
||||
irqs_cfg = &_ctrl->irqs_cfg[irq_id];
|
||||
|
||||
AMP_GIC_DBG(" %s: group cpu-%d, irq-%d: prio-%x, aff-%x en-%d\n",
|
||||
AMP_GIC_DBG(" %s: group cpu-%d, irq-%d: prio-%x, aff-%llx en-%d\n",
|
||||
__func__, i, gpio_grp->irq_id[i], gpio_grp->prio,
|
||||
gpio_grp->irq_aff[i], gpio_grp->en[i]);
|
||||
|
||||
if (gpio_grp->en[i]) {
|
||||
irqs_cfg->prio = gpio_grp->prio;
|
||||
irqs_cfg->aff = irq_aff;
|
||||
irqs_cfg->cpumask = amp_get_cpumask_bit(irq_aff);
|
||||
if (amp_ctrl->gic_version == GIC_V2) {
|
||||
irqs_cfg->cpumask = amp_get_cpumask_bit(irq_aff);
|
||||
if (!irqs_cfg->cpumask) {
|
||||
pr_err(" %s: get cpumask error\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
irqs_cfg->amp_flag = 1;
|
||||
}
|
||||
|
||||
AMP_GIC_DBG(" %s: irqs_cfg prio-%x aff-%x cpumaks-%x en-%d\n",
|
||||
AMP_GIC_DBG(" %s: prio-%x aff-%llx cpumaks-%x flag-%d\n",
|
||||
__func__, irqs_cfg->prio, irqs_cfg->aff,
|
||||
irqs_cfg->cpumask, irqs_cfg->amp_flag);
|
||||
}
|
||||
@@ -404,33 +424,37 @@ static int amp_gic_get_cpumask(struct device_node *np, struct amp_gic_ctrl_s *am
|
||||
{
|
||||
const struct property *prop;
|
||||
int count, i;
|
||||
u32 cluster, aff_cpu, aff, cpumask;
|
||||
u32 cluster, aff_cpu;
|
||||
u64 aff, cpumask;
|
||||
|
||||
if (amp_ctrl->gic_version != GIC_V2)
|
||||
return 0;
|
||||
prop = of_find_property(np, "amp-cpu-aff-maskbits", NULL);
|
||||
|
||||
if (!prop)
|
||||
return -1;
|
||||
|
||||
if (!prop->value)
|
||||
return -1;
|
||||
|
||||
count = of_property_count_u32_elems(np, "amp-cpu-aff-maskbits");
|
||||
count = of_property_count_u64_elems(np, "amp-cpu-aff-maskbits");
|
||||
if (count % 2)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < count / 2; i++) {
|
||||
of_property_read_u32_index(np, "amp-cpu-aff-maskbits",
|
||||
of_property_read_u64_index(np, "amp-cpu-aff-maskbits",
|
||||
2 * i, &aff);
|
||||
cluster = MPIDR_AFFINITY_LEVEL(aff, 1);
|
||||
aff_cpu = MPIDR_AFFINITY_LEVEL(aff, 0);
|
||||
amp_ctrl->aff_to_cpumask[cluster][aff_cpu].aff = aff;
|
||||
|
||||
of_property_read_u32_index(np, "amp-cpu-aff-maskbits",
|
||||
of_property_read_u64_index(np, "amp-cpu-aff-maskbits",
|
||||
2 * i + 1, &cpumask);
|
||||
|
||||
amp_ctrl->aff_to_cpumask[cluster][aff_cpu].cpumask = cpumask;
|
||||
amp_ctrl->aff_to_cpumask[cluster][aff_cpu].cpumask = (u32)cpumask;
|
||||
|
||||
AMP_GIC_DBG("cpumask: %d-%d: aff-%d cpumask-%d\n",
|
||||
cluster, aff_cpu, aff, cpumask);
|
||||
AMP_GIC_DBG("cpumask: %d-%d: aff-%llx cpumask-%d\n",
|
||||
cluster, aff_cpu, aff, (u32)cpumask);
|
||||
|
||||
if (!cpumask)
|
||||
return -1;
|
||||
@@ -443,8 +467,9 @@ static void amp_gic_get_irqs_config(struct device_node *np,
|
||||
struct amp_gic_ctrl_s *amp_ctrl)
|
||||
{
|
||||
const struct property *prop;
|
||||
int count, i;
|
||||
u32 irq, prio, aff;
|
||||
u32 irq, i;
|
||||
int count;
|
||||
u64 aff, val, prio;
|
||||
|
||||
prop = of_find_property(np, "amp-irqs", NULL);
|
||||
if (!prop)
|
||||
@@ -453,30 +478,31 @@ static void amp_gic_get_irqs_config(struct device_node *np,
|
||||
if (!prop->value)
|
||||
return;
|
||||
|
||||
count = of_property_count_u32_elems(np, "amp-irqs");
|
||||
count = of_property_count_u64_elems(np, "amp-irqs");
|
||||
|
||||
if (count < 0 || count % 3)
|
||||
if (count % 3)
|
||||
return;
|
||||
|
||||
for (i = 0; i < count / 3; i++) {
|
||||
of_property_read_u32_index(np, "amp-irqs", 3 * i, &irq);
|
||||
|
||||
if (irq > 1020)
|
||||
of_property_read_u64_index(np, "amp-irqs", 3 * i, &val);
|
||||
irq = (u32)val;
|
||||
if (irq > amp_ctrl->spis_num)
|
||||
break;
|
||||
|
||||
of_property_read_u32_index(np, "amp-irqs", 3 * i + 1, &prio);
|
||||
of_property_read_u32_index(np, "amp-irqs", 3 * i + 2, &aff);
|
||||
of_property_read_u64_index(np, "amp-irqs", 3 * i + 1, &prio);
|
||||
of_property_read_u64_index(np, "amp-irqs", 3 * i + 2, &aff);
|
||||
|
||||
AMP_GIC_DBG("%s: irq-%d aff-%d prio-%x\n",
|
||||
AMP_GIC_DBG("%s: irq-%d aff-%llx prio-%llx\n",
|
||||
__func__, irq, aff, prio);
|
||||
|
||||
amp_ctrl->irqs_cfg[irq].prio = prio;
|
||||
amp_ctrl->irqs_cfg[irq].prio = (u32)prio;
|
||||
amp_ctrl->irqs_cfg[irq].aff = aff;
|
||||
amp_ctrl->irqs_cfg[irq].cpumask = amp_get_cpumask_bit(aff);
|
||||
|
||||
if (!amp_ctrl->irqs_cfg[irq].cpumask) {
|
||||
AMP_GIC_DBG("%s: get cpumask error\n", __func__);
|
||||
break;
|
||||
if (amp_ctrl->gic_version == GIC_V2) {
|
||||
amp_ctrl->irqs_cfg[irq].cpumask = amp_get_cpumask_bit(aff);
|
||||
if (!amp_ctrl->irqs_cfg[irq].cpumask) {
|
||||
pr_err("%s: get cpumask error\n", __func__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!amp_ctrl->irqs_cfg[irq].aff &&
|
||||
@@ -485,17 +511,20 @@ static void amp_gic_get_irqs_config(struct device_node *np,
|
||||
|
||||
amp_ctrl->irqs_cfg[irq].amp_flag = 1;
|
||||
|
||||
AMP_GIC_DBG("%s: irq-%d aff-%d cpumask-%d pri-%x\n",
|
||||
AMP_GIC_DBG(" %s: irq-%d aff-%llx cpumask-%x pri-%x\n",
|
||||
__func__, irq, amp_ctrl->irqs_cfg[irq].aff,
|
||||
amp_ctrl->irqs_cfg[irq].cpumask,
|
||||
amp_ctrl->irqs_cfg[irq].prio);
|
||||
}
|
||||
}
|
||||
|
||||
void rockchip_amp_get_gic_info(void)
|
||||
void rockchip_amp_get_gic_info(u32 spis_num, enum gic_type gic_version)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
amp_ctrl.spis_num = spis_num;
|
||||
amp_ctrl.gic_version = gic_version;
|
||||
|
||||
np = of_find_node_by_name(NULL, "rockchip-amp");
|
||||
if (!np)
|
||||
return;
|
||||
@@ -504,6 +533,7 @@ void rockchip_amp_get_gic_info(void)
|
||||
pr_err("%s: get amp gic cpu mask error\n", __func__);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
gic_of_get_gpio_group(np, &_ctrl);
|
||||
amp_gic_get_irqs_config(np, &_ctrl);
|
||||
|
||||
|
||||
@@ -1285,7 +1285,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
|
||||
* the first wake signalling failed, give it that chance.
|
||||
*/
|
||||
pending_portevent = xhci_pending_portevent(xhci);
|
||||
if (!pending_portevent) {
|
||||
if (!pending_portevent && !IS_ENABLED(CONFIG_ARCH_ROCKCHIP)) {
|
||||
msleep(120);
|
||||
pending_portevent = xhci_pending_portevent(xhci);
|
||||
}
|
||||
|
||||
@@ -7,3 +7,4 @@ source "drivers/video/rockchip/iep/Kconfig"
|
||||
source "drivers/video/rockchip/mpp/Kconfig"
|
||||
source "drivers/video/rockchip/dvbm/Kconfig"
|
||||
source "drivers/video/rockchip/vehicle/Kconfig"
|
||||
source "drivers/video/rockchip/vtunnel/Kconfig"
|
||||
|
||||
@@ -7,3 +7,4 @@ obj-$(CONFIG_IEP) += iep/
|
||||
obj-$(CONFIG_ROCKCHIP_MPP_SERVICE) += mpp/
|
||||
obj-$(CONFIG_ROCKCHIP_DVBM) += dvbm/
|
||||
obj-$(CONFIG_VIDEO_REVERSE_IMAGE) += vehicle/
|
||||
obj-$(CONFIG_ROCKCHIP_VIDEO_TUNNEL) += vtunnel/
|
||||
|
||||
@@ -461,6 +461,12 @@ static int mpp_iommu_handle(struct iommu_domain *iommu,
|
||||
else
|
||||
mpp_task_dump_hw_reg(mpp);
|
||||
|
||||
/*
|
||||
* Mask iommu irq, in order for iommu not repeatedly trigger pagefault.
|
||||
* Until the pagefault task finish by hw timeout.
|
||||
*/
|
||||
rockchip_iommu_mask_irq(mpp->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <soc/rockchip/rockchip_ipa.h>
|
||||
#include <soc/rockchip/rockchip_opp_select.h>
|
||||
#include <soc/rockchip/rockchip_system_monitor.h>
|
||||
#include <soc/rockchip/rockchip_iommu.h>
|
||||
|
||||
#include "mpp_debug.h"
|
||||
#include "mpp_iommu.h"
|
||||
@@ -43,6 +44,8 @@
|
||||
#define RKVENC_MAX_DCHS_ID 4
|
||||
#define RKVENC_MAX_SLICE_FIFO_LEN 256
|
||||
#define RKVENC_SCLR_DONE_STA BIT(2)
|
||||
#define RKVENC_WDG 0x38
|
||||
#define TIMEOUT_MS 100
|
||||
|
||||
#define to_rkvenc_info(info) \
|
||||
container_of(info, struct rkvenc_hw_info, hw)
|
||||
@@ -1193,6 +1196,7 @@ static int rkvenc_run(struct mpp_dev *mpp, struct mpp_task *mpp_task)
|
||||
struct rkvenc_task *task = to_rkvenc_task(mpp_task);
|
||||
struct rkvenc_hw_info *hw = enc->hw_info;
|
||||
u32 timing_en = mpp->srv->timing_en;
|
||||
u32 timeout_thd;
|
||||
|
||||
mpp_debug_enter();
|
||||
|
||||
@@ -1246,6 +1250,13 @@ static int rkvenc_run(struct mpp_dev *mpp, struct mpp_task *mpp_task)
|
||||
/* Flush the register before the start the device */
|
||||
wmb();
|
||||
|
||||
/*
|
||||
* reconfig timeout threshold.
|
||||
* bit0-bit23,x1024 core clk cycles
|
||||
*/
|
||||
timeout_thd = mpp_read(mpp, RKVENC_WDG) & 0xff000000;
|
||||
timeout_thd |= TIMEOUT_MS * clk_get_rate(enc->core_clk_info.clk) / 1024000;
|
||||
mpp_write(mpp, RKVENC_WDG, timeout_thd);
|
||||
mpp_write(mpp, enc->hw_info->enc_start_base, start_val);
|
||||
|
||||
mpp_task_run_end(mpp_task, timing_en);
|
||||
@@ -1457,7 +1468,7 @@ static int rkvenc_finish(struct mpp_dev *mpp, struct mpp_task *mpp_task)
|
||||
if (task->bs_buf) {
|
||||
u32 bs_size = mpp_read(mpp, 0x4064);
|
||||
|
||||
mpp_dma_buf_sync(task->bs_buf, 0, bs_size / 8 + task->offset_bs,
|
||||
mpp_dma_buf_sync(task->bs_buf, 0, bs_size + task->offset_bs,
|
||||
DMA_FROM_DEVICE, true);
|
||||
}
|
||||
|
||||
@@ -1862,7 +1873,7 @@ static int rkvenc_soft_reset(struct mpp_dev *mpp)
|
||||
|
||||
/* safe reset */
|
||||
mpp_write(mpp, hw->int_mask_base, 0x3FF);
|
||||
mpp_write(mpp, hw->enc_clr_base, 0x1);
|
||||
mpp_write(mpp, hw->enc_clr_base, 0x3);
|
||||
ret = readl_relaxed_poll_timeout(mpp->reg_base + hw->int_sta_base,
|
||||
rst_status,
|
||||
rst_status & RKVENC_SCLR_DONE_STA,
|
||||
@@ -2386,14 +2397,33 @@ static int rkvenc2_iommu_fault_handle(struct iommu_domain *iommu,
|
||||
{
|
||||
struct mpp_dev *mpp = (struct mpp_dev *)arg;
|
||||
struct rkvenc_dev *enc = to_rkvenc_dev(mpp);
|
||||
struct mpp_task *mpp_task = mpp->cur_task;
|
||||
struct mpp_task *mpp_task;
|
||||
struct rkvenc_ccu *ccu = enc->ccu;
|
||||
|
||||
if (ccu) {
|
||||
struct rkvenc_dev *core = NULL, *n;
|
||||
|
||||
list_for_each_entry_safe(core, n, &ccu->core_list, core_link) {
|
||||
if (core->mpp.iommu_info &&
|
||||
(&core->mpp.iommu_info->pdev->dev == iommu_dev)) {
|
||||
mpp = &core->mpp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
mpp_task = mpp->cur_task;
|
||||
dev_info(mpp->dev, "core %d page fault found dchs %08x\n",
|
||||
mpp->core_id, mpp_read_relaxed(&enc->mpp, DCHS_REG_OFFSET));
|
||||
|
||||
if (mpp_task)
|
||||
mpp_task_dump_mem_region(mpp, mpp_task);
|
||||
|
||||
/*
|
||||
* Mask iommu irq, in order for iommu not repeatedly trigger pagefault.
|
||||
* Until the pagefault task finish by hw timeout.
|
||||
*/
|
||||
rockchip_iommu_mask_irq(mpp->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/nospec.h>
|
||||
#include <soc/rockchip/pm_domains.h>
|
||||
#include <soc/rockchip/rockchip_iommu.h>
|
||||
|
||||
#include "mpp_debug.h"
|
||||
#include "mpp_common.h"
|
||||
@@ -882,6 +883,48 @@ static int vepu_reset(struct mpp_dev *mpp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vepu2_iommu_fault_handle(struct iommu_domain *iommu, struct device *iommu_dev,
|
||||
unsigned long iova, int status, void *arg)
|
||||
{
|
||||
struct mpp_dev *mpp = (struct mpp_dev *)arg;
|
||||
struct mpp_task *mpp_task;
|
||||
struct vepu_dev *enc = to_vepu_dev(mpp);
|
||||
struct vepu_ccu *ccu = enc->ccu;
|
||||
|
||||
dev_err(iommu_dev, "fault addr 0x%08lx status %x arg %p\n",
|
||||
iova, status, arg);
|
||||
|
||||
if (ccu) {
|
||||
int i;
|
||||
struct mpp_dev *core;
|
||||
|
||||
for (i = 0; i < ccu->core_num; i++) {
|
||||
core = ccu->cores[i];
|
||||
if (core->iommu_info && (&core->iommu_info->pdev->dev == iommu_dev)) {
|
||||
mpp = core;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!mpp) {
|
||||
dev_err(iommu_dev, "pagefault without device to handle\n");
|
||||
return 0;
|
||||
}
|
||||
mpp_task = mpp->cur_task;
|
||||
if (mpp_task)
|
||||
mpp_task_dump_mem_region(mpp, mpp_task);
|
||||
|
||||
mpp_task_dump_hw_reg(mpp);
|
||||
/*
|
||||
* Mask iommu irq, in order for iommu not repeatedly trigger pagefault.
|
||||
* Until the pagefault task finish by hw timeout.
|
||||
*/
|
||||
rockchip_iommu_mask_irq(mpp->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct mpp_hw_ops vepu_v2_hw_ops = {
|
||||
.init = vepu_init,
|
||||
.clk_on = vepu_clk_on,
|
||||
@@ -1100,6 +1143,7 @@ static int vepu_core_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mpp->fault_handler = vepu2_iommu_fault_handle;
|
||||
mpp->session_max_buffers = VEPU2_SESSION_MAX_BUFFERS;
|
||||
vepu_procfs_init(mpp);
|
||||
vepu_procfs_ccu_init(mpp);
|
||||
@@ -1149,6 +1193,7 @@ static int vepu_probe_default(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mpp->fault_handler = vepu2_iommu_fault_handle;
|
||||
mpp->session_max_buffers = VEPU2_SESSION_MAX_BUFFERS;
|
||||
vepu_procfs_init(mpp);
|
||||
/* register current device to mpp service */
|
||||
|
||||
@@ -76,7 +76,6 @@
|
||||
#define RGA2_PHY_PAGE_SIZE (((8192 * 8192 * 4) / 4096) + 1)
|
||||
|
||||
ktime_t rga2_start;
|
||||
ktime_t rga2_end;
|
||||
int rga2_flag;
|
||||
int first_RGA2_proc;
|
||||
static int rk3368;
|
||||
@@ -1179,9 +1178,11 @@ retry:
|
||||
|
||||
#ifdef CONFIG_ROCKCHIP_RGA2_DEBUGGER
|
||||
if (RGA2_TEST_TIME) {
|
||||
rga2_end = ktime_get();
|
||||
rga2_end = ktime_sub(rga2_end, rga2_start);
|
||||
DBG("sync one cmd end time %d\n", (int)ktime_to_us(rga2_end));
|
||||
ktime_t rga2_cmd_end;
|
||||
|
||||
rga2_cmd_end = ktime_get();
|
||||
rga2_cmd_end = ktime_sub(rga2_cmd_end, rga2_start);
|
||||
DBG("sync one cmd end time %d us\n", (int)ktime_to_us(rga2_cmd_end));
|
||||
}
|
||||
#endif
|
||||
if (ret == -ETIMEDOUT && try--) {
|
||||
@@ -1657,6 +1658,14 @@ static irqreturn_t rga2_irq_thread(int irq, void *dev_id)
|
||||
if (RGA2_INT_FLAG)
|
||||
INFO("irqthread INT[%x],STATS[%x]\n", rga2_read(RGA2_INT),
|
||||
rga2_read(RGA2_STATUS));
|
||||
|
||||
if (RGA2_TEST_TIME) {
|
||||
ktime_t rga2_hw_end;
|
||||
|
||||
rga2_hw_end = ktime_get();
|
||||
rga2_hw_end = ktime_sub(rga2_hw_end, rga2_start);
|
||||
DBG("RGA hardware cost time %d us\n", (int)ktime_to_us(rga2_hw_end));
|
||||
}
|
||||
#endif
|
||||
RGA2_flush_page();
|
||||
mutex_lock(&rga2_service.lock);
|
||||
|
||||
12
drivers/video/rockchip/vtunnel/Kconfig
Normal file
12
drivers/video/rockchip/vtunnel/Kconfig
Normal file
@@ -0,0 +1,12 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
|
||||
menu "Rockchip video tunnel support"
|
||||
|
||||
config ROCKCHIP_VIDEO_TUNNEL
|
||||
tristate "Rockchip video tunnel device support"
|
||||
depends on ARCH_ROCKCHIP
|
||||
default n
|
||||
help
|
||||
Rockchip videotunnel device support.
|
||||
|
||||
endmenu
|
||||
3
drivers/video/rockchip/vtunnel/Makefile
Normal file
3
drivers/video/rockchip/vtunnel/Makefile
Normal file
@@ -0,0 +1,3 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
obj-$(CONFIG_ROCKCHIP_VIDEO_TUNNEL) += rkvtunnel.o
|
||||
1523
drivers/video/rockchip/vtunnel/rkvtunnel.c
Normal file
1523
drivers/video/rockchip/vtunnel/rkvtunnel.c
Normal file
File diff suppressed because it is too large
Load Diff
81
drivers/video/rockchip/vtunnel/rkvtunnel.h
Normal file
81
drivers/video/rockchip/vtunnel/rkvtunnel.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
|
||||
/*
|
||||
* Copyright (c) 2022 Rockchip Electronics Co., Ltd
|
||||
*/
|
||||
#ifndef __ROCKCHIP_VIDEO_TUNNEL_H__
|
||||
#define __ROCKCHIP_VIDEO_TUNNEL_H__
|
||||
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define MAX_BUF_HANDLE_FDS 16
|
||||
#define MAX_BUF_HANDLE_INTS 128
|
||||
|
||||
#define RKVT_IOC_MAGIC 'V'
|
||||
#define RKVT_IOWR(nr, type) _IOWR(RKVT_IOC_MAGIC, nr, type)
|
||||
|
||||
#define RKVT_IOC_ALLOC_ID RKVT_IOWR(0x0, struct rkvt_alloc_id_data)
|
||||
#define RKVT_IOC_FREE_ID RKVT_IOWR(0x1, struct rkvt_alloc_id_data)
|
||||
#define RKVT_IOC_CTRL RKVT_IOWR(0x2, struct rkvt_ctrl_data)
|
||||
#define RKVT_IOC_QUEUE_BUF RKVT_IOWR(0x3, struct rkvt_buf_data)
|
||||
#define RKVT_IOC_DEQUE_BUF RKVT_IOWR(0x4, struct rkvt_buf_data)
|
||||
#define RKVT_IOC_CANCEL_BUF RKVT_IOWR(0x5, struct rkvt_buf_data)
|
||||
#define RKVT_IOC_ACQUIRE_BUF RKVT_IOWR(0x6, struct rkvt_buf_data)
|
||||
#define RKVT_IOC_RELEASE_BUF RKVT_IOWR(0x7, struct rkvt_buf_data)
|
||||
|
||||
// caller type
|
||||
enum rkvt_caller_e {
|
||||
RKVT_CALLER_PRODUCER,
|
||||
RKVT_CALLER_CONSUMER,
|
||||
RKVT_CALLER_BUTT,
|
||||
};
|
||||
|
||||
// video tunnel caller control
|
||||
enum rkvt_ctrl_cmd_e {
|
||||
RKVT_CTRL_CONNECT,
|
||||
RKVT_CTRL_DISCONNECT,
|
||||
RKVT_CTRL_RESET,
|
||||
RKVT_CTRL_HAS_CONSUMER,
|
||||
RKVT_CTRL_BUTT,
|
||||
};
|
||||
|
||||
struct rkvt_alloc_id_data {
|
||||
int vt_id;
|
||||
};
|
||||
|
||||
struct rkvt_ctrl_data {
|
||||
int vt_id;
|
||||
enum rkvt_caller_e caller;
|
||||
enum rkvt_ctrl_cmd_e ctrl_cmd;
|
||||
int ctrl_data;
|
||||
};
|
||||
|
||||
struct rkvt_rect {
|
||||
int left;
|
||||
int top;
|
||||
int right;
|
||||
int bottom;
|
||||
};
|
||||
|
||||
struct rkvt_buf_base {
|
||||
int vt_id;
|
||||
int fence_fd;
|
||||
int buf_status;
|
||||
int num_fds; /* number of file-descriptors at &data[0] */
|
||||
int num_ints; /* number of ints at &data[numFds] */
|
||||
int reserved;
|
||||
int fds[MAX_BUF_HANDLE_FDS];
|
||||
int ints[MAX_BUF_HANDLE_INTS];
|
||||
int64_t priv_data;
|
||||
uint64_t expected_present_time;
|
||||
uint64_t buffer_id;
|
||||
struct rkvt_rect crop;
|
||||
};
|
||||
|
||||
struct rkvt_buf_data {
|
||||
int vt_id;
|
||||
int timeout_ms; /* 0: non block, negative: block, other: timeout ms */
|
||||
struct rkvt_buf_base base;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -145,6 +145,7 @@ struct data_chunk {
|
||||
* Otherwise, destination is filled contiguously (icg ignored).
|
||||
* Ignored if dst_inc is false.
|
||||
* @numf: Number of frames in this template.
|
||||
* @nump: Number of period frames in this template.
|
||||
* @frame_size: Number of chunks in a frame i.e, size of sgl[].
|
||||
* @sgl: Array of {chunk,icg} pairs that make up a frame.
|
||||
*/
|
||||
@@ -157,6 +158,9 @@ struct dma_interleaved_template {
|
||||
bool src_sgl;
|
||||
bool dst_sgl;
|
||||
size_t numf;
|
||||
#ifdef CONFIG_NO_GKI
|
||||
size_t nump;
|
||||
#endif
|
||||
size_t frame_size;
|
||||
struct data_chunk sgl[];
|
||||
};
|
||||
@@ -448,10 +452,6 @@ struct dma_slave_config {
|
||||
bool device_fc;
|
||||
void *peripheral_config;
|
||||
size_t peripheral_size;
|
||||
#ifdef CONFIG_NO_GKI
|
||||
unsigned int src_interlace_size;
|
||||
unsigned int dst_interlace_size;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
432
include/linux/icm4260x.h
Normal file
432
include/linux/icm4260x.h
Normal file
@@ -0,0 +1,432 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Definitions for icm4260x chip.
|
||||
*/
|
||||
#ifndef __ICM4260X_ACC_H
|
||||
#define __ICM4260X_ACC_H
|
||||
|
||||
/* Registers and associated bit definitions */
|
||||
/* Bank 0 */
|
||||
#define ICM4260X_MISC_1 0x00
|
||||
#define ICM4260X_CHIP_CONFIG_REG 0x01
|
||||
#define ICM4260X_SIGNAL_PATH_RESET 0x02
|
||||
#define ICM4260X_DRIVE_CONFIG_REG1 0x03
|
||||
#define ICM4260X_DRIVE_CONFIG_REG2 0x04
|
||||
#define ICM4260X_DRIVE_CONFIG_REG3 0x05
|
||||
#define ICM4260X_INT_CONFIG_REG 0x06
|
||||
#define ICM4260X_ODRGRID0 0x07
|
||||
#define ICM4260X_ODRGRID1 0x08
|
||||
#define ICM4260X_TEMP_DATA0 0x09
|
||||
#define ICM4260X_TEMP_DATA1 0x0a
|
||||
#define ICM4260X_ACCEL_DATA_X0 0x0b
|
||||
#define ICM4260X_ACCEL_DATA_X1 0x0c
|
||||
#define ICM4260X_ACCEL_DATA_Y0 0x0d
|
||||
#define ICM4260X_ACCEL_DATA_Y1 0x0e
|
||||
#define ICM4260X_ACCEL_DATA_Z0 0x0f
|
||||
#define ICM4260X_ACCEL_DATA_Z1 0x10
|
||||
#define ICM4260X_GYRO_DATA_X0 0x11
|
||||
#define ICM4260X_GYRO_DATA_X1 0x12
|
||||
#define ICM4260X_GYRO_DATA_Y0 0x13
|
||||
#define ICM4260X_GYRO_DATA_Y1 0x14
|
||||
#define ICM4260X_GYRO_DATA_Z0 0x15
|
||||
#define ICM4260X_GYRO_DATA_Z1 0x16
|
||||
#define ICM4260X_TMST_FSYNC1 0x17
|
||||
#define ICM4260X_TMST_FSYNC2 0x18
|
||||
#define ICM4260X_ODR_LP_STATUS 0x19
|
||||
#define ICM4260X_PWR_MGMT_0 0x1f
|
||||
#define ICM4260X_GYRO_CONFIG0 0x20
|
||||
#define ICM4260X_ACCEL_CONFIG0 0x21
|
||||
#define ICM4260X_TEMP_CONFIG0 0x22
|
||||
#define ICM4260X_GYRO_CONFIG1 0x23
|
||||
#define ICM4260X_ACCEL_CONFIG1 0x24
|
||||
#define ICM4260X_APEX_CONFIG0 0x25
|
||||
#define ICM4260X_APEX_CONFIG1 0x26
|
||||
#define ICM4260X_WOM_CONFIG 0x27
|
||||
#define ICM4260X_FIFO_CONFIG1 0x28
|
||||
#define ICM4260X_FIFO_CONFIG2 0x29
|
||||
#define ICM4260X_FIFO_CONFIG3 0x2a
|
||||
#define ICM4260X_INT_SOURCE0 0x2b
|
||||
#define ICM4260X_INT_SOURCE1 0x2c
|
||||
#define ICM4260X_INT_SOURCE3 0x2d
|
||||
#define ICM4260X_INT_SOURCE4 0x2e
|
||||
#define ICM4260X_FIFO_LOST_PKT0 0x2f
|
||||
#define ICM4260X_FIFO_LOST_PKT1 0x30
|
||||
#define ICM4260X_APEX_DATA0 0x31
|
||||
#define ICM4260X_APEX_DATA1 0x32
|
||||
#define ICM4260X_APEX_DATA2 0x33
|
||||
#define ICM4260X_APEX_DATA3 0x34
|
||||
#define ICM4260X_INTF_CONFIG0 0x35
|
||||
#define ICM4260X_INTF_CONFIG1 0x36
|
||||
#define ICM4260X_INT_STATUS_DRDY 0x39
|
||||
#define ICM4260X_INT_STATUS 0x3a
|
||||
#define ICM4260X_INT_STATUS2 0x3b
|
||||
#define ICM4260X_INT_STATUS3 0x3c
|
||||
#define ICM4260X_FIFO_BYTE_COUNT1 0x3d
|
||||
#define ICM4260X_FIFO_BYTE_COUNT2 0x3e
|
||||
#define ICM4260X_FIFO_DATA_REG 0x3f
|
||||
#define ICM4260X_S4S_GYRO_TPH1 0x40
|
||||
#define ICM4260X_S4S_GYRO_TPH2 0x41
|
||||
#define ICM4260X_S4S_ACCEL_TPH1 0x42
|
||||
#define ICM4260X_S4S_ACCEL_TPH2 0x43
|
||||
#define ICM4260X_S4S_RR 0x44
|
||||
#define ICM4260X_GYR_BIAS_CFG1 0x46
|
||||
#define ICM4260X_WHO_AM_I 0x75
|
||||
#define ICM4260X_S4S_ST 0x76
|
||||
#define ICM4260X_S4S_ST_CLONE 0x77
|
||||
#define ICM4260X_S4S_DT 0x78
|
||||
#define ICM4260X_BLK_SEL_W 0x79
|
||||
#define ICM4260X_MADDR_W 0x7a
|
||||
#define ICM4260X_M_W 0x7b
|
||||
#define ICM4260X_BLK_SEL_R 0x7c
|
||||
#define ICM4260X_MADDR_R 0x7d
|
||||
#define ICM4260X_M_R 0x7e
|
||||
|
||||
/* MREG_TOP1 */
|
||||
#define ICM4260X_TMST_CONFIG1_MREG_TOP1 0x00
|
||||
#define ICM4260X_FIFO_CONFIG5_MREG_TOP1 0x01
|
||||
#define ICM4260X_FIFO_CONFIG6_MREG_TOP1 0x02
|
||||
#define ICM4260X_FSYNC_CONFIG_MREG_TOP1 0x03
|
||||
#define ICM4260X_INT_CONFIG0_MREG_TOP1 0x04
|
||||
#define ICM4260X_INT_CONFIG1_MREG_TOP1 0x05
|
||||
#define ICM4260X_AFSR_CONFIG0_MREG_TOP1 0x07
|
||||
#define ICM4260X_AFSR_CONFIG1_MREG_TOP1 0x08
|
||||
#define ICM4260X_TBC_RCOSC_MREG_TOP1 0x0d
|
||||
#define ICM4260X_TBC_PLL_MREG_TOP1 0x0e
|
||||
#define ICM4260X_ST_CONFIG_MREG_TOP1 0x13
|
||||
#define ICM4260X_SELFTEST_MREG_TOP1 0x14
|
||||
#define ICM4260X_PADS_CONFIG3_MREG_TOP1 0x17
|
||||
#define ICM4260X_TEMP_CONFIG1_MREG_TOP1 0x1c
|
||||
#define ICM4260X_TEMP_CONFIG3_MREG_TOP1 0x1e
|
||||
#define ICM4260X_S4S_CONFIG1_MREG_TOP1 0x1f
|
||||
#define ICM4260X_S4S_CONFIG2_MREG_TOP1 0x20
|
||||
#define ICM4260X_S4S_FREQ_RATIO1_MREG_TOP1 0x21
|
||||
#define ICM4260X_S4S_FREQ_RATIO2_MREG_TOP1 0x22
|
||||
#define ICM4260X_INTF_CONFIG6_MREG_TOP1 0x23
|
||||
#define ICM4260X_INTF_CONFIG10_MREG_TOP1 0x25
|
||||
#define ICM4260X_INTF_CONFIG7_MREG_TOP1 0x28
|
||||
#define ICM4260X_OTP_CONFIG_MREG_TOP1 0x2b
|
||||
#define ICM4260X_INT_SOURCE6_MREG_TOP1 0x2f
|
||||
#define ICM4260X_INT_SOURCE7_MREG_TOP1 0x30
|
||||
#define ICM4260X_INT_SOURCE8_MREG_TOP1 0x31
|
||||
#define ICM4260X_INT_SOURCE9_MREG_TOP1 0x32
|
||||
#define ICM4260X_INT_SOURCE10_MREG_TOP1 0x33
|
||||
#define ICM4260X_GYRO_PWR_CFG0_MREG_TOP1 0x38
|
||||
#define ICM4260X_ACCEL_CP_CFG0_MREG_TOP1 0x39
|
||||
#define ICM4260X_APEX_CONFIG2_MREG_TOP1 0x44
|
||||
#define ICM4260X_APEX_CONFIG3_MREG_TOP1 0x45
|
||||
#define ICM4260X_APEX_CONFIG4_MREG_TOP1 0x46
|
||||
#define ICM4260X_APEX_CONFIG5_MREG_TOP1 0x47
|
||||
#define ICM4260X_APEX_CONFIG9_MREG_TOP1 0x48
|
||||
#define ICM4260X_APEX_CONFIG10_MREG_TOP1 0x49
|
||||
#define ICM4260X_APEX_CONFIG11_MREG_TOP1 0x4a
|
||||
#define ICM4260X_APEX_CONFIG12_MREG_TOP1 0x67
|
||||
#define ICM4260X_ACCEL_WOM_X_THR_MREG_TOP1 0x4b
|
||||
#define ICM4260X_ACCEL_WOM_Y_THR_MREG_TOP1 0x4c
|
||||
#define ICM4260X_ACCEL_WOM_Z_THR_MREG_TOP1 0x4d
|
||||
#define ICM4260X_GOS_USER0_MREG_TOP1 0x4e
|
||||
#define ICM4260X_GOS_USER1_MREG_TOP1 0x4f
|
||||
#define ICM4260X_GOS_USER2_MREG_TOP1 0x50
|
||||
#define ICM4260X_GOS_USER3_MREG_TOP1 0x51
|
||||
#define ICM4260X_GOS_USER4_MREG_TOP1 0x52
|
||||
#define ICM4260X_GOS_USER5_MREG_TOP1 0x53
|
||||
#define ICM4260X_GOS_USER6_MREG_TOP1 0x54
|
||||
#define ICM4260X_GOS_USER7_MREG_TOP1 0x55
|
||||
#define ICM4260X_GOS_USER8_MREG_TOP1 0x56
|
||||
#define ICM4260X_ST_STATUS1_MREG_TOP1 0x63
|
||||
#define ICM4260X_ST_STATUS2_MREG_TOP1 0x64
|
||||
|
||||
/* MMEM_TOP */
|
||||
#define ICM4260X_XA_ST_DATA_MMEM_TOP 0x5000
|
||||
#define ICM4260X_YA_ST_DATA_MMEM_TOP 0x5001
|
||||
#define ICM4260X_ZA_ST_DATA_MMEM_TOP 0x5002
|
||||
#define ICM4260X_XG_ST_DATA_MMEM_TOP 0x5003
|
||||
#define ICM4260X_YG_ST_DATA_MMEM_TOP 0x5004
|
||||
#define ICM4260X_ZG_ST_DATA_MMEM_TOP 0x5005
|
||||
|
||||
/* MREG_OTP */
|
||||
#define ICM4260X_OTP_CTRL7_MREG_OTP 0x2806
|
||||
|
||||
/* Bank0 REG_GYRO_CONFIG0/REG_ACCEL_CONFIG0 */
|
||||
#define SHIFT_GYRO_FS_SEL 5
|
||||
#define SHIFT_ACCEL_FS_SEL 5
|
||||
#define SHIFT_ODR_CONF 0
|
||||
#define BIT_GYRO_FSR 0x60
|
||||
#define BIT_GYRO_ODR 0x0F
|
||||
#define BIT_ACCEL_FSR 0x60
|
||||
#define ACCEL_FS_SEL 3 //(-2G, +2G)
|
||||
#define GYRO_FS_SEL 3 //00~11:2000dps\1000dps\500dps\250dps
|
||||
#define BIT_ACCEL_ODR 0x0F
|
||||
#define BIT_SENSOR_ODR_800HZ 0x06
|
||||
#define BIT_SENSOR_ODR_400HZ 0x07
|
||||
#define BIT_SENSOR_ODR_200HZ 0x08
|
||||
#define BIT_SENSOR_ODR_100HZ 0x09
|
||||
#define BIT_SENSOR_ODR_50HZ 0x0A
|
||||
#define BIT_SENSOR_ODR_25HZ 0x0B
|
||||
#define BIT_SENSOR_ODR_12HZ 0x0C
|
||||
#define BIT_SENSOR_ODR_6HZ 0x0D
|
||||
#define BIT_SENSOR_ODR_3HZ 0x0E
|
||||
|
||||
/* Bank0 REG_GYRO_CONFIG1 */
|
||||
#define BIT_GYR_UI_FLT_BW_BYPASS 0x00
|
||||
#define BIT_GYR_UI_FLT_BW_180HZ 0x01
|
||||
#define BIT_GYR_UI_FLT_BW_121HZ 0x02
|
||||
#define BIT_GYR_UI_FLT_BW_73HZ 0x03
|
||||
#define BIT_GYR_UI_FLT_BW_53HZ 0x04
|
||||
#define BIT_GYR_UI_FLT_BW_34HZ 0x05
|
||||
#define BIT_GYR_UI_FLT_BW_25HZ 0x06
|
||||
#define BIT_GYR_UI_FLT_BW_16HZ 0x07
|
||||
#define BIT_GYR_UI_AVG_IND_2X 0x00
|
||||
#define BIT_GYR_UI_AVG_IND_4X 0x10
|
||||
#define BIT_GYR_UI_AVG_IND_8X 0x20
|
||||
#define BIT_GYR_UI_AVG_IND_16X 0x30
|
||||
#define BIT_GYR_UI_AVG_IND_32X 0x40
|
||||
#define BIT_GYR_UI_AVG_IND_64X 0x50
|
||||
|
||||
/* Bank0 REG_ACCEL_CONFIG1 */
|
||||
#define BIT_ACC_FILT_BW_IND_BYPASS 0x00
|
||||
#define BIT_ACC_FILT_BW_IND_180HZ 0x01
|
||||
#define BIT_ACC_FILT_BW_IND_121HZ 0x02
|
||||
#define BIT_ACC_FILT_BW_IND_73HZ 0x03
|
||||
#define BIT_ACC_FILT_BW_IND_53HZ 0x04
|
||||
#define BIT_ACC_FILT_BW_IND_34HZ 0x05
|
||||
#define BIT_ACC_FILT_BW_IND_25HZ 0x06
|
||||
#define BIT_ACC_FILT_BW_IND_16HZ 0x07
|
||||
#define BIT_ACC_UI_AVG_IND_2X 0x00
|
||||
#define BIT_ACC_UI_AVG_IND_4X 0x10
|
||||
#define BIT_ACC_UI_AVG_IND_8X 0x20
|
||||
#define BIT_ACC_UI_AVG_IND_16X 0x30
|
||||
#define BIT_ACC_UI_AVG_IND_32X 0x40
|
||||
#define BIT_ACC_UI_AVG_IND_64X 0x50
|
||||
|
||||
/* Bank0 REG_INT_CONFIG_REG */
|
||||
#define SHIFT_INT1_MODE 0x02
|
||||
#define SHIFT_INT1_DRIVE_CIRCUIT 0x01
|
||||
#define SHIFT_INT1_POLARITY 0x00
|
||||
|
||||
/* Bank0 REG_PWR_MGMT_0 */
|
||||
#define BIT_ACCEL_MODE_OFF 0x00
|
||||
#define BIT_ACCEL_MODE_LPM 0x02
|
||||
#define BIT_ACCEL_MODE_LNM 0x03
|
||||
#define BIT_ACCEL_MODE_MASK 0x03
|
||||
#define BIT_GYRO_MODE_OFF 0x00
|
||||
#define BIT_GYRO_MODE_STBY 0x04
|
||||
#define BIT_GYRO_MODE_LPM 0x08
|
||||
#define BIT_GYRO_MODE_LNM 0x0c
|
||||
#define BIT_GYRO_MODE_MASK 0x0c
|
||||
#define BIT_IDLE 0x10
|
||||
#define BIT_ACCEL_LP_CLK_SEL 0x80
|
||||
|
||||
/* Bank0 REG_SIGNAL_PATH_RESET */
|
||||
#define BIT_FIFO_FLUSH 0x04
|
||||
#define BIT_SOFT_RESET_CHIP_CONFIG 0x10
|
||||
|
||||
/* Bank0 REG_INTF_CONFIG0 */
|
||||
#define BIT_SIFS_CFG_I2C_ONLY 0x02
|
||||
#define BIT_SIFS_CFG_SPI_ONLY 0x03
|
||||
#define BIT_SENSOR_DATA_ENDIAN 0x10
|
||||
#define BIT_FIFO_COUNT_ENDIAN 0x20
|
||||
#define BIT_FIFO_COUNT_FORMAT 0x40
|
||||
#define BIT_FIFO_SREG_INVALID_IND_DIS 0x80
|
||||
|
||||
/* Bank0 REG_INTF_CONFIG1 */
|
||||
#define BIT_CLK_SEL_RC 0x00
|
||||
#define BIT_CLK_SEL_PLL 0x01
|
||||
#define BIT_CLK_SEL_DIS 0x03
|
||||
#define BIT_I3C_DDR_EN 0x04
|
||||
#define BIT_I3C_SDR_EN 0x08
|
||||
#define BIT_GYRO_AFSR_MODE_LFS 0x00
|
||||
#define BIT_GYRO_AFSR_MODE_HFS 0x20
|
||||
#define BIT_GYRO_AFSR_MODE_DYN 0x40
|
||||
|
||||
/* Bank0 REG_FIFO_CONFIG1 */
|
||||
#define BIT_FIFO_MODE_NO_BYPASS 0x00
|
||||
#define BIT_FIFO_MODE_BYPASS 0x01
|
||||
#define BIT_FIFO_MODE_STREAM 0x00
|
||||
#define BIT_FIFO_MODE_STOPFULL 0x02
|
||||
|
||||
/* Bank 0 REG_INT_SOURCE0 */
|
||||
#define BIT_INT_AGC_RDY_INT1_EN 0x01
|
||||
#define BIT_INT_FIFO_FULL_INT1_EN 0x02
|
||||
#define BIT_INT_FIFO_THS_INT1_EN 0x04
|
||||
#define BIT_INT_DRDY_INT_EN 0x08
|
||||
#define BIT_INT_RESET_DONE_INT1_EN 0x10
|
||||
#define BIT_INT_PLL_RDY_INT1_EN 0x20
|
||||
#define BIT_INT_FSYNC_INT1_EN 0x40
|
||||
#define BIT_INT_ST_DONE_INT1_EN 0x80
|
||||
|
||||
/* Bank 0 REG_INT_SOURCE1 */
|
||||
#define BIT_INT_WOM_X_INT1_EN 0x01
|
||||
#define BIT_INT_WOM_Y_INT1_EN 0x02
|
||||
#define BIT_INT_WOM_Z_INT1_EN 0x04
|
||||
#define BIT_INT_WOM_XYZ_INT1_EN (BIT_INT_WOM_X_INT1_EN | \
|
||||
BIT_INT_WOM_Y_INT1_EN | BIT_INT_WOM_Z_INT1_EN)
|
||||
#define BIT_INT_SMD_INT1_EN 0x08
|
||||
#define BIT_INT_I3C_PROTCL_ERR_INT1_EN 0x40
|
||||
|
||||
/* Bank0 REG_INT_STATUS_DRDY */
|
||||
#define BIT_INT_STATUS_DRDY 0x01
|
||||
|
||||
/* Bank0 REG_INT_STATUS */
|
||||
#define BIT_INT_STATUS_AGC_RDY 0x01
|
||||
#define BIT_INT_STATUS_FIFO_FULL 0x02
|
||||
#define BIT_INT_STATUS_FIFO_THS 0x04
|
||||
#define BIT_INT_STATUS_RESET_DONE 0x10
|
||||
#define BIT_INT_STATUS_PLL_RDY 0x20
|
||||
#define BIT_INT_STATUS_FSYNC 0x40
|
||||
#define BIT_INT_STATUS_ST_DONE 0x80
|
||||
|
||||
/* Bank0 REG_INT_STATUS2 */
|
||||
#define BIT_INT_STATUS_WOM_Z 0x01
|
||||
#define BIT_INT_STATUS_WOM_Y 0x02
|
||||
#define BIT_INT_STATUS_WOM_X 0x04
|
||||
#define BIT_INT_STATUS_WOM_XYZ (BIT_INT_STATUS_WOM_X | \
|
||||
BIT_INT_STATUS_WOM_Y | BIT_INT_STATUS_WOM_Z)
|
||||
#define BIT_INT_STATUS_SMD 0x08
|
||||
|
||||
/* Bank 0 REG_INT_STATUS3 */
|
||||
#define BIT_INT_STATUS_LOWG_DET 0x02
|
||||
#define BIT_INT_STATUS_FF_DET 0x04
|
||||
#define BIT_INT_STATUS_TILT_DET 0x08
|
||||
#define BIT_INT_STATUS_STEP_CNT_OVFL 0x10
|
||||
#define BIT_INT_STATUS_STEP_DET 0x20
|
||||
|
||||
/* Bank0 REG_WOM_CONFIG */
|
||||
#define BIT_WOM_EN_OFF 0x00
|
||||
#define BIT_WOM_EN_ON 0x01
|
||||
#define BIT_WOM_MODE_INITIAL 0x00
|
||||
#define BIT_WOM_MODE_PREV 0x02
|
||||
#define BIT_WOM_INT_MODE_OR 0x00
|
||||
#define BIT_WOM_INT_MODE_AND 0x04
|
||||
#define BIT_WOM_INT_DUR_LEGACY 0x00
|
||||
#define BIT_WOM_INT_DUR_2ND 0x08
|
||||
#define BIT_WOM_INT_DUR_3RD 0x10
|
||||
#define BIT_WOM_INT_DUR_4TH 0x18
|
||||
|
||||
/* Bank0 REG_APEX_CONFIG0 */
|
||||
#define BIT_DMP_SRAM_RESET_APEX 0x01
|
||||
#define BIT_DMP_INIT_EN 0x04
|
||||
#define BIT_DMP_POWER_SAVE_EN 0x08
|
||||
|
||||
/* Bank0 REG_APEX_CONFIG1 */
|
||||
#define BIT_DMP_ODR_25HZ 0x00
|
||||
#define BIT_DMP_ODR_50HZ 0x02
|
||||
#define BIT_DMP_ODR_100HZ 0x03
|
||||
#define BIT_DMP_PEDO_EN 0x08
|
||||
#define BIT_DMP_TILT_EN 0x10
|
||||
#define BIT_DMP_FF_EN 0x20
|
||||
#define BIT_DMP_SMD_EN 0x40
|
||||
|
||||
/* REG_OTP_CONFIG_MREG_TOP1 */
|
||||
#define BIT_OTP_COPY_NORMAL 0x04
|
||||
#define BIT_OTP_COPY_ST_DATA 0x0C
|
||||
#define OTP_COPY_MODE_MASK 0x0C
|
||||
|
||||
/* REG_INT_SOURCE6_MREG_TOP1 */
|
||||
#define BIT_INT_TLT_DET_INT1_EN 0x08
|
||||
#define BIT_INT_STEP_CNT_OVFL_INT1_EN 0x10
|
||||
#define BIT_INT_STEP_DET_INT1_EN 0x20
|
||||
#define BIT_INT_LOWG_INT1_EN 0x40
|
||||
#define BIT_INT_FF_INT1_EN 0x80
|
||||
|
||||
/* REG_TMST_CONFIG1_MREG_TOP1 */
|
||||
#define BIT_TMST_EN 0x01
|
||||
#define BIT_TMST_FSYNC_EN 0x02
|
||||
#define BIT_TMST_DELTA_EN 0x04
|
||||
#define BIT_TMST_RESOL 0x08
|
||||
#define BIT_TMST_ON_SREG_EN 0x10
|
||||
#define BIT_ODR_EN_WITHOUT_SENSOR 0x40
|
||||
|
||||
/* REG_FIFO_CONFIG5_MREG_TOP1 */
|
||||
#define BIT_FIFO_ACCEL_EN 0x01
|
||||
#define BIT_FIFO_GYRO_EN 0x02
|
||||
#define BIT_FIFO_TMST_FSYNC_EN 0x04
|
||||
#define BIT_FIFO_HIRES_EN 0x08
|
||||
#define BIT_RESUME_PARTIAL_RD 0x10
|
||||
#define BIT_WM_GT_TH 0x20
|
||||
|
||||
/* REG_SELFTEST_MREG_TOP1 */
|
||||
#define BIT_EN_AX_ST 0x01
|
||||
#define BIT_EN_AY_ST 0x02
|
||||
#define BIT_EN_AZ_ST 0x04
|
||||
#define BIT_EN_GX_ST 0x08
|
||||
#define BIT_EN_GY_ST 0x10
|
||||
#define BIT_EN_GZ_ST 0x20
|
||||
#define BIT_ACCEL_ST_EN 0x40
|
||||
#define BIT_GYRO_ST_EN 0x80
|
||||
|
||||
/* REG_ST_CONFIG_MREG_TOP1 */
|
||||
#define BIT_PD_ACCEL_CP45_ST_REG 0x80
|
||||
#define SHIFT_GYRO_ST_LIM 0
|
||||
#define SHIFT_ACCEL_ST_LIM 3
|
||||
#define SHIFT_ST_NUM_SAMPLE 6
|
||||
|
||||
/* REG_ST_STATUS1_MREG_TOP1 */
|
||||
#define BIT_DMP_AX_ST_PASS 0x02
|
||||
#define BIT_DMP_AY_ST_PASS 0x04
|
||||
#define BIT_DMP_AZ_ST_PASS 0x08
|
||||
#define BIT_DMP_ACCEL_ST_DONE 0x10
|
||||
#define BIT_DMP_ACCEL_ST_PASS 0x20
|
||||
|
||||
/* REG_ST_STATUS2_MREG_TOP1 */
|
||||
#define BIT_DMP_GX_ST_PASS 0x02
|
||||
#define BIT_DMP_GY_ST_PASS 0x04
|
||||
#define BIT_DMP_GZ_ST_PASS 0x08
|
||||
#define BIT_DMP_GYRO_ST_DONE 0x10
|
||||
#define BIT_DMP_GYRO_ST_PASS 0x20
|
||||
#define BIT_DMP_ST_INCOMPLETE 0x40
|
||||
|
||||
/* REG_OTP_CTRL7_MREG_OTP */
|
||||
#define BIT_OTP_RELOAD 0x08
|
||||
#define BIT_OTP_PWR_DOWN 0x02
|
||||
|
||||
|
||||
/* fifo data packet header */
|
||||
#define BIT_FIFO_HEAD_MSG 0x80
|
||||
#define BIT_FIFO_HEAD_ACCEL 0x40
|
||||
#define BIT_FIFO_HEAD_GYRO 0x20
|
||||
#define BIT_FIFO_HEAD_20 0x10
|
||||
#define BIT_FIFO_HEAD_TMSP_ODR 0x08
|
||||
#define BIT_FIFO_HEAD_TMSP_NO_ODR 0x04
|
||||
#define BIT_FIFO_HEAD_TMSP_FSYNC 0x0C
|
||||
#define BIT_FIFO_HEAD_ODR_ACCEL 0x02
|
||||
#define BIT_FIFO_HEAD_ODR_GYRO 0x01
|
||||
|
||||
/* data definitions */
|
||||
#define FIFO_PACKET_BYTE_SINGLE 8
|
||||
#define FIFO_PACKET_BYTE_6X 16
|
||||
#define FIFO_PACKET_BYTE_HIRES 20
|
||||
#define FIFO_COUNT_BYTE 2
|
||||
|
||||
/* sensor startup time */
|
||||
#define INV_ICM43600_GYRO_START_TIME 100
|
||||
#define INV_ICM43600_ACCEL_START_TIME 100
|
||||
|
||||
/* sensor stop time */
|
||||
#define INV_ICM43600_GYRO_STOP_TIME 20
|
||||
|
||||
/* M-reg access wait tile */
|
||||
#define INV_ICM42607_MCLK_WAIT_US 20
|
||||
#define INV_ICM42607_BLK_SEL_WAIT_US 10
|
||||
#define INV_ICM42607_MADDR_WAIT_US 10
|
||||
#define INV_ICM42607_M_RW_WAIT_US 10
|
||||
|
||||
/* temperature sensor */
|
||||
#define TEMP_SCALE 100 /* scale by 100 */
|
||||
#define TEMP_LSB_PER_DEG 2 /* 2LSB=1degC */
|
||||
#define TEMP_OFFSET 25 /* 25 degC */
|
||||
|
||||
/*
|
||||
* INT configurations
|
||||
* Polarity: 0 -> Active Low, 1 -> Active High
|
||||
* Drive circuit: 0 -> Open Drain, 1 -> Push-Pull
|
||||
* Mode: 0 -> Pulse, 1 -> Latch
|
||||
*/
|
||||
#define INT_POLARITY 1
|
||||
#define INT_DRIVE_CIRCUIT 1
|
||||
#define INT_MODE 0
|
||||
|
||||
#define ICM42607_DEVICE_ID 0x61
|
||||
#define ICM4260X_PRECISION 16
|
||||
#define ICM42607_ADDR 0x68
|
||||
|
||||
#endif
|
||||
@@ -70,6 +70,7 @@ enum sensor_id {
|
||||
ACCEL_ID_DA215S,
|
||||
ACCEL_ID_DA228E,
|
||||
ACCEL_ID_IAM20680,
|
||||
ACCEL_ID_ICM4260X,
|
||||
COMPASS_ID_ALL,
|
||||
COMPASS_ID_AK8975,
|
||||
COMPASS_ID_AK8963,
|
||||
@@ -97,6 +98,7 @@ enum sensor_id {
|
||||
GYRO_ID_LSM330,
|
||||
GYRO_ID_ICM2060X,
|
||||
GYRO_ID_IAM20680,
|
||||
GYRO_ID_ICM4260X,
|
||||
LIGHT_ID_ALL,
|
||||
LIGHT_ID_CM3217,
|
||||
LIGHT_ID_CM3218,
|
||||
|
||||
@@ -9,15 +9,18 @@
|
||||
#ifndef _ROCKCHIP_AMP
|
||||
#define _ROCKCHIP_AMP
|
||||
|
||||
#include <linux/irqchip/arm-gic-common.h>
|
||||
|
||||
#if IS_REACHABLE(CONFIG_ROCKCHIP_AMP)
|
||||
void rockchip_amp_get_gic_info(void);
|
||||
void rockchip_amp_get_gic_info(u32 spis_num, enum gic_type gic_version);
|
||||
int rockchip_amp_check_amp_irq(u32 irq);
|
||||
u32 rockchip_amp_get_irq_prio(u32 irq);
|
||||
u32 rockchip_amp_get_irq_cpumask(u32 irq);
|
||||
u64 rockchip_amp_get_irq_aff(u32 irq);
|
||||
int rockchip_amp_need_init_amp_irq(u32 irq);
|
||||
#else
|
||||
#include <linux/irqchip/arm-gic-common.h>
|
||||
|
||||
static inline void rockchip_amp_get_gic_info(void)
|
||||
static inline void rockchip_amp_get_gic_info(u32 spis_num,
|
||||
enum gic_type gic_version)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -35,5 +38,11 @@ static inline u32 rockchip_amp_get_irq_cpumask(u32 irq)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int rockchip_amp_need_init_amp_irq(u32 irq)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ROCKCHIP_AMP */
|
||||
#endif /* _ROCKCHIP_AMP */
|
||||
|
||||
@@ -82,4 +82,7 @@ enum hdmirx_color_space {
|
||||
#define RK_HDMIRX_V4L2_EVENT_SIGNAL_LOST \
|
||||
(V4L2_EVENT_PRIVATE_START + 1)
|
||||
|
||||
#define RK_HDMIRX_V4L2_EVENT_AUDIOINFO \
|
||||
(V4L2_EVENT_PRIVATE_START + 2)
|
||||
|
||||
#endif /* _UAPI_RK_HDMIRX_CONFIG_H */
|
||||
|
||||
@@ -33,6 +33,7 @@ struct dmaengine_mpcm {
|
||||
|
||||
struct dmaengine_mpcm_runtime_data {
|
||||
struct dma_chan *chans[MAX_DAIS];
|
||||
struct dma_interleaved_template *xt;
|
||||
dma_cookie_t cookies[MAX_DAIS];
|
||||
unsigned int *channel_maps;
|
||||
int num_chans;
|
||||
@@ -133,33 +134,71 @@ static void dmaengine_mpcm_get_master_chan(struct dmaengine_mpcm_runtime_data *p
|
||||
}
|
||||
}
|
||||
|
||||
static int dmaengine_config_interleaved(struct snd_pcm_substream *substream,
|
||||
struct dma_interleaved_template *xt,
|
||||
int offset, int sample_bytes, int nump, int numf)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
int frame_bytes;
|
||||
|
||||
frame_bytes = frames_to_bytes(runtime, 1);
|
||||
|
||||
xt->frame_size = 1;
|
||||
xt->sgl[0].size = sample_bytes;
|
||||
xt->sgl[0].icg = frame_bytes - sample_bytes;
|
||||
|
||||
#ifdef CONFIG_NO_GKI
|
||||
xt->nump = nump;
|
||||
#endif
|
||||
xt->numf = numf;
|
||||
|
||||
xt->dir = snd_pcm_substream_to_dma_direction(substream);
|
||||
|
||||
if (xt->dir == DMA_MEM_TO_DEV) {
|
||||
xt->src_start = runtime->dma_addr + offset;
|
||||
xt->src_inc = true;
|
||||
xt->src_sgl = true;
|
||||
xt->dst_inc = false;
|
||||
xt->dst_sgl = false;
|
||||
} else {
|
||||
xt->dst_start = runtime->dma_addr + offset;
|
||||
xt->src_inc = false;
|
||||
xt->src_sgl = false;
|
||||
xt->dst_inc = true;
|
||||
xt->dst_sgl = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dmaengine_mpcm_prepare_and_submit(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct dmaengine_mpcm_runtime_data *prtd = substream_to_prtd(substream);
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct dma_async_tx_descriptor *desc = NULL;
|
||||
enum dma_transfer_direction direction;
|
||||
struct dma_interleaved_template *xt = prtd->xt;
|
||||
unsigned long flags = DMA_CTRL_ACK;
|
||||
unsigned int *maps = prtd->channel_maps;
|
||||
int offset, buffer_bytes, period_bytes;
|
||||
int offset;
|
||||
int i;
|
||||
|
||||
direction = snd_pcm_substream_to_dma_direction(substream);
|
||||
|
||||
if (!substream->runtime->no_period_wakeup)
|
||||
flags |= DMA_PREP_INTERRUPT;
|
||||
|
||||
prtd->pos = 0;
|
||||
offset = 0;
|
||||
period_bytes = snd_pcm_lib_period_bytes(substream);
|
||||
buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
|
||||
|
||||
for (i = 0; i < prtd->num_chans; i++) {
|
||||
if (!prtd->chans[i])
|
||||
continue;
|
||||
desc = dmaengine_prep_dma_cyclic(prtd->chans[i],
|
||||
runtime->dma_addr + offset,
|
||||
buffer_bytes, period_bytes,
|
||||
direction, flags);
|
||||
|
||||
dmaengine_config_interleaved(substream, xt, offset,
|
||||
samples_to_bytes(runtime, maps[i]),
|
||||
runtime->period_size,
|
||||
runtime->buffer_size);
|
||||
|
||||
desc = dmaengine_prep_interleaved_dma(prtd->chans[i], xt,
|
||||
flags | DMA_PREP_REPEAT);
|
||||
|
||||
if (!desc)
|
||||
return -ENOMEM;
|
||||
@@ -247,33 +286,34 @@ static void dmaengine_mpcm_single_dma_complete(void *arg)
|
||||
}
|
||||
|
||||
static int __mpcm_prepare_single_and_submit(struct snd_pcm_substream *substream,
|
||||
dma_addr_t buf_start, int size)
|
||||
int buf_offset, int size)
|
||||
{
|
||||
struct dmaengine_mpcm_runtime_data *prtd = substream_to_prtd(substream);
|
||||
struct dma_interleaved_template *xt = prtd->xt;
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct dma_async_tx_descriptor *desc;
|
||||
enum dma_transfer_direction direction;
|
||||
unsigned long flags = DMA_CTRL_ACK;
|
||||
unsigned int *maps = prtd->channel_maps;
|
||||
int offset, i;
|
||||
bool callback = false;
|
||||
|
||||
direction = snd_pcm_substream_to_dma_direction(substream);
|
||||
|
||||
if (!substream->runtime->no_period_wakeup)
|
||||
flags |= DMA_PREP_INTERRUPT;
|
||||
|
||||
offset = 0;
|
||||
offset = buf_offset;
|
||||
for (i = 0; i < prtd->num_chans; i++) {
|
||||
if (!prtd->chans[i])
|
||||
continue;
|
||||
desc = dmaengine_prep_slave_single(prtd->chans[i],
|
||||
buf_start + offset,
|
||||
size,
|
||||
direction, flags);
|
||||
|
||||
dmaengine_config_interleaved(substream, xt, offset,
|
||||
samples_to_bytes(runtime, maps[i]),
|
||||
0,
|
||||
bytes_to_frames(runtime, size));
|
||||
|
||||
desc = dmaengine_prep_interleaved_dma(prtd->chans[i], xt, flags);
|
||||
if (!desc)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!callback) {
|
||||
desc->callback = dmaengine_mpcm_single_dma_complete;
|
||||
desc->callback_param = substream;
|
||||
@@ -314,15 +354,15 @@ static int dmaengine_mpcm_prepare_single_and_submit(struct snd_pcm_substream *su
|
||||
pr_debug("%s: offset: %d, buffer_bytes: %d\n", __func__, offset, buffer_bytes);
|
||||
pr_debug("%s: count: %d, residue_bytes: %d\n", __func__, count, residue_bytes);
|
||||
for (i = 0; i < count; i++) {
|
||||
ret = __mpcm_prepare_single_and_submit(substream, buf_start,
|
||||
ret = __mpcm_prepare_single_and_submit(substream, offset,
|
||||
period_bytes);
|
||||
if (ret)
|
||||
return ret;
|
||||
buf_start += period_bytes;
|
||||
offset += period_bytes;
|
||||
}
|
||||
|
||||
if (residue_bytes) {
|
||||
ret = __mpcm_prepare_single_and_submit(substream, buf_start,
|
||||
ret = __mpcm_prepare_single_and_submit(substream, offset,
|
||||
residue_bytes);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -421,22 +461,12 @@ static int dmaengine_mpcm_hw_params(struct snd_soc_component *component,
|
||||
sz = snd_pcm_format_size(format, maps[i]);
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
chan = pcm->tx_chans[i];
|
||||
#ifdef CONFIG_NO_GKI
|
||||
if (sz) {
|
||||
slave_config.src_interlace_size = frame_bytes - sz;
|
||||
if (slave_config.src_interlace_size)
|
||||
slave_config.dst_maxburst = sz / slave_config.dst_addr_width;
|
||||
}
|
||||
#endif
|
||||
if (sz && (frame_bytes - sz) > 0)
|
||||
slave_config.dst_maxburst = sz / slave_config.dst_addr_width;
|
||||
} else {
|
||||
chan = pcm->rx_chans[i];
|
||||
#ifdef CONFIG_NO_GKI
|
||||
if (sz) {
|
||||
slave_config.dst_interlace_size = frame_bytes - sz;
|
||||
if (slave_config.dst_interlace_size)
|
||||
slave_config.src_maxburst = sz / slave_config.src_addr_width;
|
||||
}
|
||||
#endif
|
||||
if (sz && (frame_bytes - sz) > 0)
|
||||
slave_config.src_maxburst = sz / slave_config.src_addr_width;
|
||||
}
|
||||
if (!chan)
|
||||
continue;
|
||||
@@ -540,6 +570,13 @@ static int dmaengine_mpcm_open(struct snd_soc_component *component,
|
||||
if (!prtd)
|
||||
return -ENOMEM;
|
||||
|
||||
prtd->xt = kzalloc(sizeof(struct dma_interleaved_template) +
|
||||
sizeof(struct data_chunk), GFP_KERNEL);
|
||||
if (!prtd->xt) {
|
||||
kfree(prtd);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
prtd->channel_maps = pcm->mdais->playback_channel_maps;
|
||||
for (i = 0; i < pcm->mdais->num_dais; i++)
|
||||
@@ -640,6 +677,7 @@ static int dmaengine_mpcm_close(struct snd_soc_component *component,
|
||||
{
|
||||
struct dmaengine_mpcm_runtime_data *prtd = substream_to_prtd(substream);
|
||||
|
||||
kfree(prtd->xt);
|
||||
kfree(prtd);
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user