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
68006825out :
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
68276852static 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 )
0 commit comments