From 96cbc30f4a4b9ae712d117fe96a57be0f3a6be68 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Fri, 21 Oct 2011 11:03:05 +0200 Subject: staging: nmf-cm: Add NMF/CM driver This is driver for loading code to a DSP Signed-off-by: Philippe Langlais Signed-off-by: Robert Marklund --- drivers/staging/camera_flash/adp1653.c | 595 +++++++++++++++++++++++++++++++++ 1 file changed, 595 insertions(+) create mode 100644 drivers/staging/camera_flash/adp1653.c (limited to 'drivers/staging/camera_flash/adp1653.c') diff --git a/drivers/staging/camera_flash/adp1653.c b/drivers/staging/camera_flash/adp1653.c new file mode 100644 index 00000000000..c97014fc5ad --- /dev/null +++ b/drivers/staging/camera_flash/adp1653.c @@ -0,0 +1,595 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * adp1653: Driver Adp1653 HPLED flash driver chip. This driver + * currently support I2C interface, 2bit interface is not supported. + * Author: Pankaj Chauhan/pankaj.chauhan@stericsson.com for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "flash_common.h" +#include "adp1653.h" +#include "camera_flash.h" + +/* This data is platform specific for 8500 href-v1 platform, + * Ideally this should be supplied from platform code + */ +//#define ADAPTER_I2C2 (2) +#define STR_GPIO (6) + +static int strobe_gpio = 0; //TODO: set to 0 when it works +static int adapter_i2c2 = 2; +static int flash_irq = 7; +static int enable_gpio = 272; +static int flash_position = 0; +module_param(strobe_gpio, int, S_IRUGO); +MODULE_PARM_DESC(strobe_gpio, "use GPIO 6 to strobe, 0 means that someone else (sensor?) will strobe for us"); +module_param(adapter_i2c2, int, S_IRUGO); +MODULE_PARM_DESC(adapter_i2c2, "use the given I2C adaptater to communicate with the chip"); +module_param(flash_irq, int, S_IRUGO); +MODULE_PARM_DESC(flash_irq, "the GPIO number associated to the i2c irq line"); +module_param(enable_gpio, int, S_IRUGO); +MODULE_PARM_DESC(enable_gpio, "use the given GPIO line to enable the chip"); +module_param(flash_position, int, S_IRUGO); +MODULE_PARM_DESC(flash_position, "the position of the flash chip (0=PRIMARY, 1=SECONDARY)"); + + +int __flash_gpio_to_irq(int gpio) +{ + + return NOMADIK_GPIO_TO_IRQ(gpio); +} + +#define DEBUG_LOG(...) printk(KERN_DEBUG "Adp1653 flash driver: " __VA_ARGS__) + +#define ADP1653_SUPPORTED_MODES (FLASH_MODE_VIDEO_LED | FLASH_MODE_STILL_LED | \ + FLASH_MODE_STILL_LED_EXTERNAL_STROBE | \ + FLASH_MODE_AF_ASSISTANT | FLASH_MODE_INDICATOR) + +#define ADP1653_SELFTEST_SUPPORTED_MODES (FLASH_SELFTEST_CONNECTION | FLASH_SELFTEST_FLASH_WITH_STROBE | \ + FLASH_SELFTEST_VIDEO_LIGHT | FLASH_SELFTEST_AF_LIGHT | FLASH_SELFTEST_INDICATOR | FLASH_SELFTEST_TORCH_LIGHT) + +static int adp1653_trigger_strobe(void *priv_data, int enable); + +static int adp1653_get_modes(void *priv_data,unsigned long *modes) +{ + int err; + struct adp1653_priv_data *priv_p = (struct adp1653_priv_data *)priv_data; + err = i2c_smbus_read_byte_data(priv_p->i2c_client, FAULT_STATUS_REG); + if (err) + *modes = 0x0; + else + *modes = ADP1653_SUPPORTED_MODES; + return 0; +} + +static int adp1653_get_mode_details(void *priv_data, unsigned long mode, +struct flash_mode_details *details_p) +{ + int err = 0; + memset(details_p,0,sizeof(struct flash_mode_details)); + + details_p->led_type = 2; + + /* Still LED settings*/ + details_p->nbFaultRegisters = 1; + if(mode & (FLASH_MODE_STILL_LED | FLASH_MODE_STILL_LED_EXTERNAL_STROBE)){ + details_p->max_intensity_uAmp = FLASH_MAX_INTENSITY; + details_p->min_intensity_uAmp = FLASH_MIN_INTENSITY; + details_p->max_strobe_duration_uSecs = FLASH_MAX_STROBE_DURATION; + details_p->feature_bitmap = INTENSITY_PROGRAMMABLE | DURATION_PROGRAMMABLE; + goto out; + } + /*Video LED settings*/ + if(mode & FLASH_MODE_VIDEO_LED){ + details_p->max_intensity_uAmp = TORCH_MAX_INTENSITY; + details_p->min_intensity_uAmp = TORCH_MIN_INTENSITY; + details_p->max_strobe_duration_uSecs = 0; + details_p->feature_bitmap = INTENSITY_PROGRAMMABLE; + goto out; + } + /*Privacy Indicator settings */ + if(mode & FLASH_MODE_INDICATOR){ + details_p->max_intensity_uAmp = ILED_MAX_INTENSITY; + details_p->min_intensity_uAmp = ILED_MIN_INTENSITY; + details_p->max_strobe_duration_uSecs = 0; + details_p->feature_bitmap = INTENSITY_PROGRAMMABLE; + goto out; + } + DEBUG_LOG("Mode %lx, not supported\n",mode); + err = EINVAL; +out: + return err; +} + +static int adp1653_enable_flash_mode(void *priv_data, + unsigned long mode, int enable) +{ + int err = 0; + struct adp1653_priv_data *priv_p = (struct adp1653_priv_data *)priv_data; + + if(enable){ + + if(!(mode & ADP1653_SUPPORTED_MODES)){ + DEBUG_LOG("Unsupported mode %lx\n",mode); + err = -EINVAL; + goto out; + } + /*Nothing to be done in enabling, just set current mode and return*/ + /*May be enable disable can be done here but why not enable in + *probe and keep it on always + */ + adp1653_trigger_strobe(priv_p,0); + priv_p->curr_mode = mode; + }else{ + adp1653_trigger_strobe(priv_p,0); + priv_p->curr_mode =0; + } +out: + return err; +} + +static int adp1653_configure_flash_mode(void *priv,unsigned long mode, +struct flash_mode_params *params_p) +{ + int err = 0; + unsigned char intensity_code; + struct adp1653_priv_data *priv_p = (struct adp1653_priv_data *)priv; + + if(!(mode & ADP1653_SUPPORTED_MODES)){ + DEBUG_LOG("Mode %lx not supported\n",mode); + err = -EINVAL; + goto out; + } + switch(mode){ + case FLASH_MODE_STILL_LED: + case FLASH_MODE_STILL_LED_EXTERNAL_STROBE: + { + FLASH_UAMP_TO_CODE(intensity_code,params_p->intensity_uAmp); + if(params_p->duration_uSecs){ + DURATION_USEC_TO_CODE(priv_p->flash_duration, + params_p->duration_uSecs); + DEBUG_LOG("Duration %lu, code 0x%x\n",params_p->duration_uSecs, + priv_p->flash_duration); + priv_p->flash_duration |= TIMER_ENABLE; + }else{ + priv_p->flash_duration = 0; + } + priv_p->flash_intensity = intensity_code << 3; + } + break; + case FLASH_MODE_VIDEO_LED: + { + TORCH_UAMP_TO_CODE(intensity_code,params_p->intensity_uAmp); + DEBUG_LOG("Torch mode setting intensity 0x%x, current(uA) %lu\n", + intensity_code,params_p->intensity_uAmp); + priv_p->torch_intensity = intensity_code << 3; + } + break; + case FLASH_MODE_INDICATOR: + { + ILED_UAMP_TO_CODE(intensity_code,params_p->intensity_uAmp); + DEBUG_LOG("ILED setting intensity 0x%x, current(uA) %lu\n", + intensity_code,params_p->intensity_uAmp); + priv_p->indicator_intensity = intensity_code; + } + break; + default: + err = -EINVAL; + DEBUG_LOG("Unsupported mode %lx\n",mode); + break; + } + + if((mode == FLASH_MODE_STILL_LED_EXTERNAL_STROBE) || (mode == FLASH_MODE_STILL_LED)) + { + adp1653_trigger_strobe(priv_p,0); + DEBUG_LOG("CONFIG_TIMER_REG : 0x%x\n",priv_p->flash_duration); + DEBUG_LOG("OUTPUT_SEL_REG : 0x%x\n",priv_p->flash_intensity); + + /*TimeOut Must be programmed before Intensity*/ + err = i2c_smbus_write_byte_data(priv_p->i2c_client,CONFIG_TIMER_REG, + priv_p->flash_duration); + if(err){ + DEBUG_LOG("I2C: Unsable to write timer config, err %d\n",err); + goto out; + } + err = i2c_smbus_write_byte_data(priv_p->i2c_client,OUTPUT_SEL_REG, + priv_p->flash_intensity); + if(err){ + DEBUG_LOG("I2C: Unable to write OUTPUT_SEL_REG , err %d\n",err); + goto out; + } + } +out: + return err; +} + +static int adp1653_set_intensity(struct adp1653_priv_data *priv_p, uint8_t intensity) +{ + return i2c_smbus_write_byte_data(priv_p->i2c_client,OUTPUT_SEL_REG,intensity); +} + +static int adp1653_strobe_still_led(struct adp1653_priv_data *priv_p,int enable) +{ + int err=0,gpio_val; + uint8_t intensity,duration; + + if(enable){ + intensity = priv_p->flash_intensity; + duration = priv_p->flash_duration; + gpio_val = 1; + }else{ + intensity = 0; + duration = 0; + gpio_val = 0; + } + + err = adp1653_set_intensity(priv_p,intensity); + if(err){ + DEBUG_LOG("I2C: Unable to write OUTPUT_SEL_REG reg, err %d\n",err); + goto out; + } + + /*TimeOut Must be programmed before Intensity*/ + err = i2c_smbus_write_byte_data(priv_p->i2c_client,CONFIG_TIMER_REG, + priv_p->flash_duration); + if(err){ + DEBUG_LOG("I2C: Unsable to write timer config, err %d\n",err); + goto out; + } + err = i2c_smbus_write_byte_data(priv_p->i2c_client,OUTPUT_SEL_REG,intensity); + if(err){ + DEBUG_LOG("I2C: Unable to write OUTPUT_SEL_REG, err %d\n",err); + goto out; + } + + if (strobe_gpio != 0 ) + { + gpio_set_value(priv_p->strobe_gpio,gpio_val); + } + +out: + return err; +} + +static int adp1653_trigger_strobe(void *priv, int enable) +{ + int err = 0; + uint8_t intensity; + struct adp1653_priv_data *priv_p = (struct adp1653_priv_data *)priv; + + switch(priv_p->curr_mode){ + case FLASH_MODE_STILL_LED: + case FLASH_MODE_STILL_LED_EXTERNAL_STROBE: + err = adp1653_strobe_still_led(priv_p,enable); + break; + case FLASH_MODE_VIDEO_LED: + { + if(enable) + intensity = priv_p->torch_intensity; + else + intensity = 0; + err = adp1653_set_intensity(priv_p,intensity); + } + break; + case FLASH_MODE_INDICATOR: + { + if(enable) + intensity = priv_p->indicator_intensity; + else + intensity =0; + err = adp1653_set_intensity(priv_p,intensity); + } + break; + default: + DEBUG_LOG("Unsupported mode %lx\n",priv_p->curr_mode); + goto out; + } + if(err){ + DEBUG_LOG("Unable to enable/disable %d, strobe. Mode %lx, err %d\n",enable, + priv_p->curr_mode,err); + goto out; + } + disable_irq(priv_p->i2c_client->irq); + if(enable) + SET_FLASH_STATUS(priv_p->status,FLASH_STATUS_LIT); + else + CLR_FLASH_STATUS(priv_p->status,FLASH_STATUS_LIT); + + enable_irq(priv_p->i2c_client->irq); + +out: + return err; +} +#define FLASH_ERR_ALL (FLASH_ERR_OVER_CHARGE |FLASH_ERR_OVER_HEAT | \ + FLASH_ERR_SHORT_CIRCUIT | FLASH_ERR_TIMEOUT | \ + FLASH_ERR_OVER_VOLTAGE) +int adp1653_get_status(void *priv_data,unsigned long *status) +{ + struct adp1653_priv_data *priv_p= (struct adp1653_priv_data *)priv_data; + disable_irq(priv_p->i2c_client->irq); + if(priv_p->fault){ + if(priv_p->fault & OVER_VOLTAGE_FAULT) + SET_FLASH_ERROR(priv_p->status,FLASH_ERR_OVER_VOLTAGE); + if(priv_p->fault & TIMEOUT_FAULT) + SET_FLASH_ERROR(priv_p->status,FLASH_ERR_TIMEOUT); + if(priv_p->fault & OVER_TEMPERATURE_FAULT) + SET_FLASH_ERROR(priv_p->status,FLASH_ERR_OVER_HEAT); + if(priv_p->fault & SHORT_CIRCUIT_FAULT){ + CLR_FLASH_STATUS(priv_p->status,FLASH_STATUS_READY); + SET_FLASH_STATUS(priv_p->status,FLASH_STATUS_BROKEN); + SET_FLASH_ERROR(priv_p->status,FLASH_ERR_SHORT_CIRCUIT); + } + priv_p->fault =0; + }else{ + CLR_FLASH_ERROR(priv_p->status,FLASH_ERR_ALL); + } + enable_irq(priv_p->i2c_client->irq); + *status = priv_p->status; + return 0; +} + +int adp1653_get_selftest_modes(void *priv_data, unsigned long *modes) +{ + int err; + struct adp1653_priv_data *priv_p = (struct adp1653_priv_data *)priv_data; + err = i2c_smbus_read_byte_data(priv_p->i2c_client, FAULT_STATUS_REG); + if (err) *modes = 0x0; + else *modes = ADP1653_SELFTEST_SUPPORTED_MODES; + return 0; +} + +int adp1653_get_fault_registers(void *priv_data, unsigned long mode, unsigned long *status) +{ + int err = 0; + struct adp1653_priv_data *priv_p = (struct adp1653_priv_data *)priv_data; + + *status = i2c_smbus_read_byte_data(priv_p->i2c_client, FAULT_STATUS_REG); + + /* clear fault register */ + err = i2c_smbus_write_byte_data(priv_p->i2c_client,OUTPUT_SEL_REG,0); + if(0 != err) + { + DEBUG_LOG("Unable to write OUTPUT_SEL_REG, err %d\n",err); + } + return err; +} + +struct flash_chip_ops adp1653_ops = { + .get_modes = adp1653_get_modes, + .get_mode_details = adp1653_get_mode_details, + .get_status = adp1653_get_status, + .enable_flash_mode = adp1653_enable_flash_mode, + .configure_flash_mode = adp1653_configure_flash_mode, + .trigger_strobe = adp1653_trigger_strobe, + .get_selftest_modes = adp1653_get_selftest_modes, + .get_fault_registers = adp1653_get_fault_registers +}; + +static irqreturn_t adp1653_irq_hdlr(int irq_no,void *data) +{ + int err; + struct adp1653_priv_data *priv_p= (struct adp1653_priv_data *)data; + + priv_p->fault = i2c_smbus_read_byte_data(priv_p->i2c_client, + FAULT_STATUS_REG); + DEBUG_LOG("Got Fault, status 0x%x\n",priv_p->fault); + /*Writing 0 to OUTPUT_SEL_REG clears the interrtup + *and FAULT_STATUS_REG register + */ + err = i2c_smbus_write_byte_data(priv_p->i2c_client,OUTPUT_SEL_REG,0); + if(err) + DEBUG_LOG("Unable to write OUTPUT_SEL_REG to clr intr, err %d\n",err); + /*TBD: send even to user process*/ + return IRQ_HANDLED; +} +static int __devinit adp1653_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int err=0; + struct flash_chip *flash_chip_p=NULL; + struct adp1653_priv_data *priv_p=NULL; + + DEBUG_LOG("> adp1653_probe\n"); + + priv_p = kzalloc(sizeof(struct adp1653_priv_data),GFP_KERNEL); + if(!priv_p){ + DEBUG_LOG("Kmalloc failed for priv data\n"); + err = ENOMEM; + goto out; + } + priv_p->i2c_client = client; + flash_chip_p = kzalloc(sizeof(struct flash_chip),GFP_KERNEL); + if(!flash_chip_p){ + DEBUG_LOG("Kmalloc failed for flash_chip_p"); + err = ENOMEM; + goto out; + } + flash_chip_p->priv_data = priv_p; + flash_chip_p->ops = &adp1653_ops; + SET_FLASHCHIP_TYPE(flash_chip_p,FLASH_TYPE_HPLED); + SET_FLASHCHIP_ID(flash_chip_p,ADP1653_ID); + + strncpy(flash_chip_p->name,"Adp1653",FLASH_NAME_SIZE); + + i2c_set_clientdata(client,priv_p); + /*Request GPIO and Register IRQ if supported by platform and flash chip*/ + + if(machine_is_hrefv60()) + enable_gpio = 21; + else + enable_gpio = 272; + + if(enable_gpio){ + err = gpio_request(enable_gpio,"Camera LED flash Enable"); + if(err){ + DEBUG_LOG("Unable to get GPIO %d, for enable\n",enable_gpio); + goto out; + } + priv_p->enable_gpio = enable_gpio; + + err = gpio_direction_output(priv_p->enable_gpio, 1); + if(err){ + DEBUG_LOG("Unable to set GPIO %lu in output mode, err %d\n",priv_p->enable_gpio,err); + gpio_free(priv_p->enable_gpio); + goto out; + } + gpio_set_value(priv_p->enable_gpio, 1); + } + + if (strobe_gpio != 0) + { + err = gpio_request(STR_GPIO,"Camera flash strobe\n"); + if(err){ + DEBUG_LOG("Unable to request strobe GPIO\n"); + // somebody else requested this gpio ... + //goto out; + } + + err = gpio_direction_output(STR_GPIO, 0); + if(err){ + DEBUG_LOG("Unable to set GPIO %d in output mode, err %d\n",STR_GPIO,err); + goto out; + } + } + else + { + err = gpio_request(STR_GPIO,"Camera flash strobe\n"); + if(err){ + DEBUG_LOG("Unable to request strobe GPIO\n"); + // somebody else requested this gpio ... + //goto out; + } + + err = gpio_direction_input(STR_GPIO); + if(err){ + DEBUG_LOG("Unable to set GPIO %d in input mode, err %d\n",STR_GPIO,err); + goto out; + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) + err = nmk_gpio_set_pull(STR_GPIO, NMK_GPIO_PULL_DOWN); +#endif + if(err){ + DEBUG_LOG("Unable to set pull down on GPIO %d\n",STR_GPIO); + goto out; + } + + } + + priv_p->strobe_gpio = STR_GPIO; + + if(client->irq){ + err = request_threaded_irq(client->irq,NULL,adp1653_irq_hdlr, + IRQF_ONESHOT|IRQF_TRIGGER_FALLING, + "Adp1653 flash",priv_p); + if(err){ + DEBUG_LOG("Unable to register flash IRQ handler, irq %d, err %d\n", + client->irq,err); + goto out; + } + } + err = register_flash_chip(flash_position,flash_chip_p); + if(err){ + DEBUG_LOG("Failed to register Adp1653 as flash for %s camera\n", + (flash_position?"Primary":"Secondary")); + goto out; + } + SET_FLASH_STATUS(priv_p->status,FLASH_STATUS_READY); + DEBUG_LOG("< adp1653_probe ok\n"); + return err; +out: + if(priv_p->irq_no) + free_irq(priv_p->irq_no,NULL); + if(priv_p->enable_gpio) + gpio_free(priv_p->enable_gpio); + if(priv_p) + kfree(priv_p); + if(flash_chip_p) + kfree(flash_chip_p); + DEBUG_LOG("< adp1653_probe (%d)\n", err); + return err; +} + +static int __devexit adp1653_remove(struct i2c_client *client) +{ + int err=0; + /*Nothing here yet, implement it later.*/ + return err; +} +static const struct i2c_device_id adp1653_id[] = { + { "adp1653", 0}, + {} +}; +static struct i2c_driver adp1653_i2c_driver = { + .driver = { + .name = "adp1653", + .owner = THIS_MODULE, + }, + .probe = adp1653_probe, + .remove = __devexit_p(adp1653_remove), + .id_table = adp1653_id, +}; + +int adp1653_init(void){ + int err=0; + struct i2c_adapter *adap_p; + struct i2c_board_info info; + + /*Registration of I2C flash device is platform specific code + *Ideally it should be done from kernel (arch/arm/mach-XXX). + *Do it locally till the time it gets into platform code + *OR This portion (registration of device) and flash chip init + *Routine can be moved to Flash chip module init. + */ + DEBUG_LOG("getting I2C adaptor %d\n",adapter_i2c2); + adap_p = i2c_get_adapter(adapter_i2c2); + if(!adap_p){ + DEBUG_LOG("Unable to get I2C adaptor\n"); + goto out; + } + memset(&info,0,sizeof( struct i2c_board_info)); + + info.irq = __flash_gpio_to_irq(flash_irq); + + strcpy(&info.type[0],"adp1653"); + DEBUG_LOG("trying to register %s at position %d, GPIO enable %d, GPIO IRQ line %d\n", + info.type, + flash_position, + enable_gpio, + flash_irq); + + /* I2C framework expects least significant 7 bits as address, not complete + * 8 bits with bit 0 (read/write bit) + */ + info.addr = 0x60 >> 1; + + + err = i2c_add_driver(&adp1653_i2c_driver); + if(err) + { + DEBUG_LOG("Failed to register i2c driver\n"); + goto out; + } + + + DEBUG_LOG("Initialized adp1653\n"); + if(!i2c_new_device(adap_p,&info)){ + DEBUG_LOG("Unable to add i2c dev: %s (err=%d)\n",info.type, err); + goto out; + } + +out: + return err; +} + +/* +MODULE_DEPEND +*/ -- cgit v1.2.3 From 4a229e574d63c884f6a79e977262b397ec4e40e2 Mon Sep 17 00:00:00 2001 From: Rajat Verma Date: Thu, 15 Sep 2011 15:47:34 +0530 Subject: staging: camera_flash: Enable FLASH_MODE_NONE FLASH_MODE_NONE should be enabled by flash clients to put the flash IC in sleep mode, dropping the input current to less that 45 microamperes. ST-Ericsson ID: 361897 ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Rajat Verma Change-Id: I5ff4e409344578043b2f35e19474e215ddde2e44 Signed-off-by: Rajat Verma Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/31744 Reviewed-by: Bibek BASU Tested-by: Bibek BASU --- drivers/staging/camera_flash/adp1653.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/staging/camera_flash/adp1653.c') diff --git a/drivers/staging/camera_flash/adp1653.c b/drivers/staging/camera_flash/adp1653.c index c97014fc5ad..8264e46a1f2 100644 --- a/drivers/staging/camera_flash/adp1653.c +++ b/drivers/staging/camera_flash/adp1653.c @@ -117,7 +117,8 @@ static int adp1653_enable_flash_mode(void *priv_data, if(enable){ - if(!(mode & ADP1653_SUPPORTED_MODES)){ + if((!(mode & ADP1653_SUPPORTED_MODES)) && + (mode != FLASH_MODE_NONE)) { DEBUG_LOG("Unsupported mode %lx\n",mode); err = -EINVAL; goto out; -- cgit v1.2.3 From f819c5ccb26dd5b031b1564bcda2d30c13038b0c Mon Sep 17 00:00:00 2001 From: Rajat Verma Date: Fri, 7 Oct 2011 12:13:05 +0530 Subject: ux500: camera_flash: add platform data for adp1653 board specific information such as enable_gpio and interrupt line information should be obtained using platform_data and not hardcoded inside the driver itself. ST-Ericsson Linux next: NA ST-Ericsson ID: 361940 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I73a0f3e986bd3cbf19a0797190d514af9b84e3df Signed-off-by: Rajat Verma Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33282 Reviewed-by: Jonas ABERG Reviewed-by: Rabin VINCENT Signed-off-by: Robert Marklund --- drivers/staging/camera_flash/adp1653.c | 163 +++++++++------------------- drivers/staging/camera_flash/adp1653_plat.h | 24 ++++ 2 files changed, 76 insertions(+), 111 deletions(-) create mode 100755 drivers/staging/camera_flash/adp1653_plat.h (limited to 'drivers/staging/camera_flash/adp1653.c') diff --git a/drivers/staging/camera_flash/adp1653.c b/drivers/staging/camera_flash/adp1653.c index 8264e46a1f2..f7483eac11f 100644 --- a/drivers/staging/camera_flash/adp1653.c +++ b/drivers/staging/camera_flash/adp1653.c @@ -17,26 +17,16 @@ #include "flash_common.h" #include "adp1653.h" #include "camera_flash.h" +#include "adp1653_plat.h" /* This data is platform specific for 8500 href-v1 platform, * Ideally this should be supplied from platform code */ -//#define ADAPTER_I2C2 (2) -#define STR_GPIO (6) -static int strobe_gpio = 0; //TODO: set to 0 when it works static int adapter_i2c2 = 2; -static int flash_irq = 7; -static int enable_gpio = 272; static int flash_position = 0; -module_param(strobe_gpio, int, S_IRUGO); -MODULE_PARM_DESC(strobe_gpio, "use GPIO 6 to strobe, 0 means that someone else (sensor?) will strobe for us"); module_param(adapter_i2c2, int, S_IRUGO); MODULE_PARM_DESC(adapter_i2c2, "use the given I2C adaptater to communicate with the chip"); -module_param(flash_irq, int, S_IRUGO); -MODULE_PARM_DESC(flash_irq, "the GPIO number associated to the i2c irq line"); -module_param(enable_gpio, int, S_IRUGO); -MODULE_PARM_DESC(enable_gpio, "use the given GPIO line to enable the chip"); module_param(flash_position, int, S_IRUGO); MODULE_PARM_DESC(flash_position, "the position of the flash chip (0=PRIMARY, 1=SECONDARY)"); @@ -251,11 +241,6 @@ static int adp1653_strobe_still_led(struct adp1653_priv_data *priv_p,int enable) goto out; } - if (strobe_gpio != 0 ) - { - gpio_set_value(priv_p->strobe_gpio,gpio_val); - } - out: return err; } @@ -394,9 +379,10 @@ static irqreturn_t adp1653_irq_hdlr(int irq_no,void *data) static int __devinit adp1653_probe(struct i2c_client *client, const struct i2c_device_id *id) { - int err=0; + int err = 0; struct flash_chip *flash_chip_p=NULL; struct adp1653_priv_data *priv_p=NULL; + struct adp1653_platform_data *pdata = client->dev.platform_data; DEBUG_LOG("> adp1653_probe\n"); @@ -404,15 +390,23 @@ static int __devinit adp1653_probe(struct i2c_client *client, if(!priv_p){ DEBUG_LOG("Kmalloc failed for priv data\n"); err = ENOMEM; - goto out; + goto err_priv; } priv_p->i2c_client = client; flash_chip_p = kzalloc(sizeof(struct flash_chip),GFP_KERNEL); if(!flash_chip_p){ DEBUG_LOG("Kmalloc failed for flash_chip_p"); err = ENOMEM; - goto out; + goto err_flash_chip_alloc; } + + if (!pdata) { + dev_err(&client->dev, + "%s: No platform data supplied.\n", __func__); + err = -EINVAL; + goto err_pdata; + } + flash_chip_p->priv_data = priv_p; flash_chip_p->ops = &adp1653_ops; SET_FLASHCHIP_TYPE(flash_chip_p,FLASH_TYPE_HPLED); @@ -423,98 +417,53 @@ static int __devinit adp1653_probe(struct i2c_client *client, i2c_set_clientdata(client,priv_p); /*Request GPIO and Register IRQ if supported by platform and flash chip*/ - if(machine_is_hrefv60()) - enable_gpio = 21; - else - enable_gpio = 272; - - if(enable_gpio){ - err = gpio_request(enable_gpio,"Camera LED flash Enable"); - if(err){ - DEBUG_LOG("Unable to get GPIO %d, for enable\n",enable_gpio); - goto out; - } - priv_p->enable_gpio = enable_gpio; - - err = gpio_direction_output(priv_p->enable_gpio, 1); - if(err){ - DEBUG_LOG("Unable to set GPIO %lu in output mode, err %d\n",priv_p->enable_gpio,err); - gpio_free(priv_p->enable_gpio); - goto out; - } - gpio_set_value(priv_p->enable_gpio, 1); + err = gpio_request(pdata->enable_gpio,"Camera LED flash Enable"); + if(err){ + DEBUG_LOG("Unable to get GPIO %d, for enable\n",pdata->enable_gpio); + goto err_pdata; } - if (strobe_gpio != 0) - { - err = gpio_request(STR_GPIO,"Camera flash strobe\n"); - if(err){ - DEBUG_LOG("Unable to request strobe GPIO\n"); - // somebody else requested this gpio ... - //goto out; - } - - err = gpio_direction_output(STR_GPIO, 0); - if(err){ - DEBUG_LOG("Unable to set GPIO %d in output mode, err %d\n",STR_GPIO,err); - goto out; - } + err = gpio_direction_output(pdata->enable_gpio, 1); + if(err){ + DEBUG_LOG("Unable to set GPIO %u in output mode, err %d\n",pdata->enable_gpio,err); + gpio_free(pdata->enable_gpio); + goto err_gpio_set; } - else - { - err = gpio_request(STR_GPIO,"Camera flash strobe\n"); - if(err){ - DEBUG_LOG("Unable to request strobe GPIO\n"); - // somebody else requested this gpio ... - //goto out; - } - - err = gpio_direction_input(STR_GPIO); - if(err){ - DEBUG_LOG("Unable to set GPIO %d in input mode, err %d\n",STR_GPIO,err); - goto out; - } - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) - err = nmk_gpio_set_pull(STR_GPIO, NMK_GPIO_PULL_DOWN); -#endif - if(err){ - DEBUG_LOG("Unable to set pull down on GPIO %d\n",STR_GPIO); - goto out; - } + gpio_set_value_cansleep(pdata->enable_gpio, 1); + err = request_threaded_irq(gpio_to_irq(pdata->irq_no),NULL,adp1653_irq_hdlr, + IRQF_ONESHOT|IRQF_TRIGGER_FALLING, + "Adp1653 flash",priv_p); + if(err){ + DEBUG_LOG("Unable to register flash IRQ handler, irq %d, err %d\n", + pdata->irq_no,err); + goto err_irq; } - priv_p->strobe_gpio = STR_GPIO; - - if(client->irq){ - err = request_threaded_irq(client->irq,NULL,adp1653_irq_hdlr, - IRQF_ONESHOT|IRQF_TRIGGER_FALLING, - "Adp1653 flash",priv_p); - if(err){ - DEBUG_LOG("Unable to register flash IRQ handler, irq %d, err %d\n", - client->irq,err); - goto out; - } - } err = register_flash_chip(flash_position,flash_chip_p); if(err){ DEBUG_LOG("Failed to register Adp1653 as flash for %s camera\n", (flash_position?"Primary":"Secondary")); - goto out; + goto err_register; } SET_FLASH_STATUS(priv_p->status,FLASH_STATUS_READY); DEBUG_LOG("< adp1653_probe ok\n"); return err; -out: - if(priv_p->irq_no) - free_irq(priv_p->irq_no,NULL); - if(priv_p->enable_gpio) - gpio_free(priv_p->enable_gpio); - if(priv_p) - kfree(priv_p); +err_register: + if(pdata->irq_no) + free_irq(pdata->irq_no,NULL); +err_irq: + gpio_set_value_cansleep(pdata->enable_gpio, 0); +err_gpio_set: + if(pdata->enable_gpio) + gpio_free(pdata->enable_gpio); +err_pdata: if(flash_chip_p) kfree(flash_chip_p); +err_flash_chip_alloc: + if(priv_p) + kfree(priv_p); +err_priv: DEBUG_LOG("< adp1653_probe (%d)\n", err); return err; } @@ -540,16 +489,15 @@ static struct i2c_driver adp1653_i2c_driver = { }; int adp1653_init(void){ - int err=0; + int err = 0; struct i2c_adapter *adap_p; struct i2c_board_info info; - /*Registration of I2C flash device is platform specific code - *Ideally it should be done from kernel (arch/arm/mach-XXX). - *Do it locally till the time it gets into platform code - *OR This portion (registration of device) and flash chip init - *Routine can be moved to Flash chip module init. - */ + /* Registration of I2C flash device is platform specific code + * Ideally it should be done from kernel (arch/arm/mach-XXX). + * Do it locally till the time it gets into platform code + * OR This portion (registration of device) and flash chip init + * Routine can be moved to Flash chip module init. */ DEBUG_LOG("getting I2C adaptor %d\n",adapter_i2c2); adap_p = i2c_get_adapter(adapter_i2c2); if(!adap_p){ @@ -558,21 +506,16 @@ int adp1653_init(void){ } memset(&info,0,sizeof( struct i2c_board_info)); - info.irq = __flash_gpio_to_irq(flash_irq); - strcpy(&info.type[0],"adp1653"); - DEBUG_LOG("trying to register %s at position %d, GPIO enable %d, GPIO IRQ line %d\n", + DEBUG_LOG("trying to register %s at position %d\n", info.type, - flash_position, - enable_gpio, - flash_irq); + flash_position); /* I2C framework expects least significant 7 bits as address, not complete * 8 bits with bit 0 (read/write bit) */ info.addr = 0x60 >> 1; - err = i2c_add_driver(&adp1653_i2c_driver); if(err) { @@ -580,13 +523,11 @@ int adp1653_init(void){ goto out; } - DEBUG_LOG("Initialized adp1653\n"); if(!i2c_new_device(adap_p,&info)){ DEBUG_LOG("Unable to add i2c dev: %s (err=%d)\n",info.type, err); goto out; } - out: return err; } diff --git a/drivers/staging/camera_flash/adp1653_plat.h b/drivers/staging/camera_flash/adp1653_plat.h new file mode 100755 index 00000000000..325097aa2a8 --- /dev/null +++ b/drivers/staging/camera_flash/adp1653_plat.h @@ -0,0 +1,24 @@ +/* + * adp1653_plat.h + * ADP1653 Led Flash Driver platform specific structures + * + * Copyright (C) ST-Ericsson SA 2011 + * Author: Rajat Verma + * + * License Terms: GNU General Public License v2 + */ + +#ifndef __LINUX_I2C_ADP1653_PLAT_H__ +#define __LINUX_I2C_ADP1653_PLAT_H__ + +/** + * struct adp1653_platform_data - platform data structure for adp1653 + * @enable_gpio: gpio for chip enable/disable + * @irq_no: interrupt line for flash ic + */ +struct adp1653_platform_data { + u32 enable_gpio; + u32 irq_no; +}; + +#endif //__LINUX_I2C_ADP1653_PLAT_H__ -- cgit v1.2.3