diff options
Diffstat (limited to 'drivers/gpu/drm/sti/sti_drv.c')
| -rw-r--r-- | drivers/gpu/drm/sti/sti_drv.c | 148 |
1 files changed, 98 insertions, 50 deletions
diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c index 872495e72294..96bd3d08b2d4 100644 --- a/drivers/gpu/drm/sti/sti_drv.c +++ b/drivers/gpu/drm/sti/sti_drv.c | |||
| @@ -72,11 +72,6 @@ static int sti_drm_fps_dbg_show(struct seq_file *s, void *data) | |||
| 72 | struct drm_info_node *node = s->private; | 72 | struct drm_info_node *node = s->private; |
| 73 | struct drm_device *dev = node->minor->dev; | 73 | struct drm_device *dev = node->minor->dev; |
| 74 | struct drm_plane *p; | 74 | struct drm_plane *p; |
| 75 | int ret; | ||
| 76 | |||
| 77 | ret = mutex_lock_interruptible(&dev->struct_mutex); | ||
| 78 | if (ret) | ||
| 79 | return ret; | ||
| 80 | 75 | ||
| 81 | list_for_each_entry(p, &dev->mode_config.plane_list, head) { | 76 | list_for_each_entry(p, &dev->mode_config.plane_list, head) { |
| 82 | struct sti_plane *plane = to_sti_plane(p); | 77 | struct sti_plane *plane = to_sti_plane(p); |
| @@ -86,7 +81,6 @@ static int sti_drm_fps_dbg_show(struct seq_file *s, void *data) | |||
| 86 | plane->fps_info.fips_str); | 81 | plane->fps_info.fips_str); |
| 87 | } | 82 | } |
| 88 | 83 | ||
| 89 | mutex_unlock(&dev->struct_mutex); | ||
| 90 | return 0; | 84 | return 0; |
| 91 | } | 85 | } |
| 92 | 86 | ||
| @@ -221,7 +215,7 @@ static int sti_atomic_commit(struct drm_device *drm, | |||
| 221 | * the software side now. | 215 | * the software side now. |
| 222 | */ | 216 | */ |
| 223 | 217 | ||
| 224 | drm_atomic_helper_swap_state(drm, state); | 218 | drm_atomic_helper_swap_state(state, true); |
| 225 | 219 | ||
| 226 | if (nonblock) | 220 | if (nonblock) |
| 227 | sti_atomic_schedule(private, state); | 221 | sti_atomic_schedule(private, state); |
| @@ -232,8 +226,28 @@ static int sti_atomic_commit(struct drm_device *drm, | |||
| 232 | return 0; | 226 | return 0; |
| 233 | } | 227 | } |
| 234 | 228 | ||
| 229 | static void sti_output_poll_changed(struct drm_device *ddev) | ||
| 230 | { | ||
| 231 | struct sti_private *private = ddev->dev_private; | ||
| 232 | |||
| 233 | if (!ddev->mode_config.num_connector) | ||
| 234 | return; | ||
| 235 | |||
| 236 | if (private->fbdev) { | ||
| 237 | drm_fbdev_cma_hotplug_event(private->fbdev); | ||
| 238 | return; | ||
| 239 | } | ||
| 240 | |||
| 241 | private->fbdev = drm_fbdev_cma_init(ddev, 32, | ||
| 242 | ddev->mode_config.num_crtc, | ||
| 243 | ddev->mode_config.num_connector); | ||
| 244 | if (IS_ERR(private->fbdev)) | ||
| 245 | private->fbdev = NULL; | ||
| 246 | } | ||
| 247 | |||
| 235 | static const struct drm_mode_config_funcs sti_mode_config_funcs = { | 248 | static const struct drm_mode_config_funcs sti_mode_config_funcs = { |
| 236 | .fb_create = drm_fb_cma_create, | 249 | .fb_create = drm_fb_cma_create, |
| 250 | .output_poll_changed = sti_output_poll_changed, | ||
| 237 | .atomic_check = drm_atomic_helper_check, | 251 | .atomic_check = drm_atomic_helper_check, |
| 238 | .atomic_commit = sti_atomic_commit, | 252 | .atomic_commit = sti_atomic_commit, |
| 239 | }; | 253 | }; |
| @@ -254,45 +268,6 @@ static void sti_mode_config_init(struct drm_device *dev) | |||
| 254 | dev->mode_config.funcs = &sti_mode_config_funcs; | 268 | dev->mode_config.funcs = &sti_mode_config_funcs; |
| 255 | } | 269 | } |
| 256 | 270 | ||
| 257 | static int sti_load(struct drm_device *dev, unsigned long flags) | ||
| 258 | { | ||
| 259 | struct sti_private *private; | ||
| 260 | int ret; | ||
| 261 | |||
| 262 | private = kzalloc(sizeof(*private), GFP_KERNEL); | ||
| 263 | if (!private) { | ||
| 264 | DRM_ERROR("Failed to allocate private\n"); | ||
| 265 | return -ENOMEM; | ||
| 266 | } | ||
| 267 | dev->dev_private = (void *)private; | ||
| 268 | private->drm_dev = dev; | ||
| 269 | |||
| 270 | mutex_init(&private->commit.lock); | ||
| 271 | INIT_WORK(&private->commit.work, sti_atomic_work); | ||
| 272 | |||
| 273 | drm_mode_config_init(dev); | ||
| 274 | drm_kms_helper_poll_init(dev); | ||
| 275 | |||
| 276 | sti_mode_config_init(dev); | ||
| 277 | |||
| 278 | ret = component_bind_all(dev->dev, dev); | ||
| 279 | if (ret) { | ||
| 280 | drm_kms_helper_poll_fini(dev); | ||
| 281 | drm_mode_config_cleanup(dev); | ||
| 282 | kfree(private); | ||
| 283 | return ret; | ||
| 284 | } | ||
| 285 | |||
| 286 | drm_mode_config_reset(dev); | ||
| 287 | |||
| 288 | drm_helper_disable_unused_functions(dev); | ||
| 289 | drm_fbdev_cma_init(dev, 32, | ||
| 290 | dev->mode_config.num_crtc, | ||
| 291 | dev->mode_config.num_connector); | ||
| 292 | |||
| 293 | return 0; | ||
| 294 | } | ||
| 295 | |||
| 296 | static const struct file_operations sti_driver_fops = { | 271 | static const struct file_operations sti_driver_fops = { |
| 297 | .owner = THIS_MODULE, | 272 | .owner = THIS_MODULE, |
| 298 | .open = drm_open, | 273 | .open = drm_open, |
| @@ -309,8 +284,7 @@ static const struct file_operations sti_driver_fops = { | |||
| 309 | static struct drm_driver sti_driver = { | 284 | static struct drm_driver sti_driver = { |
| 310 | .driver_features = DRIVER_HAVE_IRQ | DRIVER_MODESET | | 285 | .driver_features = DRIVER_HAVE_IRQ | DRIVER_MODESET | |
| 311 | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC, | 286 | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC, |
| 312 | .load = sti_load, | 287 | .gem_free_object_unlocked = drm_gem_cma_free_object, |
| 313 | .gem_free_object = drm_gem_cma_free_object, | ||
| 314 | .gem_vm_ops = &drm_gem_cma_vm_ops, | 288 | .gem_vm_ops = &drm_gem_cma_vm_ops, |
| 315 | .dumb_create = drm_gem_cma_dumb_create, | 289 | .dumb_create = drm_gem_cma_dumb_create, |
| 316 | .dumb_map_offset = drm_gem_cma_dumb_map_offset, | 290 | .dumb_map_offset = drm_gem_cma_dumb_map_offset, |
| @@ -346,14 +320,88 @@ static int compare_of(struct device *dev, void *data) | |||
| 346 | return dev->of_node == data; | 320 | return dev->of_node == data; |
| 347 | } | 321 | } |
| 348 | 322 | ||
| 323 | static int sti_init(struct drm_device *ddev) | ||
| 324 | { | ||
| 325 | struct sti_private *private; | ||
| 326 | |||
| 327 | private = kzalloc(sizeof(*private), GFP_KERNEL); | ||
| 328 | if (!private) | ||
| 329 | return -ENOMEM; | ||
| 330 | |||
| 331 | ddev->dev_private = (void *)private; | ||
| 332 | dev_set_drvdata(ddev->dev, ddev); | ||
| 333 | private->drm_dev = ddev; | ||
| 334 | |||
| 335 | mutex_init(&private->commit.lock); | ||
| 336 | INIT_WORK(&private->commit.work, sti_atomic_work); | ||
| 337 | |||
| 338 | drm_mode_config_init(ddev); | ||
| 339 | |||
| 340 | sti_mode_config_init(ddev); | ||
| 341 | |||
| 342 | drm_kms_helper_poll_init(ddev); | ||
| 343 | |||
| 344 | return 0; | ||
| 345 | } | ||
| 346 | |||
| 347 | static void sti_cleanup(struct drm_device *ddev) | ||
| 348 | { | ||
| 349 | struct sti_private *private = ddev->dev_private; | ||
| 350 | |||
| 351 | if (private->fbdev) { | ||
| 352 | drm_fbdev_cma_fini(private->fbdev); | ||
| 353 | private->fbdev = NULL; | ||
| 354 | } | ||
| 355 | |||
| 356 | drm_kms_helper_poll_fini(ddev); | ||
| 357 | drm_vblank_cleanup(ddev); | ||
| 358 | kfree(private); | ||
| 359 | ddev->dev_private = NULL; | ||
| 360 | } | ||
| 361 | |||
| 349 | static int sti_bind(struct device *dev) | 362 | static int sti_bind(struct device *dev) |
| 350 | { | 363 | { |
| 351 | return drm_platform_init(&sti_driver, to_platform_device(dev)); | 364 | struct drm_device *ddev; |
| 365 | int ret; | ||
| 366 | |||
| 367 | ddev = drm_dev_alloc(&sti_driver, dev); | ||
| 368 | if (!ddev) | ||
| 369 | return -ENOMEM; | ||
| 370 | |||
| 371 | ddev->platformdev = to_platform_device(dev); | ||
| 372 | |||
| 373 | ret = sti_init(ddev); | ||
| 374 | if (ret) | ||
| 375 | goto err_drm_dev_unref; | ||
| 376 | |||
| 377 | ret = component_bind_all(ddev->dev, ddev); | ||
| 378 | if (ret) | ||
| 379 | goto err_cleanup; | ||
| 380 | |||
| 381 | ret = drm_dev_register(ddev, 0); | ||
| 382 | if (ret) | ||
| 383 | goto err_register; | ||
| 384 | |||
| 385 | drm_mode_config_reset(ddev); | ||
| 386 | |||
| 387 | return 0; | ||
| 388 | |||
| 389 | err_register: | ||
| 390 | drm_mode_config_cleanup(ddev); | ||
| 391 | err_cleanup: | ||
| 392 | sti_cleanup(ddev); | ||
| 393 | err_drm_dev_unref: | ||
| 394 | drm_dev_unref(ddev); | ||
| 395 | return ret; | ||
| 352 | } | 396 | } |
| 353 | 397 | ||
| 354 | static void sti_unbind(struct device *dev) | 398 | static void sti_unbind(struct device *dev) |
| 355 | { | 399 | { |
| 356 | drm_put_dev(dev_get_drvdata(dev)); | 400 | struct drm_device *ddev = dev_get_drvdata(dev); |
| 401 | |||
| 402 | drm_dev_unregister(ddev); | ||
| 403 | sti_cleanup(ddev); | ||
| 404 | drm_dev_unref(ddev); | ||
| 357 | } | 405 | } |
| 358 | 406 | ||
| 359 | static const struct component_master_ops sti_ops = { | 407 | static const struct component_master_ops sti_ops = { |
