mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
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:
@@ -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>;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
198
drivers/media/i2c/cam-sleep-wakeup.c
Normal file
198
drivers/media/i2c/cam-sleep-wakeup.c
Normal 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");
|
||||
131
drivers/media/i2c/cam-sleep-wakeup.h
Normal file
131
drivers/media/i2c/cam-sleep-wakeup.h
Normal 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
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user