日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

【Camera专题】Qcom-高通OTP完全调试指南-上

發(fā)布時(shí)間:2025/7/25 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Camera专题】Qcom-高通OTP完全调试指南-上 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、前言

關(guān)于高通OTP編程的知識(shí),網(wǎng)上少得可憐,官方文檔又沒有那么清晰,于是就來一篇干貨吧! OTP編程完全指南分上、下2篇。 上:主要講OTP的知識(shí)和調(diào)試流程。 下:主要講OTP的源碼。

本文知識(shí)點(diǎn):

  • 1.OTP的基本概念
  • 2.OTP的作用
  • 3.OTP的調(diào)試流程

二、知識(shí)點(diǎn)

1.OTP的基本概念(是什么)

OTP(One Time Programmable)意思是一次性可編程,程序或者數(shù)據(jù)燒入【存儲(chǔ)器】后,將不可再次更改和清除。


OTP燒錄的數(shù)據(jù)類型 一般包括:

  • AF:自動(dòng)對(duì)焦校準(zhǔn)數(shù)據(jù)
  • AWB:白平衡校準(zhǔn)數(shù)據(jù)
  • LSC:鏡頭陰影校準(zhǔn) (Lens Shading Calibration)
  • Moudle Info:模組信息,包含模組的生產(chǎn)年日月,模組ID等

以AF為例子: vendor廠燒錄的AF數(shù)據(jù):

Page:3,Addr:0x01D0,Data:0x00 Page:3,Addr:0x01D8,Data:0x04 Page:3,Addr:0x01E0,Data:0x0F Page:3,Addr:0x01E8,Data:0x0C Page:3,Addr:0x01F0,Data:0x02 Page:3,Addr:0x01F8,Data:0x00 復(fù)制代碼

OTP存儲(chǔ)器的類型 按照調(diào)試的經(jīng)驗(yàn),目前主流的有2種:

  • 1.OTP數(shù)據(jù)燒錄在sensor的寄存器中。 這種方案省錢,不需要額外的存儲(chǔ)器件,但是存儲(chǔ)空間小,如果需要燒錄的數(shù)據(jù)量過大,就不適用。

  • OTP數(shù)據(jù)燒錄在EEPROM 中: EEPROM(Electrically Erasable Programmable read only memory)是指帶電可擦可編程只讀存儲(chǔ)器, 是一種掉電后數(shù)據(jù)不丟失的存儲(chǔ)芯片。 該方案優(yōu)勢(shì)是存儲(chǔ)空間大,如果數(shù)據(jù)量過多,就需要這種方案,缺點(diǎn)是多一個(gè)獨(dú)立的EEPROM存儲(chǔ)器件, 花點(diǎn)錢(5毛錢左右)。

2.OTP的作用(為什么)

OTP是用來給camera sensor做calibration(校準(zhǔn))用的。 因?yàn)槟=M生產(chǎn)出來會(huì)有很大的差異性,為了保證效果一致性, 模組廠會(huì)挑選一部分模組作為golden,然后將其他模組的相應(yīng)參數(shù)校準(zhǔn)到和這些golden一樣, (golden不是最好的模組,也不是最差的模組,而是各方面最平均的模組)。

3.OTP調(diào)試流程(怎么做)

調(diào)試平臺(tái):8909(較為低端)

PS:在高通源碼的OTP指的就是EEPROM驅(qū)動(dòng)。

例子一:以O(shè)V5675為例子(數(shù)據(jù)燒錄在Camera Sensor中)

3.1 OTP調(diào)試準(zhǔn)備工作

  • 從datasheet獲取相關(guān)信息 OTP Datasheet(OV5675 Calibration and OTP Programming Guid) Camera sensor Datasheet(sensor_OV05675-GA4A.pdf) a.弄明白上電時(shí)序(這個(gè)和camera上電時(shí)序是一致的)

b.獲得slave address

硬件上我們這個(gè)pin腳是拉高的,所以I2C addr = 0x20

c.弄清楚讀寫規(guī)則

d.其他

1. 供電:cam_vio-supply = <&pm8916_l10>; 2. clock:clocks = <&clock_gcc clk_mclk0_clk_src>,<&clock_gcc clk_gcc_camss_mclk0_clk>;clock-names = "cam_src_clk", "cam_clk"; 3.GPIO pinsgpios = <&msm_gpio 26 0>,<&msm_gpio 28 0>,<&msm_gpio 33 0>; 復(fù)制代碼

3.2 配置 DTSI文件

EEPROM數(shù)據(jù)在設(shè)備啟動(dòng)時(shí)讀取。需要將內(nèi)存映射轉(zhuǎn)換為dtsi中的對(duì)應(yīng)的屬性節(jié)點(diǎn)。 其中必須指定調(diào)節(jié)器(供電)、時(shí)鐘信號(hào)、電源啟動(dòng)序列、設(shè)備地址和讀取序列。 路徑:kernel/arch/arm/boot/dts/qcom/msm8909-pm8916-camera-sensor-i18.dtsi

eeprom1: qcom,eeprom@20 {cell-index = <1>;/*分配給eeprom subdev,唯一即可*/reg = <0x20>;/*注冊(cè)地址*/qcom,eeprom-name = "ov5675_back";/*eeprom驅(qū)動(dòng)名稱,必須與驅(qū)動(dòng)力的名稱一致*/compatible = "qcom,eeprom";/*匹配節(jié)點(diǎn),都是這個(gè)值*/qcom,slave-addr = <0x20>;/*i2c地址*/qcom,cci-master = <0>;/*默認(rèn)都為0即可*/qcom,num-blocks = <10>;/*下面配置的page個(gè)數(shù)*//*讀寫規(guī)則*/qcom,page0 = <1 0x0100 2 0x01 1 10>;/*steam on 該操作非必須*/qcom,pageen0 = <0 0x0 0 0x0 0 0>;qcom,poll0 = <0 0x0 0 0x0 0 0>;qcom,mem0 = <0 0x0 2 0 1 1>;/*初始化操作*/qcom,page1 = <1 0x5001 2 0x02 1 1>;/*往0x5001寫0x02:OTP enable*/qcom,pageen1 = <0 0x0 0 0x0 0 0>;qcom,poll1 = <0 0x0 0 0x0 0 0>;qcom,mem1 = <0 0x5001 2 0 1 1>;qcom,page2 = <1 0x3d84 2 0xc0 1 1>;/*往0x3d84寫入0xc0:Enable partial OTP write */qcom,pageen2 = <0 0x0 2 0x0 0 0>;qcom,poll2 = <0 0x0 2 0x0 0 0>;qcom,mem2 = <0 0x0 2 0 0 0>;qcom,page3 = <1 0x3d88 2 0x70 1 1>;/*往0x3d88寫入0x70:start address 高8位地址*/qcom,pageen3 = <0 0x0 2 0x0 1 1>;qcom,poll3 = <0 0x0 2 0x0 0 0>;qcom,mem3 = <0 0x0 2 0 0 0>;qcom,page4 = <1 0x3d89 2 0x10 1 1>;/*往0x3d88寫入0x10:start address 低8位地址*/qcom,pageen4 = <0 0x0 2 0x0 1 1>;qcom,poll4 = <0 0x0 2 0x0 0 0>;qcom,mem4 = <0 0x0 2 0 0 0>;qcom,page5 = <1 0x3d8a 2 0x72 1 1>;/*往0x3d8a寫入0x72:end address 高8位地址*/qcom,pageen5 = <0 0x0 2 0x0 1 1>;qcom,poll5 = <0 0x0 2 0x0 0 0>;qcom,mem5 = <0 0x0 2 0 0 0>;qcom,page6 = <1 0x3d8b 2 0x29 1 1>;/*往0x3d8b寫入0x29:end address 低8位地址*/qcom,pageen6 = <0 0x0 2 0x0 1 1>;qcom,poll6 = <0 0x0 2 0x0 0 0>;qcom,mem6 = <0 0x0 2 0 0 0>;qcom,page7 = <1 0x3d81 2 0x01 1 10>;/*往0x3d81寫入0x01:把OTP數(shù)據(jù)加載到buffer中 */qcom,pageen7 = <0 0x0 0 0x0 0 0>;qcom,poll7 = <0 0x0 0 0x0 0 0>;qcom,mem7 = <256 0x7010 2 0 1 1>;/*從0x7010開始讀取256個(gè)數(shù)據(jù)*/qcom,page8 = <1 0x5001 2 0x0a 1 1>;/*往0x5001寫0x0a:OTP disable*/qcom,pageen8 = <0 0x0 0 0x0 0 0>;qcom,poll8 = <0 0x0 0 0x0 0 0>;qcom,mem8 = <0 0x0 2 0 1 1>;qcom,page9 = <1 0x0100 2 0x00 1 10>;/*steam off*/qcom,pageen9 = <0 0x0 0 0x0 0 0>;qcom,poll9 = <0 0x0 0 0x0 0 0>;qcom,mem9 = <0 0x0 2 0 1 1>;cam_vio-supply = <&pm8916_l10>;/*供電相關(guān):和camera一致即可*/qcom,cam-vreg-name = "cam_vio";;/*硬件上只需IO供電,其他AVDD和DVDD都會(huì)被IO拉起來*/qcom,cam-vreg-type = <0>;qcom,cam-vreg-min-voltage = <1800000>;qcom,cam-vreg-max-voltage = <2800000>;qcom,cam-vreg-op-mode = <80000>;pinctrl-names = "cam_default", "cam_suspend";pinctrl-0 = <&cam_sensor_mclk1_default &cam_sensor_front_default>;pinctrl-1 = <&cam_sensor_mclk1_sleep &cam_sensor_front_sleep>;gpios = <&msm_gpio 26 0>,/*GPIO相關(guān):和camera一致即可*/<&msm_gpio 28 0>,<&msm_gpio 33 0>;qcom,gpio-reset = <1>;qcom,gpio-standby = <2>;qcom,gpio-req-tbl-num = <0 1 2>;qcom,gpio-req-tbl-flags = <1 0 0>;qcom,gpio-req-tbl-label = "CAMIF_MCLK","CAM_RESET1","CAM_STANDBY";qcom,cam-power-seq-type =/*eeprom的上電時(shí)序:和camera sensor的一致*/"sensor_vreg","sensor_gpio", "sensor_gpio","sensor_clk";qcom,cam-power-seq-val ="cam_vio","sensor_gpio_standby","sensor_gpio_reset","sensor_cam_mclk";qcom,cam-power-seq-cfg-val = <1 1 1 24000000>;qcom,cam-power-seq-delay = <10 10 10 5>;clocks = <&clock_gcc clk_mclk0_clk_src>,/*clock:和camera一致即可*/<&clock_gcc clk_gcc_camss_mclk0_clk>;clock-names = "cam_src_clk", "cam_clk";}; 復(fù)制代碼qcom,camera@1 {//在camera中應(yīng)用eeprom1 ···qcom,eeprom-src = <&eeprom1>; ··· } 復(fù)制代碼

屬性節(jié)點(diǎn)含義

  • cell-index = <1>; 該節(jié)點(diǎn)用于eeprom subdev注冊(cè)subdev_id,唯一即可!
  • reg = <0x20> 注冊(cè)地址:高端平臺(tái)要求這個(gè)地址唯一即可,低端平臺(tái)借助這個(gè)地址和i2c通信, 保險(xiǎn)起見,統(tǒng)一設(shè)置為i2c地址。
  • qcom,eeprom-name = "ov5675_back"; 這個(gè)名稱必須和eeprom驅(qū)動(dòng)的名稱一致,例如
vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/ modules/sensors/sensor_libs/ov5675_back/ov5675_back_lib.c static sensor_lib_t sensor_lib_ptr = { /* sensor eeprom name */.eeprom_name = "ov5675_back", } ```c* qcom,slave-addr = <0x20>;I2C 設(shè)備地址 * cam_vio-supply = <&pm8916_l10>;供電電源 * qcom,cam-power-seq-type 上電時(shí)序 ```c 上電的類型 qcom,cam-power-seq-type = "sensor_vreg","sensor_gpio", "sensor_gpio","sensor_clk"; 上電類型的對(duì)應(yīng)的val qcom,cam-power-seq-val = "cam_vio","sensor_gpio_standby","sensor_gpio_reset","sensor_cam_mclk"; 上電時(shí)序的值:除了clock配置成相應(yīng)的值,其他全配置1 qcom,cam-power-seq-cfg-val = <1 1 1 24000000>; 上電延遲時(shí)間 qcom,cam-power-seq-delay = <10 10 10 5>; 復(fù)制代碼

事實(shí)上,這個(gè)上電時(shí)序跟Camera Sensor的上電時(shí)序是一致的!舉個(gè)例子

  • qcom,page0 = = <有效值 地址 地址類型 數(shù)據(jù) 數(shù)據(jù)類型 延遲> 地址類型:1代表1 byte ,2代表2byte = 1 word 數(shù)據(jù)類型:1代表1 byte ,2代表2byte = 1 word 讀寫規(guī)則
qcom,page7 = <1 0x3d81 2 0x01 1 10>;/*往0x3d81寫入0x01:把OTP數(shù)據(jù)加載到buffer中 */ qcom,pageen7 = <0 0x0 0 0x0 0 0>; qcom,poll7 = <0 0x0 0 0x0 0 0>; qcom,mem7 = <256 0x7010 2 0 1 1>;/*從0x7010開始讀取256個(gè)數(shù)據(jù)*/ 復(fù)制代碼

到此,dtsi的配置就完成了!!!

3.3 軟件驅(qū)動(dòng)配置

1.添加新的EEPROM驅(qū)動(dòng)

vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/ sensors/eeprom_libs/ov5675_back * ov5675_back.c * Android.mk 復(fù)制代碼

任何新 .c 文件都應(yīng)映射和定義以下函數(shù)指針。 所有未在此 EEPROM 驅(qū)動(dòng)程 序中定義的函數(shù)必須設(shè)置為 NULL。

.get_calibration_items() – 此函數(shù)應(yīng)返回 EEPROM 模塊所支持的配置。 基于 EEPROM 所支持的配置,將指定標(biāo)記設(shè)置為 TRUE 或 FALSE。

  • Is_insensor – 如果傳感器模塊本身支持 EEPROM 配置,則將此標(biāo)記設(shè)置為 TRUE。 外部 EEPROM 均不可用。
  • Is_afc – 如果支持 AF 校準(zhǔn),將此標(biāo)記設(shè)置為 TRUE。
  • Is_wbc – 如果支持白平衡校準(zhǔn),將此標(biāo)記設(shè)置為 TRUE。
  • Is_lsc – 如果支持鏡頭陰影校準(zhǔn),將此標(biāo)記設(shè)置為 TRUE。
  • Is_dpc – 如果支持缺陷像素校正,將此標(biāo)記設(shè)置為 TRUE

.format_calibration_data() – 此函數(shù)用于格式化可寫入 eeprom/ 傳感器模塊的數(shù)據(jù)

OTP數(shù)據(jù)應(yīng)用

  • .do_af_calibration() – 此函數(shù)用于處理所有與 AF 相關(guān)的校準(zhǔn)操作, 如格式化數(shù)據(jù)和將 其寫入 EEPROM 以執(zhí)行 AF 校準(zhǔn)。
  • .do_wbc_calibration() – 此函數(shù)用于處理所有與白平衡相關(guān)的校準(zhǔn)操作, 如格式化數(shù)據(jù) 和將其寫入 EEPROM 以執(zhí)行白平衡校準(zhǔn)。
  • .do_lsc_calibration() – 此函數(shù)用于處理所有與鏡頭陰影校正相關(guān)的校準(zhǔn)操作, 如格式化 數(shù)據(jù)和將其寫入 EEPROM 以執(zhí)行鏡頭陰影校準(zhǔn)。
  • .do_dpc_calibration() – 此函數(shù)用于處理所有與缺陷像素校正相關(guān)的校準(zhǔn)操作, 如格式化 數(shù)據(jù)和將其寫入 EEPROM 以執(zhí)行缺陷像素校正

例子二:以獨(dú)立EEPROM為例子(數(shù)據(jù)燒錄在獨(dú)立的EEPROM中)

步驟和例子1是一樣的,關(guān)鍵在于dtsi的配置

eeprom0: qcom,eeprom@a0 { cell-index = <0>; reg = <0xa0>; qcom,eeprom-name = "gc8034_otp"; compatible = "qcom,eeprom"; qcom,slave-addr = <0xa0>; qcom,cci-master = <0>; qcom,num-blocks = <1>; qcom,page0 = <0 0 0 0 0 0>; qcom,pageen0 = <0 0x0 0 0x0 0 0>; qcom,poll0 = <0 0x0 0 0x0 0 0>; qcom,mem0 = <1813 0x0000 2 0 1 1>; cam_vio-supply = <&pm8916_l10>; qcom,cam-vreg-name = "cam_vio"; qcom,cam-vreg-type = <0>; qcom,cam-vreg-min-voltage = <1800000>; qcom,cam-vreg-max-voltage = <2800000>; qcom,cam-vreg-op-mode = <80000>;qcom,cam-power-seq-type = "sensor_vreg"; qcom,cam-power-seq-val ="cam_vio"; qcom,cam-power-seq-cfg-val = <1>; qcom,cam-power-seq-delay = <10>; }; 復(fù)制代碼

最關(guān)鍵的地方就是reg = <0xa0>; 這里要配置成I2C地址,讀取數(shù)組的時(shí)候,I2C會(huì)自動(dòng)把a(bǔ)0>>1=0x50去通信! 當(dāng)然高端點(diǎn)的平臺(tái)就不需要關(guān)注reg,只需配置唯一即可,最好的辦法還是配置為i2c地址!

8909平臺(tái)不支持reg配置成a0,內(nèi)核中有效地址是0x00~0x7f直接,如果配置成a0, 會(huì)報(bào)錯(cuò):Invalid7-bit I2C address 0xa0!!! 因此需要修改一下內(nèi)核: kernel/drivers/i2c/i2c-core.c

static int i2c_check_client_addr_validity(const struct i2c_client *client) {if (client->flags & I2C_CLIENT_TEN) {/* 10-bit address, all values are valid */if (client->addr > 0x3ff)return -EINVAL;} else {if (client->addr == 0xa0)//讓a0地址合法化!!!return 0;/* 7-bit address, reject the general call address */if (client->addr == 0x00 || client->addr > 0x7f)return -EINVAL;} return 0; }復(fù)制代碼

供電這一塊,eeprom只需要IO供電即可:因此配置就更簡(jiǎn)單了

cam_vio-supply = <&pm8916_l10>; qcom,cam-vreg-name = "cam_vio"; qcom,cam-vreg-type = <0>; qcom,cam-vreg-min-voltage = <1800000>; qcom,cam-vreg-max-voltage = <2800000>; qcom,cam-vreg-op-mode = <80000>;qcom,cam-power-seq-type = "sensor_vreg"; qcom,cam-power-seq-val ="cam_vio"; qcom,cam-power-seq-cfg-val = <1>; qcom,cam-power-seq-delay = <10>; 復(fù)制代碼

讀寫規(guī)則:直接從0x00開始讀1813個(gè)數(shù)據(jù),不需要操作任何寄存器!

qcom,mem0 = <1813 0x0000 2 0 1 1>; 復(fù)制代碼

例子三:以GC8034為例子(數(shù)據(jù)燒錄在Camera Sensor中)

GC8034的讀寫規(guī)則比較復(fù)雜,和高通要求的不一樣!

高通的源碼是給一個(gè)初始地址,然后不停+1的往后讀取數(shù)據(jù),最后保存在buffer中! GC8034是去讀d7這個(gè)寄存器的值!(這些讀寫規(guī)則,要多和模組廠跟sensor廠溝通) 因此要改動(dòng)kernel層的源碼

static int read_eeprom_memory(struct msm_eeprom_ctrl_t *e_ctrl,struct msm_eeprom_memory_block_t *block)if (emap[j].mem.valid_size) {/* galaxycore start */if(0 == strcmp(eb_info->eeprom_name,"gc8034_otp")){e_ctrl->i2c_client.addr_type = 1; /* luyi *//*讀取0xf4到gc_readf4變量中*/rc=e_ctrl->i2c_client.i2c_func_tbl->i2c_read(&(e_ctrl->i2c_client), 0xf4, &gc_readf4, emap[j].mem.data_t);/*往d4寄存器寫page和高8位地址*/e_ctrl->i2c_client.i2c_func_tbl->i2c_write(&(e_ctrl->i2c_client), 0xd4, (emap[j].mem.addr >> 8) & 0xff, emap[j].mem.data_t);/*往d5寄存器寫低8位地址*/e_ctrl->i2c_client.i2c_func_tbl->i2c_write(&(e_ctrl->i2c_client), 0xd5, emap[j].mem.addr & 0xff, emap[j].mem.data_t);/*往f3寄存器寫入0x20:OTP read 模式*/e_ctrl->i2c_client.i2c_func_tbl->i2c_write(&(e_ctrl->i2c_client), 0xf3, 0x20, emap[j].mem.data_t);/*往f4寄存器的第2位置1,表示地址自動(dòng)++(按照1 個(gè)byte=8bit的方式)*/e_ctrl->i2c_client.i2c_func_tbl->i2c_write(&(e_ctrl->i2c_client), 0xf4, gc_readf4 | 0x02, emap[j].mem.data_t);/*往f3寄存器寫入80,設(shè)置自動(dòng)讀取信號(hào)*/e_ctrl->i2c_client.i2c_func_tbl->i2c_write(&(e_ctrl->i2c_client), 0xf3, 0x80, emap[j].mem.data_t);msleep(emap[j].mem.delay);//延時(shí)for(gc = 0; gc < emap[j].mem.valid_size; gc++){msleep(emap[j].mem.delay);rc=e_ctrl->i2c_client.i2c_func_tbl->i2c_read(//讀d7寄存器的值到gc_read變量中&(e_ctrl->i2c_client), 0xd7, &gc_read, emap[j].mem.data_t);if (rc < 0) {pr_err("%s: read failed %d \n", __func__, __LINE__);return rc;}*memptr = (uint8_t)gc_read;//把讀出來的值保持到memptr 中memptr++;}e_ctrl->i2c_client.i2c_func_tbl->i2c_write(//讀完復(fù)位成初始狀態(tài)&(e_ctrl->i2c_client), 0xf3, 0x00, emap[j].mem.data_t);e_ctrl->i2c_client.i2c_func_tbl->i2c_write(//讀完復(fù)位成初始狀態(tài)&(e_ctrl->i2c_client), 0xf4, gc_readf4 & 0xfd, emap[j].mem.data_t);}/*galaxycore end*/else{//高通平臺(tái)默認(rèn)的讀取方式e_ctrl->i2c_client.addr_type = emap[j].mem.addr_t;rc = e_ctrl->i2c_client.i2c_func_tbl->i2c_read_seq(&(e_ctrl->i2c_client), emap[j].mem.addr,memptr, emap[j].mem.valid_size);pr_err("%s:travis read addr = %d,value = %d\n\n", __func__,emap[j].mem.addr,memptr[0]);if (rc < 0) {pr_err("%s: read failed\n", __func__);return rc;}memptr += emap[j].mem.valid_size;}} } 復(fù)制代碼

Stay Hungry,Stay Foolish!

轉(zhuǎn)載于:https://juejin.im/post/5c79d7cf6fb9a049fe35db4d

總結(jié)

以上是生活随笔為你收集整理的【Camera专题】Qcom-高通OTP完全调试指南-上的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。