aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_core.c100
1 files changed, 69 insertions, 31 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c
index 80cba2f413f4..7b0432b7a364 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_core.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_core.c
@@ -34,33 +34,15 @@
34 34
35static LIST_HEAD(exynos_drm_subdrv_list); 35static LIST_HEAD(exynos_drm_subdrv_list);
36 36
37static int exynos_drm_subdrv_probe(struct drm_device *dev, 37static int exynos_drm_create_enc_conn(struct drm_device *dev,
38 struct exynos_drm_subdrv *subdrv) 38 struct exynos_drm_subdrv *subdrv)
39{ 39{
40 struct drm_encoder *encoder; 40 struct drm_encoder *encoder;
41 struct drm_connector *connector; 41 struct drm_connector *connector;
42 int ret;
42 43
43 DRM_DEBUG_DRIVER("%s\n", __FILE__); 44 DRM_DEBUG_DRIVER("%s\n", __FILE__);
44 45
45 if (subdrv->probe) {
46 int ret;
47
48 /*
49 * this probe callback would be called by sub driver
50 * after setting of all resources to this sub driver,
51 * such as clock, irq and register map are done or by load()
52 * of exynos drm driver.
53 *
54 * P.S. note that this driver is considered for modularization.
55 */
56 ret = subdrv->probe(dev, subdrv->dev);
57 if (ret)
58 return ret;
59 }
60
61 if (!subdrv->manager)
62 return 0;
63
64 subdrv->manager->dev = subdrv->dev; 46 subdrv->manager->dev = subdrv->dev;
65 47
66 /* create and initialize a encoder for this sub driver. */ 48 /* create and initialize a encoder for this sub driver. */
@@ -78,24 +60,22 @@ static int exynos_drm_subdrv_probe(struct drm_device *dev,
78 connector = exynos_drm_connector_create(dev, encoder); 60 connector = exynos_drm_connector_create(dev, encoder);
79 if (!connector) { 61 if (!connector) {
80 DRM_ERROR("failed to create connector\n"); 62 DRM_ERROR("failed to create connector\n");
81 encoder->funcs->destroy(encoder); 63 ret = -EFAULT;
82 return -EFAULT; 64 goto err_destroy_encoder;
83 } 65 }
84 66
85 subdrv->encoder = encoder; 67 subdrv->encoder = encoder;
86 subdrv->connector = connector; 68 subdrv->connector = connector;
87 69
88 return 0; 70 return 0;
71
72err_destroy_encoder:
73 encoder->funcs->destroy(encoder);
74 return ret;
89} 75}
90 76
91static void exynos_drm_subdrv_remove(struct drm_device *dev, 77static void exynos_drm_destroy_enc_conn(struct exynos_drm_subdrv *subdrv)
92 struct exynos_drm_subdrv *subdrv)
93{ 78{
94 DRM_DEBUG_DRIVER("%s\n", __FILE__);
95
96 if (subdrv->remove)
97 subdrv->remove(dev, subdrv->dev);
98
99 if (subdrv->encoder) { 79 if (subdrv->encoder) {
100 struct drm_encoder *encoder = subdrv->encoder; 80 struct drm_encoder *encoder = subdrv->encoder;
101 encoder->funcs->destroy(encoder); 81 encoder->funcs->destroy(encoder);
@@ -109,9 +89,43 @@ static void exynos_drm_subdrv_remove(struct drm_device *dev,
109 } 89 }
110} 90}
111 91
92static int exynos_drm_subdrv_probe(struct drm_device *dev,
93 struct exynos_drm_subdrv *subdrv)
94{
95 if (subdrv->probe) {
96 int ret;
97
98 subdrv->drm_dev = dev;
99
100 /*
101 * this probe callback would be called by sub driver
102 * after setting of all resources to this sub driver,
103 * such as clock, irq and register map are done or by load()
104 * of exynos drm driver.
105 *
106 * P.S. note that this driver is considered for modularization.
107 */
108 ret = subdrv->probe(dev, subdrv->dev);
109 if (ret)
110 return ret;
111 }
112
113 return 0;
114}
115
116static void exynos_drm_subdrv_remove(struct drm_device *dev,
117 struct exynos_drm_subdrv *subdrv)
118{
119 DRM_DEBUG_DRIVER("%s\n", __FILE__);
120
121 if (subdrv->remove)
122 subdrv->remove(dev, subdrv->dev);
123}
124
112int exynos_drm_device_register(struct drm_device *dev) 125int exynos_drm_device_register(struct drm_device *dev)
113{ 126{
114 struct exynos_drm_subdrv *subdrv, *n; 127 struct exynos_drm_subdrv *subdrv, *n;
128 unsigned int fine_cnt = 0;
115 int err; 129 int err;
116 130
117 DRM_DEBUG_DRIVER("%s\n", __FILE__); 131 DRM_DEBUG_DRIVER("%s\n", __FILE__);
@@ -120,14 +134,36 @@ int exynos_drm_device_register(struct drm_device *dev)
120 return -EINVAL; 134 return -EINVAL;
121 135
122 list_for_each_entry_safe(subdrv, n, &exynos_drm_subdrv_list, list) { 136 list_for_each_entry_safe(subdrv, n, &exynos_drm_subdrv_list, list) {
123 subdrv->drm_dev = dev;
124 err = exynos_drm_subdrv_probe(dev, subdrv); 137 err = exynos_drm_subdrv_probe(dev, subdrv);
125 if (err) { 138 if (err) {
126 DRM_DEBUG("exynos drm subdrv probe failed.\n"); 139 DRM_DEBUG("exynos drm subdrv probe failed.\n");
127 list_del(&subdrv->list); 140 list_del(&subdrv->list);
141 continue;
142 }
143
144 /*
145 * if manager is null then it means that this sub driver
146 * doesn't need encoder and connector.
147 */
148 if (!subdrv->manager) {
149 fine_cnt++;
150 continue;
128 } 151 }
152
153 err = exynos_drm_create_enc_conn(dev, subdrv);
154 if (err) {
155 DRM_DEBUG("failed to create encoder and connector.\n");
156 exynos_drm_subdrv_remove(dev, subdrv);
157 list_del(&subdrv->list);
158 continue;
159 }
160
161 fine_cnt++;
129 } 162 }
130 163
164 if (!fine_cnt)
165 return -EINVAL;
166
131 return 0; 167 return 0;
132} 168}
133EXPORT_SYMBOL_GPL(exynos_drm_device_register); 169EXPORT_SYMBOL_GPL(exynos_drm_device_register);
@@ -143,8 +179,10 @@ int exynos_drm_device_unregister(struct drm_device *dev)
143 return -EINVAL; 179 return -EINVAL;
144 } 180 }
145 181
146 list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) 182 list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
147 exynos_drm_subdrv_remove(dev, subdrv); 183 exynos_drm_subdrv_remove(dev, subdrv);
184 exynos_drm_destroy_enc_conn(subdrv);
185 }
148 186
149 return 0; 187 return 0;
150} 188}