htcleo: fixed lightsensors power on/off
LS and Proximity has same power GPO in microp.
This commit is contained in:
parent
7f29fd2c9f
commit
40587c0a75
@ -81,7 +81,7 @@ static void map_adc_to_level(uint32_t adc, uint32_t *value)
|
||||
|
||||
if (adc > 1024)
|
||||
{
|
||||
pr_err("map_adc_to_level: adc > 1024\n");
|
||||
pr_err("%s: adc > 1024\n", __func__);
|
||||
*value = 5; // set some good value at error
|
||||
return;
|
||||
}
|
||||
@ -90,7 +90,7 @@ static void map_adc_to_level(uint32_t adc, uint32_t *value)
|
||||
{
|
||||
if (adc >= lsensor_adc_table[i])
|
||||
{
|
||||
D("map_adc_to_level: %d -> %d\n", adc, i);
|
||||
D("%s: %d -> %d\n", __func__, adc, i);
|
||||
*value = i;
|
||||
return;
|
||||
}
|
||||
@ -124,7 +124,7 @@ static void lightsensor_poll_function(struct work_struct *work)
|
||||
struct lsensor_data* p = &the_data;
|
||||
uint32_t adc = 0, level = 0;
|
||||
|
||||
D("@@@lsensor poll\n");
|
||||
D("%s\n", __func__);
|
||||
if (!p->enabled)
|
||||
{
|
||||
D(" disable\n");
|
||||
@ -149,14 +149,19 @@ static void lightsensor_poll_function(struct work_struct *work)
|
||||
static int lightsensor_enable(void)
|
||||
{
|
||||
struct lsensor_data* p = &the_data;
|
||||
int rc = -EIO;
|
||||
|
||||
D("@@@lightsensor_enable\n");
|
||||
D("%s\n", __func__);
|
||||
|
||||
if (p->enabled)
|
||||
{
|
||||
pr_err("lsensor: already enabled\n");
|
||||
return 0;
|
||||
}
|
||||
rc = capella_cm3602_power(LS_PWR_ON, 1);
|
||||
if (rc < 0)
|
||||
return -EIO;
|
||||
|
||||
the_data.old_level = -1;
|
||||
|
||||
p->enabled = 1;
|
||||
@ -168,14 +173,18 @@ static int lightsensor_enable(void)
|
||||
static int lightsensor_disable(void)
|
||||
{
|
||||
struct lsensor_data* p = &the_data;
|
||||
int rc = -EIO;
|
||||
|
||||
D("@@@lightsensor_disable\n");
|
||||
D("%s\n", __func__);
|
||||
|
||||
if (!p->enabled)
|
||||
{
|
||||
pr_err("lsensor: nothing to disable\n");
|
||||
return 0;
|
||||
}
|
||||
rc = capella_cm3602_power(LS_PWR_ON, 0);
|
||||
if (rc < 0)
|
||||
return -EIO;
|
||||
|
||||
p->enabled = 0;
|
||||
cancel_delayed_work_sync(&the_data.work);
|
||||
@ -231,6 +240,7 @@ static long lightsensor_ioctl(struct file *file, unsigned int cmd, unsigned long
|
||||
rc = -EFAULT;
|
||||
break;
|
||||
}
|
||||
pr_info("%s ls set to: %d\n", __func__, val);
|
||||
rc = val ? lightsensor_enable() : lightsensor_disable();
|
||||
break;
|
||||
case LIGHTSENSOR_IOCTL_GET_ENABLED:
|
||||
@ -264,8 +274,6 @@ struct miscdevice lightsensor_misc =
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
static int lsensor_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret = -EIO;
|
||||
@ -279,7 +287,7 @@ static int lsensor_probe(struct platform_device *pdev)
|
||||
/* Light Sensor */
|
||||
/*
|
||||
ret = device_create_file(&the_data->dev, &dev_attr_ls_adc);
|
||||
ret = device_create_file(&the_data->dev, &dev_attr_ls_auto);
|
||||
ret = device_create_file(&pdev->dev, &dev_attr_ls_auto);
|
||||
*/
|
||||
input_dev = input_allocate_device();
|
||||
if (!input_dev)
|
||||
@ -315,9 +323,10 @@ static int lsensor_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
the_data.old_level = -1;
|
||||
the_data.enabled=0;
|
||||
the_data.opened=0;
|
||||
INIT_DELAYED_WORK(&the_data.work, lightsensor_poll_function);
|
||||
|
||||
ret = 0; //lsensor_setup();
|
||||
if (!ret)
|
||||
goto done;
|
||||
|
||||
@ -331,7 +340,7 @@ done:
|
||||
return ret;
|
||||
|
||||
// device_remove_file(&client->dev, &dev_attr_ls_adc);
|
||||
// device_remove_file(&client->dev, &dev_attr_ls_auto);
|
||||
// device_remove_file(&pdev->dev, &dev_attr_ls_auto);
|
||||
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,9 @@
|
||||
#include "board-htcleo.h"
|
||||
|
||||
static uint32_t microp_als_kadc;
|
||||
static int als_power_control;
|
||||
static DEFINE_MUTEX(capella_cm3602_lock);
|
||||
|
||||
|
||||
extern void p_sensor_irq_handler(void);
|
||||
|
||||
@ -262,33 +265,46 @@ static int microp_read_gpi_status(struct i2c_client *client, uint16_t *status)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int microp_interrupt_enable(struct i2c_client *client, uint16_t interrupt_mask)
|
||||
static int microp_interrupt_get_status(uint16_t *interrupt_mask)
|
||||
{
|
||||
uint8_t data[2];
|
||||
int ret = -1;
|
||||
|
||||
ret = microp_i2c_read(MICROP_I2C_RCMD_GPI_INT_STATUS, data, 2);
|
||||
if (ret < 0) {
|
||||
pr_err("%s: read interrupt status fail\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
*interrupt_mask = data[0]<<8 | data[1];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int microp_interrupt_enable( uint16_t interrupt_mask)
|
||||
{
|
||||
uint8_t data[2];
|
||||
int ret = -1;
|
||||
|
||||
data[0] = interrupt_mask >> 8;
|
||||
data[1] = interrupt_mask & 0xFF;
|
||||
ret = i2c_write_block(client, MICROP_I2C_WCMD_GPI_INT_CTL_EN, data, 2);
|
||||
ret = microp_i2c_write(MICROP_I2C_WCMD_GPI_INT_CTL_EN, data, 2);
|
||||
|
||||
if (ret < 0)
|
||||
dev_err(&client->dev, "%s: enable 0x%x interrupt failed\n",
|
||||
__func__, interrupt_mask);
|
||||
pr_err("%s: enable 0x%x interrupt failed\n", __func__, interrupt_mask);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int microp_interrupt_disable(struct i2c_client *client, uint16_t interrupt_mask)
|
||||
static int microp_interrupt_disable(uint16_t interrupt_mask)
|
||||
{
|
||||
uint8_t data[2];
|
||||
int ret = -1;
|
||||
|
||||
data[0] = interrupt_mask >> 8;
|
||||
data[1] = interrupt_mask & 0xFF;
|
||||
ret = i2c_write_block(client, MICROP_I2C_WCMD_GPI_INT_CTL_DIS, data, 2);
|
||||
ret = microp_i2c_write(MICROP_I2C_WCMD_GPI_INT_CTL_DIS, data, 2);
|
||||
|
||||
if (ret < 0)
|
||||
dev_err(&client->dev, "%s: disable 0x%x interrupt failed\n",
|
||||
__func__, interrupt_mask);
|
||||
pr_err("%s: disable 0x%x interrupt failed\n", __func__, interrupt_mask);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -351,6 +367,68 @@ int microp_gpo_disable(uint16_t interrupt_mask)
|
||||
}
|
||||
EXPORT_SYMBOL(microp_gpo_disable);
|
||||
|
||||
/*
|
||||
* CM3602 Power for LS and Proximity
|
||||
*/
|
||||
int __capella_cm3602_power(int on)
|
||||
{
|
||||
int rc;
|
||||
printk(KERN_DEBUG "%s: Turn the capella_cm3602 power %s\n",
|
||||
__func__, (on) ? "on" : "off");
|
||||
if (on) {
|
||||
rc = microp_gpo_enable(GPO_CM3602);
|
||||
if (rc < 0)
|
||||
return -EIO;
|
||||
} else {
|
||||
rc = microp_gpo_disable(GPO_CM3602);
|
||||
if (rc < 0)
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int capella_cm3602_power(int pwr_device, uint8_t enable)
|
||||
{
|
||||
unsigned int old_status = 0;
|
||||
uint16_t interrupts = 0;
|
||||
int ret = 0, on = 0;
|
||||
mutex_lock(&capella_cm3602_lock);
|
||||
if(pwr_device==PS_PWR_ON) { // Switch the Proximity IRQ
|
||||
if(enable) {
|
||||
ret = microp_interrupt_get_status(&interrupts);
|
||||
if (ret < 0) {
|
||||
pr_err("%s: read interrupt status fail\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
interrupts |= IRQ_PROXIMITY;
|
||||
ret = microp_interrupt_enable(interrupts);
|
||||
}
|
||||
else {
|
||||
interrupts |= IRQ_PROXIMITY;
|
||||
ret = microp_interrupt_disable(interrupts);
|
||||
}
|
||||
if (ret < 0) {
|
||||
pr_err("%s: failed to enable gpi irqs\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
old_status = als_power_control;
|
||||
if (enable)
|
||||
als_power_control |= pwr_device;
|
||||
else
|
||||
als_power_control &= ~pwr_device;
|
||||
|
||||
on = als_power_control ? 1 : 0;
|
||||
if (old_status == 0 && on)
|
||||
ret = __capella_cm3602_power(1);
|
||||
else if (!on)
|
||||
ret = __capella_cm3602_power(0);
|
||||
|
||||
mutex_unlock(&capella_cm3602_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt
|
||||
@ -376,26 +454,25 @@ static void microp_i2c_intr_work_func(struct work_struct *work)
|
||||
struct i2c_client *client;
|
||||
struct microp_i2c_client_data *cdata;
|
||||
uint8_t data[3];
|
||||
uint16_t intr_status = 0, gpi_status = 0;
|
||||
uint16_t intr_status = 0;
|
||||
int ret = 0;
|
||||
|
||||
up_work = container_of(work, struct microp_i2c_work, work);
|
||||
client = up_work->client;
|
||||
cdata = i2c_get_clientdata(client);
|
||||
|
||||
ret = i2c_read_block(client, MICROP_I2C_RCMD_GPI_INT_STATUS, data, 2);
|
||||
ret = microp_interrupt_get_status(&intr_status);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev, "%s: read interrupt status fail\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
intr_status = data[0]<<8 | data[1];
|
||||
ret = i2c_write_block(client, MICROP_I2C_WCMD_GPI_INT_STATUS_CLR, data, 2);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev, "%s: clear interrupt status fail\n",
|
||||
__func__);
|
||||
}
|
||||
pr_debug("intr_status=0x%02x\n", intr_status);
|
||||
pr_info("intr_status=0x%02x\n", intr_status);
|
||||
|
||||
if (intr_status & IRQ_PROXIMITY) {
|
||||
p_sensor_irq_handler();
|
||||
@ -413,10 +490,8 @@ static int microp_function_initialize(struct i2c_client *client)
|
||||
|
||||
cdata = i2c_get_clientdata(client);
|
||||
|
||||
interrupts |= IRQ_PROXIMITY;
|
||||
|
||||
/* enable the interrupts */
|
||||
ret = microp_interrupt_enable(client, interrupts);
|
||||
ret = microp_interrupt_enable(interrupts);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev, "%s: failed to enable gpi irqs\n",
|
||||
__func__);
|
||||
|
@ -81,7 +81,7 @@ static int capella_cm3602_enable(struct capella_cm3602_data *data)
|
||||
input_report_abs(data->input_dev, ABS_DISTANCE, -1);
|
||||
input_sync(data->input_dev);
|
||||
|
||||
rc = microp_gpo_enable(GPO_PROXIMITY);
|
||||
rc = capella_cm3602_power(PS_PWR_ON, 1);
|
||||
if (rc < 0)
|
||||
return -EIO;
|
||||
|
||||
@ -99,7 +99,7 @@ static int capella_cm3602_disable(struct capella_cm3602_data *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = microp_gpo_disable(GPO_PROXIMITY);
|
||||
rc = capella_cm3602_power(PS_PWR_ON, 0);
|
||||
if (rc < 0)
|
||||
return -EIO;
|
||||
|
||||
|
@ -112,20 +112,21 @@ struct microp_i2c_client_data {
|
||||
#define MICROP_I2C_WCMD_MOBEAM_SEND 0xB3
|
||||
|
||||
|
||||
#define IRQ_GSENSOR (1<<10)
|
||||
#define IRQ_LSENSOR (1<<9)
|
||||
#define IRQ_REMOTEKEY (1<<7)
|
||||
#define IRQ_HEADSETIN (1<<2)
|
||||
#define IRQ_PROXIMITY (1<<1)
|
||||
#define IRQ_SDCARD (1<<0)
|
||||
#define IRQ_GSENSOR (1<<10)
|
||||
#define IRQ_LSENSOR (1<<9)
|
||||
#define IRQ_REMOTEKEY (1<<7)
|
||||
#define IRQ_HEADSETIN (1<<2)
|
||||
#define IRQ_PROXIMITY (1<<1)
|
||||
#define IRQ_SDCARD (1<<0)
|
||||
|
||||
#define READ_GPI_STATE_HPIN (1<<2)
|
||||
#define READ_GPI_STATE_SDCARD (1<<0)
|
||||
#define READ_GPI_STATE_HPIN (1<<2)
|
||||
#define READ_GPI_STATE_SDCARD (1<<0)
|
||||
|
||||
#define GPO_PROXIMITY 0x3
|
||||
#define GPO_CM3602 0x3
|
||||
#define LS_PWR_ON (1 << 0)
|
||||
#define PS_PWR_ON (1 << 1)
|
||||
|
||||
int microp_i2c_read(uint8_t addr, uint8_t *data, int length);
|
||||
int microp_i2c_write(uint8_t addr, uint8_t *data, int length);
|
||||
int microp_gpo_enable(uint16_t interrupt_mask);
|
||||
int microp_gpo_disable(uint16_t interrupt_mask);
|
||||
int capella_cm3602_power(int pwr_device, uint8_t enable);
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user