diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-01 15:10:44 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-01 15:10:44 -0400 |
commit | 06d2fe153b9b35e57221e35831a26918f462db68 (patch) | |
tree | f77cb72dfba7f2a47ceb93e120abd9399a24a1b9 /drivers/extcon | |
parent | 3aebd34b1200a902a8662da8845824a02f00772e (diff) | |
parent | e0f21e6d52cc245e7d4f7e02ca4b7b6571660ec2 (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')
-rw-r--r-- | drivers/extcon/Kconfig | 8 | ||||
-rw-r--r-- | drivers/extcon/Makefile | 5 | ||||
-rw-r--r-- | drivers/extcon/extcon-adc-jack.c | 198 | ||||
-rw-r--r-- | drivers/extcon/extcon-arizona.c | 78 | ||||
-rw-r--r-- | drivers/extcon/extcon-class.c (renamed from drivers/extcon/extcon_class.c) | 12 | ||||
-rw-r--r-- | drivers/extcon/extcon-gpio.c (renamed from drivers/extcon/extcon_gpio.c) | 0 | ||||
-rw-r--r-- | drivers/extcon/extcon-max77693.c | 8 |
7 files changed, 289 insertions, 20 deletions
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig index e175c8ed4ec..07122a9ef36 100644 --- a/drivers/extcon/Kconfig +++ b/drivers/extcon/Kconfig | |||
@@ -21,6 +21,12 @@ config EXTCON_GPIO | |||
21 | Say Y here to enable GPIO based extcon support. Note that GPIO | 21 | Say Y here to enable GPIO based extcon support. Note that GPIO |
22 | extcon supports single state per extcon instance. | 22 | extcon supports single state per extcon instance. |
23 | 23 | ||
24 | config EXTCON_ADC_JACK | ||
25 | tristate "ADC Jack extcon support" | ||
26 | depends on IIO | ||
27 | help | ||
28 | Say Y here to enable extcon device driver based on ADC values. | ||
29 | |||
24 | config EXTCON_MAX77693 | 30 | config EXTCON_MAX77693 |
25 | tristate "MAX77693 EXTCON Support" | 31 | tristate "MAX77693 EXTCON Support" |
26 | depends on MFD_MAX77693 | 32 | depends on MFD_MAX77693 |
@@ -41,7 +47,7 @@ config EXTCON_MAX8997 | |||
41 | 47 | ||
42 | config EXTCON_ARIZONA | 48 | config EXTCON_ARIZONA |
43 | tristate "Wolfson Arizona EXTCON support" | 49 | tristate "Wolfson Arizona EXTCON support" |
44 | depends on MFD_ARIZONA | 50 | depends on MFD_ARIZONA && INPUT |
45 | help | 51 | help |
46 | Say Y here to enable support for external accessory detection | 52 | Say Y here to enable support for external accessory detection |
47 | with Wolfson Arizona devices. These are audio CODECs with | 53 | with Wolfson Arizona devices. These are audio CODECs with |
diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile index 88961b33234..f98a3c4d46e 100644 --- a/drivers/extcon/Makefile +++ b/drivers/extcon/Makefile | |||
@@ -2,8 +2,9 @@ | |||
2 | # Makefile for external connector class (extcon) devices | 2 | # Makefile for external connector class (extcon) devices |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_EXTCON) += extcon_class.o | 5 | obj-$(CONFIG_EXTCON) += extcon-class.o |
6 | obj-$(CONFIG_EXTCON_GPIO) += extcon_gpio.o | 6 | obj-$(CONFIG_EXTCON_GPIO) += extcon-gpio.o |
7 | obj-$(CONFIG_EXTCON_ADC_JACK) += extcon-adc-jack.o | ||
7 | obj-$(CONFIG_EXTCON_MAX77693) += extcon-max77693.o | 8 | obj-$(CONFIG_EXTCON_MAX77693) += extcon-max77693.o |
8 | obj-$(CONFIG_EXTCON_MAX8997) += extcon-max8997.o | 9 | obj-$(CONFIG_EXTCON_MAX8997) += extcon-max8997.o |
9 | obj-$(CONFIG_EXTCON_ARIZONA) += extcon-arizona.o | 10 | obj-$(CONFIG_EXTCON_ARIZONA) += extcon-arizona.o |
diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c new file mode 100644 index 00000000000..60ac3fbb4cd --- /dev/null +++ b/drivers/extcon/extcon-adc-jack.c | |||
@@ -0,0 +1,198 @@ | |||
1 | /* | ||
2 | * drivers/extcon/extcon-adc-jack.c | ||
3 | * | ||
4 | * Analog Jack extcon driver with ADC-based detection capability. | ||
5 | * | ||
6 | * Copyright (C) 2012 Samsung Electronics | ||
7 | * MyungJoo Ham <myungjoo.ham@samsung.com> | ||
8 | * | ||
9 | * Modified for calling to IIO to get adc by <anish.singh@samsung.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/slab.h> | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/workqueue.h> | ||
23 | #include <linux/iio/consumer.h> | ||
24 | #include <linux/extcon/extcon-adc-jack.h> | ||
25 | #include <linux/extcon.h> | ||
26 | |||
27 | /** | ||
28 | * struct adc_jack_data - internal data for adc_jack device driver | ||
29 | * @edev - extcon device. | ||
30 | * @cable_names - list of supported cables. | ||
31 | * @num_cables - size of cable_names. | ||
32 | * @adc_conditions - list of adc value conditions. | ||
33 | * @num_conditions - size of adc_conditions. | ||
34 | * @irq - irq number of attach/detach event (0 if not exist). | ||
35 | * @handling_delay - interrupt handler will schedule extcon event | ||
36 | * handling at handling_delay jiffies. | ||
37 | * @handler - extcon event handler called by interrupt handler. | ||
38 | * @chan - iio channel being queried. | ||
39 | */ | ||
40 | struct adc_jack_data { | ||
41 | struct extcon_dev edev; | ||
42 | |||
43 | const char **cable_names; | ||
44 | int num_cables; | ||
45 | struct adc_jack_cond *adc_conditions; | ||
46 | int num_conditions; | ||
47 | |||
48 | int irq; | ||
49 | unsigned long handling_delay; /* in jiffies */ | ||
50 | struct delayed_work handler; | ||
51 | |||
52 | struct iio_channel *chan; | ||
53 | }; | ||
54 | |||
55 | static void adc_jack_handler(struct work_struct *work) | ||
56 | { | ||
57 | struct adc_jack_data *data = container_of(to_delayed_work(work), | ||
58 | struct adc_jack_data, | ||
59 | handler); | ||
60 | u32 state = 0; | ||
61 | int ret, adc_val; | ||
62 | int i; | ||
63 | |||
64 | ret = iio_read_channel_raw(data->chan, &adc_val); | ||
65 | if (ret < 0) { | ||
66 | dev_err(data->edev.dev, "read channel() error: %d\n", ret); | ||
67 | return; | ||
68 | } | ||
69 | |||
70 | /* Get state from adc value with adc_conditions */ | ||
71 | for (i = 0; i < data->num_conditions; i++) { | ||
72 | struct adc_jack_cond *def = &data->adc_conditions[i]; | ||
73 | if (!def->state) | ||
74 | break; | ||
75 | if (def->min_adc <= adc_val && def->max_adc >= adc_val) { | ||
76 | state = def->state; | ||
77 | break; | ||
78 | } | ||
79 | } | ||
80 | /* if no def has met, it means state = 0 (no cables attached) */ | ||
81 | |||
82 | extcon_set_state(&data->edev, state); | ||
83 | } | ||
84 | |||
85 | static irqreturn_t adc_jack_irq_thread(int irq, void *_data) | ||
86 | { | ||
87 | struct adc_jack_data *data = _data; | ||
88 | |||
89 | schedule_delayed_work(&data->handler, data->handling_delay); | ||
90 | return IRQ_HANDLED; | ||
91 | } | ||
92 | |||
93 | static int __devinit adc_jack_probe(struct platform_device *pdev) | ||
94 | { | ||
95 | struct adc_jack_data *data; | ||
96 | struct adc_jack_pdata *pdata = pdev->dev.platform_data; | ||
97 | int i, err = 0; | ||
98 | |||
99 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | ||
100 | if (!data) | ||
101 | return -ENOMEM; | ||
102 | |||
103 | data->edev.name = pdata->name; | ||
104 | |||
105 | if (!pdata->cable_names) { | ||
106 | err = -EINVAL; | ||
107 | dev_err(&pdev->dev, "error: cable_names not defined.\n"); | ||
108 | goto out; | ||
109 | } | ||
110 | |||
111 | data->edev.supported_cable = pdata->cable_names; | ||
112 | |||
113 | /* Check the length of array and set num_cables */ | ||
114 | for (i = 0; data->edev.supported_cable[i]; i++) | ||
115 | ; | ||
116 | if (i == 0 || i > SUPPORTED_CABLE_MAX) { | ||
117 | err = -EINVAL; | ||
118 | dev_err(&pdev->dev, "error: pdata->cable_names size = %d\n", | ||
119 | i - 1); | ||
120 | goto out; | ||
121 | } | ||
122 | data->num_cables = i; | ||
123 | |||
124 | if (!pdata->adc_conditions || | ||
125 | !pdata->adc_conditions[0].state) { | ||
126 | err = -EINVAL; | ||
127 | dev_err(&pdev->dev, "error: adc_conditions not defined.\n"); | ||
128 | goto out; | ||
129 | } | ||
130 | data->adc_conditions = pdata->adc_conditions; | ||
131 | |||
132 | /* Check the length of array and set num_conditions */ | ||
133 | for (i = 0; data->adc_conditions[i].state; i++) | ||
134 | ; | ||
135 | data->num_conditions = i; | ||
136 | |||
137 | data->chan = iio_channel_get(dev_name(&pdev->dev), | ||
138 | pdata->consumer_channel); | ||
139 | if (IS_ERR(data->chan)) { | ||
140 | err = PTR_ERR(data->chan); | ||
141 | goto out; | ||
142 | } | ||
143 | |||
144 | data->handling_delay = msecs_to_jiffies(pdata->handling_delay_ms); | ||
145 | |||
146 | INIT_DELAYED_WORK_DEFERRABLE(&data->handler, adc_jack_handler); | ||
147 | |||
148 | platform_set_drvdata(pdev, data); | ||
149 | |||
150 | err = extcon_dev_register(&data->edev, &pdev->dev); | ||
151 | if (err) | ||
152 | goto out; | ||
153 | |||
154 | data->irq = platform_get_irq(pdev, 0); | ||
155 | if (!data->irq) { | ||
156 | dev_err(&pdev->dev, "platform_get_irq failed\n"); | ||
157 | err = -ENODEV; | ||
158 | goto err_irq; | ||
159 | } | ||
160 | |||
161 | err = request_any_context_irq(data->irq, adc_jack_irq_thread, | ||
162 | pdata->irq_flags, pdata->name, data); | ||
163 | |||
164 | if (err) { | ||
165 | dev_err(&pdev->dev, "error: irq %d\n", data->irq); | ||
166 | err = -EINVAL; | ||
167 | goto err_irq; | ||
168 | } | ||
169 | |||
170 | goto out; | ||
171 | |||
172 | err_irq: | ||
173 | extcon_dev_unregister(&data->edev); | ||
174 | out: | ||
175 | return err; | ||
176 | } | ||
177 | |||
178 | static int __devexit adc_jack_remove(struct platform_device *pdev) | ||
179 | { | ||
180 | struct adc_jack_data *data = platform_get_drvdata(pdev); | ||
181 | |||
182 | free_irq(data->irq, data); | ||
183 | cancel_work_sync(&data->handler.work); | ||
184 | extcon_dev_unregister(&data->edev); | ||
185 | |||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | static struct platform_driver adc_jack_driver = { | ||
190 | .probe = adc_jack_probe, | ||
191 | .remove = __devexit_p(adc_jack_remove), | ||
192 | .driver = { | ||
193 | .name = "adc-jack", | ||
194 | .owner = THIS_MODULE, | ||
195 | }, | ||
196 | }; | ||
197 | |||
198 | module_platform_driver(adc_jack_driver); | ||
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 | |||
33 | struct arizona_extcon_info { | 36 | struct 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 | ||
61 | static 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 | ||
249 | handled: | 279 | handled: |
@@ -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 | ||
501 | err_micdet: | ||
502 | arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info); | ||
446 | err_fall_wake: | 503 | err_fall_wake: |
447 | arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_FALL, 0); | 504 | arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_FALL, 0); |
448 | err_fall: | 505 | err_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); |
452 | err_rise: | 509 | err_rise: |
453 | arizona_free_irq(arizona, ARIZONA_IRQ_JD_RISE, info); | 510 | arizona_free_irq(arizona, ARIZONA_IRQ_JD_RISE, info); |
511 | err_input: | ||
512 | input_free_device(info->input); | ||
454 | err_register: | 513 | err_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; |
diff --git a/drivers/extcon/extcon_class.c b/drivers/extcon/extcon-class.c index f6419f9db76..946a3188b2b 100644 --- a/drivers/extcon/extcon_class.c +++ b/drivers/extcon/extcon-class.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/err.h> | 30 | #include <linux/err.h> |
31 | #include <linux/extcon.h> | 31 | #include <linux/extcon.h> |
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/sysfs.h> | ||
33 | 34 | ||
34 | /* | 35 | /* |
35 | * extcon_cable_name suggests the standard cable names for commonly used | 36 | * extcon_cable_name suggests the standard cable names for commonly used |
@@ -442,7 +443,7 @@ static int _call_per_cable(struct notifier_block *nb, unsigned long val, | |||
442 | 443 | ||
443 | /** | 444 | /** |
444 | * extcon_register_interest() - Register a notifier for a state change of a | 445 | * extcon_register_interest() - Register a notifier for a state change of a |
445 | * specific cable, not a entier set of cables of a | 446 | * specific cable, not an entier set of cables of a |
446 | * extcon device. | 447 | * extcon device. |
447 | * @obj: an empty extcon_specific_cable_nb object to be returned. | 448 | * @obj: an empty extcon_specific_cable_nb object to be returned. |
448 | * @extcon_name: the name of extcon device. | 449 | * @extcon_name: the name of extcon device. |
@@ -498,7 +499,7 @@ int extcon_unregister_interest(struct extcon_specific_cable_nb *obj) | |||
498 | } | 499 | } |
499 | 500 | ||
500 | /** | 501 | /** |
501 | * extcon_register_notifier() - Register a notifee to get notified by | 502 | * extcon_register_notifier() - Register a notifiee to get notified by |
502 | * any attach status changes from the extcon. | 503 | * any attach status changes from the extcon. |
503 | * @edev: the extcon device. | 504 | * @edev: the extcon device. |
504 | * @nb: a notifier block to be registered. | 505 | * @nb: a notifier block to be registered. |
@@ -515,7 +516,7 @@ int extcon_register_notifier(struct extcon_dev *edev, | |||
515 | EXPORT_SYMBOL_GPL(extcon_register_notifier); | 516 | EXPORT_SYMBOL_GPL(extcon_register_notifier); |
516 | 517 | ||
517 | /** | 518 | /** |
518 | * extcon_unregister_notifier() - Unregister a notifee from the extcon device. | 519 | * extcon_unregister_notifier() - Unregister a notifiee from the extcon device. |
519 | * @edev: the extcon device. | 520 | * @edev: the extcon device. |
520 | * @nb: a registered notifier block to be unregistered. | 521 | * @nb: a registered notifier block to be unregistered. |
521 | */ | 522 | */ |
@@ -673,10 +674,12 @@ int extcon_dev_register(struct extcon_dev *edev, struct device *dev) | |||
673 | cable->attr_g.name = str; | 674 | cable->attr_g.name = str; |
674 | cable->attr_g.attrs = cable->attrs; | 675 | cable->attr_g.attrs = cable->attrs; |
675 | 676 | ||
677 | sysfs_attr_init(&cable->attr_name.attr); | ||
676 | cable->attr_name.attr.name = "name"; | 678 | cable->attr_name.attr.name = "name"; |
677 | cable->attr_name.attr.mode = 0444; | 679 | cable->attr_name.attr.mode = 0444; |
678 | cable->attr_name.show = cable_name_show; | 680 | cable->attr_name.show = cable_name_show; |
679 | 681 | ||
682 | sysfs_attr_init(&cable->attr_state.attr); | ||
680 | cable->attr_state.attr.name = "state"; | 683 | cable->attr_state.attr.name = "state"; |
681 | cable->attr_state.attr.mode = 0644; | 684 | cable->attr_state.attr.mode = 0644; |
682 | cable->attr_state.show = cable_state_show; | 685 | cable->attr_state.show = cable_state_show; |
@@ -722,6 +725,7 @@ int extcon_dev_register(struct extcon_dev *edev, struct device *dev) | |||
722 | goto err_muex; | 725 | goto err_muex; |
723 | } | 726 | } |
724 | strcpy(name, buf); | 727 | strcpy(name, buf); |
728 | sysfs_attr_init(&edev->d_attrs_muex[index].attr); | ||
725 | edev->d_attrs_muex[index].attr.name = name; | 729 | edev->d_attrs_muex[index].attr.name = name; |
726 | edev->d_attrs_muex[index].attr.mode = 0000; | 730 | edev->d_attrs_muex[index].attr.mode = 0000; |
727 | edev->attrs_muex[index] = &edev->d_attrs_muex[index] | 731 | edev->attrs_muex[index] = &edev->d_attrs_muex[index] |
@@ -802,7 +806,7 @@ EXPORT_SYMBOL_GPL(extcon_dev_register); | |||
802 | 806 | ||
803 | /** | 807 | /** |
804 | * extcon_dev_unregister() - Unregister the extcon device. | 808 | * extcon_dev_unregister() - Unregister the extcon device. |
805 | * @edev: the extcon device instance to be unregitered. | 809 | * @edev: the extcon device instance to be unregistered. |
806 | * | 810 | * |
807 | * Note that this does not call kfree(edev) because edev was not allocated | 811 | * Note that this does not call kfree(edev) because edev was not allocated |
808 | * by this class. | 812 | * by this class. |
diff --git a/drivers/extcon/extcon_gpio.c b/drivers/extcon/extcon-gpio.c index 3cc152e690b..3cc152e690b 100644 --- a/drivers/extcon/extcon_gpio.c +++ b/drivers/extcon/extcon-gpio.c | |||
diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c index 38f9e52f358..e21387e2da5 100644 --- a/drivers/extcon/extcon-max77693.c +++ b/drivers/extcon/extcon-max77693.c | |||
@@ -356,7 +356,7 @@ static int max77693_muic_adc_ground_handler(struct max77693_muic_info *info, | |||
356 | extcon_set_cable_state(info->edev, "MHL", attached); | 356 | extcon_set_cable_state(info->edev, "MHL", attached); |
357 | break; | 357 | break; |
358 | default: | 358 | default: |
359 | dev_err(info->dev, "faild to detect %s accessory\n", | 359 | dev_err(info->dev, "failed to detect %s accessory\n", |
360 | attached ? "attached" : "detached"); | 360 | attached ? "attached" : "detached"); |
361 | dev_err(info->dev, "- adc:0x%x, adclow:0x%x, adc1k:0x%x\n", | 361 | dev_err(info->dev, "- adc:0x%x, adclow:0x%x, adc1k:0x%x\n", |
362 | adc, adclow, adc1k); | 362 | adc, adclow, adc1k); |
@@ -548,7 +548,7 @@ static void max77693_muic_irq_work(struct work_struct *work) | |||
548 | curr_adc = info->status[0] & STATUS1_ADC_MASK; | 548 | curr_adc = info->status[0] & STATUS1_ADC_MASK; |
549 | curr_adc >>= STATUS1_ADC_SHIFT; | 549 | curr_adc >>= STATUS1_ADC_SHIFT; |
550 | 550 | ||
551 | /* Check accossory state which is either detached or attached */ | 551 | /* Check accessory state which is either detached or attached */ |
552 | if (curr_adc == MAX77693_MUIC_ADC_OPEN) | 552 | if (curr_adc == MAX77693_MUIC_ADC_OPEN) |
553 | attached = false; | 553 | attached = false; |
554 | 554 | ||
@@ -564,7 +564,7 @@ static void max77693_muic_irq_work(struct work_struct *work) | |||
564 | curr_chg_type = info->status[1] & STATUS2_CHGTYP_MASK; | 564 | curr_chg_type = info->status[1] & STATUS2_CHGTYP_MASK; |
565 | curr_chg_type >>= STATUS2_CHGTYP_SHIFT; | 565 | curr_chg_type >>= STATUS2_CHGTYP_SHIFT; |
566 | 566 | ||
567 | /* Check charger accossory state which | 567 | /* Check charger accessory state which |
568 | is either detached or attached */ | 568 | is either detached or attached */ |
569 | if (curr_chg_type == MAX77693_CHARGER_TYPE_NONE) | 569 | if (curr_chg_type == MAX77693_CHARGER_TYPE_NONE) |
570 | attached = false; | 570 | attached = false; |
@@ -699,7 +699,7 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev) | |||
699 | 699 | ||
700 | ret = request_threaded_irq(virq, NULL, | 700 | ret = request_threaded_irq(virq, NULL, |
701 | max77693_muic_irq_handler, | 701 | max77693_muic_irq_handler, |
702 | 0, muic_irq->name, info); | 702 | IRQF_ONESHOT, muic_irq->name, info); |
703 | if (ret) { | 703 | if (ret) { |
704 | dev_err(&pdev->dev, | 704 | dev_err(&pdev->dev, |
705 | "failed: irq request (IRQ: %d," | 705 | "failed: irq request (IRQ: %d," |