mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-31 00:17:44 +00:00
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:
commit
0007fa2416
17 changed files with 123 additions and 65 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue