diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau')
55 files changed, 2112 insertions, 2006 deletions
diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig index 1175429da102..d2d28048efb2 100644 --- a/drivers/gpu/drm/nouveau/Kconfig +++ b/drivers/gpu/drm/nouveau/Kconfig | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | config DRM_NOUVEAU | 1 | config DRM_NOUVEAU |
| 2 | tristate "Nouveau (nVidia) cards" | 2 | tristate "Nouveau (nVidia) cards" |
| 3 | depends on DRM | 3 | depends on DRM && PCI |
| 4 | select FW_LOADER | 4 | select FW_LOADER |
| 5 | select DRM_KMS_HELPER | 5 | select DRM_KMS_HELPER |
| 6 | select DRM_TTM | 6 | select DRM_TTM |
| @@ -41,4 +41,13 @@ config DRM_I2C_CH7006 | |||
| 41 | 41 | ||
| 42 | This driver is currently only useful if you're also using | 42 | This driver is currently only useful if you're also using |
| 43 | the nouveau driver. | 43 | the nouveau driver. |
| 44 | |||
| 45 | config DRM_I2C_SIL164 | ||
| 46 | tristate "Silicon Image sil164 TMDS transmitter" | ||
| 47 | default m if DRM_NOUVEAU | ||
| 48 | help | ||
| 49 | Support for sil164 and similar single-link (or dual-link | ||
| 50 | when used in pairs) TMDS transmitters, used in some nVidia | ||
| 51 | video cards. | ||
| 52 | |||
| 44 | endmenu | 53 | endmenu |
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index acd31ed861ef..2405d5ef0ca7 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile | |||
| @@ -9,10 +9,10 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ | |||
| 9 | nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \ | 9 | nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \ |
| 10 | nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \ | 10 | nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \ |
| 11 | nouveau_display.o nouveau_connector.o nouveau_fbcon.o \ | 11 | nouveau_display.o nouveau_connector.o nouveau_fbcon.o \ |
| 12 | nouveau_dp.o nouveau_grctx.o \ | 12 | nouveau_dp.o \ |
| 13 | nv04_timer.o \ | 13 | nv04_timer.o \ |
| 14 | nv04_mc.o nv40_mc.o nv50_mc.o \ | 14 | nv04_mc.o nv40_mc.o nv50_mc.o \ |
| 15 | nv04_fb.o nv10_fb.o nv40_fb.o nv50_fb.o \ | 15 | nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o \ |
| 16 | nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o \ | 16 | nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o \ |
| 17 | nv04_graph.o nv10_graph.o nv20_graph.o \ | 17 | nv04_graph.o nv10_graph.o nv20_graph.o \ |
| 18 | nv40_graph.o nv50_graph.o \ | 18 | nv40_graph.o nv50_graph.o \ |
| @@ -22,7 +22,7 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ | |||
| 22 | nv50_cursor.o nv50_display.o nv50_fbcon.o \ | 22 | nv50_cursor.o nv50_display.o nv50_fbcon.o \ |
| 23 | nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \ | 23 | nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \ |
| 24 | nv04_crtc.o nv04_display.o nv04_cursor.o nv04_fbcon.o \ | 24 | nv04_crtc.o nv04_display.o nv04_cursor.o nv04_fbcon.o \ |
| 25 | nv17_gpio.o nv50_gpio.o \ | 25 | nv10_gpio.o nv50_gpio.o \ |
| 26 | nv50_calc.o | 26 | nv50_calc.o |
| 27 | 27 | ||
| 28 | nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o | 28 | nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o |
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index d4bcca8a5133..c17a055ee3e5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | #include <linux/slab.h> | 3 | #include <linux/slab.h> |
| 4 | #include <acpi/acpi_drivers.h> | 4 | #include <acpi/acpi_drivers.h> |
| 5 | #include <acpi/acpi_bus.h> | 5 | #include <acpi/acpi_bus.h> |
| 6 | #include <acpi/video.h> | ||
| 6 | 7 | ||
| 7 | #include "drmP.h" | 8 | #include "drmP.h" |
| 8 | #include "drm.h" | 9 | #include "drm.h" |
| @@ -11,6 +12,7 @@ | |||
| 11 | #include "nouveau_drv.h" | 12 | #include "nouveau_drv.h" |
| 12 | #include "nouveau_drm.h" | 13 | #include "nouveau_drm.h" |
| 13 | #include "nv50_display.h" | 14 | #include "nv50_display.h" |
| 15 | #include "nouveau_connector.h" | ||
| 14 | 16 | ||
| 15 | #include <linux/vga_switcheroo.h> | 17 | #include <linux/vga_switcheroo.h> |
| 16 | 18 | ||
| @@ -42,7 +44,7 @@ static const char nouveau_dsm_muid[] = { | |||
| 42 | 0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4, | 44 | 0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4, |
| 43 | }; | 45 | }; |
| 44 | 46 | ||
| 45 | static int nouveau_dsm(acpi_handle handle, int func, int arg, int *result) | 47 | static int nouveau_dsm(acpi_handle handle, int func, int arg, uint32_t *result) |
| 46 | { | 48 | { |
| 47 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | 49 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; |
| 48 | struct acpi_object_list input; | 50 | struct acpi_object_list input; |
| @@ -259,3 +261,37 @@ int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len) | |||
| 259 | { | 261 | { |
| 260 | return nouveau_rom_call(nouveau_dsm_priv.rom_handle, bios, offset, len); | 262 | return nouveau_rom_call(nouveau_dsm_priv.rom_handle, bios, offset, len); |
| 261 | } | 263 | } |
| 264 | |||
| 265 | int | ||
| 266 | nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) | ||
| 267 | { | ||
| 268 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | ||
| 269 | struct acpi_device *acpidev; | ||
| 270 | acpi_handle handle; | ||
| 271 | int type, ret; | ||
| 272 | void *edid; | ||
| 273 | |||
| 274 | switch (connector->connector_type) { | ||
| 275 | case DRM_MODE_CONNECTOR_LVDS: | ||
| 276 | case DRM_MODE_CONNECTOR_eDP: | ||
| 277 | type = ACPI_VIDEO_DISPLAY_LCD; | ||
| 278 | break; | ||
| 279 | default: | ||
| 280 | return -EINVAL; | ||
| 281 | } | ||
| 282 | |||
| 283 | handle = DEVICE_ACPI_HANDLE(&dev->pdev->dev); | ||
| 284 | if (!handle) | ||
| 285 | return -ENODEV; | ||
| 286 | |||
| 287 | ret = acpi_bus_get_device(handle, &acpidev); | ||
| 288 | if (ret) | ||
| 289 | return -ENODEV; | ||
| 290 | |||
| 291 | ret = acpi_video_get_edid(acpidev, type, -1, &edid); | ||
| 292 | if (ret < 0) | ||
| 293 | return ret; | ||
| 294 | |||
| 295 | nv_connector->edid = edid; | ||
| 296 | return 0; | ||
| 297 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index e492919faf44..7369b5e73649 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c | |||
| @@ -28,6 +28,8 @@ | |||
| 28 | #include "nouveau_hw.h" | 28 | #include "nouveau_hw.h" |
| 29 | #include "nouveau_encoder.h" | 29 | #include "nouveau_encoder.h" |
| 30 | 30 | ||
| 31 | #include <linux/io-mapping.h> | ||
| 32 | |||
| 31 | /* these defines are made up */ | 33 | /* these defines are made up */ |
| 32 | #define NV_CIO_CRE_44_HEADA 0x0 | 34 | #define NV_CIO_CRE_44_HEADA 0x0 |
| 33 | #define NV_CIO_CRE_44_HEADB 0x3 | 35 | #define NV_CIO_CRE_44_HEADB 0x3 |
| @@ -209,20 +211,20 @@ static struct methods shadow_methods[] = { | |||
| 209 | { "PCIROM", load_vbios_pci, true }, | 211 | { "PCIROM", load_vbios_pci, true }, |
| 210 | { "ACPI", load_vbios_acpi, true }, | 212 | { "ACPI", load_vbios_acpi, true }, |
| 211 | }; | 213 | }; |
| 214 | #define NUM_SHADOW_METHODS ARRAY_SIZE(shadow_methods) | ||
| 212 | 215 | ||
| 213 | static bool NVShadowVBIOS(struct drm_device *dev, uint8_t *data) | 216 | static bool NVShadowVBIOS(struct drm_device *dev, uint8_t *data) |
| 214 | { | 217 | { |
| 215 | const int nr_methods = ARRAY_SIZE(shadow_methods); | ||
| 216 | struct methods *methods = shadow_methods; | 218 | struct methods *methods = shadow_methods; |
| 217 | int testscore = 3; | 219 | int testscore = 3; |
| 218 | int scores[nr_methods], i; | 220 | int scores[NUM_SHADOW_METHODS], i; |
| 219 | 221 | ||
| 220 | if (nouveau_vbios) { | 222 | if (nouveau_vbios) { |
| 221 | for (i = 0; i < nr_methods; i++) | 223 | for (i = 0; i < NUM_SHADOW_METHODS; i++) |
| 222 | if (!strcasecmp(nouveau_vbios, methods[i].desc)) | 224 | if (!strcasecmp(nouveau_vbios, methods[i].desc)) |
| 223 | break; | 225 | break; |
| 224 | 226 | ||
| 225 | if (i < nr_methods) { | 227 | if (i < NUM_SHADOW_METHODS) { |
| 226 | NV_INFO(dev, "Attempting to use BIOS image from %s\n", | 228 | NV_INFO(dev, "Attempting to use BIOS image from %s\n", |
| 227 | methods[i].desc); | 229 | methods[i].desc); |
| 228 | 230 | ||
| @@ -234,7 +236,7 @@ static bool NVShadowVBIOS(struct drm_device *dev, uint8_t *data) | |||
| 234 | NV_ERROR(dev, "VBIOS source \'%s\' invalid\n", nouveau_vbios); | 236 | NV_ERROR(dev, "VBIOS source \'%s\' invalid\n", nouveau_vbios); |
| 235 | } | 237 | } |
| 236 | 238 | ||
| 237 | for (i = 0; i < nr_methods; i++) { | 239 | for (i = 0; i < NUM_SHADOW_METHODS; i++) { |
| 238 | NV_TRACE(dev, "Attempting to load BIOS image from %s\n", | 240 | NV_TRACE(dev, "Attempting to load BIOS image from %s\n", |
| 239 | methods[i].desc); | 241 | methods[i].desc); |
| 240 | data[0] = data[1] = 0; /* avoid reuse of previous image */ | 242 | data[0] = data[1] = 0; /* avoid reuse of previous image */ |
| @@ -245,7 +247,7 @@ static bool NVShadowVBIOS(struct drm_device *dev, uint8_t *data) | |||
| 245 | } | 247 | } |
| 246 | 248 | ||
| 247 | while (--testscore > 0) { | 249 | while (--testscore > 0) { |
| 248 | for (i = 0; i < nr_methods; i++) { | 250 | for (i = 0; i < NUM_SHADOW_METHODS; i++) { |
| 249 | if (scores[i] == testscore) { | 251 | if (scores[i] == testscore) { |
| 250 | NV_TRACE(dev, "Using BIOS image from %s\n", | 252 | NV_TRACE(dev, "Using BIOS image from %s\n", |
| 251 | methods[i].desc); | 253 | methods[i].desc); |
| @@ -920,7 +922,7 @@ init_io_restrict_prog(struct nvbios *bios, uint16_t offset, | |||
| 920 | NV_ERROR(bios->dev, | 922 | NV_ERROR(bios->dev, |
| 921 | "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n", | 923 | "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n", |
| 922 | offset, config, count); | 924 | offset, config, count); |
| 923 | return -EINVAL; | 925 | return len; |
| 924 | } | 926 | } |
| 925 | 927 | ||
| 926 | configval = ROM32(bios->data[offset + 11 + config * 4]); | 928 | configval = ROM32(bios->data[offset + 11 + config * 4]); |
| @@ -1022,7 +1024,7 @@ init_io_restrict_pll(struct nvbios *bios, uint16_t offset, | |||
| 1022 | NV_ERROR(bios->dev, | 1024 | NV_ERROR(bios->dev, |
| 1023 | "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n", | 1025 | "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n", |
| 1024 | offset, config, count); | 1026 | offset, config, count); |
| 1025 | return -EINVAL; | 1027 | return len; |
| 1026 | } | 1028 | } |
| 1027 | 1029 | ||
| 1028 | freq = ROM16(bios->data[offset + 12 + config * 2]); | 1030 | 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) | |||
| 1194 | dpe = nouveau_bios_dp_table(dev, dcb, &dummy); | 1196 | dpe = nouveau_bios_dp_table(dev, dcb, &dummy); |
| 1195 | if (!dpe) { | 1197 | if (!dpe) { |
| 1196 | NV_ERROR(dev, "0x%04X: INIT_3A: no encoder table!!\n", offset); | 1198 | NV_ERROR(dev, "0x%04X: INIT_3A: no encoder table!!\n", offset); |
| 1197 | return -EINVAL; | 1199 | return 3; |
| 1198 | } | 1200 | } |
| 1199 | 1201 | ||
| 1200 | switch (cond) { | 1202 | switch (cond) { |
| @@ -1218,12 +1220,16 @@ init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
| 1218 | int ret; | 1220 | int ret; |
| 1219 | 1221 | ||
| 1220 | auxch = nouveau_i2c_find(dev, bios->display.output->i2c_index); | 1222 | auxch = nouveau_i2c_find(dev, bios->display.output->i2c_index); |
| 1221 | if (!auxch) | 1223 | if (!auxch) { |
| 1222 | return -ENODEV; | 1224 | NV_ERROR(dev, "0x%04X: couldn't get auxch\n", offset); |
| 1225 | return 3; | ||
| 1226 | } | ||
| 1223 | 1227 | ||
| 1224 | ret = nouveau_dp_auxch(auxch, 9, 0xd, &cond, 1); | 1228 | ret = nouveau_dp_auxch(auxch, 9, 0xd, &cond, 1); |
| 1225 | if (ret) | 1229 | if (ret) { |
| 1226 | return ret; | 1230 | NV_ERROR(dev, "0x%04X: auxch rd fail: %d\n", offset, ret); |
| 1231 | return 3; | ||
| 1232 | } | ||
| 1227 | 1233 | ||
| 1228 | if (cond & 1) | 1234 | if (cond & 1) |
| 1229 | iexec->execute = false; | 1235 | iexec->execute = false; |
| @@ -1392,7 +1398,7 @@ init_io_restrict_pll2(struct nvbios *bios, uint16_t offset, | |||
| 1392 | NV_ERROR(bios->dev, | 1398 | NV_ERROR(bios->dev, |
| 1393 | "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n", | 1399 | "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n", |
| 1394 | offset, config, count); | 1400 | offset, config, count); |
| 1395 | return -EINVAL; | 1401 | return len; |
| 1396 | } | 1402 | } |
| 1397 | 1403 | ||
| 1398 | freq = ROM32(bios->data[offset + 11 + config * 4]); | 1404 | 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) | |||
| 1452 | * "mask n" and OR it with "data n" before writing it back to the device | 1458 | * "mask n" and OR it with "data n" before writing it back to the device |
| 1453 | */ | 1459 | */ |
| 1454 | 1460 | ||
| 1461 | struct drm_device *dev = bios->dev; | ||
| 1455 | uint8_t i2c_index = bios->data[offset + 1]; | 1462 | uint8_t i2c_index = bios->data[offset + 1]; |
| 1456 | uint8_t i2c_address = bios->data[offset + 2] >> 1; | 1463 | uint8_t i2c_address = bios->data[offset + 2] >> 1; |
| 1457 | uint8_t count = bios->data[offset + 3]; | 1464 | uint8_t count = bios->data[offset + 3]; |
| @@ -1466,9 +1473,11 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
| 1466 | "Count: 0x%02X\n", | 1473 | "Count: 0x%02X\n", |
| 1467 | offset, i2c_index, i2c_address, count); | 1474 | offset, i2c_index, i2c_address, count); |
| 1468 | 1475 | ||
| 1469 | chan = init_i2c_device_find(bios->dev, i2c_index); | 1476 | chan = init_i2c_device_find(dev, i2c_index); |
| 1470 | if (!chan) | 1477 | if (!chan) { |
| 1471 | return -ENODEV; | 1478 | NV_ERROR(dev, "0x%04X: i2c bus not found\n", offset); |
| 1479 | return len; | ||
| 1480 | } | ||
| 1472 | 1481 | ||
| 1473 | for (i = 0; i < count; i++) { | 1482 | for (i = 0; i < count; i++) { |
| 1474 | uint8_t reg = bios->data[offset + 4 + i * 3]; | 1483 | 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) | |||
| 1479 | ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0, | 1488 | ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0, |
| 1480 | I2C_SMBUS_READ, reg, | 1489 | I2C_SMBUS_READ, reg, |
| 1481 | I2C_SMBUS_BYTE_DATA, &val); | 1490 | I2C_SMBUS_BYTE_DATA, &val); |
| 1482 | if (ret < 0) | 1491 | if (ret < 0) { |
| 1483 | return ret; | 1492 | NV_ERROR(dev, "0x%04X: i2c rd fail: %d\n", offset, ret); |
| 1493 | return len; | ||
| 1494 | } | ||
| 1484 | 1495 | ||
| 1485 | BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Value: 0x%02X, " | 1496 | BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Value: 0x%02X, " |
| 1486 | "Mask: 0x%02X, Data: 0x%02X\n", | 1497 | "Mask: 0x%02X, Data: 0x%02X\n", |
| @@ -1494,8 +1505,10 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
| 1494 | ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0, | 1505 | ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0, |
| 1495 | I2C_SMBUS_WRITE, reg, | 1506 | I2C_SMBUS_WRITE, reg, |
| 1496 | I2C_SMBUS_BYTE_DATA, &val); | 1507 | I2C_SMBUS_BYTE_DATA, &val); |
| 1497 | if (ret < 0) | 1508 | if (ret < 0) { |
| 1498 | return ret; | 1509 | NV_ERROR(dev, "0x%04X: i2c wr fail: %d\n", offset, ret); |
| 1510 | return len; | ||
| 1511 | } | ||
| 1499 | } | 1512 | } |
| 1500 | 1513 | ||
| 1501 | return len; | 1514 | return len; |
| @@ -1520,6 +1533,7 @@ init_zm_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
| 1520 | * "DCB I2C table entry index", set the register to "data n" | 1533 | * "DCB I2C table entry index", set the register to "data n" |
| 1521 | */ | 1534 | */ |
| 1522 | 1535 | ||
| 1536 | struct drm_device *dev = bios->dev; | ||
| 1523 | uint8_t i2c_index = bios->data[offset + 1]; | 1537 | uint8_t i2c_index = bios->data[offset + 1]; |
| 1524 | uint8_t i2c_address = bios->data[offset + 2] >> 1; | 1538 | uint8_t i2c_address = bios->data[offset + 2] >> 1; |
| 1525 | uint8_t count = bios->data[offset + 3]; | 1539 | 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) | |||
| 1534 | "Count: 0x%02X\n", | 1548 | "Count: 0x%02X\n", |
| 1535 | offset, i2c_index, i2c_address, count); | 1549 | offset, i2c_index, i2c_address, count); |
| 1536 | 1550 | ||
| 1537 | chan = init_i2c_device_find(bios->dev, i2c_index); | 1551 | chan = init_i2c_device_find(dev, i2c_index); |
| 1538 | if (!chan) | 1552 | if (!chan) { |
| 1539 | return -ENODEV; | 1553 | NV_ERROR(dev, "0x%04X: i2c bus not found\n", offset); |
| 1554 | return len; | ||
| 1555 | } | ||
| 1540 | 1556 | ||
| 1541 | for (i = 0; i < count; i++) { | 1557 | for (i = 0; i < count; i++) { |
| 1542 | uint8_t reg = bios->data[offset + 4 + i * 2]; | 1558 | 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) | |||
| 1553 | ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0, | 1569 | ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0, |
| 1554 | I2C_SMBUS_WRITE, reg, | 1570 | I2C_SMBUS_WRITE, reg, |
| 1555 | I2C_SMBUS_BYTE_DATA, &val); | 1571 | I2C_SMBUS_BYTE_DATA, &val); |
| 1556 | if (ret < 0) | 1572 | if (ret < 0) { |
| 1557 | return ret; | 1573 | NV_ERROR(dev, "0x%04X: i2c wr fail: %d\n", offset, ret); |
| 1574 | return len; | ||
| 1575 | } | ||
| 1558 | } | 1576 | } |
| 1559 | 1577 | ||
| 1560 | return len; | 1578 | return len; |
| @@ -1577,6 +1595,7 @@ init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
| 1577 | * address" on the I2C bus given by "DCB I2C table entry index" | 1595 | * address" on the I2C bus given by "DCB I2C table entry index" |
| 1578 | */ | 1596 | */ |
| 1579 | 1597 | ||
| 1598 | struct drm_device *dev = bios->dev; | ||
| 1580 | uint8_t i2c_index = bios->data[offset + 1]; | 1599 | uint8_t i2c_index = bios->data[offset + 1]; |
| 1581 | uint8_t i2c_address = bios->data[offset + 2] >> 1; | 1600 | uint8_t i2c_address = bios->data[offset + 2] >> 1; |
| 1582 | uint8_t count = bios->data[offset + 3]; | 1601 | uint8_t count = bios->data[offset + 3]; |
| @@ -1584,7 +1603,7 @@ init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
| 1584 | struct nouveau_i2c_chan *chan; | 1603 | struct nouveau_i2c_chan *chan; |
| 1585 | struct i2c_msg msg; | 1604 | struct i2c_msg msg; |
| 1586 | uint8_t data[256]; | 1605 | uint8_t data[256]; |
| 1587 | int i; | 1606 | int ret, i; |
| 1588 | 1607 | ||
| 1589 | if (!iexec->execute) | 1608 | if (!iexec->execute) |
| 1590 | return len; | 1609 | return len; |
| @@ -1593,9 +1612,11 @@ init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
| 1593 | "Count: 0x%02X\n", | 1612 | "Count: 0x%02X\n", |
| 1594 | offset, i2c_index, i2c_address, count); | 1613 | offset, i2c_index, i2c_address, count); |
| 1595 | 1614 | ||
| 1596 | chan = init_i2c_device_find(bios->dev, i2c_index); | 1615 | chan = init_i2c_device_find(dev, i2c_index); |
| 1597 | if (!chan) | 1616 | if (!chan) { |
| 1598 | return -ENODEV; | 1617 | NV_ERROR(dev, "0x%04X: i2c bus not found\n", offset); |
| 1618 | return len; | ||
| 1619 | } | ||
| 1599 | 1620 | ||
| 1600 | for (i = 0; i < count; i++) { | 1621 | for (i = 0; i < count; i++) { |
| 1601 | data[i] = bios->data[offset + 4 + i]; | 1622 | data[i] = bios->data[offset + 4 + i]; |
| @@ -1608,8 +1629,11 @@ init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
| 1608 | msg.flags = 0; | 1629 | msg.flags = 0; |
| 1609 | msg.len = count; | 1630 | msg.len = count; |
| 1610 | msg.buf = data; | 1631 | msg.buf = data; |
| 1611 | if (i2c_transfer(&chan->adapter, &msg, 1) != 1) | 1632 | ret = i2c_transfer(&chan->adapter, &msg, 1); |
| 1612 | return -EIO; | 1633 | if (ret != 1) { |
| 1634 | NV_ERROR(dev, "0x%04X: i2c wr fail: %d\n", offset, ret); | ||
| 1635 | return len; | ||
| 1636 | } | ||
| 1613 | } | 1637 | } |
| 1614 | 1638 | ||
| 1615 | return len; | 1639 | return len; |
| @@ -1633,6 +1657,7 @@ init_tmds(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
| 1633 | * used -- see get_tmds_index_reg() | 1657 | * used -- see get_tmds_index_reg() |
| 1634 | */ | 1658 | */ |
| 1635 | 1659 | ||
| 1660 | struct drm_device *dev = bios->dev; | ||
| 1636 | uint8_t mlv = bios->data[offset + 1]; | 1661 | uint8_t mlv = bios->data[offset + 1]; |
| 1637 | uint32_t tmdsaddr = bios->data[offset + 2]; | 1662 | uint32_t tmdsaddr = bios->data[offset + 2]; |
| 1638 | uint8_t mask = bios->data[offset + 3]; | 1663 | uint8_t mask = bios->data[offset + 3]; |
| @@ -1647,8 +1672,10 @@ init_tmds(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
| 1647 | offset, mlv, tmdsaddr, mask, data); | 1672 | offset, mlv, tmdsaddr, mask, data); |
| 1648 | 1673 | ||
| 1649 | reg = get_tmds_index_reg(bios->dev, mlv); | 1674 | reg = get_tmds_index_reg(bios->dev, mlv); |
| 1650 | if (!reg) | 1675 | if (!reg) { |
| 1651 | return -EINVAL; | 1676 | NV_ERROR(dev, "0x%04X: no tmds_index_reg\n", offset); |
| 1677 | return 5; | ||
| 1678 | } | ||
| 1652 | 1679 | ||
| 1653 | bios_wr32(bios, reg, | 1680 | bios_wr32(bios, reg, |
| 1654 | tmdsaddr | NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE); | 1681 | tmdsaddr | NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE); |
| @@ -1678,6 +1705,7 @@ init_zm_tmds_group(struct nvbios *bios, uint16_t offset, | |||
| 1678 | * register is used -- see get_tmds_index_reg() | 1705 | * register is used -- see get_tmds_index_reg() |
| 1679 | */ | 1706 | */ |
| 1680 | 1707 | ||
| 1708 | struct drm_device *dev = bios->dev; | ||
| 1681 | uint8_t mlv = bios->data[offset + 1]; | 1709 | uint8_t mlv = bios->data[offset + 1]; |
| 1682 | uint8_t count = bios->data[offset + 2]; | 1710 | uint8_t count = bios->data[offset + 2]; |
| 1683 | int len = 3 + count * 2; | 1711 | int len = 3 + count * 2; |
| @@ -1691,8 +1719,10 @@ init_zm_tmds_group(struct nvbios *bios, uint16_t offset, | |||
| 1691 | offset, mlv, count); | 1719 | offset, mlv, count); |
| 1692 | 1720 | ||
| 1693 | reg = get_tmds_index_reg(bios->dev, mlv); | 1721 | reg = get_tmds_index_reg(bios->dev, mlv); |
| 1694 | if (!reg) | 1722 | if (!reg) { |
| 1695 | return -EINVAL; | 1723 | NV_ERROR(dev, "0x%04X: no tmds_index_reg\n", offset); |
| 1724 | return len; | ||
| 1725 | } | ||
| 1696 | 1726 | ||
| 1697 | for (i = 0; i < count; i++) { | 1727 | for (i = 0; i < count; i++) { |
| 1698 | uint8_t tmdsaddr = bios->data[offset + 3 + i * 2]; | 1728 | 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) | |||
| 2039 | return 5; | 2069 | return 5; |
| 2040 | } | 2070 | } |
| 2041 | 2071 | ||
| 2072 | static inline void | ||
| 2073 | bios_md32(struct nvbios *bios, uint32_t reg, | ||
| 2074 | uint32_t mask, uint32_t val) | ||
| 2075 | { | ||
| 2076 | bios_wr32(bios, reg, (bios_rd32(bios, reg) & ~mask) | val); | ||
| 2077 | } | ||
| 2078 | |||
| 2079 | static uint32_t | ||
| 2080 | peek_fb(struct drm_device *dev, struct io_mapping *fb, | ||
| 2081 | uint32_t off) | ||
| 2082 | { | ||
| 2083 | uint32_t val = 0; | ||
| 2084 | |||
| 2085 | if (off < pci_resource_len(dev->pdev, 1)) { | ||
| 2086 | uint32_t __iomem *p = io_mapping_map_atomic_wc(fb, off, KM_USER0); | ||
| 2087 | |||
| 2088 | val = ioread32(p); | ||
| 2089 | |||
| 2090 | io_mapping_unmap_atomic(p, KM_USER0); | ||
| 2091 | } | ||
| 2092 | |||
| 2093 | return val; | ||
| 2094 | } | ||
| 2095 | |||
| 2096 | static void | ||
| 2097 | poke_fb(struct drm_device *dev, struct io_mapping *fb, | ||
| 2098 | uint32_t off, uint32_t val) | ||
| 2099 | { | ||
| 2100 | if (off < pci_resource_len(dev->pdev, 1)) { | ||
| 2101 | uint32_t __iomem *p = io_mapping_map_atomic_wc(fb, off, KM_USER0); | ||
| 2102 | |||
| 2103 | iowrite32(val, p); | ||
| 2104 | wmb(); | ||
| 2105 | |||
| 2106 | io_mapping_unmap_atomic(p, KM_USER0); | ||
| 2107 | } | ||
| 2108 | } | ||
| 2109 | |||
| 2110 | static inline bool | ||
| 2111 | read_back_fb(struct drm_device *dev, struct io_mapping *fb, | ||
| 2112 | uint32_t off, uint32_t val) | ||
| 2113 | { | ||
| 2114 | poke_fb(dev, fb, off, val); | ||
| 2115 | return val == peek_fb(dev, fb, off); | ||
| 2116 | } | ||
| 2117 | |||
| 2118 | static int | ||
| 2119 | nv04_init_compute_mem(struct nvbios *bios) | ||
| 2120 | { | ||
| 2121 | struct drm_device *dev = bios->dev; | ||
| 2122 | uint32_t patt = 0xdeadbeef; | ||
| 2123 | struct io_mapping *fb; | ||
| 2124 | int i; | ||
| 2125 | |||
| 2126 | /* Map the framebuffer aperture */ | ||
| 2127 | fb = io_mapping_create_wc(pci_resource_start(dev->pdev, 1), | ||
| 2128 | pci_resource_len(dev->pdev, 1)); | ||
| 2129 | if (!fb) | ||
| 2130 | return -ENOMEM; | ||
| 2131 | |||
| 2132 | /* Sequencer and refresh off */ | ||
| 2133 | NVWriteVgaSeq(dev, 0, 1, NVReadVgaSeq(dev, 0, 1) | 0x20); | ||
| 2134 | bios_md32(bios, NV04_PFB_DEBUG_0, 0, NV04_PFB_DEBUG_0_REFRESH_OFF); | ||
| 2135 | |||
| 2136 | bios_md32(bios, NV04_PFB_BOOT_0, ~0, | ||
| 2137 | NV04_PFB_BOOT_0_RAM_AMOUNT_16MB | | ||
| 2138 | NV04_PFB_BOOT_0_RAM_WIDTH_128 | | ||
| 2139 | NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT); | ||
| 2140 | |||
| 2141 | for (i = 0; i < 4; i++) | ||
| 2142 | poke_fb(dev, fb, 4 * i, patt); | ||
| 2143 | |||
| 2144 | poke_fb(dev, fb, 0x400000, patt + 1); | ||
| 2145 | |||
| 2146 | if (peek_fb(dev, fb, 0) == patt + 1) { | ||
| 2147 | bios_md32(bios, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_TYPE, | ||
| 2148 | NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_16MBIT); | ||
| 2149 | bios_md32(bios, NV04_PFB_DEBUG_0, | ||
| 2150 | NV04_PFB_DEBUG_0_REFRESH_OFF, 0); | ||
| 2151 | |||
| 2152 | for (i = 0; i < 4; i++) | ||
| 2153 | poke_fb(dev, fb, 4 * i, patt); | ||
| 2154 | |||
| 2155 | if ((peek_fb(dev, fb, 0xc) & 0xffff) != (patt & 0xffff)) | ||
| 2156 | bios_md32(bios, NV04_PFB_BOOT_0, | ||
| 2157 | NV04_PFB_BOOT_0_RAM_WIDTH_128 | | ||
| 2158 | NV04_PFB_BOOT_0_RAM_AMOUNT, | ||
| 2159 | NV04_PFB_BOOT_0_RAM_AMOUNT_8MB); | ||
| 2160 | |||
| 2161 | } else if ((peek_fb(dev, fb, 0xc) & 0xffff0000) != | ||
| 2162 | (patt & 0xffff0000)) { | ||
| 2163 | bios_md32(bios, NV04_PFB_BOOT_0, | ||
| 2164 | NV04_PFB_BOOT_0_RAM_WIDTH_128 | | ||
| 2165 | NV04_PFB_BOOT_0_RAM_AMOUNT, | ||
| 2166 | NV04_PFB_BOOT_0_RAM_AMOUNT_4MB); | ||
| 2167 | |||
| 2168 | } else if (peek_fb(dev, fb, 0) == patt) { | ||
| 2169 | if (read_back_fb(dev, fb, 0x800000, patt)) | ||
| 2170 | bios_md32(bios, NV04_PFB_BOOT_0, | ||
| 2171 | NV04_PFB_BOOT_0_RAM_AMOUNT, | ||
| 2172 | NV04_PFB_BOOT_0_RAM_AMOUNT_8MB); | ||
| 2173 | else | ||
| 2174 | bios_md32(bios, NV04_PFB_BOOT_0, | ||
| 2175 | NV04_PFB_BOOT_0_RAM_AMOUNT, | ||
| 2176 | NV04_PFB_BOOT_0_RAM_AMOUNT_4MB); | ||
| 2177 | |||
| 2178 | bios_md32(bios, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_TYPE, | ||
| 2179 | NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_8MBIT); | ||
| 2180 | |||
| 2181 | } else if (!read_back_fb(dev, fb, 0x800000, patt)) { | ||
| 2182 | bios_md32(bios, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, | ||
| 2183 | NV04_PFB_BOOT_0_RAM_AMOUNT_8MB); | ||
| 2184 | |||
| 2185 | } | ||
| 2186 | |||
| 2187 | /* Refresh on, sequencer on */ | ||
| 2188 | bios_md32(bios, NV04_PFB_DEBUG_0, NV04_PFB_DEBUG_0_REFRESH_OFF, 0); | ||
| 2189 | NVWriteVgaSeq(dev, 0, 1, NVReadVgaSeq(dev, 0, 1) & ~0x20); | ||
| 2190 | |||
| 2191 | io_mapping_free(fb); | ||
| 2192 | return 0; | ||
| 2193 | } | ||
| 2194 | |||
| 2195 | static const uint8_t * | ||
| 2196 | nv05_memory_config(struct nvbios *bios) | ||
| 2197 | { | ||
| 2198 | /* Defaults for BIOSes lacking a memory config table */ | ||
| 2199 | static const uint8_t default_config_tab[][2] = { | ||
| 2200 | { 0x24, 0x00 }, | ||
| 2201 | { 0x28, 0x00 }, | ||
| 2202 | { 0x24, 0x01 }, | ||
| 2203 | { 0x1f, 0x00 }, | ||
| 2204 | { 0x0f, 0x00 }, | ||
| 2205 | { 0x17, 0x00 }, | ||
| 2206 | { 0x06, 0x00 }, | ||
| 2207 | { 0x00, 0x00 } | ||
| 2208 | }; | ||
| 2209 | int i = (bios_rd32(bios, NV_PEXTDEV_BOOT_0) & | ||
| 2210 | NV_PEXTDEV_BOOT_0_RAMCFG) >> 2; | ||
| 2211 | |||
| 2212 | if (bios->legacy.mem_init_tbl_ptr) | ||
| 2213 | return &bios->data[bios->legacy.mem_init_tbl_ptr + 2 * i]; | ||
| 2214 | else | ||
| 2215 | return default_config_tab[i]; | ||
| 2216 | } | ||
| 2217 | |||
| 2218 | static int | ||
| 2219 | nv05_init_compute_mem(struct nvbios *bios) | ||
| 2220 | { | ||
| 2221 | struct drm_device *dev = bios->dev; | ||
| 2222 | const uint8_t *ramcfg = nv05_memory_config(bios); | ||
| 2223 | uint32_t patt = 0xdeadbeef; | ||
| 2224 | struct io_mapping *fb; | ||
| 2225 | int i, v; | ||
| 2226 | |||
| 2227 | /* Map the framebuffer aperture */ | ||
| 2228 | fb = io_mapping_create_wc(pci_resource_start(dev->pdev, 1), | ||
| 2229 | pci_resource_len(dev->pdev, 1)); | ||
| 2230 | if (!fb) | ||
| 2231 | return -ENOMEM; | ||
| 2232 | |||
| 2233 | /* Sequencer off */ | ||
| 2234 | NVWriteVgaSeq(dev, 0, 1, NVReadVgaSeq(dev, 0, 1) | 0x20); | ||
| 2235 | |||
| 2236 | if (bios_rd32(bios, NV04_PFB_BOOT_0) & NV04_PFB_BOOT_0_UMA_ENABLE) | ||
| 2237 | goto out; | ||
| 2238 | |||
| 2239 | bios_md32(bios, NV04_PFB_DEBUG_0, NV04_PFB_DEBUG_0_REFRESH_OFF, 0); | ||
| 2240 | |||
| 2241 | /* If present load the hardcoded scrambling table */ | ||
| 2242 | if (bios->legacy.mem_init_tbl_ptr) { | ||
| 2243 | uint32_t *scramble_tab = (uint32_t *)&bios->data[ | ||
| 2244 | bios->legacy.mem_init_tbl_ptr + 0x10]; | ||
| 2245 | |||
| 2246 | for (i = 0; i < 8; i++) | ||
| 2247 | bios_wr32(bios, NV04_PFB_SCRAMBLE(i), | ||
| 2248 | ROM32(scramble_tab[i])); | ||
| 2249 | } | ||
| 2250 | |||
| 2251 | /* Set memory type/width/length defaults depending on the straps */ | ||
| 2252 | bios_md32(bios, NV04_PFB_BOOT_0, 0x3f, ramcfg[0]); | ||
| 2253 | |||
| 2254 | if (ramcfg[1] & 0x80) | ||
| 2255 | bios_md32(bios, NV04_PFB_CFG0, 0, NV04_PFB_CFG0_SCRAMBLE); | ||
| 2256 | |||
| 2257 | bios_md32(bios, NV04_PFB_CFG1, 0x700001, (ramcfg[1] & 1) << 20); | ||
| 2258 | bios_md32(bios, NV04_PFB_CFG1, 0, 1); | ||
| 2259 | |||
| 2260 | /* Probe memory bus width */ | ||
| 2261 | for (i = 0; i < 4; i++) | ||
| 2262 | poke_fb(dev, fb, 4 * i, patt); | ||
| 2263 | |||
| 2264 | if (peek_fb(dev, fb, 0xc) != patt) | ||
| 2265 | bios_md32(bios, NV04_PFB_BOOT_0, | ||
| 2266 | NV04_PFB_BOOT_0_RAM_WIDTH_128, 0); | ||
| 2267 | |||
| 2268 | /* Probe memory length */ | ||
| 2269 | v = bios_rd32(bios, NV04_PFB_BOOT_0) & NV04_PFB_BOOT_0_RAM_AMOUNT; | ||
| 2270 | |||
| 2271 | if (v == NV04_PFB_BOOT_0_RAM_AMOUNT_32MB && | ||
| 2272 | (!read_back_fb(dev, fb, 0x1000000, ++patt) || | ||
| 2273 | !read_back_fb(dev, fb, 0, ++patt))) | ||
| 2274 | bios_md32(bios, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, | ||
| 2275 | NV04_PFB_BOOT_0_RAM_AMOUNT_16MB); | ||
| 2276 | |||
| 2277 | if (v == NV04_PFB_BOOT_0_RAM_AMOUNT_16MB && | ||
| 2278 | !read_back_fb(dev, fb, 0x800000, ++patt)) | ||
| 2279 | bios_md32(bios, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, | ||
| 2280 | NV04_PFB_BOOT_0_RAM_AMOUNT_8MB); | ||
| 2281 | |||
| 2282 | if (!read_back_fb(dev, fb, 0x400000, ++patt)) | ||
| 2283 | bios_md32(bios, NV04_PFB_BOOT_0, NV04_PFB_BOOT_0_RAM_AMOUNT, | ||
| 2284 | NV04_PFB_BOOT_0_RAM_AMOUNT_4MB); | ||
| 2285 | |||
| 2286 | out: | ||
| 2287 | /* Sequencer on */ | ||
| 2288 | NVWriteVgaSeq(dev, 0, 1, NVReadVgaSeq(dev, 0, 1) & ~0x20); | ||
| 2289 | |||
| 2290 | io_mapping_free(fb); | ||
| 2291 | return 0; | ||
| 2292 | } | ||
| 2293 | |||
| 2294 | static int | ||
| 2295 | nv10_init_compute_mem(struct nvbios *bios) | ||
| 2296 | { | ||
| 2297 | struct drm_device *dev = bios->dev; | ||
| 2298 | struct drm_nouveau_private *dev_priv = bios->dev->dev_private; | ||
| 2299 | const int mem_width[] = { 0x10, 0x00, 0x20 }; | ||
| 2300 | const int mem_width_count = (dev_priv->chipset >= 0x17 ? 3 : 2); | ||
| 2301 | uint32_t patt = 0xdeadbeef; | ||
| 2302 | struct io_mapping *fb; | ||
| 2303 | int i, j, k; | ||
| 2304 | |||
| 2305 | /* Map the framebuffer aperture */ | ||
| 2306 | fb = io_mapping_create_wc(pci_resource_start(dev->pdev, 1), | ||
| 2307 | pci_resource_len(dev->pdev, 1)); | ||
| 2308 | if (!fb) | ||
| 2309 | return -ENOMEM; | ||
| 2310 | |||
| 2311 | bios_wr32(bios, NV10_PFB_REFCTRL, NV10_PFB_REFCTRL_VALID_1); | ||
| 2312 | |||
| 2313 | /* Probe memory bus width */ | ||
| 2314 | for (i = 0; i < mem_width_count; i++) { | ||
| 2315 | bios_md32(bios, NV04_PFB_CFG0, 0x30, mem_width[i]); | ||
| 2316 | |||
| 2317 | for (j = 0; j < 4; j++) { | ||
| 2318 | for (k = 0; k < 4; k++) | ||
| 2319 | poke_fb(dev, fb, 0x1c, 0); | ||
| 2320 | |||
| 2321 | poke_fb(dev, fb, 0x1c, patt); | ||
| 2322 | poke_fb(dev, fb, 0x3c, 0); | ||
| 2323 | |||
| 2324 | if (peek_fb(dev, fb, 0x1c) == patt) | ||
| 2325 | goto mem_width_found; | ||
| 2326 | } | ||
| 2327 | } | ||
| 2328 | |||
| 2329 | mem_width_found: | ||
| 2330 | patt <<= 1; | ||
| 2331 | |||
| 2332 | /* Probe amount of installed memory */ | ||
| 2333 | for (i = 0; i < 4; i++) { | ||
| 2334 | int off = bios_rd32(bios, NV04_PFB_FIFO_DATA) - 0x100000; | ||
| 2335 | |||
| 2336 | poke_fb(dev, fb, off, patt); | ||
| 2337 | poke_fb(dev, fb, 0, 0); | ||
| 2338 | |||
| 2339 | peek_fb(dev, fb, 0); | ||
| 2340 | peek_fb(dev, fb, 0); | ||
| 2341 | peek_fb(dev, fb, 0); | ||
| 2342 | peek_fb(dev, fb, 0); | ||
| 2343 | |||
| 2344 | if (peek_fb(dev, fb, off) == patt) | ||
| 2345 | goto amount_found; | ||
| 2346 | } | ||
| 2347 | |||
| 2348 | /* IC missing - disable the upper half memory space. */ | ||
| 2349 | bios_md32(bios, NV04_PFB_CFG0, 0x1000, 0); | ||
| 2350 | |||
| 2351 | amount_found: | ||
| 2352 | io_mapping_free(fb); | ||
| 2353 | return 0; | ||
| 2354 | } | ||
| 2355 | |||
| 2356 | static int | ||
| 2357 | nv20_init_compute_mem(struct nvbios *bios) | ||
| 2358 | { | ||
| 2359 | struct drm_device *dev = bios->dev; | ||
| 2360 | struct drm_nouveau_private *dev_priv = bios->dev->dev_private; | ||
| 2361 | uint32_t mask = (dev_priv->chipset >= 0x25 ? 0x300 : 0x900); | ||
| 2362 | uint32_t amount, off; | ||
| 2363 | struct io_mapping *fb; | ||
| 2364 | |||
| 2365 | /* Map the framebuffer aperture */ | ||
| 2366 | fb = io_mapping_create_wc(pci_resource_start(dev->pdev, 1), | ||
| 2367 | pci_resource_len(dev->pdev, 1)); | ||
| 2368 | if (!fb) | ||
| 2369 | return -ENOMEM; | ||
| 2370 | |||
| 2371 | bios_wr32(bios, NV10_PFB_REFCTRL, NV10_PFB_REFCTRL_VALID_1); | ||
| 2372 | |||
| 2373 | /* Allow full addressing */ | ||
| 2374 | bios_md32(bios, NV04_PFB_CFG0, 0, mask); | ||
| 2375 | |||
| 2376 | amount = bios_rd32(bios, NV04_PFB_FIFO_DATA); | ||
| 2377 | for (off = amount; off > 0x2000000; off -= 0x2000000) | ||
| 2378 | poke_fb(dev, fb, off - 4, off); | ||
| 2379 | |||
| 2380 | amount = bios_rd32(bios, NV04_PFB_FIFO_DATA); | ||
| 2381 | if (amount != peek_fb(dev, fb, amount - 4)) | ||
| 2382 | /* IC missing - disable the upper half memory space. */ | ||
| 2383 | bios_md32(bios, NV04_PFB_CFG0, mask, 0); | ||
| 2384 | |||
| 2385 | io_mapping_free(fb); | ||
| 2386 | return 0; | ||
| 2387 | } | ||
| 2388 | |||
| 2042 | static int | 2389 | static int |
| 2043 | init_compute_mem(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | 2390 | init_compute_mem(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) |
| 2044 | { | 2391 | { |
| @@ -2047,64 +2394,57 @@ init_compute_mem(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
| 2047 | * | 2394 | * |
| 2048 | * offset (8 bit): opcode | 2395 | * offset (8 bit): opcode |
| 2049 | * | 2396 | * |
| 2050 | * This opcode is meant to set NV_PFB_CFG0 (0x100200) appropriately so | 2397 | * This opcode is meant to set the PFB memory config registers |
| 2051 | * that the hardware can correctly calculate how much VRAM it has | 2398 | * appropriately so that we can correctly calculate how much VRAM it |
| 2052 | * (and subsequently report that value in NV_PFB_CSTATUS (0x10020C)) | 2399 | * has (on nv10 and better chipsets the amount of installed VRAM is |
| 2400 | * subsequently reported in NV_PFB_CSTATUS (0x10020C)). | ||
| 2053 | * | 2401 | * |
| 2054 | * The implementation of this opcode in general consists of two parts: | 2402 | * The implementation of this opcode in general consists of several |
| 2055 | * 1) determination of the memory bus width | 2403 | * parts: |
| 2056 | * 2) determination of how many of the card's RAM pads have ICs attached | ||
| 2057 | * | 2404 | * |
| 2058 | * 1) is done by a cunning combination of writes to offsets 0x1c and | 2405 | * 1) Determination of memory type and density. Only necessary for |
| 2059 | * 0x3c in the framebuffer, and seeing whether the written values are | 2406 | * really old chipsets, the memory type reported by the strap bits |
| 2060 | * read back correctly. This then affects bits 4-7 of NV_PFB_CFG0 | 2407 | * (0x101000) is assumed to be accurate on nv05 and newer. |
| 2061 | * | 2408 | * |
| 2062 | * 2) is done by a cunning combination of writes to an offset slightly | 2409 | * 2) Determination of the memory bus width. Usually done by a cunning |
| 2063 | * less than the maximum memory reported by NV_PFB_CSTATUS, then seeing | 2410 | * combination of writes to offsets 0x1c and 0x3c in the fb, and |
| 2064 | * if the test pattern can be read back. This then affects bits 12-15 of | 2411 | * seeing whether the written values are read back correctly. |
| 2065 | * NV_PFB_CFG0 | ||
| 2066 | * | 2412 | * |
| 2067 | * In this context a "cunning combination" may include multiple reads | 2413 | * Only necessary on nv0x-nv1x and nv34, on the other cards we can |
| 2068 | * and writes to varying locations, often alternating the test pattern | 2414 | * trust the straps. |
| 2069 | * and 0, doubtless to make sure buffers are filled, residual charges | ||
| 2070 | * on tracks are removed etc. | ||
| 2071 | * | 2415 | * |
| 2072 | * Unfortunately, the "cunning combination"s mentioned above, and the | 2416 | * 3) Determination of how many of the card's RAM pads have ICs |
| 2073 | * changes to the bits in NV_PFB_CFG0 differ with nearly every bios | 2417 | * attached, usually done by a cunning combination of writes to an |
| 2074 | * trace I have. | 2418 | * offset slightly less than the maximum memory reported by |
| 2419 | * NV_PFB_CSTATUS, then seeing if the test pattern can be read back. | ||
| 2075 | * | 2420 | * |
| 2076 | * Therefore, we cheat and assume the value of NV_PFB_CFG0 with which | 2421 | * This appears to be a NOP on IGPs and NV4x or newer chipsets, both io |
| 2077 | * we started was correct, and use that instead | 2422 | * logs of the VBIOS and kmmio traces of the binary driver POSTing the |
| 2423 | * card show nothing being done for this opcode. Why is it still listed | ||
| 2424 | * in the table?! | ||
| 2078 | */ | 2425 | */ |
| 2079 | 2426 | ||
| 2080 | /* no iexec->execute check by design */ | 2427 | /* no iexec->execute check by design */ |
| 2081 | 2428 | ||
| 2082 | /* | ||
| 2083 | * This appears to be a NOP on G8x chipsets, both io logs of the VBIOS | ||
| 2084 | * and kmmio traces of the binary driver POSTing the card show nothing | ||
| 2085 | * being done for this opcode. why is it still listed in the table?! | ||
| 2086 | */ | ||
| 2087 | |||
| 2088 | struct drm_nouveau_private *dev_priv = bios->dev->dev_private; | 2429 | struct drm_nouveau_private *dev_priv = bios->dev->dev_private; |
| 2430 | int ret; | ||
| 2089 | 2431 | ||
| 2090 | if (dev_priv->card_type >= NV_40) | 2432 | if (dev_priv->chipset >= 0x40 || |
| 2091 | return 1; | 2433 | dev_priv->chipset == 0x1a || |
| 2092 | 2434 | dev_priv->chipset == 0x1f) | |
| 2093 | /* | 2435 | ret = 0; |
| 2094 | * On every card I've seen, this step gets done for us earlier in | 2436 | else if (dev_priv->chipset >= 0x20 && |
| 2095 | * the init scripts | 2437 | dev_priv->chipset != 0x34) |
| 2096 | uint8_t crdata = bios_idxprt_rd(dev, NV_VIO_SRX, 0x01); | 2438 | ret = nv20_init_compute_mem(bios); |
| 2097 | bios_idxprt_wr(dev, NV_VIO_SRX, 0x01, crdata | 0x20); | 2439 | else if (dev_priv->chipset >= 0x10) |
| 2098 | */ | 2440 | ret = nv10_init_compute_mem(bios); |
| 2099 | 2441 | else if (dev_priv->chipset >= 0x5) | |
| 2100 | /* | 2442 | ret = nv05_init_compute_mem(bios); |
| 2101 | * This also has probably been done in the scripts, but an mmio trace of | 2443 | else |
| 2102 | * s3 resume shows nvidia doing it anyway (unlike the NV_VIO_SRX write) | 2444 | ret = nv04_init_compute_mem(bios); |
| 2103 | */ | ||
| 2104 | bios_wr32(bios, NV_PFB_REFCTRL, NV_PFB_REFCTRL_VALID_1); | ||
| 2105 | 2445 | ||
| 2106 | /* write back the saved configuration value */ | 2446 | if (ret) |
| 2107 | bios_wr32(bios, NV_PFB_CFG0, bios->state.saved_nv_pfb_cfg0); | 2447 | return ret; |
| 2108 | 2448 | ||
| 2109 | return 1; | 2449 | return 1; |
| 2110 | } | 2450 | } |
| @@ -2131,7 +2471,8 @@ init_reset(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
| 2131 | /* no iexec->execute check by design */ | 2471 | /* no iexec->execute check by design */ |
| 2132 | 2472 | ||
| 2133 | pci_nv_19 = bios_rd32(bios, NV_PBUS_PCI_NV_19); | 2473 | pci_nv_19 = bios_rd32(bios, NV_PBUS_PCI_NV_19); |
| 2134 | bios_wr32(bios, NV_PBUS_PCI_NV_19, 0); | 2474 | bios_wr32(bios, NV_PBUS_PCI_NV_19, pci_nv_19 & ~0xf00); |
| 2475 | |||
| 2135 | bios_wr32(bios, reg, value1); | 2476 | bios_wr32(bios, reg, value1); |
| 2136 | 2477 | ||
| 2137 | udelay(10); | 2478 | udelay(10); |
| @@ -2167,7 +2508,7 @@ init_configure_mem(struct nvbios *bios, uint16_t offset, | |||
| 2167 | uint32_t reg, data; | 2508 | uint32_t reg, data; |
| 2168 | 2509 | ||
| 2169 | if (bios->major_version > 2) | 2510 | if (bios->major_version > 2) |
| 2170 | return -ENODEV; | 2511 | return 0; |
| 2171 | 2512 | ||
| 2172 | bios_idxprt_wr(bios, NV_VIO_SRX, NV_VIO_SR_CLOCK_INDEX, bios_idxprt_rd( | 2513 | bios_idxprt_wr(bios, NV_VIO_SRX, NV_VIO_SR_CLOCK_INDEX, bios_idxprt_rd( |
| 2173 | bios, NV_VIO_SRX, NV_VIO_SR_CLOCK_INDEX) | 0x20); | 2514 | bios, NV_VIO_SRX, NV_VIO_SR_CLOCK_INDEX) | 0x20); |
| @@ -2180,14 +2521,14 @@ init_configure_mem(struct nvbios *bios, uint16_t offset, | |||
| 2180 | reg = ROM32(bios->data[seqtbloffs += 4])) { | 2521 | reg = ROM32(bios->data[seqtbloffs += 4])) { |
| 2181 | 2522 | ||
| 2182 | switch (reg) { | 2523 | switch (reg) { |
| 2183 | case NV_PFB_PRE: | 2524 | case NV04_PFB_PRE: |
| 2184 | data = NV_PFB_PRE_CMD_PRECHARGE; | 2525 | data = NV04_PFB_PRE_CMD_PRECHARGE; |
| 2185 | break; | 2526 | break; |
| 2186 | case NV_PFB_PAD: | 2527 | case NV04_PFB_PAD: |
| 2187 | data = NV_PFB_PAD_CKE_NORMAL; | 2528 | data = NV04_PFB_PAD_CKE_NORMAL; |
| 2188 | break; | 2529 | break; |
| 2189 | case NV_PFB_REF: | 2530 | case NV04_PFB_REF: |
| 2190 | data = NV_PFB_REF_CMD_REFRESH; | 2531 | data = NV04_PFB_REF_CMD_REFRESH; |
| 2191 | break; | 2532 | break; |
| 2192 | default: | 2533 | default: |
| 2193 | data = ROM32(bios->data[meminitdata]); | 2534 | data = ROM32(bios->data[meminitdata]); |
| @@ -2222,7 +2563,7 @@ init_configure_clk(struct nvbios *bios, uint16_t offset, | |||
| 2222 | int clock; | 2563 | int clock; |
| 2223 | 2564 | ||
| 2224 | if (bios->major_version > 2) | 2565 | if (bios->major_version > 2) |
| 2225 | return -ENODEV; | 2566 | return 0; |
| 2226 | 2567 | ||
| 2227 | clock = ROM16(bios->data[meminitoffs + 4]) * 10; | 2568 | clock = ROM16(bios->data[meminitoffs + 4]) * 10; |
| 2228 | setPLL(bios, NV_PRAMDAC_NVPLL_COEFF, clock); | 2569 | setPLL(bios, NV_PRAMDAC_NVPLL_COEFF, clock); |
| @@ -2255,7 +2596,7 @@ init_configure_preinit(struct nvbios *bios, uint16_t offset, | |||
| 2255 | uint8_t cr3c = ((straps << 2) & 0xf0) | (straps & (1 << 6)); | 2596 | uint8_t cr3c = ((straps << 2) & 0xf0) | (straps & (1 << 6)); |
| 2256 | 2597 | ||
| 2257 | if (bios->major_version > 2) | 2598 | if (bios->major_version > 2) |
| 2258 | return -ENODEV; | 2599 | return 0; |
| 2259 | 2600 | ||
| 2260 | bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, | 2601 | bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, |
| 2261 | NV_CIO_CRE_SCRATCH4__INDEX, cr3c); | 2602 | NV_CIO_CRE_SCRATCH4__INDEX, cr3c); |
| @@ -2389,7 +2730,7 @@ init_ram_condition(struct nvbios *bios, uint16_t offset, | |||
| 2389 | * offset + 1 (8 bit): mask | 2730 | * offset + 1 (8 bit): mask |
| 2390 | * offset + 2 (8 bit): cmpval | 2731 | * offset + 2 (8 bit): cmpval |
| 2391 | * | 2732 | * |
| 2392 | * Test if (NV_PFB_BOOT_0 & "mask") equals "cmpval". | 2733 | * Test if (NV04_PFB_BOOT_0 & "mask") equals "cmpval". |
| 2393 | * If condition not met skip subsequent opcodes until condition is | 2734 | * If condition not met skip subsequent opcodes until condition is |
| 2394 | * inverted (INIT_NOT), or we hit INIT_RESUME | 2735 | * inverted (INIT_NOT), or we hit INIT_RESUME |
| 2395 | */ | 2736 | */ |
| @@ -2401,7 +2742,7 @@ init_ram_condition(struct nvbios *bios, uint16_t offset, | |||
| 2401 | if (!iexec->execute) | 2742 | if (!iexec->execute) |
| 2402 | return 3; | 2743 | return 3; |
| 2403 | 2744 | ||
| 2404 | data = bios_rd32(bios, NV_PFB_BOOT_0) & mask; | 2745 | data = bios_rd32(bios, NV04_PFB_BOOT_0) & mask; |
| 2405 | 2746 | ||
| 2406 | BIOSLOG(bios, "0x%04X: Checking if 0x%08X equals 0x%08X\n", | 2747 | BIOSLOG(bios, "0x%04X: Checking if 0x%08X equals 0x%08X\n", |
| 2407 | offset, data, cmpval); | 2748 | offset, data, cmpval); |
| @@ -2795,12 +3136,13 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
| 2795 | */ | 3136 | */ |
| 2796 | 3137 | ||
| 2797 | struct drm_nouveau_private *dev_priv = bios->dev->dev_private; | 3138 | struct drm_nouveau_private *dev_priv = bios->dev->dev_private; |
| 3139 | struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; | ||
| 2798 | const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c }; | 3140 | const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c }; |
| 2799 | int i; | 3141 | int i; |
| 2800 | 3142 | ||
| 2801 | if (dev_priv->card_type != NV_50) { | 3143 | if (dev_priv->card_type != NV_50) { |
| 2802 | NV_ERROR(bios->dev, "INIT_GPIO on unsupported chipset\n"); | 3144 | NV_ERROR(bios->dev, "INIT_GPIO on unsupported chipset\n"); |
| 2803 | return -ENODEV; | 3145 | return 1; |
| 2804 | } | 3146 | } |
| 2805 | 3147 | ||
| 2806 | if (!iexec->execute) | 3148 | if (!iexec->execute) |
| @@ -2815,7 +3157,7 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
| 2815 | BIOSLOG(bios, "0x%04X: set gpio 0x%02x, state %d\n", | 3157 | BIOSLOG(bios, "0x%04X: set gpio 0x%02x, state %d\n", |
| 2816 | offset, gpio->tag, gpio->state_default); | 3158 | offset, gpio->tag, gpio->state_default); |
| 2817 | if (bios->execute) | 3159 | if (bios->execute) |
| 2818 | nv50_gpio_set(bios->dev, gpio->tag, gpio->state_default); | 3160 | pgpio->set(bios->dev, gpio->tag, gpio->state_default); |
| 2819 | 3161 | ||
| 2820 | /* The NVIDIA binary driver doesn't appear to actually do | 3162 | /* The NVIDIA binary driver doesn't appear to actually do |
| 2821 | * any of this, my VBIOS does however. | 3163 | * any of this, my VBIOS does however. |
| @@ -2872,10 +3214,7 @@ init_ram_restrict_zm_reg_group(struct nvbios *bios, uint16_t offset, | |||
| 2872 | uint8_t index; | 3214 | uint8_t index; |
| 2873 | int i; | 3215 | int i; |
| 2874 | 3216 | ||
| 2875 | 3217 | /* critical! to know the length of the opcode */; | |
| 2876 | if (!iexec->execute) | ||
| 2877 | return len; | ||
| 2878 | |||
| 2879 | if (!blocklen) { | 3218 | if (!blocklen) { |
| 2880 | NV_ERROR(bios->dev, | 3219 | NV_ERROR(bios->dev, |
| 2881 | "0x%04X: Zero block length - has the M table " | 3220 | "0x%04X: Zero block length - has the M table " |
| @@ -2883,6 +3222,9 @@ init_ram_restrict_zm_reg_group(struct nvbios *bios, uint16_t offset, | |||
| 2883 | return -EINVAL; | 3222 | return -EINVAL; |
| 2884 | } | 3223 | } |
| 2885 | 3224 | ||
| 3225 | if (!iexec->execute) | ||
| 3226 | return len; | ||
| 3227 | |||
| 2886 | strap_ramcfg = (bios_rd32(bios, NV_PEXTDEV_BOOT_0) >> 2) & 0xf; | 3228 | strap_ramcfg = (bios_rd32(bios, NV_PEXTDEV_BOOT_0) >> 2) & 0xf; |
| 2887 | index = bios->data[bios->ram_restrict_tbl_ptr + strap_ramcfg]; | 3229 | index = bios->data[bios->ram_restrict_tbl_ptr + strap_ramcfg]; |
| 2888 | 3230 | ||
| @@ -3064,14 +3406,14 @@ init_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
| 3064 | 3406 | ||
| 3065 | if (!bios->display.output) { | 3407 | if (!bios->display.output) { |
| 3066 | NV_ERROR(dev, "INIT_AUXCH: no active output\n"); | 3408 | NV_ERROR(dev, "INIT_AUXCH: no active output\n"); |
| 3067 | return -EINVAL; | 3409 | return len; |
| 3068 | } | 3410 | } |
| 3069 | 3411 | ||
| 3070 | auxch = init_i2c_device_find(dev, bios->display.output->i2c_index); | 3412 | auxch = init_i2c_device_find(dev, bios->display.output->i2c_index); |
| 3071 | if (!auxch) { | 3413 | if (!auxch) { |
| 3072 | NV_ERROR(dev, "INIT_AUXCH: couldn't get auxch %d\n", | 3414 | NV_ERROR(dev, "INIT_AUXCH: couldn't get auxch %d\n", |
| 3073 | bios->display.output->i2c_index); | 3415 | bios->display.output->i2c_index); |
| 3074 | return -ENODEV; | 3416 | return len; |
| 3075 | } | 3417 | } |
| 3076 | 3418 | ||
| 3077 | if (!iexec->execute) | 3419 | if (!iexec->execute) |
| @@ -3084,7 +3426,7 @@ init_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
| 3084 | ret = nouveau_dp_auxch(auxch, 9, addr, &data, 1); | 3426 | ret = nouveau_dp_auxch(auxch, 9, addr, &data, 1); |
| 3085 | if (ret) { | 3427 | if (ret) { |
| 3086 | NV_ERROR(dev, "INIT_AUXCH: rd auxch fail %d\n", ret); | 3428 | NV_ERROR(dev, "INIT_AUXCH: rd auxch fail %d\n", ret); |
| 3087 | return ret; | 3429 | return len; |
| 3088 | } | 3430 | } |
| 3089 | 3431 | ||
| 3090 | data &= bios->data[offset + 0]; | 3432 | data &= bios->data[offset + 0]; |
| @@ -3093,7 +3435,7 @@ init_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
| 3093 | ret = nouveau_dp_auxch(auxch, 8, addr, &data, 1); | 3435 | ret = nouveau_dp_auxch(auxch, 8, addr, &data, 1); |
| 3094 | if (ret) { | 3436 | if (ret) { |
| 3095 | NV_ERROR(dev, "INIT_AUXCH: wr auxch fail %d\n", ret); | 3437 | NV_ERROR(dev, "INIT_AUXCH: wr auxch fail %d\n", ret); |
| 3096 | return ret; | 3438 | return len; |
| 3097 | } | 3439 | } |
| 3098 | } | 3440 | } |
| 3099 | 3441 | ||
| @@ -3123,14 +3465,14 @@ init_zm_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
| 3123 | 3465 | ||
| 3124 | if (!bios->display.output) { | 3466 | if (!bios->display.output) { |
| 3125 | NV_ERROR(dev, "INIT_ZM_AUXCH: no active output\n"); | 3467 | NV_ERROR(dev, "INIT_ZM_AUXCH: no active output\n"); |
| 3126 | return -EINVAL; | 3468 | return len; |
| 3127 | } | 3469 | } |
| 3128 | 3470 | ||
| 3129 | auxch = init_i2c_device_find(dev, bios->display.output->i2c_index); | 3471 | auxch = init_i2c_device_find(dev, bios->display.output->i2c_index); |
| 3130 | if (!auxch) { | 3472 | if (!auxch) { |
| 3131 | NV_ERROR(dev, "INIT_ZM_AUXCH: couldn't get auxch %d\n", | 3473 | NV_ERROR(dev, "INIT_ZM_AUXCH: couldn't get auxch %d\n", |
| 3132 | bios->display.output->i2c_index); | 3474 | bios->display.output->i2c_index); |
| 3133 | return -ENODEV; | 3475 | return len; |
| 3134 | } | 3476 | } |
| 3135 | 3477 | ||
| 3136 | if (!iexec->execute) | 3478 | if (!iexec->execute) |
| @@ -3141,7 +3483,7 @@ init_zm_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
| 3141 | ret = nouveau_dp_auxch(auxch, 8, addr, &bios->data[offset], 1); | 3483 | ret = nouveau_dp_auxch(auxch, 8, addr, &bios->data[offset], 1); |
| 3142 | if (ret) { | 3484 | if (ret) { |
| 3143 | NV_ERROR(dev, "INIT_ZM_AUXCH: wr auxch fail %d\n", ret); | 3485 | NV_ERROR(dev, "INIT_ZM_AUXCH: wr auxch fail %d\n", ret); |
| 3144 | return ret; | 3486 | return len; |
| 3145 | } | 3487 | } |
| 3146 | } | 3488 | } |
| 3147 | 3489 | ||
| @@ -5151,10 +5493,14 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi | |||
| 5151 | bios->legacy.i2c_indices.crt = bios->data[legacy_i2c_offset]; | 5493 | bios->legacy.i2c_indices.crt = bios->data[legacy_i2c_offset]; |
| 5152 | bios->legacy.i2c_indices.tv = bios->data[legacy_i2c_offset + 1]; | 5494 | bios->legacy.i2c_indices.tv = bios->data[legacy_i2c_offset + 1]; |
| 5153 | bios->legacy.i2c_indices.panel = bios->data[legacy_i2c_offset + 2]; | 5495 | bios->legacy.i2c_indices.panel = bios->data[legacy_i2c_offset + 2]; |
| 5154 | bios->dcb.i2c[0].write = bios->data[legacy_i2c_offset + 4]; | 5496 | if (bios->data[legacy_i2c_offset + 4]) |
| 5155 | bios->dcb.i2c[0].read = bios->data[legacy_i2c_offset + 5]; | 5497 | bios->dcb.i2c[0].write = bios->data[legacy_i2c_offset + 4]; |
| 5156 | bios->dcb.i2c[1].write = bios->data[legacy_i2c_offset + 6]; | 5498 | if (bios->data[legacy_i2c_offset + 5]) |
| 5157 | bios->dcb.i2c[1].read = bios->data[legacy_i2c_offset + 7]; | 5499 | bios->dcb.i2c[0].read = bios->data[legacy_i2c_offset + 5]; |
| 5500 | if (bios->data[legacy_i2c_offset + 6]) | ||
| 5501 | bios->dcb.i2c[1].write = bios->data[legacy_i2c_offset + 6]; | ||
| 5502 | if (bios->data[legacy_i2c_offset + 7]) | ||
| 5503 | bios->dcb.i2c[1].read = bios->data[legacy_i2c_offset + 7]; | ||
| 5158 | 5504 | ||
| 5159 | if (bmplength > 74) { | 5505 | if (bmplength > 74) { |
| 5160 | bios->fmaxvco = ROM32(bmp[67]); | 5506 | bios->fmaxvco = ROM32(bmp[67]); |
| @@ -5589,9 +5935,12 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, | |||
| 5589 | if (conf & 0x4 || conf & 0x8) | 5935 | if (conf & 0x4 || conf & 0x8) |
| 5590 | entry->lvdsconf.use_power_scripts = true; | 5936 | entry->lvdsconf.use_power_scripts = true; |
| 5591 | } else { | 5937 | } else { |
| 5592 | mask = ~0x5; | 5938 | mask = ~0x7; |
| 5939 | if (conf & 0x2) | ||
| 5940 | entry->lvdsconf.use_acpi_for_edid = true; | ||
| 5593 | if (conf & 0x4) | 5941 | if (conf & 0x4) |
| 5594 | entry->lvdsconf.use_power_scripts = true; | 5942 | entry->lvdsconf.use_power_scripts = true; |
| 5943 | entry->lvdsconf.sor.link = (conf & 0x00000030) >> 4; | ||
| 5595 | } | 5944 | } |
| 5596 | if (conf & mask) { | 5945 | if (conf & mask) { |
| 5597 | /* | 5946 | /* |
| @@ -5706,13 +6055,6 @@ parse_dcb15_entry(struct drm_device *dev, struct dcb_table *dcb, | |||
| 5706 | case OUTPUT_TV: | 6055 | case OUTPUT_TV: |
| 5707 | entry->tvconf.has_component_output = false; | 6056 | entry->tvconf.has_component_output = false; |
| 5708 | break; | 6057 | break; |
| 5709 | case OUTPUT_TMDS: | ||
| 5710 | /* | ||
| 5711 | * Invent a DVI-A output, by copying the fields of the DVI-D | ||
| 5712 | * output; reported to work by math_b on an NV20(!). | ||
| 5713 | */ | ||
| 5714 | fabricate_vga_output(dcb, entry->i2c_index, entry->heads); | ||
| 5715 | break; | ||
| 5716 | case OUTPUT_LVDS: | 6058 | case OUTPUT_LVDS: |
| 5717 | if ((conn & 0x00003f00) != 0x10) | 6059 | if ((conn & 0x00003f00) != 0x10) |
| 5718 | entry->lvdsconf.use_straps_for_mode = true; | 6060 | entry->lvdsconf.use_straps_for_mode = true; |
| @@ -5793,6 +6135,31 @@ void merge_like_dcb_entries(struct drm_device *dev, struct dcb_table *dcb) | |||
| 5793 | dcb->entries = newentries; | 6135 | dcb->entries = newentries; |
| 5794 | } | 6136 | } |
| 5795 | 6137 | ||
| 6138 | static bool | ||
| 6139 | apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf) | ||
| 6140 | { | ||
| 6141 | /* Dell Precision M6300 | ||
| 6142 | * DCB entry 2: 02025312 00000010 | ||
| 6143 | * DCB entry 3: 02026312 00000020 | ||
| 6144 | * | ||
| 6145 | * Identical, except apparently a different connector on a | ||
| 6146 | * different SOR link. Not a clue how we're supposed to know | ||
| 6147 | * which one is in use if it even shares an i2c line... | ||
| 6148 | * | ||
| 6149 | * Ignore the connector on the second SOR link to prevent | ||
| 6150 | * nasty problems until this is sorted (assuming it's not a | ||
| 6151 | * VBIOS bug). | ||
| 6152 | */ | ||
| 6153 | if ((dev->pdev->device == 0x040d) && | ||
| 6154 | (dev->pdev->subsystem_vendor == 0x1028) && | ||
| 6155 | (dev->pdev->subsystem_device == 0x019b)) { | ||
| 6156 | if (*conn == 0x02026312 && *conf == 0x00000020) | ||
| 6157 | return false; | ||
| 6158 | } | ||
| 6159 | |||
| 6160 | return true; | ||
| 6161 | } | ||
| 6162 | |||
| 5796 | static int | 6163 | static int |
| 5797 | parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads) | 6164 | parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads) |
| 5798 | { | 6165 | { |
| @@ -5926,6 +6293,9 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads) | |||
| 5926 | if ((connection & 0x0000000f) == 0x0000000f) | 6293 | if ((connection & 0x0000000f) == 0x0000000f) |
| 5927 | continue; | 6294 | continue; |
| 5928 | 6295 | ||
| 6296 | if (!apply_dcb_encoder_quirks(dev, i, &connection, &config)) | ||
| 6297 | continue; | ||
| 6298 | |||
| 5929 | NV_TRACEWARN(dev, "Raw DCB entry %d: %08x %08x\n", | 6299 | NV_TRACEWARN(dev, "Raw DCB entry %d: %08x %08x\n", |
| 5930 | dcb->entries, connection, config); | 6300 | dcb->entries, connection, config); |
| 5931 | 6301 | ||
| @@ -6181,9 +6551,8 @@ nouveau_run_vbios_init(struct drm_device *dev) | |||
| 6181 | struct nvbios *bios = &dev_priv->vbios; | 6551 | struct nvbios *bios = &dev_priv->vbios; |
| 6182 | int i, ret = 0; | 6552 | int i, ret = 0; |
| 6183 | 6553 | ||
| 6184 | NVLockVgaCrtcs(dev, false); | 6554 | /* Reset the BIOS head to 0. */ |
| 6185 | if (nv_two_heads(dev)) | 6555 | bios->state.crtchead = 0; |
| 6186 | NVSetOwner(dev, bios->state.crtchead); | ||
| 6187 | 6556 | ||
| 6188 | if (bios->major_version < 5) /* BMP only */ | 6557 | if (bios->major_version < 5) /* BMP only */ |
| 6189 | load_nv17_hw_sequencer_ucode(dev, bios); | 6558 | load_nv17_hw_sequencer_ucode(dev, bios); |
| @@ -6216,8 +6585,6 @@ nouveau_run_vbios_init(struct drm_device *dev) | |||
| 6216 | } | 6585 | } |
| 6217 | } | 6586 | } |
| 6218 | 6587 | ||
| 6219 | NVLockVgaCrtcs(dev, true); | ||
| 6220 | |||
| 6221 | return ret; | 6588 | return ret; |
| 6222 | } | 6589 | } |
| 6223 | 6590 | ||
| @@ -6238,7 +6605,6 @@ static bool | |||
| 6238 | nouveau_bios_posted(struct drm_device *dev) | 6605 | nouveau_bios_posted(struct drm_device *dev) |
| 6239 | { | 6606 | { |
| 6240 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 6607 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 6241 | bool was_locked; | ||
| 6242 | unsigned htotal; | 6608 | unsigned htotal; |
| 6243 | 6609 | ||
| 6244 | if (dev_priv->chipset >= NV_50) { | 6610 | if (dev_priv->chipset >= NV_50) { |
| @@ -6248,13 +6614,12 @@ nouveau_bios_posted(struct drm_device *dev) | |||
| 6248 | return true; | 6614 | return true; |
| 6249 | } | 6615 | } |
| 6250 | 6616 | ||
| 6251 | was_locked = NVLockVgaCrtcs(dev, false); | ||
| 6252 | htotal = NVReadVgaCrtc(dev, 0, 0x06); | 6617 | htotal = NVReadVgaCrtc(dev, 0, 0x06); |
| 6253 | htotal |= (NVReadVgaCrtc(dev, 0, 0x07) & 0x01) << 8; | 6618 | htotal |= (NVReadVgaCrtc(dev, 0, 0x07) & 0x01) << 8; |
| 6254 | htotal |= (NVReadVgaCrtc(dev, 0, 0x07) & 0x20) << 4; | 6619 | htotal |= (NVReadVgaCrtc(dev, 0, 0x07) & 0x20) << 4; |
| 6255 | htotal |= (NVReadVgaCrtc(dev, 0, 0x25) & 0x01) << 10; | 6620 | htotal |= (NVReadVgaCrtc(dev, 0, 0x25) & 0x01) << 10; |
| 6256 | htotal |= (NVReadVgaCrtc(dev, 0, 0x41) & 0x01) << 11; | 6621 | htotal |= (NVReadVgaCrtc(dev, 0, 0x41) & 0x01) << 11; |
| 6257 | NVLockVgaCrtcs(dev, was_locked); | 6622 | |
| 6258 | return (htotal != 0); | 6623 | return (htotal != 0); |
| 6259 | } | 6624 | } |
| 6260 | 6625 | ||
| @@ -6263,8 +6628,6 @@ nouveau_bios_init(struct drm_device *dev) | |||
| 6263 | { | 6628 | { |
| 6264 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 6629 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 6265 | struct nvbios *bios = &dev_priv->vbios; | 6630 | struct nvbios *bios = &dev_priv->vbios; |
| 6266 | uint32_t saved_nv_pextdev_boot_0; | ||
| 6267 | bool was_locked; | ||
| 6268 | int ret; | 6631 | int ret; |
| 6269 | 6632 | ||
| 6270 | if (!NVInitVBIOS(dev)) | 6633 | if (!NVInitVBIOS(dev)) |
| @@ -6284,40 +6647,27 @@ nouveau_bios_init(struct drm_device *dev) | |||
| 6284 | if (!bios->major_version) /* we don't run version 0 bios */ | 6647 | if (!bios->major_version) /* we don't run version 0 bios */ |
| 6285 | return 0; | 6648 | return 0; |
| 6286 | 6649 | ||
| 6287 | /* these will need remembering across a suspend */ | ||
| 6288 | saved_nv_pextdev_boot_0 = bios_rd32(bios, NV_PEXTDEV_BOOT_0); | ||
| 6289 | bios->state.saved_nv_pfb_cfg0 = bios_rd32(bios, NV_PFB_CFG0); | ||
| 6290 | |||
| 6291 | /* init script execution disabled */ | 6650 | /* init script execution disabled */ |
| 6292 | bios->execute = false; | 6651 | bios->execute = false; |
| 6293 | 6652 | ||
| 6294 | /* ... unless card isn't POSTed already */ | 6653 | /* ... unless card isn't POSTed already */ |
| 6295 | if (!nouveau_bios_posted(dev)) { | 6654 | if (!nouveau_bios_posted(dev)) { |
| 6296 | NV_INFO(dev, "Adaptor not initialised\n"); | 6655 | NV_INFO(dev, "Adaptor not initialised, " |
| 6297 | if (dev_priv->card_type < NV_40) { | 6656 | "running VBIOS init tables.\n"); |
| 6298 | NV_ERROR(dev, "Unable to POST this chipset\n"); | ||
| 6299 | return -ENODEV; | ||
| 6300 | } | ||
| 6301 | |||
| 6302 | NV_INFO(dev, "Running VBIOS init tables\n"); | ||
| 6303 | bios->execute = true; | 6657 | bios->execute = true; |
| 6304 | } | 6658 | } |
| 6305 | 6659 | ||
| 6306 | bios_wr32(bios, NV_PEXTDEV_BOOT_0, saved_nv_pextdev_boot_0); | ||
| 6307 | |||
| 6308 | ret = nouveau_run_vbios_init(dev); | 6660 | ret = nouveau_run_vbios_init(dev); |
| 6309 | if (ret) | 6661 | if (ret) |
| 6310 | return ret; | 6662 | return ret; |
| 6311 | 6663 | ||
| 6312 | /* feature_byte on BMP is poor, but init always sets CR4B */ | 6664 | /* feature_byte on BMP is poor, but init always sets CR4B */ |
| 6313 | was_locked = NVLockVgaCrtcs(dev, false); | ||
| 6314 | if (bios->major_version < 5) | 6665 | if (bios->major_version < 5) |
| 6315 | bios->is_mobile = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_4B) & 0x40; | 6666 | bios->is_mobile = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_4B) & 0x40; |
| 6316 | 6667 | ||
| 6317 | /* all BIT systems need p_f_m_t for digital_min_front_porch */ | 6668 | /* all BIT systems need p_f_m_t for digital_min_front_porch */ |
| 6318 | if (bios->is_mobile || bios->major_version >= 5) | 6669 | if (bios->is_mobile || bios->major_version >= 5) |
| 6319 | ret = parse_fp_mode_table(dev, bios); | 6670 | ret = parse_fp_mode_table(dev, bios); |
| 6320 | NVLockVgaCrtcs(dev, was_locked); | ||
| 6321 | 6671 | ||
| 6322 | /* allow subsequent scripts to execute */ | 6672 | /* allow subsequent scripts to execute */ |
| 6323 | bios->execute = true; | 6673 | bios->execute = true; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h index adf4ec2d06c0..024458a8d060 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 { | |||
| 81 | enum dcb_connector_type type; | 81 | enum dcb_connector_type type; |
| 82 | uint8_t index2; | 82 | uint8_t index2; |
| 83 | uint8_t gpio_tag; | 83 | uint8_t gpio_tag; |
| 84 | void *drm; | ||
| 84 | }; | 85 | }; |
| 85 | 86 | ||
| 86 | struct dcb_connector_table { | 87 | struct dcb_connector_table { |
| @@ -117,6 +118,7 @@ struct dcb_entry { | |||
| 117 | struct { | 118 | struct { |
| 118 | struct sor_conf sor; | 119 | struct sor_conf sor; |
| 119 | bool use_straps_for_mode; | 120 | bool use_straps_for_mode; |
| 121 | bool use_acpi_for_edid; | ||
| 120 | bool use_power_scripts; | 122 | bool use_power_scripts; |
| 121 | } lvdsconf; | 123 | } lvdsconf; |
| 122 | struct { | 124 | struct { |
| @@ -249,8 +251,6 @@ struct nvbios { | |||
| 249 | 251 | ||
| 250 | struct { | 252 | struct { |
| 251 | int crtchead; | 253 | int crtchead; |
| 252 | /* these need remembering across suspend */ | ||
| 253 | uint32_t saved_nv_pfb_cfg0; | ||
| 254 | } state; | 254 | } state; |
| 255 | 255 | ||
| 256 | struct { | 256 | struct { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 6f3c19522377..3ca8343c15df 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, | |||
| 461 | return ret; | 461 | return ret; |
| 462 | 462 | ||
| 463 | ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL, | 463 | ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL, |
| 464 | evict, no_wait_reserve, no_wait_gpu, new_mem); | 464 | evict || (nvbo->channel && |
| 465 | if (nvbo->channel && nvbo->channel != chan) | 465 | nvbo->channel != chan), |
| 466 | ret = nouveau_fence_wait(fence, NULL, false, false); | 466 | no_wait_reserve, no_wait_gpu, new_mem); |
| 467 | nouveau_fence_unref((void *)&fence); | 467 | nouveau_fence_unref((void *)&fence); |
| 468 | return ret; | 468 | return ret; |
| 469 | } | 469 | } |
| @@ -711,8 +711,7 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr, | |||
| 711 | return ret; | 711 | return ret; |
| 712 | 712 | ||
| 713 | /* Software copy if the card isn't up and running yet. */ | 713 | /* Software copy if the card isn't up and running yet. */ |
| 714 | if (dev_priv->init_state != NOUVEAU_CARD_INIT_DONE || | 714 | if (!dev_priv->channel) { |
| 715 | !dev_priv->channel) { | ||
| 716 | ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); | 715 | ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); |
| 717 | goto out; | 716 | goto out; |
| 718 | } | 717 | } |
| @@ -783,7 +782,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) | |||
| 783 | break; | 782 | break; |
| 784 | case TTM_PL_VRAM: | 783 | case TTM_PL_VRAM: |
| 785 | mem->bus.offset = mem->mm_node->start << PAGE_SHIFT; | 784 | mem->bus.offset = mem->mm_node->start << PAGE_SHIFT; |
| 786 | mem->bus.base = drm_get_resource_start(dev, 1); | 785 | mem->bus.base = pci_resource_start(dev->pdev, 1); |
| 787 | mem->bus.is_iomem = true; | 786 | mem->bus.is_iomem = true; |
| 788 | break; | 787 | break; |
| 789 | default: | 788 | default: |
diff --git a/drivers/gpu/drm/nouveau/nouveau_calc.c b/drivers/gpu/drm/nouveau/nouveau_calc.c index 88f9bc0941eb..ca85da784846 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, | |||
| 200 | struct nv_sim_state sim_data; | 200 | struct nv_sim_state sim_data; |
| 201 | int MClk = nouveau_hw_get_clock(dev, MPLL); | 201 | int MClk = nouveau_hw_get_clock(dev, MPLL); |
| 202 | int NVClk = nouveau_hw_get_clock(dev, NVPLL); | 202 | int NVClk = nouveau_hw_get_clock(dev, NVPLL); |
| 203 | uint32_t cfg1 = nvReadFB(dev, NV_PFB_CFG1); | 203 | uint32_t cfg1 = nvReadFB(dev, NV04_PFB_CFG1); |
| 204 | 204 | ||
| 205 | sim_data.pclk_khz = VClk; | 205 | sim_data.pclk_khz = VClk; |
| 206 | sim_data.mclk_khz = MClk; | 206 | sim_data.mclk_khz = MClk; |
| @@ -218,7 +218,7 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp, | |||
| 218 | sim_data.mem_latency = 3; | 218 | sim_data.mem_latency = 3; |
| 219 | sim_data.mem_page_miss = 10; | 219 | sim_data.mem_page_miss = 10; |
| 220 | } else { | 220 | } else { |
| 221 | sim_data.memory_type = nvReadFB(dev, NV_PFB_CFG0) & 0x1; | 221 | sim_data.memory_type = nvReadFB(dev, NV04_PFB_CFG0) & 0x1; |
| 222 | sim_data.memory_width = (nvReadEXTDEV(dev, NV_PEXTDEV_BOOT_0) & 0x10) ? 128 : 64; | 222 | sim_data.memory_width = (nvReadEXTDEV(dev, NV_PEXTDEV_BOOT_0) & 0x10) ? 128 : 64; |
| 223 | sim_data.mem_latency = cfg1 & 0xf; | 223 | sim_data.mem_latency = cfg1 & 0xf; |
| 224 | sim_data.mem_page_miss = ((cfg1 >> 4) & 0xf) + ((cfg1 >> 31) & 0x1); | 224 | 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 1fc57ef58295..90fdcda332be 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c | |||
| @@ -62,7 +62,8 @@ nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan) | |||
| 62 | * VRAM. | 62 | * VRAM. |
| 63 | */ | 63 | */ |
| 64 | ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, | 64 | ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, |
| 65 | drm_get_resource_start(dev, 1), | 65 | pci_resource_start(dev->pdev, |
| 66 | 1), | ||
| 66 | dev_priv->fb_available_size, | 67 | dev_priv->fb_available_size, |
| 67 | NV_DMA_ACCESS_RO, | 68 | NV_DMA_ACCESS_RO, |
| 68 | NV_DMA_TARGET_PCI, &pushbuf); | 69 | NV_DMA_TARGET_PCI, &pushbuf); |
| @@ -257,9 +258,7 @@ nouveau_channel_free(struct nouveau_channel *chan) | |||
| 257 | nouveau_debugfs_channel_fini(chan); | 258 | nouveau_debugfs_channel_fini(chan); |
| 258 | 259 | ||
| 259 | /* Give outstanding push buffers a chance to complete */ | 260 | /* Give outstanding push buffers a chance to complete */ |
| 260 | spin_lock_irqsave(&chan->fence.lock, flags); | ||
| 261 | nouveau_fence_update(chan); | 261 | nouveau_fence_update(chan); |
| 262 | spin_unlock_irqrestore(&chan->fence.lock, flags); | ||
| 263 | if (chan->fence.sequence != chan->fence.sequence_ack) { | 262 | if (chan->fence.sequence != chan->fence.sequence_ack) { |
| 264 | struct nouveau_fence *fence = NULL; | 263 | struct nouveau_fence *fence = NULL; |
| 265 | 264 | ||
| @@ -368,8 +367,6 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, | |||
| 368 | struct nouveau_channel *chan; | 367 | struct nouveau_channel *chan; |
| 369 | int ret; | 368 | int ret; |
| 370 | 369 | ||
| 371 | NOUVEAU_CHECK_INITIALISED_WITH_RETURN; | ||
| 372 | |||
| 373 | if (dev_priv->engine.graph.accel_blocked) | 370 | if (dev_priv->engine.graph.accel_blocked) |
| 374 | return -ENODEV; | 371 | return -ENODEV; |
| 375 | 372 | ||
| @@ -418,7 +415,6 @@ nouveau_ioctl_fifo_free(struct drm_device *dev, void *data, | |||
| 418 | struct drm_nouveau_channel_free *cfree = data; | 415 | struct drm_nouveau_channel_free *cfree = data; |
| 419 | struct nouveau_channel *chan; | 416 | struct nouveau_channel *chan; |
| 420 | 417 | ||
| 421 | NOUVEAU_CHECK_INITIALISED_WITH_RETURN; | ||
| 422 | NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(cfree->channel, file_priv, chan); | 418 | NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(cfree->channel, file_priv, chan); |
| 423 | 419 | ||
| 424 | nouveau_channel_free(chan); | 420 | nouveau_channel_free(chan); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 149ed224c3cb..734e92635e83 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) | |||
| 102 | kfree(drm_connector); | 102 | kfree(drm_connector); |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | static void | ||
| 106 | nouveau_connector_ddc_prepare(struct drm_connector *connector, int *flags) | ||
| 107 | { | ||
| 108 | struct drm_nouveau_private *dev_priv = connector->dev->dev_private; | ||
| 109 | |||
| 110 | if (dev_priv->card_type >= NV_50) | ||
| 111 | return; | ||
| 112 | |||
| 113 | *flags = 0; | ||
| 114 | if (NVLockVgaCrtcs(dev_priv->dev, false)) | ||
| 115 | *flags |= 1; | ||
| 116 | if (nv_heads_tied(dev_priv->dev)) | ||
| 117 | *flags |= 2; | ||
| 118 | |||
| 119 | if (*flags & 2) | ||
| 120 | NVSetOwner(dev_priv->dev, 0); /* necessary? */ | ||
| 121 | } | ||
| 122 | |||
| 123 | static void | ||
| 124 | nouveau_connector_ddc_finish(struct drm_connector *connector, int flags) | ||
| 125 | { | ||
| 126 | struct drm_nouveau_private *dev_priv = connector->dev->dev_private; | ||
| 127 | |||
| 128 | if (dev_priv->card_type >= NV_50) | ||
| 129 | return; | ||
| 130 | |||
| 131 | if (flags & 2) | ||
| 132 | NVSetOwner(dev_priv->dev, 4); | ||
| 133 | if (flags & 1) | ||
| 134 | NVLockVgaCrtcs(dev_priv->dev, true); | ||
| 135 | } | ||
| 136 | |||
| 137 | static struct nouveau_i2c_chan * | 105 | static struct nouveau_i2c_chan * |
| 138 | nouveau_connector_ddc_detect(struct drm_connector *connector, | 106 | nouveau_connector_ddc_detect(struct drm_connector *connector, |
| 139 | struct nouveau_encoder **pnv_encoder) | 107 | struct nouveau_encoder **pnv_encoder) |
| 140 | { | 108 | { |
| 141 | struct drm_device *dev = connector->dev; | 109 | struct drm_device *dev = connector->dev; |
| 142 | uint8_t out_buf[] = { 0x0, 0x0}, buf[2]; | 110 | int i; |
| 143 | int ret, flags, i; | ||
| 144 | |||
| 145 | struct i2c_msg msgs[] = { | ||
| 146 | { | ||
| 147 | .addr = 0x50, | ||
| 148 | .flags = 0, | ||
| 149 | .len = 1, | ||
| 150 | .buf = out_buf, | ||
| 151 | }, | ||
| 152 | { | ||
| 153 | .addr = 0x50, | ||
| 154 | .flags = I2C_M_RD, | ||
| 155 | .len = 1, | ||
| 156 | .buf = buf, | ||
| 157 | } | ||
| 158 | }; | ||
| 159 | 111 | ||
| 160 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { | 112 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
| 161 | struct nouveau_i2c_chan *i2c = NULL; | 113 | struct nouveau_i2c_chan *i2c; |
| 162 | struct nouveau_encoder *nv_encoder; | 114 | struct nouveau_encoder *nv_encoder; |
| 163 | struct drm_mode_object *obj; | 115 | struct drm_mode_object *obj; |
| 164 | int id; | 116 | int id; |
| @@ -171,17 +123,9 @@ nouveau_connector_ddc_detect(struct drm_connector *connector, | |||
| 171 | if (!obj) | 123 | if (!obj) |
| 172 | continue; | 124 | continue; |
| 173 | nv_encoder = nouveau_encoder(obj_to_encoder(obj)); | 125 | nv_encoder = nouveau_encoder(obj_to_encoder(obj)); |
| 126 | i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); | ||
| 174 | 127 | ||
| 175 | if (nv_encoder->dcb->i2c_index < 0xf) | 128 | if (i2c && nouveau_probe_i2c_addr(i2c, 0x50)) { |
| 176 | i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); | ||
| 177 | if (!i2c) | ||
| 178 | continue; | ||
| 179 | |||
| 180 | nouveau_connector_ddc_prepare(connector, &flags); | ||
| 181 | ret = i2c_transfer(&i2c->adapter, msgs, 2); | ||
| 182 | nouveau_connector_ddc_finish(connector, flags); | ||
| 183 | |||
| 184 | if (ret == 2) { | ||
| 185 | *pnv_encoder = nv_encoder; | 129 | *pnv_encoder = nv_encoder; |
| 186 | return i2c; | 130 | return i2c; |
| 187 | } | 131 | } |
| @@ -234,21 +178,7 @@ nouveau_connector_detect(struct drm_connector *connector) | |||
| 234 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | 178 | struct nouveau_connector *nv_connector = nouveau_connector(connector); |
| 235 | struct nouveau_encoder *nv_encoder = NULL; | 179 | struct nouveau_encoder *nv_encoder = NULL; |
| 236 | struct nouveau_i2c_chan *i2c; | 180 | struct nouveau_i2c_chan *i2c; |
| 237 | int type, flags; | 181 | int type; |
| 238 | |||
| 239 | if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS) | ||
| 240 | nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS); | ||
| 241 | if (nv_encoder && nv_connector->native_mode) { | ||
| 242 | unsigned status = connector_status_connected; | ||
| 243 | |||
| 244 | #if defined(CONFIG_ACPI_BUTTON) || \ | ||
| 245 | (defined(CONFIG_ACPI_BUTTON_MODULE) && defined(MODULE)) | ||
| 246 | if (!nouveau_ignorelid && !acpi_lid_open()) | ||
| 247 | status = connector_status_unknown; | ||
| 248 | #endif | ||
| 249 | nouveau_connector_set_encoder(connector, nv_encoder); | ||
| 250 | return status; | ||
| 251 | } | ||
| 252 | 182 | ||
| 253 | /* Cleanup the previous EDID block. */ | 183 | /* Cleanup the previous EDID block. */ |
| 254 | if (nv_connector->edid) { | 184 | if (nv_connector->edid) { |
| @@ -259,9 +189,7 @@ nouveau_connector_detect(struct drm_connector *connector) | |||
| 259 | 189 | ||
| 260 | i2c = nouveau_connector_ddc_detect(connector, &nv_encoder); | 190 | i2c = nouveau_connector_ddc_detect(connector, &nv_encoder); |
| 261 | if (i2c) { | 191 | if (i2c) { |
| 262 | nouveau_connector_ddc_prepare(connector, &flags); | ||
| 263 | nv_connector->edid = drm_get_edid(connector, &i2c->adapter); | 192 | nv_connector->edid = drm_get_edid(connector, &i2c->adapter); |
| 264 | nouveau_connector_ddc_finish(connector, flags); | ||
| 265 | drm_mode_connector_update_edid_property(connector, | 193 | drm_mode_connector_update_edid_property(connector, |
| 266 | nv_connector->edid); | 194 | nv_connector->edid); |
| 267 | if (!nv_connector->edid) { | 195 | if (!nv_connector->edid) { |
| @@ -321,6 +249,85 @@ detect_analog: | |||
| 321 | return connector_status_disconnected; | 249 | return connector_status_disconnected; |
| 322 | } | 250 | } |
| 323 | 251 | ||
| 252 | static enum drm_connector_status | ||
| 253 | nouveau_connector_detect_lvds(struct drm_connector *connector) | ||
| 254 | { | ||
| 255 | struct drm_device *dev = connector->dev; | ||
| 256 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 257 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | ||
| 258 | struct nouveau_encoder *nv_encoder = NULL; | ||
| 259 | enum drm_connector_status status = connector_status_disconnected; | ||
| 260 | |||
| 261 | /* Cleanup the previous EDID block. */ | ||
| 262 | if (nv_connector->edid) { | ||
| 263 | drm_mode_connector_update_edid_property(connector, NULL); | ||
| 264 | kfree(nv_connector->edid); | ||
| 265 | nv_connector->edid = NULL; | ||
| 266 | } | ||
| 267 | |||
| 268 | nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS); | ||
| 269 | if (!nv_encoder) | ||
| 270 | return connector_status_disconnected; | ||
| 271 | |||
| 272 | /* Try retrieving EDID via DDC */ | ||
| 273 | if (!dev_priv->vbios.fp_no_ddc) { | ||
| 274 | status = nouveau_connector_detect(connector); | ||
| 275 | if (status == connector_status_connected) | ||
| 276 | goto out; | ||
| 277 | } | ||
| 278 | |||
| 279 | /* On some laptops (Sony, i'm looking at you) there appears to | ||
| 280 | * be no direct way of accessing the panel's EDID. The only | ||
| 281 | * option available to us appears to be to ask ACPI for help.. | ||
| 282 | * | ||
| 283 | * It's important this check's before trying straps, one of the | ||
| 284 | * said manufacturer's laptops are configured in such a way | ||
| 285 | * the nouveau decides an entry in the VBIOS FP mode table is | ||
| 286 | * valid - it's not (rh#613284) | ||
| 287 | */ | ||
| 288 | if (nv_encoder->dcb->lvdsconf.use_acpi_for_edid) { | ||
| 289 | if (!nouveau_acpi_edid(dev, connector)) { | ||
| 290 | status = connector_status_connected; | ||
| 291 | goto out; | ||
| 292 | } | ||
| 293 | } | ||
| 294 | |||
| 295 | /* If no EDID found above, and the VBIOS indicates a hardcoded | ||
| 296 | * modeline is avalilable for the panel, set it as the panel's | ||
| 297 | * native mode and exit. | ||
| 298 | */ | ||
| 299 | if (nouveau_bios_fp_mode(dev, NULL) && (dev_priv->vbios.fp_no_ddc || | ||
| 300 | nv_encoder->dcb->lvdsconf.use_straps_for_mode)) { | ||
| 301 | status = connector_status_connected; | ||
| 302 | goto out; | ||
| 303 | } | ||
| 304 | |||
| 305 | /* Still nothing, some VBIOS images have a hardcoded EDID block | ||
| 306 | * stored for the panel stored in them. | ||
| 307 | */ | ||
| 308 | if (!dev_priv->vbios.fp_no_ddc) { | ||
| 309 | struct edid *edid = | ||
| 310 | (struct edid *)nouveau_bios_embedded_edid(dev); | ||
| 311 | if (edid) { | ||
| 312 | nv_connector->edid = kmalloc(EDID_LENGTH, GFP_KERNEL); | ||
| 313 | *(nv_connector->edid) = *edid; | ||
| 314 | status = connector_status_connected; | ||
| 315 | } | ||
| 316 | } | ||
| 317 | |||
| 318 | out: | ||
| 319 | #if defined(CONFIG_ACPI_BUTTON) || \ | ||
| 320 | (defined(CONFIG_ACPI_BUTTON_MODULE) && defined(MODULE)) | ||
| 321 | if (status == connector_status_connected && | ||
| 322 | !nouveau_ignorelid && !acpi_lid_open()) | ||
| 323 | status = connector_status_unknown; | ||
| 324 | #endif | ||
| 325 | |||
| 326 | drm_mode_connector_update_edid_property(connector, nv_connector->edid); | ||
| 327 | nouveau_connector_set_encoder(connector, nv_encoder); | ||
| 328 | return status; | ||
| 329 | } | ||
| 330 | |||
| 324 | static void | 331 | static void |
| 325 | nouveau_connector_force(struct drm_connector *connector) | 332 | nouveau_connector_force(struct drm_connector *connector) |
| 326 | { | 333 | { |
| @@ -441,7 +448,8 @@ nouveau_connector_native_mode(struct drm_connector *connector) | |||
| 441 | int high_w = 0, high_h = 0, high_v = 0; | 448 | int high_w = 0, high_h = 0, high_v = 0; |
| 442 | 449 | ||
| 443 | list_for_each_entry(mode, &nv_connector->base.probed_modes, head) { | 450 | list_for_each_entry(mode, &nv_connector->base.probed_modes, head) { |
| 444 | if (helper->mode_valid(connector, mode) != MODE_OK) | 451 | if (helper->mode_valid(connector, mode) != MODE_OK || |
| 452 | (mode->flags & DRM_MODE_FLAG_INTERLACE)) | ||
| 445 | continue; | 453 | continue; |
| 446 | 454 | ||
| 447 | /* Use preferred mode if there is one.. */ | 455 | /* Use preferred mode if there is one.. */ |
| @@ -534,21 +542,27 @@ static int | |||
| 534 | nouveau_connector_get_modes(struct drm_connector *connector) | 542 | nouveau_connector_get_modes(struct drm_connector *connector) |
| 535 | { | 543 | { |
| 536 | struct drm_device *dev = connector->dev; | 544 | struct drm_device *dev = connector->dev; |
| 545 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 537 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | 546 | struct nouveau_connector *nv_connector = nouveau_connector(connector); |
| 538 | struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; | 547 | struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; |
| 539 | int ret = 0; | 548 | int ret = 0; |
| 540 | 549 | ||
| 541 | /* If we're not LVDS, destroy the previous native mode, the attached | 550 | /* destroy the native mode, the attached monitor could have changed. |
| 542 | * monitor could have changed. | ||
| 543 | */ | 551 | */ |
| 544 | if (nv_connector->dcb->type != DCB_CONNECTOR_LVDS && | 552 | if (nv_connector->native_mode) { |
| 545 | nv_connector->native_mode) { | ||
| 546 | drm_mode_destroy(dev, nv_connector->native_mode); | 553 | drm_mode_destroy(dev, nv_connector->native_mode); |
| 547 | nv_connector->native_mode = NULL; | 554 | nv_connector->native_mode = NULL; |
| 548 | } | 555 | } |
| 549 | 556 | ||
| 550 | if (nv_connector->edid) | 557 | if (nv_connector->edid) |
| 551 | ret = drm_add_edid_modes(connector, nv_connector->edid); | 558 | ret = drm_add_edid_modes(connector, nv_connector->edid); |
| 559 | else | ||
| 560 | if (nv_encoder->dcb->type == OUTPUT_LVDS && | ||
| 561 | (nv_encoder->dcb->lvdsconf.use_straps_for_mode || | ||
| 562 | dev_priv->vbios.fp_no_ddc) && nouveau_bios_fp_mode(dev, NULL)) { | ||
| 563 | nv_connector->native_mode = drm_mode_create(dev); | ||
| 564 | nouveau_bios_fp_mode(dev, nv_connector->native_mode); | ||
| 565 | } | ||
| 552 | 566 | ||
| 553 | /* Find the native mode if this is a digital panel, if we didn't | 567 | /* Find the native mode if this is a digital panel, if we didn't |
| 554 | * find any modes through DDC previously add the native mode to | 568 | * find any modes through DDC previously add the native mode to |
| @@ -569,7 +583,8 @@ nouveau_connector_get_modes(struct drm_connector *connector) | |||
| 569 | ret = get_slave_funcs(nv_encoder)-> | 583 | ret = get_slave_funcs(nv_encoder)-> |
| 570 | get_modes(to_drm_encoder(nv_encoder), connector); | 584 | get_modes(to_drm_encoder(nv_encoder), connector); |
| 571 | 585 | ||
| 572 | if (nv_encoder->dcb->type == OUTPUT_LVDS) | 586 | if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS || |
| 587 | nv_connector->dcb->type == DCB_CONNECTOR_eDP) | ||
| 573 | ret += nouveau_connector_scaler_modes_add(connector); | 588 | ret += nouveau_connector_scaler_modes_add(connector); |
| 574 | 589 | ||
| 575 | return ret; | 590 | return ret; |
| @@ -643,6 +658,44 @@ nouveau_connector_best_encoder(struct drm_connector *connector) | |||
| 643 | return NULL; | 658 | return NULL; |
| 644 | } | 659 | } |
| 645 | 660 | ||
| 661 | void | ||
| 662 | nouveau_connector_set_polling(struct drm_connector *connector) | ||
| 663 | { | ||
| 664 | struct drm_device *dev = connector->dev; | ||
| 665 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 666 | struct drm_crtc *crtc; | ||
| 667 | bool spare_crtc = false; | ||
| 668 | |||
| 669 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) | ||
| 670 | spare_crtc |= !crtc->enabled; | ||
| 671 | |||
| 672 | connector->polled = 0; | ||
| 673 | |||
| 674 | switch (connector->connector_type) { | ||
| 675 | case DRM_MODE_CONNECTOR_VGA: | ||
| 676 | case DRM_MODE_CONNECTOR_TV: | ||
| 677 | if (dev_priv->card_type >= NV_50 || | ||
| 678 | (nv_gf4_disp_arch(dev) && spare_crtc)) | ||
| 679 | connector->polled = DRM_CONNECTOR_POLL_CONNECT; | ||
| 680 | break; | ||
| 681 | |||
| 682 | case DRM_MODE_CONNECTOR_DVII: | ||
| 683 | case DRM_MODE_CONNECTOR_DVID: | ||
| 684 | case DRM_MODE_CONNECTOR_HDMIA: | ||
| 685 | case DRM_MODE_CONNECTOR_DisplayPort: | ||
| 686 | case DRM_MODE_CONNECTOR_eDP: | ||
| 687 | if (dev_priv->card_type >= NV_50) | ||
| 688 | connector->polled = DRM_CONNECTOR_POLL_HPD; | ||
| 689 | else if (connector->connector_type == DRM_MODE_CONNECTOR_DVID || | ||
| 690 | spare_crtc) | ||
| 691 | connector->polled = DRM_CONNECTOR_POLL_CONNECT; | ||
| 692 | break; | ||
| 693 | |||
| 694 | default: | ||
| 695 | break; | ||
| 696 | } | ||
| 697 | } | ||
| 698 | |||
| 646 | static const struct drm_connector_helper_funcs | 699 | static const struct drm_connector_helper_funcs |
| 647 | nouveau_connector_helper_funcs = { | 700 | nouveau_connector_helper_funcs = { |
| 648 | .get_modes = nouveau_connector_get_modes, | 701 | .get_modes = nouveau_connector_get_modes, |
| @@ -662,148 +715,74 @@ nouveau_connector_funcs = { | |||
| 662 | .force = nouveau_connector_force | 715 | .force = nouveau_connector_force |
| 663 | }; | 716 | }; |
| 664 | 717 | ||
| 665 | static int | 718 | static const struct drm_connector_funcs |
| 666 | nouveau_connector_create_lvds(struct drm_device *dev, | 719 | nouveau_connector_funcs_lvds = { |
| 667 | struct drm_connector *connector) | 720 | .dpms = drm_helper_connector_dpms, |
| 668 | { | 721 | .save = NULL, |
| 669 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | 722 | .restore = NULL, |
| 670 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 723 | .detect = nouveau_connector_detect_lvds, |
| 671 | struct nouveau_i2c_chan *i2c = NULL; | 724 | .destroy = nouveau_connector_destroy, |
| 672 | struct nouveau_encoder *nv_encoder; | 725 | .fill_modes = drm_helper_probe_single_connector_modes, |
| 673 | struct drm_display_mode native, *mode, *temp; | 726 | .set_property = nouveau_connector_set_property, |
| 674 | bool dummy, if_is_24bit = false; | 727 | .force = nouveau_connector_force |
| 675 | int ret, flags; | 728 | }; |
| 676 | |||
| 677 | nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS); | ||
| 678 | if (!nv_encoder) | ||
| 679 | return -ENODEV; | ||
| 680 | |||
| 681 | ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &if_is_24bit); | ||
| 682 | if (ret) { | ||
| 683 | NV_ERROR(dev, "Error parsing LVDS table, disabling LVDS\n"); | ||
| 684 | return ret; | ||
| 685 | } | ||
| 686 | nv_connector->use_dithering = !if_is_24bit; | ||
| 687 | |||
| 688 | /* Firstly try getting EDID over DDC, if allowed and I2C channel | ||
| 689 | * is available. | ||
| 690 | */ | ||
| 691 | if (!dev_priv->vbios.fp_no_ddc && nv_encoder->dcb->i2c_index < 0xf) | ||
| 692 | i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); | ||
| 693 | |||
| 694 | if (i2c) { | ||
| 695 | nouveau_connector_ddc_prepare(connector, &flags); | ||
| 696 | nv_connector->edid = drm_get_edid(connector, &i2c->adapter); | ||
| 697 | nouveau_connector_ddc_finish(connector, flags); | ||
| 698 | } | ||
| 699 | |||
| 700 | /* If no EDID found above, and the VBIOS indicates a hardcoded | ||
| 701 | * modeline is avalilable for the panel, set it as the panel's | ||
| 702 | * native mode and exit. | ||
| 703 | */ | ||
| 704 | if (!nv_connector->edid && nouveau_bios_fp_mode(dev, &native) && | ||
| 705 | (nv_encoder->dcb->lvdsconf.use_straps_for_mode || | ||
| 706 | dev_priv->vbios.fp_no_ddc)) { | ||
| 707 | nv_connector->native_mode = drm_mode_duplicate(dev, &native); | ||
| 708 | goto out; | ||
| 709 | } | ||
| 710 | |||
| 711 | /* Still nothing, some VBIOS images have a hardcoded EDID block | ||
| 712 | * stored for the panel stored in them. | ||
| 713 | */ | ||
| 714 | if (!nv_connector->edid && !nv_connector->native_mode && | ||
| 715 | !dev_priv->vbios.fp_no_ddc) { | ||
| 716 | struct edid *edid = | ||
| 717 | (struct edid *)nouveau_bios_embedded_edid(dev); | ||
| 718 | if (edid) { | ||
| 719 | nv_connector->edid = kmalloc(EDID_LENGTH, GFP_KERNEL); | ||
| 720 | *(nv_connector->edid) = *edid; | ||
| 721 | } | ||
| 722 | } | ||
| 723 | |||
| 724 | if (!nv_connector->edid) | ||
| 725 | goto out; | ||
| 726 | |||
| 727 | /* We didn't find/use a panel mode from the VBIOS, so parse the EDID | ||
| 728 | * block and look for the preferred mode there. | ||
| 729 | */ | ||
| 730 | ret = drm_add_edid_modes(connector, nv_connector->edid); | ||
| 731 | if (ret == 0) | ||
| 732 | goto out; | ||
| 733 | nv_connector->detected_encoder = nv_encoder; | ||
| 734 | nv_connector->native_mode = nouveau_connector_native_mode(connector); | ||
| 735 | list_for_each_entry_safe(mode, temp, &connector->probed_modes, head) | ||
| 736 | drm_mode_remove(connector, mode); | ||
| 737 | |||
| 738 | out: | ||
| 739 | if (!nv_connector->native_mode) { | ||
| 740 | NV_ERROR(dev, "LVDS present in DCB table, but couldn't " | ||
| 741 | "determine its native mode. Disabling.\n"); | ||
| 742 | return -ENODEV; | ||
| 743 | } | ||
| 744 | |||
| 745 | drm_mode_connector_update_edid_property(connector, nv_connector->edid); | ||
| 746 | return 0; | ||
| 747 | } | ||
| 748 | 729 | ||
| 749 | int | 730 | struct drm_connector * |
| 750 | nouveau_connector_create(struct drm_device *dev, | 731 | nouveau_connector_create(struct drm_device *dev, int index) |
| 751 | struct dcb_connector_table_entry *dcb) | ||
| 752 | { | 732 | { |
| 733 | const struct drm_connector_funcs *funcs = &nouveau_connector_funcs; | ||
| 753 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 734 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 754 | struct nouveau_connector *nv_connector = NULL; | 735 | struct nouveau_connector *nv_connector = NULL; |
| 736 | struct dcb_connector_table_entry *dcb = NULL; | ||
| 755 | struct drm_connector *connector; | 737 | struct drm_connector *connector; |
| 756 | struct drm_encoder *encoder; | 738 | int type, ret = 0; |
| 757 | int ret, type; | ||
| 758 | 739 | ||
| 759 | NV_DEBUG_KMS(dev, "\n"); | 740 | NV_DEBUG_KMS(dev, "\n"); |
| 760 | 741 | ||
| 742 | if (index >= dev_priv->vbios.dcb.connector.entries) | ||
| 743 | return ERR_PTR(-EINVAL); | ||
| 744 | |||
| 745 | dcb = &dev_priv->vbios.dcb.connector.entry[index]; | ||
| 746 | if (dcb->drm) | ||
| 747 | return dcb->drm; | ||
| 748 | |||
| 761 | switch (dcb->type) { | 749 | switch (dcb->type) { |
| 762 | case DCB_CONNECTOR_NONE: | ||
| 763 | return 0; | ||
| 764 | case DCB_CONNECTOR_VGA: | 750 | case DCB_CONNECTOR_VGA: |
| 765 | NV_INFO(dev, "Detected a VGA connector\n"); | ||
| 766 | type = DRM_MODE_CONNECTOR_VGA; | 751 | type = DRM_MODE_CONNECTOR_VGA; |
| 767 | break; | 752 | break; |
| 768 | case DCB_CONNECTOR_TV_0: | 753 | case DCB_CONNECTOR_TV_0: |
| 769 | case DCB_CONNECTOR_TV_1: | 754 | case DCB_CONNECTOR_TV_1: |
| 770 | case DCB_CONNECTOR_TV_3: | 755 | case DCB_CONNECTOR_TV_3: |
| 771 | NV_INFO(dev, "Detected a TV connector\n"); | ||
| 772 | type = DRM_MODE_CONNECTOR_TV; | 756 | type = DRM_MODE_CONNECTOR_TV; |
| 773 | break; | 757 | break; |
| 774 | case DCB_CONNECTOR_DVI_I: | 758 | case DCB_CONNECTOR_DVI_I: |
| 775 | NV_INFO(dev, "Detected a DVI-I connector\n"); | ||
| 776 | type = DRM_MODE_CONNECTOR_DVII; | 759 | type = DRM_MODE_CONNECTOR_DVII; |
| 777 | break; | 760 | break; |
| 778 | case DCB_CONNECTOR_DVI_D: | 761 | case DCB_CONNECTOR_DVI_D: |
| 779 | NV_INFO(dev, "Detected a DVI-D connector\n"); | ||
| 780 | type = DRM_MODE_CONNECTOR_DVID; | 762 | type = DRM_MODE_CONNECTOR_DVID; |
| 781 | break; | 763 | break; |
| 782 | case DCB_CONNECTOR_HDMI_0: | 764 | case DCB_CONNECTOR_HDMI_0: |
| 783 | case DCB_CONNECTOR_HDMI_1: | 765 | case DCB_CONNECTOR_HDMI_1: |
| 784 | NV_INFO(dev, "Detected a HDMI connector\n"); | ||
| 785 | type = DRM_MODE_CONNECTOR_HDMIA; | 766 | type = DRM_MODE_CONNECTOR_HDMIA; |
| 786 | break; | 767 | break; |
| 787 | case DCB_CONNECTOR_LVDS: | 768 | case DCB_CONNECTOR_LVDS: |
| 788 | NV_INFO(dev, "Detected a LVDS connector\n"); | ||
| 789 | type = DRM_MODE_CONNECTOR_LVDS; | 769 | type = DRM_MODE_CONNECTOR_LVDS; |
| 770 | funcs = &nouveau_connector_funcs_lvds; | ||
| 790 | break; | 771 | break; |
| 791 | case DCB_CONNECTOR_DP: | 772 | case DCB_CONNECTOR_DP: |
| 792 | NV_INFO(dev, "Detected a DisplayPort connector\n"); | ||
| 793 | type = DRM_MODE_CONNECTOR_DisplayPort; | 773 | type = DRM_MODE_CONNECTOR_DisplayPort; |
| 794 | break; | 774 | break; |
| 795 | case DCB_CONNECTOR_eDP: | 775 | case DCB_CONNECTOR_eDP: |
| 796 | NV_INFO(dev, "Detected an eDP connector\n"); | ||
| 797 | type = DRM_MODE_CONNECTOR_eDP; | 776 | type = DRM_MODE_CONNECTOR_eDP; |
| 798 | break; | 777 | break; |
| 799 | default: | 778 | default: |
| 800 | NV_ERROR(dev, "unknown connector type: 0x%02x!!\n", dcb->type); | 779 | NV_ERROR(dev, "unknown connector type: 0x%02x!!\n", dcb->type); |
| 801 | return -EINVAL; | 780 | return ERR_PTR(-EINVAL); |
| 802 | } | 781 | } |
| 803 | 782 | ||
| 804 | nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL); | 783 | nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL); |
| 805 | if (!nv_connector) | 784 | if (!nv_connector) |
| 806 | return -ENOMEM; | 785 | return ERR_PTR(-ENOMEM); |
| 807 | nv_connector->dcb = dcb; | 786 | nv_connector->dcb = dcb; |
| 808 | connector = &nv_connector->base; | 787 | connector = &nv_connector->base; |
| 809 | 788 | ||
| @@ -811,27 +790,21 @@ nouveau_connector_create(struct drm_device *dev, | |||
| 811 | connector->interlace_allowed = false; | 790 | connector->interlace_allowed = false; |
| 812 | connector->doublescan_allowed = false; | 791 | connector->doublescan_allowed = false; |
| 813 | 792 | ||
| 814 | drm_connector_init(dev, connector, &nouveau_connector_funcs, type); | 793 | drm_connector_init(dev, connector, funcs, type); |
| 815 | drm_connector_helper_add(connector, &nouveau_connector_helper_funcs); | 794 | drm_connector_helper_add(connector, &nouveau_connector_helper_funcs); |
| 816 | 795 | ||
| 817 | /* attach encoders */ | 796 | /* Check if we need dithering enabled */ |
| 818 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 797 | if (dcb->type == DCB_CONNECTOR_LVDS) { |
| 819 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 798 | bool dummy, is_24bit = false; |
| 820 | |||
| 821 | if (nv_encoder->dcb->connector != dcb->index) | ||
| 822 | continue; | ||
| 823 | |||
| 824 | if (get_slave_funcs(nv_encoder)) | ||
| 825 | get_slave_funcs(nv_encoder)->create_resources(encoder, connector); | ||
| 826 | 799 | ||
| 827 | drm_mode_connector_attach_encoder(connector, encoder); | 800 | ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &is_24bit); |
| 828 | } | 801 | if (ret) { |
| 802 | NV_ERROR(dev, "Error parsing LVDS table, disabling " | ||
| 803 | "LVDS\n"); | ||
| 804 | goto fail; | ||
| 805 | } | ||
| 829 | 806 | ||
| 830 | if (!connector->encoder_ids[0]) { | 807 | nv_connector->use_dithering = !is_24bit; |
| 831 | NV_WARN(dev, " no encoders, ignoring\n"); | ||
| 832 | drm_connector_cleanup(connector); | ||
| 833 | kfree(connector); | ||
| 834 | return 0; | ||
| 835 | } | 808 | } |
| 836 | 809 | ||
| 837 | /* Init DVI-I specific properties */ | 810 | /* Init DVI-I specific properties */ |
| @@ -841,12 +814,8 @@ nouveau_connector_create(struct drm_device *dev, | |||
| 841 | drm_connector_attach_property(connector, dev->mode_config.dvi_i_select_subconnector_property, 0); | 814 | drm_connector_attach_property(connector, dev->mode_config.dvi_i_select_subconnector_property, 0); |
| 842 | } | 815 | } |
| 843 | 816 | ||
| 844 | if (dcb->type != DCB_CONNECTOR_LVDS) | ||
| 845 | nv_connector->use_dithering = false; | ||
| 846 | |||
| 847 | switch (dcb->type) { | 817 | switch (dcb->type) { |
| 848 | case DCB_CONNECTOR_VGA: | 818 | case DCB_CONNECTOR_VGA: |
| 849 | connector->polled = DRM_CONNECTOR_POLL_CONNECT; | ||
| 850 | if (dev_priv->card_type >= NV_50) { | 819 | if (dev_priv->card_type >= NV_50) { |
| 851 | drm_connector_attach_property(connector, | 820 | drm_connector_attach_property(connector, |
| 852 | dev->mode_config.scaling_mode_property, | 821 | dev->mode_config.scaling_mode_property, |
| @@ -858,17 +827,6 @@ nouveau_connector_create(struct drm_device *dev, | |||
| 858 | case DCB_CONNECTOR_TV_3: | 827 | case DCB_CONNECTOR_TV_3: |
| 859 | nv_connector->scaling_mode = DRM_MODE_SCALE_NONE; | 828 | nv_connector->scaling_mode = DRM_MODE_SCALE_NONE; |
| 860 | break; | 829 | break; |
| 861 | case DCB_CONNECTOR_DP: | ||
| 862 | case DCB_CONNECTOR_eDP: | ||
| 863 | case DCB_CONNECTOR_HDMI_0: | ||
| 864 | case DCB_CONNECTOR_HDMI_1: | ||
| 865 | case DCB_CONNECTOR_DVI_I: | ||
| 866 | case DCB_CONNECTOR_DVI_D: | ||
| 867 | if (dev_priv->card_type >= NV_50) | ||
| 868 | connector->polled = DRM_CONNECTOR_POLL_HPD; | ||
| 869 | else | ||
| 870 | connector->polled = DRM_CONNECTOR_POLL_CONNECT; | ||
| 871 | /* fall-through */ | ||
| 872 | default: | 830 | default: |
| 873 | nv_connector->scaling_mode = DRM_MODE_SCALE_FULLSCREEN; | 831 | nv_connector->scaling_mode = DRM_MODE_SCALE_FULLSCREEN; |
| 874 | 832 | ||
| @@ -882,15 +840,15 @@ nouveau_connector_create(struct drm_device *dev, | |||
| 882 | break; | 840 | break; |
| 883 | } | 841 | } |
| 884 | 842 | ||
| 843 | nouveau_connector_set_polling(connector); | ||
| 844 | |||
| 885 | drm_sysfs_connector_add(connector); | 845 | drm_sysfs_connector_add(connector); |
| 846 | dcb->drm = connector; | ||
| 847 | return dcb->drm; | ||
| 886 | 848 | ||
| 887 | if (dcb->type == DCB_CONNECTOR_LVDS) { | 849 | fail: |
| 888 | ret = nouveau_connector_create_lvds(dev, connector); | 850 | drm_connector_cleanup(connector); |
| 889 | if (ret) { | 851 | kfree(connector); |
| 890 | connector->funcs->destroy(connector); | 852 | return ERR_PTR(ret); |
| 891 | return ret; | ||
| 892 | } | ||
| 893 | } | ||
| 894 | 853 | ||
| 895 | return 0; | ||
| 896 | } | 854 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h index 4ef38abc2d9c..0d2e668ccfe5 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( | |||
| 49 | return container_of(con, struct nouveau_connector, base); | 49 | return container_of(con, struct nouveau_connector, base); |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | int nouveau_connector_create(struct drm_device *, | 52 | struct drm_connector * |
| 53 | struct dcb_connector_table_entry *); | 53 | nouveau_connector_create(struct drm_device *, int index); |
| 54 | |||
| 55 | void | ||
| 56 | nouveau_connector_set_polling(struct drm_connector *); | ||
| 54 | 57 | ||
| 55 | #endif /* __NOUVEAU_CONNECTOR_H__ */ | 58 | #endif /* __NOUVEAU_CONNECTOR_H__ */ |
diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c index 65c441a1999f..2e3c6caa97ee 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) | |||
| 92 | return ret; | 92 | return ret; |
| 93 | 93 | ||
| 94 | /* Map M2MF notifier object - fbcon. */ | 94 | /* Map M2MF notifier object - fbcon. */ |
| 95 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 95 | ret = nouveau_bo_map(chan->notifier_bo); |
| 96 | ret = nouveau_bo_map(chan->notifier_bo); | 96 | if (ret) |
| 97 | if (ret) | 97 | return ret; |
| 98 | return ret; | ||
| 99 | } | ||
| 100 | 98 | ||
| 101 | /* Insert NOPS for NOUVEAU_DMA_SKIPS */ | 99 | /* Insert NOPS for NOUVEAU_DMA_SKIPS */ |
| 102 | ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS); | 100 | 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 deeb21c6865c..33742b11188b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c | |||
| @@ -23,8 +23,10 @@ | |||
| 23 | */ | 23 | */ |
| 24 | 24 | ||
| 25 | #include "drmP.h" | 25 | #include "drmP.h" |
| 26 | |||
| 26 | #include "nouveau_drv.h" | 27 | #include "nouveau_drv.h" |
| 27 | #include "nouveau_i2c.h" | 28 | #include "nouveau_i2c.h" |
| 29 | #include "nouveau_connector.h" | ||
| 28 | #include "nouveau_encoder.h" | 30 | #include "nouveau_encoder.h" |
| 29 | 31 | ||
| 30 | static int | 32 | static int |
| @@ -270,13 +272,39 @@ bool | |||
| 270 | nouveau_dp_link_train(struct drm_encoder *encoder) | 272 | nouveau_dp_link_train(struct drm_encoder *encoder) |
| 271 | { | 273 | { |
| 272 | struct drm_device *dev = encoder->dev; | 274 | struct drm_device *dev = encoder->dev; |
| 275 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 276 | struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; | ||
| 273 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 277 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); |
| 274 | uint8_t config[4]; | 278 | struct nouveau_connector *nv_connector; |
| 275 | uint8_t status[3]; | 279 | struct bit_displayport_encoder_table *dpe; |
| 280 | int dpe_headerlen; | ||
| 281 | uint8_t config[4], status[3]; | ||
| 276 | bool cr_done, cr_max_vs, eq_done; | 282 | bool cr_done, cr_max_vs, eq_done; |
| 277 | int ret = 0, i, tries, voltage; | 283 | int ret = 0, i, tries, voltage; |
| 278 | 284 | ||
| 279 | NV_DEBUG_KMS(dev, "link training!!\n"); | 285 | NV_DEBUG_KMS(dev, "link training!!\n"); |
| 286 | |||
| 287 | nv_connector = nouveau_encoder_connector_get(nv_encoder); | ||
| 288 | if (!nv_connector) | ||
| 289 | return false; | ||
| 290 | |||
| 291 | dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); | ||
| 292 | if (!dpe) { | ||
| 293 | NV_ERROR(dev, "SOR-%d: no DP encoder table!\n", nv_encoder->or); | ||
| 294 | return false; | ||
| 295 | } | ||
| 296 | |||
| 297 | /* disable hotplug detect, this flips around on some panels during | ||
| 298 | * link training. | ||
| 299 | */ | ||
| 300 | pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); | ||
| 301 | |||
| 302 | if (dpe->script0) { | ||
| 303 | NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or); | ||
| 304 | nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script0), | ||
| 305 | nv_encoder->dcb); | ||
| 306 | } | ||
| 307 | |||
| 280 | train: | 308 | train: |
| 281 | cr_done = eq_done = false; | 309 | cr_done = eq_done = false; |
| 282 | 310 | ||
| @@ -403,6 +431,15 @@ stop: | |||
| 403 | } | 431 | } |
| 404 | } | 432 | } |
| 405 | 433 | ||
| 434 | if (dpe->script1) { | ||
| 435 | NV_DEBUG_KMS(dev, "SOR-%d: running DP script 1\n", nv_encoder->or); | ||
| 436 | nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script1), | ||
| 437 | nv_encoder->dcb); | ||
| 438 | } | ||
| 439 | |||
| 440 | /* re-enable hotplug detect */ | ||
| 441 | pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, true); | ||
| 442 | |||
| 406 | return eq_done; | 443 | return eq_done; |
| 407 | } | 444 | } |
| 408 | 445 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index 273770432298..1de5eb53e016 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c | |||
| @@ -35,10 +35,6 @@ | |||
| 35 | 35 | ||
| 36 | #include "drm_pciids.h" | 36 | #include "drm_pciids.h" |
| 37 | 37 | ||
| 38 | MODULE_PARM_DESC(ctxfw, "Use external firmware blob for grctx init (NV40)"); | ||
| 39 | int nouveau_ctxfw = 0; | ||
| 40 | module_param_named(ctxfw, nouveau_ctxfw, int, 0400); | ||
| 41 | |||
| 42 | MODULE_PARM_DESC(noagp, "Disable AGP"); | 38 | MODULE_PARM_DESC(noagp, "Disable AGP"); |
| 43 | int nouveau_noagp; | 39 | int nouveau_noagp; |
| 44 | module_param_named(noagp, nouveau_noagp, int, 0400); | 40 | module_param_named(noagp, nouveau_noagp, int, 0400); |
| @@ -56,7 +52,7 @@ int nouveau_vram_pushbuf; | |||
| 56 | module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400); | 52 | module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400); |
| 57 | 53 | ||
| 58 | MODULE_PARM_DESC(vram_notify, "Force DMA notifiers to be in VRAM"); | 54 | MODULE_PARM_DESC(vram_notify, "Force DMA notifiers to be in VRAM"); |
| 59 | int nouveau_vram_notify = 1; | 55 | int nouveau_vram_notify = 0; |
| 60 | module_param_named(vram_notify, nouveau_vram_notify, int, 0400); | 56 | module_param_named(vram_notify, nouveau_vram_notify, int, 0400); |
| 61 | 57 | ||
| 62 | MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (>=GeForce 8)"); | 58 | MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (>=GeForce 8)"); |
| @@ -132,7 +128,7 @@ static struct drm_driver driver; | |||
| 132 | static int __devinit | 128 | static int __devinit |
| 133 | nouveau_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 129 | nouveau_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
| 134 | { | 130 | { |
| 135 | return drm_get_dev(pdev, ent, &driver); | 131 | return drm_get_pci_dev(pdev, ent, &driver); |
| 136 | } | 132 | } |
| 137 | 133 | ||
| 138 | static void | 134 | static void |
| @@ -155,9 +151,6 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state) | |||
| 155 | struct drm_crtc *crtc; | 151 | struct drm_crtc *crtc; |
| 156 | int ret, i; | 152 | int ret, i; |
| 157 | 153 | ||
| 158 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | ||
| 159 | return -ENODEV; | ||
| 160 | |||
| 161 | if (pm_state.event == PM_EVENT_PRETHAW) | 154 | if (pm_state.event == PM_EVENT_PRETHAW) |
| 162 | return 0; | 155 | return 0; |
| 163 | 156 | ||
| @@ -257,9 +250,6 @@ nouveau_pci_resume(struct pci_dev *pdev) | |||
| 257 | struct drm_crtc *crtc; | 250 | struct drm_crtc *crtc; |
| 258 | int ret, i; | 251 | int ret, i; |
| 259 | 252 | ||
| 260 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | ||
| 261 | return -ENODEV; | ||
| 262 | |||
| 263 | nouveau_fbcon_save_disable_accel(dev); | 253 | nouveau_fbcon_save_disable_accel(dev); |
| 264 | 254 | ||
| 265 | NV_INFO(dev, "We're back, enabling device...\n"); | 255 | NV_INFO(dev, "We're back, enabling device...\n"); |
| @@ -269,6 +259,13 @@ nouveau_pci_resume(struct pci_dev *pdev) | |||
| 269 | return -1; | 259 | return -1; |
| 270 | pci_set_master(dev->pdev); | 260 | pci_set_master(dev->pdev); |
| 271 | 261 | ||
| 262 | /* Make sure the AGP controller is in a consistent state */ | ||
| 263 | if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) | ||
| 264 | nouveau_mem_reset_agp(dev); | ||
| 265 | |||
| 266 | /* Make the CRTCs accessible */ | ||
| 267 | engine->display.early_init(dev); | ||
| 268 | |||
| 272 | NV_INFO(dev, "POSTing device...\n"); | 269 | NV_INFO(dev, "POSTing device...\n"); |
| 273 | ret = nouveau_run_vbios_init(dev); | 270 | ret = nouveau_run_vbios_init(dev); |
| 274 | if (ret) | 271 | if (ret) |
| @@ -323,7 +320,6 @@ nouveau_pci_resume(struct pci_dev *pdev) | |||
| 323 | 320 | ||
| 324 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | 321 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
| 325 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 322 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |
| 326 | int ret; | ||
| 327 | 323 | ||
| 328 | ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); | 324 | ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); |
| 329 | if (!ret) | 325 | if (!ret) |
| @@ -332,11 +328,7 @@ nouveau_pci_resume(struct pci_dev *pdev) | |||
| 332 | NV_ERROR(dev, "Could not pin/map cursor.\n"); | 328 | NV_ERROR(dev, "Could not pin/map cursor.\n"); |
| 333 | } | 329 | } |
| 334 | 330 | ||
| 335 | if (dev_priv->card_type < NV_50) { | 331 | engine->display.init(dev); |
| 336 | nv04_display_restore(dev); | ||
| 337 | NVLockVgaCrtcs(dev, false); | ||
| 338 | } else | ||
| 339 | nv50_display_init(dev); | ||
| 340 | 332 | ||
| 341 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | 333 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
| 342 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 334 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |
| @@ -371,7 +363,8 @@ nouveau_pci_resume(struct pci_dev *pdev) | |||
| 371 | static struct drm_driver driver = { | 363 | static struct drm_driver driver = { |
| 372 | .driver_features = | 364 | .driver_features = |
| 373 | DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG | | 365 | DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG | |
| 374 | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM, | 366 | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM | |
| 367 | DRIVER_MODESET, | ||
| 375 | .load = nouveau_load, | 368 | .load = nouveau_load, |
| 376 | .firstopen = nouveau_firstopen, | 369 | .firstopen = nouveau_firstopen, |
| 377 | .lastclose = nouveau_lastclose, | 370 | .lastclose = nouveau_lastclose, |
| @@ -438,16 +431,18 @@ static int __init nouveau_init(void) | |||
| 438 | nouveau_modeset = 1; | 431 | nouveau_modeset = 1; |
| 439 | } | 432 | } |
| 440 | 433 | ||
| 441 | if (nouveau_modeset == 1) { | 434 | if (!nouveau_modeset) |
| 442 | driver.driver_features |= DRIVER_MODESET; | 435 | return 0; |
| 443 | nouveau_register_dsm_handler(); | ||
| 444 | } | ||
| 445 | 436 | ||
| 437 | nouveau_register_dsm_handler(); | ||
| 446 | return drm_init(&driver); | 438 | return drm_init(&driver); |
| 447 | } | 439 | } |
| 448 | 440 | ||
| 449 | static void __exit nouveau_exit(void) | 441 | static void __exit nouveau_exit(void) |
| 450 | { | 442 | { |
| 443 | if (!nouveau_modeset) | ||
| 444 | return; | ||
| 445 | |||
| 451 | drm_exit(&driver); | 446 | drm_exit(&driver); |
| 452 | nouveau_unregister_dsm_handler(); | 447 | nouveau_unregister_dsm_handler(); |
| 453 | } | 448 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index c69719106489..e15db15dca77 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) | |||
| 123 | return ioptr; | 123 | return ioptr; |
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | struct mem_block { | ||
| 127 | struct mem_block *next; | ||
| 128 | struct mem_block *prev; | ||
| 129 | uint64_t start; | ||
| 130 | uint64_t size; | ||
| 131 | struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */ | ||
| 132 | }; | ||
| 133 | |||
| 134 | enum nouveau_flags { | 126 | enum nouveau_flags { |
| 135 | NV_NFORCE = 0x10000000, | 127 | NV_NFORCE = 0x10000000, |
| 136 | NV_NFORCE2 = 0x20000000 | 128 | NV_NFORCE2 = 0x20000000 |
| @@ -149,7 +141,7 @@ struct nouveau_gpuobj { | |||
| 149 | struct list_head list; | 141 | struct list_head list; |
| 150 | 142 | ||
| 151 | struct nouveau_channel *im_channel; | 143 | struct nouveau_channel *im_channel; |
| 152 | struct mem_block *im_pramin; | 144 | struct drm_mm_node *im_pramin; |
| 153 | struct nouveau_bo *im_backing; | 145 | struct nouveau_bo *im_backing; |
| 154 | uint32_t im_backing_start; | 146 | uint32_t im_backing_start; |
| 155 | uint32_t *im_backing_suspend; | 147 | uint32_t *im_backing_suspend; |
| @@ -196,7 +188,7 @@ struct nouveau_channel { | |||
| 196 | struct list_head pending; | 188 | struct list_head pending; |
| 197 | uint32_t sequence; | 189 | uint32_t sequence; |
| 198 | uint32_t sequence_ack; | 190 | uint32_t sequence_ack; |
| 199 | uint32_t last_sequence_irq; | 191 | atomic_t last_sequence_irq; |
| 200 | } fence; | 192 | } fence; |
| 201 | 193 | ||
| 202 | /* DMA push buffer */ | 194 | /* DMA push buffer */ |
| @@ -206,7 +198,7 @@ struct nouveau_channel { | |||
| 206 | 198 | ||
| 207 | /* Notifier memory */ | 199 | /* Notifier memory */ |
| 208 | struct nouveau_bo *notifier_bo; | 200 | struct nouveau_bo *notifier_bo; |
| 209 | struct mem_block *notifier_heap; | 201 | struct drm_mm notifier_heap; |
| 210 | 202 | ||
| 211 | /* PFIFO context */ | 203 | /* PFIFO context */ |
| 212 | struct nouveau_gpuobj_ref *ramfc; | 204 | struct nouveau_gpuobj_ref *ramfc; |
| @@ -224,7 +216,7 @@ struct nouveau_channel { | |||
| 224 | 216 | ||
| 225 | /* Objects */ | 217 | /* Objects */ |
| 226 | struct nouveau_gpuobj_ref *ramin; /* Private instmem */ | 218 | struct nouveau_gpuobj_ref *ramin; /* Private instmem */ |
| 227 | struct mem_block *ramin_heap; /* Private PRAMIN heap */ | 219 | struct drm_mm ramin_heap; /* Private PRAMIN heap */ |
| 228 | struct nouveau_gpuobj_ref *ramht; /* Hash table */ | 220 | struct nouveau_gpuobj_ref *ramht; /* Hash table */ |
| 229 | struct list_head ramht_refs; /* Objects referenced by RAMHT */ | 221 | struct list_head ramht_refs; /* Objects referenced by RAMHT */ |
| 230 | 222 | ||
| @@ -277,8 +269,7 @@ struct nouveau_instmem_engine { | |||
| 277 | void (*clear)(struct drm_device *, struct nouveau_gpuobj *); | 269 | void (*clear)(struct drm_device *, struct nouveau_gpuobj *); |
| 278 | int (*bind)(struct drm_device *, struct nouveau_gpuobj *); | 270 | int (*bind)(struct drm_device *, struct nouveau_gpuobj *); |
| 279 | int (*unbind)(struct drm_device *, struct nouveau_gpuobj *); | 271 | int (*unbind)(struct drm_device *, struct nouveau_gpuobj *); |
| 280 | void (*prepare_access)(struct drm_device *, bool write); | 272 | void (*flush)(struct drm_device *); |
| 281 | void (*finish_access)(struct drm_device *); | ||
| 282 | }; | 273 | }; |
| 283 | 274 | ||
| 284 | struct nouveau_mc_engine { | 275 | struct nouveau_mc_engine { |
| @@ -303,10 +294,11 @@ struct nouveau_fb_engine { | |||
| 303 | }; | 294 | }; |
| 304 | 295 | ||
| 305 | struct nouveau_fifo_engine { | 296 | struct nouveau_fifo_engine { |
| 306 | void *priv; | ||
| 307 | |||
| 308 | int channels; | 297 | int channels; |
| 309 | 298 | ||
| 299 | struct nouveau_gpuobj_ref *playlist[2]; | ||
| 300 | int cur_playlist; | ||
| 301 | |||
| 310 | int (*init)(struct drm_device *); | 302 | int (*init)(struct drm_device *); |
| 311 | void (*takedown)(struct drm_device *); | 303 | void (*takedown)(struct drm_device *); |
| 312 | 304 | ||
| @@ -339,10 +331,11 @@ struct nouveau_pgraph_object_class { | |||
| 339 | struct nouveau_pgraph_engine { | 331 | struct nouveau_pgraph_engine { |
| 340 | struct nouveau_pgraph_object_class *grclass; | 332 | struct nouveau_pgraph_object_class *grclass; |
| 341 | bool accel_blocked; | 333 | bool accel_blocked; |
| 342 | void *ctxprog; | ||
| 343 | void *ctxvals; | ||
| 344 | int grctx_size; | 334 | int grctx_size; |
| 345 | 335 | ||
| 336 | /* NV2x/NV3x context table (0x400780) */ | ||
| 337 | struct nouveau_gpuobj_ref *ctx_table; | ||
| 338 | |||
| 346 | int (*init)(struct drm_device *); | 339 | int (*init)(struct drm_device *); |
| 347 | void (*takedown)(struct drm_device *); | 340 | void (*takedown)(struct drm_device *); |
| 348 | 341 | ||
| @@ -358,6 +351,24 @@ struct nouveau_pgraph_engine { | |||
| 358 | uint32_t size, uint32_t pitch); | 351 | uint32_t size, uint32_t pitch); |
| 359 | }; | 352 | }; |
| 360 | 353 | ||
| 354 | struct nouveau_display_engine { | ||
| 355 | int (*early_init)(struct drm_device *); | ||
| 356 | void (*late_takedown)(struct drm_device *); | ||
| 357 | int (*create)(struct drm_device *); | ||
| 358 | int (*init)(struct drm_device *); | ||
| 359 | void (*destroy)(struct drm_device *); | ||
| 360 | }; | ||
| 361 | |||
| 362 | struct nouveau_gpio_engine { | ||
| 363 | int (*init)(struct drm_device *); | ||
| 364 | void (*takedown)(struct drm_device *); | ||
| 365 | |||
| 366 | int (*get)(struct drm_device *, enum dcb_gpio_tag); | ||
| 367 | int (*set)(struct drm_device *, enum dcb_gpio_tag, int state); | ||
| 368 | |||
| 369 | void (*irq_enable)(struct drm_device *, enum dcb_gpio_tag, bool on); | ||
| 370 | }; | ||
| 371 | |||
| 361 | struct nouveau_engine { | 372 | struct nouveau_engine { |
| 362 | struct nouveau_instmem_engine instmem; | 373 | struct nouveau_instmem_engine instmem; |
| 363 | struct nouveau_mc_engine mc; | 374 | struct nouveau_mc_engine mc; |
| @@ -365,6 +376,8 @@ struct nouveau_engine { | |||
| 365 | struct nouveau_fb_engine fb; | 376 | struct nouveau_fb_engine fb; |
| 366 | struct nouveau_pgraph_engine graph; | 377 | struct nouveau_pgraph_engine graph; |
| 367 | struct nouveau_fifo_engine fifo; | 378 | struct nouveau_fifo_engine fifo; |
| 379 | struct nouveau_display_engine display; | ||
| 380 | struct nouveau_gpio_engine gpio; | ||
| 368 | }; | 381 | }; |
| 369 | 382 | ||
| 370 | struct nouveau_pll_vals { | 383 | struct nouveau_pll_vals { |
| @@ -500,11 +513,6 @@ enum nouveau_card_type { | |||
| 500 | 513 | ||
| 501 | struct drm_nouveau_private { | 514 | struct drm_nouveau_private { |
| 502 | struct drm_device *dev; | 515 | struct drm_device *dev; |
| 503 | enum { | ||
| 504 | NOUVEAU_CARD_INIT_DOWN, | ||
| 505 | NOUVEAU_CARD_INIT_DONE, | ||
| 506 | NOUVEAU_CARD_INIT_FAILED | ||
| 507 | } init_state; | ||
| 508 | 516 | ||
| 509 | /* the card type, takes NV_* as values */ | 517 | /* the card type, takes NV_* as values */ |
| 510 | enum nouveau_card_type card_type; | 518 | enum nouveau_card_type card_type; |
| @@ -525,7 +533,7 @@ struct drm_nouveau_private { | |||
| 525 | struct list_head vbl_waiting; | 533 | struct list_head vbl_waiting; |
| 526 | 534 | ||
| 527 | struct { | 535 | struct { |
| 528 | struct ttm_global_reference mem_global_ref; | 536 | struct drm_global_reference mem_global_ref; |
| 529 | struct ttm_bo_global_ref bo_global_ref; | 537 | struct ttm_bo_global_ref bo_global_ref; |
| 530 | struct ttm_bo_device bdev; | 538 | struct ttm_bo_device bdev; |
| 531 | spinlock_t bo_list_lock; | 539 | spinlock_t bo_list_lock; |
| @@ -533,8 +541,6 @@ struct drm_nouveau_private { | |||
| 533 | atomic_t validate_sequence; | 541 | atomic_t validate_sequence; |
| 534 | } ttm; | 542 | } ttm; |
| 535 | 543 | ||
| 536 | struct fb_info *fbdev_info; | ||
| 537 | |||
| 538 | int fifo_alloc_count; | 544 | int fifo_alloc_count; |
| 539 | struct nouveau_channel *fifos[NOUVEAU_MAX_CHANNEL_NR]; | 545 | struct nouveau_channel *fifos[NOUVEAU_MAX_CHANNEL_NR]; |
| 540 | 546 | ||
| @@ -595,11 +601,7 @@ struct drm_nouveau_private { | |||
| 595 | struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR]; | 601 | struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR]; |
| 596 | int vm_vram_pt_nr; | 602 | int vm_vram_pt_nr; |
| 597 | 603 | ||
| 598 | struct mem_block *ramin_heap; | 604 | struct drm_mm ramin_heap; |
| 599 | |||
| 600 | /* context table pointed to be NV_PGRAPH_CHANNEL_CTX_TABLE (0x400780) */ | ||
| 601 | uint32_t ctx_table_size; | ||
| 602 | struct nouveau_gpuobj_ref *ctx_table; | ||
| 603 | 605 | ||
| 604 | struct list_head gpuobj_list; | 606 | struct list_head gpuobj_list; |
| 605 | 607 | ||
| @@ -618,6 +620,11 @@ struct drm_nouveau_private { | |||
| 618 | struct backlight_device *backlight; | 620 | struct backlight_device *backlight; |
| 619 | 621 | ||
| 620 | struct nouveau_channel *evo; | 622 | struct nouveau_channel *evo; |
| 623 | struct { | ||
| 624 | struct dcb_entry *dcb; | ||
| 625 | u16 script; | ||
| 626 | u32 pclk; | ||
| 627 | } evo_irq; | ||
| 621 | 628 | ||
| 622 | struct { | 629 | struct { |
| 623 | struct dentry *channel_root; | 630 | struct dentry *channel_root; |
| @@ -652,14 +659,6 @@ nouveau_bo_ref(struct nouveau_bo *ref, struct nouveau_bo **pnvbo) | |||
| 652 | return 0; | 659 | return 0; |
| 653 | } | 660 | } |
| 654 | 661 | ||
| 655 | #define NOUVEAU_CHECK_INITIALISED_WITH_RETURN do { \ | ||
| 656 | struct drm_nouveau_private *nv = dev->dev_private; \ | ||
| 657 | if (nv->init_state != NOUVEAU_CARD_INIT_DONE) { \ | ||
| 658 | NV_ERROR(dev, "called without init\n"); \ | ||
| 659 | return -EINVAL; \ | ||
| 660 | } \ | ||
| 661 | } while (0) | ||
| 662 | |||
| 663 | #define NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(id, cl, ch) do { \ | 662 | #define NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(id, cl, ch) do { \ |
| 664 | struct drm_nouveau_private *nv = dev->dev_private; \ | 663 | struct drm_nouveau_private *nv = dev->dev_private; \ |
| 665 | if (!nouveau_channel_owner(dev, (cl), (id))) { \ | 664 | if (!nouveau_channel_owner(dev, (cl), (id))) { \ |
| @@ -682,7 +681,6 @@ extern int nouveau_tv_disable; | |||
| 682 | extern char *nouveau_tv_norm; | 681 | extern char *nouveau_tv_norm; |
| 683 | extern int nouveau_reg_debug; | 682 | extern int nouveau_reg_debug; |
| 684 | extern char *nouveau_vbios; | 683 | extern char *nouveau_vbios; |
| 685 | extern int nouveau_ctxfw; | ||
| 686 | extern int nouveau_ignorelid; | 684 | extern int nouveau_ignorelid; |
| 687 | extern int nouveau_nofbaccel; | 685 | extern int nouveau_nofbaccel; |
| 688 | extern int nouveau_noaccel; | 686 | extern int nouveau_noaccel; |
| @@ -707,17 +705,10 @@ extern bool nouveau_wait_for_idle(struct drm_device *); | |||
| 707 | extern int nouveau_card_init(struct drm_device *); | 705 | extern int nouveau_card_init(struct drm_device *); |
| 708 | 706 | ||
| 709 | /* nouveau_mem.c */ | 707 | /* nouveau_mem.c */ |
| 710 | extern int nouveau_mem_init_heap(struct mem_block **, uint64_t start, | ||
| 711 | uint64_t size); | ||
| 712 | extern struct mem_block *nouveau_mem_alloc_block(struct mem_block *, | ||
| 713 | uint64_t size, int align2, | ||
| 714 | struct drm_file *, int tail); | ||
| 715 | extern void nouveau_mem_takedown(struct mem_block **heap); | ||
| 716 | extern void nouveau_mem_free_block(struct mem_block *); | ||
| 717 | extern int nouveau_mem_detect(struct drm_device *dev); | 708 | extern int nouveau_mem_detect(struct drm_device *dev); |
| 718 | extern void nouveau_mem_release(struct drm_file *, struct mem_block *heap); | ||
| 719 | extern int nouveau_mem_init(struct drm_device *); | 709 | extern int nouveau_mem_init(struct drm_device *); |
| 720 | extern int nouveau_mem_init_agp(struct drm_device *); | 710 | extern int nouveau_mem_init_agp(struct drm_device *); |
| 711 | extern int nouveau_mem_reset_agp(struct drm_device *); | ||
| 721 | extern void nouveau_mem_close(struct drm_device *); | 712 | extern void nouveau_mem_close(struct drm_device *); |
| 722 | extern struct nouveau_tile_reg *nv10_mem_set_tiling(struct drm_device *dev, | 713 | extern struct nouveau_tile_reg *nv10_mem_set_tiling(struct drm_device *dev, |
| 723 | uint32_t addr, | 714 | uint32_t addr, |
| @@ -857,11 +848,13 @@ void nouveau_register_dsm_handler(void); | |||
| 857 | void nouveau_unregister_dsm_handler(void); | 848 | void nouveau_unregister_dsm_handler(void); |
| 858 | int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len); | 849 | int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len); |
| 859 | bool nouveau_acpi_rom_supported(struct pci_dev *pdev); | 850 | bool nouveau_acpi_rom_supported(struct pci_dev *pdev); |
| 851 | int nouveau_acpi_edid(struct drm_device *, struct drm_connector *); | ||
| 860 | #else | 852 | #else |
| 861 | static inline void nouveau_register_dsm_handler(void) {} | 853 | static inline void nouveau_register_dsm_handler(void) {} |
| 862 | static inline void nouveau_unregister_dsm_handler(void) {} | 854 | static inline void nouveau_unregister_dsm_handler(void) {} |
| 863 | static inline bool nouveau_acpi_rom_supported(struct pci_dev *pdev) { return false; } | 855 | static inline bool nouveau_acpi_rom_supported(struct pci_dev *pdev) { return false; } |
| 864 | static inline int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len) { return -EINVAL; } | 856 | static inline int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len) { return -EINVAL; } |
| 857 | static inline int nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) { return -EINVAL; } | ||
| 865 | #endif | 858 | #endif |
| 866 | 859 | ||
| 867 | /* nouveau_backlight.c */ | 860 | /* nouveau_backlight.c */ |
| @@ -924,6 +917,10 @@ extern void nv10_fb_takedown(struct drm_device *); | |||
| 924 | extern void nv10_fb_set_region_tiling(struct drm_device *, int, uint32_t, | 917 | extern void nv10_fb_set_region_tiling(struct drm_device *, int, uint32_t, |
| 925 | uint32_t, uint32_t); | 918 | uint32_t, uint32_t); |
| 926 | 919 | ||
| 920 | /* nv30_fb.c */ | ||
| 921 | extern int nv30_fb_init(struct drm_device *); | ||
| 922 | extern void nv30_fb_takedown(struct drm_device *); | ||
| 923 | |||
| 927 | /* nv40_fb.c */ | 924 | /* nv40_fb.c */ |
| 928 | extern int nv40_fb_init(struct drm_device *); | 925 | extern int nv40_fb_init(struct drm_device *); |
| 929 | extern void nv40_fb_takedown(struct drm_device *); | 926 | extern void nv40_fb_takedown(struct drm_device *); |
| @@ -1035,12 +1032,6 @@ extern int nv50_graph_unload_context(struct drm_device *); | |||
| 1035 | extern void nv50_graph_context_switch(struct drm_device *); | 1032 | extern void nv50_graph_context_switch(struct drm_device *); |
| 1036 | extern int nv50_grctx_init(struct nouveau_grctx *); | 1033 | extern int nv50_grctx_init(struct nouveau_grctx *); |
| 1037 | 1034 | ||
| 1038 | /* nouveau_grctx.c */ | ||
| 1039 | extern int nouveau_grctx_prog_load(struct drm_device *); | ||
| 1040 | extern void nouveau_grctx_vals_load(struct drm_device *, | ||
| 1041 | struct nouveau_gpuobj *); | ||
| 1042 | extern void nouveau_grctx_fini(struct drm_device *); | ||
| 1043 | |||
| 1044 | /* nv04_instmem.c */ | 1035 | /* nv04_instmem.c */ |
| 1045 | extern int nv04_instmem_init(struct drm_device *); | 1036 | extern int nv04_instmem_init(struct drm_device *); |
| 1046 | extern void nv04_instmem_takedown(struct drm_device *); | 1037 | extern void nv04_instmem_takedown(struct drm_device *); |
| @@ -1051,8 +1042,7 @@ extern int nv04_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, | |||
| 1051 | extern void nv04_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); | 1042 | extern void nv04_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); |
| 1052 | extern int nv04_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); | 1043 | extern int nv04_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); |
| 1053 | extern int nv04_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); | 1044 | extern int nv04_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); |
| 1054 | extern void nv04_instmem_prepare_access(struct drm_device *, bool write); | 1045 | extern void nv04_instmem_flush(struct drm_device *); |
| 1055 | extern void nv04_instmem_finish_access(struct drm_device *); | ||
| 1056 | 1046 | ||
| 1057 | /* nv50_instmem.c */ | 1047 | /* nv50_instmem.c */ |
| 1058 | extern int nv50_instmem_init(struct drm_device *); | 1048 | extern int nv50_instmem_init(struct drm_device *); |
| @@ -1064,8 +1054,9 @@ extern int nv50_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, | |||
| 1064 | extern void nv50_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); | 1054 | extern void nv50_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); |
| 1065 | extern int nv50_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); | 1055 | extern int nv50_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); |
| 1066 | extern int nv50_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); | 1056 | extern int nv50_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); |
| 1067 | extern void nv50_instmem_prepare_access(struct drm_device *, bool write); | 1057 | extern void nv50_instmem_flush(struct drm_device *); |
| 1068 | extern void nv50_instmem_finish_access(struct drm_device *); | 1058 | extern void nv84_instmem_flush(struct drm_device *); |
| 1059 | extern void nv50_vm_flush(struct drm_device *, int engine); | ||
| 1069 | 1060 | ||
| 1070 | /* nv04_mc.c */ | 1061 | /* nv04_mc.c */ |
| 1071 | extern int nv04_mc_init(struct drm_device *); | 1062 | extern int nv04_mc_init(struct drm_device *); |
| @@ -1088,13 +1079,14 @@ extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd, | |||
| 1088 | unsigned long arg); | 1079 | unsigned long arg); |
| 1089 | 1080 | ||
| 1090 | /* nv04_dac.c */ | 1081 | /* nv04_dac.c */ |
| 1091 | extern int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry); | 1082 | extern int nv04_dac_create(struct drm_connector *, struct dcb_entry *); |
| 1092 | extern uint32_t nv17_dac_sample_load(struct drm_encoder *encoder); | 1083 | extern uint32_t nv17_dac_sample_load(struct drm_encoder *encoder); |
| 1093 | extern int nv04_dac_output_offset(struct drm_encoder *encoder); | 1084 | extern int nv04_dac_output_offset(struct drm_encoder *encoder); |
| 1094 | extern void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable); | 1085 | extern void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable); |
| 1086 | extern bool nv04_dac_in_use(struct drm_encoder *encoder); | ||
| 1095 | 1087 | ||
| 1096 | /* nv04_dfp.c */ | 1088 | /* nv04_dfp.c */ |
| 1097 | extern int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry); | 1089 | extern int nv04_dfp_create(struct drm_connector *, struct dcb_entry *); |
| 1098 | extern int nv04_dfp_get_bound_head(struct drm_device *dev, struct dcb_entry *dcbent); | 1090 | extern int nv04_dfp_get_bound_head(struct drm_device *dev, struct dcb_entry *dcbent); |
| 1099 | extern void nv04_dfp_bind_head(struct drm_device *dev, struct dcb_entry *dcbent, | 1091 | extern void nv04_dfp_bind_head(struct drm_device *dev, struct dcb_entry *dcbent, |
| 1100 | int head, bool dl); | 1092 | int head, bool dl); |
| @@ -1103,15 +1095,17 @@ extern void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode); | |||
| 1103 | 1095 | ||
| 1104 | /* nv04_tv.c */ | 1096 | /* nv04_tv.c */ |
| 1105 | extern int nv04_tv_identify(struct drm_device *dev, int i2c_index); | 1097 | extern int nv04_tv_identify(struct drm_device *dev, int i2c_index); |
| 1106 | extern int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry); | 1098 | extern int nv04_tv_create(struct drm_connector *, struct dcb_entry *); |
| 1107 | 1099 | ||
| 1108 | /* nv17_tv.c */ | 1100 | /* nv17_tv.c */ |
| 1109 | extern int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry); | 1101 | extern int nv17_tv_create(struct drm_connector *, struct dcb_entry *); |
| 1110 | 1102 | ||
| 1111 | /* nv04_display.c */ | 1103 | /* nv04_display.c */ |
| 1104 | extern int nv04_display_early_init(struct drm_device *); | ||
| 1105 | extern void nv04_display_late_takedown(struct drm_device *); | ||
| 1112 | extern int nv04_display_create(struct drm_device *); | 1106 | extern int nv04_display_create(struct drm_device *); |
| 1107 | extern int nv04_display_init(struct drm_device *); | ||
| 1113 | extern void nv04_display_destroy(struct drm_device *); | 1108 | extern void nv04_display_destroy(struct drm_device *); |
| 1114 | extern void nv04_display_restore(struct drm_device *); | ||
| 1115 | 1109 | ||
| 1116 | /* nv04_crtc.c */ | 1110 | /* nv04_crtc.c */ |
| 1117 | extern int nv04_crtc_create(struct drm_device *, int index); | 1111 | extern int nv04_crtc_create(struct drm_device *, int index); |
| @@ -1147,7 +1141,6 @@ extern int nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr); | |||
| 1147 | extern int nouveau_fence_flush(void *obj, void *arg); | 1141 | extern int nouveau_fence_flush(void *obj, void *arg); |
| 1148 | extern void nouveau_fence_unref(void **obj); | 1142 | extern void nouveau_fence_unref(void **obj); |
| 1149 | extern void *nouveau_fence_ref(void *obj); | 1143 | extern void *nouveau_fence_ref(void *obj); |
| 1150 | extern void nouveau_fence_handler(struct drm_device *dev, int channel); | ||
| 1151 | 1144 | ||
| 1152 | /* nouveau_gem.c */ | 1145 | /* nouveau_gem.c */ |
| 1153 | extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *, | 1146 | extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *, |
| @@ -1167,13 +1160,15 @@ extern int nouveau_gem_ioctl_cpu_fini(struct drm_device *, void *, | |||
| 1167 | extern int nouveau_gem_ioctl_info(struct drm_device *, void *, | 1160 | extern int nouveau_gem_ioctl_info(struct drm_device *, void *, |
| 1168 | struct drm_file *); | 1161 | struct drm_file *); |
| 1169 | 1162 | ||
| 1170 | /* nv17_gpio.c */ | 1163 | /* nv10_gpio.c */ |
| 1171 | int nv17_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); | 1164 | int nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); |
| 1172 | int nv17_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); | 1165 | int nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); |
| 1173 | 1166 | ||
| 1174 | /* nv50_gpio.c */ | 1167 | /* nv50_gpio.c */ |
| 1168 | int nv50_gpio_init(struct drm_device *dev); | ||
| 1175 | int nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); | 1169 | int nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); |
| 1176 | int nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); | 1170 | int nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); |
| 1171 | void nv50_gpio_irq_enable(struct drm_device *, enum dcb_gpio_tag, bool on); | ||
| 1177 | 1172 | ||
| 1178 | /* nv50_calc. */ | 1173 | /* nv50_calc. */ |
| 1179 | int nv50_calc_pll(struct drm_device *, struct pll_lims *, int clk, | 1174 | int nv50_calc_pll(struct drm_device *, struct pll_lims *, int clk, |
| @@ -1220,6 +1215,14 @@ static inline void nv_wr32(struct drm_device *dev, unsigned reg, u32 val) | |||
| 1220 | iowrite32_native(val, dev_priv->mmio + reg); | 1215 | iowrite32_native(val, dev_priv->mmio + reg); |
| 1221 | } | 1216 | } |
| 1222 | 1217 | ||
| 1218 | static inline void nv_mask(struct drm_device *dev, u32 reg, u32 mask, u32 val) | ||
| 1219 | { | ||
| 1220 | u32 tmp = nv_rd32(dev, reg); | ||
| 1221 | tmp &= ~mask; | ||
| 1222 | tmp |= val; | ||
| 1223 | nv_wr32(dev, reg, tmp); | ||
| 1224 | } | ||
| 1225 | |||
| 1223 | static inline u8 nv_rd08(struct drm_device *dev, unsigned reg) | 1226 | static inline u8 nv_rd08(struct drm_device *dev, unsigned reg) |
| 1224 | { | 1227 | { |
| 1225 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 1228 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index e1df8209cd0f..a1a0d48ae70c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h | |||
| @@ -38,13 +38,15 @@ struct nouveau_encoder { | |||
| 38 | struct dcb_entry *dcb; | 38 | struct dcb_entry *dcb; |
| 39 | int or; | 39 | int or; |
| 40 | 40 | ||
| 41 | /* different to drm_encoder.crtc, this reflects what's | ||
| 42 | * actually programmed on the hw, not the proposed crtc */ | ||
| 43 | struct drm_crtc *crtc; | ||
| 44 | |||
| 41 | struct drm_display_mode mode; | 45 | struct drm_display_mode mode; |
| 42 | int last_dpms; | 46 | int last_dpms; |
| 43 | 47 | ||
| 44 | struct nv04_output_reg restore; | 48 | struct nv04_output_reg restore; |
| 45 | 49 | ||
| 46 | void (*disconnect)(struct nouveau_encoder *encoder); | ||
| 47 | |||
| 48 | union { | 50 | union { |
| 49 | struct { | 51 | struct { |
| 50 | int mc_unknown; | 52 | int mc_unknown; |
| @@ -71,8 +73,8 @@ static inline struct drm_encoder *to_drm_encoder(struct nouveau_encoder *enc) | |||
| 71 | 73 | ||
| 72 | struct nouveau_connector * | 74 | struct nouveau_connector * |
| 73 | nouveau_encoder_connector_get(struct nouveau_encoder *encoder); | 75 | nouveau_encoder_connector_get(struct nouveau_encoder *encoder); |
| 74 | int nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry); | 76 | int nv50_sor_create(struct drm_connector *, struct dcb_entry *); |
| 75 | int nv50_dac_create(struct drm_device *dev, struct dcb_entry *entry); | 77 | int nv50_dac_create(struct drm_connector *, struct dcb_entry *); |
| 76 | 78 | ||
| 77 | struct bit_displayport_encoder_table { | 79 | struct bit_displayport_encoder_table { |
| 78 | uint32_t match; | 80 | uint32_t match; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 257ea130ae13..2fb2444d2322 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) | |||
| 333 | drm_fb_helper_hotplug_event(&dev_priv->nfbdev->helper); | 333 | drm_fb_helper_hotplug_event(&dev_priv->nfbdev->helper); |
| 334 | } | 334 | } |
| 335 | 335 | ||
| 336 | int | 336 | static int |
| 337 | nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *nfbdev) | 337 | nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *nfbdev) |
| 338 | { | 338 | { |
| 339 | struct nouveau_framebuffer *nouveau_fb = &nfbdev->nouveau_fb; | 339 | 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 faddf53ff9ed..6b208ffafa8d 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) | |||
| 67 | if (USE_REFCNT) | 67 | if (USE_REFCNT) |
| 68 | sequence = nvchan_rd32(chan, 0x48); | 68 | sequence = nvchan_rd32(chan, 0x48); |
| 69 | else | 69 | else |
| 70 | sequence = chan->fence.last_sequence_irq; | 70 | sequence = atomic_read(&chan->fence.last_sequence_irq); |
| 71 | 71 | ||
| 72 | if (chan->fence.sequence_ack == sequence) | 72 | if (chan->fence.sequence_ack == sequence) |
| 73 | return; | 73 | return; |
| 74 | chan->fence.sequence_ack = sequence; | 74 | chan->fence.sequence_ack = sequence; |
| 75 | 75 | ||
| 76 | spin_lock(&chan->fence.lock); | ||
| 76 | list_for_each_safe(entry, tmp, &chan->fence.pending) { | 77 | list_for_each_safe(entry, tmp, &chan->fence.pending) { |
| 77 | fence = list_entry(entry, struct nouveau_fence, entry); | 78 | fence = list_entry(entry, struct nouveau_fence, entry); |
| 78 | 79 | ||
| @@ -84,6 +85,7 @@ nouveau_fence_update(struct nouveau_channel *chan) | |||
| 84 | if (sequence == chan->fence.sequence_ack) | 85 | if (sequence == chan->fence.sequence_ack) |
| 85 | break; | 86 | break; |
| 86 | } | 87 | } |
| 88 | spin_unlock(&chan->fence.lock); | ||
| 87 | } | 89 | } |
| 88 | 90 | ||
| 89 | int | 91 | int |
| @@ -119,7 +121,6 @@ nouveau_fence_emit(struct nouveau_fence *fence) | |||
| 119 | { | 121 | { |
| 120 | struct drm_nouveau_private *dev_priv = fence->channel->dev->dev_private; | 122 | struct drm_nouveau_private *dev_priv = fence->channel->dev->dev_private; |
| 121 | struct nouveau_channel *chan = fence->channel; | 123 | struct nouveau_channel *chan = fence->channel; |
| 122 | unsigned long flags; | ||
| 123 | int ret; | 124 | int ret; |
| 124 | 125 | ||
| 125 | ret = RING_SPACE(chan, 2); | 126 | ret = RING_SPACE(chan, 2); |
| @@ -127,9 +128,7 @@ nouveau_fence_emit(struct nouveau_fence *fence) | |||
| 127 | return ret; | 128 | return ret; |
| 128 | 129 | ||
| 129 | if (unlikely(chan->fence.sequence == chan->fence.sequence_ack - 1)) { | 130 | if (unlikely(chan->fence.sequence == chan->fence.sequence_ack - 1)) { |
| 130 | spin_lock_irqsave(&chan->fence.lock, flags); | ||
| 131 | nouveau_fence_update(chan); | 131 | nouveau_fence_update(chan); |
| 132 | spin_unlock_irqrestore(&chan->fence.lock, flags); | ||
| 133 | 132 | ||
| 134 | BUG_ON(chan->fence.sequence == | 133 | BUG_ON(chan->fence.sequence == |
| 135 | chan->fence.sequence_ack - 1); | 134 | chan->fence.sequence_ack - 1); |
| @@ -138,9 +137,9 @@ nouveau_fence_emit(struct nouveau_fence *fence) | |||
| 138 | fence->sequence = ++chan->fence.sequence; | 137 | fence->sequence = ++chan->fence.sequence; |
| 139 | 138 | ||
| 140 | kref_get(&fence->refcount); | 139 | kref_get(&fence->refcount); |
| 141 | spin_lock_irqsave(&chan->fence.lock, flags); | 140 | spin_lock(&chan->fence.lock); |
| 142 | list_add_tail(&fence->entry, &chan->fence.pending); | 141 | list_add_tail(&fence->entry, &chan->fence.pending); |
| 143 | spin_unlock_irqrestore(&chan->fence.lock, flags); | 142 | spin_unlock(&chan->fence.lock); |
| 144 | 143 | ||
| 145 | BEGIN_RING(chan, NvSubSw, USE_REFCNT ? 0x0050 : 0x0150, 1); | 144 | BEGIN_RING(chan, NvSubSw, USE_REFCNT ? 0x0050 : 0x0150, 1); |
| 146 | OUT_RING(chan, fence->sequence); | 145 | OUT_RING(chan, fence->sequence); |
| @@ -173,14 +172,11 @@ nouveau_fence_signalled(void *sync_obj, void *sync_arg) | |||
| 173 | { | 172 | { |
| 174 | struct nouveau_fence *fence = nouveau_fence(sync_obj); | 173 | struct nouveau_fence *fence = nouveau_fence(sync_obj); |
| 175 | struct nouveau_channel *chan = fence->channel; | 174 | struct nouveau_channel *chan = fence->channel; |
| 176 | unsigned long flags; | ||
| 177 | 175 | ||
| 178 | if (fence->signalled) | 176 | if (fence->signalled) |
| 179 | return true; | 177 | return true; |
| 180 | 178 | ||
| 181 | spin_lock_irqsave(&chan->fence.lock, flags); | ||
| 182 | nouveau_fence_update(chan); | 179 | nouveau_fence_update(chan); |
| 183 | spin_unlock_irqrestore(&chan->fence.lock, flags); | ||
| 184 | return fence->signalled; | 180 | return fence->signalled; |
| 185 | } | 181 | } |
| 186 | 182 | ||
| @@ -190,8 +186,6 @@ nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) | |||
| 190 | unsigned long timeout = jiffies + (3 * DRM_HZ); | 186 | unsigned long timeout = jiffies + (3 * DRM_HZ); |
| 191 | int ret = 0; | 187 | int ret = 0; |
| 192 | 188 | ||
| 193 | __set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); | ||
| 194 | |||
| 195 | while (1) { | 189 | while (1) { |
| 196 | if (nouveau_fence_signalled(sync_obj, sync_arg)) | 190 | if (nouveau_fence_signalled(sync_obj, sync_arg)) |
| 197 | break; | 191 | break; |
| @@ -201,6 +195,8 @@ nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) | |||
| 201 | break; | 195 | break; |
| 202 | } | 196 | } |
| 203 | 197 | ||
| 198 | __set_current_state(intr ? TASK_INTERRUPTIBLE | ||
| 199 | : TASK_UNINTERRUPTIBLE); | ||
| 204 | if (lazy) | 200 | if (lazy) |
| 205 | schedule_timeout(1); | 201 | schedule_timeout(1); |
| 206 | 202 | ||
| @@ -221,27 +217,12 @@ nouveau_fence_flush(void *sync_obj, void *sync_arg) | |||
| 221 | return 0; | 217 | return 0; |
| 222 | } | 218 | } |
| 223 | 219 | ||
| 224 | void | ||
| 225 | nouveau_fence_handler(struct drm_device *dev, int channel) | ||
| 226 | { | ||
| 227 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 228 | struct nouveau_channel *chan = NULL; | ||
| 229 | |||
| 230 | if (channel >= 0 && channel < dev_priv->engine.fifo.channels) | ||
| 231 | chan = dev_priv->fifos[channel]; | ||
| 232 | |||
| 233 | if (chan) { | ||
| 234 | spin_lock_irq(&chan->fence.lock); | ||
| 235 | nouveau_fence_update(chan); | ||
| 236 | spin_unlock_irq(&chan->fence.lock); | ||
| 237 | } | ||
| 238 | } | ||
| 239 | |||
| 240 | int | 220 | int |
| 241 | nouveau_fence_init(struct nouveau_channel *chan) | 221 | nouveau_fence_init(struct nouveau_channel *chan) |
| 242 | { | 222 | { |
| 243 | INIT_LIST_HEAD(&chan->fence.pending); | 223 | INIT_LIST_HEAD(&chan->fence.pending); |
| 244 | spin_lock_init(&chan->fence.lock); | 224 | spin_lock_init(&chan->fence.lock); |
| 225 | atomic_set(&chan->fence.last_sequence_irq, 0); | ||
| 245 | return 0; | 226 | return 0; |
| 246 | } | 227 | } |
| 247 | 228 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 69c76cf93407..547f2c24c1e7 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, | |||
| 137 | uint32_t flags = 0; | 137 | uint32_t flags = 0; |
| 138 | int ret = 0; | 138 | int ret = 0; |
| 139 | 139 | ||
| 140 | NOUVEAU_CHECK_INITIALISED_WITH_RETURN; | ||
| 141 | |||
| 142 | if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL)) | 140 | if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL)) |
| 143 | dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping; | 141 | dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping; |
| 144 | 142 | ||
| @@ -577,10 +575,9 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, | |||
| 577 | struct drm_nouveau_gem_pushbuf_bo *bo; | 575 | struct drm_nouveau_gem_pushbuf_bo *bo; |
| 578 | struct nouveau_channel *chan; | 576 | struct nouveau_channel *chan; |
| 579 | struct validate_op op; | 577 | struct validate_op op; |
| 580 | struct nouveau_fence *fence = 0; | 578 | struct nouveau_fence *fence = NULL; |
| 581 | int i, j, ret = 0, do_reloc = 0; | 579 | int i, j, ret = 0, do_reloc = 0; |
| 582 | 580 | ||
| 583 | NOUVEAU_CHECK_INITIALISED_WITH_RETURN; | ||
| 584 | NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel, file_priv, chan); | 581 | NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel, file_priv, chan); |
| 585 | 582 | ||
| 586 | req->vram_available = dev_priv->fb_aper_free; | 583 | req->vram_available = dev_priv->fb_aper_free; |
| @@ -760,8 +757,6 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data, | |||
| 760 | bool no_wait = !!(req->flags & NOUVEAU_GEM_CPU_PREP_NOWAIT); | 757 | bool no_wait = !!(req->flags & NOUVEAU_GEM_CPU_PREP_NOWAIT); |
| 761 | int ret = -EINVAL; | 758 | int ret = -EINVAL; |
| 762 | 759 | ||
| 763 | NOUVEAU_CHECK_INITIALISED_WITH_RETURN; | ||
| 764 | |||
| 765 | gem = drm_gem_object_lookup(dev, file_priv, req->handle); | 760 | gem = drm_gem_object_lookup(dev, file_priv, req->handle); |
| 766 | if (!gem) | 761 | if (!gem) |
| 767 | return ret; | 762 | return ret; |
| @@ -800,8 +795,6 @@ nouveau_gem_ioctl_cpu_fini(struct drm_device *dev, void *data, | |||
| 800 | struct nouveau_bo *nvbo; | 795 | struct nouveau_bo *nvbo; |
| 801 | int ret = -EINVAL; | 796 | int ret = -EINVAL; |
| 802 | 797 | ||
| 803 | NOUVEAU_CHECK_INITIALISED_WITH_RETURN; | ||
| 804 | |||
| 805 | gem = drm_gem_object_lookup(dev, file_priv, req->handle); | 798 | gem = drm_gem_object_lookup(dev, file_priv, req->handle); |
| 806 | if (!gem) | 799 | if (!gem) |
| 807 | return ret; | 800 | return ret; |
| @@ -827,8 +820,6 @@ nouveau_gem_ioctl_info(struct drm_device *dev, void *data, | |||
| 827 | struct drm_gem_object *gem; | 820 | struct drm_gem_object *gem; |
| 828 | int ret; | 821 | int ret; |
| 829 | 822 | ||
| 830 | NOUVEAU_CHECK_INITIALISED_WITH_RETURN; | ||
| 831 | |||
| 832 | gem = drm_gem_object_lookup(dev, file_priv, req->handle); | 823 | gem = drm_gem_object_lookup(dev, file_priv, req->handle); |
| 833 | if (!gem) | 824 | if (!gem) |
| 834 | return -EINVAL; | 825 | 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 f731c5f60536..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_grctx.c +++ /dev/null | |||
| @@ -1,160 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2009 Red Hat Inc. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice shall be included in | ||
| 12 | * all copies or substantial portions of the Software. | ||
| 13 | * | ||
| 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 21 | * | ||
| 22 | * Authors: Ben Skeggs | ||
| 23 | */ | ||
| 24 | |||
| 25 | #include <linux/firmware.h> | ||
| 26 | #include <linux/slab.h> | ||
| 27 | |||
| 28 | #include "drmP.h" | ||
| 29 | #include "nouveau_drv.h" | ||
| 30 | |||
| 31 | struct nouveau_ctxprog { | ||
| 32 | uint32_t signature; | ||
| 33 | uint8_t version; | ||
| 34 | uint16_t length; | ||
| 35 | uint32_t data[]; | ||
| 36 | } __attribute__ ((packed)); | ||
| 37 | |||
| 38 | struct nouveau_ctxvals { | ||
| 39 | uint32_t signature; | ||
| 40 | uint8_t version; | ||
| 41 | uint32_t length; | ||
| 42 | struct { | ||
| 43 | uint32_t offset; | ||
| 44 | uint32_t value; | ||
| 45 | } data[]; | ||
| 46 | } __attribute__ ((packed)); | ||
| 47 | |||
| 48 | int | ||
| 49 | nouveau_grctx_prog_load(struct drm_device *dev) | ||
| 50 | { | ||
| 51 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 52 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; | ||
| 53 | const int chipset = dev_priv->chipset; | ||
| 54 | const struct firmware *fw; | ||
| 55 | const struct nouveau_ctxprog *cp; | ||
| 56 | const struct nouveau_ctxvals *cv; | ||
| 57 | char name[32]; | ||
| 58 | int ret, i; | ||
| 59 | |||
| 60 | if (pgraph->accel_blocked) | ||
| 61 | return -ENODEV; | ||
| 62 | |||
| 63 | if (!pgraph->ctxprog) { | ||
| 64 | sprintf(name, "nouveau/nv%02x.ctxprog", chipset); | ||
| 65 | ret = request_firmware(&fw, name, &dev->pdev->dev); | ||
| 66 | if (ret) { | ||
| 67 | NV_ERROR(dev, "No ctxprog for NV%02x\n", chipset); | ||
| 68 | return ret; | ||
| 69 | } | ||
| 70 | |||
| 71 | pgraph->ctxprog = kmemdup(fw->data, fw->size, GFP_KERNEL); | ||
| 72 | if (!pgraph->ctxprog) { | ||
| 73 | NV_ERROR(dev, "OOM copying ctxprog\n"); | ||
| 74 | release_firmware(fw); | ||
| 75 | return -ENOMEM; | ||
| 76 | } | ||
| 77 | |||
| 78 | cp = pgraph->ctxprog; | ||
| 79 | if (le32_to_cpu(cp->signature) != 0x5043564e || | ||
| 80 | cp->version != 0 || | ||
| 81 | le16_to_cpu(cp->length) != ((fw->size - 7) / 4)) { | ||
| 82 | NV_ERROR(dev, "ctxprog invalid\n"); | ||
| 83 | release_firmware(fw); | ||
| 84 | nouveau_grctx_fini(dev); | ||
| 85 | return -EINVAL; | ||
| 86 | } | ||
| 87 | release_firmware(fw); | ||
| 88 | } | ||
| 89 | |||
| 90 | if (!pgraph->ctxvals) { | ||
| 91 | sprintf(name, "nouveau/nv%02x.ctxvals", chipset); | ||
| 92 | ret = request_firmware(&fw, name, &dev->pdev->dev); | ||
| 93 | if (ret) { | ||
| 94 | NV_ERROR(dev, "No ctxvals for NV%02x\n", chipset); | ||
| 95 | nouveau_grctx_fini(dev); | ||
| 96 | return ret; | ||
| 97 | } | ||
| 98 | |||
| 99 | pgraph->ctxvals = kmemdup(fw->data, fw->size, GFP_KERNEL); | ||
| 100 | if (!pgraph->ctxvals) { | ||
| 101 | NV_ERROR(dev, "OOM copying ctxvals\n"); | ||
| 102 | release_firmware(fw); | ||
| 103 | nouveau_grctx_fini(dev); | ||
| 104 | return -ENOMEM; | ||
| 105 | } | ||
| 106 | |||
| 107 | cv = (void *)pgraph->ctxvals; | ||
| 108 | if (le32_to_cpu(cv->signature) != 0x5643564e || | ||
| 109 | cv->version != 0 || | ||
| 110 | le32_to_cpu(cv->length) != ((fw->size - 9) / 8)) { | ||
| 111 | NV_ERROR(dev, "ctxvals invalid\n"); | ||
| 112 | release_firmware(fw); | ||
| 113 | nouveau_grctx_fini(dev); | ||
| 114 | return -EINVAL; | ||
| 115 | } | ||
| 116 | release_firmware(fw); | ||
| 117 | } | ||
| 118 | |||
| 119 | cp = pgraph->ctxprog; | ||
| 120 | |||
| 121 | nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); | ||
| 122 | for (i = 0; i < le16_to_cpu(cp->length); i++) | ||
| 123 | nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, | ||
| 124 | le32_to_cpu(cp->data[i])); | ||
| 125 | |||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | |||
| 129 | void | ||
| 130 | nouveau_grctx_fini(struct drm_device *dev) | ||
| 131 | { | ||
| 132 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 133 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; | ||
| 134 | |||
| 135 | if (pgraph->ctxprog) { | ||
| 136 | kfree(pgraph->ctxprog); | ||
| 137 | pgraph->ctxprog = NULL; | ||
| 138 | } | ||
| 139 | |||
| 140 | if (pgraph->ctxvals) { | ||
| 141 | kfree(pgraph->ctxprog); | ||
| 142 | pgraph->ctxvals = NULL; | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | void | ||
| 147 | nouveau_grctx_vals_load(struct drm_device *dev, struct nouveau_gpuobj *ctx) | ||
| 148 | { | ||
| 149 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 150 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; | ||
| 151 | struct nouveau_ctxvals *cv = pgraph->ctxvals; | ||
| 152 | int i; | ||
| 153 | |||
| 154 | if (!cv) | ||
| 155 | return; | ||
| 156 | |||
| 157 | for (i = 0; i < le32_to_cpu(cv->length); i++) | ||
| 158 | nv_wo32(dev, ctx, le32_to_cpu(cv->data[i].offset), | ||
| 159 | le32_to_cpu(cv->data[i].value)); | ||
| 160 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c index 316a3c7e6eb4..cb0cb34440c6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_i2c.c +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c | |||
| @@ -278,3 +278,45 @@ nouveau_i2c_find(struct drm_device *dev, int index) | |||
| 278 | return i2c->chan; | 278 | return i2c->chan; |
| 279 | } | 279 | } |
| 280 | 280 | ||
| 281 | bool | ||
| 282 | nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr) | ||
| 283 | { | ||
| 284 | uint8_t buf[] = { 0 }; | ||
| 285 | struct i2c_msg msgs[] = { | ||
| 286 | { | ||
| 287 | .addr = addr, | ||
| 288 | .flags = 0, | ||
| 289 | .len = 1, | ||
| 290 | .buf = buf, | ||
| 291 | }, | ||
| 292 | { | ||
| 293 | .addr = addr, | ||
| 294 | .flags = I2C_M_RD, | ||
| 295 | .len = 1, | ||
| 296 | .buf = buf, | ||
| 297 | } | ||
| 298 | }; | ||
| 299 | |||
| 300 | return i2c_transfer(&i2c->adapter, msgs, 2) == 2; | ||
| 301 | } | ||
| 302 | |||
| 303 | int | ||
| 304 | nouveau_i2c_identify(struct drm_device *dev, const char *what, | ||
| 305 | struct i2c_board_info *info, int index) | ||
| 306 | { | ||
| 307 | struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, index); | ||
| 308 | int i; | ||
| 309 | |||
| 310 | NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, index); | ||
| 311 | |||
| 312 | for (i = 0; info[i].addr; i++) { | ||
| 313 | if (nouveau_probe_i2c_addr(i2c, info[i].addr)) { | ||
| 314 | NV_INFO(dev, "Detected %s: %s\n", what, info[i].type); | ||
| 315 | return i; | ||
| 316 | } | ||
| 317 | } | ||
| 318 | |||
| 319 | NV_DEBUG(dev, "No devices found.\n"); | ||
| 320 | |||
| 321 | return -ENODEV; | ||
| 322 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.h b/drivers/gpu/drm/nouveau/nouveau_i2c.h index c8eaf7a9fcbb..6dd2f8713cd1 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 { | |||
| 45 | int nouveau_i2c_init(struct drm_device *, struct dcb_i2c_entry *, int index); | 45 | int nouveau_i2c_init(struct drm_device *, struct dcb_i2c_entry *, int index); |
| 46 | void nouveau_i2c_fini(struct drm_device *, struct dcb_i2c_entry *); | 46 | void nouveau_i2c_fini(struct drm_device *, struct dcb_i2c_entry *); |
| 47 | struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, int index); | 47 | struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, int index); |
| 48 | bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr); | ||
| 49 | int nouveau_i2c_identify(struct drm_device *dev, const char *what, | ||
| 50 | struct i2c_board_info *info, int index); | ||
| 48 | 51 | ||
| 49 | int nouveau_dp_i2c_aux_ch(struct i2c_adapter *, int mode, uint8_t write_byte, | 52 | int nouveau_dp_i2c_aux_ch(struct i2c_adapter *, int mode, uint8_t write_byte, |
| 50 | uint8_t *read_byte); | 53 | uint8_t *read_byte); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index c1fd42b0dad1..a9f36ab256b7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c | |||
| @@ -35,162 +35,6 @@ | |||
| 35 | #include "drm_sarea.h" | 35 | #include "drm_sarea.h" |
| 36 | #include "nouveau_drv.h" | 36 | #include "nouveau_drv.h" |
| 37 | 37 | ||
| 38 | static struct mem_block * | ||
| 39 | split_block(struct mem_block *p, uint64_t start, uint64_t size, | ||
| 40 | struct drm_file *file_priv) | ||
| 41 | { | ||
| 42 | /* Maybe cut off the start of an existing block */ | ||
| 43 | if (start > p->start) { | ||
| 44 | struct mem_block *newblock = | ||
| 45 | kmalloc(sizeof(*newblock), GFP_KERNEL); | ||
| 46 | if (!newblock) | ||
| 47 | goto out; | ||
| 48 | newblock->start = start; | ||
| 49 | newblock->size = p->size - (start - p->start); | ||
| 50 | newblock->file_priv = NULL; | ||
| 51 | newblock->next = p->next; | ||
| 52 | newblock->prev = p; | ||
| 53 | p->next->prev = newblock; | ||
| 54 | p->next = newblock; | ||
| 55 | p->size -= newblock->size; | ||
| 56 | p = newblock; | ||
| 57 | } | ||
| 58 | |||
| 59 | /* Maybe cut off the end of an existing block */ | ||
| 60 | if (size < p->size) { | ||
| 61 | struct mem_block *newblock = | ||
| 62 | kmalloc(sizeof(*newblock), GFP_KERNEL); | ||
| 63 | if (!newblock) | ||
| 64 | goto out; | ||
| 65 | newblock->start = start + size; | ||
| 66 | newblock->size = p->size - size; | ||
| 67 | newblock->file_priv = NULL; | ||
| 68 | newblock->next = p->next; | ||
| 69 | newblock->prev = p; | ||
| 70 | p->next->prev = newblock; | ||
| 71 | p->next = newblock; | ||
| 72 | p->size = size; | ||
| 73 | } | ||
| 74 | |||
| 75 | out: | ||
| 76 | /* Our block is in the middle */ | ||
| 77 | p->file_priv = file_priv; | ||
| 78 | return p; | ||
| 79 | } | ||
| 80 | |||
| 81 | struct mem_block * | ||
| 82 | nouveau_mem_alloc_block(struct mem_block *heap, uint64_t size, | ||
| 83 | int align2, struct drm_file *file_priv, int tail) | ||
| 84 | { | ||
| 85 | struct mem_block *p; | ||
| 86 | uint64_t mask = (1 << align2) - 1; | ||
| 87 | |||
| 88 | if (!heap) | ||
| 89 | return NULL; | ||
| 90 | |||
| 91 | if (tail) { | ||
| 92 | list_for_each_prev(p, heap) { | ||
| 93 | uint64_t start = ((p->start + p->size) - size) & ~mask; | ||
| 94 | |||
| 95 | if (p->file_priv == NULL && start >= p->start && | ||
| 96 | start + size <= p->start + p->size) | ||
| 97 | return split_block(p, start, size, file_priv); | ||
| 98 | } | ||
| 99 | } else { | ||
| 100 | list_for_each(p, heap) { | ||
| 101 | uint64_t start = (p->start + mask) & ~mask; | ||
| 102 | |||
| 103 | if (p->file_priv == NULL && | ||
| 104 | start + size <= p->start + p->size) | ||
| 105 | return split_block(p, start, size, file_priv); | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 109 | return NULL; | ||
| 110 | } | ||
| 111 | |||
| 112 | void nouveau_mem_free_block(struct mem_block *p) | ||
| 113 | { | ||
| 114 | p->file_priv = NULL; | ||
| 115 | |||
| 116 | /* Assumes a single contiguous range. Needs a special file_priv in | ||
| 117 | * 'heap' to stop it being subsumed. | ||
| 118 | */ | ||
| 119 | if (p->next->file_priv == NULL) { | ||
| 120 | struct mem_block *q = p->next; | ||
| 121 | p->size += q->size; | ||
| 122 | p->next = q->next; | ||
| 123 | p->next->prev = p; | ||
| 124 | kfree(q); | ||
| 125 | } | ||
| 126 | |||
| 127 | if (p->prev->file_priv == NULL) { | ||
| 128 | struct mem_block *q = p->prev; | ||
| 129 | q->size += p->size; | ||
| 130 | q->next = p->next; | ||
| 131 | q->next->prev = q; | ||
| 132 | kfree(p); | ||
| 133 | } | ||
| 134 | } | ||
| 135 | |||
| 136 | /* Initialize. How to check for an uninitialized heap? | ||
| 137 | */ | ||
| 138 | int nouveau_mem_init_heap(struct mem_block **heap, uint64_t start, | ||
| 139 | uint64_t size) | ||
| 140 | { | ||
| 141 | struct mem_block *blocks = kmalloc(sizeof(*blocks), GFP_KERNEL); | ||
| 142 | |||
| 143 | if (!blocks) | ||
| 144 | return -ENOMEM; | ||
| 145 | |||
| 146 | *heap = kmalloc(sizeof(**heap), GFP_KERNEL); | ||
| 147 | if (!*heap) { | ||
| 148 | kfree(blocks); | ||
| 149 | return -ENOMEM; | ||
| 150 | } | ||
| 151 | |||
| 152 | blocks->start = start; | ||
| 153 | blocks->size = size; | ||
| 154 | blocks->file_priv = NULL; | ||
| 155 | blocks->next = blocks->prev = *heap; | ||
| 156 | |||
| 157 | memset(*heap, 0, sizeof(**heap)); | ||
| 158 | (*heap)->file_priv = (struct drm_file *) -1; | ||
| 159 | (*heap)->next = (*heap)->prev = blocks; | ||
| 160 | return 0; | ||
| 161 | } | ||
| 162 | |||
| 163 | /* | ||
| 164 | * Free all blocks associated with the releasing file_priv | ||
| 165 | */ | ||
| 166 | void nouveau_mem_release(struct drm_file *file_priv, struct mem_block *heap) | ||
| 167 | { | ||
| 168 | struct mem_block *p; | ||
| 169 | |||
| 170 | if (!heap || !heap->next) | ||
| 171 | return; | ||
| 172 | |||
| 173 | list_for_each(p, heap) { | ||
| 174 | if (p->file_priv == file_priv) | ||
| 175 | p->file_priv = NULL; | ||
| 176 | } | ||
| 177 | |||
| 178 | /* Assumes a single contiguous range. Needs a special file_priv in | ||
| 179 | * 'heap' to stop it being subsumed. | ||
| 180 | */ | ||
| 181 | list_for_each(p, heap) { | ||
| 182 | while ((p->file_priv == NULL) && | ||
| 183 | (p->next->file_priv == NULL) && | ||
| 184 | (p->next != heap)) { | ||
| 185 | struct mem_block *q = p->next; | ||
| 186 | p->size += q->size; | ||
| 187 | p->next = q->next; | ||
| 188 | p->next->prev = p; | ||
| 189 | kfree(q); | ||
| 190 | } | ||
| 191 | } | ||
| 192 | } | ||
| 193 | |||
| 194 | /* | 38 | /* |
| 195 | * NV10-NV40 tiling helpers | 39 | * NV10-NV40 tiling helpers |
| 196 | */ | 40 | */ |
| @@ -299,7 +143,6 @@ nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size, | |||
| 299 | phys |= 0x30; | 143 | phys |= 0x30; |
| 300 | } | 144 | } |
| 301 | 145 | ||
| 302 | dev_priv->engine.instmem.prepare_access(dev, true); | ||
| 303 | while (size) { | 146 | while (size) { |
| 304 | unsigned offset_h = upper_32_bits(phys); | 147 | unsigned offset_h = upper_32_bits(phys); |
| 305 | unsigned offset_l = lower_32_bits(phys); | 148 | 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, | |||
| 331 | } | 174 | } |
| 332 | } | 175 | } |
| 333 | } | 176 | } |
| 334 | dev_priv->engine.instmem.finish_access(dev); | 177 | dev_priv->engine.instmem.flush(dev); |
| 335 | |||
| 336 | nv_wr32(dev, 0x100c80, 0x00050001); | ||
| 337 | if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { | ||
| 338 | NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); | ||
| 339 | NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); | ||
| 340 | return -EBUSY; | ||
| 341 | } | ||
| 342 | |||
| 343 | nv_wr32(dev, 0x100c80, 0x00000001); | ||
| 344 | if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { | ||
| 345 | NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); | ||
| 346 | NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); | ||
| 347 | return -EBUSY; | ||
| 348 | } | ||
| 349 | |||
| 350 | nv_wr32(dev, 0x100c80, 0x00040001); | ||
| 351 | if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { | ||
| 352 | NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); | ||
| 353 | NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); | ||
| 354 | return -EBUSY; | ||
| 355 | } | ||
| 356 | |||
| 357 | nv_wr32(dev, 0x100c80, 0x00060001); | ||
| 358 | if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { | ||
| 359 | NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); | ||
| 360 | NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); | ||
| 361 | return -EBUSY; | ||
| 362 | } | ||
| 363 | 178 | ||
| 179 | nv50_vm_flush(dev, 5); | ||
| 180 | nv50_vm_flush(dev, 0); | ||
| 181 | nv50_vm_flush(dev, 4); | ||
| 182 | nv50_vm_flush(dev, 6); | ||
| 364 | return 0; | 183 | return 0; |
| 365 | } | 184 | } |
| 366 | 185 | ||
| @@ -374,7 +193,6 @@ nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size) | |||
| 374 | virt -= dev_priv->vm_vram_base; | 193 | virt -= dev_priv->vm_vram_base; |
| 375 | pages = (size >> 16) << 1; | 194 | pages = (size >> 16) << 1; |
| 376 | 195 | ||
| 377 | dev_priv->engine.instmem.prepare_access(dev, true); | ||
| 378 | while (pages) { | 196 | while (pages) { |
| 379 | pgt = dev_priv->vm_vram_pt[virt >> 29]; | 197 | pgt = dev_priv->vm_vram_pt[virt >> 29]; |
| 380 | pte = (virt & 0x1ffe0000ULL) >> 15; | 198 | pte = (virt & 0x1ffe0000ULL) >> 15; |
| @@ -388,57 +206,19 @@ nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size) | |||
| 388 | while (pte < end) | 206 | while (pte < end) |
| 389 | nv_wo32(dev, pgt, pte++, 0); | 207 | nv_wo32(dev, pgt, pte++, 0); |
| 390 | } | 208 | } |
| 391 | dev_priv->engine.instmem.finish_access(dev); | 209 | dev_priv->engine.instmem.flush(dev); |
| 392 | |||
| 393 | nv_wr32(dev, 0x100c80, 0x00050001); | ||
| 394 | if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { | ||
| 395 | NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); | ||
| 396 | NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); | ||
| 397 | return; | ||
| 398 | } | ||
| 399 | |||
| 400 | nv_wr32(dev, 0x100c80, 0x00000001); | ||
| 401 | if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { | ||
| 402 | NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); | ||
| 403 | NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); | ||
| 404 | return; | ||
| 405 | } | ||
| 406 | |||
| 407 | nv_wr32(dev, 0x100c80, 0x00040001); | ||
| 408 | if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { | ||
| 409 | NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); | ||
| 410 | NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); | ||
| 411 | return; | ||
| 412 | } | ||
| 413 | 210 | ||
| 414 | nv_wr32(dev, 0x100c80, 0x00060001); | 211 | nv50_vm_flush(dev, 5); |
| 415 | if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { | 212 | nv50_vm_flush(dev, 0); |
| 416 | NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); | 213 | nv50_vm_flush(dev, 4); |
| 417 | NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); | 214 | nv50_vm_flush(dev, 6); |
| 418 | } | ||
| 419 | } | 215 | } |
| 420 | 216 | ||
| 421 | /* | 217 | /* |
| 422 | * Cleanup everything | 218 | * Cleanup everything |
| 423 | */ | 219 | */ |
| 424 | void nouveau_mem_takedown(struct mem_block **heap) | 220 | void |
| 425 | { | 221 | nouveau_mem_close(struct drm_device *dev) |
| 426 | struct mem_block *p; | ||
| 427 | |||
| 428 | if (!*heap) | ||
| 429 | return; | ||
| 430 | |||
| 431 | for (p = (*heap)->next; p != *heap;) { | ||
| 432 | struct mem_block *q = p; | ||
| 433 | p = p->next; | ||
| 434 | kfree(q); | ||
| 435 | } | ||
| 436 | |||
| 437 | kfree(*heap); | ||
| 438 | *heap = NULL; | ||
| 439 | } | ||
| 440 | |||
| 441 | void nouveau_mem_close(struct drm_device *dev) | ||
| 442 | { | 222 | { |
| 443 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 223 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 444 | 224 | ||
| @@ -449,8 +229,7 @@ void nouveau_mem_close(struct drm_device *dev) | |||
| 449 | 229 | ||
| 450 | nouveau_ttm_global_release(dev_priv); | 230 | nouveau_ttm_global_release(dev_priv); |
| 451 | 231 | ||
| 452 | if (drm_core_has_AGP(dev) && dev->agp && | 232 | if (drm_core_has_AGP(dev) && dev->agp) { |
| 453 | drm_core_check_feature(dev, DRIVER_MODESET)) { | ||
| 454 | struct drm_agp_mem *entry, *tempe; | 233 | struct drm_agp_mem *entry, *tempe; |
| 455 | 234 | ||
| 456 | /* Remove AGP resources, but leave dev->agp | 235 | /* Remove AGP resources, but leave dev->agp |
| @@ -471,28 +250,29 @@ void nouveau_mem_close(struct drm_device *dev) | |||
| 471 | } | 250 | } |
| 472 | 251 | ||
| 473 | if (dev_priv->fb_mtrr) { | 252 | if (dev_priv->fb_mtrr) { |
| 474 | drm_mtrr_del(dev_priv->fb_mtrr, drm_get_resource_start(dev, 1), | 253 | drm_mtrr_del(dev_priv->fb_mtrr, |
| 475 | drm_get_resource_len(dev, 1), DRM_MTRR_WC); | 254 | pci_resource_start(dev->pdev, 1), |
| 476 | dev_priv->fb_mtrr = 0; | 255 | pci_resource_len(dev->pdev, 1), DRM_MTRR_WC); |
| 256 | dev_priv->fb_mtrr = -1; | ||
| 477 | } | 257 | } |
| 478 | } | 258 | } |
| 479 | 259 | ||
| 480 | static uint32_t | 260 | static uint32_t |
| 481 | nouveau_mem_detect_nv04(struct drm_device *dev) | 261 | nouveau_mem_detect_nv04(struct drm_device *dev) |
| 482 | { | 262 | { |
| 483 | uint32_t boot0 = nv_rd32(dev, NV03_BOOT_0); | 263 | uint32_t boot0 = nv_rd32(dev, NV04_PFB_BOOT_0); |
| 484 | 264 | ||
| 485 | if (boot0 & 0x00000100) | 265 | if (boot0 & 0x00000100) |
| 486 | return (((boot0 >> 12) & 0xf) * 2 + 2) * 1024 * 1024; | 266 | return (((boot0 >> 12) & 0xf) * 2 + 2) * 1024 * 1024; |
| 487 | 267 | ||
| 488 | switch (boot0 & NV03_BOOT_0_RAM_AMOUNT) { | 268 | switch (boot0 & NV04_PFB_BOOT_0_RAM_AMOUNT) { |
| 489 | case NV04_BOOT_0_RAM_AMOUNT_32MB: | 269 | case NV04_PFB_BOOT_0_RAM_AMOUNT_32MB: |
| 490 | return 32 * 1024 * 1024; | 270 | return 32 * 1024 * 1024; |
| 491 | case NV04_BOOT_0_RAM_AMOUNT_16MB: | 271 | case NV04_PFB_BOOT_0_RAM_AMOUNT_16MB: |
| 492 | return 16 * 1024 * 1024; | 272 | return 16 * 1024 * 1024; |
| 493 | case NV04_BOOT_0_RAM_AMOUNT_8MB: | 273 | case NV04_PFB_BOOT_0_RAM_AMOUNT_8MB: |
| 494 | return 8 * 1024 * 1024; | 274 | return 8 * 1024 * 1024; |
| 495 | case NV04_BOOT_0_RAM_AMOUNT_4MB: | 275 | case NV04_PFB_BOOT_0_RAM_AMOUNT_4MB: |
| 496 | return 4 * 1024 * 1024; | 276 | return 4 * 1024 * 1024; |
| 497 | } | 277 | } |
| 498 | 278 | ||
| @@ -536,12 +316,18 @@ nouveau_mem_detect(struct drm_device *dev) | |||
| 536 | } else | 316 | } else |
| 537 | if (dev_priv->flags & (NV_NFORCE | NV_NFORCE2)) { | 317 | if (dev_priv->flags & (NV_NFORCE | NV_NFORCE2)) { |
| 538 | dev_priv->vram_size = nouveau_mem_detect_nforce(dev); | 318 | dev_priv->vram_size = nouveau_mem_detect_nforce(dev); |
| 319 | } else | ||
| 320 | if (dev_priv->card_type < NV_50) { | ||
| 321 | dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); | ||
| 322 | dev_priv->vram_size &= NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK; | ||
| 539 | } else { | 323 | } else { |
| 540 | dev_priv->vram_size = nv_rd32(dev, NV04_FIFO_DATA); | 324 | dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); |
| 541 | dev_priv->vram_size &= NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK; | 325 | dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32; |
| 542 | if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) | 326 | dev_priv->vram_size &= 0xffffffff00ll; |
| 327 | if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) { | ||
| 543 | dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10); | 328 | dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10); |
| 544 | dev_priv->vram_sys_base <<= 12; | 329 | dev_priv->vram_sys_base <<= 12; |
| 330 | } | ||
| 545 | } | 331 | } |
| 546 | 332 | ||
| 547 | NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20)); | 333 | NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20)); |
| @@ -555,18 +341,36 @@ nouveau_mem_detect(struct drm_device *dev) | |||
| 555 | return -ENOMEM; | 341 | return -ENOMEM; |
| 556 | } | 342 | } |
| 557 | 343 | ||
| 558 | #if __OS_HAS_AGP | 344 | int |
| 559 | static void nouveau_mem_reset_agp(struct drm_device *dev) | 345 | nouveau_mem_reset_agp(struct drm_device *dev) |
| 560 | { | 346 | { |
| 561 | uint32_t saved_pci_nv_1, saved_pci_nv_19, pmc_enable; | 347 | #if __OS_HAS_AGP |
| 348 | uint32_t saved_pci_nv_1, pmc_enable; | ||
| 349 | int ret; | ||
| 350 | |||
| 351 | /* First of all, disable fast writes, otherwise if it's | ||
| 352 | * already enabled in the AGP bridge and we disable the card's | ||
| 353 | * AGP controller we might be locking ourselves out of it. */ | ||
| 354 | if (dev->agp->acquired) { | ||
| 355 | struct drm_agp_info info; | ||
| 356 | struct drm_agp_mode mode; | ||
| 357 | |||
| 358 | ret = drm_agp_info(dev, &info); | ||
| 359 | if (ret) | ||
| 360 | return ret; | ||
| 361 | |||
| 362 | mode.mode = info.mode & ~0x10; | ||
| 363 | ret = drm_agp_enable(dev, mode); | ||
| 364 | if (ret) | ||
| 365 | return ret; | ||
| 366 | } | ||
| 562 | 367 | ||
| 563 | saved_pci_nv_1 = nv_rd32(dev, NV04_PBUS_PCI_NV_1); | 368 | saved_pci_nv_1 = nv_rd32(dev, NV04_PBUS_PCI_NV_1); |
| 564 | saved_pci_nv_19 = nv_rd32(dev, NV04_PBUS_PCI_NV_19); | ||
| 565 | 369 | ||
| 566 | /* clear busmaster bit */ | 370 | /* clear busmaster bit */ |
| 567 | nv_wr32(dev, NV04_PBUS_PCI_NV_1, saved_pci_nv_1 & ~0x4); | 371 | nv_wr32(dev, NV04_PBUS_PCI_NV_1, saved_pci_nv_1 & ~0x4); |
| 568 | /* clear SBA and AGP bits */ | 372 | /* disable AGP */ |
| 569 | nv_wr32(dev, NV04_PBUS_PCI_NV_19, saved_pci_nv_19 & 0xfffff0ff); | 373 | nv_wr32(dev, NV04_PBUS_PCI_NV_19, 0); |
| 570 | 374 | ||
| 571 | /* power cycle pgraph, if enabled */ | 375 | /* power cycle pgraph, if enabled */ |
| 572 | pmc_enable = nv_rd32(dev, NV03_PMC_ENABLE); | 376 | pmc_enable = nv_rd32(dev, NV03_PMC_ENABLE); |
| @@ -578,11 +382,12 @@ static void nouveau_mem_reset_agp(struct drm_device *dev) | |||
| 578 | } | 382 | } |
| 579 | 383 | ||
| 580 | /* and restore (gives effect of resetting AGP) */ | 384 | /* and restore (gives effect of resetting AGP) */ |
| 581 | nv_wr32(dev, NV04_PBUS_PCI_NV_19, saved_pci_nv_19); | ||
| 582 | nv_wr32(dev, NV04_PBUS_PCI_NV_1, saved_pci_nv_1); | 385 | nv_wr32(dev, NV04_PBUS_PCI_NV_1, saved_pci_nv_1); |
| 583 | } | ||
| 584 | #endif | 386 | #endif |
| 585 | 387 | ||
| 388 | return 0; | ||
| 389 | } | ||
| 390 | |||
| 586 | int | 391 | int |
| 587 | nouveau_mem_init_agp(struct drm_device *dev) | 392 | nouveau_mem_init_agp(struct drm_device *dev) |
| 588 | { | 393 | { |
| @@ -592,11 +397,6 @@ nouveau_mem_init_agp(struct drm_device *dev) | |||
| 592 | struct drm_agp_mode mode; | 397 | struct drm_agp_mode mode; |
| 593 | int ret; | 398 | int ret; |
| 594 | 399 | ||
| 595 | if (nouveau_noagp) | ||
| 596 | return 0; | ||
| 597 | |||
| 598 | nouveau_mem_reset_agp(dev); | ||
| 599 | |||
| 600 | if (!dev->agp->acquired) { | 400 | if (!dev->agp->acquired) { |
| 601 | ret = drm_agp_acquire(dev); | 401 | ret = drm_agp_acquire(dev); |
| 602 | if (ret) { | 402 | if (ret) { |
| @@ -633,7 +433,7 @@ nouveau_mem_init(struct drm_device *dev) | |||
| 633 | struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; | 433 | struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; |
| 634 | int ret, dma_bits = 32; | 434 | int ret, dma_bits = 32; |
| 635 | 435 | ||
| 636 | dev_priv->fb_phys = drm_get_resource_start(dev, 1); | 436 | dev_priv->fb_phys = pci_resource_start(dev->pdev, 1); |
| 637 | dev_priv->gart_info.type = NOUVEAU_GART_NONE; | 437 | dev_priv->gart_info.type = NOUVEAU_GART_NONE; |
| 638 | 438 | ||
| 639 | if (dev_priv->card_type >= NV_50 && | 439 | if (dev_priv->card_type >= NV_50 && |
| @@ -665,8 +465,9 @@ nouveau_mem_init(struct drm_device *dev) | |||
| 665 | 465 | ||
| 666 | dev_priv->fb_available_size = dev_priv->vram_size; | 466 | dev_priv->fb_available_size = dev_priv->vram_size; |
| 667 | dev_priv->fb_mappable_pages = dev_priv->fb_available_size; | 467 | dev_priv->fb_mappable_pages = dev_priv->fb_available_size; |
| 668 | if (dev_priv->fb_mappable_pages > drm_get_resource_len(dev, 1)) | 468 | if (dev_priv->fb_mappable_pages > pci_resource_len(dev->pdev, 1)) |
| 669 | dev_priv->fb_mappable_pages = drm_get_resource_len(dev, 1); | 469 | dev_priv->fb_mappable_pages = |
| 470 | pci_resource_len(dev->pdev, 1); | ||
| 670 | dev_priv->fb_mappable_pages >>= PAGE_SHIFT; | 471 | dev_priv->fb_mappable_pages >>= PAGE_SHIFT; |
| 671 | 472 | ||
| 672 | /* remove reserved space at end of vram from available amount */ | 473 | /* remove reserved space at end of vram from available amount */ |
| @@ -692,7 +493,8 @@ nouveau_mem_init(struct drm_device *dev) | |||
| 692 | 493 | ||
| 693 | /* GART */ | 494 | /* GART */ |
| 694 | #if !defined(__powerpc__) && !defined(__ia64__) | 495 | #if !defined(__powerpc__) && !defined(__ia64__) |
| 695 | if (drm_device_is_agp(dev) && dev->agp) { | 496 | if (drm_device_is_agp(dev) && dev->agp && !nouveau_noagp) { |
| 497 | nouveau_mem_reset_agp(dev); | ||
| 696 | ret = nouveau_mem_init_agp(dev); | 498 | ret = nouveau_mem_init_agp(dev); |
| 697 | if (ret) | 499 | if (ret) |
| 698 | NV_ERROR(dev, "Error initialising AGP: %d\n", ret); | 500 | NV_ERROR(dev, "Error initialising AGP: %d\n", ret); |
| @@ -718,8 +520,8 @@ nouveau_mem_init(struct drm_device *dev) | |||
| 718 | return ret; | 520 | return ret; |
| 719 | } | 521 | } |
| 720 | 522 | ||
| 721 | dev_priv->fb_mtrr = drm_mtrr_add(drm_get_resource_start(dev, 1), | 523 | dev_priv->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 1), |
| 722 | drm_get_resource_len(dev, 1), | 524 | pci_resource_len(dev->pdev, 1), |
| 723 | DRM_MTRR_WC); | 525 | DRM_MTRR_WC); |
| 724 | 526 | ||
| 725 | return 0; | 527 | return 0; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_notifier.c b/drivers/gpu/drm/nouveau/nouveau_notifier.c index 9537f3e30115..3ec181ff50ce 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) | |||
| 55 | if (ret) | 55 | if (ret) |
| 56 | goto out_err; | 56 | goto out_err; |
| 57 | 57 | ||
| 58 | ret = nouveau_mem_init_heap(&chan->notifier_heap, 0, ntfy->bo.mem.size); | 58 | ret = drm_mm_init(&chan->notifier_heap, 0, ntfy->bo.mem.size); |
| 59 | if (ret) | 59 | if (ret) |
| 60 | goto out_err; | 60 | goto out_err; |
| 61 | 61 | ||
| @@ -80,7 +80,7 @@ nouveau_notifier_takedown_channel(struct nouveau_channel *chan) | |||
| 80 | nouveau_bo_unpin(chan->notifier_bo); | 80 | nouveau_bo_unpin(chan->notifier_bo); |
| 81 | mutex_unlock(&dev->struct_mutex); | 81 | mutex_unlock(&dev->struct_mutex); |
| 82 | drm_gem_object_unreference_unlocked(chan->notifier_bo->gem); | 82 | drm_gem_object_unreference_unlocked(chan->notifier_bo->gem); |
| 83 | nouveau_mem_takedown(&chan->notifier_heap); | 83 | drm_mm_takedown(&chan->notifier_heap); |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | static void | 86 | static void |
| @@ -90,7 +90,7 @@ nouveau_notifier_gpuobj_dtor(struct drm_device *dev, | |||
| 90 | NV_DEBUG(dev, "\n"); | 90 | NV_DEBUG(dev, "\n"); |
| 91 | 91 | ||
| 92 | if (gpuobj->priv) | 92 | if (gpuobj->priv) |
| 93 | nouveau_mem_free_block(gpuobj->priv); | 93 | drm_mm_put_block(gpuobj->priv); |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | int | 96 | int |
| @@ -100,18 +100,13 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, | |||
| 100 | struct drm_device *dev = chan->dev; | 100 | struct drm_device *dev = chan->dev; |
| 101 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 101 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 102 | struct nouveau_gpuobj *nobj = NULL; | 102 | struct nouveau_gpuobj *nobj = NULL; |
| 103 | struct mem_block *mem; | 103 | struct drm_mm_node *mem; |
| 104 | uint32_t offset; | 104 | uint32_t offset; |
| 105 | int target, ret; | 105 | int target, ret; |
| 106 | 106 | ||
| 107 | if (!chan->notifier_heap) { | 107 | mem = drm_mm_search_free(&chan->notifier_heap, size, 0, 0); |
| 108 | NV_ERROR(dev, "Channel %d doesn't have a notifier heap!\n", | 108 | if (mem) |
| 109 | chan->id); | 109 | mem = drm_mm_get_block(mem, size, 0); |
| 110 | return -EINVAL; | ||
| 111 | } | ||
| 112 | |||
| 113 | mem = nouveau_mem_alloc_block(chan->notifier_heap, size, 0, | ||
| 114 | (struct drm_file *)-2, 0); | ||
| 115 | if (!mem) { | 110 | if (!mem) { |
| 116 | NV_ERROR(dev, "Channel %d notifier block full\n", chan->id); | 111 | NV_ERROR(dev, "Channel %d notifier block full\n", chan->id); |
| 117 | return -ENOMEM; | 112 | return -ENOMEM; |
| @@ -144,17 +139,17 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, | |||
| 144 | mem->size, NV_DMA_ACCESS_RW, target, | 139 | mem->size, NV_DMA_ACCESS_RW, target, |
| 145 | &nobj); | 140 | &nobj); |
| 146 | if (ret) { | 141 | if (ret) { |
| 147 | nouveau_mem_free_block(mem); | 142 | drm_mm_put_block(mem); |
| 148 | NV_ERROR(dev, "Error creating notifier ctxdma: %d\n", ret); | 143 | NV_ERROR(dev, "Error creating notifier ctxdma: %d\n", ret); |
| 149 | return ret; | 144 | return ret; |
| 150 | } | 145 | } |
| 151 | nobj->dtor = nouveau_notifier_gpuobj_dtor; | 146 | nobj->dtor = nouveau_notifier_gpuobj_dtor; |
| 152 | nobj->priv = mem; | 147 | nobj->priv = mem; |
| 153 | 148 | ||
| 154 | ret = nouveau_gpuobj_ref_add(dev, chan, handle, nobj, NULL); | 149 | ret = nouveau_gpuobj_ref_add(dev, chan, handle, nobj, NULL); |
| 155 | if (ret) { | 150 | if (ret) { |
| 156 | nouveau_gpuobj_del(dev, &nobj); | 151 | nouveau_gpuobj_del(dev, &nobj); |
| 157 | nouveau_mem_free_block(mem); | 152 | drm_mm_put_block(mem); |
| 158 | NV_ERROR(dev, "Error referencing notifier ctxdma: %d\n", ret); | 153 | NV_ERROR(dev, "Error referencing notifier ctxdma: %d\n", ret); |
| 159 | return ret; | 154 | return ret; |
| 160 | } | 155 | } |
| @@ -170,7 +165,7 @@ nouveau_notifier_offset(struct nouveau_gpuobj *nobj, uint32_t *poffset) | |||
| 170 | return -EINVAL; | 165 | return -EINVAL; |
| 171 | 166 | ||
| 172 | if (poffset) { | 167 | if (poffset) { |
| 173 | struct mem_block *mem = nobj->priv; | 168 | struct drm_mm_node *mem = nobj->priv; |
| 174 | 169 | ||
| 175 | if (*poffset >= mem->size) | 170 | if (*poffset >= mem->size) |
| 176 | return false; | 171 | return false; |
| @@ -189,7 +184,6 @@ nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data, | |||
| 189 | struct nouveau_channel *chan; | 184 | struct nouveau_channel *chan; |
| 190 | int ret; | 185 | int ret; |
| 191 | 186 | ||
| 192 | NOUVEAU_CHECK_INITIALISED_WITH_RETURN; | ||
| 193 | NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(na->channel, file_priv, chan); | 187 | NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(na->channel, file_priv, chan); |
| 194 | 188 | ||
| 195 | ret = nouveau_notifier_alloc(chan, na->handle, na->size, &na->offset); | 189 | 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 e7c100ba63a1..b6bcb254f4ab 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) | |||
| 132 | } | 132 | } |
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | instmem->prepare_access(dev, true); | ||
| 136 | co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle); | 135 | co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle); |
| 137 | do { | 136 | do { |
| 138 | if (!nouveau_ramht_entry_valid(dev, ramht, co)) { | 137 | if (!nouveau_ramht_entry_valid(dev, ramht, co)) { |
| @@ -143,7 +142,7 @@ nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) | |||
| 143 | nv_wo32(dev, ramht, (co + 4)/4, ctx); | 142 | nv_wo32(dev, ramht, (co + 4)/4, ctx); |
| 144 | 143 | ||
| 145 | list_add_tail(&ref->list, &chan->ramht_refs); | 144 | list_add_tail(&ref->list, &chan->ramht_refs); |
| 146 | instmem->finish_access(dev); | 145 | instmem->flush(dev); |
| 147 | return 0; | 146 | return 0; |
| 148 | } | 147 | } |
| 149 | NV_DEBUG(dev, "collision ch%d 0x%08x: h=0x%08x\n", | 148 | 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) | |||
| 153 | if (co >= dev_priv->ramht_size) | 152 | if (co >= dev_priv->ramht_size) |
| 154 | co = 0; | 153 | co = 0; |
| 155 | } while (co != ho); | 154 | } while (co != ho); |
| 156 | instmem->finish_access(dev); | ||
| 157 | 155 | ||
| 158 | NV_ERROR(dev, "RAMHT space exhausted. ch=%d\n", chan->id); | 156 | NV_ERROR(dev, "RAMHT space exhausted. ch=%d\n", chan->id); |
| 159 | return -ENOMEM; | 157 | return -ENOMEM; |
| @@ -173,7 +171,6 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) | |||
| 173 | return; | 171 | return; |
| 174 | } | 172 | } |
| 175 | 173 | ||
| 176 | instmem->prepare_access(dev, true); | ||
| 177 | co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle); | 174 | co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle); |
| 178 | do { | 175 | do { |
| 179 | if (nouveau_ramht_entry_valid(dev, ramht, co) && | 176 | if (nouveau_ramht_entry_valid(dev, ramht, co) && |
| @@ -186,7 +183,7 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) | |||
| 186 | nv_wo32(dev, ramht, (co + 4)/4, 0x00000000); | 183 | nv_wo32(dev, ramht, (co + 4)/4, 0x00000000); |
| 187 | 184 | ||
| 188 | list_del(&ref->list); | 185 | list_del(&ref->list); |
| 189 | instmem->finish_access(dev); | 186 | instmem->flush(dev); |
| 190 | return; | 187 | return; |
| 191 | } | 188 | } |
| 192 | 189 | ||
| @@ -195,7 +192,6 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) | |||
| 195 | co = 0; | 192 | co = 0; |
| 196 | } while (co != ho); | 193 | } while (co != ho); |
| 197 | list_del(&ref->list); | 194 | list_del(&ref->list); |
| 198 | instmem->finish_access(dev); | ||
| 199 | 195 | ||
| 200 | NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n", | 196 | NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n", |
| 201 | chan->id, ref->handle); | 197 | chan->id, ref->handle); |
| @@ -209,7 +205,7 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, | |||
| 209 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 205 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 210 | struct nouveau_engine *engine = &dev_priv->engine; | 206 | struct nouveau_engine *engine = &dev_priv->engine; |
| 211 | struct nouveau_gpuobj *gpuobj; | 207 | struct nouveau_gpuobj *gpuobj; |
| 212 | struct mem_block *pramin = NULL; | 208 | struct drm_mm *pramin = NULL; |
| 213 | int ret; | 209 | int ret; |
| 214 | 210 | ||
| 215 | NV_DEBUG(dev, "ch%d size=%u align=%d flags=0x%08x\n", | 211 | 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, | |||
| 233 | * available. | 229 | * available. |
| 234 | */ | 230 | */ |
| 235 | if (chan) { | 231 | if (chan) { |
| 236 | if (chan->ramin_heap) { | 232 | NV_DEBUG(dev, "channel heap\n"); |
| 237 | NV_DEBUG(dev, "private heap\n"); | 233 | pramin = &chan->ramin_heap; |
| 238 | pramin = chan->ramin_heap; | ||
| 239 | } else | ||
| 240 | if (dev_priv->card_type < NV_50) { | ||
| 241 | NV_DEBUG(dev, "global heap fallback\n"); | ||
| 242 | pramin = dev_priv->ramin_heap; | ||
| 243 | } | ||
| 244 | } else { | 234 | } else { |
| 245 | NV_DEBUG(dev, "global heap\n"); | 235 | NV_DEBUG(dev, "global heap\n"); |
| 246 | pramin = dev_priv->ramin_heap; | 236 | pramin = &dev_priv->ramin_heap; |
| 247 | } | ||
| 248 | |||
| 249 | if (!pramin) { | ||
| 250 | NV_ERROR(dev, "No PRAMIN heap!\n"); | ||
| 251 | return -EINVAL; | ||
| 252 | } | ||
| 253 | 237 | ||
| 254 | if (!chan) { | ||
| 255 | ret = engine->instmem.populate(dev, gpuobj, &size); | 238 | ret = engine->instmem.populate(dev, gpuobj, &size); |
| 256 | if (ret) { | 239 | if (ret) { |
| 257 | nouveau_gpuobj_del(dev, &gpuobj); | 240 | nouveau_gpuobj_del(dev, &gpuobj); |
| @@ -260,9 +243,10 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, | |||
| 260 | } | 243 | } |
| 261 | 244 | ||
| 262 | /* Allocate a chunk of the PRAMIN aperture */ | 245 | /* Allocate a chunk of the PRAMIN aperture */ |
| 263 | gpuobj->im_pramin = nouveau_mem_alloc_block(pramin, size, | 246 | gpuobj->im_pramin = drm_mm_search_free(pramin, size, align, 0); |
| 264 | drm_order(align), | 247 | if (gpuobj->im_pramin) |
| 265 | (struct drm_file *)-2, 0); | 248 | gpuobj->im_pramin = drm_mm_get_block(gpuobj->im_pramin, size, align); |
| 249 | |||
| 266 | if (!gpuobj->im_pramin) { | 250 | if (!gpuobj->im_pramin) { |
| 267 | nouveau_gpuobj_del(dev, &gpuobj); | 251 | nouveau_gpuobj_del(dev, &gpuobj); |
| 268 | return -ENOMEM; | 252 | return -ENOMEM; |
| @@ -279,10 +263,9 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, | |||
| 279 | if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) { | 263 | if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) { |
| 280 | int i; | 264 | int i; |
| 281 | 265 | ||
| 282 | engine->instmem.prepare_access(dev, true); | ||
| 283 | for (i = 0; i < gpuobj->im_pramin->size; i += 4) | 266 | for (i = 0; i < gpuobj->im_pramin->size; i += 4) |
| 284 | nv_wo32(dev, gpuobj, i/4, 0); | 267 | nv_wo32(dev, gpuobj, i/4, 0); |
| 285 | engine->instmem.finish_access(dev); | 268 | engine->instmem.flush(dev); |
| 286 | } | 269 | } |
| 287 | 270 | ||
| 288 | *gpuobj_ret = gpuobj; | 271 | *gpuobj_ret = gpuobj; |
| @@ -370,10 +353,9 @@ nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj) | |||
| 370 | } | 353 | } |
| 371 | 354 | ||
| 372 | if (gpuobj->im_pramin && (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE)) { | 355 | if (gpuobj->im_pramin && (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE)) { |
| 373 | engine->instmem.prepare_access(dev, true); | ||
| 374 | for (i = 0; i < gpuobj->im_pramin->size; i += 4) | 356 | for (i = 0; i < gpuobj->im_pramin->size; i += 4) |
| 375 | nv_wo32(dev, gpuobj, i/4, 0); | 357 | nv_wo32(dev, gpuobj, i/4, 0); |
| 376 | engine->instmem.finish_access(dev); | 358 | engine->instmem.flush(dev); |
| 377 | } | 359 | } |
| 378 | 360 | ||
| 379 | if (gpuobj->dtor) | 361 | if (gpuobj->dtor) |
| @@ -386,7 +368,7 @@ nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj) | |||
| 386 | if (gpuobj->flags & NVOBJ_FLAG_FAKE) | 368 | if (gpuobj->flags & NVOBJ_FLAG_FAKE) |
| 387 | kfree(gpuobj->im_pramin); | 369 | kfree(gpuobj->im_pramin); |
| 388 | else | 370 | else |
| 389 | nouveau_mem_free_block(gpuobj->im_pramin); | 371 | drm_mm_put_block(gpuobj->im_pramin); |
| 390 | } | 372 | } |
| 391 | 373 | ||
| 392 | list_del(&gpuobj->list); | 374 | list_del(&gpuobj->list); |
| @@ -589,7 +571,7 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t p_offset, | |||
| 589 | list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); | 571 | list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); |
| 590 | 572 | ||
| 591 | if (p_offset != ~0) { | 573 | if (p_offset != ~0) { |
| 592 | gpuobj->im_pramin = kzalloc(sizeof(struct mem_block), | 574 | gpuobj->im_pramin = kzalloc(sizeof(struct drm_mm_node), |
| 593 | GFP_KERNEL); | 575 | GFP_KERNEL); |
| 594 | if (!gpuobj->im_pramin) { | 576 | if (!gpuobj->im_pramin) { |
| 595 | nouveau_gpuobj_del(dev, &gpuobj); | 577 | nouveau_gpuobj_del(dev, &gpuobj); |
| @@ -605,10 +587,9 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t p_offset, | |||
| 605 | } | 587 | } |
| 606 | 588 | ||
| 607 | if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) { | 589 | if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) { |
| 608 | dev_priv->engine.instmem.prepare_access(dev, true); | ||
| 609 | for (i = 0; i < gpuobj->im_pramin->size; i += 4) | 590 | for (i = 0; i < gpuobj->im_pramin->size; i += 4) |
| 610 | nv_wo32(dev, gpuobj, i/4, 0); | 591 | nv_wo32(dev, gpuobj, i/4, 0); |
| 611 | dev_priv->engine.instmem.finish_access(dev); | 592 | dev_priv->engine.instmem.flush(dev); |
| 612 | } | 593 | } |
| 613 | 594 | ||
| 614 | if (pref) { | 595 | if (pref) { |
| @@ -696,8 +677,6 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, | |||
| 696 | return ret; | 677 | return ret; |
| 697 | } | 678 | } |
| 698 | 679 | ||
| 699 | instmem->prepare_access(dev, true); | ||
| 700 | |||
| 701 | if (dev_priv->card_type < NV_50) { | 680 | if (dev_priv->card_type < NV_50) { |
| 702 | uint32_t frame, adjust, pte_flags = 0; | 681 | uint32_t frame, adjust, pte_flags = 0; |
| 703 | 682 | ||
| @@ -734,7 +713,7 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, | |||
| 734 | nv_wo32(dev, *gpuobj, 5, flags5); | 713 | nv_wo32(dev, *gpuobj, 5, flags5); |
| 735 | } | 714 | } |
| 736 | 715 | ||
| 737 | instmem->finish_access(dev); | 716 | instmem->flush(dev); |
| 738 | 717 | ||
| 739 | (*gpuobj)->engine = NVOBJ_ENGINE_SW; | 718 | (*gpuobj)->engine = NVOBJ_ENGINE_SW; |
| 740 | (*gpuobj)->class = class; | 719 | (*gpuobj)->class = class; |
| @@ -849,7 +828,6 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class, | |||
| 849 | return ret; | 828 | return ret; |
| 850 | } | 829 | } |
| 851 | 830 | ||
| 852 | dev_priv->engine.instmem.prepare_access(dev, true); | ||
| 853 | if (dev_priv->card_type >= NV_50) { | 831 | if (dev_priv->card_type >= NV_50) { |
| 854 | nv_wo32(dev, *gpuobj, 0, class); | 832 | nv_wo32(dev, *gpuobj, 0, class); |
| 855 | nv_wo32(dev, *gpuobj, 5, 0x00010000); | 833 | nv_wo32(dev, *gpuobj, 5, 0x00010000); |
| @@ -874,7 +852,7 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class, | |||
| 874 | } | 852 | } |
| 875 | } | 853 | } |
| 876 | } | 854 | } |
| 877 | dev_priv->engine.instmem.finish_access(dev); | 855 | dev_priv->engine.instmem.flush(dev); |
| 878 | 856 | ||
| 879 | (*gpuobj)->engine = NVOBJ_ENGINE_GR; | 857 | (*gpuobj)->engine = NVOBJ_ENGINE_GR; |
| 880 | (*gpuobj)->class = class; | 858 | (*gpuobj)->class = class; |
| @@ -920,6 +898,7 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan) | |||
| 920 | base = 0; | 898 | base = 0; |
| 921 | 899 | ||
| 922 | /* PGRAPH context */ | 900 | /* PGRAPH context */ |
| 901 | size += dev_priv->engine.graph.grctx_size; | ||
| 923 | 902 | ||
| 924 | if (dev_priv->card_type == NV_50) { | 903 | if (dev_priv->card_type == NV_50) { |
| 925 | /* Various fixed table thingos */ | 904 | /* Various fixed table thingos */ |
| @@ -930,12 +909,8 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan) | |||
| 930 | size += 0x8000; | 909 | size += 0x8000; |
| 931 | /* RAMFC */ | 910 | /* RAMFC */ |
| 932 | size += 0x1000; | 911 | size += 0x1000; |
| 933 | /* PGRAPH context */ | ||
| 934 | size += 0x70000; | ||
| 935 | } | 912 | } |
| 936 | 913 | ||
| 937 | NV_DEBUG(dev, "ch%d PRAMIN size: 0x%08x bytes, base alloc=0x%08x\n", | ||
| 938 | chan->id, size, base); | ||
| 939 | ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, size, 0x1000, 0, | 914 | ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, size, 0x1000, 0, |
| 940 | &chan->ramin); | 915 | &chan->ramin); |
| 941 | if (ret) { | 916 | if (ret) { |
| @@ -944,8 +919,7 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan) | |||
| 944 | } | 919 | } |
| 945 | pramin = chan->ramin->gpuobj; | 920 | pramin = chan->ramin->gpuobj; |
| 946 | 921 | ||
| 947 | ret = nouveau_mem_init_heap(&chan->ramin_heap, | 922 | ret = drm_mm_init(&chan->ramin_heap, pramin->im_pramin->start + base, size); |
| 948 | pramin->im_pramin->start + base, size); | ||
| 949 | if (ret) { | 923 | if (ret) { |
| 950 | NV_ERROR(dev, "Error creating PRAMIN heap: %d\n", ret); | 924 | NV_ERROR(dev, "Error creating PRAMIN heap: %d\n", ret); |
| 951 | nouveau_gpuobj_ref_del(dev, &chan->ramin); | 925 | nouveau_gpuobj_ref_del(dev, &chan->ramin); |
| @@ -969,15 +943,11 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, | |||
| 969 | 943 | ||
| 970 | NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); | 944 | NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); |
| 971 | 945 | ||
| 972 | /* Reserve a block of PRAMIN for the channel | 946 | /* Allocate a chunk of memory for per-channel object storage */ |
| 973 | *XXX: maybe on <NV50 too at some point | 947 | ret = nouveau_gpuobj_channel_init_pramin(chan); |
| 974 | */ | 948 | if (ret) { |
| 975 | if (0 || dev_priv->card_type == NV_50) { | 949 | NV_ERROR(dev, "init pramin\n"); |
| 976 | ret = nouveau_gpuobj_channel_init_pramin(chan); | 950 | return ret; |
| 977 | if (ret) { | ||
| 978 | NV_ERROR(dev, "init pramin\n"); | ||
| 979 | return ret; | ||
| 980 | } | ||
| 981 | } | 951 | } |
| 982 | 952 | ||
| 983 | /* NV50 VM | 953 | /* NV50 VM |
| @@ -988,17 +958,13 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, | |||
| 988 | if (dev_priv->card_type >= NV_50) { | 958 | if (dev_priv->card_type >= NV_50) { |
| 989 | uint32_t vm_offset, pde; | 959 | uint32_t vm_offset, pde; |
| 990 | 960 | ||
| 991 | instmem->prepare_access(dev, true); | ||
| 992 | |||
| 993 | vm_offset = (dev_priv->chipset & 0xf0) == 0x50 ? 0x1400 : 0x200; | 961 | vm_offset = (dev_priv->chipset & 0xf0) == 0x50 ? 0x1400 : 0x200; |
| 994 | vm_offset += chan->ramin->gpuobj->im_pramin->start; | 962 | vm_offset += chan->ramin->gpuobj->im_pramin->start; |
| 995 | 963 | ||
| 996 | ret = nouveau_gpuobj_new_fake(dev, vm_offset, ~0, 0x4000, | 964 | ret = nouveau_gpuobj_new_fake(dev, vm_offset, ~0, 0x4000, |
| 997 | 0, &chan->vm_pd, NULL); | 965 | 0, &chan->vm_pd, NULL); |
| 998 | if (ret) { | 966 | if (ret) |
| 999 | instmem->finish_access(dev); | ||
| 1000 | return ret; | 967 | return ret; |
| 1001 | } | ||
| 1002 | for (i = 0; i < 0x4000; i += 8) { | 968 | for (i = 0; i < 0x4000; i += 8) { |
| 1003 | nv_wo32(dev, chan->vm_pd, (i+0)/4, 0x00000000); | 969 | nv_wo32(dev, chan->vm_pd, (i+0)/4, 0x00000000); |
| 1004 | nv_wo32(dev, chan->vm_pd, (i+4)/4, 0xdeadcafe); | 970 | nv_wo32(dev, chan->vm_pd, (i+4)/4, 0xdeadcafe); |
| @@ -1008,10 +974,8 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, | |||
| 1008 | ret = nouveau_gpuobj_ref_add(dev, NULL, 0, | 974 | ret = nouveau_gpuobj_ref_add(dev, NULL, 0, |
| 1009 | dev_priv->gart_info.sg_ctxdma, | 975 | dev_priv->gart_info.sg_ctxdma, |
| 1010 | &chan->vm_gart_pt); | 976 | &chan->vm_gart_pt); |
| 1011 | if (ret) { | 977 | if (ret) |
| 1012 | instmem->finish_access(dev); | ||
| 1013 | return ret; | 978 | return ret; |
| 1014 | } | ||
| 1015 | nv_wo32(dev, chan->vm_pd, pde++, | 979 | nv_wo32(dev, chan->vm_pd, pde++, |
| 1016 | chan->vm_gart_pt->instance | 0x03); | 980 | chan->vm_gart_pt->instance | 0x03); |
| 1017 | nv_wo32(dev, chan->vm_pd, pde++, 0x00000000); | 981 | nv_wo32(dev, chan->vm_pd, pde++, 0x00000000); |
| @@ -1021,17 +985,15 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, | |||
| 1021 | ret = nouveau_gpuobj_ref_add(dev, NULL, 0, | 985 | ret = nouveau_gpuobj_ref_add(dev, NULL, 0, |
| 1022 | dev_priv->vm_vram_pt[i], | 986 | dev_priv->vm_vram_pt[i], |
| 1023 | &chan->vm_vram_pt[i]); | 987 | &chan->vm_vram_pt[i]); |
| 1024 | if (ret) { | 988 | if (ret) |
| 1025 | instmem->finish_access(dev); | ||
| 1026 | return ret; | 989 | return ret; |
| 1027 | } | ||
| 1028 | 990 | ||
| 1029 | nv_wo32(dev, chan->vm_pd, pde++, | 991 | nv_wo32(dev, chan->vm_pd, pde++, |
| 1030 | chan->vm_vram_pt[i]->instance | 0x61); | 992 | chan->vm_vram_pt[i]->instance | 0x61); |
| 1031 | nv_wo32(dev, chan->vm_pd, pde++, 0x00000000); | 993 | nv_wo32(dev, chan->vm_pd, pde++, 0x00000000); |
| 1032 | } | 994 | } |
| 1033 | 995 | ||
| 1034 | instmem->finish_access(dev); | 996 | instmem->flush(dev); |
| 1035 | } | 997 | } |
| 1036 | 998 | ||
| 1037 | /* RAMHT */ | 999 | /* RAMHT */ |
| @@ -1130,8 +1092,8 @@ nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan) | |||
| 1130 | for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) | 1092 | for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) |
| 1131 | nouveau_gpuobj_ref_del(dev, &chan->vm_vram_pt[i]); | 1093 | nouveau_gpuobj_ref_del(dev, &chan->vm_vram_pt[i]); |
| 1132 | 1094 | ||
| 1133 | if (chan->ramin_heap) | 1095 | if (chan->ramin_heap.free_stack.next) |
| 1134 | nouveau_mem_takedown(&chan->ramin_heap); | 1096 | drm_mm_takedown(&chan->ramin_heap); |
| 1135 | if (chan->ramin) | 1097 | if (chan->ramin) |
| 1136 | nouveau_gpuobj_ref_del(dev, &chan->ramin); | 1098 | nouveau_gpuobj_ref_del(dev, &chan->ramin); |
| 1137 | 1099 | ||
| @@ -1164,10 +1126,8 @@ nouveau_gpuobj_suspend(struct drm_device *dev) | |||
| 1164 | return -ENOMEM; | 1126 | return -ENOMEM; |
| 1165 | } | 1127 | } |
| 1166 | 1128 | ||
| 1167 | dev_priv->engine.instmem.prepare_access(dev, false); | ||
| 1168 | for (i = 0; i < gpuobj->im_pramin->size / 4; i++) | 1129 | for (i = 0; i < gpuobj->im_pramin->size / 4; i++) |
| 1169 | gpuobj->im_backing_suspend[i] = nv_ro32(dev, gpuobj, i); | 1130 | gpuobj->im_backing_suspend[i] = nv_ro32(dev, gpuobj, i); |
| 1170 | dev_priv->engine.instmem.finish_access(dev); | ||
| 1171 | } | 1131 | } |
| 1172 | 1132 | ||
| 1173 | return 0; | 1133 | return 0; |
| @@ -1212,10 +1172,9 @@ nouveau_gpuobj_resume(struct drm_device *dev) | |||
| 1212 | if (!gpuobj->im_backing_suspend) | 1172 | if (!gpuobj->im_backing_suspend) |
| 1213 | continue; | 1173 | continue; |
| 1214 | 1174 | ||
| 1215 | dev_priv->engine.instmem.prepare_access(dev, true); | ||
| 1216 | for (i = 0; i < gpuobj->im_pramin->size / 4; i++) | 1175 | for (i = 0; i < gpuobj->im_pramin->size / 4; i++) |
| 1217 | nv_wo32(dev, gpuobj, i, gpuobj->im_backing_suspend[i]); | 1176 | nv_wo32(dev, gpuobj, i, gpuobj->im_backing_suspend[i]); |
| 1218 | dev_priv->engine.instmem.finish_access(dev); | 1177 | dev_priv->engine.instmem.flush(dev); |
| 1219 | } | 1178 | } |
| 1220 | 1179 | ||
| 1221 | nouveau_gpuobj_suspend_cleanup(dev); | 1180 | nouveau_gpuobj_suspend_cleanup(dev); |
| @@ -1232,7 +1191,6 @@ int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data, | |||
| 1232 | struct nouveau_channel *chan; | 1191 | struct nouveau_channel *chan; |
| 1233 | int ret; | 1192 | int ret; |
| 1234 | 1193 | ||
| 1235 | NOUVEAU_CHECK_INITIALISED_WITH_RETURN; | ||
| 1236 | NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(init->channel, file_priv, chan); | 1194 | NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(init->channel, file_priv, chan); |
| 1237 | 1195 | ||
| 1238 | if (init->handle == ~0) | 1196 | if (init->handle == ~0) |
| @@ -1283,7 +1241,6 @@ int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data, | |||
| 1283 | struct nouveau_channel *chan; | 1241 | struct nouveau_channel *chan; |
| 1284 | int ret; | 1242 | int ret; |
| 1285 | 1243 | ||
| 1286 | NOUVEAU_CHECK_INITIALISED_WITH_RETURN; | ||
| 1287 | NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(objfree->channel, file_priv, chan); | 1244 | NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(objfree->channel, file_priv, chan); |
| 1288 | 1245 | ||
| 1289 | ret = nouveau_gpuobj_ref_find(chan, objfree->handle, &ref); | 1246 | 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 6ca80a3fe70d..9c1056cb8a90 100644 --- a/drivers/gpu/drm/nouveau/nouveau_reg.h +++ b/drivers/gpu/drm/nouveau/nouveau_reg.h | |||
| @@ -1,19 +1,64 @@ | |||
| 1 | 1 | ||
| 2 | #define NV04_PFB_BOOT_0 0x00100000 | ||
| 3 | # define NV04_PFB_BOOT_0_RAM_AMOUNT 0x00000003 | ||
| 4 | # define NV04_PFB_BOOT_0_RAM_AMOUNT_32MB 0x00000000 | ||
| 5 | # define NV04_PFB_BOOT_0_RAM_AMOUNT_4MB 0x00000001 | ||
| 6 | # define NV04_PFB_BOOT_0_RAM_AMOUNT_8MB 0x00000002 | ||
| 7 | # define NV04_PFB_BOOT_0_RAM_AMOUNT_16MB 0x00000003 | ||
| 8 | # define NV04_PFB_BOOT_0_RAM_WIDTH_128 0x00000004 | ||
| 9 | # define NV04_PFB_BOOT_0_RAM_TYPE 0x00000028 | ||
| 10 | # define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_8MBIT 0x00000000 | ||
| 11 | # define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT 0x00000008 | ||
| 12 | # define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT_4BANK 0x00000010 | ||
| 13 | # define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_16MBIT 0x00000018 | ||
| 14 | # define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_64MBIT 0x00000020 | ||
| 15 | # define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_64MBITX16 0x00000028 | ||
| 16 | # define NV04_PFB_BOOT_0_UMA_ENABLE 0x00000100 | ||
| 17 | # define NV04_PFB_BOOT_0_UMA_SIZE 0x0000f000 | ||
| 18 | #define NV04_PFB_DEBUG_0 0x00100080 | ||
| 19 | # define NV04_PFB_DEBUG_0_PAGE_MODE 0x00000001 | ||
| 20 | # define NV04_PFB_DEBUG_0_REFRESH_OFF 0x00000010 | ||
| 21 | # define NV04_PFB_DEBUG_0_REFRESH_COUNTX64 0x00003f00 | ||
| 22 | # define NV04_PFB_DEBUG_0_REFRESH_SLOW_CLK 0x00004000 | ||
| 23 | # define NV04_PFB_DEBUG_0_SAFE_MODE 0x00008000 | ||
| 24 | # define NV04_PFB_DEBUG_0_ALOM_ENABLE 0x00010000 | ||
| 25 | # define NV04_PFB_DEBUG_0_CASOE 0x00100000 | ||
| 26 | # define NV04_PFB_DEBUG_0_CKE_INVERT 0x10000000 | ||
| 27 | # define NV04_PFB_DEBUG_0_REFINC 0x20000000 | ||
| 28 | # define NV04_PFB_DEBUG_0_SAVE_POWER_OFF 0x40000000 | ||
| 29 | #define NV04_PFB_CFG0 0x00100200 | ||
| 30 | # define NV04_PFB_CFG0_SCRAMBLE 0x20000000 | ||
| 31 | #define NV04_PFB_CFG1 0x00100204 | ||
| 32 | #define NV04_PFB_FIFO_DATA 0x0010020c | ||
| 33 | # define NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK 0xfff00000 | ||
| 34 | # define NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_SHIFT 20 | ||
| 35 | #define NV10_PFB_REFCTRL 0x00100210 | ||
| 36 | # define NV10_PFB_REFCTRL_VALID_1 (1 << 31) | ||
| 37 | #define NV04_PFB_PAD 0x0010021c | ||
| 38 | # define NV04_PFB_PAD_CKE_NORMAL (1 << 0) | ||
| 39 | #define NV10_PFB_TILE(i) (0x00100240 + (i*16)) | ||
| 40 | #define NV10_PFB_TILE__SIZE 8 | ||
| 41 | #define NV10_PFB_TLIMIT(i) (0x00100244 + (i*16)) | ||
| 42 | #define NV10_PFB_TSIZE(i) (0x00100248 + (i*16)) | ||
| 43 | #define NV10_PFB_TSTATUS(i) (0x0010024c + (i*16)) | ||
| 44 | #define NV04_PFB_REF 0x001002d0 | ||
| 45 | # define NV04_PFB_REF_CMD_REFRESH (1 << 0) | ||
| 46 | #define NV04_PFB_PRE 0x001002d4 | ||
| 47 | # define NV04_PFB_PRE_CMD_PRECHARGE (1 << 0) | ||
| 48 | #define NV10_PFB_CLOSE_PAGE2 0x0010033c | ||
| 49 | #define NV04_PFB_SCRAMBLE(i) (0x00100400 + 4 * (i)) | ||
| 50 | #define NV40_PFB_TILE(i) (0x00100600 + (i*16)) | ||
| 51 | #define NV40_PFB_TILE__SIZE_0 12 | ||
| 52 | #define NV40_PFB_TILE__SIZE_1 15 | ||
| 53 | #define NV40_PFB_TLIMIT(i) (0x00100604 + (i*16)) | ||
| 54 | #define NV40_PFB_TSIZE(i) (0x00100608 + (i*16)) | ||
| 55 | #define NV40_PFB_TSTATUS(i) (0x0010060c + (i*16)) | ||
| 56 | #define NV40_PFB_UNK_800 0x00100800 | ||
| 2 | 57 | ||
| 3 | #define NV03_BOOT_0 0x00100000 | 58 | #define NV_PEXTDEV_BOOT_0 0x00101000 |
| 4 | # define NV03_BOOT_0_RAM_AMOUNT 0x00000003 | 59 | #define NV_PEXTDEV_BOOT_0_RAMCFG 0x0000003c |
| 5 | # define NV03_BOOT_0_RAM_AMOUNT_8MB 0x00000000 | 60 | # define NV_PEXTDEV_BOOT_0_STRAP_FP_IFACE_12BIT (8 << 12) |
| 6 | # define NV03_BOOT_0_RAM_AMOUNT_2MB 0x00000001 | 61 | #define NV_PEXTDEV_BOOT_3 0x0010100c |
| 7 | # define NV03_BOOT_0_RAM_AMOUNT_4MB 0x00000002 | ||
| 8 | # define NV03_BOOT_0_RAM_AMOUNT_8MB_SDRAM 0x00000003 | ||
| 9 | # define NV04_BOOT_0_RAM_AMOUNT_32MB 0x00000000 | ||
| 10 | # define NV04_BOOT_0_RAM_AMOUNT_4MB 0x00000001 | ||
| 11 | # define NV04_BOOT_0_RAM_AMOUNT_8MB 0x00000002 | ||
| 12 | # define NV04_BOOT_0_RAM_AMOUNT_16MB 0x00000003 | ||
| 13 | |||
| 14 | #define NV04_FIFO_DATA 0x0010020c | ||
| 15 | # define NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK 0xfff00000 | ||
| 16 | # define NV10_FIFO_DATA_RAM_AMOUNT_MB_SHIFT 20 | ||
| 17 | 62 | ||
| 18 | #define NV_RAMIN 0x00700000 | 63 | #define NV_RAMIN 0x00700000 |
| 19 | 64 | ||
| @@ -131,23 +176,6 @@ | |||
| 131 | #define NV04_PTIMER_TIME_1 0x00009410 | 176 | #define NV04_PTIMER_TIME_1 0x00009410 |
| 132 | #define NV04_PTIMER_ALARM_0 0x00009420 | 177 | #define NV04_PTIMER_ALARM_0 0x00009420 |
| 133 | 178 | ||
| 134 | #define NV04_PFB_CFG0 0x00100200 | ||
| 135 | #define NV04_PFB_CFG1 0x00100204 | ||
| 136 | #define NV40_PFB_020C 0x0010020C | ||
| 137 | #define NV10_PFB_TILE(i) (0x00100240 + (i*16)) | ||
| 138 | #define NV10_PFB_TILE__SIZE 8 | ||
| 139 | #define NV10_PFB_TLIMIT(i) (0x00100244 + (i*16)) | ||
| 140 | #define NV10_PFB_TSIZE(i) (0x00100248 + (i*16)) | ||
| 141 | #define NV10_PFB_TSTATUS(i) (0x0010024C + (i*16)) | ||
| 142 | #define NV10_PFB_CLOSE_PAGE2 0x0010033C | ||
| 143 | #define NV40_PFB_TILE(i) (0x00100600 + (i*16)) | ||
| 144 | #define NV40_PFB_TILE__SIZE_0 12 | ||
| 145 | #define NV40_PFB_TILE__SIZE_1 15 | ||
| 146 | #define NV40_PFB_TLIMIT(i) (0x00100604 + (i*16)) | ||
| 147 | #define NV40_PFB_TSIZE(i) (0x00100608 + (i*16)) | ||
| 148 | #define NV40_PFB_TSTATUS(i) (0x0010060C + (i*16)) | ||
| 149 | #define NV40_PFB_UNK_800 0x00100800 | ||
| 150 | |||
| 151 | #define NV04_PGRAPH_DEBUG_0 0x00400080 | 179 | #define NV04_PGRAPH_DEBUG_0 0x00400080 |
| 152 | #define NV04_PGRAPH_DEBUG_1 0x00400084 | 180 | #define NV04_PGRAPH_DEBUG_1 0x00400084 |
| 153 | #define NV04_PGRAPH_DEBUG_2 0x00400088 | 181 | #define NV04_PGRAPH_DEBUG_2 0x00400088 |
| @@ -814,6 +842,7 @@ | |||
| 814 | #define NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE 0x80000000 | 842 | #define NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE 0x80000000 |
| 815 | #define NV50_PDISPLAY_SOR_BACKLIGHT_LEVEL 0x00000fff | 843 | #define NV50_PDISPLAY_SOR_BACKLIGHT_LEVEL 0x00000fff |
| 816 | #define NV50_SOR_DP_CTRL(i,l) (0x0061c10c + (i) * 0x800 + (l) * 0x80) | 844 | #define NV50_SOR_DP_CTRL(i,l) (0x0061c10c + (i) * 0x800 + (l) * 0x80) |
| 845 | #define NV50_SOR_DP_CTRL_ENABLED 0x00000001 | ||
| 817 | #define NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED 0x00004000 | 846 | #define NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED 0x00004000 |
| 818 | #define NV50_SOR_DP_CTRL_LANE_MASK 0x001f0000 | 847 | #define NV50_SOR_DP_CTRL_LANE_MASK 0x001f0000 |
| 819 | #define NV50_SOR_DP_CTRL_LANE_0_ENABLED 0x00010000 | 848 | #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 1d6ee8b55154..491767fe4fcf 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) | |||
| 97 | 97 | ||
| 98 | NV_DEBUG(dev, "pg=0x%lx\n", mem->mm_node->start); | 98 | NV_DEBUG(dev, "pg=0x%lx\n", mem->mm_node->start); |
| 99 | 99 | ||
| 100 | dev_priv->engine.instmem.prepare_access(nvbe->dev, true); | ||
| 101 | pte = nouveau_sgdma_pte(nvbe->dev, mem->mm_node->start << PAGE_SHIFT); | 100 | pte = nouveau_sgdma_pte(nvbe->dev, mem->mm_node->start << PAGE_SHIFT); |
| 102 | nvbe->pte_start = pte; | 101 | nvbe->pte_start = pte; |
| 103 | for (i = 0; i < nvbe->nr_pages; i++) { | 102 | for (i = 0; i < nvbe->nr_pages; i++) { |
| @@ -116,24 +115,11 @@ nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) | |||
| 116 | dma_offset += NV_CTXDMA_PAGE_SIZE; | 115 | dma_offset += NV_CTXDMA_PAGE_SIZE; |
| 117 | } | 116 | } |
| 118 | } | 117 | } |
| 119 | dev_priv->engine.instmem.finish_access(nvbe->dev); | 118 | dev_priv->engine.instmem.flush(nvbe->dev); |
| 120 | 119 | ||
| 121 | if (dev_priv->card_type == NV_50) { | 120 | if (dev_priv->card_type == NV_50) { |
| 122 | nv_wr32(dev, 0x100c80, 0x00050001); | 121 | nv50_vm_flush(dev, 5); /* PGRAPH */ |
| 123 | if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { | 122 | nv50_vm_flush(dev, 0); /* PFIFO */ |
| 124 | NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); | ||
| 125 | NV_ERROR(dev, "0x100c80 = 0x%08x\n", | ||
| 126 | nv_rd32(dev, 0x100c80)); | ||
| 127 | return -EBUSY; | ||
| 128 | } | ||
| 129 | |||
| 130 | nv_wr32(dev, 0x100c80, 0x00000001); | ||
| 131 | if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { | ||
| 132 | NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); | ||
| 133 | NV_ERROR(dev, "0x100c80 = 0x%08x\n", | ||
| 134 | nv_rd32(dev, 0x100c80)); | ||
| 135 | return -EBUSY; | ||
| 136 | } | ||
| 137 | } | 123 | } |
| 138 | 124 | ||
| 139 | nvbe->bound = true; | 125 | nvbe->bound = true; |
| @@ -154,7 +140,6 @@ nouveau_sgdma_unbind(struct ttm_backend *be) | |||
| 154 | if (!nvbe->bound) | 140 | if (!nvbe->bound) |
| 155 | return 0; | 141 | return 0; |
| 156 | 142 | ||
| 157 | dev_priv->engine.instmem.prepare_access(nvbe->dev, true); | ||
| 158 | pte = nvbe->pte_start; | 143 | pte = nvbe->pte_start; |
| 159 | for (i = 0; i < nvbe->nr_pages; i++) { | 144 | for (i = 0; i < nvbe->nr_pages; i++) { |
| 160 | dma_addr_t dma_offset = dev_priv->gart_info.sg_dummy_bus; | 145 | dma_addr_t dma_offset = dev_priv->gart_info.sg_dummy_bus; |
| @@ -170,24 +155,11 @@ nouveau_sgdma_unbind(struct ttm_backend *be) | |||
| 170 | dma_offset += NV_CTXDMA_PAGE_SIZE; | 155 | dma_offset += NV_CTXDMA_PAGE_SIZE; |
| 171 | } | 156 | } |
| 172 | } | 157 | } |
| 173 | dev_priv->engine.instmem.finish_access(nvbe->dev); | 158 | dev_priv->engine.instmem.flush(nvbe->dev); |
| 174 | 159 | ||
| 175 | if (dev_priv->card_type == NV_50) { | 160 | if (dev_priv->card_type == NV_50) { |
| 176 | nv_wr32(dev, 0x100c80, 0x00050001); | 161 | nv50_vm_flush(dev, 5); |
| 177 | if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { | 162 | nv50_vm_flush(dev, 0); |
| 178 | NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); | ||
| 179 | NV_ERROR(dev, "0x100c80 = 0x%08x\n", | ||
| 180 | nv_rd32(dev, 0x100c80)); | ||
| 181 | return -EBUSY; | ||
| 182 | } | ||
| 183 | |||
| 184 | nv_wr32(dev, 0x100c80, 0x00000001); | ||
| 185 | if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { | ||
| 186 | NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); | ||
| 187 | NV_ERROR(dev, "0x100c80 = 0x%08x\n", | ||
| 188 | nv_rd32(dev, 0x100c80)); | ||
| 189 | return -EBUSY; | ||
| 190 | } | ||
| 191 | } | 163 | } |
| 192 | 164 | ||
| 193 | nvbe->bound = false; | 165 | nvbe->bound = false; |
| @@ -272,7 +244,6 @@ nouveau_sgdma_init(struct drm_device *dev) | |||
| 272 | pci_map_page(dev->pdev, dev_priv->gart_info.sg_dummy_page, 0, | 244 | pci_map_page(dev->pdev, dev_priv->gart_info.sg_dummy_page, 0, |
| 273 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | 245 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); |
| 274 | 246 | ||
| 275 | dev_priv->engine.instmem.prepare_access(dev, true); | ||
| 276 | if (dev_priv->card_type < NV_50) { | 247 | if (dev_priv->card_type < NV_50) { |
| 277 | /* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and | 248 | /* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and |
| 278 | * confirmed to work on c51. Perhaps means NV_DMA_TARGET_PCIE | 249 | * confirmed to work on c51. Perhaps means NV_DMA_TARGET_PCIE |
| @@ -294,7 +265,7 @@ nouveau_sgdma_init(struct drm_device *dev) | |||
| 294 | nv_wo32(dev, gpuobj, (i+4)/4, 0); | 265 | nv_wo32(dev, gpuobj, (i+4)/4, 0); |
| 295 | } | 266 | } |
| 296 | } | 267 | } |
| 297 | dev_priv->engine.instmem.finish_access(dev); | 268 | dev_priv->engine.instmem.flush(dev); |
| 298 | 269 | ||
| 299 | dev_priv->gart_info.type = NOUVEAU_GART_SGDMA; | 270 | dev_priv->gart_info.type = NOUVEAU_GART_SGDMA; |
| 300 | dev_priv->gart_info.aper_base = 0; | 271 | 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) | |||
| 325 | { | 296 | { |
| 326 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 297 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 327 | struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; | 298 | struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; |
| 328 | struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; | ||
| 329 | int pte; | 299 | int pte; |
| 330 | 300 | ||
| 331 | pte = (offset >> NV_CTXDMA_PAGE_SHIFT); | 301 | pte = (offset >> NV_CTXDMA_PAGE_SHIFT); |
| 332 | if (dev_priv->card_type < NV_50) { | 302 | if (dev_priv->card_type < NV_50) { |
| 333 | instmem->prepare_access(dev, false); | ||
| 334 | *page = nv_ro32(dev, gpuobj, (pte + 2)) & ~NV_CTXDMA_PAGE_MASK; | 303 | *page = nv_ro32(dev, gpuobj, (pte + 2)) & ~NV_CTXDMA_PAGE_MASK; |
| 335 | instmem->finish_access(dev); | ||
| 336 | return 0; | 304 | return 0; |
| 337 | } | 305 | } |
| 338 | 306 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index b02a231d6937..ee3729e7823b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include "nv50_display.h" | 38 | #include "nv50_display.h" |
| 39 | 39 | ||
| 40 | static void nouveau_stub_takedown(struct drm_device *dev) {} | 40 | static void nouveau_stub_takedown(struct drm_device *dev) {} |
| 41 | static int nouveau_stub_init(struct drm_device *dev) { return 0; } | ||
| 41 | 42 | ||
| 42 | static int nouveau_init_engine_ptrs(struct drm_device *dev) | 43 | static int nouveau_init_engine_ptrs(struct drm_device *dev) |
| 43 | { | 44 | { |
| @@ -54,8 +55,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
| 54 | engine->instmem.clear = nv04_instmem_clear; | 55 | engine->instmem.clear = nv04_instmem_clear; |
| 55 | engine->instmem.bind = nv04_instmem_bind; | 56 | engine->instmem.bind = nv04_instmem_bind; |
| 56 | engine->instmem.unbind = nv04_instmem_unbind; | 57 | engine->instmem.unbind = nv04_instmem_unbind; |
| 57 | engine->instmem.prepare_access = nv04_instmem_prepare_access; | 58 | engine->instmem.flush = nv04_instmem_flush; |
| 58 | engine->instmem.finish_access = nv04_instmem_finish_access; | ||
| 59 | engine->mc.init = nv04_mc_init; | 59 | engine->mc.init = nv04_mc_init; |
| 60 | engine->mc.takedown = nv04_mc_takedown; | 60 | engine->mc.takedown = nv04_mc_takedown; |
| 61 | engine->timer.init = nv04_timer_init; | 61 | engine->timer.init = nv04_timer_init; |
| @@ -85,6 +85,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
| 85 | engine->fifo.destroy_context = nv04_fifo_destroy_context; | 85 | engine->fifo.destroy_context = nv04_fifo_destroy_context; |
| 86 | engine->fifo.load_context = nv04_fifo_load_context; | 86 | engine->fifo.load_context = nv04_fifo_load_context; |
| 87 | engine->fifo.unload_context = nv04_fifo_unload_context; | 87 | engine->fifo.unload_context = nv04_fifo_unload_context; |
| 88 | engine->display.early_init = nv04_display_early_init; | ||
| 89 | engine->display.late_takedown = nv04_display_late_takedown; | ||
| 90 | engine->display.create = nv04_display_create; | ||
| 91 | engine->display.init = nv04_display_init; | ||
| 92 | engine->display.destroy = nv04_display_destroy; | ||
| 93 | engine->gpio.init = nouveau_stub_init; | ||
| 94 | engine->gpio.takedown = nouveau_stub_takedown; | ||
| 95 | engine->gpio.get = NULL; | ||
| 96 | engine->gpio.set = NULL; | ||
| 97 | engine->gpio.irq_enable = NULL; | ||
| 88 | break; | 98 | break; |
| 89 | case 0x10: | 99 | case 0x10: |
| 90 | engine->instmem.init = nv04_instmem_init; | 100 | engine->instmem.init = nv04_instmem_init; |
| @@ -95,8 +105,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
| 95 | engine->instmem.clear = nv04_instmem_clear; | 105 | engine->instmem.clear = nv04_instmem_clear; |
| 96 | engine->instmem.bind = nv04_instmem_bind; | 106 | engine->instmem.bind = nv04_instmem_bind; |
| 97 | engine->instmem.unbind = nv04_instmem_unbind; | 107 | engine->instmem.unbind = nv04_instmem_unbind; |
| 98 | engine->instmem.prepare_access = nv04_instmem_prepare_access; | 108 | engine->instmem.flush = nv04_instmem_flush; |
| 99 | engine->instmem.finish_access = nv04_instmem_finish_access; | ||
| 100 | engine->mc.init = nv04_mc_init; | 109 | engine->mc.init = nv04_mc_init; |
| 101 | engine->mc.takedown = nv04_mc_takedown; | 110 | engine->mc.takedown = nv04_mc_takedown; |
| 102 | engine->timer.init = nv04_timer_init; | 111 | engine->timer.init = nv04_timer_init; |
| @@ -128,6 +137,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
| 128 | engine->fifo.destroy_context = nv10_fifo_destroy_context; | 137 | engine->fifo.destroy_context = nv10_fifo_destroy_context; |
| 129 | engine->fifo.load_context = nv10_fifo_load_context; | 138 | engine->fifo.load_context = nv10_fifo_load_context; |
| 130 | engine->fifo.unload_context = nv10_fifo_unload_context; | 139 | engine->fifo.unload_context = nv10_fifo_unload_context; |
| 140 | engine->display.early_init = nv04_display_early_init; | ||
| 141 | engine->display.late_takedown = nv04_display_late_takedown; | ||
| 142 | engine->display.create = nv04_display_create; | ||
| 143 | engine->display.init = nv04_display_init; | ||
| 144 | engine->display.destroy = nv04_display_destroy; | ||
| 145 | engine->gpio.init = nouveau_stub_init; | ||
| 146 | engine->gpio.takedown = nouveau_stub_takedown; | ||
| 147 | engine->gpio.get = nv10_gpio_get; | ||
| 148 | engine->gpio.set = nv10_gpio_set; | ||
| 149 | engine->gpio.irq_enable = NULL; | ||
| 131 | break; | 150 | break; |
| 132 | case 0x20: | 151 | case 0x20: |
| 133 | engine->instmem.init = nv04_instmem_init; | 152 | engine->instmem.init = nv04_instmem_init; |
| @@ -138,8 +157,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
| 138 | engine->instmem.clear = nv04_instmem_clear; | 157 | engine->instmem.clear = nv04_instmem_clear; |
| 139 | engine->instmem.bind = nv04_instmem_bind; | 158 | engine->instmem.bind = nv04_instmem_bind; |
| 140 | engine->instmem.unbind = nv04_instmem_unbind; | 159 | engine->instmem.unbind = nv04_instmem_unbind; |
| 141 | engine->instmem.prepare_access = nv04_instmem_prepare_access; | 160 | engine->instmem.flush = nv04_instmem_flush; |
| 142 | engine->instmem.finish_access = nv04_instmem_finish_access; | ||
| 143 | engine->mc.init = nv04_mc_init; | 161 | engine->mc.init = nv04_mc_init; |
| 144 | engine->mc.takedown = nv04_mc_takedown; | 162 | engine->mc.takedown = nv04_mc_takedown; |
| 145 | engine->timer.init = nv04_timer_init; | 163 | engine->timer.init = nv04_timer_init; |
| @@ -171,6 +189,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
| 171 | engine->fifo.destroy_context = nv10_fifo_destroy_context; | 189 | engine->fifo.destroy_context = nv10_fifo_destroy_context; |
| 172 | engine->fifo.load_context = nv10_fifo_load_context; | 190 | engine->fifo.load_context = nv10_fifo_load_context; |
| 173 | engine->fifo.unload_context = nv10_fifo_unload_context; | 191 | engine->fifo.unload_context = nv10_fifo_unload_context; |
| 192 | engine->display.early_init = nv04_display_early_init; | ||
| 193 | engine->display.late_takedown = nv04_display_late_takedown; | ||
| 194 | engine->display.create = nv04_display_create; | ||
| 195 | engine->display.init = nv04_display_init; | ||
| 196 | engine->display.destroy = nv04_display_destroy; | ||
| 197 | engine->gpio.init = nouveau_stub_init; | ||
| 198 | engine->gpio.takedown = nouveau_stub_takedown; | ||
| 199 | engine->gpio.get = nv10_gpio_get; | ||
| 200 | engine->gpio.set = nv10_gpio_set; | ||
| 201 | engine->gpio.irq_enable = NULL; | ||
| 174 | break; | 202 | break; |
| 175 | case 0x30: | 203 | case 0x30: |
| 176 | engine->instmem.init = nv04_instmem_init; | 204 | engine->instmem.init = nv04_instmem_init; |
| @@ -181,15 +209,14 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
| 181 | engine->instmem.clear = nv04_instmem_clear; | 209 | engine->instmem.clear = nv04_instmem_clear; |
| 182 | engine->instmem.bind = nv04_instmem_bind; | 210 | engine->instmem.bind = nv04_instmem_bind; |
| 183 | engine->instmem.unbind = nv04_instmem_unbind; | 211 | engine->instmem.unbind = nv04_instmem_unbind; |
| 184 | engine->instmem.prepare_access = nv04_instmem_prepare_access; | 212 | engine->instmem.flush = nv04_instmem_flush; |
| 185 | engine->instmem.finish_access = nv04_instmem_finish_access; | ||
| 186 | engine->mc.init = nv04_mc_init; | 213 | engine->mc.init = nv04_mc_init; |
| 187 | engine->mc.takedown = nv04_mc_takedown; | 214 | engine->mc.takedown = nv04_mc_takedown; |
| 188 | engine->timer.init = nv04_timer_init; | 215 | engine->timer.init = nv04_timer_init; |
| 189 | engine->timer.read = nv04_timer_read; | 216 | engine->timer.read = nv04_timer_read; |
| 190 | engine->timer.takedown = nv04_timer_takedown; | 217 | engine->timer.takedown = nv04_timer_takedown; |
| 191 | engine->fb.init = nv10_fb_init; | 218 | engine->fb.init = nv30_fb_init; |
| 192 | engine->fb.takedown = nv10_fb_takedown; | 219 | engine->fb.takedown = nv30_fb_takedown; |
| 193 | engine->fb.set_region_tiling = nv10_fb_set_region_tiling; | 220 | engine->fb.set_region_tiling = nv10_fb_set_region_tiling; |
| 194 | engine->graph.grclass = nv30_graph_grclass; | 221 | engine->graph.grclass = nv30_graph_grclass; |
| 195 | engine->graph.init = nv30_graph_init; | 222 | engine->graph.init = nv30_graph_init; |
| @@ -214,6 +241,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
| 214 | engine->fifo.destroy_context = nv10_fifo_destroy_context; | 241 | engine->fifo.destroy_context = nv10_fifo_destroy_context; |
| 215 | engine->fifo.load_context = nv10_fifo_load_context; | 242 | engine->fifo.load_context = nv10_fifo_load_context; |
| 216 | engine->fifo.unload_context = nv10_fifo_unload_context; | 243 | engine->fifo.unload_context = nv10_fifo_unload_context; |
| 244 | engine->display.early_init = nv04_display_early_init; | ||
| 245 | engine->display.late_takedown = nv04_display_late_takedown; | ||
| 246 | engine->display.create = nv04_display_create; | ||
| 247 | engine->display.init = nv04_display_init; | ||
| 248 | engine->display.destroy = nv04_display_destroy; | ||
| 249 | engine->gpio.init = nouveau_stub_init; | ||
| 250 | engine->gpio.takedown = nouveau_stub_takedown; | ||
| 251 | engine->gpio.get = nv10_gpio_get; | ||
| 252 | engine->gpio.set = nv10_gpio_set; | ||
| 253 | engine->gpio.irq_enable = NULL; | ||
| 217 | break; | 254 | break; |
| 218 | case 0x40: | 255 | case 0x40: |
| 219 | case 0x60: | 256 | case 0x60: |
| @@ -225,8 +262,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
| 225 | engine->instmem.clear = nv04_instmem_clear; | 262 | engine->instmem.clear = nv04_instmem_clear; |
| 226 | engine->instmem.bind = nv04_instmem_bind; | 263 | engine->instmem.bind = nv04_instmem_bind; |
| 227 | engine->instmem.unbind = nv04_instmem_unbind; | 264 | engine->instmem.unbind = nv04_instmem_unbind; |
| 228 | engine->instmem.prepare_access = nv04_instmem_prepare_access; | 265 | engine->instmem.flush = nv04_instmem_flush; |
| 229 | engine->instmem.finish_access = nv04_instmem_finish_access; | ||
| 230 | engine->mc.init = nv40_mc_init; | 266 | engine->mc.init = nv40_mc_init; |
| 231 | engine->mc.takedown = nv40_mc_takedown; | 267 | engine->mc.takedown = nv40_mc_takedown; |
| 232 | engine->timer.init = nv04_timer_init; | 268 | engine->timer.init = nv04_timer_init; |
| @@ -258,6 +294,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
| 258 | engine->fifo.destroy_context = nv40_fifo_destroy_context; | 294 | engine->fifo.destroy_context = nv40_fifo_destroy_context; |
| 259 | engine->fifo.load_context = nv40_fifo_load_context; | 295 | engine->fifo.load_context = nv40_fifo_load_context; |
| 260 | engine->fifo.unload_context = nv40_fifo_unload_context; | 296 | engine->fifo.unload_context = nv40_fifo_unload_context; |
| 297 | engine->display.early_init = nv04_display_early_init; | ||
| 298 | engine->display.late_takedown = nv04_display_late_takedown; | ||
| 299 | engine->display.create = nv04_display_create; | ||
| 300 | engine->display.init = nv04_display_init; | ||
| 301 | engine->display.destroy = nv04_display_destroy; | ||
| 302 | engine->gpio.init = nouveau_stub_init; | ||
| 303 | engine->gpio.takedown = nouveau_stub_takedown; | ||
| 304 | engine->gpio.get = nv10_gpio_get; | ||
| 305 | engine->gpio.set = nv10_gpio_set; | ||
| 306 | engine->gpio.irq_enable = NULL; | ||
| 261 | break; | 307 | break; |
| 262 | case 0x50: | 308 | case 0x50: |
| 263 | case 0x80: /* gotta love NVIDIA's consistency.. */ | 309 | case 0x80: /* gotta love NVIDIA's consistency.. */ |
| @@ -271,8 +317,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
| 271 | engine->instmem.clear = nv50_instmem_clear; | 317 | engine->instmem.clear = nv50_instmem_clear; |
| 272 | engine->instmem.bind = nv50_instmem_bind; | 318 | engine->instmem.bind = nv50_instmem_bind; |
| 273 | engine->instmem.unbind = nv50_instmem_unbind; | 319 | engine->instmem.unbind = nv50_instmem_unbind; |
| 274 | engine->instmem.prepare_access = nv50_instmem_prepare_access; | 320 | if (dev_priv->chipset == 0x50) |
| 275 | engine->instmem.finish_access = nv50_instmem_finish_access; | 321 | engine->instmem.flush = nv50_instmem_flush; |
| 322 | else | ||
| 323 | engine->instmem.flush = nv84_instmem_flush; | ||
| 276 | engine->mc.init = nv50_mc_init; | 324 | engine->mc.init = nv50_mc_init; |
| 277 | engine->mc.takedown = nv50_mc_takedown; | 325 | engine->mc.takedown = nv50_mc_takedown; |
| 278 | engine->timer.init = nv04_timer_init; | 326 | engine->timer.init = nv04_timer_init; |
| @@ -300,6 +348,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
| 300 | engine->fifo.destroy_context = nv50_fifo_destroy_context; | 348 | engine->fifo.destroy_context = nv50_fifo_destroy_context; |
| 301 | engine->fifo.load_context = nv50_fifo_load_context; | 349 | engine->fifo.load_context = nv50_fifo_load_context; |
| 302 | engine->fifo.unload_context = nv50_fifo_unload_context; | 350 | engine->fifo.unload_context = nv50_fifo_unload_context; |
| 351 | engine->display.early_init = nv50_display_early_init; | ||
| 352 | engine->display.late_takedown = nv50_display_late_takedown; | ||
| 353 | engine->display.create = nv50_display_create; | ||
| 354 | engine->display.init = nv50_display_init; | ||
| 355 | engine->display.destroy = nv50_display_destroy; | ||
| 356 | engine->gpio.init = nv50_gpio_init; | ||
| 357 | engine->gpio.takedown = nouveau_stub_takedown; | ||
| 358 | engine->gpio.get = nv50_gpio_get; | ||
| 359 | engine->gpio.set = nv50_gpio_set; | ||
| 360 | engine->gpio.irq_enable = nv50_gpio_irq_enable; | ||
| 303 | break; | 361 | break; |
| 304 | default: | 362 | default: |
| 305 | NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); | 363 | NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); |
| @@ -407,11 +465,6 @@ nouveau_card_init(struct drm_device *dev) | |||
| 407 | struct nouveau_engine *engine; | 465 | struct nouveau_engine *engine; |
| 408 | int ret; | 466 | int ret; |
| 409 | 467 | ||
| 410 | NV_DEBUG(dev, "prev state = %d\n", dev_priv->init_state); | ||
| 411 | |||
| 412 | if (dev_priv->init_state == NOUVEAU_CARD_INIT_DONE) | ||
| 413 | return 0; | ||
| 414 | |||
| 415 | vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode); | 468 | vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode); |
| 416 | vga_switcheroo_register_client(dev->pdev, nouveau_switcheroo_set_state, | 469 | vga_switcheroo_register_client(dev->pdev, nouveau_switcheroo_set_state, |
| 417 | nouveau_switcheroo_can_switch); | 470 | nouveau_switcheroo_can_switch); |
| @@ -421,15 +474,17 @@ nouveau_card_init(struct drm_device *dev) | |||
| 421 | if (ret) | 474 | if (ret) |
| 422 | goto out; | 475 | goto out; |
| 423 | engine = &dev_priv->engine; | 476 | engine = &dev_priv->engine; |
| 424 | dev_priv->init_state = NOUVEAU_CARD_INIT_FAILED; | ||
| 425 | spin_lock_init(&dev_priv->context_switch_lock); | 477 | spin_lock_init(&dev_priv->context_switch_lock); |
| 426 | 478 | ||
| 479 | /* Make the CRTCs and I2C buses accessible */ | ||
| 480 | ret = engine->display.early_init(dev); | ||
| 481 | if (ret) | ||
| 482 | goto out; | ||
| 483 | |||
| 427 | /* Parse BIOS tables / Run init tables if card not POSTed */ | 484 | /* Parse BIOS tables / Run init tables if card not POSTed */ |
| 428 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 485 | ret = nouveau_bios_init(dev); |
| 429 | ret = nouveau_bios_init(dev); | 486 | if (ret) |
| 430 | if (ret) | 487 | goto out_display_early; |
| 431 | goto out; | ||
| 432 | } | ||
| 433 | 488 | ||
| 434 | ret = nouveau_mem_detect(dev); | 489 | ret = nouveau_mem_detect(dev); |
| 435 | if (ret) | 490 | if (ret) |
| @@ -461,10 +516,15 @@ nouveau_card_init(struct drm_device *dev) | |||
| 461 | if (ret) | 516 | if (ret) |
| 462 | goto out_gpuobj; | 517 | goto out_gpuobj; |
| 463 | 518 | ||
| 519 | /* PGPIO */ | ||
| 520 | ret = engine->gpio.init(dev); | ||
| 521 | if (ret) | ||
| 522 | goto out_mc; | ||
| 523 | |||
| 464 | /* PTIMER */ | 524 | /* PTIMER */ |
| 465 | ret = engine->timer.init(dev); | 525 | ret = engine->timer.init(dev); |
| 466 | if (ret) | 526 | if (ret) |
| 467 | goto out_mc; | 527 | goto out_gpio; |
| 468 | 528 | ||
| 469 | /* PFB */ | 529 | /* PFB */ |
| 470 | ret = engine->fb.init(dev); | 530 | ret = engine->fb.init(dev); |
| @@ -485,12 +545,16 @@ nouveau_card_init(struct drm_device *dev) | |||
| 485 | goto out_graph; | 545 | goto out_graph; |
| 486 | } | 546 | } |
| 487 | 547 | ||
| 548 | ret = engine->display.create(dev); | ||
| 549 | if (ret) | ||
| 550 | goto out_fifo; | ||
| 551 | |||
| 488 | /* this call irq_preinstall, register irq handler and | 552 | /* this call irq_preinstall, register irq handler and |
| 489 | * call irq_postinstall | 553 | * call irq_postinstall |
| 490 | */ | 554 | */ |
| 491 | ret = drm_irq_install(dev); | 555 | ret = drm_irq_install(dev); |
| 492 | if (ret) | 556 | if (ret) |
| 493 | goto out_fifo; | 557 | goto out_display; |
| 494 | 558 | ||
| 495 | ret = drm_vblank_init(dev, 0); | 559 | ret = drm_vblank_init(dev, 0); |
| 496 | if (ret) | 560 | if (ret) |
| @@ -504,35 +568,18 @@ nouveau_card_init(struct drm_device *dev) | |||
| 504 | goto out_irq; | 568 | goto out_irq; |
| 505 | } | 569 | } |
| 506 | 570 | ||
| 507 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | ||
| 508 | if (dev_priv->card_type >= NV_50) | ||
| 509 | ret = nv50_display_create(dev); | ||
| 510 | else | ||
| 511 | ret = nv04_display_create(dev); | ||
| 512 | if (ret) | ||
| 513 | goto out_channel; | ||
| 514 | } | ||
| 515 | |||
| 516 | ret = nouveau_backlight_init(dev); | 571 | ret = nouveau_backlight_init(dev); |
| 517 | if (ret) | 572 | if (ret) |
| 518 | NV_ERROR(dev, "Error %d registering backlight\n", ret); | 573 | NV_ERROR(dev, "Error %d registering backlight\n", ret); |
| 519 | 574 | ||
| 520 | dev_priv->init_state = NOUVEAU_CARD_INIT_DONE; | 575 | nouveau_fbcon_init(dev); |
| 521 | 576 | drm_kms_helper_poll_init(dev); | |
| 522 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | ||
| 523 | nouveau_fbcon_init(dev); | ||
| 524 | drm_kms_helper_poll_init(dev); | ||
| 525 | } | ||
| 526 | |||
| 527 | return 0; | 577 | return 0; |
| 528 | 578 | ||
| 529 | out_channel: | ||
| 530 | if (dev_priv->channel) { | ||
| 531 | nouveau_channel_free(dev_priv->channel); | ||
| 532 | dev_priv->channel = NULL; | ||
| 533 | } | ||
| 534 | out_irq: | 579 | out_irq: |
| 535 | drm_irq_uninstall(dev); | 580 | drm_irq_uninstall(dev); |
| 581 | out_display: | ||
| 582 | engine->display.destroy(dev); | ||
| 536 | out_fifo: | 583 | out_fifo: |
| 537 | if (!nouveau_noaccel) | 584 | if (!nouveau_noaccel) |
| 538 | engine->fifo.takedown(dev); | 585 | engine->fifo.takedown(dev); |
| @@ -543,6 +590,8 @@ out_fb: | |||
| 543 | engine->fb.takedown(dev); | 590 | engine->fb.takedown(dev); |
| 544 | out_timer: | 591 | out_timer: |
| 545 | engine->timer.takedown(dev); | 592 | engine->timer.takedown(dev); |
| 593 | out_gpio: | ||
| 594 | engine->gpio.takedown(dev); | ||
| 546 | out_mc: | 595 | out_mc: |
| 547 | engine->mc.takedown(dev); | 596 | engine->mc.takedown(dev); |
| 548 | out_gpuobj: | 597 | out_gpuobj: |
| @@ -556,6 +605,8 @@ out_gpuobj_early: | |||
| 556 | nouveau_gpuobj_late_takedown(dev); | 605 | nouveau_gpuobj_late_takedown(dev); |
| 557 | out_bios: | 606 | out_bios: |
| 558 | nouveau_bios_takedown(dev); | 607 | nouveau_bios_takedown(dev); |
| 608 | out_display_early: | ||
| 609 | engine->display.late_takedown(dev); | ||
| 559 | out: | 610 | out: |
| 560 | vga_client_register(dev->pdev, NULL, NULL, NULL); | 611 | vga_client_register(dev->pdev, NULL, NULL, NULL); |
| 561 | return ret; | 612 | return ret; |
| @@ -566,45 +617,39 @@ static void nouveau_card_takedown(struct drm_device *dev) | |||
| 566 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 617 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 567 | struct nouveau_engine *engine = &dev_priv->engine; | 618 | struct nouveau_engine *engine = &dev_priv->engine; |
| 568 | 619 | ||
| 569 | NV_DEBUG(dev, "prev state = %d\n", dev_priv->init_state); | 620 | nouveau_backlight_exit(dev); |
| 570 | |||
| 571 | if (dev_priv->init_state != NOUVEAU_CARD_INIT_DOWN) { | ||
| 572 | |||
| 573 | nouveau_backlight_exit(dev); | ||
| 574 | |||
| 575 | if (dev_priv->channel) { | ||
| 576 | nouveau_channel_free(dev_priv->channel); | ||
| 577 | dev_priv->channel = NULL; | ||
| 578 | } | ||
| 579 | 621 | ||
| 580 | if (!nouveau_noaccel) { | 622 | if (dev_priv->channel) { |
| 581 | engine->fifo.takedown(dev); | 623 | nouveau_channel_free(dev_priv->channel); |
| 582 | engine->graph.takedown(dev); | 624 | dev_priv->channel = NULL; |
| 583 | } | 625 | } |
| 584 | engine->fb.takedown(dev); | ||
| 585 | engine->timer.takedown(dev); | ||
| 586 | engine->mc.takedown(dev); | ||
| 587 | 626 | ||
| 588 | mutex_lock(&dev->struct_mutex); | 627 | if (!nouveau_noaccel) { |
| 589 | ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM); | 628 | engine->fifo.takedown(dev); |
| 590 | ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT); | 629 | engine->graph.takedown(dev); |
| 591 | mutex_unlock(&dev->struct_mutex); | 630 | } |
| 592 | nouveau_sgdma_takedown(dev); | 631 | engine->fb.takedown(dev); |
| 632 | engine->timer.takedown(dev); | ||
| 633 | engine->gpio.takedown(dev); | ||
| 634 | engine->mc.takedown(dev); | ||
| 635 | engine->display.late_takedown(dev); | ||
| 593 | 636 | ||
| 594 | nouveau_gpuobj_takedown(dev); | 637 | mutex_lock(&dev->struct_mutex); |
| 595 | nouveau_mem_close(dev); | 638 | ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM); |
| 596 | engine->instmem.takedown(dev); | 639 | ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT); |
| 640 | mutex_unlock(&dev->struct_mutex); | ||
| 641 | nouveau_sgdma_takedown(dev); | ||
| 597 | 642 | ||
| 598 | if (drm_core_check_feature(dev, DRIVER_MODESET)) | 643 | nouveau_gpuobj_takedown(dev); |
| 599 | drm_irq_uninstall(dev); | 644 | nouveau_mem_close(dev); |
| 645 | engine->instmem.takedown(dev); | ||
| 600 | 646 | ||
| 601 | nouveau_gpuobj_late_takedown(dev); | 647 | drm_irq_uninstall(dev); |
| 602 | nouveau_bios_takedown(dev); | ||
| 603 | 648 | ||
| 604 | vga_client_register(dev->pdev, NULL, NULL, NULL); | 649 | nouveau_gpuobj_late_takedown(dev); |
| 650 | nouveau_bios_takedown(dev); | ||
| 605 | 651 | ||
| 606 | dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN; | 652 | vga_client_register(dev->pdev, NULL, NULL, NULL); |
| 607 | } | ||
| 608 | } | 653 | } |
| 609 | 654 | ||
| 610 | /* here a client dies, release the stuff that was allocated for its | 655 | /* here a client dies, release the stuff that was allocated for its |
| @@ -691,6 +736,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
| 691 | struct drm_nouveau_private *dev_priv; | 736 | struct drm_nouveau_private *dev_priv; |
| 692 | uint32_t reg0; | 737 | uint32_t reg0; |
| 693 | resource_size_t mmio_start_offs; | 738 | resource_size_t mmio_start_offs; |
| 739 | int ret; | ||
| 694 | 740 | ||
| 695 | dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); | 741 | dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); |
| 696 | if (!dev_priv) | 742 | if (!dev_priv) |
| @@ -699,7 +745,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
| 699 | dev_priv->dev = dev; | 745 | dev_priv->dev = dev; |
| 700 | 746 | ||
| 701 | dev_priv->flags = flags & NOUVEAU_FLAGS; | 747 | dev_priv->flags = flags & NOUVEAU_FLAGS; |
| 702 | dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN; | ||
| 703 | 748 | ||
| 704 | NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n", | 749 | NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n", |
| 705 | dev->pci_vendor, dev->pci_device, dev->pdev->class); | 750 | dev->pci_vendor, dev->pci_device, dev->pdev->class); |
| @@ -773,11 +818,9 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
| 773 | NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n", | 818 | NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n", |
| 774 | dev_priv->card_type, reg0); | 819 | dev_priv->card_type, reg0); |
| 775 | 820 | ||
| 776 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 821 | ret = nouveau_remove_conflicting_drivers(dev); |
| 777 | int ret = nouveau_remove_conflicting_drivers(dev); | 822 | if (ret) |
| 778 | if (ret) | 823 | return ret; |
| 779 | return ret; | ||
| 780 | } | ||
| 781 | 824 | ||
| 782 | /* Map PRAMIN BAR, or on older cards, the aperture withing BAR0 */ | 825 | /* Map PRAMIN BAR, or on older cards, the aperture withing BAR0 */ |
| 783 | if (dev_priv->card_type >= NV_40) { | 826 | if (dev_priv->card_type >= NV_40) { |
| @@ -812,46 +855,26 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
| 812 | dev_priv->flags |= NV_NFORCE2; | 855 | dev_priv->flags |= NV_NFORCE2; |
| 813 | 856 | ||
| 814 | /* For kernel modesetting, init card now and bring up fbcon */ | 857 | /* For kernel modesetting, init card now and bring up fbcon */ |
| 815 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 858 | ret = nouveau_card_init(dev); |
| 816 | int ret = nouveau_card_init(dev); | 859 | if (ret) |
| 817 | if (ret) | 860 | return ret; |
| 818 | return ret; | ||
| 819 | } | ||
| 820 | 861 | ||
| 821 | return 0; | 862 | return 0; |
| 822 | } | 863 | } |
| 823 | 864 | ||
| 824 | static void nouveau_close(struct drm_device *dev) | ||
| 825 | { | ||
| 826 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 827 | |||
| 828 | /* In the case of an error dev_priv may not be allocated yet */ | ||
| 829 | if (dev_priv) | ||
| 830 | nouveau_card_takedown(dev); | ||
| 831 | } | ||
| 832 | |||
| 833 | /* KMS: we need mmio at load time, not when the first drm client opens. */ | ||
| 834 | void nouveau_lastclose(struct drm_device *dev) | 865 | void nouveau_lastclose(struct drm_device *dev) |
| 835 | { | 866 | { |
| 836 | if (drm_core_check_feature(dev, DRIVER_MODESET)) | ||
| 837 | return; | ||
| 838 | |||
| 839 | nouveau_close(dev); | ||
| 840 | } | 867 | } |
| 841 | 868 | ||
| 842 | int nouveau_unload(struct drm_device *dev) | 869 | int nouveau_unload(struct drm_device *dev) |
| 843 | { | 870 | { |
| 844 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 871 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 872 | struct nouveau_engine *engine = &dev_priv->engine; | ||
| 845 | 873 | ||
| 846 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 874 | drm_kms_helper_poll_fini(dev); |
| 847 | drm_kms_helper_poll_fini(dev); | 875 | nouveau_fbcon_fini(dev); |
| 848 | nouveau_fbcon_fini(dev); | 876 | engine->display.destroy(dev); |
| 849 | if (dev_priv->card_type >= NV_50) | 877 | nouveau_card_takedown(dev); |
| 850 | nv50_display_destroy(dev); | ||
| 851 | else | ||
| 852 | nv04_display_destroy(dev); | ||
| 853 | nouveau_close(dev); | ||
| 854 | } | ||
| 855 | 878 | ||
| 856 | iounmap(dev_priv->mmio); | 879 | iounmap(dev_priv->mmio); |
| 857 | iounmap(dev_priv->ramin); | 880 | iounmap(dev_priv->ramin); |
| @@ -867,8 +890,6 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data, | |||
| 867 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 890 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 868 | struct drm_nouveau_getparam *getparam = data; | 891 | struct drm_nouveau_getparam *getparam = data; |
| 869 | 892 | ||
| 870 | NOUVEAU_CHECK_INITIALISED_WITH_RETURN; | ||
| 871 | |||
| 872 | switch (getparam->param) { | 893 | switch (getparam->param) { |
| 873 | case NOUVEAU_GETPARAM_CHIPSET_ID: | 894 | case NOUVEAU_GETPARAM_CHIPSET_ID: |
| 874 | getparam->value = dev_priv->chipset; | 895 | getparam->value = dev_priv->chipset; |
| @@ -937,8 +958,6 @@ nouveau_ioctl_setparam(struct drm_device *dev, void *data, | |||
| 937 | { | 958 | { |
| 938 | struct drm_nouveau_setparam *setparam = data; | 959 | struct drm_nouveau_setparam *setparam = data; |
| 939 | 960 | ||
| 940 | NOUVEAU_CHECK_INITIALISED_WITH_RETURN; | ||
| 941 | |||
| 942 | switch (setparam->param) { | 961 | switch (setparam->param) { |
| 943 | default: | 962 | default: |
| 944 | NV_ERROR(dev, "unknown parameter %lld\n", setparam->param); | 963 | NV_ERROR(dev, "unknown parameter %lld\n", setparam->param); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index c385d50f041b..bd35f930568c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c | |||
| @@ -42,13 +42,13 @@ nouveau_ttm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | static int | 44 | static int |
| 45 | nouveau_ttm_mem_global_init(struct ttm_global_reference *ref) | 45 | nouveau_ttm_mem_global_init(struct drm_global_reference *ref) |
| 46 | { | 46 | { |
| 47 | return ttm_mem_global_init(ref->object); | 47 | return ttm_mem_global_init(ref->object); |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | static void | 50 | static void |
| 51 | nouveau_ttm_mem_global_release(struct ttm_global_reference *ref) | 51 | nouveau_ttm_mem_global_release(struct drm_global_reference *ref) |
| 52 | { | 52 | { |
| 53 | ttm_mem_global_release(ref->object); | 53 | ttm_mem_global_release(ref->object); |
| 54 | } | 54 | } |
| @@ -56,16 +56,16 @@ nouveau_ttm_mem_global_release(struct ttm_global_reference *ref) | |||
| 56 | int | 56 | int |
| 57 | nouveau_ttm_global_init(struct drm_nouveau_private *dev_priv) | 57 | nouveau_ttm_global_init(struct drm_nouveau_private *dev_priv) |
| 58 | { | 58 | { |
| 59 | struct ttm_global_reference *global_ref; | 59 | struct drm_global_reference *global_ref; |
| 60 | int ret; | 60 | int ret; |
| 61 | 61 | ||
| 62 | global_ref = &dev_priv->ttm.mem_global_ref; | 62 | global_ref = &dev_priv->ttm.mem_global_ref; |
| 63 | global_ref->global_type = TTM_GLOBAL_TTM_MEM; | 63 | global_ref->global_type = DRM_GLOBAL_TTM_MEM; |
| 64 | global_ref->size = sizeof(struct ttm_mem_global); | 64 | global_ref->size = sizeof(struct ttm_mem_global); |
| 65 | global_ref->init = &nouveau_ttm_mem_global_init; | 65 | global_ref->init = &nouveau_ttm_mem_global_init; |
| 66 | global_ref->release = &nouveau_ttm_mem_global_release; | 66 | global_ref->release = &nouveau_ttm_mem_global_release; |
| 67 | 67 | ||
| 68 | ret = ttm_global_item_ref(global_ref); | 68 | ret = drm_global_item_ref(global_ref); |
| 69 | if (unlikely(ret != 0)) { | 69 | if (unlikely(ret != 0)) { |
| 70 | DRM_ERROR("Failed setting up TTM memory accounting\n"); | 70 | DRM_ERROR("Failed setting up TTM memory accounting\n"); |
| 71 | dev_priv->ttm.mem_global_ref.release = NULL; | 71 | dev_priv->ttm.mem_global_ref.release = NULL; |
| @@ -74,15 +74,15 @@ nouveau_ttm_global_init(struct drm_nouveau_private *dev_priv) | |||
| 74 | 74 | ||
| 75 | dev_priv->ttm.bo_global_ref.mem_glob = global_ref->object; | 75 | dev_priv->ttm.bo_global_ref.mem_glob = global_ref->object; |
| 76 | global_ref = &dev_priv->ttm.bo_global_ref.ref; | 76 | global_ref = &dev_priv->ttm.bo_global_ref.ref; |
| 77 | global_ref->global_type = TTM_GLOBAL_TTM_BO; | 77 | global_ref->global_type = DRM_GLOBAL_TTM_BO; |
| 78 | global_ref->size = sizeof(struct ttm_bo_global); | 78 | global_ref->size = sizeof(struct ttm_bo_global); |
| 79 | global_ref->init = &ttm_bo_global_init; | 79 | global_ref->init = &ttm_bo_global_init; |
| 80 | global_ref->release = &ttm_bo_global_release; | 80 | global_ref->release = &ttm_bo_global_release; |
| 81 | 81 | ||
| 82 | ret = ttm_global_item_ref(global_ref); | 82 | ret = drm_global_item_ref(global_ref); |
| 83 | if (unlikely(ret != 0)) { | 83 | if (unlikely(ret != 0)) { |
| 84 | DRM_ERROR("Failed setting up TTM BO subsystem\n"); | 84 | DRM_ERROR("Failed setting up TTM BO subsystem\n"); |
| 85 | ttm_global_item_unref(&dev_priv->ttm.mem_global_ref); | 85 | drm_global_item_unref(&dev_priv->ttm.mem_global_ref); |
| 86 | dev_priv->ttm.mem_global_ref.release = NULL; | 86 | dev_priv->ttm.mem_global_ref.release = NULL; |
| 87 | return ret; | 87 | return ret; |
| 88 | } | 88 | } |
| @@ -96,8 +96,8 @@ nouveau_ttm_global_release(struct drm_nouveau_private *dev_priv) | |||
| 96 | if (dev_priv->ttm.mem_global_ref.release == NULL) | 96 | if (dev_priv->ttm.mem_global_ref.release == NULL) |
| 97 | return; | 97 | return; |
| 98 | 98 | ||
| 99 | ttm_global_item_unref(&dev_priv->ttm.bo_global_ref.ref); | 99 | drm_global_item_unref(&dev_priv->ttm.bo_global_ref.ref); |
| 100 | ttm_global_item_unref(&dev_priv->ttm.mem_global_ref); | 100 | drm_global_item_unref(&dev_priv->ttm.mem_global_ref); |
| 101 | dev_priv->ttm.mem_global_ref.release = NULL; | 101 | dev_priv->ttm.mem_global_ref.release = NULL; |
| 102 | } | 102 | } |
| 103 | 103 | ||
diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c index eba687f1099e..1c20c08ce67c 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) | |||
| 157 | { | 157 | { |
| 158 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 158 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |
| 159 | struct drm_device *dev = crtc->dev; | 159 | struct drm_device *dev = crtc->dev; |
| 160 | struct drm_connector *connector; | ||
| 160 | unsigned char seq1 = 0, crtc17 = 0; | 161 | unsigned char seq1 = 0, crtc17 = 0; |
| 161 | unsigned char crtc1A; | 162 | unsigned char crtc1A; |
| 162 | 163 | ||
| @@ -211,6 +212,10 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
| 211 | NVVgaSeqReset(dev, nv_crtc->index, false); | 212 | NVVgaSeqReset(dev, nv_crtc->index, false); |
| 212 | 213 | ||
| 213 | NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RPC1_INDEX, crtc1A); | 214 | NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RPC1_INDEX, crtc1A); |
| 215 | |||
| 216 | /* Update connector polling modes */ | ||
| 217 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) | ||
| 218 | nouveau_connector_set_polling(connector); | ||
| 214 | } | 219 | } |
| 215 | 220 | ||
| 216 | static bool | 221 | static bool |
diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c index 1cb19e3acb55..ea3627041ecf 100644 --- a/drivers/gpu/drm/nouveau/nv04_dac.c +++ b/drivers/gpu/drm/nouveau/nv04_dac.c | |||
| @@ -220,6 +220,7 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) | |||
| 220 | { | 220 | { |
| 221 | struct drm_device *dev = encoder->dev; | 221 | struct drm_device *dev = encoder->dev; |
| 222 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 222 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 223 | struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio; | ||
| 223 | struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; | 224 | struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; |
| 224 | uint32_t sample, testval, regoffset = nv04_dac_output_offset(encoder); | 225 | uint32_t sample, testval, regoffset = nv04_dac_output_offset(encoder); |
| 225 | uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput, | 226 | uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput, |
| @@ -251,22 +252,21 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) | |||
| 251 | nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf); | 252 | nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf); |
| 252 | } | 253 | } |
| 253 | 254 | ||
| 254 | saved_gpio1 = nv17_gpio_get(dev, DCB_GPIO_TVDAC1); | 255 | saved_gpio1 = gpio->get(dev, DCB_GPIO_TVDAC1); |
| 255 | saved_gpio0 = nv17_gpio_get(dev, DCB_GPIO_TVDAC0); | 256 | saved_gpio0 = gpio->get(dev, DCB_GPIO_TVDAC0); |
| 256 | 257 | ||
| 257 | nv17_gpio_set(dev, DCB_GPIO_TVDAC1, dcb->type == OUTPUT_TV); | 258 | gpio->set(dev, DCB_GPIO_TVDAC1, dcb->type == OUTPUT_TV); |
| 258 | nv17_gpio_set(dev, DCB_GPIO_TVDAC0, dcb->type == OUTPUT_TV); | 259 | gpio->set(dev, DCB_GPIO_TVDAC0, dcb->type == OUTPUT_TV); |
| 259 | 260 | ||
| 260 | msleep(4); | 261 | msleep(4); |
| 261 | 262 | ||
| 262 | saved_routput = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset); | 263 | saved_routput = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset); |
| 263 | head = (saved_routput & 0x100) >> 8; | 264 | head = (saved_routput & 0x100) >> 8; |
| 264 | #if 0 | 265 | |
| 265 | /* if there's a spare crtc, using it will minimise flicker for the case | 266 | /* if there's a spare crtc, using it will minimise flicker */ |
| 266 | * where the in-use crtc is in use by an off-chip tmds encoder */ | 267 | if (!(NVReadVgaCrtc(dev, head, NV_CIO_CRE_RPC1_INDEX) & 0xC0)) |
| 267 | if (xf86_config->crtc[head]->enabled && !xf86_config->crtc[head ^ 1]->enabled) | ||
| 268 | head ^= 1; | 268 | head ^= 1; |
| 269 | #endif | 269 | |
| 270 | /* nv driver and nv31 use 0xfffffeee, nv34 and 6600 use 0xfffffece */ | 270 | /* nv driver and nv31 use 0xfffffeee, nv34 and 6600 use 0xfffffece */ |
| 271 | routput = (saved_routput & 0xfffffece) | head << 8; | 271 | routput = (saved_routput & 0xfffffece) | head << 8; |
| 272 | 272 | ||
| @@ -304,8 +304,8 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) | |||
| 304 | nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4); | 304 | nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4); |
| 305 | nvWriteMC(dev, NV_PBUS_POWERCTRL_2, saved_powerctrl_2); | 305 | nvWriteMC(dev, NV_PBUS_POWERCTRL_2, saved_powerctrl_2); |
| 306 | 306 | ||
| 307 | nv17_gpio_set(dev, DCB_GPIO_TVDAC1, saved_gpio1); | 307 | gpio->set(dev, DCB_GPIO_TVDAC1, saved_gpio1); |
| 308 | nv17_gpio_set(dev, DCB_GPIO_TVDAC0, saved_gpio0); | 308 | gpio->set(dev, DCB_GPIO_TVDAC0, saved_gpio0); |
| 309 | 309 | ||
| 310 | return sample; | 310 | return sample; |
| 311 | } | 311 | } |
| @@ -315,9 +315,12 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) | |||
| 315 | { | 315 | { |
| 316 | struct drm_device *dev = encoder->dev; | 316 | struct drm_device *dev = encoder->dev; |
| 317 | struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; | 317 | struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; |
| 318 | uint32_t sample = nv17_dac_sample_load(encoder); | ||
| 319 | 318 | ||
| 320 | if (sample & NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) { | 319 | if (nv04_dac_in_use(encoder)) |
| 320 | return connector_status_disconnected; | ||
| 321 | |||
| 322 | if (nv17_dac_sample_load(encoder) & | ||
| 323 | NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) { | ||
| 321 | NV_INFO(dev, "Load detected on output %c\n", | 324 | NV_INFO(dev, "Load detected on output %c\n", |
| 322 | '@' + ffs(dcb->or)); | 325 | '@' + ffs(dcb->or)); |
| 323 | return connector_status_connected; | 326 | return connector_status_connected; |
| @@ -330,6 +333,9 @@ static bool nv04_dac_mode_fixup(struct drm_encoder *encoder, | |||
| 330 | struct drm_display_mode *mode, | 333 | struct drm_display_mode *mode, |
| 331 | struct drm_display_mode *adjusted_mode) | 334 | struct drm_display_mode *adjusted_mode) |
| 332 | { | 335 | { |
| 336 | if (nv04_dac_in_use(encoder)) | ||
| 337 | return false; | ||
| 338 | |||
| 333 | return true; | 339 | return true; |
| 334 | } | 340 | } |
| 335 | 341 | ||
| @@ -428,6 +434,17 @@ void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable) | |||
| 428 | } | 434 | } |
| 429 | } | 435 | } |
| 430 | 436 | ||
| 437 | /* Check if the DAC corresponding to 'encoder' is being used by | ||
| 438 | * someone else. */ | ||
| 439 | bool nv04_dac_in_use(struct drm_encoder *encoder) | ||
| 440 | { | ||
| 441 | struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; | ||
| 442 | struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; | ||
| 443 | |||
| 444 | return nv_gf4_disp_arch(encoder->dev) && | ||
| 445 | (dev_priv->dac_users[ffs(dcb->or) - 1] & ~(1 << dcb->index)); | ||
| 446 | } | ||
| 447 | |||
| 431 | static void nv04_dac_dpms(struct drm_encoder *encoder, int mode) | 448 | static void nv04_dac_dpms(struct drm_encoder *encoder, int mode) |
| 432 | { | 449 | { |
| 433 | struct drm_device *dev = encoder->dev; | 450 | struct drm_device *dev = encoder->dev; |
| @@ -501,11 +518,13 @@ static const struct drm_encoder_funcs nv04_dac_funcs = { | |||
| 501 | .destroy = nv04_dac_destroy, | 518 | .destroy = nv04_dac_destroy, |
| 502 | }; | 519 | }; |
| 503 | 520 | ||
| 504 | int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry) | 521 | int |
| 522 | nv04_dac_create(struct drm_connector *connector, struct dcb_entry *entry) | ||
| 505 | { | 523 | { |
| 506 | const struct drm_encoder_helper_funcs *helper; | 524 | const struct drm_encoder_helper_funcs *helper; |
| 507 | struct drm_encoder *encoder; | ||
| 508 | struct nouveau_encoder *nv_encoder = NULL; | 525 | struct nouveau_encoder *nv_encoder = NULL; |
| 526 | struct drm_device *dev = connector->dev; | ||
| 527 | struct drm_encoder *encoder; | ||
| 509 | 528 | ||
| 510 | nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); | 529 | nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); |
| 511 | if (!nv_encoder) | 530 | if (!nv_encoder) |
| @@ -527,5 +546,6 @@ int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry) | |||
| 527 | encoder->possible_crtcs = entry->heads; | 546 | encoder->possible_crtcs = entry->heads; |
| 528 | encoder->possible_clones = 0; | 547 | encoder->possible_clones = 0; |
| 529 | 548 | ||
| 549 | drm_mode_connector_attach_encoder(connector, encoder); | ||
| 530 | return 0; | 550 | return 0; |
| 531 | } | 551 | } |
diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index 41634d4752fe..3311f3a8c818 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) | |||
| 413 | struct dcb_entry *dcbe = nv_encoder->dcb; | 413 | struct dcb_entry *dcbe = nv_encoder->dcb; |
| 414 | int head = nouveau_crtc(encoder->crtc)->index; | 414 | int head = nouveau_crtc(encoder->crtc)->index; |
| 415 | 415 | ||
| 416 | NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", | ||
| 417 | drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), | ||
| 418 | nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); | ||
| 419 | |||
| 420 | if (dcbe->type == OUTPUT_TMDS) | 416 | if (dcbe->type == OUTPUT_TMDS) |
| 421 | run_tmds_table(dev, dcbe, head, nv_encoder->mode.clock); | 417 | run_tmds_table(dev, dcbe, head, nv_encoder->mode.clock); |
| 422 | else if (dcbe->type == OUTPUT_LVDS) | 418 | else if (dcbe->type == OUTPUT_LVDS) |
| @@ -584,11 +580,12 @@ static const struct drm_encoder_funcs nv04_dfp_funcs = { | |||
| 584 | .destroy = nv04_dfp_destroy, | 580 | .destroy = nv04_dfp_destroy, |
| 585 | }; | 581 | }; |
| 586 | 582 | ||
| 587 | int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry) | 583 | int |
| 584 | nv04_dfp_create(struct drm_connector *connector, struct dcb_entry *entry) | ||
| 588 | { | 585 | { |
| 589 | const struct drm_encoder_helper_funcs *helper; | 586 | const struct drm_encoder_helper_funcs *helper; |
| 590 | struct drm_encoder *encoder; | ||
| 591 | struct nouveau_encoder *nv_encoder = NULL; | 587 | struct nouveau_encoder *nv_encoder = NULL; |
| 588 | struct drm_encoder *encoder; | ||
| 592 | int type; | 589 | int type; |
| 593 | 590 | ||
| 594 | switch (entry->type) { | 591 | switch (entry->type) { |
| @@ -613,11 +610,12 @@ int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry) | |||
| 613 | nv_encoder->dcb = entry; | 610 | nv_encoder->dcb = entry; |
| 614 | nv_encoder->or = ffs(entry->or) - 1; | 611 | nv_encoder->or = ffs(entry->or) - 1; |
| 615 | 612 | ||
| 616 | drm_encoder_init(dev, encoder, &nv04_dfp_funcs, type); | 613 | drm_encoder_init(connector->dev, encoder, &nv04_dfp_funcs, type); |
| 617 | drm_encoder_helper_add(encoder, helper); | 614 | drm_encoder_helper_add(encoder, helper); |
| 618 | 615 | ||
| 619 | encoder->possible_crtcs = entry->heads; | 616 | encoder->possible_crtcs = entry->heads; |
| 620 | encoder->possible_clones = 0; | 617 | encoder->possible_clones = 0; |
| 621 | 618 | ||
| 619 | drm_mode_connector_attach_encoder(connector, encoder); | ||
| 622 | return 0; | 620 | return 0; |
| 623 | } | 621 | } |
diff --git a/drivers/gpu/drm/nouveau/nv04_display.c b/drivers/gpu/drm/nouveau/nv04_display.c index c7898b4f6dfb..9e28cf772e3c 100644 --- a/drivers/gpu/drm/nouveau/nv04_display.c +++ b/drivers/gpu/drm/nouveau/nv04_display.c | |||
| @@ -32,8 +32,6 @@ | |||
| 32 | #include "nouveau_encoder.h" | 32 | #include "nouveau_encoder.h" |
| 33 | #include "nouveau_connector.h" | 33 | #include "nouveau_connector.h" |
| 34 | 34 | ||
| 35 | #define MULTIPLE_ENCODERS(e) (e & (e - 1)) | ||
| 36 | |||
| 37 | static void | 35 | static void |
| 38 | nv04_display_store_initial_head_owner(struct drm_device *dev) | 36 | nv04_display_store_initial_head_owner(struct drm_device *dev) |
| 39 | { | 37 | { |
| @@ -41,7 +39,7 @@ nv04_display_store_initial_head_owner(struct drm_device *dev) | |||
| 41 | 39 | ||
| 42 | if (dev_priv->chipset != 0x11) { | 40 | if (dev_priv->chipset != 0x11) { |
| 43 | dev_priv->crtc_owner = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_44); | 41 | dev_priv->crtc_owner = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_44); |
| 44 | goto ownerknown; | 42 | return; |
| 45 | } | 43 | } |
| 46 | 44 | ||
| 47 | /* reading CR44 is broken on nv11, so we attempt to infer it */ | 45 | /* 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) | |||
| 52 | bool tvA = false; | 50 | bool tvA = false; |
| 53 | bool tvB = false; | 51 | bool tvB = false; |
| 54 | 52 | ||
| 55 | NVLockVgaCrtcs(dev, false); | ||
| 56 | |||
| 57 | slaved_on_B = NVReadVgaCrtc(dev, 1, NV_CIO_CRE_PIXEL_INDEX) & | 53 | slaved_on_B = NVReadVgaCrtc(dev, 1, NV_CIO_CRE_PIXEL_INDEX) & |
| 58 | 0x80; | 54 | 0x80; |
| 59 | if (slaved_on_B) | 55 | if (slaved_on_B) |
| @@ -66,8 +62,6 @@ nv04_display_store_initial_head_owner(struct drm_device *dev) | |||
| 66 | tvA = !(NVReadVgaCrtc(dev, 0, NV_CIO_CRE_LCD__INDEX) & | 62 | tvA = !(NVReadVgaCrtc(dev, 0, NV_CIO_CRE_LCD__INDEX) & |
| 67 | MASK(NV_CIO_CRE_LCD_LCD_SELECT)); | 63 | MASK(NV_CIO_CRE_LCD_LCD_SELECT)); |
| 68 | 64 | ||
| 69 | NVLockVgaCrtcs(dev, true); | ||
| 70 | |||
| 71 | if (slaved_on_A && !tvA) | 65 | if (slaved_on_A && !tvA) |
| 72 | dev_priv->crtc_owner = 0x0; | 66 | dev_priv->crtc_owner = 0x0; |
| 73 | else if (slaved_on_B && !tvB) | 67 | else if (slaved_on_B && !tvB) |
| @@ -79,14 +73,40 @@ nv04_display_store_initial_head_owner(struct drm_device *dev) | |||
| 79 | else | 73 | else |
| 80 | dev_priv->crtc_owner = 0x0; | 74 | dev_priv->crtc_owner = 0x0; |
| 81 | } | 75 | } |
| 76 | } | ||
| 77 | |||
| 78 | int | ||
| 79 | nv04_display_early_init(struct drm_device *dev) | ||
| 80 | { | ||
| 81 | /* Make the I2C buses accessible. */ | ||
| 82 | if (!nv_gf4_disp_arch(dev)) { | ||
| 83 | uint32_t pmc_enable = nv_rd32(dev, NV03_PMC_ENABLE); | ||
| 84 | |||
| 85 | if (!(pmc_enable & 1)) | ||
| 86 | nv_wr32(dev, NV03_PMC_ENABLE, pmc_enable | 1); | ||
| 87 | } | ||
| 82 | 88 | ||
| 83 | ownerknown: | 89 | /* Unlock the VGA CRTCs. */ |
| 84 | NV_INFO(dev, "Initial CRTC_OWNER is %d\n", dev_priv->crtc_owner); | 90 | NVLockVgaCrtcs(dev, false); |
| 91 | |||
| 92 | /* Make sure the CRTCs aren't in slaved mode. */ | ||
| 93 | if (nv_two_heads(dev)) { | ||
| 94 | nv04_display_store_initial_head_owner(dev); | ||
| 95 | NVSetOwner(dev, 0); | ||
| 96 | } | ||
| 97 | |||
| 98 | return 0; | ||
| 99 | } | ||
| 100 | |||
| 101 | void | ||
| 102 | nv04_display_late_takedown(struct drm_device *dev) | ||
| 103 | { | ||
| 104 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 105 | |||
| 106 | if (nv_two_heads(dev)) | ||
| 107 | NVSetOwner(dev, dev_priv->crtc_owner); | ||
| 85 | 108 | ||
| 86 | /* we need to ensure the heads are not tied henceforth, or reading any | 109 | NVLockVgaCrtcs(dev, true); |
| 87 | * 8 bit reg on head B will fail | ||
| 88 | * setting a single arbitrary head solves that */ | ||
| 89 | NVSetOwner(dev, 0); | ||
| 90 | } | 110 | } |
| 91 | 111 | ||
| 92 | int | 112 | int |
| @@ -94,14 +114,13 @@ nv04_display_create(struct drm_device *dev) | |||
| 94 | { | 114 | { |
| 95 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 115 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 96 | struct dcb_table *dcb = &dev_priv->vbios.dcb; | 116 | struct dcb_table *dcb = &dev_priv->vbios.dcb; |
| 117 | struct drm_connector *connector, *ct; | ||
| 97 | struct drm_encoder *encoder; | 118 | struct drm_encoder *encoder; |
| 98 | struct drm_crtc *crtc; | 119 | struct drm_crtc *crtc; |
| 99 | int i, ret; | 120 | int i, ret; |
| 100 | 121 | ||
| 101 | NV_DEBUG_KMS(dev, "\n"); | 122 | NV_DEBUG_KMS(dev, "\n"); |
| 102 | 123 | ||
| 103 | if (nv_two_heads(dev)) | ||
| 104 | nv04_display_store_initial_head_owner(dev); | ||
| 105 | nouveau_hw_save_vga_fonts(dev, 1); | 124 | nouveau_hw_save_vga_fonts(dev, 1); |
| 106 | 125 | ||
| 107 | drm_mode_config_init(dev); | 126 | drm_mode_config_init(dev); |
| @@ -132,19 +151,23 @@ nv04_display_create(struct drm_device *dev) | |||
| 132 | for (i = 0; i < dcb->entries; i++) { | 151 | for (i = 0; i < dcb->entries; i++) { |
| 133 | struct dcb_entry *dcbent = &dcb->entry[i]; | 152 | struct dcb_entry *dcbent = &dcb->entry[i]; |
| 134 | 153 | ||
| 154 | connector = nouveau_connector_create(dev, dcbent->connector); | ||
| 155 | if (IS_ERR(connector)) | ||
| 156 | continue; | ||
| 157 | |||
| 135 | switch (dcbent->type) { | 158 | switch (dcbent->type) { |
| 136 | case OUTPUT_ANALOG: | 159 | case OUTPUT_ANALOG: |
| 137 | ret = nv04_dac_create(dev, dcbent); | 160 | ret = nv04_dac_create(connector, dcbent); |
| 138 | break; | 161 | break; |
| 139 | case OUTPUT_LVDS: | 162 | case OUTPUT_LVDS: |
| 140 | case OUTPUT_TMDS: | 163 | case OUTPUT_TMDS: |
| 141 | ret = nv04_dfp_create(dev, dcbent); | 164 | ret = nv04_dfp_create(connector, dcbent); |
| 142 | break; | 165 | break; |
| 143 | case OUTPUT_TV: | 166 | case OUTPUT_TV: |
| 144 | if (dcbent->location == DCB_LOC_ON_CHIP) | 167 | if (dcbent->location == DCB_LOC_ON_CHIP) |
| 145 | ret = nv17_tv_create(dev, dcbent); | 168 | ret = nv17_tv_create(connector, dcbent); |
| 146 | else | 169 | else |
| 147 | ret = nv04_tv_create(dev, dcbent); | 170 | ret = nv04_tv_create(connector, dcbent); |
| 148 | break; | 171 | break; |
| 149 | default: | 172 | default: |
| 150 | NV_WARN(dev, "DCB type %d not known\n", dcbent->type); | 173 | NV_WARN(dev, "DCB type %d not known\n", dcbent->type); |
| @@ -155,12 +178,16 @@ nv04_display_create(struct drm_device *dev) | |||
| 155 | continue; | 178 | continue; |
| 156 | } | 179 | } |
| 157 | 180 | ||
| 158 | for (i = 0; i < dcb->connector.entries; i++) | 181 | list_for_each_entry_safe(connector, ct, |
| 159 | nouveau_connector_create(dev, &dcb->connector.entry[i]); | 182 | &dev->mode_config.connector_list, head) { |
| 183 | if (!connector->encoder_ids[0]) { | ||
| 184 | NV_WARN(dev, "%s has no encoders, removing\n", | ||
| 185 | drm_get_connector_name(connector)); | ||
| 186 | connector->funcs->destroy(connector); | ||
| 187 | } | ||
| 188 | } | ||
| 160 | 189 | ||
| 161 | /* Save previous state */ | 190 | /* Save previous state */ |
| 162 | NVLockVgaCrtcs(dev, false); | ||
| 163 | |||
| 164 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) | 191 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) |
| 165 | crtc->funcs->save(crtc); | 192 | crtc->funcs->save(crtc); |
| 166 | 193 | ||
| @@ -191,8 +218,6 @@ nv04_display_destroy(struct drm_device *dev) | |||
| 191 | } | 218 | } |
| 192 | 219 | ||
| 193 | /* Restore state */ | 220 | /* Restore state */ |
| 194 | NVLockVgaCrtcs(dev, false); | ||
| 195 | |||
| 196 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 221 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
| 197 | struct drm_encoder_helper_funcs *func = encoder->helper_private; | 222 | struct drm_encoder_helper_funcs *func = encoder->helper_private; |
| 198 | 223 | ||
| @@ -207,15 +232,12 @@ nv04_display_destroy(struct drm_device *dev) | |||
| 207 | nouveau_hw_save_vga_fonts(dev, 0); | 232 | nouveau_hw_save_vga_fonts(dev, 0); |
| 208 | } | 233 | } |
| 209 | 234 | ||
| 210 | void | 235 | int |
| 211 | nv04_display_restore(struct drm_device *dev) | 236 | nv04_display_init(struct drm_device *dev) |
| 212 | { | 237 | { |
| 213 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 214 | struct drm_encoder *encoder; | 238 | struct drm_encoder *encoder; |
| 215 | struct drm_crtc *crtc; | 239 | struct drm_crtc *crtc; |
| 216 | 240 | ||
| 217 | NVLockVgaCrtcs(dev, false); | ||
| 218 | |||
| 219 | /* meh.. modeset apparently doesn't setup all the regs and depends | 241 | /* meh.. modeset apparently doesn't setup all the regs and depends |
| 220 | * on pre-existing state, for now load the state of the card *before* | 242 | * on pre-existing state, for now load the state of the card *before* |
| 221 | * nouveau was loaded, and then do a modeset. | 243 | * nouveau was loaded, and then do a modeset. |
| @@ -233,12 +255,6 @@ nv04_display_restore(struct drm_device *dev) | |||
| 233 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) | 255 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) |
| 234 | crtc->funcs->restore(crtc); | 256 | crtc->funcs->restore(crtc); |
| 235 | 257 | ||
| 236 | if (nv_two_heads(dev)) { | 258 | return 0; |
| 237 | NV_INFO(dev, "Restoring CRTC_OWNER to %d.\n", | ||
| 238 | dev_priv->crtc_owner); | ||
| 239 | NVSetOwner(dev, dev_priv->crtc_owner); | ||
| 240 | } | ||
| 241 | |||
| 242 | NVLockVgaCrtcs(dev, true); | ||
| 243 | } | 259 | } |
| 244 | 260 | ||
diff --git a/drivers/gpu/drm/nouveau/nv04_fifo.c b/drivers/gpu/drm/nouveau/nv04_fifo.c index 66fe55983b6e..06cedd99c26a 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) | |||
| 112 | NV03_PFIFO_CACHE1_PUSH1_CHID_MASK; | 112 | NV03_PFIFO_CACHE1_PUSH1_CHID_MASK; |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | #ifdef __BIG_ENDIAN | ||
| 116 | #define DMA_FETCH_ENDIANNESS NV_PFIFO_CACHE1_BIG_ENDIAN | ||
| 117 | #else | ||
| 118 | #define DMA_FETCH_ENDIANNESS 0 | ||
| 119 | #endif | ||
| 120 | |||
| 115 | int | 121 | int |
| 116 | nv04_fifo_create_context(struct nouveau_channel *chan) | 122 | nv04_fifo_create_context(struct nouveau_channel *chan) |
| 117 | { | 123 | { |
| @@ -131,18 +137,13 @@ nv04_fifo_create_context(struct nouveau_channel *chan) | |||
| 131 | spin_lock_irqsave(&dev_priv->context_switch_lock, flags); | 137 | spin_lock_irqsave(&dev_priv->context_switch_lock, flags); |
| 132 | 138 | ||
| 133 | /* Setup initial state */ | 139 | /* Setup initial state */ |
| 134 | dev_priv->engine.instmem.prepare_access(dev, true); | ||
| 135 | RAMFC_WR(DMA_PUT, chan->pushbuf_base); | 140 | RAMFC_WR(DMA_PUT, chan->pushbuf_base); |
| 136 | RAMFC_WR(DMA_GET, chan->pushbuf_base); | 141 | RAMFC_WR(DMA_GET, chan->pushbuf_base); |
| 137 | RAMFC_WR(DMA_INSTANCE, chan->pushbuf->instance >> 4); | 142 | RAMFC_WR(DMA_INSTANCE, chan->pushbuf->instance >> 4); |
| 138 | RAMFC_WR(DMA_FETCH, (NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | | 143 | RAMFC_WR(DMA_FETCH, (NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | |
| 139 | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | | 144 | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | |
| 140 | NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 | | 145 | NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 | |
| 141 | #ifdef __BIG_ENDIAN | 146 | DMA_FETCH_ENDIANNESS)); |
| 142 | NV_PFIFO_CACHE1_BIG_ENDIAN | | ||
| 143 | #endif | ||
| 144 | 0)); | ||
| 145 | dev_priv->engine.instmem.finish_access(dev); | ||
| 146 | 147 | ||
| 147 | /* enable the fifo dma operation */ | 148 | /* enable the fifo dma operation */ |
| 148 | nv_wr32(dev, NV04_PFIFO_MODE, | 149 | nv_wr32(dev, NV04_PFIFO_MODE, |
| @@ -169,8 +170,6 @@ nv04_fifo_do_load_context(struct drm_device *dev, int chid) | |||
| 169 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 170 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 170 | uint32_t fc = NV04_RAMFC(chid), tmp; | 171 | uint32_t fc = NV04_RAMFC(chid), tmp; |
| 171 | 172 | ||
| 172 | dev_priv->engine.instmem.prepare_access(dev, false); | ||
| 173 | |||
| 174 | nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0)); | 173 | nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0)); |
| 175 | nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4)); | 174 | nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4)); |
| 176 | tmp = nv_ri32(dev, fc + 8); | 175 | tmp = nv_ri32(dev, fc + 8); |
| @@ -181,8 +180,6 @@ nv04_fifo_do_load_context(struct drm_device *dev, int chid) | |||
| 181 | nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_ri32(dev, fc + 20)); | 180 | nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_ri32(dev, fc + 20)); |
| 182 | nv_wr32(dev, NV04_PFIFO_CACHE1_PULL1, nv_ri32(dev, fc + 24)); | 181 | nv_wr32(dev, NV04_PFIFO_CACHE1_PULL1, nv_ri32(dev, fc + 24)); |
| 183 | 182 | ||
| 184 | dev_priv->engine.instmem.finish_access(dev); | ||
| 185 | |||
| 186 | nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); | 183 | nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); |
| 187 | nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0); | 184 | nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0); |
| 188 | } | 185 | } |
| @@ -223,7 +220,6 @@ nv04_fifo_unload_context(struct drm_device *dev) | |||
| 223 | return -EINVAL; | 220 | return -EINVAL; |
| 224 | } | 221 | } |
| 225 | 222 | ||
| 226 | dev_priv->engine.instmem.prepare_access(dev, true); | ||
| 227 | RAMFC_WR(DMA_PUT, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT)); | 223 | RAMFC_WR(DMA_PUT, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT)); |
| 228 | RAMFC_WR(DMA_GET, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET)); | 224 | RAMFC_WR(DMA_GET, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET)); |
| 229 | tmp = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT) << 16; | 225 | tmp = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT) << 16; |
| @@ -233,7 +229,6 @@ nv04_fifo_unload_context(struct drm_device *dev) | |||
| 233 | RAMFC_WR(DMA_FETCH, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_FETCH)); | 229 | RAMFC_WR(DMA_FETCH, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_FETCH)); |
| 234 | RAMFC_WR(ENGINE, nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE)); | 230 | RAMFC_WR(ENGINE, nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE)); |
| 235 | RAMFC_WR(PULL1_ENGINE, nv_rd32(dev, NV04_PFIFO_CACHE1_PULL1)); | 231 | RAMFC_WR(PULL1_ENGINE, nv_rd32(dev, NV04_PFIFO_CACHE1_PULL1)); |
| 236 | dev_priv->engine.instmem.finish_access(dev); | ||
| 237 | 232 | ||
| 238 | nv04_fifo_do_load_context(dev, pfifo->channels - 1); | 233 | nv04_fifo_do_load_context(dev, pfifo->channels - 1); |
| 239 | nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1); | 234 | nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1); |
| @@ -297,6 +292,7 @@ nv04_fifo_init(struct drm_device *dev) | |||
| 297 | 292 | ||
| 298 | nv04_fifo_init_intr(dev); | 293 | nv04_fifo_init_intr(dev); |
| 299 | pfifo->enable(dev); | 294 | pfifo->enable(dev); |
| 295 | pfifo->reassign(dev, true); | ||
| 300 | 296 | ||
| 301 | for (i = 0; i < dev_priv->engine.fifo.channels; i++) { | 297 | for (i = 0; i < dev_priv->engine.fifo.channels; i++) { |
| 302 | if (dev_priv->fifos[i]) { | 298 | if (dev_priv->fifos[i]) { |
diff --git a/drivers/gpu/drm/nouveau/nv04_graph.c b/drivers/gpu/drm/nouveau/nv04_graph.c index 618355e9cdd5..c8973421b635 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[] = { | |||
| 342 | }; | 342 | }; |
| 343 | 343 | ||
| 344 | struct graph_state { | 344 | struct graph_state { |
| 345 | int nv04[ARRAY_SIZE(nv04_graph_ctx_regs)]; | 345 | uint32_t nv04[ARRAY_SIZE(nv04_graph_ctx_regs)]; |
| 346 | }; | 346 | }; |
| 347 | 347 | ||
| 348 | struct nouveau_channel * | 348 | struct nouveau_channel * |
| @@ -527,8 +527,7 @@ static int | |||
| 527 | nv04_graph_mthd_set_ref(struct nouveau_channel *chan, int grclass, | 527 | nv04_graph_mthd_set_ref(struct nouveau_channel *chan, int grclass, |
| 528 | int mthd, uint32_t data) | 528 | int mthd, uint32_t data) |
| 529 | { | 529 | { |
| 530 | chan->fence.last_sequence_irq = data; | 530 | atomic_set(&chan->fence.last_sequence_irq, data); |
| 531 | nouveau_fence_handler(chan->dev, chan->id); | ||
| 532 | return 0; | 531 | return 0; |
| 533 | } | 532 | } |
| 534 | 533 | ||
diff --git a/drivers/gpu/drm/nouveau/nv04_instmem.c b/drivers/gpu/drm/nouveau/nv04_instmem.c index a3b9563a6f60..4408232d33f1 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) | |||
| 49 | NV_DEBUG(dev, "RAMIN size: %dKiB\n", dev_priv->ramin_rsvd_vram >> 10); | 49 | NV_DEBUG(dev, "RAMIN size: %dKiB\n", dev_priv->ramin_rsvd_vram >> 10); |
| 50 | 50 | ||
| 51 | /* Clear all of it, except the BIOS image that's in the first 64KiB */ | 51 | /* Clear all of it, except the BIOS image that's in the first 64KiB */ |
| 52 | dev_priv->engine.instmem.prepare_access(dev, true); | ||
| 53 | for (i = 64 * 1024; i < dev_priv->ramin_rsvd_vram; i += 4) | 52 | for (i = 64 * 1024; i < dev_priv->ramin_rsvd_vram; i += 4) |
| 54 | nv_wi32(dev, i, 0x00000000); | 53 | nv_wi32(dev, i, 0x00000000); |
| 55 | dev_priv->engine.instmem.finish_access(dev); | ||
| 56 | } | 54 | } |
| 57 | 55 | ||
| 58 | static void | 56 | static void |
| @@ -106,7 +104,7 @@ int nv04_instmem_init(struct drm_device *dev) | |||
| 106 | { | 104 | { |
| 107 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 105 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 108 | uint32_t offset; | 106 | uint32_t offset; |
| 109 | int ret = 0; | 107 | int ret; |
| 110 | 108 | ||
| 111 | nv04_instmem_determine_amount(dev); | 109 | nv04_instmem_determine_amount(dev); |
| 112 | nv04_instmem_configure_fixed_tables(dev); | 110 | nv04_instmem_configure_fixed_tables(dev); |
| @@ -129,14 +127,14 @@ int nv04_instmem_init(struct drm_device *dev) | |||
| 129 | offset = 0x40000; | 127 | offset = 0x40000; |
| 130 | } | 128 | } |
| 131 | 129 | ||
| 132 | ret = nouveau_mem_init_heap(&dev_priv->ramin_heap, | 130 | ret = drm_mm_init(&dev_priv->ramin_heap, offset, |
| 133 | offset, dev_priv->ramin_rsvd_vram - offset); | 131 | dev_priv->ramin_rsvd_vram - offset); |
| 134 | if (ret) { | 132 | if (ret) { |
| 135 | dev_priv->ramin_heap = NULL; | 133 | NV_ERROR(dev, "Failed to init RAMIN heap: %d\n", ret); |
| 136 | NV_ERROR(dev, "Failed to init RAMIN heap\n"); | 134 | return ret; |
| 137 | } | 135 | } |
| 138 | 136 | ||
| 139 | return ret; | 137 | return 0; |
| 140 | } | 138 | } |
| 141 | 139 | ||
| 142 | void | 140 | void |
| @@ -186,12 +184,7 @@ nv04_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | |||
| 186 | } | 184 | } |
| 187 | 185 | ||
| 188 | void | 186 | void |
| 189 | nv04_instmem_prepare_access(struct drm_device *dev, bool write) | 187 | nv04_instmem_flush(struct drm_device *dev) |
| 190 | { | ||
| 191 | } | ||
| 192 | |||
| 193 | void | ||
| 194 | nv04_instmem_finish_access(struct drm_device *dev) | ||
| 195 | { | 188 | { |
| 196 | } | 189 | } |
| 197 | 190 | ||
diff --git a/drivers/gpu/drm/nouveau/nv04_mc.c b/drivers/gpu/drm/nouveau/nv04_mc.c index 617ed1e05269..2af43a1cb2ec 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) | |||
| 11 | */ | 11 | */ |
| 12 | 12 | ||
| 13 | nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF); | 13 | nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF); |
| 14 | |||
| 15 | /* Disable PROM access. */ | ||
| 16 | nv_wr32(dev, NV_PBUS_PCI_NV_20, NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED); | ||
| 17 | |||
| 14 | return 0; | 18 | return 0; |
| 15 | } | 19 | } |
| 16 | 20 | ||
diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/nv04_tv.c index c4e3404337d4..94e299cef0b2 100644 --- a/drivers/gpu/drm/nouveau/nv04_tv.c +++ b/drivers/gpu/drm/nouveau/nv04_tv.c | |||
| @@ -34,69 +34,26 @@ | |||
| 34 | 34 | ||
| 35 | #include "i2c/ch7006.h" | 35 | #include "i2c/ch7006.h" |
| 36 | 36 | ||
| 37 | static struct { | 37 | static struct i2c_board_info nv04_tv_encoder_info[] = { |
| 38 | struct i2c_board_info board_info; | ||
| 39 | struct drm_encoder_funcs funcs; | ||
| 40 | struct drm_encoder_helper_funcs hfuncs; | ||
| 41 | void *params; | ||
| 42 | |||
| 43 | } nv04_tv_encoder_info[] = { | ||
| 44 | { | 38 | { |
| 45 | .board_info = { I2C_BOARD_INFO("ch7006", 0x75) }, | 39 | I2C_BOARD_INFO("ch7006", 0x75), |
| 46 | .params = &(struct ch7006_encoder_params) { | 40 | .platform_data = &(struct ch7006_encoder_params) { |
| 47 | CH7006_FORMAT_RGB24m12I, CH7006_CLOCK_MASTER, | 41 | CH7006_FORMAT_RGB24m12I, CH7006_CLOCK_MASTER, |
| 48 | 0, 0, 0, | 42 | 0, 0, 0, |
| 49 | CH7006_SYNC_SLAVE, CH7006_SYNC_SEPARATED, | 43 | CH7006_SYNC_SLAVE, CH7006_SYNC_SEPARATED, |
| 50 | CH7006_POUT_3_3V, CH7006_ACTIVE_HSYNC | 44 | CH7006_POUT_3_3V, CH7006_ACTIVE_HSYNC |
| 51 | }, | 45 | } |
| 52 | }, | 46 | }, |
| 47 | { } | ||
| 53 | }; | 48 | }; |
| 54 | 49 | ||
| 55 | static bool probe_i2c_addr(struct i2c_adapter *adapter, int addr) | ||
| 56 | { | ||
| 57 | struct i2c_msg msg = { | ||
| 58 | .addr = addr, | ||
| 59 | .len = 0, | ||
| 60 | }; | ||
| 61 | |||
| 62 | return i2c_transfer(adapter, &msg, 1) == 1; | ||
| 63 | } | ||
| 64 | |||
| 65 | int nv04_tv_identify(struct drm_device *dev, int i2c_index) | 50 | int nv04_tv_identify(struct drm_device *dev, int i2c_index) |
| 66 | { | 51 | { |
| 67 | struct nouveau_i2c_chan *i2c; | 52 | return nouveau_i2c_identify(dev, "TV encoder", |
| 68 | bool was_locked; | 53 | nv04_tv_encoder_info, i2c_index); |
| 69 | int i, ret; | ||
| 70 | |||
| 71 | NV_TRACE(dev, "Probing TV encoders on I2C bus: %d\n", i2c_index); | ||
| 72 | |||
| 73 | i2c = nouveau_i2c_find(dev, i2c_index); | ||
| 74 | if (!i2c) | ||
| 75 | return -ENODEV; | ||
| 76 | |||
| 77 | was_locked = NVLockVgaCrtcs(dev, false); | ||
| 78 | |||
| 79 | for (i = 0; i < ARRAY_SIZE(nv04_tv_encoder_info); i++) { | ||
| 80 | if (probe_i2c_addr(&i2c->adapter, | ||
| 81 | nv04_tv_encoder_info[i].board_info.addr)) { | ||
| 82 | ret = i; | ||
| 83 | break; | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 87 | if (i < ARRAY_SIZE(nv04_tv_encoder_info)) { | ||
| 88 | NV_TRACE(dev, "Detected TV encoder: %s\n", | ||
| 89 | nv04_tv_encoder_info[i].board_info.type); | ||
| 90 | |||
| 91 | } else { | ||
| 92 | NV_TRACE(dev, "No TV encoders found.\n"); | ||
| 93 | i = -ENODEV; | ||
| 94 | } | ||
| 95 | |||
| 96 | NVLockVgaCrtcs(dev, was_locked); | ||
| 97 | return i; | ||
| 98 | } | 54 | } |
| 99 | 55 | ||
| 56 | |||
| 100 | #define PLLSEL_TV_CRTC1_MASK \ | 57 | #define PLLSEL_TV_CRTC1_MASK \ |
| 101 | (NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK1 \ | 58 | (NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK1 \ |
| 102 | | NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK1) | 59 | | NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK1) |
| @@ -214,30 +171,32 @@ static void nv04_tv_commit(struct drm_encoder *encoder) | |||
| 214 | 171 | ||
| 215 | static void nv04_tv_destroy(struct drm_encoder *encoder) | 172 | static void nv04_tv_destroy(struct drm_encoder *encoder) |
| 216 | { | 173 | { |
| 217 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||
| 218 | |||
| 219 | to_encoder_slave(encoder)->slave_funcs->destroy(encoder); | 174 | to_encoder_slave(encoder)->slave_funcs->destroy(encoder); |
| 220 | 175 | ||
| 221 | drm_encoder_cleanup(encoder); | 176 | drm_encoder_cleanup(encoder); |
| 222 | 177 | ||
| 223 | kfree(nv_encoder); | 178 | kfree(encoder->helper_private); |
| 179 | kfree(nouveau_encoder(encoder)); | ||
| 224 | } | 180 | } |
| 225 | 181 | ||
| 226 | int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry) | 182 | static const struct drm_encoder_funcs nv04_tv_funcs = { |
| 183 | .destroy = nv04_tv_destroy, | ||
| 184 | }; | ||
| 185 | |||
| 186 | int | ||
| 187 | nv04_tv_create(struct drm_connector *connector, struct dcb_entry *entry) | ||
| 227 | { | 188 | { |
| 228 | struct nouveau_encoder *nv_encoder; | 189 | struct nouveau_encoder *nv_encoder; |
| 229 | struct drm_encoder *encoder; | 190 | struct drm_encoder *encoder; |
| 230 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 191 | struct drm_device *dev = connector->dev; |
| 231 | struct i2c_adapter *adap; | 192 | struct drm_encoder_helper_funcs *hfuncs; |
| 232 | struct drm_encoder_funcs *funcs = NULL; | 193 | struct drm_encoder_slave_funcs *sfuncs; |
| 233 | struct drm_encoder_helper_funcs *hfuncs = NULL; | 194 | struct nouveau_i2c_chan *i2c = |
| 234 | struct drm_encoder_slave_funcs *sfuncs = NULL; | 195 | nouveau_i2c_find(dev, entry->i2c_index); |
| 235 | int i2c_index = entry->i2c_index; | ||
| 236 | int type, ret; | 196 | int type, ret; |
| 237 | bool was_locked; | ||
| 238 | 197 | ||
| 239 | /* Ensure that we can talk to this encoder */ | 198 | /* Ensure that we can talk to this encoder */ |
| 240 | type = nv04_tv_identify(dev, i2c_index); | 199 | type = nv04_tv_identify(dev, entry->i2c_index); |
| 241 | if (type < 0) | 200 | if (type < 0) |
| 242 | return type; | 201 | return type; |
| 243 | 202 | ||
| @@ -246,41 +205,32 @@ int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry) | |||
| 246 | if (!nv_encoder) | 205 | if (!nv_encoder) |
| 247 | return -ENOMEM; | 206 | return -ENOMEM; |
| 248 | 207 | ||
| 208 | hfuncs = kzalloc(sizeof(*hfuncs), GFP_KERNEL); | ||
| 209 | if (!hfuncs) { | ||
| 210 | ret = -ENOMEM; | ||
| 211 | goto fail_free; | ||
| 212 | } | ||
| 213 | |||
| 249 | /* Initialize the common members */ | 214 | /* Initialize the common members */ |
| 250 | encoder = to_drm_encoder(nv_encoder); | 215 | encoder = to_drm_encoder(nv_encoder); |
| 251 | 216 | ||
| 252 | funcs = &nv04_tv_encoder_info[type].funcs; | 217 | drm_encoder_init(dev, encoder, &nv04_tv_funcs, DRM_MODE_ENCODER_TVDAC); |
| 253 | hfuncs = &nv04_tv_encoder_info[type].hfuncs; | ||
| 254 | |||
| 255 | drm_encoder_init(dev, encoder, funcs, DRM_MODE_ENCODER_TVDAC); | ||
| 256 | drm_encoder_helper_add(encoder, hfuncs); | 218 | drm_encoder_helper_add(encoder, hfuncs); |
| 257 | 219 | ||
| 258 | encoder->possible_crtcs = entry->heads; | 220 | encoder->possible_crtcs = entry->heads; |
| 259 | encoder->possible_clones = 0; | 221 | encoder->possible_clones = 0; |
| 260 | |||
| 261 | nv_encoder->dcb = entry; | 222 | nv_encoder->dcb = entry; |
| 262 | nv_encoder->or = ffs(entry->or) - 1; | 223 | nv_encoder->or = ffs(entry->or) - 1; |
| 263 | 224 | ||
| 264 | /* Run the slave-specific initialization */ | 225 | /* Run the slave-specific initialization */ |
| 265 | adap = &dev_priv->vbios.dcb.i2c[i2c_index].chan->adapter; | 226 | ret = drm_i2c_encoder_init(dev, to_encoder_slave(encoder), |
| 266 | 227 | &i2c->adapter, &nv04_tv_encoder_info[type]); | |
| 267 | was_locked = NVLockVgaCrtcs(dev, false); | ||
| 268 | |||
| 269 | ret = drm_i2c_encoder_init(encoder->dev, to_encoder_slave(encoder), adap, | ||
| 270 | &nv04_tv_encoder_info[type].board_info); | ||
| 271 | |||
| 272 | NVLockVgaCrtcs(dev, was_locked); | ||
| 273 | |||
| 274 | if (ret < 0) | 228 | if (ret < 0) |
| 275 | goto fail; | 229 | goto fail_cleanup; |
| 276 | 230 | ||
| 277 | /* Fill the function pointers */ | 231 | /* Fill the function pointers */ |
| 278 | sfuncs = to_encoder_slave(encoder)->slave_funcs; | 232 | sfuncs = to_encoder_slave(encoder)->slave_funcs; |
| 279 | 233 | ||
| 280 | *funcs = (struct drm_encoder_funcs) { | ||
| 281 | .destroy = nv04_tv_destroy, | ||
| 282 | }; | ||
| 283 | |||
| 284 | *hfuncs = (struct drm_encoder_helper_funcs) { | 234 | *hfuncs = (struct drm_encoder_helper_funcs) { |
| 285 | .dpms = nv04_tv_dpms, | 235 | .dpms = nv04_tv_dpms, |
| 286 | .save = sfuncs->save, | 236 | .save = sfuncs->save, |
| @@ -292,14 +242,17 @@ int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry) | |||
| 292 | .detect = sfuncs->detect, | 242 | .detect = sfuncs->detect, |
| 293 | }; | 243 | }; |
| 294 | 244 | ||
| 295 | /* Set the slave encoder configuration */ | 245 | /* Attach it to the specified connector. */ |
| 296 | sfuncs->set_config(encoder, nv04_tv_encoder_info[type].params); | 246 | sfuncs->set_config(encoder, nv04_tv_encoder_info[type].platform_data); |
| 247 | sfuncs->create_resources(encoder, connector); | ||
| 248 | drm_mode_connector_attach_encoder(connector, encoder); | ||
| 297 | 249 | ||
| 298 | return 0; | 250 | return 0; |
| 299 | 251 | ||
| 300 | fail: | 252 | fail_cleanup: |
| 301 | drm_encoder_cleanup(encoder); | 253 | drm_encoder_cleanup(encoder); |
| 302 | 254 | kfree(hfuncs); | |
| 255 | fail_free: | ||
| 303 | kfree(nv_encoder); | 256 | kfree(nv_encoder); |
| 304 | return ret; | 257 | return ret; |
| 305 | } | 258 | } |
diff --git a/drivers/gpu/drm/nouveau/nv10_fifo.c b/drivers/gpu/drm/nouveau/nv10_fifo.c index 7aeabf262bc0..7a4069cf5d0b 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) | |||
| 55 | /* Fill entries that are seen filled in dumps of nvidia driver just | 55 | /* Fill entries that are seen filled in dumps of nvidia driver just |
| 56 | * after channel's is put into DMA mode | 56 | * after channel's is put into DMA mode |
| 57 | */ | 57 | */ |
| 58 | dev_priv->engine.instmem.prepare_access(dev, true); | ||
| 59 | nv_wi32(dev, fc + 0, chan->pushbuf_base); | 58 | nv_wi32(dev, fc + 0, chan->pushbuf_base); |
| 60 | nv_wi32(dev, fc + 4, chan->pushbuf_base); | 59 | nv_wi32(dev, fc + 4, chan->pushbuf_base); |
| 61 | nv_wi32(dev, fc + 12, chan->pushbuf->instance >> 4); | 60 | nv_wi32(dev, fc + 12, chan->pushbuf->instance >> 4); |
| @@ -66,7 +65,6 @@ nv10_fifo_create_context(struct nouveau_channel *chan) | |||
| 66 | NV_PFIFO_CACHE1_BIG_ENDIAN | | 65 | NV_PFIFO_CACHE1_BIG_ENDIAN | |
| 67 | #endif | 66 | #endif |
| 68 | 0); | 67 | 0); |
| 69 | dev_priv->engine.instmem.finish_access(dev); | ||
| 70 | 68 | ||
| 71 | /* enable the fifo dma operation */ | 69 | /* enable the fifo dma operation */ |
| 72 | nv_wr32(dev, NV04_PFIFO_MODE, | 70 | nv_wr32(dev, NV04_PFIFO_MODE, |
| @@ -91,8 +89,6 @@ nv10_fifo_do_load_context(struct drm_device *dev, int chid) | |||
| 91 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 89 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 92 | uint32_t fc = NV10_RAMFC(chid), tmp; | 90 | uint32_t fc = NV10_RAMFC(chid), tmp; |
| 93 | 91 | ||
| 94 | dev_priv->engine.instmem.prepare_access(dev, false); | ||
| 95 | |||
| 96 | nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0)); | 92 | nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0)); |
| 97 | nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4)); | 93 | nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4)); |
| 98 | nv_wr32(dev, NV10_PFIFO_CACHE1_REF_CNT, nv_ri32(dev, fc + 8)); | 94 | 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) | |||
| 117 | nv_wr32(dev, NV10_PFIFO_CACHE1_DMA_SUBROUTINE, nv_ri32(dev, fc + 48)); | 113 | nv_wr32(dev, NV10_PFIFO_CACHE1_DMA_SUBROUTINE, nv_ri32(dev, fc + 48)); |
| 118 | 114 | ||
| 119 | out: | 115 | out: |
| 120 | dev_priv->engine.instmem.finish_access(dev); | ||
| 121 | |||
| 122 | nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); | 116 | nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); |
| 123 | nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0); | 117 | nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0); |
| 124 | } | 118 | } |
| @@ -155,8 +149,6 @@ nv10_fifo_unload_context(struct drm_device *dev) | |||
| 155 | return 0; | 149 | return 0; |
| 156 | fc = NV10_RAMFC(chid); | 150 | fc = NV10_RAMFC(chid); |
| 157 | 151 | ||
| 158 | dev_priv->engine.instmem.prepare_access(dev, true); | ||
| 159 | |||
| 160 | nv_wi32(dev, fc + 0, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT)); | 152 | nv_wi32(dev, fc + 0, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT)); |
| 161 | nv_wi32(dev, fc + 4, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET)); | 153 | nv_wi32(dev, fc + 4, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET)); |
| 162 | nv_wi32(dev, fc + 8, nv_rd32(dev, NV10_PFIFO_CACHE1_REF_CNT)); | 154 | 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) | |||
| 179 | nv_wi32(dev, fc + 48, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET)); | 171 | nv_wi32(dev, fc + 48, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET)); |
| 180 | 172 | ||
| 181 | out: | 173 | out: |
| 182 | dev_priv->engine.instmem.finish_access(dev); | ||
| 183 | |||
| 184 | nv10_fifo_do_load_context(dev, pfifo->channels - 1); | 174 | nv10_fifo_do_load_context(dev, pfifo->channels - 1); |
| 185 | nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1); | 175 | nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1); |
| 186 | return 0; | 176 | return 0; |
diff --git a/drivers/gpu/drm/nouveau/nv17_gpio.c b/drivers/gpu/drm/nouveau/nv10_gpio.c index 2e58c331e9b7..007fc29e2f86 100644 --- a/drivers/gpu/drm/nouveau/nv17_gpio.c +++ b/drivers/gpu/drm/nouveau/nv10_gpio.c | |||
| @@ -55,7 +55,7 @@ get_gpio_location(struct dcb_gpio_entry *ent, uint32_t *reg, uint32_t *shift, | |||
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | int | 57 | int |
| 58 | nv17_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag) | 58 | nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag) |
| 59 | { | 59 | { |
| 60 | struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag); | 60 | struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag); |
| 61 | uint32_t reg, shift, mask, value; | 61 | uint32_t reg, shift, mask, value; |
| @@ -72,7 +72,7 @@ nv17_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag) | |||
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | int | 74 | int |
| 75 | nv17_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state) | 75 | nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state) |
| 76 | { | 76 | { |
| 77 | struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag); | 77 | struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag); |
| 78 | uint32_t reg, shift, mask, value; | 78 | uint32_t reg, shift, mask, value; |
diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c b/drivers/gpu/drm/nouveau/nv17_tv.c index 74c880374fb9..44fefb0c7083 100644 --- a/drivers/gpu/drm/nouveau/nv17_tv.c +++ b/drivers/gpu/drm/nouveau/nv17_tv.c | |||
| @@ -37,6 +37,7 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) | |||
| 37 | { | 37 | { |
| 38 | struct drm_device *dev = encoder->dev; | 38 | struct drm_device *dev = encoder->dev; |
| 39 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 39 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 40 | struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio; | ||
| 40 | uint32_t testval, regoffset = nv04_dac_output_offset(encoder); | 41 | uint32_t testval, regoffset = nv04_dac_output_offset(encoder); |
| 41 | uint32_t gpio0, gpio1, fp_htotal, fp_hsync_start, fp_hsync_end, | 42 | uint32_t gpio0, gpio1, fp_htotal, fp_hsync_start, fp_hsync_end, |
| 42 | fp_control, test_ctrl, dacclk, ctv_14, ctv_1c, ctv_6c; | 43 | fp_control, test_ctrl, dacclk, ctv_14, ctv_1c, ctv_6c; |
| @@ -52,8 +53,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) | |||
| 52 | head = (dacclk & 0x100) >> 8; | 53 | head = (dacclk & 0x100) >> 8; |
| 53 | 54 | ||
| 54 | /* Save the previous state. */ | 55 | /* Save the previous state. */ |
| 55 | gpio1 = nv17_gpio_get(dev, DCB_GPIO_TVDAC1); | 56 | gpio1 = gpio->get(dev, DCB_GPIO_TVDAC1); |
| 56 | gpio0 = nv17_gpio_get(dev, DCB_GPIO_TVDAC0); | 57 | gpio0 = gpio->get(dev, DCB_GPIO_TVDAC0); |
| 57 | fp_htotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL); | 58 | fp_htotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL); |
| 58 | fp_hsync_start = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START); | 59 | fp_hsync_start = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START); |
| 59 | fp_hsync_end = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END); | 60 | fp_hsync_end = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END); |
| @@ -64,8 +65,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) | |||
| 64 | ctv_6c = NVReadRAMDAC(dev, head, 0x680c6c); | 65 | ctv_6c = NVReadRAMDAC(dev, head, 0x680c6c); |
| 65 | 66 | ||
| 66 | /* Prepare the DAC for load detection. */ | 67 | /* Prepare the DAC for load detection. */ |
| 67 | nv17_gpio_set(dev, DCB_GPIO_TVDAC1, true); | 68 | gpio->set(dev, DCB_GPIO_TVDAC1, true); |
| 68 | nv17_gpio_set(dev, DCB_GPIO_TVDAC0, true); | 69 | gpio->set(dev, DCB_GPIO_TVDAC0, true); |
| 69 | 70 | ||
| 70 | NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, 1343); | 71 | NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, 1343); |
| 71 | NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, 1047); | 72 | NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, 1047); |
| @@ -110,12 +111,27 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) | |||
| 110 | NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, fp_hsync_end); | 111 | NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, fp_hsync_end); |
| 111 | NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, fp_hsync_start); | 112 | NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, fp_hsync_start); |
| 112 | NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, fp_htotal); | 113 | NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, fp_htotal); |
| 113 | nv17_gpio_set(dev, DCB_GPIO_TVDAC1, gpio1); | 114 | gpio->set(dev, DCB_GPIO_TVDAC1, gpio1); |
| 114 | nv17_gpio_set(dev, DCB_GPIO_TVDAC0, gpio0); | 115 | gpio->set(dev, DCB_GPIO_TVDAC0, gpio0); |
| 115 | 116 | ||
| 116 | return sample; | 117 | return sample; |
| 117 | } | 118 | } |
| 118 | 119 | ||
| 120 | static bool | ||
| 121 | get_tv_detect_quirks(struct drm_device *dev, uint32_t *pin_mask) | ||
| 122 | { | ||
| 123 | /* Zotac FX5200 */ | ||
| 124 | if (dev->pdev->device == 0x0322 && | ||
| 125 | dev->pdev->subsystem_vendor == 0x19da && | ||
| 126 | (dev->pdev->subsystem_device == 0x1035 || | ||
| 127 | dev->pdev->subsystem_device == 0x2035)) { | ||
| 128 | *pin_mask = 0xc; | ||
| 129 | return false; | ||
| 130 | } | ||
| 131 | |||
| 132 | return true; | ||
| 133 | } | ||
| 134 | |||
| 119 | static enum drm_connector_status | 135 | static enum drm_connector_status |
| 120 | nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) | 136 | nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) |
| 121 | { | 137 | { |
| @@ -124,12 +140,20 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) | |||
| 124 | struct drm_mode_config *conf = &dev->mode_config; | 140 | struct drm_mode_config *conf = &dev->mode_config; |
| 125 | struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); | 141 | struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); |
| 126 | struct dcb_entry *dcb = tv_enc->base.dcb; | 142 | struct dcb_entry *dcb = tv_enc->base.dcb; |
| 143 | bool reliable = get_tv_detect_quirks(dev, &tv_enc->pin_mask); | ||
| 127 | 144 | ||
| 128 | if (dev_priv->chipset == 0x42 || | 145 | if (nv04_dac_in_use(encoder)) |
| 129 | dev_priv->chipset == 0x43) | 146 | return connector_status_disconnected; |
| 130 | tv_enc->pin_mask = nv42_tv_sample_load(encoder) >> 28 & 0xe; | 147 | |
| 131 | else | 148 | if (reliable) { |
| 132 | tv_enc->pin_mask = nv17_dac_sample_load(encoder) >> 28 & 0xe; | 149 | if (dev_priv->chipset == 0x42 || |
| 150 | dev_priv->chipset == 0x43) | ||
| 151 | tv_enc->pin_mask = | ||
| 152 | nv42_tv_sample_load(encoder) >> 28 & 0xe; | ||
| 153 | else | ||
| 154 | tv_enc->pin_mask = | ||
| 155 | nv17_dac_sample_load(encoder) >> 28 & 0xe; | ||
| 156 | } | ||
| 133 | 157 | ||
| 134 | switch (tv_enc->pin_mask) { | 158 | switch (tv_enc->pin_mask) { |
| 135 | case 0x2: | 159 | case 0x2: |
| @@ -154,7 +178,9 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) | |||
| 154 | conf->tv_subconnector_property, | 178 | conf->tv_subconnector_property, |
| 155 | tv_enc->subconnector); | 179 | tv_enc->subconnector); |
| 156 | 180 | ||
| 157 | if (tv_enc->subconnector) { | 181 | if (!reliable) { |
| 182 | return connector_status_unknown; | ||
| 183 | } else if (tv_enc->subconnector) { | ||
| 158 | NV_INFO(dev, "Load detected on output %c\n", | 184 | NV_INFO(dev, "Load detected on output %c\n", |
| 159 | '@' + ffs(dcb->or)); | 185 | '@' + ffs(dcb->or)); |
| 160 | return connector_status_connected; | 186 | return connector_status_connected; |
| @@ -296,6 +322,9 @@ static bool nv17_tv_mode_fixup(struct drm_encoder *encoder, | |||
| 296 | { | 322 | { |
| 297 | struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); | 323 | struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); |
| 298 | 324 | ||
| 325 | if (nv04_dac_in_use(encoder)) | ||
| 326 | return false; | ||
| 327 | |||
| 299 | if (tv_norm->kind == CTV_ENC_MODE) | 328 | if (tv_norm->kind == CTV_ENC_MODE) |
| 300 | adjusted_mode->clock = tv_norm->ctv_enc_mode.mode.clock; | 329 | adjusted_mode->clock = tv_norm->ctv_enc_mode.mode.clock; |
| 301 | else | 330 | else |
| @@ -307,6 +336,8 @@ static bool nv17_tv_mode_fixup(struct drm_encoder *encoder, | |||
| 307 | static void nv17_tv_dpms(struct drm_encoder *encoder, int mode) | 336 | static void nv17_tv_dpms(struct drm_encoder *encoder, int mode) |
| 308 | { | 337 | { |
| 309 | struct drm_device *dev = encoder->dev; | 338 | struct drm_device *dev = encoder->dev; |
| 339 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 340 | struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio; | ||
| 310 | struct nv17_tv_state *regs = &to_tv_enc(encoder)->state; | 341 | struct nv17_tv_state *regs = &to_tv_enc(encoder)->state; |
| 311 | struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); | 342 | struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); |
| 312 | 343 | ||
| @@ -331,8 +362,8 @@ static void nv17_tv_dpms(struct drm_encoder *encoder, int mode) | |||
| 331 | 362 | ||
| 332 | nv_load_ptv(dev, regs, 200); | 363 | nv_load_ptv(dev, regs, 200); |
| 333 | 364 | ||
| 334 | nv17_gpio_set(dev, DCB_GPIO_TVDAC1, mode == DRM_MODE_DPMS_ON); | 365 | gpio->set(dev, DCB_GPIO_TVDAC1, mode == DRM_MODE_DPMS_ON); |
| 335 | nv17_gpio_set(dev, DCB_GPIO_TVDAC0, mode == DRM_MODE_DPMS_ON); | 366 | gpio->set(dev, DCB_GPIO_TVDAC0, mode == DRM_MODE_DPMS_ON); |
| 336 | 367 | ||
| 337 | nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON); | 368 | nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON); |
| 338 | } | 369 | } |
| @@ -744,8 +775,10 @@ static struct drm_encoder_funcs nv17_tv_funcs = { | |||
| 744 | .destroy = nv17_tv_destroy, | 775 | .destroy = nv17_tv_destroy, |
| 745 | }; | 776 | }; |
| 746 | 777 | ||
| 747 | int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry) | 778 | int |
| 779 | nv17_tv_create(struct drm_connector *connector, struct dcb_entry *entry) | ||
| 748 | { | 780 | { |
| 781 | struct drm_device *dev = connector->dev; | ||
| 749 | struct drm_encoder *encoder; | 782 | struct drm_encoder *encoder; |
| 750 | struct nv17_tv_encoder *tv_enc = NULL; | 783 | struct nv17_tv_encoder *tv_enc = NULL; |
| 751 | 784 | ||
| @@ -774,5 +807,7 @@ int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry) | |||
| 774 | encoder->possible_crtcs = entry->heads; | 807 | encoder->possible_crtcs = entry->heads; |
| 775 | encoder->possible_clones = 0; | 808 | encoder->possible_clones = 0; |
| 776 | 809 | ||
| 810 | nv17_tv_create_resources(encoder, connector); | ||
| 811 | drm_mode_connector_attach_encoder(connector, encoder); | ||
| 777 | return 0; | 812 | return 0; |
| 778 | } | 813 | } |
diff --git a/drivers/gpu/drm/nouveau/nv20_graph.c b/drivers/gpu/drm/nouveau/nv20_graph.c index d6fc0a82f03d..17f309b36c91 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) | |||
| 370 | { | 370 | { |
| 371 | struct drm_device *dev = chan->dev; | 371 | struct drm_device *dev = chan->dev; |
| 372 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 372 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 373 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; | ||
| 373 | void (*ctx_init)(struct drm_device *, struct nouveau_gpuobj *); | 374 | void (*ctx_init)(struct drm_device *, struct nouveau_gpuobj *); |
| 374 | unsigned int ctx_size; | ||
| 375 | unsigned int idoffs = 0x28/4; | 375 | unsigned int idoffs = 0x28/4; |
| 376 | int ret; | 376 | int ret; |
| 377 | 377 | ||
| 378 | switch (dev_priv->chipset) { | 378 | switch (dev_priv->chipset) { |
| 379 | case 0x20: | 379 | case 0x20: |
| 380 | ctx_size = NV20_GRCTX_SIZE; | ||
| 381 | ctx_init = nv20_graph_context_init; | 380 | ctx_init = nv20_graph_context_init; |
| 382 | idoffs = 0; | 381 | idoffs = 0; |
| 383 | break; | 382 | break; |
| 384 | case 0x25: | 383 | case 0x25: |
| 385 | case 0x28: | 384 | case 0x28: |
| 386 | ctx_size = NV25_GRCTX_SIZE; | ||
| 387 | ctx_init = nv25_graph_context_init; | 385 | ctx_init = nv25_graph_context_init; |
| 388 | break; | 386 | break; |
| 389 | case 0x2a: | 387 | case 0x2a: |
| 390 | ctx_size = NV2A_GRCTX_SIZE; | ||
| 391 | ctx_init = nv2a_graph_context_init; | 388 | ctx_init = nv2a_graph_context_init; |
| 392 | idoffs = 0; | 389 | idoffs = 0; |
| 393 | break; | 390 | break; |
| 394 | case 0x30: | 391 | case 0x30: |
| 395 | case 0x31: | 392 | case 0x31: |
| 396 | ctx_size = NV30_31_GRCTX_SIZE; | ||
| 397 | ctx_init = nv30_31_graph_context_init; | 393 | ctx_init = nv30_31_graph_context_init; |
| 398 | break; | 394 | break; |
| 399 | case 0x34: | 395 | case 0x34: |
| 400 | ctx_size = NV34_GRCTX_SIZE; | ||
| 401 | ctx_init = nv34_graph_context_init; | 396 | ctx_init = nv34_graph_context_init; |
| 402 | break; | 397 | break; |
| 403 | case 0x35: | 398 | case 0x35: |
| 404 | case 0x36: | 399 | case 0x36: |
| 405 | ctx_size = NV35_36_GRCTX_SIZE; | ||
| 406 | ctx_init = nv35_36_graph_context_init; | 400 | ctx_init = nv35_36_graph_context_init; |
| 407 | break; | 401 | break; |
| 408 | default: | 402 | default: |
| 409 | ctx_size = 0; | 403 | BUG_ON(1); |
| 410 | ctx_init = nv35_36_graph_context_init; | ||
| 411 | NV_ERROR(dev, "Please contact the devs if you want your NV%x" | ||
| 412 | " card to work\n", dev_priv->chipset); | ||
| 413 | return -ENOSYS; | ||
| 414 | break; | ||
| 415 | } | 404 | } |
| 416 | 405 | ||
| 417 | ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, ctx_size, 16, | 406 | ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pgraph->grctx_size, |
| 418 | NVOBJ_FLAG_ZERO_ALLOC, | 407 | 16, NVOBJ_FLAG_ZERO_ALLOC, |
| 419 | &chan->ramin_grctx); | 408 | &chan->ramin_grctx); |
| 420 | if (ret) | 409 | if (ret) |
| 421 | return ret; | 410 | return ret; |
| 422 | 411 | ||
| 423 | /* Initialise default context values */ | 412 | /* Initialise default context values */ |
| 424 | dev_priv->engine.instmem.prepare_access(dev, true); | ||
| 425 | ctx_init(dev, chan->ramin_grctx->gpuobj); | 413 | ctx_init(dev, chan->ramin_grctx->gpuobj); |
| 426 | 414 | ||
| 427 | /* nv20: nv_wo32(dev, chan->ramin_grctx->gpuobj, 10, chan->id<<24); */ | 415 | /* nv20: nv_wo32(dev, chan->ramin_grctx->gpuobj, 10, chan->id<<24); */ |
| 428 | nv_wo32(dev, chan->ramin_grctx->gpuobj, idoffs, | 416 | nv_wo32(dev, chan->ramin_grctx->gpuobj, idoffs, |
| 429 | (chan->id << 24) | 0x1); /* CTX_USER */ | 417 | (chan->id << 24) | 0x1); /* CTX_USER */ |
| 430 | 418 | ||
| 431 | nv_wo32(dev, dev_priv->ctx_table->gpuobj, chan->id, | 419 | nv_wo32(dev, pgraph->ctx_table->gpuobj, chan->id, |
| 432 | chan->ramin_grctx->instance >> 4); | 420 | chan->ramin_grctx->instance >> 4); |
| 433 | |||
| 434 | dev_priv->engine.instmem.finish_access(dev); | ||
| 435 | return 0; | 421 | return 0; |
| 436 | } | 422 | } |
| 437 | 423 | ||
| @@ -440,13 +426,12 @@ nv20_graph_destroy_context(struct nouveau_channel *chan) | |||
| 440 | { | 426 | { |
| 441 | struct drm_device *dev = chan->dev; | 427 | struct drm_device *dev = chan->dev; |
| 442 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 428 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 429 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; | ||
| 443 | 430 | ||
| 444 | if (chan->ramin_grctx) | 431 | if (chan->ramin_grctx) |
| 445 | nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx); | 432 | nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx); |
| 446 | 433 | ||
| 447 | dev_priv->engine.instmem.prepare_access(dev, true); | 434 | nv_wo32(dev, pgraph->ctx_table->gpuobj, chan->id, 0); |
| 448 | nv_wo32(dev, dev_priv->ctx_table->gpuobj, chan->id, 0); | ||
| 449 | dev_priv->engine.instmem.finish_access(dev); | ||
| 450 | } | 435 | } |
| 451 | 436 | ||
| 452 | int | 437 | int |
| @@ -538,29 +523,44 @@ nv20_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, | |||
| 538 | int | 523 | int |
| 539 | nv20_graph_init(struct drm_device *dev) | 524 | nv20_graph_init(struct drm_device *dev) |
| 540 | { | 525 | { |
| 541 | struct drm_nouveau_private *dev_priv = | 526 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 542 | (struct drm_nouveau_private *)dev->dev_private; | 527 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; |
| 543 | uint32_t tmp, vramsz; | 528 | uint32_t tmp, vramsz; |
| 544 | int ret, i; | 529 | int ret, i; |
| 545 | 530 | ||
| 531 | switch (dev_priv->chipset) { | ||
| 532 | case 0x20: | ||
| 533 | pgraph->grctx_size = NV20_GRCTX_SIZE; | ||
| 534 | break; | ||
| 535 | case 0x25: | ||
| 536 | case 0x28: | ||
| 537 | pgraph->grctx_size = NV25_GRCTX_SIZE; | ||
| 538 | break; | ||
| 539 | case 0x2a: | ||
| 540 | pgraph->grctx_size = NV2A_GRCTX_SIZE; | ||
| 541 | break; | ||
| 542 | default: | ||
| 543 | NV_ERROR(dev, "unknown chipset, disabling acceleration\n"); | ||
| 544 | pgraph->accel_blocked = true; | ||
| 545 | return 0; | ||
| 546 | } | ||
| 547 | |||
| 546 | nv_wr32(dev, NV03_PMC_ENABLE, | 548 | nv_wr32(dev, NV03_PMC_ENABLE, |
| 547 | nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PGRAPH); | 549 | nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PGRAPH); |
| 548 | nv_wr32(dev, NV03_PMC_ENABLE, | 550 | nv_wr32(dev, NV03_PMC_ENABLE, |
| 549 | nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PGRAPH); | 551 | nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PGRAPH); |
| 550 | 552 | ||
| 551 | if (!dev_priv->ctx_table) { | 553 | if (!pgraph->ctx_table) { |
| 552 | /* Create Context Pointer Table */ | 554 | /* Create Context Pointer Table */ |
| 553 | dev_priv->ctx_table_size = 32 * 4; | 555 | ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 32 * 4, 16, |
| 554 | ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, | ||
| 555 | dev_priv->ctx_table_size, 16, | ||
| 556 | NVOBJ_FLAG_ZERO_ALLOC, | 556 | NVOBJ_FLAG_ZERO_ALLOC, |
| 557 | &dev_priv->ctx_table); | 557 | &pgraph->ctx_table); |
| 558 | if (ret) | 558 | if (ret) |
| 559 | return ret; | 559 | return ret; |
| 560 | } | 560 | } |
| 561 | 561 | ||
| 562 | nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, | 562 | nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, |
| 563 | dev_priv->ctx_table->instance >> 4); | 563 | pgraph->ctx_table->instance >> 4); |
| 564 | 564 | ||
| 565 | nv20_graph_rdi(dev); | 565 | nv20_graph_rdi(dev); |
| 566 | 566 | ||
| @@ -616,7 +616,7 @@ nv20_graph_init(struct drm_device *dev) | |||
| 616 | nv_wr32(dev, NV10_PGRAPH_SURFACE, tmp); | 616 | nv_wr32(dev, NV10_PGRAPH_SURFACE, tmp); |
| 617 | 617 | ||
| 618 | /* begin RAM config */ | 618 | /* begin RAM config */ |
| 619 | vramsz = drm_get_resource_len(dev, 0) - 1; | 619 | vramsz = pci_resource_len(dev->pdev, 0) - 1; |
| 620 | nv_wr32(dev, 0x4009A4, nv_rd32(dev, NV04_PFB_CFG0)); | 620 | nv_wr32(dev, 0x4009A4, nv_rd32(dev, NV04_PFB_CFG0)); |
| 621 | nv_wr32(dev, 0x4009A8, nv_rd32(dev, NV04_PFB_CFG1)); | 621 | nv_wr32(dev, 0x4009A8, nv_rd32(dev, NV04_PFB_CFG1)); |
| 622 | nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0000); | 622 | nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0000); |
| @@ -644,34 +644,52 @@ void | |||
| 644 | nv20_graph_takedown(struct drm_device *dev) | 644 | nv20_graph_takedown(struct drm_device *dev) |
| 645 | { | 645 | { |
| 646 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 646 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 647 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; | ||
| 647 | 648 | ||
| 648 | nouveau_gpuobj_ref_del(dev, &dev_priv->ctx_table); | 649 | nouveau_gpuobj_ref_del(dev, &pgraph->ctx_table); |
| 649 | } | 650 | } |
| 650 | 651 | ||
| 651 | int | 652 | int |
| 652 | nv30_graph_init(struct drm_device *dev) | 653 | nv30_graph_init(struct drm_device *dev) |
| 653 | { | 654 | { |
| 654 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 655 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 656 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; | ||
| 655 | int ret, i; | 657 | int ret, i; |
| 656 | 658 | ||
| 659 | switch (dev_priv->chipset) { | ||
| 660 | case 0x30: | ||
| 661 | case 0x31: | ||
| 662 | pgraph->grctx_size = NV30_31_GRCTX_SIZE; | ||
| 663 | break; | ||
| 664 | case 0x34: | ||
| 665 | pgraph->grctx_size = NV34_GRCTX_SIZE; | ||
| 666 | break; | ||
| 667 | case 0x35: | ||
| 668 | case 0x36: | ||
| 669 | pgraph->grctx_size = NV35_36_GRCTX_SIZE; | ||
| 670 | break; | ||
| 671 | default: | ||
| 672 | NV_ERROR(dev, "unknown chipset, disabling acceleration\n"); | ||
| 673 | pgraph->accel_blocked = true; | ||
| 674 | return 0; | ||
| 675 | } | ||
| 676 | |||
| 657 | nv_wr32(dev, NV03_PMC_ENABLE, | 677 | nv_wr32(dev, NV03_PMC_ENABLE, |
| 658 | nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PGRAPH); | 678 | nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PGRAPH); |
| 659 | nv_wr32(dev, NV03_PMC_ENABLE, | 679 | nv_wr32(dev, NV03_PMC_ENABLE, |
| 660 | nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PGRAPH); | 680 | nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PGRAPH); |
| 661 | 681 | ||
| 662 | if (!dev_priv->ctx_table) { | 682 | if (!pgraph->ctx_table) { |
| 663 | /* Create Context Pointer Table */ | 683 | /* Create Context Pointer Table */ |
| 664 | dev_priv->ctx_table_size = 32 * 4; | 684 | ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 32 * 4, 16, |
| 665 | ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, | ||
| 666 | dev_priv->ctx_table_size, 16, | ||
| 667 | NVOBJ_FLAG_ZERO_ALLOC, | 685 | NVOBJ_FLAG_ZERO_ALLOC, |
| 668 | &dev_priv->ctx_table); | 686 | &pgraph->ctx_table); |
| 669 | if (ret) | 687 | if (ret) |
| 670 | return ret; | 688 | return ret; |
| 671 | } | 689 | } |
| 672 | 690 | ||
| 673 | nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, | 691 | nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, |
| 674 | dev_priv->ctx_table->instance >> 4); | 692 | pgraph->ctx_table->instance >> 4); |
| 675 | 693 | ||
| 676 | nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); | 694 | nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); |
| 677 | nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); | 695 | nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); |
| @@ -717,7 +735,7 @@ nv30_graph_init(struct drm_device *dev) | |||
| 717 | nv_wr32(dev, 0x0040075c , 0x00000001); | 735 | nv_wr32(dev, 0x0040075c , 0x00000001); |
| 718 | 736 | ||
| 719 | /* begin RAM config */ | 737 | /* begin RAM config */ |
| 720 | /* vramsz = drm_get_resource_len(dev, 0) - 1; */ | 738 | /* vramsz = pci_resource_len(dev->pdev, 0) - 1; */ |
| 721 | nv_wr32(dev, 0x4009A4, nv_rd32(dev, NV04_PFB_CFG0)); | 739 | nv_wr32(dev, 0x4009A4, nv_rd32(dev, NV04_PFB_CFG0)); |
| 722 | nv_wr32(dev, 0x4009A8, nv_rd32(dev, NV04_PFB_CFG1)); | 740 | nv_wr32(dev, 0x4009A8, nv_rd32(dev, NV04_PFB_CFG1)); |
| 723 | if (dev_priv->chipset != 0x34) { | 741 | if (dev_priv->chipset != 0x34) { |
diff --git a/drivers/gpu/drm/nouveau/nv30_fb.c b/drivers/gpu/drm/nouveau/nv30_fb.c new file mode 100644 index 000000000000..9d35c8b3b839 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv30_fb.c | |||
| @@ -0,0 +1,87 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2010 Francisco Jerez. | ||
| 3 | * All Rights Reserved. | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining | ||
| 6 | * a copy of this software and associated documentation files (the | ||
| 7 | * "Software"), to deal in the Software without restriction, including | ||
| 8 | * without limitation the rights to use, copy, modify, merge, publish, | ||
| 9 | * distribute, sublicense, and/or sell copies of the Software, and to | ||
| 10 | * permit persons to whom the Software is furnished to do so, subject to | ||
| 11 | * the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice (including the | ||
| 14 | * next paragraph) shall be included in all copies or substantial | ||
| 15 | * portions of the Software. | ||
| 16 | * | ||
| 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
| 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
| 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
| 20 | * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | ||
| 21 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
| 22 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
| 23 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 24 | * | ||
| 25 | */ | ||
| 26 | |||
| 27 | #include "drmP.h" | ||
| 28 | #include "drm.h" | ||
| 29 | #include "nouveau_drv.h" | ||
| 30 | #include "nouveau_drm.h" | ||
| 31 | |||
| 32 | static int | ||
| 33 | calc_ref(int b, int l, int i) | ||
| 34 | { | ||
| 35 | int j, x = 0; | ||
| 36 | |||
| 37 | for (j = 0; j < 4; j++) { | ||
| 38 | int n = (b >> (8 * j) & 0xf); | ||
| 39 | int m = (l >> (8 * i) & 0xff) + 2 * (n & 0x8 ? n - 0x10 : n); | ||
| 40 | |||
| 41 | x |= (0x80 | (m & 0x1f)) << (8 * j); | ||
| 42 | } | ||
| 43 | |||
| 44 | return x; | ||
| 45 | } | ||
| 46 | |||
| 47 | int | ||
| 48 | nv30_fb_init(struct drm_device *dev) | ||
| 49 | { | ||
| 50 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 51 | struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; | ||
| 52 | int i, j; | ||
| 53 | |||
| 54 | pfb->num_tiles = NV10_PFB_TILE__SIZE; | ||
| 55 | |||
| 56 | /* Turn all the tiling regions off. */ | ||
| 57 | for (i = 0; i < pfb->num_tiles; i++) | ||
| 58 | pfb->set_region_tiling(dev, i, 0, 0, 0); | ||
| 59 | |||
| 60 | /* Init the memory timing regs at 0x10037c/0x1003ac */ | ||
| 61 | if (dev_priv->chipset == 0x30 || | ||
| 62 | dev_priv->chipset == 0x31 || | ||
| 63 | dev_priv->chipset == 0x35) { | ||
| 64 | /* Related to ROP count */ | ||
| 65 | int n = (dev_priv->chipset == 0x31 ? 2 : 4); | ||
| 66 | int b = (dev_priv->chipset > 0x30 ? | ||
| 67 | nv_rd32(dev, 0x122c) & 0xf : 0); | ||
| 68 | int l = nv_rd32(dev, 0x1003d0); | ||
| 69 | |||
| 70 | for (i = 0; i < n; i++) { | ||
| 71 | for (j = 0; j < 3; j++) | ||
| 72 | nv_wr32(dev, 0x10037c + 0xc * i + 0x4 * j, | ||
| 73 | calc_ref(b, l, j)); | ||
| 74 | |||
| 75 | for (j = 0; j < 2; j++) | ||
| 76 | nv_wr32(dev, 0x1003ac + 0x8 * i + 0x4 * j, | ||
| 77 | calc_ref(b, l, j)); | ||
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 81 | return 0; | ||
| 82 | } | ||
| 83 | |||
| 84 | void | ||
| 85 | nv30_fb_takedown(struct drm_device *dev) | ||
| 86 | { | ||
| 87 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nv40_fifo.c b/drivers/gpu/drm/nouveau/nv40_fifo.c index 500ccfd3a0b8..2b67f1835c39 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) | |||
| 48 | 48 | ||
| 49 | spin_lock_irqsave(&dev_priv->context_switch_lock, flags); | 49 | spin_lock_irqsave(&dev_priv->context_switch_lock, flags); |
| 50 | 50 | ||
| 51 | dev_priv->engine.instmem.prepare_access(dev, true); | ||
| 52 | nv_wi32(dev, fc + 0, chan->pushbuf_base); | 51 | nv_wi32(dev, fc + 0, chan->pushbuf_base); |
| 53 | nv_wi32(dev, fc + 4, chan->pushbuf_base); | 52 | nv_wi32(dev, fc + 4, chan->pushbuf_base); |
| 54 | nv_wi32(dev, fc + 12, chan->pushbuf->instance >> 4); | 53 | nv_wi32(dev, fc + 12, chan->pushbuf->instance >> 4); |
| @@ -61,7 +60,6 @@ nv40_fifo_create_context(struct nouveau_channel *chan) | |||
| 61 | 0x30000000 /* no idea.. */); | 60 | 0x30000000 /* no idea.. */); |
| 62 | nv_wi32(dev, fc + 56, chan->ramin_grctx->instance >> 4); | 61 | nv_wi32(dev, fc + 56, chan->ramin_grctx->instance >> 4); |
| 63 | nv_wi32(dev, fc + 60, 0x0001FFFF); | 62 | nv_wi32(dev, fc + 60, 0x0001FFFF); |
| 64 | dev_priv->engine.instmem.finish_access(dev); | ||
| 65 | 63 | ||
| 66 | /* enable the fifo dma operation */ | 64 | /* enable the fifo dma operation */ |
| 67 | nv_wr32(dev, NV04_PFIFO_MODE, | 65 | nv_wr32(dev, NV04_PFIFO_MODE, |
| @@ -89,8 +87,6 @@ nv40_fifo_do_load_context(struct drm_device *dev, int chid) | |||
| 89 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 87 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 90 | uint32_t fc = NV40_RAMFC(chid), tmp, tmp2; | 88 | uint32_t fc = NV40_RAMFC(chid), tmp, tmp2; |
| 91 | 89 | ||
| 92 | dev_priv->engine.instmem.prepare_access(dev, false); | ||
| 93 | |||
| 94 | nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0)); | 90 | nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0)); |
| 95 | nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4)); | 91 | nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4)); |
| 96 | nv_wr32(dev, NV10_PFIFO_CACHE1_REF_CNT, nv_ri32(dev, fc + 8)); | 92 | 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) | |||
| 127 | nv_wr32(dev, 0x2088, nv_ri32(dev, fc + 76)); | 123 | nv_wr32(dev, 0x2088, nv_ri32(dev, fc + 76)); |
| 128 | nv_wr32(dev, 0x3300, nv_ri32(dev, fc + 80)); | 124 | nv_wr32(dev, 0x3300, nv_ri32(dev, fc + 80)); |
| 129 | 125 | ||
| 130 | dev_priv->engine.instmem.finish_access(dev); | ||
| 131 | |||
| 132 | nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); | 126 | nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); |
| 133 | nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0); | 127 | nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0); |
| 134 | } | 128 | } |
| @@ -166,7 +160,6 @@ nv40_fifo_unload_context(struct drm_device *dev) | |||
| 166 | return 0; | 160 | return 0; |
| 167 | fc = NV40_RAMFC(chid); | 161 | fc = NV40_RAMFC(chid); |
| 168 | 162 | ||
| 169 | dev_priv->engine.instmem.prepare_access(dev, true); | ||
| 170 | nv_wi32(dev, fc + 0, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT)); | 163 | nv_wi32(dev, fc + 0, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT)); |
| 171 | nv_wi32(dev, fc + 4, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET)); | 164 | nv_wi32(dev, fc + 4, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET)); |
| 172 | nv_wi32(dev, fc + 8, nv_rd32(dev, NV10_PFIFO_CACHE1_REF_CNT)); | 165 | 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) | |||
| 200 | tmp |= (nv_rd32(dev, NV04_PFIFO_CACHE1_PUT) << 16); | 193 | tmp |= (nv_rd32(dev, NV04_PFIFO_CACHE1_PUT) << 16); |
| 201 | nv_wi32(dev, fc + 72, tmp); | 194 | nv_wi32(dev, fc + 72, tmp); |
| 202 | #endif | 195 | #endif |
| 203 | dev_priv->engine.instmem.finish_access(dev); | ||
| 204 | 196 | ||
| 205 | nv40_fifo_do_load_context(dev, pfifo->channels - 1); | 197 | nv40_fifo_do_load_context(dev, pfifo->channels - 1); |
| 206 | nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, | 198 | 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 704a25d04ac9..fd7d2b501316 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) | |||
| 58 | struct drm_device *dev = chan->dev; | 58 | struct drm_device *dev = chan->dev; |
| 59 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 59 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 60 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; | 60 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; |
| 61 | struct nouveau_grctx ctx = {}; | ||
| 61 | int ret; | 62 | int ret; |
| 62 | 63 | ||
| 63 | ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pgraph->grctx_size, | 64 | ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pgraph->grctx_size, |
| @@ -67,20 +68,13 @@ nv40_graph_create_context(struct nouveau_channel *chan) | |||
| 67 | return ret; | 68 | return ret; |
| 68 | 69 | ||
| 69 | /* Initialise default context values */ | 70 | /* Initialise default context values */ |
| 70 | dev_priv->engine.instmem.prepare_access(dev, true); | 71 | ctx.dev = chan->dev; |
| 71 | if (!pgraph->ctxprog) { | 72 | ctx.mode = NOUVEAU_GRCTX_VALS; |
| 72 | struct nouveau_grctx ctx = {}; | 73 | ctx.data = chan->ramin_grctx->gpuobj; |
| 73 | 74 | nv40_grctx_init(&ctx); | |
| 74 | ctx.dev = chan->dev; | 75 | |
| 75 | ctx.mode = NOUVEAU_GRCTX_VALS; | ||
| 76 | ctx.data = chan->ramin_grctx->gpuobj; | ||
| 77 | nv40_grctx_init(&ctx); | ||
| 78 | } else { | ||
| 79 | nouveau_grctx_vals_load(dev, chan->ramin_grctx->gpuobj); | ||
| 80 | } | ||
| 81 | nv_wo32(dev, chan->ramin_grctx->gpuobj, 0, | 76 | nv_wo32(dev, chan->ramin_grctx->gpuobj, 0, |
| 82 | chan->ramin_grctx->gpuobj->im_pramin->start); | 77 | chan->ramin_grctx->gpuobj->im_pramin->start); |
| 83 | dev_priv->engine.instmem.finish_access(dev); | ||
| 84 | return 0; | 78 | return 0; |
| 85 | } | 79 | } |
| 86 | 80 | ||
| @@ -238,7 +232,8 @@ nv40_graph_init(struct drm_device *dev) | |||
| 238 | struct drm_nouveau_private *dev_priv = | 232 | struct drm_nouveau_private *dev_priv = |
| 239 | (struct drm_nouveau_private *)dev->dev_private; | 233 | (struct drm_nouveau_private *)dev->dev_private; |
| 240 | struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; | 234 | struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; |
| 241 | uint32_t vramsz; | 235 | struct nouveau_grctx ctx = {}; |
| 236 | uint32_t vramsz, *cp; | ||
| 242 | int i, j; | 237 | int i, j; |
| 243 | 238 | ||
| 244 | nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & | 239 | nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & |
| @@ -246,32 +241,22 @@ nv40_graph_init(struct drm_device *dev) | |||
| 246 | nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | | 241 | nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | |
| 247 | NV_PMC_ENABLE_PGRAPH); | 242 | NV_PMC_ENABLE_PGRAPH); |
| 248 | 243 | ||
| 249 | if (nouveau_ctxfw) { | 244 | cp = kmalloc(sizeof(*cp) * 256, GFP_KERNEL); |
| 250 | nouveau_grctx_prog_load(dev); | 245 | if (!cp) |
| 251 | dev_priv->engine.graph.grctx_size = 175 * 1024; | 246 | return -ENOMEM; |
| 252 | } | ||
| 253 | 247 | ||
| 254 | if (!dev_priv->engine.graph.ctxprog) { | 248 | ctx.dev = dev; |
| 255 | struct nouveau_grctx ctx = {}; | 249 | ctx.mode = NOUVEAU_GRCTX_PROG; |
| 256 | uint32_t *cp; | 250 | ctx.data = cp; |
| 251 | ctx.ctxprog_max = 256; | ||
| 252 | nv40_grctx_init(&ctx); | ||
| 253 | dev_priv->engine.graph.grctx_size = ctx.ctxvals_pos * 4; | ||
| 257 | 254 | ||
| 258 | cp = kmalloc(sizeof(*cp) * 256, GFP_KERNEL); | 255 | nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); |
| 259 | if (!cp) | 256 | for (i = 0; i < ctx.ctxprog_len; i++) |
| 260 | return -ENOMEM; | 257 | nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, cp[i]); |
| 261 | 258 | ||
| 262 | ctx.dev = dev; | 259 | kfree(cp); |
| 263 | ctx.mode = NOUVEAU_GRCTX_PROG; | ||
| 264 | ctx.data = cp; | ||
| 265 | ctx.ctxprog_max = 256; | ||
| 266 | nv40_grctx_init(&ctx); | ||
| 267 | dev_priv->engine.graph.grctx_size = ctx.ctxvals_pos * 4; | ||
| 268 | |||
| 269 | nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); | ||
| 270 | for (i = 0; i < ctx.ctxprog_len; i++) | ||
| 271 | nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, cp[i]); | ||
| 272 | |||
| 273 | kfree(cp); | ||
| 274 | } | ||
| 275 | 260 | ||
| 276 | /* No context present currently */ | 261 | /* No context present currently */ |
| 277 | nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); | 262 | nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); |
| @@ -367,7 +352,7 @@ nv40_graph_init(struct drm_device *dev) | |||
| 367 | nv40_graph_set_region_tiling(dev, i, 0, 0, 0); | 352 | nv40_graph_set_region_tiling(dev, i, 0, 0, 0); |
| 368 | 353 | ||
| 369 | /* begin RAM config */ | 354 | /* begin RAM config */ |
| 370 | vramsz = drm_get_resource_len(dev, 0) - 1; | 355 | vramsz = pci_resource_len(dev->pdev, 0) - 1; |
| 371 | switch (dev_priv->chipset) { | 356 | switch (dev_priv->chipset) { |
| 372 | case 0x40: | 357 | case 0x40: |
| 373 | nv_wr32(dev, 0x4009A4, nv_rd32(dev, NV04_PFB_CFG0)); | 358 | nv_wr32(dev, 0x4009A4, nv_rd32(dev, NV04_PFB_CFG0)); |
| @@ -407,7 +392,6 @@ nv40_graph_init(struct drm_device *dev) | |||
| 407 | 392 | ||
| 408 | void nv40_graph_takedown(struct drm_device *dev) | 393 | void nv40_graph_takedown(struct drm_device *dev) |
| 409 | { | 394 | { |
| 410 | nouveau_grctx_fini(dev); | ||
| 411 | } | 395 | } |
| 412 | 396 | ||
| 413 | struct nouveau_pgraph_object_class nv40_graph_grclass[] = { | 397 | 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 2a3495e848e9..e4e72c12ab6a 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) | |||
| 19 | case 0x46: /* G72 */ | 19 | case 0x46: /* G72 */ |
| 20 | case 0x4e: | 20 | case 0x4e: |
| 21 | case 0x4c: /* C51_G7X */ | 21 | case 0x4c: /* C51_G7X */ |
| 22 | tmp = nv_rd32(dev, NV40_PFB_020C); | 22 | tmp = nv_rd32(dev, NV04_PFB_FIFO_DATA); |
| 23 | nv_wr32(dev, NV40_PMC_1700, tmp); | 23 | nv_wr32(dev, NV40_PMC_1700, tmp); |
| 24 | nv_wr32(dev, NV40_PMC_1704, 0); | 24 | nv_wr32(dev, NV40_PMC_1704, 0); |
| 25 | nv_wr32(dev, NV40_PMC_1708, 0); | 25 | 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 b4e4a3b05eae..5d11ea101666 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) | |||
| 440 | { | 440 | { |
| 441 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 441 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |
| 442 | struct drm_device *dev = crtc->dev; | 442 | struct drm_device *dev = crtc->dev; |
| 443 | struct drm_encoder *encoder; | ||
| 444 | uint32_t dac = 0, sor = 0; | ||
| 445 | 443 | ||
| 446 | NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); | 444 | NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); |
| 447 | 445 | ||
| 448 | /* Disconnect all unused encoders. */ | ||
| 449 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
| 450 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||
| 451 | |||
| 452 | if (!drm_helper_encoder_in_use(encoder)) | ||
| 453 | continue; | ||
| 454 | |||
| 455 | if (nv_encoder->dcb->type == OUTPUT_ANALOG || | ||
| 456 | nv_encoder->dcb->type == OUTPUT_TV) | ||
| 457 | dac |= (1 << nv_encoder->or); | ||
| 458 | else | ||
| 459 | sor |= (1 << nv_encoder->or); | ||
| 460 | } | ||
| 461 | |||
| 462 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
| 463 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||
| 464 | |||
| 465 | if (nv_encoder->dcb->type == OUTPUT_ANALOG || | ||
| 466 | nv_encoder->dcb->type == OUTPUT_TV) { | ||
| 467 | if (dac & (1 << nv_encoder->or)) | ||
| 468 | continue; | ||
| 469 | } else { | ||
| 470 | if (sor & (1 << nv_encoder->or)) | ||
| 471 | continue; | ||
| 472 | } | ||
| 473 | |||
| 474 | nv_encoder->disconnect(nv_encoder); | ||
| 475 | } | ||
| 476 | |||
| 477 | nv50_crtc_blank(nv_crtc, true); | 446 | nv50_crtc_blank(nv_crtc, true); |
| 478 | } | 447 | } |
| 479 | 448 | ||
| 480 | static void | 449 | static void |
| 481 | nv50_crtc_commit(struct drm_crtc *crtc) | 450 | nv50_crtc_commit(struct drm_crtc *crtc) |
| 482 | { | 451 | { |
| 483 | struct drm_crtc *crtc2; | ||
| 484 | struct drm_device *dev = crtc->dev; | 452 | struct drm_device *dev = crtc->dev; |
| 485 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 453 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 486 | struct nouveau_channel *evo = dev_priv->evo; | 454 | struct nouveau_channel *evo = dev_priv->evo; |
| @@ -491,20 +459,14 @@ nv50_crtc_commit(struct drm_crtc *crtc) | |||
| 491 | 459 | ||
| 492 | nv50_crtc_blank(nv_crtc, false); | 460 | nv50_crtc_blank(nv_crtc, false); |
| 493 | 461 | ||
| 494 | /* Explicitly blank all unused crtc's. */ | ||
| 495 | list_for_each_entry(crtc2, &dev->mode_config.crtc_list, head) { | ||
| 496 | if (!drm_helper_crtc_in_use(crtc2)) | ||
| 497 | nv50_crtc_blank(nouveau_crtc(crtc2), true); | ||
| 498 | } | ||
| 499 | |||
| 500 | ret = RING_SPACE(evo, 2); | 462 | ret = RING_SPACE(evo, 2); |
| 501 | if (ret) { | 463 | if (ret) { |
| 502 | NV_ERROR(dev, "no space while committing crtc\n"); | 464 | NV_ERROR(dev, "no space while committing crtc\n"); |
| 503 | return; | 465 | return; |
| 504 | } | 466 | } |
| 505 | BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); | 467 | BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); |
| 506 | OUT_RING(evo, 0); | 468 | OUT_RING (evo, 0); |
| 507 | FIRE_RING(evo); | 469 | FIRE_RING (evo); |
| 508 | } | 470 | } |
| 509 | 471 | ||
| 510 | static bool | 472 | static bool |
diff --git a/drivers/gpu/drm/nouveau/nv50_dac.c b/drivers/gpu/drm/nouveau/nv50_dac.c index 1fd9537beff6..1bc085962945 100644 --- a/drivers/gpu/drm/nouveau/nv50_dac.c +++ b/drivers/gpu/drm/nouveau/nv50_dac.c | |||
| @@ -37,22 +37,31 @@ | |||
| 37 | #include "nv50_display.h" | 37 | #include "nv50_display.h" |
| 38 | 38 | ||
| 39 | static void | 39 | static void |
| 40 | nv50_dac_disconnect(struct nouveau_encoder *nv_encoder) | 40 | nv50_dac_disconnect(struct drm_encoder *encoder) |
| 41 | { | 41 | { |
| 42 | struct drm_device *dev = to_drm_encoder(nv_encoder)->dev; | 42 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); |
| 43 | struct drm_device *dev = encoder->dev; | ||
| 43 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 44 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 44 | struct nouveau_channel *evo = dev_priv->evo; | 45 | struct nouveau_channel *evo = dev_priv->evo; |
| 45 | int ret; | 46 | int ret; |
| 46 | 47 | ||
| 48 | if (!nv_encoder->crtc) | ||
| 49 | return; | ||
| 50 | nv50_crtc_blank(nouveau_crtc(nv_encoder->crtc), true); | ||
| 51 | |||
| 47 | NV_DEBUG_KMS(dev, "Disconnecting DAC %d\n", nv_encoder->or); | 52 | NV_DEBUG_KMS(dev, "Disconnecting DAC %d\n", nv_encoder->or); |
| 48 | 53 | ||
| 49 | ret = RING_SPACE(evo, 2); | 54 | ret = RING_SPACE(evo, 4); |
| 50 | if (ret) { | 55 | if (ret) { |
| 51 | NV_ERROR(dev, "no space while disconnecting DAC\n"); | 56 | NV_ERROR(dev, "no space while disconnecting DAC\n"); |
| 52 | return; | 57 | return; |
| 53 | } | 58 | } |
| 54 | BEGIN_RING(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 1); | 59 | BEGIN_RING(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 1); |
| 55 | OUT_RING(evo, 0); | 60 | OUT_RING (evo, 0); |
| 61 | BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); | ||
| 62 | OUT_RING (evo, 0); | ||
| 63 | |||
| 64 | nv_encoder->crtc = NULL; | ||
| 56 | } | 65 | } |
| 57 | 66 | ||
| 58 | static enum drm_connector_status | 67 | static enum drm_connector_status |
| @@ -213,7 +222,8 @@ nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
| 213 | uint32_t mode_ctl = 0, mode_ctl2 = 0; | 222 | uint32_t mode_ctl = 0, mode_ctl2 = 0; |
| 214 | int ret; | 223 | int ret; |
| 215 | 224 | ||
| 216 | NV_DEBUG_KMS(dev, "or %d\n", nv_encoder->or); | 225 | NV_DEBUG_KMS(dev, "or %d type %d crtc %d\n", |
| 226 | nv_encoder->or, nv_encoder->dcb->type, crtc->index); | ||
| 217 | 227 | ||
| 218 | nv50_dac_dpms(encoder, DRM_MODE_DPMS_ON); | 228 | nv50_dac_dpms(encoder, DRM_MODE_DPMS_ON); |
| 219 | 229 | ||
| @@ -243,6 +253,14 @@ nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
| 243 | BEGIN_RING(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 2); | 253 | BEGIN_RING(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 2); |
| 244 | OUT_RING(evo, mode_ctl); | 254 | OUT_RING(evo, mode_ctl); |
| 245 | OUT_RING(evo, mode_ctl2); | 255 | OUT_RING(evo, mode_ctl2); |
| 256 | |||
| 257 | nv_encoder->crtc = encoder->crtc; | ||
| 258 | } | ||
| 259 | |||
| 260 | static struct drm_crtc * | ||
| 261 | nv50_dac_crtc_get(struct drm_encoder *encoder) | ||
| 262 | { | ||
| 263 | return nouveau_encoder(encoder)->crtc; | ||
| 246 | } | 264 | } |
| 247 | 265 | ||
| 248 | static const struct drm_encoder_helper_funcs nv50_dac_helper_funcs = { | 266 | 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 = { | |||
| 253 | .prepare = nv50_dac_prepare, | 271 | .prepare = nv50_dac_prepare, |
| 254 | .commit = nv50_dac_commit, | 272 | .commit = nv50_dac_commit, |
| 255 | .mode_set = nv50_dac_mode_set, | 273 | .mode_set = nv50_dac_mode_set, |
| 256 | .detect = nv50_dac_detect | 274 | .get_crtc = nv50_dac_crtc_get, |
| 275 | .detect = nv50_dac_detect, | ||
| 276 | .disable = nv50_dac_disconnect | ||
| 257 | }; | 277 | }; |
| 258 | 278 | ||
| 259 | static void | 279 | static void |
| @@ -275,14 +295,11 @@ static const struct drm_encoder_funcs nv50_dac_encoder_funcs = { | |||
| 275 | }; | 295 | }; |
| 276 | 296 | ||
| 277 | int | 297 | int |
| 278 | nv50_dac_create(struct drm_device *dev, struct dcb_entry *entry) | 298 | nv50_dac_create(struct drm_connector *connector, struct dcb_entry *entry) |
| 279 | { | 299 | { |
| 280 | struct nouveau_encoder *nv_encoder; | 300 | struct nouveau_encoder *nv_encoder; |
| 281 | struct drm_encoder *encoder; | 301 | struct drm_encoder *encoder; |
| 282 | 302 | ||
| 283 | NV_DEBUG_KMS(dev, "\n"); | ||
| 284 | NV_INFO(dev, "Detected a DAC output\n"); | ||
| 285 | |||
| 286 | nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); | 303 | nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); |
| 287 | if (!nv_encoder) | 304 | if (!nv_encoder) |
| 288 | return -ENOMEM; | 305 | return -ENOMEM; |
| @@ -291,14 +308,14 @@ nv50_dac_create(struct drm_device *dev, struct dcb_entry *entry) | |||
| 291 | nv_encoder->dcb = entry; | 308 | nv_encoder->dcb = entry; |
| 292 | nv_encoder->or = ffs(entry->or) - 1; | 309 | nv_encoder->or = ffs(entry->or) - 1; |
| 293 | 310 | ||
| 294 | nv_encoder->disconnect = nv50_dac_disconnect; | 311 | drm_encoder_init(connector->dev, encoder, &nv50_dac_encoder_funcs, |
| 295 | |||
| 296 | drm_encoder_init(dev, encoder, &nv50_dac_encoder_funcs, | ||
| 297 | DRM_MODE_ENCODER_DAC); | 312 | DRM_MODE_ENCODER_DAC); |
| 298 | drm_encoder_helper_add(encoder, &nv50_dac_helper_funcs); | 313 | drm_encoder_helper_add(encoder, &nv50_dac_helper_funcs); |
| 299 | 314 | ||
| 300 | encoder->possible_crtcs = entry->heads; | 315 | encoder->possible_crtcs = entry->heads; |
| 301 | encoder->possible_clones = 0; | 316 | encoder->possible_clones = 0; |
| 317 | |||
| 318 | drm_mode_connector_attach_encoder(connector, encoder); | ||
| 302 | return 0; | 319 | return 0; |
| 303 | } | 320 | } |
| 304 | 321 | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 580a5d10be93..f13ad0de9c8f 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, | |||
| 71 | return ret; | 71 | return ret; |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | dev_priv->engine.instmem.prepare_access(dev, true); | ||
| 75 | nv_wo32(dev, obj, 0, (tile_flags << 22) | (magic_flags << 16) | class); | 74 | nv_wo32(dev, obj, 0, (tile_flags << 22) | (magic_flags << 16) | class); |
| 76 | nv_wo32(dev, obj, 1, limit); | 75 | nv_wo32(dev, obj, 1, limit); |
| 77 | nv_wo32(dev, obj, 2, offset); | 76 | nv_wo32(dev, obj, 2, offset); |
| 78 | nv_wo32(dev, obj, 3, 0x00000000); | 77 | nv_wo32(dev, obj, 3, 0x00000000); |
| 79 | nv_wo32(dev, obj, 4, 0x00000000); | 78 | nv_wo32(dev, obj, 4, 0x00000000); |
| 80 | nv_wo32(dev, obj, 5, 0x00010000); | 79 | nv_wo32(dev, obj, 5, 0x00010000); |
| 81 | dev_priv->engine.instmem.finish_access(dev); | 80 | dev_priv->engine.instmem.flush(dev); |
| 82 | 81 | ||
| 83 | return 0; | 82 | return 0; |
| 84 | } | 83 | } |
| @@ -110,8 +109,8 @@ nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pchan) | |||
| 110 | return ret; | 109 | return ret; |
| 111 | } | 110 | } |
| 112 | 111 | ||
| 113 | ret = nouveau_mem_init_heap(&chan->ramin_heap, chan->ramin->gpuobj-> | 112 | ret = drm_mm_init(&chan->ramin_heap, |
| 114 | im_pramin->start, 32768); | 113 | chan->ramin->gpuobj->im_pramin->start, 32768); |
| 115 | if (ret) { | 114 | if (ret) { |
| 116 | NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret); | 115 | NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret); |
| 117 | nv50_evo_channel_del(pchan); | 116 | nv50_evo_channel_del(pchan); |
| @@ -179,13 +178,25 @@ nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pchan) | |||
| 179 | } | 178 | } |
| 180 | 179 | ||
| 181 | int | 180 | int |
| 181 | nv50_display_early_init(struct drm_device *dev) | ||
| 182 | { | ||
| 183 | return 0; | ||
| 184 | } | ||
| 185 | |||
| 186 | void | ||
| 187 | nv50_display_late_takedown(struct drm_device *dev) | ||
| 188 | { | ||
| 189 | } | ||
| 190 | |||
| 191 | int | ||
| 182 | nv50_display_init(struct drm_device *dev) | 192 | nv50_display_init(struct drm_device *dev) |
| 183 | { | 193 | { |
| 184 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 194 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 185 | struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; | 195 | struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; |
| 196 | struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; | ||
| 186 | struct nouveau_channel *evo = dev_priv->evo; | 197 | struct nouveau_channel *evo = dev_priv->evo; |
| 187 | struct drm_connector *connector; | 198 | struct drm_connector *connector; |
| 188 | uint32_t val, ram_amount, hpd_en[2]; | 199 | uint32_t val, ram_amount; |
| 189 | uint64_t start; | 200 | uint64_t start; |
| 190 | int ret, i; | 201 | int ret, i; |
| 191 | 202 | ||
| @@ -366,26 +377,13 @@ nv50_display_init(struct drm_device *dev) | |||
| 366 | NV50_PDISPLAY_INTR_EN_CLK_UNK40)); | 377 | NV50_PDISPLAY_INTR_EN_CLK_UNK40)); |
| 367 | 378 | ||
| 368 | /* enable hotplug interrupts */ | 379 | /* enable hotplug interrupts */ |
| 369 | hpd_en[0] = hpd_en[1] = 0; | ||
| 370 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 380 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
| 371 | struct nouveau_connector *conn = nouveau_connector(connector); | 381 | struct nouveau_connector *conn = nouveau_connector(connector); |
| 372 | struct dcb_gpio_entry *gpio; | ||
| 373 | 382 | ||
| 374 | if (conn->dcb->gpio_tag == 0xff) | 383 | if (conn->dcb->gpio_tag == 0xff) |
| 375 | continue; | 384 | continue; |
| 376 | 385 | ||
| 377 | gpio = nouveau_bios_gpio_entry(dev, conn->dcb->gpio_tag); | 386 | pgpio->irq_enable(dev, conn->dcb->gpio_tag, true); |
| 378 | if (!gpio) | ||
| 379 | continue; | ||
| 380 | |||
| 381 | hpd_en[gpio->line >> 4] |= (0x00010001 << (gpio->line & 0xf)); | ||
| 382 | } | ||
| 383 | |||
| 384 | nv_wr32(dev, 0xe054, 0xffffffff); | ||
| 385 | nv_wr32(dev, 0xe050, hpd_en[0]); | ||
| 386 | if (dev_priv->chipset >= 0x90) { | ||
| 387 | nv_wr32(dev, 0xe074, 0xffffffff); | ||
| 388 | nv_wr32(dev, 0xe070, hpd_en[1]); | ||
| 389 | } | 387 | } |
| 390 | 388 | ||
| 391 | return 0; | 389 | return 0; |
| @@ -465,6 +463,7 @@ int nv50_display_create(struct drm_device *dev) | |||
| 465 | { | 463 | { |
| 466 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 464 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 467 | struct dcb_table *dcb = &dev_priv->vbios.dcb; | 465 | struct dcb_table *dcb = &dev_priv->vbios.dcb; |
| 466 | struct drm_connector *connector, *ct; | ||
| 468 | int ret, i; | 467 | int ret, i; |
| 469 | 468 | ||
| 470 | NV_DEBUG_KMS(dev, "\n"); | 469 | NV_DEBUG_KMS(dev, "\n"); |
| @@ -507,14 +506,18 @@ int nv50_display_create(struct drm_device *dev) | |||
| 507 | continue; | 506 | continue; |
| 508 | } | 507 | } |
| 509 | 508 | ||
| 509 | connector = nouveau_connector_create(dev, entry->connector); | ||
| 510 | if (IS_ERR(connector)) | ||
| 511 | continue; | ||
| 512 | |||
| 510 | switch (entry->type) { | 513 | switch (entry->type) { |
| 511 | case OUTPUT_TMDS: | 514 | case OUTPUT_TMDS: |
| 512 | case OUTPUT_LVDS: | 515 | case OUTPUT_LVDS: |
| 513 | case OUTPUT_DP: | 516 | case OUTPUT_DP: |
| 514 | nv50_sor_create(dev, entry); | 517 | nv50_sor_create(connector, entry); |
| 515 | break; | 518 | break; |
| 516 | case OUTPUT_ANALOG: | 519 | case OUTPUT_ANALOG: |
| 517 | nv50_dac_create(dev, entry); | 520 | nv50_dac_create(connector, entry); |
| 518 | break; | 521 | break; |
| 519 | default: | 522 | default: |
| 520 | NV_WARN(dev, "DCB encoder %d unknown\n", entry->type); | 523 | NV_WARN(dev, "DCB encoder %d unknown\n", entry->type); |
| @@ -522,11 +525,13 @@ int nv50_display_create(struct drm_device *dev) | |||
| 522 | } | 525 | } |
| 523 | } | 526 | } |
| 524 | 527 | ||
| 525 | for (i = 0 ; i < dcb->connector.entries; i++) { | 528 | list_for_each_entry_safe(connector, ct, |
| 526 | if (i != 0 && dcb->connector.entry[i].index2 == | 529 | &dev->mode_config.connector_list, head) { |
| 527 | dcb->connector.entry[i - 1].index2) | 530 | if (!connector->encoder_ids[0]) { |
| 528 | continue; | 531 | NV_WARN(dev, "%s has no encoders, removing\n", |
| 529 | nouveau_connector_create(dev, &dcb->connector.entry[i]); | 532 | drm_get_connector_name(connector)); |
| 533 | connector->funcs->destroy(connector); | ||
| 534 | } | ||
| 530 | } | 535 | } |
| 531 | 536 | ||
| 532 | ret = nv50_display_init(dev); | 537 | ret = nv50_display_init(dev); |
| @@ -538,7 +543,8 @@ int nv50_display_create(struct drm_device *dev) | |||
| 538 | return 0; | 543 | return 0; |
| 539 | } | 544 | } |
| 540 | 545 | ||
| 541 | int nv50_display_destroy(struct drm_device *dev) | 546 | void |
| 547 | nv50_display_destroy(struct drm_device *dev) | ||
| 542 | { | 548 | { |
| 543 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 549 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 544 | 550 | ||
| @@ -548,135 +554,30 @@ int nv50_display_destroy(struct drm_device *dev) | |||
| 548 | 554 | ||
| 549 | nv50_display_disable(dev); | 555 | nv50_display_disable(dev); |
| 550 | nv50_evo_channel_del(&dev_priv->evo); | 556 | nv50_evo_channel_del(&dev_priv->evo); |
| 551 | |||
| 552 | return 0; | ||
| 553 | } | ||
| 554 | |||
| 555 | static inline uint32_t | ||
| 556 | nv50_display_mode_ctrl(struct drm_device *dev, bool sor, int or) | ||
| 557 | { | ||
| 558 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 559 | uint32_t mc; | ||
| 560 | |||
| 561 | if (sor) { | ||
| 562 | if (dev_priv->chipset < 0x90 || | ||
| 563 | dev_priv->chipset == 0x92 || dev_priv->chipset == 0xa0) | ||
| 564 | mc = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_P(or)); | ||
| 565 | else | ||
| 566 | mc = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_P(or)); | ||
| 567 | } else { | ||
| 568 | mc = nv_rd32(dev, NV50_PDISPLAY_DAC_MODE_CTRL_P(or)); | ||
| 569 | } | ||
| 570 | |||
| 571 | return mc; | ||
| 572 | } | ||
| 573 | |||
| 574 | static int | ||
| 575 | nv50_display_irq_head(struct drm_device *dev, int *phead, | ||
| 576 | struct dcb_entry **pdcbent) | ||
| 577 | { | ||
| 578 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 579 | uint32_t unk30 = nv_rd32(dev, NV50_PDISPLAY_UNK30_CTRL); | ||
| 580 | uint32_t dac = 0, sor = 0; | ||
| 581 | int head, i, or = 0, type = OUTPUT_ANY; | ||
| 582 | |||
| 583 | /* We're assuming that head 0 *or* head 1 will be active here, | ||
| 584 | * and not both. I'm not sure if the hw will even signal both | ||
| 585 | * ever, but it definitely shouldn't for us as we commit each | ||
| 586 | * CRTC separately, and submission will be blocked by the GPU | ||
| 587 | * until we handle each in turn. | ||
| 588 | */ | ||
| 589 | NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); | ||
| 590 | head = ffs((unk30 >> 9) & 3) - 1; | ||
| 591 | if (head < 0) | ||
| 592 | return -EINVAL; | ||
| 593 | |||
| 594 | /* This assumes CRTCs are never bound to multiple encoders, which | ||
| 595 | * should be the case. | ||
| 596 | */ | ||
| 597 | for (i = 0; i < 3 && type == OUTPUT_ANY; i++) { | ||
| 598 | uint32_t mc = nv50_display_mode_ctrl(dev, false, i); | ||
| 599 | if (!(mc & (1 << head))) | ||
| 600 | continue; | ||
| 601 | |||
| 602 | switch ((mc >> 8) & 0xf) { | ||
| 603 | case 0: type = OUTPUT_ANALOG; break; | ||
| 604 | case 1: type = OUTPUT_TV; break; | ||
| 605 | default: | ||
| 606 | NV_ERROR(dev, "unknown dac mode_ctrl: 0x%08x\n", dac); | ||
| 607 | return -1; | ||
| 608 | } | ||
| 609 | |||
| 610 | or = i; | ||
| 611 | } | ||
| 612 | |||
| 613 | for (i = 0; i < 4 && type == OUTPUT_ANY; i++) { | ||
| 614 | uint32_t mc = nv50_display_mode_ctrl(dev, true, i); | ||
| 615 | if (!(mc & (1 << head))) | ||
| 616 | continue; | ||
| 617 | |||
| 618 | switch ((mc >> 8) & 0xf) { | ||
| 619 | case 0: type = OUTPUT_LVDS; break; | ||
| 620 | case 1: type = OUTPUT_TMDS; break; | ||
| 621 | case 2: type = OUTPUT_TMDS; break; | ||
| 622 | case 5: type = OUTPUT_TMDS; break; | ||
| 623 | case 8: type = OUTPUT_DP; break; | ||
| 624 | case 9: type = OUTPUT_DP; break; | ||
| 625 | default: | ||
| 626 | NV_ERROR(dev, "unknown sor mode_ctrl: 0x%08x\n", sor); | ||
| 627 | return -1; | ||
| 628 | } | ||
| 629 | |||
| 630 | or = i; | ||
| 631 | } | ||
| 632 | |||
| 633 | NV_DEBUG_KMS(dev, "type %d, or %d\n", type, or); | ||
| 634 | if (type == OUTPUT_ANY) { | ||
| 635 | NV_ERROR(dev, "unknown encoder!!\n"); | ||
| 636 | return -1; | ||
| 637 | } | ||
| 638 | |||
| 639 | for (i = 0; i < dev_priv->vbios.dcb.entries; i++) { | ||
| 640 | struct dcb_entry *dcbent = &dev_priv->vbios.dcb.entry[i]; | ||
| 641 | |||
| 642 | if (dcbent->type != type) | ||
| 643 | continue; | ||
| 644 | |||
| 645 | if (!(dcbent->or & (1 << or))) | ||
| 646 | continue; | ||
| 647 | |||
| 648 | *phead = head; | ||
| 649 | *pdcbent = dcbent; | ||
| 650 | return 0; | ||
| 651 | } | ||
| 652 | |||
| 653 | NV_ERROR(dev, "no DCB entry for %d %d\n", dac != 0, or); | ||
| 654 | return 0; | ||
| 655 | } | 557 | } |
| 656 | 558 | ||
| 657 | static uint32_t | 559 | static u16 |
| 658 | nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcbent, | 560 | nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcb, |
| 659 | int pxclk) | 561 | u32 mc, int pxclk) |
| 660 | { | 562 | { |
| 661 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 563 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 662 | struct nouveau_connector *nv_connector = NULL; | 564 | struct nouveau_connector *nv_connector = NULL; |
| 663 | struct drm_encoder *encoder; | 565 | struct drm_encoder *encoder; |
| 664 | struct nvbios *bios = &dev_priv->vbios; | 566 | struct nvbios *bios = &dev_priv->vbios; |
| 665 | uint32_t mc, script = 0, or; | 567 | u32 script = 0, or; |
| 666 | 568 | ||
| 667 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 569 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
| 668 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 570 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); |
| 669 | 571 | ||
| 670 | if (nv_encoder->dcb != dcbent) | 572 | if (nv_encoder->dcb != dcb) |
| 671 | continue; | 573 | continue; |
| 672 | 574 | ||
| 673 | nv_connector = nouveau_encoder_connector_get(nv_encoder); | 575 | nv_connector = nouveau_encoder_connector_get(nv_encoder); |
| 674 | break; | 576 | break; |
| 675 | } | 577 | } |
| 676 | 578 | ||
| 677 | or = ffs(dcbent->or) - 1; | 579 | or = ffs(dcb->or) - 1; |
| 678 | mc = nv50_display_mode_ctrl(dev, dcbent->type != OUTPUT_ANALOG, or); | 580 | switch (dcb->type) { |
| 679 | switch (dcbent->type) { | ||
| 680 | case OUTPUT_LVDS: | 581 | case OUTPUT_LVDS: |
| 681 | script = (mc >> 8) & 0xf; | 582 | script = (mc >> 8) & 0xf; |
| 682 | if (bios->fp_no_ddc) { | 583 | if (bios->fp_no_ddc) { |
| @@ -767,17 +668,88 @@ nv50_display_vblank_handler(struct drm_device *dev, uint32_t intr) | |||
| 767 | static void | 668 | static void |
| 768 | nv50_display_unk10_handler(struct drm_device *dev) | 669 | nv50_display_unk10_handler(struct drm_device *dev) |
| 769 | { | 670 | { |
| 770 | struct dcb_entry *dcbent; | 671 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 771 | int head, ret; | 672 | u32 unk30 = nv_rd32(dev, 0x610030), mc; |
| 673 | int i, crtc, or, type = OUTPUT_ANY; | ||
| 772 | 674 | ||
| 773 | ret = nv50_display_irq_head(dev, &head, &dcbent); | 675 | NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); |
| 774 | if (ret) | 676 | dev_priv->evo_irq.dcb = NULL; |
| 775 | goto ack; | ||
| 776 | 677 | ||
| 777 | nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) & ~8); | 678 | nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) & ~8); |
| 778 | 679 | ||
| 779 | nouveau_bios_run_display_table(dev, dcbent, 0, -1); | 680 | /* Determine which CRTC we're dealing with, only 1 ever will be |
| 681 | * signalled at the same time with the current nouveau code. | ||
| 682 | */ | ||
| 683 | crtc = ffs((unk30 & 0x00000060) >> 5) - 1; | ||
| 684 | if (crtc < 0) | ||
| 685 | goto ack; | ||
| 686 | |||
| 687 | /* Nothing needs to be done for the encoder */ | ||
| 688 | crtc = ffs((unk30 & 0x00000180) >> 7) - 1; | ||
| 689 | if (crtc < 0) | ||
| 690 | goto ack; | ||
| 780 | 691 | ||
| 692 | /* Find which encoder was connected to the CRTC */ | ||
| 693 | for (i = 0; type == OUTPUT_ANY && i < 3; i++) { | ||
| 694 | mc = nv_rd32(dev, NV50_PDISPLAY_DAC_MODE_CTRL_C(i)); | ||
| 695 | NV_DEBUG_KMS(dev, "DAC-%d mc: 0x%08x\n", i, mc); | ||
| 696 | if (!(mc & (1 << crtc))) | ||
| 697 | continue; | ||
| 698 | |||
| 699 | switch ((mc & 0x00000f00) >> 8) { | ||
| 700 | case 0: type = OUTPUT_ANALOG; break; | ||
| 701 | case 1: type = OUTPUT_TV; break; | ||
| 702 | default: | ||
| 703 | NV_ERROR(dev, "invalid mc, DAC-%d: 0x%08x\n", i, mc); | ||
| 704 | goto ack; | ||
| 705 | } | ||
| 706 | |||
| 707 | or = i; | ||
| 708 | } | ||
| 709 | |||
| 710 | for (i = 0; type == OUTPUT_ANY && i < 4; i++) { | ||
| 711 | if (dev_priv->chipset < 0x90 || | ||
| 712 | dev_priv->chipset == 0x92 || | ||
| 713 | dev_priv->chipset == 0xa0) | ||
| 714 | mc = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_C(i)); | ||
| 715 | else | ||
| 716 | mc = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_C(i)); | ||
| 717 | |||
| 718 | NV_DEBUG_KMS(dev, "SOR-%d mc: 0x%08x\n", i, mc); | ||
| 719 | if (!(mc & (1 << crtc))) | ||
| 720 | continue; | ||
| 721 | |||
| 722 | switch ((mc & 0x00000f00) >> 8) { | ||
| 723 | case 0: type = OUTPUT_LVDS; break; | ||
| 724 | case 1: type = OUTPUT_TMDS; break; | ||
| 725 | case 2: type = OUTPUT_TMDS; break; | ||
| 726 | case 5: type = OUTPUT_TMDS; break; | ||
| 727 | case 8: type = OUTPUT_DP; break; | ||
| 728 | case 9: type = OUTPUT_DP; break; | ||
| 729 | default: | ||
| 730 | NV_ERROR(dev, "invalid mc, SOR-%d: 0x%08x\n", i, mc); | ||
| 731 | goto ack; | ||
| 732 | } | ||
| 733 | |||
| 734 | or = i; | ||
| 735 | } | ||
| 736 | |||
| 737 | /* There was no encoder to disable */ | ||
| 738 | if (type == OUTPUT_ANY) | ||
| 739 | goto ack; | ||
| 740 | |||
| 741 | /* Disable the encoder */ | ||
| 742 | for (i = 0; i < dev_priv->vbios.dcb.entries; i++) { | ||
| 743 | struct dcb_entry *dcb = &dev_priv->vbios.dcb.entry[i]; | ||
| 744 | |||
| 745 | if (dcb->type == type && (dcb->or & (1 << or))) { | ||
| 746 | nouveau_bios_run_display_table(dev, dcb, 0, -1); | ||
| 747 | dev_priv->evo_irq.dcb = dcb; | ||
| 748 | goto ack; | ||
| 749 | } | ||
| 750 | } | ||
| 751 | |||
| 752 | NV_ERROR(dev, "no dcb for %d %d 0x%08x\n", or, type, mc); | ||
| 781 | ack: | 753 | ack: |
| 782 | nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK10); | 754 | nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK10); |
| 783 | nv_wr32(dev, 0x610030, 0x80000000); | 755 | nv_wr32(dev, 0x610030, 0x80000000); |
| @@ -817,33 +789,103 @@ nv50_display_unk20_dp_hack(struct drm_device *dev, struct dcb_entry *dcb) | |||
| 817 | static void | 789 | static void |
| 818 | nv50_display_unk20_handler(struct drm_device *dev) | 790 | nv50_display_unk20_handler(struct drm_device *dev) |
| 819 | { | 791 | { |
| 820 | struct dcb_entry *dcbent; | 792 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 821 | uint32_t tmp, pclk, script; | 793 | u32 unk30 = nv_rd32(dev, 0x610030), tmp, pclk, script, mc; |
| 822 | int head, or, ret; | 794 | struct dcb_entry *dcb; |
| 795 | int i, crtc, or, type = OUTPUT_ANY; | ||
| 823 | 796 | ||
| 824 | ret = nv50_display_irq_head(dev, &head, &dcbent); | 797 | NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); |
| 825 | if (ret) | 798 | dcb = dev_priv->evo_irq.dcb; |
| 799 | if (dcb) { | ||
| 800 | nouveau_bios_run_display_table(dev, dcb, 0, -2); | ||
| 801 | dev_priv->evo_irq.dcb = NULL; | ||
| 802 | } | ||
| 803 | |||
| 804 | /* CRTC clock change requested? */ | ||
| 805 | crtc = ffs((unk30 & 0x00000600) >> 9) - 1; | ||
| 806 | if (crtc >= 0) { | ||
| 807 | pclk = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(crtc, CLOCK)); | ||
| 808 | pclk &= 0x003fffff; | ||
| 809 | |||
| 810 | nv50_crtc_set_clock(dev, crtc, pclk); | ||
| 811 | |||
| 812 | tmp = nv_rd32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(crtc)); | ||
| 813 | tmp &= ~0x000000f; | ||
| 814 | nv_wr32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(crtc), tmp); | ||
| 815 | } | ||
| 816 | |||
| 817 | /* Nothing needs to be done for the encoder */ | ||
| 818 | crtc = ffs((unk30 & 0x00000180) >> 7) - 1; | ||
| 819 | if (crtc < 0) | ||
| 826 | goto ack; | 820 | goto ack; |
| 827 | or = ffs(dcbent->or) - 1; | 821 | pclk = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(crtc, CLOCK)) & 0x003fffff; |
| 828 | pclk = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(head, CLOCK)) & 0x3fffff; | ||
| 829 | script = nv50_display_script_select(dev, dcbent, pclk); | ||
| 830 | 822 | ||
| 831 | NV_DEBUG_KMS(dev, "head %d pxclk: %dKHz\n", head, pclk); | 823 | /* Find which encoder is connected to the CRTC */ |
| 824 | for (i = 0; type == OUTPUT_ANY && i < 3; i++) { | ||
| 825 | mc = nv_rd32(dev, NV50_PDISPLAY_DAC_MODE_CTRL_P(i)); | ||
| 826 | NV_DEBUG_KMS(dev, "DAC-%d mc: 0x%08x\n", i, mc); | ||
| 827 | if (!(mc & (1 << crtc))) | ||
| 828 | continue; | ||
| 832 | 829 | ||
| 833 | if (dcbent->type != OUTPUT_DP) | 830 | switch ((mc & 0x00000f00) >> 8) { |
| 834 | nouveau_bios_run_display_table(dev, dcbent, 0, -2); | 831 | case 0: type = OUTPUT_ANALOG; break; |
| 832 | case 1: type = OUTPUT_TV; break; | ||
| 833 | default: | ||
| 834 | NV_ERROR(dev, "invalid mc, DAC-%d: 0x%08x\n", i, mc); | ||
| 835 | goto ack; | ||
| 836 | } | ||
| 835 | 837 | ||
| 836 | nv50_crtc_set_clock(dev, head, pclk); | 838 | or = i; |
| 839 | } | ||
| 837 | 840 | ||
| 838 | nouveau_bios_run_display_table(dev, dcbent, script, pclk); | 841 | for (i = 0; type == OUTPUT_ANY && i < 4; i++) { |
| 842 | if (dev_priv->chipset < 0x90 || | ||
| 843 | dev_priv->chipset == 0x92 || | ||
| 844 | dev_priv->chipset == 0xa0) | ||
| 845 | mc = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_P(i)); | ||
| 846 | else | ||
| 847 | mc = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_P(i)); | ||
| 839 | 848 | ||
| 840 | nv50_display_unk20_dp_hack(dev, dcbent); | 849 | NV_DEBUG_KMS(dev, "SOR-%d mc: 0x%08x\n", i, mc); |
| 850 | if (!(mc & (1 << crtc))) | ||
| 851 | continue; | ||
| 852 | |||
| 853 | switch ((mc & 0x00000f00) >> 8) { | ||
| 854 | case 0: type = OUTPUT_LVDS; break; | ||
| 855 | case 1: type = OUTPUT_TMDS; break; | ||
| 856 | case 2: type = OUTPUT_TMDS; break; | ||
| 857 | case 5: type = OUTPUT_TMDS; break; | ||
| 858 | case 8: type = OUTPUT_DP; break; | ||
| 859 | case 9: type = OUTPUT_DP; break; | ||
| 860 | default: | ||
| 861 | NV_ERROR(dev, "invalid mc, SOR-%d: 0x%08x\n", i, mc); | ||
| 862 | goto ack; | ||
| 863 | } | ||
| 864 | |||
| 865 | or = i; | ||
| 866 | } | ||
| 867 | |||
| 868 | if (type == OUTPUT_ANY) | ||
| 869 | goto ack; | ||
| 870 | |||
| 871 | /* Enable the encoder */ | ||
| 872 | for (i = 0; i < dev_priv->vbios.dcb.entries; i++) { | ||
| 873 | dcb = &dev_priv->vbios.dcb.entry[i]; | ||
| 874 | if (dcb->type == type && (dcb->or & (1 << or))) | ||
| 875 | break; | ||
| 876 | } | ||
| 877 | |||
| 878 | if (i == dev_priv->vbios.dcb.entries) { | ||
| 879 | NV_ERROR(dev, "no dcb for %d %d 0x%08x\n", or, type, mc); | ||
| 880 | goto ack; | ||
| 881 | } | ||
| 841 | 882 | ||
| 842 | tmp = nv_rd32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(head)); | 883 | script = nv50_display_script_select(dev, dcb, mc, pclk); |
| 843 | tmp &= ~0x000000f; | 884 | nouveau_bios_run_display_table(dev, dcb, script, pclk); |
| 844 | nv_wr32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(head), tmp); | ||
| 845 | 885 | ||
| 846 | if (dcbent->type != OUTPUT_ANALOG) { | 886 | nv50_display_unk20_dp_hack(dev, dcb); |
| 887 | |||
| 888 | if (dcb->type != OUTPUT_ANALOG) { | ||
| 847 | tmp = nv_rd32(dev, NV50_PDISPLAY_SOR_CLK_CTRL2(or)); | 889 | tmp = nv_rd32(dev, NV50_PDISPLAY_SOR_CLK_CTRL2(or)); |
| 848 | tmp &= ~0x00000f0f; | 890 | tmp &= ~0x00000f0f; |
| 849 | if (script & 0x0100) | 891 | if (script & 0x0100) |
| @@ -853,24 +895,61 @@ nv50_display_unk20_handler(struct drm_device *dev) | |||
| 853 | nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL2(or), 0); | 895 | nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL2(or), 0); |
| 854 | } | 896 | } |
| 855 | 897 | ||
| 898 | dev_priv->evo_irq.dcb = dcb; | ||
| 899 | dev_priv->evo_irq.pclk = pclk; | ||
| 900 | dev_priv->evo_irq.script = script; | ||
| 901 | |||
| 856 | ack: | 902 | ack: |
| 857 | nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK20); | 903 | nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK20); |
| 858 | nv_wr32(dev, 0x610030, 0x80000000); | 904 | nv_wr32(dev, 0x610030, 0x80000000); |
| 859 | } | 905 | } |
| 860 | 906 | ||
| 907 | /* If programming a TMDS output on a SOR that can also be configured for | ||
| 908 | * DisplayPort, make sure NV50_SOR_DP_CTRL_ENABLE is forced off. | ||
| 909 | * | ||
| 910 | * It looks like the VBIOS TMDS scripts make an attempt at this, however, | ||
| 911 | * the VBIOS scripts on at least one board I have only switch it off on | ||
| 912 | * link 0, causing a blank display if the output has previously been | ||
| 913 | * programmed for DisplayPort. | ||
| 914 | */ | ||
| 915 | static void | ||
| 916 | nv50_display_unk40_dp_set_tmds(struct drm_device *dev, struct dcb_entry *dcb) | ||
| 917 | { | ||
| 918 | int or = ffs(dcb->or) - 1, link = !(dcb->dpconf.sor.link & 1); | ||
| 919 | struct drm_encoder *encoder; | ||
| 920 | u32 tmp; | ||
| 921 | |||
| 922 | if (dcb->type != OUTPUT_TMDS) | ||
| 923 | return; | ||
| 924 | |||
| 925 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
| 926 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||
| 927 | |||
| 928 | if (nv_encoder->dcb->type == OUTPUT_DP && | ||
| 929 | nv_encoder->dcb->or & (1 << or)) { | ||
| 930 | tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); | ||
| 931 | tmp &= ~NV50_SOR_DP_CTRL_ENABLED; | ||
| 932 | nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp); | ||
| 933 | break; | ||
| 934 | } | ||
| 935 | } | ||
| 936 | } | ||
| 937 | |||
| 861 | static void | 938 | static void |
| 862 | nv50_display_unk40_handler(struct drm_device *dev) | 939 | nv50_display_unk40_handler(struct drm_device *dev) |
| 863 | { | 940 | { |
| 864 | struct dcb_entry *dcbent; | 941 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 865 | int head, pclk, script, ret; | 942 | struct dcb_entry *dcb = dev_priv->evo_irq.dcb; |
| 943 | u16 script = dev_priv->evo_irq.script; | ||
| 944 | u32 unk30 = nv_rd32(dev, 0x610030), pclk = dev_priv->evo_irq.pclk; | ||
| 866 | 945 | ||
| 867 | ret = nv50_display_irq_head(dev, &head, &dcbent); | 946 | NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); |
| 868 | if (ret) | 947 | dev_priv->evo_irq.dcb = NULL; |
| 948 | if (!dcb) | ||
| 869 | goto ack; | 949 | goto ack; |
| 870 | pclk = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(head, CLOCK)) & 0x3fffff; | ||
| 871 | script = nv50_display_script_select(dev, dcbent, pclk); | ||
| 872 | 950 | ||
| 873 | nouveau_bios_run_display_table(dev, dcbent, script, -pclk); | 951 | nouveau_bios_run_display_table(dev, dcb, script, -pclk); |
| 952 | nv50_display_unk40_dp_set_tmds(dev, dcb); | ||
| 874 | 953 | ||
| 875 | ack: | 954 | ack: |
| 876 | nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK40); | 955 | nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK40); |
diff --git a/drivers/gpu/drm/nouveau/nv50_display.h b/drivers/gpu/drm/nouveau/nv50_display.h index 581d405ac014..c551f0b85ee0 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.h +++ b/drivers/gpu/drm/nouveau/nv50_display.h | |||
| @@ -38,9 +38,11 @@ | |||
| 38 | void nv50_display_irq_handler(struct drm_device *dev); | 38 | void nv50_display_irq_handler(struct drm_device *dev); |
| 39 | void nv50_display_irq_handler_bh(struct work_struct *work); | 39 | void nv50_display_irq_handler_bh(struct work_struct *work); |
| 40 | void nv50_display_irq_hotplug_bh(struct work_struct *work); | 40 | void nv50_display_irq_hotplug_bh(struct work_struct *work); |
| 41 | int nv50_display_init(struct drm_device *dev); | 41 | int nv50_display_early_init(struct drm_device *dev); |
| 42 | void nv50_display_late_takedown(struct drm_device *dev); | ||
| 42 | int nv50_display_create(struct drm_device *dev); | 43 | int nv50_display_create(struct drm_device *dev); |
| 43 | int nv50_display_destroy(struct drm_device *dev); | 44 | int nv50_display_init(struct drm_device *dev); |
| 45 | void nv50_display_destroy(struct drm_device *dev); | ||
| 44 | int nv50_crtc_blank(struct nouveau_crtc *, bool blank); | 46 | int nv50_crtc_blank(struct nouveau_crtc *, bool blank); |
| 45 | int nv50_crtc_set_clock(struct drm_device *, int head, int pclk); | 47 | int nv50_crtc_set_clock(struct drm_device *, int head, int pclk); |
| 46 | 48 | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_fifo.c b/drivers/gpu/drm/nouveau/nv50_fifo.c index e20c0e2474f3..fb0281ae8f90 100644 --- a/drivers/gpu/drm/nouveau/nv50_fifo.c +++ b/drivers/gpu/drm/nouveau/nv50_fifo.c | |||
| @@ -28,41 +28,33 @@ | |||
| 28 | #include "drm.h" | 28 | #include "drm.h" |
| 29 | #include "nouveau_drv.h" | 29 | #include "nouveau_drv.h" |
| 30 | 30 | ||
| 31 | struct nv50_fifo_priv { | ||
| 32 | struct nouveau_gpuobj_ref *thingo[2]; | ||
| 33 | int cur_thingo; | ||
| 34 | }; | ||
| 35 | |||
| 36 | #define IS_G80 ((dev_priv->chipset & 0xf0) == 0x50) | ||
| 37 | |||
| 38 | static void | 31 | static void |
| 39 | nv50_fifo_init_thingo(struct drm_device *dev) | 32 | nv50_fifo_playlist_update(struct drm_device *dev) |
| 40 | { | 33 | { |
| 41 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 34 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 42 | struct nv50_fifo_priv *priv = dev_priv->engine.fifo.priv; | 35 | struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; |
| 43 | struct nouveau_gpuobj_ref *cur; | 36 | struct nouveau_gpuobj_ref *cur; |
| 44 | int i, nr; | 37 | int i, nr; |
| 45 | 38 | ||
| 46 | NV_DEBUG(dev, "\n"); | 39 | NV_DEBUG(dev, "\n"); |
| 47 | 40 | ||
| 48 | cur = priv->thingo[priv->cur_thingo]; | 41 | cur = pfifo->playlist[pfifo->cur_playlist]; |
| 49 | priv->cur_thingo = !priv->cur_thingo; | 42 | pfifo->cur_playlist = !pfifo->cur_playlist; |
| 50 | 43 | ||
| 51 | /* We never schedule channel 0 or 127 */ | 44 | /* We never schedule channel 0 or 127 */ |
| 52 | dev_priv->engine.instmem.prepare_access(dev, true); | ||
| 53 | for (i = 1, nr = 0; i < 127; i++) { | 45 | for (i = 1, nr = 0; i < 127; i++) { |
| 54 | if (dev_priv->fifos[i] && dev_priv->fifos[i]->ramfc) | 46 | if (dev_priv->fifos[i] && dev_priv->fifos[i]->ramfc) |
| 55 | nv_wo32(dev, cur->gpuobj, nr++, i); | 47 | nv_wo32(dev, cur->gpuobj, nr++, i); |
| 56 | } | 48 | } |
| 57 | dev_priv->engine.instmem.finish_access(dev); | 49 | dev_priv->engine.instmem.flush(dev); |
| 58 | 50 | ||
| 59 | nv_wr32(dev, 0x32f4, cur->instance >> 12); | 51 | nv_wr32(dev, 0x32f4, cur->instance >> 12); |
| 60 | nv_wr32(dev, 0x32ec, nr); | 52 | nv_wr32(dev, 0x32ec, nr); |
| 61 | nv_wr32(dev, 0x2500, 0x101); | 53 | nv_wr32(dev, 0x2500, 0x101); |
| 62 | } | 54 | } |
| 63 | 55 | ||
| 64 | static int | 56 | static void |
| 65 | nv50_fifo_channel_enable(struct drm_device *dev, int channel, bool nt) | 57 | nv50_fifo_channel_enable(struct drm_device *dev, int channel) |
| 66 | { | 58 | { |
| 67 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 59 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 68 | struct nouveau_channel *chan = dev_priv->fifos[channel]; | 60 | struct nouveau_channel *chan = dev_priv->fifos[channel]; |
| @@ -70,37 +62,28 @@ nv50_fifo_channel_enable(struct drm_device *dev, int channel, bool nt) | |||
| 70 | 62 | ||
| 71 | NV_DEBUG(dev, "ch%d\n", channel); | 63 | NV_DEBUG(dev, "ch%d\n", channel); |
| 72 | 64 | ||
| 73 | if (!chan->ramfc) | 65 | if (dev_priv->chipset == 0x50) |
| 74 | return -EINVAL; | ||
| 75 | |||
| 76 | if (IS_G80) | ||
| 77 | inst = chan->ramfc->instance >> 12; | 66 | inst = chan->ramfc->instance >> 12; |
| 78 | else | 67 | else |
| 79 | inst = chan->ramfc->instance >> 8; | 68 | inst = chan->ramfc->instance >> 8; |
| 80 | nv_wr32(dev, NV50_PFIFO_CTX_TABLE(channel), | ||
| 81 | inst | NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED); | ||
| 82 | 69 | ||
| 83 | if (!nt) | 70 | nv_wr32(dev, NV50_PFIFO_CTX_TABLE(channel), inst | |
| 84 | nv50_fifo_init_thingo(dev); | 71 | NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED); |
| 85 | return 0; | ||
| 86 | } | 72 | } |
| 87 | 73 | ||
| 88 | static void | 74 | static void |
| 89 | nv50_fifo_channel_disable(struct drm_device *dev, int channel, bool nt) | 75 | nv50_fifo_channel_disable(struct drm_device *dev, int channel) |
| 90 | { | 76 | { |
| 91 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 77 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 92 | uint32_t inst; | 78 | uint32_t inst; |
| 93 | 79 | ||
| 94 | NV_DEBUG(dev, "ch%d, nt=%d\n", channel, nt); | 80 | NV_DEBUG(dev, "ch%d\n", channel); |
| 95 | 81 | ||
| 96 | if (IS_G80) | 82 | if (dev_priv->chipset == 0x50) |
| 97 | inst = NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G80; | 83 | inst = NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G80; |
| 98 | else | 84 | else |
| 99 | inst = NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G84; | 85 | inst = NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G84; |
| 100 | nv_wr32(dev, NV50_PFIFO_CTX_TABLE(channel), inst); | 86 | nv_wr32(dev, NV50_PFIFO_CTX_TABLE(channel), inst); |
| 101 | |||
| 102 | if (!nt) | ||
| 103 | nv50_fifo_init_thingo(dev); | ||
| 104 | } | 87 | } |
| 105 | 88 | ||
| 106 | static void | 89 | static void |
| @@ -133,12 +116,12 @@ nv50_fifo_init_context_table(struct drm_device *dev) | |||
| 133 | 116 | ||
| 134 | for (i = 0; i < NV50_PFIFO_CTX_TABLE__SIZE; i++) { | 117 | for (i = 0; i < NV50_PFIFO_CTX_TABLE__SIZE; i++) { |
| 135 | if (dev_priv->fifos[i]) | 118 | if (dev_priv->fifos[i]) |
| 136 | nv50_fifo_channel_enable(dev, i, true); | 119 | nv50_fifo_channel_enable(dev, i); |
| 137 | else | 120 | else |
| 138 | nv50_fifo_channel_disable(dev, i, true); | 121 | nv50_fifo_channel_disable(dev, i); |
| 139 | } | 122 | } |
| 140 | 123 | ||
| 141 | nv50_fifo_init_thingo(dev); | 124 | nv50_fifo_playlist_update(dev); |
| 142 | } | 125 | } |
| 143 | 126 | ||
| 144 | static void | 127 | static void |
| @@ -162,41 +145,38 @@ nv50_fifo_init_regs(struct drm_device *dev) | |||
| 162 | nv_wr32(dev, 0x3270, 0); | 145 | nv_wr32(dev, 0x3270, 0); |
| 163 | 146 | ||
| 164 | /* Enable dummy channels setup by nv50_instmem.c */ | 147 | /* Enable dummy channels setup by nv50_instmem.c */ |
| 165 | nv50_fifo_channel_enable(dev, 0, true); | 148 | nv50_fifo_channel_enable(dev, 0); |
| 166 | nv50_fifo_channel_enable(dev, 127, true); | 149 | nv50_fifo_channel_enable(dev, 127); |
| 167 | } | 150 | } |
| 168 | 151 | ||
| 169 | int | 152 | int |
| 170 | nv50_fifo_init(struct drm_device *dev) | 153 | nv50_fifo_init(struct drm_device *dev) |
| 171 | { | 154 | { |
| 172 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 155 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 173 | struct nv50_fifo_priv *priv; | 156 | struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; |
| 174 | int ret; | 157 | int ret; |
| 175 | 158 | ||
| 176 | NV_DEBUG(dev, "\n"); | 159 | NV_DEBUG(dev, "\n"); |
| 177 | 160 | ||
| 178 | priv = dev_priv->engine.fifo.priv; | 161 | if (pfifo->playlist[0]) { |
| 179 | if (priv) { | 162 | pfifo->cur_playlist = !pfifo->cur_playlist; |
| 180 | priv->cur_thingo = !priv->cur_thingo; | ||
| 181 | goto just_reset; | 163 | goto just_reset; |
| 182 | } | 164 | } |
| 183 | 165 | ||
| 184 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
| 185 | if (!priv) | ||
| 186 | return -ENOMEM; | ||
| 187 | dev_priv->engine.fifo.priv = priv; | ||
| 188 | |||
| 189 | ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 128*4, 0x1000, | 166 | ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 128*4, 0x1000, |
| 190 | NVOBJ_FLAG_ZERO_ALLOC, &priv->thingo[0]); | 167 | NVOBJ_FLAG_ZERO_ALLOC, |
| 168 | &pfifo->playlist[0]); | ||
| 191 | if (ret) { | 169 | if (ret) { |
| 192 | NV_ERROR(dev, "error creating thingo0: %d\n", ret); | 170 | NV_ERROR(dev, "error creating playlist 0: %d\n", ret); |
| 193 | return ret; | 171 | return ret; |
| 194 | } | 172 | } |
| 195 | 173 | ||
| 196 | ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 128*4, 0x1000, | 174 | ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 128*4, 0x1000, |
| 197 | NVOBJ_FLAG_ZERO_ALLOC, &priv->thingo[1]); | 175 | NVOBJ_FLAG_ZERO_ALLOC, |
| 176 | &pfifo->playlist[1]); | ||
| 198 | if (ret) { | 177 | if (ret) { |
| 199 | NV_ERROR(dev, "error creating thingo1: %d\n", ret); | 178 | nouveau_gpuobj_ref_del(dev, &pfifo->playlist[0]); |
| 179 | NV_ERROR(dev, "error creating playlist 1: %d\n", ret); | ||
| 200 | return ret; | 180 | return ret; |
| 201 | } | 181 | } |
| 202 | 182 | ||
| @@ -216,18 +196,15 @@ void | |||
| 216 | nv50_fifo_takedown(struct drm_device *dev) | 196 | nv50_fifo_takedown(struct drm_device *dev) |
| 217 | { | 197 | { |
| 218 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 198 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 219 | struct nv50_fifo_priv *priv = dev_priv->engine.fifo.priv; | 199 | struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; |
| 220 | 200 | ||
| 221 | NV_DEBUG(dev, "\n"); | 201 | NV_DEBUG(dev, "\n"); |
| 222 | 202 | ||
| 223 | if (!priv) | 203 | if (!pfifo->playlist[0]) |
| 224 | return; | 204 | return; |
| 225 | 205 | ||
| 226 | nouveau_gpuobj_ref_del(dev, &priv->thingo[0]); | 206 | nouveau_gpuobj_ref_del(dev, &pfifo->playlist[0]); |
| 227 | nouveau_gpuobj_ref_del(dev, &priv->thingo[1]); | 207 | nouveau_gpuobj_ref_del(dev, &pfifo->playlist[1]); |
| 228 | |||
| 229 | dev_priv->engine.fifo.priv = NULL; | ||
| 230 | kfree(priv); | ||
| 231 | } | 208 | } |
| 232 | 209 | ||
| 233 | int | 210 | int |
| @@ -248,7 +225,7 @@ nv50_fifo_create_context(struct nouveau_channel *chan) | |||
| 248 | 225 | ||
| 249 | NV_DEBUG(dev, "ch%d\n", chan->id); | 226 | NV_DEBUG(dev, "ch%d\n", chan->id); |
| 250 | 227 | ||
| 251 | if (IS_G80) { | 228 | if (dev_priv->chipset == 0x50) { |
| 252 | uint32_t ramin_poffset = chan->ramin->gpuobj->im_pramin->start; | 229 | uint32_t ramin_poffset = chan->ramin->gpuobj->im_pramin->start; |
| 253 | uint32_t ramin_voffset = chan->ramin->gpuobj->im_backing_start; | 230 | uint32_t ramin_voffset = chan->ramin->gpuobj->im_backing_start; |
| 254 | 231 | ||
| @@ -281,10 +258,10 @@ nv50_fifo_create_context(struct nouveau_channel *chan) | |||
| 281 | 258 | ||
| 282 | spin_lock_irqsave(&dev_priv->context_switch_lock, flags); | 259 | spin_lock_irqsave(&dev_priv->context_switch_lock, flags); |
| 283 | 260 | ||
| 284 | dev_priv->engine.instmem.prepare_access(dev, true); | ||
| 285 | |||
| 286 | nv_wo32(dev, ramfc, 0x48/4, chan->pushbuf->instance >> 4); | 261 | nv_wo32(dev, ramfc, 0x48/4, chan->pushbuf->instance >> 4); |
| 287 | nv_wo32(dev, ramfc, 0x80/4, (0xc << 24) | (chan->ramht->instance >> 4)); | 262 | nv_wo32(dev, ramfc, 0x80/4, (0 << 27) /* 4KiB */ | |
| 263 | (4 << 24) /* SEARCH_FULL */ | | ||
| 264 | (chan->ramht->instance >> 4)); | ||
| 288 | nv_wo32(dev, ramfc, 0x44/4, 0x2101ffff); | 265 | nv_wo32(dev, ramfc, 0x44/4, 0x2101ffff); |
| 289 | nv_wo32(dev, ramfc, 0x60/4, 0x7fffffff); | 266 | nv_wo32(dev, ramfc, 0x60/4, 0x7fffffff); |
| 290 | nv_wo32(dev, ramfc, 0x40/4, 0x00000000); | 267 | nv_wo32(dev, ramfc, 0x40/4, 0x00000000); |
| @@ -295,7 +272,7 @@ nv50_fifo_create_context(struct nouveau_channel *chan) | |||
| 295 | chan->dma.ib_base * 4); | 272 | chan->dma.ib_base * 4); |
| 296 | nv_wo32(dev, ramfc, 0x54/4, drm_order(chan->dma.ib_max + 1) << 16); | 273 | nv_wo32(dev, ramfc, 0x54/4, drm_order(chan->dma.ib_max + 1) << 16); |
| 297 | 274 | ||
| 298 | if (!IS_G80) { | 275 | if (dev_priv->chipset != 0x50) { |
| 299 | nv_wo32(dev, chan->ramin->gpuobj, 0, chan->id); | 276 | nv_wo32(dev, chan->ramin->gpuobj, 0, chan->id); |
| 300 | nv_wo32(dev, chan->ramin->gpuobj, 1, | 277 | nv_wo32(dev, chan->ramin->gpuobj, 1, |
| 301 | chan->ramfc->instance >> 8); | 278 | chan->ramfc->instance >> 8); |
| @@ -304,16 +281,10 @@ nv50_fifo_create_context(struct nouveau_channel *chan) | |||
| 304 | nv_wo32(dev, ramfc, 0x98/4, chan->ramin->instance >> 12); | 281 | nv_wo32(dev, ramfc, 0x98/4, chan->ramin->instance >> 12); |
| 305 | } | 282 | } |
| 306 | 283 | ||
| 307 | dev_priv->engine.instmem.finish_access(dev); | 284 | dev_priv->engine.instmem.flush(dev); |
| 308 | |||
| 309 | ret = nv50_fifo_channel_enable(dev, chan->id, false); | ||
| 310 | if (ret) { | ||
| 311 | NV_ERROR(dev, "error enabling ch%d: %d\n", chan->id, ret); | ||
| 312 | spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); | ||
| 313 | nouveau_gpuobj_ref_del(dev, &chan->ramfc); | ||
| 314 | return ret; | ||
| 315 | } | ||
| 316 | 285 | ||
| 286 | nv50_fifo_channel_enable(dev, chan->id); | ||
| 287 | nv50_fifo_playlist_update(dev); | ||
| 317 | spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); | 288 | spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); |
| 318 | return 0; | 289 | return 0; |
| 319 | } | 290 | } |
| @@ -328,11 +299,12 @@ nv50_fifo_destroy_context(struct nouveau_channel *chan) | |||
| 328 | 299 | ||
| 329 | /* This will ensure the channel is seen as disabled. */ | 300 | /* This will ensure the channel is seen as disabled. */ |
| 330 | chan->ramfc = NULL; | 301 | chan->ramfc = NULL; |
| 331 | nv50_fifo_channel_disable(dev, chan->id, false); | 302 | nv50_fifo_channel_disable(dev, chan->id); |
| 332 | 303 | ||
| 333 | /* Dummy channel, also used on ch 127 */ | 304 | /* Dummy channel, also used on ch 127 */ |
| 334 | if (chan->id == 0) | 305 | if (chan->id == 0) |
| 335 | nv50_fifo_channel_disable(dev, 127, false); | 306 | nv50_fifo_channel_disable(dev, 127); |
| 307 | nv50_fifo_playlist_update(dev); | ||
| 336 | 308 | ||
| 337 | nouveau_gpuobj_ref_del(dev, &ramfc); | 309 | nouveau_gpuobj_ref_del(dev, &ramfc); |
| 338 | nouveau_gpuobj_ref_del(dev, &chan->cache); | 310 | nouveau_gpuobj_ref_del(dev, &chan->cache); |
| @@ -349,8 +321,6 @@ nv50_fifo_load_context(struct nouveau_channel *chan) | |||
| 349 | 321 | ||
| 350 | NV_DEBUG(dev, "ch%d\n", chan->id); | 322 | NV_DEBUG(dev, "ch%d\n", chan->id); |
| 351 | 323 | ||
| 352 | dev_priv->engine.instmem.prepare_access(dev, false); | ||
| 353 | |||
| 354 | nv_wr32(dev, 0x3330, nv_ro32(dev, ramfc, 0x00/4)); | 324 | nv_wr32(dev, 0x3330, nv_ro32(dev, ramfc, 0x00/4)); |
| 355 | nv_wr32(dev, 0x3334, nv_ro32(dev, ramfc, 0x04/4)); | 325 | nv_wr32(dev, 0x3334, nv_ro32(dev, ramfc, 0x04/4)); |
| 356 | nv_wr32(dev, 0x3240, nv_ro32(dev, ramfc, 0x08/4)); | 326 | nv_wr32(dev, 0x3240, nv_ro32(dev, ramfc, 0x08/4)); |
| @@ -396,7 +366,7 @@ nv50_fifo_load_context(struct nouveau_channel *chan) | |||
| 396 | nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); | 366 | nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); |
| 397 | 367 | ||
| 398 | /* guessing that all the 0x34xx regs aren't on NV50 */ | 368 | /* guessing that all the 0x34xx regs aren't on NV50 */ |
| 399 | if (!IS_G80) { | 369 | if (dev_priv->chipset != 0x50) { |
| 400 | nv_wr32(dev, 0x340c, nv_ro32(dev, ramfc, 0x88/4)); | 370 | nv_wr32(dev, 0x340c, nv_ro32(dev, ramfc, 0x88/4)); |
| 401 | nv_wr32(dev, 0x3400, nv_ro32(dev, ramfc, 0x8c/4)); | 371 | nv_wr32(dev, 0x3400, nv_ro32(dev, ramfc, 0x8c/4)); |
| 402 | nv_wr32(dev, 0x3404, nv_ro32(dev, ramfc, 0x90/4)); | 372 | nv_wr32(dev, 0x3404, nv_ro32(dev, ramfc, 0x90/4)); |
| @@ -404,8 +374,6 @@ nv50_fifo_load_context(struct nouveau_channel *chan) | |||
| 404 | nv_wr32(dev, 0x3410, nv_ro32(dev, ramfc, 0x98/4)); | 374 | nv_wr32(dev, 0x3410, nv_ro32(dev, ramfc, 0x98/4)); |
| 405 | } | 375 | } |
| 406 | 376 | ||
| 407 | dev_priv->engine.instmem.finish_access(dev); | ||
| 408 | |||
| 409 | nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, chan->id | (1<<16)); | 377 | nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, chan->id | (1<<16)); |
| 410 | return 0; | 378 | return 0; |
| 411 | } | 379 | } |
| @@ -434,8 +402,6 @@ nv50_fifo_unload_context(struct drm_device *dev) | |||
| 434 | ramfc = chan->ramfc->gpuobj; | 402 | ramfc = chan->ramfc->gpuobj; |
| 435 | cache = chan->cache->gpuobj; | 403 | cache = chan->cache->gpuobj; |
| 436 | 404 | ||
| 437 | dev_priv->engine.instmem.prepare_access(dev, true); | ||
| 438 | |||
| 439 | nv_wo32(dev, ramfc, 0x00/4, nv_rd32(dev, 0x3330)); | 405 | nv_wo32(dev, ramfc, 0x00/4, nv_rd32(dev, 0x3330)); |
| 440 | nv_wo32(dev, ramfc, 0x04/4, nv_rd32(dev, 0x3334)); | 406 | nv_wo32(dev, ramfc, 0x04/4, nv_rd32(dev, 0x3334)); |
| 441 | nv_wo32(dev, ramfc, 0x08/4, nv_rd32(dev, 0x3240)); | 407 | nv_wo32(dev, ramfc, 0x08/4, nv_rd32(dev, 0x3240)); |
| @@ -482,7 +448,7 @@ nv50_fifo_unload_context(struct drm_device *dev) | |||
| 482 | } | 448 | } |
| 483 | 449 | ||
| 484 | /* guessing that all the 0x34xx regs aren't on NV50 */ | 450 | /* guessing that all the 0x34xx regs aren't on NV50 */ |
| 485 | if (!IS_G80) { | 451 | if (dev_priv->chipset != 0x50) { |
| 486 | nv_wo32(dev, ramfc, 0x84/4, ptr >> 1); | 452 | nv_wo32(dev, ramfc, 0x84/4, ptr >> 1); |
| 487 | nv_wo32(dev, ramfc, 0x88/4, nv_rd32(dev, 0x340c)); | 453 | nv_wo32(dev, ramfc, 0x88/4, nv_rd32(dev, 0x340c)); |
| 488 | nv_wo32(dev, ramfc, 0x8c/4, nv_rd32(dev, 0x3400)); | 454 | nv_wo32(dev, ramfc, 0x8c/4, nv_rd32(dev, 0x3400)); |
| @@ -491,7 +457,7 @@ nv50_fifo_unload_context(struct drm_device *dev) | |||
| 491 | nv_wo32(dev, ramfc, 0x98/4, nv_rd32(dev, 0x3410)); | 457 | nv_wo32(dev, ramfc, 0x98/4, nv_rd32(dev, 0x3410)); |
| 492 | } | 458 | } |
| 493 | 459 | ||
| 494 | dev_priv->engine.instmem.finish_access(dev); | 460 | dev_priv->engine.instmem.flush(dev); |
| 495 | 461 | ||
| 496 | /*XXX: probably reload ch127 (NULL) state back too */ | 462 | /*XXX: probably reload ch127 (NULL) state back too */ |
| 497 | nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, 127); | 463 | nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, 127); |
diff --git a/drivers/gpu/drm/nouveau/nv50_gpio.c b/drivers/gpu/drm/nouveau/nv50_gpio.c index bb47ad737267..b2fab2bf3d61 100644 --- a/drivers/gpu/drm/nouveau/nv50_gpio.c +++ b/drivers/gpu/drm/nouveau/nv50_gpio.c | |||
| @@ -74,3 +74,38 @@ nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state) | |||
| 74 | nv_wr32(dev, r, v); | 74 | nv_wr32(dev, r, v); |
| 75 | return 0; | 75 | return 0; |
| 76 | } | 76 | } |
| 77 | |||
| 78 | void | ||
| 79 | nv50_gpio_irq_enable(struct drm_device *dev, enum dcb_gpio_tag tag, bool on) | ||
| 80 | { | ||
| 81 | struct dcb_gpio_entry *gpio; | ||
| 82 | u32 reg, mask; | ||
| 83 | |||
| 84 | gpio = nouveau_bios_gpio_entry(dev, tag); | ||
| 85 | if (!gpio) { | ||
| 86 | NV_ERROR(dev, "gpio tag 0x%02x not found\n", tag); | ||
| 87 | return; | ||
| 88 | } | ||
| 89 | |||
| 90 | reg = gpio->line < 16 ? 0xe050 : 0xe070; | ||
| 91 | mask = 0x00010001 << (gpio->line & 0xf); | ||
| 92 | |||
| 93 | nv_wr32(dev, reg + 4, mask); | ||
| 94 | nv_mask(dev, reg + 0, mask, on ? mask : 0); | ||
| 95 | } | ||
| 96 | |||
| 97 | int | ||
| 98 | nv50_gpio_init(struct drm_device *dev) | ||
| 99 | { | ||
| 100 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 101 | |||
| 102 | /* disable, and ack any pending gpio interrupts */ | ||
| 103 | nv_wr32(dev, 0xe050, 0x00000000); | ||
| 104 | nv_wr32(dev, 0xe054, 0xffffffff); | ||
| 105 | if (dev_priv->chipset >= 0x90) { | ||
| 106 | nv_wr32(dev, 0xe070, 0x00000000); | ||
| 107 | nv_wr32(dev, 0xe074, 0xffffffff); | ||
| 108 | } | ||
| 109 | |||
| 110 | return 0; | ||
| 111 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c index b203d06f601f..1413028e1580 100644 --- a/drivers/gpu/drm/nouveau/nv50_graph.c +++ b/drivers/gpu/drm/nouveau/nv50_graph.c | |||
| @@ -30,8 +30,6 @@ | |||
| 30 | 30 | ||
| 31 | #include "nouveau_grctx.h" | 31 | #include "nouveau_grctx.h" |
| 32 | 32 | ||
| 33 | #define IS_G80 ((dev_priv->chipset & 0xf0) == 0x50) | ||
| 34 | |||
| 35 | static void | 33 | static void |
| 36 | nv50_graph_init_reset(struct drm_device *dev) | 34 | nv50_graph_init_reset(struct drm_device *dev) |
| 37 | { | 35 | { |
| @@ -103,37 +101,33 @@ static int | |||
| 103 | nv50_graph_init_ctxctl(struct drm_device *dev) | 101 | nv50_graph_init_ctxctl(struct drm_device *dev) |
| 104 | { | 102 | { |
| 105 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 103 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 104 | struct nouveau_grctx ctx = {}; | ||
| 105 | uint32_t *cp; | ||
| 106 | int i; | ||
| 106 | 107 | ||
| 107 | NV_DEBUG(dev, "\n"); | 108 | NV_DEBUG(dev, "\n"); |
| 108 | 109 | ||
| 109 | if (nouveau_ctxfw) { | 110 | cp = kmalloc(512 * 4, GFP_KERNEL); |
| 110 | nouveau_grctx_prog_load(dev); | 111 | if (!cp) { |
| 111 | dev_priv->engine.graph.grctx_size = 0x70000; | 112 | NV_ERROR(dev, "failed to allocate ctxprog\n"); |
| 113 | dev_priv->engine.graph.accel_blocked = true; | ||
| 114 | return 0; | ||
| 112 | } | 115 | } |
| 113 | if (!dev_priv->engine.graph.ctxprog) { | 116 | |
| 114 | struct nouveau_grctx ctx = {}; | 117 | ctx.dev = dev; |
| 115 | uint32_t *cp = kmalloc(512 * 4, GFP_KERNEL); | 118 | ctx.mode = NOUVEAU_GRCTX_PROG; |
| 116 | int i; | 119 | ctx.data = cp; |
| 117 | if (!cp) { | 120 | ctx.ctxprog_max = 512; |
| 118 | NV_ERROR(dev, "Couldn't alloc ctxprog! Disabling acceleration.\n"); | 121 | if (!nv50_grctx_init(&ctx)) { |
| 119 | dev_priv->engine.graph.accel_blocked = true; | 122 | dev_priv->engine.graph.grctx_size = ctx.ctxvals_pos * 4; |
| 120 | return 0; | 123 | |
| 121 | } | 124 | nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); |
| 122 | ctx.dev = dev; | 125 | for (i = 0; i < ctx.ctxprog_len; i++) |
| 123 | ctx.mode = NOUVEAU_GRCTX_PROG; | 126 | nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, cp[i]); |
| 124 | ctx.data = cp; | 127 | } else { |
| 125 | ctx.ctxprog_max = 512; | 128 | dev_priv->engine.graph.accel_blocked = true; |
| 126 | if (!nv50_grctx_init(&ctx)) { | ||
| 127 | dev_priv->engine.graph.grctx_size = ctx.ctxvals_pos * 4; | ||
| 128 | |||
| 129 | nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); | ||
| 130 | for (i = 0; i < ctx.ctxprog_len; i++) | ||
| 131 | nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, cp[i]); | ||
| 132 | } else { | ||
| 133 | dev_priv->engine.graph.accel_blocked = true; | ||
| 134 | } | ||
| 135 | kfree(cp); | ||
| 136 | } | 129 | } |
| 130 | kfree(cp); | ||
| 137 | 131 | ||
| 138 | nv_wr32(dev, 0x400320, 4); | 132 | nv_wr32(dev, 0x400320, 4); |
| 139 | nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0); | 133 | nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0); |
| @@ -164,7 +158,6 @@ void | |||
| 164 | nv50_graph_takedown(struct drm_device *dev) | 158 | nv50_graph_takedown(struct drm_device *dev) |
| 165 | { | 159 | { |
| 166 | NV_DEBUG(dev, "\n"); | 160 | NV_DEBUG(dev, "\n"); |
| 167 | nouveau_grctx_fini(dev); | ||
| 168 | } | 161 | } |
| 169 | 162 | ||
| 170 | void | 163 | void |
| @@ -212,8 +205,9 @@ nv50_graph_create_context(struct nouveau_channel *chan) | |||
| 212 | struct drm_device *dev = chan->dev; | 205 | struct drm_device *dev = chan->dev; |
| 213 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 206 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 214 | struct nouveau_gpuobj *ramin = chan->ramin->gpuobj; | 207 | struct nouveau_gpuobj *ramin = chan->ramin->gpuobj; |
| 215 | struct nouveau_gpuobj *ctx; | 208 | struct nouveau_gpuobj *obj; |
| 216 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; | 209 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; |
| 210 | struct nouveau_grctx ctx = {}; | ||
| 217 | int hdr, ret; | 211 | int hdr, ret; |
| 218 | 212 | ||
| 219 | NV_DEBUG(dev, "ch%d\n", chan->id); | 213 | NV_DEBUG(dev, "ch%d\n", chan->id); |
| @@ -223,10 +217,9 @@ nv50_graph_create_context(struct nouveau_channel *chan) | |||
| 223 | NVOBJ_FLAG_ZERO_FREE, &chan->ramin_grctx); | 217 | NVOBJ_FLAG_ZERO_FREE, &chan->ramin_grctx); |
| 224 | if (ret) | 218 | if (ret) |
| 225 | return ret; | 219 | return ret; |
| 226 | ctx = chan->ramin_grctx->gpuobj; | 220 | obj = chan->ramin_grctx->gpuobj; |
| 227 | 221 | ||
| 228 | hdr = IS_G80 ? 0x200 : 0x20; | 222 | hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20; |
| 229 | dev_priv->engine.instmem.prepare_access(dev, true); | ||
| 230 | nv_wo32(dev, ramin, (hdr + 0x00)/4, 0x00190002); | 223 | nv_wo32(dev, ramin, (hdr + 0x00)/4, 0x00190002); |
| 231 | nv_wo32(dev, ramin, (hdr + 0x04)/4, chan->ramin_grctx->instance + | 224 | nv_wo32(dev, ramin, (hdr + 0x04)/4, chan->ramin_grctx->instance + |
| 232 | pgraph->grctx_size - 1); | 225 | pgraph->grctx_size - 1); |
| @@ -234,21 +227,15 @@ nv50_graph_create_context(struct nouveau_channel *chan) | |||
| 234 | nv_wo32(dev, ramin, (hdr + 0x0c)/4, 0); | 227 | nv_wo32(dev, ramin, (hdr + 0x0c)/4, 0); |
| 235 | nv_wo32(dev, ramin, (hdr + 0x10)/4, 0); | 228 | nv_wo32(dev, ramin, (hdr + 0x10)/4, 0); |
| 236 | nv_wo32(dev, ramin, (hdr + 0x14)/4, 0x00010000); | 229 | nv_wo32(dev, ramin, (hdr + 0x14)/4, 0x00010000); |
| 237 | dev_priv->engine.instmem.finish_access(dev); | ||
| 238 | |||
| 239 | dev_priv->engine.instmem.prepare_access(dev, true); | ||
| 240 | if (!pgraph->ctxprog) { | ||
| 241 | struct nouveau_grctx ctx = {}; | ||
| 242 | ctx.dev = chan->dev; | ||
| 243 | ctx.mode = NOUVEAU_GRCTX_VALS; | ||
| 244 | ctx.data = chan->ramin_grctx->gpuobj; | ||
| 245 | nv50_grctx_init(&ctx); | ||
| 246 | } else { | ||
| 247 | nouveau_grctx_vals_load(dev, ctx); | ||
| 248 | } | ||
| 249 | nv_wo32(dev, ctx, 0x00000/4, chan->ramin->instance >> 12); | ||
| 250 | dev_priv->engine.instmem.finish_access(dev); | ||
| 251 | 230 | ||
| 231 | ctx.dev = chan->dev; | ||
| 232 | ctx.mode = NOUVEAU_GRCTX_VALS; | ||
| 233 | ctx.data = obj; | ||
| 234 | nv50_grctx_init(&ctx); | ||
| 235 | |||
| 236 | nv_wo32(dev, obj, 0x00000/4, chan->ramin->instance >> 12); | ||
| 237 | |||
| 238 | dev_priv->engine.instmem.flush(dev); | ||
| 252 | return 0; | 239 | return 0; |
| 253 | } | 240 | } |
| 254 | 241 | ||
| @@ -257,17 +244,16 @@ nv50_graph_destroy_context(struct nouveau_channel *chan) | |||
| 257 | { | 244 | { |
| 258 | struct drm_device *dev = chan->dev; | 245 | struct drm_device *dev = chan->dev; |
| 259 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 246 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 260 | int i, hdr = IS_G80 ? 0x200 : 0x20; | 247 | int i, hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20; |
| 261 | 248 | ||
| 262 | NV_DEBUG(dev, "ch%d\n", chan->id); | 249 | NV_DEBUG(dev, "ch%d\n", chan->id); |
| 263 | 250 | ||
| 264 | if (!chan->ramin || !chan->ramin->gpuobj) | 251 | if (!chan->ramin || !chan->ramin->gpuobj) |
| 265 | return; | 252 | return; |
| 266 | 253 | ||
| 267 | dev_priv->engine.instmem.prepare_access(dev, true); | ||
| 268 | for (i = hdr; i < hdr + 24; i += 4) | 254 | for (i = hdr; i < hdr + 24; i += 4) |
| 269 | nv_wo32(dev, chan->ramin->gpuobj, i/4, 0); | 255 | nv_wo32(dev, chan->ramin->gpuobj, i/4, 0); |
| 270 | dev_priv->engine.instmem.finish_access(dev); | 256 | dev_priv->engine.instmem.flush(dev); |
| 271 | 257 | ||
| 272 | nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx); | 258 | nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx); |
| 273 | } | 259 | } |
diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c index 5f21df31f3aa..37c7b48ab24a 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 { | |||
| 35 | struct nouveau_gpuobj_ref *pramin_pt; | 35 | struct nouveau_gpuobj_ref *pramin_pt; |
| 36 | struct nouveau_gpuobj_ref *pramin_bar; | 36 | struct nouveau_gpuobj_ref *pramin_bar; |
| 37 | struct nouveau_gpuobj_ref *fb_bar; | 37 | struct nouveau_gpuobj_ref *fb_bar; |
| 38 | |||
| 39 | bool last_access_wr; | ||
| 40 | }; | 38 | }; |
| 41 | 39 | ||
| 42 | #define NV50_INSTMEM_PAGE_SHIFT 12 | 40 | #define NV50_INSTMEM_PAGE_SHIFT 12 |
| @@ -147,7 +145,7 @@ nv50_instmem_init(struct drm_device *dev) | |||
| 147 | if (ret) | 145 | if (ret) |
| 148 | return ret; | 146 | return ret; |
| 149 | 147 | ||
| 150 | if (nouveau_mem_init_heap(&chan->ramin_heap, c_base, c_size - c_base)) | 148 | if (drm_mm_init(&chan->ramin_heap, c_base, c_size - c_base)) |
| 151 | return -ENOMEM; | 149 | return -ENOMEM; |
| 152 | 150 | ||
| 153 | /* RAMFC + zero channel's PRAMIN up to start of VM pagedir */ | 151 | /* RAMFC + zero channel's PRAMIN up to start of VM pagedir */ |
| @@ -241,7 +239,7 @@ nv50_instmem_init(struct drm_device *dev) | |||
| 241 | return ret; | 239 | return ret; |
| 242 | BAR0_WI32(priv->fb_bar->gpuobj, 0x00, 0x7fc00000); | 240 | BAR0_WI32(priv->fb_bar->gpuobj, 0x00, 0x7fc00000); |
| 243 | BAR0_WI32(priv->fb_bar->gpuobj, 0x04, 0x40000000 + | 241 | BAR0_WI32(priv->fb_bar->gpuobj, 0x04, 0x40000000 + |
| 244 | drm_get_resource_len(dev, 1) - 1); | 242 | pci_resource_len(dev->pdev, 1) - 1); |
| 245 | BAR0_WI32(priv->fb_bar->gpuobj, 0x08, 0x40000000); | 243 | BAR0_WI32(priv->fb_bar->gpuobj, 0x08, 0x40000000); |
| 246 | BAR0_WI32(priv->fb_bar->gpuobj, 0x0c, 0x00000000); | 244 | BAR0_WI32(priv->fb_bar->gpuobj, 0x0c, 0x00000000); |
| 247 | BAR0_WI32(priv->fb_bar->gpuobj, 0x10, 0x00000000); | 245 | BAR0_WI32(priv->fb_bar->gpuobj, 0x10, 0x00000000); |
| @@ -262,23 +260,18 @@ nv50_instmem_init(struct drm_device *dev) | |||
| 262 | 260 | ||
| 263 | /* Assume that praying isn't enough, check that we can re-read the | 261 | /* Assume that praying isn't enough, check that we can re-read the |
| 264 | * entire fake channel back from the PRAMIN BAR */ | 262 | * entire fake channel back from the PRAMIN BAR */ |
| 265 | dev_priv->engine.instmem.prepare_access(dev, false); | ||
| 266 | for (i = 0; i < c_size; i += 4) { | 263 | for (i = 0; i < c_size; i += 4) { |
| 267 | if (nv_rd32(dev, NV_RAMIN + i) != nv_ri32(dev, i)) { | 264 | if (nv_rd32(dev, NV_RAMIN + i) != nv_ri32(dev, i)) { |
| 268 | NV_ERROR(dev, "Error reading back PRAMIN at 0x%08x\n", | 265 | NV_ERROR(dev, "Error reading back PRAMIN at 0x%08x\n", |
| 269 | i); | 266 | i); |
| 270 | dev_priv->engine.instmem.finish_access(dev); | ||
| 271 | return -EINVAL; | 267 | return -EINVAL; |
| 272 | } | 268 | } |
| 273 | } | 269 | } |
| 274 | dev_priv->engine.instmem.finish_access(dev); | ||
| 275 | 270 | ||
| 276 | nv_wr32(dev, NV50_PUNK_BAR0_PRAMIN, save_nv001700); | 271 | nv_wr32(dev, NV50_PUNK_BAR0_PRAMIN, save_nv001700); |
| 277 | 272 | ||
| 278 | /* Global PRAMIN heap */ | 273 | /* Global PRAMIN heap */ |
| 279 | if (nouveau_mem_init_heap(&dev_priv->ramin_heap, | 274 | if (drm_mm_init(&dev_priv->ramin_heap, c_size, dev_priv->ramin_size - c_size)) { |
| 280 | c_size, dev_priv->ramin_size - c_size)) { | ||
| 281 | dev_priv->ramin_heap = NULL; | ||
| 282 | NV_ERROR(dev, "Failed to init RAMIN heap\n"); | 275 | NV_ERROR(dev, "Failed to init RAMIN heap\n"); |
| 283 | } | 276 | } |
| 284 | 277 | ||
| @@ -321,7 +314,7 @@ nv50_instmem_takedown(struct drm_device *dev) | |||
| 321 | nouveau_gpuobj_del(dev, &chan->vm_pd); | 314 | nouveau_gpuobj_del(dev, &chan->vm_pd); |
| 322 | nouveau_gpuobj_ref_del(dev, &chan->ramfc); | 315 | nouveau_gpuobj_ref_del(dev, &chan->ramfc); |
| 323 | nouveau_gpuobj_ref_del(dev, &chan->ramin); | 316 | nouveau_gpuobj_ref_del(dev, &chan->ramin); |
| 324 | nouveau_mem_takedown(&chan->ramin_heap); | 317 | drm_mm_takedown(&chan->ramin_heap); |
| 325 | 318 | ||
| 326 | dev_priv->fifos[0] = dev_priv->fifos[127] = NULL; | 319 | dev_priv->fifos[0] = dev_priv->fifos[127] = NULL; |
| 327 | kfree(chan); | 320 | kfree(chan); |
| @@ -436,14 +429,14 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | |||
| 436 | if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound) | 429 | if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound) |
| 437 | return -EINVAL; | 430 | return -EINVAL; |
| 438 | 431 | ||
| 439 | NV_DEBUG(dev, "st=0x%0llx sz=0x%0llx\n", | 432 | NV_DEBUG(dev, "st=0x%lx sz=0x%lx\n", |
| 440 | gpuobj->im_pramin->start, gpuobj->im_pramin->size); | 433 | gpuobj->im_pramin->start, gpuobj->im_pramin->size); |
| 441 | 434 | ||
| 442 | pte = (gpuobj->im_pramin->start >> 12) << 1; | 435 | pte = (gpuobj->im_pramin->start >> 12) << 1; |
| 443 | pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte; | 436 | pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte; |
| 444 | vram = gpuobj->im_backing_start; | 437 | vram = gpuobj->im_backing_start; |
| 445 | 438 | ||
| 446 | NV_DEBUG(dev, "pramin=0x%llx, pte=%d, pte_end=%d\n", | 439 | NV_DEBUG(dev, "pramin=0x%lx, pte=%d, pte_end=%d\n", |
| 447 | gpuobj->im_pramin->start, pte, pte_end); | 440 | gpuobj->im_pramin->start, pte, pte_end); |
| 448 | NV_DEBUG(dev, "first vram page: 0x%08x\n", gpuobj->im_backing_start); | 441 | NV_DEBUG(dev, "first vram page: 0x%08x\n", gpuobj->im_backing_start); |
| 449 | 442 | ||
| @@ -453,27 +446,15 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | |||
| 453 | vram |= 0x30; | 446 | vram |= 0x30; |
| 454 | } | 447 | } |
| 455 | 448 | ||
| 456 | dev_priv->engine.instmem.prepare_access(dev, true); | ||
| 457 | while (pte < pte_end) { | 449 | while (pte < pte_end) { |
| 458 | nv_wo32(dev, pramin_pt, pte++, lower_32_bits(vram)); | 450 | nv_wo32(dev, pramin_pt, pte++, lower_32_bits(vram)); |
| 459 | nv_wo32(dev, pramin_pt, pte++, upper_32_bits(vram)); | 451 | nv_wo32(dev, pramin_pt, pte++, upper_32_bits(vram)); |
| 460 | vram += NV50_INSTMEM_PAGE_SIZE; | 452 | vram += NV50_INSTMEM_PAGE_SIZE; |
| 461 | } | 453 | } |
| 462 | dev_priv->engine.instmem.finish_access(dev); | 454 | dev_priv->engine.instmem.flush(dev); |
| 463 | |||
| 464 | nv_wr32(dev, 0x100c80, 0x00040001); | ||
| 465 | if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { | ||
| 466 | NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (1)\n"); | ||
| 467 | NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); | ||
| 468 | return -EBUSY; | ||
| 469 | } | ||
| 470 | 455 | ||
| 471 | nv_wr32(dev, 0x100c80, 0x00060001); | 456 | nv50_vm_flush(dev, 4); |
| 472 | if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { | 457 | nv50_vm_flush(dev, 6); |
| 473 | NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); | ||
| 474 | NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); | ||
| 475 | return -EBUSY; | ||
| 476 | } | ||
| 477 | 458 | ||
| 478 | gpuobj->im_bound = 1; | 459 | gpuobj->im_bound = 1; |
| 479 | return 0; | 460 | return 0; |
| @@ -492,36 +473,37 @@ nv50_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | |||
| 492 | pte = (gpuobj->im_pramin->start >> 12) << 1; | 473 | pte = (gpuobj->im_pramin->start >> 12) << 1; |
| 493 | pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte; | 474 | pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte; |
| 494 | 475 | ||
| 495 | dev_priv->engine.instmem.prepare_access(dev, true); | ||
| 496 | while (pte < pte_end) { | 476 | while (pte < pte_end) { |
| 497 | nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000); | 477 | nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000); |
| 498 | nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000); | 478 | nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000); |
| 499 | } | 479 | } |
| 500 | dev_priv->engine.instmem.finish_access(dev); | 480 | dev_priv->engine.instmem.flush(dev); |
| 501 | 481 | ||
| 502 | gpuobj->im_bound = 0; | 482 | gpuobj->im_bound = 0; |
| 503 | return 0; | 483 | return 0; |
| 504 | } | 484 | } |
| 505 | 485 | ||
| 506 | void | 486 | void |
| 507 | nv50_instmem_prepare_access(struct drm_device *dev, bool write) | 487 | nv50_instmem_flush(struct drm_device *dev) |
| 508 | { | 488 | { |
| 509 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 489 | nv_wr32(dev, 0x00330c, 0x00000001); |
| 510 | struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; | 490 | if (!nv_wait(0x00330c, 0x00000002, 0x00000000)) |
| 511 | 491 | NV_ERROR(dev, "PRAMIN flush timeout\n"); | |
| 512 | priv->last_access_wr = write; | ||
| 513 | } | 492 | } |
| 514 | 493 | ||
| 515 | void | 494 | void |
| 516 | nv50_instmem_finish_access(struct drm_device *dev) | 495 | nv84_instmem_flush(struct drm_device *dev) |
| 517 | { | 496 | { |
| 518 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 497 | nv_wr32(dev, 0x070000, 0x00000001); |
| 519 | struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; | 498 | if (!nv_wait(0x070000, 0x00000002, 0x00000000)) |
| 499 | NV_ERROR(dev, "PRAMIN flush timeout\n"); | ||
| 500 | } | ||
| 520 | 501 | ||
| 521 | if (priv->last_access_wr) { | 502 | void |
| 522 | nv_wr32(dev, 0x070000, 0x00000001); | 503 | nv50_vm_flush(struct drm_device *dev, int engine) |
| 523 | if (!nv_wait(0x070000, 0x00000001, 0x00000000)) | 504 | { |
| 524 | NV_ERROR(dev, "PRAMIN flush timeout\n"); | 505 | nv_wr32(dev, 0x100c80, (engine << 16) | 1); |
| 525 | } | 506 | if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) |
| 507 | NV_ERROR(dev, "vm flush timeout: engine %d\n", engine); | ||
| 526 | } | 508 | } |
| 527 | 509 | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c index 812778db76ac..bcd4cf84a7e6 100644 --- a/drivers/gpu/drm/nouveau/nv50_sor.c +++ b/drivers/gpu/drm/nouveau/nv50_sor.c | |||
| @@ -37,52 +37,32 @@ | |||
| 37 | #include "nv50_display.h" | 37 | #include "nv50_display.h" |
| 38 | 38 | ||
| 39 | static void | 39 | static void |
| 40 | nv50_sor_disconnect(struct nouveau_encoder *nv_encoder) | 40 | nv50_sor_disconnect(struct drm_encoder *encoder) |
| 41 | { | 41 | { |
| 42 | struct drm_device *dev = to_drm_encoder(nv_encoder)->dev; | 42 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); |
| 43 | struct drm_device *dev = encoder->dev; | ||
| 43 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 44 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 44 | struct nouveau_channel *evo = dev_priv->evo; | 45 | struct nouveau_channel *evo = dev_priv->evo; |
| 45 | int ret; | 46 | int ret; |
| 46 | 47 | ||
| 48 | if (!nv_encoder->crtc) | ||
| 49 | return; | ||
| 50 | nv50_crtc_blank(nouveau_crtc(nv_encoder->crtc), true); | ||
| 51 | |||
| 47 | NV_DEBUG_KMS(dev, "Disconnecting SOR %d\n", nv_encoder->or); | 52 | NV_DEBUG_KMS(dev, "Disconnecting SOR %d\n", nv_encoder->or); |
| 48 | 53 | ||
| 49 | ret = RING_SPACE(evo, 2); | 54 | ret = RING_SPACE(evo, 4); |
| 50 | if (ret) { | 55 | if (ret) { |
| 51 | NV_ERROR(dev, "no space while disconnecting SOR\n"); | 56 | NV_ERROR(dev, "no space while disconnecting SOR\n"); |
| 52 | return; | 57 | return; |
| 53 | } | 58 | } |
| 54 | BEGIN_RING(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1); | 59 | BEGIN_RING(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1); |
| 55 | OUT_RING(evo, 0); | 60 | OUT_RING (evo, 0); |
| 56 | } | 61 | BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); |
| 57 | 62 | OUT_RING (evo, 0); | |
| 58 | static void | ||
| 59 | nv50_sor_dp_link_train(struct drm_encoder *encoder) | ||
| 60 | { | ||
| 61 | struct drm_device *dev = encoder->dev; | ||
| 62 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||
| 63 | struct bit_displayport_encoder_table *dpe; | ||
| 64 | int dpe_headerlen; | ||
| 65 | |||
| 66 | dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); | ||
| 67 | if (!dpe) { | ||
| 68 | NV_ERROR(dev, "SOR-%d: no DP encoder table!\n", nv_encoder->or); | ||
| 69 | return; | ||
| 70 | } | ||
| 71 | 63 | ||
| 72 | if (dpe->script0) { | 64 | nv_encoder->crtc = NULL; |
| 73 | NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or); | 65 | nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; |
| 74 | nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script0), | ||
| 75 | nv_encoder->dcb); | ||
| 76 | } | ||
| 77 | |||
| 78 | if (!nouveau_dp_link_train(encoder)) | ||
| 79 | NV_ERROR(dev, "SOR-%d: link training failed\n", nv_encoder->or); | ||
| 80 | |||
| 81 | if (dpe->script1) { | ||
| 82 | NV_DEBUG_KMS(dev, "SOR-%d: running DP script 1\n", nv_encoder->or); | ||
| 83 | nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script1), | ||
| 84 | nv_encoder->dcb); | ||
| 85 | } | ||
| 86 | } | 66 | } |
| 87 | 67 | ||
| 88 | static void | 68 | static void |
| @@ -94,14 +74,16 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) | |||
| 94 | uint32_t val; | 74 | uint32_t val; |
| 95 | int or = nv_encoder->or; | 75 | int or = nv_encoder->or; |
| 96 | 76 | ||
| 97 | NV_DEBUG_KMS(dev, "or %d mode %d\n", or, mode); | 77 | NV_DEBUG_KMS(dev, "or %d type %d mode %d\n", or, nv_encoder->dcb->type, mode); |
| 98 | 78 | ||
| 99 | nv_encoder->last_dpms = mode; | 79 | nv_encoder->last_dpms = mode; |
| 100 | list_for_each_entry(enc, &dev->mode_config.encoder_list, head) { | 80 | list_for_each_entry(enc, &dev->mode_config.encoder_list, head) { |
| 101 | struct nouveau_encoder *nvenc = nouveau_encoder(enc); | 81 | struct nouveau_encoder *nvenc = nouveau_encoder(enc); |
| 102 | 82 | ||
| 103 | if (nvenc == nv_encoder || | 83 | if (nvenc == nv_encoder || |
| 104 | nvenc->disconnect != nv50_sor_disconnect || | 84 | (nvenc->dcb->type != OUTPUT_TMDS && |
| 85 | nvenc->dcb->type != OUTPUT_LVDS && | ||
| 86 | nvenc->dcb->type != OUTPUT_DP) || | ||
| 105 | nvenc->dcb->or != nv_encoder->dcb->or) | 87 | nvenc->dcb->or != nv_encoder->dcb->or) |
| 106 | continue; | 88 | continue; |
| 107 | 89 | ||
| @@ -133,8 +115,22 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) | |||
| 133 | nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_STATE(or))); | 115 | nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_STATE(or))); |
| 134 | } | 116 | } |
| 135 | 117 | ||
| 136 | if (nv_encoder->dcb->type == OUTPUT_DP && mode == DRM_MODE_DPMS_ON) | 118 | if (nv_encoder->dcb->type == OUTPUT_DP) { |
| 137 | nv50_sor_dp_link_train(encoder); | 119 | struct nouveau_i2c_chan *auxch; |
| 120 | |||
| 121 | auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); | ||
| 122 | if (!auxch) | ||
| 123 | return; | ||
| 124 | |||
| 125 | if (mode == DRM_MODE_DPMS_ON) { | ||
| 126 | u8 status = DP_SET_POWER_D0; | ||
| 127 | nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1); | ||
| 128 | nouveau_dp_link_train(encoder); | ||
| 129 | } else { | ||
| 130 | u8 status = DP_SET_POWER_D3; | ||
| 131 | nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1); | ||
| 132 | } | ||
| 133 | } | ||
| 138 | } | 134 | } |
| 139 | 135 | ||
| 140 | static void | 136 | static void |
| @@ -196,7 +192,8 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
| 196 | uint32_t mode_ctl = 0; | 192 | uint32_t mode_ctl = 0; |
| 197 | int ret; | 193 | int ret; |
| 198 | 194 | ||
| 199 | NV_DEBUG_KMS(dev, "or %d\n", nv_encoder->or); | 195 | NV_DEBUG_KMS(dev, "or %d type %d -> crtc %d\n", |
| 196 | nv_encoder->or, nv_encoder->dcb->type, crtc->index); | ||
| 200 | 197 | ||
| 201 | nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON); | 198 | nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON); |
| 202 | 199 | ||
| @@ -239,6 +236,14 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
| 239 | } | 236 | } |
| 240 | BEGIN_RING(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1); | 237 | BEGIN_RING(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1); |
| 241 | OUT_RING(evo, mode_ctl); | 238 | OUT_RING(evo, mode_ctl); |
| 239 | |||
| 240 | nv_encoder->crtc = encoder->crtc; | ||
| 241 | } | ||
| 242 | |||
| 243 | static struct drm_crtc * | ||
| 244 | nv50_sor_crtc_get(struct drm_encoder *encoder) | ||
| 245 | { | ||
| 246 | return nouveau_encoder(encoder)->crtc; | ||
| 242 | } | 247 | } |
| 243 | 248 | ||
| 244 | static const struct drm_encoder_helper_funcs nv50_sor_helper_funcs = { | 249 | 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 = { | |||
| 249 | .prepare = nv50_sor_prepare, | 254 | .prepare = nv50_sor_prepare, |
| 250 | .commit = nv50_sor_commit, | 255 | .commit = nv50_sor_commit, |
| 251 | .mode_set = nv50_sor_mode_set, | 256 | .mode_set = nv50_sor_mode_set, |
| 252 | .detect = NULL | 257 | .get_crtc = nv50_sor_crtc_get, |
| 258 | .detect = NULL, | ||
| 259 | .disable = nv50_sor_disconnect | ||
| 253 | }; | 260 | }; |
| 254 | 261 | ||
| 255 | static void | 262 | static void |
| @@ -272,32 +279,22 @@ static const struct drm_encoder_funcs nv50_sor_encoder_funcs = { | |||
| 272 | }; | 279 | }; |
| 273 | 280 | ||
| 274 | int | 281 | int |
| 275 | nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry) | 282 | nv50_sor_create(struct drm_connector *connector, struct dcb_entry *entry) |
| 276 | { | 283 | { |
| 277 | struct nouveau_encoder *nv_encoder = NULL; | 284 | struct nouveau_encoder *nv_encoder = NULL; |
| 285 | struct drm_device *dev = connector->dev; | ||
| 278 | struct drm_encoder *encoder; | 286 | struct drm_encoder *encoder; |
| 279 | bool dum; | ||
| 280 | int type; | 287 | int type; |
| 281 | 288 | ||
| 282 | NV_DEBUG_KMS(dev, "\n"); | 289 | NV_DEBUG_KMS(dev, "\n"); |
| 283 | 290 | ||
| 284 | switch (entry->type) { | 291 | switch (entry->type) { |
| 285 | case OUTPUT_TMDS: | 292 | case OUTPUT_TMDS: |
| 286 | NV_INFO(dev, "Detected a TMDS output\n"); | 293 | case OUTPUT_DP: |
| 287 | type = DRM_MODE_ENCODER_TMDS; | 294 | type = DRM_MODE_ENCODER_TMDS; |
| 288 | break; | 295 | break; |
| 289 | case OUTPUT_LVDS: | 296 | case OUTPUT_LVDS: |
| 290 | NV_INFO(dev, "Detected a LVDS output\n"); | ||
| 291 | type = DRM_MODE_ENCODER_LVDS; | 297 | type = DRM_MODE_ENCODER_LVDS; |
| 292 | |||
| 293 | if (nouveau_bios_parse_lvds_table(dev, 0, &dum, &dum)) { | ||
| 294 | NV_ERROR(dev, "Failed parsing LVDS table\n"); | ||
| 295 | return -EINVAL; | ||
| 296 | } | ||
| 297 | break; | ||
| 298 | case OUTPUT_DP: | ||
| 299 | NV_INFO(dev, "Detected a DP output\n"); | ||
| 300 | type = DRM_MODE_ENCODER_TMDS; | ||
| 301 | break; | 298 | break; |
| 302 | default: | 299 | default: |
| 303 | return -EINVAL; | 300 | return -EINVAL; |
| @@ -310,8 +307,7 @@ nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry) | |||
| 310 | 307 | ||
| 311 | nv_encoder->dcb = entry; | 308 | nv_encoder->dcb = entry; |
| 312 | nv_encoder->or = ffs(entry->or) - 1; | 309 | nv_encoder->or = ffs(entry->or) - 1; |
| 313 | 310 | nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; | |
| 314 | nv_encoder->disconnect = nv50_sor_disconnect; | ||
| 315 | 311 | ||
| 316 | drm_encoder_init(dev, encoder, &nv50_sor_encoder_funcs, type); | 312 | drm_encoder_init(dev, encoder, &nv50_sor_encoder_funcs, type); |
| 317 | drm_encoder_helper_add(encoder, &nv50_sor_helper_funcs); | 313 | drm_encoder_helper_add(encoder, &nv50_sor_helper_funcs); |
| @@ -342,5 +338,6 @@ nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry) | |||
| 342 | nv_encoder->dp.mc_unknown = 5; | 338 | nv_encoder->dp.mc_unknown = 5; |
| 343 | } | 339 | } |
| 344 | 340 | ||
| 341 | drm_mode_connector_attach_encoder(connector, encoder); | ||
| 345 | return 0; | 342 | return 0; |
| 346 | } | 343 | } |
diff --git a/drivers/gpu/drm/nouveau/nvreg.h b/drivers/gpu/drm/nouveau/nvreg.h index 5998c35237b0..ad64673ace1f 100644 --- a/drivers/gpu/drm/nouveau/nvreg.h +++ b/drivers/gpu/drm/nouveau/nvreg.h | |||
| @@ -147,28 +147,6 @@ | |||
| 147 | # define NV_VIO_GX_DONT_CARE_INDEX 0x07 | 147 | # define NV_VIO_GX_DONT_CARE_INDEX 0x07 |
| 148 | # define NV_VIO_GX_BIT_MASK_INDEX 0x08 | 148 | # define NV_VIO_GX_BIT_MASK_INDEX 0x08 |
| 149 | 149 | ||
| 150 | #define NV_PFB_BOOT_0 0x00100000 | ||
| 151 | #define NV_PFB_CFG0 0x00100200 | ||
| 152 | #define NV_PFB_CFG1 0x00100204 | ||
| 153 | #define NV_PFB_CSTATUS 0x0010020C | ||
| 154 | #define NV_PFB_REFCTRL 0x00100210 | ||
| 155 | # define NV_PFB_REFCTRL_VALID_1 (1 << 31) | ||
| 156 | #define NV_PFB_PAD 0x0010021C | ||
| 157 | # define NV_PFB_PAD_CKE_NORMAL (1 << 0) | ||
| 158 | #define NV_PFB_TILE_NV10 0x00100240 | ||
| 159 | #define NV_PFB_TILE_SIZE_NV10 0x00100244 | ||
| 160 | #define NV_PFB_REF 0x001002D0 | ||
| 161 | # define NV_PFB_REF_CMD_REFRESH (1 << 0) | ||
| 162 | #define NV_PFB_PRE 0x001002D4 | ||
| 163 | # define NV_PFB_PRE_CMD_PRECHARGE (1 << 0) | ||
| 164 | #define NV_PFB_CLOSE_PAGE2 0x0010033C | ||
| 165 | #define NV_PFB_TILE_NV40 0x00100600 | ||
| 166 | #define NV_PFB_TILE_SIZE_NV40 0x00100604 | ||
| 167 | |||
| 168 | #define NV_PEXTDEV_BOOT_0 0x00101000 | ||
| 169 | # define NV_PEXTDEV_BOOT_0_STRAP_FP_IFACE_12BIT (8 << 12) | ||
| 170 | #define NV_PEXTDEV_BOOT_3 0x0010100c | ||
| 171 | |||
| 172 | #define NV_PCRTC_INTR_0 0x00600100 | 150 | #define NV_PCRTC_INTR_0 0x00600100 |
| 173 | # define NV_PCRTC_INTR_0_VBLANK (1 << 0) | 151 | # define NV_PCRTC_INTR_0_VBLANK (1 << 0) |
| 174 | #define NV_PCRTC_INTR_EN_0 0x00600140 | 152 | #define NV_PCRTC_INTR_EN_0 0x00600140 |
