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/sc200ai.c | 213 +++++++++++++++++++++++++--------------------------- 1 files changed, 102 insertions(+), 111 deletions(-) diff --git a/kernel/drivers/media/i2c/sc200ai.c b/kernel/drivers/media/i2c/sc200ai.c index daa7e4e..44c7156 100644 --- a/kernel/drivers/media/i2c/sc200ai.c +++ b/kernel/drivers/media/i2c/sc200ai.c @@ -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> @@ -34,8 +37,10 @@ #include <media/v4l2-subdev.h> #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 @@ -179,6 +184,7 @@ 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) @@ -611,20 +617,6 @@ .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] = V4L2_MBUS_CSI2_CHANNEL_0, - }, { - .width = 1920, - .height = 1080, - .max_fps = { - .numerator = 10000, .denominator = 600000, }, .exp_def = 0x0080, @@ -634,7 +626,23 @@ .reg_list = sc200ai_linear_10_1920x1080_60fps_regs, .hdr_mode = NO_HDR, .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_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] = V4L2_MBUS_CSI2_CHANNEL_0, + }, + { .width = 1920, .height = 1080, .max_fps = { @@ -1215,17 +1223,23 @@ 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: stream = *((u32 *)arg); - if (stream) + if (stream) { + gpiod_set_value_cansleep(sc200ai->pwdn_gpio, 1); ret = sc200ai_write_reg(sc200ai->client, SC200AI_REG_CTRL_MODE, SC200AI_REG_VALUE_08BIT, SC200AI_MODE_STREAMING); - else + } else { ret = sc200ai_write_reg(sc200ai->client, SC200AI_REG_CTRL_MODE, SC200AI_REG_VALUE_08BIT, SC200AI_MODE_SW_STANDBY); + gpiod_set_value_cansleep(sc200ai->pwdn_gpio, 0); + } break; case RKMODULE_GET_CHANNEL_INFO: ch_info = (struct rkmodule_channel_info *)arg; @@ -1512,6 +1526,9 @@ 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; @@ -1576,6 +1593,51 @@ 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); @@ -1636,6 +1698,7 @@ 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 @@ -1889,109 +1952,28 @@ } #ifdef CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP -static u32 rk_cam_hdr; -static u32 rk_cam_w; -static u32 rk_cam_h; -static u32 rk_cam_fps; - -static int __init __maybe_unused rk_cam_hdr_setup(char *str) -{ - int ret = 0; - unsigned long val = 0; - - ret = kstrtoul(str, 0, &val); - if (!ret) - rk_cam_hdr = (u32)val; - else - pr_err("get rk_cam_hdr fail\n"); - return 1; -} - -static int __init __maybe_unused rk_cam_w_setup(char *str) -{ - int ret = 0; - unsigned long val = 0; - - ret = kstrtoul(str, 0, &val); - if (!ret) - rk_cam_w = (u32)val; - else - pr_err("get rk_cam_w fail\n"); - return 1; -} - -static int __init __maybe_unused rk_cam_h_setup(char *str) -{ - int ret = 0; - unsigned long val = 0; - - ret = kstrtoul(str, 0, &val); - if (!ret) - rk_cam_h = (u32)val; - else - pr_err("get rk_cam_h fail\n"); - return 1; -} - -static int __init __maybe_unused rk_cam_fps_setup(char *str) -{ - int ret = 0; - unsigned long val = 0; - - ret = kstrtoul(str, 0, &val); - if (!ret) - rk_cam_fps = (u32)val; - else - pr_err("get rk_cam_fps fail\n"); - return 1; -} - -__setup("rk_cam_hdr=", rk_cam_hdr_setup); -__setup("rk_cam_w=", rk_cam_w_setup); -__setup("rk_cam_h=", rk_cam_h_setup); -__setup("rk_cam_fps=", rk_cam_fps_setup); - static void find_terminal_resolution(struct sc200ai *sc200ai) { int i = 0; const struct sc200ai_mode *mode = NULL; - const struct sc200ai_mode *fit_mode = NULL; - u32 cur_fps = 0; - u32 dst_fps = 0; - u32 tmp_fps = 0; + u32 rk_cam_hdr = get_rk_cam_hdr(); + u32 rk_cam_w = get_rk_cam_w(); + u32 rk_cam_h = get_rk_cam_h(); - if (rk_cam_w == 0 || rk_cam_h == 0 || - rk_cam_fps == 0) + if (rk_cam_w == 0 || rk_cam_h == 0) goto err_find_res; - dst_fps = rk_cam_fps; for (i = 0; i < ARRAY_SIZE(supported_modes); i++) { mode = &supported_modes[i]; - cur_fps = mode->max_fps.denominator / mode->max_fps.numerator; if (mode->width == rk_cam_w && mode->height == rk_cam_h && mode->hdr_mode == rk_cam_hdr) { - if (cur_fps == dst_fps) { - sc200ai->cur_mode = mode; - return; - } - if (cur_fps >= dst_fps) { - if (fit_mode) { - tmp_fps = fit_mode->max_fps.denominator / fit_mode->max_fps.numerator; - if (tmp_fps - dst_fps > cur_fps - dst_fps) - fit_mode = mode; - } else { - fit_mode = mode; - } - } + sc200ai->cur_mode = mode; + return; } } - if (fit_mode) { - sc200ai->cur_mode = fit_mode; - return; - } err_find_res: - dev_err(&sc200ai->client->dev, "not match %dx%d@%dfps mode %d\n!", - rk_cam_w, rk_cam_h, dst_fps, rk_cam_hdr); + dev_err(&sc200ai->client->dev, "not match %dx%d mode %d\n!", + rk_cam_w, rk_cam_h, rk_cam_hdr); sc200ai->cur_mode = &supported_modes[0]; } #else @@ -2057,11 +2039,11 @@ return -EINVAL; } - sc200ai->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_ASIS); + sc200ai->reset_gpio = devm_gpiod_get(dev, "reset", sc200ai->is_thunderboot ? GPIOD_ASIS : GPIOD_OUT_LOW); if (IS_ERR(sc200ai->reset_gpio)) dev_warn(dev, "Failed to get reset-gpios\n"); - sc200ai->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_ASIS); + sc200ai->pwdn_gpio = devm_gpiod_get(dev, "pwdn", sc200ai->is_thunderboot ? GPIOD_ASIS : GPIOD_OUT_LOW); if (IS_ERR(sc200ai->pwdn_gpio)) dev_warn(dev, "Failed to get pwdn-gpios\n"); @@ -2117,6 +2099,13 @@ 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'; @@ -2167,6 +2156,8 @@ 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); -- Gitblit v1.6.2