htcleo: fixed lightsensors power on/off

LS and Proximity has same power GPO in microp.
This commit is contained in:
Markinus 2010-10-11 22:19:31 +02:00
parent 7f29fd2c9f
commit 40587c0a75
4 changed files with 123 additions and 38 deletions

View File

@ -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);
}

View File

@ -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__);

View File

@ -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;

View File

@ -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