aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/extcon/extcon-arizona.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-01 15:10:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-01 15:10:44 -0400
commit06d2fe153b9b35e57221e35831a26918f462db68 (patch)
treef77cb72dfba7f2a47ceb93e120abd9399a24a1b9 /drivers/extcon/extcon-arizona.c
parent3aebd34b1200a902a8662da8845824a02f00772e (diff)
parente0f21e6d52cc245e7d4f7e02ca4b7b6571660ec2 (diff)
Merge tag 'driver-core-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core
Pull driver core merge from Greg Kroah-Hartman: "Here is the big driver core update for 3.7-rc1. A number of firmware_class.c updates (as you saw a month or so ago), and some hyper-v updates and some printk fixes as well. All patches that are outside of the drivers/base area have been acked by the respective maintainers, and have all been in the linux-next tree for a while. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>" * tag 'driver-core-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (95 commits) memory: tegra{20,30}-mc: Fix reading incorrect register in mc_readl() device.h: Add missing inline to #ifndef CONFIG_PRINTK dev_vprintk_emit memory: emif: Add ifdef CONFIG_DEBUG_FS guard for emif_debugfs_[init|exit] Documentation: Fixes some translation error in Documentation/zh_CN/gpio.txt Documentation: Remove 3 byte redundant code at the head of the Documentation/zh_CN/arm/booting Documentation: Chinese translation of Documentation/video4linux/omap3isp.txt device and dynamic_debug: Use dev_vprintk_emit and dev_printk_emit dev: Add dev_vprintk_emit and dev_printk_emit netdev_printk/netif_printk: Remove a superfluous logging colon netdev_printk/dynamic_netdev_dbg: Directly call printk_emit dev_dbg/dynamic_debug: Update to use printk_emit, optimize stack driver-core: Shut up dev_dbg_reatelimited() without DEBUG tools/hv: Parse /etc/os-release tools/hv: Check for read/write errors tools/hv: Fix exit() error code tools/hv: Fix file handle leak Tools: hv: Implement the KVP verb - KVP_OP_GET_IP_INFO Tools: hv: Rename the function kvp_get_ip_address() Tools: hv: Implement the KVP verb - KVP_OP_SET_IP_INFO Tools: hv: Add an example script to configure an interface ...
Diffstat (limited to 'drivers/extcon/extcon-arizona.c')
-rw-r--r--drivers/extcon/extcon-arizona.c78
1 files changed, 69 insertions, 9 deletions
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index 6c19833ed2d..cdab9e59829 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -21,6 +21,7 @@
21#include <linux/interrupt.h> 21#include <linux/interrupt.h>
22#include <linux/err.h> 22#include <linux/err.h>
23#include <linux/gpio.h> 23#include <linux/gpio.h>
24#include <linux/input.h>
24#include <linux/platform_device.h> 25#include <linux/platform_device.h>
25#include <linux/pm_runtime.h> 26#include <linux/pm_runtime.h>
26#include <linux/regulator/consumer.h> 27#include <linux/regulator/consumer.h>
@@ -30,11 +31,14 @@
30#include <linux/mfd/arizona/pdata.h> 31#include <linux/mfd/arizona/pdata.h>
31#include <linux/mfd/arizona/registers.h> 32#include <linux/mfd/arizona/registers.h>
32 33
34#define ARIZONA_NUM_BUTTONS 6
35
33struct arizona_extcon_info { 36struct arizona_extcon_info {
34 struct device *dev; 37 struct device *dev;
35 struct arizona *arizona; 38 struct arizona *arizona;
36 struct mutex lock; 39 struct mutex lock;
37 struct regulator *micvdd; 40 struct regulator *micvdd;
41 struct input_dev *input;
38 42
39 int micd_mode; 43 int micd_mode;
40 const struct arizona_micd_config *micd_modes; 44 const struct arizona_micd_config *micd_modes;
@@ -54,6 +58,18 @@ static const struct arizona_micd_config micd_default_modes[] = {
54 { 0, 2 << ARIZONA_MICD_BIAS_SRC_SHIFT, 1 }, 58 { 0, 2 << ARIZONA_MICD_BIAS_SRC_SHIFT, 1 },
55}; 59};
56 60
61static struct {
62 u16 status;
63 int report;
64} arizona_lvl_to_key[ARIZONA_NUM_BUTTONS] = {
65 { 0x1, BTN_0 },
66 { 0x2, BTN_1 },
67 { 0x4, BTN_2 },
68 { 0x8, BTN_3 },
69 { 0x10, BTN_4 },
70 { 0x20, BTN_5 },
71};
72
57#define ARIZONA_CABLE_MECHANICAL 0 73#define ARIZONA_CABLE_MECHANICAL 0
58#define ARIZONA_CABLE_MICROPHONE 1 74#define ARIZONA_CABLE_MICROPHONE 1
59#define ARIZONA_CABLE_HEADPHONE 2 75#define ARIZONA_CABLE_HEADPHONE 2
@@ -133,6 +149,7 @@ static void arizona_stop_mic(struct arizona_extcon_info *info)
133 149
134 if (change) { 150 if (change) {
135 regulator_disable(info->micvdd); 151 regulator_disable(info->micvdd);
152 pm_runtime_mark_last_busy(info->dev);
136 pm_runtime_put_autosuspend(info->dev); 153 pm_runtime_put_autosuspend(info->dev);
137 } 154 }
138} 155}
@@ -141,8 +158,8 @@ static irqreturn_t arizona_micdet(int irq, void *data)
141{ 158{
142 struct arizona_extcon_info *info = data; 159 struct arizona_extcon_info *info = data;
143 struct arizona *arizona = info->arizona; 160 struct arizona *arizona = info->arizona;
144 unsigned int val; 161 unsigned int val, lvl;
145 int ret; 162 int ret, i;
146 163
147 mutex_lock(&info->lock); 164 mutex_lock(&info->lock);
148 165
@@ -219,13 +236,22 @@ static irqreturn_t arizona_micdet(int irq, void *data)
219 236
220 /* 237 /*
221 * If we're still detecting and we detect a short then we've 238 * If we're still detecting and we detect a short then we've
222 * got a headphone. Otherwise it's a button press, the 239 * got a headphone. Otherwise it's a button press.
223 * button reporting is stubbed out for now.
224 */ 240 */
225 if (val & 0x3fc) { 241 if (val & 0x3fc) {
226 if (info->mic) { 242 if (info->mic) {
227 dev_dbg(arizona->dev, "Mic button detected\n"); 243 dev_dbg(arizona->dev, "Mic button detected\n");
228 244
245 lvl = val & ARIZONA_MICD_LVL_MASK;
246 lvl >>= ARIZONA_MICD_LVL_SHIFT;
247
248 for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
249 if (lvl & arizona_lvl_to_key[i].status)
250 input_report_key(info->input,
251 arizona_lvl_to_key[i].report,
252 1);
253 input_sync(info->input);
254
229 } else if (info->detecting) { 255 } else if (info->detecting) {
230 dev_dbg(arizona->dev, "Headphone detected\n"); 256 dev_dbg(arizona->dev, "Headphone detected\n");
231 info->detecting = false; 257 info->detecting = false;
@@ -244,6 +270,10 @@ static irqreturn_t arizona_micdet(int irq, void *data)
244 } 270 }
245 } else { 271 } else {
246 dev_dbg(arizona->dev, "Mic button released\n"); 272 dev_dbg(arizona->dev, "Mic button released\n");
273 for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
274 input_report_key(info->input,
275 arizona_lvl_to_key[i].report, 0);
276 input_sync(info->input);
247 } 277 }
248 278
249handled: 279handled:
@@ -258,7 +288,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
258 struct arizona_extcon_info *info = data; 288 struct arizona_extcon_info *info = data;
259 struct arizona *arizona = info->arizona; 289 struct arizona *arizona = info->arizona;
260 unsigned int val; 290 unsigned int val;
261 int ret; 291 int ret, i;
262 292
263 pm_runtime_get_sync(info->dev); 293 pm_runtime_get_sync(info->dev);
264 294
@@ -288,6 +318,11 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
288 318
289 arizona_stop_mic(info); 319 arizona_stop_mic(info);
290 320
321 for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
322 input_report_key(info->input,
323 arizona_lvl_to_key[i].report, 0);
324 input_sync(info->input);
325
291 ret = extcon_update_state(&info->edev, 0xffffffff, 0); 326 ret = extcon_update_state(&info->edev, 0xffffffff, 0);
292 if (ret != 0) 327 if (ret != 0)
293 dev_err(arizona->dev, "Removal report failed: %d\n", 328 dev_err(arizona->dev, "Removal report failed: %d\n",
@@ -307,13 +342,13 @@ static int __devinit arizona_extcon_probe(struct platform_device *pdev)
307 struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); 342 struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
308 struct arizona_pdata *pdata; 343 struct arizona_pdata *pdata;
309 struct arizona_extcon_info *info; 344 struct arizona_extcon_info *info;
310 int ret, mode; 345 int ret, mode, i;
311 346
312 pdata = dev_get_platdata(arizona->dev); 347 pdata = dev_get_platdata(arizona->dev);
313 348
314 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); 349 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
315 if (!info) { 350 if (!info) {
316 dev_err(&pdev->dev, "failed to allocate memory\n"); 351 dev_err(&pdev->dev, "Failed to allocate memory\n");
317 ret = -ENOMEM; 352 ret = -ENOMEM;
318 goto err; 353 goto err;
319 } 354 }
@@ -350,7 +385,7 @@ static int __devinit arizona_extcon_probe(struct platform_device *pdev)
350 385
351 ret = extcon_dev_register(&info->edev, arizona->dev); 386 ret = extcon_dev_register(&info->edev, arizona->dev);
352 if (ret < 0) { 387 if (ret < 0) {
353 dev_err(arizona->dev, "extcon_dev_regster() failed: %d\n", 388 dev_err(arizona->dev, "extcon_dev_register() failed: %d\n",
354 ret); 389 ret);
355 goto err; 390 goto err;
356 } 391 }
@@ -382,6 +417,20 @@ static int __devinit arizona_extcon_probe(struct platform_device *pdev)
382 417
383 arizona_extcon_set_mode(info, 0); 418 arizona_extcon_set_mode(info, 0);
384 419
420 info->input = input_allocate_device();
421 if (!info->input) {
422 dev_err(arizona->dev, "Can't allocate input dev\n");
423 ret = -ENOMEM;
424 goto err_register;
425 }
426
427 for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
428 input_set_capability(info->input, EV_KEY,
429 arizona_lvl_to_key[i].report);
430 info->input->name = "Headset";
431 info->input->phys = "arizona/extcon";
432 info->input->dev.parent = &pdev->dev;
433
385 pm_runtime_enable(&pdev->dev); 434 pm_runtime_enable(&pdev->dev);
386 pm_runtime_idle(&pdev->dev); 435 pm_runtime_idle(&pdev->dev);
387 pm_runtime_get_sync(&pdev->dev); 436 pm_runtime_get_sync(&pdev->dev);
@@ -391,7 +440,7 @@ static int __devinit arizona_extcon_probe(struct platform_device *pdev)
391 if (ret != 0) { 440 if (ret != 0) {
392 dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n", 441 dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n",
393 ret); 442 ret);
394 goto err_register; 443 goto err_input;
395 } 444 }
396 445
397 ret = arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_RISE, 1); 446 ret = arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_RISE, 1);
@@ -441,8 +490,16 @@ static int __devinit arizona_extcon_probe(struct platform_device *pdev)
441 490
442 pm_runtime_put(&pdev->dev); 491 pm_runtime_put(&pdev->dev);
443 492
493 ret = input_register_device(info->input);
494 if (ret) {
495 dev_err(&pdev->dev, "Can't register input device: %d\n", ret);
496 goto err_micdet;
497 }
498
444 return 0; 499 return 0;
445 500
501err_micdet:
502 arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
446err_fall_wake: 503err_fall_wake:
447 arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_FALL, 0); 504 arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_FALL, 0);
448err_fall: 505err_fall:
@@ -451,6 +508,8 @@ err_rise_wake:
451 arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_RISE, 0); 508 arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_RISE, 0);
452err_rise: 509err_rise:
453 arizona_free_irq(arizona, ARIZONA_IRQ_JD_RISE, info); 510 arizona_free_irq(arizona, ARIZONA_IRQ_JD_RISE, info);
511err_input:
512 input_free_device(info->input);
454err_register: 513err_register:
455 pm_runtime_disable(&pdev->dev); 514 pm_runtime_disable(&pdev->dev);
456 extcon_dev_unregister(&info->edev); 515 extcon_dev_unregister(&info->edev);
@@ -473,6 +532,7 @@ static int __devexit arizona_extcon_remove(struct platform_device *pdev)
473 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, 532 regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
474 ARIZONA_JD1_ENA, 0); 533 ARIZONA_JD1_ENA, 0);
475 arizona_clk32k_disable(arizona); 534 arizona_clk32k_disable(arizona);
535 input_unregister_device(info->input);
476 extcon_dev_unregister(&info->edev); 536 extcon_dev_unregister(&info->edev);
477 537
478 return 0; 538 return 0;