7676#define VC5_HDMI_VERTB_VSPO_SHIFT 16
7777#define VC5_HDMI_VERTB_VSPO_MASK VC4_MASK(29, 16)
7878
79+ #define VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE_SHIFT 8
80+ #define VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE_MASK VC4_MASK(10, 8)
81+
82+ #define VC5_HDMI_DEEP_COLOR_CONFIG_1_COLOR_DEPTH_SHIFT 0
83+ #define VC5_HDMI_DEEP_COLOR_CONFIG_1_COLOR_DEPTH_MASK VC4_MASK(3, 0)
84+
85+ #define VC5_HDMI_GCP_CONFIG_GCP_ENABLE BIT(31)
86+
87+ #define VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1_SHIFT 8
88+ #define VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1_MASK VC4_MASK(15, 8)
89+
7990# define VC4_HD_M_SW_RST BIT(2)
8091# define VC4_HD_M_ENABLE BIT(0)
8192
@@ -186,6 +197,8 @@ static void vc4_hdmi_connector_reset(struct drm_connector *connector)
186197 if (!new_state )
187198 return ;
188199
200+ new_state -> base .max_bpc = 8 ;
201+ new_state -> base .max_requested_bpc = 8 ;
189202 drm_atomic_helper_connector_tv_reset (connector );
190203}
191204
@@ -232,12 +245,20 @@ static int vc4_hdmi_connector_init(struct drm_device *dev,
232245 vc4_hdmi -> ddc );
233246 drm_connector_helper_add (connector , & vc4_hdmi_connector_helper_funcs );
234247
248+ /*
249+ * Some of the properties below require access to state, like bpc.
250+ * Allocate some default initial connector state with our reset helper.
251+ */
252+ if (connector -> funcs -> reset )
253+ connector -> funcs -> reset (connector );
254+
235255 /* Create and attach TV margin props to this connector. */
236256 ret = drm_mode_create_tv_margin_properties (dev );
237257 if (ret )
238258 return ret ;
239259
240260 drm_connector_attach_tv_margin_properties (connector );
261+ drm_connector_attach_max_bpc_property (connector , 8 , 12 );
241262
242263 connector -> polled = (DRM_CONNECTOR_POLL_CONNECT |
243264 DRM_CONNECTOR_POLL_DISCONNECT );
@@ -506,6 +527,7 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
506527}
507528
508529static void vc4_hdmi_set_timings (struct vc4_hdmi * vc4_hdmi ,
530+ struct drm_connector_state * state ,
509531 struct drm_display_mode * mode )
510532{
511533 bool hsync_pos = mode -> flags & DRM_MODE_FLAG_PHSYNC ;
@@ -549,7 +571,9 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
549571 HDMI_WRITE (HDMI_VERTB0 , vertb_even );
550572 HDMI_WRITE (HDMI_VERTB1 , vertb );
551573}
574+
552575static void vc5_hdmi_set_timings (struct vc4_hdmi * vc4_hdmi ,
576+ struct drm_connector_state * state ,
553577 struct drm_display_mode * mode )
554578{
555579 bool hsync_pos = mode -> flags & DRM_MODE_FLAG_PHSYNC ;
@@ -569,6 +593,9 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
569593 mode -> crtc_vsync_end -
570594 interlaced ,
571595 VC4_HDMI_VERTB_VBP ));
596+ unsigned char gcp ;
597+ bool gcp_en ;
598+ u32 reg ;
572599
573600 HDMI_WRITE (HDMI_VEC_INTERFACE_XBAR , 0x354021 );
574601 HDMI_WRITE (HDMI_HORZA ,
@@ -594,6 +621,39 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
594621 HDMI_WRITE (HDMI_VERTB0 , vertb_even );
595622 HDMI_WRITE (HDMI_VERTB1 , vertb );
596623
624+ switch (state -> max_bpc ) {
625+ case 12 :
626+ gcp = 6 ;
627+ gcp_en = true;
628+ break ;
629+ case 10 :
630+ gcp = 5 ;
631+ gcp_en = true;
632+ break ;
633+ case 8 :
634+ default :
635+ gcp = 4 ;
636+ gcp_en = false;
637+ break ;
638+ }
639+
640+ reg = HDMI_READ (HDMI_DEEP_COLOR_CONFIG_1 );
641+ reg &= ~(VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE_MASK |
642+ VC5_HDMI_DEEP_COLOR_CONFIG_1_COLOR_DEPTH_MASK );
643+ reg |= VC4_SET_FIELD (2 , VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE ) |
644+ VC4_SET_FIELD (gcp , VC5_HDMI_DEEP_COLOR_CONFIG_1_COLOR_DEPTH );
645+ HDMI_WRITE (HDMI_DEEP_COLOR_CONFIG_1 , reg );
646+
647+ reg = HDMI_READ (HDMI_GCP_WORD_1 );
648+ reg &= ~VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1_MASK ;
649+ reg |= VC4_SET_FIELD (gcp , VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1 );
650+ HDMI_WRITE (HDMI_GCP_WORD_1 , reg );
651+
652+ reg = HDMI_READ (HDMI_GCP_CONFIG );
653+ reg &= ~VC5_HDMI_GCP_CONFIG_GCP_ENABLE ;
654+ reg |= gcp_en ? VC5_HDMI_GCP_CONFIG_GCP_ENABLE : 0 ;
655+ HDMI_WRITE (HDMI_GCP_CONFIG , reg );
656+
597657 HDMI_WRITE (HDMI_CLOCK_STOP , 0 );
598658}
599659
@@ -731,7 +791,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
731791 VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS );
732792
733793 if (vc4_hdmi -> variant -> set_timings )
734- vc4_hdmi -> variant -> set_timings (vc4_hdmi , mode );
794+ vc4_hdmi -> variant -> set_timings (vc4_hdmi , conn_state , mode );
735795}
736796
737797static void vc4_hdmi_encoder_pre_crtc_enable (struct drm_encoder * encoder ,
@@ -852,6 +912,14 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
852912 pixel_rate = mode -> clock * 1000 ;
853913 }
854914
915+ if (conn_state -> max_bpc == 12 ) {
916+ pixel_rate = pixel_rate * 150 ;
917+ do_div (pixel_rate , 100 );
918+ } else if (conn_state -> max_bpc == 10 ) {
919+ pixel_rate = pixel_rate * 125 ;
920+ do_div (pixel_rate , 100 );
921+ }
922+
855923 if (mode -> flags & DRM_MODE_FLAG_DBLCLK )
856924 pixel_rate = pixel_rate * 2 ;
857925
0 commit comments