2 * Xilinx DRM crtc driver for Xilinx
4 * Copyright (C) 2013 Xilinx, Inc.
6 * Author: Hyun Woo Kwon <hyunk@xilinx.com>
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.
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.
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>
24 #include <linux/clk.h>
25 #include <linux/delay.h>
26 #include <linux/device.h>
27 #include <linux/i2c.h>
29 #include <video/videomode.h>
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"
36 #include "xilinx_cresample.h"
37 #include "xilinx_rgb2yuv.h"
38 #include "xilinx_vtc.h"
39 #include "xilinx_drm_sdi.h"
41 struct xilinx_drm_crtc {
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;
51 struct drm_pending_vblank_event *event;
52 struct xilinx_drm_dp_sub *dp_sub;
53 struct xilinx_sdi *sdi;
56 #define to_xilinx_crtc(x) container_of(x, struct xilinx_drm_crtc, base)
59 static void xilinx_drm_crtc_dpms(struct drm_crtc *base_crtc, int dpms)
61 struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
64 DRM_DEBUG_KMS("dpms: %d -> %d\n", crtc->dpms, dpms);
66 if (crtc->dpms == dpms)
72 case DRM_MODE_DPMS_ON:
73 if (!crtc->pixel_clock_enabled) {
74 ret = clk_prepare_enable(crtc->pixel_clock);
76 DRM_ERROR("failed to enable a pixel clock\n");
78 crtc->pixel_clock_enabled = true;
81 xilinx_drm_plane_manager_dpms(crtc->plane_manager, dpms);
82 xilinx_drm_plane_dpms(base_crtc->primary, dpms);
84 xilinx_rgb2yuv_enable(crtc->rgb2yuv);
86 xilinx_cresample_enable(crtc->cresample);
88 xilinx_vtc_enable(crtc->vtc);
92 xilinx_vtc_disable(crtc->vtc);
93 xilinx_vtc_reset(crtc->vtc);
95 if (crtc->cresample) {
96 xilinx_cresample_disable(crtc->cresample);
97 xilinx_cresample_reset(crtc->cresample);
100 xilinx_rgb2yuv_disable(crtc->rgb2yuv);
101 xilinx_rgb2yuv_reset(crtc->rgb2yuv);
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;
114 static void xilinx_drm_crtc_prepare(struct drm_crtc *base_crtc)
116 xilinx_drm_crtc_dpms(base_crtc, DRM_MODE_DPMS_OFF);
119 /* apply mode to crtc pipe */
120 static void xilinx_drm_crtc_commit(struct drm_crtc *base_crtc)
122 xilinx_drm_crtc_dpms(base_crtc, DRM_MODE_DPMS_ON);
123 xilinx_drm_plane_commit(base_crtc->primary);
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)
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,
140 struct drm_framebuffer *old_fb)
142 struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
147 if (crtc->pixel_clock_enabled) {
148 clk_disable_unprepare(crtc->pixel_clock);
149 crtc->pixel_clock_enabled = false;
152 /* set pixel clock */
153 ret = clk_set_rate(crtc->pixel_clock, adjusted_mode->clock * 1000);
155 DRM_ERROR("failed to set a pixel clock\n");
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);
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;
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;
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;
190 xilinx_vtc_config_sig(crtc->vtc, &vm);
193 /* configure cresample and rgb2yuv */
195 xilinx_cresample_configure(crtc->cresample,
196 adjusted_mode->hdisplay,
197 adjusted_mode->vdisplay);
199 xilinx_rgb2yuv_configure(crtc->rgb2yuv,
200 adjusted_mode->hdisplay,
201 adjusted_mode->vdisplay);
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,
212 adjusted_mode->hdisplay,
213 adjusted_mode->vdisplay);
215 DRM_ERROR("failed to mode set a plane\n");
222 static int _xilinx_drm_crtc_mode_set_base(struct drm_crtc *base_crtc,
223 struct drm_framebuffer *fb,
226 struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
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,
235 base_crtc->hwmode.hdisplay,
236 base_crtc->hwmode.vdisplay,
238 base_crtc->hwmode.hdisplay,
239 base_crtc->hwmode.vdisplay);
241 DRM_ERROR("failed to mode set a plane\n");
245 /* apply the new fb addr */
246 xilinx_drm_crtc_commit(base_crtc);
251 /* update address and information from fb */
252 static int xilinx_drm_crtc_mode_set_base(struct drm_crtc *base_crtc,
254 struct drm_framebuffer *old_fb)
256 /* configure a plane */
257 return _xilinx_drm_crtc_mode_set_base(base_crtc, base_crtc->primary->fb,
261 /* load rgb LUT for crtc */
262 static void xilinx_drm_crtc_load_lut(struct drm_crtc *base_crtc)
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,
278 void xilinx_drm_crtc_destroy(struct drm_crtc *base_crtc)
280 struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
282 /* make sure crtc is off */
283 xilinx_drm_crtc_dpms(base_crtc, DRM_MODE_DPMS_OFF);
285 drm_crtc_cleanup(base_crtc);
288 xilinx_drm_dp_sub_put(crtc->dp_sub);
290 if (crtc->pixel_clock_enabled) {
291 clk_disable_unprepare(crtc->pixel_clock);
292 crtc->pixel_clock_enabled = false;
295 xilinx_drm_plane_remove_manager(crtc->plane_manager);
298 /* cancel page flip functions */
299 void xilinx_drm_crtc_cancel_page_flip(struct drm_crtc *base_crtc,
300 struct drm_file *file)
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;
307 spin_lock_irqsave(&drm->event_lock, flags);
309 if (event && (event->base.file_priv == file)) {
312 drm_crtc_vblank_put(base_crtc);
314 spin_unlock_irqrestore(&drm->event_lock, flags);
317 /* finish page flip functions */
318 static void xilinx_drm_crtc_finish_page_flip(struct drm_crtc *base_crtc)
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;
325 spin_lock_irqsave(&drm->event_lock, flags);
329 drm_crtc_send_vblank_event(base_crtc, event);
330 drm_crtc_vblank_put(base_crtc);
332 spin_unlock_irqrestore(&drm->event_lock, flags);
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)
341 struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
342 struct drm_device *drm = base_crtc->dev;
346 spin_lock_irqsave(&drm->event_lock, flags);
348 spin_unlock_irqrestore(&drm->event_lock, flags);
351 spin_unlock_irqrestore(&drm->event_lock, flags);
353 /* configure a plane */
354 ret = _xilinx_drm_crtc_mode_set_base(base_crtc, fb,
355 base_crtc->x, base_crtc->y);
357 DRM_ERROR("failed to mode set a plane\n");
361 base_crtc->primary->fb = fb;
365 drm_crtc_vblank_get(base_crtc);
366 spin_lock_irqsave(&drm->event_lock, flags);
368 spin_unlock_irqrestore(&drm->event_lock, flags);
374 /* vblank interrupt handler */
375 static void xilinx_drm_crtc_vblank_handler(void *data)
377 struct drm_crtc *base_crtc = data;
378 struct drm_device *drm;
383 drm = base_crtc->dev;
385 drm_handle_vblank(drm, 0);
386 xilinx_drm_crtc_finish_page_flip(base_crtc);
389 /* enable vblank interrupt */
390 void xilinx_drm_crtc_enable_vblank(struct drm_crtc *base_crtc)
392 struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
395 xilinx_vtc_enable_vblank_intr(crtc->vtc,
396 xilinx_drm_crtc_vblank_handler,
399 xilinx_drm_dp_sub_enable_vblank(crtc->dp_sub,
400 xilinx_drm_crtc_vblank_handler,
402 #ifdef CONFIG_DRM_XILINX_SDI
404 xilinx_drm_sdi_enable_vblank(crtc->sdi,
405 xilinx_drm_crtc_vblank_handler,
410 /* disable vblank interrupt */
411 void xilinx_drm_crtc_disable_vblank(struct drm_crtc *base_crtc)
413 struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
416 xilinx_drm_dp_sub_disable_vblank(crtc->dp_sub);
418 xilinx_vtc_disable_vblank_intr(crtc->vtc);
419 #ifdef CONFIG_DRM_XILINX_SDI
421 xilinx_drm_sdi_disable_vblank(crtc->sdi);
426 * xilinx_drm_crtc_restore - Restore the crtc states
427 * @base_crtc: base crtc object
429 * Restore the crtc states to the default ones. The request is propagated
430 * to the plane driver.
432 void xilinx_drm_crtc_restore(struct drm_crtc *base_crtc)
434 struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
436 xilinx_drm_plane_restore(crtc->plane_manager);
439 /* check max width */
440 unsigned int xilinx_drm_crtc_get_max_width(struct drm_crtc *base_crtc)
442 return xilinx_drm_plane_get_max_width(base_crtc->primary);
446 bool xilinx_drm_crtc_check_format(struct drm_crtc *base_crtc, uint32_t fourcc)
448 struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
450 return xilinx_drm_plane_check_format(crtc->plane_manager, fourcc);
454 uint32_t xilinx_drm_crtc_get_format(struct drm_crtc *base_crtc)
456 return xilinx_drm_plane_get_format(base_crtc->primary);
460 * xilinx_drm_crtc_get_align - Get the alignment value for pitch
461 * @base_crtc: Base crtc object
463 * Get the alignment value for pitch from the plane
465 * Return: The alignment value if successful, or the error code.
467 unsigned int xilinx_drm_crtc_get_align(struct drm_crtc *base_crtc)
469 return xilinx_drm_plane_get_align(base_crtc->primary);
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,
479 struct drm_crtc *xilinx_drm_crtc_create(struct drm_device *drm)
481 struct xilinx_drm_crtc *crtc;
482 struct drm_plane *primary_plane;
483 struct device_node *sub_node;
484 int possible_crtcs = 1;
487 crtc = devm_kzalloc(drm->dev, sizeof(*crtc), GFP_KERNEL);
489 return ERR_PTR(-ENOMEM);
491 /* probe chroma resampler and enable */
492 sub_node = of_parse_phandle(drm->dev->of_node, "xlnx,cresample", 0);
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);
502 /* probe color space converter and enable */
503 sub_node = of_parse_phandle(drm->dev->of_node, "xlnx,rgb2yuv", 0);
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);
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);
521 /* create a primary plane. there's only one crtc now */
522 primary_plane = xilinx_drm_plane_create_primary(crtc->plane_manager,
524 if (IS_ERR(primary_plane)) {
525 DRM_ERROR("failed to create a primary plane for crtc\n");
526 ret = PTR_ERR(primary_plane);
530 /* create extra planes */
531 xilinx_drm_plane_create_planes(crtc->plane_manager, possible_crtcs);
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);
539 DRM_DEBUG_KMS("failed to get pixel clock\n");
540 crtc->pixel_clock = NULL;
544 ret = clk_prepare_enable(crtc->pixel_clock);
546 DRM_ERROR("failed to enable a pixel clock\n");
547 crtc->pixel_clock_enabled = false;
550 clk_disable_unprepare(crtc->pixel_clock);
552 sub_node = of_parse_phandle(drm->dev->of_node, "xlnx,vtc", 0);
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);
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");
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");
580 crtc->dpms = DRM_MODE_DPMS_OFF;
582 /* initialize drm crtc */
583 ret = drm_crtc_init_with_planes(drm, &crtc->base, primary_plane,
584 NULL, &xilinx_drm_crtc_funcs, NULL);
586 DRM_ERROR("failed to initialize crtc\n");
589 drm_crtc_helper_add(&crtc->base, &xilinx_drm_crtc_helper_funcs);
594 if (crtc->pixel_clock_enabled) {
595 clk_disable_unprepare(crtc->pixel_clock);
596 crtc->pixel_clock_enabled = false;
599 xilinx_drm_plane_remove_manager(crtc->plane_manager);