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 2ed41d339f6a..e76ec2d207a9 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) |