Merge branch 'drm-nouveau-fixes' of git://git.freedesktop.org/git/nouveau/linux-2.6 into drm-fixes

* 'drm-nouveau-fixes' of git://git.freedesktop.org/git/nouveau/linux-2.6:
  drm/nouveau: Fix bandwidth calculation for DisplayPort
  drm/nouveau: by default use low bpp framebuffer on low memory cards
  drm/nv10: Change the BO size threshold determining the memory placement range.
  drm/nvc0: enable acceleration for nvc1 by default
  drm/nvc0/gr: fixup the mmio list register writes for 0xc1
  drm/nvc1: hacky workaround to fix accel issues
  drm/nvc0/gr: fix some bugs in grctx generation
  drm/nvc0: enable acceleration on 0xc8 by default
  drm/nvc0/vram: skip disabled PBFB subunits
  drm/nv40/pm: fix issues on igp chipsets, which don't have memory
  drm/nouveau: testing the wrong variable
  drm/nvc0/vram: storage type 0xc3 is not compressed
  drm/nv50: fix stability issue on NV86.
  drm/nouveau: initialize chan->fence.lock before use
  drm/nv50/vram: fix incorrect detection of bank count on newer chipsets
  drm/nv50/gr: typo fix, how about we not reset fifo during graph init?
  drm/nv50/bios: fixup mpll programming from the init table parser
  drm/nouveau: fix oops if i2c bus not found in nouveau_i2c_identify()
  drm: make sure drm_vblank_init() has been called before touching vbl_lock
This commit is contained in:
Dave Airlie 2011-11-11 11:17:43 +00:00
commit 0007fa2416
17 changed files with 123 additions and 65 deletions

View File

@ -407,13 +407,16 @@ int drm_irq_uninstall(struct drm_device *dev)
/*
* Wake up any waiters so they don't hang.
*/
spin_lock_irqsave(&dev->vbl_lock, irqflags);
for (i = 0; i < dev->num_crtcs; i++) {
DRM_WAKEUP(&dev->vbl_queue[i]);
dev->vblank_enabled[i] = 0;
dev->last_vblank[i] = dev->driver->get_vblank_counter(dev, i);
if (dev->num_crtcs) {
spin_lock_irqsave(&dev->vbl_lock, irqflags);
for (i = 0; i < dev->num_crtcs; i++) {
DRM_WAKEUP(&dev->vbl_queue[i]);
dev->vblank_enabled[i] = 0;
dev->last_vblank[i] =
dev->driver->get_vblank_counter(dev, i);
}
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
}
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
if (!irq_enabled)
return -EINVAL;

View File

@ -640,10 +640,9 @@ static int
nv50_pll_set(struct drm_device *dev, uint32_t reg, uint32_t clk)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
uint32_t reg0 = nv_rd32(dev, reg + 0);
uint32_t reg1 = nv_rd32(dev, reg + 4);
struct nouveau_pll_vals pll;
struct pll_lims pll_limits;
u32 ctrl, mask, coef;
int ret;
ret = get_pll_limits(dev, reg, &pll_limits);
@ -654,15 +653,20 @@ nv50_pll_set(struct drm_device *dev, uint32_t reg, uint32_t clk)
if (!clk)
return -ERANGE;
reg0 = (reg0 & 0xfff8ffff) | (pll.log2P << 16);
reg1 = (reg1 & 0xffff0000) | (pll.N1 << 8) | pll.M1;
if (dev_priv->vbios.execute) {
still_alive();
nv_wr32(dev, reg + 4, reg1);
nv_wr32(dev, reg + 0, reg0);
coef = pll.N1 << 8 | pll.M1;
ctrl = pll.log2P << 16;
mask = 0x00070000;
if (reg == 0x004008) {
mask |= 0x01f80000;
ctrl |= (pll_limits.log2p_bias << 19);
ctrl |= (pll.log2P << 22);
}
if (!dev_priv->vbios.execute)
return 0;
nv_mask(dev, reg + 0, mask, ctrl);
nv_wr32(dev, reg + 4, coef);
return 0;
}

View File

@ -148,7 +148,7 @@ set_placement_range(struct nouveau_bo *nvbo, uint32_t type)
if (dev_priv->card_type == NV_10 &&
nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM) &&
nvbo->bo.mem.num_pages < vram_pages / 2) {
nvbo->bo.mem.num_pages < vram_pages / 4) {
/*
* Make sure that the color and depth buffers are handled
* by independent memory controller units. Up to a 9x

View File

@ -158,6 +158,7 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
INIT_LIST_HEAD(&chan->nvsw.vbl_wait);
INIT_LIST_HEAD(&chan->nvsw.flip);
INIT_LIST_HEAD(&chan->fence.pending);
spin_lock_init(&chan->fence.lock);
/* setup channel's memory and vm */
ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle);

View File

@ -710,7 +710,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
case OUTPUT_DP:
max_clock = nv_encoder->dp.link_nr;
max_clock *= nv_encoder->dp.link_bw;
clock = clock * nouveau_connector_bpp(connector) / 8;
clock = clock * nouveau_connector_bpp(connector) / 10;
break;
default:
BUG_ON(1);

View File

@ -487,6 +487,7 @@ int nouveau_fbcon_init(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_fbdev *nfbdev;
int preferred_bpp;
int ret;
nfbdev = kzalloc(sizeof(struct nouveau_fbdev), GFP_KERNEL);
@ -505,7 +506,15 @@ int nouveau_fbcon_init(struct drm_device *dev)
}
drm_fb_helper_single_add_all_connectors(&nfbdev->helper);
drm_fb_helper_initial_config(&nfbdev->helper, 32);
if (dev_priv->vram_size <= 32 * 1024 * 1024)
preferred_bpp = 8;
else if (dev_priv->vram_size <= 64 * 1024 * 1024)
preferred_bpp = 16;
else
preferred_bpp = 32;
drm_fb_helper_initial_config(&nfbdev->helper, preferred_bpp);
return 0;
}

View File

@ -539,8 +539,6 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)
return ret;
}
INIT_LIST_HEAD(&chan->fence.pending);
spin_lock_init(&chan->fence.lock);
atomic_set(&chan->fence.last_sequence_irq, 0);
return 0;
}

View File

@ -333,7 +333,7 @@ nouveau_i2c_identify(struct drm_device *dev, const char *what,
NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, index);
for (i = 0; info[i].addr; i++) {
for (i = 0; i2c && info[i].addr; i++) {
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);

View File

@ -239,7 +239,7 @@ nouveau_perf_init(struct drm_device *dev)
if(version == 0x15) {
memtimings->timing =
kcalloc(entries, sizeof(*memtimings->timing), GFP_KERNEL);
if(!memtimings) {
if (!memtimings->timing) {
NV_WARN(dev,"Could not allocate memtiming table\n");
return;
}

View File

@ -579,6 +579,14 @@ nouveau_card_init(struct drm_device *dev)
if (ret)
goto out_display_early;
/* workaround an odd issue on nvc1 by disabling the device's
* nosnoop capability. hopefully won't cause issues until a
* better fix is found - assuming there is one...
*/
if (dev_priv->chipset == 0xc1) {
nv_mask(dev, 0x00088080, 0x00000800, 0x00000000);
}
nouveau_pm_init(dev);
ret = engine->vram.init(dev);
@ -1102,12 +1110,13 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
dev_priv->noaccel = !!nouveau_noaccel;
if (nouveau_noaccel == -1) {
switch (dev_priv->chipset) {
case 0xc1: /* known broken */
case 0xc8: /* never tested */
#if 0
case 0xXX: /* known broken */
NV_INFO(dev, "acceleration disabled by default, pass "
"noaccel=0 to force enable\n");
dev_priv->noaccel = true;
break;
#endif
default:
dev_priv->noaccel = false;
break;

View File

@ -57,12 +57,14 @@ read_pll_2(struct drm_device *dev, u32 reg)
int P = (ctrl & 0x00070000) >> 16;
u32 ref = 27000, clk = 0;
if (ctrl & 0x80000000)
if ((ctrl & 0x80000000) && M1) {
clk = ref * N1 / M1;
if (!(ctrl & 0x00000100)) {
if (ctrl & 0x40000000)
clk = clk * N2 / M2;
if ((ctrl & 0x40000100) == 0x40000000) {
if (M2)
clk = clk * N2 / M2;
else
clk = 0;
}
}
return clk >> P;
@ -177,6 +179,11 @@ nv40_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
}
/* memory clock */
if (!perflvl->memory) {
info->mpll_ctrl = 0x00000000;
goto out;
}
ret = nv40_calc_pll(dev, 0x004020, &pll, perflvl->memory,
&N1, &M1, &N2, &M2, &log2P);
if (ret < 0)
@ -264,6 +271,9 @@ nv40_pm_clocks_set(struct drm_device *dev, void *pre_state)
mdelay(5);
nv_mask(dev, 0x00c040, 0x00000333, info->ctrl);
if (!info->mpll_ctrl)
goto resume;
/* wait for vblank start on active crtcs, disable memory access */
for (i = 0; i < 2; i++) {
if (!(crtc_mask & (1 << i)))

View File

@ -131,8 +131,8 @@ nv50_graph_init(struct drm_device *dev, int engine)
NV_DEBUG(dev, "\n");
/* master reset */
nv_mask(dev, 0x000200, 0x00200100, 0x00000000);
nv_mask(dev, 0x000200, 0x00200100, 0x00200100);
nv_mask(dev, 0x000200, 0x00201000, 0x00000000);
nv_mask(dev, 0x000200, 0x00201000, 0x00201000);
nv_wr32(dev, 0x40008c, 0x00000004); /* HW_CTX_SWITCH_ENABLED */
/* reset/enable traps and interrupts */

View File

@ -601,7 +601,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx)
gr_def(ctx, offset + 0x1c, 0x00880000);
break;
case 0x86:
gr_def(ctx, offset + 0x1c, 0x008c0000);
gr_def(ctx, offset + 0x1c, 0x018c0000);
break;
case 0x92:
case 0x96:

View File

@ -160,7 +160,7 @@ nv50_vram_rblock(struct drm_device *dev)
colbits = (r4 & 0x0000f000) >> 12;
rowbitsa = ((r4 & 0x000f0000) >> 16) + 8;
rowbitsb = ((r4 & 0x00f00000) >> 20) + 8;
banks = ((r4 & 0x01000000) ? 8 : 4);
banks = 1 << (((r4 & 0x03000000) >> 24) + 2);
rowsize = parts * banks * (1 << colbits) * 8;
predicted = rowsize << rowbitsa;

View File

@ -157,8 +157,8 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan)
struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR);
struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR];
struct drm_device *dev = chan->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
int i = 0, gpc, tp, ret;
u32 magic;
ret = nouveau_gpuobj_new(dev, chan, 0x2000, 256, NVOBJ_FLAG_VM,
&grch->unk408004);
@ -207,14 +207,37 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan)
nv_wo32(grch->mmio, i++ * 4, 0x0041880c);
nv_wo32(grch->mmio, i++ * 4, 0x80000018);
magic = 0x02180000;
nv_wo32(grch->mmio, i++ * 4, 0x00405830);
nv_wo32(grch->mmio, i++ * 4, magic);
for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
for (tp = 0; tp < priv->tp_nr[gpc]; tp++, magic += 0x0324) {
u32 reg = 0x504520 + (gpc * 0x8000) + (tp * 0x0800);
nv_wo32(grch->mmio, i++ * 4, reg);
nv_wo32(grch->mmio, i++ * 4, magic);
if (dev_priv->chipset != 0xc1) {
u32 magic = 0x02180000;
nv_wo32(grch->mmio, i++ * 4, 0x00405830);
nv_wo32(grch->mmio, i++ * 4, magic);
for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
for (tp = 0; tp < priv->tp_nr[gpc]; tp++) {
u32 reg = TP_UNIT(gpc, tp, 0x520);
nv_wo32(grch->mmio, i++ * 4, reg);
nv_wo32(grch->mmio, i++ * 4, magic);
magic += 0x0324;
}
}
} else {
u32 magic = 0x02180000;
nv_wo32(grch->mmio, i++ * 4, 0x00405830);
nv_wo32(grch->mmio, i++ * 4, magic | 0x0000218);
nv_wo32(grch->mmio, i++ * 4, 0x004064c4);
nv_wo32(grch->mmio, i++ * 4, 0x0086ffff);
for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
for (tp = 0; tp < priv->tp_nr[gpc]; tp++) {
u32 reg = TP_UNIT(gpc, tp, 0x520);
nv_wo32(grch->mmio, i++ * 4, reg);
nv_wo32(grch->mmio, i++ * 4, (1 << 28) | magic);
magic += 0x0324;
}
for (tp = 0; tp < priv->tp_nr[gpc]; tp++) {
u32 reg = TP_UNIT(gpc, tp, 0x544);
nv_wo32(grch->mmio, i++ * 4, reg);
nv_wo32(grch->mmio, i++ * 4, magic);
magic += 0x0324;
}
}
}

View File

@ -1812,6 +1812,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
/* calculate first set of magics */
memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
gpc = -1;
for (tp = 0; tp < priv->tp_total; tp++) {
do {
gpc = (gpc + 1) % priv->gpc_nr;
@ -1861,30 +1862,26 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
if (1) {
u32 tp_mask = 0, tp_set = 0;
u8 tpnr[GPC_MAX];
u8 tpnr[GPC_MAX], a, b;
memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
for (gpc = 0; gpc < priv->gpc_nr; gpc++)
tp_mask |= ((1 << priv->tp_nr[gpc]) - 1) << (gpc * 8);
gpc = -1;
for (i = 0, gpc = -1; i < 32; i++) {
int ltp = i * (priv->tp_total - 1) / 32;
for (i = 0, gpc = -1, b = -1; i < 32; i++) {
a = (i * (priv->tp_total - 1)) / 32;
if (a != b) {
b = a;
do {
gpc = (gpc + 1) % priv->gpc_nr;
} while (!tpnr[gpc]);
tp = priv->tp_nr[gpc] - tpnr[gpc]--;
do {
gpc = (gpc + 1) % priv->gpc_nr;
} while (!tpnr[gpc]);
tp = priv->tp_nr[gpc] - tpnr[gpc]--;
tp_set |= 1 << ((gpc * 8) + tp);
}
tp_set |= 1 << ((gpc * 8) + tp);
do {
nv_wr32(dev, 0x406800 + (i * 0x20), tp_set);
tp_set ^= tp_mask;
nv_wr32(dev, 0x406c00 + (i * 0x20), tp_set);
tp_set ^= tp_mask;
} while (ltp == (++i * (priv->tp_total - 1) / 32));
i--;
nv_wr32(dev, 0x406800 + (i * 0x20), tp_set);
nv_wr32(dev, 0x406c00 + (i * 0x20), tp_set ^ tp_mask);
}
}

View File

@ -43,7 +43,7 @@ static const u8 types[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3,
3, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3,
3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 3,
3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 3, 0,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 1, 0
@ -110,22 +110,26 @@ nvc0_vram_init(struct drm_device *dev)
u32 bsize = nv_rd32(dev, 0x10f20c);
u32 offset, length;
bool uniform = true;
int ret, i;
int ret, part;
NV_DEBUG(dev, "0x100800: 0x%08x\n", nv_rd32(dev, 0x100800));
NV_DEBUG(dev, "parts 0x%08x bcast_mem_amount 0x%08x\n", parts, bsize);
/* read amount of vram attached to each memory controller */
for (i = 0; i < parts; i++) {
u32 psize = nv_rd32(dev, 0x11020c + (i * 0x1000));
part = 0;
while (parts) {
u32 psize = nv_rd32(dev, 0x11020c + (part++ * 0x1000));
if (psize == 0)
continue;
parts--;
if (psize != bsize) {
if (psize < bsize)
bsize = psize;
uniform = false;
}
NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", i, psize);
NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", part, psize);
dev_priv->vram_size += (u64)psize << 20;
}