rk3288的SDK修复cm3218光敏驱动bug
瑞芯的Android 4.4的SDK中kernel的补丁例如以下:
diff --git a/arch/arm/boot/dts/rk3288-tb_8846.dts b/arch/arm/boot/dts/rk3288-tb_8846.dts index c92d973..850fd42 100644 --- a/arch/arm/boot/dts/rk3288-tb_8846.dts +++ b/arch/arm/boot/dts/rk3288-tb_8846.dts @@ -533,6 +533,15 @@ status = "okay"; }; + sensor@48 { + compatible = "light_cm3218"; + reg = <0x48>; + type = <SENSOR_TYPE_LIGHT>; + irq-gpio = <&gpio8 GPIO_A3 IRQ_TYPE_EDGE_FALLING>; + irq_enable = <0>; + poll_delay_ms = <30>; + layout = <1>; + }; }; &i2c2 { diff --git a/drivers/i2c/busses/i2c-rockchip.c b/drivers/i2c/busses/i2c-rockchip.c index 3f64ff0..db28071 100644 --- a/drivers/i2c/busses/i2c-rockchip.c +++ b/drivers/i2c/busses/i2c-rockchip.c @@ -716,12 +716,17 @@ static int rockchip_i2c_doxfer(struct rockchip_i2c *i2c, i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); rockchip_i2c_disable_irq(i2c); - rockchip_i2c_disable(i2c); spin_unlock_irqrestore(&i2c->lock, flags); - if (error == -EAGAIN) - i2c_dbg(i2c->dev, "No ack(complete_what: 0x%x), Maybe slave(addr: 0x%04x) not exist or abnormal power-on\n", + if (error == -EAGAIN){ + i2c_dbg(i2c->dev, + "No ack(complete_what: 0x%x), Maybe slave(addr: 0x%04x) not exist or abnormal power-on\n", i2c->complete_what, i2c->addr); + rockchip_i2c_send_stop(i2c); + msleep(5); + } + + rockchip_i2c_disable(i2c); return error; } diff --git a/drivers/input/sensors/lsensor/cm3218.c b/drivers/input/sensors/lsensor/cm3218.c index b6201d6..8eee009 100644 --- a/drivers/input/sensors/lsensor/cm3218.c +++ b/drivers/input/sensors/lsensor/cm3218.c @@ -119,39 +119,46 @@ static int cm3218_read(struct i2c_client *client, u8 reg) } /****************operate according to sensor chip:start************/ +static int cm3218_read_lux(struct i2c_client *client, int *lux) +{ + int lux_data; + + lux_data = cm3218_read(client, CM3218_REG_ADDR_ALS); + if (lux_data < 0) { + dev_err(&client->dev, "Error in reading Lux DATA\n"); + return lux_data; + } + + dev_vdbg(&client->dev, "lux = %u\n", lux_data); + + if (lux_data < 0) + return lux_data; + + *lux = lux_data * LENSFACTOR; + *lux /= 1000; + + return 0; +} static int sensor_active(struct i2c_client *client, int enable, int rate) { - struct sensor_private_data *sensor = - (struct sensor_private_data *) i2c_get_clientdata(client); - int result = 0; - int status = 0; - - sensor->client->addr = sensor->ops->ctrl_reg; - sensor->ops->ctrl_data = cm3218_read(client,sensor->client->addr); - - //register setting according to chip datasheet - if(!enable) - { - status = CM3218_CMD_ALS_SD; //cm3218 - sensor->ops->ctrl_data |= status; - } - else - { - status = ~CM3218_CMD_ALS_SD; //cm3218 - sensor->ops->ctrl_data &= status; + int status; + + if (!enable) { + status = cm3218_write(client, CM3218_REG_ADDR_CMD,0x0001); + } else { + status = cm3218_write(client, CM3218_REG_ADDR_CMD,0x0000); } - DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable); - result = cm3218_write(client,sensor->client->addr, sensor->ops->ctrl_data); - if(result) + if (status) printk("%s:fail to active sensor\n",__func__); - - return result; + return status; } - +/* + * cm3218 device initialization. + */ static int sensor_init(struct i2c_client *client) { int status, i; @@ -159,21 +166,24 @@ static int sensor_init(struct i2c_client *client) (struct sensor_private_data *) i2c_get_clientdata(client); for (i = 0; i < 5; i++) { - status = cm3218_write(client, CM3218_REG_ADDR_CMD, - CM3218_CMD_ALS_SD); + /* shut down */ + status = cm3218_write(client, CM3218_REG_ADDR_CMD, CM3218_CMD_ALS_SD); if (status >= 0) break; + /* Clear interrupt */ cm3218_read_ara(client); } + /* power on (1T, HS, interrupt disable) */ status = cm3218_write(client, CM3218_REG_ADDR_CMD, CM3218_DEFAULT_CMD); if (status < 0) { dev_err(&client->dev, "Init CM3218 CMD fails\n"); return status; } - if(sensor->pdata->irq_enable) - { + /* enable interrupt */ + if(sensor->pdata->irq_enable){ + status = cm3218_write(client, CM3218_REG_ADDR_CMD, CM3218_DEFAULT_CMD | CM3218_CMD_ALS_INT_EN); if (status < 0) { dev_err(&client->dev, "Init CM3218 CMD fails\n"); @@ -181,9 +191,7 @@ static int sensor_init(struct i2c_client *client) } } - /* Clean interrupt status */ - cm3218_read(client, CM3218_REG_ADDR_STATUS); - + return status; } @@ -224,25 +232,7 @@ report: return index; } -static int cm3218_read_lux(struct i2c_client *client, int *lux) -{ - int lux_data; - - lux_data = cm3218_read(client, CM3218_REG_ADDR_ALS); - if (lux_data < 0) { - dev_err(&client->dev, "Error in reading Lux DATA\n"); - return lux_data; - } - - dev_vdbg(&client->dev, "lux = %u\n", lux_data); - if (lux_data < 0) - return lux_data; - - *lux = lux_data * LENSFACTOR; - *lux /= 1000; - return 0; -} static int sensor_report_value(struct i2c_client *client) { @@ -254,14 +244,14 @@ static int sensor_report_value(struct i2c_client *client) cm3218_read_lux(client,&result); index = light_report_value(sensor->input_dev, result); + DBG("%s:%s result=0x%x,index=%d\n",__func__,sensor->ops->name, result,index); - if((sensor->pdata->irq_enable)&& (sensor->ops->int_status_reg >= 0)) //read sensor intterupt status register - { - + /* read sensor intterupt status register */ + if((sensor->pdata->irq_enable)&& (sensor->ops->int_status_reg >= 0)){ + result= sensor_read_reg(client, sensor->ops->int_status_reg); - if(result) - { + if(result){ printk("%s:fail to clear sensor int status,ret=0x%x\n",__func__,result); } } @@ -272,17 +262,17 @@ static int sensor_report_value(struct i2c_client *client) struct sensor_operate light_cm3218_ops = { .name = "cm3218", - .type = SENSOR_TYPE_LIGHT, //sensor type and it should be correct - .id_i2c = LIGHT_ID_CM3218, //i2c id number - .read_reg = CM3218_REG_ADDR_ALS, //read data - .read_len = 2, //data length - .id_reg = SENSOR_UNKNOW_DATA, //read device id from this register - .id_data = SENSOR_UNKNOW_DATA, //device id - .precision = 16, //8 bits - .ctrl_reg = CM3218_REG_ADDR_CMD, //enable or disable - .int_status_reg = CM3218_REG_ADDR_STATUS, //intterupt status register - .range = {0,65535}, //range - .brightness ={10,255}, // brightness + .type = SENSOR_TYPE_LIGHT, /* sensor type and it should be correct */ + .id_i2c = LIGHT_ID_CM3218, /* i2c id number */ + .read_reg = CM3218_REG_ADDR_ALS, /* read data */ + .read_len = 2, /* data length */ + .id_reg = SENSOR_UNKNOW_DATA, /* read device id from this register */ + .id_data = SENSOR_UNKNOW_DATA, /* device id */ + .precision = 16, /* 8 bits */ + .ctrl_reg = CM3218_REG_ADDR_CMD, /* enable or disable */ + .int_status_reg = SENSOR_UNKNOW_DATA, /* intterupt status register */ + .range = {0,65535}, /* range */ + .brightness ={10,255}, /* brightness */ .trig = SENSOR_UNKNOW_DATA, .active = sensor_active, .init = sensor_init, @@ -291,7 +281,7 @@ struct sensor_operate light_cm3218_ops = { /****************operate according to sensor chip:end************/ -//function name should not be changed +/* function name should not be changed */ static struct sensor_operate *light_get_ops(void) { return &light_cm3218_ops; @@ -317,5 +307,3 @@ static void __exit light_cm3218_exit(void) module_init(light_cm3218_init); module_exit(light_cm3218_exit); - - diff --git a/drivers/input/sensors/sensor-dev.c b/drivers/input/sensors/sensor-dev.c index 960d44f..68ab664 100755 --- a/drivers/input/sensors/sensor-dev.c +++ b/drivers/input/sensors/sensor-dev.c @@ -2113,9 +2113,9 @@ static const struct i2c_device_id sensor_id[] = { /*light sensor*/ {"lightsensor", LIGHT_ID_ALL}, {"light_cm3217", LIGHT_ID_CM3217}, - {"light_cm3218", LIGHT_ID_CM3218}, - {"light_cm3232", LIGHT_ID_CM3232}, - {"light_al3006", LIGHT_ID_AL3006}, + {"light_cm3218", LIGHT_ID_CM3218}, + {"light_cm3232", LIGHT_ID_CM3232}, + {"light_al3006", LIGHT_ID_AL3006}, {"ls_stk3171", LIGHT_ID_STK3171}, {"ls_isl29023", LIGHT_ID_ISL29023}, {"ls_ap321xx", LIGHT_ID_AP321XX}, @@ -2162,8 +2162,9 @@ static struct of_device_id sensor_dt_ids[] = { ^M /*light sensor*/ { .compatible = "light_cm3217" }, - { .compatible = "light_cm3232" }, - { .compatible = "light_al3006" }, + { .compatible = "light_cm3218" }, + { .compatible = "light_cm3232" }, + { .compatible = "light_al3006" }, { .compatible = "ls_stk3171" }, { .compatible = "ls_ap321xx" }, ^M diff --git a/include/linux/sensor-dev.h b/include/linux/sensor-dev.h index 16e916f..6c21fcd 100755 --- a/include/linux/sensor-dev.h +++ b/include/linux/sensor-dev.h @@ -80,7 +80,7 @@ enum sensor_id { ^M LIGHT_ID_ALL, LIGHT_ID_CM3217, - LIGHT_ID_CM3218, + LIGHT_ID_CM3218, /* ID = 46 */^M LIGHT_ID_CM3232, LIGHT_ID_AL3006, LIGHT_ID_STK3171,