@@ -599,6 +599,7 @@ static int vc4_hdmi_connector_atomic_check(struct drm_connector *connector,
599599
600600 if (old_state -> colorspace != new_state -> colorspace ||
601601 old_vc4_state -> broadcast_rgb != new_vc4_state -> broadcast_rgb ||
602+ old_vc4_state -> requested_output_format != new_vc4_state -> requested_output_format ||
602603 !drm_connector_atomic_hdr_metadata_equal (old_state , new_state )) {
603604 struct drm_crtc_state * crtc_state ;
604605
@@ -625,6 +626,8 @@ static int vc4_hdmi_connector_get_property(struct drm_connector *connector,
625626
626627 if (property == vc4_hdmi -> broadcast_rgb_property ) {
627628 * val = vc4_conn_state -> broadcast_rgb ;
629+ } else if (property == vc4_hdmi -> output_format_property ) {
630+ * val = vc4_conn_state -> requested_output_format ;
628631 } else {
629632 drm_dbg (drm , "Unknown property [PROP:%d:%s]\n" ,
630633 property -> base .id , property -> name );
@@ -648,6 +651,9 @@ static int vc4_hdmi_connector_set_property(struct drm_connector *connector,
648651 if (property == vc4_hdmi -> broadcast_rgb_property ) {
649652 vc4_conn_state -> broadcast_rgb = val ;
650653 return 0 ;
654+ } else if (property == vc4_hdmi -> output_format_property ) {
655+ vc4_conn_state -> requested_output_format = val ;
656+ return 0 ;
651657 }
652658
653659 drm_dbg (drm , "Unknown property [PROP:%d:%s]\n" ,
@@ -692,6 +698,7 @@ vc4_hdmi_connector_duplicate_state(struct drm_connector *connector)
692698 new_state -> tmds_char_rate = vc4_state -> tmds_char_rate ;
693699 new_state -> output_bpc = vc4_state -> output_bpc ;
694700 new_state -> output_format = vc4_state -> output_format ;
701+ new_state -> requested_output_format = vc4_state -> requested_output_format ;
695702 new_state -> broadcast_rgb = vc4_state -> broadcast_rgb ;
696703 __drm_atomic_helper_connector_duplicate_state (connector , & new_state -> base );
697704
@@ -740,6 +747,33 @@ vc4_hdmi_attach_broadcast_rgb_property(struct drm_device *dev,
740747 VC4_HDMI_BROADCAST_RGB_AUTO );
741748}
742749
750+ static const struct drm_prop_enum_list output_format_names [] = {
751+ { VC4_HDMI_OUTPUT_AUTO , "Automatic" },
752+ { VC4_HDMI_OUTPUT_RGB , "RGB" },
753+ { VC4_HDMI_OUTPUT_YUV422 , "YCbCr 4:2:2" },
754+ { VC4_HDMI_OUTPUT_YUV444 , "YCbCr 4:4:4" },
755+ };
756+
757+ static void
758+ vc4_hdmi_attach_output_format_property (struct drm_device * dev ,
759+ struct vc4_hdmi * vc4_hdmi )
760+ {
761+ struct drm_property * prop = vc4_hdmi -> output_format_property ;
762+
763+ if (!prop ) {
764+ prop = drm_property_create_enum (dev , DRM_MODE_PROP_ENUM ,
765+ "Output format" ,
766+ output_format_names ,
767+ ARRAY_SIZE (output_format_names ));
768+ if (!prop )
769+ return ;
770+
771+ vc4_hdmi -> output_format_property = prop ;
772+ }
773+
774+ drm_object_attach_property (& vc4_hdmi -> connector .base , prop , 0 );
775+ }
776+
743777static int vc4_hdmi_connector_init (struct drm_device * dev ,
744778 struct vc4_hdmi * vc4_hdmi )
745779{
@@ -790,6 +824,7 @@ static int vc4_hdmi_connector_init(struct drm_device *dev,
790824 }
791825
792826 vc4_hdmi_attach_broadcast_rgb_property (dev , vc4_hdmi );
827+ vc4_hdmi_attach_output_format_property (dev , vc4_hdmi );
793828
794829 drm_connector_attach_encoder (connector , encoder );
795830
@@ -1960,6 +1995,10 @@ static void vc4_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder,
19601995 & crtc_state -> adjusted_mode );
19611996 vc4_hdmi -> output_bpc = vc4_state -> output_bpc ;
19621997 vc4_hdmi -> output_format = vc4_state -> output_format ;
1998+ vc4_hdmi -> requested_output_format = vc4_state -> requested_output_format ;
1999+ memcpy (& vc4_hdmi -> saved_adjusted_mode ,
2000+ & crtc_state -> adjusted_mode ,
2001+ sizeof (vc4_hdmi -> saved_adjusted_mode ));
19632002 mutex_unlock (& vc4_hdmi -> mutex );
19642003}
19652004
@@ -2118,6 +2157,26 @@ vc4_hdmi_encoder_compute_format(const struct vc4_hdmi *vc4_hdmi,
21182157 const struct drm_display_info * info = & connector -> display_info ;
21192158 unsigned int format ;
21202159
2160+ if (vc4_state -> requested_output_format != VC4_HDMI_OUTPUT_AUTO ) {
2161+ drm_dbg (dev , "Trying with user requested output %u\n" ,
2162+ vc4_state -> requested_output_format );
2163+
2164+ format = vc4_state -> requested_output_format ;
2165+ if (vc4_hdmi_sink_supports_format_bpc (vc4_hdmi , info , mode ,
2166+ format , bpc )) {
2167+ int ret ;
2168+
2169+ ret = vc4_hdmi_encoder_compute_clock (vc4_hdmi , vc4_state ,
2170+ mode , bpc , format );
2171+ if (!ret ) {
2172+ vc4_state -> output_format = format ;
2173+ return 0 ;
2174+ }
2175+ }
2176+
2177+ return - EINVAL ;
2178+ }
2179+
21212180 drm_dbg (dev , "Trying with an RGB output\n" );
21222181
21232182 format = VC4_HDMI_OUTPUT_RGB ;
0 commit comments