diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_state.c')
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_state.c | 147 |
1 files changed, 93 insertions, 54 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 2ed41d339f6..e76ec2d207a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c | |||
| @@ -299,12 +299,57 @@ nouveau_vga_set_decode(void *priv, bool state) | |||
| 299 | return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; | 299 | return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; |
| 300 | } | 300 | } |
| 301 | 301 | ||
| 302 | static int | ||
| 303 | nouveau_card_init_channel(struct drm_device *dev) | ||
| 304 | { | ||
| 305 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 306 | struct nouveau_gpuobj *gpuobj; | ||
| 307 | int ret; | ||
| 308 | |||
| 309 | ret = nouveau_channel_alloc(dev, &dev_priv->channel, | ||
| 310 | (struct drm_file *)-2, | ||
| 311 | NvDmaFB, NvDmaTT); | ||
| 312 | if (ret) | ||
| 313 | return ret; | ||
| 314 | |||
| 315 | gpuobj = NULL; | ||
| 316 | ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, | ||
| 317 | 0, nouveau_mem_fb_amount(dev), | ||
| 318 | NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM, | ||
| 319 | &gpuobj); | ||
| 320 | if (ret) | ||
| 321 | goto out_err; | ||
| 322 | |||
| 323 | ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaVRAM, | ||
| 324 | gpuobj, NULL); | ||
| 325 | if (ret) | ||
| 326 | goto out_err; | ||
| 327 | |||
| 328 | gpuobj = NULL; | ||
| 329 | ret = nouveau_gpuobj_gart_dma_new(dev_priv->channel, 0, | ||
| 330 | dev_priv->gart_info.aper_size, | ||
| 331 | NV_DMA_ACCESS_RW, &gpuobj, NULL); | ||
| 332 | if (ret) | ||
| 333 | goto out_err; | ||
| 334 | |||
| 335 | ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaGART, | ||
| 336 | gpuobj, NULL); | ||
| 337 | if (ret) | ||
| 338 | goto out_err; | ||
| 339 | |||
| 340 | return 0; | ||
| 341 | out_err: | ||
| 342 | nouveau_gpuobj_del(dev, &gpuobj); | ||
| 343 | nouveau_channel_free(dev_priv->channel); | ||
| 344 | dev_priv->channel = NULL; | ||
| 345 | return ret; | ||
| 346 | } | ||
| 347 | |||
| 302 | int | 348 | int |
| 303 | nouveau_card_init(struct drm_device *dev) | 349 | nouveau_card_init(struct drm_device *dev) |
| 304 | { | 350 | { |
| 305 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 351 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 306 | struct nouveau_engine *engine; | 352 | struct nouveau_engine *engine; |
| 307 | struct nouveau_gpuobj *gpuobj; | ||
| 308 | int ret; | 353 | int ret; |
| 309 | 354 | ||
| 310 | NV_DEBUG(dev, "prev state = %d\n", dev_priv->init_state); | 355 | NV_DEBUG(dev, "prev state = %d\n", dev_priv->init_state); |
| @@ -317,7 +362,7 @@ nouveau_card_init(struct drm_device *dev) | |||
| 317 | /* Initialise internal driver API hooks */ | 362 | /* Initialise internal driver API hooks */ |
| 318 | ret = nouveau_init_engine_ptrs(dev); | 363 | ret = nouveau_init_engine_ptrs(dev); |
| 319 | if (ret) | 364 | if (ret) |
| 320 | return ret; | 365 | goto out; |
| 321 | engine = &dev_priv->engine; | 366 | engine = &dev_priv->engine; |
| 322 | dev_priv->init_state = NOUVEAU_CARD_INIT_FAILED; | 367 | dev_priv->init_state = NOUVEAU_CARD_INIT_FAILED; |
| 323 | 368 | ||
| @@ -325,12 +370,12 @@ nouveau_card_init(struct drm_device *dev) | |||
| 325 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 370 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
| 326 | ret = nouveau_bios_init(dev); | 371 | ret = nouveau_bios_init(dev); |
| 327 | if (ret) | 372 | if (ret) |
| 328 | return ret; | 373 | goto out; |
| 329 | } | 374 | } |
| 330 | 375 | ||
| 331 | ret = nouveau_gpuobj_early_init(dev); | 376 | ret = nouveau_gpuobj_early_init(dev); |
| 332 | if (ret) | 377 | if (ret) |
| 333 | return ret; | 378 | goto out_bios; |
| 334 | 379 | ||
| 335 | /* Initialise instance memory, must happen before mem_init so we | 380 | /* Initialise instance memory, must happen before mem_init so we |
| 336 | * know exactly how much VRAM we're able to use for "normal" | 381 | * know exactly how much VRAM we're able to use for "normal" |
| @@ -338,100 +383,68 @@ nouveau_card_init(struct drm_device *dev) | |||
| 338 | */ | 383 | */ |
| 339 | ret = engine->instmem.init(dev); | 384 | ret = engine->instmem.init(dev); |
| 340 | if (ret) | 385 | if (ret) |
| 341 | return ret; | 386 | goto out_gpuobj_early; |
| 342 | 387 | ||
| 343 | /* Setup the memory manager */ | 388 | /* Setup the memory manager */ |
| 344 | ret = nouveau_mem_init(dev); | 389 | ret = nouveau_mem_init(dev); |
| 345 | if (ret) | 390 | if (ret) |
| 346 | return ret; | 391 | goto out_instmem; |
| 347 | 392 | ||
| 348 | ret = nouveau_gpuobj_init(dev); | 393 | ret = nouveau_gpuobj_init(dev); |
| 349 | if (ret) | 394 | if (ret) |
| 350 | return ret; | 395 | goto out_mem; |
| 351 | 396 | ||
| 352 | /* PMC */ | 397 | /* PMC */ |
| 353 | ret = engine->mc.init(dev); | 398 | ret = engine->mc.init(dev); |
| 354 | if (ret) | 399 | if (ret) |
| 355 | return ret; | 400 | goto out_gpuobj; |
| 356 | 401 | ||
| 357 | /* PTIMER */ | 402 | /* PTIMER */ |
| 358 | ret = engine->timer.init(dev); | 403 | ret = engine->timer.init(dev); |
| 359 | if (ret) | 404 | if (ret) |
| 360 | return ret; | 405 | goto out_mc; |
| 361 | 406 | ||
| 362 | /* PFB */ | 407 | /* PFB */ |
| 363 | ret = engine->fb.init(dev); | 408 | ret = engine->fb.init(dev); |
| 364 | if (ret) | 409 | if (ret) |
| 365 | return ret; | 410 | goto out_timer; |
| 366 | 411 | ||
| 367 | /* PGRAPH */ | 412 | /* PGRAPH */ |
| 368 | ret = engine->graph.init(dev); | 413 | ret = engine->graph.init(dev); |
| 369 | if (ret) | 414 | if (ret) |
| 370 | return ret; | 415 | goto out_fb; |
| 371 | 416 | ||
| 372 | /* PFIFO */ | 417 | /* PFIFO */ |
| 373 | ret = engine->fifo.init(dev); | 418 | ret = engine->fifo.init(dev); |
| 374 | if (ret) | 419 | if (ret) |
| 375 | return ret; | 420 | goto out_graph; |
| 376 | 421 | ||
| 377 | /* this call irq_preinstall, register irq handler and | 422 | /* this call irq_preinstall, register irq handler and |
| 378 | * call irq_postinstall | 423 | * call irq_postinstall |
| 379 | */ | 424 | */ |
| 380 | ret = drm_irq_install(dev); | 425 | ret = drm_irq_install(dev); |
| 381 | if (ret) | 426 | if (ret) |
| 382 | return ret; | 427 | goto out_fifo; |
| 383 | 428 | ||
| 384 | ret = drm_vblank_init(dev, 0); | 429 | ret = drm_vblank_init(dev, 0); |
| 385 | if (ret) | 430 | if (ret) |
| 386 | return ret; | 431 | goto out_irq; |
| 387 | 432 | ||
| 388 | /* what about PVIDEO/PCRTC/PRAMDAC etc? */ | 433 | /* what about PVIDEO/PCRTC/PRAMDAC etc? */ |
| 389 | 434 | ||
| 390 | ret = nouveau_channel_alloc(dev, &dev_priv->channel, | 435 | if (!engine->graph.accel_blocked) { |
| 391 | (struct drm_file *)-2, | 436 | ret = nouveau_card_init_channel(dev); |
| 392 | NvDmaFB, NvDmaTT); | 437 | if (ret) |
| 393 | if (ret) | 438 | goto out_irq; |
| 394 | return ret; | ||
| 395 | |||
| 396 | gpuobj = NULL; | ||
| 397 | ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, | ||
| 398 | 0, nouveau_mem_fb_amount(dev), | ||
| 399 | NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM, | ||
| 400 | &gpuobj); | ||
| 401 | if (ret) | ||
| 402 | return ret; | ||
| 403 | |||
| 404 | ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaVRAM, | ||
| 405 | gpuobj, NULL); | ||
| 406 | if (ret) { | ||
| 407 | nouveau_gpuobj_del(dev, &gpuobj); | ||
| 408 | return ret; | ||
| 409 | } | ||
| 410 | |||
| 411 | gpuobj = NULL; | ||
| 412 | ret = nouveau_gpuobj_gart_dma_new(dev_priv->channel, 0, | ||
| 413 | dev_priv->gart_info.aper_size, | ||
| 414 | NV_DMA_ACCESS_RW, &gpuobj, NULL); | ||
| 415 | if (ret) | ||
| 416 | return ret; | ||
| 417 | |||
| 418 | ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaGART, | ||
| 419 | gpuobj, NULL); | ||
| 420 | if (ret) { | ||
| 421 | nouveau_gpuobj_del(dev, &gpuobj); | ||
| 422 | return ret; | ||
| 423 | } | 439 | } |
| 424 | 440 | ||
| 425 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 441 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
| 426 | if (dev_priv->card_type >= NV_50) { | 442 | if (dev_priv->card_type >= NV_50) |
| 427 | ret = nv50_display_create(dev); | 443 | ret = nv50_display_create(dev); |
| 428 | if (ret) | 444 | else |
| 429 | return ret; | ||
| 430 | } else { | ||
| 431 | ret = nv04_display_create(dev); | 445 | ret = nv04_display_create(dev); |
| 432 | if (ret) | 446 | if (ret) |
| 433 | return ret; | 447 | goto out_irq; |
| 434 | } | ||
| 435 | } | 448 | } |
| 436 | 449 | ||
| 437 | ret = nouveau_backlight_init(dev); | 450 | ret = nouveau_backlight_init(dev); |
| @@ -444,6 +457,32 @@ nouveau_card_init(struct drm_device *dev) | |||
| 444 | drm_helper_initial_config(dev); | 457 | drm_helper_initial_config(dev); |
| 445 | 458 | ||
| 446 | return 0; | 459 | return 0; |
| 460 | |||
| 461 | out_irq: | ||
| 462 | drm_irq_uninstall(dev); | ||
| 463 | out_fifo: | ||
| 464 | engine->fifo.takedown(dev); | ||
| 465 | out_graph: | ||
| 466 | engine->graph.takedown(dev); | ||
| 467 | out_fb: | ||
| 468 | engine->fb.takedown(dev); | ||
| 469 | out_timer: | ||
| 470 | engine->timer.takedown(dev); | ||
| 471 | out_mc: | ||
| 472 | engine->mc.takedown(dev); | ||
| 473 | out_gpuobj: | ||
| 474 | nouveau_gpuobj_takedown(dev); | ||
| 475 | out_mem: | ||
| 476 | nouveau_mem_close(dev); | ||
| 477 | out_instmem: | ||
| 478 | engine->instmem.takedown(dev); | ||
| 479 | out_gpuobj_early: | ||
| 480 | nouveau_gpuobj_late_takedown(dev); | ||
| 481 | out_bios: | ||
| 482 | nouveau_bios_takedown(dev); | ||
| 483 | out: | ||
| 484 | vga_client_register(dev->pdev, NULL, NULL, NULL); | ||
| 485 | return ret; | ||
| 447 | } | 486 | } |
| 448 | 487 | ||
| 449 | static void nouveau_card_takedown(struct drm_device *dev) | 488 | static void nouveau_card_takedown(struct drm_device *dev) |
