1、手把手?jǐn)]一份驅(qū)動(dòng) 到 點(diǎn)亮 Camera
2辙浑、Camera dtsi 完全解析
3掠械、Camera驅(qū)動(dòng)源碼全解析上
4席揽、Camera驅(qū)動(dòng)源碼全解析下
一.c文件函數(shù)全解析
#define MAX_ANALOG_GAIN 1.0
#define MIN_ANALOG_GAIN 15.5
這2個(gè)值在datasheet(規(guī)格書)血淌,參考圖1
寄存器的值 | gain倍數(shù) |
---|---|
0x0100 (256) | 1 |
··· | ··· |
0x0F80(3968) | 15.5 |
1.sensor 增益的計(jì)算
1.1 sensor_real_to_register_gain
計(jì)算模擬增益在sensor寄存器中對(duì)應(yīng)的值
12 /**
13 * FUNCTION: sensor_real_to_register_gain
14 *
15 * DESCRIPTION: Calcuate sensor analog gain register value
16 **/
17 static unsigned int sensor_real_to_register_gain(float gain)
18 {
19 uint16_t reg_analog_gain;
20 /*限制最大gain為15.5倍矩欠,最小gain為1倍*/
21 if (gain < MIN_ANALOG_GAIN) {//1
22 gain = MIN_ANALOG_GAIN;
23 } else if (gain > MAX_ANALOG_GAIN) {//15.5
24 gain = MAX_ANALOG_GAIN;
25 }
26 gain = (gain) * 256.0;//1倍gain對(duì)應(yīng)256
27 reg_analog_gain = (uint16_t) gain;//計(jì)算寫到sensor 寄存器中的值
28
29 return reg_analog_gain;
30 }
因?yàn)?倍gain 對(duì)應(yīng)到寄存器的值為 0x100(十進(jìn)制:256)
所以 gain = (gain) * 256.0;
特殊情況
18 static uint32_t sensor_real_to_register_gain(float gain) {
19 unsigned int reg_gain = 0;
/*限制最大gain為15.5倍,最小gain為1倍*/
20 if (gain > 15.5) {
21 gain = 15.5;
22 }else if(gain < 1.0){
23 gain = 1.0;
24 } else if (gain <= 2.0f) {
25 gain = ((int)(gain * 16.0f)) / 16.0f;
26 } else if (gain <= 4.0f) {
27 gain = ((int)(gain * 8.0f)) / 8.0f;
28 } else if (gain <= 8.0f) {
29 gain = ((int)(gain * 4.0f)) / 4.0f;
30 } else {
31 gain = ((int)(gain * 2.0f)) / 2.0f;
32 }
33 gain = gain*256.0;//1倍gain對(duì)應(yīng)256
34 reg_gain = (unsigned short)gain;
35 return reg_gain;
36 }
這部分為gain step 的判斷悠夯,因我們的gain step不是線性的癌淮,舉個(gè)例子:sensor analog gain= 4或4.2, ,在曝光時(shí)間一樣的情況下沦补,其亮度是一樣的乳蓄。添加了這部分的代碼,可以保證同一亮度等級(jí)的gain 值歸到一類夕膀,多出來的部分用平臺(tái)端的digital gain來補(bǔ)虚倒,一定程度上可以避免gain step引起的AE閃爍問題。
1.2 sensor_register_to_real_gain
計(jì)算 模擬增益 真實(shí)倍數(shù)的gain
38 /**
39 * FUNCTION: register_to_real_gain
40 *
41 * DESCRIPTION: Calcuate sensor real gain value
42 **/
43 static float sensor_register_to_real_gain(uint32_t RegGain)
44 {
45 float real_gain;
/*限制最大gain寄存器的值為0x0F80产舞,最小為0x100*/
46 if(RegGain>0x0F80){
47 RegGain = 0x0F80;
48 } else if(RegGain<0x100){
49 RegGain = 0x100;
50 }
51 real_gain = (float) (((float)(RegGain))/256.0);//除以256得出幾倍gain
52 return real_gain;
53 }
real_gain = (float) (((float)(寄存器的值))/256.0);
1.3 sensor_digital_gain_calc
計(jì)算 sensor數(shù)字增益
#define MIN_DIGITAL_GAIN 1.0
#define MAX_DIGITAL_GAIN 1.0
從規(guī)格書中或者FAE那里可以知道
寄存器的值 | digital_gain倍數(shù) |
---|---|
0x0400 (1024) | 1 |
··· | ··· |
0x1000(4096) | 4 |
54 /**
55 * FUNCTION: sensor_digital_gain_calc
56 *
57 * DESCRIPTION: Calcuate the sensor digital gain
58 **/
59 static unsigned int sensor_digital_gain_calc(float real_gain, float sensor_real_gain)
60 {
61 unsigned int reg_dig_gain = 0;
62 float real_dig_gain = 0;
63
64 if (real_gain > MAX_ANALOG_GAIN) {//15.5
65 real_dig_gain = real_gain / sensor_real_gain;
66 } else {
67 real_dig_gain = MAX_DIGITAL_GAIN;//1
68 }
69
70 if (real_dig_gain > MAX_DIGITAL_GAIN) {//大于1就會(huì)設(shè)置成1
71 real_dig_gain = MAX_DIGITAL_GAIN;//1
72 }
73
74 reg_dig_gain = (unsigned int)(real_dig_gain * 1024);//計(jì)算對(duì)應(yīng)的reg_dig_gain
75
76 return reg_dig_gain;
77 }
因?yàn)閿?shù)字增益補(bǔ)償都在平臺(tái)端做了裹刮,所以sensor端的數(shù)字增益補(bǔ)償就不需要了。
因此MAX_DIGITAL_GAIN 1.0設(shè)置成1倍庞瘸。
reg_dig_gain = (unsigned int)(real_dig_gain * 1024);
real_dig_gain 結(jié)果是1,reg_dig_gain = 1x1024 =1024 也就是一倍數(shù)字增益.
看一下相關(guān)log
最暗環(huán)境下:
real_gain =23.675781 > 15.5 = MAX_ANALOG_GAIN
real_dig_gain(數(shù)字增益) = real_gain / sensor_real_gain=23.675781/15.5=1.527470;
real_dig_gain >1
因此 real_dig_gain = MAX_DIGITAL_GAIN=1;//1
最亮環(huán)境下:
同理赠叼,
real_gain = 1.0 < MAX_ANALOG_GAIN = 15.5時(shí)
real_dig_gain = MAX_DIGITAL_GAIN=1;//1
因此sensor_digital_gain_calc算出了最后就是1x1024 = 1024
2.sensor曝光時(shí)間的計(jì)算
55 /**
56 * FUNCTION: sensor_calculate_exposure
57 *
58 * DESCRIPTION: Calcuate the sensor exposure
59 **/
60 int32_t sensor_calculate_exposure(
61 __attribute__((unused)) float real_gain,
62 __attribute__((unused)) uint32_t line_count,
63 __attribute__((unused)) sensor_exposure_info_t *exp_info,
64 __attribute__((unused)) float s_real_gain) {
65 if (!exp_info) {
66 return -1;
67 }
68 MLOG("exposure real_gain %f line_count %d", real_gain, line_count);
69 //計(jì)算模擬增益 對(duì)應(yīng) 寄存器的值
70 exp_info->reg_gain = sensor_real_to_register_gain(real_gain);
//計(jì)算模擬增益 真實(shí)值
71 exp_info->sensor_real_gain =
72 register_to_real_gain(exp_info->reg_gain);
//計(jì)算數(shù)字增益
73 exp_info->sensor_digital_gain = 0x400;//一倍數(shù)字gain 1024
74 exp_info->sensor_real_dig_gain = 1.0f;//no sensor digital gain
//當(dāng)然你也可以直接調(diào)用函數(shù)擦囊,不過函數(shù)返回的永遠(yuǎn)是1024,結(jié)果是一樣的
// exp_info->sensor_digital_gain =
// sensor_digital_gain_calc(real_gain, exp_info->sensor_real_gain);//結(jié)果為1024
// exp_info->sensor_real_dig_gain =
// (float)exp_info->sensor_digital_gain / 1024;//結(jié)果為 1
//計(jì)算平臺(tái)數(shù)字增益
76 exp_info->digital_gain = real_gain / exp_info->sensor_real_gain;
77 exp_info->line_count = line_count;//曝光行數(shù)
78 return 0;
79 }
1.sensor_digital_gain 和 sensor_real_dig_gain
這2個(gè)值代表的sensor端的數(shù)字增益嘴办,
但是數(shù)字增益現(xiàn)在都是平臺(tái)端做瞬场,所以sensor端不用。
因此這兩個(gè)值寫成什么都不會(huì)產(chǎn)生任何影響涧郊,不寫也行贯被。
驅(qū)動(dòng)源碼沒有對(duì)sensor 的digital_gain寄存器寫入任何值,所以sensor端不會(huì)生效。
2. exp_info->digital_gain:平臺(tái)端數(shù)字增益
exp_info->digital_gain = real_gain / exp_info->sensor_real_gain;
平臺(tái)端數(shù)字增益=需要的真實(shí)增益/sensor端模擬增益
我們以紅框?yàn)槔油睿?jì)算一下:
-
exp_info->reg_gain :sensor端 模擬增益 對(duì)應(yīng) 寄存器的值
exp_info->reg_gain =sensor_real_to_register_gain(23.675781);
23.675781 > 15.5看幼,sensor端模擬增益最大只能做15.5
exp_info->reg_gain = 15.5x256 = 3968 -
exp_info->sensor_real_gain:sensor端 模擬增益
exp_info->sensor_real_gain = register_to_real_gain(exp_info->reg_gain);
exp_info->sensor_real_gain = register_to_real_gain(3968);
exp_info->sensor_real_gain = 3968/256=15.5
exp_info->digital_gain:平臺(tái)端數(shù)字增益
exp_info->digital_gain
= real_gain / exp_info->sensor_real_gain;
=23.675781/15.5
=1.5274
這里分別就算出了sensor端需要補(bǔ)償?shù)哪M增益和平臺(tái)端需要補(bǔ)償?shù)臄?shù)字增益,
exp_info->digital_gain =1.5274會(huì)在ISP端自己做補(bǔ)償
但是exp_info->sensor_real_gain=15.5需要寫到sensor寄存器中才能生效幌陕。
因此就有了下面的函數(shù)
3.模擬增益 寫入sensor寄存器
81 /**
82 * FUNCTION: sensor_fill_exposure_array
83 *
84 * DESCRIPTION: Fill the sensor exposure array
85 **/
86 int32_t sensor_fill_exposure_array(
87 __attribute__((unused)) uint32_t gain,
88 __attribute__((unused)) uint32_t digital_gain,
89 __attribute__((unused)) uint32_t line,
90 __attribute__((unused)) uint32_t fl_lines,
91 __attribute__((unused)) int32_t luma_avg,
92 __attribute__((unused)) uint32_t hdr_param,
93 __attribute__((unused)) struct camera_i2c_reg_setting* reg_setting,
94 __attribute__((unused)) unsigned int s_gain,
95 __attribute__((unused)) int s_linecount,
96 __attribute__((unused)) int is_hdr_enabled) {
97 uint16_t i = 0;
98 uint16_t reg_count = 0;
99
100 if (!reg_setting) {
101 return -1;
102 }
103 MLOG("gain %d line %d f_line %d", gain, line, fl_lines);
//開啟sensor 端的group 功能诵姜,將曝光(line),gain等打包搏熄,保證在同一幀下進(jìn)去棚唆。
104 for (i = 0; i < sensor_lib_ptr.groupon_settings.size; i++) {
105 reg_setting->reg_setting[reg_count].reg_addr =
106 sensor_lib_ptr.groupon_settings.reg_setting_a[i].reg_addr;
107 reg_setting->reg_setting[reg_count].reg_data =
108 sensor_lib_ptr.groupon_settings.reg_setting_a[i].reg_data;
109 reg_setting->reg_setting[reg_count].delay =
110 sensor_lib_ptr.groupon_settings.reg_setting_a[i].delay;
111 reg_count++;
112 }
113 reg_setting->reg_setting[reg_count].reg_addr =
114 sensor_lib_ptr.output_reg_addr.frame_length_lines;//frame_length_lines高8位地址
115 reg_setting->reg_setting[reg_count].reg_data = (fl_lines & 0xFF00) >> 8;
116 reg_setting->reg_setting[reg_count].delay = 0;
117 reg_count++;
118
119 reg_setting->reg_setting[reg_count].reg_addr =
120 sensor_lib_ptr.output_reg_addr.frame_length_lines + 1;//frame_length_lines低8位地址
121 reg_setting->reg_setting[reg_count].reg_data = (fl_lines & 0xFF);
122 reg_setting->reg_setting[reg_count].delay = 0;
123 reg_count++;
124
125 reg_setting->reg_setting[reg_count].reg_addr =
126 sensor_lib_ptr.exp_gain_info.coarse_int_time_addr;//曝光寄存器的地址3500
127 reg_setting->reg_setting[reg_count].reg_data = (line & 0xFF0000) >> 16;
128 reg_setting->reg_setting[reg_count].delay = 0;
129 reg_count++;
130
131 reg_setting->reg_setting[reg_count].reg_addr =
132 sensor_lib_ptr.exp_gain_info.coarse_int_time_addr + 1;//曝光寄存器的地址3501
133 reg_setting->reg_setting[reg_count].reg_data = (line & 0xFF00) >> 8;
134 reg_setting->reg_setting[reg_count].delay = 0;
135 reg_count++;
136
137 reg_setting->reg_setting[reg_count].reg_addr =
138 sensor_lib_ptr.exp_gain_info.coarse_int_time_addr + 2;//曝光寄存器的地址3502
139 reg_setting->reg_setting[reg_count].reg_data = (line & 0xFF);
140 reg_setting->reg_setting[reg_count].delay = 0;
141 reg_count++;
142
143 reg_setting->reg_setting[reg_count].reg_addr =
144 sensor_lib_ptr.exp_gain_info.global_gain_addr;
//模擬增益寄存器的地址3508
145 reg_setting->reg_setting[reg_count].reg_data = (gain & 0xFF00) >> 8;
146 reg_setting->reg_setting[reg_count].delay = 0;
147 reg_count++;
//模擬增益寄存器的地址3509
149 reg_setting->reg_setting[reg_count].reg_addr =
150 sensor_lib_ptr.exp_gain_info.global_gain_addr + 1;
151 reg_setting->reg_setting[reg_count].reg_data = (gain & 0xFF);
152 reg_setting->reg_setting[reg_count].delay = 0;
153 reg_count++;
154 //關(guān)閉sensor 端的group 功能
155 for (i = 0; i < sensor_lib_ptr.groupoff_settings.size; i++) {
156 reg_setting->reg_setting[reg_count].reg_addr =
157 sensor_lib_ptr.groupoff_settings.reg_setting_a[i].reg_addr;
158 reg_setting->reg_setting[reg_count].reg_data =
159 sensor_lib_ptr.groupoff_settings.reg_setting_a[i].reg_data;
160 reg_setting->reg_setting[reg_count].delay =
161 sensor_lib_ptr.groupoff_settings.reg_setting_a[i].delay;
162 reg_count++;
163 }
164
165
166 reg_setting->size = reg_count;
167 reg_setting->addr_type = CAMERA_I2C_WORD_ADDR;
168 reg_setting->data_type = CAMERA_I2C_BYTE_DATA;
169 reg_setting->delay = 0;
170 return 0;
171 }
這里我們只是把所有的配置信息寫入了camera_i2c_reg_setting這個(gè)結(jié)構(gòu)體,真正寫入寄存器的是下面這個(gè)操作:
sensor_write_i2c_setting 通過IOCTL給內(nèi)核發(fā)了一個(gè)指令:VIDIOC_MSM_SENSOR_CFG
LOG_IOCTL(ctrl->s_data->fd, VIDIOC_MSM_SENSOR_CFG, &cfg, "write_i2c")
最終調(diào)用到內(nèi)核方法msm_sensor_config
特殊情況:
因?yàn)镺V5675 這顆sensor比較特殊心例, exposure is twice as before宵凌,Ex. [3501,3502]=0040 means 8 Tline exposure。
總結(jié)
1.sensor模擬增益
sensor_real_to_register_gain 模擬增益真實(shí)值止后,如1倍gain 2.2倍gain
sensor_register_to_real_gain 模擬增益對(duì)應(yīng)的sensor寄存器的值:如1倍gain 對(duì)應(yīng)256
2.sensor 數(shù)字增益
sensor_digital_gain_calc:返回的是1倍digital_gain的值
由于數(shù)字增益在都在平臺(tái)端做瞎惫,sensor端不再補(bǔ)償。
3.sensor曝光函數(shù)計(jì)算:
sensor端最大做15.5倍模擬增益坯门,超過的部分平臺(tái)端做數(shù)字增益補(bǔ)償微饥!
4.寫入sensor寄存器
sensor_fill_exposure_array只把寄存器信息填充到camera_i2c_reg_setting,
最終通過內(nèi)核寫入sensor
AEC 算法使用實(shí)際增益古戴。由于必須將傳感器硬件的實(shí)際增益轉(zhuǎn)換為寄存器增益才能配置傳
感器欠橘,因此,我們必須基于傳感器數(shù)據(jù)表實(shí)現(xiàn)以下函數(shù)现恼。參考傳感器數(shù)據(jù)表中的模擬和數(shù)
字增益設(shè)置部分肃续。
xxxx_real_to_register_gain()
xxxx_register_to_real_gain()
下列函數(shù)用于計(jì)算下一次曝光配置的曝光時(shí)間和增益。
xxxx_calculate_exposure()
以下函數(shù)用于準(zhǔn)備下一次曝光配置的數(shù)組叉袍。
xxxx_fill_exposure_array()
繼續(xù)當(dāng)一名咸魚( ̄︶ ̄)!