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