Merge commit '190f4223b2b4b1320d485cb6211af1733d9da7a2'

* commit '190f4223b2b4b1320d485cb6211af1733d9da7a2':
  media: i2c: sc200ai adapt sleep_wakeup
  media: i2c: add sleep-wakeup mod
  media: rockchip: vicap: call sensor quick stream only rv1106 when resume
  spi: rockchip-test: Support config spi mode
  media: rockchip: vicap add intr mask for bandwidth, and mask bandwidth err per second
  ARM: configs: rv1106-wakeup.config: enable VIDEO_CAM_SLEEP_WAKEUP
  ARM: configs: rockchip: update rv1106-wakeup.config
  arm64: dts: rockchip: rk3588-vehicle-evb-v20: change to use mfd display
  ARM: dts: rockchip: rv1106g-evb2-v12-wakeup remove rtt

Change-Id: I7d1adaee411c28b49bb004f428aba046724376ce

Conflicts:
	drivers/media/i2c/Makefile
	drivers/media/i2c/sc200ai.c
This commit is contained in:
Tao Huang
2023-12-11 16:54:03 +08:00
13 changed files with 1237 additions and 145 deletions

View File

@@ -21,31 +21,6 @@
reg = <0x40000 0x3c000>;
};
meta: meta@800000 {
/* reg's offset MUST match with RTOS */
reg = <0x00800000 0x60000>;
};
rkisp_thunderboot: rkisp@860000 {
/* reg's offset MUST match with RTOS */
/*
* vicap, capture raw10, ceil(w*10/8/256)*256*h *4(buf num)
* e.g. 1920x1080: 0xa8c000
*/
reg = <0x00860000 0xa8c000>;
};
};
thunder_boot_service: thunder-boot-service {
compatible = "rockchip,thunder-boot-service";
mbox-names = "amp-rx";
mboxes = <&mailbox 1>;
resets = <&cru SRST_CORE_MCU>, <&cru SRST_CORE_MCU_PWRUP>,
<&cru SRST_CORE_MCU_CPU>, <&cru SRST_T_CORE_MCU_CPU>;
reset-names = "core_mcu", "core_mcu_pwrup",
"core_mcu_cpu", "t_core_mcu_cpu";
memory-region = <&rtos>;
status = "disabled";
};
vcc_1v8: vcc-1v8 {
@@ -247,8 +222,6 @@
&rkcif_mipi_lvds {
status = "okay";
memory-region-thunderboot = <&rkisp_thunderboot>;
rtt-suspend;
pinctrl-names = "default";
pinctrl-0 = <&mipi_pins>;
@@ -278,9 +251,6 @@
&rkisp_vir0 {
status = "okay";
memory-region-thunderboot = <&rkisp_thunderboot>;
rtt-suspend;
port@0 {
isp_in: endpoint {
remote-endpoint = <&mipi_lvds_sditf>;

View File

@@ -3,7 +3,10 @@ CONFIG_HIGH_RES_TIMERS=y
CONFIG_INPUT=y
# CONFIG_MDIO_DEVICE is not set
# CONFIG_PHYLIB is not set
CONFIG_RV1106_HPMCU_FAST_WAKEUP=y
CONFIG_PHY_ROCKCHIP_CSI2_DPHY=y
CONFIG_RV1106_PMU_WAKEUP_TIMEOUT=y
CONFIG_VIDEO_CAM_SLEEP_WAKEUP=y
CONFIG_VIDEO_ROCKCHIP_CIF=y
CONFIG_VIDEO_SC200AI=y
CONFIG_VIDEO_SC301IOT=y
# CONFIG_VIDEO_SC3336 is not set

View File

@@ -86,6 +86,77 @@
status = "okay";
};
&pinctrl {
bl {
bl0_enable_pin: bl0-enable-pin {
rockchip,pins =
<1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>,
<4 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>,
<4 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>;
};
bl1_enable_pin: bl1-enable-pin {
rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
};
bl2_enable_pin: bl2-enable-pin {
rockchip,pins = <3 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>;
};
bl3_enable_pin: bl3-enable-pin {
rockchip,pins = <3 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>;
};
bl4_enable_pin: bl4-enable-pin {
rockchip,pins = <0 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>;
};
bl5_enable_pin: bl5-enable-pin {
rockchip,pins = <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>;
};
};
serdes {
//dsi0
ser0_rst_pin: ser0-rst-pin {
rockchip,pins = <1 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
};
//dsi1
ser1_rst_pin: ser1-rst-pin {
rockchip,pins = <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
};
};
touch {
//dsi0-i2c2
touch_gpio_dsi0: touch-gpio-dsi0 {
rockchip,pins =
<1 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; //rst
};
//dsi1-i2c6
touch_gpio_dsi1: touch-gpio-dsi1 {
rockchip,pins =
<1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, //rst
<1 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>; //int
};
//dp0-i2c4
touch_gpio_dp0: touch-gpio-dp0 {
rockchip,pins =
<3 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>, //rst
<0 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>; //int
};
//edp0-i2c5
touch_gpio_edp0: touch-gpio-edp0 {
rockchip,pins =
<0 RK_PD4 RK_FUNC_GPIO &pcfg_pull_up>, //rst
<0 RK_PD1 RK_FUNC_GPIO &pcfg_pull_up>; //int
};
};
};
&rockchip_suspend {
rockchip,sleep-mode-config = <
(0

View File

@@ -5,6 +5,12 @@
if VIDEO_DEV
config VIDEO_CAM_SLEEP_WAKEUP
tristate "Enable sensor sleep wake up function"
depends on ARCH_ROCKCHIP
help
Support for sensor sleep and wake up.
comment "IR I2C driver auto-selected by 'Autoselect ancillary drivers'"
depends on MEDIA_SUBDRV_AUTOSELECT && I2C && RC_CORE

View File

@@ -29,6 +29,7 @@ obj-$(CONFIG_VIDEO_BF3925) += bf3925.o
obj-$(CONFIG_VIDEO_BT819) += bt819.o
obj-$(CONFIG_VIDEO_BT856) += bt856.o
obj-$(CONFIG_VIDEO_BT866) += bt866.o
obj-$(CONFIG_VIDEO_CAM_SLEEP_WAKEUP) += cam-sleep-wakeup.o
obj-$(CONFIG_VIDEO_CCS) += ccs/
obj-$(CONFIG_VIDEO_CCS_PLL) += ccs-pll.o
obj-$(CONFIG_VIDEO_CN3927V) += cn3927v.o

View File

@@ -0,0 +1,198 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2023 Rockchip Electronics Co., Ltd
#include <linux/i2c.h>
#include <linux/clk.h>
#include <linux/types.h>
#include <linux/device.h>
#include <linux/rk-preisp.h>
#include <linux/gpio/consumer.h>
#include <linux/pinctrl/consumer.h>
#include <linux/regulator/consumer.h>
#include "cam-sleep-wakeup.h"
struct cam_sw_info *cam_sw_init(void)
{
struct cam_sw_info *cam_info =
kzalloc(sizeof(*cam_info), GFP_KERNEL);
if (!cam_info)
pr_err("kmalloc for cam fail\n");
return cam_info;
}
EXPORT_SYMBOL_GPL(cam_sw_init);
int cam_sw_deinit(struct cam_sw_info *info)
{
if (IS_ERR_OR_NULL(info)) {
pr_err("%s param is null\n", __func__);
return -EINVAL;
}
kfree(info);
return 0;
}
EXPORT_SYMBOL_GPL(cam_sw_deinit);
int cam_sw_clk_init(struct cam_sw_info *info, struct clk *xvclk, u32 clk_freq)
{
if (IS_ERR_OR_NULL(info)) {
pr_err("%s param is null\n", __func__);
return -EINVAL;
}
info->clk.xvclk = xvclk;
info->clk.clk_freq = clk_freq;
return 0;
}
EXPORT_SYMBOL_GPL(cam_sw_clk_init);
int cam_sw_reset_pin_init(struct cam_sw_info *info,
struct gpio_desc *reset_gpio, bool reset_active_state)
{
if (IS_ERR_OR_NULL(info)) {
pr_err("%s param is null\n", __func__);
return -EINVAL;
}
info->pin.reset_gpio = reset_gpio;
info->pin.reset_active_state = reset_active_state;
return 0;
}
EXPORT_SYMBOL_GPL(cam_sw_reset_pin_init);
int cam_sw_pwdn_pin_init(struct cam_sw_info *info, struct gpio_desc *pwdn_gpio,
bool pwdn_active_state)
{
if (IS_ERR_OR_NULL(info)) {
pr_err("%s param is null\n", __func__);
return -EINVAL;
}
info->pin.pwdn_gpio = pwdn_gpio;
info->pin.pwdn_active_state = pwdn_active_state;
return 0;
}
EXPORT_SYMBOL_GPL(cam_sw_pwdn_pin_init);
int cam_sw_pinctrl_init(struct cam_sw_info *info, struct pinctrl *pinctrl,
struct pinctrl_state *pins_default,
struct pinctrl_state *pins_sleep)
{
if (IS_ERR_OR_NULL(info)) {
pr_err("%s param is null\n", __func__);
return -EINVAL;
}
info->pin.pinctrl = pinctrl;
info->pin.pins_default = pins_default;
info->pin.pins_sleep = pins_sleep;
return 0;
}
EXPORT_SYMBOL_GPL(cam_sw_pinctrl_init);
int cam_sw_regulator_bulk_init(struct cam_sw_info *info, int supplies_num,
struct regulator_bulk_data *supplies)
{
if (IS_ERR_OR_NULL(info)) {
pr_err("%s param is null\n", __func__);
return -EINVAL;
}
info->pin.supplies_num = supplies_num;
info->pin.supplies = supplies;
return 0;
}
EXPORT_SYMBOL_GPL(cam_sw_regulator_bulk_init);
int cam_sw_write_array_cb_init(struct cam_sw_info *info,
struct i2c_client *client, void *array_regs,
sensor_write_array write_array)
{
if (IS_ERR_OR_NULL(info) || IS_ERR_OR_NULL(client)) {
pr_err("%s param is null\n", __func__);
return -EINVAL;
}
info->client = client;
info->array_regs = array_regs;
info->write_array = write_array;
return 0;
}
EXPORT_SYMBOL_GPL(cam_sw_write_array_cb_init);
int cam_sw_write_array(struct cam_sw_info *info)
{
if (IS_ERR_OR_NULL(info) || !info->write_array) {
pr_err("%s param is null\n", __func__);
return -EINVAL;
}
info->write_array(info->client, info->array_regs);
return 0;
}
EXPORT_SYMBOL_GPL(cam_sw_write_array);
int cam_sw_prepare_wakeup(struct cam_sw_info *info, struct device *dev)
{
int ret = 0;
if (!IS_ERR_OR_NULL(info->pin.pins_default)) {
ret = pinctrl_select_state(info->pin.pinctrl,
info->pin.pins_default);
if (ret < 0)
dev_err(dev, "could not set pins\n");
}
if (clk_set_rate(info->clk.xvclk, info->clk.clk_freq) < 0)
dev_warn(dev, "clk_set_rate fail!");
if (clk_get_rate(info->clk.xvclk) != info->clk.clk_freq)
dev_warn(dev, "clk_get_rate fail!");
if (clk_prepare_enable(info->clk.xvclk) < 0) {
dev_err(dev, "clk_prepare_enable fail!");
return -EINVAL;
}
if (!IS_ERR(info->pin.reset_gpio))
gpiod_set_value_cansleep(info->pin.reset_gpio, info->pin.reset_active_state);
if (!IS_ERR(info->pin.supplies) && info->pin.supplies_num) {
ret = regulator_bulk_enable(info->pin.supplies_num, info->pin.supplies);
if (ret != 0)
dev_err(dev, "regulator_bulk_enable fail");
}
if (!IS_ERR(info->pin.reset_gpio))
gpiod_set_value_cansleep(info->pin.reset_gpio, !info->pin.reset_active_state);
if (!IS_ERR(info->pin.pwdn_gpio))
gpiod_set_value_cansleep(info->pin.pwdn_gpio, info->pin.pwdn_active_state);
return 0;
}
EXPORT_SYMBOL_GPL(cam_sw_prepare_wakeup);
int cam_sw_prepare_sleep(struct cam_sw_info *info)
{
if (!IS_ERR(info->clk.xvclk))
clk_disable_unprepare(info->clk.xvclk);
if (!IS_ERR(info->pin.pwdn_gpio))
gpiod_set_value_cansleep(info->pin.pwdn_gpio, !info->pin.pwdn_active_state);
if (!IS_ERR(info->pin.reset_gpio))
gpiod_set_value_cansleep(info->pin.reset_gpio, !info->pin.reset_active_state);
if (!IS_ERR_OR_NULL(info->pin.pins_sleep))
pinctrl_select_state(info->pin.pinctrl, info->pin.pins_sleep);
if (!IS_ERR(info->pin.supplies) && info->pin.supplies_num)
regulator_bulk_disable(info->pin.supplies_num, info->pin.supplies);
return 0;
}
EXPORT_SYMBOL_GPL(cam_sw_prepare_sleep);
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,131 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2023 Rockchip Electronics Co., Ltd. */
#ifndef CAM_SLEEP_WAKEUP_H
#define CAM_SLEEP_WAKEUP_H
#include <linux/types.h>
typedef int (*sensor_write_array)(struct i2c_client *, void *);
struct sensor_clk_obj {
struct clk *xvclk;
u32 clk_freq;
};
struct sensor_pin_obj {
struct pinctrl *pinctrl;
struct pinctrl_state *pins_default;
struct pinctrl_state *pins_sleep;
bool reset_active_state;
bool pwdn_active_state;
struct gpio_desc *reset_gpio;
struct gpio_desc *pwdn_gpio;
int supplies_num;
struct regulator_bulk_data *supplies;
};
struct cam_sw_info {
phys_addr_t phys;
struct sensor_clk_obj clk;
struct sensor_pin_obj pin;
struct i2c_client *client;
void *array_regs;
struct preisp_hdrae_exp_s hdr_ae;
sensor_write_array write_array;
};
#if IS_REACHABLE(CONFIG_VIDEO_CAM_SLEEP_WAKEUP)
struct cam_sw_info *cam_sw_init(void);
int cam_sw_deinit(struct cam_sw_info *info);
int cam_sw_clk_init(struct cam_sw_info *info, struct clk *xvclk, u32 clk_freq);
int cam_sw_reset_pin_init(struct cam_sw_info *info,
struct gpio_desc *reset_gpio,
bool reset_active_state);
int cam_sw_pwdn_pin_init(struct cam_sw_info *info, struct gpio_desc *pwdn_gpio,
bool pwdn_active_state);
int cam_sw_pinctrl_init(struct cam_sw_info *info, struct pinctrl *pinctrl,
struct pinctrl_state *pins_default,
struct pinctrl_state *pins_sleep);
int cam_sw_regulator_bulk_init(struct cam_sw_info *info, int supplies_num,
struct regulator_bulk_data *supplies);
int cam_sw_write_array_cb_init(struct cam_sw_info *info,
struct i2c_client *client, void *array_regs,
sensor_write_array write_array);
int cam_sw_write_array(struct cam_sw_info *info);
int cam_sw_prepare_wakeup(struct cam_sw_info *info, struct device *dev);
int cam_sw_prepare_sleep(struct cam_sw_info *info);
#else
static inline struct cam_sw_info *cam_sw_init(void)
{
return NULL;
}
static inline int cam_sw_deinit(struct cam_sw_info *info)
{
return 0;
}
static inline int cam_sw_clk_init(struct cam_sw_info *info, struct clk *xvclk,
u32 clk_freq)
{
return 0;
}
static inline int cam_sw_reset_pin_init(struct cam_sw_info *info,
struct gpio_desc *reset_gpio,
bool reset_active_state)
{
return 0;
}
static inline int cam_sw_pwdn_pin_init(struct cam_sw_info *info,
struct gpio_desc *pwdn_gpio,
bool pwdn_active_state)
{
return 0;
}
static inline int cam_sw_pinctrl_init(struct cam_sw_info *info,
struct pinctrl *pinctrl,
struct pinctrl_state *pins_default,
struct pinctrl_state *pins_sleep)
{
return 0;
}
static inline int
cam_sw_regulator_bulk_init(struct cam_sw_info *info, int supplies_num,
struct regulator_bulk_data *supplies)
{
return 0;
}
static inline int cam_sw_write_array_cb_init(struct cam_sw_info *info,
struct i2c_client *client,
void *array_regs,
sensor_write_array write_array)
{
return 0;
}
static inline int cam_sw_write_array(struct cam_sw_info *info)
{
return 0;
}
static inline int cam_sw_prepare_wakeup(struct cam_sw_info *info,
struct device *dev)
{
return 0;
}
static inline int cam_sw_prepare_sleep(struct cam_sw_info *info)
{
return 0;
}
#endif
#endif

View File

@@ -11,8 +11,11 @@
* V0.0X01.0X05 add quick stream on/off.
* V0.0X01.0X06 fix set vflip/hflip failed bug.
* V0.0X01.0X07
* 1. fix set double times exposue value failed issue.
* 2. add some debug info.
* 1. fix set double times exposue value failed issue.
* 2. add some debug info.
* V0.0X01.0X08
* 1. add support wakeup & sleep for aov function
* 2. using 60fps output default
*/
#include <linux/clk.h>
@@ -35,8 +38,9 @@
#include <linux/pinctrl/consumer.h>
#include "../platform/rockchip/isp/rkisp_tb_helper.h"
#include "cam-tb-setup.h"
#include "cam-sleep-wakeup.h"
#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x07)
#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x08)
#ifndef V4L2_CID_DIGITAL_GAIN
#define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN
@@ -180,6 +184,7 @@ struct sc200ai {
bool is_thunderboot;
bool is_first_streamoff;
struct preisp_hdrae_exp_s init_hdrae_exp;
struct cam_sw_info *cam_sw_inf;
};
#define to_sc200ai(sd) container_of(sd, struct sc200ai, subdev)
@@ -608,20 +613,6 @@ static const struct regval sc200ai_hdr_10_1920x1080_regs[] = {
static const struct sc200ai_mode supported_modes[] = {
{
.width = 1920,
.height = 1080,
.max_fps = {
.numerator = 10000,
.denominator = 300000,
},
.exp_def = 0x0080,
.hts_def = 0x44C * 2,
.vts_def = 0x0465,
.bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10,
.reg_list = sc200ai_linear_10_1920x1080_30fps_regs,
.hdr_mode = NO_HDR,
.vc[PAD0] = 0,
}, {
.width = 1920,
.height = 1080,
.max_fps = {
@@ -635,6 +626,20 @@ static const struct sc200ai_mode supported_modes[] = {
.reg_list = sc200ai_linear_10_1920x1080_60fps_regs,
.hdr_mode = NO_HDR,
.vc[PAD0] = 0,
}, {
.width = 1920,
.height = 1080,
.max_fps = {
.numerator = 10000,
.denominator = 300000,
},
.exp_def = 0x0080,
.hts_def = 0x44C * 2,
.vts_def = 0x0465,
.bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10,
.reg_list = sc200ai_linear_10_1920x1080_30fps_regs,
.hdr_mode = NO_HDR,
.vc[PAD0] = 0,
}, {
.width = 1920,
.height = 1080,
@@ -1205,6 +1210,9 @@ static long sc200ai_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
break;
case PREISP_CMD_SET_HDRAE_EXP:
sc200ai_set_hdrae(sc200ai, arg);
if (sc200ai->cam_sw_inf)
memcpy(&sc200ai->cam_sw_inf->hdr_ae, (struct preisp_hdrae_exp_s *)(arg),
sizeof(struct preisp_hdrae_exp_s));
break;
case RKMODULE_SET_QUICK_STREAM:
@@ -1502,6 +1510,9 @@ static int __sc200ai_power_on(struct sc200ai *sc200ai)
dev_err(dev, "Failed to enable xvclk\n");
return ret;
}
cam_sw_regulator_bulk_init(sc200ai->cam_sw_inf, SC200AI_NUM_SUPPLIES, sc200ai->supplies);
if (sc200ai->is_thunderboot)
return 0;
@@ -1566,6 +1577,51 @@ static void __sc200ai_power_off(struct sc200ai *sc200ai)
regulator_bulk_disable(SC200AI_NUM_SUPPLIES, sc200ai->supplies);
}
#if IS_REACHABLE(CONFIG_VIDEO_CAM_SLEEP_WAKEUP)
static int __maybe_unused sc200ai_resume(struct device *dev)
{
int ret;
struct i2c_client *client = to_i2c_client(dev);
struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct sc200ai *sc200ai = to_sc200ai(sd);
cam_sw_prepare_wakeup(sc200ai->cam_sw_inf, dev);
usleep_range(4000, 5000);
cam_sw_write_array(sc200ai->cam_sw_inf);
if (__v4l2_ctrl_handler_setup(&sc200ai->ctrl_handler))
dev_err(dev, "__v4l2_ctrl_handler_setup fail!");
if (sc200ai->has_init_exp && sc200ai->cur_mode != NO_HDR) { // hdr mode
ret = sc200ai_ioctl(&sc200ai->subdev, PREISP_CMD_SET_HDRAE_EXP,
&sc200ai->cam_sw_inf->hdr_ae);
if (ret) {
dev_err(&sc200ai->client->dev, "set exp fail in hdr mode\n");
return ret;
}
}
return 0;
}
static int __maybe_unused sc200ai_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct sc200ai *sc200ai = to_sc200ai(sd);
cam_sw_write_array_cb_init(sc200ai->cam_sw_inf, client,
(void *)sc200ai->cur_mode->reg_list,
(sensor_write_array)sc200ai_write_array);
cam_sw_prepare_sleep(sc200ai->cam_sw_inf);
return 0;
}
#else
#define sc200ai_resume NULL
#define sc200ai_suspend NULL
#endif
static int sc200ai_runtime_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -1626,6 +1682,7 @@ static int sc200ai_enum_frame_interval(struct v4l2_subdev *sd,
static const struct dev_pm_ops sc200ai_pm_ops = {
SET_RUNTIME_PM_OPS(sc200ai_runtime_suspend,
sc200ai_runtime_resume, NULL)
SET_LATE_SYSTEM_SLEEP_PM_OPS(sc200ai_suspend, sc200ai_resume)
};
#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
@@ -2049,6 +2106,13 @@ static int sc200ai_probe(struct i2c_client *client,
goto err_power_off;
#endif
if (!sc200ai->cam_sw_inf) {
sc200ai->cam_sw_inf = cam_sw_init();
cam_sw_clk_init(sc200ai->cam_sw_inf, sc200ai->xvclk, SC200AI_XVCLK_FREQ);
cam_sw_reset_pin_init(sc200ai->cam_sw_inf, sc200ai->reset_gpio, 0);
cam_sw_pwdn_pin_init(sc200ai->cam_sw_inf, sc200ai->pwdn_gpio, 1);
}
memset(facing, 0, sizeof(facing));
if (strcmp(sc200ai->module_facing, "back") == 0)
facing[0] = 'b';
@@ -2099,6 +2163,8 @@ static void sc200ai_remove(struct i2c_client *client)
v4l2_ctrl_handler_free(&sc200ai->ctrl_handler);
mutex_destroy(&sc200ai->mutex);
cam_sw_deinit(sc200ai->cam_sw_inf);
pm_runtime_disable(&client->dev);
if (!pm_runtime_status_suspended(&client->dev))
__sc200ai_power_off(sc200ai);

View File

@@ -3619,6 +3619,7 @@ static int rkcif_csi_channel_set(struct rkcif_stream *stream,
val &= ~CSI_HIGH_ALIGN;
rkcif_write_register(dev, get_reg_index_of_id_ctrl0(channel->id), val);
dev->intr_mask = rkcif_read_register(dev, CIF_REG_MIPI_LVDS_INTEN);
return 0;
}
@@ -4007,6 +4008,7 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream,
RKCIF_YUV_ADDR_STATE_INIT,
channel->id);
}
dev->intr_mask = rkcif_read_register(dev, CIF_REG_MIPI_LVDS_INTEN);
return 0;
}
@@ -5947,6 +5949,7 @@ static int rkcif_stream_start(struct rkcif_stream *stream, unsigned int mode)
rkcif_write_register(dev, CIF_REG_DVP_CTRL,
AXI_BURST_16 | workmode | ENABLE_CAPTURE);
}
dev->intr_mask = rkcif_read_register(dev, CIF_REG_DVP_INTSTAT);
#if IS_ENABLED(CONFIG_CPU_RV1106)
rv1106_sdmmc_put_lock();
#endif
@@ -10486,7 +10489,8 @@ static int rkcif_subdevs_set_stream(struct rkcif_device *cif_dev, int on)
for (i = 0; i < p->num_subdevs; i++) {
if (p->subdevs[i] == terminal_sensor->sd && on)
rkcif_set_sof(cif_dev, cif_dev->stream[0].frame_idx);
if (p->subdevs[i] == terminal_sensor->sd) {
if (p->subdevs[i] == terminal_sensor->sd &&
cif_dev->chip_id == CHIP_RV1106_CIF) {
if (!rk_tb_mcu_is_done() && on) {
cif_dev->tb_client.data = p->subdevs[i];
cif_dev->tb_client.cb = rkcif_sensor_quick_streaming_cb;
@@ -10935,9 +10939,15 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev)
return;
}
if (intstat & CSI_BANDWIDTH_LACK_V1) {
if (intstat & CSI_BANDWIDTH_LACK_V1 &&
cif_dev->intr_mask & CSI_BANDWIDTH_LACK_V1) {
cif_dev->irq_stats.csi_bwidth_lack_cnt++;
cif_dev->err_state |= RKCIF_ERR_BANDWIDTH_LACK;
if (cif_dev->irq_stats.csi_bwidth_lack_cnt > 10) {
rkcif_write_register_and(cif_dev, CIF_REG_MIPI_LVDS_INTEN, ~(CSI_BANDWIDTH_LACK_V1));
cif_dev->intr_mask &= ~(CSI_BANDWIDTH_LACK_V1);
schedule_delayed_work(&cif_dev->work_deal_err, msecs_to_jiffies(1000));
}
}
if (intstat & CSI_ALL_ERROR_INTEN_V1) {

View File

@@ -1900,6 +1900,17 @@ void rkcif_set_sensor_stream(struct work_struct *work)
&sensor_work->on);
}
static void rkcif_deal_err_intr(struct work_struct *work)
{
struct delayed_work *dwork = to_delayed_work(work);
struct rkcif_device *cif_dev = container_of(dwork,
struct rkcif_device,
work_deal_err);
cif_dev->intr_mask |= CSI_BANDWIDTH_LACK_V1;
rkcif_write_register_or(cif_dev, CIF_REG_MIPI_LVDS_INTEN, CSI_BANDWIDTH_LACK_V1);
}
int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int inf_id)
{
struct device *dev = cif_dev->dev;
@@ -1941,6 +1952,7 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int
INIT_WORK(&cif_dev->err_state_work.work, rkcif_err_print_work);
INIT_WORK(&cif_dev->sensor_work.work, rkcif_set_sensor_stream);
INIT_DELAYED_WORK(&cif_dev->work_deal_err, rkcif_deal_err_intr);
if (cif_dev->chip_id < CHIP_RV1126_CIF) {
if (cif_dev->inf_id == RKCIF_MIPI_LVDS) {

View File

@@ -906,6 +906,8 @@ struct rkcif_device {
u32 share_mem_size;
u32 thunderboot_sensor_num;
int sensor_state;
u32 intr_mask;
struct delayed_work work_deal_err;
};
extern struct platform_driver rkcif_plat_drv;

View File

@@ -110,8 +110,8 @@ int spi_read_slt(int id, void *rxbuf, size_t n)
return ret;
}
int spi_write_then_read_slt(int id, const void *txbuf, unsigned n_tx,
void *rxbuf, unsigned n_rx)
int spi_write_then_read_slt(int id, const void *txbuf, unsigned int n_tx,
void *rxbuf, unsigned int n_rx)
{
int ret = -1;
struct spi_device *spi = NULL;
@@ -301,14 +301,21 @@ static ssize_t spi_test_write(struct file *file,
kfree(txbuf);
kfree(rxbuf);
} else if (!strcmp(cmd, "config")) {
int width;
int width, mode;
sscanf(argv[0], "%d", &width);
sscanf(argv[0], "%d", &id);
sscanf(argv[1], "%d", &width);
sscanf(argv[2], "mode=0x%x", &mode);
if (width == 16)
bit_per_word = 16;
else
bit_per_word = 8;
if (mode) {
g_spi_test_data[id]->spi->mode = mode;
spi_setup(g_spi_test_data[id]->spi);
}
} else {
printk("echo id number size > /dev/spi_misc_test\n");
printk("echo write 0 10 255 > /dev/spi_misc_test\n");
@@ -316,7 +323,7 @@ static ssize_t spi_test_write(struct file *file,
printk("echo read 0 10 255 > /dev/spi_misc_test\n");
printk("echo loop 0 10 255 > /dev/spi_misc_test\n");
printk("echo setspeed 0 1000000 > /dev/spi_misc_test\n");
printk("echo config 8 > /dev/spi_misc_test\n");
printk("echo config 0 8 mode=0xb > /dev/spi_misc_test\n");
}
return n;