brcm2708: update linux 4.4 patches to latest version
[oweals/openwrt.git] / target / linux / brcm2708 / patches-4.4 / 0520-drm-vc4-Fix-support-for-interlaced-modes-on-HDMI.patch
1 From 6e6624aeedaa97f1b81636e0be4a7478ccb22d69 Mon Sep 17 00:00:00 2001
2 From: Eric Anholt <eric@anholt.net>
3 Date: Wed, 28 Sep 2016 17:30:25 -0700
4 Subject: [PATCH] drm/vc4: Fix support for interlaced modes on HDMI.
5
6 We really do need to be using the halved V fields.  I had been
7 confused by the code I was using as a reference because it stored
8 halved vsync fields but not halved vdisplay, so it looked like I only
9 needed to divide vdisplay by 2.
10
11 This reverts part of Mario's timestamping fixes that prevented
12 CRTC_HALVE_V from applying, and instead adjusts the timestamping code
13 to not use the crtc field in that case.
14
15 Fixes locking of 1920x1080x60i on my Dell 2408WFP.  There are black
16 bars on the top and bottom, but I suspect that might be an
17 under/overscan flags problem as opposed to video timings.
18
19 Signed-off-by: Eric Anholt <eric@anholt.net>
20 ---
21  drivers/gpu/drm/vc4/vc4_crtc.c | 54 +++++++++++++++++++++++-------------------
22  drivers/gpu/drm/vc4/vc4_hdmi.c | 45 ++++++++++-------------------------
23  drivers/gpu/drm/vc4/vc4_regs.h |  3 +++
24  3 files changed, 44 insertions(+), 58 deletions(-)
25
26 --- a/drivers/gpu/drm/vc4/vc4_crtc.c
27 +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
28 @@ -220,7 +220,7 @@ int vc4_crtc_get_scanoutpos(struct drm_d
29          * and need to make things up in a approximative but consistent way.
30          */
31         ret |= DRM_SCANOUTPOS_IN_VBLANK;
32 -       vblank_lines = mode->crtc_vtotal - mode->crtc_vdisplay;
33 +       vblank_lines = mode->vtotal - mode->vdisplay;
34  
35         if (flags & DRM_CALLED_FROM_VBLIRQ) {
36                 /*
37 @@ -368,7 +368,6 @@ static void vc4_crtc_mode_set_nofb(struc
38         struct drm_crtc_state *state = crtc->state;
39         struct drm_display_mode *mode = &state->adjusted_mode;
40         bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
41 -       u32 vactive = (mode->vdisplay >> (interlace ? 1 : 0));
42         bool is_dsi = (vc4_encoder->type == VC4_ENCODER_TYPE_DSI0 ||
43                        vc4_encoder->type == VC4_ENCODER_TYPE_DSI1);
44         u32 format = is_dsi ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24;
45 @@ -395,34 +394,49 @@ static void vc4_crtc_mode_set_nofb(struc
46                    VC4_SET_FIELD(mode->hdisplay, PV_HORZB_HACTIVE));
47  
48         CRTC_WRITE(PV_VERTA,
49 -                  VC4_SET_FIELD(mode->vtotal - mode->vsync_end,
50 +                  VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end,
51                                  PV_VERTA_VBP) |
52 -                  VC4_SET_FIELD(mode->vsync_end - mode->vsync_start,
53 +                  VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start,
54                                  PV_VERTA_VSYNC));
55         CRTC_WRITE(PV_VERTB,
56 -                  VC4_SET_FIELD(mode->vsync_start - mode->vdisplay,
57 +                  VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay,
58                                  PV_VERTB_VFP) |
59 -                  VC4_SET_FIELD(vactive, PV_VERTB_VACTIVE));
60 +                  VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE));
61  
62         if (interlace) {
63                 CRTC_WRITE(PV_VERTA_EVEN,
64 -                          VC4_SET_FIELD(mode->vtotal - mode->vsync_end - 1,
65 +                          VC4_SET_FIELD(mode->crtc_vtotal -
66 +                                        mode->crtc_vsync_end - 1,
67                                          PV_VERTA_VBP) |
68 -                          VC4_SET_FIELD(mode->vsync_end - mode->vsync_start,
69 +                          VC4_SET_FIELD(mode->crtc_vsync_end -
70 +                                        mode->crtc_vsync_start,
71                                          PV_VERTA_VSYNC));
72                 CRTC_WRITE(PV_VERTB_EVEN,
73 -                          VC4_SET_FIELD(mode->vsync_start - mode->vdisplay,
74 +                          VC4_SET_FIELD(mode->crtc_vsync_start -
75 +                                        mode->crtc_vdisplay,
76                                          PV_VERTB_VFP) |
77 -                          VC4_SET_FIELD(vactive, PV_VERTB_VACTIVE));
78 +                          VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE));
79 +
80 +               /* We set up first field even mode for HDMI.  VEC's
81 +                * NTSC mode would want first field odd instead, once
82 +                * we support it (to do so, set ODD_FIRST and put the
83 +                * delay in VSYNCD_EVEN instead).
84 +                */
85 +               CRTC_WRITE(PV_V_CONTROL,
86 +                          PV_VCONTROL_CONTINUOUS |
87 +                          (is_dsi ? PV_VCONTROL_DSI : 0) |
88 +                          PV_VCONTROL_INTERLACE |
89 +                          VC4_SET_FIELD(mode->htotal / 2,
90 +                                        PV_VCONTROL_ODD_DELAY));
91 +               CRTC_WRITE(PV_VSYNCD_EVEN, 0);
92 +       } else {
93 +               CRTC_WRITE(PV_V_CONTROL,
94 +                          PV_VCONTROL_CONTINUOUS |
95 +                          (is_dsi ? PV_VCONTROL_DSI : 0));
96         }
97  
98         CRTC_WRITE(PV_HACT_ACT, mode->hdisplay);
99  
100 -       CRTC_WRITE(PV_V_CONTROL,
101 -                  PV_VCONTROL_CONTINUOUS |
102 -                  (is_dsi ? PV_VCONTROL_DSI : 0) |
103 -                  (interlace ? PV_VCONTROL_INTERLACE : 0));
104 -
105         CRTC_WRITE(PV_CONTROL,
106                    VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
107                    VC4_SET_FIELD(vc4_get_fifo_full_level(format),
108 @@ -550,16 +564,6 @@ static bool vc4_crtc_mode_fixup(struct d
109                 return false;
110         }
111  
112 -       /*
113 -        * Interlaced video modes got CRTC_INTERLACE_HALVE_V applied when
114 -        * coming from user space. We don't want this, as it screws up
115 -        * vblank timestamping, so fix it up.
116 -        */
117 -       drm_mode_set_crtcinfo(adjusted_mode, 0);
118 -
119 -       DRM_DEBUG_KMS("[CRTC:%d] adjusted_mode :\n", crtc->base.id);
120 -       drm_mode_debug_printmodeline(adjusted_mode);
121 -
122         return true;
123  }
124  
125 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
126 +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
127 @@ -219,35 +219,10 @@ vc4_hdmi_connector_best_encoder(struct d
128         return hdmi_connector->encoder;
129  }
130  
131 -/*
132 - * drm_helper_probe_single_connector_modes() applies drm_mode_set_crtcinfo to
133 - * all modes with flag CRTC_INTERLACE_HALVE_V. We don't want this, as it
134 - * screws up vblank timestamping for interlaced modes, so fix it up.
135 - */
136 -static int vc4_hdmi_connector_probe_modes(struct drm_connector *connector,
137 -                                         uint32_t maxX, uint32_t maxY)
138 -{
139 -       struct drm_display_mode *mode;
140 -       int count;
141 -
142 -       count = drm_helper_probe_single_connector_modes(connector, maxX, maxY);
143 -       if (count == 0)
144 -               return 0;
145 -
146 -       DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed adapted modes :\n",
147 -                     connector->base.id, connector->name);
148 -       list_for_each_entry(mode, &connector->modes, head) {
149 -               drm_mode_set_crtcinfo(mode, 0);
150 -               drm_mode_debug_printmodeline(mode);
151 -       }
152 -
153 -       return count;
154 -}
155 -
156  static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
157         .dpms = drm_atomic_helper_connector_dpms,
158         .detect = vc4_hdmi_connector_detect,
159 -       .fill_modes = vc4_hdmi_connector_probe_modes,
160 +       .fill_modes = drm_helper_probe_single_connector_modes,
161         .destroy = vc4_hdmi_connector_destroy,
162         .reset = drm_atomic_helper_connector_reset,
163         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
164 @@ -316,16 +291,20 @@ static void vc4_hdmi_encoder_mode_set(st
165         bool debug_dump_regs = false;
166         bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
167         bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
168 -       u32 vactive = (mode->vdisplay >>
169 -                      ((mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0));
170 -       u32 verta = (VC4_SET_FIELD(mode->vsync_end - mode->vsync_start,
171 +       bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
172 +       u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start,
173                                    VC4_HDMI_VERTA_VSP) |
174 -                    VC4_SET_FIELD(mode->vsync_start - mode->vdisplay,
175 +                    VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay,
176                                    VC4_HDMI_VERTA_VFP) |
177 -                    VC4_SET_FIELD(vactive, VC4_HDMI_VERTA_VAL));
178 +                    VC4_SET_FIELD(mode->crtc_vdisplay, VC4_HDMI_VERTA_VAL));
179         u32 vertb = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) |
180 -                    VC4_SET_FIELD(mode->vtotal - mode->vsync_end,
181 +                    VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end,
182                                    VC4_HDMI_VERTB_VBP));
183 +       u32 vertb_even = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) |
184 +                         VC4_SET_FIELD(mode->crtc_vtotal -
185 +                                       mode->crtc_vsync_end -
186 +                                       interlaced,
187 +                                       VC4_HDMI_VERTB_VBP));
188         u32 csc_ctl;
189  
190         if (debug_dump_regs) {
191 @@ -358,7 +337,7 @@ static void vc4_hdmi_encoder_mode_set(st
192         HDMI_WRITE(VC4_HDMI_VERTA0, verta);
193         HDMI_WRITE(VC4_HDMI_VERTA1, verta);
194  
195 -       HDMI_WRITE(VC4_HDMI_VERTB0, vertb);
196 +       HDMI_WRITE(VC4_HDMI_VERTB0, vertb_even);
197         HDMI_WRITE(VC4_HDMI_VERTB1, vertb);
198  
199         HD_WRITE(VC4_HD_VID_CTL,
200 --- a/drivers/gpu/drm/vc4/vc4_regs.h
201 +++ b/drivers/gpu/drm/vc4/vc4_regs.h
202 @@ -183,6 +183,9 @@
203  # define PV_CONTROL_EN                         BIT(0)
204  
205  #define PV_V_CONTROL                           0x04
206 +# define PV_VCONTROL_ODD_DELAY_MASK            VC4_MASK(22, 6)
207 +# define PV_VCONTROL_ODD_DELAY_SHIFT           6
208 +# define PV_VCONTROL_ODD_FIRST                 BIT(5)
209  # define PV_VCONTROL_INTERLACE                 BIT(4)
210  # define PV_VCONTROL_DSI                       BIT(3)
211  # define PV_VCONTROL_COMMAND                   BIT(2)