Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a75fed2e authored by Chanwoo Choi's avatar Chanwoo Choi
Browse files

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: default avatarChanwoo Choi <cw00.choi@samsung.com>
parent e1954452
Loading
Loading
Loading
Loading
+73 −5
Original line number Diff line number Diff line
@@ -228,6 +228,61 @@ static const struct regmap_config sm5502_muic_regmap_config = {
	.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 */
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,
	static unsigned int prev_cable_type = SM5502_MUIC_ADC_GROUND;
	const char **cable_names = info->edev->supported_cable;
	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;
	int ret;

	if (!cable_names)
		return 0;
@@ -344,14 +402,18 @@ static int sm5502_muic_cable_handler(struct sm5502_muic_info *info,
	switch (cable_type) {
	case SM5502_MUIC_ADC_OPEN_USB:
		idx	= EXTCON_CABLE_USB;
		con_sw	= DM_DP_SWITCH_USB;
		vbus_sw	= VBUSIN_SWITCH_VBUSOUT_WITH_USB;
		break;
	case SM5502_MUIC_ADC_OPEN_TA:
		idx	= EXTCON_CABLE_TA;
		con_sw	= DM_DP_SWITCH_OPEN;
		vbus_sw	= VBUSIN_SWITCH_VBUSOUT;
		break;
	case SM5502_MUIC_ADC_OPEN_USB_OTG:
		idx	= EXTCON_CABLE_USB_HOST;
		break;
	case SM5502_MUIC_ADC_GROUND:
		con_sw	= DM_DP_SWITCH_USB;
		vbus_sw	= VBUSIN_SWITCH_OPEN;
		break;
	default:
		dev_dbg(info->dev,
@@ -359,6 +421,12 @@ static int sm5502_muic_cable_handler(struct sm5502_muic_info *info,
		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);

	return 0;
+23 −0
Original line number Diff line number Diff line
@@ -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_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 */
enum sm5502_irq {
	/* INT1 */