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. * Wake up any waiters so they don't hang.
*/ */
spin_lock_irqsave(&dev->vbl_lock, irqflags); if (dev->num_crtcs) {
for (i = 0; i < dev->num_crtcs; i++) { spin_lock_irqsave(&dev->vbl_lock, irqflags);
DRM_WAKEUP(&dev->vbl_queue[i]); for (i = 0; i < dev->num_crtcs; i++) {
dev->vblank_enabled[i] = 0; DRM_WAKEUP(&dev->vbl_queue[i]);
dev->last_vblank[i] = dev->driver->get_vblank_counter(dev, 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) if (!irq_enabled)
return -EINVAL; return -EINVAL;

View File

@ -640,10 +640,9 @@ static int
nv50_pll_set(struct drm_device *dev, uint32_t reg, uint32_t clk) nv50_pll_set(struct drm_device *dev, uint32_t reg, uint32_t clk)
{ {
struct drm_nouveau_private *dev_priv = dev->dev_private; 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 nouveau_pll_vals pll;
struct pll_lims pll_limits; struct pll_lims pll_limits;
u32 ctrl, mask, coef;
int ret; int ret;
ret = get_pll_limits(dev, reg, &pll_limits); 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) if (!clk)
return -ERANGE; return -ERANGE;
reg0 = (reg0 & 0xfff8ffff) | (pll.log2P << 16); coef = pll.N1 << 8 | pll.M1;
reg1 = (reg1 & 0xffff0000) | (pll.N1 << 8) | pll.M1; ctrl = pll.log2P << 16;
mask = 0x00070000;
if (dev_priv->vbios.execute) { if (reg == 0x004008) {
still_alive(); mask |= 0x01f80000;
nv_wr32(dev, reg + 4, reg1); ctrl |= (pll_limits.log2p_bias << 19);
nv_wr32(dev, reg + 0, reg0); 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; 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 && if (dev_priv->card_type == NV_10 &&
nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM) && 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 * Make sure that the color and depth buffers are handled
* by independent memory controller units. Up to a 9x * 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.vbl_wait);
INIT_LIST_HEAD(&chan->nvsw.flip); INIT_LIST_HEAD(&chan->nvsw.flip);
INIT_LIST_HEAD(&chan->fence.pending); INIT_LIST_HEAD(&chan->fence.pending);
spin_lock_init(&chan->fence.lock);
/* setup channel's memory and vm */ /* setup channel's memory and vm */
ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle); 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: case OUTPUT_DP:
max_clock = nv_encoder->dp.link_nr; max_clock = nv_encoder->dp.link_nr;
max_clock *= nv_encoder->dp.link_bw; max_clock *= nv_encoder->dp.link_bw;
clock = clock * nouveau_connector_bpp(connector) / 8; clock = clock * nouveau_connector_bpp(connector) / 10;
break; break;
default: default:
BUG_ON(1); 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 drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_fbdev *nfbdev; struct nouveau_fbdev *nfbdev;
int preferred_bpp;
int ret; int ret;
nfbdev = kzalloc(sizeof(struct nouveau_fbdev), GFP_KERNEL); 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_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; return 0;
} }

View File

@ -539,8 +539,6 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)
return ret; return ret;
} }
INIT_LIST_HEAD(&chan->fence.pending);
spin_lock_init(&chan->fence.lock);
atomic_set(&chan->fence.last_sequence_irq, 0); atomic_set(&chan->fence.last_sequence_irq, 0);
return 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); 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) && if (nouveau_probe_i2c_addr(i2c, info[i].addr) &&
(!match || match(i2c, &info[i]))) { (!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);

View File

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

View File

@ -579,6 +579,14 @@ nouveau_card_init(struct drm_device *dev)
if (ret) if (ret)
goto out_display_early; 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); nouveau_pm_init(dev);
ret = engine->vram.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; dev_priv->noaccel = !!nouveau_noaccel;
if (nouveau_noaccel == -1) { if (nouveau_noaccel == -1) {
switch (dev_priv->chipset) { switch (dev_priv->chipset) {
case 0xc1: /* known broken */ #if 0
case 0xc8: /* never tested */ case 0xXX: /* known broken */
NV_INFO(dev, "acceleration disabled by default, pass " NV_INFO(dev, "acceleration disabled by default, pass "
"noaccel=0 to force enable\n"); "noaccel=0 to force enable\n");
dev_priv->noaccel = true; dev_priv->noaccel = true;
break; break;
#endif
default: default:
dev_priv->noaccel = false; dev_priv->noaccel = false;
break; break;

View File

@ -57,12 +57,14 @@ read_pll_2(struct drm_device *dev, u32 reg)
int P = (ctrl & 0x00070000) >> 16; int P = (ctrl & 0x00070000) >> 16;
u32 ref = 27000, clk = 0; u32 ref = 27000, clk = 0;
if (ctrl & 0x80000000) if ((ctrl & 0x80000000) && M1) {
clk = ref * N1 / M1; clk = ref * N1 / M1;
if ((ctrl & 0x40000100) == 0x40000000) {
if (!(ctrl & 0x00000100)) { if (M2)
if (ctrl & 0x40000000) clk = clk * N2 / M2;
clk = clk * N2 / M2; else
clk = 0;
}
} }
return clk >> P; return clk >> P;
@ -177,6 +179,11 @@ nv40_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
} }
/* memory clock */ /* memory clock */
if (!perflvl->memory) {
info->mpll_ctrl = 0x00000000;
goto out;
}
ret = nv40_calc_pll(dev, 0x004020, &pll, perflvl->memory, ret = nv40_calc_pll(dev, 0x004020, &pll, perflvl->memory,
&N1, &M1, &N2, &M2, &log2P); &N1, &M1, &N2, &M2, &log2P);
if (ret < 0) if (ret < 0)
@ -264,6 +271,9 @@ nv40_pm_clocks_set(struct drm_device *dev, void *pre_state)
mdelay(5); mdelay(5);
nv_mask(dev, 0x00c040, 0x00000333, info->ctrl); nv_mask(dev, 0x00c040, 0x00000333, info->ctrl);
if (!info->mpll_ctrl)
goto resume;
/* wait for vblank start on active crtcs, disable memory access */ /* wait for vblank start on active crtcs, disable memory access */
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
if (!(crtc_mask & (1 << 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"); NV_DEBUG(dev, "\n");
/* master reset */ /* master reset */
nv_mask(dev, 0x000200, 0x00200100, 0x00000000); nv_mask(dev, 0x000200, 0x00201000, 0x00000000);
nv_mask(dev, 0x000200, 0x00200100, 0x00200100); nv_mask(dev, 0x000200, 0x00201000, 0x00201000);
nv_wr32(dev, 0x40008c, 0x00000004); /* HW_CTX_SWITCH_ENABLED */ nv_wr32(dev, 0x40008c, 0x00000004); /* HW_CTX_SWITCH_ENABLED */
/* reset/enable traps and interrupts */ /* 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); gr_def(ctx, offset + 0x1c, 0x00880000);
break; break;
case 0x86: case 0x86:
gr_def(ctx, offset + 0x1c, 0x008c0000); gr_def(ctx, offset + 0x1c, 0x018c0000);
break; break;
case 0x92: case 0x92:
case 0x96: case 0x96:

View File

@ -160,7 +160,7 @@ nv50_vram_rblock(struct drm_device *dev)
colbits = (r4 & 0x0000f000) >> 12; colbits = (r4 & 0x0000f000) >> 12;
rowbitsa = ((r4 & 0x000f0000) >> 16) + 8; rowbitsa = ((r4 & 0x000f0000) >> 16) + 8;
rowbitsb = ((r4 & 0x00f00000) >> 20) + 8; rowbitsb = ((r4 & 0x00f00000) >> 20) + 8;
banks = ((r4 & 0x01000000) ? 8 : 4); banks = 1 << (((r4 & 0x03000000) >> 24) + 2);
rowsize = parts * banks * (1 << colbits) * 8; rowsize = parts * banks * (1 << colbits) * 8;
predicted = rowsize << rowbitsa; 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_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR);
struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR];
struct drm_device *dev = chan->dev; struct drm_device *dev = chan->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
int i = 0, gpc, tp, ret; int i = 0, gpc, tp, ret;
u32 magic;
ret = nouveau_gpuobj_new(dev, chan, 0x2000, 256, NVOBJ_FLAG_VM, ret = nouveau_gpuobj_new(dev, chan, 0x2000, 256, NVOBJ_FLAG_VM,
&grch->unk408004); &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, 0x0041880c);
nv_wo32(grch->mmio, i++ * 4, 0x80000018); nv_wo32(grch->mmio, i++ * 4, 0x80000018);
magic = 0x02180000; if (dev_priv->chipset != 0xc1) {
nv_wo32(grch->mmio, i++ * 4, 0x00405830); u32 magic = 0x02180000;
nv_wo32(grch->mmio, i++ * 4, magic); nv_wo32(grch->mmio, i++ * 4, 0x00405830);
for (gpc = 0; gpc < priv->gpc_nr; gpc++) { nv_wo32(grch->mmio, i++ * 4, magic);
for (tp = 0; tp < priv->tp_nr[gpc]; tp++, magic += 0x0324) { for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
u32 reg = 0x504520 + (gpc * 0x8000) + (tp * 0x0800); for (tp = 0; tp < priv->tp_nr[gpc]; tp++) {
nv_wo32(grch->mmio, i++ * 4, reg); u32 reg = TP_UNIT(gpc, tp, 0x520);
nv_wo32(grch->mmio, i++ * 4, magic); 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 */ /* calculate first set of magics */
memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr)); memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
gpc = -1;
for (tp = 0; tp < priv->tp_total; tp++) { for (tp = 0; tp < priv->tp_total; tp++) {
do { do {
gpc = (gpc + 1) % priv->gpc_nr; gpc = (gpc + 1) % priv->gpc_nr;
@ -1861,30 +1862,26 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
if (1) { if (1) {
u32 tp_mask = 0, tp_set = 0; 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)); memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
for (gpc = 0; gpc < priv->gpc_nr; gpc++) for (gpc = 0; gpc < priv->gpc_nr; gpc++)
tp_mask |= ((1 << priv->tp_nr[gpc]) - 1) << (gpc * 8); tp_mask |= ((1 << priv->tp_nr[gpc]) - 1) << (gpc * 8);
gpc = -1; for (i = 0, gpc = -1, b = -1; i < 32; i++) {
for (i = 0, gpc = -1; i < 32; i++) { a = (i * (priv->tp_total - 1)) / 32;
int ltp = 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 { tp_set |= 1 << ((gpc * 8) + tp);
gpc = (gpc + 1) % priv->gpc_nr; }
} while (!tpnr[gpc]);
tp = priv->tp_nr[gpc] - tpnr[gpc]--;
tp_set |= 1 << ((gpc * 8) + tp); nv_wr32(dev, 0x406800 + (i * 0x20), tp_set);
nv_wr32(dev, 0x406c00 + (i * 0x20), tp_set ^ tp_mask);
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--;
} }
} }

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, 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, 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, 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, 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, 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 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 bsize = nv_rd32(dev, 0x10f20c);
u32 offset, length; u32 offset, length;
bool uniform = true; bool uniform = true;
int ret, i; int ret, part;
NV_DEBUG(dev, "0x100800: 0x%08x\n", nv_rd32(dev, 0x100800)); 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); NV_DEBUG(dev, "parts 0x%08x bcast_mem_amount 0x%08x\n", parts, bsize);
/* read amount of vram attached to each memory controller */ /* read amount of vram attached to each memory controller */
for (i = 0; i < parts; i++) { part = 0;
u32 psize = nv_rd32(dev, 0x11020c + (i * 0x1000)); while (parts) {
u32 psize = nv_rd32(dev, 0x11020c + (part++ * 0x1000));
if (psize == 0)
continue;
parts--;
if (psize != bsize) { if (psize != bsize) {
if (psize < bsize) if (psize < bsize)
bsize = psize; bsize = psize;
uniform = false; 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; dev_priv->vram_size += (u64)psize << 20;
} }