extcon-sm5502.c (c3b5d3cea508d2c8ff493ef18c45a9cc58fb7015) extcon-sm5502.c (2a9de9c0f08d61fbe3764a21d22d0b72df97d6ae)
1/*
2 * extcon-sm5502.c - Silicon Mitus SM5502 extcon drvier to support USB switches
3 *
4 * Copyright (c) 2014 Samsung Electronics Co., Ltd
5 * Author: Chanwoo Choi <cw00.choi@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the

--- 78 unchanged lines hidden (view full) ---

87 | SM5502_REG_INTM2_STUCK_KEY_RCV_MASK
88 | SM5502_REG_INTM2_MHL_MASK,
89 .invert = true,
90 },
91 { }
92};
93
94/* List of detectable cables */
1/*
2 * extcon-sm5502.c - Silicon Mitus SM5502 extcon drvier to support USB switches
3 *
4 * Copyright (c) 2014 Samsung Electronics Co., Ltd
5 * Author: Chanwoo Choi <cw00.choi@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the

--- 78 unchanged lines hidden (view full) ---

87 | SM5502_REG_INTM2_STUCK_KEY_RCV_MASK
88 | SM5502_REG_INTM2_MHL_MASK,
89 .invert = true,
90 },
91 { }
92};
93
94/* List of detectable cables */
95enum {
96 EXTCON_CABLE_USB = 0,
97 EXTCON_CABLE_USB_HOST,
98 EXTCON_CABLE_TA,
99
100 EXTCON_CABLE_END,
95static const enum extcon sm5502_extcon_cable[] = {
96 EXTCON_USB,
97 EXTCON_USB_HOST,
98 EXTCON_TA,
99 EXTCON_NONE,
101};
102
100};
101
103static const char *sm5502_extcon_cable[] = {
104 [EXTCON_CABLE_USB] = "USB",
105 [EXTCON_CABLE_USB_HOST] = "USB-Host",
106 [EXTCON_CABLE_TA] = "TA",
107 NULL,
108};
109
110/* Define supported accessory type */
111enum sm5502_muic_acc_type {
112 SM5502_MUIC_ADC_GROUND = 0x0,
113 SM5502_MUIC_ADC_SEND_END_BUTTON,
114 SM5502_MUIC_ADC_REMOTE_S1_BUTTON,
115 SM5502_MUIC_ADC_REMOTE_S2_BUTTON,
116 SM5502_MUIC_ADC_REMOTE_S3_BUTTON,
117 SM5502_MUIC_ADC_REMOTE_S4_BUTTON,

--- 254 unchanged lines hidden (view full) ---

372
373 return cable_type;
374}
375
376static int sm5502_muic_cable_handler(struct sm5502_muic_info *info,
377 bool attached)
378{
379 static unsigned int prev_cable_type = SM5502_MUIC_ADC_GROUND;
102/* Define supported accessory type */
103enum sm5502_muic_acc_type {
104 SM5502_MUIC_ADC_GROUND = 0x0,
105 SM5502_MUIC_ADC_SEND_END_BUTTON,
106 SM5502_MUIC_ADC_REMOTE_S1_BUTTON,
107 SM5502_MUIC_ADC_REMOTE_S2_BUTTON,
108 SM5502_MUIC_ADC_REMOTE_S3_BUTTON,
109 SM5502_MUIC_ADC_REMOTE_S4_BUTTON,

--- 254 unchanged lines hidden (view full) ---

364
365 return cable_type;
366}
367
368static int sm5502_muic_cable_handler(struct sm5502_muic_info *info,
369 bool attached)
370{
371 static unsigned int prev_cable_type = SM5502_MUIC_ADC_GROUND;
380 const char **cable_names = info->edev->supported_cable;
381 unsigned int cable_type = SM5502_MUIC_ADC_GROUND;
382 unsigned int con_sw = DM_DP_SWITCH_OPEN;
383 unsigned int vbus_sw = VBUSIN_SWITCH_OPEN;
372 unsigned int cable_type = SM5502_MUIC_ADC_GROUND;
373 unsigned int con_sw = DM_DP_SWITCH_OPEN;
374 unsigned int vbus_sw = VBUSIN_SWITCH_OPEN;
384 unsigned int idx = 0;
375 enum extcon id;
385 int ret;
386
376 int ret;
377
387 if (!cable_names)
388 return 0;
389
390 /* Get the type of attached or detached cable */
391 if (attached)
392 cable_type = sm5502_muic_get_cable_type(info);
393 else
394 cable_type = prev_cable_type;
395 prev_cable_type = cable_type;
396
397 switch (cable_type) {
398 case SM5502_MUIC_ADC_OPEN_USB:
378 /* Get the type of attached or detached cable */
379 if (attached)
380 cable_type = sm5502_muic_get_cable_type(info);
381 else
382 cable_type = prev_cable_type;
383 prev_cable_type = cable_type;
384
385 switch (cable_type) {
386 case SM5502_MUIC_ADC_OPEN_USB:
399 idx = EXTCON_CABLE_USB;
387 id = EXTCON_USB;
400 con_sw = DM_DP_SWITCH_USB;
401 vbus_sw = VBUSIN_SWITCH_VBUSOUT_WITH_USB;
402 break;
403 case SM5502_MUIC_ADC_OPEN_TA:
388 con_sw = DM_DP_SWITCH_USB;
389 vbus_sw = VBUSIN_SWITCH_VBUSOUT_WITH_USB;
390 break;
391 case SM5502_MUIC_ADC_OPEN_TA:
404 idx = EXTCON_CABLE_TA;
392 id = EXTCON_TA;
405 con_sw = DM_DP_SWITCH_OPEN;
406 vbus_sw = VBUSIN_SWITCH_VBUSOUT;
407 break;
408 case SM5502_MUIC_ADC_OPEN_USB_OTG:
393 con_sw = DM_DP_SWITCH_OPEN;
394 vbus_sw = VBUSIN_SWITCH_VBUSOUT;
395 break;
396 case SM5502_MUIC_ADC_OPEN_USB_OTG:
409 idx = EXTCON_CABLE_USB_HOST;
397 id = EXTCON_USB_HOST;
410 con_sw = DM_DP_SWITCH_USB;
411 vbus_sw = VBUSIN_SWITCH_OPEN;
412 break;
413 default:
414 dev_dbg(info->dev,
415 "cannot handle this cable_type (0x%x)\n", cable_type);
416 return 0;
417 };
418
419 /* Change internal hardware path(DM_CON/DP_CON, VBUSIN) */
420 ret = sm5502_muic_set_path(info, con_sw, vbus_sw, attached);
421 if (ret < 0)
422 return ret;
423
424 /* Change the state of external accessory */
398 con_sw = DM_DP_SWITCH_USB;
399 vbus_sw = VBUSIN_SWITCH_OPEN;
400 break;
401 default:
402 dev_dbg(info->dev,
403 "cannot handle this cable_type (0x%x)\n", cable_type);
404 return 0;
405 };
406
407 /* Change internal hardware path(DM_CON/DP_CON, VBUSIN) */
408 ret = sm5502_muic_set_path(info, con_sw, vbus_sw, attached);
409 if (ret < 0)
410 return ret;
411
412 /* Change the state of external accessory */
425 extcon_set_cable_state(info->edev, cable_names[idx], attached);
413 extcon_set_cable_state_(info->edev, id, attached);
426
427 return 0;
428}
429
430static void sm5502_muic_irq_work(struct work_struct *work)
431{
432 struct sm5502_muic_info *info = container_of(work,
433 struct sm5502_muic_info, irq_work);

--- 184 unchanged lines hidden (view full) ---

618 }
619
620 /* Allocate extcon device */
621 info->edev = devm_extcon_dev_allocate(info->dev, sm5502_extcon_cable);
622 if (IS_ERR(info->edev)) {
623 dev_err(info->dev, "failed to allocate memory for extcon\n");
624 return -ENOMEM;
625 }
414
415 return 0;
416}
417
418static void sm5502_muic_irq_work(struct work_struct *work)
419{
420 struct sm5502_muic_info *info = container_of(work,
421 struct sm5502_muic_info, irq_work);

--- 184 unchanged lines hidden (view full) ---

606 }
607
608 /* Allocate extcon device */
609 info->edev = devm_extcon_dev_allocate(info->dev, sm5502_extcon_cable);
610 if (IS_ERR(info->edev)) {
611 dev_err(info->dev, "failed to allocate memory for extcon\n");
612 return -ENOMEM;
613 }
626 info->edev->name = np->name;
627
628 /* Register extcon device */
629 ret = devm_extcon_dev_register(info->dev, info->edev);
630 if (ret) {
631 dev_err(info->dev, "failed to register extcon device\n");
632 return ret;
633 }
634

--- 84 unchanged lines hidden ---
614
615 /* Register extcon device */
616 ret = devm_extcon_dev_register(info->dev, info->edev);
617 if (ret) {
618 dev_err(info->dev, "failed to register extcon device\n");
619 return ret;
620 }
621

--- 84 unchanged lines hidden ---