From 2e4de7b32adc239d566cd02751c31d0847f68e86 Mon Sep 17 00:00:00 2001 From: Bo Shen Date: Tue, 16 Oct 2012 11:56:58 +0800 Subject: ASoC: atmel-ssc: use devm_xxx() managed function Using the devm_xxx() managed function to stripdown the error and remove code. Signed-off-by: Bo Shen Signed-off-by: Mark Brown --- drivers/misc/atmel-ssc.c | 47 +++++++++++++++-------------------------------- 1 file changed, 15 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c index 5bb187781074..23dcb76abdaf 100644 --- a/drivers/misc/atmel-ssc.c +++ b/drivers/misc/atmel-ssc.c @@ -70,37 +70,33 @@ EXPORT_SYMBOL(ssc_free); static int __init ssc_probe(struct platform_device *pdev) { - int retval = 0; struct resource *regs; struct ssc_device *ssc; - ssc = kzalloc(sizeof(struct ssc_device), GFP_KERNEL); + ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL); if (!ssc) { dev_dbg(&pdev->dev, "out of memory\n"); - retval = -ENOMEM; - goto out; + return -ENOMEM; } + ssc->pdev = pdev; + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!regs) { dev_dbg(&pdev->dev, "no mmio resource defined\n"); - retval = -ENXIO; - goto out_free; + return -ENXIO; } - ssc->clk = clk_get(&pdev->dev, "pclk"); - if (IS_ERR(ssc->clk)) { - dev_dbg(&pdev->dev, "no pclk clock defined\n"); - retval = -ENXIO; - goto out_free; - } - - ssc->pdev = pdev; - ssc->regs = ioremap(regs->start, resource_size(regs)); + ssc->regs = devm_request_and_ioremap(&pdev->dev, regs); if (!ssc->regs) { dev_dbg(&pdev->dev, "ioremap failed\n"); - retval = -EINVAL; - goto out_clk; + return -EINVAL; + } + + ssc->clk = devm_clk_get(&pdev->dev, "pclk"); + if (IS_ERR(ssc->clk)) { + dev_dbg(&pdev->dev, "no pclk clock defined\n"); + return -ENXIO; } /* disable all interrupts */ @@ -112,8 +108,7 @@ static int __init ssc_probe(struct platform_device *pdev) ssc->irq = platform_get_irq(pdev, 0); if (!ssc->irq) { dev_dbg(&pdev->dev, "could not get irq\n"); - retval = -ENXIO; - goto out_unmap; + return -ENXIO; } spin_lock(&user_lock); @@ -125,16 +120,7 @@ static int __init ssc_probe(struct platform_device *pdev) dev_info(&pdev->dev, "Atmel SSC device at 0x%p (irq %d)\n", ssc->regs, ssc->irq); - goto out; - -out_unmap: - iounmap(ssc->regs); -out_clk: - clk_put(ssc->clk); -out_free: - kfree(ssc); -out: - return retval; + return 0; } static int __devexit ssc_remove(struct platform_device *pdev) @@ -142,10 +128,7 @@ static int __devexit ssc_remove(struct platform_device *pdev) struct ssc_device *ssc = platform_get_drvdata(pdev); spin_lock(&user_lock); - iounmap(ssc->regs); - clk_put(ssc->clk); list_del(&ssc->list); - kfree(ssc); spin_unlock(&user_lock); return 0; -- cgit v1.2.3 From 5c86ac695c7e2402f60e30ad8174ceb66ef22a91 Mon Sep 17 00:00:00 2001 From: Bo Shen Date: Tue, 16 Oct 2012 11:56:59 +0800 Subject: ASoC: atmel-ssc: use module_platform_driver macro This patch removes some code duplication by using module_platform_driver Signed-off-by: Bo Shen Signed-off-by: Mark Brown --- drivers/misc/atmel-ssc.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c index 23dcb76abdaf..ac00f83ea86b 100644 --- a/drivers/misc/atmel-ssc.c +++ b/drivers/misc/atmel-ssc.c @@ -68,7 +68,7 @@ void ssc_free(struct ssc_device *ssc) } EXPORT_SYMBOL(ssc_free); -static int __init ssc_probe(struct platform_device *pdev) +static int ssc_probe(struct platform_device *pdev) { struct resource *regs; struct ssc_device *ssc; @@ -135,24 +135,14 @@ static int __devexit ssc_remove(struct platform_device *pdev) } static struct platform_driver ssc_driver = { - .remove = __devexit_p(ssc_remove), .driver = { .name = "ssc", .owner = THIS_MODULE, }, + .probe = ssc_probe, + .remove = __devexit_p(ssc_remove), }; - -static int __init ssc_init(void) -{ - return platform_driver_probe(&ssc_driver, ssc_probe); -} -module_init(ssc_init); - -static void __exit ssc_exit(void) -{ - platform_driver_unregister(&ssc_driver); -} -module_exit(ssc_exit); +module_platform_driver(ssc_driver); MODULE_AUTHOR("Hans-Christian Egtvedt "); MODULE_DESCRIPTION("SSC driver for Atmel AVR32 and AT91"); -- cgit v1.2.3 From 636036d29a20154b897571e1d5949faac98bfb7c Mon Sep 17 00:00:00 2001 From: Bo Shen Date: Tue, 6 Nov 2012 13:57:51 +0800 Subject: ARM: at91: atmel-ssc: add platform device id table Add platform device id to check whether the SSC controller support pdc or dam for data transfer If match "at91rm9200_ssc", which support pdc for data transfer If match "at91sam9g45_ssc", which support dma for data transfer Signed-off-by: Bo Shen Acked-by: Nicolas Ferre Signed-off-by: Mark Brown --- drivers/misc/atmel-ssc.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers') diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c index ac00f83ea86b..f40abd8a6695 100644 --- a/drivers/misc/atmel-ssc.c +++ b/drivers/misc/atmel-ssc.c @@ -68,6 +68,26 @@ void ssc_free(struct ssc_device *ssc) } EXPORT_SYMBOL(ssc_free); +static struct atmel_ssc_platform_data at91rm9200_config = { + .use_dma = 0, +}; + +static struct atmel_ssc_platform_data at91sam9g45_config = { + .use_dma = 1, +}; + +static const struct platform_device_id atmel_ssc_devtypes[] = { + { + .name = "at91rm9200_ssc", + .driver_data = (unsigned long) &at91rm9200_config, + }, { + .name = "at91sam9g45_ssc", + .driver_data = (unsigned long) &at91sam9g45_config, + }, { + /* sentinel */ + } +}; + static int ssc_probe(struct platform_device *pdev) { struct resource *regs; @@ -80,6 +100,8 @@ static int ssc_probe(struct platform_device *pdev) } ssc->pdev = pdev; + ssc->pdata = (struct atmel_ssc_platform_data *) + platform_get_device_id(pdev)->driver_data; regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!regs) { @@ -139,6 +161,7 @@ static struct platform_driver ssc_driver = { .name = "ssc", .owner = THIS_MODULE, }, + .id_table = atmel_ssc_devtypes, .probe = ssc_probe, .remove = __devexit_p(ssc_remove), }; -- cgit v1.2.3 From 099343c64e1615ae83b0994197027be363ca4899 Mon Sep 17 00:00:00 2001 From: Bo Shen Date: Wed, 7 Nov 2012 11:41:41 +0800 Subject: ARM: at91: atmel-ssc: add device tree support Add atmel-ssc for device tree support Match "atmel,at91rm9200-ssc" for using pdc for data transfer Match "atmel,at91sam9g45-ssc" for using dma for data transfer Signed-off-by: Bo Shen Acked-by: Nicolas Ferre Signed-off-by: Mark Brown --- drivers/misc/atmel-ssc.c | 49 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c index f40abd8a6695..a769719e36bf 100644 --- a/drivers/misc/atmel-ssc.c +++ b/drivers/misc/atmel-ssc.c @@ -18,6 +18,8 @@ #include #include +#include + /* Serialize access to ssc_list and user count */ static DEFINE_SPINLOCK(user_lock); static LIST_HEAD(ssc_list); @@ -29,7 +31,13 @@ struct ssc_device *ssc_request(unsigned int ssc_num) spin_lock(&user_lock); list_for_each_entry(ssc, &ssc_list, list) { - if (ssc->pdev->id == ssc_num) { + if (ssc->pdev->dev.of_node) { + if (of_alias_get_id(ssc->pdev->dev.of_node, "ssc") + == ssc_num) { + ssc_valid = 1; + break; + } + } else if (ssc->pdev->id == ssc_num) { ssc_valid = 1; break; } @@ -88,10 +96,41 @@ static const struct platform_device_id atmel_ssc_devtypes[] = { } }; +#ifdef CONFIG_OF +static const struct of_device_id atmel_ssc_dt_ids[] = { + { + .compatible = "atmel,at91rm9200-ssc", + .data = &at91rm9200_config, + }, { + .compatible = "atmel,at91sam9g45-ssc", + .data = &at91sam9g45_config, + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(of, atmel_ssc_dt_ids); +#endif + +static inline const struct atmel_ssc_platform_data * __init + atmel_ssc_get_driver_data(struct platform_device *pdev) +{ + if (pdev->dev.of_node) { + const struct of_device_id *match; + match = of_match_node(atmel_ssc_dt_ids, pdev->dev.of_node); + if (match == NULL) + return NULL; + return match->data; + } + + return (struct atmel_ssc_platform_data *) + platform_get_device_id(pdev)->driver_data; +} + static int ssc_probe(struct platform_device *pdev) { struct resource *regs; struct ssc_device *ssc; + const struct atmel_ssc_platform_data *plat_dat; ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL); if (!ssc) { @@ -100,8 +139,11 @@ static int ssc_probe(struct platform_device *pdev) } ssc->pdev = pdev; - ssc->pdata = (struct atmel_ssc_platform_data *) - platform_get_device_id(pdev)->driver_data; + + plat_dat = atmel_ssc_get_driver_data(pdev); + if (!plat_dat) + return -ENODEV; + ssc->pdata = (struct atmel_ssc_platform_data *)plat_dat; regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!regs) { @@ -160,6 +202,7 @@ static struct platform_driver ssc_driver = { .driver = { .name = "ssc", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(atmel_ssc_dt_ids), }, .id_table = atmel_ssc_devtypes, .probe = ssc_probe, -- cgit v1.2.3 From 31974361761b18e07e821d3b262e34f1a2d105cb Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 20 Nov 2012 16:38:17 +0800 Subject: ASoC: atmel-ssc: add phybase in device structure Useful for future dmaengine use. Signed-off-by: Nicolas Ferre Signed-off-by: Mark Brown --- drivers/misc/atmel-ssc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c index a769719e36bf..d07a9eda7fff 100644 --- a/drivers/misc/atmel-ssc.c +++ b/drivers/misc/atmel-ssc.c @@ -157,6 +157,8 @@ static int ssc_probe(struct platform_device *pdev) return -EINVAL; } + ssc->phybase = regs->start; + ssc->clk = devm_clk_get(&pdev->dev, "pclk"); if (IS_ERR(ssc->clk)) { dev_dbg(&pdev->dev, "no pclk clock defined\n"); -- cgit v1.2.3 From a8a8fc287dd7497b3adb2f2952513849ab6506eb Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 8 Oct 2012 11:21:09 +0900 Subject: mfd: wm8994: Store platform data in device This is better style as platform data is supposed to be discardable after init (though hotplug usually prevents this) and will ease implementation of device tree property bindings. Signed-off-by: Mark Brown Acked-by: Samuel Ortiz --- drivers/mfd/wm8994-core.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index 8fefc961ec06..45a20c573aa3 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -401,13 +401,19 @@ static const __devinitconst struct reg_default wm1811_reva_patch[] = { */ static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq) { - struct wm8994_pdata *pdata = wm8994->dev->platform_data; + struct wm8994_pdata *pdata; struct regmap_config *regmap_config; const struct reg_default *regmap_patch = NULL; const char *devname; int ret, i, patch_regs; int pulls = 0; + if (dev_get_platdata(wm8994->dev)) { + pdata = dev_get_platdata(wm8994->dev); + wm8994->pdata = *pdata; + } + pdata = &wm8994->pdata; + dev_set_drvdata(wm8994->dev, wm8994); /* Add the on-chip regulators first for bootstrapping */ @@ -604,24 +610,21 @@ static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq) } } - if (pdata) { - wm8994->irq_base = pdata->irq_base; - wm8994->gpio_base = pdata->gpio_base; - - /* GPIO configuration is only applied if it's non-zero */ - for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) { - if (pdata->gpio_defaults[i]) { - wm8994_set_bits(wm8994, WM8994_GPIO_1 + i, - 0xffff, - pdata->gpio_defaults[i]); - } + wm8994->irq_base = pdata->irq_base; + wm8994->gpio_base = pdata->gpio_base; + + /* GPIO configuration is only applied if it's non-zero */ + for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) { + if (pdata->gpio_defaults[i]) { + wm8994_set_bits(wm8994, WM8994_GPIO_1 + i, + 0xffff, pdata->gpio_defaults[i]); } + } - wm8994->ldo_ena_always_driven = pdata->ldo_ena_always_driven; + wm8994->ldo_ena_always_driven = pdata->ldo_ena_always_driven; - if (pdata->spkmode_pu) - pulls |= WM8994_SPKMODE_PU; - } + if (pdata->spkmode_pu) + pulls |= WM8994_SPKMODE_PU; /* Disable unneeded pulls */ wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2, -- cgit v1.2.3 From 9dd555e2f4de1af1bb0f75cc84ed0708fcdb5987 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 26 Nov 2012 21:17:21 +0000 Subject: Input - arizona-haptics: Add driver haptics module on Arizona CODECs The Arizona CODECs contain a haptics module providing vibration feedback support. Implement basic support for this, providing simple start/stop and signal magnitude control. Since the output path for haptics is routed through the CODEC audio routing it is modelled as a signal generator within ASoC, the haptics driver calls DAPM to start and stop the output drivers. An appropriate output path must be configured via ALSA to connect the haptics source to the correct output. Signed-off-by: Mark Brown --- drivers/input/misc/Kconfig | 10 ++ drivers/input/misc/Makefile | 1 + drivers/input/misc/arizona-haptics.c | 255 +++++++++++++++++++++++++++++++++++ 3 files changed, 266 insertions(+) create mode 100644 drivers/input/misc/arizona-haptics.c (limited to 'drivers') diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 7c0f1ecfdd7a..104a7c3153c0 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -72,6 +72,16 @@ config INPUT_AD714X_SPI To compile this driver as a module, choose M here: the module will be called ad714x-spi. +config INPUT_ARIZONA_HAPTICS + tristate "Arizona haptics support" + depends on MFD_ARIZONA && SND_SOC + select INPUT_FF_MEMLESS + help + Say Y to enable support for the haptics module in Arizona CODECs. + + To compile this driver as a module, choose M here: the + module will be called arizona-haptics. + config INPUT_BMA150 tristate "BMA150/SMB380 acceleration sensor support" depends on I2C diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 83fe6f5b77d1..5ea769eda999 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_INPUT_ADXL34X) += adxl34x.o obj-$(CONFIG_INPUT_ADXL34X_I2C) += adxl34x-i2c.o obj-$(CONFIG_INPUT_ADXL34X_SPI) += adxl34x-spi.o obj-$(CONFIG_INPUT_APANEL) += apanel.o +obj-$(CONFIG_INPUT_ARIZONA_HAPTICS) += arizona-haptics.o obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o obj-$(CONFIG_INPUT_BFIN_ROTARY) += bfin_rotary.o diff --git a/drivers/input/misc/arizona-haptics.c b/drivers/input/misc/arizona-haptics.c new file mode 100644 index 000000000000..7a04f54ef961 --- /dev/null +++ b/drivers/input/misc/arizona-haptics.c @@ -0,0 +1,255 @@ +/* + * Arizona haptics driver + * + * Copyright 2012 Wolfson Microelectronics plc + * + * Author: Mark Brown + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +struct arizona_haptics { + struct arizona *arizona; + struct input_dev *input_dev; + struct work_struct work; + + struct mutex mutex; + u8 intensity; +}; + +static void arizona_haptics_work(struct work_struct *work) +{ + struct arizona_haptics *haptics = container_of(work, + struct arizona_haptics, + work); + struct arizona *arizona = haptics->arizona; + struct mutex *dapm_mutex = &arizona->dapm->card->dapm_mutex; + int ret; + + if (!haptics->arizona->dapm) { + dev_err(arizona->dev, "No DAPM context\n"); + return; + } + + if (haptics->intensity) { + ret = regmap_update_bits(arizona->regmap, + ARIZONA_HAPTICS_PHASE_2_INTENSITY, + ARIZONA_PHASE2_INTENSITY_MASK, + haptics->intensity); + if (ret != 0) { + dev_err(arizona->dev, "Failed to set intensity: %d\n", + ret); + return; + } + + /* This enable sequence will be a noop if already enabled */ + ret = regmap_update_bits(arizona->regmap, + ARIZONA_HAPTICS_CONTROL_1, + ARIZONA_HAP_CTRL_MASK, + 1 << ARIZONA_HAP_CTRL_SHIFT); + if (ret != 0) { + dev_err(arizona->dev, "Failed to start haptics: %d\n", + ret); + return; + } + + mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + + ret = snd_soc_dapm_enable_pin(arizona->dapm, "HAPTICS"); + if (ret != 0) { + dev_err(arizona->dev, "Failed to start HAPTICS: %d\n", + ret); + mutex_unlock(dapm_mutex); + return; + } + + ret = snd_soc_dapm_sync(arizona->dapm); + if (ret != 0) { + dev_err(arizona->dev, "Failed to sync DAPM: %d\n", + ret); + mutex_unlock(dapm_mutex); + return; + } + + mutex_unlock(dapm_mutex); + + } else { + /* This disable sequence will be a noop if already enabled */ + mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + + ret = snd_soc_dapm_disable_pin(arizona->dapm, "HAPTICS"); + if (ret != 0) { + dev_err(arizona->dev, "Failed to disable HAPTICS: %d\n", + ret); + mutex_unlock(dapm_mutex); + return; + } + + ret = snd_soc_dapm_sync(arizona->dapm); + if (ret != 0) { + dev_err(arizona->dev, "Failed to sync DAPM: %d\n", + ret); + mutex_unlock(dapm_mutex); + return; + } + + mutex_unlock(dapm_mutex); + + ret = regmap_update_bits(arizona->regmap, + ARIZONA_HAPTICS_CONTROL_1, + ARIZONA_HAP_CTRL_MASK, + 1 << ARIZONA_HAP_CTRL_SHIFT); + if (ret != 0) { + dev_err(arizona->dev, "Failed to stop haptics: %d\n", + ret); + return; + } + } +} + +static int arizona_haptics_play(struct input_dev *input, void *data, + struct ff_effect *effect) +{ + struct arizona_haptics *haptics = input_get_drvdata(input); + struct arizona *arizona = haptics->arizona; + + if (!arizona->dapm) { + dev_err(arizona->dev, "No DAPM context\n"); + return -EBUSY; + } + + if (effect->u.rumble.strong_magnitude) { + /* Scale the magnitude into the range the device supports */ + if (arizona->pdata.hap_act) { + haptics->intensity = + effect->u.rumble.strong_magnitude >> 9; + if (effect->direction < 0x8000) + haptics->intensity += 0x7f; + } else { + haptics->intensity = + effect->u.rumble.strong_magnitude >> 8; + } + } else { + haptics->intensity = 0; + } + + schedule_work(&haptics->work); + + return 0; +} + +static void arizona_haptics_close(struct input_dev *input) +{ + struct arizona_haptics *haptics = input_get_drvdata(input); + struct mutex *dapm_mutex = &haptics->arizona->dapm->card->dapm_mutex; + + cancel_work_sync(&haptics->work); + + mutex_lock_nested(dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); + + if (haptics->arizona->dapm) + snd_soc_dapm_disable_pin(haptics->arizona->dapm, "HAPTICS"); + + mutex_unlock(dapm_mutex); +} + +static int arizona_haptics_probe(struct platform_device *pdev) +{ + struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); + struct arizona_haptics *haptics; + int ret; + + haptics = devm_kzalloc(&pdev->dev, sizeof(*haptics), GFP_KERNEL); + if (!haptics) + return -ENOMEM; + + haptics->arizona = arizona; + + ret = regmap_update_bits(arizona->regmap, ARIZONA_HAPTICS_CONTROL_1, + ARIZONA_HAP_ACT, arizona->pdata.hap_act); + if (ret != 0) { + dev_err(arizona->dev, "Failed to set haptics actuator: %d\n", + ret); + return ret; + } + + INIT_WORK(&haptics->work, arizona_haptics_work); + + haptics->input_dev = input_allocate_device(); + if (haptics->input_dev == NULL) { + dev_err(arizona->dev, "Failed to allocate input device\n"); + return -ENOMEM; + } + + input_set_drvdata(haptics->input_dev, haptics); + + haptics->input_dev->name = "arizona:haptics"; + haptics->input_dev->dev.parent = pdev->dev.parent; + haptics->input_dev->close = arizona_haptics_close; + __set_bit(FF_RUMBLE, haptics->input_dev->ffbit); + + ret = input_ff_create_memless(haptics->input_dev, NULL, + arizona_haptics_play); + if (ret < 0) { + dev_err(arizona->dev, "input_ff_create_memless() failed: %d\n", + ret); + goto err_ialloc; + } + + ret = input_register_device(haptics->input_dev); + if (ret < 0) { + dev_err(arizona->dev, "couldn't register input device: %d\n", + ret); + goto err_iff; + } + + platform_set_drvdata(pdev, haptics); + + return 0; + +err_iff: + if (haptics->input_dev) + input_ff_destroy(haptics->input_dev); +err_ialloc: + input_free_device(haptics->input_dev); + + return ret; +} + +static int arizona_haptics_remove(struct platform_device *pdev) +{ + struct arizona_haptics *haptics = platform_get_drvdata(pdev); + + input_unregister_device(haptics->input_dev); + + return 0; +} + +static struct platform_driver arizona_haptics_driver = { + .probe = arizona_haptics_probe, + .remove = arizona_haptics_remove, + .driver = { + .name = "arizona-haptics", + .owner = THIS_MODULE, + }, +}; +module_platform_driver(arizona_haptics_driver); + +MODULE_ALIAS("platform:arizona-haptics"); +MODULE_DESCRIPTION("Arizona haptics driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mark Brown "); -- cgit v1.2.3 From 503b1cac5c7bb94b267c831d0a7966a18d38365e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 27 Nov 2012 17:36:38 +0000 Subject: mfd: arizona: Register haptics devices Both WM5102 and WM5110 support haptics, register the device. Signed-off-by: Mark Brown --- drivers/mfd/arizona-core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 1b48f2094806..75619711a9e7 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -272,6 +272,7 @@ static struct mfd_cell early_devs[] = { static struct mfd_cell wm5102_devs[] = { { .name = "arizona-extcon" }, { .name = "arizona-gpio" }, + { .name = "arizona-haptics" }, { .name = "arizona-micsupp" }, { .name = "arizona-pwm" }, { .name = "wm5102-codec" }, @@ -280,6 +281,7 @@ static struct mfd_cell wm5102_devs[] = { static struct mfd_cell wm5110_devs[] = { { .name = "arizona-extcon" }, { .name = "arizona-gpio" }, + { .name = "arizona-haptics" }, { .name = "arizona-micsupp" }, { .name = "arizona-pwm" }, { .name = "wm5110-codec" }, -- cgit v1.2.3