@@ -539,7 +539,10 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder)
539539 VEC_WRITE (VEC_CLMP0_START , 0xac );
540540 VEC_WRITE (VEC_CLMP0_END , 0xec );
541541 VEC_WRITE (VEC_CONFIG2 ,
542- VEC_CONFIG2_UV_DIG_DIS | VEC_CONFIG2_RGB_DIG_DIS );
542+ VEC_CONFIG2_UV_DIG_DIS |
543+ VEC_CONFIG2_RGB_DIG_DIS |
544+ ((encoder -> crtc -> state -> adjusted_mode .flags &
545+ DRM_MODE_FLAG_INTERLACE ) ? 0 : VEC_CONFIG2_PROG_SCAN ));
543546 VEC_WRITE (VEC_CONFIG3 , VEC_CONFIG3_HORIZ_LEN_STD );
544547 VEC_WRITE (VEC_DAC_CONFIG , vec -> variant -> dac_config );
545548
@@ -573,13 +576,77 @@ static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder,
573576 struct drm_crtc_state * crtc_state ,
574577 struct drm_connector_state * conn_state )
575578{
576- const struct vc4_vec_tv_mode * vec_mode ;
577-
578- vec_mode = & vc4_vec_tv_modes [conn_state -> tv .mode ];
579-
580- if (conn_state -> crtc &&
581- !drm_mode_equal (vec_mode -> mode , & crtc_state -> adjusted_mode ))
582- return - EINVAL ;
579+ if (conn_state -> crtc ) {
580+ if (crtc_state -> adjusted_mode .htotal !=
581+ vc4_vec_tv_modes [conn_state -> tv .mode ].mode -> htotal ||
582+ crtc_state -> adjusted_mode .hdisplay % 4 != 0 ||
583+ crtc_state -> adjusted_mode .hsync_end -
584+ crtc_state -> adjusted_mode .hsync_start < 1 )
585+ return - EINVAL ;
586+
587+ switch (crtc_state -> adjusted_mode .htotal ) {
588+ case 858 :
589+ /* 525-line mode */
590+ if (crtc_state -> adjusted_mode .crtc_vdisplay < 1 ||
591+ crtc_state -> adjusted_mode .crtc_vdisplay > 253 ||
592+ crtc_state -> adjusted_mode .crtc_vsync_start -
593+ crtc_state -> adjusted_mode .crtc_vdisplay < 1 ||
594+ crtc_state -> adjusted_mode .crtc_vsync_end -
595+ crtc_state -> adjusted_mode .crtc_vsync_start != 3 ||
596+ crtc_state -> adjusted_mode .crtc_vtotal -
597+ crtc_state -> adjusted_mode .crtc_vsync_end < 4 ||
598+ crtc_state -> adjusted_mode .crtc_vtotal > 262 )
599+ return - EINVAL ;
600+
601+ if ((crtc_state -> adjusted_mode .flags &
602+ DRM_MODE_FLAG_INTERLACE ) &&
603+ (crtc_state -> adjusted_mode .vdisplay % 2 != 0 ||
604+ crtc_state -> adjusted_mode .vsync_start % 2 != 1 ||
605+ crtc_state -> adjusted_mode .vsync_end % 2 != 1 ||
606+ crtc_state -> adjusted_mode .vtotal % 2 != 1 ))
607+ return - EINVAL ;
608+
609+ /* progressive mode is hard-wired to 262 total lines */
610+ if (!(crtc_state -> adjusted_mode .flags &
611+ DRM_MODE_FLAG_INTERLACE ) &&
612+ crtc_state -> adjusted_mode .vtotal != 262 )
613+ return - EINVAL ;
614+
615+ break ;
616+
617+ case 864 :
618+ /* 625-line mode */
619+ if (crtc_state -> adjusted_mode .crtc_vdisplay < 1 ||
620+ crtc_state -> adjusted_mode .crtc_vdisplay > 305 ||
621+ crtc_state -> adjusted_mode .crtc_vsync_start -
622+ crtc_state -> adjusted_mode .crtc_vdisplay < 1 ||
623+ crtc_state -> adjusted_mode .crtc_vsync_end -
624+ crtc_state -> adjusted_mode .crtc_vsync_start != 3 ||
625+ crtc_state -> adjusted_mode .crtc_vtotal -
626+ crtc_state -> adjusted_mode .crtc_vsync_end < 2 ||
627+ crtc_state -> adjusted_mode .crtc_vtotal > 312 )
628+ return - EINVAL ;
629+
630+ if ((crtc_state -> adjusted_mode .flags &
631+ DRM_MODE_FLAG_INTERLACE ) &&
632+ (crtc_state -> adjusted_mode .vdisplay % 2 != 0 ||
633+ crtc_state -> adjusted_mode .vsync_start % 2 != 0 ||
634+ crtc_state -> adjusted_mode .vsync_end % 2 != 0 ||
635+ crtc_state -> adjusted_mode .vtotal % 2 != 1 ))
636+ return - EINVAL ;
637+
638+ /* progressive mode is hard-wired to 312 total lines */
639+ if (!(crtc_state -> adjusted_mode .flags &
640+ DRM_MODE_FLAG_INTERLACE ) &&
641+ crtc_state -> adjusted_mode .vtotal != 312 )
642+ return - EINVAL ;
643+
644+ break ;
645+
646+ default :
647+ return - EINVAL ;
648+ }
649+ }
583650
584651 return 0 ;
585652}
0 commit comments