Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
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
This commit is contained in:
Коммит
007b703b3e
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче