Skip to content

Commit 2d7e047

Browse files
committed
thunderbolt: Add DisplayPort 2.x tunneling support
This adds support for the UHBR (Ultra High Bit Rate) bandwidths introduced with DisplayPort 2.0 (and refined in 2.1). These can go up to 80 Gbit/s and their support is represent in additional bits in the DP IN capability. This updates the DisplayPort tunneling to support these new rates too. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
1 parent 8d73f6b commit 2d7e047

2 files changed

Lines changed: 87 additions & 16 deletions

File tree

drivers/thunderbolt/tb_regs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,9 @@ struct tb_regs_port_header {
450450
#define DP_COMMON_CAP_1_LANE 0x0
451451
#define DP_COMMON_CAP_2_LANES 0x1
452452
#define DP_COMMON_CAP_4_LANES 0x2
453+
#define DP_COMMON_CAP_UHBR10 BIT(17)
454+
#define DP_COMMON_CAP_UHBR20 BIT(18)
455+
#define DP_COMMON_CAP_UHBR13_5 BIT(19)
453456
#define DP_COMMON_CAP_LTTPR_NS BIT(27)
454457
#define DP_COMMON_CAP_BW_MODE BIT(28)
455458
#define DP_COMMON_CAP_DPRX_DONE BIT(31)

drivers/thunderbolt/tunnel.c

Lines changed: 84 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,10 @@ static int tb_dp_cm_handshake(struct tb_port *in, struct tb_port *out,
418418
return -ETIMEDOUT;
419419
}
420420

421+
/*
422+
* Returns maximum possible rate from capability supporting only DP 2.0
423+
* and below. Used when DP BW allocation mode is not enabled.
424+
*/
421425
static inline u32 tb_dp_cap_get_rate(u32 val)
422426
{
423427
u32 rate = (val & DP_COMMON_CAP_RATE_MASK) >> DP_COMMON_CAP_RATE_SHIFT;
@@ -436,6 +440,28 @@ static inline u32 tb_dp_cap_get_rate(u32 val)
436440
}
437441
}
438442

443+
/*
444+
* Returns maximum possible rate from capability supporting DP 2.1
445+
* UHBR20, 13.5 and 10 rates as well. Use only when DP BW allocation
446+
* mode is enabled.
447+
*/
448+
static inline u32 tb_dp_cap_get_rate_ext(u32 val)
449+
{
450+
if (val & DP_COMMON_CAP_UHBR20)
451+
return 20000;
452+
else if (val & DP_COMMON_CAP_UHBR13_5)
453+
return 13500;
454+
else if (val & DP_COMMON_CAP_UHBR10)
455+
return 10000;
456+
457+
return tb_dp_cap_get_rate(val);
458+
}
459+
460+
static inline bool tb_dp_is_uhbr_rate(unsigned int rate)
461+
{
462+
return rate >= 10000;
463+
}
464+
439465
static inline u32 tb_dp_cap_set_rate(u32 val, u32 rate)
440466
{
441467
val &= ~DP_COMMON_CAP_RATE_MASK;
@@ -498,7 +524,9 @@ static inline u32 tb_dp_cap_set_lanes(u32 val, u32 lanes)
498524

499525
static unsigned int tb_dp_bandwidth(unsigned int rate, unsigned int lanes)
500526
{
501-
/* Tunneling removes the DP 8b/10b encoding */
527+
/* Tunneling removes the DP 8b/10b 128/132b encoding */
528+
if (tb_dp_is_uhbr_rate(rate))
529+
return rate * lanes * 128 / 132;
502530
return rate * lanes * 8 / 10;
503531
}
504532

@@ -691,6 +719,19 @@ static int tb_dp_bandwidth_alloc_mode_enable(struct tb_tunnel *tunnel)
691719
if (ret)
692720
return ret;
693721

722+
/*
723+
* Pick up granularity that supports maximum possible bandwidth.
724+
* For that we use the UHBR rates too.
725+
*/
726+
in_rate = tb_dp_cap_get_rate_ext(in_dp_cap);
727+
out_rate = tb_dp_cap_get_rate_ext(out_dp_cap);
728+
rate = min(in_rate, out_rate);
729+
tmp = tb_dp_bandwidth(rate, lanes);
730+
731+
tb_port_dbg(in,
732+
"maximum bandwidth through allocation mode %u Mb/s x%u = %u Mb/s\n",
733+
rate, lanes, tmp);
734+
694735
for (granularity = 250; tmp / granularity > 255 && granularity <= 1000;
695736
granularity *= 2)
696737
;
@@ -806,15 +847,42 @@ static int tb_dp_activate(struct tb_tunnel *tunnel, bool active)
806847
}
807848

808849
/* max_bw is rounded up to next granularity */
809-
static int tb_dp_nrd_bandwidth(struct tb_tunnel *tunnel, int *max_bw)
850+
static int tb_dp_bandwidth_mode_maximum_bandwidth(struct tb_tunnel *tunnel,
851+
int *max_bw)
810852
{
811853
struct tb_port *in = tunnel->src_port;
812854
int ret, rate, lanes, nrd_bw;
855+
u32 cap;
813856

814-
ret = usb4_dp_port_nrd(in, &rate, &lanes);
857+
/*
858+
* DP IN adapter DP_LOCAL_CAP gets updated to the lowest AUX
859+
* read parameter values so this so we can use this to determine
860+
* the maximum possible bandwidth over this link.
861+
*
862+
* See USB4 v2 spec 1.0 10.4.4.5.
863+
*/
864+
ret = tb_port_read(in, &cap, TB_CFG_PORT,
865+
in->cap_adap + DP_LOCAL_CAP, 1);
815866
if (ret)
816867
return ret;
817868

869+
rate = tb_dp_cap_get_rate_ext(cap);
870+
if (tb_dp_is_uhbr_rate(rate)) {
871+
/*
872+
* When UHBR is used there is no reduction in lanes so
873+
* we can use this directly.
874+
*/
875+
lanes = tb_dp_cap_get_lanes(cap);
876+
} else {
877+
/*
878+
* If there is no UHBR supported then check the
879+
* non-reduced rate and lanes.
880+
*/
881+
ret = usb4_dp_port_nrd(in, &rate, &lanes);
882+
if (ret)
883+
return ret;
884+
}
885+
818886
nrd_bw = tb_dp_bandwidth(rate, lanes);
819887

820888
if (max_bw) {
@@ -847,7 +915,7 @@ static int tb_dp_bandwidth_mode_consumed_bandwidth(struct tb_tunnel *tunnel,
847915
return ret;
848916
allocated_bw = ret;
849917

850-
ret = tb_dp_nrd_bandwidth(tunnel, &max_bw);
918+
ret = tb_dp_bandwidth_mode_maximum_bandwidth(tunnel, &max_bw);
851919
if (ret < 0)
852920
return ret;
853921
if (allocated_bw == max_bw)
@@ -885,7 +953,7 @@ static int tb_dp_allocated_bandwidth(struct tb_tunnel *tunnel, int *allocated_up
885953
return ret;
886954
allocated_bw = ret;
887955

888-
ret = tb_dp_nrd_bandwidth(tunnel, &max_bw);
956+
ret = tb_dp_bandwidth_mode_maximum_bandwidth(tunnel, &max_bw);
889957
if (ret < 0)
890958
return ret;
891959
if (allocated_bw == max_bw)
@@ -915,7 +983,7 @@ static int tb_dp_alloc_bandwidth(struct tb_tunnel *tunnel, int *alloc_up,
915983
if (!usb4_dp_port_bandwidth_mode_enabled(in))
916984
return -EOPNOTSUPP;
917985

918-
ret = tb_dp_nrd_bandwidth(tunnel, &max_bw);
986+
ret = tb_dp_bandwidth_mode_maximum_bandwidth(tunnel, &max_bw);
919987
if (ret < 0)
920988
return ret;
921989

@@ -938,6 +1006,9 @@ static int tb_dp_alloc_bandwidth(struct tb_tunnel *tunnel, int *alloc_up,
9381006
/* Now we can use BW mode registers to figure out the bandwidth */
9391007
/* TODO: need to handle discovery too */
9401008
tunnel->bw_mode = true;
1009+
1010+
tb_port_dbg(in, "allocated bandwidth through allocation mode %d Mb/s\n",
1011+
tmp);
9411012
return 0;
9421013
}
9431014

@@ -1012,23 +1083,20 @@ static int tb_dp_maximum_bandwidth(struct tb_tunnel *tunnel, int *max_up,
10121083
int *max_down)
10131084
{
10141085
struct tb_port *in = tunnel->src_port;
1015-
u32 rate, lanes;
10161086
int ret;
10171087

1018-
/*
1019-
* DP IN adapter DP_LOCAL_CAP gets updated to the lowest AUX read
1020-
* parameter values so this so we can use this to determine the
1021-
* maximum possible bandwidth over this link.
1022-
*/
1023-
ret = tb_dp_read_cap(tunnel, DP_LOCAL_CAP, &rate, &lanes);
1024-
if (ret)
1088+
if (!usb4_dp_port_bandwidth_mode_enabled(in))
1089+
return -EOPNOTSUPP;
1090+
1091+
ret = tb_dp_bandwidth_mode_maximum_bandwidth(tunnel, NULL);
1092+
if (ret < 0)
10251093
return ret;
10261094

10271095
if (in->sw->config.depth < tunnel->dst_port->sw->config.depth) {
10281096
*max_up = 0;
1029-
*max_down = tb_dp_bandwidth(rate, lanes);
1097+
*max_down = ret;
10301098
} else {
1031-
*max_up = tb_dp_bandwidth(rate, lanes);
1099+
*max_up = ret;
10321100
*max_down = 0;
10331101
}
10341102

0 commit comments

Comments
 (0)