3 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
5 * Inki Dae <inki.dae@samsung.com>
6 * Joonyoung Shim <jy0922.shim@samsung.com>
7 * Seung-Woo Kim <sw0312.kim@samsung.com>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
16 #include "exynos_drm_drv.h"
17 #include "exynos_drm_crtc.h"
18 #include "exynos_drm_encoder.h"
19 #include "exynos_drm_fbdev.h"
21 static LIST_HEAD(exynos_drm_subdrv_list
);
22 static LIST_HEAD(exynos_drm_manager_list
);
23 static LIST_HEAD(exynos_drm_display_list
);
25 static int exynos_drm_create_enc_conn(struct drm_device
*dev
,
26 struct exynos_drm_display
*display
)
28 struct drm_encoder
*encoder
;
29 struct exynos_drm_manager
*manager
;
31 unsigned long possible_crtcs
= 0;
33 /* Find possible crtcs for this display */
34 list_for_each_entry(manager
, &exynos_drm_manager_list
, list
)
35 if (manager
->type
== display
->type
)
36 possible_crtcs
|= 1 << manager
->pipe
;
38 /* create and initialize a encoder for this sub driver. */
39 encoder
= exynos_drm_encoder_create(dev
, display
, possible_crtcs
);
41 DRM_ERROR("failed to create encoder\n");
45 display
->encoder
= encoder
;
47 ret
= display
->ops
->create_connector(display
, encoder
);
49 DRM_ERROR("failed to create connector ret = %d\n", ret
);
50 goto err_destroy_encoder
;
56 encoder
->funcs
->destroy(encoder
);
60 static int exynos_drm_subdrv_probe(struct drm_device
*dev
,
61 struct exynos_drm_subdrv
*subdrv
)
66 subdrv
->drm_dev
= dev
;
69 * this probe callback would be called by sub driver
70 * after setting of all resources to this sub driver,
71 * such as clock, irq and register map are done or by load()
72 * of exynos drm driver.
74 * P.S. note that this driver is considered for modularization.
76 ret
= subdrv
->probe(dev
, subdrv
->dev
);
84 static void exynos_drm_subdrv_remove(struct drm_device
*dev
,
85 struct exynos_drm_subdrv
*subdrv
)
88 subdrv
->remove(dev
, subdrv
->dev
);
91 int exynos_drm_initialize_managers(struct drm_device
*dev
)
93 struct exynos_drm_manager
*manager
, *n
;
96 list_for_each_entry(manager
, &exynos_drm_manager_list
, list
) {
97 if (manager
->ops
->initialize
) {
98 ret
= manager
->ops
->initialize(manager
, dev
, pipe
);
100 DRM_ERROR("Mgr init [%d] failed with %d\n",
106 manager
->drm_dev
= dev
;
107 manager
->pipe
= pipe
++;
109 ret
= exynos_drm_crtc_create(manager
);
111 DRM_ERROR("CRTC create [%d] failed with %d\n",
119 list_for_each_entry_safe(manager
, n
, &exynos_drm_manager_list
, list
) {
121 exynos_drm_manager_unregister(manager
);
123 list_del(&manager
->list
);
128 void exynos_drm_remove_managers(struct drm_device
*dev
)
130 struct exynos_drm_manager
*manager
, *n
;
132 list_for_each_entry_safe(manager
, n
, &exynos_drm_manager_list
, list
)
133 exynos_drm_manager_unregister(manager
);
136 int exynos_drm_initialize_displays(struct drm_device
*dev
)
138 struct exynos_drm_display
*display
, *n
;
139 int ret
, initialized
= 0;
141 list_for_each_entry(display
, &exynos_drm_display_list
, list
) {
142 if (display
->ops
->initialize
) {
143 ret
= display
->ops
->initialize(display
, dev
);
145 DRM_ERROR("Display init [%d] failed with %d\n",
153 ret
= exynos_drm_create_enc_conn(dev
, display
);
155 DRM_ERROR("Encoder create [%d] failed with %d\n",
163 list_for_each_entry_safe(display
, n
, &exynos_drm_display_list
, list
) {
164 if (initialized
-- > 0)
165 exynos_drm_display_unregister(display
);
167 list_del(&display
->list
);
172 void exynos_drm_remove_displays(struct drm_device
*dev
)
174 struct exynos_drm_display
*display
, *n
;
176 list_for_each_entry_safe(display
, n
, &exynos_drm_display_list
, list
)
177 exynos_drm_display_unregister(display
);
180 int exynos_drm_device_register(struct drm_device
*dev
)
182 struct exynos_drm_subdrv
*subdrv
, *n
;
188 list_for_each_entry_safe(subdrv
, n
, &exynos_drm_subdrv_list
, list
) {
189 err
= exynos_drm_subdrv_probe(dev
, subdrv
);
191 DRM_DEBUG("exynos drm subdrv probe failed.\n");
192 list_del(&subdrv
->list
);
199 EXPORT_SYMBOL_GPL(exynos_drm_device_register
);
201 int exynos_drm_device_unregister(struct drm_device
*dev
)
203 struct exynos_drm_subdrv
*subdrv
;
206 WARN(1, "Unexpected drm device unregister!\n");
210 list_for_each_entry(subdrv
, &exynos_drm_subdrv_list
, list
) {
211 exynos_drm_subdrv_remove(dev
, subdrv
);
216 EXPORT_SYMBOL_GPL(exynos_drm_device_unregister
);
218 int exynos_drm_manager_register(struct exynos_drm_manager
*manager
)
220 BUG_ON(!manager
->ops
);
221 list_add_tail(&manager
->list
, &exynos_drm_manager_list
);
225 int exynos_drm_manager_unregister(struct exynos_drm_manager
*manager
)
227 if (manager
->ops
->remove
)
228 manager
->ops
->remove(manager
);
230 list_del(&manager
->list
);
234 int exynos_drm_display_register(struct exynos_drm_display
*display
)
236 BUG_ON(!display
->ops
);
237 list_add_tail(&display
->list
, &exynos_drm_display_list
);
241 int exynos_drm_display_unregister(struct exynos_drm_display
*display
)
243 if (display
->ops
->remove
)
244 display
->ops
->remove(display
);
246 list_del(&display
->list
);
250 int exynos_drm_subdrv_register(struct exynos_drm_subdrv
*subdrv
)
255 list_add_tail(&subdrv
->list
, &exynos_drm_subdrv_list
);
259 EXPORT_SYMBOL_GPL(exynos_drm_subdrv_register
);
261 int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv
*subdrv
)
266 list_del(&subdrv
->list
);
270 EXPORT_SYMBOL_GPL(exynos_drm_subdrv_unregister
);
272 int exynos_drm_subdrv_open(struct drm_device
*dev
, struct drm_file
*file
)
274 struct exynos_drm_subdrv
*subdrv
;
277 list_for_each_entry(subdrv
, &exynos_drm_subdrv_list
, list
) {
279 ret
= subdrv
->open(dev
, subdrv
->dev
, file
);
288 list_for_each_entry_reverse(subdrv
, &subdrv
->list
, list
) {
290 subdrv
->close(dev
, subdrv
->dev
, file
);
294 EXPORT_SYMBOL_GPL(exynos_drm_subdrv_open
);
296 void exynos_drm_subdrv_close(struct drm_device
*dev
, struct drm_file
*file
)
298 struct exynos_drm_subdrv
*subdrv
;
300 list_for_each_entry(subdrv
, &exynos_drm_subdrv_list
, list
) {
302 subdrv
->close(dev
, subdrv
->dev
, file
);
305 EXPORT_SYMBOL_GPL(exynos_drm_subdrv_close
);