Skip to content

Commit

Permalink
drm/vc4: Make VEC progressive modes readily accessible
Browse files Browse the repository at this point in the history
Add predefined modelines for the 240p (NTSC) and 288p (PAL) progressive
modes, and report them through vc4_vec_connector_get_modes().

Signed-off-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
  • Loading branch information
Mateusz Kwiatkowski committed Oct 3, 2021
1 parent f52a0ed commit 63c8194
Showing 1 changed file with 55 additions and 18 deletions.
73 changes: 55 additions & 18 deletions drivers/gpu/drm/vc4/vc4_vec.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,8 @@ enum vc4_vec_tv_mode_id {
};

struct vc4_vec_tv_mode {
const struct drm_display_mode *mode;
const struct drm_display_mode *interlaced_mode;
const struct drm_display_mode *progressive_mode;
u32 config0;
u32 config1;
u32 custom_freq;
Expand Down Expand Up @@ -285,61 +286,81 @@ static const struct debugfs_reg32 vec_regs[] = {
};

static const struct drm_display_mode drm_mode_480i = {
DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 13500,
DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 13500,
720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0,
480, 480 + 7, 480 + 7 + 6, 525, 0,
DRM_MODE_FLAG_INTERLACE)
};

static const struct drm_display_mode drm_mode_240p = {
DRM_MODE("720x240", DRM_MODE_TYPE_DRIVER, 13500,
720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0,
240, 240 + 3, 240 + 3 + 3, 262, 0, 0)
};

static const struct drm_display_mode drm_mode_576i = {
DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 13500,
DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 13500,
720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0,
576, 576 + 4, 576 + 4 + 6, 625, 0,
DRM_MODE_FLAG_INTERLACE)
};

static const struct drm_display_mode drm_mode_288p = {
DRM_MODE("720x288", DRM_MODE_TYPE_DRIVER, 13500,
720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0,
288, 288 + 2, 288 + 2 + 3, 312, 0, 0)
};

static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
[VC4_VEC_TV_MODE_NTSC] = {
.mode = &drm_mode_480i,
.interlaced_mode = &drm_mode_480i,
.progressive_mode = &drm_mode_240p,
.config0 = VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
[VC4_VEC_TV_MODE_NTSC_J] = {
.mode = &drm_mode_480i,
.interlaced_mode = &drm_mode_480i,
.progressive_mode = &drm_mode_240p,
.config0 = VEC_CONFIG0_NTSC_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
[VC4_VEC_TV_MODE_NTSC_443] = {
/* NTSC with PAL chroma frequency */
.mode = &drm_mode_480i,
.interlaced_mode = &drm_mode_480i,
.progressive_mode = &drm_mode_240p,
.config0 = VEC_CONFIG0_NTSC_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ,
.custom_freq = 0x2a098acb,
},
[VC4_VEC_TV_MODE_PAL] = {
.mode = &drm_mode_576i,
.interlaced_mode = &drm_mode_576i,
.progressive_mode = &drm_mode_288p,
.config0 = VEC_CONFIG0_PAL_BDGHI_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
[VC4_VEC_TV_MODE_PAL_M] = {
.mode = &drm_mode_480i,
.interlaced_mode = &drm_mode_480i,
.progressive_mode = &drm_mode_240p,
.config0 = VEC_CONFIG0_PAL_M_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
[VC4_VEC_TV_MODE_PAL_N] = {
.mode = &drm_mode_576i,
.interlaced_mode = &drm_mode_576i,
.progressive_mode = &drm_mode_288p,
.config0 = VEC_CONFIG0_PAL_N_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
[VC4_VEC_TV_MODE_PAL60] = {
/* PAL-M with chroma frequency of regular PAL */
.mode = &drm_mode_480i,
.interlaced_mode = &drm_mode_480i,
.progressive_mode = &drm_mode_240p,
.config0 = VEC_CONFIG0_PAL_M_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ,
.custom_freq = 0x2a098acb,
},
[VC4_VEC_TV_MODE_SECAM] = {
.mode = &drm_mode_576i,
.interlaced_mode = &drm_mode_576i,
.progressive_mode = &drm_mode_288p,
.config0 = VEC_CONFIG0_SECAM_STD,
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
.custom_freq = 0x29c71c72,
Expand Down Expand Up @@ -399,16 +420,32 @@ static void vc4_vec_connector_destroy(struct drm_connector *connector)
static int vc4_vec_connector_get_modes(struct drm_connector *connector)
{
struct drm_connector_state *state = connector->state;
struct drm_display_mode *mode;

mode = drm_mode_duplicate(connector->dev,
vc4_vec_tv_modes[state->tv.mode].mode);
if (!mode) {
struct drm_display_mode *interlaced_mode, *progressive_mode;

interlaced_mode =
drm_mode_duplicate(connector->dev,
vc4_vec_tv_modes[state->tv.mode].interlaced_mode);
progressive_mode =
drm_mode_duplicate(connector->dev,
vc4_vec_tv_modes[state->tv.mode].progressive_mode);
if (!interlaced_mode || !progressive_mode) {
DRM_ERROR("Failed to create a new display mode\n");
drm_mode_destroy(connector->dev, interlaced_mode);
drm_mode_destroy(connector->dev, progressive_mode);
return -ENOMEM;
}

drm_mode_probed_add(connector, mode);
if (connector->cmdline_mode.specified &&
connector->cmdline_mode.refresh_specified &&
!connector->cmdline_mode.interlace)
/* progressive mode set at boot, let's make it preferred */
progressive_mode->type |= DRM_MODE_TYPE_PREFERRED;
else
/* otherwise, interlaced mode is preferred */
interlaced_mode->type |= DRM_MODE_TYPE_PREFERRED;

drm_mode_probed_add(connector, interlaced_mode);
drm_mode_probed_add(connector, progressive_mode);

return 1;
}
Expand All @@ -434,7 +471,7 @@ static int vc4_vec_connector_atomic_check(struct drm_connector *conn,
drm_atomic_get_new_crtc_state(state, new_state->crtc);

if (crtc_state->mode.htotal !=
vc4_vec_tv_modes[new_state->tv.mode].mode->htotal ||
vc4_vec_tv_modes[new_state->tv.mode].interlaced_mode->htotal ||
crtc_state->mode.hdisplay % 4 != 0 ||
crtc_state->mode.hsync_end -
crtc_state->mode.hsync_start < 1)
Expand Down

0 comments on commit 63c8194

Please sign in to comment.