【Camera專題】Camera驅(qū)動(dòng)源碼全解析_上

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

圖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端模擬增益

log

我們以紅框?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)一名咸魚( ̄︶ ̄)!

Stay hungry始锚,Stay foolish!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末喳逛,一起剝皮案震驚了整個(gè)濱河市瞧捌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌润文,老刑警劉巖姐呐,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異典蝌,居然都是意外死亡曙砂,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門骏掀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鸠澈,“玉大人柱告,你說我怎么就攤上這事⌒Τ拢” “怎么了际度?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)新锈。 經(jīng)常有香客問我甲脏,道長(zhǎng),這世上最難降的妖魔是什么妹笆? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任块请,我火速辦了婚禮,結(jié)果婚禮上拳缠,老公的妹妹穿的比我還像新娘墩新。我一直安慰自己,他們只是感情好窟坐,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布海渊。 她就那樣靜靜地躺著,像睡著了一般哲鸳。 火紅的嫁衣襯著肌膚如雪臣疑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天徙菠,我揣著相機(jī)與錄音讯沈,去河邊找鬼。 笑死婿奔,一個(gè)胖子當(dāng)著我的面吹牛缺狠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播萍摊,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼挤茄,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了冰木?” 一聲冷哼從身側(cè)響起穷劈,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎踊沸,沒想到半個(gè)月后囚衔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡雕沿,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了猴仑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片审轮。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡肥哎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出疾渣,到底是詐尸還是另有隱情篡诽,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布榴捡,位于F島的核電站杈女,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏吊圾。R本人自食惡果不足惜达椰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望项乒。 院中可真熱鬧啰劲,春花似錦、人聲如沸檀何。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽频鉴。三九已至栓辜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間垛孔,已是汗流浹背藕甩。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留似炎,地道東北人辛萍。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像羡藐,于是被迫代替她去往敵國和親贩毕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345