Commit f22d6dda authored by Dave Airlie's avatar Dave Airlie

Merge branch 'for-airlied' of /ssd/git/drm-nouveau-next into drm-linus

* 'for-airlied' of /ssd/git/drm-nouveau-next: (28 commits)
  drm/nv04: Fix set_operation software method.
  drm/nouveau: initialise DMA tracking parameters earlier
  drm/nouveau: use dma.max rather than pushbuf size for checking GET validity
  drm/nv04: differentiate between nv04/nv05
  drm/nouveau: Fix null deref in nouveau_fence_emit due to deleted fence
  drm/nv50: prevent a possible ctxprog hang
  drm/nouveau: have ttm's fault handler called directly
  drm/nv50: restore correct cache1 get/put address on fifoctx load
  drm/nouveau: create function for "dealing" with gpu lockup
  drm/nouveau: remove unused nouveau_channel_idle() function
  drm/nouveau: fix handling of fbcon colours in 8bpp
  drm/nv04: Context switching fixes.
  drm/nouveau: Use the software object for fencing.
  drm/nouveau: Allocate a per-channel instance of NV_SW.
  drm/nv50: make the blocksize depend on vram size
  drm/nouveau: better alignment of bo sizes and use roundup instead of ALIGN
  drm/nouveau: Don't skip card take down on nv0x.
  drm/nouveau: Implement nv42-nv43 TV load detection.
  drm/nouveau: Clean up the nv17-nv4x load detection code a bit.
  drm/nv50: fix fillrect color
  ...
parents 0c9d2c41 40c2298b
...@@ -30,12 +30,11 @@ config DRM_NOUVEAU_DEBUG ...@@ -30,12 +30,11 @@ config DRM_NOUVEAU_DEBUG
via debugfs. via debugfs.
menu "I2C encoder or helper chips" menu "I2C encoder or helper chips"
depends on DRM && I2C depends on DRM && DRM_KMS_HELPER && I2C
config DRM_I2C_CH7006 config DRM_I2C_CH7006
tristate "Chrontel ch7006 TV encoder" tristate "Chrontel ch7006 TV encoder"
depends on DRM_NOUVEAU default m if DRM_NOUVEAU
default m
help help
Support for Chrontel ch7006 and similar TV encoders, found Support for Chrontel ch7006 and similar TV encoders, found
on some nVidia video cards. on some nVidia video cards.
......
This diff is collapsed.
...@@ -158,6 +158,8 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, ...@@ -158,6 +158,8 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
return ret; return ret;
} }
nouveau_dma_pre_init(chan);
/* Locate channel's user control regs */ /* Locate channel's user control regs */
if (dev_priv->card_type < NV_40) if (dev_priv->card_type < NV_40)
user = NV03_USER(channel); user = NV03_USER(channel);
...@@ -235,47 +237,6 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, ...@@ -235,47 +237,6 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
return 0; return 0;
} }
int
nouveau_channel_idle(struct nouveau_channel *chan)
{
struct drm_device *dev = chan->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_engine *engine = &dev_priv->engine;
uint32_t caches;
int idle;
if (!chan) {
NV_ERROR(dev, "no channel...\n");
return 1;
}
caches = nv_rd32(dev, NV03_PFIFO_CACHES);
nv_wr32(dev, NV03_PFIFO_CACHES, caches & ~1);
if (engine->fifo.channel_id(dev) != chan->id) {
struct nouveau_gpuobj *ramfc =
chan->ramfc ? chan->ramfc->gpuobj : NULL;
if (!ramfc) {
NV_ERROR(dev, "No RAMFC for channel %d\n", chan->id);
return 1;
}
engine->instmem.prepare_access(dev, false);
if (nv_ro32(dev, ramfc, 0) != nv_ro32(dev, ramfc, 1))
idle = 0;
else
idle = 1;
engine->instmem.finish_access(dev);
} else {
idle = (nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET) ==
nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT));
}
nv_wr32(dev, NV03_PFIFO_CACHES, caches);
return idle;
}
/* stops a fifo */ /* stops a fifo */
void void
nouveau_channel_free(struct nouveau_channel *chan) nouveau_channel_free(struct nouveau_channel *chan)
...@@ -414,7 +375,9 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, ...@@ -414,7 +375,9 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data,
init->subchan[0].grclass = 0x0039; init->subchan[0].grclass = 0x0039;
else else
init->subchan[0].grclass = 0x5039; init->subchan[0].grclass = 0x5039;
init->nr_subchan = 1; init->subchan[1].handle = NvSw;
init->subchan[1].grclass = NV_SW;
init->nr_subchan = 2;
/* Named memory object area */ /* Named memory object area */
ret = drm_gem_handle_create(file_priv, chan->notifier_bo->gem, ret = drm_gem_handle_create(file_priv, chan->notifier_bo->gem,
......
...@@ -29,12 +29,22 @@ ...@@ -29,12 +29,22 @@
#include "nouveau_drv.h" #include "nouveau_drv.h"
#include "nouveau_dma.h" #include "nouveau_dma.h"
void
nouveau_dma_pre_init(struct nouveau_channel *chan)
{
chan->dma.max = (chan->pushbuf_bo->bo.mem.size >> 2) - 2;
chan->dma.put = 0;
chan->dma.cur = chan->dma.put;
chan->dma.free = chan->dma.max - chan->dma.cur;
}
int int
nouveau_dma_init(struct nouveau_channel *chan) nouveau_dma_init(struct nouveau_channel *chan)
{ {
struct drm_device *dev = chan->dev; struct drm_device *dev = chan->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_gpuobj *m2mf = NULL; struct nouveau_gpuobj *m2mf = NULL;
struct nouveau_gpuobj *nvsw = NULL;
int ret, i; int ret, i;
/* Create NV_MEMORY_TO_MEMORY_FORMAT for buffer moves */ /* Create NV_MEMORY_TO_MEMORY_FORMAT for buffer moves */
...@@ -47,6 +57,15 @@ nouveau_dma_init(struct nouveau_channel *chan) ...@@ -47,6 +57,15 @@ nouveau_dma_init(struct nouveau_channel *chan)
if (ret) if (ret)
return ret; return ret;
/* Create an NV_SW object for various sync purposes */
ret = nouveau_gpuobj_sw_new(chan, NV_SW, &nvsw);
if (ret)
return ret;
ret = nouveau_gpuobj_ref_add(dev, chan, NvSw, nvsw, NULL);
if (ret)
return ret;
/* NV_MEMORY_TO_MEMORY_FORMAT requires a notifier object */ /* NV_MEMORY_TO_MEMORY_FORMAT requires a notifier object */
ret = nouveau_notifier_alloc(chan, NvNotify0, 32, &chan->m2mf_ntfy); ret = nouveau_notifier_alloc(chan, NvNotify0, 32, &chan->m2mf_ntfy);
if (ret) if (ret)
...@@ -64,12 +83,6 @@ nouveau_dma_init(struct nouveau_channel *chan) ...@@ -64,12 +83,6 @@ nouveau_dma_init(struct nouveau_channel *chan)
return ret; return ret;
} }
/* Initialise DMA vars */
chan->dma.max = (chan->pushbuf_bo->bo.mem.size >> 2) - 2;
chan->dma.put = 0;
chan->dma.cur = chan->dma.put;
chan->dma.free = chan->dma.max - chan->dma.cur;
/* Insert NOPS for NOUVEAU_DMA_SKIPS */ /* Insert NOPS for NOUVEAU_DMA_SKIPS */
ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS); ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS);
if (ret) if (ret)
...@@ -87,6 +100,13 @@ nouveau_dma_init(struct nouveau_channel *chan) ...@@ -87,6 +100,13 @@ nouveau_dma_init(struct nouveau_channel *chan)
BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1); BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
OUT_RING(chan, NvNotify0); OUT_RING(chan, NvNotify0);
/* Initialise NV_SW */
ret = RING_SPACE(chan, 2);
if (ret)
return ret;
BEGIN_RING(chan, NvSubSw, 0, 1);
OUT_RING(chan, NvSw);
/* Sit back and pray the channel works.. */ /* Sit back and pray the channel works.. */
FIRE_RING(chan); FIRE_RING(chan);
...@@ -113,7 +133,7 @@ READ_GET(struct nouveau_channel *chan, uint32_t *get) ...@@ -113,7 +133,7 @@ READ_GET(struct nouveau_channel *chan, uint32_t *get)
val = nvchan_rd32(chan, chan->user_get); val = nvchan_rd32(chan, chan->user_get);
if (val < chan->pushbuf_base || if (val < chan->pushbuf_base ||
val >= chan->pushbuf_base + chan->pushbuf_bo->bo.mem.size) { val > chan->pushbuf_base + (chan->dma.max << 2)) {
/* meaningless to dma_wait() except to know whether the /* meaningless to dma_wait() except to know whether the
* GPU has stalled or not * GPU has stalled or not
*/ */
......
...@@ -46,10 +46,11 @@ ...@@ -46,10 +46,11 @@
/* Hardcoded object assignments to subchannels (subchannel id). */ /* Hardcoded object assignments to subchannels (subchannel id). */
enum { enum {
NvSubM2MF = 0, NvSubM2MF = 0,
NvSub2D = 1, NvSubSw = 1,
NvSubCtxSurf2D = 1, NvSub2D = 2,
NvSubGdiRect = 2, NvSubCtxSurf2D = 2,
NvSubImageBlit = 3 NvSubGdiRect = 3,
NvSubImageBlit = 4
}; };
/* Object handles. */ /* Object handles. */
...@@ -67,6 +68,7 @@ enum { ...@@ -67,6 +68,7 @@ enum {
NvClipRect = 0x8000000b, NvClipRect = 0x8000000b,
NvGdiRect = 0x8000000c, NvGdiRect = 0x8000000c,
NvImageBlit = 0x8000000d, NvImageBlit = 0x8000000d,
NvSw = 0x8000000e,
/* G80+ display objects */ /* G80+ display objects */
NvEvoVRAM = 0x01000000, NvEvoVRAM = 0x01000000,
......
...@@ -59,11 +59,19 @@ struct nouveau_grctx; ...@@ -59,11 +59,19 @@ struct nouveau_grctx;
#define MAX_NUM_DCB_ENTRIES 16 #define MAX_NUM_DCB_ENTRIES 16
#define NOUVEAU_MAX_CHANNEL_NR 128 #define NOUVEAU_MAX_CHANNEL_NR 128
#define NOUVEAU_MAX_TILE_NR 15
#define NV50_VM_MAX_VRAM (2*1024*1024*1024ULL) #define NV50_VM_MAX_VRAM (2*1024*1024*1024ULL)
#define NV50_VM_BLOCK (512*1024*1024ULL) #define NV50_VM_BLOCK (512*1024*1024ULL)
#define NV50_VM_VRAM_NR (NV50_VM_MAX_VRAM / NV50_VM_BLOCK) #define NV50_VM_VRAM_NR (NV50_VM_MAX_VRAM / NV50_VM_BLOCK)
struct nouveau_tile_reg {
struct nouveau_fence *fence;
uint32_t addr;
uint32_t size;
bool used;
};
struct nouveau_bo { struct nouveau_bo {
struct ttm_buffer_object bo; struct ttm_buffer_object bo;
struct ttm_placement placement; struct ttm_placement placement;
...@@ -83,6 +91,7 @@ struct nouveau_bo { ...@@ -83,6 +91,7 @@ struct nouveau_bo {
uint32_t tile_mode; uint32_t tile_mode;
uint32_t tile_flags; uint32_t tile_flags;
struct nouveau_tile_reg *tile;
struct drm_gem_object *gem; struct drm_gem_object *gem;
struct drm_file *cpu_filp; struct drm_file *cpu_filp;
...@@ -277,8 +286,13 @@ struct nouveau_timer_engine { ...@@ -277,8 +286,13 @@ struct nouveau_timer_engine {
}; };
struct nouveau_fb_engine { struct nouveau_fb_engine {
int num_tiles;
int (*init)(struct drm_device *dev); int (*init)(struct drm_device *dev);
void (*takedown)(struct drm_device *dev); void (*takedown)(struct drm_device *dev);
void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr,
uint32_t size, uint32_t pitch);
}; };
struct nouveau_fifo_engine { struct nouveau_fifo_engine {
...@@ -292,6 +306,8 @@ struct nouveau_fifo_engine { ...@@ -292,6 +306,8 @@ struct nouveau_fifo_engine {
void (*disable)(struct drm_device *); void (*disable)(struct drm_device *);
void (*enable)(struct drm_device *); void (*enable)(struct drm_device *);
bool (*reassign)(struct drm_device *, bool enable); bool (*reassign)(struct drm_device *, bool enable);
bool (*cache_flush)(struct drm_device *dev);
bool (*cache_pull)(struct drm_device *dev, bool enable);
int (*channel_id)(struct drm_device *); int (*channel_id)(struct drm_device *);
...@@ -330,6 +346,9 @@ struct nouveau_pgraph_engine { ...@@ -330,6 +346,9 @@ struct nouveau_pgraph_engine {
void (*destroy_context)(struct nouveau_channel *); void (*destroy_context)(struct nouveau_channel *);
int (*load_context)(struct nouveau_channel *); int (*load_context)(struct nouveau_channel *);
int (*unload_context)(struct drm_device *); int (*unload_context)(struct drm_device *);
void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr,
uint32_t size, uint32_t pitch);
}; };
struct nouveau_engine { struct nouveau_engine {
...@@ -548,6 +567,12 @@ struct drm_nouveau_private { ...@@ -548,6 +567,12 @@ struct drm_nouveau_private {
unsigned long sg_handle; unsigned long sg_handle;
} gart_info; } gart_info;
/* nv10-nv40 tiling regions */
struct {
struct nouveau_tile_reg reg[NOUVEAU_MAX_TILE_NR];
spinlock_t lock;
} tile;
/* G8x/G9x virtual address space */ /* G8x/G9x virtual address space */
uint64_t vm_gart_base; uint64_t vm_gart_base;
uint64_t vm_gart_size; uint64_t vm_gart_size;
...@@ -685,6 +710,13 @@ extern void nouveau_mem_release(struct drm_file *, struct mem_block *heap); ...@@ -685,6 +710,13 @@ extern void nouveau_mem_release(struct drm_file *, struct mem_block *heap);
extern int nouveau_mem_init(struct drm_device *); extern int nouveau_mem_init(struct drm_device *);
extern int nouveau_mem_init_agp(struct drm_device *); extern int nouveau_mem_init_agp(struct drm_device *);
extern void nouveau_mem_close(struct drm_device *); extern void nouveau_mem_close(struct drm_device *);
extern struct nouveau_tile_reg *nv10_mem_set_tiling(struct drm_device *dev,
uint32_t addr,
uint32_t size,
uint32_t pitch);
extern void nv10_mem_expire_tiling(struct drm_device *dev,
struct nouveau_tile_reg *tile,
struct nouveau_fence *fence);
extern int nv50_mem_vm_bind_linear(struct drm_device *, uint64_t virt, extern int nv50_mem_vm_bind_linear(struct drm_device *, uint64_t virt,
uint32_t size, uint32_t flags, uint32_t size, uint32_t flags,
uint64_t phys); uint64_t phys);
...@@ -713,7 +745,6 @@ extern int nouveau_channel_alloc(struct drm_device *dev, ...@@ -713,7 +745,6 @@ extern int nouveau_channel_alloc(struct drm_device *dev,
struct drm_file *file_priv, struct drm_file *file_priv,
uint32_t fb_ctxdma, uint32_t tt_ctxdma); uint32_t fb_ctxdma, uint32_t tt_ctxdma);
extern void nouveau_channel_free(struct nouveau_channel *); extern void nouveau_channel_free(struct nouveau_channel *);
extern int nouveau_channel_idle(struct nouveau_channel *chan);
/* nouveau_object.c */ /* nouveau_object.c */
extern int nouveau_gpuobj_early_init(struct drm_device *); extern int nouveau_gpuobj_early_init(struct drm_device *);
...@@ -756,6 +787,8 @@ extern int nouveau_gpuobj_gart_dma_new(struct nouveau_channel *, ...@@ -756,6 +787,8 @@ extern int nouveau_gpuobj_gart_dma_new(struct nouveau_channel *,
uint32_t *o_ret); uint32_t *o_ret);
extern int nouveau_gpuobj_gr_new(struct nouveau_channel *, int class, extern int nouveau_gpuobj_gr_new(struct nouveau_channel *, int class,
struct nouveau_gpuobj **); struct nouveau_gpuobj **);
extern int nouveau_gpuobj_sw_new(struct nouveau_channel *, int class,
struct nouveau_gpuobj **);
extern int nouveau_ioctl_grobj_alloc(struct drm_device *, void *data, extern int nouveau_ioctl_grobj_alloc(struct drm_device *, void *data,
struct drm_file *); struct drm_file *);
extern int nouveau_ioctl_gpuobj_free(struct drm_device *, void *data, extern int nouveau_ioctl_gpuobj_free(struct drm_device *, void *data,
...@@ -804,6 +837,7 @@ nouveau_debugfs_channel_fini(struct nouveau_channel *chan) ...@@ -804,6 +837,7 @@ nouveau_debugfs_channel_fini(struct nouveau_channel *chan)
#endif #endif
/* nouveau_dma.c */ /* nouveau_dma.c */
extern void nouveau_dma_pre_init(struct nouveau_channel *);
extern int nouveau_dma_init(struct nouveau_channel *); extern int nouveau_dma_init(struct nouveau_channel *);
extern int nouveau_dma_wait(struct nouveau_channel *, int size); extern int nouveau_dma_wait(struct nouveau_channel *, int size);
...@@ -879,16 +913,22 @@ extern void nv04_fb_takedown(struct drm_device *); ...@@ -879,16 +913,22 @@ extern void nv04_fb_takedown(struct drm_device *);
/* nv10_fb.c */ /* nv10_fb.c */
extern int nv10_fb_init(struct drm_device *); extern int nv10_fb_init(struct drm_device *);
extern void nv10_fb_takedown(struct drm_device *); extern void nv10_fb_takedown(struct drm_device *);
extern void nv10_fb_set_region_tiling(struct drm_device *, int, uint32_t,
uint32_t, uint32_t);
/* nv40_fb.c */ /* nv40_fb.c */
extern int nv40_fb_init(struct drm_device *); extern int nv40_fb_init(struct drm_device *);
extern void nv40_fb_takedown(struct drm_device *); extern void nv40_fb_takedown(struct drm_device *);
extern void nv40_fb_set_region_tiling(struct drm_device *, int, uint32_t,
uint32_t, uint32_t);
/* nv04_fifo.c */ /* nv04_fifo.c */
extern int nv04_fifo_init(struct drm_device *); extern int nv04_fifo_init(struct drm_device *);
extern void nv04_fifo_disable(struct drm_device *); extern void nv04_fifo_disable(struct drm_device *);
extern void nv04_fifo_enable(struct drm_device *); extern void nv04_fifo_enable(struct drm_device *);
extern bool nv04_fifo_reassign(struct drm_device *, bool); extern bool nv04_fifo_reassign(struct drm_device *, bool);
extern bool nv04_fifo_cache_flush(struct drm_device *);
extern bool nv04_fifo_cache_pull(struct drm_device *, bool);
extern int nv04_fifo_channel_id(struct drm_device *); extern int nv04_fifo_channel_id(struct drm_device *);
extern int nv04_fifo_create_context(struct nouveau_channel *); extern int nv04_fifo_create_context(struct nouveau_channel *);
extern void nv04_fifo_destroy_context(struct nouveau_channel *); extern void nv04_fifo_destroy_context(struct nouveau_channel *);
...@@ -941,6 +981,8 @@ extern void nv10_graph_destroy_context(struct nouveau_channel *); ...@@ -941,6 +981,8 @@ extern void nv10_graph_destroy_context(struct nouveau_channel *);
extern int nv10_graph_load_context(struct nouveau_channel *); extern int nv10_graph_load_context(struct nouveau_channel *);
extern int nv10_graph_unload_context(struct drm_device *); extern int nv10_graph_unload_context(struct drm_device *);
extern void nv10_graph_context_switch(struct drm_device *); extern void nv10_graph_context_switch(struct drm_device *);
extern void nv10_graph_set_region_tiling(struct drm_device *, int, uint32_t,
uint32_t, uint32_t);
/* nv20_graph.c */ /* nv20_graph.c */
extern struct nouveau_pgraph_object_class nv20_graph_grclass[]; extern struct nouveau_pgraph_object_class nv20_graph_grclass[];
...@@ -952,6 +994,8 @@ extern int nv20_graph_unload_context(struct drm_device *); ...@@ -952,6 +994,8 @@ extern int nv20_graph_unload_context(struct drm_device *);
extern int nv20_graph_init(struct drm_device *); extern int nv20_graph_init(struct drm_device *);
extern void nv20_graph_takedown(struct drm_device *); extern void nv20_graph_takedown(struct drm_device *);
extern int nv30_graph_init(struct drm_device *); extern int nv30_graph_init(struct drm_device *);
extern void nv20_graph_set_region_tiling(struct drm_device *, int, uint32_t,
uint32_t, uint32_t);
/* nv40_graph.c */ /* nv40_graph.c */
extern struct nouveau_pgraph_object_class nv40_graph_grclass[]; extern struct nouveau_pgraph_object_class nv40_graph_grclass[];
...@@ -963,6 +1007,8 @@ extern void nv40_graph_destroy_context(struct nouveau_channel *); ...@@ -963,6 +1007,8 @@ extern void nv40_graph_destroy_context(struct nouveau_channel *);
extern int nv40_graph_load_context(struct nouveau_channel *); extern int nv40_graph_load_context(struct nouveau_channel *);
extern int nv40_graph_unload_context(struct drm_device *); extern int nv40_graph_unload_context(struct drm_device *);
extern void nv40_grctx_init(struct nouveau_grctx *); extern void nv40_grctx_init(struct nouveau_grctx *);
extern void nv40_graph_set_region_tiling(struct drm_device *, int, uint32_t,
uint32_t, uint32_t);
/* nv50_graph.c */ /* nv50_graph.c */
extern struct nouveau_pgraph_object_class nv50_graph_grclass[]; extern struct nouveau_pgraph_object_class nv50_graph_grclass[];
...@@ -1030,8 +1076,7 @@ extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd, ...@@ -1030,8 +1076,7 @@ extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd,
/* nv04_dac.c */ /* nv04_dac.c */
extern int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry); extern int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry);
extern enum drm_connector_status nv17_dac_detect(struct drm_encoder *encoder, extern uint32_t nv17_dac_sample_load(struct drm_encoder *encoder);
struct drm_connector *connector);
extern int nv04_dac_output_offset(struct drm_encoder *encoder); extern int nv04_dac_output_offset(struct drm_encoder *encoder);
extern void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable); extern void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable);
...@@ -1049,9 +1094,6 @@ extern int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry); ...@@ -1049,9 +1094,6 @@ extern int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry);
/* nv17_tv.c */ /* nv17_tv.c */
extern int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry); extern int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry);
extern enum drm_connector_status nv17_tv_detect(struct drm_encoder *encoder,
struct drm_connector *connector,
uint32_t pin_mask);
/* nv04_display.c */ /* nv04_display.c */
extern int nv04_display_create(struct drm_device *); extern int nv04_display_create(struct drm_device *);
...@@ -1290,14 +1332,14 @@ nv_two_reg_pll(struct drm_device *dev) ...@@ -1290,14 +1332,14 @@ nv_two_reg_pll(struct drm_device *dev)
return false; return false;
} }
#define NV50_NVSW 0x0000506e #define NV_SW 0x0000506e
#define NV50_NVSW_DMA_SEMAPHORE 0x00000060 #define NV_SW_DMA_SEMAPHORE 0x00000060
#define NV50_NVSW_SEMAPHORE_OFFSET 0x00000064 #define NV_SW_SEMAPHORE_OFFSET 0x00000064
#define NV50_NVSW_SEMAPHORE_ACQUIRE 0x00000068 #define NV_SW_SEMAPHORE_ACQUIRE 0x00000068
#define NV50_NVSW_SEMAPHORE_RELEASE 0x0000006c #define NV_SW_SEMAPHORE_RELEASE 0x0000006c
#define NV50_NVSW_DMA_VBLSEM 0x0000018c #define NV_SW_DMA_VBLSEM 0x0000018c
#define NV50_NVSW_VBLSEM_OFFSET 0x00000400 #define NV_SW_VBLSEM_OFFSET 0x00000400
#define NV50_NVSW_VBLSEM_RELEASE_VALUE 0x00000404 #define NV_SW_VBLSEM_RELEASE_VALUE 0x00000404
#define NV50_NVSW_VBLSEM_RELEASE 0x00000408 #define NV_SW_VBLSEM_RELEASE 0x00000408
#endif /* __NOUVEAU_DRV_H__ */ #endif /* __NOUVEAU_DRV_H__ */
...@@ -64,8 +64,7 @@ nouveau_fbcon_sync(struct fb_info *info) ...@@ -64,8 +64,7 @@ nouveau_fbcon_sync(struct fb_info *info)
return 0; return 0;
if (RING_SPACE(chan, 4)) { if (RING_SPACE(chan, 4)) {
NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); nouveau_fbcon_gpu_lockup(info);
info->flags |= FBINFO_HWACCEL_DISABLED;
return 0; return 0;
} }
...@@ -86,8 +85,7 @@ nouveau_fbcon_sync(struct fb_info *info) ...@@ -86,8 +85,7 @@ nouveau_fbcon_sync(struct fb_info *info)
} }
if (ret) { if (ret) {
NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); nouveau_fbcon_gpu_lockup(info);
info->flags |= FBINFO_HWACCEL_DISABLED;
return 0; return 0;
} }
...@@ -212,11 +210,11 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width, ...@@ -212,11 +210,11 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width,
mode_cmd.bpp = surface_bpp; mode_cmd.bpp = surface_bpp;
mode_cmd.pitch = mode_cmd.width * (mode_cmd.bpp >> 3); mode_cmd.pitch = mode_cmd.width * (mode_cmd.bpp >> 3);
mode_cmd.pitch = ALIGN(mode_cmd.pitch, 256); mode_cmd.pitch = roundup(mode_cmd.pitch, 256);
mode_cmd.depth = surface_depth; mode_cmd.depth = surface_depth;
size = mode_cmd.pitch * mode_cmd.height; size = mode_cmd.pitch * mode_cmd.height;
size = ALIGN(size, PAGE_SIZE); size = roundup(size, PAGE_SIZE);
ret = nouveau_gem_new(dev, dev_priv->channel, size, 0, TTM_PL_FLAG_VRAM, ret = nouveau_gem_new(dev, dev_priv->channel, size, 0, TTM_PL_FLAG_VRAM,
0, 0x0000, false, true, &nvbo); 0, 0x0000, false, true, &nvbo);
...@@ -380,3 +378,12 @@ nouveau_fbcon_remove(struct drm_device *dev, struct drm_framebuffer *fb) ...@@ -380,3 +378,12 @@ nouveau_fbcon_remove(struct drm_device *dev, struct drm_framebuffer *fb)
return 0; return 0;
} }
void nouveau_fbcon_gpu_lockup(struct fb_info *info)
{
struct nouveau_fbcon_par *par = info->par;
struct drm_device *dev = par->dev;
NV_ERROR(dev, "GPU lockup - switching to software fbcon\n");
info->flags |= FBINFO_HWACCEL_DISABLED;
}
...@@ -43,5 +43,6 @@ void nouveau_fbcon_zfill(struct drm_device *dev); ...@@ -43,5 +43,6 @@ void nouveau_fbcon_zfill(struct drm_device *dev);
int nv04_fbcon_accel_init(struct fb_info *info); int nv04_fbcon_accel_init(struct fb_info *info);
int nv50_fbcon_accel_init(struct fb_info *info); int nv50_fbcon_accel_init(struct fb_info *info);
void nouveau_fbcon_gpu_lockup(struct fb_info *info);
#endif /* __NV50_FBCON_H__ */ #endif /* __NV50_FBCON_H__ */
...@@ -142,7 +142,7 @@ nouveau_fence_emit(struct nouveau_fence *fence) ...@@ -142,7 +142,7 @@ nouveau_fence_emit(struct nouveau_fence *fence)
list_add_tail(&fence->entry, &chan->fence.pending); list_add_tail(&fence->entry, &chan->fence.pending);
spin_unlock_irqrestore(&chan->fence.lock, flags); spin_unlock_irqrestore(&chan->fence.lock, flags);
BEGIN_RING(chan, NvSubM2MF, USE_REFCNT ? 0x0050 : 0x0150, 1); BEGIN_RING(chan, NvSubSw, USE_REFCNT ? 0x0050 : 0x0150, 1);
OUT_RING(chan, fence->sequence); OUT_RING(chan, fence->sequence);
FIRE_RING(chan); FIRE_RING(chan);
......
...@@ -220,7 +220,6 @@ nouveau_gem_set_domain(struct drm_gem_object *gem, uint32_t read_domains, ...@@ -220,7 +220,6 @@ nouveau_gem_set_domain(struct drm_gem_object *gem, uint32_t read_domains,
} }
struct validate_op { struct validate_op {
struct nouveau_fence *fence;
struct list_head vram_list; struct list_head vram_list;
struct list_head gart_list; struct list_head gart_list;
struct list_head both_list; struct list_head both_list;
...@@ -252,17 +251,11 @@ validate_fini_list(struct list_head *list, struct nouveau_fence *fence) ...@@ -252,17 +251,11 @@ validate_fini_list(struct list_head *list, struct nouveau_fence *fence)
} }
static void static void
validate_fini(struct validate_op *op, bool success) validate_fini(struct validate_op *op, struct nouveau_fence* fence)
{ {
struct nouveau_fence *fence = op->fence; validate_fini_list(&op->vram_list, fence);
validate_fini_list(&op->gart_list, fence);
if (unlikely(!success)) validate_fini_list(&op->both_list, fence);
op->fence = NULL;
validate_fini_list(&op->vram_list, op->fence);
validate_fini_list(&op->gart_list, op->fence);
validate_fini_list(&op->both_list, op->fence);
nouveau_fence_unref((void *)&fence);
} }
static int static int
...@@ -420,10 +413,6 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan, ...@@ -420,10 +413,6 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan,
INIT_LIST_HEAD(&op->gart_list); INIT_LIST_HEAD(&op->gart_list);
INIT_LIST_HEAD(&op->both_list); INIT_LIST_HEAD(&op->both_list);
ret = nouveau_fence_new(chan, &op->fence, false);
if (ret)
return ret;
if (nr_buffers == 0) if (nr_buffers == 0)
return 0; return 0;
...@@ -541,6 +530,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, ...@@ -541,6 +530,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
struct drm_nouveau_gem_pushbuf_bo *bo = NULL; struct drm_nouveau_gem_pushbuf_bo *bo = NULL;
struct nouveau_channel *chan; struct nouveau_channel *chan;
struct validate_op op; struct validate_op op;
struct nouveau_fence* fence = 0;
uint32_t *pushbuf = NULL; uint32_t *pushbuf = NULL;
int ret = 0, do_reloc = 0, i; int ret = 0, do_reloc = 0, i;
...@@ -597,7 +587,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, ...@@ -597,7 +587,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
OUT_RINGp(chan, pushbuf, req->nr_dwords); OUT_RINGp(chan, pushbuf, req->nr_dwords);
ret = nouveau_fence_emit(op.fence); ret = nouveau_fence_new(chan, &fence, true);
if (ret) { if (ret) {
NV_ERROR(dev, "error fencing pushbuf: %d\n", ret); NV_ERROR(dev, "error fencing pushbuf: %d\n", ret);
WIND_RING(chan); WIND_RING(chan);
...@@ -605,7 +595,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, ...@@ -605,7 +595,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
} }
if (nouveau_gem_pushbuf_sync(chan)) { if (nouveau_gem_pushbuf_sync(chan)) {
ret = nouveau_fence_wait(op.fence, NULL, false, false); ret = nouveau_fence_wait(fence, NULL, false, false);
if (ret) { if (ret) {
for (i = 0; i < req->nr_dwords; i++) for (i = 0; i < req->nr_dwords; i++)
NV_ERROR(dev, "0x%08x\n", pushbuf[i]); NV_ERROR(dev, "0x%08x\n", pushbuf[i]);
...@@ -614,7 +604,8 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, ...@@ -614,7 +604,8 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
} }
out: out:
validate_fini(&op, ret == 0); validate_fini(&op, fence);
nouveau_fence_unref((void**)&fence);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
kfree(pushbuf); kfree(pushbuf);
kfree(bo); kfree(bo);
...@@ -634,6 +625,7 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data, ...@@ -634,6 +625,7 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data,
struct drm_gem_object *gem; struct drm_gem_object *gem;
struct nouveau_bo *pbbo; struct nouveau_bo *pbbo;
struct validate_op op; struct validate_op op;
struct nouveau_fence* fence = 0;
int i, ret = 0, do_reloc = 0; int i, ret = 0, do_reloc = 0;
NOUVEAU_CHECK_INITIALISED_WITH_RETURN; NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
...@@ -772,7 +764,7 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data, ...@@ -772,7 +764,7 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data,
OUT_RING(chan, 0); OUT_RING(chan, 0);
} }
ret = nouveau_fence_emit(op.fence); ret = nouveau_fence_new(chan, &fence, true);
if (ret) { if (ret) {
NV_ERROR(dev, "error fencing pushbuf: %d\n", ret); NV_ERROR(dev, "error fencing pushbuf: %d\n", ret);
WIND_RING(chan); WIND_RING(chan);
...@@ -780,7 +772,8 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data, ...@@ -780,7 +772,8 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data,
} }
out: out:
validate_fini(&op, ret == 0); validate_fini(&op, fence);
nouveau_fence_unref((void**)&fence);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
kfree(bo); kfree(bo);
......
...@@ -635,6 +635,7 @@ nv50_pgraph_irq_handler(struct drm_device *dev) ...@@ -635,6 +635,7 @@ nv50_pgraph_irq_handler(struct drm_device *dev)
if ((nv_rd32(dev, 0x400500) & isb) != isb) if ((nv_rd32(dev, 0x400500) & isb) != isb)
nv_wr32(dev, 0x400500, nv_rd32(dev, 0x400500) | isb); nv_wr32(dev, 0x400500, nv_rd32(dev, 0x400500) | isb);
nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31));
} }
nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING); nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING);
......
...@@ -191,6 +191,92 @@ void nouveau_mem_release(struct drm_file *file_priv, struct mem_block *heap) ...@@ -191,6 +191,92 @@ void nouveau_mem_release(struct drm_file *file_priv, struct mem_block *heap)
} }
} }
/*
* NV10-NV40 tiling helpers
*/
static void
nv10_mem_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
uint32_t size, uint32_t pitch)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
tile->addr = addr;
tile->size = size;
tile->used = !!pitch;
nouveau_fence_unref((void **)&tile->fence);
if (!pfifo->cache_flush(dev))
return;
pfifo->reassign(dev, false);
pfifo->cache_flush(dev);
pfifo->cache_pull(dev, false);
nouveau_wait_for_idle(dev);
pgraph->set_region_tiling(dev, i, addr, size, pitch);
pfb->set_region_tiling(dev, i, addr, size, pitch);
pfifo->cache_pull(dev, true);
pfifo->reassign(dev, true);
}
struct nouveau_tile_reg *
nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size,
uint32_t pitch)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
struct nouveau_tile_reg *tile = dev_priv->tile.reg, *found = NULL;
int i;
spin_lock(&dev_priv->tile.lock);
for (i = 0; i < pfb->num_tiles; i++) {
if (tile[i].used)
/* Tile region in use. */
continue;
if (tile[i].fence &&
!nouveau_fence_signalled(tile[i].fence, NULL))
/* Pending tile region. */
continue;
if (max(tile[i].addr, addr) <
min(tile[i].addr + tile[i].size, addr + size))
/* Kill an intersecting tile region. */
nv10_mem_set_region_tiling(dev, i, 0, 0, 0);
if (pitch && !found) {
/* Free tile region. */
nv10_mem_set_region_tiling(dev, i, addr, size, pitch);
found = &tile[i];
}
}
spin_unlock(&dev_priv->tile.lock);
return found;
}
void
nv10_mem_expire_tiling(struct drm_device *dev, struct nouveau_tile_reg *tile,
struct nouveau_fence *fence)
{
if (fence) {
/* Mark it as pending. */
tile->fence = fence;
nouveau_fence_ref(fence);
}
tile->used = false;
}
/* /*
* NV50 VM helpers * NV50 VM helpers
*/ */
...@@ -513,6 +599,7 @@ nouveau_mem_init(struct drm_device *dev) ...@@ -513,6 +599,7 @@ nouveau_mem_init(struct drm_device *dev)
INIT_LIST_HEAD(&dev_priv->ttm.bo_list); INIT_LIST_HEAD(&dev_priv->ttm.bo_list);
spin_lock_init(&dev_priv->ttm.bo_list_lock); spin_lock_init(&dev_priv->ttm.bo_list_lock);
spin_lock_init(&dev_priv->tile.lock);
dev_priv->fb_available_size = nouveau_mem_fb_amount(dev); dev_priv->fb_available_size = nouveau_mem_fb_amount(dev);
......
...@@ -881,7 +881,7 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class, ...@@ -881,7 +881,7 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class,
return 0; return 0;
} }
static int int
nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class, nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class,
struct nouveau_gpuobj **gpuobj_ret) struct nouveau_gpuobj **gpuobj_ret)
{ {
......
...@@ -349,19 +349,19 @@ ...@@ -349,19 +349,19 @@
#define NV04_PGRAPH_BLEND 0x00400824 #define NV04_PGRAPH_BLEND 0x00400824
#define NV04_PGRAPH_STORED_FMT 0x00400830 #define NV04_PGRAPH_STORED_FMT 0x00400830
#define NV04_PGRAPH_PATT_COLORRAM 0x00400900 #define NV04_PGRAPH_PATT_COLORRAM 0x00400900
#define NV40_PGRAPH_TILE0(i) (0x00400900 + (i*16)) #define NV20_PGRAPH_TILE(i) (0x00400900 + (i*16))
#define NV40_PGRAPH_TLIMIT0(i) (0x00400904 + (i*16)) #define NV20_PGRAPH_TLIMIT(i) (0x00400904 + (i*16))
#define NV40_PGRAPH_TSIZE0(i) (0x00400908 + (i*16)) #define NV20_PGRAPH_TSIZE(i) (0x00400908 + (i*16))
#define NV40_PGRAPH_TSTATUS0(i) (0x0040090C + (i*16)) #define NV20_PGRAPH_TSTATUS(i) (0x0040090C + (i*16))
#define NV10_PGRAPH_TILE(i) (0x00400B00 + (i*16)) #define NV10_PGRAPH_TILE(i) (0x00400B00 + (i*16))
#define NV10_PGRAPH_TLIMIT(i) (0x00400B04 + (i*16)) #define NV10_PGRAPH_TLIMIT(i) (0x00400B04 + (i*16))
#define NV10_PGRAPH_TSIZE(i) (0x00400B08 + (i*16)) #define NV10_PGRAPH_TSIZE(i) (0x00400B08 + (i*16))
#define NV10_PGRAPH_TSTATUS(i) (0x00400B0C + (i*16)) #define NV10_PGRAPH_TSTATUS(i) (0x00400B0C + (i*16))
#define NV04_PGRAPH_U_RAM 0x00400D00 #define NV04_PGRAPH_U_RAM 0x00400D00
#define NV47_PGRAPH_TILE0(i) (0x00400D00 + (i*16)) #define NV47_PGRAPH_TILE(i) (0x00400D00 + (i*16))
#define NV47_PGRAPH_TLIMIT0(i) (0x00400D04 + (i*16)) #define NV47_PGRAPH_TLIMIT(i) (0x00400D04 + (i*16))
#define NV47_PGRAPH_TSIZE0(i) (0x00400D08 + (i*16)) #define NV47_PGRAPH_TSIZE(i) (0x00400D08 + (i*16))
#define NV47_PGRAPH_TSTATUS0(i) (0x00400D0C + (i*16)) #define NV47_PGRAPH_TSTATUS(i) (0x00400D0C + (i*16))
#define NV04_PGRAPH_V_RAM 0x00400D40 #define NV04_PGRAPH_V_RAM 0x00400D40
#define NV04_PGRAPH_W_RAM 0x00400D80 #define NV04_PGRAPH_W_RAM 0x00400D80
#define NV10_PGRAPH_COMBINER0_IN_ALPHA 0x00400E40 #define NV10_PGRAPH_COMBINER0_IN_ALPHA 0x00400E40
......
...@@ -76,6 +76,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) ...@@ -76,6 +76,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->fifo.disable = nv04_fifo_disable; engine->fifo.disable = nv04_fifo_disable;
engine->fifo.enable = nv04_fifo_enable; engine->fifo.enable = nv04_fifo_enable;
engine->fifo.reassign = nv04_fifo_reassign; engine->fifo.reassign = nv04_fifo_reassign;
engine->fifo.cache_flush = nv04_fifo_cache_flush;
engine->fifo.cache_pull = nv04_fifo_cache_pull;
engine->fifo.channel_id = nv04_fifo_channel_id; engine->fifo.channel_id = nv04_fifo_channel_id;
engine->fifo.create_context = nv04_fifo_create_context; engine->fifo.create_context = nv04_fifo_create_context;
engine->fifo.destroy_context = nv04_fifo_destroy_context; engine->fifo.destroy_context = nv04_fifo_destroy_context;
...@@ -100,6 +102,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) ...@@ -100,6 +102,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->timer.takedown = nv04_timer_takedown; engine->timer.takedown = nv04_timer_takedown;
engine->fb.init = nv10_fb_init; engine->fb.init = nv10_fb_init;
engine->fb.takedown = nv10_fb_takedown; engine->fb.takedown = nv10_fb_takedown;
engine->fb.set_region_tiling = nv10_fb_set_region_tiling;
engine->graph.grclass = nv10_graph_grclass; engine->graph.grclass = nv10_graph_grclass;
engine->graph.init = nv10_graph_init; engine->graph.init = nv10_graph_init;
engine->graph.takedown = nv10_graph_takedown; engine->graph.takedown = nv10_graph_takedown;
...@@ -109,12 +112,15 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) ...@@ -109,12 +112,15 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->graph.fifo_access = nv04_graph_fifo_access; engine->graph.fifo_access = nv04_graph_fifo_access;
engine->graph.load_context = nv10_graph_load_context; engine->graph.load_context = nv10_graph_load_context;
engine->graph.unload_context = nv10_graph_unload_context; engine->graph.unload_context = nv10_graph_unload_context;
engine->graph.set_region_tiling = nv10_graph_set_region_tiling;
engine->fifo.channels = 32; engine->fifo.channels = 32;
engine->fifo.init = nv10_fifo_init; engine->fifo.init = nv10_fifo_init;
engine->fifo.takedown = nouveau_stub_takedown; engine->fifo.takedown = nouveau_stub_takedown;
engine->fifo.disable = nv04_fifo_disable; engine->fifo.disable = nv04_fifo_disable;
engine->fifo.enable = nv04_fifo_enable; engine->fifo.enable = nv04_fifo_enable;
engine->fifo.reassign = nv04_fifo_reassign; engine->fifo.reassign = nv04_fifo_reassign;
engine->fifo.cache_flush = nv04_fifo_cache_flush;
engine->fifo.cache_pull = nv04_fifo_cache_pull;
engine->fifo.channel_id = nv10_fifo_channel_id; engine->fifo.channel_id = nv10_fifo_channel_id;
engine->fifo.create_context = nv10_fifo_create_context; engine->fifo.create_context = nv10_fifo_create_context;
engine->fifo.destroy_context = nv10_fifo_destroy_context; engine->fifo.destroy_context = nv10_fifo_destroy_context;
...@@ -139,6 +145,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) ...@@ -139,6 +145,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->timer.takedown = nv04_timer_takedown; engine->timer.takedown = nv04_timer_takedown;
engine->fb.init = nv10_fb_init; engine->fb.init = nv10_fb_init;
engine->fb.takedown = nv10_fb_takedown; engine->fb.takedown = nv10_fb_takedown;
engine->fb.set_region_tiling = nv10_fb_set_region_tiling;
engine->graph.grclass = nv20_graph_grclass; engine->graph.grclass = nv20_graph_grclass;
engine->graph.init = nv20_graph_init; engine->graph.init = nv20_graph_init;
engine->graph.takedown = nv20_graph_takedown; engine->graph.takedown = nv20_graph_takedown;
...@@ -148,12 +155,15 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) ...@@ -148,12 +155,15 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->graph.fifo_access = nv04_graph_fifo_access; engine->graph.fifo_access = nv04_graph_fifo_access;
engine->graph.load_context = nv20_graph_load_context; engine->graph.load_context = nv20_graph_load_context;
engine->graph.unload_context = nv20_graph_unload_context; engine->graph.unload_context = nv20_graph_unload_context;
engine->graph.set_region_tiling = nv20_graph_set_region_tiling;
engine->fifo.channels = 32; engine->fifo.channels = 32;
engine->fifo.init = nv10_fifo_init; engine->fifo.init = nv10_fifo_init;
engine->fifo.takedown = nouveau_stub_takedown; engine->fifo.takedown = nouveau_stub_takedown;
engine->fifo.disable = nv04_fifo_disable; engine->fifo.disable = nv04_fifo_disable;
engine->fifo.enable = nv04_fifo_enable; engine->fifo.enable = nv04_fifo_enable;
engine->fifo.reassign = nv04_fifo_reassign; engine->fifo.reassign = nv04_fifo_reassign;
engine->fifo.cache_flush = nv04_fifo_cache_flush;
engine->fifo.cache_pull = nv04_fifo_cache_pull;
engine->fifo.channel_id = nv10_fifo_channel_id; engine->fifo.channel_id = nv10_fifo_channel_id;
engine->fifo.create_context = nv10_fifo_create_context; engine->fifo.create_context = nv10_fifo_create_context;
engine->fifo.destroy_context = nv10_fifo_destroy_context; engine->fifo.destroy_context = nv10_fifo_destroy_context;
...@@ -178,6 +188,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) ...@@ -178,6 +188,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->timer.takedown = nv04_timer_takedown; engine->timer.takedown = nv04_timer_takedown;
engine->fb.init = nv10_fb_init; engine->fb.init = nv10_fb_init;
engine->fb.takedown = nv10_fb_takedown; engine->fb.takedown = nv10_fb_takedown;
engine->fb.set_region_tiling = nv10_fb_set_region_tiling;
engine->graph.grclass = nv30_graph_grclass; engine->graph.grclass = nv30_graph_grclass;
engine->graph.init = nv30_graph_init; engine->graph.init = nv30_graph_init;
engine->graph.takedown = nv20_graph_takedown; engine->graph.takedown = nv20_graph_takedown;
...@@ -187,12 +198,15 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) ...@@ -187,12 +198,15 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->graph.destroy_context = nv20_graph_destroy_context; engine->graph.destroy_context = nv20_graph_destroy_context;
engine->graph.load_context = nv20_graph_load_context; engine->graph.load_context = nv20_graph_load_context;
engine->graph.unload_context = nv20_graph_unload_context; engine->graph.unload_context = nv20_graph_unload_context;
engine->graph.set_region_tiling = nv20_graph_set_region_tiling;
engine->fifo.channels = 32; engine->fifo.channels = 32;
engine->fifo.init = nv10_fifo_init; engine->fifo.init = nv10_fifo_init;
engine->fifo.takedown = nouveau_stub_takedown; engine->fifo.takedown = nouveau_stub_takedown;
engine->fifo.disable = nv04_fifo_disable; engine->fifo.disable = nv04_fifo_disable;
engine->fifo.enable = nv04_fifo_enable; engine->fifo.enable = nv04_fifo_enable;
engine->fifo.reassign = nv04_fifo_reassign; engine->fifo.reassign = nv04_fifo_reassign;
engine->fifo.cache_flush = nv04_fifo_cache_flush;
engine->fifo.cache_pull = nv04_fifo_cache_pull;
engine->fifo.channel_id = nv10_fifo_channel_id; engine->fifo.channel_id = nv10_fifo_channel_id;
engine->fifo.create_context = nv10_fifo_create_context; engine->fifo.create_context = nv10_fifo_create_context;
engine->fifo.destroy_context = nv10_fifo_destroy_context; engine->fifo.destroy_context = nv10_fifo_destroy_context;
...@@ -218,6 +232,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) ...@@ -218,6 +232,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->timer.takedown = nv04_timer_takedown; engine->timer.takedown = nv04_timer_takedown;
engine->fb.init = nv40_fb_init; engine->fb.init = nv40_fb_init;
engine->fb.takedown = nv40_fb_takedown; engine->fb.takedown = nv40_fb_takedown;
engine->fb.set_region_tiling = nv40_fb_set_region_tiling;
engine->graph.grclass = nv40_graph_grclass; engine->graph.grclass = nv40_graph_grclass;
engine->graph.init = nv40_graph_init; engine->graph.init = nv40_graph_init;
engine->graph.takedown = nv40_graph_takedown; engine->graph.takedown = nv40_graph_takedown;
...@@ -227,12 +242,15 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) ...@@ -227,12 +242,15 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->graph.destroy_context = nv40_graph_destroy_context; engine->graph.destroy_context = nv40_graph_destroy_context;
engine->graph.load_context = nv40_graph_load_context; engine->graph.load_context = nv40_graph_load_context;
engine->graph.unload_context = nv40_graph_unload_context; engine->graph.unload_context = nv40_graph_unload_context;
engine->graph.set_region_tiling = nv40_graph_set_region_tiling;
engine->fifo.channels = 32; engine->fifo.channels = 32;
engine->fifo.init = nv40_fifo_init; engine->fifo.init = nv40_fifo_init;
engine->fifo.takedown = nouveau_stub_takedown; engine->fifo.takedown = nouveau_stub_takedown;
engine->fifo.disable = nv04_fifo_disable; engine->fifo.disable = nv04_fifo_disable;
engine->fifo.enable = nv04_fifo_enable; engine->fifo.enable = nv04_fifo_enable;
engine->fifo.reassign = nv04_fifo_reassign; engine->fifo.reassign = nv04_fifo_reassign;
engine->fifo.cache_flush = nv04_fifo_cache_flush;
engine->fifo.cache_pull = nv04_fifo_cache_pull;
engine->fifo.channel_id = nv10_fifo_channel_id; engine->fifo.channel_id = nv10_fifo_channel_id;
engine->fifo.create_context = nv40_fifo_create_context; engine->fifo.create_context = nv40_fifo_create_context;
engine->fifo.destroy_context = nv40_fifo_destroy_context; engine->fifo.destroy_context = nv40_fifo_destroy_context;
...@@ -624,6 +642,9 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) ...@@ -624,6 +642,9 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
dev_priv->chipset = (reg0 & 0xff00000) >> 20; dev_priv->chipset = (reg0 & 0xff00000) >> 20;
/* NV04 or NV05 */ /* NV04 or NV05 */
} else if ((reg0 & 0xff00fff0) == 0x20004000) { } else if ((reg0 & 0xff00fff0) == 0x20004000) {
if (reg0 & 0x00f00000)
dev_priv->chipset = 0x05;
else
dev_priv->chipset = 0x04; dev_priv->chipset = 0x04;
} else } else
dev_priv->chipset = 0xff; dev_priv->chipset = 0xff;
...@@ -704,8 +725,8 @@ static void nouveau_close(struct drm_device *dev) ...@@ -704,8 +725,8 @@ static void nouveau_close(struct drm_device *dev)
{ {
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
/* In the case of an error dev_priv may not be be allocated yet */ /* In the case of an error dev_priv may not be allocated yet */
if (dev_priv && dev_priv->card_type) if (dev_priv)
nouveau_card_takedown(dev); nouveau_card_takedown(dev);
} }
......
...@@ -28,45 +28,17 @@ ...@@ -28,45 +28,17 @@
#include "nouveau_drv.h" #include "nouveau_drv.h"
static struct vm_operations_struct nouveau_ttm_vm_ops;
static const struct vm_operations_struct *ttm_vm_ops;
static int
nouveau_ttm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
struct ttm_buffer_object *bo = vma->vm_private_data;
int ret;
if (unlikely(bo == NULL))
return VM_FAULT_NOPAGE;
ret = ttm_vm_ops->fault(vma, vmf);
return ret;
}
int int
nouveau_ttm_mmap(struct file *filp, struct vm_area_struct *vma) nouveau_ttm_mmap(struct file *filp, struct vm_area_struct *vma)
{ {
struct drm_file *file_priv = filp->private_data; struct drm_file *file_priv = filp->private_data;
struct drm_nouveau_private *dev_priv = struct drm_nouveau_private *dev_priv =
file_priv->minor->dev->dev_private; file_priv->minor->dev->dev_private;
int ret;
if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET))
return drm_mmap(filp, vma); return drm_mmap(filp, vma);
ret = ttm_bo_mmap(filp, vma, &dev_priv->ttm.bdev); return ttm_bo_mmap(filp, vma, &dev_priv->ttm.bdev);
if (unlikely(ret != 0))
return ret;
if (unlikely(ttm_vm_ops == NULL)) {
ttm_vm_ops = vma->vm_ops;
nouveau_ttm_vm_ops = *ttm_vm_ops;
nouveau_ttm_vm_ops.fault = &nouveau_ttm_fault;
}
vma->vm_ops = &nouveau_ttm_vm_ops;
return 0;
} }
static int static int
......
...@@ -212,16 +212,15 @@ static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder, ...@@ -212,16 +212,15 @@ static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder,
return connector_status_disconnected; return connector_status_disconnected;
} }
enum drm_connector_status nv17_dac_detect(struct drm_encoder *encoder, uint32_t nv17_dac_sample_load(struct drm_encoder *encoder)
struct drm_connector *connector)
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
uint32_t testval, regoffset = nv04_dac_output_offset(encoder); uint32_t sample, testval, regoffset = nv04_dac_output_offset(encoder);
uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput, uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput,
saved_rtest_ctrl, saved_gpio0, saved_gpio1, temp, routput; saved_rtest_ctrl, saved_gpio0, saved_gpio1, temp, routput;
int head, present = 0; int head;
#define RGB_TEST_DATA(r, g, b) (r << 0 | g << 10 | b << 20) #define RGB_TEST_DATA(r, g, b) (r << 0 | g << 10 | b << 20)
if (dcb->type == OUTPUT_TV) { if (dcb->type == OUTPUT_TV) {
...@@ -287,13 +286,7 @@ enum drm_connector_status nv17_dac_detect(struct drm_encoder *encoder, ...@@ -287,13 +286,7 @@ enum drm_connector_status nv17_dac_detect(struct drm_encoder *encoder,
temp | NV_PRAMDAC_TEST_CONTROL_TP_INS_EN_ASSERTED); temp | NV_PRAMDAC_TEST_CONTROL_TP_INS_EN_ASSERTED);
msleep(5); msleep(5);
temp = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset); sample = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset);
if (dcb->type == OUTPUT_TV)
present = (nv17_tv_detect(encoder, connector, temp)
== connector_status_connected);
else
present = temp & NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI;
temp = NVReadRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL); temp = NVReadRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL);
NVWriteRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL, NVWriteRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL,
...@@ -310,15 +303,25 @@ enum drm_connector_status nv17_dac_detect(struct drm_encoder *encoder, ...@@ -310,15 +303,25 @@ enum drm_connector_status nv17_dac_detect(struct drm_encoder *encoder,
nv17_gpio_set(dev, DCB_GPIO_TVDAC1, saved_gpio1); nv17_gpio_set(dev, DCB_GPIO_TVDAC1, saved_gpio1);
nv17_gpio_set(dev, DCB_GPIO_TVDAC0, saved_gpio0); nv17_gpio_set(dev, DCB_GPIO_TVDAC0, saved_gpio0);
if (present) { return sample;
NV_INFO(dev, "Load detected on output %c\n", '@' + ffs(dcb->or)); }
return connector_status_connected;
}
static enum drm_connector_status
nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
{
struct drm_device *dev = encoder->dev;
struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
uint32_t sample = nv17_dac_sample_load(encoder);
if (sample & NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) {
NV_INFO(dev, "Load detected on output %c\n",
'@' + ffs(dcb->or));
return connector_status_connected;
} else {
return connector_status_disconnected; return connector_status_disconnected;
}
} }
static bool nv04_dac_mode_fixup(struct drm_encoder *encoder, static bool nv04_dac_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode) struct drm_display_mode *adjusted_mode)
......
...@@ -39,8 +39,7 @@ nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) ...@@ -39,8 +39,7 @@ nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
return; return;
if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 4)) { if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 4)) {
NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); nouveau_fbcon_gpu_lockup(info);
info->flags |= FBINFO_HWACCEL_DISABLED;
} }
if (info->flags & FBINFO_HWACCEL_DISABLED) { if (info->flags & FBINFO_HWACCEL_DISABLED) {
...@@ -62,14 +61,12 @@ nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) ...@@ -62,14 +61,12 @@ nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
struct drm_device *dev = par->dev; struct drm_device *dev = par->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_channel *chan = dev_priv->channel; struct nouveau_channel *chan = dev_priv->channel;
uint32_t color = ((uint32_t *) info->pseudo_palette)[rect->color];
if (info->state != FBINFO_STATE_RUNNING) if (info->state != FBINFO_STATE_RUNNING)
return; return;
if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 7)) { if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 7)) {
NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); nouveau_fbcon_gpu_lockup(info);
info->flags |= FBINFO_HWACCEL_DISABLED;
} }
if (info->flags & FBINFO_HWACCEL_DISABLED) { if (info->flags & FBINFO_HWACCEL_DISABLED) {
...@@ -80,7 +77,11 @@ nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) ...@@ -80,7 +77,11 @@ nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
BEGIN_RING(chan, NvSubGdiRect, 0x02fc, 1); BEGIN_RING(chan, NvSubGdiRect, 0x02fc, 1);
OUT_RING(chan, (rect->rop != ROP_COPY) ? 1 : 3); OUT_RING(chan, (rect->rop != ROP_COPY) ? 1 : 3);
BEGIN_RING(chan, NvSubGdiRect, 0x03fc, 1); BEGIN_RING(chan, NvSubGdiRect, 0x03fc, 1);
OUT_RING(chan, color); if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
info->fix.visual == FB_VISUAL_DIRECTCOLOR)
OUT_RING(chan, ((uint32_t *)info->pseudo_palette)[rect->color]);
else
OUT_RING(chan, rect->color);
BEGIN_RING(chan, NvSubGdiRect, 0x0400, 2); BEGIN_RING(chan, NvSubGdiRect, 0x0400, 2);
OUT_RING(chan, (rect->dx << 16) | rect->dy); OUT_RING(chan, (rect->dx << 16) | rect->dy);
OUT_RING(chan, (rect->width << 16) | rect->height); OUT_RING(chan, (rect->width << 16) | rect->height);
...@@ -109,8 +110,7 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) ...@@ -109,8 +110,7 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
} }
if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 8)) { if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 8)) {
NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); nouveau_fbcon_gpu_lockup(info);
info->flags |= FBINFO_HWACCEL_DISABLED;
} }
if (info->flags & FBINFO_HWACCEL_DISABLED) { if (info->flags & FBINFO_HWACCEL_DISABLED) {
...@@ -144,8 +144,7 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) ...@@ -144,8 +144,7 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
int iter_len = dsize > 128 ? 128 : dsize; int iter_len = dsize > 128 ? 128 : dsize;
if (RING_SPACE(chan, iter_len + 1)) { if (RING_SPACE(chan, iter_len + 1)) {
NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); nouveau_fbcon_gpu_lockup(info);
info->flags |= FBINFO_HWACCEL_DISABLED;
cfb_imageblit(info, image); cfb_imageblit(info, image);
return; return;
} }
...@@ -184,6 +183,7 @@ nv04_fbcon_accel_init(struct fb_info *info) ...@@ -184,6 +183,7 @@ nv04_fbcon_accel_init(struct fb_info *info)
struct drm_device *dev = par->dev; struct drm_device *dev = par->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_channel *chan = dev_priv->channel; struct nouveau_channel *chan = dev_priv->channel;
const int sub = NvSubCtxSurf2D;
int surface_fmt, pattern_fmt, rect_fmt; int surface_fmt, pattern_fmt, rect_fmt;
int ret; int ret;
...@@ -242,30 +242,29 @@ nv04_fbcon_accel_init(struct fb_info *info) ...@@ -242,30 +242,29 @@ nv04_fbcon_accel_init(struct fb_info *info)
return ret; return ret;
if (RING_SPACE(chan, 49)) { if (RING_SPACE(chan, 49)) {
NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); nouveau_fbcon_gpu_lockup(info);
info->flags |= FBINFO_HWACCEL_DISABLED;
return 0; return 0;
} }
BEGIN_RING(chan, 1, 0x0000, 1); BEGIN_RING(chan, sub, 0x0000, 1);
OUT_RING(chan, NvCtxSurf2D); OUT_RING(chan, NvCtxSurf2D);
BEGIN_RING(chan, 1, 0x0184, 2); BEGIN_RING(chan, sub, 0x0184, 2);
OUT_RING(chan, NvDmaFB); OUT_RING(chan, NvDmaFB);
OUT_RING(chan, NvDmaFB); OUT_RING(chan, NvDmaFB);
BEGIN_RING(chan, 1, 0x0300, 4); BEGIN_RING(chan, sub, 0x0300, 4);
OUT_RING(chan, surface_fmt); OUT_RING(chan, surface_fmt);
OUT_RING(chan, info->fix.line_length | (info->fix.line_length << 16)); OUT_RING(chan, info->fix.line_length | (info->fix.line_length << 16));
OUT_RING(chan, info->fix.smem_start - dev->mode_config.fb_base); OUT_RING(chan, info->fix.smem_start - dev->mode_config.fb_base);
OUT_RING(chan, info->fix.smem_start - dev->mode_config.fb_base); OUT_RING(chan, info->fix.smem_start - dev->mode_config.fb_base);
BEGIN_RING(chan, 1, 0x0000, 1); BEGIN_RING(chan, sub, 0x0000, 1);
OUT_RING(chan, NvRop); OUT_RING(chan, NvRop);
BEGIN_RING(chan, 1, 0x0300, 1); BEGIN_RING(chan, sub, 0x0300, 1);
OUT_RING(chan, 0x55); OUT_RING(chan, 0x55);
BEGIN_RING(chan, 1, 0x0000, 1); BEGIN_RING(chan, sub, 0x0000, 1);
OUT_RING(chan, NvImagePatt); OUT_RING(chan, NvImagePatt);
BEGIN_RING(chan, 1, 0x0300, 8); BEGIN_RING(chan, sub, 0x0300, 8);
OUT_RING(chan, pattern_fmt); OUT_RING(chan, pattern_fmt);
#ifdef __BIG_ENDIAN #ifdef __BIG_ENDIAN
OUT_RING(chan, 2); OUT_RING(chan, 2);
...@@ -279,9 +278,9 @@ nv04_fbcon_accel_init(struct fb_info *info) ...@@ -279,9 +278,9 @@ nv04_fbcon_accel_init(struct fb_info *info)
OUT_RING(chan, ~0); OUT_RING(chan, ~0);
OUT_RING(chan, ~0); OUT_RING(chan, ~0);
BEGIN_RING(chan, 1, 0x0000, 1); BEGIN_RING(chan, sub, 0x0000, 1);
OUT_RING(chan, NvClipRect); OUT_RING(chan, NvClipRect);
BEGIN_RING(chan, 1, 0x0300, 2); BEGIN_RING(chan, sub, 0x0300, 2);
OUT_RING(chan, 0); OUT_RING(chan, 0);
OUT_RING(chan, (info->var.yres_virtual << 16) | info->var.xres_virtual); OUT_RING(chan, (info->var.yres_virtual << 16) | info->var.xres_virtual);
......
...@@ -71,6 +71,40 @@ nv04_fifo_reassign(struct drm_device *dev, bool enable) ...@@ -71,6 +71,40 @@ nv04_fifo_reassign(struct drm_device *dev, bool enable)
return (reassign == 1); return (reassign == 1);
} }
bool
nv04_fifo_cache_flush(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
uint64_t start = ptimer->read(dev);
do {
if (nv_rd32(dev, NV03_PFIFO_CACHE1_GET) ==
nv_rd32(dev, NV03_PFIFO_CACHE1_PUT))
return true;
} while (ptimer->read(dev) - start < 100000000);
NV_ERROR(dev, "Timeout flushing the PFIFO cache.\n");
return false;
}
bool
nv04_fifo_cache_pull(struct drm_device *dev, bool enable)
{
uint32_t pull = nv_rd32(dev, NV04_PFIFO_CACHE1_PULL0);
if (enable) {
nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, pull | 1);
} else {
nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, pull & ~1);
nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0);
}
return !!(pull & 1);
}
int int
nv04_fifo_channel_id(struct drm_device *dev) nv04_fifo_channel_id(struct drm_device *dev)
{ {
......
...@@ -28,6 +28,10 @@ ...@@ -28,6 +28,10 @@
#include "nouveau_drv.h" #include "nouveau_drv.h"
static uint32_t nv04_graph_ctx_regs[] = { static uint32_t nv04_graph_ctx_regs[] = {
0x0040053c,
0x00400544,
0x00400540,
0x00400548,
NV04_PGRAPH_CTX_SWITCH1, NV04_PGRAPH_CTX_SWITCH1,
NV04_PGRAPH_CTX_SWITCH2, NV04_PGRAPH_CTX_SWITCH2,
NV04_PGRAPH_CTX_SWITCH3, NV04_PGRAPH_CTX_SWITCH3,
...@@ -102,69 +106,69 @@ static uint32_t nv04_graph_ctx_regs[] = { ...@@ -102,69 +106,69 @@ static uint32_t nv04_graph_ctx_regs[] = {
NV04_PGRAPH_PATT_COLOR0, NV04_PGRAPH_PATT_COLOR0,
NV04_PGRAPH_PATT_COLOR1, NV04_PGRAPH_PATT_COLOR1,
NV04_PGRAPH_PATT_COLORRAM+0x00, NV04_PGRAPH_PATT_COLORRAM+0x00,
NV04_PGRAPH_PATT_COLORRAM+0x01,
NV04_PGRAPH_PATT_COLORRAM+0x02,
NV04_PGRAPH_PATT_COLORRAM+0x03,
NV04_PGRAPH_PATT_COLORRAM+0x04, NV04_PGRAPH_PATT_COLORRAM+0x04,
NV04_PGRAPH_PATT_COLORRAM+0x05,
NV04_PGRAPH_PATT_COLORRAM+0x06,
NV04_PGRAPH_PATT_COLORRAM+0x07,
NV04_PGRAPH_PATT_COLORRAM+0x08, NV04_PGRAPH_PATT_COLORRAM+0x08,
NV04_PGRAPH_PATT_COLORRAM+0x09, NV04_PGRAPH_PATT_COLORRAM+0x0c,
NV04_PGRAPH_PATT_COLORRAM+0x0A,
NV04_PGRAPH_PATT_COLORRAM+0x0B,
NV04_PGRAPH_PATT_COLORRAM+0x0C,
NV04_PGRAPH_PATT_COLORRAM+0x0D,
NV04_PGRAPH_PATT_COLORRAM+0x0E,
NV04_PGRAPH_PATT_COLORRAM+0x0F,
NV04_PGRAPH_PATT_COLORRAM+0x10, NV04_PGRAPH_PATT_COLORRAM+0x10,
NV04_PGRAPH_PATT_COLORRAM+0x11,
NV04_PGRAPH_PATT_COLORRAM+0x12,
NV04_PGRAPH_PATT_COLORRAM+0x13,
NV04_PGRAPH_PATT_COLORRAM+0x14, NV04_PGRAPH_PATT_COLORRAM+0x14,
NV04_PGRAPH_PATT_COLORRAM+0x15,
NV04_PGRAPH_PATT_COLORRAM+0x16,
NV04_PGRAPH_PATT_COLORRAM+0x17,
NV04_PGRAPH_PATT_COLORRAM+0x18, NV04_PGRAPH_PATT_COLORRAM+0x18,
NV04_PGRAPH_PATT_COLORRAM+0x19, NV04_PGRAPH_PATT_COLORRAM+0x1c,
NV04_PGRAPH_PATT_COLORRAM+0x1A,
NV04_PGRAPH_PATT_COLORRAM+0x1B,
NV04_PGRAPH_PATT_COLORRAM+0x1C,
NV04_PGRAPH_PATT_COLORRAM+0x1D,
NV04_PGRAPH_PATT_COLORRAM+0x1E,
NV04_PGRAPH_PATT_COLORRAM+0x1F,
NV04_PGRAPH_PATT_COLORRAM+0x20, NV04_PGRAPH_PATT_COLORRAM+0x20,
NV04_PGRAPH_PATT_COLORRAM+0x21,
NV04_PGRAPH_PATT_COLORRAM+0x22,
NV04_PGRAPH_PATT_COLORRAM+0x23,
NV04_PGRAPH_PATT_COLORRAM+0x24, NV04_PGRAPH_PATT_COLORRAM+0x24,
NV04_PGRAPH_PATT_COLORRAM+0x25,
NV04_PGRAPH_PATT_COLORRAM+0x26,
NV04_PGRAPH_PATT_COLORRAM+0x27,
NV04_PGRAPH_PATT_COLORRAM+0x28, NV04_PGRAPH_PATT_COLORRAM+0x28,
NV04_PGRAPH_PATT_COLORRAM+0x29, NV04_PGRAPH_PATT_COLORRAM+0x2c,
NV04_PGRAPH_PATT_COLORRAM+0x2A,
NV04_PGRAPH_PATT_COLORRAM+0x2B,
NV04_PGRAPH_PATT_COLORRAM+0x2C,
NV04_PGRAPH_PATT_COLORRAM+0x2D,
NV04_PGRAPH_PATT_COLORRAM+0x2E,
NV04_PGRAPH_PATT_COLORRAM+0x2F,
NV04_PGRAPH_PATT_COLORRAM+0x30, NV04_PGRAPH_PATT_COLORRAM+0x30,
NV04_PGRAPH_PATT_COLORRAM+0x31,
NV04_PGRAPH_PATT_COLORRAM+0x32,
NV04_PGRAPH_PATT_COLORRAM+0x33,
NV04_PGRAPH_PATT_COLORRAM+0x34, NV04_PGRAPH_PATT_COLORRAM+0x34,
NV04_PGRAPH_PATT_COLORRAM+0x35,
NV04_PGRAPH_PATT_COLORRAM+0x36,
NV04_PGRAPH_PATT_COLORRAM+0x37,
NV04_PGRAPH_PATT_COLORRAM+0x38, NV04_PGRAPH_PATT_COLORRAM+0x38,
NV04_PGRAPH_PATT_COLORRAM+0x39, NV04_PGRAPH_PATT_COLORRAM+0x3c,
NV04_PGRAPH_PATT_COLORRAM+0x3A, NV04_PGRAPH_PATT_COLORRAM+0x40,
NV04_PGRAPH_PATT_COLORRAM+0x3B, NV04_PGRAPH_PATT_COLORRAM+0x44,
NV04_PGRAPH_PATT_COLORRAM+0x3C, NV04_PGRAPH_PATT_COLORRAM+0x48,
NV04_PGRAPH_PATT_COLORRAM+0x3D, NV04_PGRAPH_PATT_COLORRAM+0x4c,
NV04_PGRAPH_PATT_COLORRAM+0x3E, NV04_PGRAPH_PATT_COLORRAM+0x50,
NV04_PGRAPH_PATT_COLORRAM+0x3F, NV04_PGRAPH_PATT_COLORRAM+0x54,
NV04_PGRAPH_PATT_COLORRAM+0x58,
NV04_PGRAPH_PATT_COLORRAM+0x5c,
NV04_PGRAPH_PATT_COLORRAM+0x60,
NV04_PGRAPH_PATT_COLORRAM+0x64,
NV04_PGRAPH_PATT_COLORRAM+0x68,
NV04_PGRAPH_PATT_COLORRAM+0x6c,
NV04_PGRAPH_PATT_COLORRAM+0x70,
NV04_PGRAPH_PATT_COLORRAM+0x74,
NV04_PGRAPH_PATT_COLORRAM+0x78,
NV04_PGRAPH_PATT_COLORRAM+0x7c,
NV04_PGRAPH_PATT_COLORRAM+0x80,
NV04_PGRAPH_PATT_COLORRAM+0x84,
NV04_PGRAPH_PATT_COLORRAM+0x88,
NV04_PGRAPH_PATT_COLORRAM+0x8c,
NV04_PGRAPH_PATT_COLORRAM+0x90,
NV04_PGRAPH_PATT_COLORRAM+0x94,
NV04_PGRAPH_PATT_COLORRAM+0x98,
NV04_PGRAPH_PATT_COLORRAM+0x9c,
NV04_PGRAPH_PATT_COLORRAM+0xa0,
NV04_PGRAPH_PATT_COLORRAM+0xa4,
NV04_PGRAPH_PATT_COLORRAM+0xa8,
NV04_PGRAPH_PATT_COLORRAM+0xac,
NV04_PGRAPH_PATT_COLORRAM+0xb0,
NV04_PGRAPH_PATT_COLORRAM+0xb4,
NV04_PGRAPH_PATT_COLORRAM+0xb8,
NV04_PGRAPH_PATT_COLORRAM+0xbc,
NV04_PGRAPH_PATT_COLORRAM+0xc0,
NV04_PGRAPH_PATT_COLORRAM+0xc4,
NV04_PGRAPH_PATT_COLORRAM+0xc8,
NV04_PGRAPH_PATT_COLORRAM+0xcc,
NV04_PGRAPH_PATT_COLORRAM+0xd0,
NV04_PGRAPH_PATT_COLORRAM+0xd4,
NV04_PGRAPH_PATT_COLORRAM+0xd8,
NV04_PGRAPH_PATT_COLORRAM+0xdc,
NV04_PGRAPH_PATT_COLORRAM+0xe0,
NV04_PGRAPH_PATT_COLORRAM+0xe4,
NV04_PGRAPH_PATT_COLORRAM+0xe8,
NV04_PGRAPH_PATT_COLORRAM+0xec,
NV04_PGRAPH_PATT_COLORRAM+0xf0,
NV04_PGRAPH_PATT_COLORRAM+0xf4,
NV04_PGRAPH_PATT_COLORRAM+0xf8,
NV04_PGRAPH_PATT_COLORRAM+0xfc,
NV04_PGRAPH_PATTERN, NV04_PGRAPH_PATTERN,
0x0040080c, 0x0040080c,
NV04_PGRAPH_PATTERN_SHAPE, NV04_PGRAPH_PATTERN_SHAPE,
...@@ -247,14 +251,6 @@ static uint32_t nv04_graph_ctx_regs[] = { ...@@ -247,14 +251,6 @@ static uint32_t nv04_graph_ctx_regs[] = {
0x004004f8, 0x004004f8,
0x0040047c, 0x0040047c,
0x004004fc, 0x004004fc,
0x0040053c,
0x00400544,
0x00400540,
0x00400548,
0x00400560,
0x00400568,
0x00400564,
0x0040056c,
0x00400534, 0x00400534,
0x00400538, 0x00400538,
0x00400514, 0x00400514,
...@@ -341,9 +337,8 @@ static uint32_t nv04_graph_ctx_regs[] = { ...@@ -341,9 +337,8 @@ static uint32_t nv04_graph_ctx_regs[] = {
0x00400500, 0x00400500,
0x00400504, 0x00400504,
NV04_PGRAPH_VALID1, NV04_PGRAPH_VALID1,
NV04_PGRAPH_VALID2 NV04_PGRAPH_VALID2,
NV04_PGRAPH_DEBUG_3
}; };
struct graph_state { struct graph_state {
...@@ -388,6 +383,18 @@ nv04_graph_context_switch(struct drm_device *dev) ...@@ -388,6 +383,18 @@ nv04_graph_context_switch(struct drm_device *dev)
pgraph->fifo_access(dev, true); pgraph->fifo_access(dev, true);
} }
static uint32_t *ctx_reg(struct graph_state *ctx, uint32_t reg)
{
int i;
for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++) {
if (nv04_graph_ctx_regs[i] == reg)
return &ctx->nv04[i];
}
return NULL;
}
int nv04_graph_create_context(struct nouveau_channel *chan) int nv04_graph_create_context(struct nouveau_channel *chan)
{ {
struct graph_state *pgraph_ctx; struct graph_state *pgraph_ctx;
...@@ -398,15 +405,8 @@ int nv04_graph_create_context(struct nouveau_channel *chan) ...@@ -398,15 +405,8 @@ int nv04_graph_create_context(struct nouveau_channel *chan)
if (pgraph_ctx == NULL) if (pgraph_ctx == NULL)
return -ENOMEM; return -ENOMEM;
/* dev_priv->fifos[channel].pgraph_ctx_user = channel << 24; */ *ctx_reg(pgraph_ctx, NV04_PGRAPH_DEBUG_3) = 0xfad4ff31;
pgraph_ctx->nv04[0] = 0x0001ffff;
/* is it really needed ??? */
#if 0
dev_priv->fifos[channel].pgraph_ctx[1] =
nv_rd32(dev, NV_PGRAPH_DEBUG_4);
dev_priv->fifos[channel].pgraph_ctx[2] =
nv_rd32(dev, 0x004006b0);
#endif
return 0; return 0;
} }
...@@ -429,9 +429,13 @@ int nv04_graph_load_context(struct nouveau_channel *chan) ...@@ -429,9 +429,13 @@ int nv04_graph_load_context(struct nouveau_channel *chan)
nv_wr32(dev, nv04_graph_ctx_regs[i], pgraph_ctx->nv04[i]); nv_wr32(dev, nv04_graph_ctx_regs[i], pgraph_ctx->nv04[i]);
nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL, 0x10010100); nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL, 0x10010100);
nv_wr32(dev, NV04_PGRAPH_CTX_USER, chan->id << 24);
tmp = nv_rd32(dev, NV04_PGRAPH_CTX_USER) & 0x00ffffff;
nv_wr32(dev, NV04_PGRAPH_CTX_USER, tmp | chan->id << 24);
tmp = nv_rd32(dev, NV04_PGRAPH_FFINTFC_ST2); tmp = nv_rd32(dev, NV04_PGRAPH_FFINTFC_ST2);
nv_wr32(dev, NV04_PGRAPH_FFINTFC_ST2, tmp & 0x000fffff); nv_wr32(dev, NV04_PGRAPH_FFINTFC_ST2, tmp & 0x000fffff);
return 0; return 0;
} }
...@@ -494,7 +498,7 @@ int nv04_graph_init(struct drm_device *dev) ...@@ -494,7 +498,7 @@ int nv04_graph_init(struct drm_device *dev)
nv_wr32(dev, NV04_PGRAPH_STATE , 0xFFFFFFFF); nv_wr32(dev, NV04_PGRAPH_STATE , 0xFFFFFFFF);
nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL , 0x10000100); nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL , 0x10000100);
tmp = nv_rd32(dev, NV04_PGRAPH_CTX_USER) & 0x00ffffff; tmp = nv_rd32(dev, NV04_PGRAPH_CTX_USER) & 0x00ffffff;
tmp |= dev_priv->engine.fifo.channels << 24; tmp |= (dev_priv->engine.fifo.channels - 1) << 24;
nv_wr32(dev, NV04_PGRAPH_CTX_USER, tmp); nv_wr32(dev, NV04_PGRAPH_CTX_USER, tmp);
/* These don't belong here, they're part of a per-channel context */ /* These don't belong here, they're part of a per-channel context */
...@@ -533,7 +537,7 @@ nv04_graph_mthd_set_operation(struct nouveau_channel *chan, int grclass, ...@@ -533,7 +537,7 @@ nv04_graph_mthd_set_operation(struct nouveau_channel *chan, int grclass,
int mthd, uint32_t data) int mthd, uint32_t data)
{ {
struct drm_device *dev = chan->dev; struct drm_device *dev = chan->dev;
uint32_t instance = nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff; uint32_t instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4;
int subc = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7; int subc = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7;
uint32_t tmp; uint32_t tmp;
...@@ -547,7 +551,7 @@ nv04_graph_mthd_set_operation(struct nouveau_channel *chan, int grclass, ...@@ -547,7 +551,7 @@ nv04_graph_mthd_set_operation(struct nouveau_channel *chan, int grclass,
return 0; return 0;
} }
static struct nouveau_pgraph_object_method nv04_graph_mthds_m2mf[] = { static struct nouveau_pgraph_object_method nv04_graph_mthds_sw[] = {
{ 0x0150, nv04_graph_mthd_set_ref }, { 0x0150, nv04_graph_mthd_set_ref },
{} {}
}; };
...@@ -558,7 +562,7 @@ static struct nouveau_pgraph_object_method nv04_graph_mthds_set_operation[] = { ...@@ -558,7 +562,7 @@ static struct nouveau_pgraph_object_method nv04_graph_mthds_set_operation[] = {
}; };
struct nouveau_pgraph_object_class nv04_graph_grclass[] = { struct nouveau_pgraph_object_class nv04_graph_grclass[] = {
{ 0x0039, false, nv04_graph_mthds_m2mf }, { 0x0039, false, NULL },
{ 0x004a, false, nv04_graph_mthds_set_operation }, /* gdirect */ { 0x004a, false, nv04_graph_mthds_set_operation }, /* gdirect */
{ 0x005f, false, nv04_graph_mthds_set_operation }, /* imageblit */ { 0x005f, false, nv04_graph_mthds_set_operation }, /* imageblit */
{ 0x0061, false, nv04_graph_mthds_set_operation }, /* ifc */ { 0x0061, false, nv04_graph_mthds_set_operation }, /* ifc */
...@@ -574,6 +578,7 @@ struct nouveau_pgraph_object_class nv04_graph_grclass[] = { ...@@ -574,6 +578,7 @@ struct nouveau_pgraph_object_class nv04_graph_grclass[] = {
{ 0x0053, false, NULL }, /* surf3d */ { 0x0053, false, NULL }, /* surf3d */
{ 0x0054, false, NULL }, /* tex_tri */ { 0x0054, false, NULL }, /* tex_tri */
{ 0x0055, false, NULL }, /* multitex_tri */ { 0x0055, false, NULL }, /* multitex_tri */
{ 0x506e, true, nv04_graph_mthds_sw },
{} {}
}; };
...@@ -3,17 +3,37 @@ ...@@ -3,17 +3,37 @@
#include "nouveau_drv.h" #include "nouveau_drv.h"
#include "nouveau_drm.h" #include "nouveau_drm.h"
void
nv10_fb_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
uint32_t size, uint32_t pitch)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
uint32_t limit = max(1u, addr + size) - 1;
if (pitch) {
if (dev_priv->card_type >= NV_20)
addr |= 1;
else
addr |= 1 << 31;
}
nv_wr32(dev, NV10_PFB_TLIMIT(i), limit);
nv_wr32(dev, NV10_PFB_TSIZE(i), pitch);
nv_wr32(dev, NV10_PFB_TILE(i), addr);
}
int int
nv10_fb_init(struct drm_device *dev) nv10_fb_init(struct drm_device *dev)
{ {
uint32_t fb_bar_size; struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
int i; int i;
fb_bar_size = drm_get_resource_len(dev, 0) - 1; pfb->num_tiles = NV10_PFB_TILE__SIZE;
for (i = 0; i < NV10_PFB_TILE__SIZE; i++) {
nv_wr32(dev, NV10_PFB_TILE(i), 0); /* Turn all the tiling regions off. */
nv_wr32(dev, NV10_PFB_TLIMIT(i), fb_bar_size); for (i = 0; i < pfb->num_tiles; i++)
} pfb->set_region_tiling(dev, i, 0, 0, 0);
return 0; return 0;
} }
......
...@@ -807,6 +807,20 @@ void nv10_graph_destroy_context(struct nouveau_channel *chan) ...@@ -807,6 +807,20 @@ void nv10_graph_destroy_context(struct nouveau_channel *chan)
chan->pgraph_ctx = NULL; chan->pgraph_ctx = NULL;
} }
void
nv10_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
uint32_t size, uint32_t pitch)
{
uint32_t limit = max(1u, addr + size) - 1;
if (pitch)
addr |= 1 << 31;
nv_wr32(dev, NV10_PGRAPH_TLIMIT(i), limit);
nv_wr32(dev, NV10_PGRAPH_TSIZE(i), pitch);
nv_wr32(dev, NV10_PGRAPH_TILE(i), addr);
}
int nv10_graph_init(struct drm_device *dev) int nv10_graph_init(struct drm_device *dev)
{ {
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
...@@ -838,17 +852,9 @@ int nv10_graph_init(struct drm_device *dev) ...@@ -838,17 +852,9 @@ int nv10_graph_init(struct drm_device *dev)
} else } else
nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00000000); nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00000000);
/* copy tile info from PFB */ /* Turn all the tiling regions off. */
for (i = 0; i < NV10_PFB_TILE__SIZE; i++) { for (i = 0; i < NV10_PFB_TILE__SIZE; i++)
nv_wr32(dev, NV10_PGRAPH_TILE(i), nv10_graph_set_region_tiling(dev, i, 0, 0, 0);
nv_rd32(dev, NV10_PFB_TILE(i)));
nv_wr32(dev, NV10_PGRAPH_TLIMIT(i),
nv_rd32(dev, NV10_PFB_TLIMIT(i)));
nv_wr32(dev, NV10_PGRAPH_TSIZE(i),
nv_rd32(dev, NV10_PFB_TSIZE(i)));
nv_wr32(dev, NV10_PGRAPH_TSTATUS(i),
nv_rd32(dev, NV10_PFB_TSTATUS(i)));
}
nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH1, 0x00000000); nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH1, 0x00000000);
nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH2, 0x00000000); nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH2, 0x00000000);
......
...@@ -33,13 +33,103 @@ ...@@ -33,13 +33,103 @@
#include "nouveau_hw.h" #include "nouveau_hw.h"
#include "nv17_tv.h" #include "nv17_tv.h"
enum drm_connector_status nv17_tv_detect(struct drm_encoder *encoder, static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder)
struct drm_connector *connector, {
uint32_t pin_mask) struct drm_device *dev = encoder->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
uint32_t testval, regoffset = nv04_dac_output_offset(encoder);
uint32_t gpio0, gpio1, fp_htotal, fp_hsync_start, fp_hsync_end,
fp_control, test_ctrl, dacclk, ctv_14, ctv_1c, ctv_6c;
uint32_t sample = 0;
int head;
#define RGB_TEST_DATA(r, g, b) (r << 0 | g << 10 | b << 20)
testval = RGB_TEST_DATA(0x82, 0xeb, 0x82);
if (dev_priv->vbios->tvdactestval)
testval = dev_priv->vbios->tvdactestval;
dacclk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset);
head = (dacclk & 0x100) >> 8;
/* Save the previous state. */
gpio1 = nv17_gpio_get(dev, DCB_GPIO_TVDAC1);
gpio0 = nv17_gpio_get(dev, DCB_GPIO_TVDAC0);
fp_htotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL);
fp_hsync_start = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START);
fp_hsync_end = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END);
fp_control = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL);
test_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset);
ctv_1c = NVReadRAMDAC(dev, head, 0x680c1c);
ctv_14 = NVReadRAMDAC(dev, head, 0x680c14);
ctv_6c = NVReadRAMDAC(dev, head, 0x680c6c);
/* Prepare the DAC for load detection. */
nv17_gpio_set(dev, DCB_GPIO_TVDAC1, true);
nv17_gpio_set(dev, DCB_GPIO_TVDAC0, true);
NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, 1343);
NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, 1047);
NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, 1183);
NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL,
NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS |
NV_PRAMDAC_FP_TG_CONTROL_WIDTH_12 |
NV_PRAMDAC_FP_TG_CONTROL_READ_PROG |
NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS |
NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS);
NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, 0);
NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset,
(dacclk & ~0xff) | 0x22);
msleep(1);
NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset,
(dacclk & ~0xff) | 0x21);
NVWriteRAMDAC(dev, head, 0x680c1c, 1 << 20);
NVWriteRAMDAC(dev, head, 0x680c14, 4 << 16);
/* Sample pin 0x4 (usually S-video luma). */
NVWriteRAMDAC(dev, head, 0x680c6c, testval >> 10 & 0x3ff);
msleep(20);
sample |= NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset)
& 0x4 << 28;
/* Sample the remaining pins. */
NVWriteRAMDAC(dev, head, 0x680c6c, testval & 0x3ff);
msleep(20);
sample |= NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset)
& 0xa << 28;
/* Restore the previous state. */
NVWriteRAMDAC(dev, head, 0x680c1c, ctv_1c);
NVWriteRAMDAC(dev, head, 0x680c14, ctv_14);
NVWriteRAMDAC(dev, head, 0x680c6c, ctv_6c);
NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, dacclk);
NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, test_ctrl);
NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL, fp_control);
NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, fp_hsync_end);
NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, fp_hsync_start);
NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, fp_htotal);
nv17_gpio_set(dev, DCB_GPIO_TVDAC1, gpio1);
nv17_gpio_set(dev, DCB_GPIO_TVDAC0, gpio0);
return sample;
}
static enum drm_connector_status
nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector)
{ {
struct drm_device *dev = encoder->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct drm_mode_config *conf = &dev->mode_config;
struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
struct dcb_entry *dcb = tv_enc->base.dcb;
tv_enc->pin_mask = pin_mask >> 28 & 0xe; if (dev_priv->chipset == 0x42 ||
dev_priv->chipset == 0x43)
tv_enc->pin_mask = nv42_tv_sample_load(encoder) >> 28 & 0xe;
else
tv_enc->pin_mask = nv17_dac_sample_load(encoder) >> 28 & 0xe;
switch (tv_enc->pin_mask) { switch (tv_enc->pin_mask) {
case 0x2: case 0x2:
...@@ -50,7 +140,7 @@ enum drm_connector_status nv17_tv_detect(struct drm_encoder *encoder, ...@@ -50,7 +140,7 @@ enum drm_connector_status nv17_tv_detect(struct drm_encoder *encoder,
tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_SVIDEO; tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_SVIDEO;
break; break;
case 0xe: case 0xe:
if (nouveau_encoder(encoder)->dcb->tvconf.has_component_output) if (dcb->tvconf.has_component_output)
tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_Component; tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_Component;
else else
tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_SCART; tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_SCART;
...@@ -61,11 +151,16 @@ enum drm_connector_status nv17_tv_detect(struct drm_encoder *encoder, ...@@ -61,11 +151,16 @@ enum drm_connector_status nv17_tv_detect(struct drm_encoder *encoder,
} }
drm_connector_property_set_value(connector, drm_connector_property_set_value(connector,
encoder->dev->mode_config.tv_subconnector_property, conf->tv_subconnector_property,
tv_enc->subconnector); tv_enc->subconnector);
return tv_enc->subconnector ? connector_status_connected : if (tv_enc->subconnector) {
connector_status_disconnected; NV_INFO(dev, "Load detected on output %c\n",
'@' + ffs(dcb->or));
return connector_status_connected;
} else {
return connector_status_disconnected;
}
} }
static const struct { static const struct {
...@@ -633,7 +728,7 @@ static struct drm_encoder_helper_funcs nv17_tv_helper_funcs = { ...@@ -633,7 +728,7 @@ static struct drm_encoder_helper_funcs nv17_tv_helper_funcs = {
.prepare = nv17_tv_prepare, .prepare = nv17_tv_prepare,
.commit = nv17_tv_commit, .commit = nv17_tv_commit,
.mode_set = nv17_tv_mode_set, .mode_set = nv17_tv_mode_set,
.detect = nv17_dac_detect, .detect = nv17_tv_detect,
}; };
static struct drm_encoder_slave_funcs nv17_tv_slave_funcs = { static struct drm_encoder_slave_funcs nv17_tv_slave_funcs = {
......
...@@ -514,6 +514,27 @@ nv20_graph_rdi(struct drm_device *dev) ...@@ -514,6 +514,27 @@ nv20_graph_rdi(struct drm_device *dev)
nouveau_wait_for_idle(dev); nouveau_wait_for_idle(dev);
} }
void
nv20_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
uint32_t size, uint32_t pitch)
{
uint32_t limit = max(1u, addr + size) - 1;
if (pitch)
addr |= 1;
nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit);
nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch);
nv_wr32(dev, NV20_PGRAPH_TILE(i), addr);
nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0030 + 4 * i);
nv_wr32(dev, NV10_PGRAPH_RDI_DATA, limit);
nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0050 + 4 * i);
nv_wr32(dev, NV10_PGRAPH_RDI_DATA, pitch);
nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0010 + 4 * i);
nv_wr32(dev, NV10_PGRAPH_RDI_DATA, addr);
}
int int
nv20_graph_init(struct drm_device *dev) nv20_graph_init(struct drm_device *dev)
{ {
...@@ -572,27 +593,10 @@ nv20_graph_init(struct drm_device *dev) ...@@ -572,27 +593,10 @@ nv20_graph_init(struct drm_device *dev)
nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000030); nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000030);
} }
/* copy tile info from PFB */ /* Turn all the tiling regions off. */
for (i = 0; i < NV10_PFB_TILE__SIZE; i++) { for (i = 0; i < NV10_PFB_TILE__SIZE; i++)
nv_wr32(dev, 0x00400904 + i * 0x10, nv20_graph_set_region_tiling(dev, i, 0, 0, 0);
nv_rd32(dev, NV10_PFB_TLIMIT(i)));
/* which is NV40_PGRAPH_TLIMIT0(i) ?? */
nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0030 + i * 4);
nv_wr32(dev, NV10_PGRAPH_RDI_DATA,
nv_rd32(dev, NV10_PFB_TLIMIT(i)));
nv_wr32(dev, 0x00400908 + i * 0x10,
nv_rd32(dev, NV10_PFB_TSIZE(i)));
/* which is NV40_PGRAPH_TSIZE0(i) ?? */
nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0050 + i * 4);
nv_wr32(dev, NV10_PGRAPH_RDI_DATA,
nv_rd32(dev, NV10_PFB_TSIZE(i)));
nv_wr32(dev, 0x00400900 + i * 0x10,
nv_rd32(dev, NV10_PFB_TILE(i)));
/* which is NV40_PGRAPH_TILE0(i) ?? */
nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0010 + i * 4);
nv_wr32(dev, NV10_PGRAPH_RDI_DATA,
nv_rd32(dev, NV10_PFB_TILE(i)));
}
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
nv_wr32(dev, 0x400980 + i * 4, nv_rd32(dev, 0x100300 + i * 4)); nv_wr32(dev, 0x400980 + i * 4, nv_rd32(dev, 0x100300 + i * 4));
nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0090 + i * 4); nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0090 + i * 4);
...@@ -704,18 +708,9 @@ nv30_graph_init(struct drm_device *dev) ...@@ -704,18 +708,9 @@ nv30_graph_init(struct drm_device *dev)
nv_wr32(dev, 0x4000c0, 0x00000016); nv_wr32(dev, 0x4000c0, 0x00000016);
/* copy tile info from PFB */ /* Turn all the tiling regions off. */
for (i = 0; i < NV10_PFB_TILE__SIZE; i++) { for (i = 0; i < NV10_PFB_TILE__SIZE; i++)
nv_wr32(dev, 0x00400904 + i * 0x10, nv20_graph_set_region_tiling(dev, i, 0, 0, 0);
nv_rd32(dev, NV10_PFB_TLIMIT(i)));
/* which is NV40_PGRAPH_TLIMIT0(i) ?? */
nv_wr32(dev, 0x00400908 + i * 0x10,
nv_rd32(dev, NV10_PFB_TSIZE(i)));
/* which is NV40_PGRAPH_TSIZE0(i) ?? */
nv_wr32(dev, 0x00400900 + i * 0x10,
nv_rd32(dev, NV10_PFB_TILE(i)));
/* which is NV40_PGRAPH_TILE0(i) ?? */
}
nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000100); nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000100);
nv_wr32(dev, NV10_PGRAPH_STATE , 0xFFFFFFFF); nv_wr32(dev, NV10_PGRAPH_STATE , 0xFFFFFFFF);
......
...@@ -3,12 +3,37 @@ ...@@ -3,12 +3,37 @@
#include "nouveau_drv.h" #include "nouveau_drv.h"
#include "nouveau_drm.h" #include "nouveau_drm.h"
void
nv40_fb_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
uint32_t size, uint32_t pitch)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
uint32_t limit = max(1u, addr + size) - 1;
if (pitch)
addr |= 1;
switch (dev_priv->chipset) {
case 0x40:
nv_wr32(dev, NV10_PFB_TLIMIT(i), limit);
nv_wr32(dev, NV10_PFB_TSIZE(i), pitch);
nv_wr32(dev, NV10_PFB_TILE(i), addr);
break;
default:
nv_wr32(dev, NV40_PFB_TLIMIT(i), limit);
nv_wr32(dev, NV40_PFB_TSIZE(i), pitch);
nv_wr32(dev, NV40_PFB_TILE(i), addr);
break;
}
}
int int
nv40_fb_init(struct drm_device *dev) nv40_fb_init(struct drm_device *dev)
{ {
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
uint32_t fb_bar_size, tmp; struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
int num_tiles; uint32_t tmp;
int i; int i;
/* This is strictly a NV4x register (don't know about NV5x). */ /* This is strictly a NV4x register (don't know about NV5x). */
...@@ -23,35 +48,23 @@ nv40_fb_init(struct drm_device *dev) ...@@ -23,35 +48,23 @@ nv40_fb_init(struct drm_device *dev)
case 0x45: case 0x45:
tmp = nv_rd32(dev, NV10_PFB_CLOSE_PAGE2); tmp = nv_rd32(dev, NV10_PFB_CLOSE_PAGE2);
nv_wr32(dev, NV10_PFB_CLOSE_PAGE2, tmp & ~(1 << 15)); nv_wr32(dev, NV10_PFB_CLOSE_PAGE2, tmp & ~(1 << 15));
num_tiles = NV10_PFB_TILE__SIZE; pfb->num_tiles = NV10_PFB_TILE__SIZE;
break; break;
case 0x46: /* G72 */ case 0x46: /* G72 */
case 0x47: /* G70 */ case 0x47: /* G70 */
case 0x49: /* G71 */ case 0x49: /* G71 */
case 0x4b: /* G73 */ case 0x4b: /* G73 */
case 0x4c: /* C51 (G7X version) */ case 0x4c: /* C51 (G7X version) */
num_tiles = NV40_PFB_TILE__SIZE_1; pfb->num_tiles = NV40_PFB_TILE__SIZE_1;
break; break;
default: default:
num_tiles = NV40_PFB_TILE__SIZE_0; pfb->num_tiles = NV40_PFB_TILE__SIZE_0;
break; break;
} }
fb_bar_size = drm_get_resource_len(dev, 0) - 1; /* Turn all the tiling regions off. */
switch (dev_priv->chipset) { for (i = 0; i < pfb->num_tiles; i++)
case 0x40: pfb->set_region_tiling(dev, i, 0, 0, 0);
for (i = 0; i < num_tiles; i++) {
nv_wr32(dev, NV10_PFB_TILE(i), 0);
nv_wr32(dev, NV10_PFB_TLIMIT(i), fb_bar_size);
}
break;
default:
for (i = 0; i < num_tiles; i++) {
nv_wr32(dev, NV40_PFB_TILE(i), 0);
nv_wr32(dev, NV40_PFB_TLIMIT(i), fb_bar_size);
}
break;
}
return 0; return 0;
} }
......
...@@ -181,6 +181,48 @@ nv40_graph_unload_context(struct drm_device *dev) ...@@ -181,6 +181,48 @@ nv40_graph_unload_context(struct drm_device *dev)
return ret; return ret;
} }
void
nv40_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
uint32_t size, uint32_t pitch)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
uint32_t limit = max(1u, addr + size) - 1;
if (pitch)
addr |= 1;
switch (dev_priv->chipset) {
case 0x44:
case 0x4a:
case 0x4e:
nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch);
nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit);
nv_wr32(dev, NV20_PGRAPH_TILE(i), addr);
break;
case 0x46:
case 0x47:
case 0x49:
case 0x4b:
nv_wr32(dev, NV47_PGRAPH_TSIZE(i), pitch);
nv_wr32(dev, NV47_PGRAPH_TLIMIT(i), limit);
nv_wr32(dev, NV47_PGRAPH_TILE(i), addr);
nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), pitch);
nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), limit);
nv_wr32(dev, NV40_PGRAPH_TILE1(i), addr);
break;
default:
nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch);
nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit);
nv_wr32(dev, NV20_PGRAPH_TILE(i), addr);
nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), pitch);
nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), limit);
nv_wr32(dev, NV40_PGRAPH_TILE1(i), addr);
break;
}
}
/* /*
* G70 0x47 * G70 0x47
* G71 0x49 * G71 0x49
...@@ -195,7 +237,8 @@ nv40_graph_init(struct drm_device *dev) ...@@ -195,7 +237,8 @@ nv40_graph_init(struct drm_device *dev)
{ {
struct drm_nouveau_private *dev_priv = struct drm_nouveau_private *dev_priv =
(struct drm_nouveau_private *)dev->dev_private; (struct drm_nouveau_private *)dev->dev_private;
uint32_t vramsz, tmp; struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
uint32_t vramsz;
int i, j; int i, j;
nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) &
...@@ -292,74 +335,9 @@ nv40_graph_init(struct drm_device *dev) ...@@ -292,74 +335,9 @@ nv40_graph_init(struct drm_device *dev)
nv_wr32(dev, 0x400b38, 0x2ffff800); nv_wr32(dev, 0x400b38, 0x2ffff800);
nv_wr32(dev, 0x400b3c, 0x00006000); nv_wr32(dev, 0x400b3c, 0x00006000);
/* copy tile info from PFB */ /* Turn all the tiling regions off. */
switch (dev_priv->chipset) { for (i = 0; i < pfb->num_tiles; i++)
case 0x40: /* vanilla NV40 */ nv40_graph_set_region_tiling(dev, i, 0, 0, 0);
for (i = 0; i < NV10_PFB_TILE__SIZE; i++) {
tmp = nv_rd32(dev, NV10_PFB_TILE(i));
nv_wr32(dev, NV40_PGRAPH_TILE0(i), tmp);
nv_wr32(dev, NV40_PGRAPH_TILE1(i), tmp);
tmp = nv_rd32(dev, NV10_PFB_TLIMIT(i));
nv_wr32(dev, NV40_PGRAPH_TLIMIT0(i), tmp);
nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tmp);
tmp = nv_rd32(dev, NV10_PFB_TSIZE(i));
nv_wr32(dev, NV40_PGRAPH_TSIZE0(i), tmp);
nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tmp);
tmp = nv_rd32(dev, NV10_PFB_TSTATUS(i));
nv_wr32(dev, NV40_PGRAPH_TSTATUS0(i), tmp);
nv_wr32(dev, NV40_PGRAPH_TSTATUS1(i), tmp);
}
break;
case 0x44:
case 0x4a:
case 0x4e: /* NV44-based cores don't have 0x406900? */
for (i = 0; i < NV40_PFB_TILE__SIZE_0; i++) {
tmp = nv_rd32(dev, NV40_PFB_TILE(i));
nv_wr32(dev, NV40_PGRAPH_TILE0(i), tmp);
tmp = nv_rd32(dev, NV40_PFB_TLIMIT(i));
nv_wr32(dev, NV40_PGRAPH_TLIMIT0(i), tmp);
tmp = nv_rd32(dev, NV40_PFB_TSIZE(i));
nv_wr32(dev, NV40_PGRAPH_TSIZE0(i), tmp);
tmp = nv_rd32(dev, NV40_PFB_TSTATUS(i));
nv_wr32(dev, NV40_PGRAPH_TSTATUS0(i), tmp);
}
break;
case 0x46:
case 0x47:
case 0x49:
case 0x4b: /* G7X-based cores */
for (i = 0; i < NV40_PFB_TILE__SIZE_1; i++) {
tmp = nv_rd32(dev, NV40_PFB_TILE(i));
nv_wr32(dev, NV47_PGRAPH_TILE0(i), tmp);
nv_wr32(dev, NV40_PGRAPH_TILE1(i), tmp);
tmp = nv_rd32(dev, NV40_PFB_TLIMIT(i));
nv_wr32(dev, NV47_PGRAPH_TLIMIT0(i), tmp);
nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tmp);
tmp = nv_rd32(dev, NV40_PFB_TSIZE(i));
nv_wr32(dev, NV47_PGRAPH_TSIZE0(i), tmp);
nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tmp);
tmp = nv_rd32(dev, NV40_PFB_TSTATUS(i));
nv_wr32(dev, NV47_PGRAPH_TSTATUS0(i), tmp);
nv_wr32(dev, NV40_PGRAPH_TSTATUS1(i), tmp);
}
break;
default: /* everything else */
for (i = 0; i < NV40_PFB_TILE__SIZE_0; i++) {
tmp = nv_rd32(dev, NV40_PFB_TILE(i));
nv_wr32(dev, NV40_PGRAPH_TILE0(i), tmp);
nv_wr32(dev, NV40_PGRAPH_TILE1(i), tmp);
tmp = nv_rd32(dev, NV40_PFB_TLIMIT(i));
nv_wr32(dev, NV40_PGRAPH_TLIMIT0(i), tmp);
nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tmp);
tmp = nv_rd32(dev, NV40_PFB_TSIZE(i));
nv_wr32(dev, NV40_PGRAPH_TSIZE0(i), tmp);
nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tmp);
tmp = nv_rd32(dev, NV40_PFB_TSTATUS(i));
nv_wr32(dev, NV40_PGRAPH_TSTATUS0(i), tmp);
nv_wr32(dev, NV40_PGRAPH_TSTATUS1(i), tmp);
}
break;
}
/* begin RAM config */ /* begin RAM config */
vramsz = drm_get_resource_len(dev, 0) - 1; vramsz = drm_get_resource_len(dev, 0) - 1;
......
...@@ -690,9 +690,21 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcbent, ...@@ -690,9 +690,21 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcbent,
int pxclk) int pxclk)
{ {
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_connector *nv_connector = NULL;
struct drm_encoder *encoder;
struct nvbios *bios = &dev_priv->VBIOS; struct nvbios *bios = &dev_priv->VBIOS;
uint32_t mc, script = 0, or; uint32_t mc, script = 0, or;
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
if (nv_encoder->dcb != dcbent)
continue;
nv_connector = nouveau_encoder_connector_get(nv_encoder);
break;
}
or = ffs(dcbent->or) - 1; or = ffs(dcbent->or) - 1;
mc = nv50_display_mode_ctrl(dev, dcbent->type != OUTPUT_ANALOG, or); mc = nv50_display_mode_ctrl(dev, dcbent->type != OUTPUT_ANALOG, or);
switch (dcbent->type) { switch (dcbent->type) {
...@@ -711,6 +723,11 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcbent, ...@@ -711,6 +723,11 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcbent,
} else } else
if (bios->fp.strapless_is_24bit & 1) if (bios->fp.strapless_is_24bit & 1)
script |= 0x0200; script |= 0x0200;
if (nv_connector && nv_connector->edid &&
(nv_connector->edid->revision >= 4) &&
(nv_connector->edid->input & 0x70) >= 0x20)
script |= 0x0200;
} }
if (nouveau_uscript_lvds >= 0) { if (nouveau_uscript_lvds >= 0) {
......
...@@ -16,9 +16,7 @@ nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) ...@@ -16,9 +16,7 @@ nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
if (!(info->flags & FBINFO_HWACCEL_DISABLED) && if (!(info->flags & FBINFO_HWACCEL_DISABLED) &&
RING_SPACE(chan, rect->rop == ROP_COPY ? 7 : 11)) { RING_SPACE(chan, rect->rop == ROP_COPY ? 7 : 11)) {
NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); nouveau_fbcon_gpu_lockup(info);
info->flags |= FBINFO_HWACCEL_DISABLED;
} }
if (info->flags & FBINFO_HWACCEL_DISABLED) { if (info->flags & FBINFO_HWACCEL_DISABLED) {
...@@ -31,6 +29,10 @@ nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) ...@@ -31,6 +29,10 @@ nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
OUT_RING(chan, 1); OUT_RING(chan, 1);
} }
BEGIN_RING(chan, NvSub2D, 0x0588, 1); BEGIN_RING(chan, NvSub2D, 0x0588, 1);
if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
info->fix.visual == FB_VISUAL_DIRECTCOLOR)
OUT_RING(chan, ((uint32_t *)info->pseudo_palette)[rect->color]);
else
OUT_RING(chan, rect->color); OUT_RING(chan, rect->color);
BEGIN_RING(chan, NvSub2D, 0x0600, 4); BEGIN_RING(chan, NvSub2D, 0x0600, 4);
OUT_RING(chan, rect->dx); OUT_RING(chan, rect->dx);
...@@ -56,9 +58,7 @@ nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) ...@@ -56,9 +58,7 @@ nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
return; return;
if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 12)) { if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 12)) {
NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); nouveau_fbcon_gpu_lockup(info);
info->flags |= FBINFO_HWACCEL_DISABLED;
} }
if (info->flags & FBINFO_HWACCEL_DISABLED) { if (info->flags & FBINFO_HWACCEL_DISABLED) {
...@@ -101,8 +101,7 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) ...@@ -101,8 +101,7 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
} }
if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 11)) { if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 11)) {
NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); nouveau_fbcon_gpu_lockup(info);
info->flags |= FBINFO_HWACCEL_DISABLED;
} }
if (info->flags & FBINFO_HWACCEL_DISABLED) { if (info->flags & FBINFO_HWACCEL_DISABLED) {
...@@ -135,9 +134,7 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) ...@@ -135,9 +134,7 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
int push = dwords > 2047 ? 2047 : dwords; int push = dwords > 2047 ? 2047 : dwords;
if (RING_SPACE(chan, push + 1)) { if (RING_SPACE(chan, push + 1)) {
NV_ERROR(dev, nouveau_fbcon_gpu_lockup(info);
"GPU lockup - switching to software fbcon\n");
info->flags |= FBINFO_HWACCEL_DISABLED;
cfb_imageblit(info, image); cfb_imageblit(info, image);
return; return;
} }
...@@ -199,7 +196,7 @@ nv50_fbcon_accel_init(struct fb_info *info) ...@@ -199,7 +196,7 @@ nv50_fbcon_accel_init(struct fb_info *info)
ret = RING_SPACE(chan, 59); ret = RING_SPACE(chan, 59);
if (ret) { if (ret) {
NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); nouveau_fbcon_gpu_lockup(info);
return ret; return ret;
} }
......
...@@ -384,8 +384,8 @@ nv50_fifo_load_context(struct nouveau_channel *chan) ...@@ -384,8 +384,8 @@ nv50_fifo_load_context(struct nouveau_channel *chan)
nv_wr32(dev, NV40_PFIFO_CACHE1_DATA(ptr), nv_wr32(dev, NV40_PFIFO_CACHE1_DATA(ptr),
nv_ro32(dev, cache, (ptr * 2) + 1)); nv_ro32(dev, cache, (ptr * 2) + 1));
} }
nv_wr32(dev, 0x3210, cnt << 2); nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, cnt << 2);
nv_wr32(dev, 0x3270, 0); nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0);
/* guessing that all the 0x34xx regs aren't on NV50 */ /* guessing that all the 0x34xx regs aren't on NV50 */
if (!IS_G80) { if (!IS_G80) {
...@@ -398,8 +398,6 @@ nv50_fifo_load_context(struct nouveau_channel *chan) ...@@ -398,8 +398,6 @@ nv50_fifo_load_context(struct nouveau_channel *chan)
dev_priv->engine.instmem.finish_access(dev); dev_priv->engine.instmem.finish_access(dev);
nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0);
nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0);
nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, chan->id | (1<<16)); nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, chan->id | (1<<16));
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment