diff options
Diffstat (limited to 'drivers/gpu/drm/tilcdc/tilcdc_drv.c')
-rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_drv.c | 60 |
1 files changed, 50 insertions, 10 deletions
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index aea4b7663934..79a34cbd29f5 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c | |||
@@ -84,6 +84,7 @@ static int modeset_init(struct drm_device *dev) | |||
84 | if ((priv->num_encoders == 0) || (priv->num_connectors == 0)) { | 84 | if ((priv->num_encoders == 0) || (priv->num_connectors == 0)) { |
85 | /* oh nos! */ | 85 | /* oh nos! */ |
86 | dev_err(dev->dev, "no encoders/connectors found\n"); | 86 | dev_err(dev->dev, "no encoders/connectors found\n"); |
87 | drm_mode_config_cleanup(dev); | ||
87 | return -ENXIO; | 88 | return -ENXIO; |
88 | } | 89 | } |
89 | 90 | ||
@@ -172,33 +173,37 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) | |||
172 | dev->dev_private = priv; | 173 | dev->dev_private = priv; |
173 | 174 | ||
174 | priv->wq = alloc_ordered_workqueue("tilcdc", 0); | 175 | priv->wq = alloc_ordered_workqueue("tilcdc", 0); |
176 | if (!priv->wq) { | ||
177 | ret = -ENOMEM; | ||
178 | goto fail_free_priv; | ||
179 | } | ||
175 | 180 | ||
176 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 181 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
177 | if (!res) { | 182 | if (!res) { |
178 | dev_err(dev->dev, "failed to get memory resource\n"); | 183 | dev_err(dev->dev, "failed to get memory resource\n"); |
179 | ret = -EINVAL; | 184 | ret = -EINVAL; |
180 | goto fail; | 185 | goto fail_free_wq; |
181 | } | 186 | } |
182 | 187 | ||
183 | priv->mmio = ioremap_nocache(res->start, resource_size(res)); | 188 | priv->mmio = ioremap_nocache(res->start, resource_size(res)); |
184 | if (!priv->mmio) { | 189 | if (!priv->mmio) { |
185 | dev_err(dev->dev, "failed to ioremap\n"); | 190 | dev_err(dev->dev, "failed to ioremap\n"); |
186 | ret = -ENOMEM; | 191 | ret = -ENOMEM; |
187 | goto fail; | 192 | goto fail_free_wq; |
188 | } | 193 | } |
189 | 194 | ||
190 | priv->clk = clk_get(dev->dev, "fck"); | 195 | priv->clk = clk_get(dev->dev, "fck"); |
191 | if (IS_ERR(priv->clk)) { | 196 | if (IS_ERR(priv->clk)) { |
192 | dev_err(dev->dev, "failed to get functional clock\n"); | 197 | dev_err(dev->dev, "failed to get functional clock\n"); |
193 | ret = -ENODEV; | 198 | ret = -ENODEV; |
194 | goto fail; | 199 | goto fail_iounmap; |
195 | } | 200 | } |
196 | 201 | ||
197 | priv->disp_clk = clk_get(dev->dev, "dpll_disp_ck"); | 202 | priv->disp_clk = clk_get(dev->dev, "dpll_disp_ck"); |
198 | if (IS_ERR(priv->clk)) { | 203 | if (IS_ERR(priv->clk)) { |
199 | dev_err(dev->dev, "failed to get display clock\n"); | 204 | dev_err(dev->dev, "failed to get display clock\n"); |
200 | ret = -ENODEV; | 205 | ret = -ENODEV; |
201 | goto fail; | 206 | goto fail_put_clk; |
202 | } | 207 | } |
203 | 208 | ||
204 | #ifdef CONFIG_CPU_FREQ | 209 | #ifdef CONFIG_CPU_FREQ |
@@ -208,7 +213,7 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) | |||
208 | CPUFREQ_TRANSITION_NOTIFIER); | 213 | CPUFREQ_TRANSITION_NOTIFIER); |
209 | if (ret) { | 214 | if (ret) { |
210 | dev_err(dev->dev, "failed to register cpufreq notifier\n"); | 215 | dev_err(dev->dev, "failed to register cpufreq notifier\n"); |
211 | goto fail; | 216 | goto fail_put_disp_clk; |
212 | } | 217 | } |
213 | #endif | 218 | #endif |
214 | 219 | ||
@@ -253,13 +258,13 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) | |||
253 | ret = modeset_init(dev); | 258 | ret = modeset_init(dev); |
254 | if (ret < 0) { | 259 | if (ret < 0) { |
255 | dev_err(dev->dev, "failed to initialize mode setting\n"); | 260 | dev_err(dev->dev, "failed to initialize mode setting\n"); |
256 | goto fail; | 261 | goto fail_cpufreq_unregister; |
257 | } | 262 | } |
258 | 263 | ||
259 | ret = drm_vblank_init(dev, 1); | 264 | ret = drm_vblank_init(dev, 1); |
260 | if (ret < 0) { | 265 | if (ret < 0) { |
261 | dev_err(dev->dev, "failed to initialize vblank\n"); | 266 | dev_err(dev->dev, "failed to initialize vblank\n"); |
262 | goto fail; | 267 | goto fail_mode_config_cleanup; |
263 | } | 268 | } |
264 | 269 | ||
265 | pm_runtime_get_sync(dev->dev); | 270 | pm_runtime_get_sync(dev->dev); |
@@ -267,7 +272,7 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) | |||
267 | pm_runtime_put_sync(dev->dev); | 272 | pm_runtime_put_sync(dev->dev); |
268 | if (ret < 0) { | 273 | if (ret < 0) { |
269 | dev_err(dev->dev, "failed to install IRQ handler\n"); | 274 | dev_err(dev->dev, "failed to install IRQ handler\n"); |
270 | goto fail; | 275 | goto fail_vblank_cleanup; |
271 | } | 276 | } |
272 | 277 | ||
273 | platform_set_drvdata(pdev, dev); | 278 | platform_set_drvdata(pdev, dev); |
@@ -283,13 +288,48 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) | |||
283 | priv->fbdev = drm_fbdev_cma_init(dev, bpp, | 288 | priv->fbdev = drm_fbdev_cma_init(dev, bpp, |
284 | dev->mode_config.num_crtc, | 289 | dev->mode_config.num_crtc, |
285 | dev->mode_config.num_connector); | 290 | dev->mode_config.num_connector); |
291 | if (IS_ERR(priv->fbdev)) { | ||
292 | ret = PTR_ERR(priv->fbdev); | ||
293 | goto fail_irq_uninstall; | ||
294 | } | ||
286 | 295 | ||
287 | drm_kms_helper_poll_init(dev); | 296 | drm_kms_helper_poll_init(dev); |
288 | 297 | ||
289 | return 0; | 298 | return 0; |
290 | 299 | ||
291 | fail: | 300 | fail_irq_uninstall: |
292 | tilcdc_unload(dev); | 301 | pm_runtime_get_sync(dev->dev); |
302 | drm_irq_uninstall(dev); | ||
303 | pm_runtime_put_sync(dev->dev); | ||
304 | |||
305 | fail_vblank_cleanup: | ||
306 | drm_vblank_cleanup(dev); | ||
307 | |||
308 | fail_mode_config_cleanup: | ||
309 | drm_mode_config_cleanup(dev); | ||
310 | |||
311 | fail_cpufreq_unregister: | ||
312 | pm_runtime_disable(dev->dev); | ||
313 | #ifdef CONFIG_CPU_FREQ | ||
314 | cpufreq_unregister_notifier(&priv->freq_transition, | ||
315 | CPUFREQ_TRANSITION_NOTIFIER); | ||
316 | fail_put_disp_clk: | ||
317 | clk_put(priv->disp_clk); | ||
318 | #endif | ||
319 | |||
320 | fail_put_clk: | ||
321 | clk_put(priv->clk); | ||
322 | |||
323 | fail_iounmap: | ||
324 | iounmap(priv->mmio); | ||
325 | |||
326 | fail_free_wq: | ||
327 | flush_workqueue(priv->wq); | ||
328 | destroy_workqueue(priv->wq); | ||
329 | |||
330 | fail_free_priv: | ||
331 | dev->dev_private = NULL; | ||
332 | kfree(priv); | ||
293 | return ret; | 333 | return ret; |
294 | } | 334 | } |
295 | 335 | ||