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:
Tao Huang
2023-10-12 18:42:13 +08:00
73 changed files with 4635 additions and 369 deletions

View File

@@ -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

View File

@@ -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";

View File

@@ -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 {

View File

@@ -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";

View File

@@ -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";
};

View File

@@ -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>;

View File

@@ -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>;

View File

@@ -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 = <&lt6911uxc_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 = <&lt6911uxc_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 = <&lt6911uxc_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 = <&lt6911uxc_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>;
};
};
};

View File

@@ -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";

View File

@@ -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";

View File

@@ -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";

View File

@@ -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";

View File

@@ -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";

View File

@@ -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";

View File

@@ -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;

View File

@@ -19,6 +19,13 @@
status = "disabled";
};
/*
* The pins of gt1x and sii9022 are multiplexed
*/
&gt1x {
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 {

View File

@@ -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";

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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))

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View 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");

View File

@@ -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

View File

@@ -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

View 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");

View File

@@ -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 {

View File

@@ -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:

View File

@@ -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

View 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);

View 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

View File

@@ -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)

View File

@@ -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], &lt6911uxc->timings);
if (cur_best_fit_dist == -1 || dist < cur_best_fit_dist) {
cur_best_fit_dist = dist;
cur_best_fit = i;
}
}
dev_info(&lt6911uxc->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(&lt6911uxc->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(&lt6911uxc->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 = &lt6911uxc->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(&lt6911uxc->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(&lt6911uxc->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 = &lt6911uxc->sd;
ret = v4l2_ctrl_handler_init(&lt6911uxc->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(&lt6911uxc->hdl, NULL, V4L2_CID_PIXEL_RATE,
0, LT6911UXC_PIXEL_RATE, 1, LT6911UXC_PIXEL_RATE);
lt6911uxc->pixel_rate = v4l2_ctrl_new_std(&lt6911uxc->hdl, NULL,
V4L2_CID_PIXEL_RATE,
0, LT6911UXC_PIXEL_RATE, 1, LT6911UXC_PIXEL_RATE);
lt6911uxc->detect_tx_5v_ctrl = v4l2_ctrl_new_std(&lt6911uxc->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 = &lt6911uxc->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",
&lt6911uxc->multi_dev_info.dev_idx[0]);
of_property_read_u32(multi_info_np, "dev-idx-r",
&lt6911uxc->multi_dev_info.dev_idx[1]);
of_property_read_u32(multi_info_np, "combine-idx",
&lt6911uxc->multi_dev_info.combine_idx[0]);
of_property_read_u32(multi_info_np, "pixel-offset",
&lt6911uxc->multi_dev_info.pixel_offset);
of_property_read_u32(multi_info_np, "dev-num",
&lt6911uxc->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(&lt6911uxc_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");

View File

@@ -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

View File

@@ -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

View File

@@ -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__ */

View 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);

View File

@@ -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);

View File

@@ -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__ */

View File

@@ -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);

View File

@@ -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;

View File

@@ -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");

View File

@@ -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;

View File

@@ -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 ||

View File

@@ -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);

View File

@@ -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",
},
};

View File

@@ -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,
},
};

View File

@@ -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);

View File

@@ -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)

View File

@@ -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),
};

View File

@@ -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);
}

View File

@@ -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 = &amp_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, &amp_ctrl);
amp_gic_get_irqs_config(np, &amp_ctrl);

View File

@@ -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);
}

View File

@@ -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"

View File

@@ -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/

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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 */

View File

@@ -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);

View 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

View File

@@ -0,0 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_ROCKCHIP_VIDEO_TUNNEL) += rkvtunnel.o

File diff suppressed because it is too large Load Diff

View 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

View File

@@ -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
View 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

View File

@@ -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,

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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;