From 1543e317f1da31b75942316931e8f491a8920811 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Thu, 04 Jan 2024 10:08:02 +0000
Subject: [PATCH] disable FB
---
kernel/drivers/media/i2c/sc401ai.c | 144 +++++++++++++++++++++++++++++++++++------------
1 files changed, 107 insertions(+), 37 deletions(-)
diff --git a/kernel/drivers/media/i2c/sc401ai.c b/kernel/drivers/media/i2c/sc401ai.c
index 1c0bfbe..0eac2d3 100644
--- a/kernel/drivers/media/i2c/sc401ai.c
+++ b/kernel/drivers/media/i2c/sc401ai.c
@@ -9,6 +9,7 @@
* V0.0X01.0X03 fix gain range.
* V0.0X01.0X04 add enum_frame_interval function.
* V0.0X01.0X05 add quick stream on/off
+ * V0.0X01.0X06 support thunder boot function.
*/
#include <linux/clk.h>
@@ -31,8 +32,9 @@
#include <media/v4l2-ctrls.h>
#include <media/v4l2-subdev.h>
#include <linux/pinctrl/consumer.h>
+#include "../platform/rockchip/isp/rkisp_tb_helper.h"
-#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x05)
+#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x06)
#ifndef V4L2_CID_DIGITAL_GAIN
#define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN
@@ -120,14 +122,6 @@
#define SC401AI_NUM_SUPPLIES ARRAY_SIZE(sc401ai_supply_names)
-enum sc401ai_max_pad {
- PAD0, /* link to isp */
- PAD1, /* link to csi wr0 | hdr x2:L x3:M */
- PAD2, /* link to csi wr1 | hdr x3:L */
- PAD3, /* link to csi wr2 | hdr x2:M x3:S */
- PAD_MAX,
-};
-
struct regval {
u16 addr;
u8 val;
@@ -170,6 +164,7 @@
struct v4l2_ctrl *pixel_rate;
struct v4l2_ctrl *link_freq;
struct mutex mutex;
+ struct v4l2_fract cur_fps;
bool streaming;
bool power_on;
unsigned int lane_num;
@@ -180,6 +175,8 @@
const char *module_name;
const char *len_name;
u32 cur_vts;
+ bool is_thunderboot;
+ bool is_first_streamoff;
struct preisp_hdrae_exp_s init_hdrae_exp;
};
@@ -454,6 +451,8 @@
SC401AI_LINK_FREQ_630,
};
+static int __sc401ai_power_on(struct sc401ai *sc401ai);
+
/* Write registers up to 4 at a time */
static int sc401ai_write_reg(struct i2c_client *client, u16 reg,
u32 len, u32 val)
@@ -631,6 +630,11 @@
DIG_Fine_gain_reg = abs(800 * gain / (Dcg_gainx100 * Coarse_gain *
DIG_gain) / ANA_Fine_gainx64);
+ if (sc401ai->is_thunderboot && rkisp_tb_get_state() == RKISP_TB_NG) {
+ sc401ai->is_thunderboot = false;
+ __sc401ai_power_on(sc401ai);
+ }
+
ret = sc401ai_write_reg(sc401ai->client,
SC401AI_REG_DIG_GAIN,
SC401AI_REG_VALUE_08BIT,
@@ -709,6 +713,8 @@
__v4l2_ctrl_modify_range(sc401ai->vblank, vblank_def,
SC401AI_VTS_MAX - mode->height,
1, vblank_def);
+ sc401ai->cur_fps = mode->max_fps;
+ sc401ai->cur_vts = mode->vts_def;
}
mutex_unlock(&sc401ai->mutex);
@@ -800,15 +806,17 @@
struct sc401ai *sc401ai = to_sc401ai(sd);
const struct sc401ai_mode *mode = sc401ai->cur_mode;
- mutex_lock(&sc401ai->mutex);
- fi->interval = mode->max_fps;
- mutex_unlock(&sc401ai->mutex);
+ if (sc401ai->streaming)
+ fi->interval = sc401ai->cur_fps;
+ else
+ fi->interval = mode->max_fps;
return 0;
}
static int sc401ai_g_mbus_config(struct v4l2_subdev *sd,
- struct v4l2_mbus_config *config)
+ unsigned int pad_id,
+ struct v4l2_mbus_config *config)
{
struct sc401ai *sc401ai = to_sc401ai(sd);
const struct sc401ai_mode *mode = sc401ai->cur_mode;
@@ -823,7 +831,7 @@
if (mode->hdr_mode == HDR_X3)
val |= V4L2_MBUS_CSI2_CHANNEL_2;
- config->type = V4L2_MBUS_CSI2;
+ config->type = V4L2_MBUS_CSI2_DPHY;
config->flags = val;
return 0;
@@ -833,10 +841,10 @@
struct rkmodule_inf *inf)
{
memset(inf, 0, sizeof(*inf));
- strlcpy(inf->base.sensor, SC401AI_NAME, sizeof(inf->base.sensor));
- strlcpy(inf->base.module, sc401ai->module_name,
+ strscpy(inf->base.sensor, SC401AI_NAME, sizeof(inf->base.sensor));
+ strscpy(inf->base.module, sc401ai->module_name,
sizeof(inf->base.module));
- strlcpy(inf->base.lens, sc401ai->len_name, sizeof(inf->base.lens));
+ strscpy(inf->base.lens, sc401ai->len_name, sizeof(inf->base.lens));
}
static long sc401ai_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
@@ -992,23 +1000,31 @@
{
int ret;
- ret = sc401ai_write_array(sc401ai->client, sc401ai->cur_mode->reg_list);
- if (ret)
- return ret;
+ if (!sc401ai->is_thunderboot) {
+ ret = sc401ai_write_array(sc401ai->client, sc401ai->cur_mode->reg_list);
+ if (ret)
+ return ret;
- /* In case these controls are set before streaming */
- ret = __v4l2_ctrl_handler_setup(&sc401ai->ctrl_handler);
- if (ret)
- return ret;
+ /* In case these controls are set before streaming */
+ ret = __v4l2_ctrl_handler_setup(&sc401ai->ctrl_handler);
+ if (ret)
+ return ret;
+ }
return sc401ai_write_reg(sc401ai->client,
- SC401AI_REG_CTRL_MODE,
- SC401AI_REG_VALUE_08BIT,
- SC401AI_MODE_STREAMING);
+ SC401AI_REG_CTRL_MODE,
+ SC401AI_REG_VALUE_08BIT,
+ SC401AI_MODE_STREAMING);
+
}
static int __sc401ai_stop_stream(struct sc401ai *sc401ai)
{
+ if (sc401ai->is_thunderboot) {
+ sc401ai->is_first_streamoff = true;
+ pm_runtime_put(&sc401ai->client->dev);
+ }
+
return sc401ai_write_reg(sc401ai->client,
SC401AI_REG_CTRL_MODE,
SC401AI_REG_VALUE_08BIT,
@@ -1027,6 +1043,10 @@
goto unlock_and_return;
if (on) {
+ if (sc401ai->is_thunderboot && rkisp_tb_get_state() == RKISP_TB_NG) {
+ sc401ai->is_thunderboot = false;
+ __sc401ai_power_on(sc401ai);
+ }
ret = pm_runtime_get_sync(&client->dev);
if (ret < 0) {
pm_runtime_put_noidle(&client->dev);
@@ -1118,6 +1138,10 @@
dev_err(dev, "Failed to enable xvclk\n");
return ret;
}
+
+ if (sc401ai->is_thunderboot)
+ return 0;
+
if (!IS_ERR(sc401ai->reset_gpio))
gpiod_set_value_cansleep(sc401ai->reset_gpio, 0);
@@ -1155,6 +1179,15 @@
{
int ret;
struct device *dev = &sc401ai->client->dev;
+
+ if (sc401ai->is_thunderboot) {
+ if (sc401ai->is_first_streamoff) {
+ sc401ai->is_thunderboot = false;
+ sc401ai->is_first_streamoff = false;
+ } else {
+ return;
+ }
+ }
if (!IS_ERR(sc401ai->pwdn_gpio))
gpiod_set_value_cansleep(sc401ai->pwdn_gpio, 0);
@@ -1249,7 +1282,6 @@
static const struct v4l2_subdev_video_ops sc401ai_video_ops = {
.s_stream = sc401ai_s_stream,
.g_frame_interval = sc401ai_g_frame_interval,
- .g_mbus_config = sc401ai_g_mbus_config,
};
static const struct v4l2_subdev_pad_ops sc401ai_pad_ops = {
@@ -1258,6 +1290,7 @@
.enum_frame_interval = sc401ai_enum_frame_interval,
.get_fmt = sc401ai_get_fmt,
.set_fmt = sc401ai_set_fmt,
+ .get_mbus_config = sc401ai_g_mbus_config,
};
static const struct v4l2_subdev_ops sc401ai_subdev_ops = {
@@ -1265,6 +1298,14 @@
.video = &sc401ai_video_ops,
.pad = &sc401ai_pad_ops,
};
+
+static void sc401ai_modify_fps_info(struct sc401ai *sc401ai)
+{
+ const struct sc401ai_mode *mode = sc401ai->cur_mode;
+
+ sc401ai->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def /
+ sc401ai->cur_vts;
+}
static int sc401ai_set_ctrl(struct v4l2_ctrl *ctrl)
{
@@ -1324,7 +1365,9 @@
SC401AI_REG_VALUE_08BIT,
(ctrl->val + sc401ai->cur_mode->height)
& 0xff);
- sc401ai->cur_vts = ctrl->val + sc401ai->cur_mode->height;
+ if (!ret)
+ sc401ai->cur_vts = ctrl->val + sc401ai->cur_mode->height;
+ sc401ai_modify_fps_info(sc401ai);
break;
case V4L2_CID_TEST_PATTERN:
ret = sc401ai_enable_test_pattern(sc401ai, ctrl->val);
@@ -1466,6 +1509,8 @@
}
sc401ai->subdev.ctrl_handler = handler;
+ sc401ai->cur_fps = mode->max_fps;
+ sc401ai->cur_vts = mode->vts_def;
return 0;
@@ -1481,6 +1526,11 @@
struct device *dev = &sc401ai->client->dev;
u32 id = 0;
int ret;
+
+ if (sc401ai->is_thunderboot) {
+ dev_info(dev, "Enable thunderboot mode, skip sensor id check\n");
+ return 0;
+ }
ret = sc401ai_read_reg(client, SC401AI_REG_CHIP_ID,
SC401AI_REG_VALUE_16BIT, &id);
@@ -1540,6 +1590,8 @@
return -EINVAL;
}
+ sc401ai->is_thunderboot = IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP);
+
sc401ai->client = client;
for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
if (hdr_mode == supported_modes[i].hdr_mode) {
@@ -1556,13 +1608,23 @@
return -EINVAL;
}
- sc401ai->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
- if (IS_ERR(sc401ai->reset_gpio))
- dev_warn(dev, "Failed to get reset-gpios\n");
+ if (sc401ai->is_thunderboot) {
+ sc401ai->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_ASIS);
+ if (IS_ERR(sc401ai->reset_gpio))
+ dev_warn(dev, "Failed to get reset-gpios\n");
- sc401ai->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW);
- if (IS_ERR(sc401ai->pwdn_gpio))
- dev_warn(dev, "Failed to get pwdn-gpios\n");
+ sc401ai->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_ASIS);
+ if (IS_ERR(sc401ai->pwdn_gpio))
+ dev_warn(dev, "Failed to get pwdn-gpios\n");
+ } else {
+ sc401ai->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(sc401ai->reset_gpio))
+ dev_warn(dev, "Failed to get reset-gpios\n");
+
+ sc401ai->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW);
+ if (IS_ERR(sc401ai->pwdn_gpio))
+ dev_warn(dev, "Failed to get pwdn-gpios\n");
+ }
sc401ai->pinctrl = devm_pinctrl_get(dev);
if (!IS_ERR(sc401ai->pinctrl)) {
@@ -1637,7 +1699,10 @@
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
- pm_runtime_idle(dev);
+ if (sc401ai->is_thunderboot)
+ pm_runtime_get_sync(dev);
+ else
+ pm_runtime_idle(dev);
return 0;
@@ -1709,8 +1774,13 @@
i2c_del_driver(&sc401ai_i2c_driver);
}
+#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC)
+subsys_initcall(sensor_mod_init);
+#else
device_initcall_sync(sensor_mod_init);
+#endif
+
module_exit(sensor_mod_exit);
MODULE_DESCRIPTION("smartsens sc401ai sensor driver");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
--
Gitblit v1.6.2