From 40587c0a7567a804eb66c43b890a6c0ef9d1c5fb Mon Sep 17 00:00:00 2001 From: Markinus Date: Mon, 11 Oct 2010 22:19:31 +0200 Subject: [PATCH] htcleo: fixed lightsensors power on/off LS and Proximity has same power GPO in microp. --- arch/arm/mach-msm/board-htcleo-ls.c | 29 +++-- arch/arm/mach-msm/board-htcleo-microp.c | 105 +++++++++++++++--- arch/arm/mach-msm/board-htcleo-proximity.c | 4 +- .../include/mach/board-htcleo-microp.h | 23 ++-- 4 files changed, 123 insertions(+), 38 deletions(-) diff --git a/arch/arm/mach-msm/board-htcleo-ls.c b/arch/arm/mach-msm/board-htcleo-ls.c index 49a9f442..6595d660 100644 --- a/arch/arm/mach-msm/board-htcleo-ls.c +++ b/arch/arm/mach-msm/board-htcleo-ls.c @@ -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); } diff --git a/arch/arm/mach-msm/board-htcleo-microp.c b/arch/arm/mach-msm/board-htcleo-microp.c index 7a3584ee..403fdb63 100644 --- a/arch/arm/mach-msm/board-htcleo-microp.c +++ b/arch/arm/mach-msm/board-htcleo-microp.c @@ -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__); diff --git a/arch/arm/mach-msm/board-htcleo-proximity.c b/arch/arm/mach-msm/board-htcleo-proximity.c index 7a940da2..0242e9ff 100644 --- a/arch/arm/mach-msm/board-htcleo-proximity.c +++ b/arch/arm/mach-msm/board-htcleo-proximity.c @@ -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; diff --git a/arch/arm/mach-msm/include/mach/board-htcleo-microp.h b/arch/arm/mach-msm/include/mach/board-htcleo-microp.h index 86f654ef..d136835c 100644 --- a/arch/arm/mach-msm/include/mach/board-htcleo-microp.h +++ b/arch/arm/mach-msm/include/mach/board-htcleo-microp.h @@ -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