提交 a75fed2e 编写于 作者: C Chanwoo Choi

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: NChanwoo Choi <cw00.choi@samsung.com>
上级 e1954452
...@@ -228,6 +228,61 @@ static const struct regmap_config sm5502_muic_regmap_config = { ...@@ -228,6 +228,61 @@ static const struct regmap_config sm5502_muic_regmap_config = {
.max_register = SM5502_REG_END, .max_register = SM5502_REG_END,
}; };
/* Change DM_CON/DP_CON/VBUSIN switch according to cable type */
static int sm5502_muic_set_path(struct sm5502_muic_info *info,
unsigned int con_sw, unsigned int vbus_sw,
bool attached)
{
int ret;
if (!attached) {
con_sw = DM_DP_SWITCH_OPEN;
vbus_sw = VBUSIN_SWITCH_OPEN;
}
switch (con_sw) {
case DM_DP_SWITCH_OPEN:
case DM_DP_SWITCH_USB:
case DM_DP_SWITCH_AUDIO:
case DM_DP_SWITCH_UART:
ret = regmap_update_bits(info->regmap, SM5502_REG_MANUAL_SW1,
SM5502_REG_MANUAL_SW1_DP_MASK |
SM5502_REG_MANUAL_SW1_DM_MASK,
con_sw);
if (ret < 0) {
dev_err(info->dev,
"cannot update DM_CON/DP_CON switch\n");
return ret;
}
break;
default:
dev_err(info->dev, "Unknown DM_CON/DP_CON switch type (%d)\n",
con_sw);
return -EINVAL;
};
switch (vbus_sw) {
case VBUSIN_SWITCH_OPEN:
case VBUSIN_SWITCH_VBUSOUT:
case VBUSIN_SWITCH_MIC:
case VBUSIN_SWITCH_VBUSOUT_WITH_USB:
ret = regmap_update_bits(info->regmap, SM5502_REG_MANUAL_SW1,
SM5502_REG_MANUAL_SW1_VBUSIN_MASK,
vbus_sw);
if (ret < 0) {
dev_err(info->dev,
"cannot update VBUSIN switch\n");
return ret;
}
break;
default:
dev_err(info->dev, "Unknown VBUS switch type (%d)\n", vbus_sw);
return -EINVAL;
};
return 0;
}
/* Return cable type of attached or detached accessories */ /* Return cable type of attached or detached accessories */
static unsigned int sm5502_muic_get_cable_type(struct sm5502_muic_info *info) static unsigned int sm5502_muic_get_cable_type(struct sm5502_muic_info *info)
{ {
...@@ -329,7 +384,10 @@ static int sm5502_muic_cable_handler(struct sm5502_muic_info *info, ...@@ -329,7 +384,10 @@ static int sm5502_muic_cable_handler(struct sm5502_muic_info *info,
static unsigned int prev_cable_type = SM5502_MUIC_ADC_GROUND; static unsigned int prev_cable_type = SM5502_MUIC_ADC_GROUND;
const char **cable_names = info->edev->supported_cable; const char **cable_names = info->edev->supported_cable;
unsigned int cable_type = SM5502_MUIC_ADC_GROUND; unsigned int cable_type = SM5502_MUIC_ADC_GROUND;
unsigned int con_sw = DM_DP_SWITCH_OPEN;
unsigned int vbus_sw = VBUSIN_SWITCH_OPEN;
unsigned int idx = 0; unsigned int idx = 0;
int ret;
if (!cable_names) if (!cable_names)
return 0; return 0;
...@@ -343,15 +401,19 @@ static int sm5502_muic_cable_handler(struct sm5502_muic_info *info, ...@@ -343,15 +401,19 @@ static int sm5502_muic_cable_handler(struct sm5502_muic_info *info,
switch (cable_type) { switch (cable_type) {
case SM5502_MUIC_ADC_OPEN_USB: case SM5502_MUIC_ADC_OPEN_USB:
idx = EXTCON_CABLE_USB; idx = EXTCON_CABLE_USB;
con_sw = DM_DP_SWITCH_USB;
vbus_sw = VBUSIN_SWITCH_VBUSOUT_WITH_USB;
break; break;
case SM5502_MUIC_ADC_OPEN_TA: case SM5502_MUIC_ADC_OPEN_TA:
idx = EXTCON_CABLE_TA; idx = EXTCON_CABLE_TA;
con_sw = DM_DP_SWITCH_OPEN;
vbus_sw = VBUSIN_SWITCH_VBUSOUT;
break; break;
case SM5502_MUIC_ADC_OPEN_USB_OTG: case SM5502_MUIC_ADC_OPEN_USB_OTG:
idx = EXTCON_CABLE_USB_HOST; idx = EXTCON_CABLE_USB_HOST;
break; con_sw = DM_DP_SWITCH_USB;
case SM5502_MUIC_ADC_GROUND: vbus_sw = VBUSIN_SWITCH_OPEN;
break; break;
default: default:
dev_dbg(info->dev, dev_dbg(info->dev,
...@@ -359,6 +421,12 @@ static int sm5502_muic_cable_handler(struct sm5502_muic_info *info, ...@@ -359,6 +421,12 @@ static int sm5502_muic_cable_handler(struct sm5502_muic_info *info,
return 0; return 0;
}; };
/* Change internal hardware path(DM_CON/DP_CON, VBUSIN) */
ret = sm5502_muic_set_path(info, con_sw, vbus_sw, attached);
if (ret < 0)
return ret;
/* Change the state of external accessory */
extcon_set_cable_state(info->edev, cable_names[idx], attached); extcon_set_cable_state(info->edev, cable_names[idx], attached);
return 0; return 0;
......
...@@ -223,6 +223,29 @@ enum sm5502_reg { ...@@ -223,6 +223,29 @@ enum sm5502_reg {
#define SM5502_REG_DEV_TYPE2_TTY_MASK (0x1 << SM5502_REG_DEV_TYPE2_TTY_SHIFT) #define SM5502_REG_DEV_TYPE2_TTY_MASK (0x1 << SM5502_REG_DEV_TYPE2_TTY_SHIFT)
#define SM5502_REG_DEV_TYPE2_AV_CABLE_MASK (0x1 << SM5502_REG_DEV_TYPE2_AV_CABLE_SHIFT) #define SM5502_REG_DEV_TYPE2_AV_CABLE_MASK (0x1 << SM5502_REG_DEV_TYPE2_AV_CABLE_SHIFT)
#define SM5502_REG_MANUAL_SW1_VBUSIN_SHIFT 0
#define SM5502_REG_MANUAL_SW1_DP_SHIFT 2
#define SM5502_REG_MANUAL_SW1_DM_SHIFT 5
#define SM5502_REG_MANUAL_SW1_VBUSIN_MASK (0x3 << SM5502_REG_MANUAL_SW1_VBUSIN_SHIFT)
#define SM5502_REG_MANUAL_SW1_DP_MASK (0x7 << SM5502_REG_MANUAL_SW1_DP_SHIFT)
#define SM5502_REG_MANUAL_SW1_DM_MASK (0x7 << SM5502_REG_MANUAL_SW1_DM_SHIFT)
#define VBUSIN_SWITCH_OPEN 0x0
#define VBUSIN_SWITCH_VBUSOUT 0x1
#define VBUSIN_SWITCH_MIC 0x2
#define VBUSIN_SWITCH_VBUSOUT_WITH_USB 0x3
#define DM_DP_CON_SWITCH_OPEN 0x0
#define DM_DP_CON_SWITCH_USB 0x1
#define DM_DP_CON_SWITCH_AUDIO 0x2
#define DM_DP_CON_SWITCH_UART 0x3
#define DM_DP_SWITCH_OPEN ((DM_DP_CON_SWITCH_OPEN <<SM5502_REG_MANUAL_SW1_DP_SHIFT) \
| (DM_DP_CON_SWITCH_OPEN <<SM5502_REG_MANUAL_SW1_DM_SHIFT))
#define DM_DP_SWITCH_USB ((DM_DP_CON_SWITCH_USB <<SM5502_REG_MANUAL_SW1_DP_SHIFT) \
| (DM_DP_CON_SWITCH_USB <<SM5502_REG_MANUAL_SW1_DM_SHIFT))
#define DM_DP_SWITCH_AUDIO ((DM_DP_CON_SWITCH_AUDIO <<SM5502_REG_MANUAL_SW1_DP_SHIFT) \
| (DM_DP_CON_SWITCH_AUDIO <<SM5502_REG_MANUAL_SW1_DM_SHIFT))
#define DM_DP_SWITCH_UART ((DM_DP_CON_SWITCH_UART <<SM5502_REG_MANUAL_SW1_DP_SHIFT) \
| (DM_DP_CON_SWITCH_UART <<SM5502_REG_MANUAL_SW1_DM_SHIFT))
/* SM5502 Interrupts */ /* SM5502 Interrupts */
enum sm5502_irq { enum sm5502_irq {
/* INT1 */ /* INT1 */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册