diff --git a/drm-nouveau-updates.patch b/drm-nouveau-updates.patch index 1b704ff0a..607602cfc 100644 --- a/drm-nouveau-updates.patch +++ b/drm-nouveau-updates.patch @@ -1,6997 +1 @@ - drivers/gpu/drm/drm_crtc_helper.c | 22 +- - drivers/gpu/drm/i2c/ch7006_drv.c | 22 +- - drivers/gpu/drm/i2c/ch7006_priv.h | 2 +- - drivers/gpu/drm/nouveau/Makefile | 2 +- - drivers/gpu/drm/nouveau/nouveau_acpi.c | 38 ++- - drivers/gpu/drm/nouveau/nouveau_bios.c | 636 +++++++++++++++++++++------ - drivers/gpu/drm/nouveau/nouveau_bios.h | 4 +- - drivers/gpu/drm/nouveau/nouveau_bo.c | 9 +- - drivers/gpu/drm/nouveau/nouveau_calc.c | 4 +- - drivers/gpu/drm/nouveau/nouveau_channel.c | 5 - - drivers/gpu/drm/nouveau/nouveau_connector.c | 404 ++++++++---------- - drivers/gpu/drm/nouveau/nouveau_connector.h | 7 +- - drivers/gpu/drm/nouveau/nouveau_dma.c | 8 +- - drivers/gpu/drm/nouveau/nouveau_dp.c | 24 +- - drivers/gpu/drm/nouveau/nouveau_drv.c | 31 +- - drivers/gpu/drm/nouveau/nouveau_drv.h | 90 ++--- - drivers/gpu/drm/nouveau/nouveau_encoder.h | 10 +- - drivers/gpu/drm/nouveau/nouveau_fbcon.c | 2 +- - drivers/gpu/drm/nouveau/nouveau_fence.c | 31 +- - drivers/gpu/drm/nouveau/nouveau_gem.c | 11 +- - drivers/gpu/drm/nouveau/nouveau_grctx.c | 160 ------- - drivers/gpu/drm/nouveau/nouveau_i2c.c | 34 ++ - drivers/gpu/drm/nouveau/nouveau_i2c.h | 3 + - drivers/gpu/drm/nouveau/nouveau_mem.c | 275 ++---------- - drivers/gpu/drm/nouveau/nouveau_notifier.c | 30 +- - drivers/gpu/drm/nouveau/nouveau_object.c | 105 ++--- - drivers/gpu/drm/nouveau/nouveau_reg.h | 91 +++-- - drivers/gpu/drm/nouveau/nouveau_sgdma.c | 46 +-- - drivers/gpu/drm/nouveau/nouveau_state.c | 172 +++----- - drivers/gpu/drm/nouveau/nv04_crtc.c | 5 + - drivers/gpu/drm/nouveau/nv04_dac.c | 37 ++- - drivers/gpu/drm/nouveau/nv04_dfp.c | 12 +- - drivers/gpu/drm/nouveau/nv04_display.c | 64 ++-- - drivers/gpu/drm/nouveau/nv04_fifo.c | 20 +- - drivers/gpu/drm/nouveau/nv04_graph.c | 5 +- - drivers/gpu/drm/nouveau/nv04_instmem.c | 21 +- - drivers/gpu/drm/nouveau/nv04_mc.c | 4 + - drivers/gpu/drm/nouveau/nv04_tv.c | 125 ++---- - drivers/gpu/drm/nouveau/nv10_fifo.c | 10 - - drivers/gpu/drm/nouveau/nv17_tv.c | 46 ++- - drivers/gpu/drm/nouveau/nv20_graph.c | 96 +++-- - drivers/gpu/drm/nouveau/nv40_fifo.c | 8 - - drivers/gpu/drm/nouveau/nv40_graph.c | 58 +-- - drivers/gpu/drm/nouveau/nv40_mc.c | 2 +- - drivers/gpu/drm/nouveau/nv50_crtc.c | 42 +-- - drivers/gpu/drm/nouveau/nv50_dac.c | 43 ++- - drivers/gpu/drm/nouveau/nv50_display.c | 385 ++++++++++------- - drivers/gpu/drm/nouveau/nv50_fifo.c | 126 ++---- - drivers/gpu/drm/nouveau/nv50_graph.c | 86 ++--- - drivers/gpu/drm/nouveau/nv50_instmem.c | 67 +-- - drivers/gpu/drm/nouveau/nv50_sor.c | 105 +++--- - drivers/gpu/drm/nouveau/nvreg.h | 22 - - 52 files changed, 1748 insertions(+), 1919 deletions(-) - -diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c -index 9b2a541..1eaa315 100644 ---- a/drivers/gpu/drm/drm_crtc_helper.c -+++ b/drivers/gpu/drm/drm_crtc_helper.c -@@ -201,6 +201,17 @@ bool drm_helper_crtc_in_use(struct drm_crtc *crtc) - } - EXPORT_SYMBOL(drm_helper_crtc_in_use); - -+static void -+drm_encoder_disable(struct drm_encoder *encoder) -+{ -+ struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; -+ -+ if (encoder_funcs->disable) -+ (*encoder_funcs->disable)(encoder); -+ else -+ (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); -+} -+ - /** - * drm_helper_disable_unused_functions - disable unused objects - * @dev: DRM device -@@ -215,7 +226,6 @@ void drm_helper_disable_unused_functions(struct drm_device *dev) - { - struct drm_encoder *encoder; - struct drm_connector *connector; -- struct drm_encoder_helper_funcs *encoder_funcs; - struct drm_crtc *crtc; - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { -@@ -226,12 +236,8 @@ void drm_helper_disable_unused_functions(struct drm_device *dev) - } - - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { -- encoder_funcs = encoder->helper_private; - if (!drm_helper_encoder_in_use(encoder)) { -- if (encoder_funcs->disable) -- (*encoder_funcs->disable)(encoder); -- else -- (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); -+ drm_encoder_disable(encoder); - /* disconnector encoder from any connector */ - encoder->crtc = NULL; - } -@@ -292,11 +298,11 @@ drm_crtc_prepare_encoders(struct drm_device *dev) - encoder_funcs = encoder->helper_private; - /* Disable unused encoders */ - if (encoder->crtc == NULL) -- (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); -+ drm_encoder_disable(encoder); - /* Disable encoders whose CRTC is about to change */ - if (encoder_funcs->get_crtc && - encoder->crtc != (*encoder_funcs->get_crtc)(encoder)) -- (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); -+ drm_encoder_disable(encoder); - } - } - -diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c -index 81681a0..833b35f 100644 ---- a/drivers/gpu/drm/i2c/ch7006_drv.c -+++ b/drivers/gpu/drm/i2c/ch7006_drv.c -@@ -33,7 +33,7 @@ static void ch7006_encoder_set_config(struct drm_encoder *encoder, - { - struct ch7006_priv *priv = to_ch7006_priv(encoder); - -- priv->params = params; -+ priv->params = *(struct ch7006_encoder_params *)params; - } - - static void ch7006_encoder_destroy(struct drm_encoder *encoder) -@@ -114,7 +114,7 @@ static void ch7006_encoder_mode_set(struct drm_encoder *encoder, - { - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); - struct ch7006_priv *priv = to_ch7006_priv(encoder); -- struct ch7006_encoder_params *params = priv->params; -+ struct ch7006_encoder_params *params = &priv->params; - struct ch7006_state *state = &priv->state; - uint8_t *regs = state->regs; - struct ch7006_mode *mode = priv->mode; -@@ -428,6 +428,22 @@ static int ch7006_remove(struct i2c_client *client) - return 0; - } - -+static int ch7006_suspend(struct i2c_client *client, pm_message_t mesg) -+{ -+ ch7006_dbg(client, "\n"); -+ -+ return 0; -+} -+ -+static int ch7006_resume(struct i2c_client *client) -+{ -+ ch7006_dbg(client, "\n"); -+ -+ ch7006_write(client, 0x3d, 0x0); -+ -+ return 0; -+} -+ - static int ch7006_encoder_init(struct i2c_client *client, - struct drm_device *dev, - struct drm_encoder_slave *encoder) -@@ -487,6 +503,8 @@ static struct drm_i2c_encoder_driver ch7006_driver = { - .i2c_driver = { - .probe = ch7006_probe, - .remove = ch7006_remove, -+ .suspend = ch7006_suspend, -+ .resume = ch7006_resume, - - .driver = { - .name = "ch7006", -diff --git a/drivers/gpu/drm/i2c/ch7006_priv.h b/drivers/gpu/drm/i2c/ch7006_priv.h -index b06d3d9..1c6d2e3 100644 ---- a/drivers/gpu/drm/i2c/ch7006_priv.h -+++ b/drivers/gpu/drm/i2c/ch7006_priv.h -@@ -77,7 +77,7 @@ struct ch7006_state { - }; - - struct ch7006_priv { -- struct ch7006_encoder_params *params; -+ struct ch7006_encoder_params params; - struct ch7006_mode *mode; - - struct ch7006_state state; -diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile -index acd31ed..4a1db73 100644 ---- a/drivers/gpu/drm/nouveau/Makefile -+++ b/drivers/gpu/drm/nouveau/Makefile -@@ -9,7 +9,7 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ - nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \ - nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \ - nouveau_display.o nouveau_connector.o nouveau_fbcon.o \ -- nouveau_dp.o nouveau_grctx.o \ -+ nouveau_dp.o \ - nv04_timer.o \ - nv04_mc.o nv40_mc.o nv50_mc.o \ - nv04_fb.o nv10_fb.o nv40_fb.o nv50_fb.o \ -diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c -index d4bcca8..c17a055 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_acpi.c -+++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c -@@ -3,6 +3,7 @@ - #include - #include - #include -+#include - - #include "drmP.h" - #include "drm.h" -@@ -11,6 +12,7 @@ - #include "nouveau_drv.h" - #include "nouveau_drm.h" - #include "nv50_display.h" -+#include "nouveau_connector.h" - - #include - -@@ -42,7 +44,7 @@ static const char nouveau_dsm_muid[] = { - 0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4, - }; - --static int nouveau_dsm(acpi_handle handle, int func, int arg, int *result) -+static int nouveau_dsm(acpi_handle handle, int func, int arg, uint32_t *result) - { - struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; - struct acpi_object_list input; -@@ -259,3 +261,37 @@ int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len) - { - return nouveau_rom_call(nouveau_dsm_priv.rom_handle, bios, offset, len); - } -+ -+int -+nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) -+{ -+ struct nouveau_connector *nv_connector = nouveau_connector(connector); -+ struct acpi_device *acpidev; -+ acpi_handle handle; -+ int type, ret; -+ void *edid; -+ -+ switch (connector->connector_type) { -+ case DRM_MODE_CONNECTOR_LVDS: -+ case DRM_MODE_CONNECTOR_eDP: -+ type = ACPI_VIDEO_DISPLAY_LCD; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ handle = DEVICE_ACPI_HANDLE(&dev->pdev->dev); -+ if (!handle) -+ return -ENODEV; -+ -+ ret = acpi_bus_get_device(handle, &acpidev); -+ if (ret) -+ return -ENODEV; -+ -+ ret = acpi_video_get_edid(acpidev, type, -1, &edid); -+ if (ret < 0) -+ return ret; -+ -+ nv_connector->edid = edid; -+ return 0; -+} -diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c -index e492919..aae29cc 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_bios.c -+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c -@@ -28,6 +28,8 @@ - #include "nouveau_hw.h" - #include "nouveau_encoder.h" - -+#include -+ - /* these defines are made up */ - #define NV_CIO_CRE_44_HEADA 0x0 - #define NV_CIO_CRE_44_HEADB 0x3 -@@ -209,20 +211,20 @@ static struct methods shadow_methods[] = { - { "PCIROM", load_vbios_pci, true }, - { "ACPI", load_vbios_acpi, true }, - }; -+#define NUM_SHADOW_METHODS ARRAY_SIZE(shadow_methods) - - static bool NVShadowVBIOS(struct drm_device *dev, uint8_t *data) - { -- const int nr_methods = ARRAY_SIZE(shadow_methods); - struct methods *methods = shadow_methods; - int testscore = 3; -- int scores[nr_methods], i; -+ int scores[NUM_SHADOW_METHODS], i; - - if (nouveau_vbios) { -- for (i = 0; i < nr_methods; i++) -+ for (i = 0; i < NUM_SHADOW_METHODS; i++) - if (!strcasecmp(nouveau_vbios, methods[i].desc)) - break; - -- if (i < nr_methods) { -+ if (i < NUM_SHADOW_METHODS) { - NV_INFO(dev, "Attempting to use BIOS image from %s\n", - methods[i].desc); - -@@ -234,7 +236,7 @@ static bool NVShadowVBIOS(struct drm_device *dev, uint8_t *data) - NV_ERROR(dev, "VBIOS source \'%s\' invalid\n", nouveau_vbios); - } - -- for (i = 0; i < nr_methods; i++) { -+ for (i = 0; i < NUM_SHADOW_METHODS; i++) { - NV_TRACE(dev, "Attempting to load BIOS image from %s\n", - methods[i].desc); - data[0] = data[1] = 0; /* avoid reuse of previous image */ -@@ -245,7 +247,7 @@ static bool NVShadowVBIOS(struct drm_device *dev, uint8_t *data) - } - - while (--testscore > 0) { -- for (i = 0; i < nr_methods; i++) { -+ for (i = 0; i < NUM_SHADOW_METHODS; i++) { - if (scores[i] == testscore) { - NV_TRACE(dev, "Using BIOS image from %s\n", - methods[i].desc); -@@ -920,7 +922,7 @@ init_io_restrict_prog(struct nvbios *bios, uint16_t offset, - NV_ERROR(bios->dev, - "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n", - offset, config, count); -- return -EINVAL; -+ return len; - } - - configval = ROM32(bios->data[offset + 11 + config * 4]); -@@ -1022,7 +1024,7 @@ init_io_restrict_pll(struct nvbios *bios, uint16_t offset, - NV_ERROR(bios->dev, - "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n", - offset, config, count); -- return -EINVAL; -+ return len; - } - - freq = ROM16(bios->data[offset + 12 + config * 2]); -@@ -1194,7 +1196,7 @@ init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - dpe = nouveau_bios_dp_table(dev, dcb, &dummy); - if (!dpe) { - NV_ERROR(dev, "0x%04X: INIT_3A: no encoder table!!\n", offset); -- return -EINVAL; -+ return 3; - } - - switch (cond) { -@@ -1218,12 +1220,16 @@ init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - int ret; - - auxch = nouveau_i2c_find(dev, bios->display.output->i2c_index); -- if (!auxch) -- return -ENODEV; -+ if (!auxch) { -+ NV_ERROR(dev, "0x%04X: couldn't get auxch\n", offset); -+ return 3; -+ } - - ret = nouveau_dp_auxch(auxch, 9, 0xd, &cond, 1); -- if (ret) -- return ret; -+ if (ret) { -+ NV_ERROR(dev, "0x%04X: auxch rd fail: %d\n", offset, ret); -+ return 3; -+ } - - if (cond & 1) - iexec->execute = false; -@@ -1392,7 +1398,7 @@ init_io_restrict_pll2(struct nvbios *bios, uint16_t offset, - NV_ERROR(bios->dev, - "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n", - offset, config, count); -- return -EINVAL; -+ return len; - } - - freq = ROM32(bios->data[offset + 11 + config * 4]); -@@ -1452,6 +1458,7 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - * "mask n" and OR it with "data n" before writing it back to the device - */ - -+ struct drm_device *dev = bios->dev; - uint8_t i2c_index = bios->data[offset + 1]; - uint8_t i2c_address = bios->data[offset + 2] >> 1; - uint8_t count = bios->data[offset + 3]; -@@ -1466,9 +1473,11 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - "Count: 0x%02X\n", - offset, i2c_index, i2c_address, count); - -- chan = init_i2c_device_find(bios->dev, i2c_index); -- if (!chan) -- return -ENODEV; -+ chan = init_i2c_device_find(dev, i2c_index); -+ if (!chan) { -+ NV_ERROR(dev, "0x%04X: i2c bus not found\n", offset); -+ return len; -+ } - - for (i = 0; i < count; i++) { - uint8_t reg = bios->data[offset + 4 + i * 3]; -@@ -1479,8 +1488,10 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0, - I2C_SMBUS_READ, reg, - I2C_SMBUS_BYTE_DATA, &val); -- if (ret < 0) -- return ret; -+ if (ret < 0) { -+ NV_ERROR(dev, "0x%04X: i2c rd fail: %d\n", offset, ret); -+ return len; -+ } - - BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Value: 0x%02X, " - "Mask: 0x%02X, Data: 0x%02X\n", -@@ -1494,8 +1505,10 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0, - I2C_SMBUS_WRITE, reg, - I2C_SMBUS_BYTE_DATA, &val); -- if (ret < 0) -- return ret; -+ if (ret < 0) { -+ NV_ERROR(dev, "0x%04X: i2c wr fail: %d\n", offset, ret); -+ return len; -+ } - } - - return len; -@@ -1520,6 +1533,7 @@ init_zm_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - * "DCB I2C table entry index", set the register to "data n" - */ - -+ struct drm_device *dev = bios->dev; - uint8_t i2c_index = bios->data[offset + 1]; - uint8_t i2c_address = bios->data[offset + 2] >> 1; - uint8_t count = bios->data[offset + 3]; -@@ -1534,9 +1548,11 @@ init_zm_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - "Count: 0x%02X\n", - offset, i2c_index, i2c_address, count); - -- chan = init_i2c_device_find(bios->dev, i2c_index); -- if (!chan) -- return -ENODEV; -+ chan = init_i2c_device_find(dev, i2c_index); -+ if (!chan) { -+ NV_ERROR(dev, "0x%04X: i2c bus not found\n", offset); -+ return len; -+ } - - for (i = 0; i < count; i++) { - uint8_t reg = bios->data[offset + 4 + i * 2]; -@@ -1553,8 +1569,10 @@ init_zm_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0, - I2C_SMBUS_WRITE, reg, - I2C_SMBUS_BYTE_DATA, &val); -- if (ret < 0) -- return ret; -+ if (ret < 0) { -+ NV_ERROR(dev, "0x%04X: i2c wr fail: %d\n", offset, ret); -+ return len; -+ } - } - - return len; -@@ -1577,6 +1595,7 @@ init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - * address" on the I2C bus given by "DCB I2C table entry index" - */ - -+ struct drm_device *dev = bios->dev; - uint8_t i2c_index = bios->data[offset + 1]; - uint8_t i2c_address = bios->data[offset + 2] >> 1; - uint8_t count = bios->data[offset + 3]; -@@ -1584,7 +1603,7 @@ init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - struct nouveau_i2c_chan *chan; - struct i2c_msg msg; - uint8_t data[256]; -- int i; -+ int ret, i; - - if (!iexec->execute) - return len; -@@ -1593,9 +1612,11 @@ init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - "Count: 0x%02X\n", - offset, i2c_index, i2c_address, count); - -- chan = init_i2c_device_find(bios->dev, i2c_index); -- if (!chan) -- return -ENODEV; -+ chan = init_i2c_device_find(dev, i2c_index); -+ if (!chan) { -+ NV_ERROR(dev, "0x%04X: i2c bus not found\n", offset); -+ return len; -+ } - - for (i = 0; i < count; i++) { - data[i] = bios->data[offset + 4 + i]; -@@ -1608,8 +1629,11 @@ init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - msg.flags = 0; - msg.len = count; - msg.buf = data; -- if (i2c_transfer(&chan->adapter, &msg, 1) != 1) -- return -EIO; -+ ret = i2c_transfer(&chan->adapter, &msg, 1); -+ if (ret != 1) { -+ NV_ERROR(dev, "0x%04X: i2c wr fail: %d\n", offset, ret); -+ return len; -+ } - } - - return len; -@@ -1633,6 +1657,7 @@ init_tmds(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - * used -- see get_tmds_index_reg() - */ - -+ struct drm_device *dev = bios->dev; - uint8_t mlv = bios->data[offset + 1]; - uint32_t tmdsaddr = bios->data[offset + 2]; - uint8_t mask = bios->data[offset + 3]; -@@ -1647,8 +1672,10 @@ init_tmds(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - offset, mlv, tmdsaddr, mask, data); - - reg = get_tmds_index_reg(bios->dev, mlv); -- if (!reg) -- return -EINVAL; -+ if (!reg) { -+ NV_ERROR(dev, "0x%04X: no tmds_index_reg\n", offset); -+ return 5; -+ } - - bios_wr32(bios, reg, - tmdsaddr | NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE); -@@ -1678,6 +1705,7 @@ init_zm_tmds_group(struct nvbios *bios, uint16_t offset, - * register is used -- see get_tmds_index_reg() - */ - -+ struct drm_device *dev = bios->dev; - uint8_t mlv = bios->data[offset + 1]; - uint8_t count = bios->data[offset + 2]; - int len = 3 + count * 2; -@@ -1691,8 +1719,10 @@ init_zm_tmds_group(struct nvbios *bios, uint16_t offset, - offset, mlv, count); - - reg = get_tmds_index_reg(bios->dev, mlv); -- if (!reg) -- return -EINVAL; -+ if (!reg) { -+ NV_ERROR(dev, "0x%04X: no tmds_index_reg\n", offset); -+ return len; -+ } - - for (i = 0; i < count; i++) { - uint8_t tmdsaddr = bios->data[offset + 3 + i * 2]; -@@ -2039,6 +2069,323 @@ init_zm_index_io(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - return 5; - } - -+static inline void -+bios_md32(struct nvbios *bios, uint32_t reg, -+ uint32_t mask, uint32_t val) -+{ -+ bios_wr32(bios, reg, (bios_rd32(bios, reg) & ~mask) | val); -+} -+ -+static uint32_t -+peek_fb(struct drm_device *dev, struct io_mapping *fb, -+ uint32_t off) -+{ -+ uint32_t val = 0; -+ -+ if (off < pci_resource_len(dev->pdev, 1)) { -+ uint32_t __iomem *p = io_mapping_map_atomic_wc(fb, off); -+ -+ val = ioread32(p); -+ -+ io_mapping_unmap_atomic(p); -+ } -+ -+ return val; -+} -+ -+static void -+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 = io_mapping_map_atomic_wc(fb, off); -+ -+ iowrite32(val, p); -+ wmb(); -+ -+ io_mapping_unmap_atomic(p); -+ } -+} -+ -+static inline bool -+read_back_fb(struct drm_device *dev, struct io_mapping *fb, -+ uint32_t off, uint32_t val) -+{ -+ poke_fb(dev, fb, off, val); -+ return val == peek_fb(dev, fb, off); -+} -+ -+static int -+nv04_init_compute_mem(struct nvbios *bios) -+{ -+ struct drm_device *dev = bios->dev; -+ uint32_t patt = 0xdeadbeef; -+ struct io_mapping *fb; -+ int i; -+ -+ /* Map the framebuffer aperture */ -+ fb = io_mapping_create_wc(pci_resource_start(dev->pdev, 1), -+ pci_resource_len(dev->pdev, 1)); -+ if (!fb) -+ return -ENOMEM; -+ -+ /* Sequencer and refresh off */ -+ NVWriteVgaSeq(dev, 0, 1, NVReadVgaSeq(dev, 0, 1) | 0x20); -+ bios_md32(bios, NV04_PFB_DEBUG_0, 0, NV04_PFB_DEBUG_0_REFRESH_OFF); -+ -+ bios_md32(bios, NV04_PFB_BOOT_0, ~0, -+ NV04_PFB_BOOT_0_RAM_AMOUNT_16MB | -+ NV04_PFB_BOOT_0_RAM_WIDTH_128 | -+ NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT); -+ -+ for (i = 0; i < 4; i++) -+ poke_fb(dev, fb, 4 * i, patt); -+ -+ poke_fb(dev, fb, 0x400000, patt + 1); -+ -+ if (peek_fb(dev, fb, 0) == patt + 1) { -+ bios_md32(bios, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_TYPE, -+ NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_16MBIT); -+ bios_md32(bios, NV04_PFB_DEBUG_0, -+ NV04_PFB_DEBUG_0_REFRESH_OFF, 0); -+ -+ for (i = 0; i < 4; i++) -+ poke_fb(dev, fb, 4 * i, patt); -+ -+ if ((peek_fb(dev, fb, 0xc) & 0xffff) != (patt & 0xffff)) -+ bios_md32(bios, NV04_PFB_BOOT_0, -+ NV04_PFB_BOOT_0_RAM_WIDTH_128 | -+ NV04_PFB_BOOT_0_RAM_AMOUNT, -+ NV04_PFB_BOOT_0_RAM_AMOUNT_8MB); -+ -+ } else if ((peek_fb(dev, fb, 0xc) & 0xffff0000) != -+ (patt & 0xffff0000)) { -+ bios_md32(bios, NV04_PFB_BOOT_0, -+ NV04_PFB_BOOT_0_RAM_WIDTH_128 | -+ NV04_PFB_BOOT_0_RAM_AMOUNT, -+ NV04_PFB_BOOT_0_RAM_AMOUNT_4MB); -+ -+ } else if (peek_fb(dev, fb, 0) == patt) { -+ if (read_back_fb(dev, fb, 0x800000, patt)) -+ bios_md32(bios, NV04_PFB_BOOT_0, -+ NV04_PFB_BOOT_0_RAM_AMOUNT, -+ NV04_PFB_BOOT_0_RAM_AMOUNT_8MB); -+ else -+ bios_md32(bios, NV04_PFB_BOOT_0, -+ NV04_PFB_BOOT_0_RAM_AMOUNT, -+ NV04_PFB_BOOT_0_RAM_AMOUNT_4MB); -+ -+ bios_md32(bios, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_TYPE, -+ NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_8MBIT); -+ -+ } else if (!read_back_fb(dev, fb, 0x800000, patt)) { -+ bios_md32(bios, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, -+ NV04_PFB_BOOT_0_RAM_AMOUNT_8MB); -+ -+ } -+ -+ /* Refresh on, sequencer on */ -+ bios_md32(bios, NV04_PFB_DEBUG_0, NV04_PFB_DEBUG_0_REFRESH_OFF, 0); -+ NVWriteVgaSeq(dev, 0, 1, NVReadVgaSeq(dev, 0, 1) & ~0x20); -+ -+ io_mapping_free(fb); -+ return 0; -+} -+ -+static const uint8_t * -+nv05_memory_config(struct nvbios *bios) -+{ -+ /* Defaults for BIOSes lacking a memory config table */ -+ static const uint8_t default_config_tab[][2] = { -+ { 0x24, 0x00 }, -+ { 0x28, 0x00 }, -+ { 0x24, 0x01 }, -+ { 0x1f, 0x00 }, -+ { 0x0f, 0x00 }, -+ { 0x17, 0x00 }, -+ { 0x06, 0x00 }, -+ { 0x00, 0x00 } -+ }; -+ int i = (bios_rd32(bios, NV_PEXTDEV_BOOT_0) & -+ NV_PEXTDEV_BOOT_0_RAMCFG) >> 2; -+ -+ if (bios->legacy.mem_init_tbl_ptr) -+ return &bios->data[bios->legacy.mem_init_tbl_ptr + 2 * i]; -+ else -+ return default_config_tab[i]; -+} -+ -+static int -+nv05_init_compute_mem(struct nvbios *bios) -+{ -+ struct drm_device *dev = bios->dev; -+ const uint8_t *ramcfg = nv05_memory_config(bios); -+ uint32_t patt = 0xdeadbeef; -+ struct io_mapping *fb; -+ int i, v; -+ -+ /* Map the framebuffer aperture */ -+ fb = io_mapping_create_wc(pci_resource_start(dev->pdev, 1), -+ pci_resource_len(dev->pdev, 1)); -+ if (!fb) -+ return -ENOMEM; -+ -+ /* Sequencer off */ -+ NVWriteVgaSeq(dev, 0, 1, NVReadVgaSeq(dev, 0, 1) | 0x20); -+ -+ if (bios_rd32(bios, NV04_PFB_BOOT_0) & NV04_PFB_BOOT_0_UMA_ENABLE) -+ goto out; -+ -+ bios_md32(bios, NV04_PFB_DEBUG_0, NV04_PFB_DEBUG_0_REFRESH_OFF, 0); -+ -+ /* If present load the hardcoded scrambling table */ -+ if (bios->legacy.mem_init_tbl_ptr) { -+ uint32_t *scramble_tab = (uint32_t *)&bios->data[ -+ bios->legacy.mem_init_tbl_ptr + 0x10]; -+ -+ for (i = 0; i < 8; i++) -+ bios_wr32(bios, NV04_PFB_SCRAMBLE(i), -+ ROM32(scramble_tab[i])); -+ } -+ -+ /* Set memory type/width/length defaults depending on the straps */ -+ bios_md32(bios, NV04_PFB_BOOT_0, 0x3f, ramcfg[0]); -+ -+ if (ramcfg[1] & 0x80) -+ bios_md32(bios, NV04_PFB_CFG0, 0, NV04_PFB_CFG0_SCRAMBLE); -+ -+ bios_md32(bios, NV04_PFB_CFG1, 0x700001, (ramcfg[1] & 1) << 20); -+ bios_md32(bios, NV04_PFB_CFG1, 0, 1); -+ -+ /* Probe memory bus width */ -+ for (i = 0; i < 4; i++) -+ poke_fb(dev, fb, 4 * i, patt); -+ -+ if (peek_fb(dev, fb, 0xc) != patt) -+ bios_md32(bios, NV04_PFB_BOOT_0, -+ NV04_PFB_BOOT_0_RAM_WIDTH_128, 0); -+ -+ /* Probe memory length */ -+ v = bios_rd32(bios, NV04_PFB_BOOT_0) & NV04_PFB_BOOT_0_RAM_AMOUNT; -+ -+ if (v == NV04_PFB_BOOT_0_RAM_AMOUNT_32MB && -+ (!read_back_fb(dev, fb, 0x1000000, ++patt) || -+ !read_back_fb(dev, fb, 0, ++patt))) -+ bios_md32(bios, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, -+ NV04_PFB_BOOT_0_RAM_AMOUNT_16MB); -+ -+ if (v == NV04_PFB_BOOT_0_RAM_AMOUNT_16MB && -+ !read_back_fb(dev, fb, 0x800000, ++patt)) -+ bios_md32(bios, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, -+ NV04_PFB_BOOT_0_RAM_AMOUNT_8MB); -+ -+ if (!read_back_fb(dev, fb, 0x400000, ++patt)) -+ bios_md32(bios, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, -+ NV04_PFB_BOOT_0_RAM_AMOUNT_4MB); -+ -+out: -+ /* Sequencer on */ -+ NVWriteVgaSeq(dev, 0, 1, NVReadVgaSeq(dev, 0, 1) & ~0x20); -+ -+ io_mapping_free(fb); -+ return 0; -+} -+ -+static int -+nv10_init_compute_mem(struct nvbios *bios) -+{ -+ struct drm_device *dev = bios->dev; -+ struct drm_nouveau_private *dev_priv = bios->dev->dev_private; -+ const int mem_width[] = { 0x10, 0x00, 0x20 }; -+ const int mem_width_count = (dev_priv->chipset >= 0x17 ? 3 : 2); -+ uint32_t patt = 0xdeadbeef; -+ struct io_mapping *fb; -+ int i, j, k; -+ -+ /* Map the framebuffer aperture */ -+ fb = io_mapping_create_wc(pci_resource_start(dev->pdev, 1), -+ pci_resource_len(dev->pdev, 1)); -+ if (!fb) -+ return -ENOMEM; -+ -+ bios_wr32(bios, NV10_PFB_REFCTRL, NV10_PFB_REFCTRL_VALID_1); -+ -+ /* Probe memory bus width */ -+ for (i = 0; i < mem_width_count; i++) { -+ bios_md32(bios, NV04_PFB_CFG0, 0x30, mem_width[i]); -+ -+ for (j = 0; j < 4; j++) { -+ for (k = 0; k < 4; k++) -+ poke_fb(dev, fb, 0x1c, 0); -+ -+ poke_fb(dev, fb, 0x1c, patt); -+ poke_fb(dev, fb, 0x3c, 0); -+ -+ if (peek_fb(dev, fb, 0x1c) == patt) -+ goto mem_width_found; -+ } -+ } -+ -+mem_width_found: -+ patt <<= 1; -+ -+ /* Probe amount of installed memory */ -+ for (i = 0; i < 4; i++) { -+ int off = bios_rd32(bios, NV04_PFB_FIFO_DATA) - 0x100000; -+ -+ poke_fb(dev, fb, off, patt); -+ poke_fb(dev, fb, 0, 0); -+ -+ peek_fb(dev, fb, 0); -+ peek_fb(dev, fb, 0); -+ peek_fb(dev, fb, 0); -+ peek_fb(dev, fb, 0); -+ -+ if (peek_fb(dev, fb, off) == patt) -+ goto amount_found; -+ } -+ -+ /* IC missing - disable the upper half memory space. */ -+ bios_md32(bios, NV04_PFB_CFG0, 0x1000, 0); -+ -+amount_found: -+ io_mapping_free(fb); -+ return 0; -+} -+ -+static int -+nv20_init_compute_mem(struct nvbios *bios) -+{ -+ struct drm_device *dev = bios->dev; -+ struct drm_nouveau_private *dev_priv = bios->dev->dev_private; -+ uint32_t mask = (dev_priv->chipset >= 0x25 ? 0x300 : 0x900); -+ uint32_t amount, off; -+ struct io_mapping *fb; -+ -+ /* Map the framebuffer aperture */ -+ fb = io_mapping_create_wc(pci_resource_start(dev->pdev, 1), -+ pci_resource_len(dev->pdev, 1)); -+ if (!fb) -+ return -ENOMEM; -+ -+ bios_wr32(bios, NV10_PFB_REFCTRL, NV10_PFB_REFCTRL_VALID_1); -+ -+ /* Allow full addressing */ -+ bios_md32(bios, NV04_PFB_CFG0, 0, mask); -+ -+ amount = bios_rd32(bios, NV04_PFB_FIFO_DATA); -+ for (off = amount; off > 0x2000000; off -= 0x2000000) -+ poke_fb(dev, fb, off - 4, off); -+ -+ amount = bios_rd32(bios, NV04_PFB_FIFO_DATA); -+ if (amount != peek_fb(dev, fb, amount - 4)) -+ /* IC missing - disable the upper half memory space. */ -+ bios_md32(bios, NV04_PFB_CFG0, mask, 0); -+ -+ io_mapping_free(fb); -+ return 0; -+} -+ - static int - init_compute_mem(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - { -@@ -2047,64 +2394,57 @@ init_compute_mem(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - * - * offset (8 bit): opcode - * -- * This opcode is meant to set NV_PFB_CFG0 (0x100200) appropriately so -- * that the hardware can correctly calculate how much VRAM it has -- * (and subsequently report that value in NV_PFB_CSTATUS (0x10020C)) -+ * This opcode is meant to set the PFB memory config registers -+ * appropriately so that we can correctly calculate how much VRAM it -+ * has (on nv10 and better chipsets the amount of installed VRAM is -+ * subsequently reported in NV_PFB_CSTATUS (0x10020C)). - * -- * The implementation of this opcode in general consists of two parts: -- * 1) determination of the memory bus width -- * 2) determination of how many of the card's RAM pads have ICs attached -+ * The implementation of this opcode in general consists of several -+ * parts: - * -- * 1) is done by a cunning combination of writes to offsets 0x1c and -- * 0x3c in the framebuffer, and seeing whether the written values are -- * read back correctly. This then affects bits 4-7 of NV_PFB_CFG0 -+ * 1) Determination of memory type and density. Only necessary for -+ * really old chipsets, the memory type reported by the strap bits -+ * (0x101000) is assumed to be accurate on nv05 and newer. - * -- * 2) is done by a cunning combination of writes to an offset slightly -- * less than the maximum memory reported by NV_PFB_CSTATUS, then seeing -- * if the test pattern can be read back. This then affects bits 12-15 of -- * NV_PFB_CFG0 -+ * 2) Determination of the memory bus width. Usually done by a cunning -+ * combination of writes to offsets 0x1c and 0x3c in the fb, and -+ * seeing whether the written values are read back correctly. - * -- * In this context a "cunning combination" may include multiple reads -- * and writes to varying locations, often alternating the test pattern -- * and 0, doubtless to make sure buffers are filled, residual charges -- * on tracks are removed etc. -+ * Only necessary on nv0x-nv1x and nv34, on the other cards we can -+ * trust the straps. - * -- * Unfortunately, the "cunning combination"s mentioned above, and the -- * changes to the bits in NV_PFB_CFG0 differ with nearly every bios -- * trace I have. -+ * 3) Determination of how many of the card's RAM pads have ICs -+ * attached, usually done by a cunning combination of writes to an -+ * offset slightly less than the maximum memory reported by -+ * NV_PFB_CSTATUS, then seeing if the test pattern can be read back. - * -- * Therefore, we cheat and assume the value of NV_PFB_CFG0 with which -- * we started was correct, and use that instead -+ * This appears to be a NOP on IGPs and NV4x or newer chipsets, both io -+ * logs of the VBIOS and kmmio traces of the binary driver POSTing the -+ * card show nothing being done for this opcode. Why is it still listed -+ * in the table?! - */ - - /* no iexec->execute check by design */ - -- /* -- * This appears to be a NOP on G8x chipsets, both io logs of the VBIOS -- * and kmmio traces of the binary driver POSTing the card show nothing -- * being done for this opcode. why is it still listed in the table?! -- */ -- - struct drm_nouveau_private *dev_priv = bios->dev->dev_private; -+ int ret; - -- if (dev_priv->card_type >= NV_40) -- return 1; -- -- /* -- * On every card I've seen, this step gets done for us earlier in -- * the init scripts -- uint8_t crdata = bios_idxprt_rd(dev, NV_VIO_SRX, 0x01); -- bios_idxprt_wr(dev, NV_VIO_SRX, 0x01, crdata | 0x20); -- */ -- -- /* -- * This also has probably been done in the scripts, but an mmio trace of -- * s3 resume shows nvidia doing it anyway (unlike the NV_VIO_SRX write) -- */ -- bios_wr32(bios, NV_PFB_REFCTRL, NV_PFB_REFCTRL_VALID_1); -+ if (dev_priv->chipset >= 0x40 || -+ dev_priv->chipset == 0x1a || -+ dev_priv->chipset == 0x1f) -+ ret = 0; -+ else if (dev_priv->chipset >= 0x20 && -+ dev_priv->chipset != 0x34) -+ ret = nv20_init_compute_mem(bios); -+ else if (dev_priv->chipset >= 0x10) -+ ret = nv10_init_compute_mem(bios); -+ else if (dev_priv->chipset >= 0x5) -+ ret = nv05_init_compute_mem(bios); -+ else -+ ret = nv04_init_compute_mem(bios); - -- /* write back the saved configuration value */ -- bios_wr32(bios, NV_PFB_CFG0, bios->state.saved_nv_pfb_cfg0); -+ if (ret) -+ return ret; - - return 1; - } -@@ -2131,7 +2471,8 @@ init_reset(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - /* no iexec->execute check by design */ - - pci_nv_19 = bios_rd32(bios, NV_PBUS_PCI_NV_19); -- bios_wr32(bios, NV_PBUS_PCI_NV_19, 0); -+ bios_wr32(bios, NV_PBUS_PCI_NV_19, pci_nv_19 & ~0xf00); -+ - bios_wr32(bios, reg, value1); - - udelay(10); -@@ -2167,7 +2508,7 @@ init_configure_mem(struct nvbios *bios, uint16_t offset, - uint32_t reg, data; - - if (bios->major_version > 2) -- return -ENODEV; -+ return 0; - - bios_idxprt_wr(bios, NV_VIO_SRX, NV_VIO_SR_CLOCK_INDEX, bios_idxprt_rd( - bios, NV_VIO_SRX, NV_VIO_SR_CLOCK_INDEX) | 0x20); -@@ -2180,14 +2521,14 @@ init_configure_mem(struct nvbios *bios, uint16_t offset, - reg = ROM32(bios->data[seqtbloffs += 4])) { - - switch (reg) { -- case NV_PFB_PRE: -- data = NV_PFB_PRE_CMD_PRECHARGE; -+ case NV04_PFB_PRE: -+ data = NV04_PFB_PRE_CMD_PRECHARGE; - break; -- case NV_PFB_PAD: -- data = NV_PFB_PAD_CKE_NORMAL; -+ case NV04_PFB_PAD: -+ data = NV04_PFB_PAD_CKE_NORMAL; - break; -- case NV_PFB_REF: -- data = NV_PFB_REF_CMD_REFRESH; -+ case NV04_PFB_REF: -+ data = NV04_PFB_REF_CMD_REFRESH; - break; - default: - data = ROM32(bios->data[meminitdata]); -@@ -2222,7 +2563,7 @@ init_configure_clk(struct nvbios *bios, uint16_t offset, - int clock; - - if (bios->major_version > 2) -- return -ENODEV; -+ return 0; - - clock = ROM16(bios->data[meminitoffs + 4]) * 10; - setPLL(bios, NV_PRAMDAC_NVPLL_COEFF, clock); -@@ -2255,7 +2596,7 @@ init_configure_preinit(struct nvbios *bios, uint16_t offset, - uint8_t cr3c = ((straps << 2) & 0xf0) | (straps & (1 << 6)); - - if (bios->major_version > 2) -- return -ENODEV; -+ return 0; - - bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, - NV_CIO_CRE_SCRATCH4__INDEX, cr3c); -@@ -2389,7 +2730,7 @@ init_ram_condition(struct nvbios *bios, uint16_t offset, - * offset + 1 (8 bit): mask - * offset + 2 (8 bit): cmpval - * -- * Test if (NV_PFB_BOOT_0 & "mask") equals "cmpval". -+ * Test if (NV04_PFB_BOOT_0 & "mask") equals "cmpval". - * If condition not met skip subsequent opcodes until condition is - * inverted (INIT_NOT), or we hit INIT_RESUME - */ -@@ -2401,7 +2742,7 @@ init_ram_condition(struct nvbios *bios, uint16_t offset, - if (!iexec->execute) - return 3; - -- data = bios_rd32(bios, NV_PFB_BOOT_0) & mask; -+ data = bios_rd32(bios, NV04_PFB_BOOT_0) & mask; - - BIOSLOG(bios, "0x%04X: Checking if 0x%08X equals 0x%08X\n", - offset, data, cmpval); -@@ -2800,7 +3141,7 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - - if (dev_priv->card_type != NV_50) { - NV_ERROR(bios->dev, "INIT_GPIO on unsupported chipset\n"); -- return -ENODEV; -+ return 1; - } - - if (!iexec->execute) -@@ -2872,10 +3213,7 @@ init_ram_restrict_zm_reg_group(struct nvbios *bios, uint16_t offset, - uint8_t index; - int i; - -- -- if (!iexec->execute) -- return len; -- -+ /* critical! to know the length of the opcode */; - if (!blocklen) { - NV_ERROR(bios->dev, - "0x%04X: Zero block length - has the M table " -@@ -2883,6 +3221,9 @@ init_ram_restrict_zm_reg_group(struct nvbios *bios, uint16_t offset, - return -EINVAL; - } - -+ if (!iexec->execute) -+ return len; -+ - strap_ramcfg = (bios_rd32(bios, NV_PEXTDEV_BOOT_0) >> 2) & 0xf; - index = bios->data[bios->ram_restrict_tbl_ptr + strap_ramcfg]; - -@@ -3064,14 +3405,14 @@ init_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - - if (!bios->display.output) { - NV_ERROR(dev, "INIT_AUXCH: no active output\n"); -- return -EINVAL; -+ return len; - } - - auxch = init_i2c_device_find(dev, bios->display.output->i2c_index); - if (!auxch) { - NV_ERROR(dev, "INIT_AUXCH: couldn't get auxch %d\n", - bios->display.output->i2c_index); -- return -ENODEV; -+ return len; - } - - if (!iexec->execute) -@@ -3084,7 +3425,7 @@ init_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - ret = nouveau_dp_auxch(auxch, 9, addr, &data, 1); - if (ret) { - NV_ERROR(dev, "INIT_AUXCH: rd auxch fail %d\n", ret); -- return ret; -+ return len; - } - - data &= bios->data[offset + 0]; -@@ -3093,7 +3434,7 @@ init_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - ret = nouveau_dp_auxch(auxch, 8, addr, &data, 1); - if (ret) { - NV_ERROR(dev, "INIT_AUXCH: wr auxch fail %d\n", ret); -- return ret; -+ return len; - } - } - -@@ -3123,14 +3464,14 @@ init_zm_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - - if (!bios->display.output) { - NV_ERROR(dev, "INIT_ZM_AUXCH: no active output\n"); -- return -EINVAL; -+ return len; - } - - auxch = init_i2c_device_find(dev, bios->display.output->i2c_index); - if (!auxch) { - NV_ERROR(dev, "INIT_ZM_AUXCH: couldn't get auxch %d\n", - bios->display.output->i2c_index); -- return -ENODEV; -+ return len; - } - - if (!iexec->execute) -@@ -3141,7 +3482,7 @@ init_zm_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - ret = nouveau_dp_auxch(auxch, 8, addr, &bios->data[offset], 1); - if (ret) { - NV_ERROR(dev, "INIT_ZM_AUXCH: wr auxch fail %d\n", ret); -- return ret; -+ return len; - } - } - -@@ -5151,10 +5492,14 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi - bios->legacy.i2c_indices.crt = bios->data[legacy_i2c_offset]; - bios->legacy.i2c_indices.tv = bios->data[legacy_i2c_offset + 1]; - bios->legacy.i2c_indices.panel = bios->data[legacy_i2c_offset + 2]; -- bios->dcb.i2c[0].write = bios->data[legacy_i2c_offset + 4]; -- bios->dcb.i2c[0].read = bios->data[legacy_i2c_offset + 5]; -- bios->dcb.i2c[1].write = bios->data[legacy_i2c_offset + 6]; -- bios->dcb.i2c[1].read = bios->data[legacy_i2c_offset + 7]; -+ if (bios->data[legacy_i2c_offset + 4]) -+ bios->dcb.i2c[0].write = bios->data[legacy_i2c_offset + 4]; -+ if (bios->data[legacy_i2c_offset + 5]) -+ bios->dcb.i2c[0].read = bios->data[legacy_i2c_offset + 5]; -+ if (bios->data[legacy_i2c_offset + 6]) -+ bios->dcb.i2c[1].write = bios->data[legacy_i2c_offset + 6]; -+ if (bios->data[legacy_i2c_offset + 7]) -+ bios->dcb.i2c[1].read = bios->data[legacy_i2c_offset + 7]; - - if (bmplength > 74) { - bios->fmaxvco = ROM32(bmp[67]); -@@ -5589,9 +5934,12 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, - if (conf & 0x4 || conf & 0x8) - entry->lvdsconf.use_power_scripts = true; - } else { -- mask = ~0x5; -+ mask = ~0x7; -+ if (conf & 0x2) -+ entry->lvdsconf.use_acpi_for_edid = true; - if (conf & 0x4) - entry->lvdsconf.use_power_scripts = true; -+ entry->lvdsconf.sor.link = (conf & 0x00000030) >> 4; - } - if (conf & mask) { - /* -@@ -5706,13 +6054,6 @@ parse_dcb15_entry(struct drm_device *dev, struct dcb_table *dcb, - case OUTPUT_TV: - entry->tvconf.has_component_output = false; - break; -- case OUTPUT_TMDS: -- /* -- * Invent a DVI-A output, by copying the fields of the DVI-D -- * output; reported to work by math_b on an NV20(!). -- */ -- fabricate_vga_output(dcb, entry->i2c_index, entry->heads); -- break; - case OUTPUT_LVDS: - if ((conn & 0x00003f00) != 0x10) - entry->lvdsconf.use_straps_for_mode = true; -@@ -5793,6 +6134,31 @@ void merge_like_dcb_entries(struct drm_device *dev, struct dcb_table *dcb) - dcb->entries = newentries; - } - -+static bool -+apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf) -+{ -+ /* Dell Precision M6300 -+ * DCB entry 2: 02025312 00000010 -+ * DCB entry 3: 02026312 00000020 -+ * -+ * Identical, except apparently a different connector on a -+ * different SOR link. Not a clue how we're supposed to know -+ * which one is in use if it even shares an i2c line... -+ * -+ * Ignore the connector on the second SOR link to prevent -+ * nasty problems until this is sorted (assuming it's not a -+ * VBIOS bug). -+ */ -+ if ((dev->pdev->device == 0x040d) && -+ (dev->pdev->subsystem_vendor == 0x1028) && -+ (dev->pdev->subsystem_device == 0x019b)) { -+ if (*conn == 0x02026312 && *conf == 0x00000020) -+ return false; -+ } -+ -+ return true; -+} -+ - static int - parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads) - { -@@ -5926,6 +6292,9 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads) - if ((connection & 0x0000000f) == 0x0000000f) - continue; - -+ if (!apply_dcb_encoder_quirks(dev, i, &connection, &config)) -+ continue; -+ - NV_TRACEWARN(dev, "Raw DCB entry %d: %08x %08x\n", - dcb->entries, connection, config); - -@@ -6182,8 +6551,10 @@ nouveau_run_vbios_init(struct drm_device *dev) - int i, ret = 0; - - NVLockVgaCrtcs(dev, false); -- if (nv_two_heads(dev)) -- NVSetOwner(dev, bios->state.crtchead); -+ if (nv_two_heads(dev)) { -+ bios->state.crtchead = 0; -+ NVSetOwner(dev, 0); -+ } - - if (bios->major_version < 5) /* BMP only */ - load_nv17_hw_sequencer_ucode(dev, bios); -@@ -6238,7 +6609,6 @@ 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) { -@@ -6248,13 +6618,14 @@ nouveau_bios_posted(struct drm_device *dev) - return true; - } - -- was_locked = NVLockVgaCrtcs(dev, false); -+ 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); -+ NVLockVgaCrtcs(dev, true); -+ - return (htotal != 0); - } - -@@ -6263,8 +6634,6 @@ nouveau_bios_init(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; -- uint32_t saved_nv_pextdev_boot_0; -- bool was_locked; - int ret; - - if (!NVInitVBIOS(dev)) -@@ -6284,40 +6653,29 @@ nouveau_bios_init(struct drm_device *dev) - if (!bios->major_version) /* we don't run version 0 bios */ - return 0; - -- /* these will need remembering across a suspend */ -- saved_nv_pextdev_boot_0 = bios_rd32(bios, NV_PEXTDEV_BOOT_0); -- bios->state.saved_nv_pfb_cfg0 = bios_rd32(bios, NV_PFB_CFG0); -- - /* init script execution disabled */ - bios->execute = false; - - /* ... unless card isn't POSTed already */ - if (!nouveau_bios_posted(dev)) { -- NV_INFO(dev, "Adaptor not initialised\n"); -- if (dev_priv->card_type < NV_40) { -- NV_ERROR(dev, "Unable to POST this chipset\n"); -- return -ENODEV; -- } -- -- NV_INFO(dev, "Running VBIOS init tables\n"); -+ NV_INFO(dev, "Adaptor not initialised, " -+ "running VBIOS init tables.\n"); - bios->execute = true; - } - -- bios_wr32(bios, NV_PEXTDEV_BOOT_0, saved_nv_pextdev_boot_0); -- - ret = nouveau_run_vbios_init(dev); - if (ret) - return ret; - - /* feature_byte on BMP is poor, but init always sets CR4B */ -- was_locked = NVLockVgaCrtcs(dev, false); -+ NVLockVgaCrtcs(dev, false); - if (bios->major_version < 5) - bios->is_mobile = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_4B) & 0x40; - - /* all BIT systems need p_f_m_t for digital_min_front_porch */ - if (bios->is_mobile || bios->major_version >= 5) - ret = parse_fp_mode_table(dev, bios); -- NVLockVgaCrtcs(dev, was_locked); -+ NVLockVgaCrtcs(dev, true); - - /* allow subsequent scripts to execute */ - bios->execute = true; -diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h -index adf4ec2..024458a 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_bios.h -+++ b/drivers/gpu/drm/nouveau/nouveau_bios.h -@@ -81,6 +81,7 @@ struct dcb_connector_table_entry { - enum dcb_connector_type type; - uint8_t index2; - uint8_t gpio_tag; -+ void *drm; - }; - - struct dcb_connector_table { -@@ -117,6 +118,7 @@ struct dcb_entry { - struct { - struct sor_conf sor; - bool use_straps_for_mode; -+ bool use_acpi_for_edid; - bool use_power_scripts; - } lvdsconf; - struct { -@@ -249,8 +251,6 @@ struct nvbios { - - struct { - int crtchead; -- /* these need remembering across suspend */ -- uint32_t saved_nv_pfb_cfg0; - } state; - - struct { -diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c -index 6f3c195..d8c341d 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_bo.c -+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c -@@ -461,9 +461,9 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan, - return ret; - - ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL, -- evict, no_wait_reserve, no_wait_gpu, new_mem); -- if (nvbo->channel && nvbo->channel != chan) -- ret = nouveau_fence_wait(fence, NULL, false, false); -+ evict || (nvbo->channel && -+ nvbo->channel != chan), -+ no_wait_reserve, no_wait_gpu, new_mem); - nouveau_fence_unref((void *)&fence); - return ret; - } -@@ -711,8 +711,7 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr, - return ret; - - /* Software copy if the card isn't up and running yet. */ -- if (dev_priv->init_state != NOUVEAU_CARD_INIT_DONE || -- !dev_priv->channel) { -+ if (!dev_priv->channel) { - ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); - goto out; - } -diff --git a/drivers/gpu/drm/nouveau/nouveau_calc.c b/drivers/gpu/drm/nouveau/nouveau_calc.c -index 88f9bc0..ca85da7 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_calc.c -+++ b/drivers/gpu/drm/nouveau/nouveau_calc.c -@@ -200,7 +200,7 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp, - struct nv_sim_state sim_data; - int MClk = nouveau_hw_get_clock(dev, MPLL); - int NVClk = nouveau_hw_get_clock(dev, NVPLL); -- uint32_t cfg1 = nvReadFB(dev, NV_PFB_CFG1); -+ uint32_t cfg1 = nvReadFB(dev, NV04_PFB_CFG1); - - sim_data.pclk_khz = VClk; - sim_data.mclk_khz = MClk; -@@ -218,7 +218,7 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp, - sim_data.mem_latency = 3; - sim_data.mem_page_miss = 10; - } else { -- sim_data.memory_type = nvReadFB(dev, NV_PFB_CFG0) & 0x1; -+ sim_data.memory_type = nvReadFB(dev, NV04_PFB_CFG0) & 0x1; - sim_data.memory_width = (nvReadEXTDEV(dev, NV_PEXTDEV_BOOT_0) & 0x10) ? 128 : 64; - sim_data.mem_latency = cfg1 & 0xf; - sim_data.mem_page_miss = ((cfg1 >> 4) & 0xf) + ((cfg1 >> 31) & 0x1); -diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c -index 1fc57ef..e952c3b 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_channel.c -+++ b/drivers/gpu/drm/nouveau/nouveau_channel.c -@@ -257,9 +257,7 @@ nouveau_channel_free(struct nouveau_channel *chan) - nouveau_debugfs_channel_fini(chan); - - /* Give outstanding push buffers a chance to complete */ -- spin_lock_irqsave(&chan->fence.lock, flags); - nouveau_fence_update(chan); -- spin_unlock_irqrestore(&chan->fence.lock, flags); - if (chan->fence.sequence != chan->fence.sequence_ack) { - struct nouveau_fence *fence = NULL; - -@@ -368,8 +366,6 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, - struct nouveau_channel *chan; - int ret; - -- NOUVEAU_CHECK_INITIALISED_WITH_RETURN; -- - if (dev_priv->engine.graph.accel_blocked) - return -ENODEV; - -@@ -418,7 +414,6 @@ nouveau_ioctl_fifo_free(struct drm_device *dev, void *data, - struct drm_nouveau_channel_free *cfree = data; - struct nouveau_channel *chan; - -- NOUVEAU_CHECK_INITIALISED_WITH_RETURN; - NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(cfree->channel, file_priv, chan); - - nouveau_channel_free(chan); -diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c -index 149ed22..734e926 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_connector.c -+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c -@@ -102,63 +102,15 @@ nouveau_connector_destroy(struct drm_connector *drm_connector) - kfree(drm_connector); - } - --static void --nouveau_connector_ddc_prepare(struct drm_connector *connector, int *flags) --{ -- struct drm_nouveau_private *dev_priv = connector->dev->dev_private; -- -- if (dev_priv->card_type >= NV_50) -- return; -- -- *flags = 0; -- if (NVLockVgaCrtcs(dev_priv->dev, false)) -- *flags |= 1; -- if (nv_heads_tied(dev_priv->dev)) -- *flags |= 2; -- -- if (*flags & 2) -- NVSetOwner(dev_priv->dev, 0); /* necessary? */ --} -- --static void --nouveau_connector_ddc_finish(struct drm_connector *connector, int flags) --{ -- struct drm_nouveau_private *dev_priv = connector->dev->dev_private; -- -- if (dev_priv->card_type >= NV_50) -- return; -- -- if (flags & 2) -- NVSetOwner(dev_priv->dev, 4); -- if (flags & 1) -- NVLockVgaCrtcs(dev_priv->dev, true); --} -- - static struct nouveau_i2c_chan * - nouveau_connector_ddc_detect(struct drm_connector *connector, - struct nouveau_encoder **pnv_encoder) - { - struct drm_device *dev = connector->dev; -- uint8_t out_buf[] = { 0x0, 0x0}, buf[2]; -- int ret, flags, i; -- -- struct i2c_msg msgs[] = { -- { -- .addr = 0x50, -- .flags = 0, -- .len = 1, -- .buf = out_buf, -- }, -- { -- .addr = 0x50, -- .flags = I2C_M_RD, -- .len = 1, -- .buf = buf, -- } -- }; -+ int i; - - for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { -- struct nouveau_i2c_chan *i2c = NULL; -+ struct nouveau_i2c_chan *i2c; - struct nouveau_encoder *nv_encoder; - struct drm_mode_object *obj; - int id; -@@ -171,17 +123,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) -- continue; -- -- nouveau_connector_ddc_prepare(connector, &flags); -- ret = i2c_transfer(&i2c->adapter, msgs, 2); -- nouveau_connector_ddc_finish(connector, flags); -- -- if (ret == 2) { -+ if (i2c && nouveau_probe_i2c_addr(i2c, 0x50)) { - *pnv_encoder = nv_encoder; - return i2c; - } -@@ -234,21 +178,7 @@ nouveau_connector_detect(struct drm_connector *connector) - struct nouveau_connector *nv_connector = nouveau_connector(connector); - struct nouveau_encoder *nv_encoder = NULL; - struct nouveau_i2c_chan *i2c; -- int type, flags; -- -- if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS) -- nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS); -- if (nv_encoder && nv_connector->native_mode) { -- unsigned status = connector_status_connected; -- --#if defined(CONFIG_ACPI_BUTTON) || \ -- (defined(CONFIG_ACPI_BUTTON_MODULE) && defined(MODULE)) -- if (!nouveau_ignorelid && !acpi_lid_open()) -- status = connector_status_unknown; --#endif -- nouveau_connector_set_encoder(connector, nv_encoder); -- return status; -- } -+ int type; - - /* Cleanup the previous EDID block. */ - if (nv_connector->edid) { -@@ -259,9 +189,7 @@ nouveau_connector_detect(struct drm_connector *connector) - - i2c = nouveau_connector_ddc_detect(connector, &nv_encoder); - if (i2c) { -- nouveau_connector_ddc_prepare(connector, &flags); - nv_connector->edid = drm_get_edid(connector, &i2c->adapter); -- nouveau_connector_ddc_finish(connector, flags); - drm_mode_connector_update_edid_property(connector, - nv_connector->edid); - if (!nv_connector->edid) { -@@ -321,6 +249,85 @@ detect_analog: - return connector_status_disconnected; - } - -+static enum drm_connector_status -+nouveau_connector_detect_lvds(struct drm_connector *connector) -+{ -+ struct drm_device *dev = connector->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_connector *nv_connector = nouveau_connector(connector); -+ struct nouveau_encoder *nv_encoder = NULL; -+ enum drm_connector_status status = connector_status_disconnected; -+ -+ /* Cleanup the previous EDID block. */ -+ if (nv_connector->edid) { -+ drm_mode_connector_update_edid_property(connector, NULL); -+ kfree(nv_connector->edid); -+ nv_connector->edid = NULL; -+ } -+ -+ nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS); -+ if (!nv_encoder) -+ return connector_status_disconnected; -+ -+ /* Try retrieving EDID via DDC */ -+ if (!dev_priv->vbios.fp_no_ddc) { -+ status = nouveau_connector_detect(connector); -+ if (status == connector_status_connected) -+ goto out; -+ } -+ -+ /* On some laptops (Sony, i'm looking at you) there appears to -+ * be no direct way of accessing the panel's EDID. The only -+ * option available to us appears to be to ask ACPI for help.. -+ * -+ * It's important this check's before trying straps, one of the -+ * said manufacturer's laptops are configured in such a way -+ * the nouveau decides an entry in the VBIOS FP mode table is -+ * valid - it's not (rh#613284) -+ */ -+ if (nv_encoder->dcb->lvdsconf.use_acpi_for_edid) { -+ if (!nouveau_acpi_edid(dev, connector)) { -+ status = connector_status_connected; -+ goto out; -+ } -+ } -+ -+ /* If no EDID found above, and the VBIOS indicates a hardcoded -+ * modeline is avalilable for the panel, set it as the panel's -+ * native mode and exit. -+ */ -+ if (nouveau_bios_fp_mode(dev, NULL) && (dev_priv->vbios.fp_no_ddc || -+ nv_encoder->dcb->lvdsconf.use_straps_for_mode)) { -+ status = connector_status_connected; -+ goto out; -+ } -+ -+ /* Still nothing, some VBIOS images have a hardcoded EDID block -+ * stored for the panel stored in them. -+ */ -+ if (!dev_priv->vbios.fp_no_ddc) { -+ struct edid *edid = -+ (struct edid *)nouveau_bios_embedded_edid(dev); -+ if (edid) { -+ nv_connector->edid = kmalloc(EDID_LENGTH, GFP_KERNEL); -+ *(nv_connector->edid) = *edid; -+ status = connector_status_connected; -+ } -+ } -+ -+out: -+#if defined(CONFIG_ACPI_BUTTON) || \ -+ (defined(CONFIG_ACPI_BUTTON_MODULE) && defined(MODULE)) -+ if (status == connector_status_connected && -+ !nouveau_ignorelid && !acpi_lid_open()) -+ status = connector_status_unknown; -+#endif -+ -+ drm_mode_connector_update_edid_property(connector, nv_connector->edid); -+ nouveau_connector_set_encoder(connector, nv_encoder); -+ return status; -+} -+ - static void - nouveau_connector_force(struct drm_connector *connector) - { -@@ -441,7 +448,8 @@ nouveau_connector_native_mode(struct drm_connector *connector) - int high_w = 0, high_h = 0, high_v = 0; - - list_for_each_entry(mode, &nv_connector->base.probed_modes, head) { -- if (helper->mode_valid(connector, mode) != MODE_OK) -+ if (helper->mode_valid(connector, mode) != MODE_OK || -+ (mode->flags & DRM_MODE_FLAG_INTERLACE)) - continue; - - /* Use preferred mode if there is one.. */ -@@ -534,21 +542,27 @@ static int - nouveau_connector_get_modes(struct drm_connector *connector) - { - struct drm_device *dev = connector->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_connector *nv_connector = nouveau_connector(connector); - struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; - int ret = 0; - -- /* If we're not LVDS, destroy the previous native mode, the attached -- * monitor could have changed. -+ /* destroy the native mode, the attached monitor could have changed. - */ -- if (nv_connector->dcb->type != DCB_CONNECTOR_LVDS && -- nv_connector->native_mode) { -+ if (nv_connector->native_mode) { - drm_mode_destroy(dev, nv_connector->native_mode); - nv_connector->native_mode = NULL; - } - - if (nv_connector->edid) - ret = drm_add_edid_modes(connector, nv_connector->edid); -+ else -+ if (nv_encoder->dcb->type == OUTPUT_LVDS && -+ (nv_encoder->dcb->lvdsconf.use_straps_for_mode || -+ dev_priv->vbios.fp_no_ddc) && nouveau_bios_fp_mode(dev, NULL)) { -+ nv_connector->native_mode = drm_mode_create(dev); -+ nouveau_bios_fp_mode(dev, nv_connector->native_mode); -+ } - - /* Find the native mode if this is a digital panel, if we didn't - * find any modes through DDC previously add the native mode to -@@ -569,7 +583,8 @@ nouveau_connector_get_modes(struct drm_connector *connector) - ret = get_slave_funcs(nv_encoder)-> - get_modes(to_drm_encoder(nv_encoder), connector); - -- if (nv_encoder->dcb->type == OUTPUT_LVDS) -+ if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS || -+ nv_connector->dcb->type == DCB_CONNECTOR_eDP) - ret += nouveau_connector_scaler_modes_add(connector); - - return ret; -@@ -643,6 +658,44 @@ nouveau_connector_best_encoder(struct drm_connector *connector) - return NULL; - } - -+void -+nouveau_connector_set_polling(struct drm_connector *connector) -+{ -+ struct drm_device *dev = connector->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct drm_crtc *crtc; -+ bool spare_crtc = false; -+ -+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) -+ spare_crtc |= !crtc->enabled; -+ -+ connector->polled = 0; -+ -+ switch (connector->connector_type) { -+ case DRM_MODE_CONNECTOR_VGA: -+ case DRM_MODE_CONNECTOR_TV: -+ if (dev_priv->card_type >= NV_50 || -+ (nv_gf4_disp_arch(dev) && spare_crtc)) -+ connector->polled = DRM_CONNECTOR_POLL_CONNECT; -+ break; -+ -+ case DRM_MODE_CONNECTOR_DVII: -+ case DRM_MODE_CONNECTOR_DVID: -+ case DRM_MODE_CONNECTOR_HDMIA: -+ case DRM_MODE_CONNECTOR_DisplayPort: -+ case DRM_MODE_CONNECTOR_eDP: -+ if (dev_priv->card_type >= NV_50) -+ connector->polled = DRM_CONNECTOR_POLL_HPD; -+ else if (connector->connector_type == DRM_MODE_CONNECTOR_DVID || -+ spare_crtc) -+ connector->polled = DRM_CONNECTOR_POLL_CONNECT; -+ break; -+ -+ default: -+ break; -+ } -+} -+ - static const struct drm_connector_helper_funcs - nouveau_connector_helper_funcs = { - .get_modes = nouveau_connector_get_modes, -@@ -662,148 +715,74 @@ nouveau_connector_funcs = { - .force = nouveau_connector_force - }; - --static int --nouveau_connector_create_lvds(struct drm_device *dev, -- struct drm_connector *connector) --{ -- struct nouveau_connector *nv_connector = nouveau_connector(connector); -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_i2c_chan *i2c = NULL; -- struct nouveau_encoder *nv_encoder; -- struct drm_display_mode native, *mode, *temp; -- bool dummy, if_is_24bit = false; -- int ret, flags; -- -- nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS); -- if (!nv_encoder) -- return -ENODEV; -- -- ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &if_is_24bit); -- if (ret) { -- NV_ERROR(dev, "Error parsing LVDS table, disabling LVDS\n"); -- return ret; -- } -- nv_connector->use_dithering = !if_is_24bit; -- -- /* Firstly try getting EDID over DDC, if allowed and I2C channel -- * is available. -- */ -- if (!dev_priv->vbios.fp_no_ddc && nv_encoder->dcb->i2c_index < 0xf) -- i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); -- -- if (i2c) { -- nouveau_connector_ddc_prepare(connector, &flags); -- nv_connector->edid = drm_get_edid(connector, &i2c->adapter); -- nouveau_connector_ddc_finish(connector, flags); -- } -- -- /* If no EDID found above, and the VBIOS indicates a hardcoded -- * modeline is avalilable for the panel, set it as the panel's -- * native mode and exit. -- */ -- if (!nv_connector->edid && nouveau_bios_fp_mode(dev, &native) && -- (nv_encoder->dcb->lvdsconf.use_straps_for_mode || -- dev_priv->vbios.fp_no_ddc)) { -- nv_connector->native_mode = drm_mode_duplicate(dev, &native); -- goto out; -- } -- -- /* Still nothing, some VBIOS images have a hardcoded EDID block -- * stored for the panel stored in them. -- */ -- if (!nv_connector->edid && !nv_connector->native_mode && -- !dev_priv->vbios.fp_no_ddc) { -- struct edid *edid = -- (struct edid *)nouveau_bios_embedded_edid(dev); -- if (edid) { -- nv_connector->edid = kmalloc(EDID_LENGTH, GFP_KERNEL); -- *(nv_connector->edid) = *edid; -- } -- } -- -- if (!nv_connector->edid) -- goto out; -- -- /* We didn't find/use a panel mode from the VBIOS, so parse the EDID -- * block and look for the preferred mode there. -- */ -- ret = drm_add_edid_modes(connector, nv_connector->edid); -- if (ret == 0) -- goto out; -- nv_connector->detected_encoder = nv_encoder; -- nv_connector->native_mode = nouveau_connector_native_mode(connector); -- list_for_each_entry_safe(mode, temp, &connector->probed_modes, head) -- drm_mode_remove(connector, mode); -- --out: -- if (!nv_connector->native_mode) { -- NV_ERROR(dev, "LVDS present in DCB table, but couldn't " -- "determine its native mode. Disabling.\n"); -- return -ENODEV; -- } -- -- drm_mode_connector_update_edid_property(connector, nv_connector->edid); -- return 0; --} -+static const struct drm_connector_funcs -+nouveau_connector_funcs_lvds = { -+ .dpms = drm_helper_connector_dpms, -+ .save = NULL, -+ .restore = NULL, -+ .detect = nouveau_connector_detect_lvds, -+ .destroy = nouveau_connector_destroy, -+ .fill_modes = drm_helper_probe_single_connector_modes, -+ .set_property = nouveau_connector_set_property, -+ .force = nouveau_connector_force -+}; - --int --nouveau_connector_create(struct drm_device *dev, -- struct dcb_connector_table_entry *dcb) -+struct drm_connector * -+nouveau_connector_create(struct drm_device *dev, int index) - { -+ const struct drm_connector_funcs *funcs = &nouveau_connector_funcs; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_connector *nv_connector = NULL; -+ struct dcb_connector_table_entry *dcb = NULL; - struct drm_connector *connector; -- struct drm_encoder *encoder; -- int ret, type; -+ int type, ret = 0; - - NV_DEBUG_KMS(dev, "\n"); - -+ if (index >= dev_priv->vbios.dcb.connector.entries) -+ return ERR_PTR(-EINVAL); -+ -+ dcb = &dev_priv->vbios.dcb.connector.entry[index]; -+ if (dcb->drm) -+ return dcb->drm; -+ - switch (dcb->type) { -- case DCB_CONNECTOR_NONE: -- return 0; - case DCB_CONNECTOR_VGA: -- NV_INFO(dev, "Detected a VGA connector\n"); - type = DRM_MODE_CONNECTOR_VGA; - break; - case DCB_CONNECTOR_TV_0: - case DCB_CONNECTOR_TV_1: - case DCB_CONNECTOR_TV_3: -- NV_INFO(dev, "Detected a TV connector\n"); - type = DRM_MODE_CONNECTOR_TV; - break; - case DCB_CONNECTOR_DVI_I: -- NV_INFO(dev, "Detected a DVI-I connector\n"); - type = DRM_MODE_CONNECTOR_DVII; - break; - case DCB_CONNECTOR_DVI_D: -- NV_INFO(dev, "Detected a DVI-D connector\n"); - type = DRM_MODE_CONNECTOR_DVID; - break; - case DCB_CONNECTOR_HDMI_0: - case DCB_CONNECTOR_HDMI_1: -- NV_INFO(dev, "Detected a HDMI connector\n"); - type = DRM_MODE_CONNECTOR_HDMIA; - break; - case DCB_CONNECTOR_LVDS: -- NV_INFO(dev, "Detected a LVDS connector\n"); - type = DRM_MODE_CONNECTOR_LVDS; -+ funcs = &nouveau_connector_funcs_lvds; - break; - case DCB_CONNECTOR_DP: -- NV_INFO(dev, "Detected a DisplayPort connector\n"); - type = DRM_MODE_CONNECTOR_DisplayPort; - break; - case DCB_CONNECTOR_eDP: -- NV_INFO(dev, "Detected an eDP connector\n"); - type = DRM_MODE_CONNECTOR_eDP; - break; - default: - NV_ERROR(dev, "unknown connector type: 0x%02x!!\n", dcb->type); -- return -EINVAL; -+ return ERR_PTR(-EINVAL); - } - - nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL); - if (!nv_connector) -- return -ENOMEM; -+ return ERR_PTR(-ENOMEM); - nv_connector->dcb = dcb; - connector = &nv_connector->base; - -@@ -811,27 +790,21 @@ nouveau_connector_create(struct drm_device *dev, - connector->interlace_allowed = false; - connector->doublescan_allowed = false; - -- drm_connector_init(dev, connector, &nouveau_connector_funcs, type); -+ drm_connector_init(dev, connector, funcs, type); - drm_connector_helper_add(connector, &nouveau_connector_helper_funcs); - -- /* attach encoders */ -- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { -- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -- -- if (nv_encoder->dcb->connector != dcb->index) -- continue; -- -- if (get_slave_funcs(nv_encoder)) -- get_slave_funcs(nv_encoder)->create_resources(encoder, connector); -+ /* Check if we need dithering enabled */ -+ if (dcb->type == DCB_CONNECTOR_LVDS) { -+ bool dummy, is_24bit = false; - -- drm_mode_connector_attach_encoder(connector, encoder); -- } -+ ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &is_24bit); -+ if (ret) { -+ NV_ERROR(dev, "Error parsing LVDS table, disabling " -+ "LVDS\n"); -+ goto fail; -+ } - -- if (!connector->encoder_ids[0]) { -- NV_WARN(dev, " no encoders, ignoring\n"); -- drm_connector_cleanup(connector); -- kfree(connector); -- return 0; -+ nv_connector->use_dithering = !is_24bit; - } - - /* Init DVI-I specific properties */ -@@ -841,12 +814,8 @@ nouveau_connector_create(struct drm_device *dev, - drm_connector_attach_property(connector, dev->mode_config.dvi_i_select_subconnector_property, 0); - } - -- if (dcb->type != DCB_CONNECTOR_LVDS) -- nv_connector->use_dithering = false; -- - switch (dcb->type) { - case DCB_CONNECTOR_VGA: -- connector->polled = DRM_CONNECTOR_POLL_CONNECT; - if (dev_priv->card_type >= NV_50) { - drm_connector_attach_property(connector, - dev->mode_config.scaling_mode_property, -@@ -858,17 +827,6 @@ nouveau_connector_create(struct drm_device *dev, - case DCB_CONNECTOR_TV_3: - nv_connector->scaling_mode = DRM_MODE_SCALE_NONE; - break; -- case DCB_CONNECTOR_DP: -- case DCB_CONNECTOR_eDP: -- case DCB_CONNECTOR_HDMI_0: -- case DCB_CONNECTOR_HDMI_1: -- case DCB_CONNECTOR_DVI_I: -- case DCB_CONNECTOR_DVI_D: -- if (dev_priv->card_type >= NV_50) -- connector->polled = DRM_CONNECTOR_POLL_HPD; -- else -- connector->polled = DRM_CONNECTOR_POLL_CONNECT; -- /* fall-through */ - default: - nv_connector->scaling_mode = DRM_MODE_SCALE_FULLSCREEN; - -@@ -882,15 +840,15 @@ nouveau_connector_create(struct drm_device *dev, - break; - } - -+ nouveau_connector_set_polling(connector); -+ - drm_sysfs_connector_add(connector); -+ dcb->drm = connector; -+ return dcb->drm; - -- if (dcb->type == DCB_CONNECTOR_LVDS) { -- ret = nouveau_connector_create_lvds(dev, connector); -- if (ret) { -- connector->funcs->destroy(connector); -- return ret; -- } -- } -+fail: -+ drm_connector_cleanup(connector); -+ kfree(connector); -+ return ERR_PTR(ret); - -- return 0; - } -diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h -index 4ef38ab..0d2e668 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_connector.h -+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h -@@ -49,7 +49,10 @@ static inline struct nouveau_connector *nouveau_connector( - return container_of(con, struct nouveau_connector, base); - } - --int nouveau_connector_create(struct drm_device *, -- struct dcb_connector_table_entry *); -+struct drm_connector * -+nouveau_connector_create(struct drm_device *, int index); -+ -+void -+nouveau_connector_set_polling(struct drm_connector *); - - #endif /* __NOUVEAU_CONNECTOR_H__ */ -diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c -index 65c441a..2e3c6ca 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_dma.c -+++ b/drivers/gpu/drm/nouveau/nouveau_dma.c -@@ -92,11 +92,9 @@ nouveau_dma_init(struct nouveau_channel *chan) - return ret; - - /* Map M2MF notifier object - fbcon. */ -- if (drm_core_check_feature(dev, DRIVER_MODESET)) { -- ret = nouveau_bo_map(chan->notifier_bo); -- if (ret) -- return ret; -- } -+ ret = nouveau_bo_map(chan->notifier_bo); -+ if (ret) -+ return ret; - - /* Insert NOPS for NOUVEAU_DMA_SKIPS */ - ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS); -diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c -index deeb21c..184bc95 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_dp.c -+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c -@@ -271,12 +271,26 @@ nouveau_dp_link_train(struct drm_encoder *encoder) - { - struct drm_device *dev = encoder->dev; - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -- uint8_t config[4]; -- uint8_t status[3]; -+ struct bit_displayport_encoder_table *dpe; -+ int dpe_headerlen; -+ uint8_t config[4], status[3]; - bool cr_done, cr_max_vs, eq_done; - int ret = 0, i, tries, voltage; - - NV_DEBUG_KMS(dev, "link training!!\n"); -+ -+ dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); -+ if (!dpe) { -+ NV_ERROR(dev, "SOR-%d: no DP encoder table!\n", nv_encoder->or); -+ return false; -+ } -+ -+ if (dpe->script0) { -+ NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or); -+ nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script0), -+ nv_encoder->dcb); -+ } -+ - train: - cr_done = eq_done = false; - -@@ -403,6 +417,12 @@ stop: - } - } - -+ if (dpe->script1) { -+ NV_DEBUG_KMS(dev, "SOR-%d: running DP script 1\n", nv_encoder->or); -+ nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script1), -+ nv_encoder->dcb); -+ } -+ - return eq_done; - } - -diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c -index 2737704..203d0b6 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_drv.c -+++ b/drivers/gpu/drm/nouveau/nouveau_drv.c -@@ -35,10 +35,6 @@ - - #include "drm_pciids.h" - --MODULE_PARM_DESC(ctxfw, "Use external firmware blob for grctx init (NV40)"); --int nouveau_ctxfw = 0; --module_param_named(ctxfw, nouveau_ctxfw, int, 0400); -- - MODULE_PARM_DESC(noagp, "Disable AGP"); - int nouveau_noagp; - module_param_named(noagp, nouveau_noagp, int, 0400); -@@ -56,7 +52,7 @@ int nouveau_vram_pushbuf; - module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400); - - MODULE_PARM_DESC(vram_notify, "Force DMA notifiers to be in VRAM"); --int nouveau_vram_notify = 1; -+int nouveau_vram_notify = 0; - module_param_named(vram_notify, nouveau_vram_notify, int, 0400); - - MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (>=GeForce 8)"); -@@ -155,9 +151,6 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state) - struct drm_crtc *crtc; - int ret, i; - -- if (!drm_core_check_feature(dev, DRIVER_MODESET)) -- return -ENODEV; -- - if (pm_state.event == PM_EVENT_PRETHAW) - return 0; - -@@ -257,9 +250,6 @@ nouveau_pci_resume(struct pci_dev *pdev) - struct drm_crtc *crtc; - int ret, i; - -- if (!drm_core_check_feature(dev, DRIVER_MODESET)) -- return -ENODEV; -- - nouveau_fbcon_save_disable_accel(dev); - - NV_INFO(dev, "We're back, enabling device...\n"); -@@ -323,7 +313,6 @@ nouveau_pci_resume(struct pci_dev *pdev) - - 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) -@@ -332,10 +321,9 @@ nouveau_pci_resume(struct pci_dev *pdev) - 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); -- NVLockVgaCrtcs(dev, false); -- } else -+ else - nv50_display_init(dev); - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { -@@ -371,7 +359,8 @@ nouveau_pci_resume(struct pci_dev *pdev) - static struct drm_driver driver = { - .driver_features = - DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG | -- DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM, -+ DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM | -+ DRIVER_MODESET, - .load = nouveau_load, - .firstopen = nouveau_firstopen, - .lastclose = nouveau_lastclose, -@@ -438,16 +427,18 @@ static int __init nouveau_init(void) - nouveau_modeset = 1; - } - -- if (nouveau_modeset == 1) { -- driver.driver_features |= DRIVER_MODESET; -- nouveau_register_dsm_handler(); -- } -+ if (!nouveau_modeset) -+ return 0; - -+ nouveau_register_dsm_handler(); - return drm_init(&driver); - } - - static void __exit nouveau_exit(void) - { -+ if (!nouveau_modeset) -+ return; -+ - drm_exit(&driver); - nouveau_unregister_dsm_handler(); - } -diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h -index c697191..20ca5b8 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_drv.h -+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h -@@ -123,14 +123,6 @@ nvbo_kmap_obj_iovirtual(struct nouveau_bo *nvbo) - return ioptr; - } - --struct mem_block { -- struct mem_block *next; -- struct mem_block *prev; -- uint64_t start; -- uint64_t size; -- struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */ --}; -- - enum nouveau_flags { - NV_NFORCE = 0x10000000, - NV_NFORCE2 = 0x20000000 -@@ -149,7 +141,7 @@ struct nouveau_gpuobj { - struct list_head list; - - struct nouveau_channel *im_channel; -- struct mem_block *im_pramin; -+ struct drm_mm_node *im_pramin; - struct nouveau_bo *im_backing; - uint32_t im_backing_start; - uint32_t *im_backing_suspend; -@@ -196,7 +188,7 @@ struct nouveau_channel { - struct list_head pending; - uint32_t sequence; - uint32_t sequence_ack; -- uint32_t last_sequence_irq; -+ atomic_t last_sequence_irq; - } fence; - - /* DMA push buffer */ -@@ -206,7 +198,7 @@ struct nouveau_channel { - - /* Notifier memory */ - struct nouveau_bo *notifier_bo; -- struct mem_block *notifier_heap; -+ struct drm_mm notifier_heap; - - /* PFIFO context */ - struct nouveau_gpuobj_ref *ramfc; -@@ -224,7 +216,7 @@ struct nouveau_channel { - - /* Objects */ - struct nouveau_gpuobj_ref *ramin; /* Private instmem */ -- struct mem_block *ramin_heap; /* Private PRAMIN heap */ -+ struct drm_mm ramin_heap; /* Private PRAMIN heap */ - struct nouveau_gpuobj_ref *ramht; /* Hash table */ - struct list_head ramht_refs; /* Objects referenced by RAMHT */ - -@@ -277,8 +269,7 @@ struct nouveau_instmem_engine { - void (*clear)(struct drm_device *, struct nouveau_gpuobj *); - int (*bind)(struct drm_device *, struct nouveau_gpuobj *); - int (*unbind)(struct drm_device *, struct nouveau_gpuobj *); -- void (*prepare_access)(struct drm_device *, bool write); -- void (*finish_access)(struct drm_device *); -+ void (*flush)(struct drm_device *); - }; - - struct nouveau_mc_engine { -@@ -303,10 +294,11 @@ struct nouveau_fb_engine { - }; - - struct nouveau_fifo_engine { -- void *priv; -- - int channels; - -+ struct nouveau_gpuobj_ref *playlist[2]; -+ int cur_playlist; -+ - int (*init)(struct drm_device *); - void (*takedown)(struct drm_device *); - -@@ -339,10 +331,11 @@ struct nouveau_pgraph_object_class { - struct nouveau_pgraph_engine { - struct nouveau_pgraph_object_class *grclass; - bool accel_blocked; -- void *ctxprog; -- void *ctxvals; - int grctx_size; - -+ /* NV2x/NV3x context table (0x400780) */ -+ struct nouveau_gpuobj_ref *ctx_table; -+ - int (*init)(struct drm_device *); - void (*takedown)(struct drm_device *); - -@@ -500,11 +493,6 @@ enum nouveau_card_type { - - struct drm_nouveau_private { - struct drm_device *dev; -- enum { -- NOUVEAU_CARD_INIT_DOWN, -- NOUVEAU_CARD_INIT_DONE, -- NOUVEAU_CARD_INIT_FAILED -- } init_state; - - /* the card type, takes NV_* as values */ - enum nouveau_card_type card_type; -@@ -533,8 +521,6 @@ struct drm_nouveau_private { - atomic_t validate_sequence; - } ttm; - -- struct fb_info *fbdev_info; -- - int fifo_alloc_count; - struct nouveau_channel *fifos[NOUVEAU_MAX_CHANNEL_NR]; - -@@ -595,11 +581,7 @@ struct drm_nouveau_private { - struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR]; - int vm_vram_pt_nr; - -- struct mem_block *ramin_heap; -- -- /* context table pointed to be NV_PGRAPH_CHANNEL_CTX_TABLE (0x400780) */ -- uint32_t ctx_table_size; -- struct nouveau_gpuobj_ref *ctx_table; -+ struct drm_mm ramin_heap; - - struct list_head gpuobj_list; - -@@ -618,6 +600,11 @@ struct drm_nouveau_private { - struct backlight_device *backlight; - - struct nouveau_channel *evo; -+ struct { -+ struct dcb_entry *dcb; -+ u16 script; -+ u32 pclk; -+ } evo_irq; - - struct { - struct dentry *channel_root; -@@ -652,14 +639,6 @@ nouveau_bo_ref(struct nouveau_bo *ref, struct nouveau_bo **pnvbo) - return 0; - } - --#define NOUVEAU_CHECK_INITIALISED_WITH_RETURN do { \ -- struct drm_nouveau_private *nv = dev->dev_private; \ -- if (nv->init_state != NOUVEAU_CARD_INIT_DONE) { \ -- NV_ERROR(dev, "called without init\n"); \ -- return -EINVAL; \ -- } \ --} while (0) -- - #define NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(id, cl, ch) do { \ - struct drm_nouveau_private *nv = dev->dev_private; \ - if (!nouveau_channel_owner(dev, (cl), (id))) { \ -@@ -682,7 +661,6 @@ extern int nouveau_tv_disable; - extern char *nouveau_tv_norm; - extern int nouveau_reg_debug; - extern char *nouveau_vbios; --extern int nouveau_ctxfw; - extern int nouveau_ignorelid; - extern int nouveau_nofbaccel; - extern int nouveau_noaccel; -@@ -707,15 +685,7 @@ extern bool nouveau_wait_for_idle(struct drm_device *); - extern int nouveau_card_init(struct drm_device *); - - /* nouveau_mem.c */ --extern int nouveau_mem_init_heap(struct mem_block **, uint64_t start, -- uint64_t size); --extern struct mem_block *nouveau_mem_alloc_block(struct mem_block *, -- uint64_t size, int align2, -- struct drm_file *, int tail); --extern void nouveau_mem_takedown(struct mem_block **heap); --extern void nouveau_mem_free_block(struct mem_block *); - extern int nouveau_mem_detect(struct drm_device *dev); --extern void nouveau_mem_release(struct drm_file *, struct mem_block *heap); - extern int nouveau_mem_init(struct drm_device *); - extern int nouveau_mem_init_agp(struct drm_device *); - extern void nouveau_mem_close(struct drm_device *); -@@ -857,11 +827,13 @@ void nouveau_register_dsm_handler(void); - void nouveau_unregister_dsm_handler(void); - int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len); - bool nouveau_acpi_rom_supported(struct pci_dev *pdev); -+int nouveau_acpi_edid(struct drm_device *, struct drm_connector *); - #else - static inline void nouveau_register_dsm_handler(void) {} - static inline void nouveau_unregister_dsm_handler(void) {} - static inline bool nouveau_acpi_rom_supported(struct pci_dev *pdev) { return false; } - static inline int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len) { return -EINVAL; } -+static inline int nouveau_acpi_edid(struct drm_device *, struct drm_connector *) { return -EINVAL; } - #endif - - /* nouveau_backlight.c */ -@@ -1035,12 +1007,6 @@ extern int nv50_graph_unload_context(struct drm_device *); - extern void nv50_graph_context_switch(struct drm_device *); - extern int nv50_grctx_init(struct nouveau_grctx *); - --/* nouveau_grctx.c */ --extern int nouveau_grctx_prog_load(struct drm_device *); --extern void nouveau_grctx_vals_load(struct drm_device *, -- struct nouveau_gpuobj *); --extern void nouveau_grctx_fini(struct drm_device *); -- - /* nv04_instmem.c */ - extern int nv04_instmem_init(struct drm_device *); - extern void nv04_instmem_takedown(struct drm_device *); -@@ -1051,8 +1017,7 @@ extern int nv04_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, - extern void nv04_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); - extern int nv04_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); - extern int nv04_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); --extern void nv04_instmem_prepare_access(struct drm_device *, bool write); --extern void nv04_instmem_finish_access(struct drm_device *); -+extern void nv04_instmem_flush(struct drm_device *); - - /* nv50_instmem.c */ - extern int nv50_instmem_init(struct drm_device *); -@@ -1064,8 +1029,9 @@ extern int nv50_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, - extern void nv50_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); - extern int nv50_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); - extern int nv50_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); --extern void nv50_instmem_prepare_access(struct drm_device *, bool write); --extern void nv50_instmem_finish_access(struct drm_device *); -+extern void nv50_instmem_flush(struct drm_device *); -+extern void nv84_instmem_flush(struct drm_device *); -+extern void nv50_vm_flush(struct drm_device *, int engine); - - /* nv04_mc.c */ - extern int nv04_mc_init(struct drm_device *); -@@ -1088,13 +1054,14 @@ extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd, - unsigned long arg); - - /* nv04_dac.c */ --extern int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry); -+extern int nv04_dac_create(struct drm_connector *, struct dcb_entry *); - extern uint32_t nv17_dac_sample_load(struct drm_encoder *encoder); - extern int nv04_dac_output_offset(struct drm_encoder *encoder); - extern void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable); -+extern bool nv04_dac_in_use(struct drm_encoder *encoder); - - /* nv04_dfp.c */ --extern int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry); -+extern int nv04_dfp_create(struct drm_connector *, struct dcb_entry *); - extern int nv04_dfp_get_bound_head(struct drm_device *dev, struct dcb_entry *dcbent); - extern void nv04_dfp_bind_head(struct drm_device *dev, struct dcb_entry *dcbent, - int head, bool dl); -@@ -1103,10 +1070,10 @@ extern void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode); - - /* nv04_tv.c */ - extern int nv04_tv_identify(struct drm_device *dev, int i2c_index); --extern int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry); -+extern int nv04_tv_create(struct drm_connector *, struct dcb_entry *); - - /* nv17_tv.c */ --extern int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry); -+extern int nv17_tv_create(struct drm_connector *, struct dcb_entry *); - - /* nv04_display.c */ - extern int nv04_display_create(struct drm_device *); -@@ -1147,7 +1114,6 @@ extern int nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr); - extern int nouveau_fence_flush(void *obj, void *arg); - extern void nouveau_fence_unref(void **obj); - extern void *nouveau_fence_ref(void *obj); --extern void nouveau_fence_handler(struct drm_device *dev, int channel); - - /* nouveau_gem.c */ - extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *, -diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h -index e1df820..a1a0d48 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_encoder.h -+++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h -@@ -38,13 +38,15 @@ struct nouveau_encoder { - struct dcb_entry *dcb; - int or; - -+ /* different to drm_encoder.crtc, this reflects what's -+ * actually programmed on the hw, not the proposed crtc */ -+ struct drm_crtc *crtc; -+ - struct drm_display_mode mode; - int last_dpms; - - struct nv04_output_reg restore; - -- void (*disconnect)(struct nouveau_encoder *encoder); -- - union { - struct { - int mc_unknown; -@@ -71,8 +73,8 @@ static inline struct drm_encoder *to_drm_encoder(struct nouveau_encoder *enc) - - struct nouveau_connector * - nouveau_encoder_connector_get(struct nouveau_encoder *encoder); --int nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry); --int nv50_dac_create(struct drm_device *dev, struct dcb_entry *entry); -+int nv50_sor_create(struct drm_connector *, struct dcb_entry *); -+int nv50_dac_create(struct drm_connector *, struct dcb_entry *); - - struct bit_displayport_encoder_table { - uint32_t match; -diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c -index 257ea13..2fb2444 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c -+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c -@@ -333,7 +333,7 @@ nouveau_fbcon_output_poll_changed(struct drm_device *dev) - drm_fb_helper_hotplug_event(&dev_priv->nfbdev->helper); - } - --int -+static int - nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *nfbdev) - { - struct nouveau_framebuffer *nouveau_fb = &nfbdev->nouveau_fb; -diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c -index faddf53..813d853 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_fence.c -+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c -@@ -67,12 +67,13 @@ nouveau_fence_update(struct nouveau_channel *chan) - if (USE_REFCNT) - sequence = nvchan_rd32(chan, 0x48); - else -- sequence = chan->fence.last_sequence_irq; -+ sequence = atomic_read(&chan->fence.last_sequence_irq); - - if (chan->fence.sequence_ack == sequence) - return; - chan->fence.sequence_ack = sequence; - -+ spin_lock(&chan->fence.lock); - list_for_each_safe(entry, tmp, &chan->fence.pending) { - fence = list_entry(entry, struct nouveau_fence, entry); - -@@ -84,6 +85,7 @@ nouveau_fence_update(struct nouveau_channel *chan) - if (sequence == chan->fence.sequence_ack) - break; - } -+ spin_unlock(&chan->fence.lock); - } - - int -@@ -119,7 +121,6 @@ nouveau_fence_emit(struct nouveau_fence *fence) - { - struct drm_nouveau_private *dev_priv = fence->channel->dev->dev_private; - struct nouveau_channel *chan = fence->channel; -- unsigned long flags; - int ret; - - ret = RING_SPACE(chan, 2); -@@ -127,9 +128,7 @@ nouveau_fence_emit(struct nouveau_fence *fence) - return ret; - - if (unlikely(chan->fence.sequence == chan->fence.sequence_ack - 1)) { -- spin_lock_irqsave(&chan->fence.lock, flags); - nouveau_fence_update(chan); -- spin_unlock_irqrestore(&chan->fence.lock, flags); - - BUG_ON(chan->fence.sequence == - chan->fence.sequence_ack - 1); -@@ -138,9 +137,9 @@ nouveau_fence_emit(struct nouveau_fence *fence) - fence->sequence = ++chan->fence.sequence; - - kref_get(&fence->refcount); -- spin_lock_irqsave(&chan->fence.lock, flags); -+ spin_lock(&chan->fence.lock); - list_add_tail(&fence->entry, &chan->fence.pending); -- spin_unlock_irqrestore(&chan->fence.lock, flags); -+ spin_unlock(&chan->fence.lock); - - BEGIN_RING(chan, NvSubSw, USE_REFCNT ? 0x0050 : 0x0150, 1); - OUT_RING(chan, fence->sequence); -@@ -173,14 +172,11 @@ nouveau_fence_signalled(void *sync_obj, void *sync_arg) - { - struct nouveau_fence *fence = nouveau_fence(sync_obj); - struct nouveau_channel *chan = fence->channel; -- unsigned long flags; - - if (fence->signalled) - return true; - -- spin_lock_irqsave(&chan->fence.lock, flags); - nouveau_fence_update(chan); -- spin_unlock_irqrestore(&chan->fence.lock, flags); - return fence->signalled; - } - -@@ -221,27 +217,12 @@ nouveau_fence_flush(void *sync_obj, void *sync_arg) - return 0; - } - --void --nouveau_fence_handler(struct drm_device *dev, int channel) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_channel *chan = NULL; -- -- if (channel >= 0 && channel < dev_priv->engine.fifo.channels) -- chan = dev_priv->fifos[channel]; -- -- if (chan) { -- spin_lock_irq(&chan->fence.lock); -- nouveau_fence_update(chan); -- spin_unlock_irq(&chan->fence.lock); -- } --} -- - int - nouveau_fence_init(struct nouveau_channel *chan) - { - INIT_LIST_HEAD(&chan->fence.pending); - spin_lock_init(&chan->fence.lock); -+ atomic_set(&chan->fence.last_sequence_irq, 0); - return 0; - } - -diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c -index 69c76cf..547f2c2 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_gem.c -+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c -@@ -137,8 +137,6 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, - uint32_t flags = 0; - int ret = 0; - -- NOUVEAU_CHECK_INITIALISED_WITH_RETURN; -- - if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL)) - dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping; - -@@ -577,10 +575,9 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, - struct drm_nouveau_gem_pushbuf_bo *bo; - struct nouveau_channel *chan; - struct validate_op op; -- struct nouveau_fence *fence = 0; -+ struct nouveau_fence *fence = NULL; - int i, j, ret = 0, do_reloc = 0; - -- NOUVEAU_CHECK_INITIALISED_WITH_RETURN; - NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel, file_priv, chan); - - req->vram_available = dev_priv->fb_aper_free; -@@ -760,8 +757,6 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data, - bool no_wait = !!(req->flags & NOUVEAU_GEM_CPU_PREP_NOWAIT); - int ret = -EINVAL; - -- NOUVEAU_CHECK_INITIALISED_WITH_RETURN; -- - gem = drm_gem_object_lookup(dev, file_priv, req->handle); - if (!gem) - return ret; -@@ -800,8 +795,6 @@ nouveau_gem_ioctl_cpu_fini(struct drm_device *dev, void *data, - struct nouveau_bo *nvbo; - int ret = -EINVAL; - -- NOUVEAU_CHECK_INITIALISED_WITH_RETURN; -- - gem = drm_gem_object_lookup(dev, file_priv, req->handle); - if (!gem) - return ret; -@@ -827,8 +820,6 @@ nouveau_gem_ioctl_info(struct drm_device *dev, void *data, - struct drm_gem_object *gem; - int ret; - -- NOUVEAU_CHECK_INITIALISED_WITH_RETURN; -- - gem = drm_gem_object_lookup(dev, file_priv, req->handle); - if (!gem) - return -EINVAL; -diff --git a/drivers/gpu/drm/nouveau/nouveau_grctx.c b/drivers/gpu/drm/nouveau/nouveau_grctx.c -deleted file mode 100644 -index f731c5f..0000000 ---- a/drivers/gpu/drm/nouveau/nouveau_grctx.c -+++ /dev/null -@@ -1,160 +0,0 @@ --/* -- * Copyright 2009 Red Hat Inc. -- * -- * Permission is hereby granted, free of charge, to any person obtaining a -- * copy of this software and associated documentation files (the "Software"), -- * to deal in the Software without restriction, including without limitation -- * the rights to use, copy, modify, merge, publish, distribute, sublicense, -- * and/or sell copies of the Software, and to permit persons to whom the -- * Software is furnished to do so, subject to the following conditions: -- * -- * The above copyright notice and this permission notice shall be included in -- * all copies or substantial portions of the Software. -- * -- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -- * OTHER DEALINGS IN THE SOFTWARE. -- * -- * Authors: Ben Skeggs -- */ -- --#include --#include -- --#include "drmP.h" --#include "nouveau_drv.h" -- --struct nouveau_ctxprog { -- uint32_t signature; -- uint8_t version; -- uint16_t length; -- uint32_t data[]; --} __attribute__ ((packed)); -- --struct nouveau_ctxvals { -- uint32_t signature; -- uint8_t version; -- uint32_t length; -- struct { -- uint32_t offset; -- uint32_t value; -- } data[]; --} __attribute__ ((packed)); -- --int --nouveau_grctx_prog_load(struct drm_device *dev) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; -- const int chipset = dev_priv->chipset; -- const struct firmware *fw; -- const struct nouveau_ctxprog *cp; -- const struct nouveau_ctxvals *cv; -- char name[32]; -- int ret, i; -- -- if (pgraph->accel_blocked) -- return -ENODEV; -- -- if (!pgraph->ctxprog) { -- sprintf(name, "nouveau/nv%02x.ctxprog", chipset); -- ret = request_firmware(&fw, name, &dev->pdev->dev); -- if (ret) { -- NV_ERROR(dev, "No ctxprog for NV%02x\n", chipset); -- return ret; -- } -- -- pgraph->ctxprog = kmemdup(fw->data, fw->size, GFP_KERNEL); -- if (!pgraph->ctxprog) { -- NV_ERROR(dev, "OOM copying ctxprog\n"); -- release_firmware(fw); -- return -ENOMEM; -- } -- -- cp = pgraph->ctxprog; -- if (le32_to_cpu(cp->signature) != 0x5043564e || -- cp->version != 0 || -- le16_to_cpu(cp->length) != ((fw->size - 7) / 4)) { -- NV_ERROR(dev, "ctxprog invalid\n"); -- release_firmware(fw); -- nouveau_grctx_fini(dev); -- return -EINVAL; -- } -- release_firmware(fw); -- } -- -- if (!pgraph->ctxvals) { -- sprintf(name, "nouveau/nv%02x.ctxvals", chipset); -- ret = request_firmware(&fw, name, &dev->pdev->dev); -- if (ret) { -- NV_ERROR(dev, "No ctxvals for NV%02x\n", chipset); -- nouveau_grctx_fini(dev); -- return ret; -- } -- -- pgraph->ctxvals = kmemdup(fw->data, fw->size, GFP_KERNEL); -- if (!pgraph->ctxvals) { -- NV_ERROR(dev, "OOM copying ctxvals\n"); -- release_firmware(fw); -- nouveau_grctx_fini(dev); -- return -ENOMEM; -- } -- -- cv = (void *)pgraph->ctxvals; -- if (le32_to_cpu(cv->signature) != 0x5643564e || -- cv->version != 0 || -- le32_to_cpu(cv->length) != ((fw->size - 9) / 8)) { -- NV_ERROR(dev, "ctxvals invalid\n"); -- release_firmware(fw); -- nouveau_grctx_fini(dev); -- return -EINVAL; -- } -- release_firmware(fw); -- } -- -- cp = pgraph->ctxprog; -- -- nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); -- for (i = 0; i < le16_to_cpu(cp->length); i++) -- nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, -- le32_to_cpu(cp->data[i])); -- -- return 0; --} -- --void --nouveau_grctx_fini(struct drm_device *dev) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; -- -- if (pgraph->ctxprog) { -- kfree(pgraph->ctxprog); -- pgraph->ctxprog = NULL; -- } -- -- if (pgraph->ctxvals) { -- kfree(pgraph->ctxprog); -- pgraph->ctxvals = NULL; -- } --} -- --void --nouveau_grctx_vals_load(struct drm_device *dev, struct nouveau_gpuobj *ctx) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; -- struct nouveau_ctxvals *cv = pgraph->ctxvals; -- int i; -- -- if (!cv) -- return; -- -- for (i = 0; i < le32_to_cpu(cv->length); i++) -- nv_wo32(dev, ctx, le32_to_cpu(cv->data[i].offset), -- le32_to_cpu(cv->data[i].value)); --} -diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c -index 316a3c7..97ba89e 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_i2c.c -+++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c -@@ -278,3 +278,37 @@ nouveau_i2c_find(struct drm_device *dev, int index) - return i2c->chan; - } - -+bool -+nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr) -+{ -+ struct i2c_msg msg = { -+ .addr = addr, -+ .len = 0, -+ }; -+ -+ return i2c_transfer(&i2c->adapter, &msg, 1) == 1; -+} -+ -+int -+nouveau_i2c_identify(struct drm_device *dev, const char *what, -+ struct i2c_board_info *info, int index) -+{ -+ struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, index); -+ int was_locked, i; -+ -+ was_locked = NVLockVgaCrtcs(dev, false); -+ NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, index); -+ -+ for (i = 0; info[i].addr; i++) { -+ if (nouveau_probe_i2c_addr(i2c, info[i].addr)) { -+ NV_INFO(dev, "Detected %s: %s\n", what, info[i].type); -+ goto out; -+ } -+ } -+ -+ NV_DEBUG(dev, "No devices found.\n"); -+out: -+ NVLockVgaCrtcs(dev, was_locked); -+ -+ return info[i].addr ? i : -ENODEV; -+} -diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.h b/drivers/gpu/drm/nouveau/nouveau_i2c.h -index c8eaf7a..6dd2f87 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_i2c.h -+++ b/drivers/gpu/drm/nouveau/nouveau_i2c.h -@@ -45,6 +45,9 @@ struct nouveau_i2c_chan { - int nouveau_i2c_init(struct drm_device *, struct dcb_i2c_entry *, int index); - void nouveau_i2c_fini(struct drm_device *, struct dcb_i2c_entry *); - struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, int index); -+bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr); -+int nouveau_i2c_identify(struct drm_device *dev, const char *what, -+ struct i2c_board_info *info, int index); - - int nouveau_dp_i2c_aux_ch(struct i2c_adapter *, int mode, uint8_t write_byte, - uint8_t *read_byte); -diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c -index c1fd42b..adf5ac4 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_mem.c -+++ b/drivers/gpu/drm/nouveau/nouveau_mem.c -@@ -35,162 +35,6 @@ - #include "drm_sarea.h" - #include "nouveau_drv.h" - --static struct mem_block * --split_block(struct mem_block *p, uint64_t start, uint64_t size, -- struct drm_file *file_priv) --{ -- /* Maybe cut off the start of an existing block */ -- if (start > p->start) { -- struct mem_block *newblock = -- kmalloc(sizeof(*newblock), GFP_KERNEL); -- if (!newblock) -- goto out; -- newblock->start = start; -- newblock->size = p->size - (start - p->start); -- newblock->file_priv = NULL; -- newblock->next = p->next; -- newblock->prev = p; -- p->next->prev = newblock; -- p->next = newblock; -- p->size -= newblock->size; -- p = newblock; -- } -- -- /* Maybe cut off the end of an existing block */ -- if (size < p->size) { -- struct mem_block *newblock = -- kmalloc(sizeof(*newblock), GFP_KERNEL); -- if (!newblock) -- goto out; -- newblock->start = start + size; -- newblock->size = p->size - size; -- newblock->file_priv = NULL; -- newblock->next = p->next; -- newblock->prev = p; -- p->next->prev = newblock; -- p->next = newblock; -- p->size = size; -- } -- --out: -- /* Our block is in the middle */ -- p->file_priv = file_priv; -- return p; --} -- --struct mem_block * --nouveau_mem_alloc_block(struct mem_block *heap, uint64_t size, -- int align2, struct drm_file *file_priv, int tail) --{ -- struct mem_block *p; -- uint64_t mask = (1 << align2) - 1; -- -- if (!heap) -- return NULL; -- -- if (tail) { -- list_for_each_prev(p, heap) { -- uint64_t start = ((p->start + p->size) - size) & ~mask; -- -- if (p->file_priv == NULL && start >= p->start && -- start + size <= p->start + p->size) -- return split_block(p, start, size, file_priv); -- } -- } else { -- list_for_each(p, heap) { -- uint64_t start = (p->start + mask) & ~mask; -- -- if (p->file_priv == NULL && -- start + size <= p->start + p->size) -- return split_block(p, start, size, file_priv); -- } -- } -- -- return NULL; --} -- --void nouveau_mem_free_block(struct mem_block *p) --{ -- p->file_priv = NULL; -- -- /* Assumes a single contiguous range. Needs a special file_priv in -- * 'heap' to stop it being subsumed. -- */ -- if (p->next->file_priv == NULL) { -- struct mem_block *q = p->next; -- p->size += q->size; -- p->next = q->next; -- p->next->prev = p; -- kfree(q); -- } -- -- if (p->prev->file_priv == NULL) { -- struct mem_block *q = p->prev; -- q->size += p->size; -- q->next = p->next; -- q->next->prev = q; -- kfree(p); -- } --} -- --/* Initialize. How to check for an uninitialized heap? -- */ --int nouveau_mem_init_heap(struct mem_block **heap, uint64_t start, -- uint64_t size) --{ -- struct mem_block *blocks = kmalloc(sizeof(*blocks), GFP_KERNEL); -- -- if (!blocks) -- return -ENOMEM; -- -- *heap = kmalloc(sizeof(**heap), GFP_KERNEL); -- if (!*heap) { -- kfree(blocks); -- return -ENOMEM; -- } -- -- blocks->start = start; -- blocks->size = size; -- blocks->file_priv = NULL; -- blocks->next = blocks->prev = *heap; -- -- memset(*heap, 0, sizeof(**heap)); -- (*heap)->file_priv = (struct drm_file *) -1; -- (*heap)->next = (*heap)->prev = blocks; -- return 0; --} -- --/* -- * Free all blocks associated with the releasing file_priv -- */ --void nouveau_mem_release(struct drm_file *file_priv, struct mem_block *heap) --{ -- struct mem_block *p; -- -- if (!heap || !heap->next) -- return; -- -- list_for_each(p, heap) { -- if (p->file_priv == file_priv) -- p->file_priv = NULL; -- } -- -- /* Assumes a single contiguous range. Needs a special file_priv in -- * 'heap' to stop it being subsumed. -- */ -- list_for_each(p, heap) { -- while ((p->file_priv == NULL) && -- (p->next->file_priv == NULL) && -- (p->next != heap)) { -- struct mem_block *q = p->next; -- p->size += q->size; -- p->next = q->next; -- p->next->prev = p; -- kfree(q); -- } -- } --} -- - /* - * NV10-NV40 tiling helpers - */ -@@ -299,7 +143,6 @@ nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size, - phys |= 0x30; - } - -- dev_priv->engine.instmem.prepare_access(dev, true); - while (size) { - unsigned offset_h = upper_32_bits(phys); - unsigned offset_l = lower_32_bits(phys); -@@ -331,36 +174,12 @@ nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size, - } - } - } -- dev_priv->engine.instmem.finish_access(dev); -- -- nv_wr32(dev, 0x100c80, 0x00050001); -- if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { -- NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); -- NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); -- return -EBUSY; -- } -- -- nv_wr32(dev, 0x100c80, 0x00000001); -- if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { -- NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); -- NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); -- return -EBUSY; -- } -- -- nv_wr32(dev, 0x100c80, 0x00040001); -- if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { -- NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); -- NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); -- return -EBUSY; -- } -- -- nv_wr32(dev, 0x100c80, 0x00060001); -- if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { -- NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); -- NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); -- return -EBUSY; -- } -+ dev_priv->engine.instmem.flush(dev); - -+ nv50_vm_flush(dev, 5); -+ nv50_vm_flush(dev, 0); -+ nv50_vm_flush(dev, 4); -+ nv50_vm_flush(dev, 6); - return 0; - } - -@@ -374,7 +193,6 @@ nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size) - virt -= dev_priv->vm_vram_base; - pages = (size >> 16) << 1; - -- dev_priv->engine.instmem.prepare_access(dev, true); - while (pages) { - pgt = dev_priv->vm_vram_pt[virt >> 29]; - pte = (virt & 0x1ffe0000ULL) >> 15; -@@ -388,57 +206,19 @@ nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size) - while (pte < end) - nv_wo32(dev, pgt, pte++, 0); - } -- dev_priv->engine.instmem.finish_access(dev); -- -- nv_wr32(dev, 0x100c80, 0x00050001); -- if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { -- NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); -- NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); -- return; -- } -- -- nv_wr32(dev, 0x100c80, 0x00000001); -- if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { -- NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); -- NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); -- return; -- } -- -- nv_wr32(dev, 0x100c80, 0x00040001); -- if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { -- NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); -- NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); -- return; -- } -+ dev_priv->engine.instmem.flush(dev); - -- nv_wr32(dev, 0x100c80, 0x00060001); -- if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { -- NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); -- NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); -- } -+ nv50_vm_flush(dev, 5); -+ nv50_vm_flush(dev, 0); -+ nv50_vm_flush(dev, 4); -+ nv50_vm_flush(dev, 6); - } - - /* - * Cleanup everything - */ --void nouveau_mem_takedown(struct mem_block **heap) --{ -- struct mem_block *p; -- -- if (!*heap) -- return; -- -- for (p = (*heap)->next; p != *heap;) { -- struct mem_block *q = p; -- p = p->next; -- kfree(q); -- } -- -- kfree(*heap); -- *heap = NULL; --} -- --void nouveau_mem_close(struct drm_device *dev) -+void -+nouveau_mem_close(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - -@@ -449,8 +229,7 @@ void nouveau_mem_close(struct drm_device *dev) - - nouveau_ttm_global_release(dev_priv); - -- if (drm_core_has_AGP(dev) && dev->agp && -- drm_core_check_feature(dev, DRIVER_MODESET)) { -+ if (drm_core_has_AGP(dev) && dev->agp) { - struct drm_agp_mem *entry, *tempe; - - /* Remove AGP resources, but leave dev->agp -@@ -470,29 +249,29 @@ void nouveau_mem_close(struct drm_device *dev) - dev->agp->enabled = 0; - } - -- if (dev_priv->fb_mtrr) { -+ if (dev_priv->fb_mtrr >= 0) { - drm_mtrr_del(dev_priv->fb_mtrr, drm_get_resource_start(dev, 1), - drm_get_resource_len(dev, 1), DRM_MTRR_WC); -- dev_priv->fb_mtrr = 0; -+ dev_priv->fb_mtrr = -1; - } - } - - static uint32_t - nouveau_mem_detect_nv04(struct drm_device *dev) - { -- uint32_t boot0 = nv_rd32(dev, NV03_BOOT_0); -+ uint32_t boot0 = nv_rd32(dev, NV04_PFB_BOOT_0); - - if (boot0 & 0x00000100) - return (((boot0 >> 12) & 0xf) * 2 + 2) * 1024 * 1024; - -- switch (boot0 & NV03_BOOT_0_RAM_AMOUNT) { -- case NV04_BOOT_0_RAM_AMOUNT_32MB: -+ switch (boot0 & NV04_PFB_BOOT_0_RAM_AMOUNT) { -+ case NV04_PFB_BOOT_0_RAM_AMOUNT_32MB: - return 32 * 1024 * 1024; -- case NV04_BOOT_0_RAM_AMOUNT_16MB: -+ case NV04_PFB_BOOT_0_RAM_AMOUNT_16MB: - return 16 * 1024 * 1024; -- case NV04_BOOT_0_RAM_AMOUNT_8MB: -+ case NV04_PFB_BOOT_0_RAM_AMOUNT_8MB: - return 8 * 1024 * 1024; -- case NV04_BOOT_0_RAM_AMOUNT_4MB: -+ case NV04_PFB_BOOT_0_RAM_AMOUNT_4MB: - return 4 * 1024 * 1024; - } - -@@ -536,12 +315,18 @@ nouveau_mem_detect(struct drm_device *dev) - } else - if (dev_priv->flags & (NV_NFORCE | NV_NFORCE2)) { - dev_priv->vram_size = nouveau_mem_detect_nforce(dev); -+ } else -+ if (dev_priv->card_type < NV_50) { -+ dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); -+ dev_priv->vram_size &= NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK; - } else { -- dev_priv->vram_size = nv_rd32(dev, NV04_FIFO_DATA); -- dev_priv->vram_size &= NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK; -- if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) -+ dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); -+ dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32; -+ dev_priv->vram_size &= 0xffffffff00ll; -+ if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) { - 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)); -diff --git a/drivers/gpu/drm/nouveau/nouveau_notifier.c b/drivers/gpu/drm/nouveau/nouveau_notifier.c -index 9537f3e..3ec181f 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_notifier.c -+++ b/drivers/gpu/drm/nouveau/nouveau_notifier.c -@@ -55,7 +55,7 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan) - if (ret) - goto out_err; - -- ret = nouveau_mem_init_heap(&chan->notifier_heap, 0, ntfy->bo.mem.size); -+ ret = drm_mm_init(&chan->notifier_heap, 0, ntfy->bo.mem.size); - if (ret) - goto out_err; - -@@ -80,7 +80,7 @@ nouveau_notifier_takedown_channel(struct nouveau_channel *chan) - nouveau_bo_unpin(chan->notifier_bo); - mutex_unlock(&dev->struct_mutex); - drm_gem_object_unreference_unlocked(chan->notifier_bo->gem); -- nouveau_mem_takedown(&chan->notifier_heap); -+ drm_mm_takedown(&chan->notifier_heap); - } - - static void -@@ -90,7 +90,7 @@ nouveau_notifier_gpuobj_dtor(struct drm_device *dev, - NV_DEBUG(dev, "\n"); - - if (gpuobj->priv) -- nouveau_mem_free_block(gpuobj->priv); -+ drm_mm_put_block(gpuobj->priv); - } - - int -@@ -100,18 +100,13 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *nobj = NULL; -- struct mem_block *mem; -+ struct drm_mm_node *mem; - uint32_t offset; - int target, ret; - -- if (!chan->notifier_heap) { -- NV_ERROR(dev, "Channel %d doesn't have a notifier heap!\n", -- chan->id); -- return -EINVAL; -- } -- -- mem = nouveau_mem_alloc_block(chan->notifier_heap, size, 0, -- (struct drm_file *)-2, 0); -+ mem = drm_mm_search_free(&chan->notifier_heap, size, 0, 0); -+ if (mem) -+ mem = drm_mm_get_block(mem, size, 0); - if (!mem) { - NV_ERROR(dev, "Channel %d notifier block full\n", chan->id); - return -ENOMEM; -@@ -144,17 +139,17 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, - mem->size, NV_DMA_ACCESS_RW, target, - &nobj); - if (ret) { -- nouveau_mem_free_block(mem); -+ drm_mm_put_block(mem); - NV_ERROR(dev, "Error creating notifier ctxdma: %d\n", ret); - return ret; - } -- nobj->dtor = nouveau_notifier_gpuobj_dtor; -- nobj->priv = mem; -+ nobj->dtor = nouveau_notifier_gpuobj_dtor; -+ nobj->priv = mem; - - ret = nouveau_gpuobj_ref_add(dev, chan, handle, nobj, NULL); - if (ret) { - nouveau_gpuobj_del(dev, &nobj); -- nouveau_mem_free_block(mem); -+ drm_mm_put_block(mem); - NV_ERROR(dev, "Error referencing notifier ctxdma: %d\n", ret); - return ret; - } -@@ -170,7 +165,7 @@ nouveau_notifier_offset(struct nouveau_gpuobj *nobj, uint32_t *poffset) - return -EINVAL; - - if (poffset) { -- struct mem_block *mem = nobj->priv; -+ struct drm_mm_node *mem = nobj->priv; - - if (*poffset >= mem->size) - return false; -@@ -189,7 +184,6 @@ nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data, - struct nouveau_channel *chan; - int ret; - -- NOUVEAU_CHECK_INITIALISED_WITH_RETURN; - NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(na->channel, file_priv, chan); - - ret = nouveau_notifier_alloc(chan, na->handle, na->size, &na->offset); -diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c -index e7c100b..4bf6b33 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_object.c -+++ b/drivers/gpu/drm/nouveau/nouveau_object.c -@@ -132,7 +132,6 @@ nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) - } - } - -- instmem->prepare_access(dev, true); - co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle); - do { - if (!nouveau_ramht_entry_valid(dev, ramht, co)) { -@@ -143,7 +142,7 @@ nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) - nv_wo32(dev, ramht, (co + 4)/4, ctx); - - list_add_tail(&ref->list, &chan->ramht_refs); -- instmem->finish_access(dev); -+ instmem->flush(dev); - return 0; - } - NV_DEBUG(dev, "collision ch%d 0x%08x: h=0x%08x\n", -@@ -153,7 +152,6 @@ nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) - if (co >= dev_priv->ramht_size) - co = 0; - } while (co != ho); -- instmem->finish_access(dev); - - NV_ERROR(dev, "RAMHT space exhausted. ch=%d\n", chan->id); - return -ENOMEM; -@@ -173,7 +171,6 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) - return; - } - -- instmem->prepare_access(dev, true); - co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle); - do { - if (nouveau_ramht_entry_valid(dev, ramht, co) && -@@ -186,7 +183,7 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) - nv_wo32(dev, ramht, (co + 4)/4, 0x00000000); - - list_del(&ref->list); -- instmem->finish_access(dev); -+ instmem->flush(dev); - return; - } - -@@ -195,7 +192,6 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) - co = 0; - } while (co != ho); - list_del(&ref->list); -- instmem->finish_access(dev); - - NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n", - chan->id, ref->handle); -@@ -209,7 +205,7 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_engine *engine = &dev_priv->engine; - struct nouveau_gpuobj *gpuobj; -- struct mem_block *pramin = NULL; -+ struct drm_mm *pramin = NULL; - int ret; - - NV_DEBUG(dev, "ch%d size=%u align=%d flags=0x%08x\n", -@@ -233,25 +229,12 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, - * available. - */ - if (chan) { -- if (chan->ramin_heap) { -- NV_DEBUG(dev, "private heap\n"); -- pramin = chan->ramin_heap; -- } else -- if (dev_priv->card_type < NV_50) { -- NV_DEBUG(dev, "global heap fallback\n"); -- pramin = dev_priv->ramin_heap; -- } -+ NV_DEBUG(dev, "channel heap\n"); -+ pramin = &chan->ramin_heap; - } else { - NV_DEBUG(dev, "global heap\n"); -- pramin = dev_priv->ramin_heap; -- } -- -- if (!pramin) { -- NV_ERROR(dev, "No PRAMIN heap!\n"); -- return -EINVAL; -- } -+ pramin = &dev_priv->ramin_heap; - -- if (!chan) { - ret = engine->instmem.populate(dev, gpuobj, &size); - if (ret) { - nouveau_gpuobj_del(dev, &gpuobj); -@@ -260,9 +243,10 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, - } - - /* Allocate a chunk of the PRAMIN aperture */ -- gpuobj->im_pramin = nouveau_mem_alloc_block(pramin, size, -- drm_order(align), -- (struct drm_file *)-2, 0); -+ gpuobj->im_pramin = drm_mm_search_free(pramin, size, align, 0); -+ if (gpuobj->im_pramin) -+ gpuobj->im_pramin = drm_mm_get_block(gpuobj->im_pramin, size, align); -+ - if (!gpuobj->im_pramin) { - nouveau_gpuobj_del(dev, &gpuobj); - return -ENOMEM; -@@ -279,10 +263,9 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, - if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) { - int i; - -- engine->instmem.prepare_access(dev, true); - for (i = 0; i < gpuobj->im_pramin->size; i += 4) - nv_wo32(dev, gpuobj, i/4, 0); -- engine->instmem.finish_access(dev); -+ engine->instmem.flush(dev); - } - - *gpuobj_ret = gpuobj; -@@ -370,10 +353,9 @@ nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj) - } - - if (gpuobj->im_pramin && (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE)) { -- engine->instmem.prepare_access(dev, true); - for (i = 0; i < gpuobj->im_pramin->size; i += 4) - nv_wo32(dev, gpuobj, i/4, 0); -- engine->instmem.finish_access(dev); -+ engine->instmem.flush(dev); - } - - if (gpuobj->dtor) -@@ -386,7 +368,7 @@ nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj) - if (gpuobj->flags & NVOBJ_FLAG_FAKE) - kfree(gpuobj->im_pramin); - else -- nouveau_mem_free_block(gpuobj->im_pramin); -+ drm_mm_put_block(gpuobj->im_pramin); - } - - list_del(&gpuobj->list); -@@ -589,7 +571,7 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t p_offset, - list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); - - if (p_offset != ~0) { -- gpuobj->im_pramin = kzalloc(sizeof(struct mem_block), -+ gpuobj->im_pramin = kzalloc(sizeof(struct drm_mm_node), - GFP_KERNEL); - if (!gpuobj->im_pramin) { - nouveau_gpuobj_del(dev, &gpuobj); -@@ -605,10 +587,9 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t p_offset, - } - - if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) { -- dev_priv->engine.instmem.prepare_access(dev, true); - for (i = 0; i < gpuobj->im_pramin->size; i += 4) - nv_wo32(dev, gpuobj, i/4, 0); -- dev_priv->engine.instmem.finish_access(dev); -+ dev_priv->engine.instmem.flush(dev); - } - - if (pref) { -@@ -696,8 +677,6 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, - return ret; - } - -- instmem->prepare_access(dev, true); -- - if (dev_priv->card_type < NV_50) { - uint32_t frame, adjust, pte_flags = 0; - -@@ -734,7 +713,7 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, - nv_wo32(dev, *gpuobj, 5, flags5); - } - -- instmem->finish_access(dev); -+ instmem->flush(dev); - - (*gpuobj)->engine = NVOBJ_ENGINE_SW; - (*gpuobj)->class = class; -@@ -849,7 +828,6 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class, - return ret; - } - -- dev_priv->engine.instmem.prepare_access(dev, true); - if (dev_priv->card_type >= NV_50) { - nv_wo32(dev, *gpuobj, 0, class); - nv_wo32(dev, *gpuobj, 5, 0x00010000); -@@ -874,7 +852,7 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class, - } - } - } -- dev_priv->engine.instmem.finish_access(dev); -+ dev_priv->engine.instmem.flush(dev); - - (*gpuobj)->engine = NVOBJ_ENGINE_GR; - (*gpuobj)->class = class; -@@ -920,6 +898,7 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan) - base = 0; - - /* PGRAPH context */ -+ size += dev_priv->engine.graph.grctx_size; - - if (dev_priv->card_type == NV_50) { - /* Various fixed table thingos */ -@@ -930,12 +909,8 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan) - size += 0x8000; - /* RAMFC */ - size += 0x1000; -- /* PGRAPH context */ -- size += 0x70000; - } - -- NV_DEBUG(dev, "ch%d PRAMIN size: 0x%08x bytes, base alloc=0x%08x\n", -- chan->id, size, base); - ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, size, 0x1000, 0, - &chan->ramin); - if (ret) { -@@ -944,8 +919,7 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan) - } - pramin = chan->ramin->gpuobj; - -- ret = nouveau_mem_init_heap(&chan->ramin_heap, -- pramin->im_pramin->start + base, size); -+ ret = drm_mm_init(&chan->ramin_heap, pramin->im_pramin->start + base, size); - if (ret) { - NV_ERROR(dev, "Error creating PRAMIN heap: %d\n", ret); - nouveau_gpuobj_ref_del(dev, &chan->ramin); -@@ -969,15 +943,11 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, - - NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); - -- /* Reserve a block of PRAMIN for the channel -- *XXX: maybe on card_type == NV_50) { -- ret = nouveau_gpuobj_channel_init_pramin(chan); -- if (ret) { -- NV_ERROR(dev, "init pramin\n"); -- return ret; -- } -+ /* Allocate a chunk of memory for per-channel object storage */ -+ ret = nouveau_gpuobj_channel_init_pramin(chan); -+ if (ret) { -+ NV_ERROR(dev, "init pramin\n"); -+ return ret; - } - - /* NV50 VM -@@ -988,17 +958,13 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, - if (dev_priv->card_type >= NV_50) { - uint32_t vm_offset, pde; - -- instmem->prepare_access(dev, true); -- - vm_offset = (dev_priv->chipset & 0xf0) == 0x50 ? 0x1400 : 0x200; - vm_offset += chan->ramin->gpuobj->im_pramin->start; - - ret = nouveau_gpuobj_new_fake(dev, vm_offset, ~0, 0x4000, - 0, &chan->vm_pd, NULL); -- if (ret) { -- instmem->finish_access(dev); -+ if (ret) - return ret; -- } - for (i = 0; i < 0x4000; i += 8) { - nv_wo32(dev, chan->vm_pd, (i+0)/4, 0x00000000); - nv_wo32(dev, chan->vm_pd, (i+4)/4, 0xdeadcafe); -@@ -1008,10 +974,8 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, - ret = nouveau_gpuobj_ref_add(dev, NULL, 0, - dev_priv->gart_info.sg_ctxdma, - &chan->vm_gart_pt); -- if (ret) { -- instmem->finish_access(dev); -+ if (ret) - return ret; -- } - nv_wo32(dev, chan->vm_pd, pde++, - chan->vm_gart_pt->instance | 0x03); - nv_wo32(dev, chan->vm_pd, pde++, 0x00000000); -@@ -1021,17 +985,15 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, - ret = nouveau_gpuobj_ref_add(dev, NULL, 0, - dev_priv->vm_vram_pt[i], - &chan->vm_vram_pt[i]); -- if (ret) { -- instmem->finish_access(dev); -+ if (ret) - return ret; -- } - - nv_wo32(dev, chan->vm_pd, pde++, - chan->vm_vram_pt[i]->instance | 0x61); - nv_wo32(dev, chan->vm_pd, pde++, 0x00000000); - } - -- instmem->finish_access(dev); -+ instmem->flush(dev); - } - - /* RAMHT */ -@@ -1130,8 +1092,8 @@ nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan) - for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) - nouveau_gpuobj_ref_del(dev, &chan->vm_vram_pt[i]); - -- if (chan->ramin_heap) -- nouveau_mem_takedown(&chan->ramin_heap); -+ if (chan->ramin_heap.fl_entry.next) -+ drm_mm_takedown(&chan->ramin_heap); - if (chan->ramin) - nouveau_gpuobj_ref_del(dev, &chan->ramin); - -@@ -1164,10 +1126,8 @@ nouveau_gpuobj_suspend(struct drm_device *dev) - return -ENOMEM; - } - -- dev_priv->engine.instmem.prepare_access(dev, false); - for (i = 0; i < gpuobj->im_pramin->size / 4; i++) - gpuobj->im_backing_suspend[i] = nv_ro32(dev, gpuobj, i); -- dev_priv->engine.instmem.finish_access(dev); - } - - return 0; -@@ -1212,10 +1172,9 @@ nouveau_gpuobj_resume(struct drm_device *dev) - if (!gpuobj->im_backing_suspend) - continue; - -- dev_priv->engine.instmem.prepare_access(dev, true); - for (i = 0; i < gpuobj->im_pramin->size / 4; i++) - nv_wo32(dev, gpuobj, i, gpuobj->im_backing_suspend[i]); -- dev_priv->engine.instmem.finish_access(dev); -+ dev_priv->engine.instmem.flush(dev); - } - - nouveau_gpuobj_suspend_cleanup(dev); -@@ -1232,7 +1191,6 @@ int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data, - struct nouveau_channel *chan; - int ret; - -- NOUVEAU_CHECK_INITIALISED_WITH_RETURN; - NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(init->channel, file_priv, chan); - - if (init->handle == ~0) -@@ -1283,7 +1241,6 @@ int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data, - struct nouveau_channel *chan; - int ret; - -- NOUVEAU_CHECK_INITIALISED_WITH_RETURN; - NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(objfree->channel, file_priv, chan); - - ret = nouveau_gpuobj_ref_find(chan, objfree->handle, &ref); -diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h b/drivers/gpu/drm/nouveau/nouveau_reg.h -index 6ca80a3..9c1056c 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_reg.h -+++ b/drivers/gpu/drm/nouveau/nouveau_reg.h -@@ -1,19 +1,64 @@ - -+#define NV04_PFB_BOOT_0 0x00100000 -+# define NV04_PFB_BOOT_0_RAM_AMOUNT 0x00000003 -+# define NV04_PFB_BOOT_0_RAM_AMOUNT_32MB 0x00000000 -+# define NV04_PFB_BOOT_0_RAM_AMOUNT_4MB 0x00000001 -+# define NV04_PFB_BOOT_0_RAM_AMOUNT_8MB 0x00000002 -+# define NV04_PFB_BOOT_0_RAM_AMOUNT_16MB 0x00000003 -+# define NV04_PFB_BOOT_0_RAM_WIDTH_128 0x00000004 -+# define NV04_PFB_BOOT_0_RAM_TYPE 0x00000028 -+# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_8MBIT 0x00000000 -+# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT 0x00000008 -+# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT_4BANK 0x00000010 -+# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_16MBIT 0x00000018 -+# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_64MBIT 0x00000020 -+# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_64MBITX16 0x00000028 -+# define NV04_PFB_BOOT_0_UMA_ENABLE 0x00000100 -+# define NV04_PFB_BOOT_0_UMA_SIZE 0x0000f000 -+#define NV04_PFB_DEBUG_0 0x00100080 -+# define NV04_PFB_DEBUG_0_PAGE_MODE 0x00000001 -+# define NV04_PFB_DEBUG_0_REFRESH_OFF 0x00000010 -+# define NV04_PFB_DEBUG_0_REFRESH_COUNTX64 0x00003f00 -+# define NV04_PFB_DEBUG_0_REFRESH_SLOW_CLK 0x00004000 -+# define NV04_PFB_DEBUG_0_SAFE_MODE 0x00008000 -+# define NV04_PFB_DEBUG_0_ALOM_ENABLE 0x00010000 -+# define NV04_PFB_DEBUG_0_CASOE 0x00100000 -+# define NV04_PFB_DEBUG_0_CKE_INVERT 0x10000000 -+# define NV04_PFB_DEBUG_0_REFINC 0x20000000 -+# define NV04_PFB_DEBUG_0_SAVE_POWER_OFF 0x40000000 -+#define NV04_PFB_CFG0 0x00100200 -+# define NV04_PFB_CFG0_SCRAMBLE 0x20000000 -+#define NV04_PFB_CFG1 0x00100204 -+#define NV04_PFB_FIFO_DATA 0x0010020c -+# define NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK 0xfff00000 -+# define NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_SHIFT 20 -+#define NV10_PFB_REFCTRL 0x00100210 -+# define NV10_PFB_REFCTRL_VALID_1 (1 << 31) -+#define NV04_PFB_PAD 0x0010021c -+# define NV04_PFB_PAD_CKE_NORMAL (1 << 0) -+#define NV10_PFB_TILE(i) (0x00100240 + (i*16)) -+#define NV10_PFB_TILE__SIZE 8 -+#define NV10_PFB_TLIMIT(i) (0x00100244 + (i*16)) -+#define NV10_PFB_TSIZE(i) (0x00100248 + (i*16)) -+#define NV10_PFB_TSTATUS(i) (0x0010024c + (i*16)) -+#define NV04_PFB_REF 0x001002d0 -+# define NV04_PFB_REF_CMD_REFRESH (1 << 0) -+#define NV04_PFB_PRE 0x001002d4 -+# define NV04_PFB_PRE_CMD_PRECHARGE (1 << 0) -+#define NV10_PFB_CLOSE_PAGE2 0x0010033c -+#define NV04_PFB_SCRAMBLE(i) (0x00100400 + 4 * (i)) -+#define NV40_PFB_TILE(i) (0x00100600 + (i*16)) -+#define NV40_PFB_TILE__SIZE_0 12 -+#define NV40_PFB_TILE__SIZE_1 15 -+#define NV40_PFB_TLIMIT(i) (0x00100604 + (i*16)) -+#define NV40_PFB_TSIZE(i) (0x00100608 + (i*16)) -+#define NV40_PFB_TSTATUS(i) (0x0010060c + (i*16)) -+#define NV40_PFB_UNK_800 0x00100800 - --#define NV03_BOOT_0 0x00100000 --# define NV03_BOOT_0_RAM_AMOUNT 0x00000003 --# define NV03_BOOT_0_RAM_AMOUNT_8MB 0x00000000 --# define NV03_BOOT_0_RAM_AMOUNT_2MB 0x00000001 --# define NV03_BOOT_0_RAM_AMOUNT_4MB 0x00000002 --# define NV03_BOOT_0_RAM_AMOUNT_8MB_SDRAM 0x00000003 --# define NV04_BOOT_0_RAM_AMOUNT_32MB 0x00000000 --# define NV04_BOOT_0_RAM_AMOUNT_4MB 0x00000001 --# define NV04_BOOT_0_RAM_AMOUNT_8MB 0x00000002 --# define NV04_BOOT_0_RAM_AMOUNT_16MB 0x00000003 -- --#define NV04_FIFO_DATA 0x0010020c --# define NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK 0xfff00000 --# define NV10_FIFO_DATA_RAM_AMOUNT_MB_SHIFT 20 -+#define NV_PEXTDEV_BOOT_0 0x00101000 -+#define NV_PEXTDEV_BOOT_0_RAMCFG 0x0000003c -+# define NV_PEXTDEV_BOOT_0_STRAP_FP_IFACE_12BIT (8 << 12) -+#define NV_PEXTDEV_BOOT_3 0x0010100c - - #define NV_RAMIN 0x00700000 - -@@ -131,23 +176,6 @@ - #define NV04_PTIMER_TIME_1 0x00009410 - #define NV04_PTIMER_ALARM_0 0x00009420 - --#define NV04_PFB_CFG0 0x00100200 --#define NV04_PFB_CFG1 0x00100204 --#define NV40_PFB_020C 0x0010020C --#define NV10_PFB_TILE(i) (0x00100240 + (i*16)) --#define NV10_PFB_TILE__SIZE 8 --#define NV10_PFB_TLIMIT(i) (0x00100244 + (i*16)) --#define NV10_PFB_TSIZE(i) (0x00100248 + (i*16)) --#define NV10_PFB_TSTATUS(i) (0x0010024C + (i*16)) --#define NV10_PFB_CLOSE_PAGE2 0x0010033C --#define NV40_PFB_TILE(i) (0x00100600 + (i*16)) --#define NV40_PFB_TILE__SIZE_0 12 --#define NV40_PFB_TILE__SIZE_1 15 --#define NV40_PFB_TLIMIT(i) (0x00100604 + (i*16)) --#define NV40_PFB_TSIZE(i) (0x00100608 + (i*16)) --#define NV40_PFB_TSTATUS(i) (0x0010060C + (i*16)) --#define NV40_PFB_UNK_800 0x00100800 -- - #define NV04_PGRAPH_DEBUG_0 0x00400080 - #define NV04_PGRAPH_DEBUG_1 0x00400084 - #define NV04_PGRAPH_DEBUG_2 0x00400088 -@@ -814,6 +842,7 @@ - #define NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE 0x80000000 - #define NV50_PDISPLAY_SOR_BACKLIGHT_LEVEL 0x00000fff - #define NV50_SOR_DP_CTRL(i,l) (0x0061c10c + (i) * 0x800 + (l) * 0x80) -+#define NV50_SOR_DP_CTRL_ENABLED 0x00000001 - #define NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED 0x00004000 - #define NV50_SOR_DP_CTRL_LANE_MASK 0x001f0000 - #define NV50_SOR_DP_CTRL_LANE_0_ENABLED 0x00010000 -diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c -index 1d6ee8b..491767f 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c -+++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c -@@ -97,7 +97,6 @@ nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) - - NV_DEBUG(dev, "pg=0x%lx\n", mem->mm_node->start); - -- dev_priv->engine.instmem.prepare_access(nvbe->dev, true); - pte = nouveau_sgdma_pte(nvbe->dev, mem->mm_node->start << PAGE_SHIFT); - nvbe->pte_start = pte; - for (i = 0; i < nvbe->nr_pages; i++) { -@@ -116,24 +115,11 @@ nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) - dma_offset += NV_CTXDMA_PAGE_SIZE; - } - } -- dev_priv->engine.instmem.finish_access(nvbe->dev); -+ dev_priv->engine.instmem.flush(nvbe->dev); - - if (dev_priv->card_type == NV_50) { -- nv_wr32(dev, 0x100c80, 0x00050001); -- if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { -- NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); -- NV_ERROR(dev, "0x100c80 = 0x%08x\n", -- nv_rd32(dev, 0x100c80)); -- return -EBUSY; -- } -- -- nv_wr32(dev, 0x100c80, 0x00000001); -- if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { -- NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); -- NV_ERROR(dev, "0x100c80 = 0x%08x\n", -- nv_rd32(dev, 0x100c80)); -- return -EBUSY; -- } -+ nv50_vm_flush(dev, 5); /* PGRAPH */ -+ nv50_vm_flush(dev, 0); /* PFIFO */ - } - - nvbe->bound = true; -@@ -154,7 +140,6 @@ nouveau_sgdma_unbind(struct ttm_backend *be) - if (!nvbe->bound) - return 0; - -- dev_priv->engine.instmem.prepare_access(nvbe->dev, true); - pte = nvbe->pte_start; - for (i = 0; i < nvbe->nr_pages; i++) { - dma_addr_t dma_offset = dev_priv->gart_info.sg_dummy_bus; -@@ -170,24 +155,11 @@ nouveau_sgdma_unbind(struct ttm_backend *be) - dma_offset += NV_CTXDMA_PAGE_SIZE; - } - } -- dev_priv->engine.instmem.finish_access(nvbe->dev); -+ dev_priv->engine.instmem.flush(nvbe->dev); - - if (dev_priv->card_type == NV_50) { -- nv_wr32(dev, 0x100c80, 0x00050001); -- if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { -- NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); -- NV_ERROR(dev, "0x100c80 = 0x%08x\n", -- nv_rd32(dev, 0x100c80)); -- return -EBUSY; -- } -- -- nv_wr32(dev, 0x100c80, 0x00000001); -- if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { -- NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); -- NV_ERROR(dev, "0x100c80 = 0x%08x\n", -- nv_rd32(dev, 0x100c80)); -- return -EBUSY; -- } -+ nv50_vm_flush(dev, 5); -+ nv50_vm_flush(dev, 0); - } - - nvbe->bound = false; -@@ -272,7 +244,6 @@ nouveau_sgdma_init(struct drm_device *dev) - pci_map_page(dev->pdev, dev_priv->gart_info.sg_dummy_page, 0, - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - -- dev_priv->engine.instmem.prepare_access(dev, true); - if (dev_priv->card_type < NV_50) { - /* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and - * confirmed to work on c51. Perhaps means NV_DMA_TARGET_PCIE -@@ -294,7 +265,7 @@ nouveau_sgdma_init(struct drm_device *dev) - nv_wo32(dev, gpuobj, (i+4)/4, 0); - } - } -- dev_priv->engine.instmem.finish_access(dev); -+ dev_priv->engine.instmem.flush(dev); - - dev_priv->gart_info.type = NOUVEAU_GART_SGDMA; - dev_priv->gart_info.aper_base = 0; -@@ -325,14 +296,11 @@ nouveau_sgdma_get_page(struct drm_device *dev, uint32_t offset, uint32_t *page) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; -- struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; - int pte; - - pte = (offset >> NV_CTXDMA_PAGE_SHIFT); - if (dev_priv->card_type < NV_50) { -- instmem->prepare_access(dev, false); - *page = nv_ro32(dev, gpuobj, (pte + 2)) & ~NV_CTXDMA_PAGE_MASK; -- instmem->finish_access(dev); - return 0; - } - -diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c -index b02a231..621e080 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_state.c -+++ b/drivers/gpu/drm/nouveau/nouveau_state.c -@@ -54,8 +54,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) - engine->instmem.clear = nv04_instmem_clear; - engine->instmem.bind = nv04_instmem_bind; - engine->instmem.unbind = nv04_instmem_unbind; -- engine->instmem.prepare_access = nv04_instmem_prepare_access; -- engine->instmem.finish_access = nv04_instmem_finish_access; -+ engine->instmem.flush = nv04_instmem_flush; - engine->mc.init = nv04_mc_init; - engine->mc.takedown = nv04_mc_takedown; - engine->timer.init = nv04_timer_init; -@@ -95,8 +94,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) - engine->instmem.clear = nv04_instmem_clear; - engine->instmem.bind = nv04_instmem_bind; - engine->instmem.unbind = nv04_instmem_unbind; -- engine->instmem.prepare_access = nv04_instmem_prepare_access; -- engine->instmem.finish_access = nv04_instmem_finish_access; -+ engine->instmem.flush = nv04_instmem_flush; - engine->mc.init = nv04_mc_init; - engine->mc.takedown = nv04_mc_takedown; - engine->timer.init = nv04_timer_init; -@@ -138,8 +136,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) - engine->instmem.clear = nv04_instmem_clear; - engine->instmem.bind = nv04_instmem_bind; - engine->instmem.unbind = nv04_instmem_unbind; -- engine->instmem.prepare_access = nv04_instmem_prepare_access; -- engine->instmem.finish_access = nv04_instmem_finish_access; -+ engine->instmem.flush = nv04_instmem_flush; - engine->mc.init = nv04_mc_init; - engine->mc.takedown = nv04_mc_takedown; - engine->timer.init = nv04_timer_init; -@@ -181,8 +178,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) - engine->instmem.clear = nv04_instmem_clear; - engine->instmem.bind = nv04_instmem_bind; - engine->instmem.unbind = nv04_instmem_unbind; -- engine->instmem.prepare_access = nv04_instmem_prepare_access; -- engine->instmem.finish_access = nv04_instmem_finish_access; -+ engine->instmem.flush = nv04_instmem_flush; - engine->mc.init = nv04_mc_init; - engine->mc.takedown = nv04_mc_takedown; - engine->timer.init = nv04_timer_init; -@@ -225,8 +221,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) - engine->instmem.clear = nv04_instmem_clear; - engine->instmem.bind = nv04_instmem_bind; - engine->instmem.unbind = nv04_instmem_unbind; -- engine->instmem.prepare_access = nv04_instmem_prepare_access; -- engine->instmem.finish_access = nv04_instmem_finish_access; -+ engine->instmem.flush = nv04_instmem_flush; - engine->mc.init = nv40_mc_init; - engine->mc.takedown = nv40_mc_takedown; - engine->timer.init = nv04_timer_init; -@@ -271,8 +266,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) - engine->instmem.clear = nv50_instmem_clear; - engine->instmem.bind = nv50_instmem_bind; - engine->instmem.unbind = nv50_instmem_unbind; -- engine->instmem.prepare_access = nv50_instmem_prepare_access; -- engine->instmem.finish_access = nv50_instmem_finish_access; -+ if (dev_priv->chipset == 0x50) -+ engine->instmem.flush = nv50_instmem_flush; -+ else -+ engine->instmem.flush = nv84_instmem_flush; - engine->mc.init = nv50_mc_init; - engine->mc.takedown = nv50_mc_takedown; - engine->timer.init = nv04_timer_init; -@@ -407,11 +404,6 @@ nouveau_card_init(struct drm_device *dev) - struct nouveau_engine *engine; - int ret; - -- NV_DEBUG(dev, "prev state = %d\n", dev_priv->init_state); -- -- if (dev_priv->init_state == NOUVEAU_CARD_INIT_DONE) -- return 0; -- - vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode); - vga_switcheroo_register_client(dev->pdev, nouveau_switcheroo_set_state, - nouveau_switcheroo_can_switch); -@@ -421,15 +413,12 @@ nouveau_card_init(struct drm_device *dev) - if (ret) - goto out; - engine = &dev_priv->engine; -- dev_priv->init_state = NOUVEAU_CARD_INIT_FAILED; - spin_lock_init(&dev_priv->context_switch_lock); - - /* Parse BIOS tables / Run init tables if card not POSTed */ -- if (drm_core_check_feature(dev, DRIVER_MODESET)) { -- ret = nouveau_bios_init(dev); -- if (ret) -- goto out; -- } -+ ret = nouveau_bios_init(dev); -+ if (ret) -+ goto out; - - ret = nouveau_mem_detect(dev); - if (ret) -@@ -485,12 +474,19 @@ nouveau_card_init(struct drm_device *dev) - goto out_graph; - } - -+ if (dev_priv->card_type >= NV_50) -+ ret = nv50_display_create(dev); -+ else -+ ret = nv04_display_create(dev); -+ if (ret) -+ goto out_fifo; -+ - /* this call irq_preinstall, register irq handler and - * call irq_postinstall - */ - ret = drm_irq_install(dev); - if (ret) -- goto out_fifo; -+ goto out_display; - - ret = drm_vblank_init(dev, 0); - if (ret) -@@ -504,35 +500,21 @@ nouveau_card_init(struct drm_device *dev) - goto out_irq; - } - -- if (drm_core_check_feature(dev, DRIVER_MODESET)) { -- if (dev_priv->card_type >= NV_50) -- ret = nv50_display_create(dev); -- else -- ret = nv04_display_create(dev); -- if (ret) -- goto out_channel; -- } -- - ret = nouveau_backlight_init(dev); - if (ret) - NV_ERROR(dev, "Error %d registering backlight\n", ret); - -- dev_priv->init_state = NOUVEAU_CARD_INIT_DONE; -- -- if (drm_core_check_feature(dev, DRIVER_MODESET)) { -- nouveau_fbcon_init(dev); -- drm_kms_helper_poll_init(dev); -- } -- -+ nouveau_fbcon_init(dev); -+ drm_kms_helper_poll_init(dev); - return 0; - --out_channel: -- if (dev_priv->channel) { -- nouveau_channel_free(dev_priv->channel); -- dev_priv->channel = NULL; -- } - out_irq: - drm_irq_uninstall(dev); -+out_display: -+ if (dev_priv->card_type >= NV_50) -+ nv50_display_destroy(dev); -+ else -+ nv04_display_destroy(dev); - out_fifo: - if (!nouveau_noaccel) - engine->fifo.takedown(dev); -@@ -566,45 +548,37 @@ static void nouveau_card_takedown(struct drm_device *dev) - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_engine *engine = &dev_priv->engine; - -- NV_DEBUG(dev, "prev state = %d\n", dev_priv->init_state); -+ nouveau_backlight_exit(dev); - -- if (dev_priv->init_state != NOUVEAU_CARD_INIT_DOWN) { -- -- nouveau_backlight_exit(dev); -- -- if (dev_priv->channel) { -- nouveau_channel_free(dev_priv->channel); -- dev_priv->channel = NULL; -- } -- -- if (!nouveau_noaccel) { -- engine->fifo.takedown(dev); -- engine->graph.takedown(dev); -- } -- engine->fb.takedown(dev); -- engine->timer.takedown(dev); -- engine->mc.takedown(dev); -+ if (dev_priv->channel) { -+ nouveau_channel_free(dev_priv->channel); -+ dev_priv->channel = NULL; -+ } - -- mutex_lock(&dev->struct_mutex); -- ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM); -- ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT); -- mutex_unlock(&dev->struct_mutex); -- nouveau_sgdma_takedown(dev); -+ if (!nouveau_noaccel) { -+ engine->fifo.takedown(dev); -+ engine->graph.takedown(dev); -+ } -+ engine->fb.takedown(dev); -+ engine->timer.takedown(dev); -+ engine->mc.takedown(dev); - -- nouveau_gpuobj_takedown(dev); -- nouveau_mem_close(dev); -- engine->instmem.takedown(dev); -+ mutex_lock(&dev->struct_mutex); -+ ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM); -+ ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT); -+ mutex_unlock(&dev->struct_mutex); -+ nouveau_sgdma_takedown(dev); - -- if (drm_core_check_feature(dev, DRIVER_MODESET)) -- drm_irq_uninstall(dev); -+ nouveau_gpuobj_takedown(dev); -+ nouveau_mem_close(dev); -+ engine->instmem.takedown(dev); - -- nouveau_gpuobj_late_takedown(dev); -- nouveau_bios_takedown(dev); -+ drm_irq_uninstall(dev); - -- vga_client_register(dev->pdev, NULL, NULL, NULL); -+ nouveau_gpuobj_late_takedown(dev); -+ nouveau_bios_takedown(dev); - -- dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN; -- } -+ vga_client_register(dev->pdev, NULL, NULL, NULL); - } - - /* here a client dies, release the stuff that was allocated for its -@@ -691,6 +665,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) - struct drm_nouveau_private *dev_priv; - uint32_t reg0; - resource_size_t mmio_start_offs; -+ int ret; - - dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); - if (!dev_priv) -@@ -699,7 +674,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) - dev_priv->dev = dev; - - dev_priv->flags = flags & NOUVEAU_FLAGS; -- dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN; - - NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n", - dev->pci_vendor, dev->pci_device, dev->pdev->class); -@@ -812,46 +786,28 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) - dev_priv->flags |= NV_NFORCE2; - - /* For kernel modesetting, init card now and bring up fbcon */ -- if (drm_core_check_feature(dev, DRIVER_MODESET)) { -- int ret = nouveau_card_init(dev); -- if (ret) -- return ret; -- } -+ ret = nouveau_card_init(dev); -+ if (ret) -+ return ret; - - return 0; - } - --static void nouveau_close(struct drm_device *dev) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- -- /* In the case of an error dev_priv may not be allocated yet */ -- if (dev_priv) -- nouveau_card_takedown(dev); --} -- --/* KMS: we need mmio at load time, not when the first drm client opens. */ - void nouveau_lastclose(struct drm_device *dev) - { -- if (drm_core_check_feature(dev, DRIVER_MODESET)) -- return; -- -- nouveau_close(dev); - } - - int nouveau_unload(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - -- if (drm_core_check_feature(dev, DRIVER_MODESET)) { -- drm_kms_helper_poll_fini(dev); -- nouveau_fbcon_fini(dev); -- if (dev_priv->card_type >= NV_50) -- nv50_display_destroy(dev); -- else -- nv04_display_destroy(dev); -- nouveau_close(dev); -- } -+ drm_kms_helper_poll_fini(dev); -+ nouveau_fbcon_fini(dev); -+ if (dev_priv->card_type >= NV_50) -+ nv50_display_destroy(dev); -+ else -+ nv04_display_destroy(dev); -+ nouveau_card_takedown(dev); - - iounmap(dev_priv->mmio); - iounmap(dev_priv->ramin); -@@ -867,8 +823,6 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data, - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct drm_nouveau_getparam *getparam = data; - -- NOUVEAU_CHECK_INITIALISED_WITH_RETURN; -- - switch (getparam->param) { - case NOUVEAU_GETPARAM_CHIPSET_ID: - getparam->value = dev_priv->chipset; -@@ -937,8 +891,6 @@ nouveau_ioctl_setparam(struct drm_device *dev, void *data, - { - struct drm_nouveau_setparam *setparam = data; - -- NOUVEAU_CHECK_INITIALISED_WITH_RETURN; -- - switch (setparam->param) { - default: - NV_ERROR(dev, "unknown parameter %lld\n", setparam->param); -diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c -index eba687f..1c20c08 100644 ---- a/drivers/gpu/drm/nouveau/nv04_crtc.c -+++ b/drivers/gpu/drm/nouveau/nv04_crtc.c -@@ -157,6 +157,7 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode) - { - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - struct drm_device *dev = crtc->dev; -+ struct drm_connector *connector; - unsigned char seq1 = 0, crtc17 = 0; - unsigned char crtc1A; - -@@ -211,6 +212,10 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode) - NVVgaSeqReset(dev, nv_crtc->index, false); - - NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RPC1_INDEX, crtc1A); -+ -+ /* Update connector polling modes */ -+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) -+ nouveau_connector_set_polling(connector); - } - - static bool -diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c -index 1cb19e3..2d0fee5 100644 ---- a/drivers/gpu/drm/nouveau/nv04_dac.c -+++ b/drivers/gpu/drm/nouveau/nv04_dac.c -@@ -261,12 +261,11 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) - - saved_routput = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset); - head = (saved_routput & 0x100) >> 8; --#if 0 -- /* if there's a spare crtc, using it will minimise flicker for the case -- * where the in-use crtc is in use by an off-chip tmds encoder */ -- if (xf86_config->crtc[head]->enabled && !xf86_config->crtc[head ^ 1]->enabled) -+ -+ /* if there's a spare crtc, using it will minimise flicker */ -+ if (!(NVReadVgaCrtc(dev, head, NV_CIO_CRE_RPC1_INDEX) & 0xC0)) - head ^= 1; --#endif -+ - /* nv driver and nv31 use 0xfffffeee, nv34 and 6600 use 0xfffffece */ - routput = (saved_routput & 0xfffffece) | head << 8; - -@@ -315,9 +314,12 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) - { - struct drm_device *dev = encoder->dev; - struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; -- uint32_t sample = nv17_dac_sample_load(encoder); - -- if (sample & NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) { -+ if (nv04_dac_in_use(encoder)) -+ return connector_status_disconnected; -+ -+ if (nv17_dac_sample_load(encoder) & -+ NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) { - NV_INFO(dev, "Load detected on output %c\n", - '@' + ffs(dcb->or)); - return connector_status_connected; -@@ -330,6 +332,9 @@ static bool nv04_dac_mode_fixup(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) - { -+ if (nv04_dac_in_use(encoder)) -+ return false; -+ - return true; - } - -@@ -428,6 +433,17 @@ void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable) - } - } - -+/* Check if the DAC corresponding to 'encoder' is being used by -+ * someone else. */ -+bool nv04_dac_in_use(struct drm_encoder *encoder) -+{ -+ struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; -+ struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; -+ -+ return nv_gf4_disp_arch(encoder->dev) && -+ (dev_priv->dac_users[ffs(dcb->or) - 1] & ~(1 << dcb->index)); -+} -+ - static void nv04_dac_dpms(struct drm_encoder *encoder, int mode) - { - struct drm_device *dev = encoder->dev; -@@ -501,11 +517,13 @@ static const struct drm_encoder_funcs nv04_dac_funcs = { - .destroy = nv04_dac_destroy, - }; - --int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry) -+int -+nv04_dac_create(struct drm_connector *connector, struct dcb_entry *entry) - { - const struct drm_encoder_helper_funcs *helper; -- struct drm_encoder *encoder; - struct nouveau_encoder *nv_encoder = NULL; -+ struct drm_device *dev = connector->dev; -+ struct drm_encoder *encoder; - - nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); - if (!nv_encoder) -@@ -527,5 +545,6 @@ int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry) - encoder->possible_crtcs = entry->heads; - encoder->possible_clones = 0; - -+ drm_mode_connector_attach_encoder(connector, encoder); - return 0; - } -diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c -index 41634d4..3311f3a 100644 ---- a/drivers/gpu/drm/nouveau/nv04_dfp.c -+++ b/drivers/gpu/drm/nouveau/nv04_dfp.c -@@ -413,10 +413,6 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) - struct dcb_entry *dcbe = nv_encoder->dcb; - int head = nouveau_crtc(encoder->crtc)->index; - -- NV_INFO(dev, "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, '@' + ffs(nv_encoder->dcb->or)); -- - if (dcbe->type == OUTPUT_TMDS) - run_tmds_table(dev, dcbe, head, nv_encoder->mode.clock); - else if (dcbe->type == OUTPUT_LVDS) -@@ -584,11 +580,12 @@ static const struct drm_encoder_funcs nv04_dfp_funcs = { - .destroy = nv04_dfp_destroy, - }; - --int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry) -+int -+nv04_dfp_create(struct drm_connector *connector, struct dcb_entry *entry) - { - const struct drm_encoder_helper_funcs *helper; -- struct drm_encoder *encoder; - struct nouveau_encoder *nv_encoder = NULL; -+ struct drm_encoder *encoder; - int type; - - switch (entry->type) { -@@ -613,11 +610,12 @@ int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry) - nv_encoder->dcb = entry; - nv_encoder->or = ffs(entry->or) - 1; - -- drm_encoder_init(dev, encoder, &nv04_dfp_funcs, type); -+ drm_encoder_init(connector->dev, encoder, &nv04_dfp_funcs, type); - drm_encoder_helper_add(encoder, helper); - - encoder->possible_crtcs = entry->heads; - encoder->possible_clones = 0; - -+ drm_mode_connector_attach_encoder(connector, encoder); - return 0; - } -diff --git a/drivers/gpu/drm/nouveau/nv04_display.c b/drivers/gpu/drm/nouveau/nv04_display.c -index c7898b4..c6df391 100644 ---- a/drivers/gpu/drm/nouveau/nv04_display.c -+++ b/drivers/gpu/drm/nouveau/nv04_display.c -@@ -32,8 +32,6 @@ - #include "nouveau_encoder.h" - #include "nouveau_connector.h" - --#define MULTIPLE_ENCODERS(e) (e & (e - 1)) -- - static void - nv04_display_store_initial_head_owner(struct drm_device *dev) - { -@@ -41,7 +39,7 @@ nv04_display_store_initial_head_owner(struct drm_device *dev) - - if (dev_priv->chipset != 0x11) { - dev_priv->crtc_owner = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_44); -- goto ownerknown; -+ return; - } - - /* reading CR44 is broken on nv11, so we attempt to infer it */ -@@ -52,8 +50,6 @@ nv04_display_store_initial_head_owner(struct drm_device *dev) - bool tvA = false; - bool tvB = false; - -- NVLockVgaCrtcs(dev, false); -- - slaved_on_B = NVReadVgaCrtc(dev, 1, NV_CIO_CRE_PIXEL_INDEX) & - 0x80; - if (slaved_on_B) -@@ -66,8 +62,6 @@ nv04_display_store_initial_head_owner(struct drm_device *dev) - tvA = !(NVReadVgaCrtc(dev, 0, NV_CIO_CRE_LCD__INDEX) & - MASK(NV_CIO_CRE_LCD_LCD_SELECT)); - -- NVLockVgaCrtcs(dev, true); -- - if (slaved_on_A && !tvA) - dev_priv->crtc_owner = 0x0; - else if (slaved_on_B && !tvB) -@@ -79,14 +73,6 @@ nv04_display_store_initial_head_owner(struct drm_device *dev) - else - dev_priv->crtc_owner = 0x0; - } -- --ownerknown: -- NV_INFO(dev, "Initial CRTC_OWNER is %d\n", dev_priv->crtc_owner); -- -- /* we need to ensure the heads are not tied henceforth, or reading any -- * 8 bit reg on head B will fail -- * setting a single arbitrary head solves that */ -- NVSetOwner(dev, 0); - } - - int -@@ -94,14 +80,20 @@ nv04_display_create(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct dcb_table *dcb = &dev_priv->vbios.dcb; -+ struct drm_connector *connector, *ct; - struct drm_encoder *encoder; - struct drm_crtc *crtc; - int i, ret; - - NV_DEBUG_KMS(dev, "\n"); - -- if (nv_two_heads(dev)) -+ NVLockVgaCrtcs(dev, false); -+ -+ if (nv_two_heads(dev)) { - nv04_display_store_initial_head_owner(dev); -+ NVSetOwner(dev, 0); -+ } -+ - nouveau_hw_save_vga_fonts(dev, 1); - - drm_mode_config_init(dev); -@@ -132,19 +124,23 @@ nv04_display_create(struct drm_device *dev) - for (i = 0; i < dcb->entries; i++) { - struct dcb_entry *dcbent = &dcb->entry[i]; - -+ connector = nouveau_connector_create(dev, dcbent->connector); -+ if (IS_ERR(connector)) -+ continue; -+ - switch (dcbent->type) { - case OUTPUT_ANALOG: -- ret = nv04_dac_create(dev, dcbent); -+ ret = nv04_dac_create(connector, dcbent); - break; - case OUTPUT_LVDS: - case OUTPUT_TMDS: -- ret = nv04_dfp_create(dev, dcbent); -+ ret = nv04_dfp_create(connector, dcbent); - break; - case OUTPUT_TV: - if (dcbent->location == DCB_LOC_ON_CHIP) -- ret = nv17_tv_create(dev, dcbent); -+ ret = nv17_tv_create(connector, dcbent); - else -- ret = nv04_tv_create(dev, dcbent); -+ ret = nv04_tv_create(connector, dcbent); - break; - default: - NV_WARN(dev, "DCB type %d not known\n", dcbent->type); -@@ -155,12 +151,16 @@ nv04_display_create(struct drm_device *dev) - continue; - } - -- for (i = 0; i < dcb->connector.entries; i++) -- nouveau_connector_create(dev, &dcb->connector.entry[i]); -+ list_for_each_entry_safe(connector, ct, -+ &dev->mode_config.connector_list, head) { -+ if (!connector->encoder_ids[0]) { -+ NV_WARN(dev, "%s has no encoders, removing\n", -+ drm_get_connector_name(connector)); -+ connector->funcs->destroy(connector); -+ } -+ } - - /* Save previous state */ -- NVLockVgaCrtcs(dev, false); -- - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) - crtc->funcs->save(crtc); - -@@ -176,6 +176,7 @@ nv04_display_create(struct drm_device *dev) - void - nv04_display_destroy(struct drm_device *dev) - { -+ struct drm_nouveau_private *dev_priv = dev->dev_private; - struct drm_encoder *encoder; - struct drm_crtc *crtc; - -@@ -191,8 +192,6 @@ nv04_display_destroy(struct drm_device *dev) - } - - /* Restore state */ -- NVLockVgaCrtcs(dev, false); -- - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { - struct drm_encoder_helper_funcs *func = encoder->helper_private; - -@@ -205,12 +204,15 @@ nv04_display_destroy(struct drm_device *dev) - drm_mode_config_cleanup(dev); - - nouveau_hw_save_vga_fonts(dev, 0); -+ -+ if (nv_two_heads(dev)) -+ NVSetOwner(dev, dev_priv->crtc_owner); -+ NVLockVgaCrtcs(dev, true); - } - - void - nv04_display_restore(struct drm_device *dev) - { -- struct drm_nouveau_private *dev_priv = dev->dev_private; - struct drm_encoder *encoder; - struct drm_crtc *crtc; - -@@ -232,13 +234,5 @@ nv04_display_restore(struct drm_device *dev) - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) - crtc->funcs->restore(crtc); -- -- if (nv_two_heads(dev)) { -- NV_INFO(dev, "Restoring CRTC_OWNER to %d.\n", -- dev_priv->crtc_owner); -- NVSetOwner(dev, dev_priv->crtc_owner); -- } -- -- NVLockVgaCrtcs(dev, true); - } - -diff --git a/drivers/gpu/drm/nouveau/nv04_fifo.c b/drivers/gpu/drm/nouveau/nv04_fifo.c -index 66fe559..06cedd9 100644 ---- a/drivers/gpu/drm/nouveau/nv04_fifo.c -+++ b/drivers/gpu/drm/nouveau/nv04_fifo.c -@@ -112,6 +112,12 @@ nv04_fifo_channel_id(struct drm_device *dev) - NV03_PFIFO_CACHE1_PUSH1_CHID_MASK; - } - -+#ifdef __BIG_ENDIAN -+#define DMA_FETCH_ENDIANNESS NV_PFIFO_CACHE1_BIG_ENDIAN -+#else -+#define DMA_FETCH_ENDIANNESS 0 -+#endif -+ - int - nv04_fifo_create_context(struct nouveau_channel *chan) - { -@@ -131,18 +137,13 @@ nv04_fifo_create_context(struct nouveau_channel *chan) - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - - /* Setup initial state */ -- dev_priv->engine.instmem.prepare_access(dev, true); - RAMFC_WR(DMA_PUT, chan->pushbuf_base); - RAMFC_WR(DMA_GET, chan->pushbuf_base); - RAMFC_WR(DMA_INSTANCE, chan->pushbuf->instance >> 4); - RAMFC_WR(DMA_FETCH, (NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | - NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | - NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 | --#ifdef __BIG_ENDIAN -- NV_PFIFO_CACHE1_BIG_ENDIAN | --#endif -- 0)); -- dev_priv->engine.instmem.finish_access(dev); -+ DMA_FETCH_ENDIANNESS)); - - /* enable the fifo dma operation */ - nv_wr32(dev, NV04_PFIFO_MODE, -@@ -169,8 +170,6 @@ nv04_fifo_do_load_context(struct drm_device *dev, int chid) - struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t fc = NV04_RAMFC(chid), tmp; - -- dev_priv->engine.instmem.prepare_access(dev, false); -- - nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0)); - nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4)); - tmp = nv_ri32(dev, fc + 8); -@@ -181,8 +180,6 @@ nv04_fifo_do_load_context(struct drm_device *dev, int chid) - nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_ri32(dev, fc + 20)); - nv_wr32(dev, NV04_PFIFO_CACHE1_PULL1, nv_ri32(dev, fc + 24)); - -- dev_priv->engine.instmem.finish_access(dev); -- - nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); - nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0); - } -@@ -223,7 +220,6 @@ nv04_fifo_unload_context(struct drm_device *dev) - return -EINVAL; - } - -- dev_priv->engine.instmem.prepare_access(dev, true); - RAMFC_WR(DMA_PUT, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT)); - RAMFC_WR(DMA_GET, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET)); - tmp = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT) << 16; -@@ -233,7 +229,6 @@ nv04_fifo_unload_context(struct drm_device *dev) - RAMFC_WR(DMA_FETCH, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_FETCH)); - RAMFC_WR(ENGINE, nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE)); - RAMFC_WR(PULL1_ENGINE, nv_rd32(dev, NV04_PFIFO_CACHE1_PULL1)); -- dev_priv->engine.instmem.finish_access(dev); - - nv04_fifo_do_load_context(dev, pfifo->channels - 1); - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1); -@@ -297,6 +292,7 @@ nv04_fifo_init(struct drm_device *dev) - - nv04_fifo_init_intr(dev); - pfifo->enable(dev); -+ pfifo->reassign(dev, true); - - for (i = 0; i < dev_priv->engine.fifo.channels; i++) { - if (dev_priv->fifos[i]) { -diff --git a/drivers/gpu/drm/nouveau/nv04_graph.c b/drivers/gpu/drm/nouveau/nv04_graph.c -index 618355e..c897342 100644 ---- a/drivers/gpu/drm/nouveau/nv04_graph.c -+++ b/drivers/gpu/drm/nouveau/nv04_graph.c -@@ -342,7 +342,7 @@ static uint32_t nv04_graph_ctx_regs[] = { - }; - - struct graph_state { -- int nv04[ARRAY_SIZE(nv04_graph_ctx_regs)]; -+ uint32_t nv04[ARRAY_SIZE(nv04_graph_ctx_regs)]; - }; - - struct nouveau_channel * -@@ -527,8 +527,7 @@ static int - nv04_graph_mthd_set_ref(struct nouveau_channel *chan, int grclass, - int mthd, uint32_t data) - { -- chan->fence.last_sequence_irq = data; -- nouveau_fence_handler(chan->dev, chan->id); -+ atomic_set(&chan->fence.last_sequence_irq, data); - return 0; - } - -diff --git a/drivers/gpu/drm/nouveau/nv04_instmem.c b/drivers/gpu/drm/nouveau/nv04_instmem.c -index a3b9563..4408232 100644 ---- a/drivers/gpu/drm/nouveau/nv04_instmem.c -+++ b/drivers/gpu/drm/nouveau/nv04_instmem.c -@@ -49,10 +49,8 @@ nv04_instmem_determine_amount(struct drm_device *dev) - NV_DEBUG(dev, "RAMIN size: %dKiB\n", dev_priv->ramin_rsvd_vram >> 10); - - /* Clear all of it, except the BIOS image that's in the first 64KiB */ -- dev_priv->engine.instmem.prepare_access(dev, true); - for (i = 64 * 1024; i < dev_priv->ramin_rsvd_vram; i += 4) - nv_wi32(dev, i, 0x00000000); -- dev_priv->engine.instmem.finish_access(dev); - } - - static void -@@ -106,7 +104,7 @@ int nv04_instmem_init(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t offset; -- int ret = 0; -+ int ret; - - nv04_instmem_determine_amount(dev); - nv04_instmem_configure_fixed_tables(dev); -@@ -129,14 +127,14 @@ int nv04_instmem_init(struct drm_device *dev) - offset = 0x40000; - } - -- ret = nouveau_mem_init_heap(&dev_priv->ramin_heap, -- offset, dev_priv->ramin_rsvd_vram - offset); -+ ret = drm_mm_init(&dev_priv->ramin_heap, offset, -+ dev_priv->ramin_rsvd_vram - offset); - if (ret) { -- dev_priv->ramin_heap = NULL; -- NV_ERROR(dev, "Failed to init RAMIN heap\n"); -+ NV_ERROR(dev, "Failed to init RAMIN heap: %d\n", ret); -+ return ret; - } - -- return ret; -+ return 0; - } - - void -@@ -186,12 +184,7 @@ nv04_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) - } - - void --nv04_instmem_prepare_access(struct drm_device *dev, bool write) --{ --} -- --void --nv04_instmem_finish_access(struct drm_device *dev) -+nv04_instmem_flush(struct drm_device *dev) - { - } - -diff --git a/drivers/gpu/drm/nouveau/nv04_mc.c b/drivers/gpu/drm/nouveau/nv04_mc.c -index 617ed1e..2af43a1 100644 ---- a/drivers/gpu/drm/nouveau/nv04_mc.c -+++ b/drivers/gpu/drm/nouveau/nv04_mc.c -@@ -11,6 +11,10 @@ nv04_mc_init(struct drm_device *dev) - */ - - nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF); -+ -+ /* Disable PROM access. */ -+ nv_wr32(dev, NV_PBUS_PCI_NV_20, NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED); -+ - return 0; - } - -diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/nv04_tv.c -index c4e3404..94e299c 100644 ---- a/drivers/gpu/drm/nouveau/nv04_tv.c -+++ b/drivers/gpu/drm/nouveau/nv04_tv.c -@@ -34,69 +34,26 @@ - - #include "i2c/ch7006.h" - --static struct { -- struct i2c_board_info board_info; -- struct drm_encoder_funcs funcs; -- struct drm_encoder_helper_funcs hfuncs; -- void *params; -- --} nv04_tv_encoder_info[] = { -+static struct i2c_board_info nv04_tv_encoder_info[] = { - { -- .board_info = { I2C_BOARD_INFO("ch7006", 0x75) }, -- .params = &(struct ch7006_encoder_params) { -+ I2C_BOARD_INFO("ch7006", 0x75), -+ .platform_data = &(struct ch7006_encoder_params) { - CH7006_FORMAT_RGB24m12I, CH7006_CLOCK_MASTER, - 0, 0, 0, - CH7006_SYNC_SLAVE, CH7006_SYNC_SEPARATED, - CH7006_POUT_3_3V, CH7006_ACTIVE_HSYNC -- }, -+ } - }, -+ { } - }; - --static bool probe_i2c_addr(struct i2c_adapter *adapter, int addr) --{ -- struct i2c_msg msg = { -- .addr = addr, -- .len = 0, -- }; -- -- return i2c_transfer(adapter, &msg, 1) == 1; --} -- - int nv04_tv_identify(struct drm_device *dev, int i2c_index) - { -- struct nouveau_i2c_chan *i2c; -- bool was_locked; -- int i, ret; -- -- NV_TRACE(dev, "Probing TV encoders on I2C bus: %d\n", i2c_index); -- -- i2c = nouveau_i2c_find(dev, i2c_index); -- if (!i2c) -- return -ENODEV; -- -- was_locked = NVLockVgaCrtcs(dev, false); -- -- for (i = 0; i < ARRAY_SIZE(nv04_tv_encoder_info); i++) { -- if (probe_i2c_addr(&i2c->adapter, -- nv04_tv_encoder_info[i].board_info.addr)) { -- ret = i; -- break; -- } -- } -- -- if (i < ARRAY_SIZE(nv04_tv_encoder_info)) { -- NV_TRACE(dev, "Detected TV encoder: %s\n", -- nv04_tv_encoder_info[i].board_info.type); -- -- } else { -- NV_TRACE(dev, "No TV encoders found.\n"); -- i = -ENODEV; -- } -- -- NVLockVgaCrtcs(dev, was_locked); -- return i; -+ return nouveau_i2c_identify(dev, "TV encoder", -+ nv04_tv_encoder_info, i2c_index); - } - -+ - #define PLLSEL_TV_CRTC1_MASK \ - (NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK1 \ - | NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK1) -@@ -214,30 +171,32 @@ static void nv04_tv_commit(struct drm_encoder *encoder) - - static void nv04_tv_destroy(struct drm_encoder *encoder) - { -- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -- - to_encoder_slave(encoder)->slave_funcs->destroy(encoder); - - drm_encoder_cleanup(encoder); - -- kfree(nv_encoder); -+ kfree(encoder->helper_private); -+ kfree(nouveau_encoder(encoder)); - } - --int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry) -+static const struct drm_encoder_funcs nv04_tv_funcs = { -+ .destroy = nv04_tv_destroy, -+}; -+ -+int -+nv04_tv_create(struct drm_connector *connector, struct dcb_entry *entry) - { - struct nouveau_encoder *nv_encoder; - struct drm_encoder *encoder; -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct i2c_adapter *adap; -- struct drm_encoder_funcs *funcs = NULL; -- struct drm_encoder_helper_funcs *hfuncs = NULL; -- struct drm_encoder_slave_funcs *sfuncs = NULL; -- int i2c_index = entry->i2c_index; -+ struct drm_device *dev = connector->dev; -+ struct drm_encoder_helper_funcs *hfuncs; -+ struct drm_encoder_slave_funcs *sfuncs; -+ struct nouveau_i2c_chan *i2c = -+ nouveau_i2c_find(dev, entry->i2c_index); - int type, ret; -- bool was_locked; - - /* Ensure that we can talk to this encoder */ -- type = nv04_tv_identify(dev, i2c_index); -+ type = nv04_tv_identify(dev, entry->i2c_index); - if (type < 0) - return type; - -@@ -246,41 +205,32 @@ int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry) - if (!nv_encoder) - return -ENOMEM; - -+ hfuncs = kzalloc(sizeof(*hfuncs), GFP_KERNEL); -+ if (!hfuncs) { -+ ret = -ENOMEM; -+ goto fail_free; -+ } -+ - /* Initialize the common members */ - encoder = to_drm_encoder(nv_encoder); - -- funcs = &nv04_tv_encoder_info[type].funcs; -- hfuncs = &nv04_tv_encoder_info[type].hfuncs; -- -- drm_encoder_init(dev, encoder, funcs, DRM_MODE_ENCODER_TVDAC); -+ drm_encoder_init(dev, encoder, &nv04_tv_funcs, DRM_MODE_ENCODER_TVDAC); - drm_encoder_helper_add(encoder, hfuncs); - - encoder->possible_crtcs = entry->heads; - encoder->possible_clones = 0; -- - nv_encoder->dcb = entry; - nv_encoder->or = ffs(entry->or) - 1; - - /* Run the slave-specific initialization */ -- adap = &dev_priv->vbios.dcb.i2c[i2c_index].chan->adapter; -- -- was_locked = NVLockVgaCrtcs(dev, false); -- -- ret = drm_i2c_encoder_init(encoder->dev, to_encoder_slave(encoder), adap, -- &nv04_tv_encoder_info[type].board_info); -- -- NVLockVgaCrtcs(dev, was_locked); -- -+ ret = drm_i2c_encoder_init(dev, to_encoder_slave(encoder), -+ &i2c->adapter, &nv04_tv_encoder_info[type]); - if (ret < 0) -- goto fail; -+ goto fail_cleanup; - - /* Fill the function pointers */ - sfuncs = to_encoder_slave(encoder)->slave_funcs; - -- *funcs = (struct drm_encoder_funcs) { -- .destroy = nv04_tv_destroy, -- }; -- - *hfuncs = (struct drm_encoder_helper_funcs) { - .dpms = nv04_tv_dpms, - .save = sfuncs->save, -@@ -292,14 +242,17 @@ int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry) - .detect = sfuncs->detect, - }; - -- /* Set the slave encoder configuration */ -- sfuncs->set_config(encoder, nv04_tv_encoder_info[type].params); -+ /* Attach it to the specified connector. */ -+ sfuncs->set_config(encoder, nv04_tv_encoder_info[type].platform_data); -+ sfuncs->create_resources(encoder, connector); -+ drm_mode_connector_attach_encoder(connector, encoder); - - return 0; - --fail: -+fail_cleanup: - drm_encoder_cleanup(encoder); -- -+ kfree(hfuncs); -+fail_free: - kfree(nv_encoder); - return ret; - } -diff --git a/drivers/gpu/drm/nouveau/nv10_fifo.c b/drivers/gpu/drm/nouveau/nv10_fifo.c -index 7aeabf2..7a4069c 100644 ---- a/drivers/gpu/drm/nouveau/nv10_fifo.c -+++ b/drivers/gpu/drm/nouveau/nv10_fifo.c -@@ -55,7 +55,6 @@ nv10_fifo_create_context(struct nouveau_channel *chan) - /* Fill entries that are seen filled in dumps of nvidia driver just - * after channel's is put into DMA mode - */ -- dev_priv->engine.instmem.prepare_access(dev, true); - nv_wi32(dev, fc + 0, chan->pushbuf_base); - nv_wi32(dev, fc + 4, chan->pushbuf_base); - nv_wi32(dev, fc + 12, chan->pushbuf->instance >> 4); -@@ -66,7 +65,6 @@ nv10_fifo_create_context(struct nouveau_channel *chan) - NV_PFIFO_CACHE1_BIG_ENDIAN | - #endif - 0); -- dev_priv->engine.instmem.finish_access(dev); - - /* enable the fifo dma operation */ - nv_wr32(dev, NV04_PFIFO_MODE, -@@ -91,8 +89,6 @@ nv10_fifo_do_load_context(struct drm_device *dev, int chid) - struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t fc = NV10_RAMFC(chid), tmp; - -- dev_priv->engine.instmem.prepare_access(dev, false); -- - nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0)); - nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4)); - nv_wr32(dev, NV10_PFIFO_CACHE1_REF_CNT, nv_ri32(dev, fc + 8)); -@@ -117,8 +113,6 @@ nv10_fifo_do_load_context(struct drm_device *dev, int chid) - nv_wr32(dev, NV10_PFIFO_CACHE1_DMA_SUBROUTINE, nv_ri32(dev, fc + 48)); - - out: -- dev_priv->engine.instmem.finish_access(dev); -- - nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); - nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0); - } -@@ -155,8 +149,6 @@ nv10_fifo_unload_context(struct drm_device *dev) - return 0; - fc = NV10_RAMFC(chid); - -- dev_priv->engine.instmem.prepare_access(dev, true); -- - nv_wi32(dev, fc + 0, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT)); - nv_wi32(dev, fc + 4, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET)); - nv_wi32(dev, fc + 8, nv_rd32(dev, NV10_PFIFO_CACHE1_REF_CNT)); -@@ -179,8 +171,6 @@ nv10_fifo_unload_context(struct drm_device *dev) - nv_wi32(dev, fc + 48, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET)); - - out: -- dev_priv->engine.instmem.finish_access(dev); -- - nv10_fifo_do_load_context(dev, pfifo->channels - 1); - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1); - return 0; -diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c b/drivers/gpu/drm/nouveau/nv17_tv.c -index 74c8803..bb3a284 100644 ---- a/drivers/gpu/drm/nouveau/nv17_tv.c -+++ b/drivers/gpu/drm/nouveau/nv17_tv.c -@@ -116,6 +116,21 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) - return sample; - } - -+static bool -+get_tv_detect_quirks(struct drm_device *dev, uint32_t *pin_mask) -+{ -+ /* Zotac FX5200 */ -+ if (dev->pdev->device == 0x0322 && -+ dev->pdev->subsystem_vendor == 0x19da && -+ (dev->pdev->subsystem_device == 0x1035 || -+ dev->pdev->subsystem_device == 0x2035)) { -+ *pin_mask = 0xc; -+ return false; -+ } -+ -+ return true; -+} -+ - static enum drm_connector_status - nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) - { -@@ -124,12 +139,20 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) - struct drm_mode_config *conf = &dev->mode_config; - struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); - struct dcb_entry *dcb = tv_enc->base.dcb; -+ bool reliable = get_tv_detect_quirks(dev, &tv_enc->pin_mask); - -- if (dev_priv->chipset == 0x42 || -- dev_priv->chipset == 0x43) -- tv_enc->pin_mask = nv42_tv_sample_load(encoder) >> 28 & 0xe; -- else -- tv_enc->pin_mask = nv17_dac_sample_load(encoder) >> 28 & 0xe; -+ if (nv04_dac_in_use(encoder)) -+ return connector_status_disconnected; -+ -+ if (reliable) { -+ if (dev_priv->chipset == 0x42 || -+ dev_priv->chipset == 0x43) -+ tv_enc->pin_mask = -+ nv42_tv_sample_load(encoder) >> 28 & 0xe; -+ else -+ tv_enc->pin_mask = -+ nv17_dac_sample_load(encoder) >> 28 & 0xe; -+ } - - switch (tv_enc->pin_mask) { - case 0x2: -@@ -154,7 +177,9 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) - conf->tv_subconnector_property, - tv_enc->subconnector); - -- if (tv_enc->subconnector) { -+ if (!reliable) { -+ return connector_status_unknown; -+ } else if (tv_enc->subconnector) { - NV_INFO(dev, "Load detected on output %c\n", - '@' + ffs(dcb->or)); - return connector_status_connected; -@@ -296,6 +321,9 @@ static bool nv17_tv_mode_fixup(struct drm_encoder *encoder, - { - struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); - -+ if (nv04_dac_in_use(encoder)) -+ return false; -+ - if (tv_norm->kind == CTV_ENC_MODE) - adjusted_mode->clock = tv_norm->ctv_enc_mode.mode.clock; - else -@@ -744,8 +772,10 @@ static struct drm_encoder_funcs nv17_tv_funcs = { - .destroy = nv17_tv_destroy, - }; - --int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry) -+int -+nv17_tv_create(struct drm_connector *connector, struct dcb_entry *entry) - { -+ struct drm_device *dev = connector->dev; - struct drm_encoder *encoder; - struct nv17_tv_encoder *tv_enc = NULL; - -@@ -774,5 +804,7 @@ int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry) - encoder->possible_crtcs = entry->heads; - encoder->possible_clones = 0; - -+ nv17_tv_create_resources(encoder, connector); -+ drm_mode_connector_attach_encoder(connector, encoder); - return 0; - } -diff --git a/drivers/gpu/drm/nouveau/nv20_graph.c b/drivers/gpu/drm/nouveau/nv20_graph.c -index d6fc0a8..191c15c 100644 ---- a/drivers/gpu/drm/nouveau/nv20_graph.c -+++ b/drivers/gpu/drm/nouveau/nv20_graph.c -@@ -370,68 +370,54 @@ nv20_graph_create_context(struct nouveau_channel *chan) - { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - void (*ctx_init)(struct drm_device *, struct nouveau_gpuobj *); -- unsigned int ctx_size; - unsigned int idoffs = 0x28/4; - int ret; - - switch (dev_priv->chipset) { - case 0x20: -- ctx_size = NV20_GRCTX_SIZE; - ctx_init = nv20_graph_context_init; - idoffs = 0; - break; - case 0x25: - case 0x28: -- ctx_size = NV25_GRCTX_SIZE; - ctx_init = nv25_graph_context_init; - break; - case 0x2a: -- ctx_size = NV2A_GRCTX_SIZE; - ctx_init = nv2a_graph_context_init; - idoffs = 0; - break; - case 0x30: - case 0x31: -- ctx_size = NV30_31_GRCTX_SIZE; - ctx_init = nv30_31_graph_context_init; - break; - case 0x34: -- ctx_size = NV34_GRCTX_SIZE; - ctx_init = nv34_graph_context_init; - break; - case 0x35: - case 0x36: -- ctx_size = NV35_36_GRCTX_SIZE; - ctx_init = nv35_36_graph_context_init; - break; - default: -- ctx_size = 0; -- ctx_init = nv35_36_graph_context_init; -- NV_ERROR(dev, "Please contact the devs if you want your NV%x" -- " card to work\n", dev_priv->chipset); -- return -ENOSYS; -- break; -+ BUG_ON(1); - } - -- ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, ctx_size, 16, -- NVOBJ_FLAG_ZERO_ALLOC, -- &chan->ramin_grctx); -+ ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pgraph->grctx_size, -+ 16, NVOBJ_FLAG_ZERO_ALLOC, -+ &chan->ramin_grctx); - if (ret) - return ret; - - /* Initialise default context values */ -- dev_priv->engine.instmem.prepare_access(dev, true); - ctx_init(dev, chan->ramin_grctx->gpuobj); - - /* nv20: nv_wo32(dev, chan->ramin_grctx->gpuobj, 10, chan->id<<24); */ - nv_wo32(dev, chan->ramin_grctx->gpuobj, idoffs, - (chan->id << 24) | 0x1); /* CTX_USER */ - -- nv_wo32(dev, dev_priv->ctx_table->gpuobj, chan->id, -- chan->ramin_grctx->instance >> 4); -- -- dev_priv->engine.instmem.finish_access(dev); -+ nv_wo32(dev, pgraph->ctx_table->gpuobj, chan->id, -+ chan->ramin_grctx->instance >> 4); - return 0; - } - -@@ -440,13 +426,12 @@ nv20_graph_destroy_context(struct nouveau_channel *chan) - { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - - if (chan->ramin_grctx) - nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx); - -- dev_priv->engine.instmem.prepare_access(dev, true); -- nv_wo32(dev, dev_priv->ctx_table->gpuobj, chan->id, 0); -- dev_priv->engine.instmem.finish_access(dev); -+ nv_wo32(dev, pgraph->ctx_table->gpuobj, chan->id, 0); - } - - int -@@ -538,29 +523,44 @@ nv20_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, - int - nv20_graph_init(struct drm_device *dev) - { -- struct drm_nouveau_private *dev_priv = -- (struct drm_nouveau_private *)dev->dev_private; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - uint32_t tmp, vramsz; - int ret, i; - -+ switch (dev_priv->chipset) { -+ case 0x20: -+ pgraph->grctx_size = NV20_GRCTX_SIZE; -+ break; -+ case 0x25: -+ case 0x28: -+ pgraph->grctx_size = NV25_GRCTX_SIZE; -+ break; -+ case 0x2a: -+ pgraph->grctx_size = NV2A_GRCTX_SIZE; -+ break; -+ default: -+ NV_ERROR(dev, "unknown chipset, disabling acceleration\n"); -+ pgraph->accel_blocked = true; -+ return 0; -+ } -+ - nv_wr32(dev, NV03_PMC_ENABLE, - nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PGRAPH); - nv_wr32(dev, NV03_PMC_ENABLE, - nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PGRAPH); - -- if (!dev_priv->ctx_table) { -+ if (!pgraph->ctx_table) { - /* Create Context Pointer Table */ -- dev_priv->ctx_table_size = 32 * 4; -- ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, -- dev_priv->ctx_table_size, 16, -+ ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 32 * 4, 16, - NVOBJ_FLAG_ZERO_ALLOC, -- &dev_priv->ctx_table); -+ &pgraph->ctx_table); - if (ret) - return ret; - } - - nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, -- dev_priv->ctx_table->instance >> 4); -+ pgraph->ctx_table->instance >> 4); - - nv20_graph_rdi(dev); - -@@ -644,34 +644,52 @@ void - nv20_graph_takedown(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - -- nouveau_gpuobj_ref_del(dev, &dev_priv->ctx_table); -+ nouveau_gpuobj_ref_del(dev, &pgraph->ctx_table); - } - - int - nv30_graph_init(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - int ret, i; - -+ switch (dev_priv->chipset) { -+ case 0x30: -+ case 0x31: -+ pgraph->grctx_size = NV30_31_GRCTX_SIZE; -+ break; -+ case 0x34: -+ pgraph->grctx_size = NV34_GRCTX_SIZE; -+ break; -+ case 0x35: -+ case 0x36: -+ pgraph->grctx_size = NV35_36_GRCTX_SIZE; -+ break; -+ default: -+ NV_ERROR(dev, "unknown chipset, disabling acceleration\n"); -+ pgraph->accel_blocked = true; -+ return 0; -+ } -+ - nv_wr32(dev, NV03_PMC_ENABLE, - nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PGRAPH); - nv_wr32(dev, NV03_PMC_ENABLE, - nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PGRAPH); - -- if (!dev_priv->ctx_table) { -+ if (!pgraph->ctx_table) { - /* Create Context Pointer Table */ -- dev_priv->ctx_table_size = 32 * 4; -- ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, -- dev_priv->ctx_table_size, 16, -+ ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 32 * 4, 16, - NVOBJ_FLAG_ZERO_ALLOC, -- &dev_priv->ctx_table); -+ &pgraph->ctx_table); - if (ret) - return ret; - } - - nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, -- dev_priv->ctx_table->instance >> 4); -+ pgraph->ctx_table->instance >> 4); - - nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); -diff --git a/drivers/gpu/drm/nouveau/nv40_fifo.c b/drivers/gpu/drm/nouveau/nv40_fifo.c -index 500ccfd..2b67f18 100644 ---- a/drivers/gpu/drm/nouveau/nv40_fifo.c -+++ b/drivers/gpu/drm/nouveau/nv40_fifo.c -@@ -48,7 +48,6 @@ nv40_fifo_create_context(struct nouveau_channel *chan) - - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - -- dev_priv->engine.instmem.prepare_access(dev, true); - nv_wi32(dev, fc + 0, chan->pushbuf_base); - nv_wi32(dev, fc + 4, chan->pushbuf_base); - nv_wi32(dev, fc + 12, chan->pushbuf->instance >> 4); -@@ -61,7 +60,6 @@ nv40_fifo_create_context(struct nouveau_channel *chan) - 0x30000000 /* no idea.. */); - nv_wi32(dev, fc + 56, chan->ramin_grctx->instance >> 4); - nv_wi32(dev, fc + 60, 0x0001FFFF); -- dev_priv->engine.instmem.finish_access(dev); - - /* enable the fifo dma operation */ - nv_wr32(dev, NV04_PFIFO_MODE, -@@ -89,8 +87,6 @@ nv40_fifo_do_load_context(struct drm_device *dev, int chid) - struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t fc = NV40_RAMFC(chid), tmp, tmp2; - -- dev_priv->engine.instmem.prepare_access(dev, false); -- - nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0)); - nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4)); - nv_wr32(dev, NV10_PFIFO_CACHE1_REF_CNT, nv_ri32(dev, fc + 8)); -@@ -127,8 +123,6 @@ nv40_fifo_do_load_context(struct drm_device *dev, int chid) - nv_wr32(dev, 0x2088, nv_ri32(dev, fc + 76)); - nv_wr32(dev, 0x3300, nv_ri32(dev, fc + 80)); - -- dev_priv->engine.instmem.finish_access(dev); -- - nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); - nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0); - } -@@ -166,7 +160,6 @@ nv40_fifo_unload_context(struct drm_device *dev) - return 0; - fc = NV40_RAMFC(chid); - -- dev_priv->engine.instmem.prepare_access(dev, true); - nv_wi32(dev, fc + 0, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT)); - nv_wi32(dev, fc + 4, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET)); - nv_wi32(dev, fc + 8, nv_rd32(dev, NV10_PFIFO_CACHE1_REF_CNT)); -@@ -200,7 +193,6 @@ nv40_fifo_unload_context(struct drm_device *dev) - tmp |= (nv_rd32(dev, NV04_PFIFO_CACHE1_PUT) << 16); - nv_wi32(dev, fc + 72, tmp); - #endif -- dev_priv->engine.instmem.finish_access(dev); - - nv40_fifo_do_load_context(dev, pfifo->channels - 1); - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, -diff --git a/drivers/gpu/drm/nouveau/nv40_graph.c b/drivers/gpu/drm/nouveau/nv40_graph.c -index 704a25d..ef550ce 100644 ---- a/drivers/gpu/drm/nouveau/nv40_graph.c -+++ b/drivers/gpu/drm/nouveau/nv40_graph.c -@@ -58,6 +58,7 @@ nv40_graph_create_context(struct nouveau_channel *chan) - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; -+ struct nouveau_grctx ctx = {}; - int ret; - - ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pgraph->grctx_size, -@@ -67,20 +68,13 @@ nv40_graph_create_context(struct nouveau_channel *chan) - return ret; - - /* Initialise default context values */ -- dev_priv->engine.instmem.prepare_access(dev, true); -- if (!pgraph->ctxprog) { -- struct nouveau_grctx ctx = {}; -- -- ctx.dev = chan->dev; -- ctx.mode = NOUVEAU_GRCTX_VALS; -- ctx.data = chan->ramin_grctx->gpuobj; -- nv40_grctx_init(&ctx); -- } else { -- nouveau_grctx_vals_load(dev, chan->ramin_grctx->gpuobj); -- } -+ ctx.dev = chan->dev; -+ ctx.mode = NOUVEAU_GRCTX_VALS; -+ ctx.data = chan->ramin_grctx->gpuobj; -+ nv40_grctx_init(&ctx); -+ - nv_wo32(dev, chan->ramin_grctx->gpuobj, 0, - chan->ramin_grctx->gpuobj->im_pramin->start); -- dev_priv->engine.instmem.finish_access(dev); - return 0; - } - -@@ -238,7 +232,8 @@ nv40_graph_init(struct drm_device *dev) - struct drm_nouveau_private *dev_priv = - (struct drm_nouveau_private *)dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; -- uint32_t vramsz; -+ struct nouveau_grctx ctx = {}; -+ uint32_t vramsz, *cp; - int i, j; - - nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & -@@ -246,32 +241,22 @@ nv40_graph_init(struct drm_device *dev) - nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | - NV_PMC_ENABLE_PGRAPH); - -- if (nouveau_ctxfw) { -- nouveau_grctx_prog_load(dev); -- dev_priv->engine.graph.grctx_size = 175 * 1024; -- } -+ cp = kmalloc(sizeof(*cp) * 256, GFP_KERNEL); -+ if (!cp) -+ return -ENOMEM; - -- if (!dev_priv->engine.graph.ctxprog) { -- struct nouveau_grctx ctx = {}; -- uint32_t *cp; -+ ctx.dev = dev; -+ ctx.mode = NOUVEAU_GRCTX_PROG; -+ ctx.data = cp; -+ ctx.ctxprog_max = 256; -+ nv40_grctx_init(&ctx); -+ dev_priv->engine.graph.grctx_size = ctx.ctxvals_pos * 4; - -- cp = kmalloc(sizeof(*cp) * 256, GFP_KERNEL); -- if (!cp) -- return -ENOMEM; -+ nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); -+ for (i = 0; i < ctx.ctxprog_len; i++) -+ nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, cp[i]); - -- ctx.dev = dev; -- ctx.mode = NOUVEAU_GRCTX_PROG; -- ctx.data = cp; -- ctx.ctxprog_max = 256; -- nv40_grctx_init(&ctx); -- dev_priv->engine.graph.grctx_size = ctx.ctxvals_pos * 4; -- -- nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); -- for (i = 0; i < ctx.ctxprog_len; i++) -- nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, cp[i]); -- -- kfree(cp); -- } -+ kfree(cp); - - /* No context present currently */ - nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); -@@ -407,7 +392,6 @@ nv40_graph_init(struct drm_device *dev) - - void nv40_graph_takedown(struct drm_device *dev) - { -- nouveau_grctx_fini(dev); - } - - struct nouveau_pgraph_object_class nv40_graph_grclass[] = { -diff --git a/drivers/gpu/drm/nouveau/nv40_mc.c b/drivers/gpu/drm/nouveau/nv40_mc.c -index 2a3495e..e4e72c1 100644 ---- a/drivers/gpu/drm/nouveau/nv40_mc.c -+++ b/drivers/gpu/drm/nouveau/nv40_mc.c -@@ -19,7 +19,7 @@ nv40_mc_init(struct drm_device *dev) - case 0x46: /* G72 */ - case 0x4e: - case 0x4c: /* C51_G7X */ -- tmp = nv_rd32(dev, NV40_PFB_020C); -+ tmp = nv_rd32(dev, NV04_PFB_FIFO_DATA); - nv_wr32(dev, NV40_PMC_1700, tmp); - nv_wr32(dev, NV40_PMC_1704, 0); - nv_wr32(dev, NV40_PMC_1708, 0); -diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c -index b4e4a3b..5d11ea1 100644 ---- a/drivers/gpu/drm/nouveau/nv50_crtc.c -+++ b/drivers/gpu/drm/nouveau/nv50_crtc.c -@@ -440,47 +440,15 @@ nv50_crtc_prepare(struct drm_crtc *crtc) - { - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - struct drm_device *dev = crtc->dev; -- struct drm_encoder *encoder; -- uint32_t dac = 0, sor = 0; - - NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); - -- /* Disconnect all unused encoders. */ -- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { -- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -- -- if (!drm_helper_encoder_in_use(encoder)) -- continue; -- -- if (nv_encoder->dcb->type == OUTPUT_ANALOG || -- nv_encoder->dcb->type == OUTPUT_TV) -- dac |= (1 << nv_encoder->or); -- else -- sor |= (1 << nv_encoder->or); -- } -- -- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { -- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -- -- if (nv_encoder->dcb->type == OUTPUT_ANALOG || -- nv_encoder->dcb->type == OUTPUT_TV) { -- if (dac & (1 << nv_encoder->or)) -- continue; -- } else { -- if (sor & (1 << nv_encoder->or)) -- continue; -- } -- -- nv_encoder->disconnect(nv_encoder); -- } -- - nv50_crtc_blank(nv_crtc, true); - } - - static void - nv50_crtc_commit(struct drm_crtc *crtc) - { -- struct drm_crtc *crtc2; - struct drm_device *dev = crtc->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *evo = dev_priv->evo; -@@ -491,20 +459,14 @@ nv50_crtc_commit(struct drm_crtc *crtc) - - nv50_crtc_blank(nv_crtc, false); - -- /* Explicitly blank all unused crtc's. */ -- list_for_each_entry(crtc2, &dev->mode_config.crtc_list, head) { -- if (!drm_helper_crtc_in_use(crtc2)) -- nv50_crtc_blank(nouveau_crtc(crtc2), true); -- } -- - ret = RING_SPACE(evo, 2); - if (ret) { - NV_ERROR(dev, "no space while committing crtc\n"); - return; - } - BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); -- OUT_RING(evo, 0); -- FIRE_RING(evo); -+ OUT_RING (evo, 0); -+ FIRE_RING (evo); - } - - static bool -diff --git a/drivers/gpu/drm/nouveau/nv50_dac.c b/drivers/gpu/drm/nouveau/nv50_dac.c -index 1fd9537..1bc0859 100644 ---- a/drivers/gpu/drm/nouveau/nv50_dac.c -+++ b/drivers/gpu/drm/nouveau/nv50_dac.c -@@ -37,22 +37,31 @@ - #include "nv50_display.h" - - static void --nv50_dac_disconnect(struct nouveau_encoder *nv_encoder) -+nv50_dac_disconnect(struct drm_encoder *encoder) - { -- struct drm_device *dev = to_drm_encoder(nv_encoder)->dev; -+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -+ struct drm_device *dev = encoder->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *evo = dev_priv->evo; - int ret; - -+ if (!nv_encoder->crtc) -+ return; -+ nv50_crtc_blank(nouveau_crtc(nv_encoder->crtc), true); -+ - NV_DEBUG_KMS(dev, "Disconnecting DAC %d\n", nv_encoder->or); - -- ret = RING_SPACE(evo, 2); -+ ret = RING_SPACE(evo, 4); - if (ret) { - NV_ERROR(dev, "no space while disconnecting DAC\n"); - return; - } - BEGIN_RING(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 1); -- OUT_RING(evo, 0); -+ OUT_RING (evo, 0); -+ BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); -+ OUT_RING (evo, 0); -+ -+ nv_encoder->crtc = NULL; - } - - static enum drm_connector_status -@@ -213,7 +222,8 @@ nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, - uint32_t mode_ctl = 0, mode_ctl2 = 0; - int ret; - -- NV_DEBUG_KMS(dev, "or %d\n", nv_encoder->or); -+ NV_DEBUG_KMS(dev, "or %d type %d crtc %d\n", -+ nv_encoder->or, nv_encoder->dcb->type, crtc->index); - - nv50_dac_dpms(encoder, DRM_MODE_DPMS_ON); - -@@ -243,6 +253,14 @@ nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, - BEGIN_RING(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 2); - OUT_RING(evo, mode_ctl); - OUT_RING(evo, mode_ctl2); -+ -+ nv_encoder->crtc = encoder->crtc; -+} -+ -+static struct drm_crtc * -+nv50_dac_crtc_get(struct drm_encoder *encoder) -+{ -+ return nouveau_encoder(encoder)->crtc; - } - - static const struct drm_encoder_helper_funcs nv50_dac_helper_funcs = { -@@ -253,7 +271,9 @@ static const struct drm_encoder_helper_funcs nv50_dac_helper_funcs = { - .prepare = nv50_dac_prepare, - .commit = nv50_dac_commit, - .mode_set = nv50_dac_mode_set, -- .detect = nv50_dac_detect -+ .get_crtc = nv50_dac_crtc_get, -+ .detect = nv50_dac_detect, -+ .disable = nv50_dac_disconnect - }; - - static void -@@ -275,14 +295,11 @@ static const struct drm_encoder_funcs nv50_dac_encoder_funcs = { - }; - - int --nv50_dac_create(struct drm_device *dev, struct dcb_entry *entry) -+nv50_dac_create(struct drm_connector *connector, struct dcb_entry *entry) - { - struct nouveau_encoder *nv_encoder; - struct drm_encoder *encoder; - -- NV_DEBUG_KMS(dev, "\n"); -- NV_INFO(dev, "Detected a DAC output\n"); -- - nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); - if (!nv_encoder) - return -ENOMEM; -@@ -291,14 +308,14 @@ nv50_dac_create(struct drm_device *dev, struct dcb_entry *entry) - nv_encoder->dcb = entry; - nv_encoder->or = ffs(entry->or) - 1; - -- nv_encoder->disconnect = nv50_dac_disconnect; -- -- drm_encoder_init(dev, encoder, &nv50_dac_encoder_funcs, -+ drm_encoder_init(connector->dev, encoder, &nv50_dac_encoder_funcs, - DRM_MODE_ENCODER_DAC); - drm_encoder_helper_add(encoder, &nv50_dac_helper_funcs); - - encoder->possible_crtcs = entry->heads; - encoder->possible_clones = 0; -+ -+ drm_mode_connector_attach_encoder(connector, encoder); - return 0; - } - -diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c -index 580a5d1..c19ed8c 100644 ---- a/drivers/gpu/drm/nouveau/nv50_display.c -+++ b/drivers/gpu/drm/nouveau/nv50_display.c -@@ -71,14 +71,13 @@ nv50_evo_dmaobj_new(struct nouveau_channel *evo, uint32_t class, uint32_t name, - return ret; - } - -- dev_priv->engine.instmem.prepare_access(dev, true); - nv_wo32(dev, obj, 0, (tile_flags << 22) | (magic_flags << 16) | class); - nv_wo32(dev, obj, 1, limit); - nv_wo32(dev, obj, 2, offset); - nv_wo32(dev, obj, 3, 0x00000000); - nv_wo32(dev, obj, 4, 0x00000000); - nv_wo32(dev, obj, 5, 0x00010000); -- dev_priv->engine.instmem.finish_access(dev); -+ dev_priv->engine.instmem.flush(dev); - - return 0; - } -@@ -110,8 +109,8 @@ nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pchan) - return ret; - } - -- ret = nouveau_mem_init_heap(&chan->ramin_heap, chan->ramin->gpuobj-> -- im_pramin->start, 32768); -+ ret = drm_mm_init(&chan->ramin_heap, -+ chan->ramin->gpuobj->im_pramin->start, 32768); - if (ret) { - NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret); - nv50_evo_channel_del(pchan); -@@ -465,6 +464,7 @@ int nv50_display_create(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct dcb_table *dcb = &dev_priv->vbios.dcb; -+ struct drm_connector *connector, *ct; - int ret, i; - - NV_DEBUG_KMS(dev, "\n"); -@@ -507,14 +507,18 @@ int nv50_display_create(struct drm_device *dev) - continue; - } - -+ connector = nouveau_connector_create(dev, entry->connector); -+ if (IS_ERR(connector)) -+ continue; -+ - switch (entry->type) { - case OUTPUT_TMDS: - case OUTPUT_LVDS: - case OUTPUT_DP: -- nv50_sor_create(dev, entry); -+ nv50_sor_create(connector, entry); - break; - case OUTPUT_ANALOG: -- nv50_dac_create(dev, entry); -+ nv50_dac_create(connector, entry); - break; - default: - NV_WARN(dev, "DCB encoder %d unknown\n", entry->type); -@@ -522,11 +526,13 @@ int nv50_display_create(struct drm_device *dev) - } - } - -- for (i = 0 ; i < dcb->connector.entries; i++) { -- if (i != 0 && dcb->connector.entry[i].index2 == -- dcb->connector.entry[i - 1].index2) -- continue; -- nouveau_connector_create(dev, &dcb->connector.entry[i]); -+ list_for_each_entry_safe(connector, ct, -+ &dev->mode_config.connector_list, head) { -+ if (!connector->encoder_ids[0]) { -+ NV_WARN(dev, "%s has no encoders, removing\n", -+ drm_get_connector_name(connector)); -+ connector->funcs->destroy(connector); -+ } - } - - ret = nv50_display_init(dev); -@@ -552,131 +558,28 @@ int nv50_display_destroy(struct drm_device *dev) - return 0; - } - --static inline uint32_t --nv50_display_mode_ctrl(struct drm_device *dev, bool sor, int or) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- uint32_t mc; -- -- if (sor) { -- if (dev_priv->chipset < 0x90 || -- dev_priv->chipset == 0x92 || dev_priv->chipset == 0xa0) -- mc = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_P(or)); -- else -- mc = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_P(or)); -- } else { -- mc = nv_rd32(dev, NV50_PDISPLAY_DAC_MODE_CTRL_P(or)); -- } -- -- return mc; --} -- --static int --nv50_display_irq_head(struct drm_device *dev, int *phead, -- struct dcb_entry **pdcbent) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- uint32_t unk30 = nv_rd32(dev, NV50_PDISPLAY_UNK30_CTRL); -- uint32_t dac = 0, sor = 0; -- int head, i, or = 0, type = OUTPUT_ANY; -- -- /* We're assuming that head 0 *or* head 1 will be active here, -- * and not both. I'm not sure if the hw will even signal both -- * ever, but it definitely shouldn't for us as we commit each -- * CRTC separately, and submission will be blocked by the GPU -- * until we handle each in turn. -- */ -- NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); -- head = ffs((unk30 >> 9) & 3) - 1; -- if (head < 0) -- return -EINVAL; -- -- /* This assumes CRTCs are never bound to multiple encoders, which -- * should be the case. -- */ -- for (i = 0; i < 3 && type == OUTPUT_ANY; i++) { -- uint32_t mc = nv50_display_mode_ctrl(dev, false, i); -- if (!(mc & (1 << head))) -- continue; -- -- switch ((mc >> 8) & 0xf) { -- case 0: type = OUTPUT_ANALOG; break; -- case 1: type = OUTPUT_TV; break; -- default: -- NV_ERROR(dev, "unknown dac mode_ctrl: 0x%08x\n", dac); -- return -1; -- } -- -- or = i; -- } -- -- for (i = 0; i < 4 && type == OUTPUT_ANY; i++) { -- uint32_t mc = nv50_display_mode_ctrl(dev, true, i); -- if (!(mc & (1 << head))) -- continue; -- -- switch ((mc >> 8) & 0xf) { -- case 0: type = OUTPUT_LVDS; break; -- case 1: type = OUTPUT_TMDS; break; -- case 2: type = OUTPUT_TMDS; break; -- case 5: type = OUTPUT_TMDS; break; -- case 8: type = OUTPUT_DP; break; -- case 9: type = OUTPUT_DP; break; -- default: -- NV_ERROR(dev, "unknown sor mode_ctrl: 0x%08x\n", sor); -- return -1; -- } -- -- or = i; -- } -- -- NV_DEBUG_KMS(dev, "type %d, or %d\n", type, or); -- if (type == OUTPUT_ANY) { -- NV_ERROR(dev, "unknown encoder!!\n"); -- return -1; -- } -- -- for (i = 0; i < dev_priv->vbios.dcb.entries; i++) { -- struct dcb_entry *dcbent = &dev_priv->vbios.dcb.entry[i]; -- -- if (dcbent->type != type) -- continue; -- -- if (!(dcbent->or & (1 << or))) -- continue; -- -- *phead = head; -- *pdcbent = dcbent; -- return 0; -- } -- -- NV_ERROR(dev, "no DCB entry for %d %d\n", dac != 0, or); -- return 0; --} -- --static uint32_t --nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcbent, -- int pxclk) -+static u16 -+nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcb, -+ u32 mc, int pxclk) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_connector *nv_connector = NULL; - struct drm_encoder *encoder; - struct nvbios *bios = &dev_priv->vbios; -- uint32_t mc, script = 0, or; -+ u32 script = 0, or; - - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - -- if (nv_encoder->dcb != dcbent) -+ if (nv_encoder->dcb != dcb) - continue; - - nv_connector = nouveau_encoder_connector_get(nv_encoder); - break; - } - -- or = ffs(dcbent->or) - 1; -- mc = nv50_display_mode_ctrl(dev, dcbent->type != OUTPUT_ANALOG, or); -- switch (dcbent->type) { -+ or = ffs(dcb->or) - 1; -+ switch (dcb->type) { - case OUTPUT_LVDS: - script = (mc >> 8) & 0xf; - if (bios->fp_no_ddc) { -@@ -767,17 +670,88 @@ nv50_display_vblank_handler(struct drm_device *dev, uint32_t intr) - static void - nv50_display_unk10_handler(struct drm_device *dev) - { -- struct dcb_entry *dcbent; -- int head, ret; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ u32 unk30 = nv_rd32(dev, 0x610030), mc; -+ int i, crtc, or, type = OUTPUT_ANY; - -- ret = nv50_display_irq_head(dev, &head, &dcbent); -- if (ret) -- goto ack; -+ NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); -+ dev_priv->evo_irq.dcb = NULL; - - nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) & ~8); - -- nouveau_bios_run_display_table(dev, dcbent, 0, -1); -+ /* Determine which CRTC we're dealing with, only 1 ever will be -+ * signalled at the same time with the current nouveau code. -+ */ -+ crtc = ffs((unk30 & 0x00000060) >> 5) - 1; -+ if (crtc < 0) -+ goto ack; -+ -+ /* Nothing needs to be done for the encoder */ -+ crtc = ffs((unk30 & 0x00000180) >> 7) - 1; -+ if (crtc < 0) -+ goto ack; -+ -+ /* Find which encoder was connected to the CRTC */ -+ for (i = 0; type == OUTPUT_ANY && i < 3; i++) { -+ mc = nv_rd32(dev, NV50_PDISPLAY_DAC_MODE_CTRL_C(i)); -+ NV_DEBUG_KMS(dev, "DAC-%d mc: 0x%08x\n", i, mc); -+ if (!(mc & (1 << crtc))) -+ continue; -+ -+ switch ((mc & 0x00000f00) >> 8) { -+ case 0: type = OUTPUT_ANALOG; break; -+ case 1: type = OUTPUT_TV; break; -+ default: -+ NV_ERROR(dev, "invalid mc, DAC-%d: 0x%08x\n", i, mc); -+ goto ack; -+ } -+ -+ or = i; -+ } -+ -+ for (i = 0; type == OUTPUT_ANY && i < 4; i++) { -+ if (dev_priv->chipset < 0x90 || -+ dev_priv->chipset == 0x92 || -+ dev_priv->chipset == 0xa0) -+ mc = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_C(i)); -+ else -+ mc = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_C(i)); - -+ NV_DEBUG_KMS(dev, "SOR-%d mc: 0x%08x\n", i, mc); -+ if (!(mc & (1 << crtc))) -+ continue; -+ -+ switch ((mc & 0x00000f00) >> 8) { -+ case 0: type = OUTPUT_LVDS; break; -+ case 1: type = OUTPUT_TMDS; break; -+ case 2: type = OUTPUT_TMDS; break; -+ case 5: type = OUTPUT_TMDS; break; -+ case 8: type = OUTPUT_DP; break; -+ case 9: type = OUTPUT_DP; break; -+ default: -+ NV_ERROR(dev, "invalid mc, SOR-%d: 0x%08x\n", i, mc); -+ goto ack; -+ } -+ -+ or = i; -+ } -+ -+ /* There was no encoder to disable */ -+ if (type == OUTPUT_ANY) -+ goto ack; -+ -+ /* Disable the encoder */ -+ for (i = 0; i < dev_priv->vbios.dcb.entries; i++) { -+ struct dcb_entry *dcb = &dev_priv->vbios.dcb.entry[i]; -+ -+ if (dcb->type == type && (dcb->or & (1 << or))) { -+ nouveau_bios_run_display_table(dev, dcb, 0, -1); -+ dev_priv->evo_irq.dcb = dcb; -+ goto ack; -+ } -+ } -+ -+ NV_ERROR(dev, "no dcb for %d %d 0x%08x\n", or, type, mc); - ack: - nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK10); - nv_wr32(dev, 0x610030, 0x80000000); -@@ -817,33 +791,103 @@ nv50_display_unk20_dp_hack(struct drm_device *dev, struct dcb_entry *dcb) - static void - nv50_display_unk20_handler(struct drm_device *dev) - { -- struct dcb_entry *dcbent; -- uint32_t tmp, pclk, script; -- int head, or, ret; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ u32 unk30 = nv_rd32(dev, 0x610030), tmp, pclk, script, mc; -+ struct dcb_entry *dcb; -+ int i, crtc, or, type = OUTPUT_ANY; - -- ret = nv50_display_irq_head(dev, &head, &dcbent); -- if (ret) -+ NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); -+ dcb = dev_priv->evo_irq.dcb; -+ if (dcb) { -+ nouveau_bios_run_display_table(dev, dcb, 0, -2); -+ dev_priv->evo_irq.dcb = NULL; -+ } -+ -+ /* CRTC clock change requested? */ -+ crtc = ffs((unk30 & 0x00000600) >> 9) - 1; -+ if (crtc >= 0) { -+ pclk = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(crtc, CLOCK)); -+ pclk &= 0x003fffff; -+ -+ nv50_crtc_set_clock(dev, crtc, pclk); -+ -+ tmp = nv_rd32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(crtc)); -+ tmp &= ~0x000000f; -+ nv_wr32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(crtc), tmp); -+ } -+ -+ /* Nothing needs to be done for the encoder */ -+ crtc = ffs((unk30 & 0x00000180) >> 7) - 1; -+ if (crtc < 0) - goto ack; -- or = ffs(dcbent->or) - 1; -- pclk = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(head, CLOCK)) & 0x3fffff; -- script = nv50_display_script_select(dev, dcbent, pclk); -+ pclk = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(crtc, CLOCK)) & 0x003fffff; - -- NV_DEBUG_KMS(dev, "head %d pxclk: %dKHz\n", head, pclk); -+ /* Find which encoder is connected to the CRTC */ -+ for (i = 0; type == OUTPUT_ANY && i < 3; i++) { -+ mc = nv_rd32(dev, NV50_PDISPLAY_DAC_MODE_CTRL_P(i)); -+ NV_DEBUG_KMS(dev, "DAC-%d mc: 0x%08x\n", i, mc); -+ if (!(mc & (1 << crtc))) -+ continue; - -- if (dcbent->type != OUTPUT_DP) -- nouveau_bios_run_display_table(dev, dcbent, 0, -2); -+ switch ((mc & 0x00000f00) >> 8) { -+ case 0: type = OUTPUT_ANALOG; break; -+ case 1: type = OUTPUT_TV; break; -+ default: -+ NV_ERROR(dev, "invalid mc, DAC-%d: 0x%08x\n", i, mc); -+ goto ack; -+ } - -- nv50_crtc_set_clock(dev, head, pclk); -+ or = i; -+ } - -- nouveau_bios_run_display_table(dev, dcbent, script, pclk); -+ for (i = 0; type == OUTPUT_ANY && i < 4; i++) { -+ if (dev_priv->chipset < 0x90 || -+ dev_priv->chipset == 0x92 || -+ dev_priv->chipset == 0xa0) -+ mc = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_P(i)); -+ else -+ mc = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_P(i)); - -- nv50_display_unk20_dp_hack(dev, dcbent); -+ NV_DEBUG_KMS(dev, "SOR-%d mc: 0x%08x\n", i, mc); -+ if (!(mc & (1 << crtc))) -+ continue; - -- tmp = nv_rd32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(head)); -- tmp &= ~0x000000f; -- nv_wr32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(head), tmp); -+ switch ((mc & 0x00000f00) >> 8) { -+ case 0: type = OUTPUT_LVDS; break; -+ case 1: type = OUTPUT_TMDS; break; -+ case 2: type = OUTPUT_TMDS; break; -+ case 5: type = OUTPUT_TMDS; break; -+ case 8: type = OUTPUT_DP; break; -+ case 9: type = OUTPUT_DP; break; -+ default: -+ NV_ERROR(dev, "invalid mc, SOR-%d: 0x%08x\n", i, mc); -+ goto ack; -+ } -+ -+ or = i; -+ } -+ -+ if (type == OUTPUT_ANY) -+ goto ack; -+ -+ /* Enable the encoder */ -+ for (i = 0; i < dev_priv->vbios.dcb.entries; i++) { -+ dcb = &dev_priv->vbios.dcb.entry[i]; -+ if (dcb->type == type && (dcb->or & (1 << or))) -+ break; -+ } -+ -+ if (i == dev_priv->vbios.dcb.entries) { -+ NV_ERROR(dev, "no dcb for %d %d 0x%08x\n", or, type, mc); -+ goto ack; -+ } -+ -+ script = nv50_display_script_select(dev, dcb, mc, pclk); -+ nouveau_bios_run_display_table(dev, dcb, script, pclk); -+ -+ nv50_display_unk20_dp_hack(dev, dcb); - -- if (dcbent->type != OUTPUT_ANALOG) { -+ if (dcb->type != OUTPUT_ANALOG) { - tmp = nv_rd32(dev, NV50_PDISPLAY_SOR_CLK_CTRL2(or)); - tmp &= ~0x00000f0f; - if (script & 0x0100) -@@ -853,24 +897,61 @@ nv50_display_unk20_handler(struct drm_device *dev) - nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL2(or), 0); - } - -+ dev_priv->evo_irq.dcb = dcb; -+ dev_priv->evo_irq.pclk = pclk; -+ dev_priv->evo_irq.script = script; -+ - ack: - nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK20); - nv_wr32(dev, 0x610030, 0x80000000); - } - -+/* If programming a TMDS output on a SOR that can also be configured for -+ * DisplayPort, make sure NV50_SOR_DP_CTRL_ENABLE is forced off. -+ * -+ * It looks like the VBIOS TMDS scripts make an attempt at this, however, -+ * the VBIOS scripts on at least one board I have only switch it off on -+ * link 0, causing a blank display if the output has previously been -+ * programmed for DisplayPort. -+ */ -+static void -+nv50_display_unk40_dp_set_tmds(struct drm_device *dev, struct dcb_entry *dcb) -+{ -+ int or = ffs(dcb->or) - 1, link = !(dcb->dpconf.sor.link & 1); -+ struct drm_encoder *encoder; -+ u32 tmp; -+ -+ if (dcb->type != OUTPUT_TMDS) -+ return; -+ -+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { -+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -+ -+ if (nv_encoder->dcb->type == OUTPUT_DP && -+ nv_encoder->dcb->or & (1 << or)) { -+ tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); -+ tmp &= ~NV50_SOR_DP_CTRL_ENABLED; -+ nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp); -+ break; -+ } -+ } -+} -+ - static void - nv50_display_unk40_handler(struct drm_device *dev) - { -- struct dcb_entry *dcbent; -- int head, pclk, script, ret; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct dcb_entry *dcb = dev_priv->evo_irq.dcb; -+ u16 script = dev_priv->evo_irq.script; -+ u32 unk30 = nv_rd32(dev, 0x610030), pclk = dev_priv->evo_irq.pclk; - -- ret = nv50_display_irq_head(dev, &head, &dcbent); -- if (ret) -+ NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); -+ dev_priv->evo_irq.dcb = NULL; -+ if (!dcb) - goto ack; -- pclk = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(head, CLOCK)) & 0x3fffff; -- script = nv50_display_script_select(dev, dcbent, pclk); - -- nouveau_bios_run_display_table(dev, dcbent, script, -pclk); -+ nouveau_bios_run_display_table(dev, dcb, script, -pclk); -+ nv50_display_unk40_dp_set_tmds(dev, dcb); - - ack: - nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK40); -diff --git a/drivers/gpu/drm/nouveau/nv50_fifo.c b/drivers/gpu/drm/nouveau/nv50_fifo.c -index e20c0e2..fb0281a 100644 ---- a/drivers/gpu/drm/nouveau/nv50_fifo.c -+++ b/drivers/gpu/drm/nouveau/nv50_fifo.c -@@ -28,41 +28,33 @@ - #include "drm.h" - #include "nouveau_drv.h" - --struct nv50_fifo_priv { -- struct nouveau_gpuobj_ref *thingo[2]; -- int cur_thingo; --}; -- --#define IS_G80 ((dev_priv->chipset & 0xf0) == 0x50) -- - static void --nv50_fifo_init_thingo(struct drm_device *dev) -+nv50_fifo_playlist_update(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nv50_fifo_priv *priv = dev_priv->engine.fifo.priv; -+ struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; - struct nouveau_gpuobj_ref *cur; - int i, nr; - - NV_DEBUG(dev, "\n"); - -- cur = priv->thingo[priv->cur_thingo]; -- priv->cur_thingo = !priv->cur_thingo; -+ cur = pfifo->playlist[pfifo->cur_playlist]; -+ pfifo->cur_playlist = !pfifo->cur_playlist; - - /* We never schedule channel 0 or 127 */ -- dev_priv->engine.instmem.prepare_access(dev, true); - for (i = 1, nr = 0; i < 127; i++) { - if (dev_priv->fifos[i] && dev_priv->fifos[i]->ramfc) - nv_wo32(dev, cur->gpuobj, nr++, i); - } -- dev_priv->engine.instmem.finish_access(dev); -+ dev_priv->engine.instmem.flush(dev); - - nv_wr32(dev, 0x32f4, cur->instance >> 12); - nv_wr32(dev, 0x32ec, nr); - nv_wr32(dev, 0x2500, 0x101); - } - --static int --nv50_fifo_channel_enable(struct drm_device *dev, int channel, bool nt) -+static void -+nv50_fifo_channel_enable(struct drm_device *dev, int channel) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = dev_priv->fifos[channel]; -@@ -70,37 +62,28 @@ nv50_fifo_channel_enable(struct drm_device *dev, int channel, bool nt) - - NV_DEBUG(dev, "ch%d\n", channel); - -- if (!chan->ramfc) -- return -EINVAL; -- -- if (IS_G80) -+ if (dev_priv->chipset == 0x50) - inst = chan->ramfc->instance >> 12; - else - inst = chan->ramfc->instance >> 8; -- nv_wr32(dev, NV50_PFIFO_CTX_TABLE(channel), -- inst | NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED); - -- if (!nt) -- nv50_fifo_init_thingo(dev); -- return 0; -+ nv_wr32(dev, NV50_PFIFO_CTX_TABLE(channel), inst | -+ NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED); - } - - static void --nv50_fifo_channel_disable(struct drm_device *dev, int channel, bool nt) -+nv50_fifo_channel_disable(struct drm_device *dev, int channel) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t inst; - -- NV_DEBUG(dev, "ch%d, nt=%d\n", channel, nt); -+ NV_DEBUG(dev, "ch%d\n", channel); - -- if (IS_G80) -+ if (dev_priv->chipset == 0x50) - inst = NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G80; - else - inst = NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G84; - nv_wr32(dev, NV50_PFIFO_CTX_TABLE(channel), inst); -- -- if (!nt) -- nv50_fifo_init_thingo(dev); - } - - static void -@@ -133,12 +116,12 @@ nv50_fifo_init_context_table(struct drm_device *dev) - - for (i = 0; i < NV50_PFIFO_CTX_TABLE__SIZE; i++) { - if (dev_priv->fifos[i]) -- nv50_fifo_channel_enable(dev, i, true); -+ nv50_fifo_channel_enable(dev, i); - else -- nv50_fifo_channel_disable(dev, i, true); -+ nv50_fifo_channel_disable(dev, i); - } - -- nv50_fifo_init_thingo(dev); -+ nv50_fifo_playlist_update(dev); - } - - static void -@@ -162,41 +145,38 @@ nv50_fifo_init_regs(struct drm_device *dev) - nv_wr32(dev, 0x3270, 0); - - /* Enable dummy channels setup by nv50_instmem.c */ -- nv50_fifo_channel_enable(dev, 0, true); -- nv50_fifo_channel_enable(dev, 127, true); -+ nv50_fifo_channel_enable(dev, 0); -+ nv50_fifo_channel_enable(dev, 127); - } - - int - nv50_fifo_init(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nv50_fifo_priv *priv; -+ struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; - int ret; - - NV_DEBUG(dev, "\n"); - -- priv = dev_priv->engine.fifo.priv; -- if (priv) { -- priv->cur_thingo = !priv->cur_thingo; -+ if (pfifo->playlist[0]) { -+ pfifo->cur_playlist = !pfifo->cur_playlist; - goto just_reset; - } - -- priv = kzalloc(sizeof(*priv), GFP_KERNEL); -- if (!priv) -- return -ENOMEM; -- dev_priv->engine.fifo.priv = priv; -- - ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 128*4, 0x1000, -- NVOBJ_FLAG_ZERO_ALLOC, &priv->thingo[0]); -+ NVOBJ_FLAG_ZERO_ALLOC, -+ &pfifo->playlist[0]); - if (ret) { -- NV_ERROR(dev, "error creating thingo0: %d\n", ret); -+ NV_ERROR(dev, "error creating playlist 0: %d\n", ret); - return ret; - } - - ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 128*4, 0x1000, -- NVOBJ_FLAG_ZERO_ALLOC, &priv->thingo[1]); -+ NVOBJ_FLAG_ZERO_ALLOC, -+ &pfifo->playlist[1]); - if (ret) { -- NV_ERROR(dev, "error creating thingo1: %d\n", ret); -+ nouveau_gpuobj_ref_del(dev, &pfifo->playlist[0]); -+ NV_ERROR(dev, "error creating playlist 1: %d\n", ret); - return ret; - } - -@@ -216,18 +196,15 @@ void - nv50_fifo_takedown(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nv50_fifo_priv *priv = dev_priv->engine.fifo.priv; -+ struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; - - NV_DEBUG(dev, "\n"); - -- if (!priv) -+ if (!pfifo->playlist[0]) - return; - -- nouveau_gpuobj_ref_del(dev, &priv->thingo[0]); -- nouveau_gpuobj_ref_del(dev, &priv->thingo[1]); -- -- dev_priv->engine.fifo.priv = NULL; -- kfree(priv); -+ nouveau_gpuobj_ref_del(dev, &pfifo->playlist[0]); -+ nouveau_gpuobj_ref_del(dev, &pfifo->playlist[1]); - } - - int -@@ -248,7 +225,7 @@ nv50_fifo_create_context(struct nouveau_channel *chan) - - NV_DEBUG(dev, "ch%d\n", chan->id); - -- if (IS_G80) { -+ if (dev_priv->chipset == 0x50) { - uint32_t ramin_poffset = chan->ramin->gpuobj->im_pramin->start; - uint32_t ramin_voffset = chan->ramin->gpuobj->im_backing_start; - -@@ -281,10 +258,10 @@ nv50_fifo_create_context(struct nouveau_channel *chan) - - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - -- dev_priv->engine.instmem.prepare_access(dev, true); -- - nv_wo32(dev, ramfc, 0x48/4, chan->pushbuf->instance >> 4); -- nv_wo32(dev, ramfc, 0x80/4, (0xc << 24) | (chan->ramht->instance >> 4)); -+ nv_wo32(dev, ramfc, 0x80/4, (0 << 27) /* 4KiB */ | -+ (4 << 24) /* SEARCH_FULL */ | -+ (chan->ramht->instance >> 4)); - nv_wo32(dev, ramfc, 0x44/4, 0x2101ffff); - nv_wo32(dev, ramfc, 0x60/4, 0x7fffffff); - nv_wo32(dev, ramfc, 0x40/4, 0x00000000); -@@ -295,7 +272,7 @@ nv50_fifo_create_context(struct nouveau_channel *chan) - chan->dma.ib_base * 4); - nv_wo32(dev, ramfc, 0x54/4, drm_order(chan->dma.ib_max + 1) << 16); - -- if (!IS_G80) { -+ if (dev_priv->chipset != 0x50) { - nv_wo32(dev, chan->ramin->gpuobj, 0, chan->id); - nv_wo32(dev, chan->ramin->gpuobj, 1, - chan->ramfc->instance >> 8); -@@ -304,16 +281,10 @@ nv50_fifo_create_context(struct nouveau_channel *chan) - nv_wo32(dev, ramfc, 0x98/4, chan->ramin->instance >> 12); - } - -- dev_priv->engine.instmem.finish_access(dev); -- -- ret = nv50_fifo_channel_enable(dev, chan->id, false); -- if (ret) { -- NV_ERROR(dev, "error enabling ch%d: %d\n", chan->id, ret); -- spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -- nouveau_gpuobj_ref_del(dev, &chan->ramfc); -- return ret; -- } -+ dev_priv->engine.instmem.flush(dev); - -+ nv50_fifo_channel_enable(dev, chan->id); -+ nv50_fifo_playlist_update(dev); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - return 0; - } -@@ -328,11 +299,12 @@ nv50_fifo_destroy_context(struct nouveau_channel *chan) - - /* This will ensure the channel is seen as disabled. */ - chan->ramfc = NULL; -- nv50_fifo_channel_disable(dev, chan->id, false); -+ nv50_fifo_channel_disable(dev, chan->id); - - /* Dummy channel, also used on ch 127 */ - if (chan->id == 0) -- nv50_fifo_channel_disable(dev, 127, false); -+ nv50_fifo_channel_disable(dev, 127); -+ nv50_fifo_playlist_update(dev); - - nouveau_gpuobj_ref_del(dev, &ramfc); - nouveau_gpuobj_ref_del(dev, &chan->cache); -@@ -349,8 +321,6 @@ nv50_fifo_load_context(struct nouveau_channel *chan) - - NV_DEBUG(dev, "ch%d\n", chan->id); - -- dev_priv->engine.instmem.prepare_access(dev, false); -- - nv_wr32(dev, 0x3330, nv_ro32(dev, ramfc, 0x00/4)); - nv_wr32(dev, 0x3334, nv_ro32(dev, ramfc, 0x04/4)); - nv_wr32(dev, 0x3240, nv_ro32(dev, ramfc, 0x08/4)); -@@ -396,7 +366,7 @@ nv50_fifo_load_context(struct nouveau_channel *chan) - nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); - - /* guessing that all the 0x34xx regs aren't on NV50 */ -- if (!IS_G80) { -+ if (dev_priv->chipset != 0x50) { - nv_wr32(dev, 0x340c, nv_ro32(dev, ramfc, 0x88/4)); - nv_wr32(dev, 0x3400, nv_ro32(dev, ramfc, 0x8c/4)); - nv_wr32(dev, 0x3404, nv_ro32(dev, ramfc, 0x90/4)); -@@ -404,8 +374,6 @@ nv50_fifo_load_context(struct nouveau_channel *chan) - nv_wr32(dev, 0x3410, nv_ro32(dev, ramfc, 0x98/4)); - } - -- dev_priv->engine.instmem.finish_access(dev); -- - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, chan->id | (1<<16)); - return 0; - } -@@ -434,8 +402,6 @@ nv50_fifo_unload_context(struct drm_device *dev) - ramfc = chan->ramfc->gpuobj; - cache = chan->cache->gpuobj; - -- dev_priv->engine.instmem.prepare_access(dev, true); -- - nv_wo32(dev, ramfc, 0x00/4, nv_rd32(dev, 0x3330)); - nv_wo32(dev, ramfc, 0x04/4, nv_rd32(dev, 0x3334)); - nv_wo32(dev, ramfc, 0x08/4, nv_rd32(dev, 0x3240)); -@@ -482,7 +448,7 @@ nv50_fifo_unload_context(struct drm_device *dev) - } - - /* guessing that all the 0x34xx regs aren't on NV50 */ -- if (!IS_G80) { -+ if (dev_priv->chipset != 0x50) { - nv_wo32(dev, ramfc, 0x84/4, ptr >> 1); - nv_wo32(dev, ramfc, 0x88/4, nv_rd32(dev, 0x340c)); - nv_wo32(dev, ramfc, 0x8c/4, nv_rd32(dev, 0x3400)); -@@ -491,7 +457,7 @@ nv50_fifo_unload_context(struct drm_device *dev) - nv_wo32(dev, ramfc, 0x98/4, nv_rd32(dev, 0x3410)); - } - -- dev_priv->engine.instmem.finish_access(dev); -+ dev_priv->engine.instmem.flush(dev); - - /*XXX: probably reload ch127 (NULL) state back too */ - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, 127); -diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c -index b203d06..1413028 100644 ---- a/drivers/gpu/drm/nouveau/nv50_graph.c -+++ b/drivers/gpu/drm/nouveau/nv50_graph.c -@@ -30,8 +30,6 @@ - - #include "nouveau_grctx.h" - --#define IS_G80 ((dev_priv->chipset & 0xf0) == 0x50) -- - static void - nv50_graph_init_reset(struct drm_device *dev) - { -@@ -103,37 +101,33 @@ static int - nv50_graph_init_ctxctl(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_grctx ctx = {}; -+ uint32_t *cp; -+ int i; - - NV_DEBUG(dev, "\n"); - -- if (nouveau_ctxfw) { -- nouveau_grctx_prog_load(dev); -- dev_priv->engine.graph.grctx_size = 0x70000; -+ cp = kmalloc(512 * 4, GFP_KERNEL); -+ if (!cp) { -+ NV_ERROR(dev, "failed to allocate ctxprog\n"); -+ dev_priv->engine.graph.accel_blocked = true; -+ return 0; - } -- if (!dev_priv->engine.graph.ctxprog) { -- struct nouveau_grctx ctx = {}; -- uint32_t *cp = kmalloc(512 * 4, GFP_KERNEL); -- int i; -- if (!cp) { -- NV_ERROR(dev, "Couldn't alloc ctxprog! Disabling acceleration.\n"); -- dev_priv->engine.graph.accel_blocked = true; -- return 0; -- } -- ctx.dev = dev; -- ctx.mode = NOUVEAU_GRCTX_PROG; -- ctx.data = cp; -- ctx.ctxprog_max = 512; -- if (!nv50_grctx_init(&ctx)) { -- dev_priv->engine.graph.grctx_size = ctx.ctxvals_pos * 4; -- -- nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); -- for (i = 0; i < ctx.ctxprog_len; i++) -- nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, cp[i]); -- } else { -- dev_priv->engine.graph.accel_blocked = true; -- } -- kfree(cp); -+ -+ ctx.dev = dev; -+ ctx.mode = NOUVEAU_GRCTX_PROG; -+ ctx.data = cp; -+ ctx.ctxprog_max = 512; -+ if (!nv50_grctx_init(&ctx)) { -+ dev_priv->engine.graph.grctx_size = ctx.ctxvals_pos * 4; -+ -+ nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); -+ for (i = 0; i < ctx.ctxprog_len; i++) -+ nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, cp[i]); -+ } else { -+ dev_priv->engine.graph.accel_blocked = true; - } -+ kfree(cp); - - nv_wr32(dev, 0x400320, 4); - nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0); -@@ -164,7 +158,6 @@ void - nv50_graph_takedown(struct drm_device *dev) - { - NV_DEBUG(dev, "\n"); -- nouveau_grctx_fini(dev); - } - - void -@@ -212,8 +205,9 @@ nv50_graph_create_context(struct nouveau_channel *chan) - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *ramin = chan->ramin->gpuobj; -- struct nouveau_gpuobj *ctx; -+ struct nouveau_gpuobj *obj; - struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; -+ struct nouveau_grctx ctx = {}; - int hdr, ret; - - NV_DEBUG(dev, "ch%d\n", chan->id); -@@ -223,10 +217,9 @@ nv50_graph_create_context(struct nouveau_channel *chan) - NVOBJ_FLAG_ZERO_FREE, &chan->ramin_grctx); - if (ret) - return ret; -- ctx = chan->ramin_grctx->gpuobj; -+ obj = chan->ramin_grctx->gpuobj; - -- hdr = IS_G80 ? 0x200 : 0x20; -- dev_priv->engine.instmem.prepare_access(dev, true); -+ hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20; - nv_wo32(dev, ramin, (hdr + 0x00)/4, 0x00190002); - nv_wo32(dev, ramin, (hdr + 0x04)/4, chan->ramin_grctx->instance + - pgraph->grctx_size - 1); -@@ -234,21 +227,15 @@ nv50_graph_create_context(struct nouveau_channel *chan) - nv_wo32(dev, ramin, (hdr + 0x0c)/4, 0); - nv_wo32(dev, ramin, (hdr + 0x10)/4, 0); - nv_wo32(dev, ramin, (hdr + 0x14)/4, 0x00010000); -- dev_priv->engine.instmem.finish_access(dev); -- -- dev_priv->engine.instmem.prepare_access(dev, true); -- if (!pgraph->ctxprog) { -- struct nouveau_grctx ctx = {}; -- ctx.dev = chan->dev; -- ctx.mode = NOUVEAU_GRCTX_VALS; -- ctx.data = chan->ramin_grctx->gpuobj; -- nv50_grctx_init(&ctx); -- } else { -- nouveau_grctx_vals_load(dev, ctx); -- } -- nv_wo32(dev, ctx, 0x00000/4, chan->ramin->instance >> 12); -- dev_priv->engine.instmem.finish_access(dev); - -+ ctx.dev = chan->dev; -+ ctx.mode = NOUVEAU_GRCTX_VALS; -+ ctx.data = obj; -+ nv50_grctx_init(&ctx); -+ -+ nv_wo32(dev, obj, 0x00000/4, chan->ramin->instance >> 12); -+ -+ dev_priv->engine.instmem.flush(dev); - return 0; - } - -@@ -257,17 +244,16 @@ nv50_graph_destroy_context(struct nouveau_channel *chan) - { - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -- int i, hdr = IS_G80 ? 0x200 : 0x20; -+ int i, hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20; - - NV_DEBUG(dev, "ch%d\n", chan->id); - - if (!chan->ramin || !chan->ramin->gpuobj) - return; - -- dev_priv->engine.instmem.prepare_access(dev, true); - for (i = hdr; i < hdr + 24; i += 4) - nv_wo32(dev, chan->ramin->gpuobj, i/4, 0); -- dev_priv->engine.instmem.finish_access(dev); -+ dev_priv->engine.instmem.flush(dev); - - nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx); - } -diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c -index 5f21df3..b7ad258 100644 ---- a/drivers/gpu/drm/nouveau/nv50_instmem.c -+++ b/drivers/gpu/drm/nouveau/nv50_instmem.c -@@ -35,8 +35,6 @@ struct nv50_instmem_priv { - struct nouveau_gpuobj_ref *pramin_pt; - struct nouveau_gpuobj_ref *pramin_bar; - struct nouveau_gpuobj_ref *fb_bar; -- -- bool last_access_wr; - }; - - #define NV50_INSTMEM_PAGE_SHIFT 12 -@@ -147,7 +145,7 @@ nv50_instmem_init(struct drm_device *dev) - if (ret) - return ret; - -- if (nouveau_mem_init_heap(&chan->ramin_heap, c_base, c_size - c_base)) -+ if (drm_mm_init(&chan->ramin_heap, c_base, c_size - c_base)) - return -ENOMEM; - - /* RAMFC + zero channel's PRAMIN up to start of VM pagedir */ -@@ -262,23 +260,18 @@ nv50_instmem_init(struct drm_device *dev) - - /* Assume that praying isn't enough, check that we can re-read the - * entire fake channel back from the PRAMIN BAR */ -- dev_priv->engine.instmem.prepare_access(dev, false); - for (i = 0; i < c_size; i += 4) { - if (nv_rd32(dev, NV_RAMIN + i) != nv_ri32(dev, i)) { - NV_ERROR(dev, "Error reading back PRAMIN at 0x%08x\n", - i); -- dev_priv->engine.instmem.finish_access(dev); - return -EINVAL; - } - } -- dev_priv->engine.instmem.finish_access(dev); - - nv_wr32(dev, NV50_PUNK_BAR0_PRAMIN, save_nv001700); - - /* Global PRAMIN heap */ -- if (nouveau_mem_init_heap(&dev_priv->ramin_heap, -- c_size, dev_priv->ramin_size - c_size)) { -- dev_priv->ramin_heap = NULL; -+ if (drm_mm_init(&dev_priv->ramin_heap, c_size, dev_priv->ramin_size - c_size)) { - NV_ERROR(dev, "Failed to init RAMIN heap\n"); - } - -@@ -321,7 +314,7 @@ nv50_instmem_takedown(struct drm_device *dev) - nouveau_gpuobj_del(dev, &chan->vm_pd); - nouveau_gpuobj_ref_del(dev, &chan->ramfc); - nouveau_gpuobj_ref_del(dev, &chan->ramin); -- nouveau_mem_takedown(&chan->ramin_heap); -+ drm_mm_takedown(&chan->ramin_heap); - - dev_priv->fifos[0] = dev_priv->fifos[127] = NULL; - kfree(chan); -@@ -436,14 +429,14 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) - if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound) - return -EINVAL; - -- NV_DEBUG(dev, "st=0x%0llx sz=0x%0llx\n", -+ NV_DEBUG(dev, "st=0x%lx sz=0x%lx\n", - gpuobj->im_pramin->start, gpuobj->im_pramin->size); - - pte = (gpuobj->im_pramin->start >> 12) << 1; - pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte; - vram = gpuobj->im_backing_start; - -- NV_DEBUG(dev, "pramin=0x%llx, pte=%d, pte_end=%d\n", -+ NV_DEBUG(dev, "pramin=0x%lx, pte=%d, pte_end=%d\n", - gpuobj->im_pramin->start, pte, pte_end); - NV_DEBUG(dev, "first vram page: 0x%08x\n", gpuobj->im_backing_start); - -@@ -453,27 +446,15 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) - vram |= 0x30; - } - -- dev_priv->engine.instmem.prepare_access(dev, true); - while (pte < pte_end) { - nv_wo32(dev, pramin_pt, pte++, lower_32_bits(vram)); - nv_wo32(dev, pramin_pt, pte++, upper_32_bits(vram)); - vram += NV50_INSTMEM_PAGE_SIZE; - } -- dev_priv->engine.instmem.finish_access(dev); -- -- nv_wr32(dev, 0x100c80, 0x00040001); -- if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { -- NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (1)\n"); -- NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); -- return -EBUSY; -- } -+ dev_priv->engine.instmem.flush(dev); - -- nv_wr32(dev, 0x100c80, 0x00060001); -- if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { -- NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); -- NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); -- return -EBUSY; -- } -+ nv50_vm_flush(dev, 4); -+ nv50_vm_flush(dev, 6); - - gpuobj->im_bound = 1; - return 0; -@@ -492,36 +473,36 @@ nv50_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) - pte = (gpuobj->im_pramin->start >> 12) << 1; - pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte; - -- dev_priv->engine.instmem.prepare_access(dev, true); - while (pte < pte_end) { - nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000); - nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000); - } -- dev_priv->engine.instmem.finish_access(dev); -+ dev_priv->engine.instmem.flush(dev); - - gpuobj->im_bound = 0; - return 0; - } - - void --nv50_instmem_prepare_access(struct drm_device *dev, bool write) -+nv50_instmem_flush(struct drm_device *dev) - { -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; -- -- priv->last_access_wr = write; -+ nv_wr32(dev, 0x00330c, 0x00000001); -+ if (!nv_wait(0x00330c, 0x00000001, 0x00000000)) -+ NV_ERROR(dev, "PRAMIN flush timeout\n"); - } - - void --nv50_instmem_finish_access(struct drm_device *dev) -+nv84_instmem_flush(struct drm_device *dev) - { -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; -- -- if (priv->last_access_wr) { -- nv_wr32(dev, 0x070000, 0x00000001); -- if (!nv_wait(0x070000, 0x00000001, 0x00000000)) -- NV_ERROR(dev, "PRAMIN flush timeout\n"); -- } -+ nv_wr32(dev, 0x070000, 0x00000001); -+ if (!nv_wait(0x070000, 0x00000001, 0x00000000)) -+ NV_ERROR(dev, "PRAMIN flush timeout\n"); - } - -+void -+nv50_vm_flush(struct drm_device *dev, int engine) -+{ -+ nv_wr32(dev, 0x100c80, (engine << 16) | 1); -+ if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) -+ NV_ERROR(dev, "vm flush timeout: engine %d\n", engine); -+} -diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c -index 812778d..bcd4cf8 100644 ---- a/drivers/gpu/drm/nouveau/nv50_sor.c -+++ b/drivers/gpu/drm/nouveau/nv50_sor.c -@@ -37,52 +37,32 @@ - #include "nv50_display.h" - - static void --nv50_sor_disconnect(struct nouveau_encoder *nv_encoder) -+nv50_sor_disconnect(struct drm_encoder *encoder) - { -- struct drm_device *dev = to_drm_encoder(nv_encoder)->dev; -+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -+ struct drm_device *dev = encoder->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *evo = dev_priv->evo; - int ret; - -+ if (!nv_encoder->crtc) -+ return; -+ nv50_crtc_blank(nouveau_crtc(nv_encoder->crtc), true); -+ - NV_DEBUG_KMS(dev, "Disconnecting SOR %d\n", nv_encoder->or); - -- ret = RING_SPACE(evo, 2); -+ ret = RING_SPACE(evo, 4); - if (ret) { - NV_ERROR(dev, "no space while disconnecting SOR\n"); - return; - } - BEGIN_RING(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1); -- OUT_RING(evo, 0); --} -- --static void --nv50_sor_dp_link_train(struct drm_encoder *encoder) --{ -- struct drm_device *dev = encoder->dev; -- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -- struct bit_displayport_encoder_table *dpe; -- int dpe_headerlen; -- -- dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); -- if (!dpe) { -- NV_ERROR(dev, "SOR-%d: no DP encoder table!\n", nv_encoder->or); -- return; -- } -+ OUT_RING (evo, 0); -+ BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); -+ OUT_RING (evo, 0); - -- if (dpe->script0) { -- NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or); -- nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script0), -- nv_encoder->dcb); -- } -- -- if (!nouveau_dp_link_train(encoder)) -- NV_ERROR(dev, "SOR-%d: link training failed\n", nv_encoder->or); -- -- if (dpe->script1) { -- NV_DEBUG_KMS(dev, "SOR-%d: running DP script 1\n", nv_encoder->or); -- nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script1), -- nv_encoder->dcb); -- } -+ nv_encoder->crtc = NULL; -+ nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; - } - - static void -@@ -94,14 +74,16 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) - uint32_t val; - int or = nv_encoder->or; - -- NV_DEBUG_KMS(dev, "or %d mode %d\n", or, mode); -+ NV_DEBUG_KMS(dev, "or %d type %d mode %d\n", or, nv_encoder->dcb->type, mode); - - nv_encoder->last_dpms = mode; - list_for_each_entry(enc, &dev->mode_config.encoder_list, head) { - struct nouveau_encoder *nvenc = nouveau_encoder(enc); - - if (nvenc == nv_encoder || -- nvenc->disconnect != nv50_sor_disconnect || -+ (nvenc->dcb->type != OUTPUT_TMDS && -+ nvenc->dcb->type != OUTPUT_LVDS && -+ nvenc->dcb->type != OUTPUT_DP) || - nvenc->dcb->or != nv_encoder->dcb->or) - continue; - -@@ -133,8 +115,22 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) - nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_STATE(or))); - } - -- if (nv_encoder->dcb->type == OUTPUT_DP && mode == DRM_MODE_DPMS_ON) -- nv50_sor_dp_link_train(encoder); -+ if (nv_encoder->dcb->type == OUTPUT_DP) { -+ struct nouveau_i2c_chan *auxch; -+ -+ auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); -+ if (!auxch) -+ return; -+ -+ if (mode == DRM_MODE_DPMS_ON) { -+ u8 status = DP_SET_POWER_D0; -+ nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1); -+ nouveau_dp_link_train(encoder); -+ } else { -+ u8 status = DP_SET_POWER_D3; -+ nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1); -+ } -+ } - } - - static void -@@ -196,7 +192,8 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, - uint32_t mode_ctl = 0; - int ret; - -- NV_DEBUG_KMS(dev, "or %d\n", nv_encoder->or); -+ NV_DEBUG_KMS(dev, "or %d type %d -> crtc %d\n", -+ nv_encoder->or, nv_encoder->dcb->type, crtc->index); - - nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON); - -@@ -239,6 +236,14 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, - } - BEGIN_RING(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1); - OUT_RING(evo, mode_ctl); -+ -+ nv_encoder->crtc = encoder->crtc; -+} -+ -+static struct drm_crtc * -+nv50_sor_crtc_get(struct drm_encoder *encoder) -+{ -+ return nouveau_encoder(encoder)->crtc; - } - - static const struct drm_encoder_helper_funcs nv50_sor_helper_funcs = { -@@ -249,7 +254,9 @@ static const struct drm_encoder_helper_funcs nv50_sor_helper_funcs = { - .prepare = nv50_sor_prepare, - .commit = nv50_sor_commit, - .mode_set = nv50_sor_mode_set, -- .detect = NULL -+ .get_crtc = nv50_sor_crtc_get, -+ .detect = NULL, -+ .disable = nv50_sor_disconnect - }; - - static void -@@ -272,32 +279,22 @@ static const struct drm_encoder_funcs nv50_sor_encoder_funcs = { - }; - - int --nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry) -+nv50_sor_create(struct drm_connector *connector, struct dcb_entry *entry) - { - struct nouveau_encoder *nv_encoder = NULL; -+ struct drm_device *dev = connector->dev; - struct drm_encoder *encoder; -- bool dum; - int type; - - NV_DEBUG_KMS(dev, "\n"); - - switch (entry->type) { - case OUTPUT_TMDS: -- NV_INFO(dev, "Detected a TMDS output\n"); -+ case OUTPUT_DP: - type = DRM_MODE_ENCODER_TMDS; - break; - case OUTPUT_LVDS: -- NV_INFO(dev, "Detected a LVDS output\n"); - type = DRM_MODE_ENCODER_LVDS; -- -- if (nouveau_bios_parse_lvds_table(dev, 0, &dum, &dum)) { -- NV_ERROR(dev, "Failed parsing LVDS table\n"); -- return -EINVAL; -- } -- break; -- case OUTPUT_DP: -- NV_INFO(dev, "Detected a DP output\n"); -- type = DRM_MODE_ENCODER_TMDS; - break; - default: - return -EINVAL; -@@ -310,8 +307,7 @@ nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry) - - nv_encoder->dcb = entry; - nv_encoder->or = ffs(entry->or) - 1; -- -- nv_encoder->disconnect = nv50_sor_disconnect; -+ nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; - - drm_encoder_init(dev, encoder, &nv50_sor_encoder_funcs, type); - drm_encoder_helper_add(encoder, &nv50_sor_helper_funcs); -@@ -342,5 +338,6 @@ nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry) - nv_encoder->dp.mc_unknown = 5; - } - -+ drm_mode_connector_attach_encoder(connector, encoder); - return 0; - } -diff --git a/drivers/gpu/drm/nouveau/nvreg.h b/drivers/gpu/drm/nouveau/nvreg.h -index 5998c35..ad64673 100644 ---- a/drivers/gpu/drm/nouveau/nvreg.h -+++ b/drivers/gpu/drm/nouveau/nvreg.h -@@ -147,28 +147,6 @@ - # define NV_VIO_GX_DONT_CARE_INDEX 0x07 - # define NV_VIO_GX_BIT_MASK_INDEX 0x08 - --#define NV_PFB_BOOT_0 0x00100000 --#define NV_PFB_CFG0 0x00100200 --#define NV_PFB_CFG1 0x00100204 --#define NV_PFB_CSTATUS 0x0010020C --#define NV_PFB_REFCTRL 0x00100210 --# define NV_PFB_REFCTRL_VALID_1 (1 << 31) --#define NV_PFB_PAD 0x0010021C --# define NV_PFB_PAD_CKE_NORMAL (1 << 0) --#define NV_PFB_TILE_NV10 0x00100240 --#define NV_PFB_TILE_SIZE_NV10 0x00100244 --#define NV_PFB_REF 0x001002D0 --# define NV_PFB_REF_CMD_REFRESH (1 << 0) --#define NV_PFB_PRE 0x001002D4 --# define NV_PFB_PRE_CMD_PRECHARGE (1 << 0) --#define NV_PFB_CLOSE_PAGE2 0x0010033C --#define NV_PFB_TILE_NV40 0x00100600 --#define NV_PFB_TILE_SIZE_NV40 0x00100604 -- --#define NV_PEXTDEV_BOOT_0 0x00101000 --# define NV_PEXTDEV_BOOT_0_STRAP_FP_IFACE_12BIT (8 << 12) --#define NV_PEXTDEV_BOOT_3 0x0010100c -- - #define NV_PCRTC_INTR_0 0x00600100 - # define NV_PCRTC_INTR_0_VBLANK (1 << 0) - #define NV_PCRTC_INTR_EN_0 0x00600140 +nil diff --git a/drm-revert-drm-fbdev-rework-output-polling-to-be-back-in-core.patch b/drm-revert-drm-fbdev-rework-output-polling-to-be-back-in-core.patch deleted file mode 100644 index 481a08fdc..000000000 --- a/drm-revert-drm-fbdev-rework-output-polling-to-be-back-in-core.patch +++ /dev/null @@ -1,958 +0,0 @@ -From 5b904034b0ab5195d971b139d0c0b67ab21b063c Mon Sep 17 00:00:00 2001 -From: Kyle McMartin -Date: Mon, 21 Jun 2010 20:33:16 +0100 -Subject: Revert "drm/fbdev: rework output polling to be back in the core. (v4)" - -This reverts commit eb1f8e4f3be898df808e2dfc131099f5831d491d. - -Conflicts: - - drivers/gpu/drm/drm_crtc_helper.c - drivers/gpu/drm/i915/i915_dma.c - drivers/gpu/drm/i915/intel_fb.c - drivers/gpu/drm/nouveau/nouveau_fbcon.c - drivers/gpu/drm/radeon/radeon_fb.c - include/drm/drm_crtc_helper.h ---- - drivers/gpu/drm/Kconfig | 2 +- - drivers/gpu/drm/drm_crtc_helper.c | 111 ------------------------ - drivers/gpu/drm/drm_fb_helper.c | 123 +++++++++++++++++++++++---- - drivers/gpu/drm/i915/i915_dma.c | 1 - - drivers/gpu/drm/i915/i915_irq.c | 3 +- - drivers/gpu/drm/i915/intel_crt.c | 5 - - drivers/gpu/drm/i915/intel_display.c | 2 - - drivers/gpu/drm/i915/intel_dp.c | 2 - - drivers/gpu/drm/i915/intel_drv.h | 2 +- - drivers/gpu/drm/i915/intel_fb.c | 14 ++-- - drivers/gpu/drm/i915/intel_hdmi.c | 1 - - drivers/gpu/drm/i915/intel_sdvo.c | 2 - - drivers/gpu/drm/nouveau/nouveau_connector.c | 12 --- - drivers/gpu/drm/nouveau/nouveau_display.c | 1 - - drivers/gpu/drm/nouveau/nouveau_fbcon.c | 13 ++- - drivers/gpu/drm/nouveau/nouveau_fbcon.h | 2 +- - drivers/gpu/drm/nouveau/nouveau_state.c | 5 +- - drivers/gpu/drm/nouveau/nv50_display.c | 2 +- - drivers/gpu/drm/radeon/radeon_connectors.c | 13 --- - drivers/gpu/drm/radeon/radeon_display.c | 10 -- - drivers/gpu/drm/radeon/radeon_fb.c | 15 +++- - drivers/gpu/drm/radeon/radeon_irq_kms.c | 5 +- - drivers/gpu/drm/radeon/radeon_mode.h | 3 +- - include/drm/drm_crtc.h | 17 ---- - include/drm/drm_crtc_helper.h | 6 -- - include/drm/drm_fb_helper.h | 13 +++- - 26 files changed, 155 insertions(+), 230 deletions(-) - -diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig -index c2711c6..a51a1e4 100644 ---- a/drivers/gpu/drm/Kconfig -+++ b/drivers/gpu/drm/Kconfig -@@ -9,7 +9,6 @@ menuconfig DRM - depends on (AGP || AGP=n) && PCI && !EMULATED_CMPXCHG && MMU - select I2C - select I2C_ALGOBIT -- select SLOW_WORK - help - Kernel-level support for the Direct Rendering Infrastructure (DRI) - introduced in XFree86 4.0. If you say Y here, you need to select -@@ -24,6 +23,7 @@ config DRM_KMS_HELPER - depends on DRM - select FB - select FRAMEBUFFER_CONSOLE if !EMBEDDED -+ select SLOW_WORK - help - FB and CRTC helpers for KMS drivers. - -diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c -index 9b2a541..b142ac2 100644 ---- a/drivers/gpu/drm/drm_crtc_helper.c -+++ b/drivers/gpu/drm/drm_crtc_helper.c -@@ -807,114 +807,3 @@ int drm_helper_resume_force_mode(struct drm_device *dev) - return 0; - } - EXPORT_SYMBOL(drm_helper_resume_force_mode); -- --static struct slow_work_ops output_poll_ops; -- --#define DRM_OUTPUT_POLL_PERIOD (10*HZ) --static void output_poll_execute(struct slow_work *work) --{ -- struct delayed_slow_work *delayed_work = container_of(work, struct delayed_slow_work, work); -- struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_slow_work); -- struct drm_connector *connector; -- enum drm_connector_status old_status, status; -- bool repoll = false, changed = false; -- int ret; -- -- mutex_lock(&dev->mode_config.mutex); -- list_for_each_entry(connector, &dev->mode_config.connector_list, head) { -- -- /* if this is HPD or polled don't check it - -- TV out for instance */ -- if (!connector->polled) -- continue; -- -- else if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT)) -- repoll = true; -- -- old_status = connector->status; -- /* if we are connected and don't want to poll for disconnect -- skip it */ -- if (old_status == connector_status_connected && -- !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT) && -- !(connector->polled & DRM_CONNECTOR_POLL_HPD)) -- continue; -- -- status = connector->funcs->detect(connector); -- if (old_status != status) -- changed = true; -- } -- -- mutex_unlock(&dev->mode_config.mutex); -- -- if (changed) { -- /* send a uevent + call fbdev */ -- drm_sysfs_hotplug_event(dev); -- if (dev->mode_config.funcs->output_poll_changed) -- dev->mode_config.funcs->output_poll_changed(dev); -- } -- -- if (repoll) { -- ret = delayed_slow_work_enqueue(delayed_work, DRM_OUTPUT_POLL_PERIOD); -- if (ret) -- DRM_ERROR("delayed enqueue failed %d\n", ret); -- } --} -- --void drm_kms_helper_poll_disable(struct drm_device *dev) --{ -- if (!dev->mode_config.poll_enabled) -- return; -- delayed_slow_work_cancel(&dev->mode_config.output_poll_slow_work); --} --EXPORT_SYMBOL(drm_kms_helper_poll_disable); -- --void drm_kms_helper_poll_enable(struct drm_device *dev) --{ -- bool poll = false; -- struct drm_connector *connector; -- int ret; -- -- list_for_each_entry(connector, &dev->mode_config.connector_list, head) { -- if (connector->polled) -- poll = true; -- } -- -- if (poll) { -- ret = delayed_slow_work_enqueue(&dev->mode_config.output_poll_slow_work, DRM_OUTPUT_POLL_PERIOD); -- if (ret) -- DRM_ERROR("delayed enqueue failed %d\n", ret); -- } --} --EXPORT_SYMBOL(drm_kms_helper_poll_enable); -- --void drm_kms_helper_poll_init(struct drm_device *dev) --{ -- slow_work_register_user(THIS_MODULE); -- delayed_slow_work_init(&dev->mode_config.output_poll_slow_work, -- &output_poll_ops); -- dev->mode_config.poll_enabled = true; -- -- drm_kms_helper_poll_enable(dev); --} --EXPORT_SYMBOL(drm_kms_helper_poll_init); -- --void drm_kms_helper_poll_fini(struct drm_device *dev) --{ -- drm_kms_helper_poll_disable(dev); -- slow_work_unregister_user(THIS_MODULE); --} --EXPORT_SYMBOL(drm_kms_helper_poll_fini); -- --void drm_helper_hpd_irq_event(struct drm_device *dev) --{ -- if (!dev->mode_config.poll_enabled) -- return; -- delayed_slow_work_cancel(&dev->mode_config.output_poll_slow_work); -- /* schedule a slow work asap */ -- delayed_slow_work_enqueue(&dev->mode_config.output_poll_slow_work, 0); --} --EXPORT_SYMBOL(drm_helper_hpd_irq_event); -- --static struct slow_work_ops output_poll_ops = { -- .execute = output_poll_execute, --}; -diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c -index 08c4c92..dcc6601 100644 ---- a/drivers/gpu/drm/drm_fb_helper.c -+++ b/drivers/gpu/drm/drm_fb_helper.c -@@ -42,6 +42,8 @@ MODULE_LICENSE("GPL and additional rights"); - - static LIST_HEAD(kernel_fb_helper_list); - -+static struct slow_work_ops output_status_change_ops; -+ - /* simple single crtc case helper function */ - int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) - { -@@ -423,13 +425,19 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper) - - int drm_fb_helper_init(struct drm_device *dev, - struct drm_fb_helper *fb_helper, -- int crtc_count, int max_conn_count) -+ int crtc_count, int max_conn_count, -+ bool polled) - { - struct drm_crtc *crtc; - int ret = 0; - int i; - - fb_helper->dev = dev; -+ fb_helper->poll_enabled = polled; -+ -+ slow_work_register_user(THIS_MODULE); -+ delayed_slow_work_init(&fb_helper->output_status_change_slow_work, -+ &output_status_change_ops); - - INIT_LIST_HEAD(&fb_helper->kernel_fb_list); - -@@ -486,6 +494,8 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) - - drm_fb_helper_crtc_free(fb_helper); - -+ delayed_slow_work_cancel(&fb_helper->output_status_change_slow_work); -+ slow_work_unregister_user(THIS_MODULE); - } - EXPORT_SYMBOL(drm_fb_helper_fini); - -@@ -703,7 +713,7 @@ int drm_fb_helper_set_par(struct fb_info *info) - - if (fb_helper->delayed_hotplug) { - fb_helper->delayed_hotplug = false; -- drm_fb_helper_hotplug_event(fb_helper); -+ delayed_slow_work_enqueue(&fb_helper->output_status_change_slow_work, 0); - } - return 0; - } -@@ -816,7 +826,7 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, - if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) { - /* hmm everyone went away - assume VGA cable just fell out - and will come back later. */ -- DRM_INFO("Cannot find any crtc or sizes - going 1024x768\n"); -+ DRM_ERROR("Cannot find any crtc or sizes - going 1024x768\n"); - sizes.fb_width = sizes.surface_width = 1024; - sizes.fb_height = sizes.surface_height = 768; - } -@@ -1362,7 +1372,12 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) - * we shouldn't end up with no modes here. - */ - if (count == 0) { -- printk(KERN_INFO "No connectors reported connected with modes\n"); -+ if (fb_helper->poll_enabled) { -+ delayed_slow_work_enqueue(&fb_helper->output_status_change_slow_work, -+ 5*HZ); -+ printk(KERN_INFO "No connectors reported connected with modes - started polling\n"); -+ } else -+ printk(KERN_INFO "No connectors reported connected with modes\n"); - } - drm_setup_crtcs(fb_helper); - -@@ -1370,16 +1385,71 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) - } - EXPORT_SYMBOL(drm_fb_helper_initial_config); - --bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) -+/* we got a hotplug irq - need to update fbcon */ -+void drm_helper_fb_hpd_irq_event(struct drm_fb_helper *fb_helper) -+{ -+ /* if we don't have the fbdev registered yet do nothing */ -+ if (!fb_helper->fbdev) -+ return; -+ -+ /* schedule a slow work asap */ -+ delayed_slow_work_enqueue(&fb_helper->output_status_change_slow_work, 0); -+} -+EXPORT_SYMBOL(drm_helper_fb_hpd_irq_event); -+ -+bool drm_helper_fb_hotplug_event(struct drm_fb_helper *fb_helper, bool polled) - { - int count = 0; -+ int ret; - u32 max_width, max_height, bpp_sel; -- bool bound = false, crtcs_bound = false; -- struct drm_crtc *crtc; - - if (!fb_helper->fb) - return false; -+ DRM_DEBUG_KMS("\n"); -+ -+ max_width = fb_helper->fb->width; -+ max_height = fb_helper->fb->height; -+ bpp_sel = fb_helper->fb->bits_per_pixel; -+ -+ count = drm_fb_helper_probe_connector_modes(fb_helper, max_width, -+ max_height); -+ if (fb_helper->poll_enabled && !polled) { -+ if (count) { -+ delayed_slow_work_cancel(&fb_helper->output_status_change_slow_work); -+ } else { -+ ret = delayed_slow_work_enqueue(&fb_helper->output_status_change_slow_work, 5*HZ); -+ } -+ } -+ drm_setup_crtcs(fb_helper); -+ -+ return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel); -+} -+EXPORT_SYMBOL(drm_helper_fb_hotplug_event); -+ -+/* -+ * delayed work queue execution function -+ * - check if fbdev is actually in use on the gpu -+ * - if not set delayed flag and repoll if necessary -+ * - check for connector status change -+ * - repoll if 0 modes found -+ *- call driver output status changed notifier -+ */ -+static void output_status_change_execute(struct slow_work *work) -+{ -+ struct delayed_slow_work *delayed_work = container_of(work, struct delayed_slow_work, work); -+ struct drm_fb_helper *fb_helper = container_of(delayed_work, struct drm_fb_helper, output_status_change_slow_work); -+ struct drm_connector *connector; -+ enum drm_connector_status old_status, status; -+ bool repoll, changed = false; -+ int ret; -+ int i; -+ bool bound = false, crtcs_bound = false; -+ struct drm_crtc *crtc; - -+ repoll = fb_helper->poll_enabled; -+ -+ /* first of all check the fbcon framebuffer is actually bound to any crtc */ -+ /* take into account that no crtc at all maybe bound */ - list_for_each_entry(crtc, &fb_helper->dev->mode_config.crtc_list, head) { - if (crtc->fb) - crtcs_bound = true; -@@ -1387,21 +1457,38 @@ bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) - bound = true; - } - -- if (!bound && crtcs_bound) { -+ if (bound == false && crtcs_bound) { - fb_helper->delayed_hotplug = true; -- return false; -+ goto requeue; - } -- DRM_DEBUG_KMS("\n"); - -- max_width = fb_helper->fb->width; -- max_height = fb_helper->fb->height; -- bpp_sel = fb_helper->fb->bits_per_pixel; -+ for (i = 0; i < fb_helper->connector_count; i++) { -+ connector = fb_helper->connector_info[i]->connector; -+ old_status = connector->status; -+ status = connector->funcs->detect(connector); -+ if (old_status != status) { -+ changed = true; -+ } -+ if (status == connector_status_connected && repoll) { -+ DRM_DEBUG("%s is connected - stop polling\n", drm_get_connector_name(connector)); -+ repoll = false; -+ } -+ } - -- count = drm_fb_helper_probe_connector_modes(fb_helper, max_width, -- max_height); -- drm_setup_crtcs(fb_helper); -+ if (changed) { -+ if (fb_helper->funcs->fb_output_status_changed) -+ fb_helper->funcs->fb_output_status_changed(fb_helper); -+ } - -- return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel); -+requeue: -+ if (repoll) { -+ ret = delayed_slow_work_enqueue(delayed_work, 5*HZ); -+ if (ret) -+ DRM_ERROR("delayed enqueue failed %d\n", ret); -+ } - } --EXPORT_SYMBOL(drm_fb_helper_hotplug_event); -+ -+static struct slow_work_ops output_status_change_ops = { -+ .execute = output_status_change_execute, -+}; - -diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c -index 59a2bf8..76ace2d 100644 ---- a/drivers/gpu/drm/i915/i915_dma.c -+++ b/drivers/gpu/drm/i915/i915_dma.c -@@ -1430,7 +1430,6 @@ static int i915_load_modeset_init(struct drm_device *dev, - if (ret) - goto cleanup_irq; - -- drm_kms_helper_poll_init(dev); - return 0; - - cleanup_irq: -diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c -index 2479be0..6350bd3 100644 ---- a/drivers/gpu/drm/i915/i915_irq.c -+++ b/drivers/gpu/drm/i915/i915_irq.c -@@ -271,7 +271,8 @@ static void i915_hotplug_work_func(struct work_struct *work) - } - } - /* Just fire off a uevent and let userspace tell us what to do */ -- drm_helper_hpd_irq_event(dev); -+ intelfb_hotplug(dev, false); -+ drm_sysfs_hotplug_event(dev); - } - - static void i915_handle_rps_change(struct drm_device *dev) -diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c -index 22ff384..125eded 100644 ---- a/drivers/gpu/drm/i915/intel_crt.c -+++ b/drivers/gpu/drm/i915/intel_crt.c -@@ -584,10 +584,5 @@ void intel_crt_init(struct drm_device *dev) - - drm_sysfs_connector_add(connector); - -- if (I915_HAS_HOTPLUG(dev)) -- connector->polled = DRM_CONNECTOR_POLL_HPD; -- else -- connector->polled = DRM_CONNECTOR_POLL_CONNECT; -- - dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS; - } -diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c -index d753257..70537cf 100644 ---- a/drivers/gpu/drm/i915/intel_display.c -+++ b/drivers/gpu/drm/i915/intel_display.c -@@ -5036,7 +5036,6 @@ intel_user_framebuffer_create(struct drm_device *dev, - - static const struct drm_mode_config_funcs intel_mode_funcs = { - .fb_create = intel_user_framebuffer_create, -- .output_poll_changed = intel_fb_output_poll_changed, - }; - - static struct drm_gem_object * -@@ -5538,7 +5537,6 @@ void intel_modeset_cleanup(struct drm_device *dev) - - mutex_lock(&dev->struct_mutex); - -- drm_kms_helper_poll_fini(dev); - intel_fbdev_fini(dev); - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { -diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c -index 49b54f0..1815df5 100644 ---- a/drivers/gpu/drm/i915/intel_dp.c -+++ b/drivers/gpu/drm/i915/intel_dp.c -@@ -1393,8 +1393,6 @@ intel_dp_init(struct drm_device *dev, int output_reg) - DRM_MODE_CONNECTOR_DisplayPort); - drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs); - -- connector->polled = DRM_CONNECTOR_POLL_HPD; -- - if (output_reg == DP_A) - intel_encoder->type = INTEL_OUTPUT_EDP; - else -diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h -index df931f7..3230e8d 100644 ---- a/drivers/gpu/drm/i915/intel_drv.h -+++ b/drivers/gpu/drm/i915/intel_drv.h -@@ -235,5 +235,5 @@ extern int intel_overlay_put_image(struct drm_device *dev, void *data, - extern int intel_overlay_attrs(struct drm_device *dev, void *data, - struct drm_file *file_priv); - --extern void intel_fb_output_poll_changed(struct drm_device *dev); -+void intelfb_hotplug(struct drm_device *dev, bool polled); - #endif /* __INTEL_DRV_H__ */ -diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c -index c3c5052..79098b3 100644 ---- a/drivers/gpu/drm/i915/intel_fb.c -+++ b/drivers/gpu/drm/i915/intel_fb.c -@@ -211,6 +211,12 @@ static int intel_fb_find_or_create_single(struct drm_fb_helper *helper, - return new_fb; - } - -+void intelfb_hotplug(struct drm_device *dev, bool polled) -+{ -+ drm_i915_private_t *dev_priv = dev->dev_private; -+ drm_helper_fb_hpd_irq_event(&dev_priv->fbdev->helper); -+} -+ - static struct drm_fb_helper_funcs intel_fb_helper_funcs = { - .gamma_set = intel_crtc_fb_gamma_set, - .gamma_get = intel_crtc_fb_gamma_get, -@@ -256,7 +262,7 @@ int intel_fbdev_init(struct drm_device *dev) - - ret = drm_fb_helper_init(dev, &ifbdev->helper, - dev_priv->num_pipe, -- INTELFB_CONN_LIMIT); -+ INTELFB_CONN_LIMIT, false); - if (ret) { - kfree(ifbdev); - return ret; -@@ -278,9 +284,3 @@ void intel_fbdev_fini(struct drm_device *dev) - dev_priv->fbdev = NULL; - } - MODULE_LICENSE("GPL and additional rights"); -- --void intel_fb_output_poll_changed(struct drm_device *dev) --{ -- drm_i915_private_t *dev_priv = dev->dev_private; -- drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper); --} -diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c -index 83bd764..acaca07 100644 ---- a/drivers/gpu/drm/i915/intel_hdmi.c -+++ b/drivers/gpu/drm/i915/intel_hdmi.c -@@ -240,7 +240,6 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) - - intel_encoder->type = INTEL_OUTPUT_HDMI; - -- connector->polled = DRM_CONNECTOR_POLL_HPD; - connector->interlace_allowed = 0; - connector->doublescan_allowed = 0; - intel_encoder->crtc_mask = (1 << 0) | (1 << 1); -diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c -index 76993ac..1c716b5 100644 ---- a/drivers/gpu/drm/i915/intel_sdvo.c -+++ b/drivers/gpu/drm/i915/intel_sdvo.c -@@ -2218,7 +2218,6 @@ intel_sdvo_dvi_init(struct intel_encoder *intel_encoder, int device) - } - - connector = &intel_connector->base; -- connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; - encoder->encoder_type = DRM_MODE_ENCODER_TMDS; - connector->connector_type = DRM_MODE_CONNECTOR_DVID; - -@@ -2285,7 +2284,6 @@ intel_sdvo_analog_init(struct intel_encoder *intel_encoder, int device) - return false; - - connector = &intel_connector->base; -- connector->polled = DRM_CONNECTOR_POLL_CONNECT; - encoder->encoder_type = DRM_MODE_ENCODER_DAC; - connector->connector_type = DRM_MODE_CONNECTOR_VGA; - sdvo_connector = intel_connector->dev_priv; -diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c -index 149ed22..9a61f3c 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_connector.c -+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c -@@ -846,7 +846,6 @@ nouveau_connector_create(struct drm_device *dev, - - switch (dcb->type) { - case DCB_CONNECTOR_VGA: -- connector->polled = DRM_CONNECTOR_POLL_CONNECT; - if (dev_priv->card_type >= NV_50) { - drm_connector_attach_property(connector, - dev->mode_config.scaling_mode_property, -@@ -858,17 +857,6 @@ nouveau_connector_create(struct drm_device *dev, - case DCB_CONNECTOR_TV_3: - nv_connector->scaling_mode = DRM_MODE_SCALE_NONE; - break; -- case DCB_CONNECTOR_DP: -- case DCB_CONNECTOR_eDP: -- case DCB_CONNECTOR_HDMI_0: -- case DCB_CONNECTOR_HDMI_1: -- case DCB_CONNECTOR_DVI_I: -- case DCB_CONNECTOR_DVI_D: -- if (dev_priv->card_type >= NV_50) -- connector->polled = DRM_CONNECTOR_POLL_HPD; -- else -- connector->polled = DRM_CONNECTOR_POLL_CONNECT; -- /* fall-through */ - default: - nv_connector->scaling_mode = DRM_MODE_SCALE_FULLSCREEN; - -diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c -index 74e6b4e..9d7928f 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_display.c -+++ b/drivers/gpu/drm/nouveau/nouveau_display.c -@@ -101,6 +101,5 @@ nouveau_user_framebuffer_create(struct drm_device *dev, - - const struct drm_mode_config_funcs nouveau_mode_config_funcs = { - .fb_create = nouveau_user_framebuffer_create, -- .output_poll_changed = nouveau_fbcon_output_poll_changed, - }; - -diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c -index c9a4a0d..0a59f96 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c -+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c -@@ -326,11 +326,15 @@ nouveau_fbcon_find_or_create_single(struct drm_fb_helper *helper, - return new_fb; - } - --void --nouveau_fbcon_output_poll_changed(struct drm_device *dev) -+void nouveau_fbcon_hotplug(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- drm_fb_helper_hotplug_event(&dev_priv->nfbdev->helper); -+ drm_helper_fb_hpd_irq_event(&dev_priv->nfbdev->helper); -+} -+ -+static void nouveau_fbcon_output_status_changed(struct drm_fb_helper *fb_helper) -+{ -+ drm_helper_fb_hotplug_event(fb_helper, true); - } - - int -@@ -370,6 +374,7 @@ static struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = { - .gamma_set = nouveau_fbcon_gamma_set, - .gamma_get = nouveau_fbcon_gamma_get, - .fb_probe = nouveau_fbcon_find_or_create_single, -+ .fb_output_status_changed = nouveau_fbcon_output_status_changed, - }; - - -@@ -387,7 +392,7 @@ int nouveau_fbcon_init(struct drm_device *dev) - dev_priv->nfbdev = nfbdev; - nfbdev->helper.funcs = &nouveau_fbcon_helper_funcs; - -- ret = drm_fb_helper_init(dev, &nfbdev->helper, 2, 4); -+ ret = drm_fb_helper_init(dev, &nfbdev->helper, 2, 4, true); - if (ret) { - kfree(nfbdev); - return ret; -diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.h b/drivers/gpu/drm/nouveau/nouveau_fbcon.h -index e7e1268..bf8e00d 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_fbcon.h -+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.h -@@ -58,6 +58,6 @@ void nouveau_fbcon_zfill_all(struct drm_device *dev); - void nouveau_fbcon_save_disable_accel(struct drm_device *dev); - void nouveau_fbcon_restore_accel(struct drm_device *dev); - --void nouveau_fbcon_output_poll_changed(struct drm_device *dev); -+void nouveau_fbcon_hotplug(struct drm_device *dev); - #endif /* __NV50_FBCON_H__ */ - -diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c -index b02a231..4dcb976 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_state.c -+++ b/drivers/gpu/drm/nouveau/nouveau_state.c -@@ -519,10 +519,8 @@ nouveau_card_init(struct drm_device *dev) - - dev_priv->init_state = NOUVEAU_CARD_INIT_DONE; - -- if (drm_core_check_feature(dev, DRIVER_MODESET)) { -+ if (drm_core_check_feature(dev, DRIVER_MODESET)) - nouveau_fbcon_init(dev); -- drm_kms_helper_poll_init(dev); -- } - - return 0; - -@@ -844,7 +842,6 @@ int nouveau_unload(struct drm_device *dev) - struct drm_nouveau_private *dev_priv = dev->dev_private; - - if (drm_core_check_feature(dev, DRIVER_MODESET)) { -- drm_kms_helper_poll_fini(dev); - nouveau_fbcon_fini(dev); - if (dev_priv->card_type >= NV_50) - nv50_display_destroy(dev); -diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c -index 580a5d1..e6a44af 100644 ---- a/drivers/gpu/drm/nouveau/nv50_display.c -+++ b/drivers/gpu/drm/nouveau/nv50_display.c -@@ -980,7 +980,7 @@ nv50_display_irq_hotplug_bh(struct work_struct *work) - if (dev_priv->chipset >= 0x90) - nv_wr32(dev, 0xe074, nv_rd32(dev, 0xe074)); - -- drm_helper_hpd_irq_event(dev); -+ nouveau_fbcon_hotplug(dev); - } - - void -diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c -index 0c7ccc6..40a24c9 100644 ---- a/drivers/gpu/drm/radeon/radeon_connectors.c -+++ b/drivers/gpu/drm/radeon/radeon_connectors.c -@@ -1085,7 +1085,6 @@ radeon_add_atom_connector(struct drm_device *dev, - drm_connector_attach_property(&radeon_connector->base, - rdev->mode_info.load_detect_property, - 1); -- connector->polled = DRM_CONNECTOR_POLL_CONNECT; - break; - case DRM_MODE_CONNECTOR_DVIA: - drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); -@@ -1212,12 +1211,6 @@ radeon_add_atom_connector(struct drm_device *dev, - break; - } - -- if (hpd->hpd == RADEON_HPD_NONE) { -- if (i2c_bus->valid) -- connector->polled = DRM_CONNECTOR_POLL_CONNECT; -- } else -- connector->polled = DRM_CONNECTOR_POLL_HPD; -- - connector->display_info.subpixel_order = subpixel_order; - drm_sysfs_connector_add(connector); - return; -@@ -1279,7 +1272,6 @@ radeon_add_legacy_connector(struct drm_device *dev, - drm_connector_attach_property(&radeon_connector->base, - rdev->mode_info.load_detect_property, - 1); -- connector->polled = DRM_CONNECTOR_POLL_CONNECT; - break; - case DRM_MODE_CONNECTOR_DVIA: - drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); -@@ -1348,11 +1340,6 @@ radeon_add_legacy_connector(struct drm_device *dev, - break; - } - -- if (hpd->hpd == RADEON_HPD_NONE) { -- if (i2c_bus->valid) -- connector->polled = DRM_CONNECTOR_POLL_CONNECT; -- } else -- connector->polled = DRM_CONNECTOR_POLL_HPD; - connector->display_info.subpixel_order = subpixel_order; - drm_sysfs_connector_add(connector); - return; -diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c -index c73444a..ed756be 100644 ---- a/drivers/gpu/drm/radeon/radeon_display.c -+++ b/drivers/gpu/drm/radeon/radeon_display.c -@@ -887,15 +887,8 @@ radeon_user_framebuffer_create(struct drm_device *dev, - return &radeon_fb->base; - } - --static void radeon_output_poll_changed(struct drm_device *dev) --{ -- struct radeon_device *rdev = dev->dev_private; -- radeon_fb_output_poll_changed(rdev); --} -- - static const struct drm_mode_config_funcs radeon_mode_funcs = { - .fb_create = radeon_user_framebuffer_create, -- .output_poll_changed = radeon_output_poll_changed - }; - - struct drm_prop_enum_list { -@@ -1044,8 +1037,6 @@ int radeon_modeset_init(struct radeon_device *rdev) - radeon_pm_init(rdev); - - radeon_fbdev_init(rdev); -- drm_kms_helper_poll_init(rdev->ddev); -- - return 0; - } - -@@ -1058,7 +1049,6 @@ void radeon_modeset_fini(struct radeon_device *rdev) - radeon_pm_fini(rdev); - - if (rdev->mode_info.mode_config_initialized) { -- drm_kms_helper_poll_fini(rdev->ddev); - radeon_hpd_fini(rdev); - drm_mode_config_cleanup(rdev->ddev); - rdev->mode_info.mode_config_initialized = false; -diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c -index dc1634b..7dc38f6 100644 ---- a/drivers/gpu/drm/radeon/radeon_fb.c -+++ b/drivers/gpu/drm/radeon/radeon_fb.c -@@ -316,9 +316,16 @@ int radeon_parse_options(char *options) - return 0; - } - --void radeon_fb_output_poll_changed(struct radeon_device *rdev) -+void radeonfb_hotplug(struct drm_device *dev, bool polled) - { -- drm_fb_helper_hotplug_event(&rdev->mode_info.rfbdev->helper); -+ struct radeon_device *rdev = dev->dev_private; -+ -+ drm_helper_fb_hpd_irq_event(&rdev->mode_info.rfbdev->helper); -+} -+ -+static void radeon_fb_output_status_changed(struct drm_fb_helper *fb_helper) -+{ -+ drm_helper_fb_hotplug_event(fb_helper, true); - } - - static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfbdev) -@@ -357,6 +364,7 @@ static struct drm_fb_helper_funcs radeon_fb_helper_funcs = { - .gamma_set = radeon_crtc_fb_gamma_set, - .gamma_get = radeon_crtc_fb_gamma_get, - .fb_probe = radeon_fb_find_or_create_single, -+ .fb_output_status_changed = radeon_fb_output_status_changed, - }; - - int radeon_fbdev_init(struct radeon_device *rdev) -@@ -379,7 +387,7 @@ int radeon_fbdev_init(struct radeon_device *rdev) - - ret = drm_fb_helper_init(rdev->ddev, &rfbdev->helper, - rdev->num_crtc, -- RADEONFB_CONN_LIMIT); -+ RADEONFB_CONN_LIMIT, true); - if (ret) { - kfree(rfbdev); - return ret; -@@ -388,6 +396,7 @@ int radeon_fbdev_init(struct radeon_device *rdev) - drm_fb_helper_single_add_all_connectors(&rfbdev->helper); - drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel); - return 0; -+ - } - - void radeon_fbdev_fini(struct radeon_device *rdev) -diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c -index 059bfa4..b0178de 100644 ---- a/drivers/gpu/drm/radeon/radeon_irq_kms.c -+++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c -@@ -26,7 +26,6 @@ - * Jerome Glisse - */ - #include "drmP.h" --#include "drm_crtc_helper.h" - #include "radeon_drm.h" - #include "radeon_reg.h" - #include "radeon.h" -@@ -56,7 +55,9 @@ static void radeon_hotplug_work_func(struct work_struct *work) - radeon_connector_hotplug(connector); - } - /* Just fire off a uevent and let userspace tell us what to do */ -- drm_helper_hpd_irq_event(dev); -+ radeonfb_hotplug(dev, false); -+ -+ drm_sysfs_hotplug_event(dev); - } - - void radeon_driver_irq_preinstall_kms(struct drm_device *dev) -diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h -index 67358ba..fdd1611 100644 ---- a/drivers/gpu/drm/radeon/radeon_mode.h -+++ b/drivers/gpu/drm/radeon/radeon_mode.h -@@ -588,6 +588,5 @@ void radeon_fbdev_fini(struct radeon_device *rdev); - void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state); - int radeon_fbdev_total_size(struct radeon_device *rdev); - bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj); -- --void radeon_fb_output_poll_changed(struct radeon_device *rdev); -+void radeonfb_hotplug(struct drm_device *dev, bool polled); - #endif -diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h -index 93a1a31..a7148d2 100644 ---- a/include/drm/drm_crtc.h -+++ b/include/drm/drm_crtc.h -@@ -31,7 +31,6 @@ - #include - - #include --#include - - struct drm_device; - struct drm_mode_set; -@@ -461,15 +460,6 @@ enum drm_connector_force { - DRM_FORCE_ON_DIGITAL, /* for DVI-I use digital connector */ - }; - --/* should we poll this connector for connects and disconnects */ --/* hot plug detectable */ --#define DRM_CONNECTOR_POLL_HPD (1 << 0) --/* poll for connections */ --#define DRM_CONNECTOR_POLL_CONNECT (1 << 1) --/* can cleanly poll for disconnections without flickering the screen */ --/* DACs should rarely do this without a lot of testing */ --#define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2) -- - /** - * drm_connector - central DRM connector control structure - * @crtc: CRTC this connector is currently connected to, NULL if none -@@ -514,8 +504,6 @@ struct drm_connector { - u32 property_ids[DRM_CONNECTOR_MAX_PROPERTY]; - uint64_t property_values[DRM_CONNECTOR_MAX_PROPERTY]; - -- uint8_t polled; /* DRM_CONNECTOR_POLL_* */ -- - /* requested DPMS state */ - int dpms; - -@@ -555,7 +543,6 @@ struct drm_mode_set { - */ - struct drm_mode_config_funcs { - struct drm_framebuffer *(*fb_create)(struct drm_device *dev, struct drm_file *file_priv, struct drm_mode_fb_cmd *mode_cmd); -- void (*output_poll_changed)(struct drm_device *dev); - }; - - struct drm_mode_group { -@@ -593,10 +580,6 @@ struct drm_mode_config { - struct drm_mode_config_funcs *funcs; - resource_size_t fb_base; - -- /* output poll support */ -- bool poll_enabled; -- struct delayed_slow_work output_poll_slow_work; -- - /* pointers to standard properties */ - struct list_head property_blob_list; - struct drm_property *edid_property; -diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h -index 1121f77..b1fa0f8 100644 ---- a/include/drm/drm_crtc_helper.h -+++ b/include/drm/drm_crtc_helper.h -@@ -127,10 +127,4 @@ static inline void drm_connector_helper_add(struct drm_connector *connector, - } - - extern int drm_helper_resume_force_mode(struct drm_device *dev); --extern void drm_kms_helper_poll_init(struct drm_device *dev); --extern void drm_kms_helper_poll_fini(struct drm_device *dev); --extern void drm_helper_hpd_irq_event(struct drm_device *dev); -- --extern void drm_kms_helper_poll_disable(struct drm_device *dev); --extern void drm_kms_helper_poll_enable(struct drm_device *dev); - #endif -diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h -index f0a6afc..9b55a94 100644 ---- a/include/drm/drm_fb_helper.h -+++ b/include/drm/drm_fb_helper.h -@@ -30,6 +30,8 @@ - #ifndef DRM_FB_HELPER_H - #define DRM_FB_HELPER_H - -+#include -+ - struct drm_fb_helper; - - struct drm_fb_helper_crtc { -@@ -69,6 +71,9 @@ struct drm_fb_helper_funcs { - - int (*fb_probe)(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes); -+ -+ void (*fb_output_status_changed)(struct drm_fb_helper *helper); -+ - }; - - struct drm_fb_helper_connector { -@@ -90,6 +95,8 @@ struct drm_fb_helper { - u32 pseudo_palette[17]; - struct list_head kernel_fb_list; - -+ struct delayed_slow_work output_status_change_slow_work; -+ bool poll_enabled; - /* we got a hotplug but fbdev wasn't running the console - delay until next set_par */ - bool delayed_hotplug; -@@ -100,7 +107,7 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *helper, - - int drm_fb_helper_init(struct drm_device *dev, - struct drm_fb_helper *helper, int crtc_count, -- int max_conn); -+ int max_conn, bool polled); - void drm_fb_helper_fini(struct drm_fb_helper *helper); - int drm_fb_helper_blank(int blank, struct fb_info *info); - int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, -@@ -123,8 +130,10 @@ void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, - - int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info); - --bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper); -+bool drm_helper_fb_hotplug_event(struct drm_fb_helper *fb_helper, -+ bool polled); - bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel); - int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper); - -+void drm_helper_fb_hpd_irq_event(struct drm_fb_helper *fb_helper); - #endif --- -1.7.0.1 - diff --git a/kernel.spec b/kernel.spec index dfa85e324..affce54e7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -648,8 +648,7 @@ Patch800: linux-2.6-crash-driver.patch Patch1555: fix_xen_guest_on_old_EC2.patch # DRM -Patch1801: drm-revert-drm-fbdev-rework-output-polling-to-be-back-in-core.patch -Patch1802: revert-drm-kms-toggle-poll-around-switcheroo.patch + # nouveau + drm fixes Patch1810: drm-nouveau-updates.patch Patch1819: drm-intel-big-hammer.patch @@ -1261,13 +1260,14 @@ ApplyPatch linux-2.6-e1000-ich9-montevina.patch # Assorted Virt Fixes ApplyPatch fix_xen_guest_on_old_EC2.patch -#ApplyPatch drm-revert-drm-fbdev-rework-output-polling-to-be-back-in-core.patch -#ApplyPatch revert-drm-kms-toggle-poll-around-switcheroo.patch +# DRM core -# Nouveau DRM + drm fixes -#ApplyPatch drm-nouveau-updates.patch -ApplyPatch drm-intel-big-hammer.patch +# Nouveau DRM +ApplyOptionalPatch drm-nouveau-updates.patch + +# Intel DRM ApplyOptionalPatch drm-intel-next.patch +ApplyPatch drm-intel-big-hammer.patch ApplyPatch drm-intel-make-lvds-work.patch ApplyPatch linux-2.6-intel-iommu-igfx.patch diff --git a/revert-drm-kms-toggle-poll-around-switcheroo.patch b/revert-drm-kms-toggle-poll-around-switcheroo.patch deleted file mode 100644 index f83fc2fdf..000000000 --- a/revert-drm-kms-toggle-poll-around-switcheroo.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 69b711c0c5e3d9cb3a5b9f741fb4cdc96b5739cb Mon Sep 17 00:00:00 2001 -From: Kyle McMartin -Subject: Revert "drm/kms: disable/enable poll around switcheroo on/off" - -This reverts commit fbf81762e385d3d45acad057b654d56972acf58c, mostly. ---- - drivers/gpu/drm/i915/i915_dma.c | 4 +--- - drivers/gpu/drm/nouveau/nouveau_state.c | 3 --- - drivers/gpu/drm/radeon/radeon_device.c | 2 -- - -diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c -index 59a2bf8..2df3286 100644 ---- a/drivers/gpu/drm/i915/i915_dma.c -+++ b/drivers/gpu/drm/i915/i915_dma.c -@@ -1320,14 +1320,12 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_ - struct drm_device *dev = pci_get_drvdata(pdev); - pm_message_t pmm = { .event = PM_EVENT_SUSPEND }; - if (state == VGA_SWITCHEROO_ON) { -- printk(KERN_INFO "i915: switched on\n"); -+ printk(KERN_INFO "i915: switched off\n"); - /* i915 resume handler doesn't set to D0 */ - pci_set_power_state(dev->pdev, PCI_D0); - i915_resume(dev); -- drm_kms_helper_poll_enable(dev); - } else { - printk(KERN_ERR "i915: switched off\n"); -- drm_kms_helper_poll_disable(dev); - i915_suspend(dev, pmm); - } - } -diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c -index b02a231..0c28266 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_state.c -+++ b/drivers/gpu/drm/nouveau/nouveau_state.c -@@ -376,15 +376,12 @@ out_err: - static void nouveau_switcheroo_set_state(struct pci_dev *pdev, - enum vga_switcheroo_state state) - { -- struct drm_device *dev = pci_get_drvdata(pdev); - pm_message_t pmm = { .event = PM_EVENT_SUSPEND }; - if (state == VGA_SWITCHEROO_ON) { - printk(KERN_ERR "VGA switcheroo: switched nouveau on\n"); - nouveau_pci_resume(pdev); -- drm_kms_helper_poll_enable(dev); - } else { - printk(KERN_ERR "VGA switcheroo: switched nouveau off\n"); -- drm_kms_helper_poll_disable(dev); - nouveau_pci_suspend(pdev, pmm); - } - } -diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c -index f10faed..225a9f2 100644 ---- a/drivers/gpu/drm/radeon/radeon_device.c -+++ b/drivers/gpu/drm/radeon/radeon_device.c -@@ -546,10 +546,8 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero - /* don't suspend or resume card normally */ - rdev->powered_down = false; - radeon_resume_kms(dev); -- drm_kms_helper_poll_enable(dev); - } else { - printk(KERN_INFO "radeon: switched off\n"); -- drm_kms_helper_poll_disable(dev); - radeon_suspend_kms(dev, pmm); - /* don't suspend or resume card normally */ - rdev->powered_down = true;