kernel-brax3-ubuntu-touch/drivers/misc/mediatek/imgsensor/src-v4l2/adaptor-subdrv-ctrl.c
erascape f319b992b1 kernel-5.15: Initial import brax3 UT kernel
* halium configs enabled

Signed-off-by: erascape <erascape@proton.me>
2025-09-23 15:17:10 +00:00

2175 lines
64 KiB
C

// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2022 MediaTek Inc.
#include <linux/videodev2.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/fs.h>
#include <linux/atomic.h>
#include <linux/types.h>
#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;
}