]> rtime.felk.cvut.cz Git - zynq/linux.git/blob - drivers/gpu/drm/xilinx/xilinx_drm_crtc.c
drm: xilinx: crtc: disabling SDI for zynq(arm)
[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 #ifdef CONFIG_DRM_XILINX_SDI
403         if (crtc->sdi)
404                 xilinx_drm_sdi_enable_vblank(crtc->sdi,
405                                              xilinx_drm_crtc_vblank_handler,
406                                              base_crtc);
407 #endif
408 }
409
410 /* disable vblank interrupt */
411 void xilinx_drm_crtc_disable_vblank(struct drm_crtc *base_crtc)
412 {
413         struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
414
415         if (crtc->dp_sub)
416                 xilinx_drm_dp_sub_disable_vblank(crtc->dp_sub);
417         if (crtc->vtc)
418                 xilinx_vtc_disable_vblank_intr(crtc->vtc);
419 #ifdef CONFIG_DRM_XILINX_SDI
420         if (crtc->sdi)
421                 xilinx_drm_sdi_disable_vblank(crtc->sdi);
422 #endif
423 }
424
425 /**
426  * xilinx_drm_crtc_restore - Restore the crtc states
427  * @base_crtc: base crtc object
428  *
429  * Restore the crtc states to the default ones. The request is propagated
430  * to the plane driver.
431  */
432 void xilinx_drm_crtc_restore(struct drm_crtc *base_crtc)
433 {
434         struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
435
436         xilinx_drm_plane_restore(crtc->plane_manager);
437 }
438
439 /* check max width */
440 unsigned int xilinx_drm_crtc_get_max_width(struct drm_crtc *base_crtc)
441 {
442         return xilinx_drm_plane_get_max_width(base_crtc->primary);
443 }
444
445 /* check format */
446 bool xilinx_drm_crtc_check_format(struct drm_crtc *base_crtc, uint32_t fourcc)
447 {
448         struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
449
450         return xilinx_drm_plane_check_format(crtc->plane_manager, fourcc);
451 }
452
453 /* get format */
454 uint32_t xilinx_drm_crtc_get_format(struct drm_crtc *base_crtc)
455 {
456         return xilinx_drm_plane_get_format(base_crtc->primary);
457 }
458
459 /**
460  * xilinx_drm_crtc_get_align - Get the alignment value for pitch
461  * @base_crtc: Base crtc object
462  *
463  * Get the alignment value for pitch from the plane
464  *
465  * Return: The alignment value if successful, or the error code.
466  */
467 unsigned int xilinx_drm_crtc_get_align(struct drm_crtc *base_crtc)
468 {
469         return xilinx_drm_plane_get_align(base_crtc->primary);
470 }
471
472 static struct drm_crtc_funcs xilinx_drm_crtc_funcs = {
473         .destroy        = xilinx_drm_crtc_destroy,
474         .set_config     = drm_crtc_helper_set_config,
475         .page_flip      = xilinx_drm_crtc_page_flip,
476 };
477
478 /* create crtc */
479 struct drm_crtc *xilinx_drm_crtc_create(struct drm_device *drm)
480 {
481         struct xilinx_drm_crtc *crtc;
482         struct drm_plane *primary_plane;
483         struct device_node *sub_node;
484         int possible_crtcs = 1;
485         int ret;
486
487         crtc = devm_kzalloc(drm->dev, sizeof(*crtc), GFP_KERNEL);
488         if (!crtc)
489                 return ERR_PTR(-ENOMEM);
490
491         /* probe chroma resampler and enable */
492         sub_node = of_parse_phandle(drm->dev->of_node, "xlnx,cresample", 0);
493         if (sub_node) {
494                 crtc->cresample = xilinx_cresample_probe(drm->dev, sub_node);
495                 of_node_put(sub_node);
496                 if (IS_ERR(crtc->cresample)) {
497                         DRM_ERROR("failed to probe a cresample\n");
498                         return ERR_CAST(crtc->cresample);
499                 }
500         }
501
502         /* probe color space converter and enable */
503         sub_node = of_parse_phandle(drm->dev->of_node, "xlnx,rgb2yuv", 0);
504         if (sub_node) {
505                 crtc->rgb2yuv = xilinx_rgb2yuv_probe(drm->dev, sub_node);
506                 of_node_put(sub_node);
507                 if (IS_ERR(crtc->rgb2yuv)) {
508                         DRM_ERROR("failed to probe a rgb2yuv\n");
509                         return ERR_CAST(crtc->rgb2yuv);
510                 }
511         }
512
513         /* probe a plane manager */
514         crtc->plane_manager = xilinx_drm_plane_probe_manager(drm);
515         if (IS_ERR(crtc->plane_manager)) {
516                 if (PTR_ERR(crtc->plane_manager) != -EPROBE_DEFER)
517                         DRM_ERROR("failed to probe a plane manager\n");
518                 return ERR_CAST(crtc->plane_manager);
519         }
520
521         /* create a primary plane. there's only one crtc now */
522         primary_plane = xilinx_drm_plane_create_primary(crtc->plane_manager,
523                                                         possible_crtcs);
524         if (IS_ERR(primary_plane)) {
525                 DRM_ERROR("failed to create a primary plane for crtc\n");
526                 ret = PTR_ERR(primary_plane);
527                 goto err_plane;
528         }
529
530         /* create extra planes */
531         xilinx_drm_plane_create_planes(crtc->plane_manager, possible_crtcs);
532
533         crtc->pixel_clock = devm_clk_get(drm->dev, NULL);
534         if (IS_ERR(crtc->pixel_clock)) {
535                 if (PTR_ERR(crtc->pixel_clock) == -EPROBE_DEFER) {
536                         ret = PTR_ERR(crtc->pixel_clock);
537                         goto err_plane;
538                 } else {
539                         DRM_DEBUG_KMS("failed to get pixel clock\n");
540                         crtc->pixel_clock = NULL;
541                 }
542         }
543
544         ret = clk_prepare_enable(crtc->pixel_clock);
545         if (ret) {
546                 DRM_ERROR("failed to enable a pixel clock\n");
547                 crtc->pixel_clock_enabled = false;
548                 goto err_plane;
549         }
550         clk_disable_unprepare(crtc->pixel_clock);
551
552         sub_node = of_parse_phandle(drm->dev->of_node, "xlnx,vtc", 0);
553         if (sub_node) {
554                 crtc->vtc = xilinx_vtc_probe(drm->dev, sub_node);
555                 of_node_put(sub_node);
556                 if (IS_ERR(crtc->vtc)) {
557                         DRM_ERROR("failed to probe video timing controller\n");
558                         ret = PTR_ERR(crtc->vtc);
559                         goto err_pixel_clk;
560                 }
561         }
562
563         crtc->dp_sub = xilinx_drm_dp_sub_of_get(drm->dev->of_node);
564         if (IS_ERR(crtc->dp_sub)) {
565                 ret = PTR_ERR(crtc->dp_sub);
566                 if (ret != -EPROBE_DEFER)
567                         DRM_ERROR("failed to get a dp_sub\n");
568                 goto err_pixel_clk;
569         }
570
571 #ifdef CONFIG_DRM_XILINX_SDI
572         crtc->sdi = xilinx_drm_sdi_of_get(drm->dev->of_node);
573         if (IS_ERR(crtc->sdi)) {
574                 ret = PTR_ERR(crtc->sdi);
575                 if (ret != -EPROBE_DEFER)
576                         DRM_ERROR("failed to get a sdi\n");
577                 goto err_pixel_clk;
578         }
579 #endif
580         crtc->dpms = DRM_MODE_DPMS_OFF;
581
582         /* initialize drm crtc */
583         ret = drm_crtc_init_with_planes(drm, &crtc->base, primary_plane,
584                                         NULL, &xilinx_drm_crtc_funcs, NULL);
585         if (ret) {
586                 DRM_ERROR("failed to initialize crtc\n");
587                 goto err_pixel_clk;
588         }
589         drm_crtc_helper_add(&crtc->base, &xilinx_drm_crtc_helper_funcs);
590
591         return &crtc->base;
592
593 err_pixel_clk:
594         if (crtc->pixel_clock_enabled) {
595                 clk_disable_unprepare(crtc->pixel_clock);
596                 crtc->pixel_clock_enabled = false;
597         }
598 err_plane:
599         xilinx_drm_plane_remove_manager(crtc->plane_manager);
600         return ERR_PTR(ret);
601 }