Merge branch 'drm-nouveau-fixes' of git://git.freedesktop.org/git/nouveau/linux-2...
authorDave Airlie <airlied@redhat.com>
Fri, 11 Nov 2011 11:17:43 +0000 (11:17 +0000)
committerDave Airlie <airlied@redhat.com>
Fri, 11 Nov 2011 11:17:43 +0000 (11:17 +0000)
* '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

17 files changed:
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/nouveau/nouveau_bios.c
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_channel.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_fbcon.c
drivers/gpu/drm/nouveau/nouveau_fence.c
drivers/gpu/drm/nouveau/nouveau_i2c.c
drivers/gpu/drm/nouveau/nouveau_perf.c
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/nouveau/nv40_pm.c
drivers/gpu/drm/nouveau/nv50_graph.c
drivers/gpu/drm/nouveau/nv50_grctx.c
drivers/gpu/drm/nouveau/nv50_vram.c
drivers/gpu/drm/nouveau/nvc0_graph.c
drivers/gpu/drm/nouveau/nvc0_grctx.c
drivers/gpu/drm/nouveau/nvc0_vram.c

index aa3ac01..68b7562 100644 (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;
index 032a820..5fc201b 100644 (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;
 }
 
index 7226f41..7cc37e6 100644 (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
index a319d56..bb6ec9e 100644 (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);
index e0d275e..cea6696 100644 (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);
index 14a8627..3a4cc32 100644 (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;
 }
 
index 81116cf..2f6daae 100644 (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;
 }
index c6143df..d39b220 100644 (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);
index 9f178aa..33d03fb 100644 (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;
                }
index 82478e0..d8831ab 100644 (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;
index bbc0b9c..e676b0d 100644 (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)))
index 8c979b3..ac601f7 100644 (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 */
index d05c2c3..4b46d69 100644 (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:
index 9da2383..2e45e57 100644 (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;
index bbdbc51..a74e501 100644 (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;
+                       }
                }
        }
 
index dd0e6a7..96b0b93 100644 (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;
-
-                       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);
                }
        }
 
index edbfe93..ce984d5 100644 (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;
        }