]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/gpu/drm/tve200/tve200_display.c
e8723a2412a6f5d7a0522799b1bb60cca1458e60
[linux.git] / drivers / gpu / drm / tve200 / tve200_display.c
1 /*
2  * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
3  * Parts of this file were based on sources as follows:
4  *
5  * Copyright (C) 2006-2008 Intel Corporation
6  * Copyright (C) 2007 Amos Lee <amos_lee@storlinksemi.com>
7  * Copyright (C) 2007 Dave Airlie <airlied@linux.ie>
8  * Copyright (C) 2011 Texas Instruments
9  * Copyright (C) 2017 Eric Anholt
10  *
11  * This program is free software and is provided to you under the terms of the
12  * GNU General Public License version 2 as published by the Free Software
13  * Foundation, and any use by you of this program is subject to the terms of
14  * such GNU licence.
15  */
16 #include <linux/clk.h>
17 #include <linux/version.h>
18 #include <linux/dma-buf.h>
19 #include <linux/of_graph.h>
20
21 #include <drm/drmP.h>
22 #include <drm/drm_panel.h>
23 #include <drm/drm_gem_cma_helper.h>
24 #include <drm/drm_gem_framebuffer_helper.h>
25 #include <drm/drm_fb_cma_helper.h>
26
27 #include "tve200_drm.h"
28
29 irqreturn_t tve200_irq(int irq, void *data)
30 {
31         struct tve200_drm_dev_private *priv = data;
32         u32 stat;
33         u32 val;
34
35         stat = readl(priv->regs + TVE200_INT_STAT);
36
37         if (!stat)
38                 return IRQ_NONE;
39
40         /*
41          * Vblank IRQ
42          *
43          * The hardware is a bit tilted: the line stays high after clearing
44          * the vblank IRQ, firing many more interrupts. We counter this
45          * by toggling the IRQ back and forth from firing at vblank and
46          * firing at start of active image, which works around the problem
47          * since those occur strictly in sequence, and we get two IRQs for each
48          * frame, one at start of Vblank (that we make call into the CRTC) and
49          * another one at the start of the image (that we discard).
50          */
51         if (stat & TVE200_INT_V_STATUS) {
52                 val = readl(priv->regs + TVE200_CTRL);
53                 /* We have an actual start of vsync */
54                 if (!(val & TVE200_VSTSTYPE_BITS)) {
55                         drm_crtc_handle_vblank(&priv->pipe.crtc);
56                         /* Toggle trigger to start of active image */
57                         val |= TVE200_VSTSTYPE_VAI;
58                 } else {
59                         /* Toggle trigger back to start of vsync */
60                         val &= ~TVE200_VSTSTYPE_BITS;
61                 }
62                 writel(val, priv->regs + TVE200_CTRL);
63         } else
64                 dev_err(priv->drm->dev, "stray IRQ %08x\n", stat);
65
66         /* Clear the interrupt once done */
67         writel(stat, priv->regs + TVE200_INT_CLR);
68
69         return IRQ_HANDLED;
70 }
71
72 static int tve200_display_check(struct drm_simple_display_pipe *pipe,
73                                struct drm_plane_state *pstate,
74                                struct drm_crtc_state *cstate)
75 {
76         const struct drm_display_mode *mode = &cstate->mode;
77         struct drm_framebuffer *old_fb = pipe->plane.state->fb;
78         struct drm_framebuffer *fb = pstate->fb;
79
80         /*
81          * We support these specific resolutions and nothing else.
82          */
83         if (!(mode->hdisplay == 352 && mode->vdisplay == 240) && /* SIF(525) */
84             !(mode->hdisplay == 352 && mode->vdisplay == 288) && /* CIF(625) */
85             !(mode->hdisplay == 640 && mode->vdisplay == 480) && /* VGA */
86             !(mode->hdisplay == 720 && mode->vdisplay == 480) && /* D1 */
87             !(mode->hdisplay == 720 && mode->vdisplay == 576)) { /* D1 */
88                 DRM_DEBUG_KMS("unsupported display mode (%u x %u)\n",
89                         mode->hdisplay, mode->vdisplay);
90                 return -EINVAL;
91         }
92
93         if (fb) {
94                 u32 offset = drm_fb_cma_get_gem_addr(fb, pstate, 0);
95
96                 /* FB base address must be dword aligned. */
97                 if (offset & 3) {
98                         DRM_DEBUG_KMS("FB not 32-bit aligned\n");
99                         return -EINVAL;
100                 }
101
102                 /*
103                  * There's no pitch register, the mode's hdisplay
104                  * controls this.
105                  */
106                 if (fb->pitches[0] != mode->hdisplay * fb->format->cpp[0]) {
107                         DRM_DEBUG_KMS("can't handle pitches\n");
108                         return -EINVAL;
109                 }
110
111                 /*
112                  * We can't change the FB format in a flicker-free
113                  * manner (and only update it during CRTC enable).
114                  */
115                 if (old_fb && old_fb->format != fb->format)
116                         cstate->mode_changed = true;
117         }
118
119         return 0;
120 }
121
122 static void tve200_display_enable(struct drm_simple_display_pipe *pipe,
123                                  struct drm_crtc_state *cstate,
124                                  struct drm_plane_state *plane_state)
125 {
126         struct drm_crtc *crtc = &pipe->crtc;
127         struct drm_plane *plane = &pipe->plane;
128         struct drm_device *drm = crtc->dev;
129         struct tve200_drm_dev_private *priv = drm->dev_private;
130         const struct drm_display_mode *mode = &cstate->mode;
131         struct drm_framebuffer *fb = plane->state->fb;
132         struct drm_connector *connector = priv->connector;
133         u32 format = fb->format->format;
134         u32 ctrl1 = 0;
135
136         clk_prepare_enable(priv->clk);
137
138         /* Function 1 */
139         ctrl1 |= TVE200_CTRL_CSMODE;
140         /* Interlace mode for CCIR656: parameterize? */
141         ctrl1 |= TVE200_CTRL_NONINTERLACE;
142         /* 32 words per burst */
143         ctrl1 |= TVE200_CTRL_BURST_32_WORDS;
144         /* 16 retries */
145         ctrl1 |= TVE200_CTRL_RETRYCNT_16;
146         /* NTSC mode: parametrize? */
147         ctrl1 |= TVE200_CTRL_NTSC;
148
149         /* Vsync IRQ at start of Vsync at first */
150         ctrl1 |= TVE200_VSTSTYPE_VSYNC;
151
152         if (connector->display_info.bus_flags & DRM_BUS_FLAG_PIXDATA_NEGEDGE)
153                 ctrl1 |= TVE200_CTRL_TVCLKP;
154
155         if ((mode->hdisplay == 352 && mode->vdisplay == 240) || /* SIF(525) */
156             (mode->hdisplay == 352 && mode->vdisplay == 288)) { /* CIF(625) */
157                 ctrl1 |= TVE200_CTRL_IPRESOL_CIF;
158                 dev_info(drm->dev, "CIF mode\n");
159         } else if (mode->hdisplay == 640 && mode->vdisplay == 480) {
160                 ctrl1 |= TVE200_CTRL_IPRESOL_VGA;
161                 dev_info(drm->dev, "VGA mode\n");
162         } else if ((mode->hdisplay == 720 && mode->vdisplay == 480) ||
163                    (mode->hdisplay == 720 && mode->vdisplay == 576)) {
164                 ctrl1 |= TVE200_CTRL_IPRESOL_D1;
165                 dev_info(drm->dev, "D1 mode\n");
166         }
167
168         if (format & DRM_FORMAT_BIG_ENDIAN) {
169                 ctrl1 |= TVE200_CTRL_BBBP;
170                 format &= ~DRM_FORMAT_BIG_ENDIAN;
171         }
172
173         switch (format) {
174         case DRM_FORMAT_XRGB8888:
175                 ctrl1 |= TVE200_IPDMOD_RGB888;
176                 break;
177         case DRM_FORMAT_RGB565:
178                 ctrl1 |= TVE200_IPDMOD_RGB565;
179                 break;
180         case DRM_FORMAT_XRGB1555:
181                 ctrl1 |= TVE200_IPDMOD_RGB555;
182                 break;
183         case DRM_FORMAT_XBGR8888:
184                 ctrl1 |= TVE200_IPDMOD_RGB888 | TVE200_BGR;
185                 break;
186         case DRM_FORMAT_BGR565:
187                 ctrl1 |= TVE200_IPDMOD_RGB565 | TVE200_BGR;
188                 break;
189         case DRM_FORMAT_XBGR1555:
190                 ctrl1 |= TVE200_IPDMOD_RGB555 | TVE200_BGR;
191                 break;
192         case DRM_FORMAT_YUYV:
193                 ctrl1 |= TVE200_IPDMOD_YUV422;
194                 ctrl1 |= TVE200_CTRL_YCBCRODR_CR0Y1CB0Y0;
195                 break;
196         case DRM_FORMAT_YVYU:
197                 ctrl1 |= TVE200_IPDMOD_YUV422;
198                 ctrl1 |= TVE200_CTRL_YCBCRODR_CB0Y1CR0Y0;
199                 break;
200         case DRM_FORMAT_UYVY:
201                 ctrl1 |= TVE200_IPDMOD_YUV422;
202                 ctrl1 |= TVE200_CTRL_YCBCRODR_Y1CR0Y0CB0;
203                 break;
204         case DRM_FORMAT_VYUY:
205                 ctrl1 |= TVE200_IPDMOD_YUV422;
206                 ctrl1 |= TVE200_CTRL_YCBCRODR_Y1CB0Y0CR0;
207                 break;
208         case DRM_FORMAT_YUV420:
209                 ctrl1 |= TVE200_CTRL_YUV420;
210                 ctrl1 |= TVE200_IPDMOD_YUV420;
211                 break;
212         default:
213                 dev_err(drm->dev, "Unknown FB format 0x%08x\n",
214                         fb->format->format);
215                 break;
216         }
217
218         ctrl1 |= TVE200_TVEEN;
219
220         /* Turn it on */
221         writel(ctrl1, priv->regs + TVE200_CTRL);
222
223         drm_crtc_vblank_on(crtc);
224 }
225
226 static void tve200_display_disable(struct drm_simple_display_pipe *pipe)
227 {
228         struct drm_crtc *crtc = &pipe->crtc;
229         struct drm_device *drm = crtc->dev;
230         struct tve200_drm_dev_private *priv = drm->dev_private;
231
232         drm_crtc_vblank_off(crtc);
233
234         /* Disable and Power Down */
235         writel(0, priv->regs + TVE200_CTRL);
236
237         clk_disable_unprepare(priv->clk);
238 }
239
240 static void tve200_display_update(struct drm_simple_display_pipe *pipe,
241                                  struct drm_plane_state *old_pstate)
242 {
243         struct drm_crtc *crtc = &pipe->crtc;
244         struct drm_device *drm = crtc->dev;
245         struct tve200_drm_dev_private *priv = drm->dev_private;
246         struct drm_pending_vblank_event *event = crtc->state->event;
247         struct drm_plane *plane = &pipe->plane;
248         struct drm_plane_state *pstate = plane->state;
249         struct drm_framebuffer *fb = pstate->fb;
250
251         if (fb) {
252                 /* For RGB, the Y component is used as base address */
253                 writel(drm_fb_cma_get_gem_addr(fb, pstate, 0),
254                        priv->regs + TVE200_Y_FRAME_BASE_ADDR);
255
256                 /* For three plane YUV we need two more addresses */
257                 if (fb->format->format == DRM_FORMAT_YUV420) {
258                         writel(drm_fb_cma_get_gem_addr(fb, pstate, 1),
259                                priv->regs + TVE200_U_FRAME_BASE_ADDR);
260                         writel(drm_fb_cma_get_gem_addr(fb, pstate, 2),
261                                priv->regs + TVE200_V_FRAME_BASE_ADDR);
262                 }
263         }
264
265         if (event) {
266                 crtc->state->event = NULL;
267
268                 spin_lock_irq(&crtc->dev->event_lock);
269                 if (crtc->state->active && drm_crtc_vblank_get(crtc) == 0)
270                         drm_crtc_arm_vblank_event(crtc, event);
271                 else
272                         drm_crtc_send_vblank_event(crtc, event);
273                 spin_unlock_irq(&crtc->dev->event_lock);
274         }
275 }
276
277 static int tve200_display_enable_vblank(struct drm_simple_display_pipe *pipe)
278 {
279         struct drm_crtc *crtc = &pipe->crtc;
280         struct drm_device *drm = crtc->dev;
281         struct tve200_drm_dev_private *priv = drm->dev_private;
282
283         writel(TVE200_INT_V_STATUS, priv->regs + TVE200_INT_EN);
284         return 0;
285 }
286
287 static void tve200_display_disable_vblank(struct drm_simple_display_pipe *pipe)
288 {
289         struct drm_crtc *crtc = &pipe->crtc;
290         struct drm_device *drm = crtc->dev;
291         struct tve200_drm_dev_private *priv = drm->dev_private;
292
293         writel(0, priv->regs + TVE200_INT_EN);
294 }
295
296 static const struct drm_simple_display_pipe_funcs tve200_display_funcs = {
297         .check = tve200_display_check,
298         .enable = tve200_display_enable,
299         .disable = tve200_display_disable,
300         .update = tve200_display_update,
301         .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
302         .enable_vblank = tve200_display_enable_vblank,
303         .disable_vblank = tve200_display_disable_vblank,
304 };
305
306 int tve200_display_init(struct drm_device *drm)
307 {
308         struct tve200_drm_dev_private *priv = drm->dev_private;
309         int ret;
310         static const u32 formats[] = {
311                 DRM_FORMAT_XRGB8888,
312                 DRM_FORMAT_XBGR8888,
313                 DRM_FORMAT_RGB565,
314                 DRM_FORMAT_BGR565,
315                 DRM_FORMAT_XRGB1555,
316                 DRM_FORMAT_XBGR1555,
317                 /*
318                  * The controller actually supports any YCbCr ordering,
319                  * for packed YCbCr. This just lists the orderings that
320                  * DRM supports.
321                  */
322                 DRM_FORMAT_YUYV,
323                 DRM_FORMAT_YVYU,
324                 DRM_FORMAT_UYVY,
325                 DRM_FORMAT_VYUY,
326                 /* This uses three planes */
327                 DRM_FORMAT_YUV420,
328         };
329
330         ret = drm_simple_display_pipe_init(drm, &priv->pipe,
331                                            &tve200_display_funcs,
332                                            formats, ARRAY_SIZE(formats),
333                                            NULL,
334                                            priv->connector);
335         if (ret)
336                 return ret;
337
338         return 0;
339 }