From 520f195ed15c3e85d8fb4a6c458b269012cc2435 Mon Sep 17 00:00:00 2001 From: Greg Meiste Date: Thu, 29 Jul 2010 14:23:26 -0500 Subject: [PATCH] mfd: cpcap-whisper: Report dock ID to system Add support for whisper driver to report the dock ID to the system via sysfs. The dock ID can be found at: /sys/class/switch/dock/dock_addr Change-Id: Iafcc738c5e9bd10f94ee2cab1ab0d39a10b9932e Signed-off-by: Greg Meiste Signed-off-by: Nick Pelly --- drivers/mfd/cpcap-core.c | 7 ++++++- drivers/mfd/cpcap-whisper.c | 37 ++++++++++++++++++++++++++++++------- include/linux/spi/cpcap.h | 13 ++++++++++--- 3 files changed, 46 insertions(+), 11 deletions(-) diff --git a/drivers/mfd/cpcap-core.c b/drivers/mfd/cpcap-core.c index 5015e390b77f..1bedea917c7f 100644 --- a/drivers/mfd/cpcap-core.c +++ b/drivers/mfd/cpcap-core.c @@ -422,10 +422,15 @@ static int adc_ioctl(unsigned int cmd, unsigned long arg) static int accy_ioctl(unsigned int cmd, unsigned long arg) { int retval = -EINVAL; + struct cpcap_whisper_request read_data; switch (cmd) { case CPCAP_IOCTL_ACCY_WHISPER: - retval = cpcap_accy_whisper(misc_cpcap, arg); + if (copy_from_user((void *) &read_data, (void *) arg, + sizeof(read_data))) + return -EFAULT; + retval = cpcap_accy_whisper(misc_cpcap, read_data.cmd, + read_data.dock_id); break; default: diff --git a/drivers/mfd/cpcap-whisper.c b/drivers/mfd/cpcap-whisper.c index f1a1051bbcd1..ef35f10196c2 100644 --- a/drivers/mfd/cpcap-whisper.c +++ b/drivers/mfd/cpcap-whisper.c @@ -97,6 +97,7 @@ struct cpcap_whisper_data { struct switch_dev wsdev; struct switch_dev dsdev; struct switch_dev asdev; + char dock_id[CPCAP_WHISPER_ID_SIZE]; struct otg_transceiver *otg; }; @@ -121,6 +122,17 @@ static ssize_t print_name(struct switch_dev *dsdev, char *buf) return -EINVAL; } +static ssize_t dock_id_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct switch_dev *dsdev = dev_get_drvdata(dev); + struct cpcap_whisper_data *data = + container_of(dsdev, struct cpcap_whisper_data, dsdev); + + return snprintf(buf, PAGE_SIZE, "%s\n", data->dock_id); +} +static DEVICE_ATTR(dock_addr, S_IRUGO | S_IWUSR, dock_id_show, NULL); + static void vusb_enable(struct cpcap_whisper_data *data) { if (!data->is_vusb_enabled) { @@ -271,6 +283,7 @@ static void whisper_notify(struct cpcap_whisper_data *di, enum cpcap_accy accy) switch_set_state(&di->wsdev, 0); switch_set_state(&di->dsdev, NO_DOCK); switch_set_state(&di->asdev, 0); + memset(di->dock_id, 0, CPCAP_WHISPER_ID_SIZE); } } @@ -451,7 +464,8 @@ static void whisper_int_handler(enum cpcap_irqs int_event, void *data) schedule_delayed_work(&(di->work), 0); } -int cpcap_accy_whisper(struct cpcap_device *cpcap, unsigned long cmd) +int cpcap_accy_whisper(struct cpcap_device *cpcap, unsigned int cmd, + char *dock_id) { struct cpcap_whisper_data *di = cpcap->accydata; int retval = -EAGAIN; @@ -478,10 +492,11 @@ int cpcap_accy_whisper(struct cpcap_device *cpcap, unsigned long cmd) /* Report dock type to system. */ dock = (cmd & CPCAP_WHISPER_ACCY_MASK) >> CPCAP_WHISPER_ACCY_SHFT; + if (dock && (strlen(dock_id) < CPCAP_WHISPER_ID_SIZE)) + strncpy(di->dock_id, dock_id, CPCAP_WHISPER_ID_SIZE); switch_set_state(&di->dsdev, dock); - if (dock) - whisper_audio_check(di); + whisper_audio_check(di); } return retval; @@ -510,12 +525,17 @@ static int cpcap_whisper_probe(struct platform_device *pdev) data->wsdev.name = "whisper"; switch_dev_register(&data->wsdev); + data->asdev.name = "usb_audio"; + switch_dev_register(&data->asdev); + data->dsdev.name = "dock"; data->dsdev.print_name = print_name; switch_dev_register(&data->dsdev); - - data->asdev.name = "usb_audio"; - switch_dev_register(&data->asdev); + retval = device_create_file(data->dsdev.dev, &dev_attr_dock_addr); + if (retval < 0) { + dev_err(&pdev->dev, "Failed to create device file\n"); + goto free_mem; + } platform_set_drvdata(pdev, data); @@ -524,7 +544,7 @@ static int cpcap_whisper_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Could not get regulator for cpcap_whisper\n"); retval = PTR_ERR(data->regulator); - goto free_mem; + goto free_dock_id; } regulator_set_voltage(data->regulator, 3300000, 3300000); @@ -566,6 +586,8 @@ free_irqs: cpcap_irq_free(data->cpcap, CPCAP_IRQ_IDFLOAT); cpcap_irq_free(data->cpcap, CPCAP_IRQ_CHRG_DET); regulator_put(data->regulator); +free_dock_id: + device_remove_file(data->dsdev.dev, &dev_attr_dock_addr); free_mem: switch_dev_unregister(&data->wsdev); switch_dev_unregister(&data->dsdev); @@ -587,6 +609,7 @@ static int __exit cpcap_whisper_remove(struct platform_device *pdev) configure_hardware(data, CPCAP_ACCY_NONE); cancel_delayed_work_sync(&data->work); + device_remove_file(data->dsdev.dev, &dev_attr_dock_addr); switch_dev_unregister(&data->wsdev); switch_dev_unregister(&data->dsdev); switch_dev_unregister(&data->asdev); diff --git a/include/linux/spi/cpcap.h b/include/linux/spi/cpcap.h index b2d9fcf303dd..09254e9c921f 100644 --- a/include/linux/spi/cpcap.h +++ b/include/linux/spi/cpcap.h @@ -41,8 +41,9 @@ #define CPCAP_WHISPER_MODE_PU 0x00000001 #define CPCAP_WHISPER_ENABLE_UART 0x00000002 -#define CPCAP_WHISPER_ACCY_MASK 0xF1000000 +#define CPCAP_WHISPER_ACCY_MASK 0xF8000000 #define CPCAP_WHISPER_ACCY_SHFT 27 +#define CPCAP_WHISPER_ID_SIZE 16 enum cpcap_regulator_id { CPCAP_SW2, @@ -596,6 +597,11 @@ struct cpcap_regacc { unsigned short mask; }; +struct cpcap_whisper_request { + unsigned int cmd; + char dock_id[CPCAP_WHISPER_ID_SIZE]; +}; + /* * Gets the contents of the specified cpcap register. * @@ -656,7 +662,7 @@ struct cpcap_regacc { _IOW(0, CPCAP_IOCTL_NUM_UC_SET_TURBO_MODE, unsigned short) #define CPCAP_IOCTL_ACCY_WHISPER \ - _IOW(0, CPCAP_IOCTL_NUM_ACCY_WHISPER, unsigned long) + _IOW(0, CPCAP_IOCTL_NUM_ACCY_WHISPER, struct cpcap_whisper_request*) #ifdef __KERNEL__ struct cpcap_device { @@ -746,7 +752,8 @@ int cpcap_uc_stop(struct cpcap_device *cpcap, enum cpcap_macro macro); unsigned char cpcap_uc_status(struct cpcap_device *cpcap, enum cpcap_macro macro); -int cpcap_accy_whisper(struct cpcap_device *cpcap, unsigned long cmd); +int cpcap_accy_whisper(struct cpcap_device *cpcap, unsigned int cmd, + char *dock_id); #define cpcap_driver_register platform_driver_register #define cpcap_driver_unregister platform_driver_unregister -- 2.34.1