ALSPS光線距離傳感器驅動分析


一.alsps的初始化函數和重要結構體

epl2182_init //

Epl2182.c (kernel-3.10\drivers\misc\mediatek\alsps\epl2182-new)
    struct alsps_hw *hw = get_cust_alsps_hw(); //得到配置和硬件信息
        i2c_register_board_info(hw->i2c_num, &i2c_EPL2182, 1); //注冊I2C信息
            list_add_tail(&devinfo->list, &__i2c_board_list); //加入到__i2c_board_list鏈表中
        alsps_driver_add(&epl2182_init_info); // alsps_local_init函數加入
            alsps_init_list[i] = obj; //加入到alsps_init_list[i] 數組中,以備后面用
 
alsps_local_init //這個函數在alsps核心調用,下面有分析
    get_cust_alsps_hw();  //得到配置和硬件信息
        epl2182_power(hw, 1); //上電
           //mtk專門的上電函數(pmic.c),很多模塊都在用,if(hw->power_id != POWER_NONE_MACRO) 會進行上電操作,這里只是一個賦值操作power_on = on;
            hwPowerOn(hw->power_id, hw->power_vol, "EPL2182")
        i2c_add_driver(&epl2182_i2c_driver)  //I2C注冊driver
 
i2c_driver 結構體:
static struct i2c_driver epl2182_i2c_driver =
{
    .probe      = epl2182_i2c_probe,
    .remove     = epl2182_i2c_remove,
    .detect     = epl2182_i2c_detect,
    .suspend    = epl2182_i2c_suspend,
    .resume     = epl2182_i2c_resume,
    .id_table   = epl2182_i2c_id,
    .driver = {
        .name           = EPL2182_DEV_NAME,
    },
};
 
 
 
二.I2C的alsps的probe函數
通過i2c_driver 與adapter的匹配調用epl2182_i2c_probe
epl2182_i2c_probe
    epl2182_get_addr(obj->hw, &obj->addr); //得到I2C的地址
    INIT_WORK(&obj->eint_work, epl2182_eint_work); //初始化中斷工作任務
        epld = g_epl2182_ptr;   //得到epl2182私有數據
        elan_epl2182_I2C_Read(epld->client,REG_16,R_TWO_BYTE,0x02,read_data);  //i2c的讀函數,讀channel1,ps的數據
        elan_epl2182_I2C_Read(epld->client,REG_13,R_SINGLE_BYTE,0x01,read_data); //讀取到PS的中斷狀態,0或者1
        ps_report_interrupt_data 
            ps_data_report(cxt->idev,value,3);
                input_report_rel(dev, EVENT_TYPE_PS_VALUE, (value+1));  //輸入子系統上報數據
        input_report_rel(dev, EVENT_TYPE_PS_STATUS, status);
        input_sync(dev); 
    INIT_WORK(&obj->data_work, epl2182_check_ps_data);  //也是上報數據
    elan_epl2182_I2C_Write(client,REG_0,W_SINGLE_BYTE,0x02, EPL_S_SENSING_MODE); //把光照轉換到電壓的時間
    elan_epl2182_I2C_Write(client,REG_9,W_SINGLE_BYTE,0x02,EPL_INT_DISABLE); //把中斷清零
    epl2182_init_client
        if(obj->hw->polling_mode_ps == 0) //這里是中斷模式
        epl2182_setup_eint(client) //
            g_epl2182_ptr = obj;  //后面有用到epl2182的屬性
        hw8k_init_device
            epl2182_i2c_client=client; //后面有用到
    misc_register(&epl2182_device) //注冊混雜設備
    als_ctl.open_report_data= als_open_report_data;  //als_control的賦值
    als_ctl.enable_nodata = als_enable_nodata;
    als_ctl.set_delay  = als_set_delay;
 
 
混雜設備結構體:
static struct miscdevice epl2182_device =
{
    .minor = MISC_DYNAMIC_MINOR,
    .name = "als_ps",
    .fops = &epl2182_fops,
};
static struct file_operations epl2182_fops =
{
    .owner = THIS_MODULE,
    .open = epl2182_open,
    .release = epl2182_release,
    .unlocked_ioctl = epl2182_unlocked_ioctl,
};
 
 
 
三.alsps核心
在alsps.c中是alsp的上層部分,在epl2182_init之后調用
static struct platform_driver alsps_driver =
{
.probe      = alsps_probe,
.remove     = alsps_remove,    
.suspend    = alsps_suspend,
.resume     = alsps_resume,
.driver     = 
{
.name = ALSPS_PL_DEV_NAME,
        #ifdef CONFIG_OF
.of_match_table = alsps_of_match,
#endif
}
}; //平台driver結構體
 
alsps_init
    platform_driver_register(&alsps_driver) //注冊平台驅動,在mt_devs.c中有平台device:platform_device alsps_sensor
        
alsps_probe  //匹配后調用它
    alsps_context_alloc_object
        alsps_context *obj = kzalloc(sizeof(*obj), GFP_KERNEL); //分配alsps_context 結構體,保存了很多屬性
       
         初始化obj結構體,比如work的初始化: als_work_func,ps_work_func;定時器初始化,執行函數:als_poll,ps_poll分別執行schedule_work(&obj->report_als); schedule_work(&obj->report_ps);
        alsps_real_driver_init //初始化實際的alsps
            alsps_real_driver_init //
                alsps_init_list[i]->init(); //這就是具體alsps驅動注冊的init函數,在這里調用了
    alsps_factory_device_init    //is_use_common_factory被設置為true,就會進行misc_register(&alsps_factory_device),這里不用。
    alsps_input_init //輸入子系統的初始化,注冊
        input_allocate_device
        input_register_device
    
 
 
四.應用讀取sensor數據:
   als_store_active 和 ps_store_active啟動sensor,然后上報數據,PS一般用中斷,als一般用輪詢!
 
 
 
五.Light sensor level和value的設置
[DESCRIPTION]
     Light sensor level和value的設置
[PLATFORM]
     MT6575 MT6577 MT6589
[SOLUTION]
     Als_level是從sensor讀到的raw dataals_value是由als_level轉換為上報android的值,以
ltr559為例:cust_alsps.c中 :

該值要客制化,請聯系sensor vender提供。


[DESCRIPTION]

  由於結構限制或者傳感器本身原因,工廠模式下檢測到ic出來的值變化不夠明顯,可檢測的范圍小等。導致自動背光效果不明顯。

[SOLUTION]

      硬件上沒有方法改動的話,建議合理的修改,cust_alsps.c中的.level和.value這2個數組的值,driver里處理數據的原理:
     
  從driver里傳感器IC寄存器出來的數據是level值,根據此level值參照上述2個數組的對應關系,由level數組的下標取到.value數組的下標對應的值,然后上報value值給工廠模式和上層看到。

      所以需要您調cust_alsps.c里的那2個數組,如果是被遮擋而引起變化范圍變小的話,應該是寄存器出來的level變小了,所以建議把cust-als.c里的level也相應的減小,value不變,則應該有所改善。多試幾組減小.level的情況。

     另外如果需要更細膩的背光等級,可以適當的把這2個數組加大,取值更連續一些。(這個映射還與android的value(LUX)--->255級背光的映射有關,也不是連續的)
請參考 frameworks\base\core\res\res\values\config.xml

 

 

 

六.兼容

    當遇到兩個sensor同一個i2c地址,只啟用一個的時候,可以在注冊的時候該一個地址,然后在probe中改回來就可以了。

    通過工程模式可以看到sensor的raw 打他,通過工廠測試模式可以看到所有senso人上報的數值。


 
 
 
七.工程測試模式中sensor的讀取數據流程
    1.輸入*987*0#進行測試,一般用於產線的測試
     epl2182_unlocked_ioctl   : 用的是poll(ps)
 
      2.*#*#3646633#*#*這樣是可以讀到sensor的原始數據,可以調試sensor是否有遮擋              
          epl2182_unlocked_ioctl 用的是poll
 
 
 
 
八.把ps改成輪詢方式
   現在的機制是:
         1. PS單獨開啟的時候用中斷;
          2.單獨ALS是輪詢
          3.PS與ALS一起開啟的時候在als_get_data中輪詢ALS,如果是中斷模式還要輪詢PS,因為輪詢als的時候ps不會產生中斷
 
   把PS也改下輪詢:
         因為poll的時候會互相干擾,產生競爭,導致數據閃動,需要信號量來控制
        als_get_data
         mutex_lock(&epl2182_poll_mutex);
         ...............
         mutex_unlock(&epl2182_poll_mutex);
 
       ps_get_data
                       mutex_lock(&epl2182_poll_mutex);
                         ...............
                        mutex_unlock(&epl2182_poll_mutex);
 
     PS在打電話的時候不能休眠:加睡眠鎖
       目前的driver架構是對於沒有使用中斷模式的距離傳感器(cust_alsps.c .ps_polling=1) 在驅動的i2c_probe里初始化一個wake lock,在Operate函數的ENABLE分支,如果是
enable的話就wake_lock(your_lock),disable的話就wake_unlock(your_lock)

 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM