diff options
author | Inki Dae <inki.dae@samsung.com> | 2012-08-17 00:23:25 -0400 |
---|---|---|
committer | Inki Dae <inki.dae@samsung.com> | 2012-10-03 21:05:59 -0400 |
commit | 41fecf3e8268b8f285c91620c20895e946db9177 (patch) | |
tree | dd81af6909343b204aba7dea9454d74a8f96000b /drivers/gpu | |
parent | 29cb602532b0a82f22322cece8a89f022368d557 (diff) |
drm/exynos: separated subdrv_probe function into two parts.
Changelog v2:
fixed the issue that when sub driver is probed, no kms drivers such as
fimd or hdmi are failed. no kms drivers have no manager so if manager is
null then encoder and connector creation should be ignored.
Changelog v1:
this patch separates exynos_drm_subdrv_probe function into sub driver's probe call
and encoder/connector creation so that exynos drm core module can take exception
when some operation was failed properly.
Signed-off-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_core.c | 100 |
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 | ||
35 | static LIST_HEAD(exynos_drm_subdrv_list); | 35 | static LIST_HEAD(exynos_drm_subdrv_list); |
36 | 36 | ||
37 | static int exynos_drm_subdrv_probe(struct drm_device *dev, | 37 | static 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 | |||
72 | err_destroy_encoder: | ||
73 | encoder->funcs->destroy(encoder); | ||
74 | return ret; | ||
89 | } | 75 | } |
90 | 76 | ||
91 | static void exynos_drm_subdrv_remove(struct drm_device *dev, | 77 | static 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 | ||
92 | static 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 | |||
116 | static 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 | |||
112 | int exynos_drm_device_register(struct drm_device *dev) | 125 | int 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 | } |
133 | EXPORT_SYMBOL_GPL(exynos_drm_device_register); | 169 | EXPORT_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 | } |