Merge commit '3fc5e850f4018da7d2c6bacadfc77267a428abec'

* commit '3fc5e850f4018da7d2c6bacadfc77267a428abec': (23 commits)
  arm64: dts: rockchip: rv1126b: Add decom_mmu clk to decom
  media: rockchip: hdmirx: add RK_HDMIRX_CMD_GET_SCAN_MODE
  media: i2c: rk628: reconfigure cec state when hdmirx reset
  spi: rockchip-slave: Support dma cyclic for misc devices
  media: rockchip: aiisp: support picture width over 4096 in airms algo
  media: rockchip: aiisp: update airms algo
  phy: rockchip: mipi dcphy move apb_rst to runtime resume to avoid break dcphy rx
  media: rockchip: vicap fixes error of stream off when one_frame mode change to mulit_frame mode
  media: rockchip: vicap fixes error of tool node get raw
  media: rockchip: vicap fixes error of crop enable state
  media: rockchip: vicap support config complete frame of toisp
  media: i2c: os12d40 support set wbgain and blc
  usb: dwc2: platform: Fix dwc2 resume failed for RK3506 OTG1
  ARM: dts: rockchip: add rv1126b-evb2-v10-dv
  arm64: dts: rockchip: add rv1126b-evb2-v10-dv
  media: rockchip: vicap support "cat /proc/rkcif*" to show mipi csi2 error info
  media: rockchip: vicap fixes error triggrer of fs/fe not match when monitor mode enable
  power: supply: rockchip-charger-manager: Resolving charging anomalies
  ARM: dts: rockchip: Add rv1126b-evb2-v10-tb-400w-emmc support
  ARM: dts: rockchip: Add rv1126b-evb2-v10-tb-400w-spi-nor support
  ...

Change-Id: I9ffc29af2616211acb0019be57110641766798ac
This commit is contained in:
Tao Huang
2025-07-12 19:28:31 +08:00
36 changed files with 1042 additions and 132 deletions

View File

@@ -1186,10 +1186,12 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \
rv1126b-evb1-v11.dtb \
rv1126b-evb1-v11-dual-4k.dtb \
rv1126b-evb2-v10.dtb \
rv1126b-evb2-v10-dv.dtb \
rv1126b-evb2-v10-mcu-k350c4516t.dtb \
rv1126b-evb2-v10-rgb-Q7050ITH2641AA1T.dtb \
rv1126b-evb2-v10-sii9022-bt1120-to-hdmi.dtb \
rv1126b-evb2-v10-tb-400w.dtb \
rv1126b-evb2-v10-tb-400w-emmc.dtb \
rv1126b-evb2-v10-tb-400w-spi-nor.dtb \
rv1126b-evb3-v10.dtb \
rv1126b-evb4-v10.dtb \
rv1126b-iotest-v10.dtb \

View File

@@ -0,0 +1,6 @@
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2025 Rockchip Electronics Co., Ltd.
*/
#include "arm64/rockchip/rv1126b-evb2-v10-dv.dts"

View File

@@ -0,0 +1,81 @@
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2025 Rockchip Electronics Co., Ltd.
*/
/dts-v1/;
#include "arm64/rockchip/rv1126b.dtsi"
#include "arm64/rockchip/rv1126b-evb.dtsi"
#include "arm64/rockchip/rv1126b-evb2-v10.dtsi"
#include "rv1126b-thunder-boot-cam.dtsi"
#include "rv1126b-thunder-boot-emmc.dtsi"
/ {
model = "Rockchip RV1126B EVB2 V10 TB 400W eMMC Board";
compatible = "rockchip,rv1126b-evb2-v10-tb-400w-emmc", "rockchip,rv1126b";
chosen {
bootargs = "loglevel=0 initcall_nr_threads=-1 initcall_debug=0 earlycon=uart8250,mmio32,0x20810000 console=ttyFIQ0 root=/dev/rd0 rootfstype=erofs rootflags=dax snd_soc_core.prealloc_buffer_size_kbytes=16 coherent_pool=32K";
};
};
&emmc {
bus-width = <8>;
cap-mmc-highspeed;
non-removable;
mmc-hs200-1_8v;
rockchip,default-sample-phase = <90>;
no-sdio;
no-sd;
status = "okay";
};
&fspi0 {
status = "disabled";
};
&i2c3 {
clock-frequency = <400000>;
pinctrl-names = "default";
pinctrl-0 = <&i2c3m1_pins>;
rockchip,amp-shared;
status = "okay";
sc450ai: sc450ai@30 {
compatible = "smartsens,sc450ai";
reg = <0x30>;
clocks = <&cru CLK_MIPI0_OUT2IO>;
clock-names = "xvclk";
reset-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_LOW>;
pwdn-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&cam_clk0_pins>;
rockchip,camera-module-index = <0>;
rockchip,camera-module-facing = "back";
rockchip,camera-module-name = "default";
rockchip,camera-module-lens-name = "default";
port {
cam0_out: endpoint {
remote-endpoint = <&csi_dphy_input0>;
data-lanes = <1 2 3 4>;
};
};
};
};
&ramdisk_r {
reg = <0x48c40000 (60 * 0x00100000)>;
};
&ramdisk_c {
reg = <0x4c840000 (30 * 0x00100000)>;
};
&rkisp_thunderboot {
/* reg's offset MUST match with RTOS */
/*
* vicap, capture raw10, ceil(w*10/8/256)*256*h *4(buf num)
* e.g. 2688x1520: 0x14c8000
*/
reg = <0x41320000 0x14c8000>;
};

View File

@@ -4,15 +4,15 @@
*/
/dts-v1/;
#include "rv1126b.dtsi"
#include "rv1126b-evb.dtsi"
#include "rv1126b-evb2-v10.dtsi"
#include "arm64/rockchip/rv1126b.dtsi"
#include "arm64/rockchip/rv1126b-evb.dtsi"
#include "arm64/rockchip/rv1126b-evb2-v10.dtsi"
#include "rv1126b-thunder-boot-cam.dtsi"
#include "rv1126b-thunder-boot-spi-nor.dtsi"
/ {
model = "Rockchip RV1126B EVB2 V10 ARM64 TB 400W Board";
compatible = "rockchip,rv1126b-evb2-v10-tb-400w", "rockchip,rv1126b";
model = "Rockchip RV1126B EVB2 V10 TB 400W SPI NorFlash Board";
compatible = "rockchip,rv1126b-evb2-v10-tb-400w-spi-nor", "rockchip,rv1126b";
chosen {
bootargs = "loglevel=0 initcall_nr_threads=-1 initcall_debug=0 earlycon=uart8250,mmio32,0x20810000 console=ttyFIQ0 root=/dev/rd0 rootfstype=erofs rootflags=dax snd_soc_core.prealloc_buffer_size_kbytes=16 coherent_pool=32K";
@@ -28,7 +28,6 @@
sc450ai: sc450ai@30 {
compatible = "smartsens,sc450ai";
status = "okay";
reg = <0x30>;
clocks = <&cru CLK_MIPI0_OUT2IO>;
clock-names = "xvclk";
@@ -50,11 +49,11 @@
};
&ramdisk_r {
reg = <0x48c40000 (40 * 0x00100000)>;
reg = <0x48c40000 (30 * 0x00100000)>;
};
&ramdisk_c {
reg = <0x4b440000 (20 * 0x00100000)>;
reg = <0x4aa40000 (20 * 0x00100000)>;
};
&rkisp_thunderboot {

View File

@@ -1,19 +0,0 @@
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2025 Rockchip Electronics Co., Ltd.
*/
#include "arm64/rockchip/rv1126b-evb2-v10-tb-400w.dts"
/ {
model = "Rockchip RV1126B EVB2 V10 TB 400W Board";
compatible = "rockchip,rv1126b-evb2-v10-tb-400w", "rockchip,rv1126b";
};
&ramdisk_r {
reg = <0x48c40000 (30 * 0x00100000)>;
};
&ramdisk_c {
reg = <0x4aa40000 (20 * 0x00100000)>;
};

View File

@@ -116,7 +116,7 @@
};
rtos: rtos@48c00000 {
reg = <0x48c00000 0x0003a000>;
reg = <0x48c00000 0x0003c000>;
};
mcu_log: mcu_log@48c3c000 {

View File

@@ -388,10 +388,10 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb1-v11.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb1-v11-dual-4k.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10-aov-dual-cam.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10-dv.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10-mcu-k350c4516t.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10-rgb-Q7050ITH2641AA1T.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10-sii9022-bt1120-to-hdmi.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10-tb-400w.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb3-v10.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb4-v10.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-iotest-v10.dtb

View File

@@ -0,0 +1,91 @@
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2025 Rockchip Electronics Co., Ltd.
*/
/dts-v1/;
#include "rv1126b.dtsi"
#include "rv1126b-evb.dtsi"
#include "rv1126b-evb2-v10.dtsi"
#include "rv1126b-evb-cam-csi0.dtsi"
/ {
model = "Rockchip RV1126B EVB1 V10 DV Board";
compatible = "rockchip,rv1126b-evb2-v10-dv", "rockchip,rv1126b";
chosen {
bootargs = "earlycon=uart8250,mmio32,0x20810000 console=ttyFIQ0 rw root=PARTUUID=614e0000-0000 rootfstype=ext4 rootwait snd_soc_core.prealloc_buffer_size_kbytes=16 coherent_pool=32K isolcpus=3 nohz_full=3";
};
};
&gc8613 {
reset-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_LOW>;
/delete-property/ pwdn-gpios;
};
&gpio5 {
interrupt-affinity = <&cpu0>, <&cpu0>, <&cpu0>, <&cpu3>;
interrupt-pins = <0>,
<0>,
<0>,
<RK_PIN_TO_BIT(RK_PB0)>;
};
&imx415 {
reset-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>;
};
&imx586 {
reset-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_LOW>;
};
&pinctrl {
inv {
inv_int1: inv-int1 {
rockchip,pins =
<5 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>;
};
};
};
&rkfec {
status = "okay";
};
&rkfec_mmu {
status = "okay";
};
&rknpu {
status = "disabled";
};
&sc450ai {
reset-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_LOW>;
};
&sc850sl {
reset-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>;
};
&spi0 {
status = "okay";
max-freq = <24000000>;
pinctrl-names = "default";
pinctrl-0 = <&spi0m2_clk_pins &spi0m2_csn0_pins &inv_int1>;
icm42670: icm42670@0 {
compatible = "invensense,icm42670";
reg = <0x0>;
spi-max-frequency = <24000000>;
spi-cpha;
spi-cpol;
//vdd-supply = <&vcc_3v3_s0>;
int1-gpio = <&gpio5 RK_PB0 GPIO_ACTIVE_HIGH>;
interrupt-parent = <&gpio5>;
interrupts = <8 IRQ_TYPE_EDGE_FALLING>;
status = "okay";
};
};
&uart2 {
status = "disabled";
};

View File

@@ -3377,8 +3377,8 @@
compatible = "rockchip,hw-decompress";
reg = <0x22100000 0x1000>;
interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru ACLK_DECOM>, <&cru DCLK_DECOM>, <&cru PCLK_DECOM>;
clock-names = "aclk", "dclk", "pclk";
clocks = <&cru ACLK_DECOM>, <&cru DCLK_DECOM>, <&cru PCLK_DECOM>, <&cru ACLK_RKMMU_DECOM>, <&cru HCLK_RKMMU_DECOM>;
clock-names = "aclk", "dclk", "pclk", "aclk_mmu", "hclk_mmu";
resets = <&cru SRST_DRESETN_DECOM>;
reset-names = "dresetn";
status = "disabled";

View File

@@ -181,6 +181,10 @@ struct os12d40 {
const char *module_name;
const char *len_name;
struct rkmodule_awb_cfg awb_cfg;
bool has_init_wbgain;
bool has_init_blc;
struct rkmodule_wb_gain_group init_wbgain;
struct rkmodule_blc_group init_blc;
};
#define to_os12d40(sd) container_of(sd, struct os12d40, subdev)
@@ -2271,6 +2275,87 @@ static void os12d40_set_awb_cfg(struct os12d40 *os12d40,
mutex_unlock(&os12d40->mutex);
}
static int os12d40_set_wb_gain(struct os12d40 *os12d40,
struct rkmodule_wb_gain_group *wb_gain_group)
{
struct rkmodule_wb_gain wb_gain;
u16 reg_bgain = 0, reg_gbgain = 0, reg_grgain = 0, reg_rgain = 0;
int ret = 0;
#ifdef DEBUG
u32 bgain = 0, gbgain = 0, grgain = 0, rgain = 0;
#endif
if (!os12d40->has_init_wbgain && !os12d40->streaming) {
os12d40->init_wbgain = *wb_gain_group;
os12d40->has_init_wbgain = true;
dev_dbg(&os12d40->client->dev, "os12d40 don't stream, record wbgain!\n");
return ret;
}
reg_bgain = 0x7000;
reg_gbgain = 0x7002;
reg_grgain = 0x7004;
reg_rgain = 0x7006;
wb_gain = wb_gain_group->wb_gain[0];
ret = os12d40_write_reg(os12d40->client, reg_bgain,
OS12D40_REG_VALUE_16BIT, wb_gain.b_gain & 0xffff);
ret |= os12d40_write_reg(os12d40->client, reg_grgain,
OS12D40_REG_VALUE_16BIT, wb_gain.gr_gain & 0xffff);
ret |= os12d40_write_reg(os12d40->client, reg_gbgain,
OS12D40_REG_VALUE_16BIT, wb_gain.gb_gain & 0xffff);
ret |= os12d40_write_reg(os12d40->client, reg_rgain,
OS12D40_REG_VALUE_16BIT, wb_gain.r_gain & 0xffff);
dev_info(&os12d40->client->dev,
"write wb gain, type:%d, b:0x%x, gb:0x%x, gr:0x%x, r:0x%x\n",
wb_gain_group->wb_gain_type[0],
wb_gain.b_gain, wb_gain.gb_gain,
wb_gain.gr_gain, wb_gain.r_gain);
#ifdef DEBUG
ret |= os12d40_read_reg(os12d40->client, reg_bgain,
OS12D40_REG_VALUE_16BIT, &bgain);
ret |= os12d40_read_reg(os12d40->client, reg_gbgain,
OS12D40_REG_VALUE_16BIT, &gbgain);
ret |= os12d40_read_reg(os12d40->client, reg_grgain,
OS12D40_REG_VALUE_16BIT, &grgain);
ret |= os12d40_read_reg(os12d40->client, reg_rgain,
OS12D40_REG_VALUE_16BIT, &rgain);
dev_info(&os12d40->client->dev,
"read wb gain, type %d, b:0x%x, gb:0x%x, gr:0x%x, r:0x%x\n",
wb_gain_group->wb_gain_type[0], bgain, gbgain, grgain, rgain);
#endif
return ret;
}
static int os12d40_set_blc(struct os12d40 *os12d40,
struct rkmodule_blc_group *blc_group)
{
u32 reg_blc = 0;
u32 blc_val = 0;
int ret = 0;
if (!os12d40->has_init_blc && !os12d40->streaming) {
os12d40->init_blc = *blc_group;
os12d40->has_init_blc = true;
dev_dbg(&os12d40->client->dev, "os12d40 don't stream, record blc!\n");
return ret;
}
reg_blc = 0x4019;
blc_val = blc_group->blc[0];
ret = os12d40_write_reg(os12d40->client, reg_blc,
OS12D40_REG_VALUE_16BIT, blc_val & 0x3ff);
dev_info(&os12d40->client->dev,
"write blc, type:%d, blc_val:0x%x\n",
blc_group->blc_type[0],
blc_val);
#ifdef DEBUG
ret |= os12d40_read_reg(os12d40->client, reg_blc,
OS12D40_REG_VALUE_16BIT, &blc_val);
dev_info(&os12d40->client->dev,
"read blc, type %d, blc_val:0x%x\n",
blc_group->blc_type[0], blc_val);
#endif
return ret;
}
static long os12d40_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
{
struct os12d40 *os12d40 = to_os12d40(sd);
@@ -2278,6 +2363,10 @@ static long os12d40_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
long ret = 0;
u32 stream = 0;
u32 *bayer_mode;
struct rkmodule_wb_gain_info *wb_gain_info;
struct rkmodule_blc_info *blc_info;
struct rkmodule_wb_gain_group *wb_gain_group;
struct rkmodule_blc_group *blc_group;
switch (cmd) {
case RKMODULE_GET_MODULE_INFO:
@@ -2318,6 +2407,23 @@ static long os12d40_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
*bayer_mode = RKMODULE_NORMAL_BAYER;
#endif
break;
case RKMODULE_GET_WB_GAIN_INFO:
wb_gain_info = (struct rkmodule_wb_gain_info *)arg;
wb_gain_info->coarse_bit = 5;
wb_gain_info->fine_bit = 10;
break;
case RKMODULE_GET_BLC_INFO:
blc_info = (struct rkmodule_blc_info *)arg;
blc_info->bit_width = 10;
break;
case RKMODULE_SET_WB_GAIN:
wb_gain_group = (struct rkmodule_wb_gain_group *)arg;
ret = os12d40_set_wb_gain(os12d40, wb_gain_group);
break;
case RKMODULE_SET_BLC:
blc_group = (struct rkmodule_blc_group *)arg;
ret = os12d40_set_blc(os12d40, blc_group);
break;
default:
ret = -ENOIOCTLCMD;
break;
@@ -2337,6 +2443,10 @@ static long os12d40_compat_ioctl32(struct v4l2_subdev *sd,
long ret;
u32 stream = 0;
u32 bayer_mode = 0;
struct rkmodule_wb_gain_info *wb_gain_info;
struct rkmodule_blc_info *blc_info;
struct rkmodule_wb_gain_group *wb_gain_group;
struct rkmodule_blc_group *blc_group;
switch (cmd) {
case RKMODULE_GET_MODULE_INFO:
@@ -2413,6 +2523,68 @@ static long os12d40_compat_ioctl32(struct v4l2_subdev *sd,
return -EFAULT;
}
break;
case RKMODULE_GET_WB_GAIN_INFO:
wb_gain_info = kzalloc(sizeof(*wb_gain_info), GFP_KERNEL);
if (!wb_gain_info) {
ret = -ENOMEM;
return ret;
}
ret = os12d40_ioctl(sd, cmd, wb_gain_info);
if (!ret) {
if (copy_to_user(up, wb_gain_info, sizeof(*wb_gain_info))) {
kfree(wb_gain_info);
return -EFAULT;
}
}
kfree(wb_gain_info);
break;
case RKMODULE_GET_BLC_INFO:
blc_info = kzalloc(sizeof(*blc_info), GFP_KERNEL);
if (!blc_info) {
ret = -ENOMEM;
return ret;
}
ret = os12d40_ioctl(sd, cmd, blc_info);
if (!ret) {
if (copy_to_user(up, blc_info, sizeof(*blc_info))) {
kfree(blc_info);
return -EFAULT;
}
}
kfree(blc_info);
break;
case RKMODULE_SET_WB_GAIN:
wb_gain_group = kzalloc(sizeof(*wb_gain_group), GFP_KERNEL);
if (!wb_gain_group) {
ret = -ENOMEM;
return ret;
}
ret = os12d40_ioctl(sd, cmd, wb_gain_group);
if (!ret) {
ret = copy_to_user(up, wb_gain_group, sizeof(*wb_gain_group));
if (ret)
return -EFAULT;
}
kfree(wb_gain_group);
break;
case RKMODULE_SET_BLC:
blc_group = kzalloc(sizeof(*blc_group), GFP_KERNEL);
if (!blc_group) {
ret = -ENOMEM;
return ret;
}
ret = os12d40_ioctl(sd, cmd, blc_group);
if (!ret) {
ret = copy_to_user(up, blc_group, sizeof(*blc_group));
if (ret)
return -EFAULT;
}
kfree(blc_group);
break;
default:
ret = -ENOIOCTLCMD;
break;
@@ -2452,6 +2624,26 @@ static int __os12d40_start_stream(struct os12d40 *os12d40)
if (ret)
return ret;
if (os12d40->has_init_wbgain) {
ret = os12d40_ioctl(&os12d40->subdev,
RKMODULE_SET_WB_GAIN,
&os12d40->init_wbgain);
if (ret) {
dev_err(&os12d40->client->dev,
"init wbgain fail\n");
return ret;
}
}
if (os12d40->has_init_blc) {
ret = os12d40_ioctl(&os12d40->subdev,
RKMODULE_SET_BLC,
&os12d40->init_blc);
if (ret) {
dev_err(&os12d40->client->dev,
"init blc fail\n");
return ret;
}
}
ret = os12d40_write_reg(os12d40->client, OS12D40_REG_CTRL_MODE,
OS12D40_REG_VALUE_08BIT, OS12D40_MODE_STREAMING);
return ret;
@@ -2459,6 +2651,8 @@ static int __os12d40_start_stream(struct os12d40 *os12d40)
static int __os12d40_stop_stream(struct os12d40 *os12d40)
{
os12d40->has_init_wbgain = false;
os12d40->has_init_blc = false;
return os12d40_write_reg(os12d40->client, OS12D40_REG_CTRL_MODE,
OS12D40_REG_VALUE_08BIT, OS12D40_MODE_SW_STANDBY);
}
@@ -3001,6 +3195,8 @@ static int os12d40_initialize_controls(struct os12d40 *os12d40)
}
os12d40->subdev.ctrl_handler = handler;
os12d40->has_init_wbgain = false;
os12d40->has_init_blc = false;
return 0;

View File

@@ -335,6 +335,8 @@ static void rk628_bt1120_hdmirx_reset(struct v4l2_subdev *sd)
bt1120->hdcp.hdcp_start = false;
enable_irq(bt1120->plugin_irq);
enable_irq(bt1120->hdmirx_irq);
if (bt1120->cec && bt1120->cec->adap)
rk628_hdmirx_cec_state_reconfiguration(bt1120->rk628, bt1120->cec);
}
static void rk628_hdmirx_plugout(struct v4l2_subdev *sd)
@@ -438,8 +440,6 @@ static void rk628_bt1120_delayed_work_enable_hotplug(struct work_struct *work)
rk628_hdmirx_controller_setup(bt1120->rk628);
rk628_hdmirx_hpd_ctrl(sd, true);
rk628_hdmirx_config_all(sd);
if (bt1120->cec && bt1120->cec->adap)
rk628_hdmirx_cec_state_reconfiguration(bt1120->rk628, bt1120->cec);
rk628_bt1120_enable_interrupts(sd, true);
} else {
bt1120->nosignal = true;

View File

@@ -498,6 +498,8 @@ static void rk628_csi_hdmirx_reset(struct v4l2_subdev *sd)
csi->hdcp.hdcp_start = false;
enable_irq(csi->plugin_irq);
enable_irq(csi->hdmirx_irq);
if (csi->cec && csi->cec->adap)
rk628_hdmirx_cec_state_reconfiguration(csi->rk628, csi->cec);
}
static void rk628_hdmirx_plugout(struct v4l2_subdev *sd)
@@ -574,8 +576,6 @@ static void rk628_csi_delayed_work_enable_hotplug(struct work_struct *work)
rk628_hdmirx_controller_setup(csi->rk628);
rk628_hdmirx_hpd_ctrl(sd, true);
rk628_hdmirx_config_all(sd);
if (csi->cec && csi->cec->adap)
rk628_hdmirx_cec_state_reconfiguration(csi->rk628, csi->cec);
rk628_csi_enable_interrupts(sd, true);
} else {
extcon_set_state_sync(csi->extcon, EXTCON_JACK_VIDEO_IN, false);

View File

@@ -174,8 +174,8 @@ static void rkaiisp_dumpreg(struct rkaiisp_device *aidev, u32 start, u32 end)
static void rkaiisp_dump_list_reg(struct rkaiisp_device *aidev)
{
dev_info(aidev->dev, "frame_id: %d, run_idx: %d\n",
aidev->frame_id, aidev->run_idx);
dev_info(aidev->dev, "frame_id: %d, run_idx: %d, parthdl %d\n",
aidev->frame_id, aidev->run_idx, aidev->parthdl_idx);
rkaiisp_dumpreg(aidev, AIISP_CORE_CTRL, AIISP_CORE_NOISE_LMT);
rkaiisp_dumpreg(aidev, AIISP_CORE_COMP0, AIISP_CORE_DECOMP16);
@@ -350,6 +350,24 @@ static void rkaiisp_free_buffer(struct rkaiisp_device *aidev,
}
}
static void __maybe_unused rkaiisp_prepare_buffer(struct rkaiisp_device *aidev,
struct rkaiisp_dummy_buffer *buf)
{
const struct vb2_mem_ops *g_ops = aidev->hw_dev->mem_ops;
if (buf && buf->mem_priv)
g_ops->prepare(buf->mem_priv);
}
static void __maybe_unused rkaiisp_finish_buffer(struct rkaiisp_device *aidev,
struct rkaiisp_dummy_buffer *buf)
{
const struct vb2_mem_ops *g_ops = aidev->hw_dev->mem_ops;
if (buf && buf->mem_priv)
g_ops->finish(buf->mem_priv);
}
static void rkaiisp_detach_dmabuf(struct rkaiisp_device *aidev,
struct rkaiisp_dummy_buffer *buffer)
{
@@ -651,6 +669,7 @@ static int rkaiisp_init_pool(struct rkaiisp_device *aidev, struct rkaiisp_ispbuf
aidev->ispbuf = *ispbuf;
aidev->outbuf_idx = 0;
aidev->parthdl_num = 1;
aidev->init_buf = true;
v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, "init buf poll\n");
@@ -670,7 +689,6 @@ static int rkaiisp_free_airms_pool(struct rkaiisp_device *aidev)
for (i = 0; i < aidev->rmsbuf.outbuf_num; i++)
rkaiisp_free_buffer(aidev, &aidev->rms_outbuf[i]);
rkaiisp_free_buffer(aidev, &aidev->sigma_buf);
rkaiisp_free_buffer(aidev, &aidev->narmap_buf);
aidev->init_buf = false;
@@ -682,9 +700,12 @@ static int rkaiisp_free_airms_pool(struct rkaiisp_device *aidev)
static int rkaiisp_init_airms_pool(struct rkaiisp_device *aidev, struct rkaiisp_rmsbuf_info *rmsbuf)
{
int i, ret = 0;
u32 bin_width, bin_height;
u32 size;
size = rmsbuf->image_width * rmsbuf->image_height * 2;
bin_width = CEIL_BY(CEIL_DOWN(rmsbuf->image_width, 2), 2);
bin_height = CEIL_BY(CEIL_DOWN(rmsbuf->image_height, 2), 2);
size = rmsbuf->image_width * rmsbuf->image_height * 2 + bin_width * bin_height;
rmsbuf->inbuf_num = RKAIISP_MIN(rmsbuf->inbuf_num, RKAIISP_AIRMS_BUF_MAXCNT);
for (i = 0; i < rmsbuf->inbuf_num; i++) {
aidev->rms_inbuf[i].size = size;
@@ -700,6 +721,25 @@ static int rkaiisp_init_airms_pool(struct rkaiisp_device *aidev, struct rkaiisp_
rmsbuf->inbuf_fd[i] = aidev->rms_inbuf[i].dma_fd;
}
aidev->rmsbuf = *rmsbuf;
aidev->part_rmsbuf = aidev->rmsbuf;
if (rmsbuf->image_width > RKAIISP_AIRMS_MAX_WIDTH) {
int proc_width;
aidev->is_parthdl = true;
aidev->parthdl_num = 2;
proc_width = aidev->part_rmsbuf.image_width / 2 + RKAIISP_AIRMS_EXTEND_PIXEL;
aidev->part_rmsbuf.image_width = CEIL_BY(proc_width, 16);
aidev->part_rmsbuf.sigma_width = aidev->part_rmsbuf.image_width / 2;
aidev->part_rmsbuf.narmap_width = (aidev->part_rmsbuf.image_width + 7) / 8 * 2;
aidev->parthdl_image_oft = aidev->rmsbuf.image_width - aidev->part_rmsbuf.image_width;
size = (CEIL_BY(rmsbuf->image_width, 2) + 2 * RKAIISP_AIRMS_EXTEND_PIXEL) * rmsbuf->image_height * 2;
} else {
aidev->is_parthdl = false;
aidev->parthdl_num = 1;
size = rmsbuf->image_width * rmsbuf->image_height * 2;
}
rmsbuf->outbuf_num = RKAIISP_MIN(rmsbuf->outbuf_num, RKAIISP_AIRMS_BUF_MAXCNT);
for (i = 0; i < rmsbuf->outbuf_num; i++) {
aidev->rms_outbuf[i].size = size;
@@ -715,18 +755,12 @@ static int rkaiisp_init_airms_pool(struct rkaiisp_device *aidev, struct rkaiisp_
rmsbuf->outbuf_fd[i] = aidev->rms_outbuf[i].dma_fd;
}
aidev->sigma_buf.size = rmsbuf->sigma_width * rmsbuf->sigma_height;
aidev->sigma_buf.is_need_vaddr = false;
aidev->sigma_buf.is_need_dbuf = false;
aidev->sigma_buf.is_need_dmafd = false;
rkaiisp_allow_buffer(aidev, &aidev->sigma_buf);
aidev->narmap_buf.size = rmsbuf->narmap_width * rmsbuf->narmap_height;
aidev->narmap_buf.size = aidev->rmsbuf.narmap_width * aidev->rmsbuf.narmap_height;
aidev->narmap_buf.is_need_vaddr = false;
aidev->narmap_buf.is_need_dbuf = false;
aidev->narmap_buf.is_need_dmafd = false;
rkaiisp_allow_buffer(aidev, &aidev->narmap_buf);
aidev->rmsbuf = *rmsbuf;
aidev->init_buf = true;
v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, "init buf poll\n");
@@ -880,6 +914,13 @@ static void rkaiisp_gen_slice_param(struct rkaiisp_device *aidev,
}
}
if (slice_idx > 8) {
aidev->is_state_err = true;
v4l2_err(&aidev->v4l2_dev,
"slice num %d is too big, input width %d\n", slice_idx, width);
return;
}
if (slice_idx >= 1)
slice_num = slice_idx - 1;
value = slice_mode[0] |
@@ -990,6 +1031,9 @@ static int rkaiisp_determine_size(struct rkaiisp_device *aidev,
if (n == 3 && model_cfg->sw_mi_chn3_sel == 0)
bits = 8;
if (aidev->chn_size[n].stride != 0 && aidev->exealgo == AIRMS)
cols = aidev->chn_size[n].stride;
sw_mi_chn_stride[n] = CEIL_BY(cols * chns * bits, 16 * 8) / 32;
}
@@ -1130,6 +1174,7 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev,
{
struct rkaiisp_ispbuf_info *ispbuf = &aidev->ispbuf;
struct rkaiisp_rmsbuf_info *rmsbuf = &aidev->rmsbuf;
struct rkaiisp_rmsbuf_info *part_rmsbuf = &aidev->part_rmsbuf;
struct rkaiisp_dummy_buffer *vpsl_buf;
dma_addr_t dma_addr;
u32 width, height, stride;
@@ -1239,20 +1284,29 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev,
dma_addr = aidev->lastout_buf[aidev->outbuf_idx]->dma_addr;
break;
case VICAP_BAYER_RAW:
width = rmsbuf->image_width;
height = rmsbuf->image_height;
buffer_index = aidev->curr_idxbuf.airms_st.inbuf_idx;
dma_addr = aidev->rms_inbuf[buffer_index].dma_addr;
break;
case ALLZERO_SIGMA:
width = rmsbuf->sigma_width;
height = rmsbuf->sigma_height;
dma_addr = aidev->sigma_buf.dma_addr;
sig_width = width;
if (aidev->is_parthdl) {
width = part_rmsbuf->image_width;
height = part_rmsbuf->image_height;
buffer_index = aidev->curr_idxbuf.airms_st.inbuf_idx;
dma_addr = aidev->rms_inbuf[buffer_index].dma_addr;
if (aidev->parthdl_idx == 1)
dma_addr += aidev->parthdl_image_oft * 2;
stride = rmsbuf->image_width;
} else {
width = rmsbuf->image_width;
height = rmsbuf->image_height;
buffer_index = aidev->curr_idxbuf.airms_st.inbuf_idx;
dma_addr = aidev->rms_inbuf[buffer_index].dma_addr;
}
break;
case ALLZERO_NARMAP:
width = rmsbuf->narmap_width;
height = rmsbuf->narmap_height;
if (aidev->is_parthdl) {
width = part_rmsbuf->narmap_width;
height = part_rmsbuf->narmap_height;
} else {
width = rmsbuf->narmap_width;
height = rmsbuf->narmap_height;
}
dma_addr = aidev->narmap_buf.dma_addr;
break;
case ISP_FINAL_Y:
@@ -1261,6 +1315,28 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev,
buffer_index = aidev->curr_idxbuf.aibnr_st.y_src_index;
dma_addr = aidev->ynrinbuf[buffer_index].dma_addr;
break;
case VICAP_BAYER_RAW_DOWN:
if (aidev->is_parthdl) {
width = rmsbuf->image_width;
height = rmsbuf->image_height;
buffer_index = aidev->curr_idxbuf.airms_st.inbuf_idx;
dma_addr = aidev->rms_inbuf[buffer_index].dma_addr + width * height * 2;
if (aidev->parthdl_idx == 1)
dma_addr += aidev->parthdl_image_oft / 2;
width = CEIL_BY(CEIL_DOWN(part_rmsbuf->image_width, 2), 2);
height = CEIL_BY(CEIL_DOWN(part_rmsbuf->image_height, 2), 2);
sig_width = width;
stride = CEIL_BY(CEIL_DOWN(rmsbuf->image_width, 2), 2);
} else {
width = rmsbuf->image_width;
height = rmsbuf->image_height;
buffer_index = aidev->curr_idxbuf.airms_st.inbuf_idx;
dma_addr = aidev->rms_inbuf[buffer_index].dma_addr + width * height * 2;
width = CEIL_BY(CEIL_DOWN(rmsbuf->image_width, 2), 2);
height = CEIL_BY(CEIL_DOWN(rmsbuf->image_height, 2), 2);
sig_width = width;
}
break;
default:
width = 0;
height = 0;
@@ -1271,7 +1347,7 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev,
if (width > 0) {
aidev->chn_size[i].width = width;
aidev->chn_size[i].height = height;
aidev->chn_size[i].stride = stride;
aidev->chn_size[i].stride = stride > 0 ? stride : width;
rkaiisp_write(aidev, AIISP_MI_RD_CH0_BASE + 0x100 * i, dma_addr, false);
rkaiisp_write(aidev, AIISP_MI_RD_CH0_HEIGHT + 0x100 * i, height, false);
@@ -1289,6 +1365,7 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev,
static void rkaiisp_run_cfg(struct rkaiisp_device *aidev, u32 run_idx)
{
struct rkaiisp_ispbuf_info *ispbuf = &aidev->ispbuf;
struct rkaiisp_rmsbuf_info *rmsbuf = &aidev->rmsbuf;
struct rkaiisp_params *cur_params;
struct rkaiisp_model_cfg *model_cfg;
int lastlv, lv_mode, out_chns, i;
@@ -1310,6 +1387,7 @@ static void rkaiisp_run_cfg(struct rkaiisp_device *aidev, u32 run_idx)
"run frame id: %d, run_idx: %d, model_mode %d\n",
sequence, run_idx, aidev->model_mode);
aidev->is_state_err = false;
cur_params = (struct rkaiisp_params *)aidev->cur_params->vaddr[0];
model_cfg = &cur_params->model_cfg[run_idx];
@@ -1351,10 +1429,17 @@ static void rkaiisp_run_cfg(struct rkaiisp_device *aidev, u32 run_idx)
sig_width = rkaiisp_config_rdchannel(aidev, model_cfg, run_idx);
dma_addr = aidev->rms_outbuf[aidev->curr_idxbuf.airms_st.outbuf_idx].dma_addr;
if (aidev->parthdl_idx == 1)
dma_addr += 2 * (CEIL_BY(rmsbuf->image_width, 2) / 2 + RKAIISP_AIRMS_EXTEND_PIXEL);
rkaiisp_write(aidev, AIISP_MI_CHN0_WR_BASE, dma_addr, false);
rkaiisp_gen_slice_param(aidev, model_cfg, sig_width);
rkaiisp_determine_size(aidev, model_cfg);
iir_stride = CEIL_BY(rmsbuf->image_width, 2);
if (aidev->is_parthdl)
iir_stride += 2 * RKAIISP_AIRMS_EXTEND_PIXEL;
rkaiisp_write(aidev, AIISP_MI_CHN0_WR_STRIDE, iir_stride / 2, false);
} else if (aidev->model_mode == SINGLEX2_MODE) {
if (run_idx == 0) {
sig_width = rkaiisp_config_rdchannel(aidev, model_cfg, run_idx);
@@ -1462,7 +1547,8 @@ static void rkaiisp_run_cfg(struct rkaiisp_device *aidev, u32 run_idx)
rkaiisp_write(aidev, AIISP_CORE_LEVEL_CTRL0 + i * 4, val, false);
}
if ((out_chns == 4 && model_cfg->sw_out_d2s_en == 0))
if (out_chns == 4 &&
model_cfg->sw_out_d2s_en == (model_cfg->sw_out_mode == AIISP_OUT_MODE_BYPASS))
sw_lastlv_bypass = 1;
if (model_cfg->sw_aiisp_mode == 0 && model_cfg->sw_out_mode == AIISP_OUT_MODE_DIFF_MERGE)
sw_m0_diff_merge = 1;
@@ -1509,16 +1595,25 @@ static void rkaiisp_run_start(struct rkaiisp_device *aidev)
{
struct rkaiisp_hw_dev *hw_dev = aidev->hw_dev;
if (aidev->is_state_err) {
v4l2_err(&aidev->v4l2_dev,
"aiisp status is error!\n");
rkaiisp_dump_list_reg(aidev);
return;
}
rkaiisp_write(aidev, AIISP_MI_IMSC, AIISP_MI_ISR_ALL, false);
rkaiisp_write(aidev, AIISP_MI_WR_INIT, AIISP_MI_CHN0SELF_FORCE_UPD, false);
if ((aidev->run_idx == 0) && (rkaiisp_showreg != 0))
if ((aidev->run_idx == 0) && (aidev->parthdl_idx == 0) && (rkaiisp_showreg != 0))
aidev->showreg = true;
if (aidev->showreg)
rkaiisp_dump_list_reg(aidev);
if ((aidev->run_idx == aidev->model_runcnt - 1) && aidev->showreg) {
if ((aidev->run_idx + 1 == aidev->model_runcnt) &&
(aidev->parthdl_idx + 1 == aidev->parthdl_num) &&
aidev->showreg) {
aidev->showreg = false;
rkaiisp_showreg = 0;
}
@@ -1593,6 +1688,7 @@ void rkaiisp_trigger(struct rkaiisp_device *aidev)
if (!rkaiisp_update_buf(aidev)) {
aidev->run_idx = 0;
aidev->parthdl_idx = 0;
aidev->frame_id = sequence;
aidev->pre_frm_st = aidev->frm_st;
aidev->frm_st = ktime_get_ns();
@@ -1643,8 +1739,9 @@ enum rkaiisp_irqhdl_ret rkaiisp_irq_hdl(struct rkaiisp_device *aidev, u32 mi_mis
u64 frm_hdntim = 0;
v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev,
"irq val: 0x%x, run_idx %d, model_runcnt %d\n",
mi_mis, aidev->run_idx, aidev->model_runcnt);
"irq val: 0x%x, run_idx %d, model_runcnt %d, parthdl %d, %d\n",
mi_mis, aidev->run_idx, aidev->model_runcnt,
aidev->parthdl_idx, aidev->parthdl_num);
if (mi_mis & AIISP_MI_ISR_BUSERR) {
v4l2_err(&aidev->v4l2_dev, "buserr 0x%x\n", mi_mis);
@@ -1657,11 +1754,17 @@ enum rkaiisp_irqhdl_ret rkaiisp_irq_hdl(struct rkaiisp_device *aidev, u32 mi_mis
rkaiisp_write(aidev, AIISP_MI_ICR, AIISP_MI_ISR_WREND, true);
aidev->isr_wrend_cnt++;
if (aidev->run_idx < aidev->model_runcnt - 1) {
if (aidev->run_idx + 1 < aidev->model_runcnt) {
aidev->run_idx++;
rkaiisp_run_cfg(aidev, aidev->run_idx);
rkaiisp_run_start(aidev);
return CONTINUE_RUN;
} else if (aidev->is_parthdl && (aidev->parthdl_idx + 1 < aidev->parthdl_num)) {
aidev->parthdl_idx++;
aidev->run_idx = 0;
rkaiisp_run_cfg(aidev, aidev->run_idx);
rkaiisp_run_start(aidev);
return CONTINUE_RUN;
}
aidev->frm_ed = ktime_get_ns();

View File

@@ -37,6 +37,8 @@
#define RKAIISP_SW_REG_SIZE 0x3000
#define RKAIISP_SW_MAX_SIZE (RKAIISP_SW_REG_SIZE * 2)
#define RKAIISP_AIRMS_BUF_MAXCNT 8
#define RKAIISP_AIRMS_MAX_WIDTH 4096
#define RKAIISP_AIRMS_EXTEND_PIXEL 16
#define RKAIISP_MIN(a, b) ((a) < (b) ? (a) : (b))
enum rkaiisp_irqhdl_ret {
@@ -121,10 +123,11 @@ struct rkaiisp_device {
struct rkaiisp_dummy_buffer *lastout_buf[RKAIISP_LASTOUT_BUF_CNT];
u32 outbuf_idx;
bool is_parthdl;
struct rkaiisp_rmsbuf_info rmsbuf;
struct rkaiisp_rmsbuf_info part_rmsbuf;
struct rkaiisp_dummy_buffer rms_inbuf[RKAIISP_AIRMS_BUF_MAXCNT];
struct rkaiisp_dummy_buffer rms_outbuf[RKAIISP_AIRMS_BUF_MAXCNT];
struct rkaiisp_dummy_buffer sigma_buf;
struct rkaiisp_dummy_buffer narmap_buf;
struct aiisp_aiynr_ybuf_cfg ynr_ybuf_cfg;
@@ -150,6 +153,10 @@ struct rkaiisp_device {
u32 run_idx;
u32 frame_id;
u32 parthdl_idx;
u32 parthdl_num;
u32 parthdl_image_oft;
u64 pre_frm_st;
u64 frm_st;
u64 frm_ed;
@@ -161,6 +168,7 @@ struct rkaiisp_device {
bool streamon;
bool showreg;
bool init_buf;
bool is_state_err;
};
extern int rkaiisp_debug;

View File

@@ -1968,8 +1968,9 @@ static void rkcif_rdbk_with_tools(struct rkcif_stream *stream,
unsigned long flags;
spin_lock_irqsave(&stream->tools_vdev->vbq_lock, flags);
if (stream->tools_vdev->state == RKCIF_STATE_STREAMING) {
list_add_tail(&active_buf->list, &stream->tools_vdev->buf_done_head);
if (stream->tools_vdev->state == RKCIF_STATE_STREAMING && active_buf) {
list_add_tail(&active_buf->list_tool, &stream->tools_vdev->buf_done_head);
active_buf->use_cnt = 2;
if (!work_busy(&stream->tools_vdev->work))
schedule_work(&stream->tools_vdev->work);
}
@@ -4763,9 +4764,9 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream,
return 0;
}
val = rkcif_read_register(dev, CIF_REG_GLB_CTRL);
if (stream->sw_dbg_en) {
rkcif_write_register_and(dev, CIF_REG_GLB_CTRL,
~(u32)BIT(16));
val &= ~BIT(16);
v4l2_subdev_call(dev->active_sensor->sd,
core, ioctl,
RKCIF_CMD_SET_PPI_DATA_DEBUG,
@@ -4776,18 +4777,23 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream,
RKCIF_CMD_SET_PPI_DATA_DEBUG,
&stream->sw_dbg_en);
}
if (dev->chip_id == CHIP_RK3588_CIF ||
dev->chip_id == CHIP_RV1106_CIF ||
dev->chip_id == CHIP_RK3562_CIF) {
val = GLB_RESET_IDI_EN_RK3588;
val |= GLB_RESET_IDI_EN_RK3588;
} else if (dev->chip_id == CHIP_RK3576_CIF) {
val = GLB_RESET_IDI_EN_RK3576;
val |= GLB_RESET_IDI_EN_RK3576;
val |= rkcif_get_split_dphy_mask_rk3576(dev);
} else if (dev->chip_id == CHIP_RV1103B_CIF) {
val = rkcif_get_split_dphy_mask_rv1103b(dev);
val |= rkcif_get_split_dphy_mask_rv1103b(dev);
}
rkcif_write_register_or(dev, CIF_REG_GLB_CTRL, val);
if (dev->chip_id == CHIP_RV1103B_CIF) {
if (rkcif_frm_toisp_protect)
val &= ~BIT(28);
else
val |= BIT(28);
}
rkcif_write_register(dev, CIF_REG_GLB_CTRL, val);
if (dev->terminal_sensor.hdmi_input_en) {
if (dev->chip_id == CHIP_RK3562_CIF ||
@@ -5075,8 +5081,13 @@ static int rkcif_csi_channel_set_rv1126b(struct rkcif_stream *stream,
CSI_DISABLE_CAPTURE);
return 0;
}
val = rkcif_get_split_mask_rv1126b(dev);
rkcif_write_register_or(dev, CIF_REG_GLB_CTRL, val);
val = rkcif_read_register(dev, CIF_REG_GLB_CTRL);
val |= rkcif_get_split_mask_rv1126b(dev);
if (rkcif_frm_toisp_protect)
val &= ~BIT(28);
else
val |= BIT(28);
rkcif_write_register(dev, CIF_REG_GLB_CTRL, val);
rkcif_write_register_and(dev, CIF_REG_MIPI_LVDS_INTSTAT,
~(CSI_START_INTSTAT(channel->id) |
CSI_DMA_END_INTSTAT(channel->id) |
@@ -6956,6 +6967,7 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream,
kfifo_free(&stream->dcg_kfifo);
}
stream->crop_enable = false;
stream->crop_mask = 0;
stream->frame_loss = 0;
stream->is_fb_first_frame = true;
@@ -9778,6 +9790,7 @@ int rkcif_quick_stream_on(struct rkcif_device *dev, bool is_intr)
if (dev->sditf[0]->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) {
for (i = 0; i < stream_num; i++) {
stream = &dev->stream[i];
stream->is_pause_stream = false;
if (stream->cifdev->hdr.hdr_mode == NO_HDR ||
(stream->cifdev->hdr.hdr_mode == HDR_X2 && stream->id == 1) ||
(stream->cifdev->hdr.hdr_mode == HDR_X3 && stream->id == 2)) {
@@ -9807,6 +9820,7 @@ int rkcif_quick_stream_on(struct rkcif_device *dev, bool is_intr)
RKISP_VICAP_CMD_MODE, &dev->sditf[0]->mode);
}
for (i = 0; i < stream_num; i++) {
dev->stream[i].is_pause_stream = false;
if (dev->sditf[0]->mode.rdbk_mode != RKISP_VICAP_RDBK_AIQ)
dev->stream[i].to_en_dma = RKCIF_DMAEN_BY_ISP;
else
@@ -11086,7 +11100,8 @@ static bool rkcif_is_csi2_err_trigger_reset(struct rkcif_timer *timer)
* or fs and fe had been not paired.
*/
if (stream->is_fs_fe_not_paired ||
stream->fs_cnt_in_single_frame > RKCIF_FS_DETECTED_NUM) {
(stream->fs_cnt_in_single_frame > RKCIF_FS_DETECTED_NUM &&
dev->chip_id < CHIP_RK3588_CIF)) {
is_triggered = true;
v4l2_info(&dev->v4l2_dev, "reset for fs & fe not paired\n");
}
@@ -13968,9 +13983,6 @@ static void rkcif_deal_sof(struct rkcif_device *cif_dev)
RKISP_VICAP_CMD_SOF, &sof);
}
if (cif_dev->chip_id < CHIP_RK3588_CIF)
detect_stream->fs_cnt_in_single_frame++;
if (cif_dev->sditf[0] &&
cif_dev->sditf[0]->mode.rdbk_mode >= RKISP_VICAP_RDBK_AIQ &&
(!detect_stream->dma_en) && cif_dev->chip_id < CHIP_RK3576_CIF)

View File

@@ -474,6 +474,7 @@ static void rkcif_tools_vb2_stop_streaming(struct vb2_queue *vq)
struct rkcif_device *dev = tools_vdev->cifdev;
struct rkcif_buffer *buf = NULL;
struct rkcif_tools_buffer *tools_buf;
struct rkcif_rx_buffer *rx_buf = NULL;
int ret = 0;
mutex_lock(&dev->tools_lock);
@@ -485,6 +486,12 @@ static void rkcif_tools_vb2_stop_streaming(struct vb2_queue *vq)
if (!ret) {
rkcif_tools_stop(tools_vdev);
tools_vdev->stopping = false;
while (!list_empty(&tools_vdev->buf_done_head)) {
rx_buf = list_first_entry(&tools_vdev->buf_done_head,
struct rkcif_rx_buffer, list_tool);
list_del(&rx_buf->list_tool);
v4l2_subdev_call(&dev->sditf[0]->sd, video, s_rx_buffer, &rx_buf->dbufs, NULL);
}
}
/* release buffers */
if (tools_vdev->curr_buf)
@@ -710,9 +717,9 @@ retry_done_rdbk_buf:
spin_lock_irqsave(&tools_vdev->vbq_lock, flags);
if (!list_empty(&tools_vdev->buf_done_head)) {
buf = list_first_entry(&tools_vdev->buf_done_head,
struct rkcif_rx_buffer, list);
struct rkcif_rx_buffer, list_tool);
if (buf)
list_del(&buf->list);
list_del(&buf->list_tool);
}
spin_unlock_irqrestore(&tools_vdev->vbq_lock, flags);
if (!buf) {
@@ -724,12 +731,14 @@ retry_done_rdbk_buf:
if (tools_vdev->stopping) {
rkcif_tools_stop(tools_vdev);
tools_vdev->stopping = false;
if (buf)
v4l2_subdev_call(&dev->sditf[0]->sd, video, s_rx_buffer, &buf->dbufs, NULL);
spin_lock_irqsave(&tools_vdev->vbq_lock, flags);
while (!list_empty(&tools_vdev->buf_done_head)) {
buf = list_first_entry(&tools_vdev->buf_done_head,
struct rkcif_rx_buffer, list);
if (buf)
list_del(&buf->list);
struct rkcif_rx_buffer, list_tool);
list_del(&buf->list_tool);
v4l2_subdev_call(&dev->sditf[0]->sd, video, s_rx_buffer, &buf->dbufs, NULL);
}
spin_unlock_irqrestore(&tools_vdev->vbq_lock, flags);
wake_up(&tools_vdev->wq_stopped);
@@ -742,9 +751,13 @@ retry_done_rdbk_buf:
if (!tools_vdev->curr_buf || tools_vdev->state != RKCIF_STATE_STREAMING) {
spin_lock_irqsave(&tools_vdev->vbq_lock, flags);
if (!list_empty(&tools_vdev->buf_done_head)) {
if (buf)
v4l2_subdev_call(&dev->sditf[0]->sd, video, s_rx_buffer, &buf->dbufs, NULL);
spin_unlock_irqrestore(&stream->tools_vdev->vbq_lock, flags);
goto retry_done_rdbk_buf;
}
if (buf)
v4l2_subdev_call(&dev->sditf[0]->sd, video, s_rx_buffer, &buf->dbufs, NULL);
spin_unlock_irqrestore(&tools_vdev->vbq_lock, flags);
return;
}
@@ -765,10 +778,14 @@ retry_done_rdbk_buf:
payload_size);
memcpy(dst, src, payload_size);
}
v4l2_subdev_call(&dev->sditf[0]->sd, video, s_rx_buffer, &buf->dbufs, NULL);
tools_vdev->curr_buf->vb.sequence = buf->dbufs.sequence;
tools_vdev->curr_buf->vb.vb2_buf.timestamp = buf->dbufs.timestamp;
vb2_buffer_done(&tools_vdev->curr_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
tools_vdev->curr_buf = NULL;
} else {
if (buf)
v4l2_subdev_call(&dev->sditf[0]->sd, video, s_rx_buffer, &buf->dbufs, NULL);
}
spin_lock_irqsave(&tools_vdev->vbq_lock, flags);

View File

@@ -36,6 +36,10 @@ int rkcif_debug;
module_param_named(debug, rkcif_debug, int, 0644);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
bool rkcif_frm_toisp_protect = true;
module_param_named(toisp_protect, rkcif_frm_toisp_protect, bool, 0644);
MODULE_PARM_DESC(toisp_protect, "frame protect of toisp");
static char rkcif_version[RKCIF_VERNO_LEN];
module_param_string(version, rkcif_version, RKCIF_VERNO_LEN, 0444);
MODULE_PARM_DESC(version, "version number");

View File

@@ -232,6 +232,7 @@ struct rkcif_tools_buffer {
};
extern int rkcif_debug;
extern bool rkcif_frm_toisp_protect;
/*
* struct rkcif_sensor_info - Sensor infomations
@@ -478,12 +479,14 @@ enum rkcif_capture_mode {
struct rkcif_rx_buffer {
int buf_idx;
struct list_head list;
struct list_head list_tool;
struct list_head list_free;
struct rkisp_rx_buf dbufs;
struct rkcif_dummy_buffer dummy;
struct rkisp_thunderboot_shmem shmem;
u64 fe_timestamp;
bool is_init[RKCIF_MAX_DEV];
int use_cnt;
};
enum rkcif_dma_en_mode {

View File

@@ -282,6 +282,8 @@ static int csi2_start(struct csi2_dev *csi2)
else
host_type = RK_CSI_RXHOST;
csi2->irq1_timestamp = 0;
csi2->irq2_timestamp = 0;
for (i = 0; i < csi2->csi_info.csi_num; i++) {
csi_idx = csi2->csi_info.csi_idx[i];
ret |= csi2_hw_start(csi2->csi2_hw[csi_idx], host_type);
@@ -840,6 +842,7 @@ static irqreturn_t rk_csirx_irq1_handler(int irq, void *ctx)
char cur_str[CSI_ERRSTR_LEN] = {0};
char vc_info[CSI_VCINFO_LEN] = {0};
bool is_add_cnt = false;
u64 cur_timestamp = ktime_get_ns();
if (!csi2_hw) {
disable_irq_nosync(irq);
@@ -912,7 +915,7 @@ static irqreturn_t rk_csirx_irq1_handler(int irq, void *ctx)
}
if (val & CSIHOST_ERR1_ERR_ECC2) {
err_list = &csi2->err_list[RK_CSI2_ERR_CRC];
err_list = &csi2->err_list[RK_CSI2_ERR_ECC2];
err_list->cnt++;
is_add_cnt = true;
snprintf(cur_str, CSI_ERRSTR_LEN, "(ecc2) ");
@@ -920,12 +923,17 @@ static irqreturn_t rk_csirx_irq1_handler(int irq, void *ctx)
}
if (val & CSIHOST_ERR1_ERR_CTRL) {
err_list = &csi2->err_list[RK_CSI2_ERR_CTRL];
err_list->cnt++;
csi2_find_err_vc((val >> 16) & 0xf, vc_info);
snprintf(cur_str, CSI_ERRSTR_LEN, "(ctrl,vc:%s) ", vc_info);
csi2_err_strncat(err_str, cur_str);
}
pr_err("(0x%x)MIPI_CSI2 ERR1:0x%x %s\n", (u32)csi2_hw->res->start, val, err_str);
if (csi2->irq1_timestamp == 0 || cur_timestamp - csi2->irq1_timestamp > 1000000000) {
csi2->irq1_timestamp = cur_timestamp;
pr_err("(0x%x)MIPI_CSI2 ERR1:0x%x %s\n", (u32)csi2_hw->res->start, val, err_str);
}
if (is_add_cnt) {
csi2->err_list[RK_CSI2_ERR_ALL].cnt++;
@@ -946,16 +954,24 @@ static irqreturn_t rk_csirx_irq2_handler(int irq, void *ctx)
{
struct device *dev = ctx;
struct csi2_hw *csi2_hw = dev_get_drvdata(dev);
struct csi2_dev *csi2 = NULL;
u32 val;
char cur_str[CSI_ERRSTR_LEN] = {0};
char err_str[CSI_ERRSTR_LEN] = {0};
char vc_info[CSI_VCINFO_LEN] = {0};
u64 cur_timestamp = ktime_get_ns();
if (!csi2_hw) {
disable_irq_nosync(irq);
return IRQ_HANDLED;
}
csi2 = csi2_hw->csi2;
if (!csi2) {
disable_irq_nosync(irq);
return IRQ_HANDLED;
}
val = read_csihost_reg(csi2_hw->base, CSIHOST_ERR2);
if (val) {
if (val & CSIHOST_ERR2_PHYERR_ESC) {
@@ -983,7 +999,10 @@ static irqreturn_t rk_csirx_irq2_handler(int irq, void *ctx)
csi2_err_strncat(err_str, cur_str);
}
pr_err("(0x%x)MIPI_CSI2 ERR2:0x%x %s\n", (u32)csi2_hw->res->start, val, err_str);
if (csi2->irq2_timestamp == 0 || cur_timestamp - csi2->irq2_timestamp > 1000000000) {
csi2->irq2_timestamp = cur_timestamp;
pr_err("(0x%x)MIPI_CSI2 ERR2:0x%x %s\n", (u32)csi2_hw->res->start, val, err_str);
}
}
return IRQ_HANDLED;

View File

@@ -113,6 +113,8 @@ enum csi2_err {
RK_CSI2_ERR_FRM_SEQ_ERR,
RK_CSI2_ERR_CRC_ONCE,
RK_CSI2_ERR_CRC,
RK_CSI2_ERR_ECC2,
RK_CSI2_ERR_CTRL,
RK_CSI2_ERR_ALL,
RK_CSI2_ERR_MAX
};
@@ -176,6 +178,8 @@ struct csi2_dev {
struct rkcif_csi_info csi_info;
const char *dev_name;
int sw_dbg;
u64 irq1_timestamp;
u64 irq2_timestamp;
};
struct csi2_hw {

View File

@@ -526,6 +526,27 @@ static void rkcif_show_reg_dbg(struct rkcif_device *dev, struct seq_file *f)
}
}
static void rkcif_show_mipi_csi2_error_info(struct rkcif_device *dev, struct seq_file *f)
{
struct csi2_dev *csi2 = container_of(dev->active_sensor->sd, struct csi2_dev, sd);
seq_puts(f, "\nMipi error info:\n");
seq_printf(f, "\terr sot sync:%u\n",
csi2->err_list[RK_CSI2_ERR_SOTSYN].cnt);
seq_printf(f, "\terr fs/fe not match:%u\n",
csi2->err_list[RK_CSI2_ERR_FS_FE_MIS].cnt);
seq_printf(f, "\terr frm seq:%u\n",
csi2->err_list[RK_CSI2_ERR_FRM_SEQ_ERR].cnt);
seq_printf(f, "\terr crc once:%u\n",
csi2->err_list[RK_CSI2_ERR_CRC_ONCE].cnt);
seq_printf(f, "\terr crc:%u\n",
csi2->err_list[RK_CSI2_ERR_CRC].cnt);
seq_printf(f, "\terr ecc2:%u\n",
csi2->err_list[RK_CSI2_ERR_ECC2].cnt);
seq_printf(f, "\terr ctrl:%u\n",
csi2->err_list[RK_CSI2_ERR_CTRL].cnt);
}
static void rkcif_show_format(struct rkcif_device *dev, struct seq_file *f)
{
struct rkcif_stream *stream = &dev->stream[0];
@@ -676,6 +697,9 @@ static void rkcif_show_format(struct rkcif_device *dev, struct seq_file *f)
rkcif_show_toisp_info(dev, f);
if (dev->reg_dbg)
rkcif_show_reg_dbg(dev, f);
if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY ||
sensor->mbus.type == V4L2_MBUS_CSI2_CPHY)
rkcif_show_mipi_csi2_error_info(dev, f);
}
}

View File

@@ -1345,6 +1345,26 @@ static int sditf_s_power(struct v4l2_subdev *sd, int on)
return ret;
}
static int sditf_check_toolbuf_return(struct rkcif_stream *stream, struct rkcif_rx_buffer *rx_buf)
{
struct rkcif_tools_vdev *tools_vdev = stream->tools_vdev;
unsigned long flags;
if (tools_vdev) {
spin_lock_irqsave(&stream->tools_vdev->vbq_lock, flags);
if (rx_buf->use_cnt)
rx_buf->use_cnt--;
if (rx_buf->use_cnt) {
spin_unlock_irqrestore(&stream->tools_vdev->vbq_lock, flags);
return false;
}
spin_unlock_irqrestore(&stream->tools_vdev->vbq_lock, flags);
}
return true;
}
static int sditf_s_rx_buffer(struct v4l2_subdev *sd,
void *buf, unsigned int *size)
{
@@ -1422,7 +1442,8 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd,
is_free = true;
}
if (!is_free && (!dbufs->is_switch) && stream->state == RKCIF_STATE_STREAMING) {
if (!is_free && (!dbufs->is_switch) && stream->state == RKCIF_STATE_STREAMING &&
sditf_check_toolbuf_return(stream, rx_buf)) {
list_add_tail(&rx_buf->list, &buf_stream->rx_buf_head);
rkcif_assign_check_buffer_update_toisp(stream);
if (cif_dev->resume_mode != RKISP_RTT_MODE_ONE_FRAME &&

View File

@@ -2485,6 +2485,8 @@ static long hdmirx_ioctl_default(struct file *file, void *fh,
{
struct hdmirx_stream *stream = video_drvdata(file);
struct rk_hdmirx_dev *hdmirx_dev = stream->hdmirx_dev;
struct v4l2_dv_timings timings = hdmirx_dev->timings;
struct v4l2_bt_timings *bt = &timings.bt;
long ret = 0;
bool hpd;
enum mute_type type;
@@ -2497,6 +2499,14 @@ static long hdmirx_ioctl_default(struct file *file, void *fh,
case RK_HDMIRX_CMD_GET_FPS:
*(int *)arg = hdmirx_dev->get_timing ? hdmirx_dev->fps : 0;
break;
case RK_HDMIRX_CMD_GET_SCAN_MODE:
if (!hdmirx_dev->get_timing)
*(int *)arg = HDMIRX_PROGRESSIVE;
else if (bt->interlaced == V4L2_DV_INTERLACED)
*(int *)arg = HDMIRX_INTERLACED;
else
*(int *)arg = HDMIRX_PROGRESSIVE;
break;
case RK_HDMIRX_CMD_GET_SIGNAL_STABLE_STATUS:
*(int *)arg = hdmirx_dev->get_timing;
break;

View File

@@ -590,7 +590,7 @@ static int csi2_dphy_enable_clk(struct csi2_dphy *dphy)
if (dphy->csi_info.dphy_vendor[i] == PHY_VENDOR_SAMSUNG) {
samsung_phy = (struct samsung_mipi_dcphy *)dphy->phy_hw[i];
if (samsung_phy)
clk_prepare_enable(samsung_phy->pclk);
pm_runtime_get_sync(samsung_phy->dev);
} else {
hw = (struct csi2_dphy_hw *)dphy->phy_hw[i];
if (hw) {
@@ -615,7 +615,7 @@ static void csi2_dphy_disable_clk(struct csi2_dphy *dphy)
if (dphy->csi_info.dphy_vendor[i] == PHY_VENDOR_SAMSUNG) {
samsung_phy = (struct samsung_mipi_dcphy *)dphy->phy_hw[i];
if (samsung_phy)
clk_disable_unprepare(samsung_phy->pclk);
pm_runtime_put(samsung_phy->dev);
} else {
hw = (struct csi2_dphy_hw *)dphy->phy_hw[i];
if (hw)

View File

@@ -1781,25 +1781,8 @@ static int samsung_mipi_dcphy_power_on(struct phy *phy)
{
struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy);
enum phy_mode mode = phy_get_mode(phy);
int on = 0;
struct v4l2_subdev *sensor_sd = NULL;
pm_runtime_get_sync(samsung->dev);
reset_control_assert(samsung->apb_rst);
udelay(1);
reset_control_deassert(samsung->apb_rst);
if (atomic_read(&samsung->stream_cnt) && samsung->dphy_dev[0]) {
sensor_sd = get_remote_sensor(&samsung->dphy_dev[0]->sd);
samsung->stream_off(samsung->dphy_dev[0], &samsung->dphy_dev[0]->sd);
if (sensor_sd)
v4l2_subdev_call(sensor_sd, core, ioctl,
RKMODULE_SET_QUICK_STREAM, &on);
samsung->stream_on(samsung->dphy_dev[0], &samsung->dphy_dev[0]->sd);
on = 1;
if (sensor_sd)
v4l2_subdev_call(sensor_sd, core, ioctl,
RKMODULE_SET_QUICK_STREAM, &on);
}
switch (mode) {
case PHY_MODE_MIPI_DPHY:
@@ -2492,6 +2475,22 @@ static int samsung_mipi_dcphy_remove(struct platform_device *pdev)
return 0;
}
static __maybe_unused int samsung_mipi_dcphy_suspend(struct device *dev)
{
return 0;
}
static __maybe_unused int samsung_mipi_dcphy_resume(struct device *dev)
{
struct samsung_mipi_dcphy *samsung = dev_get_drvdata(dev);
reset_control_assert(samsung->apb_rst);
udelay(1);
reset_control_deassert(samsung->apb_rst);
return 0;
}
static __maybe_unused int samsung_mipi_dcphy_runtime_suspend(struct device *dev)
{
struct samsung_mipi_dcphy *samsung = dev_get_drvdata(dev);
@@ -2513,6 +2512,8 @@ static __maybe_unused int samsung_mipi_dcphy_runtime_resume(struct device *dev)
}
static const struct dev_pm_ops samsung_mipi_dcphy_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(samsung_mipi_dcphy_suspend,
samsung_mipi_dcphy_resume)
SET_RUNTIME_PM_OPS(samsung_mipi_dcphy_runtime_suspend,
samsung_mipi_dcphy_runtime_resume, NULL)
};

View File

@@ -2409,7 +2409,7 @@ static int cm_normal_adapter_det(struct charger_manager *cm)
fc_config = cm->fc_config;
fc_config->adaper_power_init_flag = 0;
cm->is_normal_charge = false;
cm->is_normal_charge = true;
cm->is_fast_charge = false;
cm->is_pps_charge = false;
@@ -2561,6 +2561,15 @@ static int charger_extcon_notifier(struct notifier_block *self,
return ret;
}
switch (val.intval) {
case POWER_SUPPLY_USB_TYPE_PD_PPS:
if ((!cm->is_pps_charge) && (desc->psy_charger_pump_stat)) {
ret = cm_pps_adapter_det(cm);
if (ret)
return NOTIFY_BAD;
CM_DBG("USB-TYPE: POWER_SUPPLY_USB_TYPE_PD\n");
break;
}
fallthrough;
case POWER_SUPPLY_USB_TYPE_PD:
if (!cm->is_pps_charge && !cm->is_pd_charge) {
ret = cm_pd_adapter_det(cm);
@@ -2569,14 +2578,6 @@ static int charger_extcon_notifier(struct notifier_block *self,
return NOTIFY_BAD;
}
break;
case POWER_SUPPLY_USB_TYPE_PD_PPS:
if (!cm->is_pps_charge) {
ret = cm_pps_adapter_det(cm);
if (ret)
return NOTIFY_BAD;
CM_DBG("USB-TYPE: POWER_SUPPLY_USB_TYPE_PD\n");
}
break;
default:
if (!cm->is_pps_charge && !cm->is_pd_charge && !cm->is_normal_charge) {
ret = cm_normal_adapter_det(cm);
@@ -2586,7 +2587,8 @@ static int charger_extcon_notifier(struct notifier_block *self,
break;
}
if (val.intval != POWER_SUPPLY_USB_TYPE_PD_PPS) {
if ((val.intval != POWER_SUPPLY_USB_TYPE_PD_PPS) ||
(!desc->psy_charger_pump_stat)) {
if (cm->fc_config->jeita_charge_support) {
cancel_delayed_work(&cm->cm_jeita_work);
queue_delayed_work(cm->cm_wq, &cm->cm_jeita_work, 0);
@@ -2631,9 +2633,11 @@ static void cm_pd_work(struct work_struct *work)
switch (usb_type) {
case POWER_SUPPLY_USB_TYPE_PD_PPS:
CM_DBG("POWER_SUPPLY_USB_TYPE_PD_PPS\n");
if (!cm->is_pps_charge)
if ((!cm->is_pps_charge) && (desc->psy_charger_pump_stat)) {
cm_pps_adapter_det(cm);
break;
break;
}
fallthrough;
case POWER_SUPPLY_USB_TYPE_PD:
CM_DBG("POWER_SUPPLY_USB_TYPE_PD\n");
power_supply_get_property(desc->tcpm_psy,

View File

@@ -816,6 +816,16 @@ config SPI_ROCKCHIP_SLAVE
SPI Slave controller.
Rockchip SPI Slave controller support DMA transport and IRQ mode.
config SPI_ROCKCHIP_SLAVE_MISCDEV
bool "Rockchip SPI controller Slave misc devices"
depends on SPI_ROCKCHIP_SLAVE
help
This selects a misc driver for Rockchip SPI Slave controller.
If you say yes to this option, It will register rkspi-slave-devN misc device
for each spi controller slave and support to get the controller register
resource by calling mmap.
config SPI_RB4XX
tristate "Mikrotik RB4XX SPI master"
depends on SPI_MASTER && ATH79

View File

@@ -12,11 +12,13 @@
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/iopoll.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/spi/rk-spi-slave.h>
#include <linux/spi/spi.h>
#include <linux/pm_runtime.h>
#include <linux/dma-mapping.h>
@@ -161,16 +163,19 @@ enum rockchip_spi_slave_xfer_mode {
};
struct rockchip_spi {
struct spi_controller *ctlr;
struct device *dev;
struct clk_bulk_data *clks;
unsigned int clk_cnt;
struct dma_async_tx_descriptor *rx_cyclic_desc;
void __iomem *regs;
dma_addr_t dma_addr_rx;
dma_addr_t dma_addr_tx;
u32 *dma_buf;
dma_addr_t dma_phys;
u32 dma_cyclic_period_count;
const void *tx;
void *rx;
@@ -183,6 +188,7 @@ struct rockchip_spi {
u32 version;
/*depth of the FIFO buffer */
u32 fifo_len;
int transfer_size;
int max_transfer_size;
u32 fixed_burst_size;
u8 tx_idle_type; /* 0-SR_TF_EMPTY 1-SR_SLAVE_TX_BUSY */
@@ -190,6 +196,7 @@ struct rockchip_spi {
u8 n_bytes;
u32 speed_hz;
u32 mode;
bool slave_aborted;
bool cs_inactive; /* spi slave tansmition stop when cs inactive */
@@ -198,6 +205,11 @@ struct rockchip_spi {
enum rockchip_spi_slave_xfer_mode xfer_mode;
bool ext_spi_clk;
/* misc */
struct miscdevice miscdev;
struct mutex lock;
size_t write_pos;
size_t read_pos;
bool verbose;
ktime_t dbg_time;
};
@@ -329,12 +341,17 @@ static irqreturn_t rockchip_spi_slave_isr(int irq, void *dev_id)
}
/* When int_cs_inactive comes, spi slave abort */
if (rs->cs_inactive && readl_relaxed(rs->regs + ROCKCHIP_SPI_ISR) & INT_CS_INACTIVE) {
rs->slave_aborted = true;
writel_relaxed(0, rs->regs + ROCKCHIP_SPI_IMR);
writel_relaxed(0xffffffff, rs->regs + ROCKCHIP_SPI_ICR);
complete(&rs->xfer_done);
if (rs->cs_inactive &&
readl_relaxed(rs->regs + ROCKCHIP_SPI_ISR) & INT_CS_INACTIVE) {
/* Means using dma cyclic now */
if (rs->rx_cyclic_desc) {
writel_relaxed(0xffffffff, rs->regs + ROCKCHIP_SPI_ICR);
} else {
rs->slave_aborted = true;
writel_relaxed(0, rs->regs + ROCKCHIP_SPI_IMR);
writel_relaxed(0xffffffff, rs->regs + ROCKCHIP_SPI_ICR);
complete(&rs->xfer_done);
}
}
return IRQ_HANDLED;
@@ -473,6 +490,46 @@ static int rockchip_spi_slave_prepare_dma(struct rockchip_spi *rs,
return 1;
}
static int rockchip_spi_slave_prepare_cyclic_dma(struct rockchip_spi *rs,
struct spi_controller *ctlr,
struct spi_transfer *xfer)
{
struct dma_async_tx_descriptor *rxdesc = NULL;
atomic_set(&rs->state, 0);
if (xfer->rx_buf) {
struct dma_slave_config rxconf = {
.direction = DMA_DEV_TO_MEM,
.src_addr = rs->dma_addr_rx,
.src_addr_width = rs->n_bytes,
.src_maxburst =
rockchip_spi_slave_calc_burst_size(rs, xfer->len / rs->n_bytes),
};
dmaengine_slave_config(ctlr->dma_rx, &rxconf);
rxdesc = dmaengine_prep_dma_cyclic(ctlr->dma_rx, rs->dma_phys, xfer->len,
xfer->len > rs->dma_cyclic_period_count ?
xfer->len / rs->dma_cyclic_period_count : xfer->len,
DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
if (!rxdesc)
return -EINVAL;
rxdesc->callback = NULL;
rxdesc->callback_param = ctlr;
}
/* rx must be started before tx due to spi instinct */
if (rxdesc) {
atomic_or(RXDMA, &rs->state);
ctlr->dma_rx->cookie = dmaengine_submit(rxdesc);
dma_async_issue_pending(ctlr->dma_rx);
rs->rx_cyclic_desc = rxdesc;
}
return 0;
}
static bool rockchip_spi_slave_can_dma(struct spi_controller *ctlr,
struct spi_device *spi,
struct spi_transfer *xfer)
@@ -497,6 +554,7 @@ static int rockchip_spi_slave_config(struct rockchip_spi *rs,
u32 cr1;
u32 dmacr = 0;
u32 val = 0;
u32 mode = 0;
rs->slave_aborted = false;
if (xfer->speed_hz)
@@ -504,8 +562,12 @@ static int rockchip_spi_slave_config(struct rockchip_spi *rs,
else
rs->speed_hz = 100000;
cr0 |= (spi->mode & 0x3U) << CR0_SCPH_OFFSET;
if (spi->mode & SPI_LSB_FIRST)
if (spi)
mode = spi->mode;
else
mode = rs->ctlr->mode_bits;
cr0 |= (mode & 0x3U) << CR0_SCPH_OFFSET;
if (mode & SPI_LSB_FIRST)
cr0 |= CR0_FBM_LSB << CR0_FBM_OFFSET;
if (xfer->rx_buf && xfer->tx_buf) {
@@ -751,11 +813,211 @@ static int rockchip_spi_slave_setup(struct spi_device *spi)
cr0 |= ((spi->mode & 0x3) << CR0_SCPH_OFFSET) | CR0_OPM_SLAVE << CR0_OPM_OFFSET;
writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0);
rs->mode = spi->mode;
pm_runtime_put(rs->dev);
return 0;
}
static int rockchip_spi_slave_misc_open(struct inode *inode, struct file *file)
{
struct miscdevice *miscdev = file->private_data;
struct rockchip_spi *rs;
rs = container_of(miscdev, struct rockchip_spi, miscdev);
file->private_data = rs;
pm_runtime_get_sync(rs->dev);
return 0;
}
static int rockchip_spi_slave_misc_init_cyclic(struct rockchip_spi *rs, int length)
{
struct spi_transfer *xfer;
int ret = 0;
u32 status;
if (length > rs->max_transfer_size) {
dev_err(rs->dev, "Transfer is too long (%d)\n", length);
return -EINVAL;
}
if (rs->cs_inactive) {
ret = readl_poll_timeout(rs->regs + ROCKCHIP_SPI_SR, status,
status & SR_SS_IN_N, 20,
ROCKCHIP_SPI_CLK_TO_CS_DEASSERT_US);
if (ret) {
dev_err(rs->dev, "The cs of spi master is still asserted\n");
return -EIO;
}
}
xfer = kzalloc(sizeof(struct spi_transfer), GFP_KERNEL);
if (!xfer)
return -ENOMEM;
xfer->rx_buf = rs->dma_buf;
xfer->tx_buf = NULL;
xfer->len = length;
xfer->bits_per_word = 8;
xfer->speed_hz = 1000000;
rs->n_bytes = xfer->bits_per_word <= 8 ? 1 : 2;
rs->xfer_mode = ROCKCHIP_SPI_DMA;
ret = rockchip_spi_slave_config(rs, NULL, xfer);
if (ret)
goto free_spi_transfer;
rockchip_spi_slave_prepare_cyclic_dma(rs, rs->ctlr, xfer);
/* Record for check */
rs->transfer_size = xfer->len;
if (rs->cs_inactive)
writel_relaxed(INT_CS_INACTIVE, rs->regs + ROCKCHIP_SPI_IMR);
spi_enable_chip(rs, true);
if (rs->ready) {
gpiod_set_value(rs->ready, 0);
gpiod_set_value(rs->ready, 1);
}
free_spi_transfer:
kfree(xfer);
return ret;
}
static int rockchip_spi_slave_misc_deinit_cyclic(struct rockchip_spi *rs)
{
struct spi_controller *ctlr = rs->ctlr;
if (rs->rx_cyclic_desc) {
dmaengine_terminate_async(ctlr->dma_rx);
dmaengine_desc_free(rs->rx_cyclic_desc);
rs->rx_cyclic_desc = NULL;
}
rockchip_spi_slave_stop(ctlr);
rs->read_pos = 0;
rs->write_pos = 0;
return 0;
}
static long rockchip_spi_slave_misc_ioctl(struct file *file, unsigned int cmd,
unsigned long args)
{
struct rockchip_spi *rs = file->private_data;
int length = (int)args;
int ret = 0;
mutex_lock(&rs->lock);
switch (cmd) {
case SPI_SLAVE_INIT_CYCLIC:
ret = rockchip_spi_slave_misc_init_cyclic(rs, length);
if (ret)
dev_err(rs->dev, "DMA cyclic init failed: %d\n", ret);
break;
case SPI_SLAVE_DEINIT_CYCLIC:
ret = rockchip_spi_slave_misc_deinit_cyclic(rs);
if (ret)
dev_err(rs->dev, "DMA cyclic deinit failed: %d\n", ret);
break;
default:
break;
}
mutex_unlock(&rs->lock);
return 0;
}
static ssize_t rockchip_spi_slave_misc_read(struct file *file, char __user *buf,
size_t n, loff_t *offset)
{
struct rockchip_spi *rs = file->private_data;
struct spi_controller *ctlr = rs->ctlr;
size_t to_copy, copied = 0;
int ret = 0;
size_t period_size = n > rs->dma_cyclic_period_count ?
n / rs->dma_cyclic_period_count : n;
size_t cur_index;
struct dma_tx_state state;
size_t data_available;
mutex_lock(&rs->lock);
if (n + (size_t)(*offset) > rs->transfer_size) {
dev_err(rs->dev, "Exceed the expected length: %zu + %lld > %d\n",
n, *offset, rs->transfer_size);
ret = -EINVAL;
goto out;
}
dmaengine_tx_status(ctlr->dma_rx, ctlr->dma_rx->cookie, &state);
cur_index = (period_size - state.residue) % period_size;
if (cur_index < rs->read_pos)
data_available = period_size - rs->read_pos + cur_index;
else
data_available = cur_index - rs->read_pos;
to_copy = min(n, data_available);
if (rs->read_pos + to_copy > period_size) {
if (copy_to_user(buf, rs->dma_buf + rs->read_pos,
period_size - rs->read_pos)) {
ret = -EFAULT;
goto out;
}
if (copy_to_user(buf + period_size - rs->read_pos, rs->dma_buf,
to_copy - period_size + rs->read_pos)) {
ret = -EFAULT;
goto out;
}
} else {
if (copy_to_user(buf, rs->dma_buf + rs->read_pos, to_copy)) {
ret = -EFAULT;
goto out;
}
}
rs->read_pos = (rs->read_pos + to_copy) % period_size;
copied = to_copy;
out:
mutex_unlock(&rs->lock);
return copied ? copied : ret;
}
static int rockchip_spi_slave_misc_release(struct inode *inode, struct file *file)
{
struct rockchip_spi *rs = file->private_data;
mutex_lock(&rs->lock);
rockchip_spi_slave_misc_deinit_cyclic(rs);
mutex_unlock(&rs->lock);
pm_runtime_put(rs->dev);
return 0;
}
static const struct file_operations rockchip_spi_slave_misc_fops = {
.open = rockchip_spi_slave_misc_open,
.release = rockchip_spi_slave_misc_release,
.unlocked_ioctl = rockchip_spi_slave_misc_ioctl,
.read = rockchip_spi_slave_misc_read,
};
static int rockchip_spi_slave_probe(struct platform_device *pdev)
{
int ret = 0;
@@ -774,6 +1036,8 @@ static int rockchip_spi_slave_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, ctlr);
rs = spi_controller_get_devdata(ctlr);
rs->ctlr = ctlr;
mutex_init(&rs->lock);
/* Get basic io resource and map it */
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -924,6 +1188,12 @@ static int rockchip_spi_slave_probe(struct platform_device *pdev)
if (!device_property_read_bool(&pdev->dev, "rockchip,dma-support-req-mix"))
rs->dma_timeout = 0;
if (!device_property_read_u32(&pdev->dev, "rockchip,dma-cyclic-period-count", &val))
/* DMA cyclic period count can't be zero */
rs->dma_cyclic_period_count = val ? val : 1;
else
rs->dma_cyclic_period_count = 1;
rs->ready = devm_gpiod_get_optional(&pdev->dev, "ready", GPIOD_OUT_HIGH);
if (IS_ERR(rs->ready)) {
ret = PTR_ERR(rs->ready);
@@ -937,6 +1207,22 @@ static int rockchip_spi_slave_probe(struct platform_device *pdev)
goto err_free_dma_rx;
}
if (IS_ENABLED(CONFIG_SPI_ROCKCHIP_SLAVE_MISCDEV)) {
char misc_name[20];
snprintf(misc_name, sizeof(misc_name), "rkspi-slv-dev%d", ctlr->bus_num);
rs->miscdev.minor = MISC_DYNAMIC_MINOR;
rs->miscdev.name = misc_name;
rs->miscdev.fops = &rockchip_spi_slave_misc_fops;
rs->miscdev.parent = &pdev->dev;
ret = misc_register(&rs->miscdev);
if (ret)
dev_err(&pdev->dev, "failed to register misc device %s\n", misc_name);
else
dev_info(&pdev->dev, "register misc device %s\n", misc_name);
}
dev_info(rs->dev, "slave probed, cs-inactive=%d, ready=%d, ext=%d, dam_buf=%x\n",
rs->cs_inactive, rs->ready ? 1 : 0, rs->ext_spi_clk, (u32)rs->dma_phys);
@@ -961,6 +1247,9 @@ static int rockchip_spi_slave_remove(struct platform_device *pdev)
struct spi_controller *ctlr = spi_controller_get(platform_get_drvdata(pdev));
struct rockchip_spi *rs = spi_controller_get_devdata(ctlr);
if (IS_ENABLED(CONFIG_SPI_ROCKCHIP_SLAVE_MISCDEV))
misc_deregister(&rs->miscdev);
pm_runtime_get_sync(&pdev->dev);
clk_bulk_disable_unprepare(rs->clk_cnt, rs->clks);

View File

@@ -1387,6 +1387,11 @@ static inline int dwc2_is_device_mode(struct dwc2_hsotg *hsotg)
return (dwc2_readl(hsotg, GINTSTS) & GINTSTS_CURMODE_HOST) == 0;
}
static inline int dwc2_is_force_host_mode(struct dwc2_hsotg *hsotg)
{
return (dwc2_readl(hsotg, GUSBCFG) & GUSBCFG_FORCEHOSTMODE) != 0;
}
int dwc2_drd_init(struct dwc2_hsotg *hsotg);
void dwc2_drd_suspend(struct dwc2_hsotg *hsotg);
void dwc2_drd_resume(struct dwc2_hsotg *hsotg);

View File

@@ -796,7 +796,8 @@ static int __maybe_unused dwc2_resume(struct device *dev)
dwc2_drd_resume(dwc2);
}
if (dwc2->dr_mode == USB_DR_MODE_HOST && dwc2_is_device_mode(dwc2)) {
if (dwc2->dr_mode == USB_DR_MODE_HOST && (dwc2_is_device_mode(dwc2) ||
!dwc2_is_force_host_mode(dwc2))) {
/* Reinit for Host mode if lost power */
dwc2_force_mode(dwc2, true);

View File

@@ -328,6 +328,9 @@ static int dp_altmode_vdm(struct typec_altmode *alt,
break;
case CMDT_RSP_NAK:
switch (cmd) {
case DP_CMD_STATUS_UPDATE:
dp->state = DP_STATE_EXIT;
break;
case DP_CMD_CONFIGURE:
dp->data.conf = 0;
ret = dp_altmode_configured(dp);

View File

@@ -56,7 +56,8 @@ enum rkaiisp_chn_src {
VICAP_BAYER_RAW,
ALLZERO_SIGMA,
ALLZERO_NARMAP,
ISP_FINAL_Y
ISP_FINAL_Y,
VICAP_BAYER_RAW_DOWN
};
enum rkaiisp_exealgo {

View File

@@ -0,0 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
* Copyright (c) 2025 Rockchip Electronics Co., Ltd.
*/
#ifndef RK_SPI_SLAVE_H
#define RK_SPI_SLAVE_H
#include <linux/types.h>
#define SPI_SLAVE_BASE 's'
#define SPI_SLAVE_INIT_CYCLIC _IOW(SPI_SLAVE_BASE, 0, int)
#define SPI_SLAVE_DEINIT_CYCLIC _IOW(SPI_SLAVE_BASE, 1, int)
#endif