diff options
Diffstat (limited to 'drivers/extcon/extcon-max77693.c')
-rw-r--r-- | drivers/extcon/extcon-max77693.c | 981 |
1 files changed, 717 insertions, 264 deletions
diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c index 8c17b65eb74d..b70e3815c459 100644 --- a/drivers/extcon/extcon-max77693.c +++ b/drivers/extcon/extcon-max77693.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/input.h> | ||
22 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
23 | #include <linux/err.h> | 24 | #include <linux/err.h> |
24 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
@@ -29,92 +30,7 @@ | |||
29 | #include <linux/irqdomain.h> | 30 | #include <linux/irqdomain.h> |
30 | 31 | ||
31 | #define DEV_NAME "max77693-muic" | 32 | #define DEV_NAME "max77693-muic" |
32 | 33 | #define DELAY_MS_DEFAULT 20000 /* unit: millisecond */ | |
33 | /* MAX77693 MUIC - STATUS1~3 Register */ | ||
34 | #define STATUS1_ADC_SHIFT (0) | ||
35 | #define STATUS1_ADCLOW_SHIFT (5) | ||
36 | #define STATUS1_ADCERR_SHIFT (6) | ||
37 | #define STATUS1_ADC1K_SHIFT (7) | ||
38 | #define STATUS1_ADC_MASK (0x1f << STATUS1_ADC_SHIFT) | ||
39 | #define STATUS1_ADCLOW_MASK (0x1 << STATUS1_ADCLOW_SHIFT) | ||
40 | #define STATUS1_ADCERR_MASK (0x1 << STATUS1_ADCERR_SHIFT) | ||
41 | #define STATUS1_ADC1K_MASK (0x1 << STATUS1_ADC1K_SHIFT) | ||
42 | |||
43 | #define STATUS2_CHGTYP_SHIFT (0) | ||
44 | #define STATUS2_CHGDETRUN_SHIFT (3) | ||
45 | #define STATUS2_DCDTMR_SHIFT (4) | ||
46 | #define STATUS2_DXOVP_SHIFT (5) | ||
47 | #define STATUS2_VBVOLT_SHIFT (6) | ||
48 | #define STATUS2_VIDRM_SHIFT (7) | ||
49 | #define STATUS2_CHGTYP_MASK (0x7 << STATUS2_CHGTYP_SHIFT) | ||
50 | #define STATUS2_CHGDETRUN_MASK (0x1 << STATUS2_CHGDETRUN_SHIFT) | ||
51 | #define STATUS2_DCDTMR_MASK (0x1 << STATUS2_DCDTMR_SHIFT) | ||
52 | #define STATUS2_DXOVP_MASK (0x1 << STATUS2_DXOVP_SHIFT) | ||
53 | #define STATUS2_VBVOLT_MASK (0x1 << STATUS2_VBVOLT_SHIFT) | ||
54 | #define STATUS2_VIDRM_MASK (0x1 << STATUS2_VIDRM_SHIFT) | ||
55 | |||
56 | #define STATUS3_OVP_SHIFT (2) | ||
57 | #define STATUS3_OVP_MASK (0x1 << STATUS3_OVP_SHIFT) | ||
58 | |||
59 | /* MAX77693 CDETCTRL1~2 register */ | ||
60 | #define CDETCTRL1_CHGDETEN_SHIFT (0) | ||
61 | #define CDETCTRL1_CHGTYPMAN_SHIFT (1) | ||
62 | #define CDETCTRL1_DCDEN_SHIFT (2) | ||
63 | #define CDETCTRL1_DCD2SCT_SHIFT (3) | ||
64 | #define CDETCTRL1_CDDELAY_SHIFT (4) | ||
65 | #define CDETCTRL1_DCDCPL_SHIFT (5) | ||
66 | #define CDETCTRL1_CDPDET_SHIFT (7) | ||
67 | #define CDETCTRL1_CHGDETEN_MASK (0x1 << CDETCTRL1_CHGDETEN_SHIFT) | ||
68 | #define CDETCTRL1_CHGTYPMAN_MASK (0x1 << CDETCTRL1_CHGTYPMAN_SHIFT) | ||
69 | #define CDETCTRL1_DCDEN_MASK (0x1 << CDETCTRL1_DCDEN_SHIFT) | ||
70 | #define CDETCTRL1_DCD2SCT_MASK (0x1 << CDETCTRL1_DCD2SCT_SHIFT) | ||
71 | #define CDETCTRL1_CDDELAY_MASK (0x1 << CDETCTRL1_CDDELAY_SHIFT) | ||
72 | #define CDETCTRL1_DCDCPL_MASK (0x1 << CDETCTRL1_DCDCPL_SHIFT) | ||
73 | #define CDETCTRL1_CDPDET_MASK (0x1 << CDETCTRL1_CDPDET_SHIFT) | ||
74 | |||
75 | #define CDETCTRL2_VIDRMEN_SHIFT (1) | ||
76 | #define CDETCTRL2_DXOVPEN_SHIFT (3) | ||
77 | #define CDETCTRL2_VIDRMEN_MASK (0x1 << CDETCTRL2_VIDRMEN_SHIFT) | ||
78 | #define CDETCTRL2_DXOVPEN_MASK (0x1 << CDETCTRL2_DXOVPEN_SHIFT) | ||
79 | |||
80 | /* MAX77693 MUIC - CONTROL1~3 register */ | ||
81 | #define COMN1SW_SHIFT (0) | ||
82 | #define COMP2SW_SHIFT (3) | ||
83 | #define COMN1SW_MASK (0x7 << COMN1SW_SHIFT) | ||
84 | #define COMP2SW_MASK (0x7 << COMP2SW_SHIFT) | ||
85 | #define COMP_SW_MASK (COMP2SW_MASK | COMN1SW_MASK) | ||
86 | #define CONTROL1_SW_USB ((1 << COMP2SW_SHIFT) \ | ||
87 | | (1 << COMN1SW_SHIFT)) | ||
88 | #define CONTROL1_SW_AUDIO ((2 << COMP2SW_SHIFT) \ | ||
89 | | (2 << COMN1SW_SHIFT)) | ||
90 | #define CONTROL1_SW_UART ((3 << COMP2SW_SHIFT) \ | ||
91 | | (3 << COMN1SW_SHIFT)) | ||
92 | #define CONTROL1_SW_OPEN ((0 << COMP2SW_SHIFT) \ | ||
93 | | (0 << COMN1SW_SHIFT)) | ||
94 | |||
95 | #define CONTROL2_LOWPWR_SHIFT (0) | ||
96 | #define CONTROL2_ADCEN_SHIFT (1) | ||
97 | #define CONTROL2_CPEN_SHIFT (2) | ||
98 | #define CONTROL2_SFOUTASRT_SHIFT (3) | ||
99 | #define CONTROL2_SFOUTORD_SHIFT (4) | ||
100 | #define CONTROL2_ACCDET_SHIFT (5) | ||
101 | #define CONTROL2_USBCPINT_SHIFT (6) | ||
102 | #define CONTROL2_RCPS_SHIFT (7) | ||
103 | #define CONTROL2_LOWPWR_MASK (0x1 << CONTROL2_LOWPWR_SHIFT) | ||
104 | #define CONTROL2_ADCEN_MASK (0x1 << CONTROL2_ADCEN_SHIFT) | ||
105 | #define CONTROL2_CPEN_MASK (0x1 << CONTROL2_CPEN_SHIFT) | ||
106 | #define CONTROL2_SFOUTASRT_MASK (0x1 << CONTROL2_SFOUTASRT_SHIFT) | ||
107 | #define CONTROL2_SFOUTORD_MASK (0x1 << CONTROL2_SFOUTORD_SHIFT) | ||
108 | #define CONTROL2_ACCDET_MASK (0x1 << CONTROL2_ACCDET_SHIFT) | ||
109 | #define CONTROL2_USBCPINT_MASK (0x1 << CONTROL2_USBCPINT_SHIFT) | ||
110 | #define CONTROL2_RCPS_MASK (0x1 << CONTROL2_RCPS_SHIFT) | ||
111 | |||
112 | #define CONTROL3_JIGSET_SHIFT (0) | ||
113 | #define CONTROL3_BTLDSET_SHIFT (2) | ||
114 | #define CONTROL3_ADCDBSET_SHIFT (4) | ||
115 | #define CONTROL3_JIGSET_MASK (0x3 << CONTROL3_JIGSET_SHIFT) | ||
116 | #define CONTROL3_BTLDSET_MASK (0x3 << CONTROL3_BTLDSET_SHIFT) | ||
117 | #define CONTROL3_ADCDBSET_MASK (0x3 << CONTROL3_ADCDBSET_SHIFT) | ||
118 | 34 | ||
119 | enum max77693_muic_adc_debounce_time { | 35 | enum max77693_muic_adc_debounce_time { |
120 | ADC_DEBOUNCE_TIME_5MS = 0, | 36 | ADC_DEBOUNCE_TIME_5MS = 0, |
@@ -127,14 +43,40 @@ struct max77693_muic_info { | |||
127 | struct device *dev; | 43 | struct device *dev; |
128 | struct max77693_dev *max77693; | 44 | struct max77693_dev *max77693; |
129 | struct extcon_dev *edev; | 45 | struct extcon_dev *edev; |
130 | int prev_adc; | 46 | int prev_cable_type; |
131 | int prev_adc_gnd; | 47 | int prev_cable_type_gnd; |
132 | int prev_chg_type; | 48 | int prev_chg_type; |
49 | int prev_button_type; | ||
133 | u8 status[2]; | 50 | u8 status[2]; |
134 | 51 | ||
135 | int irq; | 52 | int irq; |
136 | struct work_struct irq_work; | 53 | struct work_struct irq_work; |
137 | struct mutex mutex; | 54 | struct mutex mutex; |
55 | |||
56 | /* | ||
57 | * Use delayed workqueue to detect cable state and then | ||
58 | * notify cable state to notifiee/platform through uevent. | ||
59 | * After completing the booting of platform, the extcon provider | ||
60 | * driver should notify cable state to upper layer. | ||
61 | */ | ||
62 | struct delayed_work wq_detcable; | ||
63 | |||
64 | /* Button of dock device */ | ||
65 | struct input_dev *dock; | ||
66 | |||
67 | /* | ||
68 | * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB | ||
69 | * h/w path of COMP2/COMN1 on CONTROL1 register. | ||
70 | */ | ||
71 | int path_usb; | ||
72 | int path_uart; | ||
73 | }; | ||
74 | |||
75 | enum max77693_muic_cable_group { | ||
76 | MAX77693_CABLE_GROUP_ADC = 0, | ||
77 | MAX77693_CABLE_GROUP_ADC_GND, | ||
78 | MAX77693_CABLE_GROUP_CHG, | ||
79 | MAX77693_CABLE_GROUP_VBVOLT, | ||
138 | }; | 80 | }; |
139 | 81 | ||
140 | enum max77693_muic_charger_type { | 82 | enum max77693_muic_charger_type { |
@@ -215,27 +157,59 @@ enum max77693_muic_acc_type { | |||
215 | 157 | ||
216 | /* The below accessories have same ADC value so ADCLow and | 158 | /* The below accessories have same ADC value so ADCLow and |
217 | ADC1K bit is used to separate specific accessory */ | 159 | ADC1K bit is used to separate specific accessory */ |
218 | MAX77693_MUIC_GND_USB_OTG = 0x100, /* ADC:0x0, ADCLow:0, ADC1K:0 */ | 160 | MAX77693_MUIC_GND_USB_OTG = 0x100, /* ADC:0x0, VBVolot:0, ADCLow:0, ADC1K:0 */ |
219 | MAX77693_MUIC_GND_AV_CABLE_LOAD = 0x102,/* ADC:0x0, ADCLow:1, ADC1K:0 */ | 161 | MAX77693_MUIC_GND_USB_OTG_VB = 0x104, /* ADC:0x0, VBVolot:1, ADCLow:0, ADC1K:0 */ |
220 | MAX77693_MUIC_GND_MHL_CABLE = 0x103, /* ADC:0x0, ADCLow:1, ADC1K:1 */ | 162 | MAX77693_MUIC_GND_AV_CABLE_LOAD = 0x102,/* ADC:0x0, VBVolot:0, ADCLow:1, ADC1K:0 */ |
163 | MAX77693_MUIC_GND_MHL = 0x103, /* ADC:0x0, VBVolot:0, ADCLow:1, ADC1K:1 */ | ||
164 | MAX77693_MUIC_GND_MHL_VB = 0x107, /* ADC:0x0, VBVolot:1, ADCLow:1, ADC1K:1 */ | ||
221 | }; | 165 | }; |
222 | 166 | ||
223 | /* MAX77693 MUIC device support below list of accessories(external connector) */ | 167 | /* MAX77693 MUIC device support below list of accessories(external connector) */ |
224 | const char *max77693_extcon_cable[] = { | 168 | enum { |
225 | [0] = "USB", | 169 | EXTCON_CABLE_USB = 0, |
226 | [1] = "USB-Host", | 170 | EXTCON_CABLE_USB_HOST, |
227 | [2] = "TA", | 171 | EXTCON_CABLE_TA, |
228 | [3] = "Fast-charger", | 172 | EXTCON_CABLE_FAST_CHARGER, |
229 | [4] = "Slow-charger", | 173 | EXTCON_CABLE_SLOW_CHARGER, |
230 | [5] = "Charge-downstream", | 174 | EXTCON_CABLE_CHARGE_DOWNSTREAM, |
231 | [6] = "MHL", | 175 | EXTCON_CABLE_MHL, |
232 | [7] = "Audio-video-load", | 176 | EXTCON_CABLE_MHL_TA, |
233 | [8] = "Audio-video-noload", | 177 | EXTCON_CABLE_JIG_USB_ON, |
234 | [9] = "JIG", | 178 | EXTCON_CABLE_JIG_USB_OFF, |
179 | EXTCON_CABLE_JIG_UART_OFF, | ||
180 | EXTCON_CABLE_JIG_UART_ON, | ||
181 | EXTCON_CABLE_DOCK_SMART, | ||
182 | EXTCON_CABLE_DOCK_DESK, | ||
183 | EXTCON_CABLE_DOCK_AUDIO, | ||
184 | |||
185 | _EXTCON_CABLE_NUM, | ||
186 | }; | ||
187 | |||
188 | static const char *max77693_extcon_cable[] = { | ||
189 | [EXTCON_CABLE_USB] = "USB", | ||
190 | [EXTCON_CABLE_USB_HOST] = "USB-Host", | ||
191 | [EXTCON_CABLE_TA] = "TA", | ||
192 | [EXTCON_CABLE_FAST_CHARGER] = "Fast-charger", | ||
193 | [EXTCON_CABLE_SLOW_CHARGER] = "Slow-charger", | ||
194 | [EXTCON_CABLE_CHARGE_DOWNSTREAM] = "Charge-downstream", | ||
195 | [EXTCON_CABLE_MHL] = "MHL", | ||
196 | [EXTCON_CABLE_MHL_TA] = "MHL_TA", | ||
197 | [EXTCON_CABLE_JIG_USB_ON] = "JIG-USB-ON", | ||
198 | [EXTCON_CABLE_JIG_USB_OFF] = "JIG-USB-OFF", | ||
199 | [EXTCON_CABLE_JIG_UART_OFF] = "JIG-UART-OFF", | ||
200 | [EXTCON_CABLE_JIG_UART_ON] = "Dock-Car", | ||
201 | [EXTCON_CABLE_DOCK_SMART] = "Dock-Smart", | ||
202 | [EXTCON_CABLE_DOCK_DESK] = "Dock-Desk", | ||
203 | [EXTCON_CABLE_DOCK_AUDIO] = "Dock-Audio", | ||
235 | 204 | ||
236 | NULL, | 205 | NULL, |
237 | }; | 206 | }; |
238 | 207 | ||
208 | /* | ||
209 | * max77693_muic_set_debounce_time - Set the debounce time of ADC | ||
210 | * @info: the instance including private data of max77693 MUIC | ||
211 | * @time: the debounce time of ADC | ||
212 | */ | ||
239 | static int max77693_muic_set_debounce_time(struct max77693_muic_info *info, | 213 | static int max77693_muic_set_debounce_time(struct max77693_muic_info *info, |
240 | enum max77693_muic_adc_debounce_time time) | 214 | enum max77693_muic_adc_debounce_time time) |
241 | { | 215 | { |
@@ -250,18 +224,29 @@ static int max77693_muic_set_debounce_time(struct max77693_muic_info *info, | |||
250 | MAX77693_MUIC_REG_CTRL3, | 224 | MAX77693_MUIC_REG_CTRL3, |
251 | time << CONTROL3_ADCDBSET_SHIFT, | 225 | time << CONTROL3_ADCDBSET_SHIFT, |
252 | CONTROL3_ADCDBSET_MASK); | 226 | CONTROL3_ADCDBSET_MASK); |
253 | if (ret) | 227 | if (ret) { |
254 | dev_err(info->dev, "failed to set ADC debounce time\n"); | 228 | dev_err(info->dev, "failed to set ADC debounce time\n"); |
229 | return -EAGAIN; | ||
230 | } | ||
255 | break; | 231 | break; |
256 | default: | 232 | default: |
257 | dev_err(info->dev, "invalid ADC debounce time\n"); | 233 | dev_err(info->dev, "invalid ADC debounce time\n"); |
258 | ret = -EINVAL; | 234 | return -EINVAL; |
259 | break; | ||
260 | } | 235 | } |
261 | 236 | ||
262 | return ret; | 237 | return 0; |
263 | }; | 238 | }; |
264 | 239 | ||
240 | /* | ||
241 | * max77693_muic_set_path - Set hardware line according to attached cable | ||
242 | * @info: the instance including private data of max77693 MUIC | ||
243 | * @value: the path according to attached cable | ||
244 | * @attached: the state of cable (true:attached, false:detached) | ||
245 | * | ||
246 | * The max77693 MUIC device share outside H/W line among a varity of cables | ||
247 | * so, this function set internal path of H/W line according to the type of | ||
248 | * attached cable. | ||
249 | */ | ||
265 | static int max77693_muic_set_path(struct max77693_muic_info *info, | 250 | static int max77693_muic_set_path(struct max77693_muic_info *info, |
266 | u8 val, bool attached) | 251 | u8 val, bool attached) |
267 | { | 252 | { |
@@ -277,7 +262,7 @@ static int max77693_muic_set_path(struct max77693_muic_info *info, | |||
277 | MAX77693_MUIC_REG_CTRL1, ctrl1, COMP_SW_MASK); | 262 | MAX77693_MUIC_REG_CTRL1, ctrl1, COMP_SW_MASK); |
278 | if (ret < 0) { | 263 | if (ret < 0) { |
279 | dev_err(info->dev, "failed to update MUIC register\n"); | 264 | dev_err(info->dev, "failed to update MUIC register\n"); |
280 | goto out; | 265 | return -EAGAIN; |
281 | } | 266 | } |
282 | 267 | ||
283 | if (attached) | 268 | if (attached) |
@@ -290,141 +275,457 @@ static int max77693_muic_set_path(struct max77693_muic_info *info, | |||
290 | CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK); | 275 | CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK); |
291 | if (ret < 0) { | 276 | if (ret < 0) { |
292 | dev_err(info->dev, "failed to update MUIC register\n"); | 277 | dev_err(info->dev, "failed to update MUIC register\n"); |
293 | goto out; | 278 | return -EAGAIN; |
294 | } | 279 | } |
295 | 280 | ||
296 | dev_info(info->dev, | 281 | dev_info(info->dev, |
297 | "CONTROL1 : 0x%02x, CONTROL2 : 0x%02x, state : %s\n", | 282 | "CONTROL1 : 0x%02x, CONTROL2 : 0x%02x, state : %s\n", |
298 | ctrl1, ctrl2, attached ? "attached" : "detached"); | 283 | ctrl1, ctrl2, attached ? "attached" : "detached"); |
299 | out: | 284 | |
300 | return ret; | 285 | return 0; |
301 | } | 286 | } |
302 | 287 | ||
303 | static int max77693_muic_adc_ground_handler(struct max77693_muic_info *info, | 288 | /* |
304 | bool attached) | 289 | * max77693_muic_get_cable_type - Return cable type and check cable state |
290 | * @info: the instance including private data of max77693 MUIC | ||
291 | * @group: the path according to attached cable | ||
292 | * @attached: store cable state and return | ||
293 | * | ||
294 | * This function check the cable state either attached or detached, | ||
295 | * and then divide precise type of cable according to cable group. | ||
296 | * - MAX77693_CABLE_GROUP_ADC | ||
297 | * - MAX77693_CABLE_GROUP_ADC_GND | ||
298 | * - MAX77693_CABLE_GROUP_CHG | ||
299 | * - MAX77693_CABLE_GROUP_VBVOLT | ||
300 | */ | ||
301 | static int max77693_muic_get_cable_type(struct max77693_muic_info *info, | ||
302 | enum max77693_muic_cable_group group, bool *attached) | ||
305 | { | 303 | { |
306 | int ret = 0; | 304 | int cable_type = 0; |
307 | int type; | 305 | int adc; |
308 | int adc, adc1k, adclow; | 306 | int adc1k; |
307 | int adclow; | ||
308 | int vbvolt; | ||
309 | int chg_type; | ||
310 | |||
311 | switch (group) { | ||
312 | case MAX77693_CABLE_GROUP_ADC: | ||
313 | /* | ||
314 | * Read ADC value to check cable type and decide cable state | ||
315 | * according to cable type | ||
316 | */ | ||
317 | adc = info->status[0] & STATUS1_ADC_MASK; | ||
318 | adc >>= STATUS1_ADC_SHIFT; | ||
319 | |||
320 | /* | ||
321 | * Check current cable state/cable type and store cable type | ||
322 | * (info->prev_cable_type) for handling cable when cable is | ||
323 | * detached. | ||
324 | */ | ||
325 | if (adc == MAX77693_MUIC_ADC_OPEN) { | ||
326 | *attached = false; | ||
327 | |||
328 | cable_type = info->prev_cable_type; | ||
329 | info->prev_cable_type = MAX77693_MUIC_ADC_OPEN; | ||
330 | } else { | ||
331 | *attached = true; | ||
332 | |||
333 | cable_type = info->prev_cable_type = adc; | ||
334 | } | ||
335 | break; | ||
336 | case MAX77693_CABLE_GROUP_ADC_GND: | ||
337 | /* | ||
338 | * Read ADC value to check cable type and decide cable state | ||
339 | * according to cable type | ||
340 | */ | ||
341 | adc = info->status[0] & STATUS1_ADC_MASK; | ||
342 | adc >>= STATUS1_ADC_SHIFT; | ||
343 | |||
344 | /* | ||
345 | * Check current cable state/cable type and store cable type | ||
346 | * (info->prev_cable_type/_gnd) for handling cable when cable | ||
347 | * is detached. | ||
348 | */ | ||
349 | if (adc == MAX77693_MUIC_ADC_OPEN) { | ||
350 | *attached = false; | ||
351 | |||
352 | cable_type = info->prev_cable_type_gnd; | ||
353 | info->prev_cable_type_gnd = MAX77693_MUIC_ADC_OPEN; | ||
354 | } else { | ||
355 | *attached = true; | ||
356 | |||
357 | adclow = info->status[0] & STATUS1_ADCLOW_MASK; | ||
358 | adclow >>= STATUS1_ADCLOW_SHIFT; | ||
359 | adc1k = info->status[0] & STATUS1_ADC1K_MASK; | ||
360 | adc1k >>= STATUS1_ADC1K_SHIFT; | ||
361 | |||
362 | vbvolt = info->status[1] & STATUS2_VBVOLT_MASK; | ||
363 | vbvolt >>= STATUS2_VBVOLT_SHIFT; | ||
364 | |||
365 | /** | ||
366 | * [0x1][VBVolt][ADCLow][ADC1K] | ||
367 | * [0x1 0 0 0 ] : USB_OTG | ||
368 | * [0x1 1 0 0 ] : USB_OTG_VB | ||
369 | * [0x1 0 1 0 ] : Audio Video Cable with load | ||
370 | * [0x1 0 1 1 ] : MHL without charging connector | ||
371 | * [0x1 1 1 1 ] : MHL with charging connector | ||
372 | */ | ||
373 | cable_type = ((0x1 << 8) | ||
374 | | (vbvolt << 2) | ||
375 | | (adclow << 1) | ||
376 | | adc1k); | ||
377 | |||
378 | info->prev_cable_type = adc; | ||
379 | info->prev_cable_type_gnd = cable_type; | ||
380 | } | ||
309 | 381 | ||
310 | if (attached) { | 382 | break; |
383 | case MAX77693_CABLE_GROUP_CHG: | ||
384 | /* | ||
385 | * Read charger type to check cable type and decide cable state | ||
386 | * according to type of charger cable. | ||
387 | */ | ||
388 | chg_type = info->status[1] & STATUS2_CHGTYP_MASK; | ||
389 | chg_type >>= STATUS2_CHGTYP_SHIFT; | ||
390 | |||
391 | if (chg_type == MAX77693_CHARGER_TYPE_NONE) { | ||
392 | *attached = false; | ||
393 | |||
394 | cable_type = info->prev_chg_type; | ||
395 | info->prev_chg_type = MAX77693_CHARGER_TYPE_NONE; | ||
396 | } else { | ||
397 | *attached = true; | ||
398 | |||
399 | /* | ||
400 | * Check current cable state/cable type and store cable | ||
401 | * type(info->prev_chg_type) for handling cable when | ||
402 | * charger cable is detached. | ||
403 | */ | ||
404 | cable_type = info->prev_chg_type = chg_type; | ||
405 | } | ||
406 | |||
407 | break; | ||
408 | case MAX77693_CABLE_GROUP_VBVOLT: | ||
409 | /* | ||
410 | * Read ADC value to check cable type and decide cable state | ||
411 | * according to cable type | ||
412 | */ | ||
311 | adc = info->status[0] & STATUS1_ADC_MASK; | 413 | adc = info->status[0] & STATUS1_ADC_MASK; |
312 | adclow = info->status[0] & STATUS1_ADCLOW_MASK; | 414 | adc >>= STATUS1_ADC_SHIFT; |
313 | adclow >>= STATUS1_ADCLOW_SHIFT; | 415 | chg_type = info->status[1] & STATUS2_CHGTYP_MASK; |
314 | adc1k = info->status[0] & STATUS1_ADC1K_MASK; | 416 | chg_type >>= STATUS2_CHGTYP_SHIFT; |
315 | adc1k >>= STATUS1_ADC1K_SHIFT; | 417 | |
316 | 418 | if (adc == MAX77693_MUIC_ADC_OPEN | |
317 | /** | 419 | && chg_type == MAX77693_CHARGER_TYPE_NONE) |
318 | * [0x1][ADCLow][ADC1K] | 420 | *attached = false; |
319 | * [0x1 0 0 ] : USB_OTG | 421 | else |
320 | * [0x1 1 0 ] : Audio Video Cable with load | 422 | *attached = true; |
321 | * [0x1 1 1 ] : MHL | 423 | |
424 | /* | ||
425 | * Read vbvolt field, if vbvolt is 1, | ||
426 | * this cable is used for charging. | ||
427 | */ | ||
428 | vbvolt = info->status[1] & STATUS2_VBVOLT_MASK; | ||
429 | vbvolt >>= STATUS2_VBVOLT_SHIFT; | ||
430 | |||
431 | cable_type = vbvolt; | ||
432 | break; | ||
433 | default: | ||
434 | dev_err(info->dev, "Unknown cable group (%d)\n", group); | ||
435 | cable_type = -EINVAL; | ||
436 | break; | ||
437 | } | ||
438 | |||
439 | return cable_type; | ||
440 | } | ||
441 | |||
442 | static int max77693_muic_dock_handler(struct max77693_muic_info *info, | ||
443 | int cable_type, bool attached) | ||
444 | { | ||
445 | int ret = 0; | ||
446 | int vbvolt; | ||
447 | bool cable_attached; | ||
448 | char dock_name[CABLE_NAME_MAX]; | ||
449 | |||
450 | dev_info(info->dev, | ||
451 | "external connector is %s (adc:0x%02x)\n", | ||
452 | attached ? "attached" : "detached", cable_type); | ||
453 | |||
454 | switch (cable_type) { | ||
455 | case MAX77693_MUIC_ADC_RESERVED_ACC_3: /* Dock-Smart */ | ||
456 | /* | ||
457 | * Check power cable whether attached or detached state. | ||
458 | * The Dock-Smart device need surely external power supply. | ||
459 | * If power cable(USB/TA) isn't connected to Dock device, | ||
460 | * user can't use Dock-Smart for desktop mode. | ||
461 | */ | ||
462 | vbvolt = max77693_muic_get_cable_type(info, | ||
463 | MAX77693_CABLE_GROUP_VBVOLT, &cable_attached); | ||
464 | if (attached && !vbvolt) { | ||
465 | dev_warn(info->dev, | ||
466 | "Cannot detect external power supply\n"); | ||
467 | return 0; | ||
468 | } | ||
469 | |||
470 | /* | ||
471 | * Notify Dock-Smart/MHL state. | ||
472 | * - Dock-Smart device include three type of cable which | ||
473 | * are HDMI, USB for mouse/keyboard and micro-usb port | ||
474 | * for USB/TA cable. Dock-Smart device need always exteranl | ||
475 | * power supply(USB/TA cable through micro-usb cable). Dock- | ||
476 | * Smart device support screen output of target to separate | ||
477 | * monitor and mouse/keyboard for desktop mode. | ||
478 | * | ||
479 | * Features of 'USB/TA cable with Dock-Smart device' | ||
480 | * - Support MHL | ||
481 | * - Support external output feature of audio | ||
482 | * - Support charging through micro-usb port without data | ||
483 | * connection if TA cable is connected to target. | ||
484 | * - Support charging and data connection through micro-usb port | ||
485 | * if USB cable is connected between target and host | ||
486 | * device. | ||
487 | * - Support OTG device (Mouse/Keyboard) | ||
322 | */ | 488 | */ |
323 | type = ((0x1 << 8) | (adclow << 1) | adc1k); | 489 | ret = max77693_muic_set_path(info, info->path_usb, attached); |
490 | if (ret < 0) | ||
491 | return ret; | ||
492 | |||
493 | extcon_set_cable_state(info->edev, "Dock-Smart", attached); | ||
494 | extcon_set_cable_state(info->edev, "MHL", attached); | ||
495 | goto out; | ||
496 | case MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON: /* Dock-Car */ | ||
497 | strcpy(dock_name, "Dock-Car"); | ||
498 | break; | ||
499 | case MAX77693_MUIC_ADC_AUDIO_MODE_REMOTE: /* Dock-Desk */ | ||
500 | strcpy(dock_name, "Dock-Desk"); | ||
501 | break; | ||
502 | case MAX77693_MUIC_ADC_AV_CABLE_NOLOAD: /* Dock-Audio */ | ||
503 | strcpy(dock_name, "Dock-Audio"); | ||
504 | if (!attached) | ||
505 | extcon_set_cable_state(info->edev, "USB", false); | ||
506 | break; | ||
507 | default: | ||
508 | dev_err(info->dev, "failed to detect %s dock device\n", | ||
509 | attached ? "attached" : "detached"); | ||
510 | return -EINVAL; | ||
511 | } | ||
512 | |||
513 | /* Dock-Car/Desk/Audio, PATH:AUDIO */ | ||
514 | ret = max77693_muic_set_path(info, CONTROL1_SW_AUDIO, attached); | ||
515 | if (ret < 0) | ||
516 | return ret; | ||
517 | extcon_set_cable_state(info->edev, dock_name, attached); | ||
518 | |||
519 | out: | ||
520 | return 0; | ||
521 | } | ||
522 | |||
523 | static int max77693_muic_dock_button_handler(struct max77693_muic_info *info, | ||
524 | int button_type, bool attached) | ||
525 | { | ||
526 | struct input_dev *dock = info->dock; | ||
527 | unsigned int code; | ||
528 | |||
529 | switch (button_type) { | ||
530 | case MAX77693_MUIC_ADC_REMOTE_S3_BUTTON-1 | ||
531 | ... MAX77693_MUIC_ADC_REMOTE_S3_BUTTON+1: | ||
532 | /* DOCK_KEY_PREV */ | ||
533 | code = KEY_PREVIOUSSONG; | ||
534 | break; | ||
535 | case MAX77693_MUIC_ADC_REMOTE_S7_BUTTON-1 | ||
536 | ... MAX77693_MUIC_ADC_REMOTE_S7_BUTTON+1: | ||
537 | /* DOCK_KEY_NEXT */ | ||
538 | code = KEY_NEXTSONG; | ||
539 | break; | ||
540 | case MAX77693_MUIC_ADC_REMOTE_S9_BUTTON: | ||
541 | /* DOCK_VOL_DOWN */ | ||
542 | code = KEY_VOLUMEDOWN; | ||
543 | break; | ||
544 | case MAX77693_MUIC_ADC_REMOTE_S10_BUTTON: | ||
545 | /* DOCK_VOL_UP */ | ||
546 | code = KEY_VOLUMEUP; | ||
547 | break; | ||
548 | case MAX77693_MUIC_ADC_REMOTE_S12_BUTTON-1 | ||
549 | ... MAX77693_MUIC_ADC_REMOTE_S12_BUTTON+1: | ||
550 | /* DOCK_KEY_PLAY_PAUSE */ | ||
551 | code = KEY_PLAYPAUSE; | ||
552 | break; | ||
553 | default: | ||
554 | dev_err(info->dev, | ||
555 | "failed to detect %s key (adc:0x%x)\n", | ||
556 | attached ? "pressed" : "released", button_type); | ||
557 | return -EINVAL; | ||
558 | } | ||
559 | |||
560 | input_event(dock, EV_KEY, code, attached); | ||
561 | input_sync(dock); | ||
562 | |||
563 | return 0; | ||
564 | } | ||
324 | 565 | ||
325 | /* Store previous ADC value to handle accessory | 566 | static int max77693_muic_adc_ground_handler(struct max77693_muic_info *info) |
326 | when accessory will be detached */ | 567 | { |
327 | info->prev_adc = adc; | 568 | int cable_type_gnd; |
328 | info->prev_adc_gnd = type; | 569 | int ret = 0; |
329 | } else | 570 | bool attached; |
330 | type = info->prev_adc_gnd; | ||
331 | 571 | ||
332 | switch (type) { | 572 | cable_type_gnd = max77693_muic_get_cable_type(info, |
573 | MAX77693_CABLE_GROUP_ADC_GND, &attached); | ||
574 | |||
575 | switch (cable_type_gnd) { | ||
333 | case MAX77693_MUIC_GND_USB_OTG: | 576 | case MAX77693_MUIC_GND_USB_OTG: |
334 | /* USB_OTG */ | 577 | case MAX77693_MUIC_GND_USB_OTG_VB: |
578 | /* USB_OTG, PATH: AP_USB */ | ||
335 | ret = max77693_muic_set_path(info, CONTROL1_SW_USB, attached); | 579 | ret = max77693_muic_set_path(info, CONTROL1_SW_USB, attached); |
336 | if (ret < 0) | 580 | if (ret < 0) |
337 | goto out; | 581 | return ret; |
338 | extcon_set_cable_state(info->edev, "USB-Host", attached); | 582 | extcon_set_cable_state(info->edev, "USB-Host", attached); |
339 | break; | 583 | break; |
340 | case MAX77693_MUIC_GND_AV_CABLE_LOAD: | 584 | case MAX77693_MUIC_GND_AV_CABLE_LOAD: |
341 | /* Audio Video Cable with load */ | 585 | /* Audio Video Cable with load, PATH:AUDIO */ |
342 | ret = max77693_muic_set_path(info, CONTROL1_SW_AUDIO, attached); | 586 | ret = max77693_muic_set_path(info, CONTROL1_SW_AUDIO, attached); |
343 | if (ret < 0) | 587 | if (ret < 0) |
344 | goto out; | 588 | return ret; |
345 | extcon_set_cable_state(info->edev, | 589 | extcon_set_cable_state(info->edev, |
346 | "Audio-video-load", attached); | 590 | "Audio-video-load", attached); |
347 | break; | 591 | break; |
348 | case MAX77693_MUIC_GND_MHL_CABLE: | 592 | case MAX77693_MUIC_GND_MHL: |
349 | /* MHL */ | 593 | case MAX77693_MUIC_GND_MHL_VB: |
594 | /* MHL or MHL with USB/TA cable */ | ||
350 | extcon_set_cable_state(info->edev, "MHL", attached); | 595 | extcon_set_cable_state(info->edev, "MHL", attached); |
351 | break; | 596 | break; |
352 | default: | 597 | default: |
353 | dev_err(info->dev, "failed to detect %s accessory\n", | 598 | dev_err(info->dev, "failed to detect %s cable of gnd type\n", |
354 | attached ? "attached" : "detached"); | 599 | attached ? "attached" : "detached"); |
355 | dev_err(info->dev, "- adc:0x%x, adclow:0x%x, adc1k:0x%x\n", | 600 | return -EINVAL; |
356 | adc, adclow, adc1k); | 601 | } |
357 | ret = -EINVAL; | 602 | |
603 | return 0; | ||
604 | } | ||
605 | |||
606 | static int max77693_muic_jig_handler(struct max77693_muic_info *info, | ||
607 | int cable_type, bool attached) | ||
608 | { | ||
609 | char cable_name[32]; | ||
610 | int ret = 0; | ||
611 | u8 path = CONTROL1_SW_OPEN; | ||
612 | |||
613 | dev_info(info->dev, | ||
614 | "external connector is %s (adc:0x%02x)\n", | ||
615 | attached ? "attached" : "detached", cable_type); | ||
616 | |||
617 | switch (cable_type) { | ||
618 | case MAX77693_MUIC_ADC_FACTORY_MODE_USB_OFF: /* ADC_JIG_USB_OFF */ | ||
619 | /* PATH:AP_USB */ | ||
620 | strcpy(cable_name, "JIG-USB-OFF"); | ||
621 | path = CONTROL1_SW_USB; | ||
622 | break; | ||
623 | case MAX77693_MUIC_ADC_FACTORY_MODE_USB_ON: /* ADC_JIG_USB_ON */ | ||
624 | /* PATH:AP_USB */ | ||
625 | strcpy(cable_name, "JIG-USB-ON"); | ||
626 | path = CONTROL1_SW_USB; | ||
358 | break; | 627 | break; |
628 | case MAX77693_MUIC_ADC_FACTORY_MODE_UART_OFF: /* ADC_JIG_UART_OFF */ | ||
629 | /* PATH:AP_UART */ | ||
630 | strcpy(cable_name, "JIG-UART-OFF"); | ||
631 | path = CONTROL1_SW_UART; | ||
632 | break; | ||
633 | default: | ||
634 | dev_err(info->dev, "failed to detect %s jig cable\n", | ||
635 | attached ? "attached" : "detached"); | ||
636 | return -EINVAL; | ||
359 | } | 637 | } |
360 | 638 | ||
361 | out: | 639 | ret = max77693_muic_set_path(info, path, attached); |
362 | return ret; | 640 | if (ret < 0) |
641 | return ret; | ||
642 | |||
643 | extcon_set_cable_state(info->edev, cable_name, attached); | ||
644 | |||
645 | return 0; | ||
363 | } | 646 | } |
364 | 647 | ||
365 | static int max77693_muic_adc_handler(struct max77693_muic_info *info, | 648 | static int max77693_muic_adc_handler(struct max77693_muic_info *info) |
366 | int curr_adc, bool attached) | ||
367 | { | 649 | { |
650 | int cable_type; | ||
651 | int button_type; | ||
652 | bool attached; | ||
368 | int ret = 0; | 653 | int ret = 0; |
369 | int adc; | ||
370 | 654 | ||
371 | if (attached) { | 655 | /* Check accessory state which is either detached or attached */ |
372 | /* Store ADC value to handle accessory | 656 | cable_type = max77693_muic_get_cable_type(info, |
373 | when accessory will be detached */ | 657 | MAX77693_CABLE_GROUP_ADC, &attached); |
374 | info->prev_adc = curr_adc; | ||
375 | adc = curr_adc; | ||
376 | } else | ||
377 | adc = info->prev_adc; | ||
378 | 658 | ||
379 | dev_info(info->dev, | 659 | dev_info(info->dev, |
380 | "external connector is %s (adc:0x%02x, prev_adc:0x%x)\n", | 660 | "external connector is %s (adc:0x%02x, prev_adc:0x%x)\n", |
381 | attached ? "attached" : "detached", curr_adc, info->prev_adc); | 661 | attached ? "attached" : "detached", cable_type, |
662 | info->prev_cable_type); | ||
382 | 663 | ||
383 | switch (adc) { | 664 | switch (cable_type) { |
384 | case MAX77693_MUIC_ADC_GROUND: | 665 | case MAX77693_MUIC_ADC_GROUND: |
385 | /* USB_OTG/MHL/Audio */ | 666 | /* USB_OTG/MHL/Audio */ |
386 | max77693_muic_adc_ground_handler(info, attached); | 667 | max77693_muic_adc_ground_handler(info); |
387 | break; | 668 | break; |
388 | case MAX77693_MUIC_ADC_FACTORY_MODE_USB_OFF: | 669 | case MAX77693_MUIC_ADC_FACTORY_MODE_USB_OFF: |
389 | case MAX77693_MUIC_ADC_FACTORY_MODE_USB_ON: | 670 | case MAX77693_MUIC_ADC_FACTORY_MODE_USB_ON: |
390 | /* USB */ | ||
391 | ret = max77693_muic_set_path(info, CONTROL1_SW_USB, attached); | ||
392 | if (ret < 0) | ||
393 | goto out; | ||
394 | extcon_set_cable_state(info->edev, "USB", attached); | ||
395 | break; | ||
396 | case MAX77693_MUIC_ADC_FACTORY_MODE_UART_OFF: | 671 | case MAX77693_MUIC_ADC_FACTORY_MODE_UART_OFF: |
397 | case MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON: | ||
398 | /* JIG */ | 672 | /* JIG */ |
399 | ret = max77693_muic_set_path(info, CONTROL1_SW_UART, attached); | 673 | ret = max77693_muic_jig_handler(info, cable_type, attached); |
400 | if (ret < 0) | 674 | if (ret < 0) |
401 | goto out; | 675 | return ret; |
402 | extcon_set_cable_state(info->edev, "JIG", attached); | ||
403 | break; | 676 | break; |
404 | case MAX77693_MUIC_ADC_AUDIO_MODE_REMOTE: | 677 | case MAX77693_MUIC_ADC_RESERVED_ACC_3: /* Dock-Smart */ |
405 | /* Audio Video cable with no-load */ | 678 | case MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON: /* Dock-Car */ |
406 | ret = max77693_muic_set_path(info, CONTROL1_SW_AUDIO, attached); | 679 | case MAX77693_MUIC_ADC_AUDIO_MODE_REMOTE: /* Dock-Desk */ |
680 | case MAX77693_MUIC_ADC_AV_CABLE_NOLOAD: /* Dock-Audio */ | ||
681 | /* | ||
682 | * DOCK device | ||
683 | * | ||
684 | * The MAX77693 MUIC device can detect total 34 cable type | ||
685 | * except of charger cable and MUIC device didn't define | ||
686 | * specfic role of cable in the range of from 0x01 to 0x12 | ||
687 | * of ADC value. So, can use/define cable with no role according | ||
688 | * to schema of hardware board. | ||
689 | */ | ||
690 | ret = max77693_muic_dock_handler(info, cable_type, attached); | ||
407 | if (ret < 0) | 691 | if (ret < 0) |
408 | goto out; | 692 | return ret; |
409 | extcon_set_cable_state(info->edev, | 693 | break; |
410 | "Audio-video-noload", attached); | 694 | case MAX77693_MUIC_ADC_REMOTE_S3_BUTTON: /* DOCK_KEY_PREV */ |
695 | case MAX77693_MUIC_ADC_REMOTE_S7_BUTTON: /* DOCK_KEY_NEXT */ | ||
696 | case MAX77693_MUIC_ADC_REMOTE_S9_BUTTON: /* DOCK_VOL_DOWN */ | ||
697 | case MAX77693_MUIC_ADC_REMOTE_S10_BUTTON: /* DOCK_VOL_UP */ | ||
698 | case MAX77693_MUIC_ADC_REMOTE_S12_BUTTON: /* DOCK_KEY_PLAY_PAUSE */ | ||
699 | /* | ||
700 | * Button of DOCK device | ||
701 | * - the Prev/Next/Volume Up/Volume Down/Play-Pause button | ||
702 | * | ||
703 | * The MAX77693 MUIC device can detect total 34 cable type | ||
704 | * except of charger cable and MUIC device didn't define | ||
705 | * specfic role of cable in the range of from 0x01 to 0x12 | ||
706 | * of ADC value. So, can use/define cable with no role according | ||
707 | * to schema of hardware board. | ||
708 | */ | ||
709 | if (attached) | ||
710 | button_type = info->prev_button_type = cable_type; | ||
711 | else | ||
712 | button_type = info->prev_button_type; | ||
713 | |||
714 | ret = max77693_muic_dock_button_handler(info, button_type, | ||
715 | attached); | ||
716 | if (ret < 0) | ||
717 | return ret; | ||
411 | break; | 718 | break; |
412 | case MAX77693_MUIC_ADC_SEND_END_BUTTON: | 719 | case MAX77693_MUIC_ADC_SEND_END_BUTTON: |
413 | case MAX77693_MUIC_ADC_REMOTE_S1_BUTTON: | 720 | case MAX77693_MUIC_ADC_REMOTE_S1_BUTTON: |
414 | case MAX77693_MUIC_ADC_REMOTE_S2_BUTTON: | 721 | case MAX77693_MUIC_ADC_REMOTE_S2_BUTTON: |
415 | case MAX77693_MUIC_ADC_REMOTE_S3_BUTTON: | ||
416 | case MAX77693_MUIC_ADC_REMOTE_S4_BUTTON: | 722 | case MAX77693_MUIC_ADC_REMOTE_S4_BUTTON: |
417 | case MAX77693_MUIC_ADC_REMOTE_S5_BUTTON: | 723 | case MAX77693_MUIC_ADC_REMOTE_S5_BUTTON: |
418 | case MAX77693_MUIC_ADC_REMOTE_S6_BUTTON: | 724 | case MAX77693_MUIC_ADC_REMOTE_S6_BUTTON: |
419 | case MAX77693_MUIC_ADC_REMOTE_S7_BUTTON: | ||
420 | case MAX77693_MUIC_ADC_REMOTE_S8_BUTTON: | 725 | case MAX77693_MUIC_ADC_REMOTE_S8_BUTTON: |
421 | case MAX77693_MUIC_ADC_REMOTE_S9_BUTTON: | ||
422 | case MAX77693_MUIC_ADC_REMOTE_S10_BUTTON: | ||
423 | case MAX77693_MUIC_ADC_REMOTE_S11_BUTTON: | 726 | case MAX77693_MUIC_ADC_REMOTE_S11_BUTTON: |
424 | case MAX77693_MUIC_ADC_REMOTE_S12_BUTTON: | ||
425 | case MAX77693_MUIC_ADC_RESERVED_ACC_1: | 727 | case MAX77693_MUIC_ADC_RESERVED_ACC_1: |
426 | case MAX77693_MUIC_ADC_RESERVED_ACC_2: | 728 | case MAX77693_MUIC_ADC_RESERVED_ACC_2: |
427 | case MAX77693_MUIC_ADC_RESERVED_ACC_3: | ||
428 | case MAX77693_MUIC_ADC_RESERVED_ACC_4: | 729 | case MAX77693_MUIC_ADC_RESERVED_ACC_4: |
429 | case MAX77693_MUIC_ADC_RESERVED_ACC_5: | 730 | case MAX77693_MUIC_ADC_RESERVED_ACC_5: |
430 | case MAX77693_MUIC_ADC_CEA936_AUDIO: | 731 | case MAX77693_MUIC_ADC_CEA936_AUDIO: |
@@ -432,60 +733,164 @@ static int max77693_muic_adc_handler(struct max77693_muic_info *info, | |||
432 | case MAX77693_MUIC_ADC_TTY_CONVERTER: | 733 | case MAX77693_MUIC_ADC_TTY_CONVERTER: |
433 | case MAX77693_MUIC_ADC_UART_CABLE: | 734 | case MAX77693_MUIC_ADC_UART_CABLE: |
434 | case MAX77693_MUIC_ADC_CEA936A_TYPE1_CHG: | 735 | case MAX77693_MUIC_ADC_CEA936A_TYPE1_CHG: |
435 | case MAX77693_MUIC_ADC_AV_CABLE_NOLOAD: | ||
436 | case MAX77693_MUIC_ADC_CEA936A_TYPE2_CHG: | 736 | case MAX77693_MUIC_ADC_CEA936A_TYPE2_CHG: |
437 | /* This accessory isn't used in general case if it is specially | 737 | /* |
438 | needed to detect additional accessory, should implement | 738 | * This accessory isn't used in general case if it is specially |
439 | proper operation when this accessory is attached/detached. */ | 739 | * needed to detect additional accessory, should implement |
740 | * proper operation when this accessory is attached/detached. | ||
741 | */ | ||
440 | dev_info(info->dev, | 742 | dev_info(info->dev, |
441 | "accessory is %s but it isn't used (adc:0x%x)\n", | 743 | "accessory is %s but it isn't used (adc:0x%x)\n", |
442 | attached ? "attached" : "detached", adc); | 744 | attached ? "attached" : "detached", cable_type); |
443 | goto out; | 745 | return -EAGAIN; |
444 | default: | 746 | default: |
445 | dev_err(info->dev, | 747 | dev_err(info->dev, |
446 | "failed to detect %s accessory (adc:0x%x)\n", | 748 | "failed to detect %s accessory (adc:0x%x)\n", |
447 | attached ? "attached" : "detached", adc); | 749 | attached ? "attached" : "detached", cable_type); |
448 | ret = -EINVAL; | 750 | return -EINVAL; |
449 | goto out; | ||
450 | } | 751 | } |
451 | 752 | ||
452 | out: | 753 | return 0; |
453 | return ret; | ||
454 | } | 754 | } |
455 | 755 | ||
456 | static int max77693_muic_chg_handler(struct max77693_muic_info *info, | 756 | static int max77693_muic_chg_handler(struct max77693_muic_info *info) |
457 | int curr_chg_type, bool attached) | ||
458 | { | 757 | { |
459 | int ret = 0; | ||
460 | int chg_type; | 758 | int chg_type; |
759 | int cable_type_gnd; | ||
760 | int cable_type; | ||
761 | bool attached; | ||
762 | bool cable_attached; | ||
763 | int ret = 0; | ||
461 | 764 | ||
462 | if (attached) { | 765 | chg_type = max77693_muic_get_cable_type(info, |
463 | /* Store previous charger type to control | 766 | MAX77693_CABLE_GROUP_CHG, &attached); |
464 | when charger accessory will be detached */ | ||
465 | info->prev_chg_type = curr_chg_type; | ||
466 | chg_type = curr_chg_type; | ||
467 | } else | ||
468 | chg_type = info->prev_chg_type; | ||
469 | 767 | ||
470 | dev_info(info->dev, | 768 | dev_info(info->dev, |
471 | "external connector is %s(chg_type:0x%x, prev_chg_type:0x%x)\n", | 769 | "external connector is %s(chg_type:0x%x, prev_chg_type:0x%x)\n", |
472 | attached ? "attached" : "detached", | 770 | attached ? "attached" : "detached", |
473 | curr_chg_type, info->prev_chg_type); | 771 | chg_type, info->prev_chg_type); |
474 | 772 | ||
475 | switch (chg_type) { | 773 | switch (chg_type) { |
476 | case MAX77693_CHARGER_TYPE_USB: | 774 | case MAX77693_CHARGER_TYPE_USB: |
477 | ret = max77693_muic_set_path(info, CONTROL1_SW_USB, attached); | 775 | case MAX77693_CHARGER_TYPE_DEDICATED_CHG: |
478 | if (ret < 0) | 776 | case MAX77693_CHARGER_TYPE_NONE: |
479 | goto out; | 777 | /* Check MAX77693_CABLE_GROUP_ADC_GND type */ |
480 | extcon_set_cable_state(info->edev, "USB", attached); | 778 | cable_type_gnd = max77693_muic_get_cable_type(info, |
779 | MAX77693_CABLE_GROUP_ADC_GND, | ||
780 | &cable_attached); | ||
781 | switch (cable_type_gnd) { | ||
782 | case MAX77693_MUIC_GND_MHL: | ||
783 | case MAX77693_MUIC_GND_MHL_VB: | ||
784 | /* | ||
785 | * MHL cable with MHL_TA(USB/TA) cable | ||
786 | * - MHL cable include two port(HDMI line and separate micro- | ||
787 | * usb port. When the target connect MHL cable, extcon driver | ||
788 | * check whether MHL_TA(USB/TA) cable is connected. If MHL_TA | ||
789 | * cable is connected, extcon driver notify state to notifiee | ||
790 | * for charging battery. | ||
791 | * | ||
792 | * Features of 'MHL_TA(USB/TA) with MHL cable' | ||
793 | * - Support MHL | ||
794 | * - Support charging through micro-usb port without data connection | ||
795 | */ | ||
796 | extcon_set_cable_state(info->edev, "MHL_TA", attached); | ||
797 | if (!cable_attached) | ||
798 | extcon_set_cable_state(info->edev, "MHL", cable_attached); | ||
799 | break; | ||
800 | } | ||
801 | |||
802 | /* Check MAX77693_CABLE_GROUP_ADC type */ | ||
803 | cable_type = max77693_muic_get_cable_type(info, | ||
804 | MAX77693_CABLE_GROUP_ADC, | ||
805 | &cable_attached); | ||
806 | switch (cable_type) { | ||
807 | case MAX77693_MUIC_ADC_AV_CABLE_NOLOAD: /* Dock-Audio */ | ||
808 | /* | ||
809 | * Dock-Audio device with USB/TA cable | ||
810 | * - Dock device include two port(Dock-Audio and micro-usb | ||
811 | * port). When the target connect Dock-Audio device, extcon | ||
812 | * driver check whether USB/TA cable is connected. If USB/TA | ||
813 | * cable is connected, extcon driver notify state to notifiee | ||
814 | * for charging battery. | ||
815 | * | ||
816 | * Features of 'USB/TA cable with Dock-Audio device' | ||
817 | * - Support external output feature of audio. | ||
818 | * - Support charging through micro-usb port without data | ||
819 | * connection. | ||
820 | */ | ||
821 | extcon_set_cable_state(info->edev, "USB", attached); | ||
822 | |||
823 | if (!cable_attached) | ||
824 | extcon_set_cable_state(info->edev, "Dock-Audio", cable_attached); | ||
825 | break; | ||
826 | case MAX77693_MUIC_ADC_RESERVED_ACC_3: /* Dock-Smart */ | ||
827 | /* | ||
828 | * Dock-Smart device with USB/TA cable | ||
829 | * - Dock-Desk device include three type of cable which | ||
830 | * are HDMI, USB for mouse/keyboard and micro-usb port | ||
831 | * for USB/TA cable. Dock-Smart device need always exteranl | ||
832 | * power supply(USB/TA cable through micro-usb cable). Dock- | ||
833 | * Smart device support screen output of target to separate | ||
834 | * monitor and mouse/keyboard for desktop mode. | ||
835 | * | ||
836 | * Features of 'USB/TA cable with Dock-Smart device' | ||
837 | * - Support MHL | ||
838 | * - Support external output feature of audio | ||
839 | * - Support charging through micro-usb port without data | ||
840 | * connection if TA cable is connected to target. | ||
841 | * - Support charging and data connection through micro-usb port | ||
842 | * if USB cable is connected between target and host | ||
843 | * device. | ||
844 | * - Support OTG device (Mouse/Keyboard) | ||
845 | */ | ||
846 | ret = max77693_muic_set_path(info, info->path_usb, attached); | ||
847 | if (ret < 0) | ||
848 | return ret; | ||
849 | |||
850 | extcon_set_cable_state(info->edev, "Dock-Smart", attached); | ||
851 | extcon_set_cable_state(info->edev, "MHL", attached); | ||
852 | |||
853 | break; | ||
854 | } | ||
855 | |||
856 | /* Check MAX77693_CABLE_GROUP_CHG type */ | ||
857 | switch (chg_type) { | ||
858 | case MAX77693_CHARGER_TYPE_NONE: | ||
859 | /* | ||
860 | * When MHL(with USB/TA cable) or Dock-Audio with USB/TA cable | ||
861 | * is attached, muic device happen below two interrupt. | ||
862 | * - 'MAX77693_MUIC_IRQ_INT1_ADC' for detecting MHL/Dock-Audio. | ||
863 | * - 'MAX77693_MUIC_IRQ_INT2_CHGTYP' for detecting USB/TA cable | ||
864 | * connected to MHL or Dock-Audio. | ||
865 | * Always, happen eariler MAX77693_MUIC_IRQ_INT1_ADC interrupt | ||
866 | * than MAX77693_MUIC_IRQ_INT2_CHGTYP interrupt. | ||
867 | * | ||
868 | * If user attach MHL (with USB/TA cable and immediately detach | ||
869 | * MHL with USB/TA cable before MAX77693_MUIC_IRQ_INT2_CHGTYP | ||
870 | * interrupt is happened, USB/TA cable remain connected state to | ||
871 | * target. But USB/TA cable isn't connected to target. The user | ||
872 | * be face with unusual action. So, driver should check this | ||
873 | * situation in spite of, that previous charger type is N/A. | ||
874 | */ | ||
875 | break; | ||
876 | case MAX77693_CHARGER_TYPE_USB: | ||
877 | /* Only USB cable, PATH:AP_USB */ | ||
878 | ret = max77693_muic_set_path(info, info->path_usb, attached); | ||
879 | if (ret < 0) | ||
880 | return ret; | ||
881 | |||
882 | extcon_set_cable_state(info->edev, "USB", attached); | ||
883 | break; | ||
884 | case MAX77693_CHARGER_TYPE_DEDICATED_CHG: | ||
885 | /* Only TA cable */ | ||
886 | extcon_set_cable_state(info->edev, "TA", attached); | ||
887 | break; | ||
888 | } | ||
481 | break; | 889 | break; |
482 | case MAX77693_CHARGER_TYPE_DOWNSTREAM_PORT: | 890 | case MAX77693_CHARGER_TYPE_DOWNSTREAM_PORT: |
483 | extcon_set_cable_state(info->edev, | 891 | extcon_set_cable_state(info->edev, |
484 | "Charge-downstream", attached); | 892 | "Charge-downstream", attached); |
485 | break; | 893 | break; |
486 | case MAX77693_CHARGER_TYPE_DEDICATED_CHG: | ||
487 | extcon_set_cable_state(info->edev, "TA", attached); | ||
488 | break; | ||
489 | case MAX77693_CHARGER_TYPE_APPLE_500MA: | 894 | case MAX77693_CHARGER_TYPE_APPLE_500MA: |
490 | extcon_set_cable_state(info->edev, "Slow-charger", attached); | 895 | extcon_set_cable_state(info->edev, "Slow-charger", attached); |
491 | break; | 896 | break; |
@@ -498,22 +903,18 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info, | |||
498 | dev_err(info->dev, | 903 | dev_err(info->dev, |
499 | "failed to detect %s accessory (chg_type:0x%x)\n", | 904 | "failed to detect %s accessory (chg_type:0x%x)\n", |
500 | attached ? "attached" : "detached", chg_type); | 905 | attached ? "attached" : "detached", chg_type); |
501 | ret = -EINVAL; | 906 | return -EINVAL; |
502 | goto out; | ||
503 | } | 907 | } |
504 | 908 | ||
505 | out: | 909 | return 0; |
506 | return ret; | ||
507 | } | 910 | } |
508 | 911 | ||
509 | static void max77693_muic_irq_work(struct work_struct *work) | 912 | static void max77693_muic_irq_work(struct work_struct *work) |
510 | { | 913 | { |
511 | struct max77693_muic_info *info = container_of(work, | 914 | struct max77693_muic_info *info = container_of(work, |
512 | struct max77693_muic_info, irq_work); | 915 | struct max77693_muic_info, irq_work); |
513 | int curr_adc, curr_chg_type; | ||
514 | int irq_type = -1; | 916 | int irq_type = -1; |
515 | int i, ret = 0; | 917 | int i, ret = 0; |
516 | bool attached = true; | ||
517 | 918 | ||
518 | if (!info->edev) | 919 | if (!info->edev) |
519 | return; | 920 | return; |
@@ -539,14 +940,7 @@ static void max77693_muic_irq_work(struct work_struct *work) | |||
539 | case MAX77693_MUIC_IRQ_INT1_ADC1K: | 940 | case MAX77693_MUIC_IRQ_INT1_ADC1K: |
540 | /* Handle all of accessory except for | 941 | /* Handle all of accessory except for |
541 | type of charger accessory */ | 942 | type of charger accessory */ |
542 | curr_adc = info->status[0] & STATUS1_ADC_MASK; | 943 | ret = max77693_muic_adc_handler(info); |
543 | curr_adc >>= STATUS1_ADC_SHIFT; | ||
544 | |||
545 | /* Check accessory state which is either detached or attached */ | ||
546 | if (curr_adc == MAX77693_MUIC_ADC_OPEN) | ||
547 | attached = false; | ||
548 | |||
549 | ret = max77693_muic_adc_handler(info, curr_adc, attached); | ||
550 | break; | 944 | break; |
551 | case MAX77693_MUIC_IRQ_INT2_CHGTYP: | 945 | case MAX77693_MUIC_IRQ_INT2_CHGTYP: |
552 | case MAX77693_MUIC_IRQ_INT2_CHGDETREUN: | 946 | case MAX77693_MUIC_IRQ_INT2_CHGDETREUN: |
@@ -555,15 +949,7 @@ static void max77693_muic_irq_work(struct work_struct *work) | |||
555 | case MAX77693_MUIC_IRQ_INT2_VBVOLT: | 949 | case MAX77693_MUIC_IRQ_INT2_VBVOLT: |
556 | case MAX77693_MUIC_IRQ_INT2_VIDRM: | 950 | case MAX77693_MUIC_IRQ_INT2_VIDRM: |
557 | /* Handle charger accessory */ | 951 | /* Handle charger accessory */ |
558 | curr_chg_type = info->status[1] & STATUS2_CHGTYP_MASK; | 952 | ret = max77693_muic_chg_handler(info); |
559 | curr_chg_type >>= STATUS2_CHGTYP_SHIFT; | ||
560 | |||
561 | /* Check charger accessory state which | ||
562 | is either detached or attached */ | ||
563 | if (curr_chg_type == MAX77693_CHARGER_TYPE_NONE) | ||
564 | attached = false; | ||
565 | |||
566 | ret = max77693_muic_chg_handler(info, curr_chg_type, attached); | ||
567 | break; | 953 | break; |
568 | case MAX77693_MUIC_IRQ_INT3_EOC: | 954 | case MAX77693_MUIC_IRQ_INT3_EOC: |
569 | case MAX77693_MUIC_IRQ_INT3_CGMBC: | 955 | case MAX77693_MUIC_IRQ_INT3_CGMBC: |
@@ -575,7 +961,8 @@ static void max77693_muic_irq_work(struct work_struct *work) | |||
575 | default: | 961 | default: |
576 | dev_err(info->dev, "muic interrupt: irq %d occurred\n", | 962 | dev_err(info->dev, "muic interrupt: irq %d occurred\n", |
577 | irq_type); | 963 | irq_type); |
578 | break; | 964 | mutex_unlock(&info->mutex); |
965 | return; | ||
579 | } | 966 | } |
580 | 967 | ||
581 | if (ret < 0) | 968 | if (ret < 0) |
@@ -604,7 +991,9 @@ static struct regmap_config max77693_muic_regmap_config = { | |||
604 | static int max77693_muic_detect_accessory(struct max77693_muic_info *info) | 991 | static int max77693_muic_detect_accessory(struct max77693_muic_info *info) |
605 | { | 992 | { |
606 | int ret = 0; | 993 | int ret = 0; |
607 | int adc, chg_type; | 994 | int adc; |
995 | int chg_type; | ||
996 | bool attached; | ||
608 | 997 | ||
609 | mutex_lock(&info->mutex); | 998 | mutex_lock(&info->mutex); |
610 | 999 | ||
@@ -617,35 +1006,39 @@ static int max77693_muic_detect_accessory(struct max77693_muic_info *info) | |||
617 | return -EINVAL; | 1006 | return -EINVAL; |
618 | } | 1007 | } |
619 | 1008 | ||
620 | adc = info->status[0] & STATUS1_ADC_MASK; | 1009 | adc = max77693_muic_get_cable_type(info, MAX77693_CABLE_GROUP_ADC, |
621 | adc >>= STATUS1_ADC_SHIFT; | 1010 | &attached); |
622 | 1011 | if (attached && adc != MAX77693_MUIC_ADC_OPEN) { | |
623 | if (adc != MAX77693_MUIC_ADC_OPEN) { | 1012 | ret = max77693_muic_adc_handler(info); |
624 | dev_info(info->dev, | 1013 | if (ret < 0) { |
625 | "external connector is attached (adc:0x%02x)\n", adc); | 1014 | dev_err(info->dev, "Cannot detect accessory\n"); |
1015 | mutex_unlock(&info->mutex); | ||
1016 | return ret; | ||
1017 | } | ||
1018 | } | ||
626 | 1019 | ||
627 | ret = max77693_muic_adc_handler(info, adc, true); | 1020 | chg_type = max77693_muic_get_cable_type(info, MAX77693_CABLE_GROUP_CHG, |
628 | if (ret < 0) | 1021 | &attached); |
629 | dev_err(info->dev, "failed to detect accessory\n"); | 1022 | if (attached && chg_type != MAX77693_CHARGER_TYPE_NONE) { |
630 | goto out; | 1023 | ret = max77693_muic_chg_handler(info); |
1024 | if (ret < 0) { | ||
1025 | dev_err(info->dev, "Cannot detect charger accessory\n"); | ||
1026 | mutex_unlock(&info->mutex); | ||
1027 | return ret; | ||
1028 | } | ||
631 | } | 1029 | } |
632 | 1030 | ||
633 | chg_type = info->status[1] & STATUS2_CHGTYP_MASK; | 1031 | mutex_unlock(&info->mutex); |
634 | chg_type >>= STATUS2_CHGTYP_SHIFT; | ||
635 | 1032 | ||
636 | if (chg_type != MAX77693_CHARGER_TYPE_NONE) { | 1033 | return 0; |
637 | dev_info(info->dev, | 1034 | } |
638 | "external connector is attached (chg_type:0x%x)\n", | ||
639 | chg_type); | ||
640 | 1035 | ||
641 | max77693_muic_chg_handler(info, chg_type, true); | 1036 | static void max77693_muic_detect_cable_wq(struct work_struct *work) |
642 | if (ret < 0) | 1037 | { |
643 | dev_err(info->dev, "failed to detect charger accessory\n"); | 1038 | struct max77693_muic_info *info = container_of(to_delayed_work(work), |
644 | } | 1039 | struct max77693_muic_info, wq_detcable); |
645 | 1040 | ||
646 | out: | 1041 | max77693_muic_detect_accessory(info); |
647 | mutex_unlock(&info->mutex); | ||
648 | return ret; | ||
649 | } | 1042 | } |
650 | 1043 | ||
651 | static int max77693_muic_probe(struct platform_device *pdev) | 1044 | static int max77693_muic_probe(struct platform_device *pdev) |
@@ -654,7 +1047,9 @@ static int max77693_muic_probe(struct platform_device *pdev) | |||
654 | struct max77693_platform_data *pdata = dev_get_platdata(max77693->dev); | 1047 | struct max77693_platform_data *pdata = dev_get_platdata(max77693->dev); |
655 | struct max77693_muic_platform_data *muic_pdata = pdata->muic_data; | 1048 | struct max77693_muic_platform_data *muic_pdata = pdata->muic_data; |
656 | struct max77693_muic_info *info; | 1049 | struct max77693_muic_info *info; |
657 | int ret, i; | 1050 | int delay_jiffies; |
1051 | int ret; | ||
1052 | int i; | ||
658 | u8 id; | 1053 | u8 id; |
659 | 1054 | ||
660 | info = devm_kzalloc(&pdev->dev, sizeof(struct max77693_muic_info), | 1055 | info = devm_kzalloc(&pdev->dev, sizeof(struct max77693_muic_info), |
@@ -678,6 +1073,32 @@ static int max77693_muic_probe(struct platform_device *pdev) | |||
678 | return ret; | 1073 | return ret; |
679 | } | 1074 | } |
680 | } | 1075 | } |
1076 | |||
1077 | /* Register input device for button of dock device */ | ||
1078 | info->dock = devm_input_allocate_device(&pdev->dev); | ||
1079 | if (!info->dock) { | ||
1080 | dev_err(&pdev->dev, "%s: failed to allocate input\n", __func__); | ||
1081 | return -ENOMEM; | ||
1082 | } | ||
1083 | info->dock->name = "max77693-muic/dock"; | ||
1084 | info->dock->phys = "max77693-muic/extcon"; | ||
1085 | info->dock->dev.parent = &pdev->dev; | ||
1086 | |||
1087 | __set_bit(EV_REP, info->dock->evbit); | ||
1088 | |||
1089 | input_set_capability(info->dock, EV_KEY, KEY_VOLUMEUP); | ||
1090 | input_set_capability(info->dock, EV_KEY, KEY_VOLUMEDOWN); | ||
1091 | input_set_capability(info->dock, EV_KEY, KEY_PLAYPAUSE); | ||
1092 | input_set_capability(info->dock, EV_KEY, KEY_PREVIOUSSONG); | ||
1093 | input_set_capability(info->dock, EV_KEY, KEY_NEXTSONG); | ||
1094 | |||
1095 | ret = input_register_device(info->dock); | ||
1096 | if (ret < 0) { | ||
1097 | dev_err(&pdev->dev, "Cannot register input device error(%d)\n", | ||
1098 | ret); | ||
1099 | return ret; | ||
1100 | } | ||
1101 | |||
681 | platform_set_drvdata(pdev, info); | 1102 | platform_set_drvdata(pdev, info); |
682 | mutex_init(&info->mutex); | 1103 | mutex_init(&info->mutex); |
683 | 1104 | ||
@@ -697,13 +1118,13 @@ static int max77693_muic_probe(struct platform_device *pdev) | |||
697 | 1118 | ||
698 | ret = request_threaded_irq(virq, NULL, | 1119 | ret = request_threaded_irq(virq, NULL, |
699 | max77693_muic_irq_handler, | 1120 | max77693_muic_irq_handler, |
700 | IRQF_ONESHOT, muic_irq->name, info); | 1121 | IRQF_NO_SUSPEND, |
1122 | muic_irq->name, info); | ||
701 | if (ret) { | 1123 | if (ret) { |
702 | dev_err(&pdev->dev, | 1124 | dev_err(&pdev->dev, |
703 | "failed: irq request (IRQ: %d," | 1125 | "failed: irq request (IRQ: %d," |
704 | " error :%d)\n", | 1126 | " error :%d)\n", |
705 | muic_irq->irq, ret); | 1127 | muic_irq->irq, ret); |
706 | |||
707 | goto err_irq; | 1128 | goto err_irq; |
708 | } | 1129 | } |
709 | } | 1130 | } |
@@ -749,23 +1170,54 @@ static int max77693_muic_probe(struct platform_device *pdev) | |||
749 | = muic_pdata->init_data[i].data; | 1170 | = muic_pdata->init_data[i].data; |
750 | } | 1171 | } |
751 | 1172 | ||
1173 | /* | ||
1174 | * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB | ||
1175 | * h/w path of COMP2/COMN1 on CONTROL1 register. | ||
1176 | */ | ||
1177 | if (muic_pdata->path_uart) | ||
1178 | info->path_uart = muic_pdata->path_uart; | ||
1179 | else | ||
1180 | info->path_uart = CONTROL1_SW_UART; | ||
1181 | |||
1182 | if (muic_pdata->path_usb) | ||
1183 | info->path_usb = muic_pdata->path_usb; | ||
1184 | else | ||
1185 | info->path_usb = CONTROL1_SW_USB; | ||
1186 | |||
1187 | /* Set initial path for UART */ | ||
1188 | max77693_muic_set_path(info, info->path_uart, true); | ||
1189 | |||
752 | /* Check revision number of MUIC device*/ | 1190 | /* Check revision number of MUIC device*/ |
753 | ret = max77693_read_reg(info->max77693->regmap_muic, | 1191 | ret = max77693_read_reg(info->max77693->regmap_muic, |
754 | MAX77693_MUIC_REG_ID, &id); | 1192 | MAX77693_MUIC_REG_ID, &id); |
755 | if (ret < 0) { | 1193 | if (ret < 0) { |
756 | dev_err(&pdev->dev, "failed to read revision number\n"); | 1194 | dev_err(&pdev->dev, "failed to read revision number\n"); |
757 | goto err_irq; | 1195 | goto err_extcon; |
758 | } | 1196 | } |
759 | dev_info(info->dev, "device ID : 0x%x\n", id); | 1197 | dev_info(info->dev, "device ID : 0x%x\n", id); |
760 | 1198 | ||
761 | /* Set ADC debounce time */ | 1199 | /* Set ADC debounce time */ |
762 | max77693_muic_set_debounce_time(info, ADC_DEBOUNCE_TIME_25MS); | 1200 | max77693_muic_set_debounce_time(info, ADC_DEBOUNCE_TIME_25MS); |
763 | 1201 | ||
764 | /* Detect accessory on boot */ | 1202 | /* |
765 | max77693_muic_detect_accessory(info); | 1203 | * Detect accessory after completing the initialization of platform |
1204 | * | ||
1205 | * - Use delayed workqueue to detect cable state and then | ||
1206 | * notify cable state to notifiee/platform through uevent. | ||
1207 | * After completing the booting of platform, the extcon provider | ||
1208 | * driver should notify cable state to upper layer. | ||
1209 | */ | ||
1210 | INIT_DELAYED_WORK(&info->wq_detcable, max77693_muic_detect_cable_wq); | ||
1211 | if (muic_pdata->detcable_delay_ms) | ||
1212 | delay_jiffies = msecs_to_jiffies(muic_pdata->detcable_delay_ms); | ||
1213 | else | ||
1214 | delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT); | ||
1215 | schedule_delayed_work(&info->wq_detcable, delay_jiffies); | ||
766 | 1216 | ||
767 | return ret; | 1217 | return ret; |
768 | 1218 | ||
1219 | err_extcon: | ||
1220 | extcon_dev_unregister(info->edev); | ||
769 | err_irq: | 1221 | err_irq: |
770 | while (--i >= 0) | 1222 | while (--i >= 0) |
771 | free_irq(muic_irqs[i].virq, info); | 1223 | free_irq(muic_irqs[i].virq, info); |
@@ -780,6 +1232,7 @@ static int max77693_muic_remove(struct platform_device *pdev) | |||
780 | for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) | 1232 | for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) |
781 | free_irq(muic_irqs[i].virq, info); | 1233 | free_irq(muic_irqs[i].virq, info); |
782 | cancel_work_sync(&info->irq_work); | 1234 | cancel_work_sync(&info->irq_work); |
1235 | input_unregister_device(info->dock); | ||
783 | extcon_dev_unregister(info->edev); | 1236 | extcon_dev_unregister(info->edev); |
784 | 1237 | ||
785 | return 0; | 1238 | return 0; |