@@ -387,6 +387,16 @@ int cypd_update_power_status(void)
387
387
return rv ;
388
388
}
389
389
390
+ static void port_to_safe_mode (int port )
391
+ {
392
+ uint8_t data [2 ] = {0x00 , CCG_PD_USER_MUX_CONFIG_SAFE };
393
+
394
+ data [0 ] = PORT_TO_CONTROLLER_PORT (port );
395
+ cypd_write_reg_block (PORT_TO_CONTROLLER (port ), CYP5225_MUX_CFG_REG , data , 2 );
396
+ cypd_write_reg_block (PORT_TO_CONTROLLER (port ), CYP5225_DEINIT_PORT_REG , data , 1 );
397
+ CPRINTS ("P%d: Safe" , port );
398
+ }
399
+
390
400
void enable_compliance_mode (int controller )
391
401
{
392
402
int rv ;
@@ -553,6 +563,120 @@ int cyp5525_setup(int controller)
553
563
}
554
564
555
565
566
+ static bool pending_dp_poweroff [PD_PORT_COUNT ];
567
+ static void poweroff_dp_check (void )
568
+ {
569
+ int i ;
570
+ int alt_active = 0 ;
571
+
572
+ for (i = 0 ; i < PD_PORT_COUNT ; i ++ ) {
573
+ if (pending_dp_poweroff [i ]) {
574
+ /* see if alt mode is active */
575
+ cypd_read_reg8 (PORT_TO_CONTROLLER (i ),
576
+ CYP5525_DP_ALT_MODE_CONFIG_REG (PORT_TO_CONTROLLER_PORT (i )),
577
+ & alt_active );
578
+ /*
579
+ * DP_ALT should be on bit 1 always, but there is a bug
580
+ * in the PD stack that if a port does not have TBT mode
581
+ * enabled, it will shift the DP alt mode enable bit to
582
+ * bit 0. Since we only whitelist DP alt mode cards, just
583
+ * mask on both as a workaround.
584
+ */
585
+ if ((alt_active & (BIT (1 ) + BIT (0 ))) == 0 )
586
+ port_to_safe_mode (i );
587
+
588
+ pending_dp_poweroff [i ] = 0 ;
589
+ }
590
+ }
591
+ }
592
+ static void poweroff_dp_deferred (void )
593
+ {
594
+ task_set_event (TASK_ID_CYPD , CYPD_EVT_DPALT_DISABLE , 0 );
595
+
596
+ }
597
+ DECLARE_DEFERRED (poweroff_dp_deferred );
598
+
599
+ struct framework_dp_ids {
600
+ uint16_t vid ;
601
+ uint16_t pid ;
602
+ } const cypd_altmode_ids [] = {
603
+ {0x32AC , 0x0002 },
604
+ {0x32AC , 0x0003 },
605
+ {0x32AC , 0x000E },
606
+ };
607
+ struct match_vdm_header {
608
+ uint8_t idx ;
609
+ uint8_t val ;
610
+ } const framework_vdm_hdr_match [] = {
611
+ {0 , 0x8f },
612
+ /*{1, 0x52},*/
613
+ {2 , 0 },
614
+ {4 , 0x41 },
615
+ /*{5, 0xa0},*/
616
+ {6 , 0x00 },
617
+ {7 , 0xFF },
618
+ /*{8, 0xAC}, Framework VID */
619
+ /*{9, 0x32}, */
620
+ /*{10, 0x00},*/
621
+ /*{11, 0x6C}*/
622
+ };
623
+
624
+ void cypd_handle_vdm (int controller , int port , uint8_t * data , int len )
625
+ {
626
+ /* parse vdm
627
+ * if we get a DP alt mode VDM that matches our
628
+ * HDMI or DP VID/PID we will start a timer
629
+ * to set the port mux to safe/isolate
630
+ * if we get a enter alt mode later on,
631
+ * we will cancel the timer so that PD can
632
+ * properly enter the alt mode
633
+ *
634
+ * ID HDR ProductVDO
635
+ * hdr SOP R VDMHDR VDO VDO VDO
636
+ * HDMI
637
+ * 0x8f52 00 00 41a000ff ac32006c 00000000 00000200 18000000
638
+ * DP
639
+ * 0x8f52 00 00 41a000ff ac32006c 00000000 00000300 18000000
640
+ * 0 1 2 3 4 8 12 16
641
+ * 180W Power Adapter
642
+ * 0x8f59 00 00 41a800ff ac32c001 00000000 00000e00 01008020
643
+ */
644
+ int i ;
645
+ uint16_t vid , pid ;
646
+ bool trigger_deferred_update = false;
647
+
648
+ for (i = 0 ; i < sizeof (framework_vdm_hdr_match )/sizeof (struct match_vdm_header ); i ++ ) {
649
+ if (framework_vdm_hdr_match [i ].idx >= len )
650
+ continue ;
651
+
652
+ if (data [framework_vdm_hdr_match [i ].idx ] !=
653
+ framework_vdm_hdr_match [i ].val ) {
654
+ return ;
655
+ }
656
+ }
657
+
658
+ for (i = 0 ; i < sizeof (cypd_altmode_ids )/sizeof (struct framework_dp_ids ); i ++ ) {
659
+ vid = cypd_altmode_ids [i ].vid ;
660
+ pid = cypd_altmode_ids [i ].pid ;
661
+ if ((vid & 0xFF ) == data [8 ] &&
662
+ ((vid >>8 ) & 0xFF ) == data [9 ] &&
663
+ (pid & 0xFF ) == data [18 ] &&
664
+ ((pid >>8 ) & 0xFF ) == data [19 ]
665
+ ) {
666
+ pending_dp_poweroff [port + (controller <<1 )] = true;
667
+ trigger_deferred_update = true;
668
+ CPRINTS (" vdm vidpid match" );
669
+
670
+ }
671
+
672
+ }
673
+ if (trigger_deferred_update ) {
674
+ hook_call_deferred (& poweroff_dp_deferred_data , 30000 * MSEC );
675
+ }
676
+
677
+ }
678
+
679
+
556
680
void cypd_set_source_pdo_mask (int enabled_mask )
557
681
{
558
682
int i ;
@@ -1008,6 +1132,11 @@ void cyp5525_port_int(int controller, int port)
1008
1132
cypd_handle_extend_msg (controller , port , response_len , sop_type );
1009
1133
CPRINTS ("CYP_RESPONSE_RX_EXT_MSG" );
1010
1134
break ;
1135
+ case CYPD_RESPONSE_VDM_RX :
1136
+ i2c_read_offset16_block (i2c_port , addr_flags ,
1137
+ CYP5525_READ_DATA_MEMORY_REG (port , 0 ), data2 , MIN (response_len , 32 ));
1138
+ cypd_handle_vdm (controller , port , data2 , response_len );
1139
+ CPRINTS ("CYPD_RESPONSE_VDM_RX" );
1011
1140
default :
1012
1141
if (response_len && verbose_msg_logging ) {
1013
1142
CPRINTF ("Port:%d Data:0x" , port_idx );
@@ -1087,7 +1216,6 @@ void cypd_handle_state(int controller)
1087
1216
case CYP5525_STATE_APP_SETUP :
1088
1217
gpio_disable_interrupt (pd_chip_config [controller ].gpio );
1089
1218
cyp5525_get_version (controller );
1090
- cypd_write_reg8_wait_ack (controller , CYP5225_USER_MAINBOARD_VERSION , board_get_version ());
1091
1219
1092
1220
/*for(i=0; i < 50;i++) {
1093
1221
if (gpio_get_level(GPIO_PWR_3V5V_PG) &&
@@ -1332,6 +1460,9 @@ void cypd_interrupt_handler_task(void *p)
1332
1460
if (evt & CYPD_EVT_INT_CTRL_1 ) {
1333
1461
cyp5525_interrupt (1 );
1334
1462
}
1463
+ if (evt & CYPD_EVT_DPALT_DISABLE ) {
1464
+ poweroff_dp_check ();
1465
+ }
1335
1466
if (evt & CYPD_EVT_STATE_CTRL_0 ) {
1336
1467
cypd_handle_state (0 );
1337
1468
task_wait_event_mask (TASK_EVENT_TIMER ,10 );
0 commit comments