2 * Xilinx DRM KMS support 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_helper.h>
20 #include <drm/drm_gem_cma_helper.h>
22 #include <linux/device.h>
23 #include <linux/module.h>
24 #include <linux/platform_device.h>
26 #include "xilinx_drm_connector.h"
27 #include "xilinx_drm_crtc.h"
28 #include "xilinx_drm_drv.h"
29 #include "xilinx_drm_encoder.h"
30 #include "xilinx_drm_fb.h"
31 #include "xilinx_drm_gem.h"
33 #define DRIVER_NAME "xilinx_drm"
34 #define DRIVER_DESC "Xilinx DRM KMS support for Xilinx"
35 #define DRIVER_DATE "20130509"
36 #define DRIVER_MAJOR 1
37 #define DRIVER_MINOR 0
39 static uint xilinx_drm_fbdev_vres = 2;
40 module_param_named(fbdev_vres, xilinx_drm_fbdev_vres, uint, 0444);
41 MODULE_PARM_DESC(fbdev_vres,
42 "fbdev virtual resolution multiplier for fb (default: 2)");
45 * TODO: The possible pipeline configurations are numerous with Xilinx soft IPs.
46 * It's not too bad for now, but the more proper way(Common Display Framework,
47 * or some internal abstraction) should be considered, when it reaches a point
48 * that such thing is required.
51 struct xilinx_drm_private {
52 struct drm_device *drm;
53 struct drm_crtc *crtc;
54 struct drm_fb_helper *fb;
55 struct platform_device *pdev;
59 * struct xilinx_video_format_desc - Xilinx Video IP video format description
60 * @name: Xilinx video format name
62 * @bpp: bits per pixel
63 * @xilinx_format: xilinx format code
64 * @drm_format: drm format code
66 struct xilinx_video_format_desc {
70 unsigned int xilinx_format;
74 static const struct xilinx_video_format_desc xilinx_video_formats[] = {
75 { "yuv422", 16, 16, XILINX_VIDEO_FORMAT_YUV422, DRM_FORMAT_YUYV },
76 { "yuv444", 24, 24, XILINX_VIDEO_FORMAT_YUV444, DRM_FORMAT_YUV444 },
77 { "rgb888", 24, 24, XILINX_VIDEO_FORMAT_RGB, DRM_FORMAT_RGB888 },
78 { "yuv420", 16, 16, XILINX_VIDEO_FORMAT_YUV420, DRM_FORMAT_YUV420 },
79 { "xrgb8888", 24, 32, XILINX_VIDEO_FORMAT_XRGB, DRM_FORMAT_XRGB8888 },
80 { "rgba8888", 32, 32, XILINX_VIDEO_FORMAT_NONE, DRM_FORMAT_RGBA8888 },
81 { "rgb565", 16, 16, XILINX_VIDEO_FORMAT_NONE, DRM_FORMAT_RGB565 },
82 { "xbgr8888", 24, 32, XILINX_VIDEO_FORMAT_NONE, DRM_FORMAT_XBGR8888 },
83 { "abgr8888", 32, 32, XILINX_VIDEO_FORMAT_NONE, DRM_FORMAT_ABGR8888 },
87 * xilinx_drm_check_format - Check if the given format is supported
89 * @fourcc: format fourcc
91 * Check if the given format @fourcc is supported by the current pipeline
93 * Return: true if the format is supported, or false
95 bool xilinx_drm_check_format(struct drm_device *drm, uint32_t fourcc)
97 struct xilinx_drm_private *private = drm->dev_private;
99 return xilinx_drm_crtc_check_format(private->crtc, fourcc);
103 * xilinx_drm_get_format - Get the current device format
106 * Get the current format of pipeline
108 * Return: the corresponding DRM_FORMAT_XXX
110 uint32_t xilinx_drm_get_format(struct drm_device *drm)
112 struct xilinx_drm_private *private = drm->dev_private;
114 return xilinx_drm_crtc_get_format(private->crtc);
118 * xilinx_drm_get_align - Get the alignment value for pitch
121 * Get the alignment value for pitch from the plane
123 * Return: The alignment value if successful, or the error code.
125 unsigned int xilinx_drm_get_align(struct drm_device *drm)
127 struct xilinx_drm_private *private = drm->dev_private;
129 return xilinx_drm_crtc_get_align(private->crtc);
132 void xilinx_drm_set_config(struct drm_device *drm, struct drm_mode_set *set)
134 struct xilinx_drm_private *private = drm->dev_private;
136 if (private && private->fb)
137 xilinx_drm_fb_set_config(private->fb, set);
140 /* poll changed handler */
141 static void xilinx_drm_output_poll_changed(struct drm_device *drm)
143 struct xilinx_drm_private *private = drm->dev_private;
145 xilinx_drm_fb_hotplug_event(private->fb);
148 static const struct drm_mode_config_funcs xilinx_drm_mode_config_funcs = {
149 .fb_create = xilinx_drm_fb_create,
150 .output_poll_changed = xilinx_drm_output_poll_changed,
154 static int xilinx_drm_enable_vblank(struct drm_device *drm, unsigned int crtc)
156 struct xilinx_drm_private *private = drm->dev_private;
158 xilinx_drm_crtc_enable_vblank(private->crtc);
164 static void xilinx_drm_disable_vblank(struct drm_device *drm, unsigned int crtc)
166 struct xilinx_drm_private *private = drm->dev_private;
168 xilinx_drm_crtc_disable_vblank(private->crtc);
171 /* initialize mode config */
172 static void xilinx_drm_mode_config_init(struct drm_device *drm)
174 struct xilinx_drm_private *private = drm->dev_private;
176 drm->mode_config.min_width = 0;
177 drm->mode_config.min_height = 0;
179 drm->mode_config.max_width =
180 xilinx_drm_crtc_get_max_width(private->crtc);
181 drm->mode_config.max_height = 4096;
183 drm->mode_config.funcs = &xilinx_drm_mode_config_funcs;
186 /* convert xilinx format to drm format by code */
187 int xilinx_drm_format_by_code(unsigned int xilinx_format, uint32_t *drm_format)
189 const struct xilinx_video_format_desc *format;
192 for (i = 0; i < ARRAY_SIZE(xilinx_video_formats); i++) {
193 format = &xilinx_video_formats[i];
194 if (format->xilinx_format == xilinx_format) {
195 *drm_format = format->drm_format;
200 DRM_ERROR("Unknown Xilinx video format: %d\n", xilinx_format);
205 /* convert xilinx format to drm format by name */
206 int xilinx_drm_format_by_name(const char *name, uint32_t *drm_format)
208 const struct xilinx_video_format_desc *format;
211 for (i = 0; i < ARRAY_SIZE(xilinx_video_formats); i++) {
212 format = &xilinx_video_formats[i];
213 if (strcmp(format->name, name) == 0) {
214 *drm_format = format->drm_format;
219 DRM_ERROR("Unknown Xilinx video format: %s\n", name);
224 /* get bpp of given format */
225 unsigned int xilinx_drm_format_bpp(uint32_t drm_format)
227 const struct xilinx_video_format_desc *format;
230 for (i = 0; i < ARRAY_SIZE(xilinx_video_formats); i++) {
231 format = &xilinx_video_formats[i];
232 if (format->drm_format == drm_format)
239 /* get color depth of given format */
240 unsigned int xilinx_drm_format_depth(uint32_t drm_format)
242 const struct xilinx_video_format_desc *format;
245 for (i = 0; i < ARRAY_SIZE(xilinx_video_formats); i++) {
246 format = &xilinx_video_formats[i];
247 if (format->drm_format == drm_format)
248 return format->depth;
254 /* load xilinx drm */
255 static int xilinx_drm_load(struct drm_device *drm, unsigned long flags)
257 struct xilinx_drm_private *private;
258 struct drm_encoder *encoder;
259 struct drm_connector *connector;
260 struct device_node *encoder_node;
261 struct platform_device *pdev = drm->platformdev;
262 unsigned int bpp, align, i = 0;
265 private = devm_kzalloc(drm->dev, sizeof(*private), GFP_KERNEL);
269 drm_mode_config_init(drm);
271 /* create a xilinx crtc */
272 private->crtc = xilinx_drm_crtc_create(drm);
273 if (IS_ERR(private->crtc)) {
274 DRM_DEBUG_DRIVER("failed to create xilinx crtc\n");
275 ret = PTR_ERR(private->crtc);
279 while ((encoder_node = of_parse_phandle(drm->dev->of_node,
280 "xlnx,encoder-slave", i))) {
281 encoder = xilinx_drm_encoder_create(drm, encoder_node);
282 of_node_put(encoder_node);
283 if (IS_ERR(encoder)) {
284 DRM_DEBUG_DRIVER("failed to create xilinx encoder\n");
285 ret = PTR_ERR(encoder);
289 connector = xilinx_drm_connector_create(drm, encoder, i);
290 if (IS_ERR(connector)) {
291 DRM_DEBUG_DRIVER("failed to create xilinx connector\n");
292 ret = PTR_ERR(connector);
300 DRM_ERROR("failed to get an encoder slave node\n");
304 ret = drm_vblank_init(drm, 1);
306 dev_err(&pdev->dev, "failed to initialize vblank\n");
310 /* enable irq to enable vblank feature */
311 drm->irq_enabled = 1;
313 /* allow disable vblank */
314 drm->vblank_disable_allowed = 1;
316 drm->dev_private = private;
319 /* initialize xilinx framebuffer */
320 bpp = xilinx_drm_format_bpp(xilinx_drm_crtc_get_format(private->crtc));
321 align = xilinx_drm_crtc_get_align(private->crtc);
322 private->fb = xilinx_drm_fb_init(drm, bpp, 1, 1, align,
323 xilinx_drm_fbdev_vres);
324 if (IS_ERR(private->fb)) {
325 DRM_ERROR("failed to initialize drm cma fb\n");
326 ret = PTR_ERR(private->fb);
330 drm_kms_helper_poll_init(drm);
332 /* set up mode config for xilinx */
333 xilinx_drm_mode_config_init(drm);
335 drm_helper_disable_unused_functions(drm);
337 platform_set_drvdata(pdev, private);
342 drm_vblank_cleanup(drm);
344 drm_mode_config_cleanup(drm);
345 if (ret == -EPROBE_DEFER)
346 DRM_INFO("load() is defered & will be called again\n");
350 /* unload xilinx drm */
351 static int xilinx_drm_unload(struct drm_device *drm)
353 struct xilinx_drm_private *private = drm->dev_private;
355 drm_vblank_cleanup(drm);
357 drm_kms_helper_poll_fini(drm);
359 xilinx_drm_fb_fini(private->fb);
361 drm_mode_config_cleanup(drm);
367 static void xilinx_drm_preclose(struct drm_device *drm, struct drm_file *file)
369 struct xilinx_drm_private *private = drm->dev_private;
371 /* cancel pending page flip request */
372 xilinx_drm_crtc_cancel_page_flip(private->crtc, file);
375 /* restore the default mode when xilinx drm is released */
376 static void xilinx_drm_lastclose(struct drm_device *drm)
378 struct xilinx_drm_private *private = drm->dev_private;
380 xilinx_drm_crtc_restore(private->crtc);
382 xilinx_drm_fb_restore_mode(private->fb);
385 static const struct file_operations xilinx_drm_fops = {
386 .owner = THIS_MODULE,
388 .release = drm_release,
389 .unlocked_ioctl = drm_ioctl,
390 .mmap = drm_gem_cma_mmap,
394 .compat_ioctl = drm_compat_ioctl,
396 .llseek = noop_llseek,
399 static struct drm_driver xilinx_drm_driver = {
400 .driver_features = DRIVER_MODESET | DRIVER_GEM |
402 .load = xilinx_drm_load,
403 .unload = xilinx_drm_unload,
404 .preclose = xilinx_drm_preclose,
405 .lastclose = xilinx_drm_lastclose,
406 .set_busid = drm_platform_set_busid,
408 .get_vblank_counter = drm_vblank_no_hw_counter,
409 .enable_vblank = xilinx_drm_enable_vblank,
410 .disable_vblank = xilinx_drm_disable_vblank,
412 .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
413 .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
414 .gem_prime_export = drm_gem_prime_export,
415 .gem_prime_import = drm_gem_prime_import,
416 .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
417 .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
418 .gem_prime_vmap = drm_gem_cma_prime_vmap,
419 .gem_prime_vunmap = drm_gem_cma_prime_vunmap,
420 .gem_prime_mmap = drm_gem_cma_prime_mmap,
421 .gem_free_object = drm_gem_cma_free_object,
422 .gem_vm_ops = &drm_gem_cma_vm_ops,
423 .dumb_create = xilinx_drm_gem_cma_dumb_create,
424 .dumb_map_offset = drm_gem_cma_dumb_map_offset,
425 .dumb_destroy = drm_gem_dumb_destroy,
427 .fops = &xilinx_drm_fops,
432 .major = DRIVER_MAJOR,
433 .minor = DRIVER_MINOR,
436 #if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_RUNTIME)
437 /* suspend xilinx drm */
438 static int xilinx_drm_pm_suspend(struct device *dev)
440 struct xilinx_drm_private *private = dev_get_drvdata(dev);
441 struct drm_device *drm = private->drm;
442 struct drm_connector *connector;
444 drm_kms_helper_poll_disable(drm);
445 drm_modeset_lock_all(drm);
446 list_for_each_entry(connector, &drm->mode_config.connector_list, head) {
447 int old_dpms = connector->dpms;
449 if (connector->funcs->dpms)
450 connector->funcs->dpms(connector,
451 DRM_MODE_DPMS_SUSPEND);
453 connector->dpms = old_dpms;
455 drm_modeset_unlock_all(drm);
460 /* resume xilinx drm */
461 static int xilinx_drm_pm_resume(struct device *dev)
463 struct xilinx_drm_private *private = dev_get_drvdata(dev);
464 struct drm_device *drm = private->drm;
465 struct drm_connector *connector;
467 drm_modeset_lock_all(drm);
468 list_for_each_entry(connector, &drm->mode_config.connector_list, head) {
469 if (connector->funcs->dpms) {
470 int dpms = connector->dpms;
472 connector->dpms = DRM_MODE_DPMS_OFF;
473 connector->funcs->dpms(connector, dpms);
476 drm_kms_helper_poll_enable_locked(drm);
477 drm_modeset_unlock_all(drm);
483 static const struct dev_pm_ops xilinx_drm_pm_ops = {
484 SET_SYSTEM_SLEEP_PM_OPS(xilinx_drm_pm_suspend, xilinx_drm_pm_resume)
485 SET_RUNTIME_PM_OPS(xilinx_drm_pm_suspend, xilinx_drm_pm_resume, NULL)
488 /* init xilinx drm platform */
489 static int xilinx_drm_platform_probe(struct platform_device *pdev)
491 return drm_platform_init(&xilinx_drm_driver, pdev);
494 /* exit xilinx drm platform */
495 static int xilinx_drm_platform_remove(struct platform_device *pdev)
497 struct xilinx_drm_private *private = platform_get_drvdata(pdev);
499 drm_put_dev(private->drm);
504 static const struct of_device_id xilinx_drm_of_match[] = {
505 { .compatible = "xlnx,drm", },
506 { /* end of table */ },
508 MODULE_DEVICE_TABLE(of, xilinx_drm_of_match);
510 static struct platform_driver xilinx_drm_private_driver = {
511 .probe = xilinx_drm_platform_probe,
512 .remove = xilinx_drm_platform_remove,
514 .name = "xilinx-drm",
515 .pm = &xilinx_drm_pm_ops,
516 .of_match_table = xilinx_drm_of_match,
520 module_platform_driver(xilinx_drm_private_driver);
522 MODULE_AUTHOR("Xilinx, Inc.");
523 MODULE_DESCRIPTION("Xilinx DRM KMS Driver");
524 MODULE_LICENSE("GPL v2");