Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 21 May 2013 15:50:09 +0000 (08:50 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 21 May 2013 15:50:09 +0000 (08:50 -0700)
Pull DRM fixes from Dave Airlie:
 "This is just a set of nouveau and radeon fixes, the nouveau ones fix
  some suspend/resume regressions since use of copy engines and some
  fixes for Z compression on some newer chipsets."

* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux:
  drm/radeon/dce2: use 10khz units for audio dto calculation
  drm/radeon: Fix VRAM size calculation for VRAM >= 4GB
  drm/radeon: Remove superfluous variable
  drm/nouveau: ensure channels are stopped before saving fences for suspend
  drm/nv50/fifo: prevent races between clients updating playlists
  drm/nvc0/fifo: prevent CHAN_TABLE_ERROR:CHANNEL_PENDING on fifo fini
  drm/nvc0/fifo: prevent races between clients updating playlists
  drm/nve0/fifo: prevent races between clients updating playlists
  drm/nve0/ltcg: poke the partition count into yet another register
  drm/nvc0/ltcg: fix handling of disabled partitions
  drm/nvc0/ce: disable ce1 on a number of chipsets
  drm/nouveau/bios: fix thinko in ZM_MASK_ADD opcode
  drm/nouveau: fix build with nv50->nvc0

15 files changed:
drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c
drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
drivers/gpu/drm/nouveau/core/subdev/bios/init.c
drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreen_hdmi.c
drivers/gpu/drm/radeon/r600_hdmi.c
drivers/gpu/drm/radeon/radeon_legacy_crtc.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/radeon/radeon_ttm.c
drivers/gpu/drm/radeon/si.c

index 955af12..a36e64e 100644 (file)
@@ -138,7 +138,6 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_BSP    ] = &nvc0_bsp_oclass;
                device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nvc0_copy0_oclass;
-               device->oclass[NVDEV_ENGINE_COPY1  ] = &nvc0_copy1_oclass;
                device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass;
                break;
        case 0xce:
@@ -225,7 +224,6 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_BSP    ] = &nvc0_bsp_oclass;
                device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nvc0_copy0_oclass;
-               device->oclass[NVDEV_ENGINE_COPY1  ] = &nvc0_copy1_oclass;
                device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass;
                break;
        case 0xc8:
index ddaeb55..89bf459 100644 (file)
@@ -47,6 +47,7 @@ nv50_fifo_playlist_update(struct nv50_fifo_priv *priv)
        struct nouveau_gpuobj *cur;
        int i, p;
 
+       mutex_lock(&nv_subdev(priv)->mutex);
        cur = priv->playlist[priv->cur_playlist];
        priv->cur_playlist = !priv->cur_playlist;
 
@@ -60,6 +61,7 @@ nv50_fifo_playlist_update(struct nv50_fifo_priv *priv)
        nv_wr32(priv, 0x0032f4, cur->addr >> 12);
        nv_wr32(priv, 0x0032ec, p);
        nv_wr32(priv, 0x002500, 0x00000101);
+       mutex_unlock(&nv_subdev(priv)->mutex);
 }
 
 static int
index 4d4a6b9..46dfa68 100644 (file)
@@ -71,6 +71,7 @@ nvc0_fifo_playlist_update(struct nvc0_fifo_priv *priv)
        struct nouveau_gpuobj *cur;
        int i, p;
 
+       mutex_lock(&nv_subdev(priv)->mutex);
        cur = priv->playlist[priv->cur_playlist];
        priv->cur_playlist = !priv->cur_playlist;
 
@@ -87,6 +88,7 @@ nvc0_fifo_playlist_update(struct nvc0_fifo_priv *priv)
        nv_wr32(priv, 0x002274, 0x01f00000 | (p >> 3));
        if (!nv_wait(priv, 0x00227c, 0x00100000, 0x00000000))
                nv_error(priv, "playlist update failed\n");
+       mutex_unlock(&nv_subdev(priv)->mutex);
 }
 
 static int
@@ -248,9 +250,17 @@ nvc0_fifo_chan_fini(struct nouveau_object *object, bool suspend)
        struct nvc0_fifo_priv *priv = (void *)object->engine;
        struct nvc0_fifo_chan *chan = (void *)object;
        u32 chid = chan->base.chid;
+       u32 mask, engine;
 
        nv_mask(priv, 0x003004 + (chid * 8), 0x00000001, 0x00000000);
        nvc0_fifo_playlist_update(priv);
+       mask = nv_rd32(priv, 0x0025a4);
+       for (engine = 0; mask && engine < 16; engine++) {
+               if (!(mask & (1 << engine)))
+                       continue;
+               nv_mask(priv, 0x0025a8 + (engine * 4), 0x00000000, 0x00000000);
+               mask &= ~(1 << engine);
+       }
        nv_wr32(priv, 0x003000 + (chid * 8), 0x00000000);
 
        return nouveau_fifo_channel_fini(&chan->base, suspend);
index 9151919..56192a7 100644 (file)
@@ -94,11 +94,13 @@ nve0_fifo_playlist_update(struct nve0_fifo_priv *priv, u32 engine)
        u32 match = (engine << 16) | 0x00000001;
        int i, p;
 
+       mutex_lock(&nv_subdev(priv)->mutex);
        cur = engn->playlist[engn->cur_playlist];
        if (unlikely(cur == NULL)) {
                int ret = nouveau_gpuobj_new(nv_object(priv), NULL,
                                             0x8000, 0x1000, 0, &cur);
                if (ret) {
+                       mutex_unlock(&nv_subdev(priv)->mutex);
                        nv_error(priv, "playlist alloc failed\n");
                        return;
                }
@@ -122,6 +124,7 @@ nve0_fifo_playlist_update(struct nve0_fifo_priv *priv, u32 engine)
        nv_wr32(priv, 0x002274, (engine << 20) | (p >> 3));
        if (!nv_wait(priv, 0x002284 + (engine * 4), 0x00100000, 0x00000000))
                nv_error(priv, "playlist %d update timeout\n", engine);
+       mutex_unlock(&nv_subdev(priv)->mutex);
 }
 
 static int
index c300b5e..c434d39 100644 (file)
@@ -1940,8 +1940,8 @@ init_zm_mask_add(struct nvbios_init *init)
        trace("ZM_MASK_ADD\tR[0x%06x] &= 0x%08x += 0x%08x\n", addr, mask, add);
        init->offset += 13;
 
-       data  =  init_rd32(init, addr) & mask;
-       data |= ((data + add) & ~mask);
+       data =  init_rd32(init, addr);
+       data = (data & mask) | ((data + add) & ~mask);
        init_wr32(init, addr, data);
 }
 
index e4940fb..fb794e9 100644 (file)
@@ -29,7 +29,6 @@
 struct nvc0_ltcg_priv {
        struct nouveau_ltcg base;
        u32 part_nr;
-       u32 part_mask;
        u32 subp_nr;
        struct nouveau_mm tags;
        u32 num_tags;
@@ -105,8 +104,6 @@ nvc0_ltcg_tags_clear(struct nouveau_ltcg *ltcg, u32 first, u32 count)
 
        /* wait until it's finished with clearing */
        for (p = 0; p < priv->part_nr; ++p) {
-               if (!(priv->part_mask & (1 << p)))
-                       continue;
                for (i = 0; i < priv->subp_nr; ++i)
                        nv_wait(priv, 0x1410c8 + p * 0x2000 + i * 0x400, ~0, 0);
        }
@@ -121,6 +118,8 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)
        int ret;
 
        nv_wr32(priv, 0x17e8d8, priv->part_nr);
+       if (nv_device(pfb)->card_type >= NV_E0)
+               nv_wr32(priv, 0x17e000, priv->part_nr);
 
        /* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */
        priv->num_tags = (pfb->ram.size >> 17) / 4;
@@ -167,16 +166,20 @@ nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 {
        struct nvc0_ltcg_priv *priv;
        struct nouveau_fb *pfb = nouveau_fb(parent);
-       int ret;
+       u32 parts, mask;
+       int ret, i;
 
        ret = nouveau_ltcg_create(parent, engine, oclass, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
 
-       priv->part_nr = nv_rd32(priv, 0x022438);
-       priv->part_mask = nv_rd32(priv, 0x022554);
-
+       parts = nv_rd32(priv, 0x022438);
+       mask = nv_rd32(priv, 0x022554);
+       for (i = 0; i < parts; i++) {
+               if (!(mask & (1 << i)))
+                       priv->part_nr++;
+       }
        priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 28;
 
        nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */
index 46c152f..383f4e6 100644 (file)
@@ -453,18 +453,32 @@ nouveau_do_suspend(struct drm_device *dev)
        NV_INFO(drm, "evicting buffers...\n");
        ttm_bo_evict_mm(&drm->ttm.bdev, TTM_PL_VRAM);
 
+       NV_INFO(drm, "waiting for kernel channels to go idle...\n");
+       if (drm->cechan) {
+               ret = nouveau_channel_idle(drm->cechan);
+               if (ret)
+                       return ret;
+       }
+
+       if (drm->channel) {
+               ret = nouveau_channel_idle(drm->channel);
+               if (ret)
+                       return ret;
+       }
+
+       NV_INFO(drm, "suspending client object trees...\n");
        if (drm->fence && nouveau_fence(drm)->suspend) {
                if (!nouveau_fence(drm)->suspend(drm))
                        return -ENOMEM;
        }
 
-       NV_INFO(drm, "suspending client object trees...\n");
        list_for_each_entry(cli, &drm->clients, head) {
                ret = nouveau_client_fini(&cli->base, true);
                if (ret)
                        goto fail_client;
        }
 
+       NV_INFO(drm, "suspending kernel object tree...\n");
        ret = nouveau_client_fini(&drm->client.base, true);
        if (ret)
                goto fail_client;
@@ -514,17 +528,18 @@ nouveau_do_resume(struct drm_device *dev)
 
        nouveau_agp_reset(drm);
 
-       NV_INFO(drm, "resuming client object trees...\n");
+       NV_INFO(drm, "resuming kernel object tree...\n");
        nouveau_client_init(&drm->client.base);
        nouveau_agp_init(drm);
 
+       NV_INFO(drm, "resuming client object trees...\n");
+       if (drm->fence && nouveau_fence(drm)->resume)
+               nouveau_fence(drm)->resume(drm);
+
        list_for_each_entry(cli, &drm->clients, head) {
                nouveau_client_init(&cli->base);
        }
 
-       if (drm->fence && nouveau_fence(drm)->resume)
-               nouveau_fence(drm)->resume(drm);
-
        nouveau_run_vbios_init(dev);
        nouveau_pm_resume(dev);
 
index 6d6fdb3..d5df8fd 100644 (file)
@@ -1811,12 +1811,9 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
 
 static void atombios_crtc_prepare(struct drm_crtc *crtc)
 {
-       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct drm_device *dev = crtc->dev;
        struct radeon_device *rdev = dev->dev_private;
 
-       radeon_crtc->in_mode_set = true;
-
        /* disable crtc pair power gating before programming */
        if (ASIC_IS_DCE6(rdev))
                atombios_powergate_crtc(crtc, ATOM_DISABLE);
@@ -1827,11 +1824,8 @@ static void atombios_crtc_prepare(struct drm_crtc *crtc)
 
 static void atombios_crtc_commit(struct drm_crtc *crtc)
 {
-       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
-
        atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
        atombios_lock_crtc(crtc, ATOM_DISABLE);
-       radeon_crtc->in_mode_set = false;
 }
 
 static void atombios_crtc_disable(struct drm_crtc *crtc)
index 105bafb..06c261b 100644 (file)
@@ -3405,8 +3405,8 @@ int evergreen_mc_init(struct radeon_device *rdev)
                rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE);
        } else {
                /* size in MB on evergreen/cayman/tn */
-               rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
-               rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
+               rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL;
+               rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL;
        }
        rdev->mc.visible_vram_size = rdev->mc.aper_size;
        r700_vram_gtt_location(rdev, &rdev->mc);
index b4ab8ce..ed7c8a7 100644 (file)
@@ -154,19 +154,18 @@ static void evergreen_audio_set_dto(struct drm_encoder *encoder, u32 clock)
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
-       u32 base_rate = 48000;
+       u32 base_rate = 24000;
 
        if (!dig || !dig->afmt)
                return;
 
-       /* XXX: properly calculate this */
        /* XXX two dtos; generally use dto0 for hdmi */
        /* Express [24MHz / target pixel clock] as an exact rational
         * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
         * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
         */
-       WREG32(DCCG_AUDIO_DTO0_PHASE, (base_rate*50) & 0xffffff);
-       WREG32(DCCG_AUDIO_DTO0_MODULE, (clock*100) & 0xffffff);
+       WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100);
+       WREG32(DCCG_AUDIO_DTO0_MODULE, clock * 100);
        WREG32(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL(radeon_crtc->crtc_id));
 }
 
index 47f180a..456750a 100644 (file)
@@ -232,7 +232,7 @@ void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-       u32 base_rate = 48000;
+       u32 base_rate = 24000;
 
        if (!dig || !dig->afmt)
                return;
@@ -240,7 +240,6 @@ void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
        /* there are two DTOs selected by DCCG_AUDIO_DTO_SELECT.
         * doesn't matter which one you use.  Just use the first one.
         */
-       /* XXX: properly calculate this */
        /* XXX two dtos; generally use dto0 for hdmi */
        /* Express [24MHz / target pixel clock] as an exact rational
         * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
@@ -250,13 +249,13 @@ void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
                /* according to the reg specs, this should DCE3.2 only, but in
                 * practice it seems to cover DCE3.0 as well.
                 */
-               WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 50);
+               WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100);
                WREG32(DCCG_AUDIO_DTO0_MODULE, clock * 100);
                WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */
        } else {
                /* according to the reg specs, this should be DCE2.0 and DCE3.0 */
-               WREG32(AUDIO_DTO, AUDIO_DTO_PHASE(base_rate * 50) |
-                      AUDIO_DTO_MODULE(clock * 100));
+               WREG32(AUDIO_DTO, AUDIO_DTO_PHASE(base_rate / 10) |
+                      AUDIO_DTO_MODULE(clock / 10));
        }
 }
 
index 6857cb4..7cb178a 100644 (file)
@@ -1031,11 +1031,9 @@ static int radeon_crtc_mode_set(struct drm_crtc *crtc,
 
 static void radeon_crtc_prepare(struct drm_crtc *crtc)
 {
-       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct drm_device *dev = crtc->dev;
        struct drm_crtc *crtci;
 
-       radeon_crtc->in_mode_set = true;
        /*
        * The hardware wedges sometimes if you reconfigure one CRTC
        * whilst another is running (see fdo bug #24611).
@@ -1046,7 +1044,6 @@ static void radeon_crtc_prepare(struct drm_crtc *crtc)
 
 static void radeon_crtc_commit(struct drm_crtc *crtc)
 {
-       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct drm_device *dev = crtc->dev;
        struct drm_crtc *crtci;
 
@@ -1057,7 +1054,6 @@ static void radeon_crtc_commit(struct drm_crtc *crtc)
                if (crtci->enabled)
                        radeon_crtc_dpms(crtci, DRM_MODE_DPMS_ON);
        }
-       radeon_crtc->in_mode_set = false;
 }
 
 static const struct drm_crtc_helper_funcs legacy_helper_funcs = {
index 44e579e..69ad4fe 100644 (file)
@@ -302,7 +302,6 @@ struct radeon_crtc {
        u16 lut_r[256], lut_g[256], lut_b[256];
        bool enabled;
        bool can_tile;
-       bool in_mode_set;
        uint32_t crtc_offset;
        struct drm_gem_object *cursor_bo;
        uint64_t cursor_addr;
index 93f760e..6c0ce89 100644 (file)
@@ -726,7 +726,7 @@ int radeon_ttm_init(struct radeon_device *rdev)
                return r;
        }
        DRM_INFO("radeon: %uM of VRAM memory ready\n",
-                (unsigned)rdev->mc.real_vram_size / (1024 * 1024));
+                (unsigned) (rdev->mc.real_vram_size / (1024 * 1024)));
        r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT,
                                rdev->mc.gtt_size >> PAGE_SHIFT);
        if (r) {
index f0b6c2f..113ed9f 100644 (file)
@@ -3397,8 +3397,8 @@ static int si_mc_init(struct radeon_device *rdev)
        rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0);
        rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0);
        /* size in MB on si */
-       rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
-       rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
+       rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL;
+       rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL;
        rdev->mc.visible_vram_size = rdev->mc.aper_size;
        si_vram_gtt_location(rdev, &rdev->mc);
        radeon_update_bandwidth_info(rdev);