Skip to content

Commit 82f5075

Browse files
committed
Merge branch '7.0/vesa-dsc-bpp' into 7.0/base
Signed-off-by: Eric Naim <dnaim@cachyos.org>
2 parents 961b863 + 545b46d commit 82f5075

File tree

7 files changed

+112
-39
lines changed

7 files changed

+112
-39
lines changed

drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6808,6 +6808,11 @@ static void fill_stream_properties_from_drm_display_mode(
68086808

68096809
stream->output_color_space = get_output_color_space(timing_out, connector_state);
68106810
stream->content_type = get_output_content_type(connector_state);
6811+
6812+
/* DisplayID Type VII pass-through timings. */
6813+
if (mode_in->dsc_passthrough_timings_support && info->dp_dsc_bpp_x16 != 0) {
6814+
stream->timing.dsc_fixed_bits_per_pixel_x16 = info->dp_dsc_bpp_x16;
6815+
}
68116816
}
68126817

68136818
static void fill_audio_info(struct audio_info *audio_info,
@@ -7266,6 +7271,7 @@ create_stream_for_sink(struct drm_connector *connector,
72667271
struct drm_display_mode mode;
72677272
struct drm_display_mode saved_mode;
72687273
struct drm_display_mode *freesync_mode = NULL;
7274+
struct drm_display_mode *dsc_passthru_mode = NULL;
72697275
bool native_mode_found = false;
72707276
bool recalculate_timing = false;
72717277
bool scale = dm_state->scaling != RMX_OFF;
@@ -7357,6 +7363,16 @@ create_stream_for_sink(struct drm_connector *connector,
73577363
}
73587364
}
73597365

7366+
list_for_each_entry(dsc_passthru_mode, &connector->modes, head) {
7367+
if (dsc_passthru_mode->hdisplay == mode.hdisplay &&
7368+
dsc_passthru_mode->vdisplay == mode.vdisplay &&
7369+
drm_mode_vrefresh(dsc_passthru_mode) == mode_refresh) {
7370+
mode.dsc_passthrough_timings_support =
7371+
dsc_passthru_mode->dsc_passthrough_timings_support;
7372+
break;
7373+
}
7374+
}
7375+
73607376
if (recalculate_timing)
73617377
drm_mode_set_crtcinfo(&saved_mode, 0);
73627378

drivers/gpu/drm/amd/display/dc/dml/dsc/qp_tables.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ static const qp_table qp_table_444_8bpc_max = {
6363
{ 6.5, { 4, 6, 7, 8, 8, 8, 9, 10, 11, 11, 12, 12, 12, 13, 15} },
6464
{ 7, { 4, 5, 7, 7, 8, 8, 8, 9, 10, 11, 11, 12, 12, 13, 14} },
6565
{ 7.5, { 4, 5, 6, 7, 7, 8, 8, 9, 10, 10, 11, 11, 12, 13, 14} },
66-
{ 8, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13} },
66+
{ 8, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 11, 12, 13, 13, 15} },
6767
{ 8.5, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13} },
6868
{ 9, { 3, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 11, 11, 13} },
6969
{ 9.5, { 3, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 11, 11, 13} },
@@ -211,7 +211,7 @@ static const qp_table qp_table_444_8bpc_min = {
211211
{ 6.5, { 0, 1, 2, 3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 9, 14} },
212212
{ 7, { 0, 0, 2, 2, 4, 4, 4, 4, 4, 5, 5, 6, 6, 9, 13} },
213213
{ 7.5, { 0, 0, 2, 2, 3, 4, 4, 4, 4, 4, 5, 5, 6, 9, 13} },
214-
{ 8, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 4, 5, 5, 5, 8, 12} },
214+
{ 8, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 13} },
215215
{ 8.5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 4, 5, 5, 5, 8, 12} },
216216
{ 9, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 12} },
217217
{ 9.5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 12} },

drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ static void get_ofs_set(qp_set ofs, enum colour_mode mode, float bpp)
123123
*p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-6) : (-8 + dsc_roundf((bpp - 12) * (2 / 3.0))));
124124
*p++ = (bpp <= 12) ? (-10) : ((bpp >= 15) ? (-8) : (-10 + dsc_roundf((bpp - 12) * (2 / 3.0))));
125125
*p++ = -10;
126-
*p++ = (bpp <= 6) ? (-12) : ((bpp >= 8) ? (-10) : (-12 + dsc_roundf((bpp - 6) * (2 / 2.0))));
126+
*p++ = (bpp <= 6) ? (-12) : ((bpp >= 8) ? (-12) : (-12 + dsc_roundf((bpp - 6) * (2 / 2.0))));
127127
*p++ = -12;
128128
*p++ = -12;
129129
*p++ = -12;

drivers/gpu/drm/drm_displayid_internal.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ struct displayid_header {
9797
u8 ext_count;
9898
} __packed;
9999

100+
#define DISPLAYID_BLOCK_REV GENMASK(2, 0)
100101
struct displayid_block {
101102
u8 tag;
102103
u8 rev;
@@ -125,6 +126,7 @@ struct displayid_detailed_timings_1 {
125126
__le16 vsw;
126127
} __packed;
127128

129+
#define DISPLAYID_BLOCK_PASSTHROUGH_TIMINGS_SUPPORT BIT(3)
128130
struct displayid_detailed_timing_block {
129131
struct displayid_block base;
130132
struct displayid_detailed_timings_1 timings[];
@@ -137,19 +139,28 @@ struct displayid_formula_timings_9 {
137139
u8 vrefresh;
138140
} __packed;
139141

142+
#define DISPLAYID_BLOCK_DESCRIPTOR_PAYLOAD_BYTES GENMASK(6, 4)
140143
struct displayid_formula_timing_block {
141144
struct displayid_block base;
142145
struct displayid_formula_timings_9 timings[];
143146
} __packed;
144147

148+
#define DISPLAYID_VESA_DP_TYPE GENMASK(2, 0)
145149
#define DISPLAYID_VESA_MSO_OVERLAP GENMASK(3, 0)
146150
#define DISPLAYID_VESA_MSO_MODE GENMASK(6, 5)
151+
#define DISPLAYID_VESA_DSC_BPP_INT GENMASK(5, 0)
152+
#define DISPLAYID_VESA_DSC_BPP_FRACT GENMASK(3, 0)
153+
154+
#define DISPLAYID_VESA_DP_TYPE_EDP 0
155+
#define DISPLAYID_VESA_DP_TYPE_DP 1
147156

148157
struct displayid_vesa_vendor_specific_block {
149158
struct displayid_block base;
150159
u8 oui[3];
151160
u8 data_structure_type;
152161
u8 mso;
162+
u8 dsc_bpp_int;
163+
u8 dsc_bpp_fract;
153164
} __packed;
154165

155166
/*

drivers/gpu/drm/drm_edid.c

Lines changed: 66 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include <drm/drm_edid.h>
4646
#include <drm/drm_eld.h>
4747
#include <drm/drm_encoder.h>
48+
#include <drm/drm_fixed.h>
4849
#include <drm/drm_print.h>
4950

5051
#include "drm_crtc_internal.h"
@@ -6566,12 +6567,13 @@ static void drm_get_monitor_range(struct drm_connector *connector,
65666567
info->monitor_range.min_vfreq, info->monitor_range.max_vfreq);
65676568
}
65686569

6569-
static void drm_parse_vesa_mso_data(struct drm_connector *connector,
6570-
const struct displayid_block *block)
6570+
static void drm_parse_vesa_specific_block(struct drm_connector *connector,
6571+
const struct displayid_block *block)
65716572
{
65726573
struct displayid_vesa_vendor_specific_block *vesa =
65736574
(struct displayid_vesa_vendor_specific_block *)block;
65746575
struct drm_display_info *info = &connector->display_info;
6576+
int dp_type;
65756577

65766578
if (block->num_bytes < 3) {
65776579
drm_dbg_kms(connector->dev,
@@ -6583,59 +6585,81 @@ static void drm_parse_vesa_mso_data(struct drm_connector *connector,
65836585
if (oui(vesa->oui[0], vesa->oui[1], vesa->oui[2]) != VESA_IEEE_OUI)
65846586
return;
65856587

6586-
if (sizeof(*vesa) != sizeof(*block) + block->num_bytes) {
6588+
if (block->num_bytes < 5) {
65876589
drm_dbg_kms(connector->dev,
65886590
"[CONNECTOR:%d:%s] Unexpected VESA vendor block size\n",
65896591
connector->base.id, connector->name);
65906592
return;
65916593
}
65926594

6593-
switch (FIELD_GET(DISPLAYID_VESA_MSO_MODE, vesa->mso)) {
6594-
default:
6595-
drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] Reserved MSO mode value\n",
6595+
dp_type = FIELD_GET(DISPLAYID_VESA_DP_TYPE, vesa->data_structure_type);
6596+
if (dp_type > 1) {
6597+
drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] Reserved dp type value\n",
65966598
connector->base.id, connector->name);
6597-
fallthrough;
6598-
case 0:
6599-
info->mso_stream_count = 0;
6600-
break;
6601-
case 1:
6602-
info->mso_stream_count = 2; /* 2 or 4 links */
6603-
break;
6604-
case 2:
6605-
info->mso_stream_count = 4; /* 4 links */
6606-
break;
66076599
}
66086600

6609-
if (!info->mso_stream_count) {
6601+
/* MSO is only supported for eDP */
6602+
if (dp_type == DISPLAYID_VESA_DP_TYPE_EDP) {
6603+
switch (FIELD_GET(DISPLAYID_VESA_MSO_MODE, vesa->mso)) {
6604+
default:
6605+
drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] Reserved MSO mode value\n",
6606+
connector->base.id, connector->name);
6607+
fallthrough;
6608+
case 0:
6609+
info->mso_stream_count = 0;
6610+
break;
6611+
case 1:
6612+
info->mso_stream_count = 2; /* 2 or 4 links */
6613+
break;
6614+
case 2:
6615+
info->mso_stream_count = 4; /* 4 links */
6616+
break;
6617+
}
6618+
}
6619+
6620+
if (info->mso_stream_count) {
6621+
info->mso_pixel_overlap = FIELD_GET(DISPLAYID_VESA_MSO_OVERLAP, vesa->mso);
6622+
if (info->mso_pixel_overlap > 8) {
6623+
drm_dbg_kms(connector->dev,
6624+
"[CONNECTOR:%d:%s] Reserved MSO pixel overlap value %u\n",
6625+
connector->base.id, connector->name,
6626+
info->mso_pixel_overlap);
6627+
info->mso_pixel_overlap = 8;
6628+
}
6629+
drm_dbg_kms(connector->dev,
6630+
"[CONNECTOR:%d:%s] MSO stream count %u, pixel overlap %u\n",
6631+
connector->base.id, connector->name,
6632+
info->mso_stream_count, info->mso_pixel_overlap);
6633+
} else {
66106634
info->mso_pixel_overlap = 0;
6635+
}
6636+
6637+
if (block->num_bytes < 7) {
6638+
/* DSC bpp is optional */
66116639
return;
66126640
}
66136641

6614-
info->mso_pixel_overlap = FIELD_GET(DISPLAYID_VESA_MSO_OVERLAP, vesa->mso);
6615-
if (info->mso_pixel_overlap > 8) {
6642+
info->dp_dsc_bpp_x16 = FIELD_GET(DISPLAYID_VESA_DSC_BPP_INT, vesa->dsc_bpp_int) << 4 |
6643+
FIELD_GET(DISPLAYID_VESA_DSC_BPP_FRACT, vesa->dsc_bpp_fract);
6644+
6645+
if (info->dp_dsc_bpp_x16 > 0) {
66166646
drm_dbg_kms(connector->dev,
6617-
"[CONNECTOR:%d:%s] Reserved MSO pixel overlap value %u\n",
6647+
"[CONNECTOR:%d:%s] DSC bits per pixel " FXP_Q4_FMT "\n",
66186648
connector->base.id, connector->name,
6619-
info->mso_pixel_overlap);
6620-
info->mso_pixel_overlap = 8;
6649+
FXP_Q4_ARGS(info->dp_dsc_bpp_x16));
66216650
}
6622-
6623-
drm_dbg_kms(connector->dev,
6624-
"[CONNECTOR:%d:%s] MSO stream count %u, pixel overlap %u\n",
6625-
connector->base.id, connector->name,
6626-
info->mso_stream_count, info->mso_pixel_overlap);
66276651
}
66286652

6629-
static void drm_update_mso(struct drm_connector *connector,
6630-
const struct drm_edid *drm_edid)
6653+
static void drm_update_vesa_specific_block(struct drm_connector *connector,
6654+
const struct drm_edid *drm_edid)
66316655
{
66326656
const struct displayid_block *block;
66336657
struct displayid_iter iter;
66346658

66356659
displayid_iter_edid_begin(drm_edid, &iter);
66366660
displayid_iter_for_each(block, &iter) {
66376661
if (block->tag == DATA_BLOCK_2_VENDOR_SPECIFIC)
6638-
drm_parse_vesa_mso_data(connector, block);
6662+
drm_parse_vesa_specific_block(connector, block);
66396663
}
66406664
displayid_iter_end(&iter);
66416665
}
@@ -6672,6 +6696,7 @@ static void drm_reset_display_info(struct drm_connector *connector)
66726696
info->mso_stream_count = 0;
66736697
info->mso_pixel_overlap = 0;
66746698
info->max_dsc_bpp = 0;
6699+
info->dp_dsc_bpp_x16 = 0;
66756700

66766701
kfree(info->vics);
66776702
info->vics = NULL;
@@ -6795,7 +6820,7 @@ static void update_display_info(struct drm_connector *connector,
67956820
if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB422)
67966821
info->color_formats |= DRM_COLOR_FORMAT_YCBCR422;
67976822

6798-
drm_update_mso(connector, drm_edid);
6823+
drm_update_vesa_specific_block(connector, drm_edid);
67996824

68006825
out:
68016826
if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_NON_DESKTOP)) {
@@ -6825,8 +6850,8 @@ static void update_display_info(struct drm_connector *connector,
68256850
}
68266851

68276852
static struct drm_display_mode *drm_mode_displayid_detailed(struct drm_device *dev,
6828-
const struct displayid_detailed_timings_1 *timings,
6829-
bool type_7)
6853+
const struct displayid_block *block,
6854+
const struct displayid_detailed_timings_1 *timings)
68306855
{
68316856
struct drm_display_mode *mode;
68326857
unsigned int pixel_clock = (timings->pixel_clock[0] |
@@ -6842,11 +6867,16 @@ static struct drm_display_mode *drm_mode_displayid_detailed(struct drm_device *d
68426867
unsigned int vsync_width = le16_to_cpu(timings->vsw) + 1;
68436868
bool hsync_positive = le16_to_cpu(timings->hsync) & (1 << 15);
68446869
bool vsync_positive = le16_to_cpu(timings->vsync) & (1 << 15);
6870+
bool type_7 = block->tag == DATA_BLOCK_2_TYPE_7_DETAILED_TIMING;
68456871

68466872
mode = drm_mode_create(dev);
68476873
if (!mode)
68486874
return NULL;
68496875

6876+
if (type_7 && FIELD_GET(DISPLAYID_BLOCK_REV, block->rev) >= 1)
6877+
mode->dsc_passthrough_timings_support =
6878+
block->rev & DISPLAYID_BLOCK_PASSTHROUGH_TIMINGS_SUPPORT;
6879+
68506880
/* resolution is kHz for type VII, and 10 kHz for type I */
68516881
mode->clock = type_7 ? pixel_clock : pixel_clock * 10;
68526882
mode->hdisplay = hactive;
@@ -6879,7 +6909,6 @@ static int add_displayid_detailed_1_modes(struct drm_connector *connector,
68796909
int num_timings;
68806910
struct drm_display_mode *newmode;
68816911
int num_modes = 0;
6882-
bool type_7 = block->tag == DATA_BLOCK_2_TYPE_7_DETAILED_TIMING;
68836912
/* blocks must be multiple of 20 bytes length */
68846913
if (block->num_bytes % 20)
68856914
return 0;
@@ -6888,7 +6917,7 @@ static int add_displayid_detailed_1_modes(struct drm_connector *connector,
68886917
for (i = 0; i < num_timings; i++) {
68896918
struct displayid_detailed_timings_1 *timings = &det->timings[i];
68906919

6891-
newmode = drm_mode_displayid_detailed(connector->dev, timings, type_7);
6920+
newmode = drm_mode_displayid_detailed(connector->dev, block, timings);
68926921
if (!newmode)
68936922
continue;
68946923

@@ -6935,7 +6964,8 @@ static int add_displayid_formula_modes(struct drm_connector *connector,
69356964
struct drm_display_mode *newmode;
69366965
int num_modes = 0;
69376966
bool type_10 = block->tag == DATA_BLOCK_2_TYPE_10_FORMULA_TIMING;
6938-
int timing_size = 6 + ((formula_block->base.rev & 0x70) >> 4);
6967+
int timing_size = 6 +
6968+
FIELD_GET(DISPLAYID_BLOCK_DESCRIPTOR_PAYLOAD_BYTES, formula_block->base.rev);
69396969

69406970
/* extended blocks are not supported yet */
69416971
if (timing_size != 6)

include/drm/drm_connector.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -890,6 +890,12 @@ struct drm_display_info {
890890
*/
891891
u32 max_dsc_bpp;
892892

893+
/**
894+
* @dp_dsc_bpp: DP Display-Stream-Compression (DSC) timing's target
895+
* DSC bits per pixel in 6.4 fixed point format. 0 means undefined.
896+
*/
897+
u16 dp_dsc_bpp_x16;
898+
893899
/**
894900
* @vics: Array of vics_len VICs. Internal to EDID parsing.
895901
*/

include/drm/drm_modes.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,16 @@ struct drm_display_mode {
417417
*/
418418
enum hdmi_picture_aspect picture_aspect_ratio;
419419

420+
/**
421+
* @dsc_passthrough_timing_support:
422+
*
423+
* Indicates whether this mode timing descriptor is supported
424+
* with specific target DSC bits per pixel only.
425+
*
426+
* VESA vendor-specific data block shall exist with the relevant
427+
* DSC bits per pixel declaration when this flag is set to true.
428+
*/
429+
bool dsc_passthrough_timings_support;
420430
};
421431

422432
/**

0 commit comments

Comments
 (0)