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