aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/extcon
diff options
context:
space:
mode:
authorChanwoo Choi <cw00.choi@samsung.com>2014-05-28 02:35:29 -0400
committerChanwoo Choi <cw00.choi@samsung.com>2014-07-22 21:22:35 -0400
commita75fed2ee6c187ab32b1cb01882c1032c4c9e4a8 (patch)
tree706b108a592f8d109329e44a22fe54cfed1ce9c8 /drivers/extcon
parente1954452f500cb21c09ea401f6f431ab55b35ba3 (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.c78
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 */
232static 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 */
232static unsigned int sm5502_muic_get_cable_type(struct sm5502_muic_info *info) 287static 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;