AL3220光感调试记录

  • Soc:RK3288
  • Platform:Android 5.1

AL3220

AL3220B有四个RANGE:

Range TYP 时间
Range 1 33.28k 6.53ms
Range 2 8,32k 7.53ms
Range 3 2.08k 11.53ms
Range 4 0.65k 22.5ms

这四个range有不同的分辨率模式,每个range需要的conversion时间不同,总的ALS conversion时间如下:

Conversion time = RANGE time * Mean time + ALS Waiting * 2

注意:最开始调试光感时app获取到的光感总是不稳定,忽高忽低的,原因就是sensor 各个寄存器没有设置好。驱动调试时务必要认真阅读chip spec

状态图

下面是AL3220状态图:
这里写图片描述

例如,选择精度分辨率为RANGE 3,即2.08k时,各个寄存器需要如下设置:
Mean time=16, Range3 (2.08K), A-dummy=18, ALS Waiting (register 0x06) =100
Conversion time = (11.53 + 18*0.1)*16 + 100*2 = 413.28ms

AL3220寄存器如下:
这里写图片描述

首先需要enable light sensor,然后设定Ext_Gain and dynamic range for ALS的值,再根据
Conversion time计算公式,将各个值写入相应的寄存器,如下所示:

ret = i2c_smbus_write_byte_data(client, AL3320A_REG_CONFIG,
                AL3320A_CONFIG_ENABLE);
if (ret < 0)
    return ret;

ret = i2c_smbus_write_byte_data(client, AL3320A_REG_CONFIG_RANGE,
                AL3320A_RANGE_3 << AL3320A_GAIN_SHIFT);
if (ret < 0)
    return ret;

ret = i2c_smbus_write_byte_data(client, AL3320A_REG_MEAN_TIME,
                0xf);
if (ret < 0)
    return ret;

ret = i2c_smbus_write_byte_data(client, AL3320A_REG_ADUMMY,
                0x12);
if (ret < 0)
    return ret; 

ret = i2c_smbus_write_byte_data(client, AL3320A_REG_WAIT,
                0x64);
if (ret < 0)
    return ret;

这里设定的mean time是0xf,A-dummy的值是0x12, ALS Waiting的值是0x64,因此总的Conversion time是413.28ms,这个Conversion time怎么用呢?

probe

Sensor驱动初始化时sensor_probe()会从dts中获取一个变量” poll_delay_ms”, Conversion time就是这个值。
Sensor驱动采用轮询方式获取光感数据,在sensor_probe()中初始化时会先注册工作队列用于轮询获取光感数据:

sensor_irq_init()   --->
    INIT_DELAYED_WORK(&sensor->delaywork, sensor_delaywork_func);

当HAL层ioctl打开光感设备/dev/lightsensor时,sensor驱动最终调用schedule_delayed_work()唤起工作队列sensor_delaywork_func,该函数实现如下:

static void  sensor_delaywork_func(struct work_struct *work)
{
    struct delayed_work *delaywork = container_of(work, struct delayed_work, work);
    struct sensor_private_data *sensor = container_of(delaywork, struct sensor_private_data, delaywork);
    struct i2c_client *client = sensor->client;

    mutex_lock(&sensor->sensor_mutex);  
    if (sensor_get_data(client) < 0) 
        DBG(KERN_ERR "%s: Get data failed\n",__func__);

    if(!sensor->pdata->irq_enable)//restart work while polling
        schedule_delayed_work(&sensor->delaywork, msecs_to_jiffies(sensor->pdata->poll_delay_ms));
    //else
    //{
        //if((sensor->ops->trig == IRQF_TRIGGER_LOW) || (sensor->ops->trig == IRQF_TRIGGER_HIGH))
        //enable_irq(sensor->client->irq);
    //}
    mutex_unlock(&sensor->sensor_mutex);

    DBG("%s:%s\n",__func__,sensor->i2c_id->name);
}

调用sensor_get_data(),函数实现如下:

static int sensor_get_data(struct i2c_client *client)
{
    struct sensor_private_data *sensor =
        (struct sensor_private_data *) i2c_get_clientdata(client);  
    int result = 0;

    result = sensor->ops->report(client);
    if(result)
        goto error;

    /* set data_ready */
    atomic_set(&sensor->data_ready, 1);
    /*wake up data_ready  work queue*/
    wake_up(&sensor->data_ready_wq);

error:      
    return result;
}

AL3220初始化时调用sensor_register_slave()将sensor_operate注册到sensor核心中,这里调用其report方法sensor_report_value,在该函数中,读取sensor的数据并上报。

猜你喜欢

转载自blog.csdn.net/u014770862/article/details/81320153
AL
今日推荐