15
15
#include <linux/platform_device.h>
16
16
#include <linux/usb/typec.h>
17
17
#include <linux/usb/typec_altmode.h>
18
+ #include <linux/usb/typec_dp.h>
18
19
#include <linux/usb/typec_mux.h>
19
20
#include <linux/usb/role.h>
20
21
21
22
#define DRV_NAME "cros-ec-typec"
22
23
24
+ /* Supported alt modes. */
25
+ enum {
26
+ CROS_EC_ALTMODE_DP = 0 ,
27
+ CROS_EC_ALTMODE_MAX ,
28
+ };
29
+
23
30
/* Per port data. */
24
31
struct cros_typec_port {
25
32
struct typec_port * port ;
@@ -35,6 +42,9 @@ struct cros_typec_port {
35
42
/* Variables keeping track of switch state. */
36
43
struct typec_mux_state state ;
37
44
uint8_t mux_flags ;
45
+
46
+ /* Port alt modes. */
47
+ struct typec_altmode p_altmode [CROS_EC_ALTMODE_MAX ];
38
48
};
39
49
40
50
/* Platform-specific data for the Chrome OS EC Type C controller. */
@@ -142,6 +152,24 @@ static void cros_unregister_ports(struct cros_typec_data *typec)
142
152
}
143
153
}
144
154
155
+ /*
156
+ * Fake the alt mode structs until we actually start registering Type C port
157
+ * and partner alt modes.
158
+ */
159
+ static void cros_typec_register_port_altmodes (struct cros_typec_data * typec ,
160
+ int port_num )
161
+ {
162
+ struct cros_typec_port * port = typec -> ports [port_num ];
163
+
164
+ /* All PD capable CrOS devices are assumed to support DP altmode. */
165
+ port -> p_altmode [CROS_EC_ALTMODE_DP ].svid = USB_TYPEC_DP_SID ;
166
+ port -> p_altmode [CROS_EC_ALTMODE_DP ].mode = USB_TYPEC_DP_MODE ;
167
+
168
+ port -> state .alt = NULL ;
169
+ port -> state .mode = TYPEC_STATE_USB ;
170
+ port -> state .data = NULL ;
171
+ }
172
+
145
173
static int cros_typec_init_ports (struct cros_typec_data * typec )
146
174
{
147
175
struct device * dev = typec -> dev ;
@@ -205,6 +233,8 @@ static int cros_typec_init_ports(struct cros_typec_data *typec)
205
233
if (ret )
206
234
dev_dbg (dev , "No switch control for port %d\n" ,
207
235
port_num );
236
+
237
+ cros_typec_register_port_altmodes (typec , port_num );
208
238
}
209
239
210
240
return 0 ;
@@ -361,8 +391,46 @@ static int cros_typec_usb_safe_state(struct cros_typec_port *port)
361
391
return typec_mux_set (port -> mux , & port -> state );
362
392
}
363
393
394
+ /* Spoof the VDOs that were likely communicated by the partner. */
395
+ static int cros_typec_enable_dp (struct cros_typec_data * typec ,
396
+ int port_num ,
397
+ struct ec_response_usb_pd_control_v2 * pd_ctrl )
398
+ {
399
+ struct cros_typec_port * port = typec -> ports [port_num ];
400
+ struct typec_displayport_data dp_data ;
401
+ int ret ;
402
+
403
+ if (typec -> pd_ctrl_ver < 2 ) {
404
+ dev_err (typec -> dev ,
405
+ "PD_CTRL version too old: %d\n" , typec -> pd_ctrl_ver );
406
+ return - ENOTSUPP ;
407
+ }
408
+
409
+ /* Status VDO. */
410
+ dp_data .status = DP_STATUS_ENABLED ;
411
+ if (port -> mux_flags & USB_PD_MUX_HPD_IRQ )
412
+ dp_data .status |= DP_STATUS_IRQ_HPD ;
413
+ if (port -> mux_flags & USB_PD_MUX_HPD_LVL )
414
+ dp_data .status |= DP_STATUS_HPD_STATE ;
415
+
416
+ /* Configuration VDO. */
417
+ dp_data .conf = DP_CONF_SET_PIN_ASSIGN (pd_ctrl -> dp_mode );
418
+ if (!port -> state .alt ) {
419
+ port -> state .alt = & port -> p_altmode [CROS_EC_ALTMODE_DP ];
420
+ ret = cros_typec_usb_safe_state (port );
421
+ if (ret )
422
+ return ret ;
423
+ }
424
+
425
+ port -> state .data = & dp_data ;
426
+ port -> state .mode = TYPEC_MODAL_STATE (ffs (pd_ctrl -> dp_mode ));
427
+
428
+ return typec_mux_set (port -> mux , & port -> state );
429
+ }
430
+
364
431
int cros_typec_configure_mux (struct cros_typec_data * typec , int port_num ,
365
- uint8_t mux_flags )
432
+ uint8_t mux_flags ,
433
+ struct ec_response_usb_pd_control_v2 * pd_ctrl )
366
434
{
367
435
struct cros_typec_port * port = typec -> ports [port_num ];
368
436
enum typec_orientation orientation ;
@@ -380,14 +448,15 @@ int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
380
448
if (ret )
381
449
return ret ;
382
450
383
- port -> state .alt = NULL ;
384
- port -> state .mode = TYPEC_STATE_USB ;
385
-
386
- if (mux_flags & USB_PD_MUX_SAFE_MODE )
451
+ if (mux_flags & USB_PD_MUX_DP_ENABLED ) {
452
+ ret = cros_typec_enable_dp (typec , port_num , pd_ctrl );
453
+ } else if (mux_flags & USB_PD_MUX_SAFE_MODE ) {
387
454
ret = cros_typec_usb_safe_state (port );
388
- else if (mux_flags & USB_PD_MUX_USB_ENABLED )
455
+ } else if (mux_flags & USB_PD_MUX_USB_ENABLED ) {
456
+ port -> state .alt = NULL ;
457
+ port -> state .mode = TYPEC_STATE_USB ;
389
458
ret = typec_mux_set (port -> mux , & port -> state );
390
- else {
459
+ } else {
391
460
dev_info (typec -> dev ,
392
461
"Unsupported mode requested, mux flags: %x\n" ,
393
462
mux_flags );
@@ -400,7 +469,7 @@ int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
400
469
static int cros_typec_port_update (struct cros_typec_data * typec , int port_num )
401
470
{
402
471
struct ec_params_usb_pd_control req ;
403
- struct ec_response_usb_pd_control_v1 resp ;
472
+ struct ec_response_usb_pd_control_v2 resp ;
404
473
struct ec_response_usb_pd_mux_info mux_resp ;
405
474
int ret ;
406
475
@@ -427,7 +496,8 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
427
496
dev_dbg (typec -> dev , "State %d: %s\n" , port_num , resp .state );
428
497
429
498
if (typec -> pd_ctrl_ver != 0 )
430
- cros_typec_set_port_params_v1 (typec , port_num , & resp );
499
+ cros_typec_set_port_params_v1 (typec , port_num ,
500
+ (struct ec_response_usb_pd_control_v1 * )& resp );
431
501
else
432
502
cros_typec_set_port_params_v0 (typec , port_num ,
433
503
(struct ec_response_usb_pd_control * ) & resp );
@@ -446,7 +516,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
446
516
return 0 ;
447
517
448
518
typec -> ports [port_num ]-> mux_flags = mux_resp .flags ;
449
- ret = cros_typec_configure_mux (typec , port_num , mux_resp .flags );
519
+ ret = cros_typec_configure_mux (typec , port_num , mux_resp .flags , & resp );
450
520
if (ret )
451
521
dev_warn (typec -> dev , "Configure muxes failed, err = %d\n" , ret );
452
522
0 commit comments