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,
403 xilinx_drm_sdi_enable_vblank(crtc->sdi,
404 xilinx_drm_crtc_vblank_handler,
408 /* disable vblank interrupt */
409 void xilinx_drm_crtc_disable_vblank(struct drm_crtc *base_crtc)
411 struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
414 xilinx_drm_dp_sub_disable_vblank(crtc->dp_sub);
416 xilinx_vtc_disable_vblank_intr(crtc->vtc);
418 xilinx_drm_sdi_disable_vblank(crtc->sdi);
422 * xilinx_drm_crtc_restore - Restore the crtc states
423 * @base_crtc: base crtc object
425 * Restore the crtc states to the default ones. The request is propagated
426 * to the plane driver.
428 void xilinx_drm_crtc_restore(struct drm_crtc *base_crtc)
430 struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
432 xilinx_drm_plane_restore(crtc->plane_manager);
435 /* check max width */
436 unsigned int xilinx_drm_crtc_get_max_width(struct drm_crtc *base_crtc)
438 return xilinx_drm_plane_get_max_width(base_crtc->primary);
442 bool xilinx_drm_crtc_check_format(struct drm_crtc *base_crtc, uint32_t fourcc)
444 struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
446 return xilinx_drm_plane_check_format(crtc->plane_manager, fourcc);
450 uint32_t xilinx_drm_crtc_get_format(struct drm_crtc *base_crtc)
452 return xilinx_drm_plane_get_format(base_crtc->primary);
456 * xilinx_drm_crtc_get_align - Get the alignment value for pitch
457 * @base_crtc: Base crtc object
459 * Get the alignment value for pitch from the plane
461 * Return: The alignment value if successful, or the error code.
463 unsigned int xilinx_drm_crtc_get_align(struct drm_crtc *base_crtc)
465 return xilinx_drm_plane_get_align(base_crtc->primary);
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,
475 struct drm_crtc *xilinx_drm_crtc_create(struct drm_device *drm)
477 struct xilinx_drm_crtc *crtc;
478 struct drm_plane *primary_plane;
479 struct device_node *sub_node;
480 int possible_crtcs = 1;
483 crtc = devm_kzalloc(drm->dev, sizeof(*crtc), GFP_KERNEL);
485 return ERR_PTR(-ENOMEM);
487 /* probe chroma resampler and enable */
488 sub_node = of_parse_phandle(drm->dev->of_node, "xlnx,cresample", 0);
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);
498 /* probe color space converter and enable */
499 sub_node = of_parse_phandle(drm->dev->of_node, "xlnx,rgb2yuv", 0);
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);
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);
517 /* create a primary plane. there's only one crtc now */
518 primary_plane = xilinx_drm_plane_create_primary(crtc->plane_manager,
520 if (IS_ERR(primary_plane)) {
521 DRM_ERROR("failed to create a primary plane for crtc\n");
522 ret = PTR_ERR(primary_plane);
526 /* create extra planes */
527 xilinx_drm_plane_create_planes(crtc->plane_manager, possible_crtcs);
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);
535 DRM_DEBUG_KMS("failed to get pixel clock\n");
536 crtc->pixel_clock = NULL;
540 ret = clk_prepare_enable(crtc->pixel_clock);
542 DRM_ERROR("failed to enable a pixel clock\n");
543 crtc->pixel_clock_enabled = false;
546 clk_disable_unprepare(crtc->pixel_clock);
548 sub_node = of_parse_phandle(drm->dev->of_node, "xlnx,vtc", 0);
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);
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");
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");
574 crtc->dpms = DRM_MODE_DPMS_OFF;
576 /* initialize drm crtc */
577 ret = drm_crtc_init_with_planes(drm, &crtc->base, primary_plane,
578 NULL, &xilinx_drm_crtc_funcs, NULL);
580 DRM_ERROR("failed to initialize crtc\n");
583 drm_crtc_helper_add(&crtc->base, &xilinx_drm_crtc_helper_funcs);
588 if (crtc->pixel_clock_enabled) {
589 clk_disable_unprepare(crtc->pixel_clock);
590 crtc->pixel_clock_enabled = false;
593 xilinx_drm_plane_remove_manager(crtc->plane_manager);