1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <drm/drmP.h>
19#include <drm/drm_crtc_helper.h>
20#include <drm/drm_gem_cma_helper.h>
21
22#include <linux/component.h>
23#include <linux/device.h>
24#include <linux/module.h>
25#include <linux/of_graph.h>
26#include <linux/platform_device.h>
27
28#include "xilinx_drm_connector.h"
29#include "xilinx_drm_crtc.h"
30#include "xilinx_drm_drv.h"
31#include "xilinx_drm_encoder.h"
32#include "xilinx_drm_fb.h"
33#include "xilinx_drm_gem.h"
34
35#define DRIVER_NAME "xilinx_drm"
36#define DRIVER_DESC "Xilinx DRM KMS support for Xilinx"
37#define DRIVER_DATE "20130509"
38#define DRIVER_MAJOR 1
39#define DRIVER_MINOR 0
40
41static uint xilinx_drm_fbdev_vres = 2;
42module_param_named(fbdev_vres, xilinx_drm_fbdev_vres, uint, 0444);
43MODULE_PARM_DESC(fbdev_vres,
44 "fbdev virtual resolution multiplier for fb (default: 2)");
45
46
47
48
49
50
51
52
53struct xilinx_drm_private {
54 struct drm_device *drm;
55 struct drm_crtc *crtc;
56 struct drm_fb_helper *fb;
57 struct platform_device *pdev;
58 bool is_master;
59};
60
61
62
63
64
65
66
67
68
69struct xilinx_video_format_desc {
70 const char *name;
71 unsigned int depth;
72 unsigned int bpp;
73 unsigned int xilinx_format;
74 u32 drm_format;
75};
76
77static const struct xilinx_video_format_desc xilinx_video_formats[] = {
78 { "yuv420", 16, 16, XILINX_VIDEO_FORMAT_YUV420, DRM_FORMAT_YUV420 },
79 { "uvy422", 16, 16, XILINX_VIDEO_FORMAT_NONE, DRM_FORMAT_UYVY },
80 { "vuy422", 16, 16, XILINX_VIDEO_FORMAT_YUV422, DRM_FORMAT_VYUY },
81 { "yuv422", 16, 16, XILINX_VIDEO_FORMAT_YUV422, DRM_FORMAT_YUYV },
82 { "yvu422", 16, 16, XILINX_VIDEO_FORMAT_NONE, DRM_FORMAT_YVYU },
83 { "yuv444", 24, 24, XILINX_VIDEO_FORMAT_YUV444, DRM_FORMAT_YUV444 },
84 { "nv12", 16, 16, XILINX_VIDEO_FORMAT_NONE, DRM_FORMAT_NV12 },
85 { "nv21", 16, 16, XILINX_VIDEO_FORMAT_NONE, DRM_FORMAT_NV21 },
86 { "nv16", 16, 16, XILINX_VIDEO_FORMAT_NONE, DRM_FORMAT_NV16 },
87 { "nv61", 16, 16, XILINX_VIDEO_FORMAT_NONE, DRM_FORMAT_NV61 },
88 { "abgr1555", 16, 16, XILINX_VIDEO_FORMAT_NONE, DRM_FORMAT_ABGR1555 },
89 { "argb1555", 16, 16, XILINX_VIDEO_FORMAT_NONE, DRM_FORMAT_ARGB1555 },
90 { "rgba4444", 16, 16, XILINX_VIDEO_FORMAT_NONE, DRM_FORMAT_RGBA4444 },
91 { "bgra4444", 16, 16, XILINX_VIDEO_FORMAT_NONE, DRM_FORMAT_BGRA4444 },
92 { "bgr565", 16, 16, XILINX_VIDEO_FORMAT_NONE, DRM_FORMAT_BGR565 },
93 { "rgb565", 16, 16, XILINX_VIDEO_FORMAT_NONE, DRM_FORMAT_RGB565 },
94 { "bgr888", 24, 24, XILINX_VIDEO_FORMAT_RGB, DRM_FORMAT_BGR888 },
95 { "rgb888", 24, 24, XILINX_VIDEO_FORMAT_RGB, DRM_FORMAT_RGB888 },
96 { "xbgr8888", 24, 32, XILINX_VIDEO_FORMAT_NONE, DRM_FORMAT_XBGR8888 },
97 { "xrgb8888", 24, 32, XILINX_VIDEO_FORMAT_XRGB, DRM_FORMAT_XRGB8888 },
98 { "abgr8888", 32, 32, XILINX_VIDEO_FORMAT_NONE, DRM_FORMAT_ABGR8888 },
99 { "argb8888", 32, 32, XILINX_VIDEO_FORMAT_NONE, DRM_FORMAT_ARGB8888 },
100 { "bgra8888", 32, 32, XILINX_VIDEO_FORMAT_NONE, DRM_FORMAT_BGRA8888 },
101 { "rgba8888", 32, 32, XILINX_VIDEO_FORMAT_NONE, DRM_FORMAT_RGBA8888 },
102};
103
104
105
106
107
108
109
110
111
112
113bool xilinx_drm_check_format(struct drm_device *drm, u32 fourcc)
114{
115 struct xilinx_drm_private *private = drm->dev_private;
116
117 return xilinx_drm_crtc_check_format(private->crtc, fourcc);
118}
119
120
121
122
123
124
125
126
127
128u32 xilinx_drm_get_format(struct drm_device *drm)
129{
130 struct xilinx_drm_private *private = drm->dev_private;
131
132 return xilinx_drm_crtc_get_format(private->crtc);
133}
134
135
136
137
138
139
140
141
142
143unsigned int xilinx_drm_get_align(struct drm_device *drm)
144{
145 struct xilinx_drm_private *private = drm->dev_private;
146
147 return xilinx_drm_crtc_get_align(private->crtc);
148}
149
150
151static void xilinx_drm_output_poll_changed(struct drm_device *drm)
152{
153 struct xilinx_drm_private *private = drm->dev_private;
154
155 xilinx_drm_fb_hotplug_event(private->fb);
156}
157
158static const struct drm_mode_config_funcs xilinx_drm_mode_config_funcs = {
159 .fb_create = xilinx_drm_fb_create,
160 .output_poll_changed = xilinx_drm_output_poll_changed,
161};
162
163
164static int xilinx_drm_enable_vblank(struct drm_device *drm, unsigned int crtc)
165{
166 struct xilinx_drm_private *private = drm->dev_private;
167
168 xilinx_drm_crtc_enable_vblank(private->crtc);
169
170 return 0;
171}
172
173
174static void xilinx_drm_disable_vblank(struct drm_device *drm, unsigned int crtc)
175{
176 struct xilinx_drm_private *private = drm->dev_private;
177
178 xilinx_drm_crtc_disable_vblank(private->crtc);
179}
180
181
182static void xilinx_drm_mode_config_init(struct drm_device *drm)
183{
184 struct xilinx_drm_private *private = drm->dev_private;
185
186 drm->mode_config.min_width = 0;
187 drm->mode_config.min_height = 0;
188
189 drm->mode_config.max_width =
190 xilinx_drm_crtc_get_max_width(private->crtc);
191 drm->mode_config.max_height = 4096;
192
193 drm->mode_config.funcs = &xilinx_drm_mode_config_funcs;
194}
195
196
197int xilinx_drm_format_by_code(unsigned int xilinx_format, u32 *drm_format)
198{
199 const struct xilinx_video_format_desc *format;
200 unsigned int i;
201
202 for (i = 0; i < ARRAY_SIZE(xilinx_video_formats); i++) {
203 format = &xilinx_video_formats[i];
204 if (format->xilinx_format == xilinx_format) {
205 *drm_format = format->drm_format;
206 return 0;
207 }
208 }
209
210 DRM_ERROR("Unknown Xilinx video format: %d\n", xilinx_format);
211
212 return -EINVAL;
213}
214
215
216int xilinx_drm_format_by_name(const char *name, u32 *drm_format)
217{
218 const struct xilinx_video_format_desc *format;
219 unsigned int i;
220
221 for (i = 0; i < ARRAY_SIZE(xilinx_video_formats); i++) {
222 format = &xilinx_video_formats[i];
223 if (strcmp(format->name, name) == 0) {
224 *drm_format = format->drm_format;
225 return 0;
226 }
227 }
228
229 DRM_ERROR("Unknown Xilinx video format: %s\n", name);
230
231 return -EINVAL;
232}
233
234
235unsigned int xilinx_drm_format_bpp(u32 drm_format)
236{
237 const struct xilinx_video_format_desc *format;
238 unsigned int i;
239
240 for (i = 0; i < ARRAY_SIZE(xilinx_video_formats); i++) {
241 format = &xilinx_video_formats[i];
242 if (format->drm_format == drm_format)
243 return format->bpp;
244 }
245
246 return 0;
247}
248
249
250unsigned int xilinx_drm_format_depth(u32 drm_format)
251{
252 const struct xilinx_video_format_desc *format;
253 unsigned int i;
254
255 for (i = 0; i < ARRAY_SIZE(xilinx_video_formats); i++) {
256 format = &xilinx_video_formats[i];
257 if (format->drm_format == drm_format)
258 return format->depth;
259 }
260
261 return 0;
262}
263
264static int xilinx_drm_bind(struct device *dev)
265{
266 struct xilinx_drm_private *private = dev_get_drvdata(dev);
267 struct drm_device *drm = private->drm;
268
269 return component_bind_all(dev, drm);
270}
271
272static void xilinx_drm_unbind(struct device *dev)
273{
274 dev_set_drvdata(dev, NULL);
275}
276
277static const struct component_master_ops xilinx_drm_ops = {
278 .bind = xilinx_drm_bind,
279 .unbind = xilinx_drm_unbind,
280};
281
282static int compare_of(struct device *dev, void *data)
283{
284 struct device_node *np = data;
285
286 return dev->of_node == np;
287}
288
289static int xilinx_drm_open(struct drm_device *dev, struct drm_file *file)
290{
291 struct xilinx_drm_private *private = dev->dev_private;
292
293
294 if (!(drm_is_primary_client(file) && !dev->master) &&
295 !file->is_master && capable(CAP_SYS_ADMIN)) {
296 file->is_master = 1;
297 private->is_master = true;
298 }
299
300 return 0;
301}
302
303static int xilinx_drm_release(struct inode *inode, struct file *filp)
304{
305 struct drm_file *file = filp->private_data;
306 struct drm_minor *minor = file->minor;
307 struct drm_device *drm = minor->dev;
308 struct xilinx_drm_private *private = drm->dev_private;
309
310 if (private->is_master) {
311 private->is_master = false;
312 file->is_master = 0;
313 }
314
315 return drm_release(inode, filp);
316}
317
318
319static void xilinx_drm_lastclose(struct drm_device *drm)
320{
321 struct xilinx_drm_private *private = drm->dev_private;
322
323 xilinx_drm_crtc_restore(private->crtc);
324
325 xilinx_drm_fb_restore_mode(private->fb);
326}
327
328static const struct file_operations xilinx_drm_fops = {
329 .owner = THIS_MODULE,
330 .open = drm_open,
331 .release = xilinx_drm_release,
332 .unlocked_ioctl = drm_ioctl,
333 .mmap = drm_gem_cma_mmap,
334 .poll = drm_poll,
335 .read = drm_read,
336#ifdef CONFIG_COMPAT
337 .compat_ioctl = drm_compat_ioctl,
338#endif
339 .llseek = noop_llseek,
340};
341
342static struct drm_driver xilinx_drm_driver = {
343 .driver_features = DRIVER_MODESET | DRIVER_GEM |
344 DRIVER_PRIME | DRIVER_LEGACY,
345 .open = xilinx_drm_open,
346 .lastclose = xilinx_drm_lastclose,
347
348 .enable_vblank = xilinx_drm_enable_vblank,
349 .disable_vblank = xilinx_drm_disable_vblank,
350
351 .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
352 .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
353 .gem_prime_export = drm_gem_prime_export,
354 .gem_prime_import = drm_gem_prime_import,
355 .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
356 .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
357 .gem_prime_vmap = drm_gem_cma_prime_vmap,
358 .gem_prime_vunmap = drm_gem_cma_prime_vunmap,
359 .gem_prime_mmap = drm_gem_cma_prime_mmap,
360 .gem_free_object = drm_gem_cma_free_object,
361 .gem_vm_ops = &drm_gem_cma_vm_ops,
362 .dumb_create = xilinx_drm_gem_cma_dumb_create,
363
364 .fops = &xilinx_drm_fops,
365
366 .name = DRIVER_NAME,
367 .desc = DRIVER_DESC,
368 .date = DRIVER_DATE,
369 .major = DRIVER_MAJOR,
370 .minor = DRIVER_MINOR,
371};
372
373#if defined(CONFIG_PM_SLEEP)
374
375static int xilinx_drm_pm_suspend(struct device *dev)
376{
377 struct xilinx_drm_private *private = dev_get_drvdata(dev);
378 struct drm_device *drm = private->drm;
379 struct drm_connector *connector;
380
381 drm_kms_helper_poll_disable(drm);
382 drm_modeset_lock_all(drm);
383 list_for_each_entry(connector, &drm->mode_config.connector_list, head) {
384 int old_dpms = connector->dpms;
385
386 if (connector->funcs->dpms)
387 connector->funcs->dpms(connector,
388 DRM_MODE_DPMS_SUSPEND);
389
390 connector->dpms = old_dpms;
391 }
392 drm_modeset_unlock_all(drm);
393
394 return 0;
395}
396
397
398static int xilinx_drm_pm_resume(struct device *dev)
399{
400 struct xilinx_drm_private *private = dev_get_drvdata(dev);
401 struct drm_device *drm = private->drm;
402 struct drm_connector *connector;
403
404 drm_modeset_lock_all(drm);
405 list_for_each_entry(connector, &drm->mode_config.connector_list, head) {
406 if (connector->funcs->dpms) {
407 int dpms = connector->dpms;
408
409 connector->dpms = DRM_MODE_DPMS_OFF;
410 connector->funcs->dpms(connector, dpms);
411 }
412 }
413 drm_modeset_unlock_all(drm);
414
415 drm_helper_resume_force_mode(drm);
416
417 drm_modeset_lock_all(drm);
418 drm_kms_helper_poll_enable(drm);
419 drm_modeset_unlock_all(drm);
420
421 return 0;
422}
423#endif
424
425static const struct dev_pm_ops xilinx_drm_pm_ops = {
426 SET_SYSTEM_SLEEP_PM_OPS(xilinx_drm_pm_suspend, xilinx_drm_pm_resume)
427};
428
429
430static int xilinx_drm_platform_probe(struct platform_device *pdev)
431{
432 struct xilinx_drm_private *private;
433 struct drm_device *drm;
434 struct drm_encoder *encoder;
435 struct drm_connector *connector;
436 const struct drm_format_info *info;
437 struct device_node *encoder_node, *ep = NULL, *remote;
438 struct component_match *match = NULL;
439 unsigned int align, i = 0;
440 int ret;
441 u32 format;
442
443 drm = drm_dev_alloc(&xilinx_drm_driver, &pdev->dev);
444 if (IS_ERR(drm))
445 return PTR_ERR(drm);
446
447 private = devm_kzalloc(drm->dev, sizeof(*private), GFP_KERNEL);
448 if (!private) {
449 ret = -ENOMEM;
450 goto err_drm;
451 }
452
453 drm_mode_config_init(drm);
454
455
456 private->crtc = xilinx_drm_crtc_create(drm);
457 if (IS_ERR(private->crtc)) {
458 DRM_DEBUG_DRIVER("failed to create xilinx crtc\n");
459 ret = PTR_ERR(private->crtc);
460 goto err_config;
461 }
462
463 while ((encoder_node = of_parse_phandle(drm->dev->of_node,
464 "xlnx,encoder-slave", i))) {
465 encoder = xilinx_drm_encoder_create(drm, encoder_node);
466 of_node_put(encoder_node);
467 if (IS_ERR(encoder)) {
468 DRM_DEBUG_DRIVER("failed to create xilinx encoder\n");
469 ret = PTR_ERR(encoder);
470 goto err_config;
471 }
472
473 connector = xilinx_drm_connector_create(drm, encoder, i);
474 if (IS_ERR(connector)) {
475 DRM_DEBUG_DRIVER("failed to create xilinx connector\n");
476 ret = PTR_ERR(connector);
477 goto err_config;
478 }
479
480 i++;
481 }
482
483 while (1) {
484 ep = of_graph_get_next_endpoint(drm->dev->of_node, ep);
485 if (!ep)
486 break;
487
488 of_node_put(ep);
489 remote = of_graph_get_remote_port_parent(ep);
490 if (!remote || !of_device_is_available(remote)) {
491 of_node_put(remote);
492 continue;
493 }
494
495 component_match_add(drm->dev, &match, compare_of, remote);
496 of_node_put(remote);
497 i++;
498 }
499
500 if (i == 0) {
501 DRM_ERROR("failed to get an encoder slave node\n");
502 return -ENODEV;
503 }
504
505 ret = drm_vblank_init(drm, 1);
506 if (ret) {
507 dev_err(&pdev->dev, "failed to initialize vblank\n");
508 goto err_master;
509 }
510
511
512 drm->irq_enabled = 1;
513
514 drm->dev_private = private;
515 private->drm = drm;
516 xilinx_drm_mode_config_init(drm);
517
518 format = xilinx_drm_crtc_get_format(private->crtc);
519 info = drm_format_info(format);
520 if (info && info->depth && info->cpp[0]) {
521 align = xilinx_drm_crtc_get_align(private->crtc);
522 private->fb = xilinx_drm_fb_init(drm, info->cpp[0] * 8, 1,
523 align, xilinx_drm_fbdev_vres);
524 if (IS_ERR(private->fb)) {
525 DRM_ERROR("failed to initialize drm fb\n");
526 private->fb = NULL;
527 }
528 } else {
529 dev_info(&pdev->dev, "fbdev is not initialized\n");
530 }
531
532 drm_kms_helper_poll_init(drm);
533
534 drm_helper_disable_unused_functions(drm);
535
536 platform_set_drvdata(pdev, private);
537
538 if (match) {
539 ret = component_master_add_with_match(drm->dev,
540 &xilinx_drm_ops, match);
541 if (ret)
542 goto err_master;
543 }
544
545 ret = dma_set_coherent_mask(&pdev->dev,
546 DMA_BIT_MASK(sizeof(dma_addr_t) * 8));
547 if (ret) {
548 dev_info(&pdev->dev, "failed to set coherent mask (%zu)\n",
549 sizeof(dma_addr_t));
550 }
551
552 ret = drm_dev_register(drm, 0);
553 if (ret < 0)
554 goto err_master;
555
556 return 0;
557
558err_master:
559 component_master_del(drm->dev, &xilinx_drm_ops);
560err_config:
561 drm_mode_config_cleanup(drm);
562 if (ret == -EPROBE_DEFER)
563 DRM_INFO("load() is defered & will be called again\n");
564err_drm:
565 drm_dev_unref(drm);
566 return ret;
567}
568
569
570static int xilinx_drm_platform_remove(struct platform_device *pdev)
571{
572 struct xilinx_drm_private *private = platform_get_drvdata(pdev);
573 struct drm_device *drm = private->drm;
574
575 component_master_del(drm->dev, &xilinx_drm_ops);
576 drm_kms_helper_poll_fini(drm);
577 xilinx_drm_fb_fini(private->fb);
578 drm_mode_config_cleanup(drm);
579 drm->dev_private = NULL;
580 drm_dev_unref(private->drm);
581
582 return 0;
583}
584
585static void xilinx_drm_platform_shutdown(struct platform_device *pdev)
586{
587 struct xilinx_drm_private *private = platform_get_drvdata(pdev);
588
589 drm_put_dev(private->drm);
590}
591
592static const struct of_device_id xilinx_drm_of_match[] = {
593 { .compatible = "xlnx,drm", },
594 { },
595};
596MODULE_DEVICE_TABLE(of, xilinx_drm_of_match);
597
598static struct platform_driver xilinx_drm_private_driver = {
599 .probe = xilinx_drm_platform_probe,
600 .remove = xilinx_drm_platform_remove,
601 .shutdown = xilinx_drm_platform_shutdown,
602 .driver = {
603 .name = "xilinx-drm",
604 .pm = &xilinx_drm_pm_ops,
605 .of_match_table = xilinx_drm_of_match,
606 },
607};
608
609module_platform_driver(xilinx_drm_private_driver);
610
611MODULE_AUTHOR("Xilinx, Inc.");
612MODULE_DESCRIPTION("Xilinx DRM KMS Driver");
613MODULE_LICENSE("GPL v2");
614