mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-16 09:56:46 +00:00
Merge remote branch 'nouveau/for-airlied' of ../drm-nouveau-next into drm-testing
* 'nouveau/for-airlied' of ../drm-nouveau-next: drm/nv50: cast IGP memory location to u64 before shifting drm/nv50: use alternate source of SOR_MODE_CTRL for DP hack drm/nouveau: fix dual-link displays when plugged into single-link outputs drm/nv50: obey dcb->duallink_possible drm/nv50: fix duallink_possible calculation for DCB 4.0 cards drm/nouveau: don't execute INIT_GPIO unless we're really running the table drm/nv40: allow cold-booting of nv4x chipsets drm/nouveau: fix POST detection for certain chipsets drm/nouveau: Add getparam for current PTIMER time. drm/nouveau: allow cursor image and position to survive suspend
This commit is contained in:
commit
36d1701c50
@ -2827,7 +2827,10 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
|
|||||||
|
|
||||||
BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry);
|
BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry);
|
||||||
|
|
||||||
nv50_gpio_set(bios->dev, gpio->tag, gpio->state_default);
|
BIOSLOG(bios, "0x%04X: set gpio 0x%02x, state %d\n",
|
||||||
|
offset, gpio->tag, gpio->state_default);
|
||||||
|
if (bios->execute)
|
||||||
|
nv50_gpio_set(bios->dev, gpio->tag, gpio->state_default);
|
||||||
|
|
||||||
/* The NVIDIA binary driver doesn't appear to actually do
|
/* The NVIDIA binary driver doesn't appear to actually do
|
||||||
* any of this, my VBIOS does however.
|
* any of this, my VBIOS does however.
|
||||||
@ -5553,12 +5556,6 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
|
|||||||
entry->bus = (conn >> 16) & 0xf;
|
entry->bus = (conn >> 16) & 0xf;
|
||||||
entry->location = (conn >> 20) & 0x3;
|
entry->location = (conn >> 20) & 0x3;
|
||||||
entry->or = (conn >> 24) & 0xf;
|
entry->or = (conn >> 24) & 0xf;
|
||||||
/*
|
|
||||||
* Normal entries consist of a single bit, but dual link has the
|
|
||||||
* next most significant bit set too
|
|
||||||
*/
|
|
||||||
entry->duallink_possible =
|
|
||||||
((1 << (ffs(entry->or) - 1)) * 3 == entry->or);
|
|
||||||
|
|
||||||
switch (entry->type) {
|
switch (entry->type) {
|
||||||
case OUTPUT_ANALOG:
|
case OUTPUT_ANALOG:
|
||||||
@ -5642,6 +5639,16 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dcb->version < 0x40) {
|
||||||
|
/* Normal entries consist of a single bit, but dual link has
|
||||||
|
* the next most significant bit set too
|
||||||
|
*/
|
||||||
|
entry->duallink_possible =
|
||||||
|
((1 << (ffs(entry->or) - 1)) * 3 == entry->or);
|
||||||
|
} else {
|
||||||
|
entry->duallink_possible = (entry->sorconf.link == 3);
|
||||||
|
}
|
||||||
|
|
||||||
/* unsure what DCB version introduces this, 3.0? */
|
/* unsure what DCB version introduces this, 3.0? */
|
||||||
if (conf & 0x100000)
|
if (conf & 0x100000)
|
||||||
entry->i2c_upper_default = true;
|
entry->i2c_upper_default = true;
|
||||||
@ -6225,6 +6232,30 @@ nouveau_bios_i2c_devices_takedown(struct drm_device *dev)
|
|||||||
nouveau_i2c_fini(dev, entry);
|
nouveau_i2c_fini(dev, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
nouveau_bios_posted(struct drm_device *dev)
|
||||||
|
{
|
||||||
|
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||||
|
bool was_locked;
|
||||||
|
unsigned htotal;
|
||||||
|
|
||||||
|
if (dev_priv->chipset >= NV_50) {
|
||||||
|
if (NVReadVgaCrtc(dev, 0, 0x00) == 0 &&
|
||||||
|
NVReadVgaCrtc(dev, 0, 0x1a) == 0)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
was_locked = NVLockVgaCrtcs(dev, false);
|
||||||
|
htotal = NVReadVgaCrtc(dev, 0, 0x06);
|
||||||
|
htotal |= (NVReadVgaCrtc(dev, 0, 0x07) & 0x01) << 8;
|
||||||
|
htotal |= (NVReadVgaCrtc(dev, 0, 0x07) & 0x20) << 4;
|
||||||
|
htotal |= (NVReadVgaCrtc(dev, 0, 0x25) & 0x01) << 10;
|
||||||
|
htotal |= (NVReadVgaCrtc(dev, 0, 0x41) & 0x01) << 11;
|
||||||
|
NVLockVgaCrtcs(dev, was_locked);
|
||||||
|
return (htotal != 0);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
nouveau_bios_init(struct drm_device *dev)
|
nouveau_bios_init(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
@ -6259,11 +6290,9 @@ nouveau_bios_init(struct drm_device *dev)
|
|||||||
bios->execute = false;
|
bios->execute = false;
|
||||||
|
|
||||||
/* ... unless card isn't POSTed already */
|
/* ... unless card isn't POSTed already */
|
||||||
if (dev_priv->card_type >= NV_10 &&
|
if (!nouveau_bios_posted(dev)) {
|
||||||
NVReadVgaCrtc(dev, 0, 0x00) == 0 &&
|
|
||||||
NVReadVgaCrtc(dev, 0, 0x1a) == 0) {
|
|
||||||
NV_INFO(dev, "Adaptor not initialised\n");
|
NV_INFO(dev, "Adaptor not initialised\n");
|
||||||
if (dev_priv->card_type < NV_50) {
|
if (dev_priv->card_type < NV_40) {
|
||||||
NV_ERROR(dev, "Unable to POST this chipset\n");
|
NV_ERROR(dev, "Unable to POST this chipset\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
@ -432,24 +432,27 @@ nouveau_connector_set_property(struct drm_connector *connector,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct drm_display_mode *
|
static struct drm_display_mode *
|
||||||
nouveau_connector_native_mode(struct nouveau_connector *connector)
|
nouveau_connector_native_mode(struct drm_connector *connector)
|
||||||
{
|
{
|
||||||
struct drm_device *dev = connector->base.dev;
|
struct drm_connector_helper_funcs *helper = connector->helper_private;
|
||||||
|
struct nouveau_connector *nv_connector = nouveau_connector(connector);
|
||||||
|
struct drm_device *dev = connector->dev;
|
||||||
struct drm_display_mode *mode, *largest = NULL;
|
struct drm_display_mode *mode, *largest = NULL;
|
||||||
int high_w = 0, high_h = 0, high_v = 0;
|
int high_w = 0, high_h = 0, high_v = 0;
|
||||||
|
|
||||||
/* Use preferred mode if there is one.. */
|
list_for_each_entry(mode, &nv_connector->base.probed_modes, head) {
|
||||||
list_for_each_entry(mode, &connector->base.probed_modes, head) {
|
if (helper->mode_valid(connector, mode) != MODE_OK)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Use preferred mode if there is one.. */
|
||||||
if (mode->type & DRM_MODE_TYPE_PREFERRED) {
|
if (mode->type & DRM_MODE_TYPE_PREFERRED) {
|
||||||
NV_DEBUG_KMS(dev, "native mode from preferred\n");
|
NV_DEBUG_KMS(dev, "native mode from preferred\n");
|
||||||
return drm_mode_duplicate(dev, mode);
|
return drm_mode_duplicate(dev, mode);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise, take the resolution with the largest width, then height,
|
/* Otherwise, take the resolution with the largest width, then
|
||||||
* then vertical refresh
|
* height, then vertical refresh
|
||||||
*/
|
*/
|
||||||
list_for_each_entry(mode, &connector->base.probed_modes, head) {
|
|
||||||
if (mode->hdisplay < high_w)
|
if (mode->hdisplay < high_w)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -553,7 +556,7 @@ nouveau_connector_get_modes(struct drm_connector *connector)
|
|||||||
*/
|
*/
|
||||||
if (!nv_connector->native_mode)
|
if (!nv_connector->native_mode)
|
||||||
nv_connector->native_mode =
|
nv_connector->native_mode =
|
||||||
nouveau_connector_native_mode(nv_connector);
|
nouveau_connector_native_mode(connector);
|
||||||
if (ret == 0 && nv_connector->native_mode) {
|
if (ret == 0 && nv_connector->native_mode) {
|
||||||
struct drm_display_mode *mode;
|
struct drm_display_mode *mode;
|
||||||
|
|
||||||
@ -584,9 +587,9 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
|
|||||||
|
|
||||||
switch (nv_encoder->dcb->type) {
|
switch (nv_encoder->dcb->type) {
|
||||||
case OUTPUT_LVDS:
|
case OUTPUT_LVDS:
|
||||||
BUG_ON(!nv_connector->native_mode);
|
if (nv_connector->native_mode &&
|
||||||
if (mode->hdisplay > nv_connector->native_mode->hdisplay ||
|
(mode->hdisplay > nv_connector->native_mode->hdisplay ||
|
||||||
mode->vdisplay > nv_connector->native_mode->vdisplay)
|
mode->vdisplay > nv_connector->native_mode->vdisplay))
|
||||||
return MODE_PANEL;
|
return MODE_PANEL;
|
||||||
|
|
||||||
min_clock = 0;
|
min_clock = 0;
|
||||||
@ -594,8 +597,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
|
|||||||
break;
|
break;
|
||||||
case OUTPUT_TMDS:
|
case OUTPUT_TMDS:
|
||||||
if ((dev_priv->card_type >= NV_50 && !nouveau_duallink) ||
|
if ((dev_priv->card_type >= NV_50 && !nouveau_duallink) ||
|
||||||
(dev_priv->card_type < NV_50 &&
|
!nv_encoder->dcb->duallink_possible)
|
||||||
!nv_encoder->dcb->duallink_possible))
|
|
||||||
max_clock = 165000;
|
max_clock = 165000;
|
||||||
else
|
else
|
||||||
max_clock = 330000;
|
max_clock = 330000;
|
||||||
@ -729,7 +731,7 @@ nouveau_connector_create_lvds(struct drm_device *dev,
|
|||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto out;
|
goto out;
|
||||||
nv_connector->detected_encoder = nv_encoder;
|
nv_connector->detected_encoder = nv_encoder;
|
||||||
nv_connector->native_mode = nouveau_connector_native_mode(nv_connector);
|
nv_connector->native_mode = nouveau_connector_native_mode(connector);
|
||||||
list_for_each_entry_safe(mode, temp, &connector->probed_modes, head)
|
list_for_each_entry_safe(mode, temp, &connector->probed_modes, head)
|
||||||
drm_mode_remove(connector, mode);
|
drm_mode_remove(connector, mode);
|
||||||
|
|
||||||
|
@ -40,6 +40,8 @@ struct nouveau_crtc {
|
|||||||
int sharpness;
|
int sharpness;
|
||||||
int last_dpms;
|
int last_dpms;
|
||||||
|
|
||||||
|
int cursor_saved_x, cursor_saved_y;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int cpp;
|
int cpp;
|
||||||
bool blanked;
|
bool blanked;
|
||||||
|
@ -175,6 +175,13 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
|
|||||||
nouveau_bo_unpin(nouveau_fb->nvbo);
|
nouveau_bo_unpin(nouveau_fb->nvbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||||
|
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
||||||
|
|
||||||
|
nouveau_bo_unmap(nv_crtc->cursor.nvbo);
|
||||||
|
nouveau_bo_unpin(nv_crtc->cursor.nvbo);
|
||||||
|
}
|
||||||
|
|
||||||
NV_INFO(dev, "Evicting buffers...\n");
|
NV_INFO(dev, "Evicting buffers...\n");
|
||||||
ttm_bo_evict_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
|
ttm_bo_evict_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
|
||||||
|
|
||||||
@ -314,12 +321,34 @@ nouveau_pci_resume(struct pci_dev *pdev)
|
|||||||
nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM);
|
nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||||
|
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
|
||||||
|
if (!ret)
|
||||||
|
ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
|
||||||
|
if (ret)
|
||||||
|
NV_ERROR(dev, "Could not pin/map cursor.\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (dev_priv->card_type < NV_50) {
|
if (dev_priv->card_type < NV_50) {
|
||||||
nv04_display_restore(dev);
|
nv04_display_restore(dev);
|
||||||
NVLockVgaCrtcs(dev, false);
|
NVLockVgaCrtcs(dev, false);
|
||||||
} else
|
} else
|
||||||
nv50_display_init(dev);
|
nv50_display_init(dev);
|
||||||
|
|
||||||
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||||
|
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
||||||
|
|
||||||
|
nv_crtc->cursor.set_offset(nv_crtc,
|
||||||
|
nv_crtc->cursor.nvbo->bo.offset -
|
||||||
|
dev_priv->vm_vram_base);
|
||||||
|
|
||||||
|
nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x,
|
||||||
|
nv_crtc->cursor_saved_y);
|
||||||
|
}
|
||||||
|
|
||||||
/* Force CLUT to get re-loaded during modeset */
|
/* Force CLUT to get re-loaded during modeset */
|
||||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||||
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
||||||
|
@ -540,7 +540,8 @@ nouveau_mem_detect(struct drm_device *dev)
|
|||||||
dev_priv->vram_size = nv_rd32(dev, NV04_FIFO_DATA);
|
dev_priv->vram_size = nv_rd32(dev, NV04_FIFO_DATA);
|
||||||
dev_priv->vram_size &= NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK;
|
dev_priv->vram_size &= NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK;
|
||||||
if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac)
|
if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac)
|
||||||
dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10) << 12;
|
dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10);
|
||||||
|
dev_priv->vram_sys_base <<= 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20));
|
NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20));
|
||||||
|
@ -916,6 +916,9 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data,
|
|||||||
case NOUVEAU_GETPARAM_VM_VRAM_BASE:
|
case NOUVEAU_GETPARAM_VM_VRAM_BASE:
|
||||||
getparam->value = dev_priv->vm_vram_base;
|
getparam->value = dev_priv->vm_vram_base;
|
||||||
break;
|
break;
|
||||||
|
case NOUVEAU_GETPARAM_PTIMER_TIME:
|
||||||
|
getparam->value = dev_priv->engine.timer.read(dev);
|
||||||
|
break;
|
||||||
case NOUVEAU_GETPARAM_GRAPH_UNITS:
|
case NOUVEAU_GETPARAM_GRAPH_UNITS:
|
||||||
/* NV40 and NV50 versions are quite different, but register
|
/* NV40 and NV50 versions are quite different, but register
|
||||||
* address is the same. User is supposed to know the card
|
* address is the same. User is supposed to know the card
|
||||||
|
@ -20,6 +20,7 @@ nv04_cursor_hide(struct nouveau_crtc *nv_crtc, bool update)
|
|||||||
static void
|
static void
|
||||||
nv04_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y)
|
nv04_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y)
|
||||||
{
|
{
|
||||||
|
nv_crtc->cursor_saved_x = x; nv_crtc->cursor_saved_y = y;
|
||||||
NVWriteRAMDAC(nv_crtc->base.dev, nv_crtc->index,
|
NVWriteRAMDAC(nv_crtc->base.dev, nv_crtc->index,
|
||||||
NV_PRAMDAC_CU_START_POS,
|
NV_PRAMDAC_CU_START_POS,
|
||||||
XLATE(y, 0, NV_PRAMDAC_CU_START_POS_Y) |
|
XLATE(y, 0, NV_PRAMDAC_CU_START_POS_Y) |
|
||||||
|
@ -107,6 +107,7 @@ nv50_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y)
|
|||||||
{
|
{
|
||||||
struct drm_device *dev = nv_crtc->base.dev;
|
struct drm_device *dev = nv_crtc->base.dev;
|
||||||
|
|
||||||
|
nv_crtc->cursor_saved_x = x; nv_crtc->cursor_saved_y = y;
|
||||||
nv_wr32(dev, NV50_PDISPLAY_CURSOR_USER_POS(nv_crtc->index),
|
nv_wr32(dev, NV50_PDISPLAY_CURSOR_USER_POS(nv_crtc->index),
|
||||||
((y & 0xFFFF) << 16) | (x & 0xFFFF));
|
((y & 0xFFFF) << 16) | (x & 0xFFFF));
|
||||||
/* Needed to make the cursor move. */
|
/* Needed to make the cursor move. */
|
||||||
|
@ -274,7 +274,6 @@ static const struct drm_encoder_funcs nv50_sor_encoder_funcs = {
|
|||||||
int
|
int
|
||||||
nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)
|
nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)
|
||||||
{
|
{
|
||||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
|
||||||
struct nouveau_encoder *nv_encoder = NULL;
|
struct nouveau_encoder *nv_encoder = NULL;
|
||||||
struct drm_encoder *encoder;
|
struct drm_encoder *encoder;
|
||||||
bool dum;
|
bool dum;
|
||||||
@ -324,11 +323,7 @@ nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)
|
|||||||
int or = nv_encoder->or, link = !(entry->dpconf.sor.link & 1);
|
int or = nv_encoder->or, link = !(entry->dpconf.sor.link & 1);
|
||||||
uint32_t tmp;
|
uint32_t tmp;
|
||||||
|
|
||||||
if (dev_priv->chipset < 0x90 ||
|
tmp = nv_rd32(dev, 0x61c700 + (or * 0x800));
|
||||||
dev_priv->chipset == 0x92 || dev_priv->chipset == 0xa0)
|
|
||||||
tmp = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_C(or));
|
|
||||||
else
|
|
||||||
tmp = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_C(or));
|
|
||||||
|
|
||||||
switch ((tmp & 0x00000f00) >> 8) {
|
switch ((tmp & 0x00000f00) >> 8) {
|
||||||
case 8:
|
case 8:
|
||||||
|
@ -79,6 +79,7 @@ struct drm_nouveau_gpuobj_free {
|
|||||||
#define NOUVEAU_GETPARAM_CHIPSET_ID 11
|
#define NOUVEAU_GETPARAM_CHIPSET_ID 11
|
||||||
#define NOUVEAU_GETPARAM_VM_VRAM_BASE 12
|
#define NOUVEAU_GETPARAM_VM_VRAM_BASE 12
|
||||||
#define NOUVEAU_GETPARAM_GRAPH_UNITS 13
|
#define NOUVEAU_GETPARAM_GRAPH_UNITS 13
|
||||||
|
#define NOUVEAU_GETPARAM_PTIMER_TIME 14
|
||||||
struct drm_nouveau_getparam {
|
struct drm_nouveau_getparam {
|
||||||
uint64_t param;
|
uint64_t param;
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user