1 From bfd6f67af0450e29378d390386210ac91c5dcfce Mon Sep 17 00:00:00 2001
2 From: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
3 Date: Thu, 15 Jul 2021 01:08:11 +0200
4 Subject: [PATCH] drm/vc4: Make VEC progressive modes readily
7 Add predefined modelines for the 240p (NTSC) and 288p (PAL) progressive
8 modes, and report them through vc4_vec_connector_get_modes().
10 Signed-off-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
12 drivers/gpu/drm/vc4/vc4_vec.c | 73 ++++++++++++++++++++++++++---------
13 1 file changed, 55 insertions(+), 18 deletions(-)
15 --- a/drivers/gpu/drm/vc4/vc4_vec.c
16 +++ b/drivers/gpu/drm/vc4/vc4_vec.c
17 @@ -228,7 +228,8 @@ enum vc4_vec_tv_mode_id {
20 struct vc4_vec_tv_mode {
21 - const struct drm_display_mode *mode;
22 + const struct drm_display_mode *interlaced_mode;
23 + const struct drm_display_mode *progressive_mode;
27 @@ -262,61 +263,81 @@ static const struct debugfs_reg32 vec_re
30 static const struct drm_display_mode drm_mode_480i = {
31 - DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 13500,
32 + DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 13500,
33 720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0,
34 480, 480 + 7, 480 + 7 + 6, 525, 0,
35 DRM_MODE_FLAG_INTERLACE)
38 +static const struct drm_display_mode drm_mode_240p = {
39 + DRM_MODE("720x240", DRM_MODE_TYPE_DRIVER, 13500,
40 + 720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0,
41 + 240, 240 + 3, 240 + 3 + 3, 262, 0, 0)
44 static const struct drm_display_mode drm_mode_576i = {
45 - DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 13500,
46 + DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 13500,
47 720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0,
48 576, 576 + 4, 576 + 4 + 6, 625, 0,
49 DRM_MODE_FLAG_INTERLACE)
52 +static const struct drm_display_mode drm_mode_288p = {
53 + DRM_MODE("720x288", DRM_MODE_TYPE_DRIVER, 13500,
54 + 720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0,
55 + 288, 288 + 2, 288 + 2 + 3, 312, 0, 0)
58 static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
59 [VC4_VEC_TV_MODE_NTSC] = {
60 - .mode = &drm_mode_480i,
61 + .interlaced_mode = &drm_mode_480i,
62 + .progressive_mode = &drm_mode_240p,
63 .config0 = VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN,
64 .config1 = VEC_CONFIG1_C_CVBS_CVBS,
66 [VC4_VEC_TV_MODE_NTSC_J] = {
67 - .mode = &drm_mode_480i,
68 + .interlaced_mode = &drm_mode_480i,
69 + .progressive_mode = &drm_mode_240p,
70 .config0 = VEC_CONFIG0_NTSC_STD,
71 .config1 = VEC_CONFIG1_C_CVBS_CVBS,
73 [VC4_VEC_TV_MODE_NTSC_443] = {
74 /* NTSC with PAL chroma frequency */
75 - .mode = &drm_mode_480i,
76 + .interlaced_mode = &drm_mode_480i,
77 + .progressive_mode = &drm_mode_240p,
78 .config0 = VEC_CONFIG0_NTSC_STD,
79 .config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ,
80 .custom_freq = 0x2a098acb,
82 [VC4_VEC_TV_MODE_PAL] = {
83 - .mode = &drm_mode_576i,
84 + .interlaced_mode = &drm_mode_576i,
85 + .progressive_mode = &drm_mode_288p,
86 .config0 = VEC_CONFIG0_PAL_BDGHI_STD,
87 .config1 = VEC_CONFIG1_C_CVBS_CVBS,
89 [VC4_VEC_TV_MODE_PAL_M] = {
90 - .mode = &drm_mode_480i,
91 + .interlaced_mode = &drm_mode_480i,
92 + .progressive_mode = &drm_mode_240p,
93 .config0 = VEC_CONFIG0_PAL_M_STD,
94 .config1 = VEC_CONFIG1_C_CVBS_CVBS,
96 [VC4_VEC_TV_MODE_PAL_N] = {
97 - .mode = &drm_mode_576i,
98 + .interlaced_mode = &drm_mode_576i,
99 + .progressive_mode = &drm_mode_288p,
100 .config0 = VEC_CONFIG0_PAL_N_STD,
101 .config1 = VEC_CONFIG1_C_CVBS_CVBS,
103 [VC4_VEC_TV_MODE_PAL60] = {
104 /* PAL-M with chroma frequency of regular PAL */
105 - .mode = &drm_mode_480i,
106 + .interlaced_mode = &drm_mode_480i,
107 + .progressive_mode = &drm_mode_240p,
108 .config0 = VEC_CONFIG0_PAL_M_STD,
109 .config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ,
110 .custom_freq = 0x2a098acb,
112 [VC4_VEC_TV_MODE_SECAM] = {
113 - .mode = &drm_mode_576i,
114 + .interlaced_mode = &drm_mode_576i,
115 + .progressive_mode = &drm_mode_288p,
116 .config0 = VEC_CONFIG0_SECAM_STD,
117 .config1 = VEC_CONFIG1_C_CVBS_CVBS,
118 .custom_freq = 0x29c71c72,
119 @@ -370,16 +391,32 @@ vc4_vec_connector_detect(struct drm_conn
120 static int vc4_vec_connector_get_modes(struct drm_connector *connector)
122 struct drm_connector_state *state = connector->state;
123 - struct drm_display_mode *mode;
124 + struct drm_display_mode *interlaced_mode, *progressive_mode;
126 - mode = drm_mode_duplicate(connector->dev,
127 - vc4_vec_tv_modes[state->tv.mode].mode);
130 + drm_mode_duplicate(connector->dev,
131 + vc4_vec_tv_modes[state->tv.mode].interlaced_mode);
133 + drm_mode_duplicate(connector->dev,
134 + vc4_vec_tv_modes[state->tv.mode].progressive_mode);
135 + if (!interlaced_mode || !progressive_mode) {
136 DRM_ERROR("Failed to create a new display mode\n");
137 + drm_mode_destroy(connector->dev, interlaced_mode);
138 + drm_mode_destroy(connector->dev, progressive_mode);
142 - drm_mode_probed_add(connector, mode);
143 + if (connector->cmdline_mode.specified &&
144 + connector->cmdline_mode.refresh_specified &&
145 + !connector->cmdline_mode.interlace)
146 + /* progressive mode set at boot, let's make it preferred */
147 + progressive_mode->type |= DRM_MODE_TYPE_PREFERRED;
149 + /* otherwise, interlaced mode is preferred */
150 + interlaced_mode->type |= DRM_MODE_TYPE_PREFERRED;
152 + drm_mode_probed_add(connector, interlaced_mode);
153 + drm_mode_probed_add(connector, progressive_mode);
157 @@ -576,7 +613,7 @@ static int vc4_vec_encoder_atomic_check(
158 struct drm_connector_state *conn_state)
160 const struct drm_display_mode *reference_mode =
161 - vc4_vec_tv_modes[conn_state->tv.mode].mode;
162 + vc4_vec_tv_modes[conn_state->tv.mode].interlaced_mode;
164 if (crtc_state->adjusted_mode.crtc_clock != reference_mode->clock ||
165 crtc_state->adjusted_mode.crtc_htotal != reference_mode->htotal ||