diff options
author | Lucas Stach <l.stach@pengutronix.de> | 2016-08-11 05:18:48 -0400 |
---|---|---|
committer | Philipp Zabel <p.zabel@pengutronix.de> | 2016-08-29 06:45:05 -0400 |
commit | 54db5decce17b3258475a011a00b9c5c51c57a35 (patch) | |
tree | 2a60d0b2b9504fdab514e23004279efe7be60c84 /drivers/gpu/drm/imx/imx-drm-core.c | |
parent | 73cde76a61b622e768af23b0e0062dc39e6891bf (diff) |
drm/imx: drop deprecated load/unload drm_driver ops
Drop the load/unload driver ops, as they are deprecated because of their
inherent races, with devices being visible to userspace before they are
fully initialized.
Move this code into the driver bind/unbind routines bracketed by the
proper drm_dev_alloc/register and drm_dev_unregister/unref calls.
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Diffstat (limited to 'drivers/gpu/drm/imx/imx-drm-core.c')
-rw-r--r-- | drivers/gpu/drm/imx/imx-drm-core.c | 240 |
1 files changed, 112 insertions, 128 deletions
diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c index 75f35eaffb78..7a1ddf8b04cf 100644 --- a/drivers/gpu/drm/imx/imx-drm-core.c +++ b/drivers/gpu/drm/imx/imx-drm-core.c | |||
@@ -64,25 +64,6 @@ static void imx_drm_driver_lastclose(struct drm_device *drm) | |||
64 | drm_fbdev_cma_restore_mode(imxdrm->fbhelper); | 64 | drm_fbdev_cma_restore_mode(imxdrm->fbhelper); |
65 | } | 65 | } |
66 | 66 | ||
67 | static int imx_drm_driver_unload(struct drm_device *drm) | ||
68 | { | ||
69 | struct imx_drm_device *imxdrm = drm->dev_private; | ||
70 | |||
71 | drm_kms_helper_poll_fini(drm); | ||
72 | |||
73 | if (imxdrm->fbhelper) | ||
74 | drm_fbdev_cma_fini(imxdrm->fbhelper); | ||
75 | |||
76 | component_unbind_all(drm->dev, drm); | ||
77 | |||
78 | drm_vblank_cleanup(drm); | ||
79 | drm_mode_config_cleanup(drm); | ||
80 | |||
81 | platform_set_drvdata(drm->platformdev, NULL); | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static int imx_drm_enable_vblank(struct drm_device *drm, unsigned int pipe) | 67 | static int imx_drm_enable_vblank(struct drm_device *drm, unsigned int pipe) |
87 | { | 68 | { |
88 | struct imx_drm_device *imxdrm = drm->dev_private; | 69 | struct imx_drm_device *imxdrm = drm->dev_private; |
@@ -235,111 +216,6 @@ static struct drm_mode_config_helper_funcs imx_drm_mode_config_helpers = { | |||
235 | }; | 216 | }; |
236 | 217 | ||
237 | /* | 218 | /* |
238 | * Main DRM initialisation. This binds, initialises and registers | ||
239 | * with DRM the subcomponents of the driver. | ||
240 | */ | ||
241 | static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags) | ||
242 | { | ||
243 | struct imx_drm_device *imxdrm; | ||
244 | struct drm_connector *connector; | ||
245 | int ret; | ||
246 | |||
247 | imxdrm = devm_kzalloc(drm->dev, sizeof(*imxdrm), GFP_KERNEL); | ||
248 | if (!imxdrm) | ||
249 | return -ENOMEM; | ||
250 | |||
251 | imxdrm->drm = drm; | ||
252 | |||
253 | drm->dev_private = imxdrm; | ||
254 | |||
255 | /* | ||
256 | * enable drm irq mode. | ||
257 | * - with irq_enabled = true, we can use the vblank feature. | ||
258 | * | ||
259 | * P.S. note that we wouldn't use drm irq handler but | ||
260 | * just specific driver own one instead because | ||
261 | * drm framework supports only one irq handler and | ||
262 | * drivers can well take care of their interrupts | ||
263 | */ | ||
264 | drm->irq_enabled = true; | ||
265 | |||
266 | /* | ||
267 | * set max width and height as default value(4096x4096). | ||
268 | * this value would be used to check framebuffer size limitation | ||
269 | * at drm_mode_addfb(). | ||
270 | */ | ||
271 | drm->mode_config.min_width = 64; | ||
272 | drm->mode_config.min_height = 64; | ||
273 | drm->mode_config.max_width = 4096; | ||
274 | drm->mode_config.max_height = 4096; | ||
275 | drm->mode_config.funcs = &imx_drm_mode_config_funcs; | ||
276 | drm->mode_config.helper_private = &imx_drm_mode_config_helpers; | ||
277 | |||
278 | drm_mode_config_init(drm); | ||
279 | |||
280 | ret = drm_vblank_init(drm, MAX_CRTC); | ||
281 | if (ret) | ||
282 | goto err_kms; | ||
283 | |||
284 | platform_set_drvdata(drm->platformdev, drm); | ||
285 | |||
286 | /* Now try and bind all our sub-components */ | ||
287 | ret = component_bind_all(drm->dev, drm); | ||
288 | if (ret) | ||
289 | goto err_vblank; | ||
290 | |||
291 | /* | ||
292 | * All components are now added, we can publish the connector sysfs | ||
293 | * entries to userspace. This will generate hotplug events and so | ||
294 | * userspace will expect to be able to access DRM at this point. | ||
295 | */ | ||
296 | list_for_each_entry(connector, &drm->mode_config.connector_list, head) { | ||
297 | ret = drm_connector_register(connector); | ||
298 | if (ret) { | ||
299 | dev_err(drm->dev, | ||
300 | "[CONNECTOR:%d:%s] drm_connector_register failed: %d\n", | ||
301 | connector->base.id, | ||
302 | connector->name, ret); | ||
303 | goto err_unbind; | ||
304 | } | ||
305 | } | ||
306 | |||
307 | drm_mode_config_reset(drm); | ||
308 | |||
309 | /* | ||
310 | * All components are now initialised, so setup the fb helper. | ||
311 | * The fb helper takes copies of key hardware information, so the | ||
312 | * crtcs/connectors/encoders must not change after this point. | ||
313 | */ | ||
314 | #if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) | ||
315 | if (legacyfb_depth != 16 && legacyfb_depth != 32) { | ||
316 | dev_warn(drm->dev, "Invalid legacyfb_depth. Defaulting to 16bpp\n"); | ||
317 | legacyfb_depth = 16; | ||
318 | } | ||
319 | imxdrm->fbhelper = drm_fbdev_cma_init(drm, legacyfb_depth, | ||
320 | drm->mode_config.num_crtc, MAX_CRTC); | ||
321 | if (IS_ERR(imxdrm->fbhelper)) { | ||
322 | ret = PTR_ERR(imxdrm->fbhelper); | ||
323 | imxdrm->fbhelper = NULL; | ||
324 | goto err_unbind; | ||
325 | } | ||
326 | #endif | ||
327 | |||
328 | drm_kms_helper_poll_init(drm); | ||
329 | |||
330 | return 0; | ||
331 | |||
332 | err_unbind: | ||
333 | component_unbind_all(drm->dev, drm); | ||
334 | err_vblank: | ||
335 | drm_vblank_cleanup(drm); | ||
336 | err_kms: | ||
337 | drm_mode_config_cleanup(drm); | ||
338 | |||
339 | return ret; | ||
340 | } | ||
341 | |||
342 | /* | ||
343 | * imx_drm_add_crtc - add a new crtc | 219 | * imx_drm_add_crtc - add a new crtc |
344 | */ | 220 | */ |
345 | int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc, | 221 | int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc, |
@@ -431,8 +307,6 @@ static const struct drm_ioctl_desc imx_drm_ioctls[] = { | |||
431 | static struct drm_driver imx_drm_driver = { | 307 | static struct drm_driver imx_drm_driver = { |
432 | .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | | 308 | .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | |
433 | DRIVER_ATOMIC, | 309 | DRIVER_ATOMIC, |
434 | .load = imx_drm_driver_load, | ||
435 | .unload = imx_drm_driver_unload, | ||
436 | .lastclose = imx_drm_driver_lastclose, | 310 | .lastclose = imx_drm_driver_lastclose, |
437 | .gem_free_object_unlocked = drm_gem_cma_free_object, | 311 | .gem_free_object_unlocked = drm_gem_cma_free_object, |
438 | .gem_vm_ops = &drm_gem_cma_vm_ops, | 312 | .gem_vm_ops = &drm_gem_cma_vm_ops, |
@@ -485,12 +359,122 @@ static int compare_of(struct device *dev, void *data) | |||
485 | 359 | ||
486 | static int imx_drm_bind(struct device *dev) | 360 | static int imx_drm_bind(struct device *dev) |
487 | { | 361 | { |
488 | return drm_platform_init(&imx_drm_driver, to_platform_device(dev)); | 362 | struct drm_device *drm; |
363 | struct imx_drm_device *imxdrm; | ||
364 | int ret; | ||
365 | |||
366 | drm = drm_dev_alloc(&imx_drm_driver, dev); | ||
367 | if (!drm) | ||
368 | return -ENOMEM; | ||
369 | |||
370 | imxdrm = devm_kzalloc(dev, sizeof(*imxdrm), GFP_KERNEL); | ||
371 | if (!imxdrm) { | ||
372 | ret = -ENOMEM; | ||
373 | goto err_unref; | ||
374 | } | ||
375 | |||
376 | imxdrm->drm = drm; | ||
377 | drm->dev_private = imxdrm; | ||
378 | |||
379 | /* | ||
380 | * enable drm irq mode. | ||
381 | * - with irq_enabled = true, we can use the vblank feature. | ||
382 | * | ||
383 | * P.S. note that we wouldn't use drm irq handler but | ||
384 | * just specific driver own one instead because | ||
385 | * drm framework supports only one irq handler and | ||
386 | * drivers can well take care of their interrupts | ||
387 | */ | ||
388 | drm->irq_enabled = true; | ||
389 | |||
390 | /* | ||
391 | * set max width and height as default value(4096x4096). | ||
392 | * this value would be used to check framebuffer size limitation | ||
393 | * at drm_mode_addfb(). | ||
394 | */ | ||
395 | drm->mode_config.min_width = 64; | ||
396 | drm->mode_config.min_height = 64; | ||
397 | drm->mode_config.max_width = 4096; | ||
398 | drm->mode_config.max_height = 4096; | ||
399 | drm->mode_config.funcs = &imx_drm_mode_config_funcs; | ||
400 | drm->mode_config.helper_private = &imx_drm_mode_config_helpers; | ||
401 | |||
402 | drm_mode_config_init(drm); | ||
403 | |||
404 | ret = drm_vblank_init(drm, MAX_CRTC); | ||
405 | if (ret) | ||
406 | goto err_kms; | ||
407 | |||
408 | dev_set_drvdata(dev, drm); | ||
409 | |||
410 | /* Now try and bind all our sub-components */ | ||
411 | ret = component_bind_all(dev, drm); | ||
412 | if (ret) | ||
413 | goto err_vblank; | ||
414 | |||
415 | drm_mode_config_reset(drm); | ||
416 | |||
417 | /* | ||
418 | * All components are now initialised, so setup the fb helper. | ||
419 | * The fb helper takes copies of key hardware information, so the | ||
420 | * crtcs/connectors/encoders must not change after this point. | ||
421 | */ | ||
422 | #if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) | ||
423 | if (legacyfb_depth != 16 && legacyfb_depth != 32) { | ||
424 | dev_warn(dev, "Invalid legacyfb_depth. Defaulting to 16bpp\n"); | ||
425 | legacyfb_depth = 16; | ||
426 | } | ||
427 | imxdrm->fbhelper = drm_fbdev_cma_init(drm, legacyfb_depth, | ||
428 | drm->mode_config.num_crtc, MAX_CRTC); | ||
429 | if (IS_ERR(imxdrm->fbhelper)) { | ||
430 | ret = PTR_ERR(imxdrm->fbhelper); | ||
431 | imxdrm->fbhelper = NULL; | ||
432 | goto err_unbind; | ||
433 | } | ||
434 | #endif | ||
435 | |||
436 | drm_kms_helper_poll_init(drm); | ||
437 | |||
438 | ret = drm_dev_register(drm, 0); | ||
439 | if (ret) | ||
440 | goto err_fbhelper; | ||
441 | |||
442 | return 0; | ||
443 | |||
444 | err_fbhelper: | ||
445 | drm_kms_helper_poll_fini(drm); | ||
446 | if (imxdrm->fbhelper) | ||
447 | drm_fbdev_cma_fini(imxdrm->fbhelper); | ||
448 | err_unbind: | ||
449 | component_unbind_all(drm->dev, drm); | ||
450 | err_vblank: | ||
451 | drm_vblank_cleanup(drm); | ||
452 | err_kms: | ||
453 | drm_mode_config_cleanup(drm); | ||
454 | err_unref: | ||
455 | drm_dev_unref(drm); | ||
456 | |||
457 | return ret; | ||
489 | } | 458 | } |
490 | 459 | ||
491 | static void imx_drm_unbind(struct device *dev) | 460 | static void imx_drm_unbind(struct device *dev) |
492 | { | 461 | { |
493 | drm_put_dev(dev_get_drvdata(dev)); | 462 | struct drm_device *drm = dev_get_drvdata(dev); |
463 | struct imx_drm_device *imxdrm = drm->dev_private; | ||
464 | |||
465 | drm_dev_unregister(drm); | ||
466 | |||
467 | drm_kms_helper_poll_fini(drm); | ||
468 | |||
469 | if (imxdrm->fbhelper) | ||
470 | drm_fbdev_cma_fini(imxdrm->fbhelper); | ||
471 | |||
472 | component_unbind_all(drm->dev, drm); | ||
473 | dev_set_drvdata(dev, NULL); | ||
474 | |||
475 | drm_mode_config_cleanup(drm); | ||
476 | |||
477 | drm_dev_unref(drm); | ||
494 | } | 478 | } |
495 | 479 | ||
496 | static const struct component_master_ops imx_drm_ops = { | 480 | static const struct component_master_ops imx_drm_ops = { |