rk3288的SDK修複cm3218光敏驅動bug,rk3288cm3218
瑞芯的Android 4.4的SDK中kernel的補丁如下:
diff --git a/arch/arm/boot/dts/rk3288-tb_8846.dts b/arch/arm/boot/dts/rk3288-tb_8846.dtsindex 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.cindex 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.cindex 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.cindex 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" }, ^Mdiff --git a/include/linux/sensor-dev.h b/include/linux/sensor-dev.hindex 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,