3 * Copyright (C) 2012 Samsung Electronics Co.Ltd
5 * Inki Dae <inki.dae@samsung.com>
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.
15 #include <linux/kernel.h>
16 #include <linux/platform_device.h>
17 #include <linux/component.h>
19 #include <drm/exynos_drm.h>
21 #include <drm/drm_edid.h>
22 #include <drm/drm_crtc_helper.h>
24 #include "exynos_drm_drv.h"
25 #include "exynos_drm_crtc.h"
26 #include "exynos_drm_encoder.h"
27 #include "exynos_drm_vidi.h"
29 /* vidi has totally three virtual windows. */
32 #define ctx_from_connector(c) container_of(c, struct vidi_context, \
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
;
44 unsigned int buf_offsize
;
45 unsigned int line_size
; /* bytes */
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
;
60 unsigned int default_win
;
61 unsigned long irq_flags
;
62 unsigned int connected
;
66 struct work_struct work
;
71 static inline struct vidi_context
*manager_to_vidi(struct exynos_drm_manager
*m
)
73 return container_of(m
, struct vidi_context
, manager
);
76 static inline struct vidi_context
*display_to_vidi(struct exynos_drm_display
*d
)
78 return container_of(d
, struct vidi_context
, display
);
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
106 static void vidi_apply(struct exynos_drm_manager
*mgr
)
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
;
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
);
120 static int vidi_enable_vblank(struct exynos_drm_manager
*mgr
)
122 struct vidi_context
*ctx
= manager_to_vidi(mgr
);
127 if (!test_and_set_bit(0, &ctx
->irq_flags
))
128 ctx
->vblank_on
= true;
130 ctx
->direct_vblank
= true;
133 * in case of page flip request, vidi_finish_pageflip function
134 * will not be called because direct_vblank is true and then
135 * that function will be called by manager_ops->win_commit callback
137 schedule_work(&ctx
->work
);
142 static void vidi_disable_vblank(struct exynos_drm_manager
*mgr
)
144 struct vidi_context
*ctx
= manager_to_vidi(mgr
);
149 if (test_and_clear_bit(0, &ctx
->irq_flags
))
150 ctx
->vblank_on
= false;
153 static void vidi_win_mode_set(struct exynos_drm_manager
*mgr
,
154 struct exynos_drm_plane
*plane
)
156 struct vidi_context
*ctx
= manager_to_vidi(mgr
);
157 struct vidi_win_data
*win_data
;
159 unsigned long offset
;
162 DRM_ERROR("plane is NULL\n");
167 if (win
== DEFAULT_ZPOS
)
168 win
= ctx
->default_win
;
170 if (win
< 0 || win
>= WINDOWS_NR
)
173 offset
= plane
->fb_x
* (plane
->bpp
>> 3);
174 offset
+= plane
->fb_y
* plane
->pitch
;
176 DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset
, plane
->pitch
);
178 win_data
= &ctx
->win_data
[win
];
180 win_data
->offset_x
= plane
->crtc_x
;
181 win_data
->offset_y
= plane
->crtc_y
;
182 win_data
->ovl_width
= plane
->crtc_width
;
183 win_data
->ovl_height
= plane
->crtc_height
;
184 win_data
->fb_width
= plane
->fb_width
;
185 win_data
->fb_height
= plane
->fb_height
;
186 win_data
->dma_addr
= plane
->dma_addr
[0] + offset
;
187 win_data
->bpp
= plane
->bpp
;
188 win_data
->buf_offsize
= (plane
->fb_width
- plane
->crtc_width
) *
190 win_data
->line_size
= plane
->crtc_width
* (plane
->bpp
>> 3);
193 * some parts of win_data should be transferred to user side
194 * through specific ioctl.
197 DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
198 win_data
->offset_x
, win_data
->offset_y
);
199 DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
200 win_data
->ovl_width
, win_data
->ovl_height
);
201 DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data
->dma_addr
);
202 DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
203 plane
->fb_width
, plane
->crtc_width
);
206 static void vidi_win_commit(struct exynos_drm_manager
*mgr
, int zpos
)
208 struct vidi_context
*ctx
= manager_to_vidi(mgr
);
209 struct vidi_win_data
*win_data
;
215 if (win
== DEFAULT_ZPOS
)
216 win
= ctx
->default_win
;
218 if (win
< 0 || win
>= WINDOWS_NR
)
221 win_data
= &ctx
->win_data
[win
];
223 win_data
->enabled
= true;
225 DRM_DEBUG_KMS("dma_addr = %pad\n", &win_data
->dma_addr
);
228 schedule_work(&ctx
->work
);
231 static void vidi_win_disable(struct exynos_drm_manager
*mgr
, int zpos
)
233 struct vidi_context
*ctx
= manager_to_vidi(mgr
);
234 struct vidi_win_data
*win_data
;
237 if (win
== DEFAULT_ZPOS
)
238 win
= ctx
->default_win
;
240 if (win
< 0 || win
>= WINDOWS_NR
)
243 win_data
= &ctx
->win_data
[win
];
244 win_data
->enabled
= false;
249 static int vidi_power_on(struct exynos_drm_manager
*mgr
, bool enable
)
251 struct vidi_context
*ctx
= manager_to_vidi(mgr
);
253 DRM_DEBUG_KMS("%s\n", __FILE__
);
255 if (enable
!= false && enable
!= true)
259 ctx
->suspended
= false;
261 /* if vblank was enabled status, enable it again. */
262 if (test_and_clear_bit(0, &ctx
->irq_flags
))
263 vidi_enable_vblank(mgr
);
267 ctx
->suspended
= true;
273 static void vidi_dpms(struct exynos_drm_manager
*mgr
, int mode
)
275 struct vidi_context
*ctx
= manager_to_vidi(mgr
);
277 DRM_DEBUG_KMS("%d\n", mode
);
279 mutex_lock(&ctx
->lock
);
282 case DRM_MODE_DPMS_ON
:
283 vidi_power_on(mgr
, true);
285 case DRM_MODE_DPMS_STANDBY
:
286 case DRM_MODE_DPMS_SUSPEND
:
287 case DRM_MODE_DPMS_OFF
:
288 vidi_power_on(mgr
, false);
291 DRM_DEBUG_KMS("unspecified mode %d\n", mode
);
295 mutex_unlock(&ctx
->lock
);
298 static int vidi_mgr_initialize(struct exynos_drm_manager
*mgr
,
299 struct drm_device
*drm_dev
)
301 struct vidi_context
*ctx
= manager_to_vidi(mgr
);
302 struct exynos_drm_private
*priv
= drm_dev
->dev_private
;
304 ctx
->drm_dev
= drm_dev
;
305 ctx
->pipe
= priv
->pipe
++;
310 static struct exynos_drm_manager_ops vidi_manager_ops
= {
312 .enable_vblank
= vidi_enable_vblank
,
313 .disable_vblank
= vidi_disable_vblank
,
314 .win_mode_set
= vidi_win_mode_set
,
315 .win_commit
= vidi_win_commit
,
316 .win_disable
= vidi_win_disable
,
319 static void vidi_fake_vblank_handler(struct work_struct
*work
)
321 struct vidi_context
*ctx
= container_of(work
, struct vidi_context
,
327 /* refresh rate is about 50Hz. */
328 usleep_range(16000, 20000);
330 mutex_lock(&ctx
->lock
);
332 if (ctx
->direct_vblank
) {
333 drm_handle_vblank(ctx
->drm_dev
, ctx
->pipe
);
334 ctx
->direct_vblank
= false;
335 mutex_unlock(&ctx
->lock
);
339 mutex_unlock(&ctx
->lock
);
341 exynos_drm_crtc_finish_pageflip(ctx
->drm_dev
, ctx
->pipe
);
344 static int vidi_show_connection(struct device
*dev
,
345 struct device_attribute
*attr
, char *buf
)
347 struct vidi_context
*ctx
= dev_get_drvdata(dev
);
350 mutex_lock(&ctx
->lock
);
352 rc
= sprintf(buf
, "%d\n", ctx
->connected
);
354 mutex_unlock(&ctx
->lock
);
359 static int vidi_store_connection(struct device
*dev
,
360 struct device_attribute
*attr
,
361 const char *buf
, size_t len
)
363 struct vidi_context
*ctx
= dev_get_drvdata(dev
);
366 ret
= kstrtoint(buf
, 0, &ctx
->connected
);
370 if (ctx
->connected
> 1)
373 /* use fake edid data for test. */
375 ctx
->raw_edid
= (struct edid
*)fake_edid_info
;
377 /* if raw_edid isn't same as fake data then it can't be tested. */
378 if (ctx
->raw_edid
!= (struct edid
*)fake_edid_info
) {
379 DRM_DEBUG_KMS("edid data is not fake data.\n");
383 DRM_DEBUG_KMS("requested connection.\n");
385 drm_helper_hpd_irq_event(ctx
->drm_dev
);
390 static DEVICE_ATTR(connection
, 0644, vidi_show_connection
,
391 vidi_store_connection
);
393 int vidi_connection_ioctl(struct drm_device
*drm_dev
, void *data
,
394 struct drm_file
*file_priv
)
396 struct vidi_context
*ctx
= NULL
;
397 struct drm_encoder
*encoder
;
398 struct exynos_drm_display
*display
;
399 struct drm_exynos_vidi_connection
*vidi
= data
;
402 DRM_DEBUG_KMS("user data for vidi is null.\n");
406 if (vidi
->connection
> 1) {
407 DRM_DEBUG_KMS("connection should be 0 or 1.\n");
411 list_for_each_entry(encoder
, &drm_dev
->mode_config
.encoder_list
,
413 display
= exynos_drm_get_display(encoder
);
415 if (display
->type
== EXYNOS_DISPLAY_TYPE_VIDI
) {
416 ctx
= display_to_vidi(display
);
422 DRM_DEBUG_KMS("not found virtual device type encoder.\n");
426 if (ctx
->connected
== vidi
->connection
) {
427 DRM_DEBUG_KMS("same connection request.\n");
431 if (vidi
->connection
) {
432 struct edid
*raw_edid
= (struct edid
*)(uint32_t)vidi
->edid
;
433 if (!drm_edid_is_valid(raw_edid
)) {
434 DRM_DEBUG_KMS("edid data is invalid.\n");
437 ctx
->raw_edid
= drm_edid_duplicate(raw_edid
);
438 if (!ctx
->raw_edid
) {
439 DRM_DEBUG_KMS("failed to allocate raw_edid.\n");
444 * with connection = 0, free raw_edid
445 * only if raw edid data isn't same as fake data.
447 if (ctx
->raw_edid
&& ctx
->raw_edid
!=
448 (struct edid
*)fake_edid_info
) {
449 kfree(ctx
->raw_edid
);
450 ctx
->raw_edid
= NULL
;
454 ctx
->connected
= vidi
->connection
;
455 drm_helper_hpd_irq_event(ctx
->drm_dev
);
460 static enum drm_connector_status
vidi_detect(struct drm_connector
*connector
,
463 struct vidi_context
*ctx
= ctx_from_connector(connector
);
466 * connection request would come from user side
467 * to do hotplug through specific ioctl.
469 return ctx
->connected
? connector_status_connected
:
470 connector_status_disconnected
;
473 static void vidi_connector_destroy(struct drm_connector
*connector
)
477 static struct drm_connector_funcs vidi_connector_funcs
= {
478 .dpms
= drm_helper_connector_dpms
,
479 .fill_modes
= drm_helper_probe_single_connector_modes
,
480 .detect
= vidi_detect
,
481 .destroy
= vidi_connector_destroy
,
484 static int vidi_get_modes(struct drm_connector
*connector
)
486 struct vidi_context
*ctx
= ctx_from_connector(connector
);
491 * the edid data comes from user side and it would be set
492 * to ctx->raw_edid through specific ioctl.
494 if (!ctx
->raw_edid
) {
495 DRM_DEBUG_KMS("raw_edid is null.\n");
499 edid_len
= (1 + ctx
->raw_edid
->extensions
) * EDID_LENGTH
;
500 edid
= kmemdup(ctx
->raw_edid
, edid_len
, GFP_KERNEL
);
502 DRM_DEBUG_KMS("failed to allocate edid\n");
506 drm_mode_connector_update_edid_property(connector
, edid
);
508 return drm_add_edid_modes(connector
, edid
);
511 static struct drm_encoder
*vidi_best_encoder(struct drm_connector
*connector
)
513 struct vidi_context
*ctx
= ctx_from_connector(connector
);
518 static struct drm_connector_helper_funcs vidi_connector_helper_funcs
= {
519 .get_modes
= vidi_get_modes
,
520 .best_encoder
= vidi_best_encoder
,
523 static int vidi_create_connector(struct exynos_drm_display
*display
,
524 struct drm_encoder
*encoder
)
526 struct vidi_context
*ctx
= display_to_vidi(display
);
527 struct drm_connector
*connector
= &ctx
->connector
;
530 ctx
->encoder
= encoder
;
531 connector
->polled
= DRM_CONNECTOR_POLL_HPD
;
533 ret
= drm_connector_init(ctx
->drm_dev
, connector
,
534 &vidi_connector_funcs
, DRM_MODE_CONNECTOR_VIRTUAL
);
536 DRM_ERROR("Failed to initialize connector with drm\n");
540 drm_connector_helper_add(connector
, &vidi_connector_helper_funcs
);
541 drm_connector_register(connector
);
542 drm_mode_connector_attach_encoder(connector
, encoder
);
548 static struct exynos_drm_display_ops vidi_display_ops
= {
549 .create_connector
= vidi_create_connector
,
552 static int vidi_bind(struct device
*dev
, struct device
*master
, void *data
)
554 struct vidi_context
*ctx
= dev_get_drvdata(dev
);
555 struct drm_device
*drm_dev
= data
;
556 struct drm_crtc
*crtc
= ctx
->crtc
;
559 vidi_mgr_initialize(&ctx
->manager
, drm_dev
);
561 ret
= exynos_drm_crtc_create(&ctx
->manager
, drm_dev
, ctx
->pipe
,
562 EXYNOS_DISPLAY_TYPE_VIDI
);
564 DRM_ERROR("failed to create crtc.\n");
568 ret
= exynos_drm_create_enc_conn(drm_dev
, &ctx
->display
);
570 crtc
->funcs
->destroy(crtc
);
571 DRM_ERROR("failed to create encoder and connector.\n");
579 static void vidi_unbind(struct device
*dev
, struct device
*master
, void *data
)
583 static const struct component_ops vidi_component_ops
= {
585 .unbind
= vidi_unbind
,
588 static int vidi_probe(struct platform_device
*pdev
)
590 struct vidi_context
*ctx
;
593 ctx
= devm_kzalloc(&pdev
->dev
, sizeof(*ctx
), GFP_KERNEL
);
597 ctx
->manager
.ops
= &vidi_manager_ops
;
598 ctx
->display
.type
= EXYNOS_DISPLAY_TYPE_VIDI
;
599 ctx
->display
.ops
= &vidi_display_ops
;
600 ctx
->default_win
= 0;
603 ret
= exynos_drm_component_add(&pdev
->dev
, EXYNOS_DEVICE_TYPE_CRTC
,
604 EXYNOS_DISPLAY_TYPE_VIDI
);
608 ret
= exynos_drm_component_add(&pdev
->dev
, EXYNOS_DEVICE_TYPE_CONNECTOR
,
611 goto err_del_crtc_component
;
613 INIT_WORK(&ctx
->work
, vidi_fake_vblank_handler
);
615 mutex_init(&ctx
->lock
);
617 platform_set_drvdata(pdev
, ctx
);
619 ret
= device_create_file(&pdev
->dev
, &dev_attr_connection
);
621 DRM_ERROR("failed to create connection sysfs.\n");
622 goto err_del_conn_component
;
625 ret
= component_add(&pdev
->dev
, &vidi_component_ops
);
627 goto err_remove_file
;
632 device_remove_file(&pdev
->dev
, &dev_attr_connection
);
633 err_del_conn_component
:
634 exynos_drm_component_del(&pdev
->dev
, EXYNOS_DEVICE_TYPE_CONNECTOR
);
635 err_del_crtc_component
:
636 exynos_drm_component_del(&pdev
->dev
, EXYNOS_DEVICE_TYPE_CRTC
);
641 static int vidi_remove(struct platform_device
*pdev
)
643 struct vidi_context
*ctx
= platform_get_drvdata(pdev
);
645 if (ctx
->raw_edid
!= (struct edid
*)fake_edid_info
) {
646 kfree(ctx
->raw_edid
);
647 ctx
->raw_edid
= NULL
;
652 component_del(&pdev
->dev
, &vidi_component_ops
);
653 exynos_drm_component_del(&pdev
->dev
, EXYNOS_DEVICE_TYPE_CONNECTOR
);
654 exynos_drm_component_del(&pdev
->dev
, EXYNOS_DEVICE_TYPE_CRTC
);
659 struct platform_driver vidi_driver
= {
661 .remove
= vidi_remove
,
663 .name
= "exynos-drm-vidi",
664 .owner
= THIS_MODULE
,
668 int exynos_drm_probe_vidi(void)
670 struct platform_device
*pdev
;
673 pdev
= platform_device_register_simple("exynos-drm-vidi", -1, NULL
, 0);
675 return PTR_ERR(pdev
);
677 ret
= platform_driver_register(&vidi_driver
);
679 platform_device_unregister(pdev
);
686 static int exynos_drm_remove_vidi_device(struct device
*dev
, void *data
)
688 platform_device_unregister(to_platform_device(dev
));
693 void exynos_drm_remove_vidi(void)
695 int ret
= driver_for_each_device(&vidi_driver
.driver
, NULL
, NULL
,
696 exynos_drm_remove_vidi_device
);
697 /* silence compiler warning */
700 platform_driver_unregister(&vidi_driver
);