From 9370bb92b2d16684ee45cf24e879c93c509162da Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Thu, 19 Dec 2024 01:47:39 +0000 Subject: [PATCH] add wifi6 8852be driver --- kernel/drivers/media/i2c/gc8034.c | 596 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 558 insertions(+), 38 deletions(-) diff --git a/kernel/drivers/media/i2c/gc8034.c b/kernel/drivers/media/i2c/gc8034.c index 51d5320..bd7e4bd 100644 --- a/kernel/drivers/media/i2c/gc8034.c +++ b/kernel/drivers/media/i2c/gc8034.c @@ -13,8 +13,13 @@ * 1. add 2lane support. * 2. add some debug info. * 3. adjust gc8034_g_mbus_config function. + * V0.0X01.0X07 support get channel info + * V0.0X01.0X08 + * 1. default support 2lane full 30fps. + * 2. default support rk otp spec. + * V0.0X01.0X09 adjust supply sequence to suit spec */ - +//#define DEBUG #include <linux/clk.h> #include <linux/device.h> #include <linux/delay.h> @@ -39,8 +44,10 @@ #include <media/v4l2-subdev.h> #include <linux/pinctrl/consumer.h> #include <linux/slab.h> +#include <linux/of_graph.h> +#include "otp_eeprom.h" -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x06) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x09) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -49,6 +56,7 @@ #define GC8034_LANES 4 #define GC8034_BITS_PER_SAMPLE 10 #define GC8034_MIPI_FREQ_336MHZ 336000000U +#define GC8034_MIPI_FREQ_634MHZ 634000000U /* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */ #define GC8034_PIXEL_RATE 288000000 @@ -92,15 +100,20 @@ #define GC8034_NAME "gc8034" #define GC8034_MEDIA_BUS_FMT MEDIA_BUS_FMT_SRGGB10_1X10 +/* use RK_OTP or old mode */ +#define RK_OTP +/* choose 2lane support full 30fps or 15fps */ +#define GC8034_2LANE_30FPS + static const char * const gc8034_supply_names[] = { - "avdd", /* Analog power */ "dovdd", /* Digital I/O power */ "dvdd", /* Digital core power */ + "avdd", /* Analog power */ }; -static const struct regval *gc8034_global_regs; #define GC8034_NUM_SUPPLIES ARRAY_SIZE(gc8034_supply_names) +#ifndef RK_OTP struct gc8034_dd { u16 x; u16 y; @@ -145,6 +158,7 @@ {0xd0, "CK8401"}, {0x00, "Unknown"} }; +#endif struct regval { u8 addr; @@ -158,7 +172,10 @@ u32 hts_def; u32 vts_def; u32 exp_def; + u32 mipi_freq_idx; + const struct regval *global_reg_list; const struct regval *reg_list; + u32 vc[PAD_MAX]; }; struct gc8034 { @@ -192,7 +209,11 @@ const char *module_name; const char *len_name; u32 Dgain_ratio; +#ifdef RK_OTP + struct otp_info *otp; +#else struct gc8034_otp_info *otp; +#endif struct rkmodule_inf module_inf; struct rkmodule_awb_cfg awb_cfg; }; @@ -244,6 +265,217 @@ * Xclk 24Mhz */ static const struct regval gc8034_global_regs_2lane[] = { +#ifdef GC8034_2LANE_30FPS + /* SYS */ + {0xf2, 0x00}, + {0xf4, 0x90}, + {0xf5, 0x3d}, + {0xf6, 0x44}, + {0xf8, 0x63}, + {0xfa, 0x42}, + {0xf9, 0x00}, + {0xf7, 0x95}, + {0xfc, 0x00}, + {0xfc, 0x00}, + {0xfc, 0xea}, + {0xfe, 0x03}, + {0x03, 0x9a}, + {0xfc, 0xee}, + {0xfe, 0x00}, + {0x88, 0x03}, + + /*Cisctl&Analog*/ + {0xfe, 0x00}, + {0x03, 0x08}, + {0x04, 0xc6}, + {0x05, 0x02}, + {0x06, 0x16}, + {0x07, 0x00}, + {0x08, 0x10}, + {0x0a, 0x3a}, //row start + {0x0b, 0x00}, + {0x0c, 0x04}, //col start + {0x0d, 0x09}, + {0x0e, 0xa0}, //win_height 2464 + {0x0f, 0x0c}, + {0x10, 0xd4}, //win_width 3284 + {0x17, GC8034_MIRROR}, + {0x18, 0x02}, + {0x19, 0x17}, + {0x1e, 0x50}, + {0x1f, 0x80}, + {0x21, 0x4c}, + {0x25, 0x00}, + {0x28, 0x4a}, + {0x2d, 0x89}, + {0xca, 0x02}, + {0xcb, 0x00}, + {0xcc, 0x39}, + {0xce, 0xd0}, + {0xcf, 0x93}, + {0xd0, 0x1b}, + {0xd1, 0xaa}, + {0xd2, 0xcb}, + {0xd8, 0x40}, + {0xd9, 0xff}, + {0xda, 0x0e}, + {0xdb, 0xb0}, + {0xdc, 0x0e}, + {0xde, 0x08}, + {0xe4, 0xc6}, + {0xe5, 0x08}, + {0xe6, 0x10}, + {0xed, 0x2a}, + {0xfe, 0x02}, + {0x59, 0x02}, + {0x5a, 0x04}, + {0x5b, 0x08}, + {0x5c, 0x20}, + {0xfe, 0x00}, + {0x1a, 0x09}, + {0x1d, 0x13}, + {0xfe, 0x10}, + {0xfe, 0x00}, + {0xfe, 0x10}, + {0xfe, 0x00}, + + /* Gamma */ + {0xfe, 0x00}, + {0x20, 0x54}, + {0x33, 0x82}, + {0xfe, 0x01}, + {0xdf, 0x06}, + {0xe7, 0x18}, + {0xe8, 0x20}, + {0xe9, 0x16}, + {0xea, 0x17}, + {0xeb, 0x50}, + {0xec, 0x6c}, + {0xed, 0x9b}, + {0xee, 0xd8}, + + /*ISP*/ + {0xfe, 0x00}, + {0x80, 0x13}, + {0x84, 0x01}, + {0x89, 0x03}, + {0x8d, 0x03}, + {0x8f, 0x14}, + {0xad, 0x00}, + {0x66, 0x0c}, + {0xbc, 0x09}, + {0xc2, 0x7f}, + {0xc3, 0xff}, + + /*Crop window*/ + {0x90, 0x01}, + {0x92, FULL_STARTY}, + {0x94, FULL_STARTX}, + {0x95, 0x09}, + {0x96, 0x90}, + {0x97, 0x0c}, + {0x98, 0xc0}, + + /*Gain*/ + {0xb0, 0x90}, + {0xb1, 0x01}, + {0xb2, 0x00}, + {0xb6, 0x00}, + + /*BLK*/ + {0xfe, 0x00}, + {0x40, 0x22}, + {0x41, 0x20}, + {0x42, 0x02}, + {0x43, 0x08}, + {0x4e, 0x0f}, + {0x4f, 0xf0}, + {0x58, 0x80}, + {0x59, 0x80}, + {0x5a, 0x80}, + {0x5b, 0x80}, + {0x5c, 0x00}, + {0x5d, 0x00}, + {0x5e, 0x00}, + {0x5f, 0x00}, + {0x6b, 0x01}, + {0x6c, 0x00}, + {0x6d, 0x0c}, + + /*WB offset*/ + {0xfe, 0x01}, + {0xbf, 0x40}, + + /*Dark Sun*/ + {0xfe, 0x01}, + {0x68, 0x77}, + + /*DPC*/ + {0xfe, 0x01}, + {0x60, 0x00}, + {0x61, 0x10}, + {0x62, 0x60}, + {0x63, 0x30}, + {0x64, 0x00}, + + /* LSC */ + {0xfe, 0x01}, + {0xa8, 0x60}, + {0xa2, 0xd1}, + {0xc8, 0x57}, + {0xa1, 0xb8}, + {0xa3, 0x91}, + {0xc0, 0x50}, + {0xd0, 0x05}, + {0xd1, 0xb2}, + {0xd2, 0x1f}, + {0xd3, 0x00}, + {0xd4, 0x00}, + {0xd5, 0x00}, + {0xd6, 0x00}, + {0xd7, 0x00}, + {0xd8, 0x00}, + {0xd9, 0x00}, + {0xa4, 0x10}, + {0xa5, 0x20}, + {0xa6, 0x60}, + {0xa7, 0x80}, + {0xab, 0x18}, + {0xc7, 0xc0}, + + /*ABB*/ + {0xfe, 0x01}, + {0x20, 0x02}, + {0x21, 0x02}, + {0x23, 0x42}, + + /*MIPI*/ + {0xfe, 0x03}, + {0x01, 0x07}, + {0x02, 0x04}, + {0x04, 0x80}, + {0x11, 0x2b}, + {0x12, 0xf0}, //lwc 3264*5/4 + {0x13, 0x0f}, + {0x15, 0x10}, //LP + {0x16, 0x29}, + {0x17, 0xff}, + {0x18, 0x01}, + {0x19, 0xaa}, + {0x1a, 0x02}, + {0x21, 0x0c}, + {0x22, 0x0e}, + {0x23, 0x45}, + {0x24, 0x01}, + {0x25, 0x1c}, + {0x26, 0x0b}, + {0x29, 0x0e}, + {0x2a, 0x1d}, + {0x2b, 0x0b}, + {0xfe, 0x00}, + //{0x3f, 0x91}, + {0x3f, 0x00}, +#else /*SYS*/ {0xf2, 0x00}, {0xf4, 0x80}, @@ -433,10 +665,11 @@ {0xfe, 0x00}, //{0x3f, 0x91}, {0x3f, 0x00}, - +#endif {REG_NULL, 0x00}, }; +#ifndef GC8034_2LANE_30FPS /* * Xclk 24Mhz * max_framerate 30fps @@ -507,6 +740,7 @@ {REG_NULL, 0x00}, }; +#endif /* * Xclk 24Mhz @@ -514,6 +748,72 @@ * mipi_datarate per lane 672Mbps */ static const struct regval gc8034_3264x2448_regs_2lane[] = { +#ifdef GC8034_2LANE_30FPS + /* SYS */ + {0xf2, 0x00}, + {0xf4, 0x90}, + {0xf5, 0x3d}, + {0xf6, 0x44}, + {0xf8, 0x63}, + {0xfa, 0x42}, + {0xf9, 0x00}, + {0xf7, 0x95}, + {0xfc, 0x00}, + {0xfc, 0x00}, + {0xfc, 0xea}, + {0xfe, 0x03}, + {0x03, 0x9a}, + {0xfc, 0xee}, + {0xfe, 0x00}, + {0x3f, 0x00}, + {0xfe, 0x10}, + {0xfe, 0x00}, + {0xfe, 0x10}, + {0xfe, 0x00}, + + /* ISP */ + {0xfe, 0x00}, + {0x80, 0x13}, + {0xad, 0x00}, + {0x66, 0x0c}, + {0xbc, 0x06}, + + /* Crop window */ + {0x90, 0x01}, + {0x92, FULL_STARTY}, + {0x94, FULL_STARTX}, + {0x95, 0x09}, + {0x96, 0x90}, + {0x97, 0x0c}, + {0x98, 0xc0}, + + /* MIPI */ + {0xfe, 0x03}, + {0x01, 0x07}, + {0x02, 0x04}, + {0x04, 0x80}, + {0x11, 0x2b}, + {0x12, 0xf0}, //lwc 3264*5/4 + {0x13, 0x0f}, + {0x15, 0x10}, //LP + {0x16, 0x29}, + {0x17, 0xff}, + {0x18, 0x01}, + {0x19, 0xaa}, + {0x1a, 0x02}, + {0x21, 0x0c}, + {0x22, 0x0c}, + {0x23, 0x56}, + {0x24, 0x00}, + {0x25, 0x1c}, + {0x26, 0x0b}, + {0x29, 0x0e}, + {0x2a, 0x1d}, + {0x2b, 0x0b}, + {0xfe, 0x00}, + //{0x3f, 0x91}, + {0x3f, 0x00}, +#else /*SYS*/ {0xf2, 0x00}, {0xf4, 0x80}, @@ -570,6 +870,7 @@ {0xfe, 0x00}, //{0x3f, 0x91}, {0x3f, 0x00}, +#endif {REG_NULL, 0x00}, }; @@ -843,6 +1144,23 @@ }; static const struct gc8034_mode supported_modes_2lane[] = { +#ifdef GC8034_2LANE_30FPS + { + .width = 3264, + .height = 2448, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, + .exp_def = 0x0900, + .hts_def = 0x0858 * 2, + .vts_def = 0x09c0, + .mipi_freq_idx = 1, + .global_reg_list = gc8034_global_regs_2lane, + .reg_list = gc8034_3264x2448_regs_2lane, + .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0, + }, +#else { .width = 3264, .height = 2448, @@ -853,7 +1171,10 @@ .exp_def = 0x09a0, .hts_def = 0x0858 * 2, .vts_def = 0x09c4, + .mipi_freq_idx = 0, + .global_reg_list = gc8034_global_regs_2lane, .reg_list = gc8034_3264x2448_regs_2lane, + .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0, }, { .width = 1632, @@ -865,8 +1186,12 @@ .exp_def = 0x09a0, .hts_def = 0x0858 * 2, .vts_def = 0x09c4, + .mipi_freq_idx = 0, + .global_reg_list = gc8034_global_regs_2lane, .reg_list = gc8034_1632x1224_regs_2lane, + .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0, }, +#endif }; static const struct gc8034_mode supported_modes_4lane[] = { @@ -880,7 +1205,10 @@ .exp_def = 0x08c6, .hts_def = 0x10b0, .vts_def = 0x09c0, + .mipi_freq_idx = 0, + .global_reg_list = gc8034_global_regs_4lane, .reg_list = gc8034_3264x2448_regs_4lane, + .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0, }, }; @@ -888,6 +1216,7 @@ static const s64 link_freq_menu_items[] = { GC8034_MIPI_FREQ_336MHZ, + GC8034_MIPI_FREQ_634MHZ }; /* Write registers up to 4 at a time */ @@ -1017,8 +1346,8 @@ __v4l2_ctrl_modify_range(gc8034->vblank, vblank_def, GC8034_VTS_MAX - mode->height, 1, vblank_def); - __v4l2_ctrl_s_ctrl(gc8034->link_freq, - link_freq_menu_items[0]); + __v4l2_ctrl_s_ctrl(gc8034->vblank, vblank_def); + __v4l2_ctrl_s_ctrl(gc8034->link_freq, mode->mipi_freq_idx); } mutex_unlock(&gc8034->mutex); @@ -1089,13 +1418,92 @@ struct gc8034 *gc8034 = to_gc8034(sd); const struct gc8034_mode *mode = gc8034->cur_mode; - mutex_lock(&gc8034->mutex); fi->interval = mode->max_fps; - mutex_unlock(&gc8034->mutex); return 0; } +#ifdef RK_OTP +static void gc8034_get_otp(struct otp_info *otp, + struct rkmodule_inf *inf) +{ + u32 i, j; + u32 w, h; + + /* awb */ + if (otp->awb_data.flag) { + inf->awb.flag = 1; + inf->awb.r_value = otp->awb_data.r_ratio; + inf->awb.b_value = otp->awb_data.b_ratio; + inf->awb.gr_value = otp->awb_data.g_ratio; + inf->awb.gb_value = 0x0; + + inf->awb.golden_r_value = otp->awb_data.r_golden; + inf->awb.golden_b_value = otp->awb_data.b_golden; + inf->awb.golden_gr_value = otp->awb_data.g_golden; + inf->awb.golden_gb_value = 0x0; + } + + /* lsc */ + if (otp->lsc_data.flag) { + inf->lsc.flag = 1; + inf->lsc.width = otp->basic_data.size.width; + inf->lsc.height = otp->basic_data.size.height; + inf->lsc.table_size = otp->lsc_data.table_size; + + for (i = 0; i < 289; i++) { + inf->lsc.lsc_r[i] = (otp->lsc_data.data[i * 2] << 8) | + otp->lsc_data.data[i * 2 + 1]; + inf->lsc.lsc_gr[i] = (otp->lsc_data.data[i * 2 + 578] << 8) | + otp->lsc_data.data[i * 2 + 579]; + inf->lsc.lsc_gb[i] = (otp->lsc_data.data[i * 2 + 1156] << 8) | + otp->lsc_data.data[i * 2 + 1157]; + inf->lsc.lsc_b[i] = (otp->lsc_data.data[i * 2 + 1734] << 8) | + otp->lsc_data.data[i * 2 + 1735]; + } + } + + /* pdaf */ + if (otp->pdaf_data.flag) { + inf->pdaf.flag = 1; + inf->pdaf.gainmap_width = otp->pdaf_data.gainmap_width; + inf->pdaf.gainmap_height = otp->pdaf_data.gainmap_height; + inf->pdaf.pd_offset = otp->pdaf_data.pd_offset; + inf->pdaf.dcc_mode = otp->pdaf_data.dcc_mode; + inf->pdaf.dcc_dir = otp->pdaf_data.dcc_dir; + inf->pdaf.dccmap_width = otp->pdaf_data.dccmap_width; + inf->pdaf.dccmap_height = otp->pdaf_data.dccmap_height; + w = otp->pdaf_data.gainmap_width; + h = otp->pdaf_data.gainmap_height; + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + inf->pdaf.gainmap[i * w + j] = + (otp->pdaf_data.gainmap[(i * w + j) * 2] << 8) | + otp->pdaf_data.gainmap[(i * w + j) * 2 + 1]; + } + } + w = otp->pdaf_data.dccmap_width; + h = otp->pdaf_data.dccmap_height; + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + inf->pdaf.dccmap[i * w + j] = + (otp->pdaf_data.dccmap[(i * w + j) * 2] << 8) | + otp->pdaf_data.dccmap[(i * w + j) * 2 + 1]; + } + } + } + + /* af */ + if (otp->af_data.flag) { + inf->af.flag = 1; + inf->af.dir_cnt = 1; + inf->af.af_otp[0].vcm_start = otp->af_data.af_inf; + inf->af.af_otp[0].vcm_end = otp->af_data.af_macro; + inf->af.af_otp[0].vcm_dir = 0; + } + +} +#else #define DD_WIDTH 3284 #define DD_HEIGHT 2464 @@ -1605,11 +2013,16 @@ inf->af.af_otp[0].vcm_dir = otp->vcm_dir; } } +#endif static void gc8034_get_module_inf(struct gc8034 *gc8034, struct rkmodule_inf *inf) { +#ifdef RK_OTP + struct otp_info *otp = gc8034->otp; +#else struct gc8034_otp_info *otp = gc8034->otp; +#endif strlcpy(inf->base.sensor, GC8034_NAME, @@ -1632,11 +2045,23 @@ mutex_unlock(&gc8034->mutex); } +static int gc8034_get_channel_info(struct gc8034 *gc8034, struct rkmodule_channel_info *ch_info) +{ + if (ch_info->index < PAD0 || ch_info->index >= PAD_MAX) + return -EINVAL; + ch_info->vc = gc8034->cur_mode->vc[ch_info->index]; + ch_info->width = gc8034->cur_mode->width; + ch_info->height = gc8034->cur_mode->height; + ch_info->bus_fmt = GC8034_MEDIA_BUS_FMT; + return 0; +} + static long gc8034_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { struct gc8034 *gc8034 = to_gc8034(sd); long ret = 0; u32 stream = 0; + struct rkmodule_channel_info *ch_info; switch (cmd) { case RKMODULE_GET_MODULE_INFO: @@ -1671,6 +2096,10 @@ GC8034_MODE_SW_STANDBY); } break; + case RKMODULE_GET_CHANNEL_INFO: + ch_info = (struct rkmodule_channel_info *)arg; + ret = gc8034_get_channel_info(gc8034, ch_info); + break; default: ret = -ENOTTY; break; @@ -1688,6 +2117,7 @@ struct rkmodule_awb_cfg *cfg; long ret = 0; u32 stream = 0; + struct rkmodule_channel_info *ch_info; switch (cmd) { case RKMODULE_GET_MODULE_INFO: @@ -1698,8 +2128,11 @@ } ret = gc8034_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_AWB_CFG: @@ -1712,12 +2145,31 @@ ret = copy_from_user(cfg, up, sizeof(*cfg)); if (!ret) ret = gc8034_ioctl(sd, cmd, cfg); + else + ret = -EFAULT; kfree(cfg); break; case RKMODULE_SET_QUICK_STREAM: ret = copy_from_user(&stream, up, sizeof(u32)); if (!ret) ret = gc8034_ioctl(sd, cmd, &stream); + else + ret = -EFAULT; + break; + case RKMODULE_GET_CHANNEL_INFO: + ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL); + if (!ch_info) { + ret = -ENOMEM; + return ret; + } + + ret = gc8034_ioctl(sd, cmd, ch_info); + if (!ret) { + ret = copy_to_user(up, ch_info, sizeof(*ch_info)); + if (ret) + ret = -EFAULT; + } + kfree(ch_info); break; default: ret = -ENOTTY; @@ -1728,6 +2180,7 @@ } #endif +#ifndef RK_OTP /*--------------------------------------------------------------------------*/ static int gc8034_apply_otp(struct gc8034 *gc8034) { @@ -1908,11 +2361,12 @@ } return 0; } +#endif static int __gc8034_start_stream(struct gc8034 *gc8034) { int ret; - +#ifndef RK_OTP if (gc8034->otp) { ret = gc8034_otp_enable(gc8034); gc8034_check_prsel(gc8034); @@ -1922,6 +2376,7 @@ if (ret) return ret; } +#endif ret = gc8034_write_array(gc8034->client, gc8034->cur_mode->reg_list); if (ret) return ret; @@ -2006,6 +2461,7 @@ { struct gc8034 *gc8034 = to_gc8034(sd); struct i2c_client *client = gc8034->client; + const struct gc8034_mode *mode = gc8034->cur_mode; int ret = 0; dev_info(&client->dev, "%s(%d) on(%d)\n", __func__, __LINE__, on); @@ -2022,7 +2478,7 @@ goto unlock_and_return; } - ret = gc8034_write_array(gc8034->client, gc8034_global_regs); + ret = gc8034_write_array(gc8034->client, mode->global_reg_list); if (ret) { v4l2_err(sd, "could not set init registers\n"); pm_runtime_put_noidle(&client->dev); @@ -2047,6 +2503,31 @@ return DIV_ROUND_UP(cycles, GC8034_XVCLK_FREQ / 1000 / 1000); } +static int gc8034_enable_regulators(struct gc8034 *gc8034, + struct regulator_bulk_data *consumers) +{ + int i, j; + int ret = 0; + struct device *dev = &gc8034->client->dev; + int num_consumers = GC8034_NUM_SUPPLIES; + + for (i = 0; i < num_consumers; i++) { + + ret = regulator_enable(consumers[i].consumer); + if (ret < 0) { + dev_err(dev, "Failed to enable regulator: %s\n", + consumers[i].supply); + goto err; + } + } + return 0; +err: + for (j = 0; j < i; j++) + regulator_disable(consumers[j].consumer); + + return ret; +} + static int __gc8034_power_on(struct gc8034 *gc8034) { int ret; @@ -2069,27 +2550,32 @@ dev_warn(dev, "Failed to set xvclk rate (24MHz)\n"); if (clk_get_rate(gc8034->xvclk) != GC8034_XVCLK_FREQ) dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n"); - ret = clk_prepare_enable(gc8034->xvclk); - if (ret < 0) { - dev_err(dev, "Failed to enable xvclk\n"); - return ret; - } + if (!IS_ERR(gc8034->reset_gpio)) gpiod_set_value_cansleep(gc8034->reset_gpio, 1); - ret = regulator_bulk_enable(GC8034_NUM_SUPPLIES, gc8034->supplies); + ret = gc8034_enable_regulators(gc8034, gc8034->supplies); if (ret < 0) { dev_err(dev, "Failed to enable regulators\n"); goto disable_clk; } + usleep_range(100, 200); + ret = clk_prepare_enable(gc8034->xvclk); + if (ret < 0) { + dev_err(dev, "Failed to enable xvclk\n"); + return ret; + } + usleep_range(1000, 1100); + if (!IS_ERR(gc8034->pwdn_gpio)) + gpiod_set_value_cansleep(gc8034->pwdn_gpio, 0); + + usleep_range(500, 1000); if (!IS_ERR(gc8034->reset_gpio)) gpiod_set_value_cansleep(gc8034->reset_gpio, 0); - usleep_range(500, 1000); - if (!IS_ERR(gc8034->pwdn_gpio)) - gpiod_set_value_cansleep(gc8034->pwdn_gpio, 0); + usleep_range(6000, 7000); /* 8192 cycles prior to first SCCB transaction */ delay_us = gc8034_cal_delay(8192); @@ -2109,9 +2595,11 @@ if (!IS_ERR(gc8034->pwdn_gpio)) gpiod_set_value_cansleep(gc8034->pwdn_gpio, 1); - clk_disable_unprepare(gc8034->xvclk); + if (!IS_ERR(gc8034->reset_gpio)) gpiod_set_value_cansleep(gc8034->reset_gpio, 1); + + clk_disable_unprepare(gc8034->xvclk); if (!IS_ERR_OR_NULL(gc8034->pins_sleep)) { ret = pinctrl_select_state(gc8034->pinctrl, gc8034->pins_sleep); @@ -2124,7 +2612,7 @@ regulator_bulk_disable(GC8034_NUM_SUPPLIES, gc8034->supplies); } -static int gc8034_runtime_resume(struct device *dev) +static int __maybe_unused gc8034_runtime_resume(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct v4l2_subdev *sd = i2c_get_clientdata(client); @@ -2133,7 +2621,7 @@ return __gc8034_power_on(gc8034); } -static int gc8034_runtime_suspend(struct device *dev) +static int __maybe_unused gc8034_runtime_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct v4l2_subdev *sd = i2c_get_clientdata(client); @@ -2175,16 +2663,14 @@ if (fie->index >= gc8034->cfg_num) return -EINVAL; - if (fie->code != GC8034_MEDIA_BUS_FMT) - return -EINVAL; - + fie->code = GC8034_MEDIA_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 gc8034_g_mbus_config(struct v4l2_subdev *sd, +static int gc8034_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id, struct v4l2_mbus_config *config) { struct gc8034 *sensor = to_gc8034(sd); @@ -2193,12 +2679,12 @@ dev_info(dev, "%s(%d) enter!\n", __func__, __LINE__); if (2 == sensor->lane_num) { - config->type = V4L2_MBUS_CSI2; + config->type = V4L2_MBUS_CSI2_DPHY; config->flags = V4L2_MBUS_CSI2_2_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; } else if (4 == sensor->lane_num) { - config->type = V4L2_MBUS_CSI2; + config->type = V4L2_MBUS_CSI2_DPHY; config->flags = V4L2_MBUS_CSI2_4_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; @@ -2231,7 +2717,6 @@ static const struct v4l2_subdev_video_ops gc8034_video_ops = { .s_stream = gc8034_s_stream, .g_frame_interval = gc8034_g_frame_interval, - .g_mbus_config = gc8034_g_mbus_config, }; static const struct v4l2_subdev_pad_ops gc8034_pad_ops = { @@ -2240,6 +2725,7 @@ .enum_frame_interval = gc8034_enum_frame_interval, .get_fmt = gc8034_get_fmt, .set_fmt = gc8034_set_fmt, + .get_mbus_config = gc8034_g_mbus_config, }; static const struct v4l2_subdev_ops gc8034_subdev_ops = { @@ -2388,15 +2874,15 @@ switch (ctrl->id) { case V4L2_CID_EXPOSURE: /* 4 least significant bits of expsoure are fractional part */ - dev_info(&client->dev, "set exposure value 0x%x\n", ctrl->val); + dev_dbg(&client->dev, "set exposure value 0x%x\n", ctrl->val); ret = gc8034_set_exposure_reg(gc8034, ctrl->val); break; case V4L2_CID_ANALOGUE_GAIN: - dev_info(&client->dev, "set analog gain value 0x%x\n", ctrl->val); + dev_dbg(&client->dev, "set analog gain value 0x%x\n", ctrl->val); ret = gc8034_set_gain_reg(gc8034, ctrl->val); break; case V4L2_CID_VBLANK: - dev_info(&client->dev, "set vb value 0x%x\n", ctrl->val); + dev_dbg(&client->dev, "set vb value 0x%x\n", ctrl->val); /* VB = VTS - 2448 -36, according android8.1 driver */ temp = ctrl->val + gc8034->cur_mode->height - 2448 - 36; ret = gc8034_write_reg(gc8034->client, @@ -2440,8 +2926,10 @@ handler->lock = &gc8034->mutex; gc8034->link_freq = v4l2_ctrl_new_int_menu(handler, NULL, - V4L2_CID_LINK_FREQ, 0, 0, + V4L2_CID_LINK_FREQ, + ARRAY_SIZE(link_freq_menu_items) - 1, 0, link_freq_menu_items); + v4l2_ctrl_s_ctrl(gc8034->link_freq, mode->mipi_freq_idx); v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE, 0, gc8034->pixel_rate, 1, gc8034->pixel_rate); @@ -2542,7 +3030,6 @@ gc8034->cur_mode = &supported_modes_4lane[0]; supported_modes = supported_modes_4lane; gc8034->cfg_num = ARRAY_SIZE(supported_modes_4lane); - gc8034_global_regs = gc8034_global_regs_4lane; /* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */ fps = DIV_ROUND_CLOSEST(gc8034->cur_mode->max_fps.denominator, gc8034->cur_mode->max_fps.numerator); @@ -2555,7 +3042,6 @@ gc8034->cur_mode = &supported_modes_2lane[0]; supported_modes = supported_modes_2lane; gc8034->cfg_num = ARRAY_SIZE(supported_modes_2lane); - gc8034_global_regs = gc8034_global_regs_2lane; /*pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */ fps = DIV_ROUND_CLOSEST(gc8034->cur_mode->max_fps.denominator, gc8034->cur_mode->max_fps.numerator); @@ -2580,6 +3066,10 @@ struct v4l2_subdev *sd; char facing[2]; int ret; + struct device_node *eeprom_ctrl_node; + struct i2c_client *eeprom_ctrl_client; + struct v4l2_subdev *eeprom_ctrl; + struct otp_info *otp_ptr; dev_info(dev, "driver version: %02x.%02x.%02x", DRIVER_VERSION >> 16, @@ -2661,10 +3151,40 @@ ret = gc8034_check_sensor_id(gc8034, client); if (ret) goto err_power_off; - +#ifdef RK_OTP + eeprom_ctrl_node = of_parse_phandle(node, "eeprom-ctrl", 0); + if (eeprom_ctrl_node) { + eeprom_ctrl_client = + of_find_i2c_device_by_node(eeprom_ctrl_node); + of_node_put(eeprom_ctrl_node); + if (IS_ERR_OR_NULL(eeprom_ctrl_client)) { + dev_err(dev, "can not get node\n"); + goto continue_probe; + } + eeprom_ctrl = i2c_get_clientdata(eeprom_ctrl_client); + if (IS_ERR_OR_NULL(eeprom_ctrl)) { + dev_err(dev, "can not get eeprom i2c client\n"); + } else { + otp_ptr = devm_kzalloc(dev, sizeof(*otp_ptr), GFP_KERNEL); + if (!otp_ptr) + return -ENOMEM; + ret = v4l2_subdev_call(eeprom_ctrl, + core, ioctl, 0, otp_ptr); + if (!ret) { + gc8034->otp = otp_ptr; + } else { + gc8034->otp = NULL; + devm_kfree(dev, otp_ptr); + dev_warn(dev, "can not get otp info, skip!\n"); + } + } + } +continue_probe: +#else gc8034_otp_enable(gc8034); gc8034_otp_read(gc8034); gc8034_otp_disable(gc8034); +#endif #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API sd->internal_ops = &gc8034_internal_ops; -- Gitblit v1.6.2