4949#include "rp1_vec.h"
5050
5151/*
52- * Default TV standard parameter; it may be overridden by the OF
53- * property "tv_norm" (which should be one of the strings below).
54- *
55- * The default (empty string) supports various 60Hz and 50Hz modes,
56- * and will automatically select NTSC[-M] or PAL[-BDGHIKL]; the two
57- * "fake" 60Hz standards NTSC-443 and PAL60 also support 50Hz PAL.
58- * Other values will restrict the set of video modes offered.
59- *
60- * Finally, the DRM connector property "mode" (which is an integer)
61- * can be used to override this value, but it does not prevent the
62- * selection of an inapplicable video mode.
52+ * Default initial TV standard parameter; it may be overridden
53+ * by the command-line "video/tv_mode" option where specified.
54+ * It is used to initialize the connector's "tv_mode" property
55+ * and affects which video mode will be preferred.
6356 */
6457
6558static char * rp1vec_tv_norm_str ;
6659module_param_named (tv_norm , rp1vec_tv_norm_str , charp , 0600 );
6760MODULE_PARM_DESC (tv_norm , "Default TV norm.\n"
68- "\t\tSupported: NTSC, NTSC-J, NTSC-443, PAL, PAL-M, PAL-N,\n"
69- "\t\t\tPAL60.\n"
70- "\t\tDefault: empty string: infer PAL for a 50 Hz mode,\n"
71- "\t\t\tNTSC otherwise" );
72-
73- const char * const rp1vec_tvstd_names [] = {
74- [RP1VEC_TVSTD_NTSC ] = "NTSC" ,
75- [RP1VEC_TVSTD_NTSC_J ] = "NTSC-J" ,
76- [RP1VEC_TVSTD_NTSC_443 ] = "NTSC-443" ,
77- [RP1VEC_TVSTD_PAL ] = "PAL" ,
78- [RP1VEC_TVSTD_PAL_M ] = "PAL-M" ,
79- [RP1VEC_TVSTD_PAL_N ] = "PAL-N" ,
80- [RP1VEC_TVSTD_PAL60 ] = "PAL60" ,
81- [RP1VEC_TVSTD_DEFAULT ] = "" ,
82- };
83-
84- static int rp1vec_parse_tv_norm (const char * str )
85- {
86- int i ;
87-
88- if (str && * str ) {
89- for (i = 0 ; i < ARRAY_SIZE (rp1vec_tvstd_names ); ++ i ) {
90- if (strcasecmp (str , rp1vec_tvstd_names [i ]) == 0 )
91- return i ;
92- }
93- }
94- return RP1VEC_TVSTD_DEFAULT ;
95- }
61+ "\t\tSupported: NTSC, NTSC-J, NTSC-443, PAL, PAL-M, PAL-N\n"
62+ "\t\tDefault: NTSC (but 50Hz modes will default to PAL)" );
9663
9764static void rp1vec_pipe_update (struct drm_simple_display_pipe * pipe ,
9865 struct drm_plane_state * old_state )
@@ -143,7 +110,7 @@ static void rp1vec_pipe_update(struct drm_simple_display_pipe *pipe,
143110
144111static void rp1vec_pipe_enable (struct drm_simple_display_pipe * pipe ,
145112 struct drm_crtc_state * crtc_state ,
146- struct drm_plane_state * plane_state )
113+ struct drm_plane_state * plane_state )
147114{
148115 struct rp1_vec * vec = pipe -> crtc .dev -> dev_private ;
149116
@@ -231,36 +198,47 @@ static const struct drm_display_mode rp1vec_modes[4] = {
231198 }
232199};
233200
201+ /*
202+ * Advertise standard and preferred video modes.
203+ *
204+ * From each interlaced mode in the table above, derive a progressive one.
205+ *
206+ * This driver always support all 50Hz and 60Hz video modes, regardless
207+ * of tv_norm or connector->tv_mode; nonstandard combinations generally
208+ * default to PAL[-BDGHIKL] or NTSC[-M] depending on the video mode
209+ * (except that "PAL" with 525/60 will be implemented as "PAL60").
210+ */
211+
234212static int rp1vec_connector_get_modes (struct drm_connector * connector )
235213{
236214 struct rp1_vec * vec = container_of (connector , struct rp1_vec , connector );
237- bool ok525 = RP1VEC_TVSTD_SUPPORT_525 (vec -> tv_norm );
238- bool ok625 = RP1VEC_TVSTD_SUPPORT_625 (vec -> tv_norm );
215+ bool prefer625 =
216+ vec -> tv_norm == DRM_MODE_TV_MODE_PAL ||
217+ vec -> tv_norm == DRM_MODE_TV_MODE_PAL_N ||
218+ vec -> tv_norm == DRM_MODE_TV_MODE_SECAM ;
239219 int i , prog , n = 0 ;
240220
241221 for (i = 0 ; i < ARRAY_SIZE (rp1vec_modes ); i ++ ) {
242- if ((rp1vec_modes [i ].vtotal == 625 ) ? ok625 : ok525 ) {
243- for (prog = 0 ; prog < 2 ; prog ++ ) {
244- struct drm_display_mode * mode =
245- drm_mode_duplicate (connector -> dev ,
246- & rp1vec_modes [i ]);
247-
248- if (prog ) {
249- mode -> flags &= ~DRM_MODE_FLAG_INTERLACE ;
250- mode -> vdisplay >>= 1 ;
251- mode -> vsync_start >>= 1 ;
252- mode -> vsync_end >>= 1 ;
253- mode -> vtotal >>= 1 ;
254- }
255-
256- if (mode -> hdisplay == 704 &&
257- mode -> vtotal == ((ok525 ) ? 525 : 625 ))
258- mode -> type |= DRM_MODE_TYPE_PREFERRED ;
259-
260- drm_mode_set_name (mode );
261- drm_mode_probed_add (connector , mode );
262- n ++ ;
222+ for (prog = 0 ; prog < 2 ; prog ++ ) {
223+ struct drm_display_mode * mode =
224+ drm_mode_duplicate (connector -> dev ,
225+ & rp1vec_modes [i ]);
226+
227+ if (prog ) {
228+ mode -> flags &= ~DRM_MODE_FLAG_INTERLACE ;
229+ mode -> vdisplay >>= 1 ;
230+ mode -> vsync_start >>= 1 ;
231+ mode -> vsync_end >>= 1 ;
232+ mode -> vtotal >>= 1 ;
263233 }
234+
235+ if (mode -> hdisplay == 704 &&
236+ mode -> vtotal == (prefer625 ? 625 : 525 ))
237+ mode -> type |= DRM_MODE_TYPE_PREFERRED ;
238+
239+ drm_mode_set_name (mode );
240+ drm_mode_probed_add (connector , mode );
241+ n ++ ;
264242 }
265243 }
266244
@@ -396,7 +374,6 @@ static int rp1vec_platform_probe(struct platform_device *pdev)
396374 struct device * dev = & pdev -> dev ;
397375 struct drm_device * drm ;
398376 struct rp1_vec * vec ;
399- const char * str ;
400377 int i , ret ;
401378
402379 dev_info (dev , __func__ );
@@ -419,10 +396,6 @@ static int rp1vec_platform_probe(struct platform_device *pdev)
419396 drm -> dev_private = vec ;
420397 platform_set_drvdata (pdev , drm );
421398
422- str = rp1vec_tv_norm_str ;
423- of_property_read_string (dev -> of_node , "tv_norm" , & str );
424- vec -> tv_norm = rp1vec_parse_tv_norm (str );
425-
426399 for (i = 0 ; i < RP1VEC_NUM_HW_BLOCKS ; i ++ ) {
427400 vec -> hw_base [i ] =
428401 devm_ioremap_resource (dev ,
@@ -463,9 +436,7 @@ static int rp1vec_platform_probe(struct platform_device *pdev)
463436 drm -> mode_config .funcs = & rp1vec_mode_funcs ;
464437 drm_vblank_init (drm , 1 );
465438
466- ret = drm_mode_create_tv_properties_legacy (drm ,
467- ARRAY_SIZE (rp1vec_tvstd_names ),
468- rp1vec_tvstd_names );
439+ ret = drm_mode_create_tv_properties (drm , RP1VEC_SUPPORTED_TV_MODES );
469440 if (ret )
470441 goto err_free_drm ;
471442
@@ -477,6 +448,15 @@ static int rp1vec_platform_probe(struct platform_device *pdev)
477448 vec -> connector .interlace_allowed = true;
478449 drm_connector_helper_add (& vec -> connector , & rp1vec_connector_helper_funcs );
479450
451+ if (vec -> connector .cmdline_mode .tv_mode_specified ) {
452+ vec -> tv_norm = vec -> connector .cmdline_mode .tv_mode ;
453+ } else if (rp1vec_tv_norm_str ) {
454+ vec -> tv_norm = drm_get_tv_mode_from_name (rp1vec_tv_norm_str ,
455+ strlen (rp1vec_tv_norm_str ));
456+ if (vec -> tv_norm < 0 )
457+ vec -> tv_norm = DRM_MODE_TV_MODE_NTSC ;
458+ }
459+
480460 drm_object_attach_property (& vec -> connector .base ,
481461 drm -> mode_config .tv_mode_property ,
482462 vec -> tv_norm );
0 commit comments