1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
|
From 3c0725493c431bb255490269ec4171478b26b7d3 Mon Sep 17 00:00:00 2001
From: Yaroslav Bolyukin <iam@lach.pw>
Date: Tue, 2 Dec 2025 12:02:12 +0100
Subject: [PATCH 1/7] drm/edid: rename VESA block parsing functions to more
generic name
Those functions would also parse DSC Bits Per Pixel value in the future
commits.
Signed-off-by: Yaroslav Bolyukin <iam@lach.pw>
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
---
drivers/gpu/drm/drm_edid.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 404208bf23a6..4267fcd5a727 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -6598,8 +6598,8 @@ static void drm_get_monitor_range(struct drm_connector *connector,
info->monitor_range.min_vfreq, info->monitor_range.max_vfreq);
}
-static void drm_parse_vesa_mso_data(struct drm_connector *connector,
- const struct displayid_block *block)
+static void drm_parse_vesa_specific_block(struct drm_connector *connector,
+ const struct displayid_block *block)
{
struct displayid_vesa_vendor_specific_block *vesa =
(struct displayid_vesa_vendor_specific_block *)block;
@@ -6658,8 +6658,8 @@ static void drm_parse_vesa_mso_data(struct drm_connector *connector,
info->mso_stream_count, info->mso_pixel_overlap);
}
-static void drm_update_mso(struct drm_connector *connector,
- const struct drm_edid *drm_edid)
+static void drm_update_vesa_specific_block(struct drm_connector *connector,
+ const struct drm_edid *drm_edid)
{
const struct displayid_block *block;
struct displayid_iter iter;
@@ -6667,7 +6667,7 @@ static void drm_update_mso(struct drm_connector *connector,
displayid_iter_edid_begin(drm_edid, &iter);
displayid_iter_for_each(block, &iter) {
if (block->tag == DATA_BLOCK_2_VENDOR_SPECIFIC)
- drm_parse_vesa_mso_data(connector, block);
+ drm_parse_vesa_specific_block(connector, block);
}
displayid_iter_end(&iter);
}
@@ -6828,7 +6828,7 @@ static void update_display_info(struct drm_connector *connector,
if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB422)
info->color_formats |= BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422);
- drm_update_mso(connector, drm_edid);
+ drm_update_vesa_specific_block(connector, drm_edid);
out:
if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_NON_DESKTOP)) {
--
2.54.0
From f2fb7b780d967389d5349510846b43c91f37becd Mon Sep 17 00:00:00 2001
From: Yaroslav Bolyukin <iam@lach.pw>
Date: Tue, 2 Dec 2025 12:02:13 +0100
Subject: [PATCH 2/7] drm/edid: prepare for VESA vendor-specific data block
extension
Current VESA vendor-specific block parsing expects real block size to be
the same as the defined struct size, use real offsets in conditionals
instead to add struct fields in future commits.
Signed-off-by: Yaroslav Bolyukin <iam@lach.pw>
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
---
drivers/gpu/drm/drm_edid.c | 30 ++++++++++++++----------------
1 file changed, 14 insertions(+), 16 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 4267fcd5a727..5502f3935455 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -6615,7 +6615,7 @@ static void drm_parse_vesa_specific_block(struct drm_connector *connector,
if (oui(vesa->oui[0], vesa->oui[1], vesa->oui[2]) != VESA_IEEE_OUI)
return;
- if (sizeof(*vesa) != sizeof(*block) + block->num_bytes) {
+ if (block->num_bytes < 5) {
drm_dbg_kms(connector->dev,
"[CONNECTOR:%d:%s] Unexpected VESA vendor block size\n",
connector->base.id, connector->name);
@@ -6638,24 +6638,22 @@ static void drm_parse_vesa_specific_block(struct drm_connector *connector,
break;
}
- if (!info->mso_stream_count) {
- info->mso_pixel_overlap = 0;
- return;
- }
-
- info->mso_pixel_overlap = FIELD_GET(DISPLAYID_VESA_MSO_OVERLAP, vesa->mso);
- if (info->mso_pixel_overlap > 8) {
+ if (info->mso_stream_count) {
+ info->mso_pixel_overlap = FIELD_GET(DISPLAYID_VESA_MSO_OVERLAP, vesa->mso);
+ if (info->mso_pixel_overlap > 8) {
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] Reserved MSO pixel overlap value %u\n",
+ connector->base.id, connector->name,
+ info->mso_pixel_overlap);
+ info->mso_pixel_overlap = 8;
+ }
drm_dbg_kms(connector->dev,
- "[CONNECTOR:%d:%s] Reserved MSO pixel overlap value %u\n",
+ "[CONNECTOR:%d:%s] MSO stream count %u, pixel overlap %u\n",
connector->base.id, connector->name,
- info->mso_pixel_overlap);
- info->mso_pixel_overlap = 8;
+ info->mso_stream_count, info->mso_pixel_overlap);
+ } else {
+ info->mso_pixel_overlap = 0;
}
-
- drm_dbg_kms(connector->dev,
- "[CONNECTOR:%d:%s] MSO stream count %u, pixel overlap %u\n",
- connector->base.id, connector->name,
- info->mso_stream_count, info->mso_pixel_overlap);
}
static void drm_update_vesa_specific_block(struct drm_connector *connector,
--
2.54.0
From fc0a365a33d01b60e1c7d18fa4d59e9bf4f6833f Mon Sep 17 00:00:00 2001
From: Yaroslav Bolyukin <iam@lach.pw>
Date: Tue, 2 Dec 2025 12:02:14 +0100
Subject: [PATCH 3/7] drm/edid: MSO should only be used for non-eDP displays
As per DisplayID v2.1a spec:
If Offset 06h[2:0] is programmed to 001b (External DisplayPort), this
field shall be cleared to 00b (Not supported).
Link: https://lore.kernel.org/lkml/3abc1087618c822e5676e67a3ec2e64e506dc5ec@intel.com/
Signed-off-by: Yaroslav Bolyukin <iam@lach.pw>
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
---
drivers/gpu/drm/drm_displayid_internal.h | 4 +++
drivers/gpu/drm/drm_edid.c | 36 +++++++++++++++---------
2 files changed, 27 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/drm_displayid_internal.h b/drivers/gpu/drm/drm_displayid_internal.h
index 5b1b32f73516..72f107ae832f 100644
--- a/drivers/gpu/drm/drm_displayid_internal.h
+++ b/drivers/gpu/drm/drm_displayid_internal.h
@@ -142,9 +142,13 @@ struct displayid_formula_timing_block {
struct displayid_formula_timings_9 timings[];
} __packed;
+#define DISPLAYID_VESA_DP_TYPE GENMASK(2, 0)
#define DISPLAYID_VESA_MSO_OVERLAP GENMASK(3, 0)
#define DISPLAYID_VESA_MSO_MODE GENMASK(6, 5)
+#define DISPLAYID_VESA_DP_TYPE_EDP 0
+#define DISPLAYID_VESA_DP_TYPE_DP 1
+
struct displayid_vesa_vendor_specific_block {
struct displayid_block base;
u8 oui[3];
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 5502f3935455..9948c69305cf 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -6604,6 +6604,7 @@ static void drm_parse_vesa_specific_block(struct drm_connector *connector,
struct displayid_vesa_vendor_specific_block *vesa =
(struct displayid_vesa_vendor_specific_block *)block;
struct drm_display_info *info = &connector->display_info;
+ int dp_type;
if (block->num_bytes < 3) {
drm_dbg_kms(connector->dev,
@@ -6622,20 +6623,29 @@ static void drm_parse_vesa_specific_block(struct drm_connector *connector,
return;
}
- switch (FIELD_GET(DISPLAYID_VESA_MSO_MODE, vesa->mso)) {
- default:
- drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] Reserved MSO mode value\n",
+ dp_type = FIELD_GET(DISPLAYID_VESA_DP_TYPE, vesa->data_structure_type);
+ if (dp_type > 1) {
+ drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] Reserved dp type value\n",
connector->base.id, connector->name);
- fallthrough;
- case 0:
- info->mso_stream_count = 0;
- break;
- case 1:
- info->mso_stream_count = 2; /* 2 or 4 links */
- break;
- case 2:
- info->mso_stream_count = 4; /* 4 links */
- break;
+ }
+
+ /* MSO is only supported for eDP */
+ if (dp_type == DISPLAYID_VESA_DP_TYPE_EDP) {
+ switch (FIELD_GET(DISPLAYID_VESA_MSO_MODE, vesa->mso)) {
+ default:
+ drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] Reserved MSO mode value\n",
+ connector->base.id, connector->name);
+ fallthrough;
+ case 0:
+ info->mso_stream_count = 0;
+ break;
+ case 1:
+ info->mso_stream_count = 2; /* 2 or 4 links */
+ break;
+ case 2:
+ info->mso_stream_count = 4; /* 4 links */
+ break;
+ }
}
if (info->mso_stream_count) {
--
2.54.0
From 5d4b59081a05d238cfc0cd1183ef7f82bb2018b2 Mon Sep 17 00:00:00 2001
From: Yaroslav Bolyukin <iam@lach.pw>
Date: Tue, 2 Dec 2025 12:02:15 +0100
Subject: [PATCH 4/7] drm/edid: parse DSC DPP passthru support flag for mode
VII timings
For timings v7 block revision >=1, revision field also contains a bit
that indicates that the mode timings should only be used with fixed bits
per pixel value specified in vesa vendor-specific block.
Signed-off-by: Yaroslav Bolyukin <iam@lach.pw>
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
---
drivers/gpu/drm/drm_displayid_internal.h | 2 ++
drivers/gpu/drm/drm_edid.c | 12 ++++++++----
include/drm/drm_modes.h | 10 ++++++++++
3 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/drm_displayid_internal.h b/drivers/gpu/drm/drm_displayid_internal.h
index 72f107ae832f..724174b429f2 100644
--- a/drivers/gpu/drm/drm_displayid_internal.h
+++ b/drivers/gpu/drm/drm_displayid_internal.h
@@ -97,6 +97,7 @@ struct displayid_header {
u8 ext_count;
} __packed;
+#define DISPLAYID_BLOCK_REV GENMASK(2, 0)
struct displayid_block {
u8 tag;
u8 rev;
@@ -125,6 +126,7 @@ struct displayid_detailed_timings_1 {
__le16 vsw;
} __packed;
+#define DISPLAYID_BLOCK_PASSTHROUGH_TIMINGS_SUPPORT BIT(3)
struct displayid_detailed_timing_block {
struct displayid_block base;
struct displayid_detailed_timings_1 timings[];
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 9948c69305cf..81cf8afc2d2e 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -6866,8 +6866,8 @@ static void update_display_info(struct drm_connector *connector,
}
static struct drm_display_mode *drm_mode_displayid_detailed(struct drm_device *dev,
- const struct displayid_detailed_timings_1 *timings,
- bool type_7)
+ const struct displayid_block *block,
+ const struct displayid_detailed_timings_1 *timings)
{
struct drm_display_mode *mode;
unsigned int pixel_clock = (timings->pixel_clock[0] |
@@ -6883,11 +6883,16 @@ static struct drm_display_mode *drm_mode_displayid_detailed(struct drm_device *d
unsigned int vsync_width = le16_to_cpu(timings->vsw) + 1;
bool hsync_positive = le16_to_cpu(timings->hsync) & (1 << 15);
bool vsync_positive = le16_to_cpu(timings->vsync) & (1 << 15);
+ bool type_7 = block->tag == DATA_BLOCK_2_TYPE_7_DETAILED_TIMING;
mode = drm_mode_create(dev);
if (!mode)
return NULL;
+ if (type_7 && FIELD_GET(DISPLAYID_BLOCK_REV, block->rev) >= 1)
+ mode->dsc_passthrough_timings_support =
+ block->rev & DISPLAYID_BLOCK_PASSTHROUGH_TIMINGS_SUPPORT;
+
/* resolution is kHz for type VII, and 10 kHz for type I */
mode->clock = type_7 ? pixel_clock : pixel_clock * 10;
mode->hdisplay = hactive;
@@ -6920,7 +6925,6 @@ static int add_displayid_detailed_1_modes(struct drm_connector *connector,
int num_timings;
struct drm_display_mode *newmode;
int num_modes = 0;
- bool type_7 = block->tag == DATA_BLOCK_2_TYPE_7_DETAILED_TIMING;
/* blocks must be multiple of 20 bytes length */
if (block->num_bytes % 20)
return 0;
@@ -6929,7 +6933,7 @@ static int add_displayid_detailed_1_modes(struct drm_connector *connector,
for (i = 0; i < num_timings; i++) {
struct displayid_detailed_timings_1 *timings = &det->timings[i];
- newmode = drm_mode_displayid_detailed(connector->dev, timings, type_7);
+ newmode = drm_mode_displayid_detailed(connector->dev, block, timings);
if (!newmode)
continue;
diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
index b9bb92e4b029..312e5c03af9a 100644
--- a/include/drm/drm_modes.h
+++ b/include/drm/drm_modes.h
@@ -417,6 +417,16 @@ struct drm_display_mode {
*/
enum hdmi_picture_aspect picture_aspect_ratio;
+ /**
+ * @dsc_passthrough_timing_support:
+ *
+ * Indicates whether this mode timing descriptor is supported
+ * with specific target DSC bits per pixel only.
+ *
+ * VESA vendor-specific data block shall exist with the relevant
+ * DSC bits per pixel declaration when this flag is set to true.
+ */
+ bool dsc_passthrough_timings_support;
};
/**
--
2.54.0
From 89b3c7023273e23886848b06f6b6c94c1791626b Mon Sep 17 00:00:00 2001
From: Yaroslav Bolyukin <iam@lach.pw>
Date: Tue, 2 Dec 2025 12:02:16 +0100
Subject: [PATCH 5/7] drm/edid: for consistency, use mask everywhere for block
rev parsing
Other usages of block.rev bitfields were refactored to use FIELD_GET
instead of bitwise ops.
Signed-off-by: Yaroslav Bolyukin <iam@lach.pw>
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
---
drivers/gpu/drm/drm_displayid_internal.h | 1 +
drivers/gpu/drm/drm_edid.c | 3 ++-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_displayid_internal.h b/drivers/gpu/drm/drm_displayid_internal.h
index 724174b429f2..55f972d32847 100644
--- a/drivers/gpu/drm/drm_displayid_internal.h
+++ b/drivers/gpu/drm/drm_displayid_internal.h
@@ -139,6 +139,7 @@ struct displayid_formula_timings_9 {
u8 vrefresh;
} __packed;
+#define DISPLAYID_BLOCK_DESCRIPTOR_PAYLOAD_BYTES GENMASK(6, 4)
struct displayid_formula_timing_block {
struct displayid_block base;
struct displayid_formula_timings_9 timings[];
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 81cf8afc2d2e..19a635c5d91e 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -6980,7 +6980,8 @@ static int add_displayid_formula_modes(struct drm_connector *connector,
struct drm_display_mode *newmode;
int num_modes = 0;
bool type_10 = block->tag == DATA_BLOCK_2_TYPE_10_FORMULA_TIMING;
- int timing_size = 6 + ((formula_block->base.rev & 0x70) >> 4);
+ int timing_size = 6 +
+ FIELD_GET(DISPLAYID_BLOCK_DESCRIPTOR_PAYLOAD_BYTES, formula_block->base.rev);
/* extended blocks are not supported yet */
if (timing_size != 6)
--
2.54.0
From ad85af4597502bdbb7074e645e22181c6fcf0a7b Mon Sep 17 00:00:00 2001
From: Yaroslav Bolyukin <iam@lach.pw>
Date: Tue, 2 Dec 2025 12:02:17 +0100
Subject: [PATCH 6/7] drm/edid: parse DRM VESA dsc bpp target
As per DisplayID v2.1a spec "DSC pass-through timing support",
VESA vendor-specific data block may contain target DSC bits per pixel
fields, that should be always used for the VII modes that declare they
only support working with this value (Pass-through Timing Support for
Target DSC Bits per Pixel).
Signed-off-by: Yaroslav Bolyukin <iam@lach.pw>
fixup parse DRM vesa dsc bpp target
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
---
drivers/gpu/drm/drm_displayid_internal.h | 4 ++++
drivers/gpu/drm/drm_edid.c | 17 +++++++++++++++++
include/drm/drm_connector.h | 6 ++++++
3 files changed, 27 insertions(+)
diff --git a/drivers/gpu/drm/drm_displayid_internal.h b/drivers/gpu/drm/drm_displayid_internal.h
index 55f972d32847..8f1a2f33ca1a 100644
--- a/drivers/gpu/drm/drm_displayid_internal.h
+++ b/drivers/gpu/drm/drm_displayid_internal.h
@@ -148,6 +148,8 @@ struct displayid_formula_timing_block {
#define DISPLAYID_VESA_DP_TYPE GENMASK(2, 0)
#define DISPLAYID_VESA_MSO_OVERLAP GENMASK(3, 0)
#define DISPLAYID_VESA_MSO_MODE GENMASK(6, 5)
+#define DISPLAYID_VESA_DSC_BPP_INT GENMASK(5, 0)
+#define DISPLAYID_VESA_DSC_BPP_FRACT GENMASK(3, 0)
#define DISPLAYID_VESA_DP_TYPE_EDP 0
#define DISPLAYID_VESA_DP_TYPE_DP 1
@@ -157,6 +159,8 @@ struct displayid_vesa_vendor_specific_block {
u8 oui[3];
u8 data_structure_type;
u8 mso;
+ u8 dsc_bpp_int;
+ u8 dsc_bpp_fract;
} __packed;
/*
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 19a635c5d91e..18ae8b68c3d7 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -45,6 +45,7 @@
#include <drm/drm_edid.h>
#include <drm/drm_eld.h>
#include <drm/drm_encoder.h>
+#include <drm/drm_fixed.h>
#include <drm/drm_print.h>
#include "drm_crtc_internal.h"
@@ -6664,6 +6665,21 @@ static void drm_parse_vesa_specific_block(struct drm_connector *connector,
} else {
info->mso_pixel_overlap = 0;
}
+
+ if (block->num_bytes < 7) {
+ /* DSC bpp is optional */
+ return;
+ }
+
+ info->dp_dsc_bpp_x16 = FIELD_GET(DISPLAYID_VESA_DSC_BPP_INT, vesa->dsc_bpp_int) << 4 |
+ FIELD_GET(DISPLAYID_VESA_DSC_BPP_FRACT, vesa->dsc_bpp_fract);
+
+ if (info->dp_dsc_bpp_x16 > 0) {
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] DSC bits per pixel " FXP_Q4_FMT "\n",
+ connector->base.id, connector->name,
+ FXP_Q4_ARGS(info->dp_dsc_bpp_x16));
+ }
}
static void drm_update_vesa_specific_block(struct drm_connector *connector,
@@ -6712,6 +6728,7 @@ static void drm_reset_display_info(struct drm_connector *connector)
info->mso_stream_count = 0;
info->mso_pixel_overlap = 0;
info->max_dsc_bpp = 0;
+ info->dp_dsc_bpp_x16 = 0;
kfree(info->vics);
info->vics = NULL;
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index f83f28cae207..95d7490d266c 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -892,6 +892,12 @@ struct drm_display_info {
*/
u32 max_dsc_bpp;
+ /**
+ * @dp_dsc_bpp: DP Display-Stream-Compression (DSC) timing's target
+ * DSC bits per pixel in 6.4 fixed point format. 0 means undefined.
+ */
+ u16 dp_dsc_bpp_x16;
+
/**
* @vics: Array of vics_len VICs. Internal to EDID parsing.
*/
--
2.54.0
From 1b08f2d4948d39f34c5d6a1b1180a2614fd7ba35 Mon Sep 17 00:00:00 2001
From: Yaroslav Bolyukin <iam@lach.pw>
Date: Tue, 2 Dec 2025 12:02:18 +0100
Subject: [PATCH 7/7] drm/amd: use fixed dsc bits-per-pixel from edid
VESA vendor header from DisplayID spec may contain fixed bit per pixel
rate, it should be used by drm driver for the modes that declare
they are only supported with the declared fixed bits per pixel value.
Signed-off-by: Yaroslav Bolyukin <iam@lach.pw>
Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
---
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 5fc5d5608506..9e678b92bd5b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6880,6 +6880,11 @@ static void fill_stream_properties_from_drm_display_mode(
stream->output_color_space = get_output_color_space(timing_out, connector_state);
stream->content_type = get_output_content_type(connector_state);
+
+ /* DisplayID Type VII pass-through timings. */
+ if (mode_in->dsc_passthrough_timings_support && info->dp_dsc_bpp_x16 != 0) {
+ stream->timing.dsc_fixed_bits_per_pixel_x16 = info->dp_dsc_bpp_x16;
+ }
}
static void fill_audio_info(struct audio_info *audio_info,
@@ -7338,6 +7343,7 @@ create_stream_for_sink(struct drm_connector *connector,
struct drm_display_mode mode;
struct drm_display_mode saved_mode;
struct drm_display_mode *freesync_mode = NULL;
+ struct drm_display_mode *dsc_passthru_mode = NULL;
bool native_mode_found = false;
bool recalculate_timing = false;
bool scale = dm_state->scaling != RMX_OFF;
@@ -7429,6 +7435,16 @@ create_stream_for_sink(struct drm_connector *connector,
}
}
+ list_for_each_entry(dsc_passthru_mode, &connector->modes, head) {
+ if (dsc_passthru_mode->hdisplay == mode.hdisplay &&
+ dsc_passthru_mode->vdisplay == mode.vdisplay &&
+ drm_mode_vrefresh(dsc_passthru_mode) == mode_refresh) {
+ mode.dsc_passthrough_timings_support =
+ dsc_passthru_mode->dsc_passthrough_timings_support;
+ break;
+ }
+ }
+
if (recalculate_timing)
drm_mode_set_crtcinfo(&saved_mode, 0);
--
2.54.0
|