]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/gpu/drm/tve200/tve200_display.c
drm: Use new DRM_BUS_FLAG_*_(DRIVE|SAMPLE)_(POS|NEG)EDGE flags
[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 &
153             DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
154                 ctrl1 |= TVE200_CTRL_TVCLKP;
155
156         if ((mode->hdisplay == 352 && mode->vdisplay == 240) || /* SIF(525) */
157             (mode->hdisplay == 352 && mode->vdisplay == 288)) { /* CIF(625) */
158                 ctrl1 |= TVE200_CTRL_IPRESOL_CIF;
159                 dev_info(drm->dev, "CIF mode\n");
160         } else if (mode->hdisplay == 640 && mode->vdisplay == 480) {
161                 ctrl1 |= TVE200_CTRL_IPRESOL_VGA;
162                 dev_info(drm->dev, "VGA mode\n");
163         } else if ((mode->hdisplay == 720 && mode->vdisplay == 480) ||
164                    (mode->hdisplay == 720 && mode->vdisplay == 576)) {
165                 ctrl1 |= TVE200_CTRL_IPRESOL_D1;
166                 dev_info(drm->dev, "D1 mode\n");
167         }
168
169         if (format & DRM_FORMAT_BIG_ENDIAN) {
170                 ctrl1 |= TVE200_CTRL_BBBP;
171                 format &= ~DRM_FORMAT_BIG_ENDIAN;
172         }
173
174         switch (format) {
175         case DRM_FORMAT_XRGB8888:
176                 ctrl1 |= TVE200_IPDMOD_RGB888;
177                 break;
178         case DRM_FORMAT_RGB565:
179                 ctrl1 |= TVE200_IPDMOD_RGB565;
180                 break;
181         case DRM_FORMAT_XRGB1555:
182                 ctrl1 |= TVE200_IPDMOD_RGB555;
183                 break;
184         case DRM_FORMAT_XBGR8888:
185                 ctrl1 |= TVE200_IPDMOD_RGB888 | TVE200_BGR;
186                 break;
187         case DRM_FORMAT_BGR565:
188                 ctrl1 |= TVE200_IPDMOD_RGB565 | TVE200_BGR;
189                 break;
190         case DRM_FORMAT_XBGR1555:
191                 ctrl1 |= TVE200_IPDMOD_RGB555 | TVE200_BGR;
192                 break;
193         case DRM_FORMAT_YUYV:
194                 ctrl1 |= TVE200_IPDMOD_YUV422;
195                 ctrl1 |= TVE200_CTRL_YCBCRODR_CR0Y1CB0Y0;
196                 break;
197         case DRM_FORMAT_YVYU:
198                 ctrl1 |= TVE200_IPDMOD_YUV422;
199                 ctrl1 |= TVE200_CTRL_YCBCRODR_CB0Y1CR0Y0;
200                 break;
201         case DRM_FORMAT_UYVY:
202                 ctrl1 |= TVE200_IPDMOD_YUV422;
203                 ctrl1 |= TVE200_CTRL_YCBCRODR_Y1CR0Y0CB0;
204                 break;
205         case DRM_FORMAT_VYUY:
206                 ctrl1 |= TVE200_IPDMOD_YUV422;
207                 ctrl1 |= TVE200_CTRL_YCBCRODR_Y1CB0Y0CR0;
208                 break;
209         case DRM_FORMAT_YUV420:
210                 ctrl1 |= TVE200_CTRL_YUV420;
211                 ctrl1 |= TVE200_IPDMOD_YUV420;
212                 break;
213         default:
214                 dev_err(drm->dev, "Unknown FB format 0x%08x\n",
215                         fb->format->format);
216                 break;
217         }
218
219         ctrl1 |= TVE200_TVEEN;
220
221         /* Turn it on */
222         writel(ctrl1, priv->regs + TVE200_CTRL);
223
224         drm_crtc_vblank_on(crtc);
225 }
226
227 static void tve200_display_disable(struct drm_simple_display_pipe *pipe)
228 {
229         struct drm_crtc *crtc = &pipe->crtc;
230         struct drm_device *drm = crtc->dev;
231         struct tve200_drm_dev_private *priv = drm->dev_private;
232
233         drm_crtc_vblank_off(crtc);
234
235         /* Disable and Power Down */
236         writel(0, priv->regs + TVE200_CTRL);
237
238         clk_disable_unprepare(priv->clk);
239 }
240
241 static void tve200_display_update(struct drm_simple_display_pipe *pipe,
242                                  struct drm_plane_state *old_pstate)
243 {
244         struct drm_crtc *crtc = &pipe->crtc;
245         struct drm_device *drm = crtc->dev;
246         struct tve200_drm_dev_private *priv = drm->dev_private;
247         struct drm_pending_vblank_event *event = crtc->state->event;
248         struct drm_plane *plane = &pipe->plane;
249         struct drm_plane_state *pstate = plane->state;
250         struct drm_framebuffer *fb = pstate->fb;
251
252         if (fb) {
253                 /* For RGB, the Y component is used as base address */
254                 writel(drm_fb_cma_get_gem_addr(fb, pstate, 0),
255                        priv->regs + TVE200_Y_FRAME_BASE_ADDR);
256
257                 /* For three plane YUV we need two more addresses */
258                 if (fb->format->format == DRM_FORMAT_YUV420) {
259                         writel(drm_fb_cma_get_gem_addr(fb, pstate, 1),
260                                priv->regs + TVE200_U_FRAME_BASE_ADDR);
261                         writel(drm_fb_cma_get_gem_addr(fb, pstate, 2),
262                                priv->regs + TVE200_V_FRAME_BASE_ADDR);
263                 }
264         }
265
266         if (event) {
267                 crtc->state->event = NULL;
268
269                 spin_lock_irq(&crtc->dev->event_lock);
270                 if (crtc->state->active && drm_crtc_vblank_get(crtc) == 0)
271                         drm_crtc_arm_vblank_event(crtc, event);
272                 else
273                         drm_crtc_send_vblank_event(crtc, event);
274                 spin_unlock_irq(&crtc->dev->event_lock);
275         }
276 }
277
278 static int tve200_display_enable_vblank(struct drm_simple_display_pipe *pipe)
279 {
280         struct drm_crtc *crtc = &pipe->crtc;
281         struct drm_device *drm = crtc->dev;
282         struct tve200_drm_dev_private *priv = drm->dev_private;
283
284         writel(TVE200_INT_V_STATUS, priv->regs + TVE200_INT_EN);
285         return 0;
286 }
287
288 static void tve200_display_disable_vblank(struct drm_simple_display_pipe *pipe)
289 {
290         struct drm_crtc *crtc = &pipe->crtc;
291         struct drm_device *drm = crtc->dev;
292         struct tve200_drm_dev_private *priv = drm->dev_private;
293
294         writel(0, priv->regs + TVE200_INT_EN);
295 }
296
297 static const struct drm_simple_display_pipe_funcs tve200_display_funcs = {
298         .check = tve200_display_check,
299         .enable = tve200_display_enable,
300         .disable = tve200_display_disable,
301         .update = tve200_display_update,
302         .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
303         .enable_vblank = tve200_display_enable_vblank,
304         .disable_vblank = tve200_display_disable_vblank,
305 };
306
307 int tve200_display_init(struct drm_device *drm)
308 {
309         struct tve200_drm_dev_private *priv = drm->dev_private;
310         int ret;
311         static const u32 formats[] = {
312                 DRM_FORMAT_XRGB8888,
313                 DRM_FORMAT_XBGR8888,
314                 DRM_FORMAT_RGB565,
315                 DRM_FORMAT_BGR565,
316                 DRM_FORMAT_XRGB1555,
317                 DRM_FORMAT_XBGR1555,
318                 /*
319                  * The controller actually supports any YCbCr ordering,
320                  * for packed YCbCr. This just lists the orderings that
321                  * DRM supports.
322                  */
323                 DRM_FORMAT_YUYV,
324                 DRM_FORMAT_YVYU,
325                 DRM_FORMAT_UYVY,
326                 DRM_FORMAT_VYUY,
327                 /* This uses three planes */
328                 DRM_FORMAT_YUV420,
329         };
330
331         ret = drm_simple_display_pipe_init(drm, &priv->pipe,
332                                            &tve200_display_funcs,
333                                            formats, ARRAY_SIZE(formats),
334                                            NULL,
335                                            priv->connector);
336         if (ret)
337                 return ret;
338
339         return 0;
340 }