@@ -46,8 +46,11 @@ struct fsa4480 {
4646
4747 struct regmap * regmap ;
4848
49+ enum typec_orientation orientation ;
50+ unsigned long mode ;
51+ unsigned int svid ;
52+
4953 u8 cur_enable ;
50- u8 cur_select ;
5154};
5255
5356static const struct regmap_config fsa4480_regmap_config = {
@@ -58,19 +61,42 @@ static const struct regmap_config fsa4480_regmap_config = {
5861 .disable_locking = true,
5962};
6063
61- static int fsa4480_switch_set (struct typec_switch_dev * sw ,
62- enum typec_orientation orientation )
64+ static int fsa4480_set (struct fsa4480 * fsa )
6365{
64- struct fsa4480 * fsa = typec_switch_get_drvdata (sw );
65- u8 new_sel ;
66-
67- mutex_lock (& fsa -> lock );
68- new_sel = FSA4480_SEL_USB ;
69- if (orientation == TYPEC_ORIENTATION_REVERSE )
70- new_sel |= FSA4480_SEL_SBU_REVERSE ;
71-
72- if (new_sel == fsa -> cur_select )
73- goto out_unlock ;
66+ bool reverse = (fsa -> orientation == TYPEC_ORIENTATION_REVERSE );
67+ u8 enable = FSA4480_ENABLE_DEVICE ;
68+ u8 sel = 0 ;
69+
70+ /* USB Mode */
71+ if (fsa -> mode < TYPEC_STATE_MODAL ||
72+ (!fsa -> svid && (fsa -> mode == TYPEC_MODE_USB2 ||
73+ fsa -> mode == TYPEC_MODE_USB3 ))) {
74+ enable |= FSA4480_ENABLE_USB ;
75+ sel = FSA4480_SEL_USB ;
76+ } else if (fsa -> svid ) {
77+ switch (fsa -> mode ) {
78+ /* DP Only */
79+ case TYPEC_DP_STATE_C :
80+ case TYPEC_DP_STATE_E :
81+ enable |= FSA4480_ENABLE_SBU ;
82+ if (reverse )
83+ sel = FSA4480_SEL_SBU_REVERSE ;
84+ break ;
85+
86+ /* DP + USB */
87+ case TYPEC_DP_STATE_D :
88+ case TYPEC_DP_STATE_F :
89+ enable |= FSA4480_ENABLE_USB | FSA4480_ENABLE_SBU ;
90+ sel = FSA4480_SEL_USB ;
91+ if (reverse )
92+ sel |= FSA4480_SEL_SBU_REVERSE ;
93+ break ;
94+
95+ default :
96+ return - EOPNOTSUPP ;
97+ }
98+ } else
99+ return - EOPNOTSUPP ;
74100
75101 if (fsa -> cur_enable & FSA4480_ENABLE_SBU ) {
76102 /* Disable SBU output while re-configuring the switch */
@@ -81,48 +107,59 @@ static int fsa4480_switch_set(struct typec_switch_dev *sw,
81107 usleep_range (35 , 1000 );
82108 }
83109
84- regmap_write (fsa -> regmap , FSA4480_SWITCH_SELECT , new_sel );
85- fsa -> cur_select = new_sel ;
86-
87- if (fsa -> cur_enable & FSA4480_ENABLE_SBU ) {
88- regmap_write (fsa -> regmap , FSA4480_SWITCH_ENABLE , fsa -> cur_enable );
110+ regmap_write (fsa -> regmap , FSA4480_SWITCH_SELECT , sel );
111+ regmap_write (fsa -> regmap , FSA4480_SWITCH_ENABLE , enable );
89112
113+ if (enable & FSA4480_ENABLE_SBU ) {
90114 /* 15us to allow the SBU switch to turn on again */
91115 usleep_range (15 , 1000 );
92116 }
93117
94- out_unlock :
95- mutex_unlock (& fsa -> lock );
118+ fsa -> cur_enable = enable ;
96119
97120 return 0 ;
98121}
99122
123+ static int fsa4480_switch_set (struct typec_switch_dev * sw ,
124+ enum typec_orientation orientation )
125+ {
126+ struct fsa4480 * fsa = typec_switch_get_drvdata (sw );
127+ int ret = 0 ;
128+
129+ mutex_lock (& fsa -> lock );
130+
131+ if (fsa -> orientation != orientation ) {
132+ fsa -> orientation = orientation ;
133+
134+ ret = fsa4480_set (fsa );
135+ }
136+
137+ mutex_unlock (& fsa -> lock );
138+
139+ return ret ;
140+ }
141+
100142static int fsa4480_mux_set (struct typec_mux_dev * mux , struct typec_mux_state * state )
101143{
102144 struct fsa4480 * fsa = typec_mux_get_drvdata (mux );
103- u8 new_enable ;
145+ int ret = 0 ;
104146
105147 mutex_lock (& fsa -> lock );
106148
107- new_enable = FSA4480_ENABLE_DEVICE | FSA4480_ENABLE_USB ;
108- if (state -> mode >= TYPEC_DP_STATE_A )
109- new_enable |= FSA4480_ENABLE_SBU ;
149+ if (fsa -> mode != state -> mode ) {
150+ fsa -> mode = state -> mode ;
110151
111- if (new_enable == fsa -> cur_enable )
112- goto out_unlock ;
152+ if (state -> alt )
153+ fsa -> svid = state -> alt -> svid ;
154+ else
155+ fsa -> svid = 0 ; // No SVID
113156
114- regmap_write (fsa -> regmap , FSA4480_SWITCH_ENABLE , new_enable );
115- fsa -> cur_enable = new_enable ;
116-
117- if (new_enable & FSA4480_ENABLE_SBU ) {
118- /* 15us to allow the SBU switch to turn off */
119- usleep_range (15 , 1000 );
157+ ret = fsa4480_set (fsa );
120158 }
121159
122- out_unlock :
123160 mutex_unlock (& fsa -> lock );
124161
125- return 0 ;
162+ return ret ;
126163}
127164
128165static int fsa4480_probe (struct i2c_client * client )
@@ -143,8 +180,10 @@ static int fsa4480_probe(struct i2c_client *client)
143180 if (IS_ERR (fsa -> regmap ))
144181 return dev_err_probe (dev , PTR_ERR (fsa -> regmap ), "failed to initialize regmap\n" );
145182
183+ /* Safe mode */
146184 fsa -> cur_enable = FSA4480_ENABLE_DEVICE | FSA4480_ENABLE_USB ;
147- fsa -> cur_select = FSA4480_SEL_USB ;
185+ fsa -> mode = TYPEC_STATE_SAFE ;
186+ fsa -> orientation = TYPEC_ORIENTATION_NONE ;
148187
149188 /* set default settings */
150189 regmap_write (fsa -> regmap , FSA4480_SLOW_L , 0x00 );
@@ -156,7 +195,7 @@ static int fsa4480_probe(struct i2c_client *client)
156195 regmap_write (fsa -> regmap , FSA4480_DELAY_L_MIC , 0x00 );
157196 regmap_write (fsa -> regmap , FSA4480_DELAY_L_SENSE , 0x00 );
158197 regmap_write (fsa -> regmap , FSA4480_DELAY_L_AGND , 0x09 );
159- regmap_write (fsa -> regmap , FSA4480_SWITCH_SELECT , fsa -> cur_select );
198+ regmap_write (fsa -> regmap , FSA4480_SWITCH_SELECT , FSA4480_SEL_USB );
160199 regmap_write (fsa -> regmap , FSA4480_SWITCH_ENABLE , fsa -> cur_enable );
161200
162201 sw_desc .drvdata = fsa ;
0 commit comments