Commit 4936b172 authored by Dave Airlie's avatar Dave Airlie

Merge branch 'drm-nouveau-fixes' of...

Merge branch 'drm-nouveau-fixes' of git://people.freedesktop.org/git/nouveau/linux-2.6 into drm-fixes

This covers all known nouveau regressions at the moment, along with a fix
to not steal the console on headless GPUs.

* 'drm-nouveau-fixes' of git://people.freedesktop.org/git/nouveau/linux-2.6:
  drm/nouveau: headless mode by default if pci class != vga display
  drm/nouveau: resurrect headless mode since rework
  drm/nv50/fb: prevent oops on chipsets without compression tags
  drm/nouveau: allow creation of zero-sized mm
  drm/nouveau/i2c: fix typo when checking nvio i2c port validity
  drm/nouveau: silence modesetting spam on pre-gf8 chipsets
parents 8f0d8163 e412e95a
...@@ -218,13 +218,16 @@ nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block) ...@@ -218,13 +218,16 @@ nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block)
node = kzalloc(sizeof(*node), GFP_KERNEL); node = kzalloc(sizeof(*node), GFP_KERNEL);
if (!node) if (!node)
return -ENOMEM; return -ENOMEM;
node->offset = roundup(offset, mm->block_size);
node->length = rounddown(offset + length, mm->block_size) - node->offset; if (length) {
node->offset = roundup(offset, mm->block_size);
node->length = rounddown(offset + length, mm->block_size);
node->length -= node->offset;
}
list_add_tail(&node->nl_entry, &mm->nodes); list_add_tail(&node->nl_entry, &mm->nodes);
list_add_tail(&node->fl_entry, &mm->free); list_add_tail(&node->fl_entry, &mm->free);
mm->heap_nodes++; mm->heap_nodes++;
mm->heap_size += length;
return 0; return 0;
} }
......
...@@ -19,7 +19,6 @@ struct nouveau_mm { ...@@ -19,7 +19,6 @@ struct nouveau_mm {
u32 block_size; u32 block_size;
int heap_nodes; int heap_nodes;
u32 heap_size;
}; };
int nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block); int nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block);
......
...@@ -219,13 +219,11 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, ...@@ -219,13 +219,11 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
((priv->base.ram.size & 0x000000ff) << 32); ((priv->base.ram.size & 0x000000ff) << 32);
tags = nv_rd32(priv, 0x100320); tags = nv_rd32(priv, 0x100320);
if (tags) { ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1);
ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1); if (ret)
if (ret) return ret;
return ret;
nv_debug(priv, "%d compression tags\n", tags); nv_debug(priv, "%d compression tags\n", tags);
}
size = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail; size = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail;
switch (device->chipset) { switch (device->chipset) {
......
...@@ -292,7 +292,7 @@ nouveau_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, ...@@ -292,7 +292,7 @@ nouveau_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
case DCB_I2C_NVIO_BIT: case DCB_I2C_NVIO_BIT:
port->drive = info.drive & 0x0f; port->drive = info.drive & 0x0f;
if (device->card_type < NV_D0) { if (device->card_type < NV_D0) {
if (info.drive >= ARRAY_SIZE(nv50_i2c_port)) if (port->drive >= ARRAY_SIZE(nv50_i2c_port))
break; break;
port->drive = nv50_i2c_port[port->drive]; port->drive = nv50_i2c_port[port->drive];
port->sense = port->drive; port->sense = port->drive;
......
...@@ -290,6 +290,7 @@ nouveau_display_create(struct drm_device *dev) ...@@ -290,6 +290,7 @@ nouveau_display_create(struct drm_device *dev)
struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_disp *pdisp = nouveau_disp(drm->device); struct nouveau_disp *pdisp = nouveau_disp(drm->device);
struct nouveau_display *disp; struct nouveau_display *disp;
u32 pclass = dev->pdev->class >> 8;
int ret, gen; int ret, gen;
disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL); disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL);
...@@ -360,23 +361,27 @@ nouveau_display_create(struct drm_device *dev) ...@@ -360,23 +361,27 @@ nouveau_display_create(struct drm_device *dev)
drm_kms_helper_poll_init(dev); drm_kms_helper_poll_init(dev);
drm_kms_helper_poll_disable(dev); drm_kms_helper_poll_disable(dev);
if (nv_device(drm->device)->card_type < NV_50) if (nouveau_modeset == 1 ||
ret = nv04_display_create(dev); (nouveau_modeset < 0 && pclass == PCI_CLASS_DISPLAY_VGA)) {
else if (nv_device(drm->device)->card_type < NV_50)
if (nv_device(drm->device)->card_type < NV_D0) ret = nv04_display_create(dev);
ret = nv50_display_create(dev); else
else if (nv_device(drm->device)->card_type < NV_D0)
ret = nvd0_display_create(dev); ret = nv50_display_create(dev);
if (ret) else
goto disp_create_err; ret = nvd0_display_create(dev);
if (dev->mode_config.num_crtc) {
ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
if (ret) if (ret)
goto vblank_err; goto disp_create_err;
if (dev->mode_config.num_crtc) {
ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
if (ret)
goto vblank_err;
}
nouveau_backlight_init(dev);
} }
nouveau_backlight_init(dev);
return 0; return 0;
vblank_err: vblank_err:
...@@ -395,7 +400,8 @@ nouveau_display_destroy(struct drm_device *dev) ...@@ -395,7 +400,8 @@ nouveau_display_destroy(struct drm_device *dev)
nouveau_backlight_exit(dev); nouveau_backlight_exit(dev);
drm_vblank_cleanup(dev); drm_vblank_cleanup(dev);
disp->dtor(dev); if (disp->dtor)
disp->dtor(dev);
drm_kms_helper_poll_fini(dev); drm_kms_helper_poll_fini(dev);
drm_mode_config_cleanup(dev); drm_mode_config_cleanup(dev);
......
...@@ -63,8 +63,9 @@ MODULE_PARM_DESC(noaccel, "disable kernel/abi16 acceleration"); ...@@ -63,8 +63,9 @@ MODULE_PARM_DESC(noaccel, "disable kernel/abi16 acceleration");
static int nouveau_noaccel = 0; static int nouveau_noaccel = 0;
module_param_named(noaccel, nouveau_noaccel, int, 0400); module_param_named(noaccel, nouveau_noaccel, int, 0400);
MODULE_PARM_DESC(modeset, "enable driver"); MODULE_PARM_DESC(modeset, "enable driver (default: auto, "
static int nouveau_modeset = -1; "0 = disabled, 1 = enabled, 2 = headless)");
int nouveau_modeset = -1;
module_param_named(modeset, nouveau_modeset, int, 0400); module_param_named(modeset, nouveau_modeset, int, 0400);
static struct drm_driver driver; static struct drm_driver driver;
...@@ -363,7 +364,8 @@ nouveau_drm_unload(struct drm_device *dev) ...@@ -363,7 +364,8 @@ nouveau_drm_unload(struct drm_device *dev)
nouveau_pm_fini(dev); nouveau_pm_fini(dev);
nouveau_display_fini(dev); if (dev->mode_config.num_crtc)
nouveau_display_fini(dev);
nouveau_display_destroy(dev); nouveau_display_destroy(dev);
nouveau_irq_fini(dev); nouveau_irq_fini(dev);
...@@ -403,13 +405,15 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state) ...@@ -403,13 +405,15 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state)
pm_state.event == PM_EVENT_PRETHAW) pm_state.event == PM_EVENT_PRETHAW)
return 0; return 0;
NV_INFO(drm, "suspending fbcon...\n"); if (dev->mode_config.num_crtc) {
nouveau_fbcon_set_suspend(dev, 1); NV_INFO(drm, "suspending fbcon...\n");
nouveau_fbcon_set_suspend(dev, 1);
NV_INFO(drm, "suspending display...\n"); NV_INFO(drm, "suspending display...\n");
ret = nouveau_display_suspend(dev); ret = nouveau_display_suspend(dev);
if (ret) if (ret)
return ret; return ret;
}
NV_INFO(drm, "evicting buffers...\n"); NV_INFO(drm, "evicting buffers...\n");
ttm_bo_evict_mm(&drm->ttm.bdev, TTM_PL_VRAM); ttm_bo_evict_mm(&drm->ttm.bdev, TTM_PL_VRAM);
...@@ -445,8 +449,10 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state) ...@@ -445,8 +449,10 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state)
nouveau_client_init(&cli->base); nouveau_client_init(&cli->base);
} }
NV_INFO(drm, "resuming display...\n"); if (dev->mode_config.num_crtc) {
nouveau_display_resume(dev); NV_INFO(drm, "resuming display...\n");
nouveau_display_resume(dev);
}
return ret; return ret;
} }
...@@ -486,8 +492,10 @@ nouveau_drm_resume(struct pci_dev *pdev) ...@@ -486,8 +492,10 @@ nouveau_drm_resume(struct pci_dev *pdev)
nouveau_irq_postinstall(dev); nouveau_irq_postinstall(dev);
nouveau_pm_resume(dev); nouveau_pm_resume(dev);
NV_INFO(drm, "resuming display...\n"); if (dev->mode_config.num_crtc) {
nouveau_display_resume(dev); NV_INFO(drm, "resuming display...\n");
nouveau_display_resume(dev);
}
return 0; return 0;
} }
...@@ -662,9 +670,7 @@ nouveau_drm_init(void) ...@@ -662,9 +670,7 @@ nouveau_drm_init(void)
#ifdef CONFIG_VGA_CONSOLE #ifdef CONFIG_VGA_CONSOLE
if (vgacon_text_force()) if (vgacon_text_force())
nouveau_modeset = 0; nouveau_modeset = 0;
else
#endif #endif
nouveau_modeset = 1;
} }
if (!nouveau_modeset) if (!nouveau_modeset)
......
...@@ -141,4 +141,6 @@ int nouveau_drm_resume(struct pci_dev *); ...@@ -141,4 +141,6 @@ int nouveau_drm_resume(struct pci_dev *);
nv_info((cli), fmt, ##args); \ nv_info((cli), fmt, ##args); \
} while (0) } while (0)
extern int nouveau_modeset;
#endif #endif
...@@ -61,13 +61,15 @@ nouveau_irq_handler(DRM_IRQ_ARGS) ...@@ -61,13 +61,15 @@ nouveau_irq_handler(DRM_IRQ_ARGS)
nv_subdev(pmc)->intr(nv_subdev(pmc)); nv_subdev(pmc)->intr(nv_subdev(pmc));
if (device->card_type >= NV_D0) { if (dev->mode_config.num_crtc) {
if (nv_rd32(device, 0x000100) & 0x04000000) if (device->card_type >= NV_D0) {
nvd0_display_intr(dev); if (nv_rd32(device, 0x000100) & 0x04000000)
} else nvd0_display_intr(dev);
if (device->card_type >= NV_50) { } else
if (nv_rd32(device, 0x000100) & 0x04000000) if (device->card_type >= NV_50) {
nv50_display_intr(dev); if (nv_rd32(device, 0x000100) & 0x04000000)
nv50_display_intr(dev);
}
} }
return IRQ_HANDLED; return IRQ_HANDLED;
......
...@@ -220,7 +220,7 @@ static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder, ...@@ -220,7 +220,7 @@ static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder,
NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode); NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode);
if (blue == 0x18) { if (blue == 0x18) {
NV_INFO(drm, "Load detected on head A\n"); NV_DEBUG(drm, "Load detected on head A\n");
return connector_status_connected; return connector_status_connected;
} }
...@@ -338,8 +338,8 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) ...@@ -338,8 +338,8 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
if (nv17_dac_sample_load(encoder) & if (nv17_dac_sample_load(encoder) &
NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) { NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) {
NV_INFO(drm, "Load detected on output %c\n", NV_DEBUG(drm, "Load detected on output %c\n",
'@' + ffs(dcb->or)); '@' + ffs(dcb->or));
return connector_status_connected; return connector_status_connected;
} else { } else {
return connector_status_disconnected; return connector_status_disconnected;
...@@ -413,9 +413,9 @@ static void nv04_dac_commit(struct drm_encoder *encoder) ...@@ -413,9 +413,9 @@ static void nv04_dac_commit(struct drm_encoder *encoder)
helper->dpms(encoder, DRM_MODE_DPMS_ON); helper->dpms(encoder, DRM_MODE_DPMS_ON);
NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
} }
void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable) void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable)
...@@ -461,8 +461,8 @@ static void nv04_dac_dpms(struct drm_encoder *encoder, int mode) ...@@ -461,8 +461,8 @@ static void nv04_dac_dpms(struct drm_encoder *encoder, int mode)
return; return;
nv_encoder->last_dpms = mode; nv_encoder->last_dpms = mode;
NV_INFO(drm, "Setting dpms mode %d on vga encoder (output %d)\n", NV_DEBUG(drm, "Setting dpms mode %d on vga encoder (output %d)\n",
mode, nv_encoder->dcb->index); mode, nv_encoder->dcb->index);
nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON); nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON);
} }
......
...@@ -476,9 +476,9 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) ...@@ -476,9 +476,9 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
helper->dpms(encoder, DRM_MODE_DPMS_ON); helper->dpms(encoder, DRM_MODE_DPMS_ON);
NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
} }
static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode) static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode)
...@@ -520,8 +520,8 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) ...@@ -520,8 +520,8 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode)
return; return;
nv_encoder->last_dpms = mode; nv_encoder->last_dpms = mode;
NV_INFO(drm, "Setting dpms mode %d on lvds encoder (output %d)\n", NV_DEBUG(drm, "Setting dpms mode %d on lvds encoder (output %d)\n",
mode, nv_encoder->dcb->index); mode, nv_encoder->dcb->index);
if (was_powersaving && is_powersaving_dpms(mode)) if (was_powersaving && is_powersaving_dpms(mode))
return; return;
...@@ -565,8 +565,8 @@ static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode) ...@@ -565,8 +565,8 @@ static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode)
return; return;
nv_encoder->last_dpms = mode; nv_encoder->last_dpms = mode;
NV_INFO(drm, "Setting dpms mode %d on tmds encoder (output %d)\n", NV_DEBUG(drm, "Setting dpms mode %d on tmds encoder (output %d)\n",
mode, nv_encoder->dcb->index); mode, nv_encoder->dcb->index);
nv04_dfp_update_backlight(encoder, mode); nv04_dfp_update_backlight(encoder, mode);
nv04_dfp_update_fp_control(encoder, mode); nv04_dfp_update_fp_control(encoder, mode);
......
...@@ -75,8 +75,8 @@ static void nv04_tv_dpms(struct drm_encoder *encoder, int mode) ...@@ -75,8 +75,8 @@ static void nv04_tv_dpms(struct drm_encoder *encoder, int mode)
struct nv04_mode_state *state = &nv04_display(dev)->mode_reg; struct nv04_mode_state *state = &nv04_display(dev)->mode_reg;
uint8_t crtc1A; uint8_t crtc1A;
NV_INFO(drm, "Setting dpms mode %d on TV encoder (output %d)\n", NV_DEBUG(drm, "Setting dpms mode %d on TV encoder (output %d)\n",
mode, nv_encoder->dcb->index); mode, nv_encoder->dcb->index);
state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK); state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK);
...@@ -167,9 +167,8 @@ static void nv04_tv_commit(struct drm_encoder *encoder) ...@@ -167,9 +167,8 @@ static void nv04_tv_commit(struct drm_encoder *encoder)
helper->dpms(encoder, DRM_MODE_DPMS_ON); helper->dpms(encoder, DRM_MODE_DPMS_ON);
NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
'@' + ffs(nv_encoder->dcb->or));
} }
static void nv04_tv_destroy(struct drm_encoder *encoder) static void nv04_tv_destroy(struct drm_encoder *encoder)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment