]> rtime.felk.cvut.cz Git - zynq/linux.git/blob - drivers/gpu/drm/xilinx/xilinx_drm_crtc.c
drm: xilinx: crtc: Adding sdi vblank support in xlnx crtc
[zynq/linux.git] / drivers / gpu / drm / xilinx / xilinx_drm_crtc.c
1 /*
2  * Xilinx DRM crtc driver for Xilinx
3  *
4  *  Copyright (C) 2013 Xilinx, Inc.
5  *
6  *  Author: Hyun Woo Kwon <hyunk@xilinx.com>
7  *
8  * This software is licensed under the terms of the GNU General Public
9  * License version 2, as published by the Free Software Foundation, and
10  * may be copied, distributed, and modified under those terms.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  */
17
18 #include <drm/drmP.h>
19 #include <drm/drm_crtc.h>
20 #include <drm/drm_crtc_helper.h>
21 #include <drm/drm_fb_cma_helper.h>
22 #include <drm/drm_gem_cma_helper.h>
23
24 #include <linux/clk.h>
25 #include <linux/delay.h>
26 #include <linux/device.h>
27 #include <linux/i2c.h>
28
29 #include <video/videomode.h>
30
31 #include "xilinx_drm_crtc.h"
32 #include "xilinx_drm_dp_sub.h"
33 #include "xilinx_drm_drv.h"
34 #include "xilinx_drm_plane.h"
35
36 #include "xilinx_cresample.h"
37 #include "xilinx_rgb2yuv.h"
38 #include "xilinx_vtc.h"
39 #include "xilinx_drm_sdi.h"
40
41 struct xilinx_drm_crtc {
42         struct drm_crtc base;
43         struct xilinx_cresample *cresample;
44         struct xilinx_rgb2yuv *rgb2yuv;
45         struct clk *pixel_clock;
46         bool pixel_clock_enabled;
47         struct xilinx_vtc *vtc;
48         struct xilinx_drm_plane_manager *plane_manager;
49         int dpms;
50         unsigned int alpha;
51         struct drm_pending_vblank_event *event;
52         struct xilinx_drm_dp_sub *dp_sub;
53         struct xilinx_sdi *sdi;
54 };
55
56 #define to_xilinx_crtc(x)       container_of(x, struct xilinx_drm_crtc, base)
57
58 /* set crtc dpms */
59 static void xilinx_drm_crtc_dpms(struct drm_crtc *base_crtc, int dpms)
60 {
61         struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
62         int ret;
63
64         DRM_DEBUG_KMS("dpms: %d -> %d\n", crtc->dpms, dpms);
65
66         if (crtc->dpms == dpms)
67                 return;
68
69         crtc->dpms = dpms;
70
71         switch (dpms) {
72         case DRM_MODE_DPMS_ON:
73                 if (!crtc->pixel_clock_enabled) {
74                         ret = clk_prepare_enable(crtc->pixel_clock);
75                         if (ret)
76                                 DRM_ERROR("failed to enable a pixel clock\n");
77                         else
78                                 crtc->pixel_clock_enabled = true;
79                 }
80
81                 xilinx_drm_plane_manager_dpms(crtc->plane_manager, dpms);
82                 xilinx_drm_plane_dpms(base_crtc->primary, dpms);
83                 if (crtc->rgb2yuv)
84                         xilinx_rgb2yuv_enable(crtc->rgb2yuv);
85                 if (crtc->cresample)
86                         xilinx_cresample_enable(crtc->cresample);
87                 if (crtc->vtc)
88                         xilinx_vtc_enable(crtc->vtc);
89                 break;
90         default:
91                 if (crtc->vtc) {
92                         xilinx_vtc_disable(crtc->vtc);
93                         xilinx_vtc_reset(crtc->vtc);
94                 }
95                 if (crtc->cresample) {
96                         xilinx_cresample_disable(crtc->cresample);
97                         xilinx_cresample_reset(crtc->cresample);
98                 }
99                 if (crtc->rgb2yuv) {
100                         xilinx_rgb2yuv_disable(crtc->rgb2yuv);
101                         xilinx_rgb2yuv_reset(crtc->rgb2yuv);
102                 }
103                 xilinx_drm_plane_dpms(base_crtc->primary, dpms);
104                 xilinx_drm_plane_manager_dpms(crtc->plane_manager, dpms);
105                 if (crtc->pixel_clock_enabled) {
106                         clk_disable_unprepare(crtc->pixel_clock);
107                         crtc->pixel_clock_enabled = false;
108                 }
109                 break;
110         }
111 }
112
113 /* prepare crtc */
114 static void xilinx_drm_crtc_prepare(struct drm_crtc *base_crtc)
115 {
116         xilinx_drm_crtc_dpms(base_crtc, DRM_MODE_DPMS_OFF);
117 }
118
119 /* apply mode to crtc pipe */
120 static void xilinx_drm_crtc_commit(struct drm_crtc *base_crtc)
121 {
122         xilinx_drm_crtc_dpms(base_crtc, DRM_MODE_DPMS_ON);
123         xilinx_drm_plane_commit(base_crtc->primary);
124 }
125
126 /* fix mode */
127 static bool xilinx_drm_crtc_mode_fixup(struct drm_crtc *base_crtc,
128                                        const struct drm_display_mode *mode,
129                                        struct drm_display_mode *adjusted_mode)
130 {
131         /* no op */
132         return true;
133 }
134
135 /* set new mode in crtc pipe */
136 static int xilinx_drm_crtc_mode_set(struct drm_crtc *base_crtc,
137                                     struct drm_display_mode *mode,
138                                     struct drm_display_mode *adjusted_mode,
139                                     int x, int y,
140                                     struct drm_framebuffer *old_fb)
141 {
142         struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
143         struct videomode vm;
144         long diff;
145         int ret;
146
147         if (crtc->pixel_clock_enabled) {
148                 clk_disable_unprepare(crtc->pixel_clock);
149                 crtc->pixel_clock_enabled = false;
150         }
151
152         /* set pixel clock */
153         ret = clk_set_rate(crtc->pixel_clock, adjusted_mode->clock * 1000);
154         if (ret) {
155                 DRM_ERROR("failed to set a pixel clock\n");
156                 return ret;
157         }
158
159         diff = clk_get_rate(crtc->pixel_clock) - adjusted_mode->clock * 1000;
160         if (abs(diff) > (adjusted_mode->clock * 1000) / 20)
161                 DRM_DEBUG_KMS("actual pixel clock rate(%d) is off by %ld\n",
162                               adjusted_mode->clock, diff);
163
164         if (crtc->vtc) {
165                 /* set video timing */
166                 vm.hactive = adjusted_mode->hdisplay;
167                 vm.hfront_porch = adjusted_mode->hsync_start -
168                                   adjusted_mode->hdisplay;
169                 vm.hback_porch = adjusted_mode->htotal -
170                                  adjusted_mode->hsync_end;
171                 vm.hsync_len = adjusted_mode->hsync_end -
172                                adjusted_mode->hsync_start;
173
174                 vm.vactive = adjusted_mode->vdisplay;
175                 vm.vfront_porch = adjusted_mode->vsync_start -
176                                   adjusted_mode->vdisplay;
177                 vm.vback_porch = adjusted_mode->vtotal -
178                                  adjusted_mode->vsync_end;
179                 vm.vsync_len = adjusted_mode->vsync_end -
180                                adjusted_mode->vsync_start;
181
182                 vm.flags = 0;
183                 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
184                         vm.flags |= DISPLAY_FLAGS_INTERLACED;
185                 if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
186                         vm.flags |= DISPLAY_FLAGS_HSYNC_LOW;
187                 if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
188                         vm.flags |= DISPLAY_FLAGS_VSYNC_LOW;
189
190                 xilinx_vtc_config_sig(crtc->vtc, &vm);
191         }
192
193         /* configure cresample and rgb2yuv */
194         if (crtc->cresample)
195                 xilinx_cresample_configure(crtc->cresample,
196                                            adjusted_mode->hdisplay,
197                                            adjusted_mode->vdisplay);
198         if (crtc->rgb2yuv)
199                 xilinx_rgb2yuv_configure(crtc->rgb2yuv,
200                                          adjusted_mode->hdisplay,
201                                          adjusted_mode->vdisplay);
202
203         /* configure a plane: vdma and osd layer */
204         xilinx_drm_plane_manager_mode_set(crtc->plane_manager,
205                                           adjusted_mode->hdisplay,
206                                           adjusted_mode->vdisplay);
207         ret = xilinx_drm_plane_mode_set(base_crtc->primary,
208                                         base_crtc->primary->fb, 0, 0,
209                                         adjusted_mode->hdisplay,
210                                         adjusted_mode->vdisplay,
211                                         x, y,
212                                         adjusted_mode->hdisplay,
213                                         adjusted_mode->vdisplay);
214         if (ret) {
215                 DRM_ERROR("failed to mode set a plane\n");
216                 return ret;
217         }
218
219         return 0;
220 }
221
222 static int _xilinx_drm_crtc_mode_set_base(struct drm_crtc *base_crtc,
223                                           struct drm_framebuffer *fb,
224                                           int x, int y)
225 {
226         struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
227         int ret;
228
229         /* configure a plane */
230         xilinx_drm_plane_manager_mode_set(crtc->plane_manager,
231                                           base_crtc->hwmode.hdisplay,
232                                           base_crtc->hwmode.vdisplay);
233         ret = xilinx_drm_plane_mode_set(base_crtc->primary,
234                                         fb, 0, 0,
235                                         base_crtc->hwmode.hdisplay,
236                                         base_crtc->hwmode.vdisplay,
237                                         x, y,
238                                         base_crtc->hwmode.hdisplay,
239                                         base_crtc->hwmode.vdisplay);
240         if (ret) {
241                 DRM_ERROR("failed to mode set a plane\n");
242                 return ret;
243         }
244
245         /* apply the new fb addr */
246         xilinx_drm_crtc_commit(base_crtc);
247
248         return 0;
249 }
250
251 /* update address and information from fb */
252 static int xilinx_drm_crtc_mode_set_base(struct drm_crtc *base_crtc,
253                                          int x, int y,
254                                          struct drm_framebuffer *old_fb)
255 {
256         /* configure a plane */
257         return _xilinx_drm_crtc_mode_set_base(base_crtc, base_crtc->primary->fb,
258                x, y);
259 }
260
261 /* load rgb LUT for crtc */
262 static void xilinx_drm_crtc_load_lut(struct drm_crtc *base_crtc)
263 {
264         /* no op */
265 }
266
267 static struct drm_crtc_helper_funcs xilinx_drm_crtc_helper_funcs = {
268         .dpms           = xilinx_drm_crtc_dpms,
269         .prepare        = xilinx_drm_crtc_prepare,
270         .commit         = xilinx_drm_crtc_commit,
271         .mode_fixup     = xilinx_drm_crtc_mode_fixup,
272         .mode_set       = xilinx_drm_crtc_mode_set,
273         .mode_set_base  = xilinx_drm_crtc_mode_set_base,
274         .load_lut       = xilinx_drm_crtc_load_lut,
275 };
276
277 /* destroy crtc */
278 void xilinx_drm_crtc_destroy(struct drm_crtc *base_crtc)
279 {
280         struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
281
282         /* make sure crtc is off */
283         xilinx_drm_crtc_dpms(base_crtc, DRM_MODE_DPMS_OFF);
284
285         drm_crtc_cleanup(base_crtc);
286
287         if (crtc->dp_sub)
288                 xilinx_drm_dp_sub_put(crtc->dp_sub);
289
290         if (crtc->pixel_clock_enabled) {
291                 clk_disable_unprepare(crtc->pixel_clock);
292                 crtc->pixel_clock_enabled = false;
293         }
294
295         xilinx_drm_plane_remove_manager(crtc->plane_manager);
296 }
297
298 /* cancel page flip functions */
299 void xilinx_drm_crtc_cancel_page_flip(struct drm_crtc *base_crtc,
300                                       struct drm_file *file)
301 {
302         struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
303         struct drm_device *drm = base_crtc->dev;
304         struct drm_pending_vblank_event *event;
305         unsigned long flags;
306
307         spin_lock_irqsave(&drm->event_lock, flags);
308         event = crtc->event;
309         if (event && (event->base.file_priv == file)) {
310                 crtc->event = NULL;
311                 kfree(&event->base);
312                 drm_crtc_vblank_put(base_crtc);
313         }
314         spin_unlock_irqrestore(&drm->event_lock, flags);
315 }
316
317 /* finish page flip functions */
318 static void xilinx_drm_crtc_finish_page_flip(struct drm_crtc *base_crtc)
319 {
320         struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
321         struct drm_device *drm = base_crtc->dev;
322         struct drm_pending_vblank_event *event;
323         unsigned long flags;
324
325         spin_lock_irqsave(&drm->event_lock, flags);
326         event = crtc->event;
327         crtc->event = NULL;
328         if (event) {
329                 drm_crtc_send_vblank_event(base_crtc, event);
330                 drm_crtc_vblank_put(base_crtc);
331         }
332         spin_unlock_irqrestore(&drm->event_lock, flags);
333 }
334
335 /* page flip functions */
336 static int xilinx_drm_crtc_page_flip(struct drm_crtc *base_crtc,
337                                      struct drm_framebuffer *fb,
338                                      struct drm_pending_vblank_event *event,
339                                      uint32_t page_flip_flags)
340 {
341         struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
342         struct drm_device *drm = base_crtc->dev;
343         unsigned long flags;
344         int ret;
345
346         spin_lock_irqsave(&drm->event_lock, flags);
347         if (crtc->event) {
348                 spin_unlock_irqrestore(&drm->event_lock, flags);
349                 return -EBUSY;
350         }
351         spin_unlock_irqrestore(&drm->event_lock, flags);
352
353         /* configure a plane */
354         ret = _xilinx_drm_crtc_mode_set_base(base_crtc, fb,
355                                              base_crtc->x, base_crtc->y);
356         if (ret) {
357                 DRM_ERROR("failed to mode set a plane\n");
358                 return ret;
359         }
360
361         base_crtc->primary->fb = fb;
362
363         if (event) {
364                 event->pipe = 0;
365                 drm_crtc_vblank_get(base_crtc);
366                 spin_lock_irqsave(&drm->event_lock, flags);
367                 crtc->event = event;
368                 spin_unlock_irqrestore(&drm->event_lock, flags);
369         }
370
371         return 0;
372 }
373
374 /* vblank interrupt handler */
375 static void xilinx_drm_crtc_vblank_handler(void *data)
376 {
377         struct drm_crtc *base_crtc = data;
378         struct drm_device *drm;
379
380         if (!base_crtc)
381                 return;
382
383         drm = base_crtc->dev;
384
385         drm_handle_vblank(drm, 0);
386         xilinx_drm_crtc_finish_page_flip(base_crtc);
387 }
388
389 /* enable vblank interrupt */
390 void xilinx_drm_crtc_enable_vblank(struct drm_crtc *base_crtc)
391 {
392         struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
393
394         if (crtc->vtc)
395                 xilinx_vtc_enable_vblank_intr(crtc->vtc,
396                                               xilinx_drm_crtc_vblank_handler,
397                                               base_crtc);
398         if (crtc->dp_sub)
399                 xilinx_drm_dp_sub_enable_vblank(crtc->dp_sub,
400                                                 xilinx_drm_crtc_vblank_handler,
401                                                 base_crtc);
402         if (crtc->sdi)
403                 xilinx_drm_sdi_enable_vblank(crtc->sdi,
404                                              xilinx_drm_crtc_vblank_handler,
405                                              base_crtc);
406 }
407
408 /* disable vblank interrupt */
409 void xilinx_drm_crtc_disable_vblank(struct drm_crtc *base_crtc)
410 {
411         struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
412
413         if (crtc->dp_sub)
414                 xilinx_drm_dp_sub_disable_vblank(crtc->dp_sub);
415         if (crtc->vtc)
416                 xilinx_vtc_disable_vblank_intr(crtc->vtc);
417         if (crtc->sdi)
418                 xilinx_drm_sdi_disable_vblank(crtc->sdi);
419 }
420
421 /**
422  * xilinx_drm_crtc_restore - Restore the crtc states
423  * @base_crtc: base crtc object
424  *
425  * Restore the crtc states to the default ones. The request is propagated
426  * to the plane driver.
427  */
428 void xilinx_drm_crtc_restore(struct drm_crtc *base_crtc)
429 {
430         struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
431
432         xilinx_drm_plane_restore(crtc->plane_manager);
433 }
434
435 /* check max width */
436 unsigned int xilinx_drm_crtc_get_max_width(struct drm_crtc *base_crtc)
437 {
438         return xilinx_drm_plane_get_max_width(base_crtc->primary);
439 }
440
441 /* check format */
442 bool xilinx_drm_crtc_check_format(struct drm_crtc *base_crtc, uint32_t fourcc)
443 {
444         struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
445
446         return xilinx_drm_plane_check_format(crtc->plane_manager, fourcc);
447 }
448
449 /* get format */
450 uint32_t xilinx_drm_crtc_get_format(struct drm_crtc *base_crtc)
451 {
452         return xilinx_drm_plane_get_format(base_crtc->primary);
453 }
454
455 /**
456  * xilinx_drm_crtc_get_align - Get the alignment value for pitch
457  * @base_crtc: Base crtc object
458  *
459  * Get the alignment value for pitch from the plane
460  *
461  * Return: The alignment value if successful, or the error code.
462  */
463 unsigned int xilinx_drm_crtc_get_align(struct drm_crtc *base_crtc)
464 {
465         return xilinx_drm_plane_get_align(base_crtc->primary);
466 }
467
468 static struct drm_crtc_funcs xilinx_drm_crtc_funcs = {
469         .destroy        = xilinx_drm_crtc_destroy,
470         .set_config     = drm_crtc_helper_set_config,
471         .page_flip      = xilinx_drm_crtc_page_flip,
472 };
473
474 /* create crtc */
475 struct drm_crtc *xilinx_drm_crtc_create(struct drm_device *drm)
476 {
477         struct xilinx_drm_crtc *crtc;
478         struct drm_plane *primary_plane;
479         struct device_node *sub_node;
480         int possible_crtcs = 1;
481         int ret;
482
483         crtc = devm_kzalloc(drm->dev, sizeof(*crtc), GFP_KERNEL);
484         if (!crtc)
485                 return ERR_PTR(-ENOMEM);
486
487         /* probe chroma resampler and enable */
488         sub_node = of_parse_phandle(drm->dev->of_node, "xlnx,cresample", 0);
489         if (sub_node) {
490                 crtc->cresample = xilinx_cresample_probe(drm->dev, sub_node);
491                 of_node_put(sub_node);
492                 if (IS_ERR(crtc->cresample)) {
493                         DRM_ERROR("failed to probe a cresample\n");
494                         return ERR_CAST(crtc->cresample);
495                 }
496         }
497
498         /* probe color space converter and enable */
499         sub_node = of_parse_phandle(drm->dev->of_node, "xlnx,rgb2yuv", 0);
500         if (sub_node) {
501                 crtc->rgb2yuv = xilinx_rgb2yuv_probe(drm->dev, sub_node);
502                 of_node_put(sub_node);
503                 if (IS_ERR(crtc->rgb2yuv)) {
504                         DRM_ERROR("failed to probe a rgb2yuv\n");
505                         return ERR_CAST(crtc->rgb2yuv);
506                 }
507         }
508
509         /* probe a plane manager */
510         crtc->plane_manager = xilinx_drm_plane_probe_manager(drm);
511         if (IS_ERR(crtc->plane_manager)) {
512                 if (PTR_ERR(crtc->plane_manager) != -EPROBE_DEFER)
513                         DRM_ERROR("failed to probe a plane manager\n");
514                 return ERR_CAST(crtc->plane_manager);
515         }
516
517         /* create a primary plane. there's only one crtc now */
518         primary_plane = xilinx_drm_plane_create_primary(crtc->plane_manager,
519                                                         possible_crtcs);
520         if (IS_ERR(primary_plane)) {
521                 DRM_ERROR("failed to create a primary plane for crtc\n");
522                 ret = PTR_ERR(primary_plane);
523                 goto err_plane;
524         }
525
526         /* create extra planes */
527         xilinx_drm_plane_create_planes(crtc->plane_manager, possible_crtcs);
528
529         crtc->pixel_clock = devm_clk_get(drm->dev, NULL);
530         if (IS_ERR(crtc->pixel_clock)) {
531                 if (PTR_ERR(crtc->pixel_clock) == -EPROBE_DEFER) {
532                         ret = PTR_ERR(crtc->pixel_clock);
533                         goto err_plane;
534                 } else {
535                         DRM_DEBUG_KMS("failed to get pixel clock\n");
536                         crtc->pixel_clock = NULL;
537                 }
538         }
539
540         ret = clk_prepare_enable(crtc->pixel_clock);
541         if (ret) {
542                 DRM_ERROR("failed to enable a pixel clock\n");
543                 crtc->pixel_clock_enabled = false;
544                 goto err_plane;
545         }
546         clk_disable_unprepare(crtc->pixel_clock);
547
548         sub_node = of_parse_phandle(drm->dev->of_node, "xlnx,vtc", 0);
549         if (sub_node) {
550                 crtc->vtc = xilinx_vtc_probe(drm->dev, sub_node);
551                 of_node_put(sub_node);
552                 if (IS_ERR(crtc->vtc)) {
553                         DRM_ERROR("failed to probe video timing controller\n");
554                         ret = PTR_ERR(crtc->vtc);
555                         goto err_pixel_clk;
556                 }
557         }
558
559         crtc->dp_sub = xilinx_drm_dp_sub_of_get(drm->dev->of_node);
560         if (IS_ERR(crtc->dp_sub)) {
561                 ret = PTR_ERR(crtc->dp_sub);
562                 if (ret != -EPROBE_DEFER)
563                         DRM_ERROR("failed to get a dp_sub\n");
564                 goto err_pixel_clk;
565         }
566
567         crtc->sdi = xilinx_drm_sdi_of_get(drm->dev->of_node);
568         if (IS_ERR(crtc->sdi)) {
569                 ret = PTR_ERR(crtc->sdi);
570                 if (ret != -EPROBE_DEFER)
571                         DRM_ERROR("failed to get a sdi\n");
572                 goto err_pixel_clk;
573         }
574         crtc->dpms = DRM_MODE_DPMS_OFF;
575
576         /* initialize drm crtc */
577         ret = drm_crtc_init_with_planes(drm, &crtc->base, primary_plane,
578                                         NULL, &xilinx_drm_crtc_funcs, NULL);
579         if (ret) {
580                 DRM_ERROR("failed to initialize crtc\n");
581                 goto err_pixel_clk;
582         }
583         drm_crtc_helper_add(&crtc->base, &xilinx_drm_crtc_helper_funcs);
584
585         return &crtc->base;
586
587 err_pixel_clk:
588         if (crtc->pixel_clock_enabled) {
589                 clk_disable_unprepare(crtc->pixel_clock);
590                 crtc->pixel_clock_enabled = false;
591         }
592 err_plane:
593         xilinx_drm_plane_remove_manager(crtc->plane_manager);
594         return ERR_PTR(ret);
595 }