diff --git a/drivers/media/i2c/os02g10.c b/drivers/media/i2c/os02g10.c index 743618cf18bc..60f7ba228951 100644 --- a/drivers/media/i2c/os02g10.c +++ b/drivers/media/i2c/os02g10.c @@ -5,6 +5,8 @@ * Copyright (C) 2020 Rockchip Electronics Co., Ltd. * * V0.0X01.0X00 first version. + * V0.0X01.0X01 update init setting. + * V0.0X01.0X02 fix set flip/mirror failed bug and fix wrong vts_def value. */ #include @@ -27,29 +29,36 @@ #include #include "../platform/rockchip/isp/rkisp_tb_helper.h" -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x00) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN #endif -#define MIPI_FREQ_360M 360000000 -#define PIXEL_RATE_WITH_360M (MIPI_FREQ_360M * 2 * 2 / 10) - -#define OS02G10_XVCLK_FREQ 24000000 - #define OS02G10_CHIP_ID 0x5602 #define OS02G10_REG_CHIP_ID_H 0x02 #define OS02G10_REG_CHIP_ID_L 0x03 -#define OS02G10_REG_PAGE_SELECT 0xFD +#define OS02G10_XVCLK_FREQ 24000000 +#define BITS_PER_SAMPLE 10 +#define MIPI_FREQ_360M 360000000 +#define OS02G10_LANES 2 +#define PIXEL_RATE_WITH_360M (MIPI_FREQ_360M * OS02G10_LANES * 2 / BITS_PER_SAMPLE) + +#define OS02G10_REG_PAGE_SELECT 0xfd #define OS02G10_REG_EXP_H 0x03 #define OS02G10_REG_EXP_L 0x04 +#define OS02G10_EXPOSURE_MIN 4 +#define OS02G10_EXPOSURE_STEP 1 #define OS02G10_REG_AGAIN 0x24 #define OS02G10_REG_DGAIN_H 0x37 #define OS02G10_REG_DGAIN_L 0x39 +#define OS02G10_GAIN_MIN 0x10 +#define OS02G10_GAIN_MAX 0x2000 +#define OS02G10_GAIN_STEP 1 +#define OS02G10_GAIN_DEFAULT 0x10 #define OS02G10_REG_HTS_H 0x41 #define OS02G10_REG_HTS_L 0x42 @@ -59,29 +68,21 @@ #define OS02G10_REG_VBLANK_H 0x05 #define OS02G10_REG_VBLANK_L 0x06 -#define OS02G10_VTS_MAX 0xFFFF +#define OS02G10_VTS_MAX 0xffff #define OS02G10_REG_RESTART 0x01 #define OS02G10_REG_CTRL_MODE 0xb1 #define OS02G10_MODE_SW_STANDBY 0x0 #define OS02G10_MODE_STREAMING 0x03 -#define OS02G10_REG_SOFTWARE_RESET 0xFC +#define OS02G10_REG_SOFTWARE_RESET 0xfc #define OS02G10_SOFTWARE_RESET_VAL 0x1 -#define OS02G10_GAIN_MIN 0x10 -#define OS02G10_GAIN_MAX 0x2000 -#define OS02G10_GAIN_STEP 1 -#define OS02G10_GAIN_DEFAULT 0x10 - -#define OS02G10_EXPOSURE_MIN 4 -#define OS02G10_EXPOSURE_STEP 1 - #define OS02G10_FLIP_REG 0x3f #define MIRROR_BIT_MASK BIT(0) #define FLIP_BIT_MASK BIT(1) +#define OS02G10_REG_BAYER_ORDER 0x5e -#define OS02G10_LANES 2 #define OS02G10_NAME "os02g10" #define OF_CAMERA_HDR_MODE "rockchip,camera-hdr-mode" @@ -89,7 +90,7 @@ #define OF_CAMERA_PINCTRL_STATE_SLEEP "rockchip,camera_sleep" #define REG_NULL 0xFF -#define REG_DELAY 0x00 + #define SENSOR_ID(_msb, _lsb) ((_msb) << 8 | (_lsb)) static const char * const OS02G10_supply_names[] = { @@ -132,11 +133,9 @@ struct os02g10 { struct gpio_desc *reset_gpio; struct gpio_desc *pwdn_gpio; struct regulator_bulk_data supplies[OS02G10_NUM_SUPPLIES]; - struct pinctrl *pinctrl; struct pinctrl_state *pins_default; struct pinctrl_state *pins_sleep; - struct v4l2_subdev subdev; struct media_pad pad; struct v4l2_ctrl_handler ctrl_handler; @@ -147,8 +146,6 @@ struct os02g10 { struct v4l2_ctrl *vblank; struct v4l2_ctrl *pixel_rate; struct v4l2_ctrl *link_freq; - struct v4l2_ctrl *h_flip; - struct v4l2_ctrl *v_flip; struct mutex mutex; bool streaming; bool power_on; @@ -165,15 +162,7 @@ struct os02g10 { #define to_os02g10(sd) container_of(sd, struct os02g10, subdev) -/* - * Xclk 24Mhz - */ static const struct regval os02g10_linear10bit_1920x1080_regs[] = { - {0xfd, 0x00}, - {0x36, 0x01}, - {0xfd, 0x00}, - {0x36, 0x00}, - {REG_DELAY, 0x05}, {0xfd, 0x00}, {0xfd, 0x00}, {0x30, 0x0a}, @@ -285,7 +274,6 @@ static const struct regval os02g10_linear10bit_1920x1080_regs[] = { {0x9c, 0x0e}, {0xb1, 0x01}, {0xfd, 0x01}, - //{0xb1, 0x03}, {REG_NULL, 0x00}, }; @@ -308,11 +296,11 @@ static const struct os02g10_mode supported_modes[] = { .height = 1080, .max_fps = { .numerator = 10000, - .denominator = 300000, + .denominator = 250000, }, .exp_def = 0x044c, .hts_def = 0x043a * 2, - .vts_def = 0x0533, + .vts_def = 0x0516, .reg_list = os02g10_linear10bit_1920x1080_regs, .hdr_mode = NO_HDR, .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0, @@ -323,11 +311,6 @@ static const s64 link_freq_menu_items[] = { MIPI_FREQ_360M, }; -static int __os02g10_power_on(struct os02g10 *os02g10); - -static int os02g10_check_sensor_id(struct os02g10 *os02g10, - struct i2c_client *client); - /* sensor register write */ static int os02g10_write_reg(struct i2c_client *client, u8 reg, u8 val) { @@ -344,11 +327,11 @@ static int os02g10_write_reg(struct i2c_client *client, u8 reg, u8 val) msg.len = sizeof(buf); ret = i2c_transfer(client->adapter, &msg, 1); + if (ret >= 0) return 0; - dev_err(&client->dev, - "os02g10 write reg(0x%x val:0x%x) failed !\n", reg, val); + dev_err(&client->dev, "write reg(0x%x val:0x%x) failed !\n", reg, val); return ret; } @@ -356,21 +339,14 @@ static int os02g10_write_reg(struct i2c_client *client, u8 reg, u8 val) static int os02g10_write_array(struct i2c_client *client, const struct regval *regs) { - int i, delay_us, ret = 0; + int i, ret = 0; i = 0; while (regs[i].addr != REG_NULL) { - if (regs[i].addr == REG_DELAY) { - if (regs[i].val) { - delay_us = regs[i].val * 1000; - usleep_range(delay_us, 2 * delay_us); - } - } else { - ret = os02g10_write_reg(client, regs[i].addr, regs[i].val); - if (ret) { - dev_err(&client->dev, "%s failed !\n", __func__); - break; - } + ret = os02g10_write_reg(client, regs[i].addr, regs[i].val); + if (ret) { + dev_err(&client->dev, "%s failed !\n", __func__); + break; } i++; } @@ -575,11 +551,6 @@ static int os02g10_g_mbus_config(struct v4l2_subdev *sd, val = 1 << (OS02G10_LANES - 1) | V4L2_MBUS_CSI2_CHANNEL_0 | V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; - if (mode->hdr_mode == HDR_X2) - val = 1 << (OS02G10_LANES - 1) | - V4L2_MBUS_CSI2_CHANNEL_0 | - V4L2_MBUS_CSI2_CONTINUOUS_CLOCK | - V4L2_MBUS_CSI2_CHANNEL_1; config->type = V4L2_MBUS_CSI2; config->flags = val; @@ -591,10 +562,10 @@ static void os02g10_get_module_inf(struct os02g10 *os02g10, struct rkmodule_inf *inf) { memset(inf, 0, sizeof(*inf)); - strlcpy(inf->base.sensor, OS02G10_NAME, sizeof(inf->base.sensor)); - strlcpy(inf->base.module, os02g10->module_name, + strscpy(inf->base.sensor, OS02G10_NAME, sizeof(inf->base.sensor)); + strscpy(inf->base.module, os02g10->module_name, sizeof(inf->base.module)); - strlcpy(inf->base.lens, os02g10->len_name, sizeof(inf->base.lens)); + strscpy(inf->base.lens, os02g10->len_name, sizeof(inf->base.lens)); } static long os02g10_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) @@ -605,24 +576,19 @@ static long os02g10_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) u32 stream = 0; switch (cmd) { - case PREISP_CMD_SET_HDRAE_EXP: - ret = -1; + case RKMODULE_GET_MODULE_INFO: + os02g10_get_module_inf(os02g10, (struct rkmodule_inf *)arg); break; case RKMODULE_SET_HDR_CFG: hdr_cfg = (struct rkmodule_hdr_cfg *)arg; if (hdr_cfg->hdr_mode != 0) ret = -1; break; - case RKMODULE_GET_MODULE_INFO: - os02g10_get_module_inf(os02g10, (struct rkmodule_inf *)arg); - break; case RKMODULE_GET_HDR_CFG: hdr_cfg = (struct rkmodule_hdr_cfg *)arg; hdr_cfg->esp.mode = HDR_NORMAL_VC; hdr_cfg->hdr_mode = os02g10->cur_mode->hdr_mode; break; - case RKMODULE_SET_CONVERSION_GAIN: - break; case RKMODULE_SET_QUICK_STREAM: stream = *((u32 *)arg); if (stream) @@ -646,11 +612,8 @@ static long os02g10_compat_ioctl32(struct v4l2_subdev *sd, { void __user *up = compat_ptr(arg); struct rkmodule_inf *inf; - struct rkmodule_awb_cfg *cfg; struct rkmodule_hdr_cfg *hdr; - struct preisp_hdrae_exp_s *hdrae; long ret; - u32 cg = 0; u32 stream = 0; switch (cmd) { @@ -662,21 +625,12 @@ static long os02g10_compat_ioctl32(struct v4l2_subdev *sd, } ret = os02g10_ioctl(sd, cmd, inf); - if (!ret) + if (!ret) { ret = copy_to_user(up, inf, sizeof(*inf)); - kfree(inf); - break; - case RKMODULE_AWB_CFG: - cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); - if (!cfg) { - ret = -ENOMEM; - return ret; + if (ret) + ret = -EFAULT; } - - ret = copy_from_user(cfg, up, sizeof(*cfg)); - if (!ret) - ret = os02g10_ioctl(sd, cmd, cfg); - kfree(cfg); + kfree(inf); break; case RKMODULE_GET_HDR_CFG: hdr = kzalloc(sizeof(*hdr), GFP_KERNEL); @@ -686,8 +640,11 @@ static long os02g10_compat_ioctl32(struct v4l2_subdev *sd, } ret = os02g10_ioctl(sd, cmd, hdr); - if (!ret) + if (!ret) { ret = copy_to_user(up, hdr, sizeof(*hdr)); + if (ret) + ret = -EFAULT; + } kfree(hdr); break; case RKMODULE_SET_HDR_CFG: @@ -697,32 +654,17 @@ static long os02g10_compat_ioctl32(struct v4l2_subdev *sd, return ret; } - ret = copy_from_user(hdr, up, sizeof(*hdr)); - if (!ret) - ret = os02g10_ioctl(sd, cmd, hdr); + if (copy_from_user(hdr, up, sizeof(*hdr))) + return -EFAULT; + + ret = os02g10_ioctl(sd, cmd, hdr); kfree(hdr); break; - case PREISP_CMD_SET_HDRAE_EXP: - hdrae = kzalloc(sizeof(*hdrae), GFP_KERNEL); - if (!hdrae) { - ret = -ENOMEM; - return ret; - } - - ret = copy_from_user(hdrae, up, sizeof(*hdrae)); - if (!ret) - ret = os02g10_ioctl(sd, cmd, hdrae); - kfree(hdrae); - break; - case RKMODULE_SET_CONVERSION_GAIN: - ret = copy_from_user(&cg, up, sizeof(cg)); - if (!ret) - ret = os02g10_ioctl(sd, cmd, &cg); - break; case RKMODULE_SET_QUICK_STREAM: - ret = copy_from_user(&stream, up, sizeof(u32)); - if (!ret) - ret = os02g10_ioctl(sd, cmd, &stream); + if (copy_from_user(&stream, up, sizeof(u32))) + return -EFAULT; + + ret = os02g10_ioctl(sd, cmd, &stream); break; default: ret = -ENOIOCTLCMD; @@ -735,9 +677,17 @@ static long os02g10_compat_ioctl32(struct v4l2_subdev *sd, static int __os02g10_start_stream(struct os02g10 *os02g10) { - int ret; + int ret = 0; - ret = os02g10_write_array(os02g10->client, os02g10->cur_mode->reg_list); + ret |= os02g10_write_reg(os02g10->client, 0xfd, 0x00); + ret |= os02g10_write_reg(os02g10->client, 0x36, 0x01); + ret |= os02g10_write_reg(os02g10->client, 0xfd, 0x00); + ret |= os02g10_write_reg(os02g10->client, 0x36, 0x00); + ret |= os02g10_write_reg(os02g10->client, 0xfd, 0x00); + + usleep_range(5000, 6000); + + ret |= os02g10_write_array(os02g10->client, os02g10->cur_mode->reg_list); if (ret) return ret; @@ -1117,11 +1067,17 @@ static int os02g10_set_ctrl(struct v4l2_ctrl *ctrl) os02g10->flip &= ~MIRROR_BIT_MASK; ret = os02g10_write_reg(os02g10->client, - OS02G10_REG_PAGE_SELECT, 0x01); + OS02G10_REG_PAGE_SELECT, 0x01); ret |= os02g10_write_reg(os02g10->client, - OS02G10_FLIP_REG, os02g10->flip); + OS02G10_FLIP_REG, os02g10->flip); ret |= os02g10_write_reg(os02g10->client, - OS02G10_REG_RESTART, 0x01); + OS02G10_REG_PAGE_SELECT, 0x02); + ret |= os02g10_write_reg(os02g10->client, + OS02G10_REG_BAYER_ORDER, 0x32); + ret |= os02g10_write_reg(os02g10->client, + OS02G10_REG_PAGE_SELECT, 0x01); + ret |= os02g10_write_reg(os02g10->client, + OS02G10_REG_RESTART, 0x01); dev_dbg(&client->dev, "set hflip 0x%x\n", os02g10->flip); break; case V4L2_CID_VFLIP: @@ -1131,11 +1087,17 @@ static int os02g10_set_ctrl(struct v4l2_ctrl *ctrl) os02g10->flip &= ~FLIP_BIT_MASK; ret = os02g10_write_reg(os02g10->client, - OS02G10_REG_PAGE_SELECT, 0x01); + OS02G10_REG_PAGE_SELECT, 0x01); ret |= os02g10_write_reg(os02g10->client, - OS02G10_FLIP_REG, os02g10->flip); + OS02G10_FLIP_REG, os02g10->flip); ret |= os02g10_write_reg(os02g10->client, - OS02G10_REG_RESTART, 0x01); + OS02G10_REG_PAGE_SELECT, 0x02); + ret |= os02g10_write_reg(os02g10->client, + OS02G10_REG_BAYER_ORDER, 0x32); + ret |= os02g10_write_reg(os02g10->client, + OS02G10_REG_PAGE_SELECT, 0x01); + ret |= os02g10_write_reg(os02g10->client, + OS02G10_REG_RESTART, 0x01); dev_dbg(&client->dev, "set vflip 0x%x\n", os02g10->flip); break; default: @@ -1170,8 +1132,9 @@ static int os02g10_initialize_controls(struct os02g10 *os02g10) handler->lock = &os02g10->mutex; os02g10->link_freq = v4l2_ctrl_new_int_menu(handler, NULL, - V4L2_CID_LINK_FREQ, - 1, 0, link_freq_menu_items); + V4L2_CID_LINK_FREQ, + 1, 0, + link_freq_menu_items); if (os02g10->cur_mode->bus_fmt == MEDIA_BUS_FMT_SBGGR10_1X10) { dst_link_freq = 0; @@ -1179,42 +1142,42 @@ static int os02g10_initialize_controls(struct os02g10 *os02g10) } /* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */ os02g10->pixel_rate = v4l2_ctrl_new_std(handler, NULL, - V4L2_CID_PIXEL_RATE, - 0, PIXEL_RATE_WITH_360M, - 1, dst_pixel_rate); + V4L2_CID_PIXEL_RATE, + 0, PIXEL_RATE_WITH_360M, + 1, dst_pixel_rate); __v4l2_ctrl_s_ctrl(os02g10->link_freq, dst_link_freq); h_blank = mode->hts_def - mode->width; os02g10->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK, - h_blank, h_blank, 1, h_blank); + h_blank, h_blank, 1, h_blank); if (os02g10->hblank) os02g10->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; vblank_def = mode->vts_def - mode->height; os02g10->vblank = v4l2_ctrl_new_std(handler, &os02g10_ctrl_ops, - V4L2_CID_VBLANK, vblank_def, - OS02G10_VTS_MAX - mode->height, - 1, vblank_def); + V4L2_CID_VBLANK, vblank_def, + OS02G10_VTS_MAX - mode->height, + 1, vblank_def); exposure_max = mode->vts_def - 8; os02g10->exposure = v4l2_ctrl_new_std(handler, &os02g10_ctrl_ops, - V4L2_CID_EXPOSURE, OS02G10_EXPOSURE_MIN, - exposure_max, OS02G10_EXPOSURE_STEP, - mode->exp_def); + V4L2_CID_EXPOSURE, OS02G10_EXPOSURE_MIN, + exposure_max, OS02G10_EXPOSURE_STEP, + mode->exp_def); os02g10->anal_gain = v4l2_ctrl_new_std(handler, &os02g10_ctrl_ops, - V4L2_CID_ANALOGUE_GAIN, OS02G10_GAIN_MIN, - OS02G10_GAIN_MAX, OS02G10_GAIN_STEP, - OS02G10_GAIN_DEFAULT); + V4L2_CID_ANALOGUE_GAIN, OS02G10_GAIN_MIN, + OS02G10_GAIN_MAX, OS02G10_GAIN_STEP, + OS02G10_GAIN_DEFAULT); - os02g10->h_flip = v4l2_ctrl_new_std(handler, &os02g10_ctrl_ops, - V4L2_CID_HFLIP, 0, 1, 1, 0); + v4l2_ctrl_new_std(handler, &os02g10_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0); + + v4l2_ctrl_new_std(handler, &os02g10_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0); - os02g10->v_flip = v4l2_ctrl_new_std(handler, &os02g10_ctrl_ops, - V4L2_CID_VFLIP, 0, 1, 1, 0); os02g10->flip = 0; + if (handler->error) { ret = handler->error; dev_err(&os02g10->client->dev, @@ -1261,8 +1224,8 @@ static int os02g10_configure_regulators(struct os02g10 *os02g10) os02g10->supplies[i].supply = OS02G10_supply_names[i]; return devm_regulator_bulk_get(&os02g10->client->dev, - OS02G10_NUM_SUPPLIES, - os02g10->supplies); + OS02G10_NUM_SUPPLIES, + os02g10->supplies); } static int os02g10_probe(struct i2c_client *client,