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>
This commit is contained in:
		
					parent
					
						
							
								e1954452f5
							
						
					
				
			
			
				commit
				
					
						a75fed2ee6
					
				
			
		
					 2 changed files with 96 additions and 5 deletions
				
			
		|  | @ -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, | ||||||
| 	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; | ||||||
|  | @ -344,14 +402,18 @@ 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, | ||||||
| 		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 { | ||||||
| #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 */ | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Chanwoo Choi
				Chanwoo Choi