mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 19:00:25 +00:00
Merge remote branch 'nouveau/for-airlied' of /ssd/git/drm-nouveau-next into drm-core-next
* 'nouveau/for-airlied' of /ssd/git/drm-nouveau-next: drm/nouveau: fix earlier mistake when fixing merge conflict drm/nvc0: fix thinko in instmem suspend/resume drm/nouveau: Workaround missing GPIO tables on an Apple iMac G4 NV18. drm/nouveau: Add TV-out quirk for an MSI nForce2 IGP. drm/nv50-nvc0: ramht_size is meant to be in bytes, not entries drm/nouveau: punt some more log messages to debug level drm/nouveau: remove warning about unknown tmds table revisions drm/nouveau: check for error when allocating/mapping dummy page drm/nouveau: fix race condition when under memory pressure drm/nv50: fix minor thinko from nvc0 changes drm/nouveau: Don't try DDC on the dummy I2C channel.
This commit is contained in:
commit
d03330383c
10 changed files with 103 additions and 34 deletions
|
@ -2166,7 +2166,7 @@ peek_fb(struct drm_device *dev, struct io_mapping *fb,
|
|||
uint32_t val = 0;
|
||||
|
||||
if (off < pci_resource_len(dev->pdev, 1)) {
|
||||
uint32_t __iomem *p =
|
||||
uint8_t __iomem *p =
|
||||
io_mapping_map_atomic_wc(fb, off & PAGE_MASK, KM_USER0);
|
||||
|
||||
val = ioread32(p + (off & ~PAGE_MASK));
|
||||
|
@ -2182,7 +2182,7 @@ poke_fb(struct drm_device *dev, struct io_mapping *fb,
|
|||
uint32_t off, uint32_t val)
|
||||
{
|
||||
if (off < pci_resource_len(dev->pdev, 1)) {
|
||||
uint32_t __iomem *p =
|
||||
uint8_t __iomem *p =
|
||||
io_mapping_map_atomic_wc(fb, off & PAGE_MASK, KM_USER0);
|
||||
|
||||
iowrite32(val, p + (off & ~PAGE_MASK));
|
||||
|
@ -4587,7 +4587,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
|
|||
return 1;
|
||||
}
|
||||
|
||||
NV_TRACE(dev, "0x%04X: parsing output script 0\n", script);
|
||||
NV_DEBUG_KMS(dev, "0x%04X: parsing output script 0\n", script);
|
||||
nouveau_bios_run_init_table(dev, script, dcbent);
|
||||
} else
|
||||
if (pxclk == -1) {
|
||||
|
@ -4597,7 +4597,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
|
|||
return 1;
|
||||
}
|
||||
|
||||
NV_TRACE(dev, "0x%04X: parsing output script 1\n", script);
|
||||
NV_DEBUG_KMS(dev, "0x%04X: parsing output script 1\n", script);
|
||||
nouveau_bios_run_init_table(dev, script, dcbent);
|
||||
} else
|
||||
if (pxclk == -2) {
|
||||
|
@ -4610,7 +4610,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
|
|||
return 1;
|
||||
}
|
||||
|
||||
NV_TRACE(dev, "0x%04X: parsing output script 2\n", script);
|
||||
NV_DEBUG_KMS(dev, "0x%04X: parsing output script 2\n", script);
|
||||
nouveau_bios_run_init_table(dev, script, dcbent);
|
||||
} else
|
||||
if (pxclk > 0) {
|
||||
|
@ -4622,7 +4622,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
|
|||
return 1;
|
||||
}
|
||||
|
||||
NV_TRACE(dev, "0x%04X: parsing clock script 0\n", script);
|
||||
NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 0\n", script);
|
||||
nouveau_bios_run_init_table(dev, script, dcbent);
|
||||
} else
|
||||
if (pxclk < 0) {
|
||||
|
@ -4634,7 +4634,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
|
|||
return 1;
|
||||
}
|
||||
|
||||
NV_TRACE(dev, "0x%04X: parsing clock script 1\n", script);
|
||||
NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 1\n", script);
|
||||
nouveau_bios_run_init_table(dev, script, dcbent);
|
||||
}
|
||||
|
||||
|
@ -5357,19 +5357,17 @@ static int parse_bit_tmds_tbl_entry(struct drm_device *dev, struct nvbios *bios,
|
|||
}
|
||||
|
||||
tmdstableptr = ROM16(bios->data[bitentry->offset]);
|
||||
|
||||
if (tmdstableptr == 0x0) {
|
||||
if (!tmdstableptr) {
|
||||
NV_ERROR(dev, "Pointer to TMDS table invalid\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
NV_INFO(dev, "TMDS table version %d.%d\n",
|
||||
bios->data[tmdstableptr] >> 4, bios->data[tmdstableptr] & 0xf);
|
||||
|
||||
/* nv50+ has v2.0, but we don't parse it atm */
|
||||
if (bios->data[tmdstableptr] != 0x11) {
|
||||
NV_WARN(dev,
|
||||
"TMDS table revision %d.%d not currently supported\n",
|
||||
bios->data[tmdstableptr] >> 4, bios->data[tmdstableptr] & 0xf);
|
||||
if (bios->data[tmdstableptr] != 0x11)
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/*
|
||||
* These two scripts are odd: they don't seem to get run even when
|
||||
|
@ -5809,6 +5807,22 @@ parse_dcb_gpio_table(struct nvbios *bios)
|
|||
gpio->line = tvdac_gpio[1] >> 4;
|
||||
gpio->invert = tvdac_gpio[0] & 2;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* No systematic way to store GPIO info on pre-v2.2
|
||||
* DCBs, try to match the PCI device IDs.
|
||||
*/
|
||||
|
||||
/* Apple iMac G4 NV18 */
|
||||
if (dev->pdev->device == 0x0189 &&
|
||||
dev->pdev->subsystem_vendor == 0x10de &&
|
||||
dev->pdev->subsystem_device == 0x0010) {
|
||||
struct dcb_gpio_entry *gpio = new_gpio_entry(bios);
|
||||
|
||||
gpio->tag = DCB_GPIO_TVDAC0;
|
||||
gpio->line = 4;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!gpio_table_ptr)
|
||||
|
|
|
@ -36,6 +36,21 @@
|
|||
#include <linux/log2.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
int
|
||||
nouveau_bo_sync_gpu(struct nouveau_bo *nvbo, struct nouveau_channel *chan)
|
||||
{
|
||||
struct nouveau_fence *prev_fence = nvbo->bo.sync_obj;
|
||||
int ret;
|
||||
|
||||
if (!prev_fence || nouveau_fence_channel(prev_fence) == chan)
|
||||
return 0;
|
||||
|
||||
spin_lock(&nvbo->bo.lock);
|
||||
ret = ttm_bo_wait(&nvbo->bo, false, false, false);
|
||||
spin_unlock(&nvbo->bo.lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
|
||||
{
|
||||
|
|
|
@ -104,7 +104,7 @@ nouveau_connector_ddc_detect(struct drm_connector *connector,
|
|||
int i;
|
||||
|
||||
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
|
||||
struct nouveau_i2c_chan *i2c;
|
||||
struct nouveau_i2c_chan *i2c = NULL;
|
||||
struct nouveau_encoder *nv_encoder;
|
||||
struct drm_mode_object *obj;
|
||||
int id;
|
||||
|
@ -117,7 +117,9 @@ nouveau_connector_ddc_detect(struct drm_connector *connector,
|
|||
if (!obj)
|
||||
continue;
|
||||
nv_encoder = nouveau_encoder(obj_to_encoder(obj));
|
||||
i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
|
||||
|
||||
if (nv_encoder->dcb->i2c_index < 0xf)
|
||||
i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
|
||||
|
||||
if (i2c && nouveau_probe_i2c_addr(i2c, 0x50)) {
|
||||
*pnv_encoder = nv_encoder;
|
||||
|
|
|
@ -1165,6 +1165,7 @@ extern u16 nouveau_bo_rd16(struct nouveau_bo *nvbo, unsigned index);
|
|||
extern void nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val);
|
||||
extern u32 nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index);
|
||||
extern void nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val);
|
||||
extern int nouveau_bo_sync_gpu(struct nouveau_bo *, struct nouveau_channel *);
|
||||
|
||||
/* nouveau_fence.c */
|
||||
struct nouveau_fence;
|
||||
|
|
|
@ -361,16 +361,11 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
|
|||
|
||||
list_for_each_entry(nvbo, list, entry) {
|
||||
struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index];
|
||||
struct nouveau_fence *prev_fence = nvbo->bo.sync_obj;
|
||||
|
||||
if (prev_fence && nouveau_fence_channel(prev_fence) != chan) {
|
||||
spin_lock(&nvbo->bo.lock);
|
||||
ret = ttm_bo_wait(&nvbo->bo, false, false, false);
|
||||
spin_unlock(&nvbo->bo.lock);
|
||||
if (unlikely(ret)) {
|
||||
NV_ERROR(dev, "fail wait other chan\n");
|
||||
return ret;
|
||||
}
|
||||
ret = nouveau_bo_sync_gpu(nvbo, chan);
|
||||
if (unlikely(ret)) {
|
||||
NV_ERROR(dev, "fail pre-validate sync\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = nouveau_gem_set_domain(nvbo->gem, b->read_domains,
|
||||
|
@ -381,7 +376,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
|
|||
return ret;
|
||||
}
|
||||
|
||||
nvbo->channel = chan;
|
||||
nvbo->channel = (b->read_domains & (1 << 31)) ? NULL : chan;
|
||||
ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement,
|
||||
false, false, false);
|
||||
nvbo->channel = NULL;
|
||||
|
@ -390,6 +385,12 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = nouveau_bo_sync_gpu(nvbo, chan);
|
||||
if (unlikely(ret)) {
|
||||
NV_ERROR(dev, "fail post-validate sync\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (nvbo->bo.offset == b->presumed.offset &&
|
||||
((nvbo->bo.mem.mem_type == TTM_PL_VRAM &&
|
||||
b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) ||
|
||||
|
@ -615,6 +616,21 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
|
|||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
/* Mark push buffers as being used on PFIFO, the validation code
|
||||
* will then make sure that if the pushbuf bo moves, that they
|
||||
* happen on the kernel channel, which will in turn cause a sync
|
||||
* to happen before we try and submit the push buffer.
|
||||
*/
|
||||
for (i = 0; i < req->nr_push; i++) {
|
||||
if (push[i].bo_index >= req->nr_buffers) {
|
||||
NV_ERROR(dev, "push %d buffer not in list\n", i);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
bo[push[i].bo_index].read_domains |= (1 << 31);
|
||||
}
|
||||
|
||||
/* Validate buffer list */
|
||||
ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, req->buffers,
|
||||
req->nr_buffers, &op, &do_reloc);
|
||||
|
|
|
@ -163,7 +163,7 @@ nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index)
|
|||
if (entry->chan)
|
||||
return -EEXIST;
|
||||
|
||||
if (dev_priv->card_type == NV_C0 && entry->read >= NV50_I2C_PORTS) {
|
||||
if (dev_priv->card_type >= NV_50 && entry->read >= NV50_I2C_PORTS) {
|
||||
NV_ERROR(dev, "unknown i2c port %d\n", entry->read);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -214,6 +214,7 @@ int
|
|||
nouveau_sgdma_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct pci_dev *pdev = dev->pdev;
|
||||
struct nouveau_gpuobj *gpuobj = NULL;
|
||||
uint32_t aper_size, obj_size;
|
||||
int i, ret;
|
||||
|
@ -239,10 +240,19 @@ nouveau_sgdma_init(struct drm_device *dev)
|
|||
|
||||
dev_priv->gart_info.sg_dummy_page =
|
||||
alloc_page(GFP_KERNEL|__GFP_DMA32);
|
||||
if (!dev_priv->gart_info.sg_dummy_page) {
|
||||
nouveau_gpuobj_del(dev, &gpuobj);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
set_bit(PG_locked, &dev_priv->gart_info.sg_dummy_page->flags);
|
||||
dev_priv->gart_info.sg_dummy_bus =
|
||||
pci_map_page(dev->pdev, dev_priv->gart_info.sg_dummy_page, 0,
|
||||
pci_map_page(pdev, dev_priv->gart_info.sg_dummy_page, 0,
|
||||
PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
|
||||
if (pci_dma_mapping_error(pdev, dev_priv->gart_info.sg_dummy_bus)) {
|
||||
nouveau_gpuobj_del(dev, &gpuobj);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (dev_priv->card_type < NV_50) {
|
||||
/* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and
|
||||
|
|
|
@ -129,6 +129,14 @@ get_tv_detect_quirks(struct drm_device *dev, uint32_t *pin_mask)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* MSI nForce2 IGP */
|
||||
if (dev->pdev->device == 0x01f0 &&
|
||||
dev->pdev->subsystem_vendor == 0x1462 &&
|
||||
dev->pdev->subsystem_device == 0x5710) {
|
||||
*pin_mask = 0xc;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -278,7 +278,7 @@ nv50_instmem_init(struct drm_device *dev)
|
|||
/*XXX: incorrect, but needed to make hash func "work" */
|
||||
dev_priv->ramht_offset = 0x10000;
|
||||
dev_priv->ramht_bits = 9;
|
||||
dev_priv->ramht_size = (1 << dev_priv->ramht_bits);
|
||||
dev_priv->ramht_size = (1 << dev_priv->ramht_bits) * 8;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -142,14 +142,16 @@ int
|
|||
nvc0_instmem_suspend(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
u32 *buf;
|
||||
int i;
|
||||
|
||||
dev_priv->susres.ramin_copy = vmalloc(65536);
|
||||
if (!dev_priv->susres.ramin_copy)
|
||||
return -ENOMEM;
|
||||
buf = dev_priv->susres.ramin_copy;
|
||||
|
||||
for (i = 0x700000; i < 0x710000; i += 4)
|
||||
dev_priv->susres.ramin_copy[i/4] = nv_rd32(dev, i);
|
||||
for (i = 0; i < 65536; i += 4)
|
||||
buf[i/4] = nv_rd32(dev, NV04_PRAMIN + i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -157,14 +159,15 @@ void
|
|||
nvc0_instmem_resume(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
u32 *buf = dev_priv->susres.ramin_copy;
|
||||
u64 chan;
|
||||
int i;
|
||||
|
||||
chan = dev_priv->vram_size - dev_priv->ramin_rsvd_vram;
|
||||
nv_wr32(dev, 0x001700, chan >> 16);
|
||||
|
||||
for (i = 0x700000; i < 0x710000; i += 4)
|
||||
nv_wr32(dev, i, dev_priv->susres.ramin_copy[i/4]);
|
||||
for (i = 0; i < 65536; i += 4)
|
||||
nv_wr32(dev, NV04_PRAMIN + i, buf[i/4]);
|
||||
vfree(dev_priv->susres.ramin_copy);
|
||||
dev_priv->susres.ramin_copy = NULL;
|
||||
|
||||
|
@ -221,7 +224,7 @@ nvc0_instmem_init(struct drm_device *dev)
|
|||
/*XXX: incorrect, but needed to make hash func "work" */
|
||||
dev_priv->ramht_offset = 0x10000;
|
||||
dev_priv->ramht_bits = 9;
|
||||
dev_priv->ramht_size = (1 << dev_priv->ramht_bits);
|
||||
dev_priv->ramht_size = (1 << dev_priv->ramht_bits) * 8;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue