@@ -251,7 +251,8 @@ enum vc4_vec_tv_mode_id {
251251};
252252
253253struct vc4_vec_tv_mode {
254- const struct drm_display_mode * mode ;
254+ const struct drm_display_mode * interlaced_mode ;
255+ const struct drm_display_mode * progressive_mode ;
255256 u32 config0 ;
256257 u32 config1 ;
257258 u32 custom_freq ;
@@ -285,61 +286,81 @@ static const struct debugfs_reg32 vec_regs[] = {
285286};
286287
287288static const struct drm_display_mode drm_mode_480i = {
288- DRM_MODE ("720x480 " , DRM_MODE_TYPE_DRIVER , 13500 ,
289+ DRM_MODE ("720x480i " , DRM_MODE_TYPE_DRIVER , 13500 ,
289290 720 , 720 + 14 , 720 + 14 + 64 , 720 + 14 + 64 + 60 , 0 ,
290291 480 , 480 + 7 , 480 + 7 + 6 , 525 , 0 ,
291292 DRM_MODE_FLAG_INTERLACE )
292293};
293294
295+ static const struct drm_display_mode drm_mode_240p = {
296+ DRM_MODE ("720x240" , DRM_MODE_TYPE_DRIVER , 13500 ,
297+ 720 , 720 + 14 , 720 + 14 + 64 , 720 + 14 + 64 + 60 , 0 ,
298+ 240 , 240 + 3 , 240 + 3 + 3 , 262 , 0 , 0 )
299+ };
300+
294301static const struct drm_display_mode drm_mode_576i = {
295- DRM_MODE ("720x576 " , DRM_MODE_TYPE_DRIVER , 13500 ,
302+ DRM_MODE ("720x576i " , DRM_MODE_TYPE_DRIVER , 13500 ,
296303 720 , 720 + 20 , 720 + 20 + 64 , 720 + 20 + 64 + 60 , 0 ,
297304 576 , 576 + 4 , 576 + 4 + 6 , 625 , 0 ,
298305 DRM_MODE_FLAG_INTERLACE )
299306};
300307
308+ static const struct drm_display_mode drm_mode_288p = {
309+ DRM_MODE ("720x288" , DRM_MODE_TYPE_DRIVER , 13500 ,
310+ 720 , 720 + 20 , 720 + 20 + 64 , 720 + 20 + 64 + 60 , 0 ,
311+ 288 , 288 + 2 , 288 + 2 + 3 , 312 , 0 , 0 )
312+ };
313+
301314static const struct vc4_vec_tv_mode vc4_vec_tv_modes [] = {
302315 [VC4_VEC_TV_MODE_NTSC ] = {
303- .mode = & drm_mode_480i ,
316+ .interlaced_mode = & drm_mode_480i ,
317+ .progressive_mode = & drm_mode_240p ,
304318 .config0 = VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN ,
305319 .config1 = VEC_CONFIG1_C_CVBS_CVBS ,
306320 },
307321 [VC4_VEC_TV_MODE_NTSC_J ] = {
308- .mode = & drm_mode_480i ,
322+ .interlaced_mode = & drm_mode_480i ,
323+ .progressive_mode = & drm_mode_240p ,
309324 .config0 = VEC_CONFIG0_NTSC_STD ,
310325 .config1 = VEC_CONFIG1_C_CVBS_CVBS ,
311326 },
312327 [VC4_VEC_TV_MODE_NTSC_443 ] = {
313328 /* NTSC with PAL chroma frequency */
314- .mode = & drm_mode_480i ,
329+ .interlaced_mode = & drm_mode_480i ,
330+ .progressive_mode = & drm_mode_240p ,
315331 .config0 = VEC_CONFIG0_NTSC_STD ,
316332 .config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ ,
317333 .custom_freq = 0x2a098acb ,
318334 },
319335 [VC4_VEC_TV_MODE_PAL ] = {
320- .mode = & drm_mode_576i ,
336+ .interlaced_mode = & drm_mode_576i ,
337+ .progressive_mode = & drm_mode_288p ,
321338 .config0 = VEC_CONFIG0_PAL_BDGHI_STD ,
322339 .config1 = VEC_CONFIG1_C_CVBS_CVBS ,
323340 },
324341 [VC4_VEC_TV_MODE_PAL_M ] = {
325- .mode = & drm_mode_480i ,
342+ .interlaced_mode = & drm_mode_480i ,
343+ .progressive_mode = & drm_mode_240p ,
326344 .config0 = VEC_CONFIG0_PAL_M_STD ,
327345 .config1 = VEC_CONFIG1_C_CVBS_CVBS ,
328346 },
329347 [VC4_VEC_TV_MODE_PAL_N ] = {
330- .mode = & drm_mode_576i ,
348+ .interlaced_mode = & drm_mode_576i ,
349+ .progressive_mode = & drm_mode_288p ,
331350 .config0 = VEC_CONFIG0_PAL_N_STD ,
332351 .config1 = VEC_CONFIG1_C_CVBS_CVBS ,
333352 },
334353 [VC4_VEC_TV_MODE_PAL60 ] = {
335354 /* PAL-M with chroma frequency of regular PAL */
336- .mode = & drm_mode_480i ,
355+ .interlaced_mode = & drm_mode_480i ,
356+ .progressive_mode = & drm_mode_240p ,
337357 .config0 = VEC_CONFIG0_PAL_M_STD ,
338358 .config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ ,
339359 .custom_freq = 0x2a098acb ,
340360 },
341361 [VC4_VEC_TV_MODE_SECAM ] = {
342- .mode = & drm_mode_576i ,
362+ .interlaced_mode = & drm_mode_576i ,
363+ .progressive_mode = & drm_mode_288p ,
343364 .config0 = VEC_CONFIG0_SECAM_STD ,
344365 .config1 = VEC_CONFIG1_C_CVBS_CVBS ,
345366 .custom_freq = 0x29c71c72 ,
@@ -399,16 +420,32 @@ static void vc4_vec_connector_destroy(struct drm_connector *connector)
399420static int vc4_vec_connector_get_modes (struct drm_connector * connector )
400421{
401422 struct drm_connector_state * state = connector -> state ;
402- struct drm_display_mode * mode ;
403-
404- mode = drm_mode_duplicate (connector -> dev ,
405- vc4_vec_tv_modes [state -> tv .mode ].mode );
406- if (!mode ) {
423+ struct drm_display_mode * interlaced_mode , * progressive_mode ;
424+
425+ interlaced_mode =
426+ drm_mode_duplicate (connector -> dev ,
427+ vc4_vec_tv_modes [state -> tv .mode ].interlaced_mode );
428+ progressive_mode =
429+ drm_mode_duplicate (connector -> dev ,
430+ vc4_vec_tv_modes [state -> tv .mode ].progressive_mode );
431+ if (!interlaced_mode || !progressive_mode ) {
407432 DRM_ERROR ("Failed to create a new display mode\n" );
433+ drm_mode_destroy (connector -> dev , interlaced_mode );
434+ drm_mode_destroy (connector -> dev , progressive_mode );
408435 return - ENOMEM ;
409436 }
410437
411- drm_mode_probed_add (connector , mode );
438+ if (connector -> cmdline_mode .specified &&
439+ connector -> cmdline_mode .refresh_specified &&
440+ !connector -> cmdline_mode .interlace )
441+ /* progressive mode set at boot, let's make it preferred */
442+ progressive_mode -> type |= DRM_MODE_TYPE_PREFERRED ;
443+ else
444+ /* otherwise, interlaced mode is preferred */
445+ interlaced_mode -> type |= DRM_MODE_TYPE_PREFERRED ;
446+
447+ drm_mode_probed_add (connector , interlaced_mode );
448+ drm_mode_probed_add (connector , progressive_mode );
412449
413450 return 1 ;
414451}
@@ -589,7 +626,7 @@ static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder,
589626 struct drm_connector_state * conn_state )
590627{
591628 const struct drm_display_mode * reference_mode =
592- vc4_vec_tv_modes [conn_state -> tv .mode ].mode ;
629+ vc4_vec_tv_modes [conn_state -> tv .mode ].interlaced_mode ;
593630
594631 if (crtc_state -> adjusted_mode .crtc_clock != reference_mode -> clock ||
595632 crtc_state -> adjusted_mode .crtc_htotal != reference_mode -> htotal ||
0 commit comments