Commit 0c8eb0dc authored by Dave Airlie's avatar Dave Airlie

Merge remote branch 'nouveau/for-airlied' of ../drm-nouveau-next into drm-core-next

[airlied - add fix for vmwgfx build]

* 'nouveau/for-airlied' of ../drm-nouveau-next: (93 commits)
  drm/ttm: restructure to allow driver to plug in alternate memory manager
  drm/ttm: introduce utility function to free an allocated memory node
  drm/nouveau: fix thinkos in mem timing table recordlen check
  drm/nouveau: parse voltage from perf 0x40 entires
  drm/nouveau: don't use the default pll limits in table v2.1 on nv50+ cards
  drm/nv50: Fix large 3D performance regression caused by the interchannel sync patches.
  drm/nouveau: Synchronize buffer object moves in hardware.
  drm/nouveau: Use semaphores to handle inter-channel sync in hardware.
  drm/nouveau: Provide a means to have arbitrary work run on fence completion.
  drm/nouveau: Minor refactoring/cleanup of the fence code.
  drm/nouveau: Add a module option to force card POST.
  drm/nv50: prevent (IB_PUT == IB_GET) for occurring unless idle
  drm/nv0x-nv4x: Leave the 0x40 bit untouched when changing CRE_LCD.
  drm/nv30-nv40: Fix postdivider mask when writing engine/memory PLLs.
  drm/nouveau: Fix perf table parsing on BMP v5.25.
  drm/nouveau: fix required mode bandwidth calculation for DP
  drm/nouveau: fix typo in c2aa91afea5f7e7ae4530fabd37414a79c03328c
  drm/nva3: split pm backend out from nv50
  drm/nouveau: run perflvl and M table scripts on mem clock change
  drm/nouveau: pass perflvl struct to clock_pre()
  ...
parents e6b46ee7 d961db75
...@@ -10,6 +10,7 @@ config DRM_NOUVEAU ...@@ -10,6 +10,7 @@ config DRM_NOUVEAU
select FB select FB
select FRAMEBUFFER_CONSOLE if !EMBEDDED select FRAMEBUFFER_CONSOLE if !EMBEDDED
select FB_BACKLIGHT if DRM_NOUVEAU_BACKLIGHT select FB_BACKLIGHT if DRM_NOUVEAU_BACKLIGHT
select ACPI_VIDEO if ACPI
help help
Choose this option for open-source nVidia support. Choose this option for open-source nVidia support.
......
...@@ -9,7 +9,8 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ ...@@ -9,7 +9,8 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \ nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \
nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \ nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \
nouveau_display.o nouveau_connector.o nouveau_fbcon.o \ nouveau_display.o nouveau_connector.o nouveau_fbcon.o \
nouveau_dp.o \ nouveau_dp.o nouveau_ramht.o \
nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o \
nv04_timer.o \ nv04_timer.o \
nv04_mc.o nv40_mc.o nv50_mc.o \ nv04_mc.o nv40_mc.o nv50_mc.o \
nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o nvc0_fb.o \ nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o nvc0_fb.o \
...@@ -23,7 +24,8 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ ...@@ -23,7 +24,8 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \ nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \
nv04_crtc.o nv04_display.o nv04_cursor.o nv04_fbcon.o \ nv04_crtc.o nv04_display.o nv04_cursor.o nv04_fbcon.o \
nv10_gpio.o nv50_gpio.o \ nv10_gpio.o nv50_gpio.o \
nv50_calc.o nv50_calc.o \
nv04_pm.o nv50_pm.o nva3_pm.o
nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o
nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o
......
...@@ -292,6 +292,6 @@ nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) ...@@ -292,6 +292,6 @@ nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector)
if (ret < 0) if (ret < 0)
return ret; return ret;
nv_connector->edid = edid; nv_connector->edid = kmemdup(edid, EDID_LENGTH, GFP_KERNEL);
return 0; return 0;
} }
This diff is collapsed.
...@@ -34,6 +34,20 @@ ...@@ -34,6 +34,20 @@
#define DCB_LOC_ON_CHIP 0 #define DCB_LOC_ON_CHIP 0
#define ROM16(x) le16_to_cpu(*(uint16_t *)&(x))
#define ROM32(x) le32_to_cpu(*(uint32_t *)&(x))
#define ROMPTR(bios, x) (ROM16(x) ? &(bios)->data[ROM16(x)] : NULL)
struct bit_entry {
uint8_t id;
uint8_t version;
uint16_t length;
uint16_t offset;
uint8_t *data;
};
int bit_table(struct drm_device *, u8 id, struct bit_entry *);
struct dcb_i2c_entry { struct dcb_i2c_entry {
uint32_t entry; uint32_t entry;
uint8_t port_type; uint8_t port_type;
...@@ -170,16 +184,28 @@ enum LVDS_script { ...@@ -170,16 +184,28 @@ enum LVDS_script {
LVDS_PANEL_OFF LVDS_PANEL_OFF
}; };
/* changing these requires matching changes to reg tables in nv_get_clock */ /* these match types in pll limits table version 0x40,
#define MAX_PLL_TYPES 4 * nouveau uses them on all chipsets internally where a
* specific pll needs to be referenced, but the exact
* register isn't known.
*/
enum pll_types { enum pll_types {
NVPLL, PLL_CORE = 0x01,
MPLL, PLL_SHADER = 0x02,
VPLL1, PLL_UNK03 = 0x03,
VPLL2 PLL_MEMORY = 0x04,
PLL_UNK05 = 0x05,
PLL_UNK40 = 0x40,
PLL_UNK41 = 0x41,
PLL_UNK42 = 0x42,
PLL_VPLL0 = 0x80,
PLL_VPLL1 = 0x81,
PLL_MAX = 0xff
}; };
struct pll_lims { struct pll_lims {
u32 reg;
struct { struct {
int minfreq; int minfreq;
int maxfreq; int maxfreq;
...@@ -212,6 +238,11 @@ struct pll_lims { ...@@ -212,6 +238,11 @@ struct pll_lims {
struct nvbios { struct nvbios {
struct drm_device *dev; struct drm_device *dev;
enum {
NVBIOS_BMP,
NVBIOS_BIT
} type;
uint16_t offset;
uint8_t chip_version; uint8_t chip_version;
......
This diff is collapsed.
...@@ -198,8 +198,8 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp, ...@@ -198,8 +198,8 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp,
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nv_fifo_info fifo_data; struct nv_fifo_info fifo_data;
struct nv_sim_state sim_data; struct nv_sim_state sim_data;
int MClk = nouveau_hw_get_clock(dev, MPLL); int MClk = nouveau_hw_get_clock(dev, PLL_MEMORY);
int NVClk = nouveau_hw_get_clock(dev, NVPLL); int NVClk = nouveau_hw_get_clock(dev, PLL_CORE);
uint32_t cfg1 = nvReadFB(dev, NV04_PFB_CFG1); uint32_t cfg1 = nvReadFB(dev, NV04_PFB_CFG1);
sim_data.pclk_khz = VClk; sim_data.pclk_khz = VClk;
...@@ -234,7 +234,7 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp, ...@@ -234,7 +234,7 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp,
} }
static void static void
nv30_update_arb(int *burst, int *lwm) nv20_update_arb(int *burst, int *lwm)
{ {
unsigned int fifo_size, burst_size, graphics_lwm; unsigned int fifo_size, burst_size, graphics_lwm;
...@@ -251,14 +251,14 @@ nouveau_calc_arb(struct drm_device *dev, int vclk, int bpp, int *burst, int *lwm ...@@ -251,14 +251,14 @@ nouveau_calc_arb(struct drm_device *dev, int vclk, int bpp, int *burst, int *lwm
{ {
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
if (dev_priv->card_type < NV_30) if (dev_priv->card_type < NV_20)
nv04_update_arb(dev, vclk, bpp, burst, lwm); nv04_update_arb(dev, vclk, bpp, burst, lwm);
else if ((dev->pci_device & 0xfff0) == 0x0240 /*CHIPSET_C51*/ || else if ((dev->pci_device & 0xfff0) == 0x0240 /*CHIPSET_C51*/ ||
(dev->pci_device & 0xfff0) == 0x03d0 /*CHIPSET_C512*/) { (dev->pci_device & 0xfff0) == 0x03d0 /*CHIPSET_C512*/) {
*burst = 128; *burst = 128;
*lwm = 0x0480; *lwm = 0x0480;
} else } else
nv30_update_arb(burst, lwm); nv20_update_arb(burst, lwm);
} }
static int static int
......
...@@ -48,14 +48,14 @@ nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan) ...@@ -48,14 +48,14 @@ nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan)
dev_priv->gart_info.aper_size, dev_priv->gart_info.aper_size,
NV_DMA_ACCESS_RO, &pushbuf, NV_DMA_ACCESS_RO, &pushbuf,
NULL); NULL);
chan->pushbuf_base = pb->bo.mem.mm_node->start << PAGE_SHIFT; chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT;
} else } else
if (dev_priv->card_type != NV_04) { if (dev_priv->card_type != NV_04) {
ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0, ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0,
dev_priv->fb_available_size, dev_priv->fb_available_size,
NV_DMA_ACCESS_RO, NV_DMA_ACCESS_RO,
NV_DMA_TARGET_VIDMEM, &pushbuf); NV_DMA_TARGET_VIDMEM, &pushbuf);
chan->pushbuf_base = pb->bo.mem.mm_node->start << PAGE_SHIFT; chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT;
} else { } else {
/* NV04 cmdbuf hack, from original ddx.. not sure of it's /* NV04 cmdbuf hack, from original ddx.. not sure of it's
* exact reason for existing :) PCI access to cmdbuf in * exact reason for existing :) PCI access to cmdbuf in
...@@ -67,17 +67,11 @@ nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan) ...@@ -67,17 +67,11 @@ nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan)
dev_priv->fb_available_size, dev_priv->fb_available_size,
NV_DMA_ACCESS_RO, NV_DMA_ACCESS_RO,
NV_DMA_TARGET_PCI, &pushbuf); NV_DMA_TARGET_PCI, &pushbuf);
chan->pushbuf_base = pb->bo.mem.mm_node->start << PAGE_SHIFT; chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT;
}
ret = nouveau_gpuobj_ref_add(dev, chan, 0, pushbuf, &chan->pushbuf);
if (ret) {
NV_ERROR(dev, "Error referencing pushbuf ctxdma: %d\n", ret);
if (pushbuf != dev_priv->gart_info.sg_ctxdma)
nouveau_gpuobj_del(dev, &pushbuf);
return ret;
} }
nouveau_gpuobj_ref(pushbuf, &chan->pushbuf);
nouveau_gpuobj_ref(NULL, &pushbuf);
return 0; return 0;
} }
...@@ -229,7 +223,7 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, ...@@ -229,7 +223,7 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
ret = nouveau_dma_init(chan); ret = nouveau_dma_init(chan);
if (!ret) if (!ret)
ret = nouveau_fence_init(chan); ret = nouveau_fence_channel_init(chan);
if (ret) { if (ret) {
nouveau_channel_free(chan); nouveau_channel_free(chan);
return ret; return ret;
...@@ -276,7 +270,7 @@ nouveau_channel_free(struct nouveau_channel *chan) ...@@ -276,7 +270,7 @@ nouveau_channel_free(struct nouveau_channel *chan)
* above attempts at idling were OK, but if we failed this'll tell TTM * above attempts at idling were OK, but if we failed this'll tell TTM
* we're done with the buffers. * we're done with the buffers.
*/ */
nouveau_fence_fini(chan); nouveau_fence_channel_fini(chan);
/* This will prevent pfifo from switching channels. */ /* This will prevent pfifo from switching channels. */
pfifo->reassign(dev, false); pfifo->reassign(dev, false);
...@@ -308,8 +302,9 @@ nouveau_channel_free(struct nouveau_channel *chan) ...@@ -308,8 +302,9 @@ nouveau_channel_free(struct nouveau_channel *chan)
spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
/* Release the channel's resources */ /* Release the channel's resources */
nouveau_gpuobj_ref_del(dev, &chan->pushbuf); nouveau_gpuobj_ref(NULL, &chan->pushbuf);
if (chan->pushbuf_bo) { if (chan->pushbuf_bo) {
nouveau_bo_unmap(chan->pushbuf_bo);
nouveau_bo_unpin(chan->pushbuf_bo); nouveau_bo_unpin(chan->pushbuf_bo);
nouveau_bo_ref(NULL, &chan->pushbuf_bo); nouveau_bo_ref(NULL, &chan->pushbuf_bo);
} }
......
...@@ -76,6 +76,22 @@ nouveau_encoder_connector_get(struct nouveau_encoder *encoder) ...@@ -76,6 +76,22 @@ nouveau_encoder_connector_get(struct nouveau_encoder *encoder)
return NULL; return NULL;
} }
/*TODO: This could use improvement, and learn to handle the fixed
* BIOS tables etc. It's fine currently, for its only user.
*/
int
nouveau_connector_bpp(struct drm_connector *connector)
{
struct nouveau_connector *nv_connector = nouveau_connector(connector);
if (nv_connector->edid && nv_connector->edid->revision >= 4) {
u8 bpc = ((nv_connector->edid->input & 0x70) >> 3) + 4;
if (bpc > 4)
return bpc;
}
return 18;
}
static void static void
nouveau_connector_destroy(struct drm_connector *drm_connector) nouveau_connector_destroy(struct drm_connector *drm_connector)
...@@ -130,6 +146,36 @@ nouveau_connector_ddc_detect(struct drm_connector *connector, ...@@ -130,6 +146,36 @@ nouveau_connector_ddc_detect(struct drm_connector *connector,
return NULL; return NULL;
} }
static struct nouveau_encoder *
nouveau_connector_of_detect(struct drm_connector *connector)
{
#ifdef __powerpc__
struct drm_device *dev = connector->dev;
struct nouveau_connector *nv_connector = nouveau_connector(connector);
struct nouveau_encoder *nv_encoder;
struct device_node *cn, *dn = pci_device_to_OF_node(dev->pdev);
if (!dn ||
!((nv_encoder = find_encoder_by_type(connector, OUTPUT_TMDS)) ||
(nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG))))
return NULL;
for_each_child_of_node(dn, cn) {
const char *name = of_get_property(cn, "name", NULL);
const void *edid = of_get_property(cn, "EDID", NULL);
int idx = name ? name[strlen(name) - 1] - 'A' : 0;
if (nv_encoder->dcb->i2c_index == idx && edid) {
nv_connector->edid =
kmemdup(edid, EDID_LENGTH, GFP_KERNEL);
of_node_put(cn);
return nv_encoder;
}
}
#endif
return NULL;
}
static void static void
nouveau_connector_set_encoder(struct drm_connector *connector, nouveau_connector_set_encoder(struct drm_connector *connector,
struct nouveau_encoder *nv_encoder) struct nouveau_encoder *nv_encoder)
...@@ -225,6 +271,12 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) ...@@ -225,6 +271,12 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
return connector_status_connected; return connector_status_connected;
} }
nv_encoder = nouveau_connector_of_detect(connector);
if (nv_encoder) {
nouveau_connector_set_encoder(connector, nv_encoder);
return connector_status_connected;
}
detect_analog: detect_analog:
nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG); nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG);
if (!nv_encoder && !nouveau_tv_disable) if (!nv_encoder && !nouveau_tv_disable)
...@@ -630,7 +682,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector, ...@@ -630,7 +682,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
else else
max_clock = nv_encoder->dp.link_nr * 162000; max_clock = nv_encoder->dp.link_nr * 162000;
clock *= 3; clock = clock * nouveau_connector_bpp(connector) / 8;
break; break;
default: default:
BUG_ON(1); BUG_ON(1);
......
...@@ -55,4 +55,7 @@ nouveau_connector_create(struct drm_device *, int index); ...@@ -55,4 +55,7 @@ nouveau_connector_create(struct drm_device *, int index);
void void
nouveau_connector_set_polling(struct drm_connector *); nouveau_connector_set_polling(struct drm_connector *);
int
nouveau_connector_bpp(struct drm_connector *);
#endif /* __NOUVEAU_CONNECTOR_H__ */ #endif /* __NOUVEAU_CONNECTOR_H__ */
...@@ -157,7 +157,23 @@ nouveau_debugfs_vbios_image(struct seq_file *m, void *data) ...@@ -157,7 +157,23 @@ nouveau_debugfs_vbios_image(struct seq_file *m, void *data)
return 0; return 0;
} }
static int
nouveau_debugfs_evict_vram(struct seq_file *m, void *data)
{
struct drm_info_node *node = (struct drm_info_node *) m->private;
struct drm_nouveau_private *dev_priv = node->minor->dev->dev_private;
int ret;
ret = ttm_bo_evict_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
if (ret)
seq_printf(m, "failed: %d", ret);
else
seq_printf(m, "succeeded\n");
return 0;
}
static struct drm_info_list nouveau_debugfs_list[] = { static struct drm_info_list nouveau_debugfs_list[] = {
{ "evict_vram", nouveau_debugfs_evict_vram, 0, NULL },
{ "chipset", nouveau_debugfs_chipset_info, 0, NULL }, { "chipset", nouveau_debugfs_chipset_info, 0, NULL },
{ "memory", nouveau_debugfs_memory_info, 0, NULL }, { "memory", nouveau_debugfs_memory_info, 0, NULL },
{ "vbios.rom", nouveau_debugfs_vbios_image, 0, NULL }, { "vbios.rom", nouveau_debugfs_vbios_image, 0, NULL },
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "drm.h" #include "drm.h"
#include "nouveau_drv.h" #include "nouveau_drv.h"
#include "nouveau_dma.h" #include "nouveau_dma.h"
#include "nouveau_ramht.h"
void void
nouveau_dma_pre_init(struct nouveau_channel *chan) nouveau_dma_pre_init(struct nouveau_channel *chan)
...@@ -58,26 +59,17 @@ nouveau_dma_init(struct nouveau_channel *chan) ...@@ -58,26 +59,17 @@ 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 *obj = 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 */
ret = nouveau_gpuobj_gr_new(chan, dev_priv->card_type < NV_50 ? ret = nouveau_gpuobj_gr_new(chan, dev_priv->card_type < NV_50 ?
0x0039 : 0x5039, &m2mf); 0x0039 : 0x5039, &obj);
if (ret) if (ret)
return ret; return ret;
ret = nouveau_gpuobj_ref_add(dev, chan, NvM2MF, m2mf, NULL); ret = nouveau_ramht_insert(chan, NvM2MF, obj);
if (ret) nouveau_gpuobj_ref(NULL, &obj);
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) if (ret)
return ret; return ret;
...@@ -91,11 +83,6 @@ nouveau_dma_init(struct nouveau_channel *chan) ...@@ -91,11 +83,6 @@ nouveau_dma_init(struct nouveau_channel *chan)
if (ret) if (ret)
return ret; return ret;
/* Map M2MF notifier object - fbcon. */
ret = nouveau_bo_map(chan->notifier_bo);
if (ret)
return ret;
/* 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)
...@@ -113,13 +100,6 @@ nouveau_dma_init(struct nouveau_channel *chan) ...@@ -113,13 +100,6 @@ 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);
...@@ -217,7 +197,7 @@ nv50_dma_push_wait(struct nouveau_channel *chan, int count) ...@@ -217,7 +197,7 @@ nv50_dma_push_wait(struct nouveau_channel *chan, int count)
chan->dma.ib_free = get - chan->dma.ib_put; chan->dma.ib_free = get - chan->dma.ib_put;
if (chan->dma.ib_free <= 0) if (chan->dma.ib_free <= 0)
chan->dma.ib_free += chan->dma.ib_max + 1; chan->dma.ib_free += chan->dma.ib_max;
} }
return 0; return 0;
......
...@@ -72,6 +72,7 @@ enum { ...@@ -72,6 +72,7 @@ enum {
NvGdiRect = 0x8000000c, NvGdiRect = 0x8000000c,
NvImageBlit = 0x8000000d, NvImageBlit = 0x8000000d,
NvSw = 0x8000000e, NvSw = 0x8000000e,
NvSema = 0x8000000f,
/* G80+ display objects */ /* G80+ display objects */
NvEvoVRAM = 0x01000000, NvEvoVRAM = 0x01000000,
......
...@@ -317,7 +317,8 @@ nouveau_dp_link_train(struct drm_encoder *encoder) ...@@ -317,7 +317,8 @@ nouveau_dp_link_train(struct drm_encoder *encoder)
return false; return false;
config[0] = nv_encoder->dp.link_nr; config[0] = nv_encoder->dp.link_nr;
if (nv_encoder->dp.dpcd_version >= 0x11) if (nv_encoder->dp.dpcd_version >= 0x11 &&
nv_encoder->dp.enhanced_frame)
config[0] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; config[0] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
ret = nouveau_dp_lane_count_set(encoder, config[0]); ret = nouveau_dp_lane_count_set(encoder, config[0]);
...@@ -468,10 +469,12 @@ nouveau_dp_detect(struct drm_encoder *encoder) ...@@ -468,10 +469,12 @@ nouveau_dp_detect(struct drm_encoder *encoder)
!nv_encoder->dcb->dpconf.link_bw) !nv_encoder->dcb->dpconf.link_bw)
nv_encoder->dp.link_bw = DP_LINK_BW_1_62; nv_encoder->dp.link_bw = DP_LINK_BW_1_62;
nv_encoder->dp.link_nr = dpcd[2] & 0xf; nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK;
if (nv_encoder->dp.link_nr > nv_encoder->dcb->dpconf.link_nr) if (nv_encoder->dp.link_nr > nv_encoder->dcb->dpconf.link_nr)
nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr; nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr;
nv_encoder->dp.enhanced_frame = (dpcd[2] & DP_ENHANCED_FRAME_CAP);
return true; return true;
} }
...@@ -524,7 +527,8 @@ nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, ...@@ -524,7 +527,8 @@ nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x80000000); nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x80000000);
nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl); nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl);
nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x00010000); nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x00010000);
if (!nv_wait(NV50_AUXCH_CTRL(index), 0x00010000, 0x00000000)) { if (!nv_wait(dev, NV50_AUXCH_CTRL(index),
0x00010000, 0x00000000)) {
NV_ERROR(dev, "expected bit 16 == 0, got 0x%08x\n", NV_ERROR(dev, "expected bit 16 == 0, got 0x%08x\n",
nv_rd32(dev, NV50_AUXCH_CTRL(index))); nv_rd32(dev, NV50_AUXCH_CTRL(index)));
ret = -EBUSY; ret = -EBUSY;
......
...@@ -31,13 +31,14 @@ ...@@ -31,13 +31,14 @@
#include "nouveau_hw.h" #include "nouveau_hw.h"
#include "nouveau_fb.h" #include "nouveau_fb.h"
#include "nouveau_fbcon.h" #include "nouveau_fbcon.h"
#include "nouveau_pm.h"
#include "nv50_display.h" #include "nv50_display.h"
#include "drm_pciids.h" #include "drm_pciids.h"
MODULE_PARM_DESC(noagp, "Disable AGP"); MODULE_PARM_DESC(agpmode, "AGP mode (0 to disable AGP)");
int nouveau_noagp; int nouveau_agpmode = -1;
module_param_named(noagp, nouveau_noagp, int, 0400); module_param_named(agpmode, nouveau_agpmode, int, 0400);
MODULE_PARM_DESC(modeset, "Enable kernel modesetting"); MODULE_PARM_DESC(modeset, "Enable kernel modesetting");
static int nouveau_modeset = -1; /* kms */ static int nouveau_modeset = -1; /* kms */
...@@ -79,6 +80,10 @@ MODULE_PARM_DESC(nofbaccel, "Disable fbcon acceleration"); ...@@ -79,6 +80,10 @@ MODULE_PARM_DESC(nofbaccel, "Disable fbcon acceleration");
int nouveau_nofbaccel = 0; int nouveau_nofbaccel = 0;
module_param_named(nofbaccel, nouveau_nofbaccel, int, 0400); module_param_named(nofbaccel, nouveau_nofbaccel, int, 0400);
MODULE_PARM_DESC(force_post, "Force POST");
int nouveau_force_post = 0;
module_param_named(force_post, nouveau_force_post, int, 0400);
MODULE_PARM_DESC(override_conntype, "Ignore DCB connector type"); MODULE_PARM_DESC(override_conntype, "Ignore DCB connector type");
int nouveau_override_conntype = 0; int nouveau_override_conntype = 0;
module_param_named(override_conntype, nouveau_override_conntype, int, 0400); module_param_named(override_conntype, nouveau_override_conntype, int, 0400);
...@@ -102,6 +107,14 @@ MODULE_PARM_DESC(reg_debug, "Register access debug bitmask:\n" ...@@ -102,6 +107,14 @@ MODULE_PARM_DESC(reg_debug, "Register access debug bitmask:\n"
int nouveau_reg_debug; int nouveau_reg_debug;
module_param_named(reg_debug, nouveau_reg_debug, int, 0600); module_param_named(reg_debug, nouveau_reg_debug, int, 0600);
MODULE_PARM_DESC(perflvl, "Performance level (default: boot)\n");
char *nouveau_perflvl;
module_param_named(perflvl, nouveau_perflvl, charp, 0400);
MODULE_PARM_DESC(perflvl_wr, "Allow perflvl changes (warning: dangerous!)\n");
int nouveau_perflvl_wr;
module_param_named(perflvl_wr, nouveau_perflvl_wr, int, 0400);
int nouveau_fbpercrtc; int nouveau_fbpercrtc;
#if 0 #if 0
module_param_named(fbpercrtc, nouveau_fbpercrtc, int, 0400); module_param_named(fbpercrtc, nouveau_fbpercrtc, int, 0400);
...@@ -271,6 +284,8 @@ nouveau_pci_resume(struct pci_dev *pdev) ...@@ -271,6 +284,8 @@ nouveau_pci_resume(struct pci_dev *pdev)
if (ret) if (ret)
return ret; return ret;
nouveau_pm_resume(dev);
if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) { if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) {
ret = nouveau_mem_init_agp(dev); ret = nouveau_mem_init_agp(dev);
if (ret) { if (ret) {
......
This diff is collapsed.
...@@ -55,6 +55,7 @@ struct nouveau_encoder { ...@@ -55,6 +55,7 @@ struct nouveau_encoder {
int dpcd_version; int dpcd_version;
int link_nr; int link_nr;
int link_bw; int link_bw;
bool enhanced_frame;
} dp; } dp;
}; };
}; };
......
This diff is collapsed.
...@@ -362,7 +362,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list, ...@@ -362,7 +362,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
list_for_each_entry(nvbo, list, entry) { list_for_each_entry(nvbo, list, entry) {
struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index]; struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index];
ret = nouveau_bo_sync_gpu(nvbo, chan); ret = nouveau_fence_sync(nvbo->bo.sync_obj, chan);
if (unlikely(ret)) { if (unlikely(ret)) {
NV_ERROR(dev, "fail pre-validate sync\n"); NV_ERROR(dev, "fail pre-validate sync\n");
return ret; return ret;
...@@ -385,7 +385,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list, ...@@ -385,7 +385,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
return ret; return ret;
} }
ret = nouveau_bo_sync_gpu(nvbo, chan); ret = nouveau_fence_sync(nvbo->bo.sync_obj, chan);
if (unlikely(ret)) { if (unlikely(ret)) {
NV_ERROR(dev, "fail post-validate sync\n"); NV_ERROR(dev, "fail post-validate sync\n");
return ret; return ret;
......
...@@ -126,7 +126,7 @@ gr_def(struct nouveau_grctx *ctx, uint32_t reg, uint32_t val) ...@@ -126,7 +126,7 @@ gr_def(struct nouveau_grctx *ctx, uint32_t reg, uint32_t val)
reg = (reg - 0x00400000) / 4; reg = (reg - 0x00400000) / 4;
reg = (reg - ctx->ctxprog_reg) + ctx->ctxvals_base; reg = (reg - ctx->ctxprog_reg) + ctx->ctxvals_base;
nv_wo32(ctx->dev, ctx->data, reg, val); nv_wo32(ctx->data, reg * 4, val);
} }
#endif #endif
......
...@@ -305,7 +305,7 @@ setPLL_double_lowregs(struct drm_device *dev, uint32_t NMNMreg, ...@@ -305,7 +305,7 @@ setPLL_double_lowregs(struct drm_device *dev, uint32_t NMNMreg,
bool mpll = Preg == 0x4020; bool mpll = Preg == 0x4020;
uint32_t oldPval = nvReadMC(dev, Preg); uint32_t oldPval = nvReadMC(dev, Preg);
uint32_t NMNM = pv->NM2 << 16 | pv->NM1; uint32_t NMNM = pv->NM2 << 16 | pv->NM1;
uint32_t Pval = (oldPval & (mpll ? ~(0x11 << 16) : ~(1 << 16))) | uint32_t Pval = (oldPval & (mpll ? ~(0x77 << 16) : ~(7 << 16))) |
0xc << 28 | pv->log2P << 16; 0xc << 28 | pv->log2P << 16;
uint32_t saved4600 = 0; uint32_t saved4600 = 0;
/* some cards have different maskc040s */ /* some cards have different maskc040s */
...@@ -427,22 +427,12 @@ nouveau_hw_get_pllvals(struct drm_device *dev, enum pll_types plltype, ...@@ -427,22 +427,12 @@ nouveau_hw_get_pllvals(struct drm_device *dev, enum pll_types plltype,
struct nouveau_pll_vals *pllvals) struct nouveau_pll_vals *pllvals)
{ {
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
const uint32_t nv04_regs[MAX_PLL_TYPES] = { NV_PRAMDAC_NVPLL_COEFF, uint32_t reg1 = get_pll_register(dev, plltype), pll1, pll2 = 0;
NV_PRAMDAC_MPLL_COEFF,
NV_PRAMDAC_VPLL_COEFF,
NV_RAMDAC_VPLL2 };
const uint32_t nv40_regs[MAX_PLL_TYPES] = { 0x4000,
0x4020,
NV_PRAMDAC_VPLL_COEFF,
NV_RAMDAC_VPLL2 };
uint32_t reg1, pll1, pll2 = 0;
struct pll_lims pll_lim; struct pll_lims pll_lim;
int ret; int ret;
if (dev_priv->card_type < NV_40) if (reg1 == 0)
reg1 = nv04_regs[plltype]; return -ENOENT;
else
reg1 = nv40_regs[plltype];
pll1 = nvReadMC(dev, reg1); pll1 = nvReadMC(dev, reg1);
...@@ -491,8 +481,10 @@ int ...@@ -491,8 +481,10 @@ int
nouveau_hw_get_clock(struct drm_device *dev, enum pll_types plltype) nouveau_hw_get_clock(struct drm_device *dev, enum pll_types plltype)
{ {
struct nouveau_pll_vals pllvals; struct nouveau_pll_vals pllvals;
int ret;
if (plltype == MPLL && (dev->pci_device & 0x0ff0) == CHIPSET_NFORCE) { if (plltype == PLL_MEMORY &&
(dev->pci_device & 0x0ff0) == CHIPSET_NFORCE) {
uint32_t mpllP; uint32_t mpllP;
pci_read_config_dword(pci_get_bus_and_slot(0, 3), 0x6c, &mpllP); pci_read_config_dword(pci_get_bus_and_slot(0, 3), 0x6c, &mpllP);
...@@ -501,14 +493,17 @@ nouveau_hw_get_clock(struct drm_device *dev, enum pll_types plltype) ...@@ -501,14 +493,17 @@ nouveau_hw_get_clock(struct drm_device *dev, enum pll_types plltype)
return 400000 / mpllP; return 400000 / mpllP;
} else } else
if (plltype == MPLL && (dev->pci_device & 0xff0) == CHIPSET_NFORCE2) { if (plltype == PLL_MEMORY &&
(dev->pci_device & 0xff0) == CHIPSET_NFORCE2) {
uint32_t clock; uint32_t clock;
pci_read_config_dword(pci_get_bus_and_slot(0, 5), 0x4c, &clock); pci_read_config_dword(pci_get_bus_and_slot(0, 5), 0x4c, &clock);
return clock; return clock;
} }
nouveau_hw_get_pllvals(dev, plltype, &pllvals); ret = nouveau_hw_get_pllvals(dev, plltype, &pllvals);
if (ret)
return ret;
return nouveau_hw_pllvals_to_clk(&pllvals); return nouveau_hw_pllvals_to_clk(&pllvals);
} }
...@@ -526,9 +521,9 @@ nouveau_hw_fix_bad_vpll(struct drm_device *dev, int head) ...@@ -526,9 +521,9 @@ nouveau_hw_fix_bad_vpll(struct drm_device *dev, int head)
struct nouveau_pll_vals pv; struct nouveau_pll_vals pv;
uint32_t pllreg = head ? NV_RAMDAC_VPLL2 : NV_PRAMDAC_VPLL_COEFF; uint32_t pllreg = head ? NV_RAMDAC_VPLL2 : NV_PRAMDAC_VPLL_COEFF;
if (get_pll_limits(dev, head ? VPLL2 : VPLL1, &pll_lim)) if (get_pll_limits(dev, pllreg, &pll_lim))
return; return;
nouveau_hw_get_pllvals(dev, head ? VPLL2 : VPLL1, &pv); nouveau_hw_get_pllvals(dev, pllreg, &pv);
if (pv.M1 >= pll_lim.vco1.min_m && pv.M1 <= pll_lim.vco1.max_m && if (pv.M1 >= pll_lim.vco1.min_m && pv.M1 <= pll_lim.vco1.max_m &&
pv.N1 >= pll_lim.vco1.min_n && pv.N1 <= pll_lim.vco1.max_n && pv.N1 >= pll_lim.vco1.min_n && pv.N1 <= pll_lim.vco1.max_n &&
...@@ -661,7 +656,7 @@ nv_save_state_ramdac(struct drm_device *dev, int head, ...@@ -661,7 +656,7 @@ nv_save_state_ramdac(struct drm_device *dev, int head,
if (dev_priv->card_type >= NV_10) if (dev_priv->card_type >= NV_10)
regp->nv10_cursync = NVReadRAMDAC(dev, head, NV_RAMDAC_NV10_CURSYNC); regp->nv10_cursync = NVReadRAMDAC(dev, head, NV_RAMDAC_NV10_CURSYNC);
nouveau_hw_get_pllvals(dev, head ? VPLL2 : VPLL1, &regp->pllvals); nouveau_hw_get_pllvals(dev, head ? PLL_VPLL1 : PLL_VPLL0, &regp->pllvals);
state->pllsel = NVReadRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT); state->pllsel = NVReadRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT);
if (nv_two_heads(dev)) if (nv_two_heads(dev))
state->sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK); state->sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK);
...@@ -866,10 +861,11 @@ nv_save_state_ext(struct drm_device *dev, int head, ...@@ -866,10 +861,11 @@ nv_save_state_ext(struct drm_device *dev, int head,
rd_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); rd_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX);
rd_cio_state(dev, head, regp, NV_CIO_CRE_21); rd_cio_state(dev, head, regp, NV_CIO_CRE_21);
if (dev_priv->card_type >= NV_30) { if (dev_priv->card_type >= NV_20)
rd_cio_state(dev, head, regp, NV_CIO_CRE_47); rd_cio_state(dev, head, regp, NV_CIO_CRE_47);
if (dev_priv->card_type >= NV_30)
rd_cio_state(dev, head, regp, 0x9f); rd_cio_state(dev, head, regp, 0x9f);
}
rd_cio_state(dev, head, regp, NV_CIO_CRE_49); rd_cio_state(dev, head, regp, NV_CIO_CRE_49);
rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX);
...@@ -976,10 +972,11 @@ nv_load_state_ext(struct drm_device *dev, int head, ...@@ -976,10 +972,11 @@ nv_load_state_ext(struct drm_device *dev, int head,
wr_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX); wr_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX);
wr_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); wr_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX);
if (dev_priv->card_type >= NV_30) { if (dev_priv->card_type >= NV_20)
wr_cio_state(dev, head, regp, NV_CIO_CRE_47); wr_cio_state(dev, head, regp, NV_CIO_CRE_47);
if (dev_priv->card_type >= NV_30)
wr_cio_state(dev, head, regp, 0x9f); wr_cio_state(dev, head, regp, 0x9f);
}
wr_cio_state(dev, head, regp, NV_CIO_CRE_49); wr_cio_state(dev, head, regp, NV_CIO_CRE_49);
wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX);
......
...@@ -299,7 +299,10 @@ nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr) ...@@ -299,7 +299,10 @@ nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr)
int int
nouveau_i2c_identify(struct drm_device *dev, const char *what, nouveau_i2c_identify(struct drm_device *dev, const char *what,
struct i2c_board_info *info, int index) struct i2c_board_info *info,
bool (*match)(struct nouveau_i2c_chan *,
struct i2c_board_info *),
int index)
{ {
struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, index); struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, index);
int i; int i;
...@@ -307,7 +310,8 @@ nouveau_i2c_identify(struct drm_device *dev, const char *what, ...@@ -307,7 +310,8 @@ nouveau_i2c_identify(struct drm_device *dev, const char *what,
NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, index); NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, index);
for (i = 0; info[i].addr; i++) { for (i = 0; info[i].addr; i++) {
if (nouveau_probe_i2c_addr(i2c, info[i].addr)) { if (nouveau_probe_i2c_addr(i2c, info[i].addr) &&
(!match || match(i2c, &info[i]))) {
NV_INFO(dev, "Detected %s: %s\n", what, info[i].type); NV_INFO(dev, "Detected %s: %s\n", what, info[i].type);
return i; return i;
} }
......
...@@ -44,7 +44,10 @@ void nouveau_i2c_fini(struct drm_device *, struct dcb_i2c_entry *); ...@@ -44,7 +44,10 @@ void nouveau_i2c_fini(struct drm_device *, struct dcb_i2c_entry *);
struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, int index); struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, int index);
bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr); bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr);
int nouveau_i2c_identify(struct drm_device *dev, const char *what, int nouveau_i2c_identify(struct drm_device *dev, const char *what,
struct i2c_board_info *info, int index); struct i2c_board_info *info,
bool (*match)(struct nouveau_i2c_chan *,
struct i2c_board_info *),
int index);
extern const struct i2c_algorithm nouveau_dp_i2c_algo; extern const struct i2c_algorithm nouveau_dp_i2c_algo;
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "nouveau_drm.h" #include "nouveau_drm.h"
#include "nouveau_drv.h" #include "nouveau_drv.h"
#include "nouveau_reg.h" #include "nouveau_reg.h"
#include "nouveau_ramht.h"
#include <linux/ratelimit.h> #include <linux/ratelimit.h>
/* needed for hotplug irq */ /* needed for hotplug irq */
...@@ -106,15 +107,16 @@ nouveau_fifo_swmthd(struct nouveau_channel *chan, uint32_t addr, uint32_t data) ...@@ -106,15 +107,16 @@ nouveau_fifo_swmthd(struct nouveau_channel *chan, uint32_t addr, uint32_t data)
const int mthd = addr & 0x1ffc; const int mthd = addr & 0x1ffc;
if (mthd == 0x0000) { if (mthd == 0x0000) {
struct nouveau_gpuobj_ref *ref = NULL; struct nouveau_gpuobj *gpuobj;
if (nouveau_gpuobj_ref_find(chan, data, &ref)) gpuobj = nouveau_ramht_find(chan, data);
if (!gpuobj)
return false; return false;
if (ref->gpuobj->engine != NVOBJ_ENGINE_SW) if (gpuobj->engine != NVOBJ_ENGINE_SW)
return false; return false;
chan->sw_subchannel[subc] = ref->gpuobj->class; chan->sw_subchannel[subc] = gpuobj->class;
nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_rd32(dev, nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_rd32(dev,
NV04_PFIFO_CACHE1_ENGINE) & ~(0xf << subc * 4)); NV04_PFIFO_CACHE1_ENGINE) & ~(0xf << subc * 4));
return true; return true;
...@@ -200,16 +202,45 @@ nouveau_fifo_irq_handler(struct drm_device *dev) ...@@ -200,16 +202,45 @@ nouveau_fifo_irq_handler(struct drm_device *dev)
} }
if (status & NV_PFIFO_INTR_DMA_PUSHER) { if (status & NV_PFIFO_INTR_DMA_PUSHER) {
NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d\n", chid); u32 get = nv_rd32(dev, 0x003244);
u32 put = nv_rd32(dev, 0x003240);
u32 push = nv_rd32(dev, 0x003220);
u32 state = nv_rd32(dev, 0x003228);
if (dev_priv->card_type == NV_50) {
u32 ho_get = nv_rd32(dev, 0x003328);
u32 ho_put = nv_rd32(dev, 0x003320);
u32 ib_get = nv_rd32(dev, 0x003334);
u32 ib_put = nv_rd32(dev, 0x003330);
NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%02x%08x "
"Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x "
"State 0x%08x Push 0x%08x\n",
chid, ho_get, get, ho_put, put, ib_get, ib_put,
state, push);
/* METHOD_COUNT, in DMA_STATE on earlier chipsets */
nv_wr32(dev, 0x003364, 0x00000000);
if (get != put || ho_get != ho_put) {
nv_wr32(dev, 0x003244, put);
nv_wr32(dev, 0x003328, ho_put);
} else
if (ib_get != ib_put) {
nv_wr32(dev, 0x003334, ib_put);
}
} else {
NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%08x "
"Put 0x%08x State 0x%08x Push 0x%08x\n",
chid, get, put, state, push);
status &= ~NV_PFIFO_INTR_DMA_PUSHER; if (get != put)
nv_wr32(dev, NV03_PFIFO_INTR_0, nv_wr32(dev, 0x003244, put);
NV_PFIFO_INTR_DMA_PUSHER); }
nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_STATE, 0x00000000); nv_wr32(dev, 0x003228, 0x00000000);
if (nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT) != get) nv_wr32(dev, 0x003220, 0x00000001);
nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_wr32(dev, 0x002100, NV_PFIFO_INTR_DMA_PUSHER);
get + 4); status &= ~NV_PFIFO_INTR_DMA_PUSHER;
} }
if (status & NV_PFIFO_INTR_SEMAPHORE) { if (status & NV_PFIFO_INTR_SEMAPHORE) {
...@@ -226,6 +257,14 @@ nouveau_fifo_irq_handler(struct drm_device *dev) ...@@ -226,6 +257,14 @@ nouveau_fifo_irq_handler(struct drm_device *dev)
nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1);
} }
if (dev_priv->card_type == NV_50) {
if (status & 0x00000010) {
nv50_fb_vm_trap(dev, 1, "PFIFO_BAR_FAULT");
status &= ~0x00000010;
nv_wr32(dev, 0x002100, 0x00000010);
}
}
if (status) { if (status) {
NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n", NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n",
status, chid); status, chid);
...@@ -357,7 +396,7 @@ nouveau_graph_chid_from_grctx(struct drm_device *dev) ...@@ -357,7 +396,7 @@ nouveau_graph_chid_from_grctx(struct drm_device *dev)
if (!chan || !chan->ramin_grctx) if (!chan || !chan->ramin_grctx)
continue; continue;
if (inst == chan->ramin_grctx->instance) if (inst == chan->ramin_grctx->pinst)
break; break;
} }
} else { } else {
...@@ -369,7 +408,7 @@ nouveau_graph_chid_from_grctx(struct drm_device *dev) ...@@ -369,7 +408,7 @@ nouveau_graph_chid_from_grctx(struct drm_device *dev)
if (!chan || !chan->ramin) if (!chan || !chan->ramin)
continue; continue;
if (inst == chan->ramin->instance) if (inst == chan->ramin->vinst)
break; break;
} }
} }
...@@ -605,40 +644,6 @@ nouveau_pgraph_irq_handler(struct drm_device *dev) ...@@ -605,40 +644,6 @@ nouveau_pgraph_irq_handler(struct drm_device *dev)
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);
} }
static void
nv50_pfb_vm_trap(struct drm_device *dev, int display, const char *name)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
uint32_t trap[6];
int i, ch;
uint32_t idx = nv_rd32(dev, 0x100c90);
if (idx & 0x80000000) {
idx &= 0xffffff;
if (display) {
for (i = 0; i < 6; i++) {
nv_wr32(dev, 0x100c90, idx | i << 24);
trap[i] = nv_rd32(dev, 0x100c94);
}
for (ch = 0; ch < dev_priv->engine.fifo.channels; ch++) {
struct nouveau_channel *chan = dev_priv->fifos[ch];
if (!chan || !chan->ramin)
continue;
if (trap[1] == chan->ramin->instance >> 12)
break;
}
NV_INFO(dev, "%s - VM: Trapped %s at %02x%04x%04x status %08x %08x channel %d\n",
name, (trap[5]&0x100?"read":"write"),
trap[5]&0xff, trap[4]&0xffff,
trap[3]&0xffff, trap[0], trap[2], ch);
}
nv_wr32(dev, 0x100c90, idx | 0x80000000);
} else if (display) {
NV_INFO(dev, "%s - no VM fault?\n", name);
}
}
static struct nouveau_enum_names nv50_mp_exec_error_names[] = static struct nouveau_enum_names nv50_mp_exec_error_names[] =
{ {
{ 3, "STACK_UNDERFLOW" }, { 3, "STACK_UNDERFLOW" },
...@@ -711,7 +716,7 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, ...@@ -711,7 +716,7 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old,
tps++; tps++;
switch (type) { switch (type) {
case 6: /* texture error... unknown for now */ case 6: /* texture error... unknown for now */
nv50_pfb_vm_trap(dev, display, name); nv50_fb_vm_trap(dev, display, name);
if (display) { if (display) {
NV_ERROR(dev, "magic set %d:\n", i); NV_ERROR(dev, "magic set %d:\n", i);
for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4) for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4)
...@@ -734,7 +739,7 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, ...@@ -734,7 +739,7 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old,
uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14); uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14);
uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18); uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18);
uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c); uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c);
nv50_pfb_vm_trap(dev, display, name); nv50_fb_vm_trap(dev, display, name);
/* 2d engine destination */ /* 2d engine destination */
if (ustatus & 0x00000010) { if (ustatus & 0x00000010) {
if (display) { if (display) {
...@@ -817,7 +822,7 @@ nv50_pgraph_trap_handler(struct drm_device *dev) ...@@ -817,7 +822,7 @@ nv50_pgraph_trap_handler(struct drm_device *dev)
/* Known to be triggered by screwed up NOTIFY and COND... */ /* Known to be triggered by screwed up NOTIFY and COND... */
if (ustatus & 0x00000001) { if (ustatus & 0x00000001) {
nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_FAULT"); nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_FAULT");
nv_wr32(dev, 0x400500, 0); nv_wr32(dev, 0x400500, 0);
if (nv_rd32(dev, 0x400808) & 0x80000000) { if (nv_rd32(dev, 0x400808) & 0x80000000) {
if (display) { if (display) {
...@@ -842,7 +847,7 @@ nv50_pgraph_trap_handler(struct drm_device *dev) ...@@ -842,7 +847,7 @@ nv50_pgraph_trap_handler(struct drm_device *dev)
ustatus &= ~0x00000001; ustatus &= ~0x00000001;
} }
if (ustatus & 0x00000002) { if (ustatus & 0x00000002) {
nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_QUERY"); nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_QUERY");
nv_wr32(dev, 0x400500, 0); nv_wr32(dev, 0x400500, 0);
if (nv_rd32(dev, 0x40084c) & 0x80000000) { if (nv_rd32(dev, 0x40084c) & 0x80000000) {
if (display) { if (display) {
...@@ -884,15 +889,15 @@ nv50_pgraph_trap_handler(struct drm_device *dev) ...@@ -884,15 +889,15 @@ nv50_pgraph_trap_handler(struct drm_device *dev)
NV_INFO(dev, "PGRAPH_TRAP_M2MF - no ustatus?\n"); NV_INFO(dev, "PGRAPH_TRAP_M2MF - no ustatus?\n");
} }
if (ustatus & 0x00000001) { if (ustatus & 0x00000001) {
nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_NOTIFY"); nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_NOTIFY");
ustatus &= ~0x00000001; ustatus &= ~0x00000001;
} }
if (ustatus & 0x00000002) { if (ustatus & 0x00000002) {
nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_IN"); nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_IN");
ustatus &= ~0x00000002; ustatus &= ~0x00000002;
} }
if (ustatus & 0x00000004) { if (ustatus & 0x00000004) {
nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_OUT"); nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_OUT");
ustatus &= ~0x00000004; ustatus &= ~0x00000004;
} }
NV_INFO (dev, "PGRAPH_TRAP_M2MF - %08x %08x %08x %08x\n", NV_INFO (dev, "PGRAPH_TRAP_M2MF - %08x %08x %08x %08x\n",
...@@ -917,7 +922,7 @@ nv50_pgraph_trap_handler(struct drm_device *dev) ...@@ -917,7 +922,7 @@ nv50_pgraph_trap_handler(struct drm_device *dev)
NV_INFO(dev, "PGRAPH_TRAP_VFETCH - no ustatus?\n"); NV_INFO(dev, "PGRAPH_TRAP_VFETCH - no ustatus?\n");
} }
if (ustatus & 0x00000001) { if (ustatus & 0x00000001) {
nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_VFETCH_FAULT"); nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_VFETCH_FAULT");
NV_INFO (dev, "PGRAPH_TRAP_VFETCH_FAULT - %08x %08x %08x %08x\n", NV_INFO (dev, "PGRAPH_TRAP_VFETCH_FAULT - %08x %08x %08x %08x\n",
nv_rd32(dev, 0x400c00), nv_rd32(dev, 0x400c00),
nv_rd32(dev, 0x400c08), nv_rd32(dev, 0x400c08),
...@@ -939,7 +944,7 @@ nv50_pgraph_trap_handler(struct drm_device *dev) ...@@ -939,7 +944,7 @@ nv50_pgraph_trap_handler(struct drm_device *dev)
NV_INFO(dev, "PGRAPH_TRAP_STRMOUT - no ustatus?\n"); NV_INFO(dev, "PGRAPH_TRAP_STRMOUT - no ustatus?\n");
} }
if (ustatus & 0x00000001) { if (ustatus & 0x00000001) {
nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_STRMOUT_FAULT"); nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_STRMOUT_FAULT");
NV_INFO (dev, "PGRAPH_TRAP_STRMOUT_FAULT - %08x %08x %08x %08x\n", NV_INFO (dev, "PGRAPH_TRAP_STRMOUT_FAULT - %08x %08x %08x %08x\n",
nv_rd32(dev, 0x401804), nv_rd32(dev, 0x401804),
nv_rd32(dev, 0x401808), nv_rd32(dev, 0x401808),
...@@ -964,7 +969,7 @@ nv50_pgraph_trap_handler(struct drm_device *dev) ...@@ -964,7 +969,7 @@ nv50_pgraph_trap_handler(struct drm_device *dev)
NV_INFO(dev, "PGRAPH_TRAP_CCACHE - no ustatus?\n"); NV_INFO(dev, "PGRAPH_TRAP_CCACHE - no ustatus?\n");
} }
if (ustatus & 0x00000001) { if (ustatus & 0x00000001) {
nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_CCACHE_FAULT"); nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_CCACHE_FAULT");
NV_INFO (dev, "PGRAPH_TRAP_CCACHE_FAULT - %08x %08x %08x %08x %08x %08x %08x\n", NV_INFO (dev, "PGRAPH_TRAP_CCACHE_FAULT - %08x %08x %08x %08x %08x %08x %08x\n",
nv_rd32(dev, 0x405800), nv_rd32(dev, 0x405800),
nv_rd32(dev, 0x405804), nv_rd32(dev, 0x405804),
...@@ -986,7 +991,7 @@ nv50_pgraph_trap_handler(struct drm_device *dev) ...@@ -986,7 +991,7 @@ nv50_pgraph_trap_handler(struct drm_device *dev)
* remaining, so try to handle it anyway. Perhaps related to that * remaining, so try to handle it anyway. Perhaps related to that
* unknown DMA slot on tesla? */ * unknown DMA slot on tesla? */
if (status & 0x20) { if (status & 0x20) {
nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_UNKC04"); nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_UNKC04");
ustatus = nv_rd32(dev, 0x402000) & 0x7fffffff; ustatus = nv_rd32(dev, 0x402000) & 0x7fffffff;
if (display) if (display)
NV_INFO(dev, "PGRAPH_TRAP_UNKC04 - Unhandled ustatus 0x%08x\n", ustatus); NV_INFO(dev, "PGRAPH_TRAP_UNKC04 - Unhandled ustatus 0x%08x\n", ustatus);
......
This diff is collapsed.
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "drmP.h" #include "drmP.h"
#include "drm.h" #include "drm.h"
#include "nouveau_drv.h" #include "nouveau_drv.h"
#include "nouveau_ramht.h"
int int
nouveau_notifier_init_channel(struct nouveau_channel *chan) nouveau_notifier_init_channel(struct nouveau_channel *chan)
...@@ -113,7 +114,7 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, ...@@ -113,7 +114,7 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
return -ENOMEM; return -ENOMEM;
} }
offset = chan->notifier_bo->bo.mem.mm_node->start << PAGE_SHIFT; offset = chan->notifier_bo->bo.mem.start << PAGE_SHIFT;
if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM) { if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM) {
target = NV_DMA_TARGET_VIDMEM; target = NV_DMA_TARGET_VIDMEM;
} else } else
...@@ -147,11 +148,11 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, ...@@ -147,11 +148,11 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
nobj->dtor = nouveau_notifier_gpuobj_dtor; nobj->dtor = nouveau_notifier_gpuobj_dtor;
nobj->priv = mem; nobj->priv = mem;
ret = nouveau_gpuobj_ref_add(dev, chan, handle, nobj, NULL); ret = nouveau_ramht_insert(chan, handle, nobj);
nouveau_gpuobj_ref(NULL, &nobj);
if (ret) { if (ret) {
nouveau_gpuobj_del(dev, &nobj);
drm_mm_put_block(mem); drm_mm_put_block(mem);
NV_ERROR(dev, "Error referencing notifier ctxdma: %d\n", ret); NV_ERROR(dev, "Error adding notifier to ramht: %d\n", ret);
return ret; return ret;
} }
......
This diff is collapsed.
/*
* Copyright 2010 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include "drmP.h"
#include "nouveau_drv.h"
#include "nouveau_pm.h"
static void
legacy_perf_init(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nvbios *bios = &dev_priv->vbios;
struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
char *perf, *entry, *bmp = &bios->data[bios->offset];
int headerlen, use_straps;
if (bmp[5] < 0x5 || bmp[6] < 0x14) {
NV_DEBUG(dev, "BMP version too old for perf\n");
return;
}
perf = ROMPTR(bios, bmp[0x73]);
if (!perf) {
NV_DEBUG(dev, "No memclock table pointer found.\n");
return;
}
switch (perf[0]) {
case 0x12:
case 0x14:
case 0x18:
use_straps = 0;
headerlen = 1;
break;
case 0x01:
use_straps = perf[1] & 1;
headerlen = (use_straps ? 8 : 2);
break;
default:
NV_WARN(dev, "Unknown memclock table version %x.\n", perf[0]);
return;
}
entry = perf + headerlen;
if (use_straps)
entry += (nv_rd32(dev, NV_PEXTDEV_BOOT_0) & 0x3c) >> 1;
sprintf(pm->perflvl[0].name, "performance_level_0");
pm->perflvl[0].memory = ROM16(entry[0]) * 20;
pm->nr_perflvl = 1;
}
void
nouveau_perf_init(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
struct nvbios *bios = &dev_priv->vbios;
struct bit_entry P;
u8 version, headerlen, recordlen, entries;
u8 *perf, *entry;
int vid, i;
if (bios->type == NVBIOS_BIT) {
if (bit_table(dev, 'P', &P))
return;
if (P.version != 1 && P.version != 2) {
NV_WARN(dev, "unknown perf for BIT P %d\n", P.version);
return;
}
perf = ROMPTR(bios, P.data[0]);
version = perf[0];
headerlen = perf[1];
if (version < 0x40) {
recordlen = perf[3] + (perf[4] * perf[5]);
entries = perf[2];
} else {
recordlen = perf[2] + (perf[3] * perf[4]);
entries = perf[5];
}
} else {
if (bios->data[bios->offset + 6] < 0x25) {
legacy_perf_init(dev);
return;
}
perf = ROMPTR(bios, bios->data[bios->offset + 0x94]);
if (!perf) {
NV_DEBUG(dev, "perf table pointer invalid\n");
return;
}
version = perf[1];
headerlen = perf[0];
recordlen = perf[3];
entries = perf[2];
}
entry = perf + headerlen;
for (i = 0; i < entries; i++) {
struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl];
if (entry[0] == 0xff) {
entry += recordlen;
continue;
}
switch (version) {
case 0x12:
case 0x13:
case 0x15:
perflvl->fanspeed = entry[55];
perflvl->voltage = entry[56];
perflvl->core = ROM32(entry[1]) * 10;
perflvl->memory = ROM32(entry[5]) * 20;
break;
case 0x21:
case 0x23:
case 0x24:
perflvl->fanspeed = entry[4];
perflvl->voltage = entry[5];
perflvl->core = ROM16(entry[6]) * 1000;
if (dev_priv->chipset == 0x49 ||
dev_priv->chipset == 0x4b)
perflvl->memory = ROM16(entry[11]) * 1000;
else
perflvl->memory = ROM16(entry[11]) * 2000;
break;
case 0x25:
perflvl->fanspeed = entry[4];
perflvl->voltage = entry[5];
perflvl->core = ROM16(entry[6]) * 1000;
perflvl->shader = ROM16(entry[10]) * 1000;
perflvl->memory = ROM16(entry[12]) * 1000;
break;
case 0x30:
perflvl->memscript = ROM16(entry[2]);
case 0x35:
perflvl->fanspeed = entry[6];
perflvl->voltage = entry[7];
perflvl->core = ROM16(entry[8]) * 1000;
perflvl->shader = ROM16(entry[10]) * 1000;
perflvl->memory = ROM16(entry[12]) * 1000;
/*XXX: confirm on 0x35 */
perflvl->unk05 = ROM16(entry[16]) * 1000;
break;
case 0x40:
#define subent(n) entry[perf[2] + ((n) * perf[3])]
perflvl->fanspeed = 0; /*XXX*/
perflvl->voltage = entry[2];
perflvl->core = (ROM16(subent(0)) & 0xfff) * 1000;
perflvl->shader = (ROM16(subent(1)) & 0xfff) * 1000;
perflvl->memory = (ROM16(subent(2)) & 0xfff) * 1000;
break;
}
/* make sure vid is valid */
if (pm->voltage.supported && perflvl->voltage) {
vid = nouveau_volt_vid_lookup(dev, perflvl->voltage);
if (vid < 0) {
NV_DEBUG(dev, "drop perflvl %d, bad vid\n", i);
entry += recordlen;
continue;
}
}
snprintf(perflvl->name, sizeof(perflvl->name),
"performance_level_%d", i);
perflvl->id = i;
pm->nr_perflvl++;
entry += recordlen;
}
}
void
nouveau_perf_fini(struct drm_device *dev)
{
}
This diff is collapsed.
/*
* Copyright 2010 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#ifndef __NOUVEAU_PM_H__
#define __NOUVEAU_PM_H__
/* nouveau_pm.c */
int nouveau_pm_init(struct drm_device *dev);
void nouveau_pm_fini(struct drm_device *dev);
void nouveau_pm_resume(struct drm_device *dev);
/* nouveau_volt.c */
void nouveau_volt_init(struct drm_device *);
void nouveau_volt_fini(struct drm_device *);
int nouveau_volt_vid_lookup(struct drm_device *, int voltage);
int nouveau_volt_lvl_lookup(struct drm_device *, int vid);
int nouveau_voltage_gpio_get(struct drm_device *);
int nouveau_voltage_gpio_set(struct drm_device *, int voltage);
/* nouveau_perf.c */
void nouveau_perf_init(struct drm_device *);
void nouveau_perf_fini(struct drm_device *);
/* nouveau_mem.c */
void nouveau_mem_timing_init(struct drm_device *);
void nouveau_mem_timing_fini(struct drm_device *);
/* nv04_pm.c */
int nv04_pm_clock_get(struct drm_device *, u32 id);
void *nv04_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *,
u32 id, int khz);
void nv04_pm_clock_set(struct drm_device *, void *);
/* nv50_pm.c */
int nv50_pm_clock_get(struct drm_device *, u32 id);
void *nv50_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *,
u32 id, int khz);
void nv50_pm_clock_set(struct drm_device *, void *);
/* nva3_pm.c */
int nva3_pm_clock_get(struct drm_device *, u32 id);
void *nva3_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *,
u32 id, int khz);
void nva3_pm_clock_set(struct drm_device *, void *);
/* nouveau_temp.c */
void nouveau_temp_init(struct drm_device *dev);
void nouveau_temp_fini(struct drm_device *dev);
void nouveau_temp_safety_checks(struct drm_device *dev);
int nv40_temp_get(struct drm_device *dev);
int nv84_temp_get(struct drm_device *dev);
#endif
/*
* Copyright 2010 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include "drmP.h"
#include "nouveau_drv.h"
#include "nouveau_ramht.h"
static u32
nouveau_ramht_hash_handle(struct nouveau_channel *chan, u32 handle)
{
struct drm_device *dev = chan->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_ramht *ramht = chan->ramht;
u32 hash = 0;
int i;
NV_DEBUG(dev, "ch%d handle=0x%08x\n", chan->id, handle);
for (i = 32; i > 0; i -= ramht->bits) {
hash ^= (handle & ((1 << ramht->bits) - 1));
handle >>= ramht->bits;
}
if (dev_priv->card_type < NV_50)
hash ^= chan->id << (ramht->bits - 4);
hash <<= 3;
NV_DEBUG(dev, "hash=0x%08x\n", hash);
return hash;
}
static int
nouveau_ramht_entry_valid(struct drm_device *dev, struct nouveau_gpuobj *ramht,
u32 offset)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
u32 ctx = nv_ro32(ramht, offset + 4);
if (dev_priv->card_type < NV_40)
return ((ctx & NV_RAMHT_CONTEXT_VALID) != 0);
return (ctx != 0);
}
static int
nouveau_ramht_entry_same_channel(struct nouveau_channel *chan,
struct nouveau_gpuobj *ramht, u32 offset)
{
struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
u32 ctx = nv_ro32(ramht, offset + 4);
if (dev_priv->card_type >= NV_50)
return true;
else if (dev_priv->card_type >= NV_40)
return chan->id ==
((ctx >> NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) & 0x1f);
else
return chan->id ==
((ctx >> NV_RAMHT_CONTEXT_CHANNEL_SHIFT) & 0x1f);
}
int
nouveau_ramht_insert(struct nouveau_channel *chan, u32 handle,
struct nouveau_gpuobj *gpuobj)
{
struct drm_device *dev = chan->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem;
struct nouveau_ramht_entry *entry;
struct nouveau_gpuobj *ramht = chan->ramht->gpuobj;
unsigned long flags;
u32 ctx, co, ho;
if (nouveau_ramht_find(chan, handle))
return -EEXIST;
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
return -ENOMEM;
entry->channel = chan;
entry->gpuobj = NULL;
entry->handle = handle;
nouveau_gpuobj_ref(gpuobj, &entry->gpuobj);
if (dev_priv->card_type < NV_40) {
ctx = NV_RAMHT_CONTEXT_VALID | (gpuobj->cinst >> 4) |
(chan->id << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) |
(gpuobj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT);
} else
if (dev_priv->card_type < NV_50) {
ctx = (gpuobj->cinst >> 4) |
(chan->id << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) |
(gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT);
} else {
if (gpuobj->engine == NVOBJ_ENGINE_DISPLAY) {
ctx = (gpuobj->cinst << 10) | 2;
} else {
ctx = (gpuobj->cinst >> 4) |
((gpuobj->engine <<
NV40_RAMHT_CONTEXT_ENGINE_SHIFT));
}
}
spin_lock_irqsave(&chan->ramht->lock, flags);
list_add(&entry->head, &chan->ramht->entries);
co = ho = nouveau_ramht_hash_handle(chan, handle);
do {
if (!nouveau_ramht_entry_valid(dev, ramht, co)) {
NV_DEBUG(dev,
"insert ch%d 0x%08x: h=0x%08x, c=0x%08x\n",
chan->id, co, handle, ctx);
nv_wo32(ramht, co + 0, handle);
nv_wo32(ramht, co + 4, ctx);
spin_unlock_irqrestore(&chan->ramht->lock, flags);
instmem->flush(dev);
return 0;
}
NV_DEBUG(dev, "collision ch%d 0x%08x: h=0x%08x\n",
chan->id, co, nv_ro32(ramht, co));
co += 8;
if (co >= ramht->size)
co = 0;
} while (co != ho);
NV_ERROR(dev, "RAMHT space exhausted. ch=%d\n", chan->id);
list_del(&entry->head);
spin_unlock_irqrestore(&chan->ramht->lock, flags);
kfree(entry);
return -ENOMEM;
}
static void
nouveau_ramht_remove_locked(struct nouveau_channel *chan, u32 handle)
{
struct drm_device *dev = chan->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem;
struct nouveau_gpuobj *ramht = chan->ramht->gpuobj;
struct nouveau_ramht_entry *entry, *tmp;
u32 co, ho;
list_for_each_entry_safe(entry, tmp, &chan->ramht->entries, head) {
if (entry->channel != chan || entry->handle != handle)
continue;
nouveau_gpuobj_ref(NULL, &entry->gpuobj);
list_del(&entry->head);
kfree(entry);
break;
}
co = ho = nouveau_ramht_hash_handle(chan, handle);
do {
if (nouveau_ramht_entry_valid(dev, ramht, co) &&
nouveau_ramht_entry_same_channel(chan, ramht, co) &&
(handle == nv_ro32(ramht, co))) {
NV_DEBUG(dev,
"remove ch%d 0x%08x: h=0x%08x, c=0x%08x\n",
chan->id, co, handle, nv_ro32(ramht, co + 4));
nv_wo32(ramht, co + 0, 0x00000000);
nv_wo32(ramht, co + 4, 0x00000000);
instmem->flush(dev);
return;
}
co += 8;
if (co >= ramht->size)
co = 0;
} while (co != ho);
NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n",
chan->id, handle);
}
void
nouveau_ramht_remove(struct nouveau_channel *chan, u32 handle)
{
struct nouveau_ramht *ramht = chan->ramht;
unsigned long flags;
spin_lock_irqsave(&ramht->lock, flags);
nouveau_ramht_remove_locked(chan, handle);
spin_unlock_irqrestore(&ramht->lock, flags);
}
struct nouveau_gpuobj *
nouveau_ramht_find(struct nouveau_channel *chan, u32 handle)
{
struct nouveau_ramht *ramht = chan->ramht;
struct nouveau_ramht_entry *entry;
struct nouveau_gpuobj *gpuobj = NULL;
unsigned long flags;
if (unlikely(!chan->ramht))
return NULL;
spin_lock_irqsave(&ramht->lock, flags);
list_for_each_entry(entry, &chan->ramht->entries, head) {
if (entry->channel == chan && entry->handle == handle) {
gpuobj = entry->gpuobj;
break;
}
}
spin_unlock_irqrestore(&ramht->lock, flags);
return gpuobj;
}
int
nouveau_ramht_new(struct drm_device *dev, struct nouveau_gpuobj *gpuobj,
struct nouveau_ramht **pramht)
{
struct nouveau_ramht *ramht;
ramht = kzalloc(sizeof(*ramht), GFP_KERNEL);
if (!ramht)
return -ENOMEM;
ramht->dev = dev;
kref_init(&ramht->refcount);
ramht->bits = drm_order(gpuobj->size / 8);
INIT_LIST_HEAD(&ramht->entries);
spin_lock_init(&ramht->lock);
nouveau_gpuobj_ref(gpuobj, &ramht->gpuobj);
*pramht = ramht;
return 0;
}
static void
nouveau_ramht_del(struct kref *ref)
{
struct nouveau_ramht *ramht =
container_of(ref, struct nouveau_ramht, refcount);
nouveau_gpuobj_ref(NULL, &ramht->gpuobj);
kfree(ramht);
}
void
nouveau_ramht_ref(struct nouveau_ramht *ref, struct nouveau_ramht **ptr,
struct nouveau_channel *chan)
{
struct nouveau_ramht_entry *entry, *tmp;
struct nouveau_ramht *ramht;
unsigned long flags;
if (ref)
kref_get(&ref->refcount);
ramht = *ptr;
if (ramht) {
spin_lock_irqsave(&ramht->lock, flags);
list_for_each_entry_safe(entry, tmp, &ramht->entries, head) {
if (entry->channel != chan)
continue;
nouveau_ramht_remove_locked(chan, entry->handle);
}
spin_unlock_irqrestore(&ramht->lock, flags);
kref_put(&ramht->refcount, nouveau_ramht_del);
}
*ptr = ref;
}
/*
* Copyright 2010 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#ifndef __NOUVEAU_RAMHT_H__
#define __NOUVEAU_RAMHT_H__
struct nouveau_ramht_entry {
struct list_head head;
struct nouveau_channel *channel;
struct nouveau_gpuobj *gpuobj;
u32 handle;
};
struct nouveau_ramht {
struct drm_device *dev;
struct kref refcount;
spinlock_t lock;
struct nouveau_gpuobj *gpuobj;
struct list_head entries;
int bits;
};
extern int nouveau_ramht_new(struct drm_device *, struct nouveau_gpuobj *,
struct nouveau_ramht **);
extern void nouveau_ramht_ref(struct nouveau_ramht *, struct nouveau_ramht **,
struct nouveau_channel *unref_channel);
extern int nouveau_ramht_insert(struct nouveau_channel *, u32 handle,
struct nouveau_gpuobj *);
extern void nouveau_ramht_remove(struct nouveau_channel *, u32 handle);
extern struct nouveau_gpuobj *
nouveau_ramht_find(struct nouveau_channel *chan, u32 handle);
#endif
...@@ -551,6 +551,8 @@ ...@@ -551,6 +551,8 @@
#define NV10_PFIFO_CACHE1_DMA_SUBROUTINE 0x0000324C #define NV10_PFIFO_CACHE1_DMA_SUBROUTINE 0x0000324C
#define NV03_PFIFO_CACHE1_PULL0 0x00003240 #define NV03_PFIFO_CACHE1_PULL0 0x00003240
#define NV04_PFIFO_CACHE1_PULL0 0x00003250 #define NV04_PFIFO_CACHE1_PULL0 0x00003250
# define NV04_PFIFO_CACHE1_PULL0_HASH_FAILED 0x00000010
# define NV04_PFIFO_CACHE1_PULL0_HASH_BUSY 0x00001000
#define NV03_PFIFO_CACHE1_PULL1 0x00003250 #define NV03_PFIFO_CACHE1_PULL1 0x00003250
#define NV04_PFIFO_CACHE1_PULL1 0x00003254 #define NV04_PFIFO_CACHE1_PULL1 0x00003254
#define NV04_PFIFO_CACHE1_HASH 0x00003258 #define NV04_PFIFO_CACHE1_HASH 0x00003258
...@@ -785,15 +787,12 @@ ...@@ -785,15 +787,12 @@
#define NV50_PDISPLAY_DAC_MODE_CTRL_C(i) (0x00610b5c + (i) * 0x8) #define NV50_PDISPLAY_DAC_MODE_CTRL_C(i) (0x00610b5c + (i) * 0x8)
#define NV50_PDISPLAY_SOR_MODE_CTRL_P(i) (0x00610b70 + (i) * 0x8) #define NV50_PDISPLAY_SOR_MODE_CTRL_P(i) (0x00610b70 + (i) * 0x8)
#define NV50_PDISPLAY_SOR_MODE_CTRL_C(i) (0x00610b74 + (i) * 0x8) #define NV50_PDISPLAY_SOR_MODE_CTRL_C(i) (0x00610b74 + (i) * 0x8)
#define NV50_PDISPLAY_EXT_MODE_CTRL_P(i) (0x00610b80 + (i) * 0x8)
#define NV50_PDISPLAY_EXT_MODE_CTRL_C(i) (0x00610b84 + (i) * 0x8)
#define NV50_PDISPLAY_DAC_MODE_CTRL2_P(i) (0x00610bdc + (i) * 0x8) #define NV50_PDISPLAY_DAC_MODE_CTRL2_P(i) (0x00610bdc + (i) * 0x8)
#define NV50_PDISPLAY_DAC_MODE_CTRL2_C(i) (0x00610be0 + (i) * 0x8) #define NV50_PDISPLAY_DAC_MODE_CTRL2_C(i) (0x00610be0 + (i) * 0x8)
#define NV90_PDISPLAY_SOR_MODE_CTRL_P(i) (0x00610794 + (i) * 0x8) #define NV90_PDISPLAY_SOR_MODE_CTRL_P(i) (0x00610794 + (i) * 0x8)
#define NV90_PDISPLAY_SOR_MODE_CTRL_C(i) (0x00610798 + (i) * 0x8) #define NV90_PDISPLAY_SOR_MODE_CTRL_C(i) (0x00610798 + (i) * 0x8)
#define NV90_PDISPLAY_DAC_MODE_CTRL_P(i) (0x00610b58 + (i) * 0x8)
#define NV90_PDISPLAY_DAC_MODE_CTRL_C(i) (0x00610b5c + (i) * 0x8)
#define NV90_PDISPLAY_DAC_MODE_CTRL2_P(i) (0x00610b80 + (i) * 0x8)
#define NV90_PDISPLAY_DAC_MODE_CTRL2_C(i) (0x00610b84 + (i) * 0x8)
#define NV50_PDISPLAY_CRTC_CLK 0x00614000 #define NV50_PDISPLAY_CRTC_CLK 0x00614000
#define NV50_PDISPLAY_CRTC_CLK_CTRL1(i) ((i) * 0x800 + 0x614100) #define NV50_PDISPLAY_CRTC_CLK_CTRL1(i) ((i) * 0x800 + 0x614100)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -109,7 +109,7 @@ static void nv_crtc_calc_state_ext(struct drm_crtc *crtc, struct drm_display_mod ...@@ -109,7 +109,7 @@ static void nv_crtc_calc_state_ext(struct drm_crtc *crtc, struct drm_display_mod
struct nouveau_pll_vals *pv = &regp->pllvals; struct nouveau_pll_vals *pv = &regp->pllvals;
struct pll_lims pll_lim; struct pll_lims pll_lim;
if (get_pll_limits(dev, nv_crtc->index ? VPLL2 : VPLL1, &pll_lim)) if (get_pll_limits(dev, nv_crtc->index ? PLL_VPLL1 : PLL_VPLL0, &pll_lim))
return; return;
/* NM2 == 0 is used to determine single stage mode on two stage plls */ /* NM2 == 0 is used to determine single stage mode on two stage plls */
...@@ -718,6 +718,7 @@ static void nv_crtc_destroy(struct drm_crtc *crtc) ...@@ -718,6 +718,7 @@ static void nv_crtc_destroy(struct drm_crtc *crtc)
drm_crtc_cleanup(crtc); drm_crtc_cleanup(crtc);
nouveau_bo_unmap(nv_crtc->cursor.nvbo);
nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
kfree(nv_crtc); kfree(nv_crtc);
} }
...@@ -826,7 +827,7 @@ nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, ...@@ -826,7 +827,7 @@ nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FF_INDEX); crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FF_INDEX);
crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FFLWM__INDEX); crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FFLWM__INDEX);
if (dev_priv->card_type >= NV_30) { if (dev_priv->card_type >= NV_20) {
regp->CRTC[NV_CIO_CRE_47] = arb_lwm >> 8; regp->CRTC[NV_CIO_CRE_47] = arb_lwm >> 8;
crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_47); crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_47);
} }
......
...@@ -291,6 +291,8 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) ...@@ -291,6 +291,8 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder)
msleep(5); msleep(5);
sample = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset); sample = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset);
/* do it again just in case it's a residual current */
sample &= NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset);
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,
...@@ -343,22 +345,13 @@ static void nv04_dac_prepare(struct drm_encoder *encoder) ...@@ -343,22 +345,13 @@ static void nv04_dac_prepare(struct drm_encoder *encoder)
{ {
struct drm_encoder_helper_funcs *helper = encoder->helper_private; struct drm_encoder_helper_funcs *helper = encoder->helper_private;
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
int head = nouveau_crtc(encoder->crtc)->index; int head = nouveau_crtc(encoder->crtc)->index;
struct nv04_crtc_reg *crtcstate = dev_priv->mode_reg.crtc_reg;
helper->dpms(encoder, DRM_MODE_DPMS_OFF); helper->dpms(encoder, DRM_MODE_DPMS_OFF);
nv04_dfp_disable(dev, head); nv04_dfp_disable(dev, head);
/* Some NV4x have unknown values (0x3f, 0x50, 0x54, 0x6b, 0x79, 0x7f)
* at LCD__INDEX which we don't alter
*/
if (!(crtcstate[head].CRTC[NV_CIO_CRE_LCD__INDEX] & 0x44))
crtcstate[head].CRTC[NV_CIO_CRE_LCD__INDEX] = 0;
} }
static void nv04_dac_mode_set(struct drm_encoder *encoder, static void nv04_dac_mode_set(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)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -803,7 +803,7 @@ nv10_graph_context_switch(struct drm_device *dev) ...@@ -803,7 +803,7 @@ nv10_graph_context_switch(struct drm_device *dev)
/* Load context for next channel */ /* Load context for next channel */
chid = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f; chid = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f;
chan = dev_priv->fifos[chid]; chan = dev_priv->fifos[chid];
if (chan) if (chan && chan->pgraph_ctx)
nv10_graph_load_context(chan); nv10_graph_load_context(chan);
pgraph->fifo_access(dev, true); pgraph->fifo_access(dev, true);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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