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);