aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/exynos/exynos_drm_vidi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_vidi.c')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_vidi.c150
1 files changed, 92 insertions, 58 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index 50faf913e574..45899fb63272 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -14,6 +14,7 @@
14 14
15#include <linux/kernel.h> 15#include <linux/kernel.h>
16#include <linux/platform_device.h> 16#include <linux/platform_device.h>
17#include <linux/component.h>
17 18
18#include <drm/exynos_drm.h> 19#include <drm/exynos_drm.h>
19 20
@@ -28,7 +29,6 @@
28/* vidi has totally three virtual windows. */ 29/* vidi has totally three virtual windows. */
29#define WINDOWS_NR 3 30#define WINDOWS_NR 3
30 31
31#define get_vidi_mgr(dev) platform_get_drvdata(to_platform_device(dev))
32#define ctx_from_connector(c) container_of(c, struct vidi_context, \ 32#define ctx_from_connector(c) container_of(c, struct vidi_context, \
33 connector) 33 connector)
34 34
@@ -47,11 +47,13 @@ struct vidi_win_data {
47}; 47};
48 48
49struct vidi_context { 49struct vidi_context {
50 struct exynos_drm_manager manager;
51 struct exynos_drm_display display;
52 struct platform_device *pdev;
50 struct drm_device *drm_dev; 53 struct drm_device *drm_dev;
51 struct drm_crtc *crtc; 54 struct drm_crtc *crtc;
52 struct drm_encoder *encoder; 55 struct drm_encoder *encoder;
53 struct drm_connector connector; 56 struct drm_connector connector;
54 struct exynos_drm_subdrv subdrv;
55 struct vidi_win_data win_data[WINDOWS_NR]; 57 struct vidi_win_data win_data[WINDOWS_NR];
56 struct edid *raw_edid; 58 struct edid *raw_edid;
57 unsigned int clkdiv; 59 unsigned int clkdiv;
@@ -66,6 +68,16 @@ struct vidi_context {
66 int pipe; 68 int pipe;
67}; 69};
68 70
71static inline struct vidi_context *manager_to_vidi(struct exynos_drm_manager *m)
72{
73 return container_of(m, struct vidi_context, manager);
74}
75
76static inline struct vidi_context *display_to_vidi(struct exynos_drm_display *d)
77{
78 return container_of(d, struct vidi_context, display);
79}
80
69static const char fake_edid_info[] = { 81static const char fake_edid_info[] = {
70 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x4c, 0x2d, 0x05, 0x05, 82 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x4c, 0x2d, 0x05, 0x05,
71 0x00, 0x00, 0x00, 0x00, 0x30, 0x12, 0x01, 0x03, 0x80, 0x10, 0x09, 0x78, 83 0x00, 0x00, 0x00, 0x00, 0x30, 0x12, 0x01, 0x03, 0x80, 0x10, 0x09, 0x78,
@@ -93,7 +105,7 @@ static const char fake_edid_info[] = {
93 105
94static void vidi_apply(struct exynos_drm_manager *mgr) 106static void vidi_apply(struct exynos_drm_manager *mgr)
95{ 107{
96 struct vidi_context *ctx = mgr->ctx; 108 struct vidi_context *ctx = manager_to_vidi(mgr);
97 struct exynos_drm_manager_ops *mgr_ops = mgr->ops; 109 struct exynos_drm_manager_ops *mgr_ops = mgr->ops;
98 struct vidi_win_data *win_data; 110 struct vidi_win_data *win_data;
99 int i; 111 int i;
@@ -110,7 +122,7 @@ static void vidi_apply(struct exynos_drm_manager *mgr)
110 122
111static void vidi_commit(struct exynos_drm_manager *mgr) 123static void vidi_commit(struct exynos_drm_manager *mgr)
112{ 124{
113 struct vidi_context *ctx = mgr->ctx; 125 struct vidi_context *ctx = manager_to_vidi(mgr);
114 126
115 if (ctx->suspended) 127 if (ctx->suspended)
116 return; 128 return;
@@ -118,7 +130,7 @@ static void vidi_commit(struct exynos_drm_manager *mgr)
118 130
119static int vidi_enable_vblank(struct exynos_drm_manager *mgr) 131static int vidi_enable_vblank(struct exynos_drm_manager *mgr)
120{ 132{
121 struct vidi_context *ctx = mgr->ctx; 133 struct vidi_context *ctx = manager_to_vidi(mgr);
122 134
123 if (ctx->suspended) 135 if (ctx->suspended)
124 return -EPERM; 136 return -EPERM;
@@ -140,7 +152,7 @@ static int vidi_enable_vblank(struct exynos_drm_manager *mgr)
140 152
141static void vidi_disable_vblank(struct exynos_drm_manager *mgr) 153static void vidi_disable_vblank(struct exynos_drm_manager *mgr)
142{ 154{
143 struct vidi_context *ctx = mgr->ctx; 155 struct vidi_context *ctx = manager_to_vidi(mgr);
144 156
145 if (ctx->suspended) 157 if (ctx->suspended)
146 return; 158 return;
@@ -152,7 +164,7 @@ static void vidi_disable_vblank(struct exynos_drm_manager *mgr)
152static void vidi_win_mode_set(struct exynos_drm_manager *mgr, 164static void vidi_win_mode_set(struct exynos_drm_manager *mgr,
153 struct exynos_drm_overlay *overlay) 165 struct exynos_drm_overlay *overlay)
154{ 166{
155 struct vidi_context *ctx = mgr->ctx; 167 struct vidi_context *ctx = manager_to_vidi(mgr);
156 struct vidi_win_data *win_data; 168 struct vidi_win_data *win_data;
157 int win; 169 int win;
158 unsigned long offset; 170 unsigned long offset;
@@ -204,7 +216,7 @@ static void vidi_win_mode_set(struct exynos_drm_manager *mgr,
204 216
205static void vidi_win_commit(struct exynos_drm_manager *mgr, int zpos) 217static void vidi_win_commit(struct exynos_drm_manager *mgr, int zpos)
206{ 218{
207 struct vidi_context *ctx = mgr->ctx; 219 struct vidi_context *ctx = manager_to_vidi(mgr);
208 struct vidi_win_data *win_data; 220 struct vidi_win_data *win_data;
209 int win = zpos; 221 int win = zpos;
210 222
@@ -229,7 +241,7 @@ static void vidi_win_commit(struct exynos_drm_manager *mgr, int zpos)
229 241
230static void vidi_win_disable(struct exynos_drm_manager *mgr, int zpos) 242static void vidi_win_disable(struct exynos_drm_manager *mgr, int zpos)
231{ 243{
232 struct vidi_context *ctx = mgr->ctx; 244 struct vidi_context *ctx = manager_to_vidi(mgr);
233 struct vidi_win_data *win_data; 245 struct vidi_win_data *win_data;
234 int win = zpos; 246 int win = zpos;
235 247
@@ -247,7 +259,7 @@ static void vidi_win_disable(struct exynos_drm_manager *mgr, int zpos)
247 259
248static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable) 260static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable)
249{ 261{
250 struct vidi_context *ctx = mgr->ctx; 262 struct vidi_context *ctx = manager_to_vidi(mgr);
251 263
252 DRM_DEBUG_KMS("%s\n", __FILE__); 264 DRM_DEBUG_KMS("%s\n", __FILE__);
253 265
@@ -271,7 +283,7 @@ static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable)
271 283
272static void vidi_dpms(struct exynos_drm_manager *mgr, int mode) 284static void vidi_dpms(struct exynos_drm_manager *mgr, int mode)
273{ 285{
274 struct vidi_context *ctx = mgr->ctx; 286 struct vidi_context *ctx = manager_to_vidi(mgr);
275 287
276 DRM_DEBUG_KMS("%d\n", mode); 288 DRM_DEBUG_KMS("%d\n", mode);
277 289
@@ -297,7 +309,7 @@ static void vidi_dpms(struct exynos_drm_manager *mgr, int mode)
297static int vidi_mgr_initialize(struct exynos_drm_manager *mgr, 309static int vidi_mgr_initialize(struct exynos_drm_manager *mgr,
298 struct drm_device *drm_dev) 310 struct drm_device *drm_dev)
299{ 311{
300 struct vidi_context *ctx = mgr->ctx; 312 struct vidi_context *ctx = manager_to_vidi(mgr);
301 struct exynos_drm_private *priv = drm_dev->dev_private; 313 struct exynos_drm_private *priv = drm_dev->dev_private;
302 314
303 mgr->drm_dev = ctx->drm_dev = drm_dev; 315 mgr->drm_dev = ctx->drm_dev = drm_dev;
@@ -316,11 +328,6 @@ static struct exynos_drm_manager_ops vidi_manager_ops = {
316 .win_disable = vidi_win_disable, 328 .win_disable = vidi_win_disable,
317}; 329};
318 330
319static struct exynos_drm_manager vidi_manager = {
320 .type = EXYNOS_DISPLAY_TYPE_VIDI,
321 .ops = &vidi_manager_ops,
322};
323
324static void vidi_fake_vblank_handler(struct work_struct *work) 331static void vidi_fake_vblank_handler(struct work_struct *work)
325{ 332{
326 struct vidi_context *ctx = container_of(work, struct vidi_context, 333 struct vidi_context *ctx = container_of(work, struct vidi_context,
@@ -349,9 +356,8 @@ static void vidi_fake_vblank_handler(struct work_struct *work)
349static int vidi_show_connection(struct device *dev, 356static int vidi_show_connection(struct device *dev,
350 struct device_attribute *attr, char *buf) 357 struct device_attribute *attr, char *buf)
351{ 358{
359 struct vidi_context *ctx = dev_get_drvdata(dev);
352 int rc; 360 int rc;
353 struct exynos_drm_manager *mgr = get_vidi_mgr(dev);
354 struct vidi_context *ctx = mgr->ctx;
355 361
356 mutex_lock(&ctx->lock); 362 mutex_lock(&ctx->lock);
357 363
@@ -366,8 +372,7 @@ static int vidi_store_connection(struct device *dev,
366 struct device_attribute *attr, 372 struct device_attribute *attr,
367 const char *buf, size_t len) 373 const char *buf, size_t len)
368{ 374{
369 struct exynos_drm_manager *mgr = get_vidi_mgr(dev); 375 struct vidi_context *ctx = dev_get_drvdata(dev);
370 struct vidi_context *ctx = mgr->ctx;
371 int ret; 376 int ret;
372 377
373 ret = kstrtoint(buf, 0, &ctx->connected); 378 ret = kstrtoint(buf, 0, &ctx->connected);
@@ -420,7 +425,7 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
420 display = exynos_drm_get_display(encoder); 425 display = exynos_drm_get_display(encoder);
421 426
422 if (display->type == EXYNOS_DISPLAY_TYPE_VIDI) { 427 if (display->type == EXYNOS_DISPLAY_TYPE_VIDI) {
423 ctx = display->ctx; 428 ctx = display_to_vidi(display);
424 break; 429 break;
425 } 430 }
426 } 431 }
@@ -530,7 +535,7 @@ static struct drm_connector_helper_funcs vidi_connector_helper_funcs = {
530static int vidi_create_connector(struct exynos_drm_display *display, 535static int vidi_create_connector(struct exynos_drm_display *display,
531 struct drm_encoder *encoder) 536 struct drm_encoder *encoder)
532{ 537{
533 struct vidi_context *ctx = display->ctx; 538 struct vidi_context *ctx = display_to_vidi(display);
534 struct drm_connector *connector = &ctx->connector; 539 struct drm_connector *connector = &ctx->connector;
535 int ret; 540 int ret;
536 541
@@ -556,27 +561,22 @@ static struct exynos_drm_display_ops vidi_display_ops = {
556 .create_connector = vidi_create_connector, 561 .create_connector = vidi_create_connector,
557}; 562};
558 563
559static struct exynos_drm_display vidi_display = { 564static int vidi_bind(struct device *dev, struct device *master, void *data)
560 .type = EXYNOS_DISPLAY_TYPE_VIDI,
561 .ops = &vidi_display_ops,
562};
563
564static int vidi_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
565{ 565{
566 struct exynos_drm_manager *mgr = get_vidi_mgr(dev); 566 struct vidi_context *ctx = dev_get_drvdata(dev);
567 struct vidi_context *ctx = mgr->ctx; 567 struct drm_device *drm_dev = data;
568 struct drm_crtc *crtc = ctx->crtc; 568 struct drm_crtc *crtc = ctx->crtc;
569 int ret; 569 int ret;
570 570
571 vidi_mgr_initialize(mgr, drm_dev); 571 vidi_mgr_initialize(&ctx->manager, drm_dev);
572 572
573 ret = exynos_drm_crtc_create(&vidi_manager); 573 ret = exynos_drm_crtc_create(&ctx->manager);
574 if (ret) { 574 if (ret) {
575 DRM_ERROR("failed to create crtc.\n"); 575 DRM_ERROR("failed to create crtc.\n");
576 return ret; 576 return ret;
577 } 577 }
578 578
579 ret = exynos_drm_create_enc_conn(drm_dev, &vidi_display); 579 ret = exynos_drm_create_enc_conn(drm_dev, &ctx->display);
580 if (ret) { 580 if (ret) {
581 crtc->funcs->destroy(crtc); 581 crtc->funcs->destroy(crtc);
582 DRM_ERROR("failed to create encoder and connector.\n"); 582 DRM_ERROR("failed to create encoder and connector.\n");
@@ -586,9 +586,18 @@ static int vidi_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
586 return 0; 586 return 0;
587} 587}
588 588
589
590static void vidi_unbind(struct device *dev, struct device *master, void *data)
591{
592}
593
594static const struct component_ops vidi_component_ops = {
595 .bind = vidi_bind,
596 .unbind = vidi_unbind,
597};
598
589static int vidi_probe(struct platform_device *pdev) 599static int vidi_probe(struct platform_device *pdev)
590{ 600{
591 struct exynos_drm_subdrv *subdrv;
592 struct vidi_context *ctx; 601 struct vidi_context *ctx;
593 int ret; 602 int ret;
594 603
@@ -596,40 +605,54 @@ static int vidi_probe(struct platform_device *pdev)
596 if (!ctx) 605 if (!ctx)
597 return -ENOMEM; 606 return -ENOMEM;
598 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;
599 ctx->default_win = 0; 612 ctx->default_win = 0;
613 ctx->pdev = pdev;
600 614
601 INIT_WORK(&ctx->work, vidi_fake_vblank_handler); 615 ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC,
602 616 ctx->manager.type);
603 vidi_manager.ctx = ctx; 617 if (ret)
604 vidi_display.ctx = ctx; 618 return ret;
605 619
606 mutex_init(&ctx->lock); 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;
607 624
608 platform_set_drvdata(pdev, &vidi_manager); 625 INIT_WORK(&ctx->work, vidi_fake_vblank_handler);
609 626
610 subdrv = &ctx->subdrv; 627 mutex_init(&ctx->lock);
611 subdrv->dev = &pdev->dev;
612 subdrv->probe = vidi_subdrv_probe;
613 628
614 ret = exynos_drm_subdrv_register(subdrv); 629 platform_set_drvdata(pdev, ctx);
615 if (ret < 0) {
616 dev_err(&pdev->dev, "failed to register drm vidi device\n");
617 return ret;
618 }
619 630
620 ret = device_create_file(&pdev->dev, &dev_attr_connection); 631 ret = device_create_file(&pdev->dev, &dev_attr_connection);
621 if (ret < 0) { 632 if (ret < 0) {
622 exynos_drm_subdrv_unregister(subdrv); 633 DRM_ERROR("failed to create connection sysfs.\n");
623 DRM_INFO("failed to create connection sysfs.\n"); 634 goto err_del_conn_component;
624 } 635 }
625 636
626 return 0; 637 ret = component_add(&pdev->dev, &vidi_component_ops);
638 if (ret)
639 goto err_remove_file;
640
641 return ret;
642
643err_remove_file:
644 device_remove_file(&pdev->dev, &dev_attr_connection);
645err_del_conn_component:
646 exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR);
647err_del_crtc_component:
648 exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
649
650 return ret;
627} 651}
628 652
629static int vidi_remove(struct platform_device *pdev) 653static int vidi_remove(struct platform_device *pdev)
630{ 654{
631 struct exynos_drm_manager *mgr = platform_get_drvdata(pdev); 655 struct vidi_context *ctx = platform_get_drvdata(pdev);
632 struct vidi_context *ctx = mgr->ctx;
633 656
634 if (ctx->raw_edid != (struct edid *)fake_edid_info) { 657 if (ctx->raw_edid != (struct edid *)fake_edid_info) {
635 kfree(ctx->raw_edid); 658 kfree(ctx->raw_edid);
@@ -638,6 +661,10 @@ static int vidi_remove(struct platform_device *pdev)
638 return -EINVAL; 661 return -EINVAL;
639 } 662 }
640 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
641 return 0; 668 return 0;
642} 669}
643 670
@@ -668,12 +695,19 @@ int exynos_drm_probe_vidi(void)
668 return ret; 695 return ret;
669} 696}
670 697
698static 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
671void exynos_drm_remove_vidi(void) 705void exynos_drm_remove_vidi(void)
672{ 706{
673 struct vidi_context *ctx = vidi_manager.ctx; 707 int ret = driver_for_each_device(&vidi_driver.driver, NULL, NULL,
674 struct exynos_drm_subdrv *subdrv = &ctx->subdrv; 708 exynos_drm_remove_vidi_device);
675 struct platform_device *pdev = to_platform_device(subdrv->dev); 709 /* silence compiler warning */
710 (void)ret;
676 711
677 platform_driver_unregister(&vidi_driver); 712 platform_driver_unregister(&vidi_driver);
678 platform_device_unregister(pdev);
679} 713}