diff options
author | Chanwoo Choi <cw00.choi@samsung.com> | 2014-05-28 02:35:29 -0400 |
---|---|---|
committer | Chanwoo Choi <cw00.choi@samsung.com> | 2014-07-22 21:22:35 -0400 |
commit | a75fed2ee6c187ab32b1cb01882c1032c4c9e4a8 (patch) | |
tree | 706b108a592f8d109329e44a22fe54cfed1ce9c8 /drivers/extcon | |
parent | e1954452f500cb21c09ea401f6f431ab55b35ba3 (diff) |
extcon: sm5502: Change internal hardware switch according to cable type
This patch changes internal hardware DP_CON/DM_CON switch according to
cable type. The SM5502 MUIC device can set hardware switch as following:
- OPEN (not connected state) / USB / UART / AUDIO
Also, this patch set VBUSIN switch according to cable type.
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Diffstat (limited to 'drivers/extcon')
-rw-r--r-- | drivers/extcon/extcon-sm5502.c | 78 |
1 files changed, 73 insertions, 5 deletions
diff --git a/drivers/extcon/extcon-sm5502.c b/drivers/extcon/extcon-sm5502.c index a32d40f97ff0..560d7dccec7b 100644 --- a/drivers/extcon/extcon-sm5502.c +++ b/drivers/extcon/extcon-sm5502.c | |||
@@ -228,6 +228,61 @@ static const struct regmap_config sm5502_muic_regmap_config = { | |||
228 | .max_register = SM5502_REG_END, | 228 | .max_register = SM5502_REG_END, |
229 | }; | 229 | }; |
230 | 230 | ||
231 | /* Change DM_CON/DP_CON/VBUSIN switch according to cable type */ | ||
232 | static int sm5502_muic_set_path(struct sm5502_muic_info *info, | ||
233 | unsigned int con_sw, unsigned int vbus_sw, | ||
234 | bool attached) | ||
235 | { | ||
236 | int ret; | ||
237 | |||
238 | if (!attached) { | ||
239 | con_sw = DM_DP_SWITCH_OPEN; | ||
240 | vbus_sw = VBUSIN_SWITCH_OPEN; | ||
241 | } | ||
242 | |||
243 | switch (con_sw) { | ||
244 | case DM_DP_SWITCH_OPEN: | ||
245 | case DM_DP_SWITCH_USB: | ||
246 | case DM_DP_SWITCH_AUDIO: | ||
247 | case DM_DP_SWITCH_UART: | ||
248 | ret = regmap_update_bits(info->regmap, SM5502_REG_MANUAL_SW1, | ||
249 | SM5502_REG_MANUAL_SW1_DP_MASK | | ||
250 | SM5502_REG_MANUAL_SW1_DM_MASK, | ||
251 | con_sw); | ||
252 | if (ret < 0) { | ||
253 | dev_err(info->dev, | ||
254 | "cannot update DM_CON/DP_CON switch\n"); | ||
255 | return ret; | ||
256 | } | ||
257 | break; | ||
258 | default: | ||
259 | dev_err(info->dev, "Unknown DM_CON/DP_CON switch type (%d)\n", | ||
260 | con_sw); | ||
261 | return -EINVAL; | ||
262 | }; | ||
263 | |||
264 | switch (vbus_sw) { | ||
265 | case VBUSIN_SWITCH_OPEN: | ||
266 | case VBUSIN_SWITCH_VBUSOUT: | ||
267 | case VBUSIN_SWITCH_MIC: | ||
268 | case VBUSIN_SWITCH_VBUSOUT_WITH_USB: | ||
269 | ret = regmap_update_bits(info->regmap, SM5502_REG_MANUAL_SW1, | ||
270 | SM5502_REG_MANUAL_SW1_VBUSIN_MASK, | ||
271 | vbus_sw); | ||
272 | if (ret < 0) { | ||
273 | dev_err(info->dev, | ||
274 | "cannot update VBUSIN switch\n"); | ||
275 | return ret; | ||
276 | } | ||
277 | break; | ||
278 | default: | ||
279 | dev_err(info->dev, "Unknown VBUS switch type (%d)\n", vbus_sw); | ||
280 | return -EINVAL; | ||
281 | }; | ||
282 | |||
283 | return 0; | ||
284 | } | ||
285 | |||
231 | /* Return cable type of attached or detached accessories */ | 286 | /* Return cable type of attached or detached accessories */ |
232 | static unsigned int sm5502_muic_get_cable_type(struct sm5502_muic_info *info) | 287 | static unsigned int sm5502_muic_get_cable_type(struct sm5502_muic_info *info) |
233 | { | 288 | { |
@@ -329,7 +384,10 @@ static int sm5502_muic_cable_handler(struct sm5502_muic_info *info, | |||
329 | static unsigned int prev_cable_type = SM5502_MUIC_ADC_GROUND; | 384 | static unsigned int prev_cable_type = SM5502_MUIC_ADC_GROUND; |
330 | const char **cable_names = info->edev->supported_cable; | 385 | const char **cable_names = info->edev->supported_cable; |
331 | unsigned int cable_type = SM5502_MUIC_ADC_GROUND; | 386 | unsigned int cable_type = SM5502_MUIC_ADC_GROUND; |
387 | unsigned int con_sw = DM_DP_SWITCH_OPEN; | ||
388 | unsigned int vbus_sw = VBUSIN_SWITCH_OPEN; | ||
332 | unsigned int idx = 0; | 389 | unsigned int idx = 0; |
390 | int ret; | ||
333 | 391 | ||
334 | if (!cable_names) | 392 | if (!cable_names) |
335 | return 0; | 393 | return 0; |
@@ -343,15 +401,19 @@ static int sm5502_muic_cable_handler(struct sm5502_muic_info *info, | |||
343 | 401 | ||
344 | switch (cable_type) { | 402 | switch (cable_type) { |
345 | case SM5502_MUIC_ADC_OPEN_USB: | 403 | case SM5502_MUIC_ADC_OPEN_USB: |
346 | idx = EXTCON_CABLE_USB; | 404 | idx = EXTCON_CABLE_USB; |
405 | con_sw = DM_DP_SWITCH_USB; | ||
406 | vbus_sw = VBUSIN_SWITCH_VBUSOUT_WITH_USB; | ||
347 | break; | 407 | break; |
348 | case SM5502_MUIC_ADC_OPEN_TA: | 408 | case SM5502_MUIC_ADC_OPEN_TA: |
349 | idx = EXTCON_CABLE_TA; | 409 | idx = EXTCON_CABLE_TA; |
410 | con_sw = DM_DP_SWITCH_OPEN; | ||
411 | vbus_sw = VBUSIN_SWITCH_VBUSOUT; | ||
350 | break; | 412 | break; |
351 | case SM5502_MUIC_ADC_OPEN_USB_OTG: | 413 | case SM5502_MUIC_ADC_OPEN_USB_OTG: |
352 | idx = EXTCON_CABLE_USB_HOST; | 414 | idx = EXTCON_CABLE_USB_HOST; |
353 | break; | 415 | con_sw = DM_DP_SWITCH_USB; |
354 | case SM5502_MUIC_ADC_GROUND: | 416 | vbus_sw = VBUSIN_SWITCH_OPEN; |
355 | break; | 417 | break; |
356 | default: | 418 | default: |
357 | dev_dbg(info->dev, | 419 | dev_dbg(info->dev, |
@@ -359,6 +421,12 @@ static int sm5502_muic_cable_handler(struct sm5502_muic_info *info, | |||
359 | return 0; | 421 | return 0; |
360 | }; | 422 | }; |
361 | 423 | ||
424 | /* Change internal hardware path(DM_CON/DP_CON, VBUSIN) */ | ||
425 | ret = sm5502_muic_set_path(info, con_sw, vbus_sw, attached); | ||
426 | if (ret < 0) | ||
427 | return ret; | ||
428 | |||
429 | /* Change the state of external accessory */ | ||
362 | extcon_set_cable_state(info->edev, cable_names[idx], attached); | 430 | extcon_set_cable_state(info->edev, cable_names[idx], attached); |
363 | 431 | ||
364 | return 0; | 432 | return 0; |