mm: Initialize error in shmem_file_aio_read()
[linux/fpc-iii.git] / drivers / gpu / drm / exynos / exynos_drm_core.c
blob0e9e06ce36b860ae8fb5a91d40faf31d917b180a
1 /* exynos_drm_core.c
3 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
4 * Author:
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.
15 #include <drm/drmP.h>
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;
30 int ret;
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);
40 if (!encoder) {
41 DRM_ERROR("failed to create encoder\n");
42 return -EFAULT;
45 display->encoder = encoder;
47 ret = display->ops->create_connector(display, encoder);
48 if (ret) {
49 DRM_ERROR("failed to create connector ret = %d\n", ret);
50 goto err_destroy_encoder;
53 return 0;
55 err_destroy_encoder:
56 encoder->funcs->destroy(encoder);
57 return ret;
60 static int exynos_drm_subdrv_probe(struct drm_device *dev,
61 struct exynos_drm_subdrv *subdrv)
63 if (subdrv->probe) {
64 int ret;
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);
77 if (ret)
78 return ret;
81 return 0;
84 static void exynos_drm_subdrv_remove(struct drm_device *dev,
85 struct exynos_drm_subdrv *subdrv)
87 if (subdrv->remove)
88 subdrv->remove(dev, subdrv->dev);
91 int exynos_drm_initialize_managers(struct drm_device *dev)
93 struct exynos_drm_manager *manager, *n;
94 int ret, pipe = 0;
96 list_for_each_entry(manager, &exynos_drm_manager_list, list) {
97 if (manager->ops->initialize) {
98 ret = manager->ops->initialize(manager, dev, pipe);
99 if (ret) {
100 DRM_ERROR("Mgr init [%d] failed with %d\n",
101 manager->type, ret);
102 goto err;
106 manager->drm_dev = dev;
107 manager->pipe = pipe++;
109 ret = exynos_drm_crtc_create(manager);
110 if (ret) {
111 DRM_ERROR("CRTC create [%d] failed with %d\n",
112 manager->type, ret);
113 goto err;
116 return 0;
118 err:
119 list_for_each_entry_safe(manager, n, &exynos_drm_manager_list, list) {
120 if (pipe-- > 0)
121 exynos_drm_manager_unregister(manager);
122 else
123 list_del(&manager->list);
125 return ret;
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);
144 if (ret) {
145 DRM_ERROR("Display init [%d] failed with %d\n",
146 display->type, ret);
147 goto err;
151 initialized++;
153 ret = exynos_drm_create_enc_conn(dev, display);
154 if (ret) {
155 DRM_ERROR("Encoder create [%d] failed with %d\n",
156 display->type, ret);
157 goto err;
160 return 0;
162 err:
163 list_for_each_entry_safe(display, n, &exynos_drm_display_list, list) {
164 if (initialized-- > 0)
165 exynos_drm_display_unregister(display);
166 else
167 list_del(&display->list);
169 return ret;
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;
183 int err;
185 if (!dev)
186 return -EINVAL;
188 list_for_each_entry_safe(subdrv, n, &exynos_drm_subdrv_list, list) {
189 err = exynos_drm_subdrv_probe(dev, subdrv);
190 if (err) {
191 DRM_DEBUG("exynos drm subdrv probe failed.\n");
192 list_del(&subdrv->list);
193 continue;
197 return 0;
199 EXPORT_SYMBOL_GPL(exynos_drm_device_register);
201 int exynos_drm_device_unregister(struct drm_device *dev)
203 struct exynos_drm_subdrv *subdrv;
205 if (!dev) {
206 WARN(1, "Unexpected drm device unregister!\n");
207 return -EINVAL;
210 list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
211 exynos_drm_subdrv_remove(dev, subdrv);
214 return 0;
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);
222 return 0;
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);
231 return 0;
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);
238 return 0;
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);
247 return 0;
250 int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv)
252 if (!subdrv)
253 return -EINVAL;
255 list_add_tail(&subdrv->list, &exynos_drm_subdrv_list);
257 return 0;
259 EXPORT_SYMBOL_GPL(exynos_drm_subdrv_register);
261 int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *subdrv)
263 if (!subdrv)
264 return -EINVAL;
266 list_del(&subdrv->list);
268 return 0;
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;
275 int ret;
277 list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
278 if (subdrv->open) {
279 ret = subdrv->open(dev, subdrv->dev, file);
280 if (ret)
281 goto err;
285 return 0;
287 err:
288 list_for_each_entry_reverse(subdrv, &subdrv->list, list) {
289 if (subdrv->close)
290 subdrv->close(dev, subdrv->dev, file);
292 return ret;
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) {
301 if (subdrv->close)
302 subdrv->close(dev, subdrv->dev, file);
305 EXPORT_SYMBOL_GPL(exynos_drm_subdrv_close);