Skip to content

Commit 5b28c08

Browse files
Lawstorant1Naim
authored andcommitted
drm/amd/display: Restore ALLM support in HDMI vsif
[Why] Support for triggering ALLM in modern TVs is missing. When HDMI vsif was added in 2019: commit 3c2381b ("drm/amd/display: add support for VSIP info packet") it was improperly handeled as HDMI actually has two separate vsifs. The implementation was based on H14b-vsif and ALLM bit was messing it up because H14b-vsif doesn't support ALLM. It was later removed in: commit 75f77aa ("drm/amd/display: Send H14b-VSIF specified in HDMI") ALLM is supported by hf-vsif (HDMI Forum) instead. [How] Add proper logic to construct either h14b-vsif or hf-vsif based on required capabilities. Currently, only ALLM from hf-vsif is supported. Turns out, hf-vsif is almost identical to h14b-vsif, BUT has additional two bytes of data after OUI. First byte is static and seems like a version supported by leftover define. Second byte consists of 3D and ALLM bits. Implement logic to offset 3D data if building hf-vsif. Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
1 parent f8bc116 commit 5b28c08

1 file changed

Lines changed: 71 additions & 36 deletions

File tree

drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c

Lines changed: 71 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ enum vsc_packet_revision {
4949
};
5050

5151
#define HDMI_INFOFRAME_TYPE_VENDOR 0x81
52-
#define HF_VSIF_VERSION 1
52+
#define HDMI_INFOFRAME_LENGTH_MASK 0x1F
53+
#define HF_VSIF_VERSION 1
54+
#define HF_VSIF_3D_BIT 0
55+
#define HF_VSIF_ALLM_BIT 1
5356

5457
// VTEM Byte Offset
5558
#define VTEM_PB0 0
@@ -496,73 +499,105 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream,
496499
}
497500
}
498501

502+
static bool is_hdmi_vic_mode(const struct dc_stream_state *stream)
503+
{
504+
if (stream->timing.hdmi_vic == 0)
505+
return false;
506+
507+
if (stream->timing.h_total < 3840 ||
508+
stream->timing.v_total < 2160)
509+
return false;
510+
511+
/* 3D/ALLM forces HDMI VIC -> CTA VIC translation */
512+
if (stream->view_format != VIEW_3D_FORMAT_NONE)
513+
return false;
514+
515+
if (stream->link->local_sink->edid_caps.allm)
516+
return false;
517+
518+
return true;
519+
}
520+
499521
/**
500522
* mod_build_hf_vsif_infopacket - Prepare HDMI Vendor Specific info frame.
501523
* Follows HDMI Spec to build up Vendor Specific info frame
524+
* Conforms to h14b-vsif or hf-vsif based on the capabilities
502525
*
503526
* @stream: contains data we may need to construct VSIF (i.e. timing_3d_format, etc.)
504527
* @info_packet: output structure where to store VSIF
505528
*/
506529
void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream,
507530
struct dc_info_packet *info_packet)
508531
{
509-
unsigned int length = 5;
510532
bool hdmi_vic_mode = false;
533+
bool allm = false;
534+
bool stereo = false;
511535
uint8_t checksum = 0;
512-
uint32_t i = 0;
536+
uint8_t offset = 0;
537+
uint8_t i = 0;
538+
uint8_t length = 5;
539+
uint32_t oui = HDMI_IEEE_OUI;
513540
enum dc_timing_3d_format format;
514541

515542
info_packet->valid = false;
543+
516544
format = stream->timing.timing_3d_format;
517545
if (stream->view_format == VIEW_3D_FORMAT_NONE)
518546
format = TIMING_3D_FORMAT_NONE;
547+
stereo = format != TIMING_3D_FORMAT_NONE;
548+
hdmi_vic_mode = is_hdmi_vic_mode(stream);
519549

520-
if (stream->timing.hdmi_vic != 0
521-
&& stream->timing.h_total >= 3840
522-
&& stream->timing.v_total >= 2160
523-
&& format == TIMING_3D_FORMAT_NONE)
524-
hdmi_vic_mode = true;
525-
526-
if ((format == TIMING_3D_FORMAT_NONE) && !hdmi_vic_mode)
550+
if (!stereo && !hdmi_vic_mode && !allm)
527551
return;
528552

529-
info_packet->sb[1] = 0x03;
530-
info_packet->sb[2] = 0x0C;
531-
info_packet->sb[3] = 0x00;
553+
if (allm)
554+
oui = HDMI_FORUM_IEEE_OUI;
532555

533-
if (format != TIMING_3D_FORMAT_NONE)
534-
info_packet->sb[4] = (2 << 5);
556+
info_packet->sb[1] = oui & 0xFF;
557+
info_packet->sb[2] = (oui >> 8) & 0xFF;
558+
info_packet->sb[3] = (oui >> 16) & 0xFF;
535559

536-
else if (hdmi_vic_mode)
537-
info_packet->sb[4] = (1 << 5);
560+
if (oui == HDMI_FORUM_IEEE_OUI) {
561+
offset = 2;
562+
length += 2;
563+
info_packet->sb[4] = HF_VSIF_VERSION;
564+
info_packet->sb[5] = stereo << HF_VSIF_3D_BIT;
565+
info_packet->sb[5] |= allm << HF_VSIF_ALLM_BIT;
566+
}
538567

539-
switch (format) {
540-
case TIMING_3D_FORMAT_HW_FRAME_PACKING:
541-
case TIMING_3D_FORMAT_SW_FRAME_PACKING:
542-
info_packet->sb[5] = (0x0 << 4);
543-
break;
568+
if (stereo) {
569+
info_packet->sb[4 + offset] = (2 << 5);
544570

545-
case TIMING_3D_FORMAT_SIDE_BY_SIDE:
546-
case TIMING_3D_FORMAT_SBS_SW_PACKED:
547-
info_packet->sb[5] = (0x8 << 4);
548-
length = 6;
549-
break;
571+
switch (format) {
572+
case TIMING_3D_FORMAT_HW_FRAME_PACKING:
573+
case TIMING_3D_FORMAT_SW_FRAME_PACKING:
574+
info_packet->sb[5 + offset] = (0x0 << 4);
575+
break;
550576

551-
case TIMING_3D_FORMAT_TOP_AND_BOTTOM:
552-
case TIMING_3D_FORMAT_TB_SW_PACKED:
553-
info_packet->sb[5] = (0x6 << 4);
554-
break;
577+
case TIMING_3D_FORMAT_SIDE_BY_SIDE:
578+
case TIMING_3D_FORMAT_SBS_SW_PACKED:
579+
info_packet->sb[5 + offset] = (0x8 << 4);
580+
++length;
581+
break;
555582

556-
default:
557-
break;
558-
}
583+
case TIMING_3D_FORMAT_TOP_AND_BOTTOM:
584+
case TIMING_3D_FORMAT_TB_SW_PACKED:
585+
info_packet->sb[5 + offset] = (0x6 << 4);
586+
break;
559587

560-
if (hdmi_vic_mode)
588+
default:
589+
break;
590+
}
591+
592+
/* Doesn't need the offset as it can't be used with hf-vsif */
593+
} else if (hdmi_vic_mode) {
594+
info_packet->sb[4] = (1 << 5);
561595
info_packet->sb[5] = stream->timing.hdmi_vic;
596+
}
562597

563598
info_packet->hb0 = HDMI_INFOFRAME_TYPE_VENDOR;
564599
info_packet->hb1 = 0x01;
565-
info_packet->hb2 = (uint8_t) (length);
600+
info_packet->hb2 = length & HDMI_INFOFRAME_LENGTH_MASK;
566601

567602
checksum += info_packet->hb0;
568603
checksum += info_packet->hb1;

0 commit comments

Comments
 (0)