Merge branch 'upstream' of git://git.infradead.org/users/pcmoore/audit
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / exynos / exynos_drm_vidi.c
1 /* exynos_drm_vidi.c
2  *
3  * Copyright (C) 2012 Samsung Electronics Co.Ltd
4  * Authors:
5  *      Inki Dae <inki.dae@samsung.com>
6  *
7  * This program is free software; you can redistribute  it and/or modify it
8  * under  the terms of  the GNU General  Public License as published by the
9  * Free Software Foundation;  either version 2 of the  License, or (at your
10  * option) any later version.
11  *
12  */
13 #include <drm/drmP.h>
14
15 #include <linux/kernel.h>
16 #include <linux/platform_device.h>
17 #include <linux/component.h>
18
19 #include <drm/exynos_drm.h>
20
21 #include <drm/drm_edid.h>
22 #include <drm/drm_crtc_helper.h>
23
24 #include "exynos_drm_drv.h"
25 #include "exynos_drm_crtc.h"
26 #include "exynos_drm_encoder.h"
27 #include "exynos_drm_vidi.h"
28
29 /* vidi has totally three virtual windows. */
30 #define WINDOWS_NR              3
31
32 #define ctx_from_connector(c)   container_of(c, struct vidi_context, \
33                                         connector)
34
35 struct vidi_win_data {
36         unsigned int            offset_x;
37         unsigned int            offset_y;
38         unsigned int            ovl_width;
39         unsigned int            ovl_height;
40         unsigned int            fb_width;
41         unsigned int            fb_height;
42         unsigned int            bpp;
43         dma_addr_t              dma_addr;
44         unsigned int            buf_offsize;
45         unsigned int            line_size;      /* bytes */
46         bool                    enabled;
47 };
48
49 struct vidi_context {
50         struct exynos_drm_manager       manager;
51         struct exynos_drm_display       display;
52         struct platform_device          *pdev;
53         struct drm_device               *drm_dev;
54         struct drm_crtc                 *crtc;
55         struct drm_encoder              *encoder;
56         struct drm_connector            connector;
57         struct vidi_win_data            win_data[WINDOWS_NR];
58         struct edid                     *raw_edid;
59         unsigned int                    clkdiv;
60         unsigned int                    default_win;
61         unsigned long                   irq_flags;
62         unsigned int                    connected;
63         bool                            vblank_on;
64         bool                            suspended;
65         bool                            direct_vblank;
66         struct work_struct              work;
67         struct mutex                    lock;
68         int                             pipe;
69 };
70
71 static inline struct vidi_context *manager_to_vidi(struct exynos_drm_manager *m)
72 {
73         return container_of(m, struct vidi_context, manager);
74 }
75
76 static inline struct vidi_context *display_to_vidi(struct exynos_drm_display *d)
77 {
78         return container_of(d, struct vidi_context, display);
79 }
80
81 static const char fake_edid_info[] = {
82         0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x4c, 0x2d, 0x05, 0x05,
83         0x00, 0x00, 0x00, 0x00, 0x30, 0x12, 0x01, 0x03, 0x80, 0x10, 0x09, 0x78,
84         0x0a, 0xee, 0x91, 0xa3, 0x54, 0x4c, 0x99, 0x26, 0x0f, 0x50, 0x54, 0xbd,
85         0xee, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
86         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x66, 0x21, 0x50, 0xb0, 0x51, 0x00,
87         0x1b, 0x30, 0x40, 0x70, 0x36, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e,
88         0x01, 0x1d, 0x00, 0x72, 0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00,
89         0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x18,
90         0x4b, 0x1a, 0x44, 0x17, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
91         0x00, 0x00, 0x00, 0xfc, 0x00, 0x53, 0x41, 0x4d, 0x53, 0x55, 0x4e, 0x47,
92         0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0xbc, 0x02, 0x03, 0x1e, 0xf1,
93         0x46, 0x84, 0x05, 0x03, 0x10, 0x20, 0x22, 0x23, 0x09, 0x07, 0x07, 0x83,
94         0x01, 0x00, 0x00, 0xe2, 0x00, 0x0f, 0x67, 0x03, 0x0c, 0x00, 0x10, 0x00,
95         0xb8, 0x2d, 0x01, 0x1d, 0x80, 0x18, 0x71, 0x1c, 0x16, 0x20, 0x58, 0x2c,
96         0x25, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x9e, 0x8c, 0x0a, 0xd0, 0x8a,
97         0x20, 0xe0, 0x2d, 0x10, 0x10, 0x3e, 0x96, 0x00, 0xa0, 0x5a, 0x00, 0x00,
98         0x00, 0x18, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
99         0x45, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
100         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
103         0x00, 0x00, 0x00, 0x06
104 };
105
106 static void vidi_apply(struct exynos_drm_manager *mgr)
107 {
108         struct vidi_context *ctx = manager_to_vidi(mgr);
109         struct exynos_drm_manager_ops *mgr_ops = mgr->ops;
110         struct vidi_win_data *win_data;
111         int i;
112
113         for (i = 0; i < WINDOWS_NR; i++) {
114                 win_data = &ctx->win_data[i];
115                 if (win_data->enabled && (mgr_ops && mgr_ops->win_commit))
116                         mgr_ops->win_commit(mgr, i);
117         }
118
119         if (mgr_ops && mgr_ops->commit)
120                 mgr_ops->commit(mgr);
121 }
122
123 static void vidi_commit(struct exynos_drm_manager *mgr)
124 {
125         struct vidi_context *ctx = manager_to_vidi(mgr);
126
127         if (ctx->suspended)
128                 return;
129 }
130
131 static int vidi_enable_vblank(struct exynos_drm_manager *mgr)
132 {
133         struct vidi_context *ctx = manager_to_vidi(mgr);
134
135         if (ctx->suspended)
136                 return -EPERM;
137
138         if (!test_and_set_bit(0, &ctx->irq_flags))
139                 ctx->vblank_on = true;
140
141         ctx->direct_vblank = true;
142
143         /*
144          * in case of page flip request, vidi_finish_pageflip function
145          * will not be called because direct_vblank is true and then
146          * that function will be called by manager_ops->win_commit callback
147          */
148         schedule_work(&ctx->work);
149
150         return 0;
151 }
152
153 static void vidi_disable_vblank(struct exynos_drm_manager *mgr)
154 {
155         struct vidi_context *ctx = manager_to_vidi(mgr);
156
157         if (ctx->suspended)
158                 return;
159
160         if (test_and_clear_bit(0, &ctx->irq_flags))
161                 ctx->vblank_on = false;
162 }
163
164 static void vidi_win_mode_set(struct exynos_drm_manager *mgr,
165                         struct exynos_drm_overlay *overlay)
166 {
167         struct vidi_context *ctx = manager_to_vidi(mgr);
168         struct vidi_win_data *win_data;
169         int win;
170         unsigned long offset;
171
172         if (!overlay) {
173                 DRM_ERROR("overlay is NULL\n");
174                 return;
175         }
176
177         win = overlay->zpos;
178         if (win == DEFAULT_ZPOS)
179                 win = ctx->default_win;
180
181         if (win < 0 || win >= WINDOWS_NR)
182                 return;
183
184         offset = overlay->fb_x * (overlay->bpp >> 3);
185         offset += overlay->fb_y * overlay->pitch;
186
187         DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, overlay->pitch);
188
189         win_data = &ctx->win_data[win];
190
191         win_data->offset_x = overlay->crtc_x;
192         win_data->offset_y = overlay->crtc_y;
193         win_data->ovl_width = overlay->crtc_width;
194         win_data->ovl_height = overlay->crtc_height;
195         win_data->fb_width = overlay->fb_width;
196         win_data->fb_height = overlay->fb_height;
197         win_data->dma_addr = overlay->dma_addr[0] + offset;
198         win_data->bpp = overlay->bpp;
199         win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
200                                 (overlay->bpp >> 3);
201         win_data->line_size = overlay->crtc_width * (overlay->bpp >> 3);
202
203         /*
204          * some parts of win_data should be transferred to user side
205          * through specific ioctl.
206          */
207
208         DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
209                         win_data->offset_x, win_data->offset_y);
210         DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
211                         win_data->ovl_width, win_data->ovl_height);
212         DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
213         DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
214                         overlay->fb_width, overlay->crtc_width);
215 }
216
217 static void vidi_win_commit(struct exynos_drm_manager *mgr, int zpos)
218 {
219         struct vidi_context *ctx = manager_to_vidi(mgr);
220         struct vidi_win_data *win_data;
221         int win = zpos;
222
223         if (ctx->suspended)
224                 return;
225
226         if (win == DEFAULT_ZPOS)
227                 win = ctx->default_win;
228
229         if (win < 0 || win >= WINDOWS_NR)
230                 return;
231
232         win_data = &ctx->win_data[win];
233
234         win_data->enabled = true;
235
236         DRM_DEBUG_KMS("dma_addr = %pad\n", &win_data->dma_addr);
237
238         if (ctx->vblank_on)
239                 schedule_work(&ctx->work);
240 }
241
242 static void vidi_win_disable(struct exynos_drm_manager *mgr, int zpos)
243 {
244         struct vidi_context *ctx = manager_to_vidi(mgr);
245         struct vidi_win_data *win_data;
246         int win = zpos;
247
248         if (win == DEFAULT_ZPOS)
249                 win = ctx->default_win;
250
251         if (win < 0 || win >= WINDOWS_NR)
252                 return;
253
254         win_data = &ctx->win_data[win];
255         win_data->enabled = false;
256
257         /* TODO. */
258 }
259
260 static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable)
261 {
262         struct vidi_context *ctx = manager_to_vidi(mgr);
263
264         DRM_DEBUG_KMS("%s\n", __FILE__);
265
266         if (enable != false && enable != true)
267                 return -EINVAL;
268
269         if (enable) {
270                 ctx->suspended = false;
271
272                 /* if vblank was enabled status, enable it again. */
273                 if (test_and_clear_bit(0, &ctx->irq_flags))
274                         vidi_enable_vblank(mgr);
275
276                 vidi_apply(mgr);
277         } else {
278                 ctx->suspended = true;
279         }
280
281         return 0;
282 }
283
284 static void vidi_dpms(struct exynos_drm_manager *mgr, int mode)
285 {
286         struct vidi_context *ctx = manager_to_vidi(mgr);
287
288         DRM_DEBUG_KMS("%d\n", mode);
289
290         mutex_lock(&ctx->lock);
291
292         switch (mode) {
293         case DRM_MODE_DPMS_ON:
294                 vidi_power_on(mgr, true);
295                 break;
296         case DRM_MODE_DPMS_STANDBY:
297         case DRM_MODE_DPMS_SUSPEND:
298         case DRM_MODE_DPMS_OFF:
299                 vidi_power_on(mgr, false);
300                 break;
301         default:
302                 DRM_DEBUG_KMS("unspecified mode %d\n", mode);
303                 break;
304         }
305
306         mutex_unlock(&ctx->lock);
307 }
308
309 static int vidi_mgr_initialize(struct exynos_drm_manager *mgr,
310                         struct drm_device *drm_dev)
311 {
312         struct vidi_context *ctx = manager_to_vidi(mgr);
313         struct exynos_drm_private *priv = drm_dev->dev_private;
314
315         mgr->drm_dev = ctx->drm_dev = drm_dev;
316         mgr->pipe = ctx->pipe = priv->pipe++;
317
318         return 0;
319 }
320
321 static struct exynos_drm_manager_ops vidi_manager_ops = {
322         .dpms = vidi_dpms,
323         .commit = vidi_commit,
324         .enable_vblank = vidi_enable_vblank,
325         .disable_vblank = vidi_disable_vblank,
326         .win_mode_set = vidi_win_mode_set,
327         .win_commit = vidi_win_commit,
328         .win_disable = vidi_win_disable,
329 };
330
331 static void vidi_fake_vblank_handler(struct work_struct *work)
332 {
333         struct vidi_context *ctx = container_of(work, struct vidi_context,
334                                         work);
335
336         if (ctx->pipe < 0)
337                 return;
338
339         /* refresh rate is about 50Hz. */
340         usleep_range(16000, 20000);
341
342         mutex_lock(&ctx->lock);
343
344         if (ctx->direct_vblank) {
345                 drm_handle_vblank(ctx->drm_dev, ctx->pipe);
346                 ctx->direct_vblank = false;
347                 mutex_unlock(&ctx->lock);
348                 return;
349         }
350
351         mutex_unlock(&ctx->lock);
352
353         exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
354 }
355
356 static int vidi_show_connection(struct device *dev,
357                                 struct device_attribute *attr, char *buf)
358 {
359         struct vidi_context *ctx = dev_get_drvdata(dev);
360         int rc;
361
362         mutex_lock(&ctx->lock);
363
364         rc = sprintf(buf, "%d\n", ctx->connected);
365
366         mutex_unlock(&ctx->lock);
367
368         return rc;
369 }
370
371 static int vidi_store_connection(struct device *dev,
372                                 struct device_attribute *attr,
373                                 const char *buf, size_t len)
374 {
375         struct vidi_context *ctx = dev_get_drvdata(dev);
376         int ret;
377
378         ret = kstrtoint(buf, 0, &ctx->connected);
379         if (ret)
380                 return ret;
381
382         if (ctx->connected > 1)
383                 return -EINVAL;
384
385         /* use fake edid data for test. */
386         if (!ctx->raw_edid)
387                 ctx->raw_edid = (struct edid *)fake_edid_info;
388
389         /* if raw_edid isn't same as fake data then it can't be tested. */
390         if (ctx->raw_edid != (struct edid *)fake_edid_info) {
391                 DRM_DEBUG_KMS("edid data is not fake data.\n");
392                 return -EINVAL;
393         }
394
395         DRM_DEBUG_KMS("requested connection.\n");
396
397         drm_helper_hpd_irq_event(ctx->drm_dev);
398
399         return len;
400 }
401
402 static DEVICE_ATTR(connection, 0644, vidi_show_connection,
403                         vidi_store_connection);
404
405 int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
406                                 struct drm_file *file_priv)
407 {
408         struct vidi_context *ctx = NULL;
409         struct drm_encoder *encoder;
410         struct exynos_drm_display *display;
411         struct drm_exynos_vidi_connection *vidi = data;
412
413         if (!vidi) {
414                 DRM_DEBUG_KMS("user data for vidi is null.\n");
415                 return -EINVAL;
416         }
417
418         if (vidi->connection > 1) {
419                 DRM_DEBUG_KMS("connection should be 0 or 1.\n");
420                 return -EINVAL;
421         }
422
423         list_for_each_entry(encoder, &drm_dev->mode_config.encoder_list,
424                                                                 head) {
425                 display = exynos_drm_get_display(encoder);
426
427                 if (display->type == EXYNOS_DISPLAY_TYPE_VIDI) {
428                         ctx = display_to_vidi(display);
429                         break;
430                 }
431         }
432
433         if (!ctx) {
434                 DRM_DEBUG_KMS("not found virtual device type encoder.\n");
435                 return -EINVAL;
436         }
437
438         if (ctx->connected == vidi->connection) {
439                 DRM_DEBUG_KMS("same connection request.\n");
440                 return -EINVAL;
441         }
442
443         if (vidi->connection) {
444                 struct edid *raw_edid  = (struct edid *)(uint32_t)vidi->edid;
445                 if (!drm_edid_is_valid(raw_edid)) {
446                         DRM_DEBUG_KMS("edid data is invalid.\n");
447                         return -EINVAL;
448                 }
449                 ctx->raw_edid = drm_edid_duplicate(raw_edid);
450                 if (!ctx->raw_edid) {
451                         DRM_DEBUG_KMS("failed to allocate raw_edid.\n");
452                         return -ENOMEM;
453                 }
454         } else {
455                 /*
456                  * with connection = 0, free raw_edid
457                  * only if raw edid data isn't same as fake data.
458                  */
459                 if (ctx->raw_edid && ctx->raw_edid !=
460                                 (struct edid *)fake_edid_info) {
461                         kfree(ctx->raw_edid);
462                         ctx->raw_edid = NULL;
463                 }
464         }
465
466         ctx->connected = vidi->connection;
467         drm_helper_hpd_irq_event(ctx->drm_dev);
468
469         return 0;
470 }
471
472 static enum drm_connector_status vidi_detect(struct drm_connector *connector,
473                         bool force)
474 {
475         struct vidi_context *ctx = ctx_from_connector(connector);
476
477         /*
478          * connection request would come from user side
479          * to do hotplug through specific ioctl.
480          */
481         return ctx->connected ? connector_status_connected :
482                         connector_status_disconnected;
483 }
484
485 static void vidi_connector_destroy(struct drm_connector *connector)
486 {
487 }
488
489 static struct drm_connector_funcs vidi_connector_funcs = {
490         .dpms = drm_helper_connector_dpms,
491         .fill_modes = drm_helper_probe_single_connector_modes,
492         .detect = vidi_detect,
493         .destroy = vidi_connector_destroy,
494 };
495
496 static int vidi_get_modes(struct drm_connector *connector)
497 {
498         struct vidi_context *ctx = ctx_from_connector(connector);
499         struct edid *edid;
500         int edid_len;
501
502         /*
503          * the edid data comes from user side and it would be set
504          * to ctx->raw_edid through specific ioctl.
505          */
506         if (!ctx->raw_edid) {
507                 DRM_DEBUG_KMS("raw_edid is null.\n");
508                 return -EFAULT;
509         }
510
511         edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH;
512         edid = kmemdup(ctx->raw_edid, edid_len, GFP_KERNEL);
513         if (!edid) {
514                 DRM_DEBUG_KMS("failed to allocate edid\n");
515                 return -ENOMEM;
516         }
517
518         drm_mode_connector_update_edid_property(connector, edid);
519
520         return drm_add_edid_modes(connector, edid);
521 }
522
523 static struct drm_encoder *vidi_best_encoder(struct drm_connector *connector)
524 {
525         struct vidi_context *ctx = ctx_from_connector(connector);
526
527         return ctx->encoder;
528 }
529
530 static struct drm_connector_helper_funcs vidi_connector_helper_funcs = {
531         .get_modes = vidi_get_modes,
532         .best_encoder = vidi_best_encoder,
533 };
534
535 static int vidi_create_connector(struct exynos_drm_display *display,
536                                 struct drm_encoder *encoder)
537 {
538         struct vidi_context *ctx = display_to_vidi(display);
539         struct drm_connector *connector = &ctx->connector;
540         int ret;
541
542         ctx->encoder = encoder;
543         connector->polled = DRM_CONNECTOR_POLL_HPD;
544
545         ret = drm_connector_init(ctx->drm_dev, connector,
546                         &vidi_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL);
547         if (ret) {
548                 DRM_ERROR("Failed to initialize connector with drm\n");
549                 return ret;
550         }
551
552         drm_connector_helper_add(connector, &vidi_connector_helper_funcs);
553         drm_connector_register(connector);
554         drm_mode_connector_attach_encoder(connector, encoder);
555
556         return 0;
557 }
558
559
560 static struct exynos_drm_display_ops vidi_display_ops = {
561         .create_connector = vidi_create_connector,
562 };
563
564 static int vidi_bind(struct device *dev, struct device *master, void *data)
565 {
566         struct vidi_context *ctx = dev_get_drvdata(dev);
567         struct drm_device *drm_dev = data;
568         struct drm_crtc *crtc = ctx->crtc;
569         int ret;
570
571         vidi_mgr_initialize(&ctx->manager, drm_dev);
572
573         ret = exynos_drm_crtc_create(&ctx->manager);
574         if (ret) {
575                 DRM_ERROR("failed to create crtc.\n");
576                 return ret;
577         }
578
579         ret = exynos_drm_create_enc_conn(drm_dev, &ctx->display);
580         if (ret) {
581                 crtc->funcs->destroy(crtc);
582                 DRM_ERROR("failed to create encoder and connector.\n");
583                 return ret;
584         }
585
586         return 0;
587 }
588
589
590 static void vidi_unbind(struct device *dev, struct device *master, void *data)
591 {
592 }
593
594 static const struct component_ops vidi_component_ops = {
595         .bind   = vidi_bind,
596         .unbind = vidi_unbind,
597 };
598
599 static int vidi_probe(struct platform_device *pdev)
600 {
601         struct vidi_context *ctx;
602         int ret;
603
604         ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
605         if (!ctx)
606                 return -ENOMEM;
607
608         ctx->manager.type = EXYNOS_DISPLAY_TYPE_VIDI;
609         ctx->manager.ops = &vidi_manager_ops;
610         ctx->display.type = EXYNOS_DISPLAY_TYPE_VIDI;
611         ctx->display.ops = &vidi_display_ops;
612         ctx->default_win = 0;
613         ctx->pdev = pdev;
614
615         ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC,
616                                         ctx->manager.type);
617         if (ret)
618                 return ret;
619
620         ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR,
621                                         ctx->display.type);
622         if (ret)
623                 goto err_del_crtc_component;
624
625         INIT_WORK(&ctx->work, vidi_fake_vblank_handler);
626
627         mutex_init(&ctx->lock);
628
629         platform_set_drvdata(pdev, ctx);
630
631         ret = device_create_file(&pdev->dev, &dev_attr_connection);
632         if (ret < 0) {
633                 DRM_ERROR("failed to create connection sysfs.\n");
634                 goto err_del_conn_component;
635         }
636
637         ret = component_add(&pdev->dev, &vidi_component_ops);
638         if (ret)
639                 goto err_remove_file;
640
641         return ret;
642
643 err_remove_file:
644         device_remove_file(&pdev->dev, &dev_attr_connection);
645 err_del_conn_component:
646         exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR);
647 err_del_crtc_component:
648         exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
649
650         return ret;
651 }
652
653 static int vidi_remove(struct platform_device *pdev)
654 {
655         struct vidi_context *ctx = platform_get_drvdata(pdev);
656
657         if (ctx->raw_edid != (struct edid *)fake_edid_info) {
658                 kfree(ctx->raw_edid);
659                 ctx->raw_edid = NULL;
660
661                 return -EINVAL;
662         }
663
664         component_del(&pdev->dev, &vidi_component_ops);
665         exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR);
666         exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
667
668         return 0;
669 }
670
671 struct platform_driver vidi_driver = {
672         .probe          = vidi_probe,
673         .remove         = vidi_remove,
674         .driver         = {
675                 .name   = "exynos-drm-vidi",
676                 .owner  = THIS_MODULE,
677         },
678 };
679
680 int exynos_drm_probe_vidi(void)
681 {
682         struct platform_device *pdev;
683         int ret;
684
685         pdev = platform_device_register_simple("exynos-drm-vidi", -1, NULL, 0);
686         if (IS_ERR(pdev))
687                 return PTR_ERR(pdev);
688
689         ret = platform_driver_register(&vidi_driver);
690         if (ret) {
691                 platform_device_unregister(pdev);
692                 return ret;
693         }
694
695         return ret;
696 }
697
698 static int exynos_drm_remove_vidi_device(struct device *dev, void *data)
699 {
700         platform_device_unregister(to_platform_device(dev));
701
702         return 0;
703 }
704
705 void exynos_drm_remove_vidi(void)
706 {
707         int ret = driver_for_each_device(&vidi_driver.driver, NULL, NULL,
708                                          exynos_drm_remove_vidi_device);
709         /* silence compiler warning */
710         (void)ret;
711
712         platform_driver_unregister(&vidi_driver);
713 }