// SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2022 MediaTek Inc. #include #include #include #include #include #include #include #include #include #include "kd_camera_typedef.h" #include "kd_imgsensor.h" #include "kd_imgsensor_define_v4l2.h" #include "kd_imgsensor_errcode.h" #include "adaptor-subdrv-ctrl.h" #include "adaptor-i2c.h" #include "adaptor.h" void check_current_scenario_id_bound(struct subdrv_ctx *ctx) { if (ctx->current_scenario_id >= ctx->s_ctx.sensor_mode_num) { DRV_LOGE(ctx, "invalid cur_sid:%u, mode_num:%u set default\n", ctx->current_scenario_id, ctx->s_ctx.sensor_mode_num); ctx->current_scenario_id = 0; } } void i2c_table_write(struct subdrv_ctx *ctx, u16 *list, u32 len) { switch (ctx->s_ctx.i2c_transfer_data_type) { case I2C_DT_ADDR_16_DATA_16: subdrv_i2c_wr_regs_u16(ctx, list, len); break; case I2C_DT_ADDR_16_DATA_8: default: subdrv_i2c_wr_regs_u8(ctx, list, len); break; } } static void dump_i2c_buf(struct subdrv_ctx *ctx) { int i, j; char *out_str = NULL; char *strptr = NULL; size_t buf_size = SUBDRV_I2C_BUF_SIZE * sizeof(char); size_t remind = buf_size; int num = 0; out_str = kzalloc(buf_size + 1, GFP_KERNEL); if (!out_str) return; strptr = out_str; for (i = 0, j = i; ctx->_size_to_write > (i + 1); i += 2) { num = snprintf(strptr, remind, "[0x%04x, 0x%04x] ", ctx->_i2c_data[i], ctx->_i2c_data[i + 1]); if (num <= 0) { DRV_LOG(ctx, "snprintf return negative at line %d\n", __LINE__); kfree(out_str); return; } remind -= num; strptr += num; if (remind <= 20) { DRV_LOG(ctx, "write idx %d to %d: %s\n", j, i + 1, out_str); j = i + 2; strptr = out_str; remind = buf_size; } } if (ctx->_size_to_write > i) { num = snprintf(strptr, remind, "[0x%04x]", ctx->_i2c_data[i]); if (num <= 0) { DRV_LOG(ctx, "snprintf return negative at line %d\n", __LINE__); kfree(out_str); return; } i++; remind -= num; strptr += num; } if (strptr != out_str) { DRV_LOG(ctx, "write idx %d to %d: %s\n", j, i - 1, out_str); strptr = out_str; remind = buf_size; } kfree(out_str); } #define DUMP_I2C_BUF_IF_DEBUG(ctx) do { \ struct v4l2_subdev *_sd = NULL; \ struct adaptor_ctx *_adaptor_ctx = NULL; \ if (ctx->i2c_client) \ _sd = i2c_get_clientdata(ctx->i2c_client); \ if (_sd) \ _adaptor_ctx = to_ctx(_sd); \ if (_adaptor_ctx && (_adaptor_ctx)->subdrv \ && unlikely(*((_adaptor_ctx)->sensor_debug_flag))) { \ dump_i2c_buf(ctx); \ } \ } while (0) void commit_i2c_buffer(struct subdrv_ctx *ctx) { if (ctx->_size_to_write && !ctx->fast_mode_on) { subdrv_i2c_wr_regs_u8(ctx, ctx->_i2c_data, ctx->_size_to_write); DUMP_I2C_BUF_IF_DEBUG(ctx); memset(ctx->_i2c_data, 0x0, sizeof(ctx->_i2c_data)); ctx->_size_to_write = 0; } } void set_i2c_buffer(struct subdrv_ctx *ctx, u16 reg, u16 val) { if (ctx->_size_to_write + 2 >= SUBDRV_I2C_BUF_SIZE) { DRV_LOGE(ctx, "i2c buffer is full and forced to commit\n"); commit_i2c_buffer(ctx); } if (!ctx->fast_mode_on) { ctx->_i2c_data[ctx->_size_to_write++] = reg; ctx->_i2c_data[ctx->_size_to_write++] = val; } } u16 i2c_read_eeprom(struct subdrv_ctx *ctx, u16 addr) { u16 get_byte = 0; u16 idx = ctx->eeprom_index; u8 write_id = ctx->s_ctx.eeprom_info[idx].i2c_write_id; adaptor_i2c_rd_u8(ctx->i2c_client, write_id >> 1, addr, (u8 *)&get_byte); return get_byte; } void get_pdaf_reg_setting(struct subdrv_ctx *ctx, u32 regNum, u16 *regDa) { int i, idx; for (i = 0; i < regNum; i++) { idx = 2 * i; regDa[idx + 1] = subdrv_i2c_rd_u8(ctx, regDa[idx]); } DRV_LOG(ctx, "register num:%u\n", regNum); } void set_pdaf_reg_setting(struct subdrv_ctx *ctx, u32 regNum, u16 *regDa) { subdrv_i2c_wr_regs_u8(ctx, regDa, regNum*2); } void set_mirror_flip(struct subdrv_ctx *ctx, u8 image_mirror) { u8 itemp = 0; if (ctx->s_ctx.reg_addr_mirror_flip == PARAM_UNDEFINED) { DRV_LOG(ctx, "sensor no support\n"); return; } itemp = subdrv_i2c_rd_u8(ctx, ctx->s_ctx.reg_addr_mirror_flip) & ~0x03; switch (image_mirror) { case IMAGE_NORMAL: itemp |= 0x00; break; case IMAGE_V_MIRROR: itemp |= 0x02; break; case IMAGE_H_MIRROR: itemp |= 0x01; break; case IMAGE_HV_MIRROR: itemp |= 0x03; break; default: DRV_LOGE(ctx, "there is something wrong. mirror:%u\n", image_mirror); break; } subdrv_i2c_wr_u8(ctx, ctx->s_ctx.reg_addr_mirror_flip, itemp); DRV_LOG(ctx, "mirror:%u\n", image_mirror); } bool probe_eeprom(struct subdrv_ctx *ctx) { u32 eeprom_num = 0; u16 idx = 0; u32 header_id = 0; u32 addr_header_id = 0; struct eeprom_info_struct *info = ctx->s_ctx.eeprom_info; if (info == NULL) { DRV_LOG(ctx, "sensor no support eeprom\n"); return FALSE; } ctx->eeprom_index = 0; eeprom_num = ctx->s_ctx.eeprom_num; for (idx = 0; idx < eeprom_num; idx++) { ctx->eeprom_index = idx; addr_header_id = info[idx].addr_header_id; header_id = i2c_read_eeprom(ctx, addr_header_id) | (i2c_read_eeprom(ctx, addr_header_id + 1) << 8) | (i2c_read_eeprom(ctx, addr_header_id + 2) << 16) | (i2c_read_eeprom(ctx, addr_header_id + 3) << 24); DRV_LOG(ctx, "eeprom index[cur/total]:%u/%u, header id[cur/exp]:0x%08x/0x%08x\n", idx, eeprom_num, header_id, info[idx].header_id); if (header_id == info[idx].header_id) { DRV_LOG(ctx, "probe done. index:%u\n", idx); return TRUE; } } DRV_LOGE(ctx, "probe failed! no match eeprom device\n"); return FALSE; } void read_sensor_Cali(struct subdrv_ctx *ctx) { u16 idx = 0; u8 support = FALSE; u8 *buf = NULL; u16 size = 0; u16 addr = 0; int i = 0; struct eeprom_info_struct *info = ctx->s_ctx.eeprom_info; /* Probe EEPROM device */ if (!probe_eeprom(ctx)) return; idx = ctx->eeprom_index; /* QSC data */ support = info[idx].qsc_support; size = info[idx].qsc_size; addr = info[idx].addr_qsc; buf = info[idx].qsc_table; if (support && size > 0) { if (info[idx].preload_qsc_table == NULL) { info[idx].preload_qsc_table = kmalloc(size, GFP_KERNEL); if (buf == NULL) { for (i = 0; i < size; i++) *(info[idx].preload_qsc_table + i) = i2c_read_eeprom(ctx, addr + i); } else { memcpy(info[idx].preload_qsc_table, buf, size); } DRV_LOG(ctx, "preload QSC data %u bytes", size); } else { DRV_LOG(ctx, "QSC data is already preloaded %u bytes", size); } } /* PDC data */ support = info[idx].pdc_support; size = info[idx].pdc_size; addr = info[idx].addr_pdc; buf = info[idx].pdc_table; if (support && size > 0) { if (info[idx].preload_pdc_table == NULL) { info[idx].preload_pdc_table = kmalloc(size, GFP_KERNEL); if (buf == NULL) { for (i = 0; i < size; i++) *(info[idx].preload_pdc_table + i) = i2c_read_eeprom(ctx, addr + i); } else { memcpy(info[idx].preload_pdc_table, buf, size); } DRV_LOG(ctx, "preload PDC data %u bytes", size); } else { DRV_LOG(ctx, "PDC data is already preloaded %u bytes", size); } } /* LRC data */ support = info[idx].lrc_support; size = info[idx].lrc_size; addr = info[idx].addr_lrc; buf = info[idx].lrc_table; if (support && size > 0) { if (info[idx].preload_lrc_table == NULL) { info[idx].preload_lrc_table = kmalloc(size, GFP_KERNEL); if (buf == NULL) { for (i = 0; i < size; i++) *(info[idx].preload_lrc_table + i) = i2c_read_eeprom(ctx, addr + i); } else { memcpy(info[idx].preload_lrc_table, buf, size); } DRV_LOG(ctx, "preload LRC data %u bytes", size); } else { DRV_LOG(ctx, "LRC data is already preloaded %u bytes", size); } } /* XTALK data */ support = info[idx].xtalk_support; size = info[idx].xtalk_size; addr = info[idx].addr_xtalk; buf = info[idx].xtalk_table; if (support && size > 0) { if (info[idx].preload_xtalk_table == NULL) { info[idx].preload_xtalk_table = kmalloc(size, GFP_KERNEL); if (buf == NULL) { for (i = 0; i < size; i++) *(info[idx].preload_xtalk_table + i) = i2c_read_eeprom(ctx, addr + i); } else { memcpy(info[idx].preload_xtalk_table, buf, size); } DRV_LOG(ctx, "preload XTALK data %u bytes", size); } else { DRV_LOG(ctx, "XTALK data is already preloaded %u bytes", size); } } ctx->is_read_preload_eeprom = 1; } void write_sensor_Cali(struct subdrv_ctx *ctx) { DRV_LOG(ctx, "no calibration data applied to sensor."); } void check_frame_length_limitation(struct subdrv_ctx *ctx) { DRV_LOG(ctx, "no calibration data applied to sensor."); } void write_frame_length(struct subdrv_ctx *ctx, u32 fll) { u32 addr_h = ctx->s_ctx.reg_addr_frame_length.addr[0]; u32 addr_l = ctx->s_ctx.reg_addr_frame_length.addr[1]; u32 addr_ll = ctx->s_ctx.reg_addr_frame_length.addr[2]; u32 fll_step = 0; u32 dol_cnt = 1; check_current_scenario_id_bound(ctx); fll_step = ctx->s_ctx.mode[ctx->current_scenario_id].framelength_step; if (fll_step) fll = round_up(fll, fll_step); ctx->frame_length = fll; switch (ctx->s_ctx.mode[ctx->current_scenario_id].hdr_mode) { case HDR_RAW_STAGGER_2EXP: dol_cnt = 2; break; case HDR_RAW_STAGGER_3EXP: dol_cnt = 3; break; default: break; } fll = fll / dol_cnt; if (ctx->extend_frame_length_en == FALSE) { if (addr_ll) { set_i2c_buffer(ctx, addr_h, (fll >> 16) & 0xFF); set_i2c_buffer(ctx, addr_l, (fll >> 8) & 0xFF); set_i2c_buffer(ctx, addr_ll, fll & 0xFF); } else { set_i2c_buffer(ctx, addr_h, (fll >> 8) & 0xFF); set_i2c_buffer(ctx, addr_l, fll & 0xFF); } DRV_LOG(ctx, "fll[0x%x] multiply %u, fll_step:%u\n", fll, dol_cnt, fll_step); } } void set_dummy(struct subdrv_ctx *ctx) { bool gph = !ctx->is_seamless && (ctx->s_ctx.s_gph != NULL); if (gph) ctx->s_ctx.s_gph((void *)ctx, 1); write_frame_length(ctx, ctx->frame_length); if (gph) ctx->s_ctx.s_gph((void *)ctx, 0); commit_i2c_buffer(ctx); } void set_frame_length(struct subdrv_ctx *ctx, u16 frame_length) { bool gph = !ctx->is_seamless && (ctx->s_ctx.s_gph != NULL); if (frame_length) ctx->frame_length = frame_length; ctx->frame_length = max(ctx->frame_length, ctx->min_frame_length); ctx->frame_length = min(ctx->frame_length, ctx->s_ctx.frame_length_max); if (gph) ctx->s_ctx.s_gph((void *)ctx, 1); write_frame_length(ctx, ctx->frame_length); if (gph) ctx->s_ctx.s_gph((void *)ctx, 0); commit_i2c_buffer(ctx); DRV_LOG(ctx, "fll(input/output/min):%u/%u/%u\n", frame_length, ctx->frame_length, ctx->min_frame_length); } void set_max_framerate(struct subdrv_ctx *ctx, u16 framerate, bool min_framelength_en) { u32 frame_length = 0; if (framerate && ctx->line_length) frame_length = ctx->pclk / framerate * 10 / ctx->line_length; ctx->frame_length = max(frame_length, ctx->min_frame_length); ctx->frame_length = min(ctx->frame_length, ctx->s_ctx.frame_length_max); if (ctx->frame_length && ctx->line_length) ctx->current_fps = ctx->pclk / ctx->frame_length * 10 / ctx->line_length; if (min_framelength_en) ctx->min_frame_length = ctx->frame_length; DRV_LOG(ctx, "max_fps(input/output):%u/%u, min_fl_en:%u\n", framerate, ctx->current_fps, min_framelength_en); } /* set_max_framerate */ void set_max_framerate_by_scenario(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id, u32 framerate) { u32 frame_length; u32 frame_length_step; if (scenario_id >= ctx->s_ctx.sensor_mode_num) { DRV_LOG(ctx, "invalid sid:%u, mode_num:%u\n", scenario_id, ctx->s_ctx.sensor_mode_num); scenario_id = SENSOR_SCENARIO_ID_NORMAL_PREVIEW; } if (framerate == 0) { DRV_LOG(ctx, "framerate (%u) is invalid\n", framerate); return; } if (ctx->s_ctx.mode[scenario_id].linelength == 0) { DRV_LOG(ctx, "linelength (%u) is invalid\n", ctx->s_ctx.mode[scenario_id].linelength); return; } frame_length = ctx->s_ctx.mode[scenario_id].pclk / framerate * 10 / ctx->s_ctx.mode[scenario_id].linelength; frame_length_step = ctx->s_ctx.mode[scenario_id].framelength_step; frame_length = frame_length_step ? (frame_length - (frame_length % frame_length_step)) : frame_length; ctx->frame_length = max(frame_length, ctx->s_ctx.mode[scenario_id].framelength); ctx->frame_length = min(ctx->frame_length, ctx->s_ctx.frame_length_max); ctx->current_fps = ctx->pclk / ctx->frame_length * 10 / ctx->line_length; ctx->min_frame_length = ctx->frame_length; DRV_LOG(ctx, "max_fps(input/output):%u/%u(sid:%u), min_fl_en:1\n", framerate, ctx->current_fps, scenario_id); if (ctx->s_ctx.reg_addr_auto_extend || (ctx->frame_length > (ctx->exposure[0] + ctx->s_ctx.exposure_margin))) set_dummy(ctx); } bool set_auto_flicker(struct subdrv_ctx *ctx, bool min_framelength_en) { u16 framerate = 0; if (!ctx->line_length) { DRV_LOGE(ctx, "line_length(%u) is invalid\n", ctx->line_length); return FALSE; } if (!ctx->frame_length) { DRV_LOGE(ctx, "frame_length(%u) is invalid\n", ctx->frame_length); return FALSE; } framerate = ctx->pclk / ctx->line_length * 10 / ctx->frame_length; DRV_LOG(ctx, "cur_fps:%u, flick_en:%u, min_fl_en:%u\n", framerate, ctx->autoflicker_en, min_framelength_en); if (!ctx->autoflicker_en) return FALSE; if (framerate > 592 && framerate <= 607) set_max_framerate(ctx, 592, min_framelength_en); else if (framerate > 296 && framerate <= 305) set_max_framerate(ctx, 296, min_framelength_en); else if (framerate > 246 && framerate <= 253) set_max_framerate(ctx, 246, min_framelength_en); else if (framerate > 236 && framerate <= 243) set_max_framerate(ctx, 236, min_framelength_en); else if (framerate > 146 && framerate <= 153) set_max_framerate(ctx, 146, min_framelength_en); else return FALSE; return TRUE; } void set_long_exposure(struct subdrv_ctx *ctx) { u32 shutter = ctx->exposure[IMGSENSOR_STAGGER_EXPOSURE_LE]; u16 l_shift = 0; if (shutter > (ctx->s_ctx.frame_length_max - ctx->s_ctx.exposure_margin)) { if (ctx->s_ctx.long_exposure_support == FALSE) { DRV_LOGE(ctx, "sensor no support of exposure lshift!\n"); return; } if (ctx->s_ctx.reg_addr_exposure_lshift == PARAM_UNDEFINED) { DRV_LOGE(ctx, "please implement lshift register address\n"); return; } for (l_shift = 1; l_shift < 7; l_shift++) { if ((shutter >> l_shift) < (ctx->s_ctx.frame_length_max - ctx->s_ctx.exposure_margin)) break; } if (l_shift > 7) { DRV_LOGE(ctx, "unable to set exposure:%u, set to max\n", shutter); l_shift = 7; } shutter = shutter >> l_shift; if (!ctx->s_ctx.reg_addr_auto_extend) ctx->frame_length = shutter + ctx->s_ctx.exposure_margin; DRV_LOG(ctx, "long exposure mode: lshift %u times", l_shift); set_i2c_buffer(ctx, ctx->s_ctx.reg_addr_exposure_lshift, l_shift); /* Frame exposure mode customization for LE*/ ctx->ae_frm_mode.frame_mode_1 = IMGSENSOR_AE_MODE_SE; ctx->ae_frm_mode.frame_mode_2 = IMGSENSOR_AE_MODE_SE; ctx->current_ae_effective_frame = 2; } else { if (ctx->s_ctx.reg_addr_exposure_lshift != PARAM_UNDEFINED) set_i2c_buffer(ctx, ctx->s_ctx.reg_addr_exposure_lshift, l_shift); ctx->current_ae_effective_frame = 2; } ctx->exposure[IMGSENSOR_STAGGER_EXPOSURE_LE] = shutter; } void set_shutter(struct subdrv_ctx *ctx, u32 shutter) { set_shutter_frame_length(ctx, shutter, 0); } void set_shutter_frame_length(struct subdrv_ctx *ctx, u32 shutter, u32 frame_length) { u32 fine_integ_line = 0; bool gph = !ctx->is_seamless && (ctx->s_ctx.s_gph != NULL); ctx->frame_length = frame_length ? frame_length : ctx->frame_length; check_current_scenario_id_bound(ctx); /* check boundary of shutter */ fine_integ_line = ctx->s_ctx.mode[ctx->current_scenario_id].fine_integ_line; shutter = FINE_INTEG_CONVERT(shutter, fine_integ_line); shutter = max(shutter, ctx->s_ctx.exposure_min); shutter = min(shutter, ctx->s_ctx.exposure_max); /* check boundary of framelength */ ctx->frame_length = max(shutter + ctx->s_ctx.exposure_margin, ctx->min_frame_length); ctx->frame_length = min(ctx->frame_length, ctx->s_ctx.frame_length_max); /* restore shutter */ memset(ctx->exposure, 0, sizeof(ctx->exposure)); ctx->exposure[0] = shutter; /* group hold start */ if (gph) ctx->s_ctx.s_gph((void *)ctx, 1); /* enable auto extend */ if (ctx->s_ctx.reg_addr_auto_extend) set_i2c_buffer(ctx, ctx->s_ctx.reg_addr_auto_extend, 0x01); /* write framelength */ if (set_auto_flicker(ctx, 0) || frame_length || !ctx->s_ctx.reg_addr_auto_extend) write_frame_length(ctx, ctx->frame_length); /* write shutter */ set_long_exposure(ctx); if (ctx->s_ctx.reg_addr_exposure[0].addr[2]) { set_i2c_buffer(ctx, ctx->s_ctx.reg_addr_exposure[0].addr[0], (ctx->exposure[0] >> 16) & 0xFF); set_i2c_buffer(ctx, ctx->s_ctx.reg_addr_exposure[0].addr[1], (ctx->exposure[0] >> 8) & 0xFF); set_i2c_buffer(ctx, ctx->s_ctx.reg_addr_exposure[0].addr[2], ctx->exposure[0] & 0xFF); } else { set_i2c_buffer(ctx, ctx->s_ctx.reg_addr_exposure[0].addr[0], (ctx->exposure[0] >> 8) & 0xFF); set_i2c_buffer(ctx, ctx->s_ctx.reg_addr_exposure[0].addr[1], ctx->exposure[0] & 0xFF); } DRV_LOG(ctx, "exp[0x%x], fll(input/output):%u/%u, flick_en:%u\n", ctx->exposure[0], frame_length, ctx->frame_length, ctx->autoflicker_en); if (!ctx->ae_ctrl_gph_en) { if (gph) ctx->s_ctx.s_gph((void *)ctx, 0); commit_i2c_buffer(ctx); } /* group hold end */ } void set_hdr_tri_shutter(struct subdrv_ctx *ctx, u64 *shutters, u16 exp_cnt) { int i = 0; u32 values[3] = {0}; if (shutters != NULL) { for (i = 0; i < 3; i++) values[i] = (u32) *(shutters + i); } set_multi_shutter_frame_length(ctx, values, exp_cnt, 0); } void set_multi_shutter_frame_length(struct subdrv_ctx *ctx, u32 *shutters, u16 exp_cnt, u16 frame_length) { int i = 0; u32 fine_integ_line = 0; u16 last_exp_cnt = 1; u32 calc_fl[3] = {0}; int readout_diff = 0; bool gph = !ctx->is_seamless && (ctx->s_ctx.s_gph != NULL); u32 rg_shutters[3] = {0}; u32 cit_step = 0; ctx->frame_length = frame_length ? frame_length : ctx->frame_length; if (exp_cnt > ARRAY_SIZE(ctx->exposure)) { DRV_LOGE(ctx, "invalid exp_cnt:%u>%u\n", exp_cnt, ARRAY_SIZE(ctx->exposure)); exp_cnt = ARRAY_SIZE(ctx->exposure); } check_current_scenario_id_bound(ctx); /* check boundary of shutter */ for (i = 1; i < ARRAY_SIZE(ctx->exposure); i++) last_exp_cnt += ctx->exposure[i] ? 1 : 0; fine_integ_line = ctx->s_ctx.mode[ctx->current_scenario_id].fine_integ_line; cit_step = ctx->s_ctx.mode[ctx->current_scenario_id].coarse_integ_step; for (i = 0; i < exp_cnt; i++) { shutters[i] = FINE_INTEG_CONVERT(shutters[i], fine_integ_line); shutters[i] = max(shutters[i], ctx->s_ctx.exposure_min); shutters[i] = min(shutters[i], ctx->s_ctx.exposure_max); if (cit_step) shutters[i] = round_up(shutters[i], cit_step); } /* check boundary of framelength */ /* - (1) previous se + previous me + current le */ calc_fl[0] = shutters[0]; for (i = 1; i < last_exp_cnt; i++) calc_fl[0] += ctx->exposure[i]; calc_fl[0] += ctx->s_ctx.exposure_margin*exp_cnt*exp_cnt; /* - (2) current se + current me + current le */ calc_fl[1] = shutters[0]; for (i = 1; i < exp_cnt; i++) calc_fl[1] += shutters[i]; calc_fl[1] += ctx->s_ctx.exposure_margin*exp_cnt*exp_cnt; /* - (3) readout time cannot be overlapped */ calc_fl[2] = (ctx->s_ctx.mode[ctx->current_scenario_id].readout_length + ctx->s_ctx.mode[ctx->current_scenario_id].read_margin); if (last_exp_cnt == exp_cnt) for (i = 1; i < exp_cnt; i++) { readout_diff = ctx->exposure[i] - shutters[i]; calc_fl[2] += readout_diff > 0 ? readout_diff : 0; } for (i = 0; i < ARRAY_SIZE(calc_fl); i++) ctx->frame_length = max(ctx->frame_length, calc_fl[i]); ctx->frame_length = max(ctx->frame_length, ctx->min_frame_length); ctx->frame_length = min(ctx->frame_length, ctx->s_ctx.frame_length_max); /* restore shutter */ memset(ctx->exposure, 0, sizeof(ctx->exposure)); for (i = 0; i < exp_cnt; i++) ctx->exposure[i] = shutters[i]; /* group hold start */ if (gph) ctx->s_ctx.s_gph((void *)ctx, 1); /* enable auto extend */ if (ctx->s_ctx.reg_addr_auto_extend) set_i2c_buffer(ctx, ctx->s_ctx.reg_addr_auto_extend, 0x01); /* write framelength */ if (set_auto_flicker(ctx, 0) || frame_length || !ctx->s_ctx.reg_addr_auto_extend) write_frame_length(ctx, ctx->frame_length); /* write shutter */ switch (exp_cnt) { case 1: rg_shutters[0] = shutters[0] / exp_cnt; break; case 2: rg_shutters[0] = shutters[0] / exp_cnt; rg_shutters[2] = shutters[1] / exp_cnt; break; case 3: rg_shutters[0] = shutters[0] / exp_cnt; rg_shutters[1] = shutters[1] / exp_cnt; rg_shutters[2] = shutters[2] / exp_cnt; break; default: break; } if (ctx->s_ctx.reg_addr_exposure_lshift != PARAM_UNDEFINED) set_i2c_buffer(ctx, ctx->s_ctx.reg_addr_exposure_lshift, 0); for (i = 0; i < 3; i++) { if (rg_shutters[i]) { if (ctx->s_ctx.reg_addr_exposure[i].addr[2]) { set_i2c_buffer(ctx, ctx->s_ctx.reg_addr_exposure[i].addr[0], (rg_shutters[i] >> 16) & 0xFF); set_i2c_buffer(ctx, ctx->s_ctx.reg_addr_exposure[i].addr[1], (rg_shutters[i] >> 8) & 0xFF); set_i2c_buffer(ctx, ctx->s_ctx.reg_addr_exposure[i].addr[2], rg_shutters[i] & 0xFF); } else { set_i2c_buffer(ctx, ctx->s_ctx.reg_addr_exposure[i].addr[0], (rg_shutters[i] >> 8) & 0xFF); set_i2c_buffer(ctx, ctx->s_ctx.reg_addr_exposure[i].addr[1], rg_shutters[i] & 0xFF); } } } DRV_LOG(ctx, "exp[0x%x/0x%x/0x%x], fll(input/output):%u/%u, flick_en:%u\n", rg_shutters[0], rg_shutters[1], rg_shutters[2], frame_length, ctx->frame_length, ctx->autoflicker_en); if (!ctx->ae_ctrl_gph_en) { if (gph) ctx->s_ctx.s_gph((void *)ctx, 0); commit_i2c_buffer(ctx); } /* group hold end */ } u16 gain2reg(u32 gain) { return (16384 - (16384 * BASEGAIN) / gain); } void set_gain(struct subdrv_ctx *ctx, u32 gain) { u16 rg_gain; bool gph = !ctx->is_seamless && (ctx->s_ctx.s_gph != NULL); /* check boundary of gain */ gain = max(gain, ctx->s_ctx.ana_gain_min); gain = min(gain, ctx->s_ctx.ana_gain_max); /* mapping of gain to register value */ if (ctx->s_ctx.g_gain2reg != NULL) rg_gain = ctx->s_ctx.g_gain2reg(gain); else rg_gain = gain2reg(gain); /* restore gain */ memset(ctx->ana_gain, 0, sizeof(ctx->ana_gain)); ctx->ana_gain[0] = gain; /* group hold start */ if (gph && !ctx->ae_ctrl_gph_en) ctx->s_ctx.s_gph((void *)ctx, 1); /* write gain */ set_i2c_buffer(ctx, ctx->s_ctx.reg_addr_ana_gain[0].addr[0], (rg_gain >> 8) & 0xFF); set_i2c_buffer(ctx, ctx->s_ctx.reg_addr_ana_gain[0].addr[1], rg_gain & 0xFF); DRV_LOG(ctx, "gain[0x%x]\n", rg_gain); if (gph) ctx->s_ctx.s_gph((void *)ctx, 0); commit_i2c_buffer(ctx); /* group hold end */ } void set_hdr_tri_gain(struct subdrv_ctx *ctx, u64 *gains, u16 exp_cnt) { int i = 0; u32 values[3] = {0}; if (gains != NULL) { for (i = 0; i < 3; i++) values[i] = (u32) *(gains + i); } set_multi_gain(ctx, values, exp_cnt); } void set_multi_gain(struct subdrv_ctx *ctx, u32 *gains, u16 exp_cnt) { int i = 0; u16 rg_gains[3] = {0}; u8 has_gains[3] = {0}; bool gph = !ctx->is_seamless && (ctx->s_ctx.s_gph != NULL); if (exp_cnt > ARRAY_SIZE(ctx->ana_gain)) { DRV_LOGE(ctx, "invalid exp_cnt:%u>%u\n", exp_cnt, ARRAY_SIZE(ctx->ana_gain)); exp_cnt = ARRAY_SIZE(ctx->ana_gain); } for (i = 0; i < exp_cnt; i++) { /* check boundary of gain */ gains[i] = max(gains[i], ctx->s_ctx.ana_gain_min); gains[i] = min(gains[i], ctx->s_ctx.ana_gain_max); /* mapping of gain to register value */ if (ctx->s_ctx.g_gain2reg != NULL) gains[i] = ctx->s_ctx.g_gain2reg(gains[i]); else gains[i] = gain2reg(gains[i]); } /* restore gain */ memset(ctx->ana_gain, 0, sizeof(ctx->ana_gain)); for (i = 0; i < exp_cnt; i++) ctx->ana_gain[i] = gains[i]; /* group hold start */ if (gph && !ctx->ae_ctrl_gph_en) ctx->s_ctx.s_gph((void *)ctx, 1); /* write gain */ memset(has_gains, 1, sizeof(has_gains)); switch (exp_cnt) { case 2: rg_gains[0] = gains[0]; has_gains[1] = 0; rg_gains[2] = gains[1]; break; case 3: rg_gains[0] = gains[0]; rg_gains[1] = gains[1]; rg_gains[2] = gains[2]; break; default: has_gains[0] = 0; has_gains[1] = 0; has_gains[2] = 0; break; } for (i = 0; i < 3; i++) { if (has_gains[i]) { set_i2c_buffer(ctx, ctx->s_ctx.reg_addr_ana_gain[i].addr[0], (rg_gains[i] >> 8) & 0xFF); set_i2c_buffer(ctx, ctx->s_ctx.reg_addr_ana_gain[i].addr[1], rg_gains[i] & 0xFF); } } DRV_LOG(ctx, "reg[lg/mg/sg]: 0x%x 0x%x 0x%x\n", rg_gains[0], rg_gains[1], rg_gains[2]); if (gph) ctx->s_ctx.s_gph((void *)ctx, 0); commit_i2c_buffer(ctx); /* group hold end */ } static u16 dgain2reg(struct subdrv_ctx *ctx, u32 dgain) { u32 step = max((ctx->s_ctx.dig_gain_step), (u32)1); u8 integ = (u8) (dgain / BASE_DGAIN); // integer parts u8 dec = (u8) ((dgain % BASE_DGAIN) / step); // decimal parts u16 ret = ((u16)integ << 8) | dec; DRV_LOG(ctx, "dgain reg = 0x%x\n", ret); return ret; } void set_multi_dig_gain(struct subdrv_ctx *ctx, u32 *gains, u16 exp_cnt) { int i = 0; u16 rg_gains[IMGSENSOR_STAGGER_EXPOSURE_CNT] = {0}; bool gph = !ctx->is_seamless && (ctx->s_ctx.s_gph != NULL); // skip if no porting digital gain if (!ctx->s_ctx.reg_addr_dig_gain[0].addr[0]) return; if (exp_cnt > ARRAY_SIZE(ctx->dig_gain)) { DRV_LOGE(ctx, "invalid exp_cnt:%u>%u\n", exp_cnt, ARRAY_SIZE(ctx->dig_gain)); exp_cnt = ARRAY_SIZE(ctx->dig_gain); } for (i = 0; i < exp_cnt; i++) { /* check boundary of gain */ gains[i] = max(gains[i], ctx->s_ctx.dig_gain_min); gains[i] = min(gains[i], ctx->s_ctx.dig_gain_max); gains[i] = dgain2reg(ctx, gains[i]); } /* restore gain */ memset(ctx->dig_gain, 0, sizeof(ctx->dig_gain)); for (i = 0; i < exp_cnt; i++) ctx->dig_gain[i] = gains[i]; /* group hold start */ if (gph && !ctx->ae_ctrl_gph_en) ctx->s_ctx.s_gph((void *)ctx, 1); /* write gain */ switch (exp_cnt) { case 1: rg_gains[0] = gains[0]; break; case 2: rg_gains[0] = gains[0]; rg_gains[2] = gains[1]; break; case 3: rg_gains[0] = gains[0]; rg_gains[1] = gains[1]; rg_gains[2] = gains[2]; break; default: break; } for (i = 0; (i < ARRAY_SIZE(rg_gains)) && (i < ARRAY_SIZE(ctx->s_ctx.reg_addr_dig_gain)); i++) { if (!rg_gains[i]) continue; // skip zero gain setting if (ctx->s_ctx.reg_addr_dig_gain[i].addr[0]) { set_i2c_buffer(ctx, ctx->s_ctx.reg_addr_dig_gain[i].addr[0], (rg_gains[i] >> 8) & 0x0F); } if (ctx->s_ctx.reg_addr_dig_gain[i].addr[1]) { set_i2c_buffer(ctx, ctx->s_ctx.reg_addr_dig_gain[i].addr[1], rg_gains[i] & 0xFF); } } if (!ctx->ae_ctrl_gph_en) { if (gph) ctx->s_ctx.s_gph((void *)ctx, 0); commit_i2c_buffer(ctx); } DRV_LOG(ctx, "dgain reg[lg/mg/sg]: 0x%x 0x%x 0x%x\n", rg_gains[0], rg_gains[1], rg_gains[2]); } void get_lens_driver_id(struct subdrv_ctx *ctx, u32 *lens_id) { *lens_id = LENS_DRIVER_ID_DO_NOT_CARE; } void check_stream_off(struct subdrv_ctx *ctx) { u32 i = 0, framecnt = 0; int timeout = ctx->current_fps ? (10000 / ctx->current_fps) + 1 : 101; if (!ctx->s_ctx.reg_addr_frame_count) return; for (i = 0; i < timeout; i++) { framecnt = subdrv_i2c_rd_u8(ctx, ctx->s_ctx.reg_addr_frame_count); if (framecnt == 0xFF) return; mdelay(1); } DRV_LOGE(ctx, "stream off fail!\n"); } void streaming_control(struct subdrv_ctx *ctx, bool enable) { check_current_scenario_id_bound(ctx); if (ctx->s_ctx.mode[ctx->current_scenario_id].aov_mode) { DRV_LOG(ctx, "AOV mode set stream in SCP side! (sid:%u)\n", ctx->current_scenario_id); return; } if (enable) { set_dummy(ctx); subdrv_i2c_wr_u8(ctx, ctx->s_ctx.reg_addr_stream, 0x01); } else { subdrv_i2c_wr_u8(ctx, ctx->s_ctx.reg_addr_stream, 0x00); if (ctx->s_ctx.reg_addr_fast_mode && ctx->fast_mode_on) { ctx->fast_mode_on = FALSE; ctx->ref_sof_cnt = 0; DRV_LOG(ctx, "seamless_switch disabled."); set_i2c_buffer(ctx, ctx->s_ctx.reg_addr_fast_mode, 0x00); commit_i2c_buffer(ctx); } memset(ctx->exposure, 0, sizeof(ctx->exposure)); memset(ctx->ana_gain, 0, sizeof(ctx->ana_gain)); ctx->autoflicker_en = FALSE; ctx->extend_frame_length_en = 0; ctx->is_seamless = 0; if (ctx->s_ctx.chk_s_off_end) check_stream_off(ctx); } ctx->is_streaming = enable; DRV_LOG(ctx, "enable:%u\n", enable); } void set_video_mode(struct subdrv_ctx *ctx, u16 framerate) { if (!framerate) return; set_max_framerate(ctx, framerate, 0); set_auto_flicker(ctx, 1); set_dummy(ctx); DRV_LOG(ctx, "fps(input/max):%u/%u\n", framerate, ctx->current_fps); } void set_auto_flicker_mode(struct subdrv_ctx *ctx, bool enable, u16 framerate) { (void) framerate; ctx->autoflicker_en = enable ? TRUE : FALSE; DRV_LOG(ctx, "enable:%u\n", enable); } void get_output_format_by_scenario(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id, u64 *sensor_output_dataformat) { if (scenario_id >= ctx->s_ctx.sensor_mode_num) { DRV_LOG(ctx, "invalid sid:%u, mode_num:%u\n", scenario_id, ctx->s_ctx.sensor_mode_num); return; } *sensor_output_dataformat = (enum ACDK_SENSOR_OUTPUT_DATA_FORMAT_ENUM) ctx->s_ctx.mode[scenario_id].sensor_output_dataformat; } void get_ana_gain_table(struct subdrv_ctx *ctx, u64 *size, void *data) { u32 *gain_table = ctx->s_ctx.ana_gain_table; if (data == NULL) *size = ctx->s_ctx.ana_gain_table_size; else memcpy(data, (void *)gain_table, ctx->s_ctx.ana_gain_table_size); } void get_gain_range_by_scenario(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id, u64 *min_gain, u64 *max_gain) { if (scenario_id >= ctx->s_ctx.sensor_mode_num) { DRV_LOG(ctx, "invalid sid:%u, mode_num:%u\n", scenario_id, ctx->s_ctx.sensor_mode_num); scenario_id = SENSOR_SCENARIO_ID_NORMAL_PREVIEW; } *min_gain = ctx->s_ctx.mode[scenario_id].ana_gain_min; *max_gain = ctx->s_ctx.mode[scenario_id].ana_gain_max; } void get_base_gain_iso_and_step(struct subdrv_ctx *ctx, u64 *min_gain_iso, u64 *gain_step, u64 *gain_type) { *min_gain_iso = ctx->s_ctx.min_gain_iso; *gain_step = ctx->s_ctx.ana_gain_step; *gain_type = ctx->s_ctx.ana_gain_type; } void get_dig_gain_range_by_scenario(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id, u64 *min_dgain, u64 *max_dgain) { if (scenario_id >= ctx->s_ctx.sensor_mode_num) { DRV_LOG(ctx, "invalid sid:%u, mode_num:%u\n", scenario_id, ctx->s_ctx.sensor_mode_num); scenario_id = SENSOR_SCENARIO_ID_NORMAL_PREVIEW; } *min_dgain = ctx->s_ctx.mode[scenario_id].dig_gain_min; *max_dgain = ctx->s_ctx.mode[scenario_id].dig_gain_max; } void get_dig_gain_step(struct subdrv_ctx *ctx, u64 *dgain_step) { *dgain_step = ctx->s_ctx.dig_gain_step; } void get_min_shutter_by_scenario(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id, u64 *min_shutter, u64 *exposure_step) { if (scenario_id >= ctx->s_ctx.sensor_mode_num) { DRV_LOG(ctx, "invalid cur_sid:%u, mode_num:%u set default\n", scenario_id, ctx->s_ctx.sensor_mode_num); scenario_id = 0; } *min_shutter = ctx->s_ctx.exposure_min; if (ctx->s_ctx.mode[scenario_id].coarse_integ_step) { *exposure_step = ctx->s_ctx.mode[scenario_id].coarse_integ_step; } else { switch (ctx->s_ctx.mode[scenario_id].hdr_mode) { case HDR_RAW_STAGGER_2EXP: *exposure_step = ctx->s_ctx.exposure_step*2; break; case HDR_RAW_STAGGER_3EXP: *exposure_step = ctx->s_ctx.exposure_step*3; break; default: *exposure_step = ctx->s_ctx.exposure_step; break; } } } void get_offset_to_start_of_exposure(struct subdrv_ctx *ctx, u32 *offset) { *offset = ctx->s_ctx.start_exposure_offset; } void get_pixel_clock_freq_by_scenario(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id, u32 *pclk) { if (scenario_id >= ctx->s_ctx.sensor_mode_num) { DRV_LOG(ctx, "invalid sid:%u, mode_num:%u\n", scenario_id, ctx->s_ctx.sensor_mode_num); scenario_id = SENSOR_SCENARIO_ID_NORMAL_PREVIEW; } *pclk = ctx->s_ctx.mode[scenario_id].pclk; } void get_period_by_scenario(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id, u32 *period, u64 flag) { u32 ratio = 1; if (scenario_id >= ctx->s_ctx.sensor_mode_num) { DRV_LOG(ctx, "invalid sid:%u, mode_num:%u\n", scenario_id, ctx->s_ctx.sensor_mode_num); scenario_id = SENSOR_SCENARIO_ID_NORMAL_PREVIEW; } if (flag & SENSOR_GET_LINELENGTH_FOR_READOUT) switch (ctx->s_ctx.mode[scenario_id].hdr_mode) { case HDR_RAW_STAGGER_2EXP: ratio = 2; break; case HDR_RAW_STAGGER_3EXP: ratio = 3; break; default: break; } *period = (ctx->s_ctx.mode[scenario_id].framelength << 16) + (ctx->s_ctx.mode[scenario_id].linelength * ratio); } void get_period(struct subdrv_ctx *ctx, u16 *line_length, u16 *frame_length) { *line_length = ctx->line_length; *frame_length = ctx->frame_length; } void get_pixel_clock_freq(struct subdrv_ctx *ctx, u32 *pclk) { *pclk = ctx->pclk; } void get_default_framerate_by_scenario(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id, u32 *framerate) { if (scenario_id >= ctx->s_ctx.sensor_mode_num) { DRV_LOG(ctx, "invalid sid:%u, mode_num:%u\n", scenario_id, ctx->s_ctx.sensor_mode_num); return; } *framerate = ctx->s_ctx.mode[scenario_id].max_framerate; } void get_fine_integ_line_by_scenario(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id, u32 *fine_integ_line) { if (scenario_id >= ctx->s_ctx.sensor_mode_num) { DRV_LOG(ctx, "invalid sid:%u, mode_num:%u\n", scenario_id, ctx->s_ctx.sensor_mode_num); return; } *fine_integ_line = ctx->s_ctx.mode[scenario_id].fine_integ_line; } void set_test_pattern(struct subdrv_ctx *ctx, u32 mode) { DRV_LOG(ctx, "sensor no support."); } void set_test_pattern_data(struct subdrv_ctx *ctx, struct mtk_test_pattern_data *data) { DRV_LOG(ctx, "sensor no support."); } void get_test_pattern_checksum_value(struct subdrv_ctx *ctx, u32 *checksum) { *checksum = ctx->s_ctx.checksum_value; } void set_framerate(struct subdrv_ctx *ctx, u32 framerate) { ctx->current_fps = framerate; DRV_LOG(ctx, "fps:%u\n", ctx->current_fps); } void set_hdr(struct subdrv_ctx *ctx, u32 mode) { ctx->ihdr_mode = mode; DRV_LOG(ctx, "ihdr_mode:%u\n", ctx->ihdr_mode); } void get_crop_info(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id, struct SENSOR_WINSIZE_INFO_STRUCT *wininfo) { if (scenario_id >= ctx->s_ctx.sensor_mode_num) { DRV_LOG(ctx, "invalid sid:%u, mode_num:%u\n", scenario_id, ctx->s_ctx.sensor_mode_num); scenario_id = SENSOR_SCENARIO_ID_NORMAL_PREVIEW; } memcpy((void *)wininfo, (void *)&(ctx->s_ctx.mode[scenario_id].imgsensor_winsize_info), sizeof(struct SENSOR_WINSIZE_INFO_STRUCT)); DRV_LOG(ctx, "sid:%u\n", scenario_id); } void get_pdaf_info(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id, struct SET_PD_BLOCK_INFO_T *pd_info) { if (scenario_id >= ctx->s_ctx.sensor_mode_num) { DRV_LOG(ctx, "invalid sid:%u, mode_num:%u\n", scenario_id, ctx->s_ctx.sensor_mode_num); scenario_id = SENSOR_SCENARIO_ID_NORMAL_PREVIEW; } if (ctx->s_ctx.mode[scenario_id].imgsensor_pd_info != NULL) memcpy((void *)pd_info, (void *)(ctx->s_ctx.mode[scenario_id].imgsensor_pd_info), sizeof(struct SET_PD_BLOCK_INFO_T)); DRV_LOG(ctx, "sid:%u\n", scenario_id); } void get_sensor_pdaf_capacity(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id, u32 *pdaf_cap) { if (scenario_id >= ctx->s_ctx.sensor_mode_num) { *pdaf_cap = 0; DRV_LOG(ctx, "invalid sid:%u, mode_num:%u\n", scenario_id, ctx->s_ctx.sensor_mode_num); return; } *pdaf_cap = ctx->s_ctx.mode[scenario_id].pdaf_cap; DRV_LOG(ctx, "pdaf_cap:%u(sid:%u)\n", *pdaf_cap, scenario_id); } void extend_frame_length(struct subdrv_ctx *ctx, u32 ns) { int i; u32 last_exp_cnt = 1; u32 old_fl = ctx->frame_length; u32 calc_fl = 0; u32 readoutLength = 0; u32 readMargin = 0; u32 per_frame_ns = (u32)(((u64)ctx->frame_length * (u64)ctx->line_length * 1000000000) / (u64)ctx->pclk); check_current_scenario_id_bound(ctx); readoutLength = ctx->s_ctx.mode[ctx->current_scenario_id].readout_length; readMargin = ctx->s_ctx.mode[ctx->current_scenario_id].read_margin; for (i = 1; i < ARRAY_SIZE(ctx->exposure); i++) last_exp_cnt += ctx->exposure[i] ? 1 : 0; if (ns) ctx->frame_length = (u32)(((u64)(per_frame_ns + ns)) * ctx->frame_length / per_frame_ns); if (last_exp_cnt > 1) { calc_fl = (readoutLength + readMargin); for (i = 1; i < last_exp_cnt; i++) calc_fl += (ctx->exposure[i] + ctx->s_ctx.exposure_margin * last_exp_cnt); ctx->frame_length = max(calc_fl, ctx->frame_length); } set_dummy(ctx); ctx->extend_frame_length_en = TRUE; ns = (u32)(((u64)(ctx->frame_length - old_fl) * (u64)ctx->line_length * 1000000000) / (u64)ctx->pclk); DRV_LOG(ctx, "fll(old/new):%u/%u, add %u ns", old_fl, ctx->frame_length, ns); } void seamless_switch(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id, u32 *ae_ctrl) { DRV_LOGE(ctx, "please check get_seamless_scenarios or implement this in sensor driver."); } void get_seamless_scenarios(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id, u32 *pScenarios) { int i = 0; u32 num = 0; u32 group = 0; if (scenario_id >= ctx->s_ctx.sensor_mode_num) { DRV_LOG(ctx, "invalid sid:%u, mode_num:%u\n", scenario_id, ctx->s_ctx.sensor_mode_num); *pScenarios = 0xff; return; } group = ctx->s_ctx.mode[scenario_id].seamless_switch_group; for (i = 0; i < ctx->s_ctx.sensor_mode_num; i++) { if (group != 0 && i != scenario_id && (ctx->s_ctx.mode[i].seamless_switch_group == group)) { *(pScenarios + num) = i; DRV_LOG(ctx, "sid(input/output):%u/%u\n", scenario_id, *(pScenarios + num)); num++; } } if (num == 0) *pScenarios = 0xff; } void get_sensor_hdr_capacity(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id, u32 *hdr_mode) { if (scenario_id >= ctx->s_ctx.sensor_mode_num) { *hdr_mode = HDR_NONE; DRV_LOG(ctx, "invalid sid:%u, mode_num:%u\n", scenario_id, ctx->s_ctx.sensor_mode_num); return; } *hdr_mode = ctx->s_ctx.mode[scenario_id].hdr_mode; DRV_LOG(ctx, "hdr_mode:%u(sid:%u)\n", *hdr_mode, scenario_id); } void get_stagger_target_scenario(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id, enum IMGSENSOR_HDR_MODE_ENUM hdr_mode, u32 *pScenarios) { int i = 0; u32 group = 0; if (ctx->s_ctx.hdr_type == HDR_SUPPORT_NA) return; if (scenario_id >= ctx->s_ctx.sensor_mode_num) { DRV_LOG(ctx, "invalid sid:%u, mode_num:%u\n", scenario_id, ctx->s_ctx.sensor_mode_num); return; } group = ctx->s_ctx.mode[scenario_id].hdr_group; for (i = 0; i < ctx->s_ctx.sensor_mode_num; i++) { if (group != 0 && i != scenario_id && (ctx->s_ctx.mode[i].hdr_group == group) && (ctx->s_ctx.mode[i].hdr_mode == hdr_mode)) { *pScenarios = i; DRV_LOG(ctx, "sid(input/output):%u/%u, hdr_mode:%u\n", scenario_id, *pScenarios, hdr_mode); break; } } } void get_frame_ctrl_info_by_scenario(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id, u32 *margin) { if (scenario_id >= ctx->s_ctx.sensor_mode_num) { DRV_LOG(ctx, "invalid sid:%u, mode_num:%u\n", scenario_id, ctx->s_ctx.sensor_mode_num); scenario_id = SENSOR_SCENARIO_ID_NORMAL_PREVIEW; } *margin = ctx->s_ctx.exposure_margin; } void get_feature_get_4cell_data(struct subdrv_ctx *ctx, u16 type, char *data) { u16 idx = 0; u8 support = FALSE; u8 *pbuf = NULL; u16 size = 0; struct eeprom_info_struct *info = ctx->s_ctx.eeprom_info; if (!probe_eeprom(ctx)) return; idx = ctx->eeprom_index; if (type == FOUR_CELL_CAL_TYPE_XTALK_CAL) { support = info[idx].xtalk_support; pbuf = info[idx].preload_xtalk_table; size = info[idx].xtalk_size; if (support) { data[0] = size & 0xFF; data[1] = (size >> 8) & 0xFF; if (pbuf != NULL && size > 0) { memcpy(data + 2, pbuf, size); DRV_LOG(ctx, "memcpy XTALK data done %u bytes", size); } } } } void get_stagger_max_exp_time(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id, enum VC_FEATURE vc, u64 *exposure_max) { *exposure_max = 0; if (scenario_id >= ctx->s_ctx.sensor_mode_num) { DRV_LOG(ctx, "invalid sid:%u, mode_num:%u\n", scenario_id, ctx->s_ctx.sensor_mode_num); return; } switch (vc) { case VC_STAGGER_ME: if (ctx->s_ctx.mode[scenario_id].hdr_mode == HDR_RAW_STAGGER_2EXP || ctx->s_ctx.mode[scenario_id].hdr_mode == HDR_RAW_STAGGER_3EXP) *exposure_max = ctx->s_ctx.exposure_max; break; case VC_STAGGER_SE: if (ctx->s_ctx.mode[scenario_id].hdr_mode == HDR_RAW_STAGGER_3EXP) *exposure_max = ctx->s_ctx.exposure_max; break; case VC_STAGGER_NE: default: *exposure_max = ctx->s_ctx.exposure_max; break; } } void get_temperature_value(struct subdrv_ctx *ctx, u32 *value) { if (!ctx->s_ctx.temperature_support) { DRV_LOG(ctx, "temperature sensor no support\n"); return; } if (ctx->s_ctx.g_temp == NULL) { DRV_LOGE(ctx, "please implement g_temp function\n"); return; } *value = ctx->s_ctx.g_temp((void *)ctx); DRV_LOG(ctx, "temperature value:%u\n", *value); } void set_pdaf(struct subdrv_ctx *ctx, u16 mode) { ctx->pdaf_mode = mode; DRV_LOG(ctx, "pdaf_mode:%u\n", ctx->pdaf_mode); } void get_binning_type(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id, u32 *binning_ratio) { if (scenario_id >= ctx->s_ctx.sensor_mode_num) { DRV_LOG(ctx, "invalid sid:%u, mode_num:%u\n", scenario_id, ctx->s_ctx.sensor_mode_num); scenario_id = SENSOR_SCENARIO_ID_NORMAL_PREVIEW; } *binning_ratio = ctx->s_ctx.mode[scenario_id].ae_binning_ratio; } void get_ae_frame_mode_for_le(struct subdrv_ctx *ctx, u32 *ae_frm_mode) { memcpy(ae_frm_mode, &ctx->ae_frm_mode, sizeof(struct IMGSENSOR_AE_FRM_MODE)); } void get_ae_effective_frame_for_le(struct subdrv_ctx *ctx, u32 *ae_effective_frame) { *ae_effective_frame = ctx->current_ae_effective_frame; } void preload_eeprom_data(struct subdrv_ctx *ctx, u32 *is_read) { *is_read = ctx->is_read_preload_eeprom; if (!ctx->is_read_preload_eeprom) { DRV_LOG(ctx, "start to preload\n"); if (ctx->s_ctx.g_cali != NULL) ctx->s_ctx.g_cali((void *) ctx); else read_sensor_Cali(ctx); } DRV_LOG(ctx, "already preloaded\n"); } void get_mipi_pixel_rate(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id, u32 *mipi_pixel_rate) { if (scenario_id >= ctx->s_ctx.sensor_mode_num) { DRV_LOG(ctx, "invalid sid:%u, mode_num:%u\n", scenario_id, ctx->s_ctx.sensor_mode_num); scenario_id = SENSOR_SCENARIO_ID_NORMAL_PREVIEW; } *mipi_pixel_rate = ctx->s_ctx.mode[scenario_id].mipi_pixel_rate; } void get_sensor_rgbw_output_mode(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id, u32 *rgbw_output_mode) { if (scenario_id >= ctx->s_ctx.sensor_mode_num) { *rgbw_output_mode = 0; DRV_LOG(ctx, "invalid sid:%u, mode_num:%u\n", scenario_id, ctx->s_ctx.sensor_mode_num); return; } *rgbw_output_mode = ctx->s_ctx.mode[scenario_id].rgbw_output_mode; DRV_LOG(ctx, "rgbw_output_mode:%u(sid:%u)\n", *rgbw_output_mode, scenario_id); } void get_readout_by_scenario(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id, u64 *readout_time) { u32 ratio = 1; if (scenario_id >= ctx->s_ctx.sensor_mode_num) { DRV_LOG(ctx, "invalid sid:%u, mode_num:%u\n", scenario_id, ctx->s_ctx.sensor_mode_num); return; } switch (ctx->s_ctx.mode[scenario_id].hdr_mode) { case HDR_RAW_STAGGER_2EXP: ratio = 2; break; case HDR_RAW_STAGGER_3EXP: ratio = 3; break; default: break; } *readout_time = (u64)((u64)ctx->s_ctx.mode[scenario_id].linelength * ctx->s_ctx.mode[scenario_id].imgsensor_winsize_info.h2_tg_size * 1000000000) / ctx->s_ctx.mode[scenario_id].pclk * ratio; } void get_exposure_count_by_scenario(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id, u32 *scenario_exp_cnt) { u32 exp_cnt = 0; if (scenario_id >= ctx->s_ctx.sensor_mode_num) { DRV_LOG(ctx, "invalid sid:%u, mode_num:%u\n", scenario_id, ctx->s_ctx.sensor_mode_num); return; } switch (ctx->s_ctx.mode[scenario_id].hdr_mode) { case HDR_RAW_STAGGER_2EXP: exp_cnt = 2; break; case HDR_RAW_STAGGER_3EXP: exp_cnt = 3; break; default: exp_cnt = 1; break; } *scenario_exp_cnt = exp_cnt; } int common_get_imgsensor_id(struct subdrv_ctx *ctx, u32 *sensor_id) { u8 i = 0; u8 retry = 2; u32 addr_h = ctx->s_ctx.reg_addr_sensor_id.addr[0]; u32 addr_l = ctx->s_ctx.reg_addr_sensor_id.addr[1]; u32 addr_ll = ctx->s_ctx.reg_addr_sensor_id.addr[2]; while (ctx->s_ctx.i2c_addr_table[i] != 0xFF) { ctx->i2c_write_id = ctx->s_ctx.i2c_addr_table[i]; do { *sensor_id = (subdrv_i2c_rd_u8(ctx, addr_h) << 8) | subdrv_i2c_rd_u8(ctx, addr_l); if (addr_ll) *sensor_id = ((*sensor_id) << 8) | subdrv_i2c_rd_u8(ctx, addr_ll); DRV_LOG(ctx, "i2c_write_id:0x%x sensor_id(cur/exp):0x%x/0x%x\n", ctx->i2c_write_id, *sensor_id, ctx->s_ctx.sensor_id); if (*sensor_id == ctx->s_ctx.sensor_id) return ERROR_NONE; retry--; } while (retry > 0); i++; retry = 2; } if (*sensor_id != ctx->s_ctx.sensor_id) { *sensor_id = 0xFFFFFFFF; return ERROR_SENSOR_CONNECT_FAIL; } return ERROR_NONE; } void subdrv_ctx_init(struct subdrv_ctx *ctx) { int i; ctx->ana_gain_def = ctx->s_ctx.ana_gain_def; ctx->ana_gain_max = ctx->s_ctx.ana_gain_max; ctx->ana_gain_min = ctx->s_ctx.ana_gain_min; ctx->ana_gain_step = ctx->s_ctx.ana_gain_step; ctx->exposure_def = ctx->s_ctx.exposure_def; ctx->exposure_max = ctx->s_ctx.exposure_max; ctx->exposure_min = ctx->s_ctx.exposure_min; ctx->exposure_step = ctx->s_ctx.exposure_step; ctx->frame_time_delay_frame = ctx->s_ctx.frame_time_delay_frame; ctx->margin = ctx->s_ctx.exposure_margin; ctx->max_frame_length = ctx->s_ctx.frame_length_max; ctx->mirror = ctx->s_ctx.mirror; ctx->sensor_mode = 0; ctx->shutter = ctx->s_ctx.exposure_def; ctx->gain = ctx->s_ctx.ana_gain_def; ctx->dummy_pixel = 0; ctx->dummy_line = 0; ctx->current_fps = 300; ctx->autoflicker_en = FALSE; ctx->test_pattern = FALSE; ctx->current_scenario_id = SENSOR_SCENARIO_ID_MIN; ctx->ihdr_mode = 0; ctx->i2c_write_id = 0x20; ctx->readout_length = 0; ctx->read_margin = 0; ctx->current_ae_effective_frame = ctx->s_ctx.ae_effective_frame; ctx->extend_frame_length_en = FALSE; ctx->ae_ctrl_gph_en = FALSE; for (i = 0; i < ctx->s_ctx.sensor_mode_num ; i++) { if (!ctx->s_ctx.mode[i].sensor_output_dataformat) ctx->s_ctx.mode[i].sensor_output_dataformat = ctx->s_ctx.sensor_output_dataformat; if (!ctx->s_ctx.mode[i].ana_gain_min) ctx->s_ctx.mode[i].ana_gain_min = ctx->s_ctx.ana_gain_min; if (!ctx->s_ctx.mode[i].ana_gain_max) ctx->s_ctx.mode[i].ana_gain_max = ctx->s_ctx.ana_gain_max; if (!ctx->s_ctx.mode[i].dig_gain_min) ctx->s_ctx.mode[i].dig_gain_min = ctx->s_ctx.dig_gain_min; if (!ctx->s_ctx.mode[i].dig_gain_max) ctx->s_ctx.mode[i].dig_gain_max = ctx->s_ctx.dig_gain_max; if (!ctx->s_ctx.mode[i].min_exposure_line) ctx->exposure_min = ctx->s_ctx.mode[i].min_exposure_line; } } void sensor_init(struct subdrv_ctx *ctx) { /* write init setting */ if (ctx->s_ctx.init_setting_table != NULL) { DRV_LOG_MUST(ctx, "E: size:%u\n", ctx->s_ctx.init_setting_len); i2c_table_write(ctx, ctx->s_ctx.init_setting_table, ctx->s_ctx.init_setting_len); DRV_LOG(ctx, "X: size:%u\n", ctx->s_ctx.init_setting_len); } else { DRV_LOGE(ctx, "please implement initial setting!\n"); } /* enable temperature sensor */ if (ctx->s_ctx.temperature_support && ctx->s_ctx.reg_addr_temp_en) subdrv_i2c_wr_u8(ctx, ctx->s_ctx.reg_addr_temp_en, 0x01); /* enable mirror or flip */ set_mirror_flip(ctx, ctx->mirror); } int common_open(struct subdrv_ctx *ctx) { u32 sensor_id = 0; u32 scenario_id = 0; /* get sensor id */ if (common_get_imgsensor_id(ctx, &sensor_id) != ERROR_NONE) return ERROR_SENSOR_CONNECT_FAIL; /* initail setting */ sensor_init(ctx); if (ctx->s_ctx.s_cali != NULL) ctx->s_ctx.s_cali((void *) ctx); else write_sensor_Cali(ctx); memset(ctx->exposure, 0, sizeof(ctx->exposure)); memset(ctx->ana_gain, 0, sizeof(ctx->gain)); ctx->exposure[0] = ctx->s_ctx.exposure_def; ctx->ana_gain[0] = ctx->s_ctx.ana_gain_def; ctx->current_scenario_id = scenario_id; ctx->pclk = ctx->s_ctx.mode[scenario_id].pclk; ctx->line_length = ctx->s_ctx.mode[scenario_id].linelength; ctx->frame_length = ctx->s_ctx.mode[scenario_id].framelength; ctx->current_fps = 10 * ctx->pclk / ctx->line_length / ctx->frame_length; ctx->readout_length = ctx->s_ctx.mode[scenario_id].readout_length; ctx->read_margin = ctx->s_ctx.mode[scenario_id].read_margin; ctx->min_frame_length = ctx->frame_length; ctx->autoflicker_en = FALSE; ctx->test_pattern = 0; ctx->ihdr_mode = 0; ctx->pdaf_mode = 0; ctx->hdr_mode = 0; ctx->extend_frame_length_en = 0; ctx->is_seamless = 0; ctx->fast_mode_on = 0; ctx->sof_cnt = 0; ctx->ref_sof_cnt = 0; ctx->is_streaming = 0; return ERROR_NONE; } int common_get_info(struct subdrv_ctx *ctx, enum MSDK_SCENARIO_ID_ENUM scenario_id, MSDK_SENSOR_INFO_STRUCT *sensor_info, MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) { int i = 0; (void) sensor_config_data; if (scenario_id >= ctx->s_ctx.sensor_mode_num) { DRV_LOG(ctx, "invalid sid:%u, mode_num:%u\n", scenario_id, ctx->s_ctx.sensor_mode_num); scenario_id = SENSOR_SCENARIO_ID_NORMAL_PREVIEW; } else { DRV_LOG(ctx, "sid:%u\n", scenario_id); } sensor_info->SensorClockPolarity = SENSOR_CLOCK_POLARITY_LOW; sensor_info->SensorClockFallingPolarity = SENSOR_CLOCK_POLARITY_LOW; sensor_info->SensorHsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; sensor_info->SensorVsyncPolarity = SENSOR_CLOCK_POLARITY_LOW; sensor_info->SensroInterfaceType = ctx->s_ctx.sensor_interface_type; sensor_info->MIPIsensorType = ctx->s_ctx.mipi_sensor_type; sensor_info->SensorOutputDataFormat = ctx->s_ctx.mode[scenario_id].sensor_output_dataformat; for (i = 0; i < ctx->s_ctx.sensor_mode_num; i++) sensor_info->DelayFrame[i] = ctx->s_ctx.mode[i].delay_frame; sensor_info->SensorDrivingCurrent = ctx->s_ctx.isp_driving_current; sensor_info->IHDR_Support = 0; sensor_info->IHDR_LE_FirstLine = 0; sensor_info->TEMPERATURE_SUPPORT = ctx->s_ctx.temperature_support; sensor_info->SensorModeNum = ctx->s_ctx.sensor_mode_num; sensor_info->PDAF_Support = ctx->s_ctx.pdaf_type; sensor_info->HDR_Support = ctx->s_ctx.hdr_type; sensor_info->RGBW_Support = ctx->s_ctx.rgbw_support; sensor_info->SensorMIPILaneNumber = ctx->s_ctx.mipi_lane_num; sensor_info->SensorClockFreq = ctx->s_ctx.mclk; sensor_info->SensorClockRisingCount = 0; sensor_info->SensorWidthSampling = 0; sensor_info->SensorHightSampling = 0; sensor_info->SensorPacketECCOrder = 1; sensor_info->FrameTimeDelayFrame = ctx->s_ctx.frame_time_delay_frame; sensor_info->OB_pedestal = ctx->s_ctx.ob_pedestal; return ERROR_NONE; } int common_get_resolution(struct subdrv_ctx *ctx, MSDK_SENSOR_RESOLUTION_INFO_STRUCT *sensor_resolution) { int i; for (i = 0; i < ctx->s_ctx.sensor_mode_num; i++) { sensor_resolution->SensorWidth[i] = ctx->s_ctx.mode[i].imgsensor_winsize_info.w2_tg_size; sensor_resolution->SensorHeight[i] = ctx->s_ctx.mode[i].imgsensor_winsize_info.h2_tg_size; } return ERROR_NONE; } void update_mode_info(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id) { ctx->current_scenario_id = scenario_id; ctx->pclk = ctx->s_ctx.mode[scenario_id].pclk; ctx->line_length = ctx->s_ctx.mode[scenario_id].linelength; ctx->frame_length = ctx->s_ctx.mode[scenario_id].framelength; ctx->current_fps = 10 * ctx->pclk / ctx->line_length / ctx->frame_length; ctx->readout_length = ctx->s_ctx.mode[scenario_id].readout_length; ctx->read_margin = ctx->s_ctx.mode[scenario_id].read_margin; ctx->min_frame_length = ctx->frame_length; ctx->autoflicker_en = FALSE; } bool check_is_no_crop(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id) { struct SENSOR_WINSIZE_INFO_STRUCT *pinfo; if (scenario_id >= ctx->s_ctx.sensor_mode_num) { DRV_LOG(ctx, "invalid sid:%u, mode_num:%u\n", scenario_id, ctx->s_ctx.sensor_mode_num); return false; } pinfo = &(ctx->s_ctx.mode[scenario_id].imgsensor_winsize_info); return (pinfo->w0_size == pinfo->scale_w && pinfo->h0_size == pinfo->scale_h); } int common_control(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *image_window, MSDK_SENSOR_CONFIG_STRUCT *sensor_config_data) { int ret = ERROR_NONE; u16 idx = 0; u8 support = FALSE; u8 *pbuf = NULL; u16 size = 0; u16 addr = 0; struct eeprom_info_struct *info = ctx->s_ctx.eeprom_info; if (scenario_id >= ctx->s_ctx.sensor_mode_num) { DRV_LOG(ctx, "invalid sid:%u, mode_num:%u\n", scenario_id, ctx->s_ctx.sensor_mode_num); scenario_id = SENSOR_SCENARIO_ID_NORMAL_PREVIEW; ret = ERROR_INVALID_SCENARIO_ID; } if (ctx->s_ctx.chk_s_off_sta) check_stream_off(ctx); update_mode_info(ctx, scenario_id); if (ctx->s_ctx.mode[scenario_id].mode_setting_table != NULL) { DRV_LOG_MUST(ctx, "E: sid:%u size:%u\n", scenario_id, ctx->s_ctx.mode[scenario_id].mode_setting_len); i2c_table_write(ctx, ctx->s_ctx.mode[scenario_id].mode_setting_table, ctx->s_ctx.mode[scenario_id].mode_setting_len); DRV_LOG(ctx, "X: sid:%u size:%u\n", scenario_id, ctx->s_ctx.mode[scenario_id].mode_setting_len); } else { DRV_LOGE(ctx, "please implement mode setting(sid:%u)!\n", scenario_id); } if (check_is_no_crop(ctx, scenario_id) && probe_eeprom(ctx)) { idx = ctx->eeprom_index; support = info[idx].xtalk_support; pbuf = info[idx].preload_xtalk_table; size = info[idx].xtalk_size; addr = info[idx].sensor_reg_addr_xtalk; if (support) { if (pbuf != NULL && addr > 0 && size > 0) { subdrv_i2c_wr_seq_p8(ctx, addr, pbuf, size); DRV_LOG(ctx, "set XTALK calibration data done."); } } } set_mirror_flip(ctx, ctx->s_ctx.mirror); return ret; } int common_feature_control(struct subdrv_ctx *ctx, MSDK_SENSOR_FEATURE_ENUM feature_id, u8 *feature_para, u32 *feature_para_len) { u16 *feature_data_16 = (u16 *) feature_para; u32 *feature_data_32 = (u32 *) feature_para; u64 *feature_data = (u64 *) feature_para; int i = 0; int ret = ERROR_NONE; if (ctx->s_ctx.list != NULL) { for (i = 0; i < ctx->s_ctx.list_len; i++) if (ctx->s_ctx.list[i].feature_id == feature_id && ctx->s_ctx.list[i].func != NULL) { ctx->s_ctx.list[i].func(ctx, feature_para, feature_para_len); return ERROR_NONE; } } switch (feature_id) { case SENSOR_FEATURE_GET_OUTPUT_FORMAT_BY_SCENARIO: get_output_format_by_scenario(ctx, (enum SENSOR_SCENARIO_ID_ENUM)*(feature_data), feature_data + 1); break; case SENSOR_FEATURE_GET_ANA_GAIN_TABLE: get_ana_gain_table(ctx, feature_data, (void *)(uintptr_t)(*(feature_data + 1))); break; case SENSOR_FEATURE_GET_GAIN_RANGE_BY_SCENARIO: get_gain_range_by_scenario(ctx, (enum SENSOR_SCENARIO_ID_ENUM)*(feature_data), feature_data + 1, feature_data + 2); break; case SENSOR_FEATURE_GET_BASE_GAIN_ISO_AND_STEP: get_base_gain_iso_and_step(ctx, feature_data, feature_data + 1, feature_data + 2); break; case SENSOR_FEATURE_GET_DIG_GAIN_RANGE_BY_SCENARIO: get_dig_gain_range_by_scenario(ctx, (enum SENSOR_SCENARIO_ID_ENUM)*(feature_data), feature_data + 1, feature_data + 2); break; case SENSOR_FEATURE_GET_DIG_GAIN_STEP: get_dig_gain_step(ctx, feature_data); break; case SENSOR_FEATURE_GET_MIN_SHUTTER_BY_SCENARIO: get_min_shutter_by_scenario(ctx, (enum SENSOR_SCENARIO_ID_ENUM)*(feature_data), feature_data + 1, feature_data + 2); break; case SENSOR_FEATURE_GET_OFFSET_TO_START_OF_EXPOSURE: // what is + 0 ? get_offset_to_start_of_exposure(ctx, (u32 *)(uintptr_t)(*(feature_data + 1))); break; case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ_BY_SCENARIO: get_pixel_clock_freq_by_scenario(ctx, (enum SENSOR_SCENARIO_ID_ENUM)*(feature_data), (u32 *)(uintptr_t)(*(feature_data + 1))); break; case SENSOR_FEATURE_GET_PERIOD_BY_SCENARIO: get_period_by_scenario(ctx, (enum SENSOR_SCENARIO_ID_ENUM)*(feature_data), (u32 *)(uintptr_t)(*(feature_data + 1)), *(feature_data + 2)); break; case SENSOR_FEATURE_GET_PERIOD: get_period(ctx, feature_data_16, feature_data_16 + 1); *feature_para_len = 4; break; case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ: get_pixel_clock_freq(ctx, feature_data_32); *feature_para_len = 4; break; case SENSOR_FEATURE_SET_ESHUTTER: set_shutter(ctx, *feature_data); break; case SENSOR_FEATURE_SET_NIGHTMODE: break; case SENSOR_FEATURE_SET_GAIN: set_gain(ctx, *feature_data); break; case SENSOR_FEATURE_SET_FLASHLIGHT: break; case SENSOR_FEATURE_SET_ISP_MASTER_CLOCK_FREQ: break; case SENSOR_FEATURE_SET_REGISTER: subdrv_i2c_wr_u8(ctx, ((MSDK_SENSOR_REG_INFO_STRUCT *)feature_para)->RegAddr, ((MSDK_SENSOR_REG_INFO_STRUCT *)feature_para)->RegData); break; case SENSOR_FEATURE_GET_REGISTER: ((MSDK_SENSOR_REG_INFO_STRUCT *)feature_para)->RegData = subdrv_i2c_rd_u8(ctx, ((MSDK_SENSOR_REG_INFO_STRUCT *)feature_para)->RegAddr); break; case SENSOR_FEATURE_GET_LENS_DRIVER_ID: get_lens_driver_id(ctx, feature_data_32); *feature_para_len = 4; break; case SENSOR_FEATURE_SET_VIDEO_MODE: set_video_mode(ctx, *feature_data); break; case SENSOR_FEATURE_CHECK_SENSOR_ID: ret = common_get_imgsensor_id(ctx, feature_data_32); break; case SENSOR_FEATURE_SET_AUTO_FLICKER_MODE: set_auto_flicker_mode(ctx, (bool)*feature_data_16, *(feature_data_16 + 1)); break; case SENSOR_FEATURE_SET_MAX_FRAME_RATE_BY_SCENARIO: set_max_framerate_by_scenario(ctx, (enum SENSOR_SCENARIO_ID_ENUM)*feature_data, *(feature_data + 1)); break; case SENSOR_FEATURE_GET_DEFAULT_FRAME_RATE_BY_SCENARIO: get_default_framerate_by_scenario(ctx, (enum SENSOR_SCENARIO_ID_ENUM)*feature_data, (u32 *)(uintptr_t)(*(feature_data + 1))); break; case SENSOR_FEATURE_GET_FINE_INTEG_LINE_BY_SCENARIO: get_fine_integ_line_by_scenario(ctx, (enum SENSOR_SCENARIO_ID_ENUM)*feature_data, (u32 *)(uintptr_t)(*(feature_data + 1))); break; case SENSOR_FEATURE_GET_PDAF_DATA: break; case SENSOR_FEATURE_SET_TEST_PATTERN: set_test_pattern(ctx, *feature_data); break; case SENSOR_FEATURE_SET_TEST_PATTERN_DATA: set_test_pattern_data(ctx, (struct mtk_test_pattern_data *)feature_data); break; case SENSOR_FEATURE_GET_TEST_PATTERN_CHECKSUM_VALUE: get_test_pattern_checksum_value(ctx, feature_data_32); *feature_para_len = 4; break; case SENSOR_FEATURE_SET_FRAMERATE: set_framerate(ctx, *feature_data_32); break; case SENSOR_FEATURE_SET_HDR: set_hdr(ctx, *feature_data_32); break; case SENSOR_FEATURE_GET_CROP_INFO: get_crop_info(ctx, *feature_data_32, (struct SENSOR_WINSIZE_INFO_STRUCT *)(uintptr_t)(*(feature_data + 1))); break; case SENSOR_FEATURE_GET_PDAF_INFO: get_pdaf_info(ctx, *feature_data_32, (struct SET_PD_BLOCK_INFO_T *)(uintptr_t)(*(feature_data + 1))); break; case SENSOR_FEATURE_GET_SENSOR_PDAF_CAPACITY: get_sensor_pdaf_capacity(ctx, *feature_data_32, (u32 *)(uintptr_t)(*(feature_data + 1))); break; case SENSOR_FEATURE_SET_SEAMLESS_EXTEND_FRAME_LENGTH: extend_frame_length(ctx, (u32) *feature_data); break; case SENSOR_FEATURE_SEAMLESS_SWITCH: if ((feature_data + 1) != NULL) seamless_switch(ctx, (*feature_data), (u32 *)((uintptr_t)(*(feature_data + 1)))); else { DRV_LOGE(ctx, "no ae_ctrl input\n"); seamless_switch(ctx, (*feature_data), NULL); } break; case SENSOR_FEATURE_GET_SEAMLESS_SCENARIOS: if ((feature_data + 1) != NULL) get_seamless_scenarios(ctx, *feature_data, (u32 *)((uintptr_t)(*(feature_data + 1)))); else { DRV_LOGE(ctx, "input pScenarios vector is NULL!\n"); return ERROR_INVALID_SCENARIO_ID; } break; case SENSOR_FEATURE_GET_SENSOR_HDR_CAPACITY: get_sensor_hdr_capacity(ctx, *feature_data_32, (u32 *)(uintptr_t)(*(feature_data + 1))); break; case SENSOR_FEATURE_GET_VC_INFO2: break; case SENSOR_FEATURE_GET_STAGGER_TARGET_SCENARIO: get_stagger_target_scenario(ctx, (enum SENSOR_SCENARIO_ID_ENUM)*feature_data, (enum IMGSENSOR_HDR_MODE_ENUM)*(feature_data + 1), (u32 *)(feature_data + 2)); break; case SENSOR_FEATURE_GET_FRAME_CTRL_INFO_BY_SCENARIO: *(feature_data + 1) = 1; get_frame_ctrl_info_by_scenario(ctx, (enum SENSOR_SCENARIO_ID_ENUM)*feature_data, (u32 *)(feature_data + 2)); break; case SENSOR_FEATURE_GET_4CELL_DATA: get_feature_get_4cell_data(ctx, (u16)(*feature_data), (char *)(uintptr_t)(*(feature_data + 1))); break; case SENSOR_FEATURE_GET_MAX_EXP_LINE: case SENSOR_FEATURE_GET_STAGGER_MAX_EXP_TIME: get_stagger_max_exp_time(ctx, *feature_data, *(feature_data + 1), (feature_data + 2)); break; case SENSOR_FEATURE_SET_HDR_SHUTTER: set_hdr_tri_shutter(ctx, feature_data, 2); break; case SENSOR_FEATURE_SET_DUAL_GAIN: set_hdr_tri_gain(ctx, feature_data, 2); break; case SENSOR_FEATURE_SET_HDR_TRI_SHUTTER: set_hdr_tri_shutter(ctx, feature_data, 3); break; case SENSOR_FEATURE_SET_HDR_TRI_GAIN: set_hdr_tri_gain(ctx, feature_data, 3); break; case SENSOR_FEATURE_SET_MULTI_DIG_GAIN: set_multi_dig_gain(ctx, (u32 *)(*feature_data), (u16) (*(feature_data + 1))); break; case SENSOR_FEATURE_GET_TEMPERATURE_VALUE: get_temperature_value(ctx, feature_data_32); *feature_para_len = 4; break; case SENSOR_FEATURE_GET_PDAF_REG_SETTING: get_pdaf_reg_setting(ctx, (*feature_para_len)/sizeof(u32), feature_data_16); break; case SENSOR_FEATURE_SET_PDAF_REG_SETTING: set_pdaf_reg_setting(ctx, (*feature_para_len)/sizeof(u32), feature_data_16); break; case SENSOR_FEATURE_SET_PDAF: set_pdaf(ctx, *feature_data_16); break; case SENSOR_FEATURE_SET_SHUTTER_FRAME_TIME: set_shutter_frame_length(ctx, (u32) (*feature_data), (u32) (*(feature_data + 1))); break; case SENSOR_FEATURE_SET_IHDR_SHUTTER_GAIN: break; case SENSOR_FEATURE_SET_AWB_GAIN: break; case SENSOR_FEATURE_SET_STREAMING_SUSPEND: streaming_control(ctx, FALSE); break; case SENSOR_FEATURE_SET_STREAMING_RESUME: if (*feature_data) set_shutter(ctx, *feature_data); streaming_control(ctx, TRUE); break; case SENSOR_FEATURE_GET_BINNING_TYPE: get_binning_type(ctx, *(feature_data + 1), feature_data_32); *feature_para_len = 4; break; case SENSOR_FEATURE_GET_AE_FRAME_MODE_FOR_LE: get_ae_frame_mode_for_le(ctx, feature_data_32); break; case SENSOR_FEATURE_GET_AE_EFFECTIVE_FRAME_FOR_LE: get_ae_effective_frame_for_le(ctx, feature_data_32); break; case SENSOR_FEATURE_GET_MIPI_PIXEL_RATE: get_mipi_pixel_rate(ctx, *feature_data, (u32 *)(uintptr_t)(*(feature_data + 1))); break; case SENSOR_FEATURE_PRELOAD_EEPROM_DATA: preload_eeprom_data(ctx, feature_data_32); *feature_para_len = 4; break; case SENSOR_FEATURE_SET_FRAMELENGTH: set_frame_length(ctx, (u16) (*feature_data)); break; case SENSOR_FEATURE_SET_MULTI_SHUTTER_FRAME_TIME: set_multi_shutter_frame_length(ctx, (u32 *)(*feature_data), (u16) (*(feature_data + 1)), (u16) (*(feature_data + 2))); break; case SENSOR_FEATURE_GET_SENSOR_RGBW_OUTPUT_MODE: get_sensor_rgbw_output_mode(ctx, *feature_data_32, (u32 *)(uintptr_t)(*(feature_data + 1))); break; case SENSOR_FEATURE_GET_READOUT_BY_SCENARIO: get_readout_by_scenario(ctx, (enum SENSOR_SCENARIO_ID_ENUM)*feature_data, feature_data + 1); break; case SENSOR_FEATURE_GET_EXPOSURE_COUNT_BY_SCENARIO: get_exposure_count_by_scenario(ctx, (enum SENSOR_SCENARIO_ID_ENUM)*feature_data, (u32 *)(feature_data + 1)); break; default: break; } return ERROR_NONE; } int common_close(struct subdrv_ctx *ctx) { streaming_control(ctx, FALSE); DRV_LOG(ctx, "subdrv closed\n"); return ERROR_NONE; } int common_get_frame_desc(struct subdrv_ctx *ctx, int scenario_id, struct mtk_mbus_frame_desc *fd) { int ret = 0; if (scenario_id >= ctx->s_ctx.sensor_mode_num) { DRV_LOG(ctx, "invalid scenario_id(%u)\n", scenario_id); return -1; } if (ctx->s_ctx.mode[scenario_id].frame_desc != NULL) { fd->type = MTK_MBUS_FRAME_DESC_TYPE_CSI2; fd->num_entries = ctx->s_ctx.mode[scenario_id].num_entries; memcpy(fd->entry, ctx->s_ctx.mode[scenario_id].frame_desc, sizeof(struct mtk_mbus_frame_desc_entry)*fd->num_entries); } else ret = -1; return ret; } int common_get_temp(struct subdrv_ctx *ctx, int *temp) { if (!ctx->s_ctx.temperature_support) { DRV_LOG(ctx, "temperature sensor no support\n"); return -1; // Need confirm if -1. } if (ctx->s_ctx.g_temp == NULL) { DRV_LOGE(ctx, "please implement g_temp function\n"); return -1; // Need confirm if -1. } *temp = ctx->s_ctx.g_temp((void *)ctx) * 1000; return 0; } int common_get_csi_param(struct subdrv_ctx *ctx, enum SENSOR_SCENARIO_ID_ENUM scenario_id, struct mtk_csi_param *csi_param) { if (scenario_id >= ctx->s_ctx.sensor_mode_num) { DRV_LOG(ctx, "invalid sid:%u, mode_num:%u\n", scenario_id, ctx->s_ctx.sensor_mode_num); return 0; } memcpy(csi_param, &(ctx->s_ctx.mode[scenario_id].csi_param), sizeof(struct mtk_csi_param)); return 0; } int common_update_sof_cnt(struct subdrv_ctx *ctx, u32 sof_cnt) { DRV_LOG(ctx, "update ctx->sof_cnt(%u)", sof_cnt); ctx->sof_cnt = sof_cnt; return 0; }