diff options
author | Sean Paul <seanpaul@chromium.org> | 2014-01-30 16:38:07 -0500 |
---|---|---|
committer | Inki Dae <daeinki@gmail.com> | 2014-03-23 11:36:37 -0400 |
commit | ce6cb556c9fc95d69c661f8da0e3e410a4e6565a (patch) | |
tree | 4d92b3f00a203b9a8916209ff3f1a8d48ac6e301 /drivers/gpu/drm/exynos | |
parent | caa5d1e5a32598bab25de1511a74ffdfa8c75d70 (diff) |
drm/exynos: Implement drm_connector directly in vidi driver
This patch implements drm_connector directly in the vidi
driver, this will allow us to move away from the exynos_drm_connector
layer.
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
Diffstat (limited to 'drivers/gpu/drm/exynos')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_vidi.c | 162 |
1 files changed, 108 insertions, 54 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index 5d0b5cdeaacf..7afead9c3f30 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c | |||
@@ -29,6 +29,8 @@ | |||
29 | #define WINDOWS_NR 3 | 29 | #define WINDOWS_NR 3 |
30 | 30 | ||
31 | #define get_vidi_mgr(dev) platform_get_drvdata(to_platform_device(dev)) | 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, \ | ||
33 | connector) | ||
32 | 34 | ||
33 | struct vidi_win_data { | 35 | struct vidi_win_data { |
34 | unsigned int offset_x; | 36 | unsigned int offset_x; |
@@ -47,6 +49,8 @@ struct vidi_win_data { | |||
47 | struct vidi_context { | 49 | struct vidi_context { |
48 | struct drm_device *drm_dev; | 50 | struct drm_device *drm_dev; |
49 | struct drm_crtc *crtc; | 51 | struct drm_crtc *crtc; |
52 | struct drm_encoder *encoder; | ||
53 | struct drm_connector connector; | ||
50 | struct vidi_win_data win_data[WINDOWS_NR]; | 54 | struct vidi_win_data win_data[WINDOWS_NR]; |
51 | struct edid *raw_edid; | 55 | struct edid *raw_edid; |
52 | unsigned int clkdiv; | 56 | unsigned int clkdiv; |
@@ -86,60 +90,6 @@ static const char fake_edid_info[] = { | |||
86 | 0x00, 0x00, 0x00, 0x06 | 90 | 0x00, 0x00, 0x00, 0x06 |
87 | }; | 91 | }; |
88 | 92 | ||
89 | static bool vidi_display_is_connected(struct exynos_drm_display *display) | ||
90 | { | ||
91 | struct vidi_context *ctx = display->ctx; | ||
92 | |||
93 | /* | ||
94 | * connection request would come from user side | ||
95 | * to do hotplug through specific ioctl. | ||
96 | */ | ||
97 | return ctx->connected ? true : false; | ||
98 | } | ||
99 | |||
100 | static struct edid *vidi_get_edid(struct exynos_drm_display *display, | ||
101 | struct drm_connector *connector) | ||
102 | { | ||
103 | struct vidi_context *ctx = display->ctx; | ||
104 | struct edid *edid; | ||
105 | |||
106 | /* | ||
107 | * the edid data comes from user side and it would be set | ||
108 | * to ctx->raw_edid through specific ioctl. | ||
109 | */ | ||
110 | if (!ctx->raw_edid) { | ||
111 | DRM_DEBUG_KMS("raw_edid is null.\n"); | ||
112 | return ERR_PTR(-EFAULT); | ||
113 | } | ||
114 | |||
115 | edid = drm_edid_duplicate(ctx->raw_edid); | ||
116 | if (!edid) { | ||
117 | DRM_DEBUG_KMS("failed to allocate edid\n"); | ||
118 | return ERR_PTR(-ENOMEM); | ||
119 | } | ||
120 | |||
121 | return edid; | ||
122 | } | ||
123 | |||
124 | static int vidi_check_mode(struct exynos_drm_display *display, | ||
125 | struct drm_display_mode *mode) | ||
126 | { | ||
127 | /* TODO. */ | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static struct exynos_drm_display_ops vidi_display_ops = { | ||
133 | .is_connected = vidi_display_is_connected, | ||
134 | .get_edid = vidi_get_edid, | ||
135 | .check_mode = vidi_check_mode, | ||
136 | }; | ||
137 | |||
138 | static struct exynos_drm_display vidi_display = { | ||
139 | .type = EXYNOS_DISPLAY_TYPE_VIDI, | ||
140 | .ops = &vidi_display_ops, | ||
141 | }; | ||
142 | |||
143 | static void vidi_apply(struct exynos_drm_manager *mgr) | 93 | static void vidi_apply(struct exynos_drm_manager *mgr) |
144 | { | 94 | { |
145 | struct vidi_context *ctx = mgr->ctx; | 95 | struct vidi_context *ctx = mgr->ctx; |
@@ -532,6 +482,110 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, | |||
532 | return 0; | 482 | return 0; |
533 | } | 483 | } |
534 | 484 | ||
485 | static enum drm_connector_status vidi_detect(struct drm_connector *connector, | ||
486 | bool force) | ||
487 | { | ||
488 | struct vidi_context *ctx = ctx_from_connector(connector); | ||
489 | |||
490 | /* | ||
491 | * connection request would come from user side | ||
492 | * to do hotplug through specific ioctl. | ||
493 | */ | ||
494 | return ctx->connected ? connector_status_connected : | ||
495 | connector_status_disconnected; | ||
496 | } | ||
497 | |||
498 | static void vidi_connector_destroy(struct drm_connector *connector) | ||
499 | { | ||
500 | } | ||
501 | |||
502 | static struct drm_connector_funcs vidi_connector_funcs = { | ||
503 | .dpms = drm_helper_connector_dpms, | ||
504 | .fill_modes = drm_helper_probe_single_connector_modes, | ||
505 | .detect = vidi_detect, | ||
506 | .destroy = vidi_connector_destroy, | ||
507 | }; | ||
508 | |||
509 | static int vidi_get_modes(struct drm_connector *connector) | ||
510 | { | ||
511 | struct vidi_context *ctx = ctx_from_connector(connector); | ||
512 | struct edid *edid; | ||
513 | int edid_len; | ||
514 | |||
515 | /* | ||
516 | * the edid data comes from user side and it would be set | ||
517 | * to ctx->raw_edid through specific ioctl. | ||
518 | */ | ||
519 | if (!ctx->raw_edid) { | ||
520 | DRM_DEBUG_KMS("raw_edid is null.\n"); | ||
521 | return -EFAULT; | ||
522 | } | ||
523 | |||
524 | edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH; | ||
525 | edid = kmemdup(ctx->raw_edid, edid_len, GFP_KERNEL); | ||
526 | if (!edid) { | ||
527 | DRM_DEBUG_KMS("failed to allocate edid\n"); | ||
528 | return -ENOMEM; | ||
529 | } | ||
530 | |||
531 | drm_mode_connector_update_edid_property(connector, edid); | ||
532 | |||
533 | return drm_add_edid_modes(connector, edid); | ||
534 | } | ||
535 | |||
536 | static int vidi_mode_valid(struct drm_connector *connector, | ||
537 | struct drm_display_mode *mode) | ||
538 | { | ||
539 | return MODE_OK; | ||
540 | } | ||
541 | |||
542 | static struct drm_encoder *vidi_best_encoder(struct drm_connector *connector) | ||
543 | { | ||
544 | struct vidi_context *ctx = ctx_from_connector(connector); | ||
545 | |||
546 | return ctx->encoder; | ||
547 | } | ||
548 | |||
549 | static struct drm_connector_helper_funcs vidi_connector_helper_funcs = { | ||
550 | .get_modes = vidi_get_modes, | ||
551 | .mode_valid = vidi_mode_valid, | ||
552 | .best_encoder = vidi_best_encoder, | ||
553 | }; | ||
554 | |||
555 | static int vidi_create_connector(struct exynos_drm_display *display, | ||
556 | struct drm_encoder *encoder) | ||
557 | { | ||
558 | struct vidi_context *ctx = display->ctx; | ||
559 | struct drm_connector *connector = &ctx->connector; | ||
560 | int ret; | ||
561 | |||
562 | ctx->encoder = encoder; | ||
563 | connector->polled = DRM_CONNECTOR_POLL_HPD; | ||
564 | |||
565 | ret = drm_connector_init(ctx->drm_dev, connector, | ||
566 | &vidi_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL); | ||
567 | if (ret) { | ||
568 | DRM_ERROR("Failed to initialize connector with drm\n"); | ||
569 | return ret; | ||
570 | } | ||
571 | |||
572 | drm_connector_helper_add(connector, &vidi_connector_helper_funcs); | ||
573 | drm_sysfs_connector_add(connector); | ||
574 | drm_mode_connector_attach_encoder(connector, encoder); | ||
575 | |||
576 | return 0; | ||
577 | } | ||
578 | |||
579 | |||
580 | static struct exynos_drm_display_ops vidi_display_ops = { | ||
581 | .create_connector = vidi_create_connector, | ||
582 | }; | ||
583 | |||
584 | static struct exynos_drm_display vidi_display = { | ||
585 | .type = EXYNOS_DISPLAY_TYPE_VIDI, | ||
586 | .ops = &vidi_display_ops, | ||
587 | }; | ||
588 | |||
535 | static int vidi_probe(struct platform_device *pdev) | 589 | static int vidi_probe(struct platform_device *pdev) |
536 | { | 590 | { |
537 | struct device *dev = &pdev->dev; | 591 | struct device *dev = &pdev->dev; |