From 2f7c68cb55ecb7331f2381deb497c27155f32faf Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Wed, 03 Jan 2024 09:43:39 +0000
Subject: [PATCH] update kernel to 5.10.198
---
kernel/drivers/media/i2c/sc132gs.c | 294 ++++++++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 252 insertions(+), 42 deletions(-)
diff --git a/kernel/drivers/media/i2c/sc132gs.c b/kernel/drivers/media/i2c/sc132gs.c
index 5576d36..a8f0a50 100644
--- a/kernel/drivers/media/i2c/sc132gs.c
+++ b/kernel/drivers/media/i2c/sc132gs.c
@@ -8,6 +8,8 @@
* V0.0X01.0X03 add enum_frame_interval function.
* V0.0X01.0X04 add quick stream on/off
* V0.0X01.0X05 add function g_mbus_config
+ * V0.0X01.0X06 add function reset gpio control
+ * V0.0X01.0X06 add 2-lane mode as default
*/
#include <linux/clk.h>
@@ -28,12 +30,17 @@
#include <media/v4l2-subdev.h>
#include <linux/pinctrl/consumer.h>
-#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x05)
+#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x07)
#ifndef V4L2_CID_DIGITAL_GAIN
#define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN
#endif
-#define SC132GS_PIXEL_RATE (72 * 1000 * 1000)
+#define MIPI_FREQ_180M 180000000
+#define MIPI_FREQ_360M 360000000
+
+#define PIXEL_RATE_WITH_180M (MIPI_FREQ_180M * 2 / 10 * 2)
+#define PIXEL_RATE_WITH_360M (MIPI_FREQ_360M * 2 / 8 * 1)
+
#define SC132GS_XVCLK_FREQ 24000000
#define CHIP_ID 0x0132
@@ -69,13 +76,8 @@
#define SC132GS_NAME "sc132gs"
-#define PIX_FORMAT MEDIA_BUS_FMT_Y8_1X8
-
#define OF_CAMERA_PINCTRL_STATE_DEFAULT "rockchip,camera_default"
#define OF_CAMERA_PINCTRL_STATE_SLEEP "rockchip,camera_sleep"
-
-#define SC132GS_LANES 1
-#define SC132GS_BITS_PER_SAMPLE 8
static const char * const sc132gs_supply_names[] = {
"avdd", /* Analog power */
@@ -84,6 +86,11 @@
};
#define SC132GS_NUM_SUPPLIES ARRAY_SIZE(sc132gs_supply_names)
+
+enum {
+ LINK_FREQ_180M_INDEX,
+ LINK_FREQ_360M_INDEX,
+};
struct regval {
u16 addr;
@@ -97,12 +104,17 @@
u32 hts_def;
u32 vts_def;
u32 exp_def;
+ u32 link_freq_index;
+ u64 pixel_rate;
const struct regval *reg_list;
+ u32 lanes;
+ u32 bus_fmt;
};
struct sc132gs {
struct i2c_client *client;
struct clk *xvclk;
+ struct gpio_desc *reset_gpio;
struct gpio_desc *pwdn_gpio;
struct regulator_bulk_data supplies[SC132GS_NUM_SUPPLIES];
struct pinctrl *pinctrl;
@@ -117,7 +129,11 @@
struct v4l2_ctrl *hblank;
struct v4l2_ctrl *vblank;
struct v4l2_ctrl *test_pattern;
+ struct v4l2_ctrl *pixel_rate;
+ struct v4l2_ctrl *link_freq;
struct mutex mutex;
+ struct v4l2_fract cur_fps;
+ u32 cur_vts;
bool streaming;
bool power_on;
const struct sc132gs_mode *cur_mode;
@@ -131,7 +147,7 @@
/*
* Xclk 24Mhz
- * Pclk 72Mhz
+ * Pclk 90Mhz
* linelength 1696(0x06a0)
* framelength 2122(0x084a)
* grabwindow_width 1080
@@ -140,7 +156,7 @@
* max_framerate 30fps
* mipi_datarate per lane 720Mbps
*/
-static const struct regval sc132gs_global_regs[] = {
+static const struct regval sc132gs_1lane_8bit_regs[] = {
{0x0103, 0x01},
{0x0100, 0x00},
@@ -247,6 +263,130 @@
{REG_NULL, 0x00},
};
+/*
+ * Xclk 24Mhz
+ * Pclk 72Mhz
+ * linelength 1696(0x06a0)
+ * framelength 2122(0x084a)
+ * grabwindow_width 1080
+ * grabwindow_height 1280
+ * mipi 2 lane
+ * max_framerate 30fps
+ * mipi_datarate per lane 360Mbps
+ */
+static const struct regval sc132gs_2lane_10bit_regs[] = {
+ {0x0103, 0x01},
+ {0x0100, 0x00},
+
+ //PLL bypass
+ {0x36e9, 0x80},
+ {0x36f9, 0x80},
+
+ {0x3018, 0x32},
+ {0x3019, 0x0c},
+ {0x301a, 0xb4},
+ {0x3031, 0x0a},
+ {0x3032, 0x60},
+ {0x3038, 0x44},
+ {0x3207, 0x17},
+ {0x320c, 0x05},
+ {0x320d, 0xdc},
+ {0x320e, 0x09},
+ {0x320f, 0x60},
+ {0x3250, 0xcc},
+ {0x3251, 0x02},
+ {0x3252, 0x09},
+ {0x3253, 0x5b},
+ {0x3254, 0x05},
+ {0x3255, 0x3b},
+ {0x3306, 0x78},
+ {0x330a, 0x00},
+ {0x330b, 0xc8},
+ {0x330f, 0x24},
+ {0x3314, 0x80},
+ {0x3315, 0x40},
+ {0x3317, 0xf0},
+ {0x331f, 0x12},
+ {0x3364, 0x00},
+ {0x3385, 0x41},
+ {0x3387, 0x41},
+ {0x3389, 0x09},
+ {0x33ab, 0x00},
+ {0x33ac, 0x00},
+ {0x33b1, 0x03},
+ {0x33b2, 0x12},
+ {0x33f8, 0x02},
+ {0x33fa, 0x01},
+ {0x3409, 0x08},
+ {0x34f0, 0xc0},
+ {0x34f1, 0x20},
+ {0x34f2, 0x03},
+ {0x3622, 0xf5},
+ {0x3630, 0x5c},
+ {0x3631, 0x80},
+ {0x3632, 0xc8},
+ {0x3633, 0x32},
+ {0x3638, 0x2a},
+ {0x3639, 0x07},
+ {0x363b, 0x48},
+ {0x363c, 0x83},
+ {0x363d, 0x10},
+ {0x36ea, 0x38},
+ {0x36fa, 0x25},
+ {0x36fb, 0x05},
+ {0x36fd, 0x04},
+ {0x3900, 0x11},
+ {0x3901, 0x05},
+ {0x3902, 0xc5},
+ {0x3904, 0x04},
+ {0x3908, 0x91},
+ {0x391e, 0x00},
+ {0x3e01, 0x11},
+ {0x3e02, 0x20},
+ {0x3e09, 0x20},
+ {0x3e0e, 0xd2},
+ {0x3e14, 0xb0},
+ {0x3e1e, 0x7c},
+ {0x3e26, 0x20},
+ {0x4418, 0x38},
+ {0x4503, 0x10},
+ {0x4837, 0x21},
+ {0x5000, 0x0e},
+ {0x540c, 0x51},
+ {0x550f, 0x38},
+ {0x5780, 0x67},
+ {0x5784, 0x10},
+ {0x5785, 0x06},
+ {0x5787, 0x02},
+ {0x5788, 0x00},
+ {0x5789, 0x00},
+ {0x578a, 0x02},
+ {0x578b, 0x00},
+ {0x578c, 0x00},
+ {0x5790, 0x00},
+ {0x5791, 0x00},
+ {0x5792, 0x00},
+ {0x5793, 0x00},
+ {0x5794, 0x00},
+ {0x5795, 0x00},
+ {0x5799, 0x04},
+
+ //flip
+ //{0x3221, (0x3 << 5)},
+
+ //mirror
+ {0x3221, (0x3 << 1)},
+
+ //flip & mirror
+ //{0x3221, ((0x3 << 1)|(0x3 << 5))},
+
+ //PLL set
+ {0x36e9, 0x20},
+ {0x36f9, 0x24},
+
+ {REG_NULL, 0x00},
+};
+
static const struct sc132gs_mode supported_modes[] = {
{
.width = 1080,
@@ -258,7 +398,28 @@
.exp_def = 0x0148,
.hts_def = 0x06a0,
.vts_def = 0x084a,
- .reg_list = sc132gs_global_regs,
+ .link_freq_index = LINK_FREQ_180M_INDEX,
+ .pixel_rate = PIXEL_RATE_WITH_180M,
+ .reg_list = sc132gs_2lane_10bit_regs,
+ .lanes = 2,
+ .bus_fmt = MEDIA_BUS_FMT_Y10_1X10,
+ },
+
+ {
+ .width = 1080,
+ .height = 1280,
+ .max_fps = {
+ .numerator = 10000,
+ .denominator = 300000,
+ },
+ .exp_def = 0x0148,
+ .hts_def = 0x06a0,
+ .vts_def = 0x084a,
+ .link_freq_index = LINK_FREQ_360M_INDEX,
+ .pixel_rate = PIXEL_RATE_WITH_360M,
+ .reg_list = sc132gs_1lane_8bit_regs,
+ .lanes = 1,
+ .bus_fmt = MEDIA_BUS_FMT_Y8_1X8,
},
};
@@ -270,10 +431,9 @@
"Vertical Color Bar Type 4"
};
-#define SC132GS_LINK_FREQ_360MHZ (360 * 1000 * 1000)
-
static const s64 link_freq_menu_items[] = {
- SC132GS_LINK_FREQ_360MHZ
+ MIPI_FREQ_180M,
+ MIPI_FREQ_360M,
};
/* Write registers up to 4 at a time */
@@ -374,7 +534,8 @@
for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
dist = sc132gs_get_reso_dist(&supported_modes[i], framefmt);
- if (cur_best_fit_dist == -1 || dist < cur_best_fit_dist) {
+ if ((cur_best_fit_dist == -1 || dist < cur_best_fit_dist) &&
+ (supported_modes[i].bus_fmt == framefmt->code)) {
cur_best_fit_dist = dist;
cur_best_fit = i;
}
@@ -393,7 +554,7 @@
mutex_lock(&sc132gs->mutex);
mode = sc132gs_find_best_fit(fmt);
- fmt->format.code = PIX_FORMAT;
+ fmt->format.code = mode->bus_fmt;
fmt->format.width = mode->width;
fmt->format.height = mode->height;
fmt->format.field = V4L2_FIELD_NONE;
@@ -413,6 +574,10 @@
__v4l2_ctrl_modify_range(sc132gs->vblank, vblank_def,
SC132GS_VTS_MAX - mode->height,
1, vblank_def);
+ __v4l2_ctrl_s_ctrl_int64(sc132gs->pixel_rate, mode->pixel_rate);
+ __v4l2_ctrl_s_ctrl(sc132gs->link_freq, mode->link_freq_index);
+ sc132gs->cur_fps = mode->max_fps;
+ sc132gs->cur_vts = mode->vts_def;
}
mutex_unlock(&sc132gs->mutex);
@@ -438,7 +603,7 @@
} else {
fmt->format.width = mode->width;
fmt->format.height = mode->height;
- fmt->format.code = PIX_FORMAT;
+ fmt->format.code = mode->bus_fmt;
fmt->format.field = V4L2_FIELD_NONE;
}
mutex_unlock(&sc132gs->mutex);
@@ -450,9 +615,11 @@
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_mbus_code_enum *code)
{
+ struct sc132gs *sc132gs = to_sc132gs(sd);
+
if (code->index != 0)
return -EINVAL;
- code->code = PIX_FORMAT;
+ code->code = sc132gs->cur_mode->bus_fmt;
return 0;
}
@@ -464,7 +631,7 @@
if (fse->index >= ARRAY_SIZE(supported_modes))
return -EINVAL;
- if (fse->code != PIX_FORMAT)
+ if (fse->code != supported_modes[fse->index].bus_fmt)
return -EINVAL;
fse->min_width = supported_modes[fse->index].width;
@@ -533,7 +700,7 @@
{
void __user *up = compat_ptr(arg);
struct rkmodule_inf *inf;
- long ret;
+ long ret = 0;
u32 stream = 0;
switch (cmd) {
@@ -545,14 +712,18 @@
}
ret = sc132gs_ioctl(sd, cmd, inf);
- if (!ret)
+ if (!ret) {
ret = copy_to_user(up, inf, sizeof(*inf));
+ if (ret)
+ ret = -EFAULT;
+ }
kfree(inf);
break;
case RKMODULE_SET_QUICK_STREAM:
- ret = copy_from_user(&stream, up, sizeof(u32));
- if (!ret)
- ret = sc132gs_ioctl(sd, cmd, &stream);
+ if (copy_from_user(&stream, up, sizeof(u32)))
+ return -EFAULT;
+
+ ret = sc132gs_ioctl(sd, cmd, &stream);
break;
default:
ret = -ENOIOCTLCMD;
@@ -649,12 +820,21 @@
{
struct sc132gs *sc132gs = to_sc132gs(sd);
struct i2c_client *client = sc132gs->client;
+ unsigned int fps;
int ret = 0;
mutex_lock(&sc132gs->mutex);
on = !!on;
if (on == sc132gs->streaming)
goto unlock_and_return;
+
+ fps = DIV_ROUND_CLOSEST(sc132gs->cur_mode->max_fps.denominator,
+ sc132gs->cur_mode->max_fps.numerator);
+
+ dev_info(&sc132gs->client->dev, "%s: on: %d, %dx%d@%d\n", __func__, on,
+ sc132gs->cur_mode->width,
+ sc132gs->cur_mode->height,
+ fps);
if (on) {
ret = pm_runtime_get_sync(&client->dev);
@@ -718,9 +898,10 @@
struct sc132gs *sc132gs = to_sc132gs(sd);
const struct sc132gs_mode *mode = sc132gs->cur_mode;
- mutex_lock(&sc132gs->mutex);
- fi->interval = mode->max_fps;
- mutex_unlock(&sc132gs->mutex);
+ if (sc132gs->streaming)
+ fi->interval = sc132gs->cur_fps;
+ else
+ fi->interval = mode->max_fps;
return 0;
}
@@ -761,8 +942,16 @@
goto disable_clk;
}
+ if (!IS_ERR(sc132gs->reset_gpio))
+ gpiod_set_value_cansleep(sc132gs->reset_gpio, 1);
+
+ usleep_range(1000, 2000);
+
if (!IS_ERR(sc132gs->pwdn_gpio))
gpiod_set_value_cansleep(sc132gs->pwdn_gpio, 1);
+
+ if (!IS_ERR(sc132gs->reset_gpio))
+ gpiod_set_value_cansleep(sc132gs->reset_gpio, 0);
/* 8192 cycles prior to first SCCB transaction */
delay_us = sc132gs_cal_delay(8192);
@@ -779,6 +968,9 @@
static void __sc132gs_power_off(struct sc132gs *sc132gs)
{
int ret;
+
+ if (!IS_ERR(sc132gs->reset_gpio))
+ gpiod_set_value_cansleep(sc132gs->reset_gpio, 1);
if (!IS_ERR(sc132gs->pwdn_gpio))
gpiod_set_value_cansleep(sc132gs->pwdn_gpio, 0);
@@ -824,7 +1016,7 @@
/* Initialize try_fmt */
try_fmt->width = def_mode->width;
try_fmt->height = def_mode->height;
- try_fmt->code = PIX_FORMAT;
+ try_fmt->code = def_mode->bus_fmt;
try_fmt->field = V4L2_FIELD_NONE;
mutex_unlock(&sc132gs->mutex);
@@ -841,24 +1033,23 @@
if (fie->index >= ARRAY_SIZE(supported_modes))
return -EINVAL;
- if (fie->code != PIX_FORMAT)
- return -EINVAL;
-
+ fie->code = supported_modes[fie->index].bus_fmt;
fie->width = supported_modes[fie->index].width;
fie->height = supported_modes[fie->index].height;
fie->interval = supported_modes[fie->index].max_fps;
return 0;
}
-static int sc132gs_g_mbus_config(struct v4l2_subdev *sd,
+static int sc132gs_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id,
struct v4l2_mbus_config *config)
{
u32 val = 0;
+ struct sc132gs *sc132gs = to_sc132gs(sd);
- val = 1 << (SC132GS_LANES - 1) |
+ val = 1 << (sc132gs->cur_mode->lanes - 1) |
V4L2_MBUS_CSI2_CHANNEL_0 |
V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
- config->type = V4L2_MBUS_CSI2;
+ config->type = V4L2_MBUS_CSI2_DPHY;
config->flags = val;
return 0;
@@ -886,7 +1077,6 @@
static const struct v4l2_subdev_video_ops sc132gs_video_ops = {
.s_stream = sc132gs_s_stream,
.g_frame_interval = sc132gs_g_frame_interval,
- .g_mbus_config = sc132gs_g_mbus_config,
};
static const struct v4l2_subdev_pad_ops sc132gs_pad_ops = {
@@ -895,6 +1085,7 @@
.enum_frame_interval = sc132gs_enum_frame_interval,
.get_fmt = sc132gs_get_fmt,
.set_fmt = sc132gs_set_fmt,
+ .get_mbus_config = sc132gs_g_mbus_config,
};
static const struct v4l2_subdev_ops sc132gs_subdev_ops = {
@@ -902,6 +1093,14 @@
.video = &sc132gs_video_ops,
.pad = &sc132gs_pad_ops,
};
+
+static void sc132gs_modify_fps_info(struct sc132gs *sc132gs)
+{
+ const struct sc132gs_mode *mode = sc132gs->cur_mode;
+
+ sc132gs->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def /
+ sc132gs->cur_vts;
+}
static int sc132gs_set_ctrl(struct v4l2_ctrl *ctrl)
{
@@ -939,6 +1138,10 @@
ret = sc132gs_write_reg(sc132gs->client, SC132GS_REG_VTS,
SC132GS_REG_VALUE_16BIT,
ctrl->val + sc132gs->cur_mode->height);
+ if (!ret)
+ sc132gs->cur_vts = ctrl->val + sc132gs->cur_mode->height;
+ sc132gs_modify_fps_info(sc132gs);
+ break;
break;
case V4L2_CID_TEST_PATTERN:
ret = sc132gs_enable_test_pattern(sc132gs, ctrl->val);
@@ -962,7 +1165,6 @@
{
const struct sc132gs_mode *mode;
struct v4l2_ctrl_handler *handler;
- struct v4l2_ctrl *ctrl;
s64 exposure_max, vblank_def;
u32 h_blank;
int ret;
@@ -974,13 +1176,16 @@
return ret;
handler->lock = &sc132gs->mutex;
- ctrl = v4l2_ctrl_new_int_menu(handler, NULL, V4L2_CID_LINK_FREQ,
- 0, 0, link_freq_menu_items);
- if (ctrl)
- ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+ sc132gs->link_freq = v4l2_ctrl_new_int_menu(handler, NULL, V4L2_CID_LINK_FREQ,
+ ARRAY_SIZE(link_freq_menu_items) - 1, 0,
+ link_freq_menu_items);
- v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE,
- 0, SC132GS_PIXEL_RATE, 1, SC132GS_PIXEL_RATE);
+ sc132gs->pixel_rate = v4l2_ctrl_new_std(handler, NULL,
+ V4L2_CID_PIXEL_RATE,
+ 0, PIXEL_RATE_WITH_360M,
+ 1, mode->pixel_rate);
+
+ __v4l2_ctrl_s_ctrl(sc132gs->link_freq, mode->pixel_rate);
h_blank = mode->hts_def - mode->width;
sc132gs->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK,
@@ -1016,7 +1221,8 @@
"Failed to init controls(%d)\n", ret);
goto err_free_handler;
}
-
+ sc132gs->cur_fps = mode->max_fps;
+ sc132gs->cur_vts = mode->vts_def;
sc132gs->subdev.ctrl_handler = handler;
return 0;
@@ -1098,6 +1304,10 @@
return -EINVAL;
}
+ sc132gs->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(sc132gs->reset_gpio))
+ dev_warn(dev, "Failed to get reset-gpios\n");
+
sc132gs->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW);
if (IS_ERR(sc132gs->pwdn_gpio))
dev_warn(dev, "Failed to get pwdn-gpios\n");
--
Gitblit v1.6.2