From: Dave Airlie Date: Fri, 11 Nov 2011 11:17:43 +0000 (+0000) Subject: Merge branch 'drm-nouveau-fixes' of git://git.freedesktop.org/git/nouveau/linux-2... X-Git-Tag: v3.2-rc2~24^2~6 X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=commitdiff_plain;h=0007fa2416f350621709880357d2fc50c5233984;hp=a6778e9e7fb57603f15344ceb30098a3f6b7caf4 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 --- diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index aa3ac0125d90..68b756253f9f 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -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; diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 032a82098136..5fc201b49d30 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -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; } diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 7226f419e178..7cc37e690860 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -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 diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c index a319d5646ea9..bb6ec9ef8676 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c @@ -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); diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index e0d275e1c96c..cea6696b1906 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -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); diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 14a8627efe4d..3a4cc32b9e44 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -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; } diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 81116cfea275..2f6daae68b9d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -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; } diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c index c6143df48b9f..d39b2202b197 100644 --- a/drivers/gpu/drm/nouveau/nouveau_i2c.c +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c @@ -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); diff --git a/drivers/gpu/drm/nouveau/nouveau_perf.c b/drivers/gpu/drm/nouveau/nouveau_perf.c index 9f178aa94162..33d03fbf00df 100644 --- a/drivers/gpu/drm/nouveau/nouveau_perf.c +++ b/drivers/gpu/drm/nouveau/nouveau_perf.c @@ -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; } diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 82478e0998e5..d8831ab42bb9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -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; diff --git a/drivers/gpu/drm/nouveau/nv40_pm.c b/drivers/gpu/drm/nouveau/nv40_pm.c index bbc0b9c7e1f7..e676b0d53478 100644 --- a/drivers/gpu/drm/nouveau/nv40_pm.c +++ b/drivers/gpu/drm/nouveau/nv40_pm.c @@ -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))) diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c index 8c979b31ff61..ac601f7c4e1a 100644 --- a/drivers/gpu/drm/nouveau/nv50_graph.c +++ b/drivers/gpu/drm/nouveau/nv50_graph.c @@ -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 */ diff --git a/drivers/gpu/drm/nouveau/nv50_grctx.c b/drivers/gpu/drm/nouveau/nv50_grctx.c index d05c2c3b2444..4b46d6968566 100644 --- a/drivers/gpu/drm/nouveau/nv50_grctx.c +++ b/drivers/gpu/drm/nouveau/nv50_grctx.c @@ -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: diff --git a/drivers/gpu/drm/nouveau/nv50_vram.c b/drivers/gpu/drm/nouveau/nv50_vram.c index 9da23838e63e..2e45e57fd869 100644 --- a/drivers/gpu/drm/nouveau/nv50_vram.c +++ b/drivers/gpu/drm/nouveau/nv50_vram.c @@ -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; diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c index bbdbc51830c8..a74e501afd25 100644 --- a/drivers/gpu/drm/nouveau/nvc0_graph.c +++ b/drivers/gpu/drm/nouveau/nvc0_graph.c @@ -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; + } } } diff --git a/drivers/gpu/drm/nouveau/nvc0_grctx.c b/drivers/gpu/drm/nouveau/nvc0_grctx.c index dd0e6a736b3b..96b0b93d94ca 100644 --- a/drivers/gpu/drm/nouveau/nvc0_grctx.c +++ b/drivers/gpu/drm/nouveau/nvc0_grctx.c @@ -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; - - do { - gpc = (gpc + 1) % priv->gpc_nr; - } while (!tpnr[gpc]); - tp = priv->tp_nr[gpc] - tpnr[gpc]--; + 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]--; - 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); } } diff --git a/drivers/gpu/drm/nouveau/nvc0_vram.c b/drivers/gpu/drm/nouveau/nvc0_vram.c index edbfe9360ae2..ce984d573a51 100644 --- a/drivers/gpu/drm/nouveau/nvc0_vram.c +++ b/drivers/gpu/drm/nouveau/nvc0_vram.c @@ -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; }