Skip to content

Commit 96922af

Browse files
Mateusz Kwiatkowskipopcornmix
authored andcommitted
drm/vc4: Allow setting the TV norm via module parameter
Similar to the ch7006 and nouveau drivers, introduce a "tv_mode" module parameter that allow setting the TV norm by specifying vc4.tv_norm= on the kernel command line. If that is not specified, try inferring one of the most popular norms (PAL or NTSC) from the video mode specified on the command line. On Raspberry Pis, this causes the most common cases of the sdtv_mode setting in config.txt to be respected. Signed-off-by: Mateusz Kwiatkowski <[email protected]>
1 parent 79a0b89 commit 96922af

File tree

1 file changed

+81
-27
lines changed

1 file changed

+81
-27
lines changed

drivers/gpu/drm/vc4/vc4_vec.c

Lines changed: 81 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
#define VEC_CONFIG0_YCDELAY BIT(4)
6868
#define VEC_CONFIG0_RAMPEN BIT(2)
6969
#define VEC_CONFIG0_YCDIS BIT(2)
70-
#define VEC_CONFIG0_STD_MASK GENMASK(1, 0)
70+
#define VEC_CONFIG0_STD_MASK (VEC_CONFIG0_SECAM_STD | GENMASK(1, 0))
7171
#define VEC_CONFIG0_NTSC_STD 0
7272
#define VEC_CONFIG0_PAL_BDGHI_STD 1
7373
#define VEC_CONFIG0_PAL_M_STD 2
@@ -186,6 +186,8 @@
186186
#define VEC_DAC_MISC_DAC_RST_N BIT(0)
187187

188188

189+
static char *vc4_vec_tv_norm;
190+
189191
struct vc4_vec_variant {
190192
u32 dac_config;
191193
};
@@ -353,6 +355,33 @@ static const struct drm_prop_enum_list legacy_tv_mode_names[] = {
353355
{ VC4_VEC_TV_MODE_SECAM, "SECAM", },
354356
};
355357

358+
enum drm_connector_tv_mode
359+
vc4_vec_get_default_mode(struct drm_connector *connector)
360+
{
361+
if (vc4_vec_tv_norm) {
362+
int ret;
363+
364+
ret = drm_get_tv_mode_from_name(vc4_vec_tv_norm, strlen(vc4_vec_tv_norm));
365+
if (ret >= 0)
366+
return ret;
367+
} else if (connector->cmdline_mode.specified &&
368+
((connector->cmdline_mode.refresh_specified &&
369+
(connector->cmdline_mode.refresh == 25 ||
370+
connector->cmdline_mode.refresh == 50)) ||
371+
(!connector->cmdline_mode.refresh_specified &&
372+
(connector->cmdline_mode.yres == 288 ||
373+
connector->cmdline_mode.yres == 576)))) {
374+
/*
375+
* no explicitly specified TV norm; use PAL if a mode that
376+
* looks like PAL has been specified on the command line
377+
*/
378+
return DRM_MODE_TV_MODE_PAL;
379+
}
380+
381+
/* in all other cases, default to NTSC */
382+
return DRM_MODE_TV_MODE_NTSC;
383+
}
384+
356385
static enum drm_connector_status
357386
vc4_vec_connector_detect(struct drm_connector *connector, bool force)
358387
{
@@ -363,6 +392,10 @@ static void vc4_vec_connector_reset(struct drm_connector *connector)
363392
{
364393
drm_atomic_helper_connector_reset(connector);
365394
drm_atomic_helper_connector_tv_reset(connector);
395+
396+
/* preserve TV standard */
397+
if (connector->state)
398+
connector->state->tv.mode = vc4_vec_get_default_mode(connector);
366399
}
367400

368401
static int
@@ -414,48 +447,52 @@ vc4_vec_connector_set_property(struct drm_connector *connector,
414447
}
415448

416449
static int
417-
vc4_vec_connector_get_property(struct drm_connector *connector,
418-
const struct drm_connector_state *state,
419-
struct drm_property *property,
420-
uint64_t *val)
450+
vc4_vec_generic_tv_mode_to_legacy(enum drm_connector_tv_mode tv_mode)
421451
{
422-
struct vc4_vec *vec = connector_to_vc4_vec(connector);
423-
424-
if (property != vec->legacy_tv_mode_property)
425-
return -EINVAL;
426-
427-
switch (state->tv.mode) {
452+
switch (tv_mode) {
428453
case DRM_MODE_TV_MODE_NTSC:
429-
*val = VC4_VEC_TV_MODE_NTSC;
430-
break;
454+
return VC4_VEC_TV_MODE_NTSC;
431455

432456
case DRM_MODE_TV_MODE_NTSC_443:
433-
*val = VC4_VEC_TV_MODE_NTSC_443;
434-
break;
457+
return VC4_VEC_TV_MODE_NTSC_443;
435458

436459
case DRM_MODE_TV_MODE_NTSC_J:
437-
*val = VC4_VEC_TV_MODE_NTSC_J;
438-
break;
460+
return VC4_VEC_TV_MODE_NTSC_J;
439461

440462
case DRM_MODE_TV_MODE_PAL:
441-
*val = VC4_VEC_TV_MODE_PAL;
442-
break;
463+
return VC4_VEC_TV_MODE_PAL;
443464

444465
case DRM_MODE_TV_MODE_PAL_M:
445-
*val = VC4_VEC_TV_MODE_PAL_M;
446-
break;
466+
return VC4_VEC_TV_MODE_PAL_M;
447467

448468
case DRM_MODE_TV_MODE_PAL_N:
449-
*val = VC4_VEC_TV_MODE_PAL_N;
450-
break;
469+
return VC4_VEC_TV_MODE_PAL_N;
451470

452471
case DRM_MODE_TV_MODE_SECAM:
453-
*val = VC4_VEC_TV_MODE_SECAM;
454-
break;
472+
return VC4_VEC_TV_MODE_SECAM;
455473

456474
default:
457475
return -EINVAL;
458476
}
477+
}
478+
479+
static int
480+
vc4_vec_connector_get_property(struct drm_connector *connector,
481+
const struct drm_connector_state *state,
482+
struct drm_property *property,
483+
uint64_t *val)
484+
{
485+
struct vc4_vec *vec = connector_to_vc4_vec(connector);
486+
enum vc4_vec_tv_mode_id legacy_mode;
487+
488+
if (property != vec->legacy_tv_mode_property)
489+
return -EINVAL;
490+
491+
legacy_mode = vc4_vec_generic_tv_mode_to_legacy(state->tv.mode);
492+
if (legacy_mode < 0)
493+
return legacy_mode;
494+
495+
*val = legacy_mode;
459496

460497
return 0;
461498
}
@@ -478,6 +515,8 @@ static const struct drm_connector_helper_funcs vc4_vec_connector_helper_funcs =
478515
static int vc4_vec_connector_init(struct drm_device *dev, struct vc4_vec *vec)
479516
{
480517
struct drm_connector *connector = &vec->connector;
518+
enum vc4_vec_tv_mode_id legacy_default_mode;
519+
enum drm_connector_tv_mode default_mode;
481520
struct drm_property *prop;
482521
int ret;
483522

@@ -490,9 +529,17 @@ static int vc4_vec_connector_init(struct drm_device *dev, struct vc4_vec *vec)
490529

491530
drm_connector_helper_add(connector, &vc4_vec_connector_helper_funcs);
492531

532+
default_mode = vc4_vec_get_default_mode(connector);
533+
if (default_mode < 0)
534+
return default_mode;
535+
493536
drm_object_attach_property(&connector->base,
494537
dev->mode_config.tv_mode_property,
495-
DRM_MODE_TV_MODE_NTSC);
538+
default_mode);
539+
540+
legacy_default_mode = vc4_vec_generic_tv_mode_to_legacy(default_mode);
541+
if (legacy_default_mode < 0)
542+
return legacy_default_mode;
496543

497544
prop = drm_property_create_enum(dev, 0, "mode",
498545
legacy_tv_mode_names,
@@ -501,7 +548,7 @@ static int vc4_vec_connector_init(struct drm_device *dev, struct vc4_vec *vec)
501548
return -ENOMEM;
502549
vec->legacy_tv_mode_property = prop;
503550

504-
drm_object_attach_property(&connector->base, prop, VC4_VEC_TV_MODE_NTSC);
551+
drm_object_attach_property(&connector->base, prop, legacy_default_mode);
505552

506553
drm_connector_attach_encoder(connector, &vec->encoder.base);
507554

@@ -825,3 +872,10 @@ struct platform_driver vc4_vec_driver = {
825872
.of_match_table = vc4_vec_dt_match,
826873
},
827874
};
875+
876+
module_param_named(tv_norm, vc4_vec_tv_norm, charp, 0600);
877+
MODULE_PARM_DESC(tv_norm, "Default TV norm.\n"
878+
"\t\tSupported: NTSC, NTSC-J, NTSC-443, PAL, PAL-M, PAL-N,\n"
879+
"\t\t\tPAL60, SECAM.\n"
880+
"\t\tDefault: PAL if a 50 Hz mode has been set via video=,\n"
881+
"\t\t\tNTSC otherwise");

0 commit comments

Comments
 (0)