diff options
Diffstat (limited to 'drivers/gpu')
164 files changed, 9035 insertions, 5962 deletions
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 0902d446003..a6feb78c404 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig | |||
@@ -73,32 +73,17 @@ source "drivers/gpu/drm/radeon/Kconfig" | |||
73 | 73 | ||
74 | config DRM_I810 | 74 | config DRM_I810 |
75 | tristate "Intel I810" | 75 | tristate "Intel I810" |
76 | # BKL usage in order to avoid AB-BA deadlocks, may become BROKEN_ON_SMP | 76 | # !PREEMPT because of missing ioctl locking |
77 | depends on DRM && AGP && AGP_INTEL && BKL | 77 | depends on DRM && AGP && AGP_INTEL && (!PREEMPT || BROKEN) |
78 | help | 78 | help |
79 | Choose this option if you have an Intel I810 graphics card. If M is | 79 | Choose this option if you have an Intel I810 graphics card. If M is |
80 | selected, the module will be called i810. AGP support is required | 80 | selected, the module will be called i810. AGP support is required |
81 | for this driver to work. | 81 | for this driver to work. |
82 | 82 | ||
83 | choice | ||
84 | prompt "Intel 830M, 845G, 852GM, 855GM, 865G" | ||
85 | depends on DRM && AGP && AGP_INTEL | ||
86 | optional | ||
87 | |||
88 | config DRM_I830 | ||
89 | tristate "i830 driver" | ||
90 | # BKL usage in order to avoid AB-BA deadlocks, i830 may get removed | ||
91 | depends on BKL | ||
92 | help | ||
93 | Choose this option if you have a system that has Intel 830M, 845G, | ||
94 | 852GM, 855GM or 865G integrated graphics. If M is selected, the | ||
95 | module will be called i830. AGP support is required for this driver | ||
96 | to work. This driver is used by the older X releases X.org 6.7 and | ||
97 | XFree86 4.3. If unsure, build this and i915 as modules and the X server | ||
98 | will load the correct one. | ||
99 | |||
100 | config DRM_I915 | 83 | config DRM_I915 |
101 | tristate "i915 driver" | 84 | tristate "Intel 8xx/9xx/G3x/G4x/HD Graphics" |
85 | depends on DRM | ||
86 | depends on AGP | ||
102 | depends on AGP_INTEL | 87 | depends on AGP_INTEL |
103 | # we need shmfs for the swappable backing store, and in particular | 88 | # we need shmfs for the swappable backing store, and in particular |
104 | # the shmem_readpage() which depends upon tmpfs | 89 | # the shmem_readpage() which depends upon tmpfs |
@@ -115,12 +100,20 @@ config DRM_I915 | |||
115 | select ACPI_VIDEO if ACPI | 100 | select ACPI_VIDEO if ACPI |
116 | select ACPI_BUTTON if ACPI | 101 | select ACPI_BUTTON if ACPI |
117 | help | 102 | help |
118 | Choose this option if you have a system that has Intel 830M, 845G, | 103 | Choose this option if you have a system that has "Intel Graphics |
119 | 852GM, 855GM 865G or 915G integrated graphics. If M is selected, the | 104 | Media Accelerator" or "HD Graphics" integrated graphics, |
120 | module will be called i915. AGP support is required for this driver | 105 | including 830M, 845G, 852GM, 855GM, 865G, 915G, 945G, 965G, |
121 | to work. This driver is used by the Intel driver in X.org 6.8 and | 106 | G35, G41, G43, G45 chipsets and Celeron, Pentium, Core i3, |
122 | XFree86 4.4 and above. If unsure, build this and i830 as modules and | 107 | Core i5, Core i7 as well as Atom CPUs with integrated graphics. |
123 | the X server will load the correct one. | 108 | If M is selected, the module will be called i915. AGP support |
109 | is required for this driver to work. This driver is used by | ||
110 | the Intel driver in X.org 6.8 and XFree86 4.4 and above. It | ||
111 | replaces the older i830 module that supported a subset of the | ||
112 | hardware in older X.org releases. | ||
113 | |||
114 | Note that the older i810/i815 chipsets require the use of the | ||
115 | i810 driver instead, and the Atom z5xx series has an entirely | ||
116 | different implementation. | ||
124 | 117 | ||
125 | config DRM_I915_KMS | 118 | config DRM_I915_KMS |
126 | bool "Enable modesetting on intel by default" | 119 | bool "Enable modesetting on intel by default" |
@@ -132,8 +125,6 @@ config DRM_I915_KMS | |||
132 | the driver to bind to PCI devices, which precludes loading things | 125 | the driver to bind to PCI devices, which precludes loading things |
133 | like intelfb. | 126 | like intelfb. |
134 | 127 | ||
135 | endchoice | ||
136 | |||
137 | config DRM_MGA | 128 | config DRM_MGA |
138 | tristate "Matrox g200/g400" | 129 | tristate "Matrox g200/g400" |
139 | depends on DRM && PCI | 130 | depends on DRM && PCI |
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 997c43d0490..89cf05a72d1 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile | |||
@@ -12,7 +12,7 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \ | |||
12 | drm_platform.o drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o \ | 12 | drm_platform.o drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o \ |
13 | drm_crtc.o drm_modes.o drm_edid.o \ | 13 | drm_crtc.o drm_modes.o drm_edid.o \ |
14 | drm_info.o drm_debugfs.o drm_encoder_slave.o \ | 14 | drm_info.o drm_debugfs.o drm_encoder_slave.o \ |
15 | drm_trace_points.o drm_global.o | 15 | drm_trace_points.o drm_global.o drm_usb.o |
16 | 16 | ||
17 | drm-$(CONFIG_COMPAT) += drm_ioc32.o | 17 | drm-$(CONFIG_COMPAT) += drm_ioc32.o |
18 | 18 | ||
@@ -29,7 +29,6 @@ obj-$(CONFIG_DRM_R128) += r128/ | |||
29 | obj-$(CONFIG_DRM_RADEON)+= radeon/ | 29 | obj-$(CONFIG_DRM_RADEON)+= radeon/ |
30 | obj-$(CONFIG_DRM_MGA) += mga/ | 30 | obj-$(CONFIG_DRM_MGA) += mga/ |
31 | obj-$(CONFIG_DRM_I810) += i810/ | 31 | obj-$(CONFIG_DRM_I810) += i810/ |
32 | obj-$(CONFIG_DRM_I830) += i830/ | ||
33 | obj-$(CONFIG_DRM_I915) += i915/ | 32 | obj-$(CONFIG_DRM_I915) += i915/ |
34 | obj-$(CONFIG_DRM_SIS) += sis/ | 33 | obj-$(CONFIG_DRM_SIS) += sis/ |
35 | obj-$(CONFIG_DRM_SAVAGE)+= savage/ | 34 | obj-$(CONFIG_DRM_SAVAGE)+= savage/ |
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 654faa803dc..4c95b5fd9df 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -2694,3 +2694,36 @@ void drm_mode_config_reset(struct drm_device *dev) | |||
2694 | connector->funcs->reset(connector); | 2694 | connector->funcs->reset(connector); |
2695 | } | 2695 | } |
2696 | EXPORT_SYMBOL(drm_mode_config_reset); | 2696 | EXPORT_SYMBOL(drm_mode_config_reset); |
2697 | |||
2698 | int drm_mode_create_dumb_ioctl(struct drm_device *dev, | ||
2699 | void *data, struct drm_file *file_priv) | ||
2700 | { | ||
2701 | struct drm_mode_create_dumb *args = data; | ||
2702 | |||
2703 | if (!dev->driver->dumb_create) | ||
2704 | return -ENOSYS; | ||
2705 | return dev->driver->dumb_create(file_priv, dev, args); | ||
2706 | } | ||
2707 | |||
2708 | int drm_mode_mmap_dumb_ioctl(struct drm_device *dev, | ||
2709 | void *data, struct drm_file *file_priv) | ||
2710 | { | ||
2711 | struct drm_mode_map_dumb *args = data; | ||
2712 | |||
2713 | /* call driver ioctl to get mmap offset */ | ||
2714 | if (!dev->driver->dumb_map_offset) | ||
2715 | return -ENOSYS; | ||
2716 | |||
2717 | return dev->driver->dumb_map_offset(file_priv, dev, args->handle, &args->offset); | ||
2718 | } | ||
2719 | |||
2720 | int drm_mode_destroy_dumb_ioctl(struct drm_device *dev, | ||
2721 | void *data, struct drm_file *file_priv) | ||
2722 | { | ||
2723 | struct drm_mode_destroy_dumb *args = data; | ||
2724 | |||
2725 | if (!dev->driver->dumb_destroy) | ||
2726 | return -ENOSYS; | ||
2727 | |||
2728 | return dev->driver->dumb_destroy(file_priv, dev, args->handle); | ||
2729 | } | ||
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 271835a7157..93a112d45c1 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c | |||
@@ -67,6 +67,7 @@ static struct drm_ioctl_desc drm_ioctls[] = { | |||
67 | DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, 0), | 67 | DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, 0), |
68 | DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0), | 68 | DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0), |
69 | DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0), | 69 | DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0), |
70 | DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, 0), | ||
70 | DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER), | 71 | DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER), |
71 | 72 | ||
72 | DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | 73 | DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
@@ -150,7 +151,10 @@ static struct drm_ioctl_desc drm_ioctls[] = { | |||
150 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | 151 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
151 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | 152 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
152 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | 153 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
153 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED) | 154 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
155 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | ||
156 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | ||
157 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED) | ||
154 | }; | 158 | }; |
155 | 159 | ||
156 | #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) | 160 | #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) |
@@ -234,49 +238,6 @@ int drm_lastclose(struct drm_device * dev) | |||
234 | return 0; | 238 | return 0; |
235 | } | 239 | } |
236 | 240 | ||
237 | /** | ||
238 | * Module initialization. Called via init_module at module load time, or via | ||
239 | * linux/init/main.c (this is not currently supported). | ||
240 | * | ||
241 | * \return zero on success or a negative number on failure. | ||
242 | * | ||
243 | * Initializes an array of drm_device structures, and attempts to | ||
244 | * initialize all available devices, using consecutive minors, registering the | ||
245 | * stubs and initializing the device. | ||
246 | * | ||
247 | * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and | ||
248 | * after the initialization for driver customization. | ||
249 | */ | ||
250 | int drm_init(struct drm_driver *driver) | ||
251 | { | ||
252 | DRM_DEBUG("\n"); | ||
253 | INIT_LIST_HEAD(&driver->device_list); | ||
254 | |||
255 | if (driver->driver_features & DRIVER_USE_PLATFORM_DEVICE) | ||
256 | return drm_platform_init(driver); | ||
257 | else | ||
258 | return drm_pci_init(driver); | ||
259 | } | ||
260 | |||
261 | EXPORT_SYMBOL(drm_init); | ||
262 | |||
263 | void drm_exit(struct drm_driver *driver) | ||
264 | { | ||
265 | struct drm_device *dev, *tmp; | ||
266 | DRM_DEBUG("\n"); | ||
267 | |||
268 | if (driver->driver_features & DRIVER_MODESET) { | ||
269 | pci_unregister_driver(&driver->pci_driver); | ||
270 | } else { | ||
271 | list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item) | ||
272 | drm_put_dev(dev); | ||
273 | } | ||
274 | |||
275 | DRM_INFO("Module unloaded\n"); | ||
276 | } | ||
277 | |||
278 | EXPORT_SYMBOL(drm_exit); | ||
279 | |||
280 | /** File operations structure */ | 241 | /** File operations structure */ |
281 | static const struct file_operations drm_stub_fops = { | 242 | static const struct file_operations drm_stub_fops = { |
282 | .owner = THIS_MODULE, | 243 | .owner = THIS_MODULE, |
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index a245d17165a..9c595e3b9c2 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
@@ -230,24 +230,32 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf, | |||
230 | int block, int len) | 230 | int block, int len) |
231 | { | 231 | { |
232 | unsigned char start = block * EDID_LENGTH; | 232 | unsigned char start = block * EDID_LENGTH; |
233 | struct i2c_msg msgs[] = { | 233 | int ret, retries = 5; |
234 | { | ||
235 | .addr = DDC_ADDR, | ||
236 | .flags = 0, | ||
237 | .len = 1, | ||
238 | .buf = &start, | ||
239 | }, { | ||
240 | .addr = DDC_ADDR, | ||
241 | .flags = I2C_M_RD, | ||
242 | .len = len, | ||
243 | .buf = buf, | ||
244 | } | ||
245 | }; | ||
246 | 234 | ||
247 | if (i2c_transfer(adapter, msgs, 2) == 2) | 235 | /* The core i2c driver will automatically retry the transfer if the |
248 | return 0; | 236 | * adapter reports EAGAIN. However, we find that bit-banging transfers |
237 | * are susceptible to errors under a heavily loaded machine and | ||
238 | * generate spurious NAKs and timeouts. Retrying the transfer | ||
239 | * of the individual block a few times seems to overcome this. | ||
240 | */ | ||
241 | do { | ||
242 | struct i2c_msg msgs[] = { | ||
243 | { | ||
244 | .addr = DDC_ADDR, | ||
245 | .flags = 0, | ||
246 | .len = 1, | ||
247 | .buf = &start, | ||
248 | }, { | ||
249 | .addr = DDC_ADDR, | ||
250 | .flags = I2C_M_RD, | ||
251 | .len = len, | ||
252 | .buf = buf, | ||
253 | } | ||
254 | }; | ||
255 | ret = i2c_transfer(adapter, msgs, 2); | ||
256 | } while (ret != 2 && --retries); | ||
249 | 257 | ||
250 | return -1; | 258 | return ret == 2 ? 0 : -1; |
251 | } | 259 | } |
252 | 260 | ||
253 | static u8 * | 261 | static u8 * |
@@ -449,12 +457,11 @@ static void edid_fixup_preferred(struct drm_connector *connector, | |||
449 | struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev, | 457 | struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev, |
450 | int hsize, int vsize, int fresh) | 458 | int hsize, int vsize, int fresh) |
451 | { | 459 | { |
460 | struct drm_display_mode *mode = NULL; | ||
452 | int i; | 461 | int i; |
453 | struct drm_display_mode *ptr, *mode; | ||
454 | 462 | ||
455 | mode = NULL; | ||
456 | for (i = 0; i < drm_num_dmt_modes; i++) { | 463 | for (i = 0; i < drm_num_dmt_modes; i++) { |
457 | ptr = &drm_dmt_modes[i]; | 464 | const struct drm_display_mode *ptr = &drm_dmt_modes[i]; |
458 | if (hsize == ptr->hdisplay && | 465 | if (hsize == ptr->hdisplay && |
459 | vsize == ptr->vdisplay && | 466 | vsize == ptr->vdisplay && |
460 | fresh == drm_mode_vrefresh(ptr)) { | 467 | fresh == drm_mode_vrefresh(ptr)) { |
@@ -885,7 +892,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, | |||
885 | } | 892 | } |
886 | 893 | ||
887 | static bool | 894 | static bool |
888 | mode_is_rb(struct drm_display_mode *mode) | 895 | mode_is_rb(const struct drm_display_mode *mode) |
889 | { | 896 | { |
890 | return (mode->htotal - mode->hdisplay == 160) && | 897 | return (mode->htotal - mode->hdisplay == 160) && |
891 | (mode->hsync_end - mode->hdisplay == 80) && | 898 | (mode->hsync_end - mode->hdisplay == 80) && |
@@ -894,7 +901,8 @@ mode_is_rb(struct drm_display_mode *mode) | |||
894 | } | 901 | } |
895 | 902 | ||
896 | static bool | 903 | static bool |
897 | mode_in_hsync_range(struct drm_display_mode *mode, struct edid *edid, u8 *t) | 904 | mode_in_hsync_range(const struct drm_display_mode *mode, |
905 | struct edid *edid, u8 *t) | ||
898 | { | 906 | { |
899 | int hsync, hmin, hmax; | 907 | int hsync, hmin, hmax; |
900 | 908 | ||
@@ -910,7 +918,8 @@ mode_in_hsync_range(struct drm_display_mode *mode, struct edid *edid, u8 *t) | |||
910 | } | 918 | } |
911 | 919 | ||
912 | static bool | 920 | static bool |
913 | mode_in_vsync_range(struct drm_display_mode *mode, struct edid *edid, u8 *t) | 921 | mode_in_vsync_range(const struct drm_display_mode *mode, |
922 | struct edid *edid, u8 *t) | ||
914 | { | 923 | { |
915 | int vsync, vmin, vmax; | 924 | int vsync, vmin, vmax; |
916 | 925 | ||
@@ -941,7 +950,7 @@ range_pixel_clock(struct edid *edid, u8 *t) | |||
941 | } | 950 | } |
942 | 951 | ||
943 | static bool | 952 | static bool |
944 | mode_in_range(struct drm_display_mode *mode, struct edid *edid, | 953 | mode_in_range(const struct drm_display_mode *mode, struct edid *edid, |
945 | struct detailed_timing *timing) | 954 | struct detailed_timing *timing) |
946 | { | 955 | { |
947 | u32 max_clock; | 956 | u32 max_clock; |
@@ -1472,7 +1481,7 @@ int drm_add_modes_noedid(struct drm_connector *connector, | |||
1472 | int hdisplay, int vdisplay) | 1481 | int hdisplay, int vdisplay) |
1473 | { | 1482 | { |
1474 | int i, count, num_modes = 0; | 1483 | int i, count, num_modes = 0; |
1475 | struct drm_display_mode *mode, *ptr; | 1484 | struct drm_display_mode *mode; |
1476 | struct drm_device *dev = connector->dev; | 1485 | struct drm_device *dev = connector->dev; |
1477 | 1486 | ||
1478 | count = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode); | 1487 | count = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode); |
@@ -1482,7 +1491,7 @@ int drm_add_modes_noedid(struct drm_connector *connector, | |||
1482 | vdisplay = 0; | 1491 | vdisplay = 0; |
1483 | 1492 | ||
1484 | for (i = 0; i < count; i++) { | 1493 | for (i = 0; i < count; i++) { |
1485 | ptr = &drm_dmt_modes[i]; | 1494 | const struct drm_display_mode *ptr = &drm_dmt_modes[i]; |
1486 | if (hdisplay && vdisplay) { | 1495 | if (hdisplay && vdisplay) { |
1487 | /* | 1496 | /* |
1488 | * Only when two are valid, they will be used to check | 1497 | * Only when two are valid, they will be used to check |
diff --git a/drivers/gpu/drm/drm_edid_modes.h b/drivers/gpu/drm/drm_edid_modes.h index 6eb7592e152..5f2064489fd 100644 --- a/drivers/gpu/drm/drm_edid_modes.h +++ b/drivers/gpu/drm/drm_edid_modes.h | |||
@@ -32,7 +32,7 @@ | |||
32 | * This table is copied from xfree86/modes/xf86EdidModes.c. | 32 | * This table is copied from xfree86/modes/xf86EdidModes.c. |
33 | * But the mode with Reduced blank feature is deleted. | 33 | * But the mode with Reduced blank feature is deleted. |
34 | */ | 34 | */ |
35 | static struct drm_display_mode drm_dmt_modes[] = { | 35 | static const struct drm_display_mode drm_dmt_modes[] = { |
36 | /* 640x350@85Hz */ | 36 | /* 640x350@85Hz */ |
37 | { DRM_MODE("640x350", DRM_MODE_TYPE_DRIVER, 31500, 640, 672, | 37 | { DRM_MODE("640x350", DRM_MODE_TYPE_DRIVER, 31500, 640, 672, |
38 | 736, 832, 0, 350, 382, 385, 445, 0, | 38 | 736, 832, 0, 350, 382, 385, 445, 0, |
@@ -266,7 +266,7 @@ static struct drm_display_mode drm_dmt_modes[] = { | |||
266 | static const int drm_num_dmt_modes = | 266 | static const int drm_num_dmt_modes = |
267 | sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode); | 267 | sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode); |
268 | 268 | ||
269 | static struct drm_display_mode edid_est_modes[] = { | 269 | static const struct drm_display_mode edid_est_modes[] = { |
270 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840, | 270 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840, |
271 | 968, 1056, 0, 600, 601, 605, 628, 0, | 271 | 968, 1056, 0, 600, 601, 605, 628, 0, |
272 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@60Hz */ | 272 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@60Hz */ |
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index f73ef4390db..95072047396 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c | |||
@@ -627,6 +627,11 @@ static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green, | |||
627 | value = (red << info->var.red.offset) | | 627 | value = (red << info->var.red.offset) | |
628 | (green << info->var.green.offset) | | 628 | (green << info->var.green.offset) | |
629 | (blue << info->var.blue.offset); | 629 | (blue << info->var.blue.offset); |
630 | if (info->var.transp.length > 0) { | ||
631 | u32 mask = (1 << info->var.transp.length) - 1; | ||
632 | mask <<= info->var.transp.offset; | ||
633 | value |= mask; | ||
634 | } | ||
630 | palette[regno] = value; | 635 | palette[regno] = value; |
631 | return 0; | 636 | return 0; |
632 | } | 637 | } |
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index ea1c4b019eb..57ce27c9a74 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c | |||
@@ -101,7 +101,7 @@ drm_gem_init(struct drm_device *dev) | |||
101 | 101 | ||
102 | dev->mm_private = mm; | 102 | dev->mm_private = mm; |
103 | 103 | ||
104 | if (drm_ht_create(&mm->offset_hash, 19)) { | 104 | if (drm_ht_create(&mm->offset_hash, 12)) { |
105 | kfree(mm); | 105 | kfree(mm); |
106 | return -ENOMEM; | 106 | return -ENOMEM; |
107 | } | 107 | } |
@@ -181,7 +181,7 @@ EXPORT_SYMBOL(drm_gem_object_alloc); | |||
181 | /** | 181 | /** |
182 | * Removes the mapping from handle to filp for this object. | 182 | * Removes the mapping from handle to filp for this object. |
183 | */ | 183 | */ |
184 | static int | 184 | int |
185 | drm_gem_handle_delete(struct drm_file *filp, u32 handle) | 185 | drm_gem_handle_delete(struct drm_file *filp, u32 handle) |
186 | { | 186 | { |
187 | struct drm_device *dev; | 187 | struct drm_device *dev; |
@@ -214,6 +214,7 @@ drm_gem_handle_delete(struct drm_file *filp, u32 handle) | |||
214 | 214 | ||
215 | return 0; | 215 | return 0; |
216 | } | 216 | } |
217 | EXPORT_SYMBOL(drm_gem_handle_delete); | ||
217 | 218 | ||
218 | /** | 219 | /** |
219 | * Create a handle for this object. This adds a handle reference | 220 | * Create a handle for this object. This adds a handle reference |
diff --git a/drivers/gpu/drm/drm_hashtab.c b/drivers/gpu/drm/drm_hashtab.c index a93d7b4ddaa..e3a75688f3c 100644 --- a/drivers/gpu/drm/drm_hashtab.c +++ b/drivers/gpu/drm/drm_hashtab.c | |||
@@ -39,27 +39,18 @@ | |||
39 | 39 | ||
40 | int drm_ht_create(struct drm_open_hash *ht, unsigned int order) | 40 | int drm_ht_create(struct drm_open_hash *ht, unsigned int order) |
41 | { | 41 | { |
42 | unsigned int i; | 42 | unsigned int size = 1 << order; |
43 | 43 | ||
44 | ht->size = 1 << order; | ||
45 | ht->order = order; | 44 | ht->order = order; |
46 | ht->fill = 0; | ||
47 | ht->table = NULL; | 45 | ht->table = NULL; |
48 | ht->use_vmalloc = ((ht->size * sizeof(*ht->table)) > PAGE_SIZE); | 46 | if (size <= PAGE_SIZE / sizeof(*ht->table)) |
49 | if (!ht->use_vmalloc) { | 47 | ht->table = kcalloc(size, sizeof(*ht->table), GFP_KERNEL); |
50 | ht->table = kcalloc(ht->size, sizeof(*ht->table), GFP_KERNEL); | 48 | else |
51 | } | 49 | ht->table = vzalloc(size*sizeof(*ht->table)); |
52 | if (!ht->table) { | ||
53 | ht->use_vmalloc = 1; | ||
54 | ht->table = vmalloc(ht->size*sizeof(*ht->table)); | ||
55 | } | ||
56 | if (!ht->table) { | 50 | if (!ht->table) { |
57 | DRM_ERROR("Out of memory for hash table\n"); | 51 | DRM_ERROR("Out of memory for hash table\n"); |
58 | return -ENOMEM; | 52 | return -ENOMEM; |
59 | } | 53 | } |
60 | for (i=0; i< ht->size; ++i) { | ||
61 | INIT_HLIST_HEAD(&ht->table[i]); | ||
62 | } | ||
63 | return 0; | 54 | return 0; |
64 | } | 55 | } |
65 | EXPORT_SYMBOL(drm_ht_create); | 56 | EXPORT_SYMBOL(drm_ht_create); |
@@ -180,7 +171,6 @@ int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key) | |||
180 | list = drm_ht_find_key(ht, key); | 171 | list = drm_ht_find_key(ht, key); |
181 | if (list) { | 172 | if (list) { |
182 | hlist_del_init(list); | 173 | hlist_del_init(list); |
183 | ht->fill--; | ||
184 | return 0; | 174 | return 0; |
185 | } | 175 | } |
186 | return -EINVAL; | 176 | return -EINVAL; |
@@ -189,7 +179,6 @@ int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key) | |||
189 | int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item) | 179 | int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item) |
190 | { | 180 | { |
191 | hlist_del_init(&item->head); | 181 | hlist_del_init(&item->head); |
192 | ht->fill--; | ||
193 | return 0; | 182 | return 0; |
194 | } | 183 | } |
195 | EXPORT_SYMBOL(drm_ht_remove_item); | 184 | EXPORT_SYMBOL(drm_ht_remove_item); |
@@ -197,10 +186,10 @@ EXPORT_SYMBOL(drm_ht_remove_item); | |||
197 | void drm_ht_remove(struct drm_open_hash *ht) | 186 | void drm_ht_remove(struct drm_open_hash *ht) |
198 | { | 187 | { |
199 | if (ht->table) { | 188 | if (ht->table) { |
200 | if (ht->use_vmalloc) | 189 | if ((PAGE_SIZE / sizeof(*ht->table)) >> ht->order) |
201 | vfree(ht->table); | ||
202 | else | ||
203 | kfree(ht->table); | 190 | kfree(ht->table); |
191 | else | ||
192 | vfree(ht->table); | ||
204 | ht->table = NULL; | 193 | ht->table = NULL; |
205 | } | 194 | } |
206 | } | 195 | } |
diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c index be9a9c07d15..ab1162da70f 100644 --- a/drivers/gpu/drm/drm_info.c +++ b/drivers/gpu/drm/drm_info.c | |||
@@ -47,30 +47,19 @@ int drm_name_info(struct seq_file *m, void *data) | |||
47 | struct drm_minor *minor = node->minor; | 47 | struct drm_minor *minor = node->minor; |
48 | struct drm_device *dev = minor->dev; | 48 | struct drm_device *dev = minor->dev; |
49 | struct drm_master *master = minor->master; | 49 | struct drm_master *master = minor->master; |
50 | 50 | const char *bus_name; | |
51 | if (!master) | 51 | if (!master) |
52 | return 0; | 52 | return 0; |
53 | 53 | ||
54 | if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) { | 54 | bus_name = dev->driver->bus->get_name(dev); |
55 | if (master->unique) { | 55 | if (master->unique) { |
56 | seq_printf(m, "%s %s %s\n", | 56 | seq_printf(m, "%s %s %s\n", |
57 | dev->driver->platform_device->name, | 57 | bus_name, |
58 | dev_name(dev->dev), master->unique); | 58 | dev_name(dev->dev), master->unique); |
59 | } else { | ||
60 | seq_printf(m, "%s\n", | ||
61 | dev->driver->platform_device->name); | ||
62 | } | ||
63 | } else { | 59 | } else { |
64 | if (master->unique) { | 60 | seq_printf(m, "%s %s\n", |
65 | seq_printf(m, "%s %s %s\n", | 61 | bus_name, dev_name(dev->dev)); |
66 | dev->driver->pci_driver.name, | ||
67 | dev_name(dev->dev), master->unique); | ||
68 | } else { | ||
69 | seq_printf(m, "%s %s\n", dev->driver->pci_driver.name, | ||
70 | dev_name(dev->dev)); | ||
71 | } | ||
72 | } | 62 | } |
73 | |||
74 | return 0; | 63 | return 0; |
75 | } | 64 | } |
76 | 65 | ||
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 47db4df37a6..7f6912a1676 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c | |||
@@ -96,7 +96,7 @@ int drm_setunique(struct drm_device *dev, void *data, | |||
96 | { | 96 | { |
97 | struct drm_unique *u = data; | 97 | struct drm_unique *u = data; |
98 | struct drm_master *master = file_priv->master; | 98 | struct drm_master *master = file_priv->master; |
99 | int domain, bus, slot, func, ret; | 99 | int ret; |
100 | 100 | ||
101 | if (master->unique_len || master->unique) | 101 | if (master->unique_len || master->unique) |
102 | return -EBUSY; | 102 | return -EBUSY; |
@@ -104,50 +104,12 @@ int drm_setunique(struct drm_device *dev, void *data, | |||
104 | if (!u->unique_len || u->unique_len > 1024) | 104 | if (!u->unique_len || u->unique_len > 1024) |
105 | return -EINVAL; | 105 | return -EINVAL; |
106 | 106 | ||
107 | master->unique_len = u->unique_len; | 107 | if (!dev->driver->bus->set_unique) |
108 | master->unique_size = u->unique_len + 1; | 108 | return -EINVAL; |
109 | master->unique = kmalloc(master->unique_size, GFP_KERNEL); | ||
110 | if (!master->unique) { | ||
111 | ret = -ENOMEM; | ||
112 | goto err; | ||
113 | } | ||
114 | |||
115 | if (copy_from_user(master->unique, u->unique, master->unique_len)) { | ||
116 | ret = -EFAULT; | ||
117 | goto err; | ||
118 | } | ||
119 | |||
120 | master->unique[master->unique_len] = '\0'; | ||
121 | |||
122 | dev->devname = kmalloc(strlen(dev->driver->pci_driver.name) + | ||
123 | strlen(master->unique) + 2, GFP_KERNEL); | ||
124 | if (!dev->devname) { | ||
125 | ret = -ENOMEM; | ||
126 | goto err; | ||
127 | } | ||
128 | |||
129 | sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, | ||
130 | master->unique); | ||
131 | 109 | ||
132 | /* Return error if the busid submitted doesn't match the device's actual | 110 | ret = dev->driver->bus->set_unique(dev, master, u); |
133 | * busid. | 111 | if (ret) |
134 | */ | ||
135 | ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func); | ||
136 | if (ret != 3) { | ||
137 | ret = -EINVAL; | ||
138 | goto err; | 112 | goto err; |
139 | } | ||
140 | |||
141 | domain = bus >> 8; | ||
142 | bus &= 0xff; | ||
143 | |||
144 | if ((domain != drm_get_pci_domain(dev)) || | ||
145 | (bus != dev->pdev->bus->number) || | ||
146 | (slot != PCI_SLOT(dev->pdev->devfn)) || | ||
147 | (func != PCI_FUNC(dev->pdev->devfn))) { | ||
148 | ret = -EINVAL; | ||
149 | goto err; | ||
150 | } | ||
151 | 113 | ||
152 | return 0; | 114 | return 0; |
153 | 115 | ||
@@ -159,74 +121,15 @@ err: | |||
159 | static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv) | 121 | static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv) |
160 | { | 122 | { |
161 | struct drm_master *master = file_priv->master; | 123 | struct drm_master *master = file_priv->master; |
162 | int len, ret; | 124 | int ret; |
163 | 125 | ||
164 | if (master->unique != NULL) | 126 | if (master->unique != NULL) |
165 | drm_unset_busid(dev, master); | 127 | drm_unset_busid(dev, master); |
166 | 128 | ||
167 | if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) { | 129 | ret = dev->driver->bus->set_busid(dev, master); |
168 | master->unique_len = 10 + strlen(dev->platformdev->name); | 130 | if (ret) |
169 | master->unique = kmalloc(master->unique_len + 1, GFP_KERNEL); | 131 | goto err; |
170 | |||
171 | if (master->unique == NULL) | ||
172 | return -ENOMEM; | ||
173 | |||
174 | len = snprintf(master->unique, master->unique_len, | ||
175 | "platform:%s", dev->platformdev->name); | ||
176 | |||
177 | if (len > master->unique_len) { | ||
178 | DRM_ERROR("Unique buffer overflowed\n"); | ||
179 | ret = -EINVAL; | ||
180 | goto err; | ||
181 | } | ||
182 | |||
183 | dev->devname = | ||
184 | kmalloc(strlen(dev->platformdev->name) + | ||
185 | master->unique_len + 2, GFP_KERNEL); | ||
186 | |||
187 | if (dev->devname == NULL) { | ||
188 | ret = -ENOMEM; | ||
189 | goto err; | ||
190 | } | ||
191 | |||
192 | sprintf(dev->devname, "%s@%s", dev->platformdev->name, | ||
193 | master->unique); | ||
194 | |||
195 | } else { | ||
196 | master->unique_len = 40; | ||
197 | master->unique_size = master->unique_len; | ||
198 | master->unique = kmalloc(master->unique_size, GFP_KERNEL); | ||
199 | if (master->unique == NULL) | ||
200 | return -ENOMEM; | ||
201 | |||
202 | len = snprintf(master->unique, master->unique_len, | ||
203 | "pci:%04x:%02x:%02x.%d", | ||
204 | drm_get_pci_domain(dev), | ||
205 | dev->pdev->bus->number, | ||
206 | PCI_SLOT(dev->pdev->devfn), | ||
207 | PCI_FUNC(dev->pdev->devfn)); | ||
208 | if (len >= master->unique_len) { | ||
209 | DRM_ERROR("buffer overflow"); | ||
210 | ret = -EINVAL; | ||
211 | goto err; | ||
212 | } else | ||
213 | master->unique_len = len; | ||
214 | |||
215 | dev->devname = | ||
216 | kmalloc(strlen(dev->driver->pci_driver.name) + | ||
217 | master->unique_len + 2, GFP_KERNEL); | ||
218 | |||
219 | if (dev->devname == NULL) { | ||
220 | ret = -ENOMEM; | ||
221 | goto err; | ||
222 | } | ||
223 | |||
224 | sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, | ||
225 | master->unique); | ||
226 | } | ||
227 | |||
228 | return 0; | 132 | return 0; |
229 | |||
230 | err: | 133 | err: |
231 | drm_unset_busid(dev, master); | 134 | drm_unset_busid(dev, master); |
232 | return ret; | 135 | return ret; |
@@ -365,6 +268,25 @@ int drm_getstats(struct drm_device *dev, void *data, | |||
365 | } | 268 | } |
366 | 269 | ||
367 | /** | 270 | /** |
271 | * Get device/driver capabilities | ||
272 | */ | ||
273 | int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv) | ||
274 | { | ||
275 | struct drm_get_cap *req = data; | ||
276 | |||
277 | req->value = 0; | ||
278 | switch (req->capability) { | ||
279 | case DRM_CAP_DUMB_BUFFER: | ||
280 | if (dev->driver->dumb_create) | ||
281 | req->value = 1; | ||
282 | break; | ||
283 | default: | ||
284 | return -EINVAL; | ||
285 | } | ||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | /** | ||
368 | * Setversion ioctl. | 290 | * Setversion ioctl. |
369 | * | 291 | * |
370 | * \param inode device inode. | 292 | * \param inode device inode. |
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 28d1d3c24d6..a34ef97d3c8 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
@@ -74,23 +74,13 @@ int drm_irq_by_busid(struct drm_device *dev, void *data, | |||
74 | { | 74 | { |
75 | struct drm_irq_busid *p = data; | 75 | struct drm_irq_busid *p = data; |
76 | 76 | ||
77 | if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) | 77 | if (!dev->driver->bus->irq_by_busid) |
78 | return -EINVAL; | 78 | return -EINVAL; |
79 | 79 | ||
80 | if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) | 80 | if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) |
81 | return -EINVAL; | 81 | return -EINVAL; |
82 | 82 | ||
83 | if ((p->busnum >> 8) != drm_get_pci_domain(dev) || | 83 | return dev->driver->bus->irq_by_busid(dev, p); |
84 | (p->busnum & 0xff) != dev->pdev->bus->number || | ||
85 | p->devnum != PCI_SLOT(dev->pdev->devfn) || p->funcnum != PCI_FUNC(dev->pdev->devfn)) | ||
86 | return -EINVAL; | ||
87 | |||
88 | p->irq = dev->pdev->irq; | ||
89 | |||
90 | DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum, | ||
91 | p->irq); | ||
92 | |||
93 | return 0; | ||
94 | } | 84 | } |
95 | 85 | ||
96 | /* | 86 | /* |
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index c59515ba7e6..add1737dae0 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c | |||
@@ -64,8 +64,8 @@ static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, int atomic) | |||
64 | else { | 64 | else { |
65 | child = | 65 | child = |
66 | list_entry(mm->unused_nodes.next, | 66 | list_entry(mm->unused_nodes.next, |
67 | struct drm_mm_node, free_stack); | 67 | struct drm_mm_node, node_list); |
68 | list_del(&child->free_stack); | 68 | list_del(&child->node_list); |
69 | --mm->num_unused; | 69 | --mm->num_unused; |
70 | } | 70 | } |
71 | spin_unlock(&mm->unused_lock); | 71 | spin_unlock(&mm->unused_lock); |
@@ -94,195 +94,242 @@ int drm_mm_pre_get(struct drm_mm *mm) | |||
94 | return ret; | 94 | return ret; |
95 | } | 95 | } |
96 | ++mm->num_unused; | 96 | ++mm->num_unused; |
97 | list_add_tail(&node->free_stack, &mm->unused_nodes); | 97 | list_add_tail(&node->node_list, &mm->unused_nodes); |
98 | } | 98 | } |
99 | spin_unlock(&mm->unused_lock); | 99 | spin_unlock(&mm->unused_lock); |
100 | return 0; | 100 | return 0; |
101 | } | 101 | } |
102 | EXPORT_SYMBOL(drm_mm_pre_get); | 102 | EXPORT_SYMBOL(drm_mm_pre_get); |
103 | 103 | ||
104 | static int drm_mm_create_tail_node(struct drm_mm *mm, | 104 | static inline unsigned long drm_mm_hole_node_start(struct drm_mm_node *hole_node) |
105 | unsigned long start, | ||
106 | unsigned long size, int atomic) | ||
107 | { | 105 | { |
108 | struct drm_mm_node *child; | 106 | return hole_node->start + hole_node->size; |
109 | 107 | } | |
110 | child = drm_mm_kmalloc(mm, atomic); | ||
111 | if (unlikely(child == NULL)) | ||
112 | return -ENOMEM; | ||
113 | |||
114 | child->free = 1; | ||
115 | child->size = size; | ||
116 | child->start = start; | ||
117 | child->mm = mm; | ||
118 | 108 | ||
119 | list_add_tail(&child->node_list, &mm->node_list); | 109 | static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node) |
120 | list_add_tail(&child->free_stack, &mm->free_stack); | 110 | { |
111 | struct drm_mm_node *next_node = | ||
112 | list_entry(hole_node->node_list.next, struct drm_mm_node, | ||
113 | node_list); | ||
121 | 114 | ||
122 | return 0; | 115 | return next_node->start; |
123 | } | 116 | } |
124 | 117 | ||
125 | static struct drm_mm_node *drm_mm_split_at_start(struct drm_mm_node *parent, | 118 | static void drm_mm_insert_helper(struct drm_mm_node *hole_node, |
126 | unsigned long size, | 119 | struct drm_mm_node *node, |
127 | int atomic) | 120 | unsigned long size, unsigned alignment) |
128 | { | 121 | { |
129 | struct drm_mm_node *child; | 122 | struct drm_mm *mm = hole_node->mm; |
123 | unsigned long tmp = 0, wasted = 0; | ||
124 | unsigned long hole_start = drm_mm_hole_node_start(hole_node); | ||
125 | unsigned long hole_end = drm_mm_hole_node_end(hole_node); | ||
130 | 126 | ||
131 | child = drm_mm_kmalloc(parent->mm, atomic); | 127 | BUG_ON(!hole_node->hole_follows || node->allocated); |
132 | if (unlikely(child == NULL)) | ||
133 | return NULL; | ||
134 | 128 | ||
135 | INIT_LIST_HEAD(&child->free_stack); | 129 | if (alignment) |
130 | tmp = hole_start % alignment; | ||
136 | 131 | ||
137 | child->size = size; | 132 | if (!tmp) { |
138 | child->start = parent->start; | 133 | hole_node->hole_follows = 0; |
139 | child->mm = parent->mm; | 134 | list_del_init(&hole_node->hole_stack); |
135 | } else | ||
136 | wasted = alignment - tmp; | ||
140 | 137 | ||
141 | list_add_tail(&child->node_list, &parent->node_list); | 138 | node->start = hole_start + wasted; |
142 | INIT_LIST_HEAD(&child->free_stack); | 139 | node->size = size; |
140 | node->mm = mm; | ||
141 | node->allocated = 1; | ||
143 | 142 | ||
144 | parent->size -= size; | 143 | INIT_LIST_HEAD(&node->hole_stack); |
145 | parent->start += size; | 144 | list_add(&node->node_list, &hole_node->node_list); |
146 | return child; | 145 | |
147 | } | 146 | BUG_ON(node->start + node->size > hole_end); |
148 | 147 | ||
148 | if (node->start + node->size < hole_end) { | ||
149 | list_add(&node->hole_stack, &mm->hole_stack); | ||
150 | node->hole_follows = 1; | ||
151 | } else { | ||
152 | node->hole_follows = 0; | ||
153 | } | ||
154 | } | ||
149 | 155 | ||
150 | struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node, | 156 | struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *hole_node, |
151 | unsigned long size, | 157 | unsigned long size, |
152 | unsigned alignment, | 158 | unsigned alignment, |
153 | int atomic) | 159 | int atomic) |
154 | { | 160 | { |
161 | struct drm_mm_node *node; | ||
155 | 162 | ||
156 | struct drm_mm_node *align_splitoff = NULL; | 163 | node = drm_mm_kmalloc(hole_node->mm, atomic); |
157 | unsigned tmp = 0; | 164 | if (unlikely(node == NULL)) |
165 | return NULL; | ||
158 | 166 | ||
159 | if (alignment) | 167 | drm_mm_insert_helper(hole_node, node, size, alignment); |
160 | tmp = node->start % alignment; | ||
161 | 168 | ||
162 | if (tmp) { | 169 | return node; |
163 | align_splitoff = | 170 | } |
164 | drm_mm_split_at_start(node, alignment - tmp, atomic); | 171 | EXPORT_SYMBOL(drm_mm_get_block_generic); |
165 | if (unlikely(align_splitoff == NULL)) | ||
166 | return NULL; | ||
167 | } | ||
168 | 172 | ||
169 | if (node->size == size) { | 173 | /** |
170 | list_del_init(&node->free_stack); | 174 | * Search for free space and insert a preallocated memory node. Returns |
171 | node->free = 0; | 175 | * -ENOSPC if no suitable free area is available. The preallocated memory node |
172 | } else { | 176 | * must be cleared. |
173 | node = drm_mm_split_at_start(node, size, atomic); | 177 | */ |
174 | } | 178 | int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node, |
179 | unsigned long size, unsigned alignment) | ||
180 | { | ||
181 | struct drm_mm_node *hole_node; | ||
175 | 182 | ||
176 | if (align_splitoff) | 183 | hole_node = drm_mm_search_free(mm, size, alignment, 0); |
177 | drm_mm_put_block(align_splitoff); | 184 | if (!hole_node) |
185 | return -ENOSPC; | ||
178 | 186 | ||
179 | return node; | 187 | drm_mm_insert_helper(hole_node, node, size, alignment); |
188 | |||
189 | return 0; | ||
180 | } | 190 | } |
181 | EXPORT_SYMBOL(drm_mm_get_block_generic); | 191 | EXPORT_SYMBOL(drm_mm_insert_node); |
182 | 192 | ||
183 | struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *node, | 193 | static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, |
184 | unsigned long size, | 194 | struct drm_mm_node *node, |
185 | unsigned alignment, | 195 | unsigned long size, unsigned alignment, |
186 | unsigned long start, | 196 | unsigned long start, unsigned long end) |
187 | unsigned long end, | ||
188 | int atomic) | ||
189 | { | 197 | { |
190 | struct drm_mm_node *align_splitoff = NULL; | 198 | struct drm_mm *mm = hole_node->mm; |
191 | unsigned tmp = 0; | 199 | unsigned long tmp = 0, wasted = 0; |
192 | unsigned wasted = 0; | 200 | unsigned long hole_start = drm_mm_hole_node_start(hole_node); |
201 | unsigned long hole_end = drm_mm_hole_node_end(hole_node); | ||
202 | |||
203 | BUG_ON(!hole_node->hole_follows || node->allocated); | ||
193 | 204 | ||
194 | if (node->start < start) | 205 | if (hole_start < start) |
195 | wasted += start - node->start; | 206 | wasted += start - hole_start; |
196 | if (alignment) | 207 | if (alignment) |
197 | tmp = ((node->start + wasted) % alignment); | 208 | tmp = (hole_start + wasted) % alignment; |
198 | 209 | ||
199 | if (tmp) | 210 | if (tmp) |
200 | wasted += alignment - tmp; | 211 | wasted += alignment - tmp; |
201 | if (wasted) { | 212 | |
202 | align_splitoff = drm_mm_split_at_start(node, wasted, atomic); | 213 | if (!wasted) { |
203 | if (unlikely(align_splitoff == NULL)) | 214 | hole_node->hole_follows = 0; |
204 | return NULL; | 215 | list_del_init(&hole_node->hole_stack); |
205 | } | 216 | } |
206 | 217 | ||
207 | if (node->size == size) { | 218 | node->start = hole_start + wasted; |
208 | list_del_init(&node->free_stack); | 219 | node->size = size; |
209 | node->free = 0; | 220 | node->mm = mm; |
221 | node->allocated = 1; | ||
222 | |||
223 | INIT_LIST_HEAD(&node->hole_stack); | ||
224 | list_add(&node->node_list, &hole_node->node_list); | ||
225 | |||
226 | BUG_ON(node->start + node->size > hole_end); | ||
227 | BUG_ON(node->start + node->size > end); | ||
228 | |||
229 | if (node->start + node->size < hole_end) { | ||
230 | list_add(&node->hole_stack, &mm->hole_stack); | ||
231 | node->hole_follows = 1; | ||
210 | } else { | 232 | } else { |
211 | node = drm_mm_split_at_start(node, size, atomic); | 233 | node->hole_follows = 0; |
212 | } | 234 | } |
235 | } | ||
213 | 236 | ||
214 | if (align_splitoff) | 237 | struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *hole_node, |
215 | drm_mm_put_block(align_splitoff); | 238 | unsigned long size, |
239 | unsigned alignment, | ||
240 | unsigned long start, | ||
241 | unsigned long end, | ||
242 | int atomic) | ||
243 | { | ||
244 | struct drm_mm_node *node; | ||
245 | |||
246 | node = drm_mm_kmalloc(hole_node->mm, atomic); | ||
247 | if (unlikely(node == NULL)) | ||
248 | return NULL; | ||
249 | |||
250 | drm_mm_insert_helper_range(hole_node, node, size, alignment, | ||
251 | start, end); | ||
216 | 252 | ||
217 | return node; | 253 | return node; |
218 | } | 254 | } |
219 | EXPORT_SYMBOL(drm_mm_get_block_range_generic); | 255 | EXPORT_SYMBOL(drm_mm_get_block_range_generic); |
220 | 256 | ||
221 | /* | 257 | /** |
222 | * Put a block. Merge with the previous and / or next block if they are free. | 258 | * Search for free space and insert a preallocated memory node. Returns |
223 | * Otherwise add to the free stack. | 259 | * -ENOSPC if no suitable free area is available. This is for range |
260 | * restricted allocations. The preallocated memory node must be cleared. | ||
224 | */ | 261 | */ |
225 | 262 | int drm_mm_insert_node_in_range(struct drm_mm *mm, struct drm_mm_node *node, | |
226 | void drm_mm_put_block(struct drm_mm_node *cur) | 263 | unsigned long size, unsigned alignment, |
264 | unsigned long start, unsigned long end) | ||
227 | { | 265 | { |
266 | struct drm_mm_node *hole_node; | ||
228 | 267 | ||
229 | struct drm_mm *mm = cur->mm; | 268 | hole_node = drm_mm_search_free_in_range(mm, size, alignment, |
230 | struct list_head *cur_head = &cur->node_list; | 269 | start, end, 0); |
231 | struct list_head *root_head = &mm->node_list; | 270 | if (!hole_node) |
232 | struct drm_mm_node *prev_node = NULL; | 271 | return -ENOSPC; |
233 | struct drm_mm_node *next_node; | ||
234 | 272 | ||
235 | int merged = 0; | 273 | drm_mm_insert_helper_range(hole_node, node, size, alignment, |
274 | start, end); | ||
236 | 275 | ||
237 | BUG_ON(cur->scanned_block || cur->scanned_prev_free | 276 | return 0; |
238 | || cur->scanned_next_free); | 277 | } |
278 | EXPORT_SYMBOL(drm_mm_insert_node_in_range); | ||
239 | 279 | ||
240 | if (cur_head->prev != root_head) { | 280 | /** |
241 | prev_node = | 281 | * Remove a memory node from the allocator. |
242 | list_entry(cur_head->prev, struct drm_mm_node, node_list); | 282 | */ |
243 | if (prev_node->free) { | 283 | void drm_mm_remove_node(struct drm_mm_node *node) |
244 | prev_node->size += cur->size; | 284 | { |
245 | merged = 1; | 285 | struct drm_mm *mm = node->mm; |
246 | } | 286 | struct drm_mm_node *prev_node; |
247 | } | 287 | |
248 | if (cur_head->next != root_head) { | 288 | BUG_ON(node->scanned_block || node->scanned_prev_free |
249 | next_node = | 289 | || node->scanned_next_free); |
250 | list_entry(cur_head->next, struct drm_mm_node, node_list); | 290 | |
251 | if (next_node->free) { | 291 | prev_node = |
252 | if (merged) { | 292 | list_entry(node->node_list.prev, struct drm_mm_node, node_list); |
253 | prev_node->size += next_node->size; | 293 | |
254 | list_del(&next_node->node_list); | 294 | if (node->hole_follows) { |
255 | list_del(&next_node->free_stack); | 295 | BUG_ON(drm_mm_hole_node_start(node) |
256 | spin_lock(&mm->unused_lock); | 296 | == drm_mm_hole_node_end(node)); |
257 | if (mm->num_unused < MM_UNUSED_TARGET) { | 297 | list_del(&node->hole_stack); |
258 | list_add(&next_node->free_stack, | 298 | } else |
259 | &mm->unused_nodes); | 299 | BUG_ON(drm_mm_hole_node_start(node) |
260 | ++mm->num_unused; | 300 | != drm_mm_hole_node_end(node)); |
261 | } else | 301 | |
262 | kfree(next_node); | 302 | if (!prev_node->hole_follows) { |
263 | spin_unlock(&mm->unused_lock); | 303 | prev_node->hole_follows = 1; |
264 | } else { | 304 | list_add(&prev_node->hole_stack, &mm->hole_stack); |
265 | next_node->size += cur->size; | 305 | } else |
266 | next_node->start = cur->start; | 306 | list_move(&prev_node->hole_stack, &mm->hole_stack); |
267 | merged = 1; | 307 | |
268 | } | 308 | list_del(&node->node_list); |
269 | } | 309 | node->allocated = 0; |
270 | } | ||
271 | if (!merged) { | ||
272 | cur->free = 1; | ||
273 | list_add(&cur->free_stack, &mm->free_stack); | ||
274 | } else { | ||
275 | list_del(&cur->node_list); | ||
276 | spin_lock(&mm->unused_lock); | ||
277 | if (mm->num_unused < MM_UNUSED_TARGET) { | ||
278 | list_add(&cur->free_stack, &mm->unused_nodes); | ||
279 | ++mm->num_unused; | ||
280 | } else | ||
281 | kfree(cur); | ||
282 | spin_unlock(&mm->unused_lock); | ||
283 | } | ||
284 | } | 310 | } |
311 | EXPORT_SYMBOL(drm_mm_remove_node); | ||
312 | |||
313 | /* | ||
314 | * Remove a memory node from the allocator and free the allocated struct | ||
315 | * drm_mm_node. Only to be used on a struct drm_mm_node obtained by one of the | ||
316 | * drm_mm_get_block functions. | ||
317 | */ | ||
318 | void drm_mm_put_block(struct drm_mm_node *node) | ||
319 | { | ||
285 | 320 | ||
321 | struct drm_mm *mm = node->mm; | ||
322 | |||
323 | drm_mm_remove_node(node); | ||
324 | |||
325 | spin_lock(&mm->unused_lock); | ||
326 | if (mm->num_unused < MM_UNUSED_TARGET) { | ||
327 | list_add(&node->node_list, &mm->unused_nodes); | ||
328 | ++mm->num_unused; | ||
329 | } else | ||
330 | kfree(node); | ||
331 | spin_unlock(&mm->unused_lock); | ||
332 | } | ||
286 | EXPORT_SYMBOL(drm_mm_put_block); | 333 | EXPORT_SYMBOL(drm_mm_put_block); |
287 | 334 | ||
288 | static int check_free_hole(unsigned long start, unsigned long end, | 335 | static int check_free_hole(unsigned long start, unsigned long end, |
@@ -319,8 +366,10 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, | |||
319 | best = NULL; | 366 | best = NULL; |
320 | best_size = ~0UL; | 367 | best_size = ~0UL; |
321 | 368 | ||
322 | list_for_each_entry(entry, &mm->free_stack, free_stack) { | 369 | list_for_each_entry(entry, &mm->hole_stack, hole_stack) { |
323 | if (!check_free_hole(entry->start, entry->start + entry->size, | 370 | BUG_ON(!entry->hole_follows); |
371 | if (!check_free_hole(drm_mm_hole_node_start(entry), | ||
372 | drm_mm_hole_node_end(entry), | ||
324 | size, alignment)) | 373 | size, alignment)) |
325 | continue; | 374 | continue; |
326 | 375 | ||
@@ -353,12 +402,13 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm, | |||
353 | best = NULL; | 402 | best = NULL; |
354 | best_size = ~0UL; | 403 | best_size = ~0UL; |
355 | 404 | ||
356 | list_for_each_entry(entry, &mm->free_stack, free_stack) { | 405 | list_for_each_entry(entry, &mm->hole_stack, hole_stack) { |
357 | unsigned long adj_start = entry->start < start ? | 406 | unsigned long adj_start = drm_mm_hole_node_start(entry) < start ? |
358 | start : entry->start; | 407 | start : drm_mm_hole_node_start(entry); |
359 | unsigned long adj_end = entry->start + entry->size > end ? | 408 | unsigned long adj_end = drm_mm_hole_node_end(entry) > end ? |
360 | end : entry->start + entry->size; | 409 | end : drm_mm_hole_node_end(entry); |
361 | 410 | ||
411 | BUG_ON(!entry->hole_follows); | ||
362 | if (!check_free_hole(adj_start, adj_end, size, alignment)) | 412 | if (!check_free_hole(adj_start, adj_end, size, alignment)) |
363 | continue; | 413 | continue; |
364 | 414 | ||
@@ -376,6 +426,23 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm, | |||
376 | EXPORT_SYMBOL(drm_mm_search_free_in_range); | 426 | EXPORT_SYMBOL(drm_mm_search_free_in_range); |
377 | 427 | ||
378 | /** | 428 | /** |
429 | * Moves an allocation. To be used with embedded struct drm_mm_node. | ||
430 | */ | ||
431 | void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new) | ||
432 | { | ||
433 | list_replace(&old->node_list, &new->node_list); | ||
434 | list_replace(&old->node_list, &new->hole_stack); | ||
435 | new->hole_follows = old->hole_follows; | ||
436 | new->mm = old->mm; | ||
437 | new->start = old->start; | ||
438 | new->size = old->size; | ||
439 | |||
440 | old->allocated = 0; | ||
441 | new->allocated = 1; | ||
442 | } | ||
443 | EXPORT_SYMBOL(drm_mm_replace_node); | ||
444 | |||
445 | /** | ||
379 | * Initializa lru scanning. | 446 | * Initializa lru scanning. |
380 | * | 447 | * |
381 | * This simply sets up the scanning routines with the parameters for the desired | 448 | * This simply sets up the scanning routines with the parameters for the desired |
@@ -393,6 +460,7 @@ void drm_mm_init_scan(struct drm_mm *mm, unsigned long size, | |||
393 | mm->scan_hit_start = 0; | 460 | mm->scan_hit_start = 0; |
394 | mm->scan_hit_size = 0; | 461 | mm->scan_hit_size = 0; |
395 | mm->scan_check_range = 0; | 462 | mm->scan_check_range = 0; |
463 | mm->prev_scanned_node = NULL; | ||
396 | } | 464 | } |
397 | EXPORT_SYMBOL(drm_mm_init_scan); | 465 | EXPORT_SYMBOL(drm_mm_init_scan); |
398 | 466 | ||
@@ -418,6 +486,7 @@ void drm_mm_init_scan_with_range(struct drm_mm *mm, unsigned long size, | |||
418 | mm->scan_start = start; | 486 | mm->scan_start = start; |
419 | mm->scan_end = end; | 487 | mm->scan_end = end; |
420 | mm->scan_check_range = 1; | 488 | mm->scan_check_range = 1; |
489 | mm->prev_scanned_node = NULL; | ||
421 | } | 490 | } |
422 | EXPORT_SYMBOL(drm_mm_init_scan_with_range); | 491 | EXPORT_SYMBOL(drm_mm_init_scan_with_range); |
423 | 492 | ||
@@ -430,70 +499,42 @@ EXPORT_SYMBOL(drm_mm_init_scan_with_range); | |||
430 | int drm_mm_scan_add_block(struct drm_mm_node *node) | 499 | int drm_mm_scan_add_block(struct drm_mm_node *node) |
431 | { | 500 | { |
432 | struct drm_mm *mm = node->mm; | 501 | struct drm_mm *mm = node->mm; |
433 | struct list_head *prev_free, *next_free; | 502 | struct drm_mm_node *prev_node; |
434 | struct drm_mm_node *prev_node, *next_node; | 503 | unsigned long hole_start, hole_end; |
435 | unsigned long adj_start; | 504 | unsigned long adj_start; |
436 | unsigned long adj_end; | 505 | unsigned long adj_end; |
437 | 506 | ||
438 | mm->scanned_blocks++; | 507 | mm->scanned_blocks++; |
439 | 508 | ||
440 | prev_free = next_free = NULL; | 509 | BUG_ON(node->scanned_block); |
441 | |||
442 | BUG_ON(node->free); | ||
443 | node->scanned_block = 1; | 510 | node->scanned_block = 1; |
444 | node->free = 1; | ||
445 | |||
446 | if (node->node_list.prev != &mm->node_list) { | ||
447 | prev_node = list_entry(node->node_list.prev, struct drm_mm_node, | ||
448 | node_list); | ||
449 | |||
450 | if (prev_node->free) { | ||
451 | list_del(&prev_node->node_list); | ||
452 | 511 | ||
453 | node->start = prev_node->start; | 512 | prev_node = list_entry(node->node_list.prev, struct drm_mm_node, |
454 | node->size += prev_node->size; | 513 | node_list); |
455 | 514 | ||
456 | prev_node->scanned_prev_free = 1; | 515 | node->scanned_preceeds_hole = prev_node->hole_follows; |
457 | 516 | prev_node->hole_follows = 1; | |
458 | prev_free = &prev_node->free_stack; | 517 | list_del(&node->node_list); |
459 | } | 518 | node->node_list.prev = &prev_node->node_list; |
460 | } | 519 | node->node_list.next = &mm->prev_scanned_node->node_list; |
461 | 520 | mm->prev_scanned_node = node; | |
462 | if (node->node_list.next != &mm->node_list) { | ||
463 | next_node = list_entry(node->node_list.next, struct drm_mm_node, | ||
464 | node_list); | ||
465 | |||
466 | if (next_node->free) { | ||
467 | list_del(&next_node->node_list); | ||
468 | |||
469 | node->size += next_node->size; | ||
470 | |||
471 | next_node->scanned_next_free = 1; | ||
472 | |||
473 | next_free = &next_node->free_stack; | ||
474 | } | ||
475 | } | ||
476 | |||
477 | /* The free_stack list is not used for allocated objects, so these two | ||
478 | * pointers can be abused (as long as no allocations in this memory | ||
479 | * manager happens). */ | ||
480 | node->free_stack.prev = prev_free; | ||
481 | node->free_stack.next = next_free; | ||
482 | 521 | ||
522 | hole_start = drm_mm_hole_node_start(prev_node); | ||
523 | hole_end = drm_mm_hole_node_end(prev_node); | ||
483 | if (mm->scan_check_range) { | 524 | if (mm->scan_check_range) { |
484 | adj_start = node->start < mm->scan_start ? | 525 | adj_start = hole_start < mm->scan_start ? |
485 | mm->scan_start : node->start; | 526 | mm->scan_start : hole_start; |
486 | adj_end = node->start + node->size > mm->scan_end ? | 527 | adj_end = hole_end > mm->scan_end ? |
487 | mm->scan_end : node->start + node->size; | 528 | mm->scan_end : hole_end; |
488 | } else { | 529 | } else { |
489 | adj_start = node->start; | 530 | adj_start = hole_start; |
490 | adj_end = node->start + node->size; | 531 | adj_end = hole_end; |
491 | } | 532 | } |
492 | 533 | ||
493 | if (check_free_hole(adj_start , adj_end, | 534 | if (check_free_hole(adj_start , adj_end, |
494 | mm->scan_size, mm->scan_alignment)) { | 535 | mm->scan_size, mm->scan_alignment)) { |
495 | mm->scan_hit_start = node->start; | 536 | mm->scan_hit_start = hole_start; |
496 | mm->scan_hit_size = node->size; | 537 | mm->scan_hit_size = hole_end; |
497 | 538 | ||
498 | return 1; | 539 | return 1; |
499 | } | 540 | } |
@@ -519,39 +560,19 @@ EXPORT_SYMBOL(drm_mm_scan_add_block); | |||
519 | int drm_mm_scan_remove_block(struct drm_mm_node *node) | 560 | int drm_mm_scan_remove_block(struct drm_mm_node *node) |
520 | { | 561 | { |
521 | struct drm_mm *mm = node->mm; | 562 | struct drm_mm *mm = node->mm; |
522 | struct drm_mm_node *prev_node, *next_node; | 563 | struct drm_mm_node *prev_node; |
523 | 564 | ||
524 | mm->scanned_blocks--; | 565 | mm->scanned_blocks--; |
525 | 566 | ||
526 | BUG_ON(!node->scanned_block); | 567 | BUG_ON(!node->scanned_block); |
527 | node->scanned_block = 0; | 568 | node->scanned_block = 0; |
528 | node->free = 0; | ||
529 | |||
530 | prev_node = list_entry(node->free_stack.prev, struct drm_mm_node, | ||
531 | free_stack); | ||
532 | next_node = list_entry(node->free_stack.next, struct drm_mm_node, | ||
533 | free_stack); | ||
534 | 569 | ||
535 | if (prev_node) { | 570 | prev_node = list_entry(node->node_list.prev, struct drm_mm_node, |
536 | BUG_ON(!prev_node->scanned_prev_free); | 571 | node_list); |
537 | prev_node->scanned_prev_free = 0; | ||
538 | |||
539 | list_add_tail(&prev_node->node_list, &node->node_list); | ||
540 | |||
541 | node->start = prev_node->start + prev_node->size; | ||
542 | node->size -= prev_node->size; | ||
543 | } | ||
544 | 572 | ||
545 | if (next_node) { | 573 | prev_node->hole_follows = node->scanned_preceeds_hole; |
546 | BUG_ON(!next_node->scanned_next_free); | 574 | INIT_LIST_HEAD(&node->node_list); |
547 | next_node->scanned_next_free = 0; | 575 | list_add(&node->node_list, &prev_node->node_list); |
548 | |||
549 | list_add(&next_node->node_list, &node->node_list); | ||
550 | |||
551 | node->size -= next_node->size; | ||
552 | } | ||
553 | |||
554 | INIT_LIST_HEAD(&node->free_stack); | ||
555 | 576 | ||
556 | /* Only need to check for containement because start&size for the | 577 | /* Only need to check for containement because start&size for the |
557 | * complete resulting free block (not just the desired part) is | 578 | * complete resulting free block (not just the desired part) is |
@@ -568,7 +589,7 @@ EXPORT_SYMBOL(drm_mm_scan_remove_block); | |||
568 | 589 | ||
569 | int drm_mm_clean(struct drm_mm * mm) | 590 | int drm_mm_clean(struct drm_mm * mm) |
570 | { | 591 | { |
571 | struct list_head *head = &mm->node_list; | 592 | struct list_head *head = &mm->head_node.node_list; |
572 | 593 | ||
573 | return (head->next->next == head); | 594 | return (head->next->next == head); |
574 | } | 595 | } |
@@ -576,38 +597,40 @@ EXPORT_SYMBOL(drm_mm_clean); | |||
576 | 597 | ||
577 | int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size) | 598 | int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size) |
578 | { | 599 | { |
579 | INIT_LIST_HEAD(&mm->node_list); | 600 | INIT_LIST_HEAD(&mm->hole_stack); |
580 | INIT_LIST_HEAD(&mm->free_stack); | ||
581 | INIT_LIST_HEAD(&mm->unused_nodes); | 601 | INIT_LIST_HEAD(&mm->unused_nodes); |
582 | mm->num_unused = 0; | 602 | mm->num_unused = 0; |
583 | mm->scanned_blocks = 0; | 603 | mm->scanned_blocks = 0; |
584 | spin_lock_init(&mm->unused_lock); | 604 | spin_lock_init(&mm->unused_lock); |
585 | 605 | ||
586 | return drm_mm_create_tail_node(mm, start, size, 0); | 606 | /* Clever trick to avoid a special case in the free hole tracking. */ |
607 | INIT_LIST_HEAD(&mm->head_node.node_list); | ||
608 | INIT_LIST_HEAD(&mm->head_node.hole_stack); | ||
609 | mm->head_node.hole_follows = 1; | ||
610 | mm->head_node.scanned_block = 0; | ||
611 | mm->head_node.scanned_prev_free = 0; | ||
612 | mm->head_node.scanned_next_free = 0; | ||
613 | mm->head_node.mm = mm; | ||
614 | mm->head_node.start = start + size; | ||
615 | mm->head_node.size = start - mm->head_node.start; | ||
616 | list_add_tail(&mm->head_node.hole_stack, &mm->hole_stack); | ||
617 | |||
618 | return 0; | ||
587 | } | 619 | } |
588 | EXPORT_SYMBOL(drm_mm_init); | 620 | EXPORT_SYMBOL(drm_mm_init); |
589 | 621 | ||
590 | void drm_mm_takedown(struct drm_mm * mm) | 622 | void drm_mm_takedown(struct drm_mm * mm) |
591 | { | 623 | { |
592 | struct list_head *bnode = mm->free_stack.next; | 624 | struct drm_mm_node *entry, *next; |
593 | struct drm_mm_node *entry; | ||
594 | struct drm_mm_node *next; | ||
595 | 625 | ||
596 | entry = list_entry(bnode, struct drm_mm_node, free_stack); | 626 | if (!list_empty(&mm->head_node.node_list)) { |
597 | |||
598 | if (entry->node_list.next != &mm->node_list || | ||
599 | entry->free_stack.next != &mm->free_stack) { | ||
600 | DRM_ERROR("Memory manager not clean. Delaying takedown\n"); | 627 | DRM_ERROR("Memory manager not clean. Delaying takedown\n"); |
601 | return; | 628 | return; |
602 | } | 629 | } |
603 | 630 | ||
604 | list_del(&entry->free_stack); | ||
605 | list_del(&entry->node_list); | ||
606 | kfree(entry); | ||
607 | |||
608 | spin_lock(&mm->unused_lock); | 631 | spin_lock(&mm->unused_lock); |
609 | list_for_each_entry_safe(entry, next, &mm->unused_nodes, free_stack) { | 632 | list_for_each_entry_safe(entry, next, &mm->unused_nodes, node_list) { |
610 | list_del(&entry->free_stack); | 633 | list_del(&entry->node_list); |
611 | kfree(entry); | 634 | kfree(entry); |
612 | --mm->num_unused; | 635 | --mm->num_unused; |
613 | } | 636 | } |
@@ -620,19 +643,37 @@ EXPORT_SYMBOL(drm_mm_takedown); | |||
620 | void drm_mm_debug_table(struct drm_mm *mm, const char *prefix) | 643 | void drm_mm_debug_table(struct drm_mm *mm, const char *prefix) |
621 | { | 644 | { |
622 | struct drm_mm_node *entry; | 645 | struct drm_mm_node *entry; |
623 | int total_used = 0, total_free = 0, total = 0; | 646 | unsigned long total_used = 0, total_free = 0, total = 0; |
624 | 647 | unsigned long hole_start, hole_end, hole_size; | |
625 | list_for_each_entry(entry, &mm->node_list, node_list) { | 648 | |
626 | printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8ld: %s\n", | 649 | hole_start = drm_mm_hole_node_start(&mm->head_node); |
650 | hole_end = drm_mm_hole_node_end(&mm->head_node); | ||
651 | hole_size = hole_end - hole_start; | ||
652 | if (hole_size) | ||
653 | printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: free\n", | ||
654 | prefix, hole_start, hole_end, | ||
655 | hole_size); | ||
656 | total_free += hole_size; | ||
657 | |||
658 | drm_mm_for_each_node(entry, mm) { | ||
659 | printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: used\n", | ||
627 | prefix, entry->start, entry->start + entry->size, | 660 | prefix, entry->start, entry->start + entry->size, |
628 | entry->size, entry->free ? "free" : "used"); | 661 | entry->size); |
629 | total += entry->size; | 662 | total_used += entry->size; |
630 | if (entry->free) | 663 | |
631 | total_free += entry->size; | 664 | if (entry->hole_follows) { |
632 | else | 665 | hole_start = drm_mm_hole_node_start(entry); |
633 | total_used += entry->size; | 666 | hole_end = drm_mm_hole_node_end(entry); |
667 | hole_size = hole_end - hole_start; | ||
668 | printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: free\n", | ||
669 | prefix, hole_start, hole_end, | ||
670 | hole_size); | ||
671 | total_free += hole_size; | ||
672 | } | ||
634 | } | 673 | } |
635 | printk(KERN_DEBUG "%s total: %d, used %d free %d\n", prefix, total, | 674 | total = total_free + total_used; |
675 | |||
676 | printk(KERN_DEBUG "%s total: %lu, used %lu free %lu\n", prefix, total, | ||
636 | total_used, total_free); | 677 | total_used, total_free); |
637 | } | 678 | } |
638 | EXPORT_SYMBOL(drm_mm_debug_table); | 679 | EXPORT_SYMBOL(drm_mm_debug_table); |
@@ -641,17 +682,34 @@ EXPORT_SYMBOL(drm_mm_debug_table); | |||
641 | int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm) | 682 | int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm) |
642 | { | 683 | { |
643 | struct drm_mm_node *entry; | 684 | struct drm_mm_node *entry; |
644 | int total_used = 0, total_free = 0, total = 0; | 685 | unsigned long total_used = 0, total_free = 0, total = 0; |
645 | 686 | unsigned long hole_start, hole_end, hole_size; | |
646 | list_for_each_entry(entry, &mm->node_list, node_list) { | 687 | |
647 | seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: %s\n", entry->start, entry->start + entry->size, entry->size, entry->free ? "free" : "used"); | 688 | hole_start = drm_mm_hole_node_start(&mm->head_node); |
648 | total += entry->size; | 689 | hole_end = drm_mm_hole_node_end(&mm->head_node); |
649 | if (entry->free) | 690 | hole_size = hole_end - hole_start; |
650 | total_free += entry->size; | 691 | if (hole_size) |
651 | else | 692 | seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n", |
652 | total_used += entry->size; | 693 | hole_start, hole_end, hole_size); |
694 | total_free += hole_size; | ||
695 | |||
696 | drm_mm_for_each_node(entry, mm) { | ||
697 | seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: used\n", | ||
698 | entry->start, entry->start + entry->size, | ||
699 | entry->size); | ||
700 | total_used += entry->size; | ||
701 | if (entry->hole_follows) { | ||
702 | hole_start = drm_mm_hole_node_start(&mm->head_node); | ||
703 | hole_end = drm_mm_hole_node_end(&mm->head_node); | ||
704 | hole_size = hole_end - hole_start; | ||
705 | seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n", | ||
706 | hole_start, hole_end, hole_size); | ||
707 | total_free += hole_size; | ||
708 | } | ||
653 | } | 709 | } |
654 | seq_printf(m, "total: %d, used %d free %d\n", total, total_used, total_free); | 710 | total = total_free + total_used; |
711 | |||
712 | seq_printf(m, "total: %lu, used %lu free %lu\n", total, total_used, total_free); | ||
655 | return 0; | 713 | return 0; |
656 | } | 714 | } |
657 | EXPORT_SYMBOL(drm_mm_dump_table); | 715 | EXPORT_SYMBOL(drm_mm_dump_table); |
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 58e65f92c23..25bf87390f5 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c | |||
@@ -593,7 +593,7 @@ EXPORT_SYMBOL(drm_mode_height); | |||
593 | * | 593 | * |
594 | * Return @modes's hsync rate in kHz, rounded to the nearest int. | 594 | * Return @modes's hsync rate in kHz, rounded to the nearest int. |
595 | */ | 595 | */ |
596 | int drm_mode_hsync(struct drm_display_mode *mode) | 596 | int drm_mode_hsync(const struct drm_display_mode *mode) |
597 | { | 597 | { |
598 | unsigned int calc_val; | 598 | unsigned int calc_val; |
599 | 599 | ||
@@ -627,7 +627,7 @@ EXPORT_SYMBOL(drm_mode_hsync); | |||
627 | * If it is 70.288, it will return 70Hz. | 627 | * If it is 70.288, it will return 70Hz. |
628 | * If it is 59.6, it will return 60Hz. | 628 | * If it is 59.6, it will return 60Hz. |
629 | */ | 629 | */ |
630 | int drm_mode_vrefresh(struct drm_display_mode *mode) | 630 | int drm_mode_vrefresh(const struct drm_display_mode *mode) |
631 | { | 631 | { |
632 | int refresh = 0; | 632 | int refresh = 0; |
633 | unsigned int calc_val; | 633 | unsigned int calc_val; |
@@ -725,7 +725,7 @@ EXPORT_SYMBOL(drm_mode_set_crtcinfo); | |||
725 | * a pointer to it. Used to create new instances of established modes. | 725 | * a pointer to it. Used to create new instances of established modes. |
726 | */ | 726 | */ |
727 | struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev, | 727 | struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev, |
728 | struct drm_display_mode *mode) | 728 | const struct drm_display_mode *mode) |
729 | { | 729 | { |
730 | struct drm_display_mode *nmode; | 730 | struct drm_display_mode *nmode; |
731 | int new_id; | 731 | int new_id; |
diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index f5bd9e590c8..e1aee4f6a7c 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c | |||
@@ -125,6 +125,176 @@ void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah) | |||
125 | EXPORT_SYMBOL(drm_pci_free); | 125 | EXPORT_SYMBOL(drm_pci_free); |
126 | 126 | ||
127 | #ifdef CONFIG_PCI | 127 | #ifdef CONFIG_PCI |
128 | |||
129 | static int drm_get_pci_domain(struct drm_device *dev) | ||
130 | { | ||
131 | #ifndef __alpha__ | ||
132 | /* For historical reasons, drm_get_pci_domain() is busticated | ||
133 | * on most archs and has to remain so for userspace interface | ||
134 | * < 1.4, except on alpha which was right from the beginning | ||
135 | */ | ||
136 | if (dev->if_version < 0x10004) | ||
137 | return 0; | ||
138 | #endif /* __alpha__ */ | ||
139 | |||
140 | return pci_domain_nr(dev->pdev->bus); | ||
141 | } | ||
142 | |||
143 | static int drm_pci_get_irq(struct drm_device *dev) | ||
144 | { | ||
145 | return dev->pdev->irq; | ||
146 | } | ||
147 | |||
148 | static const char *drm_pci_get_name(struct drm_device *dev) | ||
149 | { | ||
150 | struct pci_driver *pdriver = dev->driver->kdriver.pci; | ||
151 | return pdriver->name; | ||
152 | } | ||
153 | |||
154 | int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master) | ||
155 | { | ||
156 | int len, ret; | ||
157 | struct pci_driver *pdriver = dev->driver->kdriver.pci; | ||
158 | master->unique_len = 40; | ||
159 | master->unique_size = master->unique_len; | ||
160 | master->unique = kmalloc(master->unique_size, GFP_KERNEL); | ||
161 | if (master->unique == NULL) | ||
162 | return -ENOMEM; | ||
163 | |||
164 | |||
165 | len = snprintf(master->unique, master->unique_len, | ||
166 | "pci:%04x:%02x:%02x.%d", | ||
167 | drm_get_pci_domain(dev), | ||
168 | dev->pdev->bus->number, | ||
169 | PCI_SLOT(dev->pdev->devfn), | ||
170 | PCI_FUNC(dev->pdev->devfn)); | ||
171 | |||
172 | if (len >= master->unique_len) { | ||
173 | DRM_ERROR("buffer overflow"); | ||
174 | ret = -EINVAL; | ||
175 | goto err; | ||
176 | } else | ||
177 | master->unique_len = len; | ||
178 | |||
179 | dev->devname = | ||
180 | kmalloc(strlen(pdriver->name) + | ||
181 | master->unique_len + 2, GFP_KERNEL); | ||
182 | |||
183 | if (dev->devname == NULL) { | ||
184 | ret = -ENOMEM; | ||
185 | goto err; | ||
186 | } | ||
187 | |||
188 | sprintf(dev->devname, "%s@%s", pdriver->name, | ||
189 | master->unique); | ||
190 | |||
191 | return 0; | ||
192 | err: | ||
193 | return ret; | ||
194 | } | ||
195 | |||
196 | int drm_pci_set_unique(struct drm_device *dev, | ||
197 | struct drm_master *master, | ||
198 | struct drm_unique *u) | ||
199 | { | ||
200 | int domain, bus, slot, func, ret; | ||
201 | const char *bus_name; | ||
202 | |||
203 | master->unique_len = u->unique_len; | ||
204 | master->unique_size = u->unique_len + 1; | ||
205 | master->unique = kmalloc(master->unique_size, GFP_KERNEL); | ||
206 | if (!master->unique) { | ||
207 | ret = -ENOMEM; | ||
208 | goto err; | ||
209 | } | ||
210 | |||
211 | if (copy_from_user(master->unique, u->unique, master->unique_len)) { | ||
212 | ret = -EFAULT; | ||
213 | goto err; | ||
214 | } | ||
215 | |||
216 | master->unique[master->unique_len] = '\0'; | ||
217 | |||
218 | bus_name = dev->driver->bus->get_name(dev); | ||
219 | dev->devname = kmalloc(strlen(bus_name) + | ||
220 | strlen(master->unique) + 2, GFP_KERNEL); | ||
221 | if (!dev->devname) { | ||
222 | ret = -ENOMEM; | ||
223 | goto err; | ||
224 | } | ||
225 | |||
226 | sprintf(dev->devname, "%s@%s", bus_name, | ||
227 | master->unique); | ||
228 | |||
229 | /* Return error if the busid submitted doesn't match the device's actual | ||
230 | * busid. | ||
231 | */ | ||
232 | ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func); | ||
233 | if (ret != 3) { | ||
234 | ret = -EINVAL; | ||
235 | goto err; | ||
236 | } | ||
237 | |||
238 | domain = bus >> 8; | ||
239 | bus &= 0xff; | ||
240 | |||
241 | if ((domain != drm_get_pci_domain(dev)) || | ||
242 | (bus != dev->pdev->bus->number) || | ||
243 | (slot != PCI_SLOT(dev->pdev->devfn)) || | ||
244 | (func != PCI_FUNC(dev->pdev->devfn))) { | ||
245 | ret = -EINVAL; | ||
246 | goto err; | ||
247 | } | ||
248 | return 0; | ||
249 | err: | ||
250 | return ret; | ||
251 | } | ||
252 | |||
253 | |||
254 | int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p) | ||
255 | { | ||
256 | if ((p->busnum >> 8) != drm_get_pci_domain(dev) || | ||
257 | (p->busnum & 0xff) != dev->pdev->bus->number || | ||
258 | p->devnum != PCI_SLOT(dev->pdev->devfn) || p->funcnum != PCI_FUNC(dev->pdev->devfn)) | ||
259 | return -EINVAL; | ||
260 | |||
261 | p->irq = dev->pdev->irq; | ||
262 | |||
263 | DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum, | ||
264 | p->irq); | ||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | int drm_pci_agp_init(struct drm_device *dev) | ||
269 | { | ||
270 | if (drm_core_has_AGP(dev)) { | ||
271 | if (drm_pci_device_is_agp(dev)) | ||
272 | dev->agp = drm_agp_init(dev); | ||
273 | if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) | ||
274 | && (dev->agp == NULL)) { | ||
275 | DRM_ERROR("Cannot initialize the agpgart module.\n"); | ||
276 | return -EINVAL; | ||
277 | } | ||
278 | if (drm_core_has_MTRR(dev)) { | ||
279 | if (dev->agp) | ||
280 | dev->agp->agp_mtrr = | ||
281 | mtrr_add(dev->agp->agp_info.aper_base, | ||
282 | dev->agp->agp_info.aper_size * | ||
283 | 1024 * 1024, MTRR_TYPE_WRCOMB, 1); | ||
284 | } | ||
285 | } | ||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | static struct drm_bus drm_pci_bus = { | ||
290 | .bus_type = DRIVER_BUS_PCI, | ||
291 | .get_irq = drm_pci_get_irq, | ||
292 | .get_name = drm_pci_get_name, | ||
293 | .set_busid = drm_pci_set_busid, | ||
294 | .set_unique = drm_pci_set_unique, | ||
295 | .agp_init = drm_pci_agp_init, | ||
296 | }; | ||
297 | |||
128 | /** | 298 | /** |
129 | * Register. | 299 | * Register. |
130 | * | 300 | * |
@@ -219,7 +389,7 @@ err_g1: | |||
219 | EXPORT_SYMBOL(drm_get_pci_dev); | 389 | EXPORT_SYMBOL(drm_get_pci_dev); |
220 | 390 | ||
221 | /** | 391 | /** |
222 | * PCI device initialization. Called via drm_init at module load time, | 392 | * PCI device initialization. Called direct from modules at load time. |
223 | * | 393 | * |
224 | * \return zero on success or a negative number on failure. | 394 | * \return zero on success or a negative number on failure. |
225 | * | 395 | * |
@@ -229,18 +399,24 @@ EXPORT_SYMBOL(drm_get_pci_dev); | |||
229 | * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and | 399 | * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and |
230 | * after the initialization for driver customization. | 400 | * after the initialization for driver customization. |
231 | */ | 401 | */ |
232 | int drm_pci_init(struct drm_driver *driver) | 402 | int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver) |
233 | { | 403 | { |
234 | struct pci_dev *pdev = NULL; | 404 | struct pci_dev *pdev = NULL; |
235 | const struct pci_device_id *pid; | 405 | const struct pci_device_id *pid; |
236 | int i; | 406 | int i; |
237 | 407 | ||
408 | DRM_DEBUG("\n"); | ||
409 | |||
410 | INIT_LIST_HEAD(&driver->device_list); | ||
411 | driver->kdriver.pci = pdriver; | ||
412 | driver->bus = &drm_pci_bus; | ||
413 | |||
238 | if (driver->driver_features & DRIVER_MODESET) | 414 | if (driver->driver_features & DRIVER_MODESET) |
239 | return pci_register_driver(&driver->pci_driver); | 415 | return pci_register_driver(pdriver); |
240 | 416 | ||
241 | /* If not using KMS, fall back to stealth mode manual scanning. */ | 417 | /* If not using KMS, fall back to stealth mode manual scanning. */ |
242 | for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) { | 418 | for (i = 0; pdriver->id_table[i].vendor != 0; i++) { |
243 | pid = &driver->pci_driver.id_table[i]; | 419 | pid = &pdriver->id_table[i]; |
244 | 420 | ||
245 | /* Loop around setting up a DRM device for each PCI device | 421 | /* Loop around setting up a DRM device for each PCI device |
246 | * matching our ID and device class. If we had the internal | 422 | * matching our ID and device class. If we had the internal |
@@ -265,10 +441,27 @@ int drm_pci_init(struct drm_driver *driver) | |||
265 | 441 | ||
266 | #else | 442 | #else |
267 | 443 | ||
268 | int drm_pci_init(struct drm_driver *driver) | 444 | int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver) |
269 | { | 445 | { |
270 | return -1; | 446 | return -1; |
271 | } | 447 | } |
272 | 448 | ||
273 | #endif | 449 | #endif |
450 | |||
451 | EXPORT_SYMBOL(drm_pci_init); | ||
452 | |||
274 | /*@}*/ | 453 | /*@}*/ |
454 | void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver) | ||
455 | { | ||
456 | struct drm_device *dev, *tmp; | ||
457 | DRM_DEBUG("\n"); | ||
458 | |||
459 | if (driver->driver_features & DRIVER_MODESET) { | ||
460 | pci_unregister_driver(pdriver); | ||
461 | } else { | ||
462 | list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item) | ||
463 | drm_put_dev(dev); | ||
464 | } | ||
465 | DRM_INFO("Module unloaded\n"); | ||
466 | } | ||
467 | EXPORT_SYMBOL(drm_pci_exit); | ||
diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c index 92d1d0fb7b7..7223f06d8e5 100644 --- a/drivers/gpu/drm/drm_platform.c +++ b/drivers/gpu/drm/drm_platform.c | |||
@@ -109,8 +109,60 @@ err_g1: | |||
109 | } | 109 | } |
110 | EXPORT_SYMBOL(drm_get_platform_dev); | 110 | EXPORT_SYMBOL(drm_get_platform_dev); |
111 | 111 | ||
112 | static int drm_platform_get_irq(struct drm_device *dev) | ||
113 | { | ||
114 | return platform_get_irq(dev->platformdev, 0); | ||
115 | } | ||
116 | |||
117 | static const char *drm_platform_get_name(struct drm_device *dev) | ||
118 | { | ||
119 | return dev->platformdev->name; | ||
120 | } | ||
121 | |||
122 | static int drm_platform_set_busid(struct drm_device *dev, struct drm_master *master) | ||
123 | { | ||
124 | int len, ret; | ||
125 | |||
126 | master->unique_len = 10 + strlen(dev->platformdev->name); | ||
127 | master->unique = kmalloc(master->unique_len + 1, GFP_KERNEL); | ||
128 | |||
129 | if (master->unique == NULL) | ||
130 | return -ENOMEM; | ||
131 | |||
132 | len = snprintf(master->unique, master->unique_len, | ||
133 | "platform:%s", dev->platformdev->name); | ||
134 | |||
135 | if (len > master->unique_len) { | ||
136 | DRM_ERROR("Unique buffer overflowed\n"); | ||
137 | ret = -EINVAL; | ||
138 | goto err; | ||
139 | } | ||
140 | |||
141 | dev->devname = | ||
142 | kmalloc(strlen(dev->platformdev->name) + | ||
143 | master->unique_len + 2, GFP_KERNEL); | ||
144 | |||
145 | if (dev->devname == NULL) { | ||
146 | ret = -ENOMEM; | ||
147 | goto err; | ||
148 | } | ||
149 | |||
150 | sprintf(dev->devname, "%s@%s", dev->platformdev->name, | ||
151 | master->unique); | ||
152 | return 0; | ||
153 | err: | ||
154 | return ret; | ||
155 | } | ||
156 | |||
157 | static struct drm_bus drm_platform_bus = { | ||
158 | .bus_type = DRIVER_BUS_PLATFORM, | ||
159 | .get_irq = drm_platform_get_irq, | ||
160 | .get_name = drm_platform_get_name, | ||
161 | .set_busid = drm_platform_set_busid, | ||
162 | }; | ||
163 | |||
112 | /** | 164 | /** |
113 | * Platform device initialization. Called via drm_init at module load time, | 165 | * Platform device initialization. Called direct from modules. |
114 | * | 166 | * |
115 | * \return zero on success or a negative number on failure. | 167 | * \return zero on success or a negative number on failure. |
116 | * | 168 | * |
@@ -121,7 +173,24 @@ EXPORT_SYMBOL(drm_get_platform_dev); | |||
121 | * after the initialization for driver customization. | 173 | * after the initialization for driver customization. |
122 | */ | 174 | */ |
123 | 175 | ||
124 | int drm_platform_init(struct drm_driver *driver) | 176 | int drm_platform_init(struct drm_driver *driver, struct platform_device *platform_device) |
125 | { | 177 | { |
126 | return drm_get_platform_dev(driver->platform_device, driver); | 178 | DRM_DEBUG("\n"); |
179 | |||
180 | driver->kdriver.platform_device = platform_device; | ||
181 | driver->bus = &drm_platform_bus; | ||
182 | INIT_LIST_HEAD(&driver->device_list); | ||
183 | return drm_get_platform_dev(platform_device, driver); | ||
184 | } | ||
185 | EXPORT_SYMBOL(drm_platform_init); | ||
186 | |||
187 | void drm_platform_exit(struct drm_driver *driver, struct platform_device *platform_device) | ||
188 | { | ||
189 | struct drm_device *dev, *tmp; | ||
190 | DRM_DEBUG("\n"); | ||
191 | |||
192 | list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item) | ||
193 | drm_put_dev(dev); | ||
194 | DRM_INFO("Module unloaded\n"); | ||
127 | } | 195 | } |
196 | EXPORT_SYMBOL(drm_platform_exit); | ||
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index d59edc18301..001273d57f2 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c | |||
@@ -269,25 +269,14 @@ int drm_fill_in_dev(struct drm_device *dev, | |||
269 | 269 | ||
270 | dev->driver = driver; | 270 | dev->driver = driver; |
271 | 271 | ||
272 | if (drm_core_has_AGP(dev)) { | 272 | if (dev->driver->bus->agp_init) { |
273 | if (drm_device_is_agp(dev)) | 273 | retcode = dev->driver->bus->agp_init(dev); |
274 | dev->agp = drm_agp_init(dev); | 274 | if (retcode) |
275 | if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) | ||
276 | && (dev->agp == NULL)) { | ||
277 | DRM_ERROR("Cannot initialize the agpgart module.\n"); | ||
278 | retcode = -EINVAL; | ||
279 | goto error_out_unreg; | 275 | goto error_out_unreg; |
280 | } | ||
281 | if (drm_core_has_MTRR(dev)) { | ||
282 | if (dev->agp) | ||
283 | dev->agp->agp_mtrr = | ||
284 | mtrr_add(dev->agp->agp_info.aper_base, | ||
285 | dev->agp->agp_info.aper_size * | ||
286 | 1024 * 1024, MTRR_TYPE_WRCOMB, 1); | ||
287 | } | ||
288 | } | 276 | } |
289 | 277 | ||
290 | 278 | ||
279 | |||
291 | retcode = drm_ctxbitmap_init(dev); | 280 | retcode = drm_ctxbitmap_init(dev); |
292 | if (retcode) { | 281 | if (retcode) { |
293 | DRM_ERROR("Cannot allocate memory for context bitmap.\n"); | 282 | DRM_ERROR("Cannot allocate memory for context bitmap.\n"); |
@@ -425,7 +414,6 @@ int drm_put_minor(struct drm_minor **minor_p) | |||
425 | * | 414 | * |
426 | * Cleans up all DRM device, calling drm_lastclose(). | 415 | * Cleans up all DRM device, calling drm_lastclose(). |
427 | * | 416 | * |
428 | * \sa drm_init | ||
429 | */ | 417 | */ |
430 | void drm_put_dev(struct drm_device *dev) | 418 | void drm_put_dev(struct drm_device *dev) |
431 | { | 419 | { |
@@ -475,6 +463,7 @@ void drm_put_dev(struct drm_device *dev) | |||
475 | 463 | ||
476 | drm_put_minor(&dev->primary); | 464 | drm_put_minor(&dev->primary); |
477 | 465 | ||
466 | list_del(&dev->driver_item); | ||
478 | if (dev->devname) { | 467 | if (dev->devname) { |
479 | kfree(dev->devname); | 468 | kfree(dev->devname); |
480 | dev->devname = NULL; | 469 | dev->devname = NULL; |
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 85da4c40694..2eee8e016b3 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c | |||
@@ -158,8 +158,15 @@ static ssize_t status_show(struct device *device, | |||
158 | { | 158 | { |
159 | struct drm_connector *connector = to_drm_connector(device); | 159 | struct drm_connector *connector = to_drm_connector(device); |
160 | enum drm_connector_status status; | 160 | enum drm_connector_status status; |
161 | int ret; | ||
162 | |||
163 | ret = mutex_lock_interruptible(&connector->dev->mode_config.mutex); | ||
164 | if (ret) | ||
165 | return ret; | ||
161 | 166 | ||
162 | status = connector->funcs->detect(connector, true); | 167 | status = connector->funcs->detect(connector, true); |
168 | mutex_unlock(&connector->dev->mode_config.mutex); | ||
169 | |||
163 | return snprintf(buf, PAGE_SIZE, "%s\n", | 170 | return snprintf(buf, PAGE_SIZE, "%s\n", |
164 | drm_get_connector_status_name(status)); | 171 | drm_get_connector_status_name(status)); |
165 | } | 172 | } |
diff --git a/drivers/gpu/drm/drm_usb.c b/drivers/gpu/drm/drm_usb.c new file mode 100644 index 00000000000..206d2300d87 --- /dev/null +++ b/drivers/gpu/drm/drm_usb.c | |||
@@ -0,0 +1,117 @@ | |||
1 | #include "drmP.h" | ||
2 | #include <linux/usb.h> | ||
3 | |||
4 | #ifdef CONFIG_USB | ||
5 | int drm_get_usb_dev(struct usb_interface *interface, | ||
6 | const struct usb_device_id *id, | ||
7 | struct drm_driver *driver) | ||
8 | { | ||
9 | struct drm_device *dev; | ||
10 | struct usb_device *usbdev; | ||
11 | int ret; | ||
12 | |||
13 | DRM_DEBUG("\n"); | ||
14 | |||
15 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
16 | if (!dev) | ||
17 | return -ENOMEM; | ||
18 | |||
19 | usbdev = interface_to_usbdev(interface); | ||
20 | dev->usbdev = usbdev; | ||
21 | dev->dev = &usbdev->dev; | ||
22 | |||
23 | mutex_lock(&drm_global_mutex); | ||
24 | |||
25 | ret = drm_fill_in_dev(dev, NULL, driver); | ||
26 | if (ret) { | ||
27 | printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); | ||
28 | goto err_g1; | ||
29 | } | ||
30 | |||
31 | usb_set_intfdata(interface, dev); | ||
32 | ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL); | ||
33 | if (ret) | ||
34 | goto err_g1; | ||
35 | |||
36 | ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY); | ||
37 | if (ret) | ||
38 | goto err_g2; | ||
39 | |||
40 | if (dev->driver->load) { | ||
41 | ret = dev->driver->load(dev, 0); | ||
42 | if (ret) | ||
43 | goto err_g3; | ||
44 | } | ||
45 | |||
46 | /* setup the grouping for the legacy output */ | ||
47 | ret = drm_mode_group_init_legacy_group(dev, | ||
48 | &dev->primary->mode_group); | ||
49 | if (ret) | ||
50 | goto err_g3; | ||
51 | |||
52 | list_add_tail(&dev->driver_item, &driver->device_list); | ||
53 | |||
54 | mutex_unlock(&drm_global_mutex); | ||
55 | |||
56 | DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", | ||
57 | driver->name, driver->major, driver->minor, driver->patchlevel, | ||
58 | driver->date, dev->primary->index); | ||
59 | |||
60 | return 0; | ||
61 | |||
62 | err_g3: | ||
63 | drm_put_minor(&dev->primary); | ||
64 | err_g2: | ||
65 | drm_put_minor(&dev->control); | ||
66 | err_g1: | ||
67 | kfree(dev); | ||
68 | mutex_unlock(&drm_global_mutex); | ||
69 | return ret; | ||
70 | |||
71 | } | ||
72 | EXPORT_SYMBOL(drm_get_usb_dev); | ||
73 | |||
74 | static int drm_usb_get_irq(struct drm_device *dev) | ||
75 | { | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static const char *drm_usb_get_name(struct drm_device *dev) | ||
80 | { | ||
81 | return "USB"; | ||
82 | } | ||
83 | |||
84 | static int drm_usb_set_busid(struct drm_device *dev, | ||
85 | struct drm_master *master) | ||
86 | { | ||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static struct drm_bus drm_usb_bus = { | ||
91 | .bus_type = DRIVER_BUS_USB, | ||
92 | .get_irq = drm_usb_get_irq, | ||
93 | .get_name = drm_usb_get_name, | ||
94 | .set_busid = drm_usb_set_busid, | ||
95 | }; | ||
96 | |||
97 | int drm_usb_init(struct drm_driver *driver, struct usb_driver *udriver) | ||
98 | { | ||
99 | int res; | ||
100 | DRM_DEBUG("\n"); | ||
101 | |||
102 | INIT_LIST_HEAD(&driver->device_list); | ||
103 | driver->kdriver.usb = udriver; | ||
104 | driver->bus = &drm_usb_bus; | ||
105 | |||
106 | res = usb_register(udriver); | ||
107 | return res; | ||
108 | } | ||
109 | EXPORT_SYMBOL(drm_usb_init); | ||
110 | |||
111 | void drm_usb_exit(struct drm_driver *driver, | ||
112 | struct usb_driver *udriver) | ||
113 | { | ||
114 | usb_deregister(udriver); | ||
115 | } | ||
116 | EXPORT_SYMBOL(drm_usb_exit); | ||
117 | #endif | ||
diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index ff33e53bbbf..8f371e8d630 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include <linux/interrupt.h> /* For task queue support */ | 37 | #include <linux/interrupt.h> /* For task queue support */ |
38 | #include <linux/delay.h> | 38 | #include <linux/delay.h> |
39 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
40 | #include <linux/smp_lock.h> | ||
41 | #include <linux/pagemap.h> | 40 | #include <linux/pagemap.h> |
42 | 41 | ||
43 | #define I810_BUF_FREE 2 | 42 | #define I810_BUF_FREE 2 |
@@ -94,7 +93,6 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma) | |||
94 | struct drm_buf *buf; | 93 | struct drm_buf *buf; |
95 | drm_i810_buf_priv_t *buf_priv; | 94 | drm_i810_buf_priv_t *buf_priv; |
96 | 95 | ||
97 | lock_kernel(); | ||
98 | dev = priv->minor->dev; | 96 | dev = priv->minor->dev; |
99 | dev_priv = dev->dev_private; | 97 | dev_priv = dev->dev_private; |
100 | buf = dev_priv->mmap_buffer; | 98 | buf = dev_priv->mmap_buffer; |
@@ -104,7 +102,6 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma) | |||
104 | vma->vm_file = filp; | 102 | vma->vm_file = filp; |
105 | 103 | ||
106 | buf_priv->currently_mapped = I810_BUF_MAPPED; | 104 | buf_priv->currently_mapped = I810_BUF_MAPPED; |
107 | unlock_kernel(); | ||
108 | 105 | ||
109 | if (io_remap_pfn_range(vma, vma->vm_start, | 106 | if (io_remap_pfn_range(vma, vma->vm_start, |
110 | vma->vm_pgoff, | 107 | vma->vm_pgoff, |
@@ -116,7 +113,7 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma) | |||
116 | static const struct file_operations i810_buffer_fops = { | 113 | static const struct file_operations i810_buffer_fops = { |
117 | .open = drm_open, | 114 | .open = drm_open, |
118 | .release = drm_release, | 115 | .release = drm_release, |
119 | .unlocked_ioctl = i810_ioctl, | 116 | .unlocked_ioctl = drm_ioctl, |
120 | .mmap = i810_mmap_buffers, | 117 | .mmap = i810_mmap_buffers, |
121 | .fasync = drm_fasync, | 118 | .fasync = drm_fasync, |
122 | .llseek = noop_llseek, | 119 | .llseek = noop_llseek, |
@@ -1242,19 +1239,6 @@ int i810_driver_dma_quiescent(struct drm_device *dev) | |||
1242 | return 0; | 1239 | return 0; |
1243 | } | 1240 | } |
1244 | 1241 | ||
1245 | /* | ||
1246 | * call the drm_ioctl under the big kernel lock because | ||
1247 | * to lock against the i810_mmap_buffers function. | ||
1248 | */ | ||
1249 | long i810_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
1250 | { | ||
1251 | int ret; | ||
1252 | lock_kernel(); | ||
1253 | ret = drm_ioctl(file, cmd, arg); | ||
1254 | unlock_kernel(); | ||
1255 | return ret; | ||
1256 | } | ||
1257 | |||
1258 | struct drm_ioctl_desc i810_ioctls[] = { | 1242 | struct drm_ioctl_desc i810_ioctls[] = { |
1259 | DRM_IOCTL_DEF_DRV(I810_INIT, i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), | 1243 | DRM_IOCTL_DEF_DRV(I810_INIT, i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), |
1260 | DRM_IOCTL_DEF_DRV(I810_VERTEX, i810_dma_vertex, DRM_AUTH|DRM_UNLOCKED), | 1244 | DRM_IOCTL_DEF_DRV(I810_VERTEX, i810_dma_vertex, DRM_AUTH|DRM_UNLOCKED), |
diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c index 88bcd331e7c..6f98d059f68 100644 --- a/drivers/gpu/drm/i810/i810_drv.c +++ b/drivers/gpu/drm/i810/i810_drv.c | |||
@@ -57,18 +57,13 @@ static struct drm_driver driver = { | |||
57 | .owner = THIS_MODULE, | 57 | .owner = THIS_MODULE, |
58 | .open = drm_open, | 58 | .open = drm_open, |
59 | .release = drm_release, | 59 | .release = drm_release, |
60 | .unlocked_ioctl = i810_ioctl, | 60 | .unlocked_ioctl = drm_ioctl, |
61 | .mmap = drm_mmap, | 61 | .mmap = drm_mmap, |
62 | .poll = drm_poll, | 62 | .poll = drm_poll, |
63 | .fasync = drm_fasync, | 63 | .fasync = drm_fasync, |
64 | .llseek = noop_llseek, | 64 | .llseek = noop_llseek, |
65 | }, | 65 | }, |
66 | 66 | ||
67 | .pci_driver = { | ||
68 | .name = DRIVER_NAME, | ||
69 | .id_table = pciidlist, | ||
70 | }, | ||
71 | |||
72 | .name = DRIVER_NAME, | 67 | .name = DRIVER_NAME, |
73 | .desc = DRIVER_DESC, | 68 | .desc = DRIVER_DESC, |
74 | .date = DRIVER_DATE, | 69 | .date = DRIVER_DATE, |
@@ -77,15 +72,24 @@ static struct drm_driver driver = { | |||
77 | .patchlevel = DRIVER_PATCHLEVEL, | 72 | .patchlevel = DRIVER_PATCHLEVEL, |
78 | }; | 73 | }; |
79 | 74 | ||
75 | static struct pci_driver i810_pci_driver = { | ||
76 | .name = DRIVER_NAME, | ||
77 | .id_table = pciidlist, | ||
78 | }; | ||
79 | |||
80 | static int __init i810_init(void) | 80 | static int __init i810_init(void) |
81 | { | 81 | { |
82 | if (num_possible_cpus() > 1) { | ||
83 | pr_err("drm/i810 does not support SMP\n"); | ||
84 | return -EINVAL; | ||
85 | } | ||
82 | driver.num_ioctls = i810_max_ioctl; | 86 | driver.num_ioctls = i810_max_ioctl; |
83 | return drm_init(&driver); | 87 | return drm_pci_init(&driver, &i810_pci_driver); |
84 | } | 88 | } |
85 | 89 | ||
86 | static void __exit i810_exit(void) | 90 | static void __exit i810_exit(void) |
87 | { | 91 | { |
88 | drm_exit(&driver); | 92 | drm_pci_exit(&driver, &i810_pci_driver); |
89 | } | 93 | } |
90 | 94 | ||
91 | module_init(i810_init); | 95 | module_init(i810_init); |
diff --git a/drivers/gpu/drm/i830/Makefile b/drivers/gpu/drm/i830/Makefile deleted file mode 100644 index c642ee0b238..00000000000 --- a/drivers/gpu/drm/i830/Makefile +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | # | ||
2 | # Makefile for the drm device driver. This driver provides support for the | ||
3 | # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. | ||
4 | |||
5 | ccflags-y := -Iinclude/drm | ||
6 | i830-y := i830_drv.o i830_dma.o i830_irq.o | ||
7 | |||
8 | obj-$(CONFIG_DRM_I830) += i830.o | ||
diff --git a/drivers/gpu/drm/i830/i830_dma.c b/drivers/gpu/drm/i830/i830_dma.c deleted file mode 100644 index ca6f31ff0ee..00000000000 --- a/drivers/gpu/drm/i830/i830_dma.c +++ /dev/null | |||
@@ -1,1560 +0,0 @@ | |||
1 | /* i830_dma.c -- DMA support for the I830 -*- linux-c -*- | ||
2 | * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com | ||
3 | * | ||
4 | * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. | ||
5 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | ||
6 | * All Rights Reserved. | ||
7 | * | ||
8 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
9 | * copy of this software and associated documentation files (the "Software"), | ||
10 | * to deal in the Software without restriction, including without limitation | ||
11 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
12 | * and/or sell copies of the Software, and to permit persons to whom the | ||
13 | * Software is furnished to do so, subject to the following conditions: | ||
14 | * | ||
15 | * The above copyright notice and this permission notice (including the next | ||
16 | * paragraph) shall be included in all copies or substantial portions of the | ||
17 | * Software. | ||
18 | * | ||
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
22 | * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
23 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
24 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
25 | * DEALINGS IN THE SOFTWARE. | ||
26 | * | ||
27 | * Authors: Rickard E. (Rik) Faith <faith@valinux.com> | ||
28 | * Jeff Hartmann <jhartmann@valinux.com> | ||
29 | * Keith Whitwell <keith@tungstengraphics.com> | ||
30 | * Abraham vd Merwe <abraham@2d3d.co.za> | ||
31 | * | ||
32 | */ | ||
33 | |||
34 | #include "drmP.h" | ||
35 | #include "drm.h" | ||
36 | #include "i830_drm.h" | ||
37 | #include "i830_drv.h" | ||
38 | #include <linux/interrupt.h> /* For task queue support */ | ||
39 | #include <linux/smp_lock.h> | ||
40 | #include <linux/pagemap.h> | ||
41 | #include <linux/delay.h> | ||
42 | #include <linux/slab.h> | ||
43 | #include <asm/uaccess.h> | ||
44 | |||
45 | #define I830_BUF_FREE 2 | ||
46 | #define I830_BUF_CLIENT 1 | ||
47 | #define I830_BUF_HARDWARE 0 | ||
48 | |||
49 | #define I830_BUF_UNMAPPED 0 | ||
50 | #define I830_BUF_MAPPED 1 | ||
51 | |||
52 | static struct drm_buf *i830_freelist_get(struct drm_device * dev) | ||
53 | { | ||
54 | struct drm_device_dma *dma = dev->dma; | ||
55 | int i; | ||
56 | int used; | ||
57 | |||
58 | /* Linear search might not be the best solution */ | ||
59 | |||
60 | for (i = 0; i < dma->buf_count; i++) { | ||
61 | struct drm_buf *buf = dma->buflist[i]; | ||
62 | drm_i830_buf_priv_t *buf_priv = buf->dev_private; | ||
63 | /* In use is already a pointer */ | ||
64 | used = cmpxchg(buf_priv->in_use, I830_BUF_FREE, | ||
65 | I830_BUF_CLIENT); | ||
66 | if (used == I830_BUF_FREE) | ||
67 | return buf; | ||
68 | } | ||
69 | return NULL; | ||
70 | } | ||
71 | |||
72 | /* This should only be called if the buffer is not sent to the hardware | ||
73 | * yet, the hardware updates in use for us once its on the ring buffer. | ||
74 | */ | ||
75 | |||
76 | static int i830_freelist_put(struct drm_device *dev, struct drm_buf *buf) | ||
77 | { | ||
78 | drm_i830_buf_priv_t *buf_priv = buf->dev_private; | ||
79 | int used; | ||
80 | |||
81 | /* In use is already a pointer */ | ||
82 | used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, I830_BUF_FREE); | ||
83 | if (used != I830_BUF_CLIENT) { | ||
84 | DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx); | ||
85 | return -EINVAL; | ||
86 | } | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma) | ||
92 | { | ||
93 | struct drm_file *priv = filp->private_data; | ||
94 | struct drm_device *dev; | ||
95 | drm_i830_private_t *dev_priv; | ||
96 | struct drm_buf *buf; | ||
97 | drm_i830_buf_priv_t *buf_priv; | ||
98 | |||
99 | lock_kernel(); | ||
100 | dev = priv->minor->dev; | ||
101 | dev_priv = dev->dev_private; | ||
102 | buf = dev_priv->mmap_buffer; | ||
103 | buf_priv = buf->dev_private; | ||
104 | |||
105 | vma->vm_flags |= (VM_IO | VM_DONTCOPY); | ||
106 | vma->vm_file = filp; | ||
107 | |||
108 | buf_priv->currently_mapped = I830_BUF_MAPPED; | ||
109 | unlock_kernel(); | ||
110 | |||
111 | if (io_remap_pfn_range(vma, vma->vm_start, | ||
112 | vma->vm_pgoff, | ||
113 | vma->vm_end - vma->vm_start, vma->vm_page_prot)) | ||
114 | return -EAGAIN; | ||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static const struct file_operations i830_buffer_fops = { | ||
119 | .open = drm_open, | ||
120 | .release = drm_release, | ||
121 | .unlocked_ioctl = i830_ioctl, | ||
122 | .mmap = i830_mmap_buffers, | ||
123 | .fasync = drm_fasync, | ||
124 | .llseek = noop_llseek, | ||
125 | }; | ||
126 | |||
127 | static int i830_map_buffer(struct drm_buf *buf, struct drm_file *file_priv) | ||
128 | { | ||
129 | struct drm_device *dev = file_priv->minor->dev; | ||
130 | drm_i830_buf_priv_t *buf_priv = buf->dev_private; | ||
131 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
132 | const struct file_operations *old_fops; | ||
133 | unsigned long virtual; | ||
134 | int retcode = 0; | ||
135 | |||
136 | if (buf_priv->currently_mapped == I830_BUF_MAPPED) | ||
137 | return -EINVAL; | ||
138 | |||
139 | down_write(¤t->mm->mmap_sem); | ||
140 | old_fops = file_priv->filp->f_op; | ||
141 | file_priv->filp->f_op = &i830_buffer_fops; | ||
142 | dev_priv->mmap_buffer = buf; | ||
143 | virtual = do_mmap(file_priv->filp, 0, buf->total, PROT_READ | PROT_WRITE, | ||
144 | MAP_SHARED, buf->bus_address); | ||
145 | dev_priv->mmap_buffer = NULL; | ||
146 | file_priv->filp->f_op = old_fops; | ||
147 | if (IS_ERR((void *)virtual)) { /* ugh */ | ||
148 | /* Real error */ | ||
149 | DRM_ERROR("mmap error\n"); | ||
150 | retcode = PTR_ERR((void *)virtual); | ||
151 | buf_priv->virtual = NULL; | ||
152 | } else { | ||
153 | buf_priv->virtual = (void __user *)virtual; | ||
154 | } | ||
155 | up_write(¤t->mm->mmap_sem); | ||
156 | |||
157 | return retcode; | ||
158 | } | ||
159 | |||
160 | static int i830_unmap_buffer(struct drm_buf *buf) | ||
161 | { | ||
162 | drm_i830_buf_priv_t *buf_priv = buf->dev_private; | ||
163 | int retcode = 0; | ||
164 | |||
165 | if (buf_priv->currently_mapped != I830_BUF_MAPPED) | ||
166 | return -EINVAL; | ||
167 | |||
168 | down_write(¤t->mm->mmap_sem); | ||
169 | retcode = do_munmap(current->mm, | ||
170 | (unsigned long)buf_priv->virtual, | ||
171 | (size_t) buf->total); | ||
172 | up_write(¤t->mm->mmap_sem); | ||
173 | |||
174 | buf_priv->currently_mapped = I830_BUF_UNMAPPED; | ||
175 | buf_priv->virtual = NULL; | ||
176 | |||
177 | return retcode; | ||
178 | } | ||
179 | |||
180 | static int i830_dma_get_buffer(struct drm_device *dev, drm_i830_dma_t *d, | ||
181 | struct drm_file *file_priv) | ||
182 | { | ||
183 | struct drm_buf *buf; | ||
184 | drm_i830_buf_priv_t *buf_priv; | ||
185 | int retcode = 0; | ||
186 | |||
187 | buf = i830_freelist_get(dev); | ||
188 | if (!buf) { | ||
189 | retcode = -ENOMEM; | ||
190 | DRM_DEBUG("retcode=%d\n", retcode); | ||
191 | return retcode; | ||
192 | } | ||
193 | |||
194 | retcode = i830_map_buffer(buf, file_priv); | ||
195 | if (retcode) { | ||
196 | i830_freelist_put(dev, buf); | ||
197 | DRM_ERROR("mapbuf failed, retcode %d\n", retcode); | ||
198 | return retcode; | ||
199 | } | ||
200 | buf->file_priv = file_priv; | ||
201 | buf_priv = buf->dev_private; | ||
202 | d->granted = 1; | ||
203 | d->request_idx = buf->idx; | ||
204 | d->request_size = buf->total; | ||
205 | d->virtual = buf_priv->virtual; | ||
206 | |||
207 | return retcode; | ||
208 | } | ||
209 | |||
210 | static int i830_dma_cleanup(struct drm_device *dev) | ||
211 | { | ||
212 | struct drm_device_dma *dma = dev->dma; | ||
213 | |||
214 | /* Make sure interrupts are disabled here because the uninstall ioctl | ||
215 | * may not have been called from userspace and after dev_private | ||
216 | * is freed, it's too late. | ||
217 | */ | ||
218 | if (dev->irq_enabled) | ||
219 | drm_irq_uninstall(dev); | ||
220 | |||
221 | if (dev->dev_private) { | ||
222 | int i; | ||
223 | drm_i830_private_t *dev_priv = | ||
224 | (drm_i830_private_t *) dev->dev_private; | ||
225 | |||
226 | if (dev_priv->ring.virtual_start) | ||
227 | drm_core_ioremapfree(&dev_priv->ring.map, dev); | ||
228 | if (dev_priv->hw_status_page) { | ||
229 | pci_free_consistent(dev->pdev, PAGE_SIZE, | ||
230 | dev_priv->hw_status_page, | ||
231 | dev_priv->dma_status_page); | ||
232 | /* Need to rewrite hardware status page */ | ||
233 | I830_WRITE(0x02080, 0x1ffff000); | ||
234 | } | ||
235 | |||
236 | kfree(dev->dev_private); | ||
237 | dev->dev_private = NULL; | ||
238 | |||
239 | for (i = 0; i < dma->buf_count; i++) { | ||
240 | struct drm_buf *buf = dma->buflist[i]; | ||
241 | drm_i830_buf_priv_t *buf_priv = buf->dev_private; | ||
242 | if (buf_priv->kernel_virtual && buf->total) | ||
243 | drm_core_ioremapfree(&buf_priv->map, dev); | ||
244 | } | ||
245 | } | ||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | int i830_wait_ring(struct drm_device *dev, int n, const char *caller) | ||
250 | { | ||
251 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
252 | drm_i830_ring_buffer_t *ring = &(dev_priv->ring); | ||
253 | int iters = 0; | ||
254 | unsigned long end; | ||
255 | unsigned int last_head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR; | ||
256 | |||
257 | end = jiffies + (HZ * 3); | ||
258 | while (ring->space < n) { | ||
259 | ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR; | ||
260 | ring->space = ring->head - (ring->tail + 8); | ||
261 | if (ring->space < 0) | ||
262 | ring->space += ring->Size; | ||
263 | |||
264 | if (ring->head != last_head) { | ||
265 | end = jiffies + (HZ * 3); | ||
266 | last_head = ring->head; | ||
267 | } | ||
268 | |||
269 | iters++; | ||
270 | if (time_before(end, jiffies)) { | ||
271 | DRM_ERROR("space: %d wanted %d\n", ring->space, n); | ||
272 | DRM_ERROR("lockup\n"); | ||
273 | goto out_wait_ring; | ||
274 | } | ||
275 | udelay(1); | ||
276 | dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT; | ||
277 | } | ||
278 | |||
279 | out_wait_ring: | ||
280 | return iters; | ||
281 | } | ||
282 | |||
283 | static void i830_kernel_lost_context(struct drm_device *dev) | ||
284 | { | ||
285 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
286 | drm_i830_ring_buffer_t *ring = &(dev_priv->ring); | ||
287 | |||
288 | ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR; | ||
289 | ring->tail = I830_READ(LP_RING + RING_TAIL) & TAIL_ADDR; | ||
290 | ring->space = ring->head - (ring->tail + 8); | ||
291 | if (ring->space < 0) | ||
292 | ring->space += ring->Size; | ||
293 | |||
294 | if (ring->head == ring->tail) | ||
295 | dev_priv->sarea_priv->perf_boxes |= I830_BOX_RING_EMPTY; | ||
296 | } | ||
297 | |||
298 | static int i830_freelist_init(struct drm_device *dev, drm_i830_private_t *dev_priv) | ||
299 | { | ||
300 | struct drm_device_dma *dma = dev->dma; | ||
301 | int my_idx = 36; | ||
302 | u32 *hw_status = (u32 *) (dev_priv->hw_status_page + my_idx); | ||
303 | int i; | ||
304 | |||
305 | if (dma->buf_count > 1019) { | ||
306 | /* Not enough space in the status page for the freelist */ | ||
307 | return -EINVAL; | ||
308 | } | ||
309 | |||
310 | for (i = 0; i < dma->buf_count; i++) { | ||
311 | struct drm_buf *buf = dma->buflist[i]; | ||
312 | drm_i830_buf_priv_t *buf_priv = buf->dev_private; | ||
313 | |||
314 | buf_priv->in_use = hw_status++; | ||
315 | buf_priv->my_use_idx = my_idx; | ||
316 | my_idx += 4; | ||
317 | |||
318 | *buf_priv->in_use = I830_BUF_FREE; | ||
319 | |||
320 | buf_priv->map.offset = buf->bus_address; | ||
321 | buf_priv->map.size = buf->total; | ||
322 | buf_priv->map.type = _DRM_AGP; | ||
323 | buf_priv->map.flags = 0; | ||
324 | buf_priv->map.mtrr = 0; | ||
325 | |||
326 | drm_core_ioremap(&buf_priv->map, dev); | ||
327 | buf_priv->kernel_virtual = buf_priv->map.handle; | ||
328 | } | ||
329 | return 0; | ||
330 | } | ||
331 | |||
332 | static int i830_dma_initialize(struct drm_device *dev, | ||
333 | drm_i830_private_t *dev_priv, | ||
334 | drm_i830_init_t *init) | ||
335 | { | ||
336 | struct drm_map_list *r_list; | ||
337 | |||
338 | memset(dev_priv, 0, sizeof(drm_i830_private_t)); | ||
339 | |||
340 | list_for_each_entry(r_list, &dev->maplist, head) { | ||
341 | if (r_list->map && | ||
342 | r_list->map->type == _DRM_SHM && | ||
343 | r_list->map->flags & _DRM_CONTAINS_LOCK) { | ||
344 | dev_priv->sarea_map = r_list->map; | ||
345 | break; | ||
346 | } | ||
347 | } | ||
348 | |||
349 | if (!dev_priv->sarea_map) { | ||
350 | dev->dev_private = (void *)dev_priv; | ||
351 | i830_dma_cleanup(dev); | ||
352 | DRM_ERROR("can not find sarea!\n"); | ||
353 | return -EINVAL; | ||
354 | } | ||
355 | dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset); | ||
356 | if (!dev_priv->mmio_map) { | ||
357 | dev->dev_private = (void *)dev_priv; | ||
358 | i830_dma_cleanup(dev); | ||
359 | DRM_ERROR("can not find mmio map!\n"); | ||
360 | return -EINVAL; | ||
361 | } | ||
362 | dev->agp_buffer_token = init->buffers_offset; | ||
363 | dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); | ||
364 | if (!dev->agp_buffer_map) { | ||
365 | dev->dev_private = (void *)dev_priv; | ||
366 | i830_dma_cleanup(dev); | ||
367 | DRM_ERROR("can not find dma buffer map!\n"); | ||
368 | return -EINVAL; | ||
369 | } | ||
370 | |||
371 | dev_priv->sarea_priv = (drm_i830_sarea_t *) | ||
372 | ((u8 *) dev_priv->sarea_map->handle + init->sarea_priv_offset); | ||
373 | |||
374 | dev_priv->ring.Start = init->ring_start; | ||
375 | dev_priv->ring.End = init->ring_end; | ||
376 | dev_priv->ring.Size = init->ring_size; | ||
377 | |||
378 | dev_priv->ring.map.offset = dev->agp->base + init->ring_start; | ||
379 | dev_priv->ring.map.size = init->ring_size; | ||
380 | dev_priv->ring.map.type = _DRM_AGP; | ||
381 | dev_priv->ring.map.flags = 0; | ||
382 | dev_priv->ring.map.mtrr = 0; | ||
383 | |||
384 | drm_core_ioremap(&dev_priv->ring.map, dev); | ||
385 | |||
386 | if (dev_priv->ring.map.handle == NULL) { | ||
387 | dev->dev_private = (void *)dev_priv; | ||
388 | i830_dma_cleanup(dev); | ||
389 | DRM_ERROR("can not ioremap virtual address for" | ||
390 | " ring buffer\n"); | ||
391 | return -ENOMEM; | ||
392 | } | ||
393 | |||
394 | dev_priv->ring.virtual_start = dev_priv->ring.map.handle; | ||
395 | |||
396 | dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; | ||
397 | |||
398 | dev_priv->w = init->w; | ||
399 | dev_priv->h = init->h; | ||
400 | dev_priv->pitch = init->pitch; | ||
401 | dev_priv->back_offset = init->back_offset; | ||
402 | dev_priv->depth_offset = init->depth_offset; | ||
403 | dev_priv->front_offset = init->front_offset; | ||
404 | |||
405 | dev_priv->front_di1 = init->front_offset | init->pitch_bits; | ||
406 | dev_priv->back_di1 = init->back_offset | init->pitch_bits; | ||
407 | dev_priv->zi1 = init->depth_offset | init->pitch_bits; | ||
408 | |||
409 | DRM_DEBUG("front_di1 %x\n", dev_priv->front_di1); | ||
410 | DRM_DEBUG("back_offset %x\n", dev_priv->back_offset); | ||
411 | DRM_DEBUG("back_di1 %x\n", dev_priv->back_di1); | ||
412 | DRM_DEBUG("pitch_bits %x\n", init->pitch_bits); | ||
413 | |||
414 | dev_priv->cpp = init->cpp; | ||
415 | /* We are using separate values as placeholders for mechanisms for | ||
416 | * private backbuffer/depthbuffer usage. | ||
417 | */ | ||
418 | |||
419 | dev_priv->back_pitch = init->back_pitch; | ||
420 | dev_priv->depth_pitch = init->depth_pitch; | ||
421 | dev_priv->do_boxes = 0; | ||
422 | dev_priv->use_mi_batchbuffer_start = 0; | ||
423 | |||
424 | /* Program Hardware Status Page */ | ||
425 | dev_priv->hw_status_page = | ||
426 | pci_alloc_consistent(dev->pdev, PAGE_SIZE, | ||
427 | &dev_priv->dma_status_page); | ||
428 | if (!dev_priv->hw_status_page) { | ||
429 | dev->dev_private = (void *)dev_priv; | ||
430 | i830_dma_cleanup(dev); | ||
431 | DRM_ERROR("Can not allocate hardware status page\n"); | ||
432 | return -ENOMEM; | ||
433 | } | ||
434 | memset(dev_priv->hw_status_page, 0, PAGE_SIZE); | ||
435 | DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page); | ||
436 | |||
437 | I830_WRITE(0x02080, dev_priv->dma_status_page); | ||
438 | DRM_DEBUG("Enabled hardware status page\n"); | ||
439 | |||
440 | /* Now we need to init our freelist */ | ||
441 | if (i830_freelist_init(dev, dev_priv) != 0) { | ||
442 | dev->dev_private = (void *)dev_priv; | ||
443 | i830_dma_cleanup(dev); | ||
444 | DRM_ERROR("Not enough space in the status page for" | ||
445 | " the freelist\n"); | ||
446 | return -ENOMEM; | ||
447 | } | ||
448 | dev->dev_private = (void *)dev_priv; | ||
449 | |||
450 | return 0; | ||
451 | } | ||
452 | |||
453 | static int i830_dma_init(struct drm_device *dev, void *data, | ||
454 | struct drm_file *file_priv) | ||
455 | { | ||
456 | drm_i830_private_t *dev_priv; | ||
457 | drm_i830_init_t *init = data; | ||
458 | int retcode = 0; | ||
459 | |||
460 | switch (init->func) { | ||
461 | case I830_INIT_DMA: | ||
462 | dev_priv = kmalloc(sizeof(drm_i830_private_t), GFP_KERNEL); | ||
463 | if (dev_priv == NULL) | ||
464 | return -ENOMEM; | ||
465 | retcode = i830_dma_initialize(dev, dev_priv, init); | ||
466 | break; | ||
467 | case I830_CLEANUP_DMA: | ||
468 | retcode = i830_dma_cleanup(dev); | ||
469 | break; | ||
470 | default: | ||
471 | retcode = -EINVAL; | ||
472 | break; | ||
473 | } | ||
474 | |||
475 | return retcode; | ||
476 | } | ||
477 | |||
478 | #define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16)) | ||
479 | #define ST1_ENABLE (1<<16) | ||
480 | #define ST1_MASK (0xffff) | ||
481 | |||
482 | /* Most efficient way to verify state for the i830 is as it is | ||
483 | * emitted. Non-conformant state is silently dropped. | ||
484 | */ | ||
485 | static void i830EmitContextVerified(struct drm_device *dev, unsigned int *code) | ||
486 | { | ||
487 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
488 | int i, j = 0; | ||
489 | unsigned int tmp; | ||
490 | RING_LOCALS; | ||
491 | |||
492 | BEGIN_LP_RING(I830_CTX_SETUP_SIZE + 4); | ||
493 | |||
494 | for (i = 0; i < I830_CTXREG_BLENDCOLR0; i++) { | ||
495 | tmp = code[i]; | ||
496 | if ((tmp & (7 << 29)) == CMD_3D && | ||
497 | (tmp & (0x1f << 24)) < (0x1d << 24)) { | ||
498 | OUT_RING(tmp); | ||
499 | j++; | ||
500 | } else { | ||
501 | DRM_ERROR("Skipping %d\n", i); | ||
502 | } | ||
503 | } | ||
504 | |||
505 | OUT_RING(STATE3D_CONST_BLEND_COLOR_CMD); | ||
506 | OUT_RING(code[I830_CTXREG_BLENDCOLR]); | ||
507 | j += 2; | ||
508 | |||
509 | for (i = I830_CTXREG_VF; i < I830_CTXREG_MCSB0; i++) { | ||
510 | tmp = code[i]; | ||
511 | if ((tmp & (7 << 29)) == CMD_3D && | ||
512 | (tmp & (0x1f << 24)) < (0x1d << 24)) { | ||
513 | OUT_RING(tmp); | ||
514 | j++; | ||
515 | } else { | ||
516 | DRM_ERROR("Skipping %d\n", i); | ||
517 | } | ||
518 | } | ||
519 | |||
520 | OUT_RING(STATE3D_MAP_COORD_SETBIND_CMD); | ||
521 | OUT_RING(code[I830_CTXREG_MCSB1]); | ||
522 | j += 2; | ||
523 | |||
524 | if (j & 1) | ||
525 | OUT_RING(0); | ||
526 | |||
527 | ADVANCE_LP_RING(); | ||
528 | } | ||
529 | |||
530 | static void i830EmitTexVerified(struct drm_device *dev, unsigned int *code) | ||
531 | { | ||
532 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
533 | int i, j = 0; | ||
534 | unsigned int tmp; | ||
535 | RING_LOCALS; | ||
536 | |||
537 | if (code[I830_TEXREG_MI0] == GFX_OP_MAP_INFO || | ||
538 | (code[I830_TEXREG_MI0] & ~(0xf * LOAD_TEXTURE_MAP0)) == | ||
539 | (STATE3D_LOAD_STATE_IMMEDIATE_2 | 4)) { | ||
540 | |||
541 | BEGIN_LP_RING(I830_TEX_SETUP_SIZE); | ||
542 | |||
543 | OUT_RING(code[I830_TEXREG_MI0]); /* TM0LI */ | ||
544 | OUT_RING(code[I830_TEXREG_MI1]); /* TM0S0 */ | ||
545 | OUT_RING(code[I830_TEXREG_MI2]); /* TM0S1 */ | ||
546 | OUT_RING(code[I830_TEXREG_MI3]); /* TM0S2 */ | ||
547 | OUT_RING(code[I830_TEXREG_MI4]); /* TM0S3 */ | ||
548 | OUT_RING(code[I830_TEXREG_MI5]); /* TM0S4 */ | ||
549 | |||
550 | for (i = 6; i < I830_TEX_SETUP_SIZE; i++) { | ||
551 | tmp = code[i]; | ||
552 | OUT_RING(tmp); | ||
553 | j++; | ||
554 | } | ||
555 | |||
556 | if (j & 1) | ||
557 | OUT_RING(0); | ||
558 | |||
559 | ADVANCE_LP_RING(); | ||
560 | } else | ||
561 | printk("rejected packet %x\n", code[0]); | ||
562 | } | ||
563 | |||
564 | static void i830EmitTexBlendVerified(struct drm_device *dev, | ||
565 | unsigned int *code, unsigned int num) | ||
566 | { | ||
567 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
568 | int i, j = 0; | ||
569 | unsigned int tmp; | ||
570 | RING_LOCALS; | ||
571 | |||
572 | if (!num) | ||
573 | return; | ||
574 | |||
575 | BEGIN_LP_RING(num + 1); | ||
576 | |||
577 | for (i = 0; i < num; i++) { | ||
578 | tmp = code[i]; | ||
579 | OUT_RING(tmp); | ||
580 | j++; | ||
581 | } | ||
582 | |||
583 | if (j & 1) | ||
584 | OUT_RING(0); | ||
585 | |||
586 | ADVANCE_LP_RING(); | ||
587 | } | ||
588 | |||
589 | static void i830EmitTexPalette(struct drm_device *dev, | ||
590 | unsigned int *palette, int number, int is_shared) | ||
591 | { | ||
592 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
593 | int i; | ||
594 | RING_LOCALS; | ||
595 | |||
596 | return; | ||
597 | |||
598 | BEGIN_LP_RING(258); | ||
599 | |||
600 | if (is_shared == 1) { | ||
601 | OUT_RING(CMD_OP_MAP_PALETTE_LOAD | | ||
602 | MAP_PALETTE_NUM(0) | MAP_PALETTE_BOTH); | ||
603 | } else { | ||
604 | OUT_RING(CMD_OP_MAP_PALETTE_LOAD | MAP_PALETTE_NUM(number)); | ||
605 | } | ||
606 | for (i = 0; i < 256; i++) | ||
607 | OUT_RING(palette[i]); | ||
608 | OUT_RING(0); | ||
609 | /* KW: WHERE IS THE ADVANCE_LP_RING? This is effectively a noop! | ||
610 | */ | ||
611 | } | ||
612 | |||
613 | /* Need to do some additional checking when setting the dest buffer. | ||
614 | */ | ||
615 | static void i830EmitDestVerified(struct drm_device *dev, unsigned int *code) | ||
616 | { | ||
617 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
618 | unsigned int tmp; | ||
619 | RING_LOCALS; | ||
620 | |||
621 | BEGIN_LP_RING(I830_DEST_SETUP_SIZE + 10); | ||
622 | |||
623 | tmp = code[I830_DESTREG_CBUFADDR]; | ||
624 | if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) { | ||
625 | if (((int)outring) & 8) { | ||
626 | OUT_RING(0); | ||
627 | OUT_RING(0); | ||
628 | } | ||
629 | |||
630 | OUT_RING(CMD_OP_DESTBUFFER_INFO); | ||
631 | OUT_RING(BUF_3D_ID_COLOR_BACK | | ||
632 | BUF_3D_PITCH(dev_priv->back_pitch * dev_priv->cpp) | | ||
633 | BUF_3D_USE_FENCE); | ||
634 | OUT_RING(tmp); | ||
635 | OUT_RING(0); | ||
636 | |||
637 | OUT_RING(CMD_OP_DESTBUFFER_INFO); | ||
638 | OUT_RING(BUF_3D_ID_DEPTH | BUF_3D_USE_FENCE | | ||
639 | BUF_3D_PITCH(dev_priv->depth_pitch * dev_priv->cpp)); | ||
640 | OUT_RING(dev_priv->zi1); | ||
641 | OUT_RING(0); | ||
642 | } else { | ||
643 | DRM_ERROR("bad di1 %x (allow %x or %x)\n", | ||
644 | tmp, dev_priv->front_di1, dev_priv->back_di1); | ||
645 | } | ||
646 | |||
647 | /* invarient: | ||
648 | */ | ||
649 | |||
650 | OUT_RING(GFX_OP_DESTBUFFER_VARS); | ||
651 | OUT_RING(code[I830_DESTREG_DV1]); | ||
652 | |||
653 | OUT_RING(GFX_OP_DRAWRECT_INFO); | ||
654 | OUT_RING(code[I830_DESTREG_DR1]); | ||
655 | OUT_RING(code[I830_DESTREG_DR2]); | ||
656 | OUT_RING(code[I830_DESTREG_DR3]); | ||
657 | OUT_RING(code[I830_DESTREG_DR4]); | ||
658 | |||
659 | /* Need to verify this */ | ||
660 | tmp = code[I830_DESTREG_SENABLE]; | ||
661 | if ((tmp & ~0x3) == GFX_OP_SCISSOR_ENABLE) { | ||
662 | OUT_RING(tmp); | ||
663 | } else { | ||
664 | DRM_ERROR("bad scissor enable\n"); | ||
665 | OUT_RING(0); | ||
666 | } | ||
667 | |||
668 | OUT_RING(GFX_OP_SCISSOR_RECT); | ||
669 | OUT_RING(code[I830_DESTREG_SR1]); | ||
670 | OUT_RING(code[I830_DESTREG_SR2]); | ||
671 | OUT_RING(0); | ||
672 | |||
673 | ADVANCE_LP_RING(); | ||
674 | } | ||
675 | |||
676 | static void i830EmitStippleVerified(struct drm_device *dev, unsigned int *code) | ||
677 | { | ||
678 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
679 | RING_LOCALS; | ||
680 | |||
681 | BEGIN_LP_RING(2); | ||
682 | OUT_RING(GFX_OP_STIPPLE); | ||
683 | OUT_RING(code[1]); | ||
684 | ADVANCE_LP_RING(); | ||
685 | } | ||
686 | |||
687 | static void i830EmitState(struct drm_device *dev) | ||
688 | { | ||
689 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
690 | drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
691 | unsigned int dirty = sarea_priv->dirty; | ||
692 | |||
693 | DRM_DEBUG("%s %x\n", __func__, dirty); | ||
694 | |||
695 | if (dirty & I830_UPLOAD_BUFFERS) { | ||
696 | i830EmitDestVerified(dev, sarea_priv->BufferState); | ||
697 | sarea_priv->dirty &= ~I830_UPLOAD_BUFFERS; | ||
698 | } | ||
699 | |||
700 | if (dirty & I830_UPLOAD_CTX) { | ||
701 | i830EmitContextVerified(dev, sarea_priv->ContextState); | ||
702 | sarea_priv->dirty &= ~I830_UPLOAD_CTX; | ||
703 | } | ||
704 | |||
705 | if (dirty & I830_UPLOAD_TEX0) { | ||
706 | i830EmitTexVerified(dev, sarea_priv->TexState[0]); | ||
707 | sarea_priv->dirty &= ~I830_UPLOAD_TEX0; | ||
708 | } | ||
709 | |||
710 | if (dirty & I830_UPLOAD_TEX1) { | ||
711 | i830EmitTexVerified(dev, sarea_priv->TexState[1]); | ||
712 | sarea_priv->dirty &= ~I830_UPLOAD_TEX1; | ||
713 | } | ||
714 | |||
715 | if (dirty & I830_UPLOAD_TEXBLEND0) { | ||
716 | i830EmitTexBlendVerified(dev, sarea_priv->TexBlendState[0], | ||
717 | sarea_priv->TexBlendStateWordsUsed[0]); | ||
718 | sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND0; | ||
719 | } | ||
720 | |||
721 | if (dirty & I830_UPLOAD_TEXBLEND1) { | ||
722 | i830EmitTexBlendVerified(dev, sarea_priv->TexBlendState[1], | ||
723 | sarea_priv->TexBlendStateWordsUsed[1]); | ||
724 | sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND1; | ||
725 | } | ||
726 | |||
727 | if (dirty & I830_UPLOAD_TEX_PALETTE_SHARED) { | ||
728 | i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 1); | ||
729 | } else { | ||
730 | if (dirty & I830_UPLOAD_TEX_PALETTE_N(0)) { | ||
731 | i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 0); | ||
732 | sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(0); | ||
733 | } | ||
734 | if (dirty & I830_UPLOAD_TEX_PALETTE_N(1)) { | ||
735 | i830EmitTexPalette(dev, sarea_priv->Palette[1], 1, 0); | ||
736 | sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(1); | ||
737 | } | ||
738 | |||
739 | /* 1.3: | ||
740 | */ | ||
741 | #if 0 | ||
742 | if (dirty & I830_UPLOAD_TEX_PALETTE_N(2)) { | ||
743 | i830EmitTexPalette(dev, sarea_priv->Palette2[0], 0, 0); | ||
744 | sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(2); | ||
745 | } | ||
746 | if (dirty & I830_UPLOAD_TEX_PALETTE_N(3)) { | ||
747 | i830EmitTexPalette(dev, sarea_priv->Palette2[1], 1, 0); | ||
748 | sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(2); | ||
749 | } | ||
750 | #endif | ||
751 | } | ||
752 | |||
753 | /* 1.3: | ||
754 | */ | ||
755 | if (dirty & I830_UPLOAD_STIPPLE) { | ||
756 | i830EmitStippleVerified(dev, sarea_priv->StippleState); | ||
757 | sarea_priv->dirty &= ~I830_UPLOAD_STIPPLE; | ||
758 | } | ||
759 | |||
760 | if (dirty & I830_UPLOAD_TEX2) { | ||
761 | i830EmitTexVerified(dev, sarea_priv->TexState2); | ||
762 | sarea_priv->dirty &= ~I830_UPLOAD_TEX2; | ||
763 | } | ||
764 | |||
765 | if (dirty & I830_UPLOAD_TEX3) { | ||
766 | i830EmitTexVerified(dev, sarea_priv->TexState3); | ||
767 | sarea_priv->dirty &= ~I830_UPLOAD_TEX3; | ||
768 | } | ||
769 | |||
770 | if (dirty & I830_UPLOAD_TEXBLEND2) { | ||
771 | i830EmitTexBlendVerified(dev, | ||
772 | sarea_priv->TexBlendState2, | ||
773 | sarea_priv->TexBlendStateWordsUsed2); | ||
774 | |||
775 | sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND2; | ||
776 | } | ||
777 | |||
778 | if (dirty & I830_UPLOAD_TEXBLEND3) { | ||
779 | i830EmitTexBlendVerified(dev, | ||
780 | sarea_priv->TexBlendState3, | ||
781 | sarea_priv->TexBlendStateWordsUsed3); | ||
782 | sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND3; | ||
783 | } | ||
784 | } | ||
785 | |||
786 | /* ================================================================ | ||
787 | * Performance monitoring functions | ||
788 | */ | ||
789 | |||
790 | static void i830_fill_box(struct drm_device *dev, | ||
791 | int x, int y, int w, int h, int r, int g, int b) | ||
792 | { | ||
793 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
794 | u32 color; | ||
795 | unsigned int BR13, CMD; | ||
796 | RING_LOCALS; | ||
797 | |||
798 | BR13 = (0xF0 << 16) | (dev_priv->pitch * dev_priv->cpp) | (1 << 24); | ||
799 | CMD = XY_COLOR_BLT_CMD; | ||
800 | x += dev_priv->sarea_priv->boxes[0].x1; | ||
801 | y += dev_priv->sarea_priv->boxes[0].y1; | ||
802 | |||
803 | if (dev_priv->cpp == 4) { | ||
804 | BR13 |= (1 << 25); | ||
805 | CMD |= (XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB); | ||
806 | color = (((0xff) << 24) | (r << 16) | (g << 8) | b); | ||
807 | } else { | ||
808 | color = (((r & 0xf8) << 8) | | ||
809 | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3)); | ||
810 | } | ||
811 | |||
812 | BEGIN_LP_RING(6); | ||
813 | OUT_RING(CMD); | ||
814 | OUT_RING(BR13); | ||
815 | OUT_RING((y << 16) | x); | ||
816 | OUT_RING(((y + h) << 16) | (x + w)); | ||
817 | |||
818 | if (dev_priv->current_page == 1) | ||
819 | OUT_RING(dev_priv->front_offset); | ||
820 | else | ||
821 | OUT_RING(dev_priv->back_offset); | ||
822 | |||
823 | OUT_RING(color); | ||
824 | ADVANCE_LP_RING(); | ||
825 | } | ||
826 | |||
827 | static void i830_cp_performance_boxes(struct drm_device *dev) | ||
828 | { | ||
829 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
830 | |||
831 | /* Purple box for page flipping | ||
832 | */ | ||
833 | if (dev_priv->sarea_priv->perf_boxes & I830_BOX_FLIP) | ||
834 | i830_fill_box(dev, 4, 4, 8, 8, 255, 0, 255); | ||
835 | |||
836 | /* Red box if we have to wait for idle at any point | ||
837 | */ | ||
838 | if (dev_priv->sarea_priv->perf_boxes & I830_BOX_WAIT) | ||
839 | i830_fill_box(dev, 16, 4, 8, 8, 255, 0, 0); | ||
840 | |||
841 | /* Blue box: lost context? | ||
842 | */ | ||
843 | if (dev_priv->sarea_priv->perf_boxes & I830_BOX_LOST_CONTEXT) | ||
844 | i830_fill_box(dev, 28, 4, 8, 8, 0, 0, 255); | ||
845 | |||
846 | /* Yellow box for texture swaps | ||
847 | */ | ||
848 | if (dev_priv->sarea_priv->perf_boxes & I830_BOX_TEXTURE_LOAD) | ||
849 | i830_fill_box(dev, 40, 4, 8, 8, 255, 255, 0); | ||
850 | |||
851 | /* Green box if hardware never idles (as far as we can tell) | ||
852 | */ | ||
853 | if (!(dev_priv->sarea_priv->perf_boxes & I830_BOX_RING_EMPTY)) | ||
854 | i830_fill_box(dev, 64, 4, 8, 8, 0, 255, 0); | ||
855 | |||
856 | /* Draw bars indicating number of buffers allocated | ||
857 | * (not a great measure, easily confused) | ||
858 | */ | ||
859 | if (dev_priv->dma_used) { | ||
860 | int bar = dev_priv->dma_used / 10240; | ||
861 | if (bar > 100) | ||
862 | bar = 100; | ||
863 | if (bar < 1) | ||
864 | bar = 1; | ||
865 | i830_fill_box(dev, 4, 16, bar, 4, 196, 128, 128); | ||
866 | dev_priv->dma_used = 0; | ||
867 | } | ||
868 | |||
869 | dev_priv->sarea_priv->perf_boxes = 0; | ||
870 | } | ||
871 | |||
872 | static void i830_dma_dispatch_clear(struct drm_device *dev, int flags, | ||
873 | unsigned int clear_color, | ||
874 | unsigned int clear_zval, | ||
875 | unsigned int clear_depthmask) | ||
876 | { | ||
877 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
878 | drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
879 | int nbox = sarea_priv->nbox; | ||
880 | struct drm_clip_rect *pbox = sarea_priv->boxes; | ||
881 | int pitch = dev_priv->pitch; | ||
882 | int cpp = dev_priv->cpp; | ||
883 | int i; | ||
884 | unsigned int BR13, CMD, D_CMD; | ||
885 | RING_LOCALS; | ||
886 | |||
887 | if (dev_priv->current_page == 1) { | ||
888 | unsigned int tmp = flags; | ||
889 | |||
890 | flags &= ~(I830_FRONT | I830_BACK); | ||
891 | if (tmp & I830_FRONT) | ||
892 | flags |= I830_BACK; | ||
893 | if (tmp & I830_BACK) | ||
894 | flags |= I830_FRONT; | ||
895 | } | ||
896 | |||
897 | i830_kernel_lost_context(dev); | ||
898 | |||
899 | switch (cpp) { | ||
900 | case 2: | ||
901 | BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24); | ||
902 | D_CMD = CMD = XY_COLOR_BLT_CMD; | ||
903 | break; | ||
904 | case 4: | ||
905 | BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24) | (1 << 25); | ||
906 | CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA | | ||
907 | XY_COLOR_BLT_WRITE_RGB); | ||
908 | D_CMD = XY_COLOR_BLT_CMD; | ||
909 | if (clear_depthmask & 0x00ffffff) | ||
910 | D_CMD |= XY_COLOR_BLT_WRITE_RGB; | ||
911 | if (clear_depthmask & 0xff000000) | ||
912 | D_CMD |= XY_COLOR_BLT_WRITE_ALPHA; | ||
913 | break; | ||
914 | default: | ||
915 | BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24); | ||
916 | D_CMD = CMD = XY_COLOR_BLT_CMD; | ||
917 | break; | ||
918 | } | ||
919 | |||
920 | if (nbox > I830_NR_SAREA_CLIPRECTS) | ||
921 | nbox = I830_NR_SAREA_CLIPRECTS; | ||
922 | |||
923 | for (i = 0; i < nbox; i++, pbox++) { | ||
924 | if (pbox->x1 > pbox->x2 || | ||
925 | pbox->y1 > pbox->y2 || | ||
926 | pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h) | ||
927 | continue; | ||
928 | |||
929 | if (flags & I830_FRONT) { | ||
930 | DRM_DEBUG("clear front\n"); | ||
931 | BEGIN_LP_RING(6); | ||
932 | OUT_RING(CMD); | ||
933 | OUT_RING(BR13); | ||
934 | OUT_RING((pbox->y1 << 16) | pbox->x1); | ||
935 | OUT_RING((pbox->y2 << 16) | pbox->x2); | ||
936 | OUT_RING(dev_priv->front_offset); | ||
937 | OUT_RING(clear_color); | ||
938 | ADVANCE_LP_RING(); | ||
939 | } | ||
940 | |||
941 | if (flags & I830_BACK) { | ||
942 | DRM_DEBUG("clear back\n"); | ||
943 | BEGIN_LP_RING(6); | ||
944 | OUT_RING(CMD); | ||
945 | OUT_RING(BR13); | ||
946 | OUT_RING((pbox->y1 << 16) | pbox->x1); | ||
947 | OUT_RING((pbox->y2 << 16) | pbox->x2); | ||
948 | OUT_RING(dev_priv->back_offset); | ||
949 | OUT_RING(clear_color); | ||
950 | ADVANCE_LP_RING(); | ||
951 | } | ||
952 | |||
953 | if (flags & I830_DEPTH) { | ||
954 | DRM_DEBUG("clear depth\n"); | ||
955 | BEGIN_LP_RING(6); | ||
956 | OUT_RING(D_CMD); | ||
957 | OUT_RING(BR13); | ||
958 | OUT_RING((pbox->y1 << 16) | pbox->x1); | ||
959 | OUT_RING((pbox->y2 << 16) | pbox->x2); | ||
960 | OUT_RING(dev_priv->depth_offset); | ||
961 | OUT_RING(clear_zval); | ||
962 | ADVANCE_LP_RING(); | ||
963 | } | ||
964 | } | ||
965 | } | ||
966 | |||
967 | static void i830_dma_dispatch_swap(struct drm_device *dev) | ||
968 | { | ||
969 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
970 | drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
971 | int nbox = sarea_priv->nbox; | ||
972 | struct drm_clip_rect *pbox = sarea_priv->boxes; | ||
973 | int pitch = dev_priv->pitch; | ||
974 | int cpp = dev_priv->cpp; | ||
975 | int i; | ||
976 | unsigned int CMD, BR13; | ||
977 | RING_LOCALS; | ||
978 | |||
979 | DRM_DEBUG("swapbuffers\n"); | ||
980 | |||
981 | i830_kernel_lost_context(dev); | ||
982 | |||
983 | if (dev_priv->do_boxes) | ||
984 | i830_cp_performance_boxes(dev); | ||
985 | |||
986 | switch (cpp) { | ||
987 | case 2: | ||
988 | BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24); | ||
989 | CMD = XY_SRC_COPY_BLT_CMD; | ||
990 | break; | ||
991 | case 4: | ||
992 | BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24) | (1 << 25); | ||
993 | CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | | ||
994 | XY_SRC_COPY_BLT_WRITE_RGB); | ||
995 | break; | ||
996 | default: | ||
997 | BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24); | ||
998 | CMD = XY_SRC_COPY_BLT_CMD; | ||
999 | break; | ||
1000 | } | ||
1001 | |||
1002 | if (nbox > I830_NR_SAREA_CLIPRECTS) | ||
1003 | nbox = I830_NR_SAREA_CLIPRECTS; | ||
1004 | |||
1005 | for (i = 0; i < nbox; i++, pbox++) { | ||
1006 | if (pbox->x1 > pbox->x2 || | ||
1007 | pbox->y1 > pbox->y2 || | ||
1008 | pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h) | ||
1009 | continue; | ||
1010 | |||
1011 | DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n", | ||
1012 | pbox->x1, pbox->y1, pbox->x2, pbox->y2); | ||
1013 | |||
1014 | BEGIN_LP_RING(8); | ||
1015 | OUT_RING(CMD); | ||
1016 | OUT_RING(BR13); | ||
1017 | OUT_RING((pbox->y1 << 16) | pbox->x1); | ||
1018 | OUT_RING((pbox->y2 << 16) | pbox->x2); | ||
1019 | |||
1020 | if (dev_priv->current_page == 0) | ||
1021 | OUT_RING(dev_priv->front_offset); | ||
1022 | else | ||
1023 | OUT_RING(dev_priv->back_offset); | ||
1024 | |||
1025 | OUT_RING((pbox->y1 << 16) | pbox->x1); | ||
1026 | OUT_RING(BR13 & 0xffff); | ||
1027 | |||
1028 | if (dev_priv->current_page == 0) | ||
1029 | OUT_RING(dev_priv->back_offset); | ||
1030 | else | ||
1031 | OUT_RING(dev_priv->front_offset); | ||
1032 | |||
1033 | ADVANCE_LP_RING(); | ||
1034 | } | ||
1035 | } | ||
1036 | |||
1037 | static void i830_dma_dispatch_flip(struct drm_device *dev) | ||
1038 | { | ||
1039 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
1040 | RING_LOCALS; | ||
1041 | |||
1042 | DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n", | ||
1043 | __func__, | ||
1044 | dev_priv->current_page, | ||
1045 | dev_priv->sarea_priv->pf_current_page); | ||
1046 | |||
1047 | i830_kernel_lost_context(dev); | ||
1048 | |||
1049 | if (dev_priv->do_boxes) { | ||
1050 | dev_priv->sarea_priv->perf_boxes |= I830_BOX_FLIP; | ||
1051 | i830_cp_performance_boxes(dev); | ||
1052 | } | ||
1053 | |||
1054 | BEGIN_LP_RING(2); | ||
1055 | OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE); | ||
1056 | OUT_RING(0); | ||
1057 | ADVANCE_LP_RING(); | ||
1058 | |||
1059 | BEGIN_LP_RING(6); | ||
1060 | OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP); | ||
1061 | OUT_RING(0); | ||
1062 | if (dev_priv->current_page == 0) { | ||
1063 | OUT_RING(dev_priv->back_offset); | ||
1064 | dev_priv->current_page = 1; | ||
1065 | } else { | ||
1066 | OUT_RING(dev_priv->front_offset); | ||
1067 | dev_priv->current_page = 0; | ||
1068 | } | ||
1069 | OUT_RING(0); | ||
1070 | ADVANCE_LP_RING(); | ||
1071 | |||
1072 | BEGIN_LP_RING(2); | ||
1073 | OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP); | ||
1074 | OUT_RING(0); | ||
1075 | ADVANCE_LP_RING(); | ||
1076 | |||
1077 | dev_priv->sarea_priv->pf_current_page = dev_priv->current_page; | ||
1078 | } | ||
1079 | |||
1080 | static void i830_dma_dispatch_vertex(struct drm_device *dev, | ||
1081 | struct drm_buf *buf, int discard, int used) | ||
1082 | { | ||
1083 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
1084 | drm_i830_buf_priv_t *buf_priv = buf->dev_private; | ||
1085 | drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
1086 | struct drm_clip_rect *box = sarea_priv->boxes; | ||
1087 | int nbox = sarea_priv->nbox; | ||
1088 | unsigned long address = (unsigned long)buf->bus_address; | ||
1089 | unsigned long start = address - dev->agp->base; | ||
1090 | int i = 0, u; | ||
1091 | RING_LOCALS; | ||
1092 | |||
1093 | i830_kernel_lost_context(dev); | ||
1094 | |||
1095 | if (nbox > I830_NR_SAREA_CLIPRECTS) | ||
1096 | nbox = I830_NR_SAREA_CLIPRECTS; | ||
1097 | |||
1098 | if (discard) { | ||
1099 | u = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, | ||
1100 | I830_BUF_HARDWARE); | ||
1101 | if (u != I830_BUF_CLIENT) | ||
1102 | DRM_DEBUG("xxxx 2\n"); | ||
1103 | } | ||
1104 | |||
1105 | if (used > 4 * 1023) | ||
1106 | used = 0; | ||
1107 | |||
1108 | if (sarea_priv->dirty) | ||
1109 | i830EmitState(dev); | ||
1110 | |||
1111 | DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n", | ||
1112 | address, used, nbox); | ||
1113 | |||
1114 | dev_priv->counter++; | ||
1115 | DRM_DEBUG("dispatch counter : %ld\n", dev_priv->counter); | ||
1116 | DRM_DEBUG("i830_dma_dispatch\n"); | ||
1117 | DRM_DEBUG("start : %lx\n", start); | ||
1118 | DRM_DEBUG("used : %d\n", used); | ||
1119 | DRM_DEBUG("start + used - 4 : %ld\n", start + used - 4); | ||
1120 | |||
1121 | if (buf_priv->currently_mapped == I830_BUF_MAPPED) { | ||
1122 | u32 *vp = buf_priv->kernel_virtual; | ||
1123 | |||
1124 | vp[0] = (GFX_OP_PRIMITIVE | | ||
1125 | sarea_priv->vertex_prim | ((used / 4) - 2)); | ||
1126 | |||
1127 | if (dev_priv->use_mi_batchbuffer_start) { | ||
1128 | vp[used / 4] = MI_BATCH_BUFFER_END; | ||
1129 | used += 4; | ||
1130 | } | ||
1131 | |||
1132 | if (used & 4) { | ||
1133 | vp[used / 4] = 0; | ||
1134 | used += 4; | ||
1135 | } | ||
1136 | |||
1137 | i830_unmap_buffer(buf); | ||
1138 | } | ||
1139 | |||
1140 | if (used) { | ||
1141 | do { | ||
1142 | if (i < nbox) { | ||
1143 | BEGIN_LP_RING(6); | ||
1144 | OUT_RING(GFX_OP_DRAWRECT_INFO); | ||
1145 | OUT_RING(sarea_priv-> | ||
1146 | BufferState[I830_DESTREG_DR1]); | ||
1147 | OUT_RING(box[i].x1 | (box[i].y1 << 16)); | ||
1148 | OUT_RING(box[i].x2 | (box[i].y2 << 16)); | ||
1149 | OUT_RING(sarea_priv-> | ||
1150 | BufferState[I830_DESTREG_DR4]); | ||
1151 | OUT_RING(0); | ||
1152 | ADVANCE_LP_RING(); | ||
1153 | } | ||
1154 | |||
1155 | if (dev_priv->use_mi_batchbuffer_start) { | ||
1156 | BEGIN_LP_RING(2); | ||
1157 | OUT_RING(MI_BATCH_BUFFER_START | (2 << 6)); | ||
1158 | OUT_RING(start | MI_BATCH_NON_SECURE); | ||
1159 | ADVANCE_LP_RING(); | ||
1160 | } else { | ||
1161 | BEGIN_LP_RING(4); | ||
1162 | OUT_RING(MI_BATCH_BUFFER); | ||
1163 | OUT_RING(start | MI_BATCH_NON_SECURE); | ||
1164 | OUT_RING(start + used - 4); | ||
1165 | OUT_RING(0); | ||
1166 | ADVANCE_LP_RING(); | ||
1167 | } | ||
1168 | |||
1169 | } while (++i < nbox); | ||
1170 | } | ||
1171 | |||
1172 | if (discard) { | ||
1173 | dev_priv->counter++; | ||
1174 | |||
1175 | (void)cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, | ||
1176 | I830_BUF_HARDWARE); | ||
1177 | |||
1178 | BEGIN_LP_RING(8); | ||
1179 | OUT_RING(CMD_STORE_DWORD_IDX); | ||
1180 | OUT_RING(20); | ||
1181 | OUT_RING(dev_priv->counter); | ||
1182 | OUT_RING(CMD_STORE_DWORD_IDX); | ||
1183 | OUT_RING(buf_priv->my_use_idx); | ||
1184 | OUT_RING(I830_BUF_FREE); | ||
1185 | OUT_RING(CMD_REPORT_HEAD); | ||
1186 | OUT_RING(0); | ||
1187 | ADVANCE_LP_RING(); | ||
1188 | } | ||
1189 | } | ||
1190 | |||
1191 | static void i830_dma_quiescent(struct drm_device *dev) | ||
1192 | { | ||
1193 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
1194 | RING_LOCALS; | ||
1195 | |||
1196 | i830_kernel_lost_context(dev); | ||
1197 | |||
1198 | BEGIN_LP_RING(4); | ||
1199 | OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE); | ||
1200 | OUT_RING(CMD_REPORT_HEAD); | ||
1201 | OUT_RING(0); | ||
1202 | OUT_RING(0); | ||
1203 | ADVANCE_LP_RING(); | ||
1204 | |||
1205 | i830_wait_ring(dev, dev_priv->ring.Size - 8, __func__); | ||
1206 | } | ||
1207 | |||
1208 | static int i830_flush_queue(struct drm_device *dev) | ||
1209 | { | ||
1210 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
1211 | struct drm_device_dma *dma = dev->dma; | ||
1212 | int i, ret = 0; | ||
1213 | RING_LOCALS; | ||
1214 | |||
1215 | i830_kernel_lost_context(dev); | ||
1216 | |||
1217 | BEGIN_LP_RING(2); | ||
1218 | OUT_RING(CMD_REPORT_HEAD); | ||
1219 | OUT_RING(0); | ||
1220 | ADVANCE_LP_RING(); | ||
1221 | |||
1222 | i830_wait_ring(dev, dev_priv->ring.Size - 8, __func__); | ||
1223 | |||
1224 | for (i = 0; i < dma->buf_count; i++) { | ||
1225 | struct drm_buf *buf = dma->buflist[i]; | ||
1226 | drm_i830_buf_priv_t *buf_priv = buf->dev_private; | ||
1227 | |||
1228 | int used = cmpxchg(buf_priv->in_use, I830_BUF_HARDWARE, | ||
1229 | I830_BUF_FREE); | ||
1230 | |||
1231 | if (used == I830_BUF_HARDWARE) | ||
1232 | DRM_DEBUG("reclaimed from HARDWARE\n"); | ||
1233 | if (used == I830_BUF_CLIENT) | ||
1234 | DRM_DEBUG("still on client\n"); | ||
1235 | } | ||
1236 | |||
1237 | return ret; | ||
1238 | } | ||
1239 | |||
1240 | /* Must be called with the lock held */ | ||
1241 | static void i830_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv) | ||
1242 | { | ||
1243 | struct drm_device_dma *dma = dev->dma; | ||
1244 | int i; | ||
1245 | |||
1246 | if (!dma) | ||
1247 | return; | ||
1248 | if (!dev->dev_private) | ||
1249 | return; | ||
1250 | if (!dma->buflist) | ||
1251 | return; | ||
1252 | |||
1253 | i830_flush_queue(dev); | ||
1254 | |||
1255 | for (i = 0; i < dma->buf_count; i++) { | ||
1256 | struct drm_buf *buf = dma->buflist[i]; | ||
1257 | drm_i830_buf_priv_t *buf_priv = buf->dev_private; | ||
1258 | |||
1259 | if (buf->file_priv == file_priv && buf_priv) { | ||
1260 | int used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, | ||
1261 | I830_BUF_FREE); | ||
1262 | |||
1263 | if (used == I830_BUF_CLIENT) | ||
1264 | DRM_DEBUG("reclaimed from client\n"); | ||
1265 | if (buf_priv->currently_mapped == I830_BUF_MAPPED) | ||
1266 | buf_priv->currently_mapped = I830_BUF_UNMAPPED; | ||
1267 | } | ||
1268 | } | ||
1269 | } | ||
1270 | |||
1271 | static int i830_flush_ioctl(struct drm_device *dev, void *data, | ||
1272 | struct drm_file *file_priv) | ||
1273 | { | ||
1274 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
1275 | |||
1276 | i830_flush_queue(dev); | ||
1277 | return 0; | ||
1278 | } | ||
1279 | |||
1280 | static int i830_dma_vertex(struct drm_device *dev, void *data, | ||
1281 | struct drm_file *file_priv) | ||
1282 | { | ||
1283 | struct drm_device_dma *dma = dev->dma; | ||
1284 | drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private; | ||
1285 | u32 *hw_status = dev_priv->hw_status_page; | ||
1286 | drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) | ||
1287 | dev_priv->sarea_priv; | ||
1288 | drm_i830_vertex_t *vertex = data; | ||
1289 | |||
1290 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
1291 | |||
1292 | DRM_DEBUG("i830 dma vertex, idx %d used %d discard %d\n", | ||
1293 | vertex->idx, vertex->used, vertex->discard); | ||
1294 | |||
1295 | if (vertex->idx < 0 || vertex->idx > dma->buf_count) | ||
1296 | return -EINVAL; | ||
1297 | |||
1298 | i830_dma_dispatch_vertex(dev, | ||
1299 | dma->buflist[vertex->idx], | ||
1300 | vertex->discard, vertex->used); | ||
1301 | |||
1302 | sarea_priv->last_enqueue = dev_priv->counter - 1; | ||
1303 | sarea_priv->last_dispatch = (int)hw_status[5]; | ||
1304 | |||
1305 | return 0; | ||
1306 | } | ||
1307 | |||
1308 | static int i830_clear_bufs(struct drm_device *dev, void *data, | ||
1309 | struct drm_file *file_priv) | ||
1310 | { | ||
1311 | drm_i830_clear_t *clear = data; | ||
1312 | |||
1313 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
1314 | |||
1315 | /* GH: Someone's doing nasty things... */ | ||
1316 | if (!dev->dev_private) | ||
1317 | return -EINVAL; | ||
1318 | |||
1319 | i830_dma_dispatch_clear(dev, clear->flags, | ||
1320 | clear->clear_color, | ||
1321 | clear->clear_depth, clear->clear_depthmask); | ||
1322 | return 0; | ||
1323 | } | ||
1324 | |||
1325 | static int i830_swap_bufs(struct drm_device *dev, void *data, | ||
1326 | struct drm_file *file_priv) | ||
1327 | { | ||
1328 | DRM_DEBUG("i830_swap_bufs\n"); | ||
1329 | |||
1330 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
1331 | |||
1332 | i830_dma_dispatch_swap(dev); | ||
1333 | return 0; | ||
1334 | } | ||
1335 | |||
1336 | /* Not sure why this isn't set all the time: | ||
1337 | */ | ||
1338 | static void i830_do_init_pageflip(struct drm_device *dev) | ||
1339 | { | ||
1340 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
1341 | |||
1342 | DRM_DEBUG("%s\n", __func__); | ||
1343 | dev_priv->page_flipping = 1; | ||
1344 | dev_priv->current_page = 0; | ||
1345 | dev_priv->sarea_priv->pf_current_page = dev_priv->current_page; | ||
1346 | } | ||
1347 | |||
1348 | static int i830_do_cleanup_pageflip(struct drm_device *dev) | ||
1349 | { | ||
1350 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
1351 | |||
1352 | DRM_DEBUG("%s\n", __func__); | ||
1353 | if (dev_priv->current_page != 0) | ||
1354 | i830_dma_dispatch_flip(dev); | ||
1355 | |||
1356 | dev_priv->page_flipping = 0; | ||
1357 | return 0; | ||
1358 | } | ||
1359 | |||
1360 | static int i830_flip_bufs(struct drm_device *dev, void *data, | ||
1361 | struct drm_file *file_priv) | ||
1362 | { | ||
1363 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
1364 | |||
1365 | DRM_DEBUG("%s\n", __func__); | ||
1366 | |||
1367 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
1368 | |||
1369 | if (!dev_priv->page_flipping) | ||
1370 | i830_do_init_pageflip(dev); | ||
1371 | |||
1372 | i830_dma_dispatch_flip(dev); | ||
1373 | return 0; | ||
1374 | } | ||
1375 | |||
1376 | static int i830_getage(struct drm_device *dev, void *data, | ||
1377 | struct drm_file *file_priv) | ||
1378 | { | ||
1379 | drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private; | ||
1380 | u32 *hw_status = dev_priv->hw_status_page; | ||
1381 | drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) | ||
1382 | dev_priv->sarea_priv; | ||
1383 | |||
1384 | sarea_priv->last_dispatch = (int)hw_status[5]; | ||
1385 | return 0; | ||
1386 | } | ||
1387 | |||
1388 | static int i830_getbuf(struct drm_device *dev, void *data, | ||
1389 | struct drm_file *file_priv) | ||
1390 | { | ||
1391 | int retcode = 0; | ||
1392 | drm_i830_dma_t *d = data; | ||
1393 | drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private; | ||
1394 | u32 *hw_status = dev_priv->hw_status_page; | ||
1395 | drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) | ||
1396 | dev_priv->sarea_priv; | ||
1397 | |||
1398 | DRM_DEBUG("getbuf\n"); | ||
1399 | |||
1400 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
1401 | |||
1402 | d->granted = 0; | ||
1403 | |||
1404 | retcode = i830_dma_get_buffer(dev, d, file_priv); | ||
1405 | |||
1406 | DRM_DEBUG("i830_dma: %d returning %d, granted = %d\n", | ||
1407 | task_pid_nr(current), retcode, d->granted); | ||
1408 | |||
1409 | sarea_priv->last_dispatch = (int)hw_status[5]; | ||
1410 | |||
1411 | return retcode; | ||
1412 | } | ||
1413 | |||
1414 | static int i830_copybuf(struct drm_device *dev, void *data, | ||
1415 | struct drm_file *file_priv) | ||
1416 | { | ||
1417 | /* Never copy - 2.4.x doesn't need it */ | ||
1418 | return 0; | ||
1419 | } | ||
1420 | |||
1421 | static int i830_docopy(struct drm_device *dev, void *data, | ||
1422 | struct drm_file *file_priv) | ||
1423 | { | ||
1424 | return 0; | ||
1425 | } | ||
1426 | |||
1427 | static int i830_getparam(struct drm_device *dev, void *data, | ||
1428 | struct drm_file *file_priv) | ||
1429 | { | ||
1430 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
1431 | drm_i830_getparam_t *param = data; | ||
1432 | int value; | ||
1433 | |||
1434 | if (!dev_priv) { | ||
1435 | DRM_ERROR("%s called with no initialization\n", __func__); | ||
1436 | return -EINVAL; | ||
1437 | } | ||
1438 | |||
1439 | switch (param->param) { | ||
1440 | case I830_PARAM_IRQ_ACTIVE: | ||
1441 | value = dev->irq_enabled; | ||
1442 | break; | ||
1443 | default: | ||
1444 | return -EINVAL; | ||
1445 | } | ||
1446 | |||
1447 | if (copy_to_user(param->value, &value, sizeof(int))) { | ||
1448 | DRM_ERROR("copy_to_user\n"); | ||
1449 | return -EFAULT; | ||
1450 | } | ||
1451 | |||
1452 | return 0; | ||
1453 | } | ||
1454 | |||
1455 | static int i830_setparam(struct drm_device *dev, void *data, | ||
1456 | struct drm_file *file_priv) | ||
1457 | { | ||
1458 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
1459 | drm_i830_setparam_t *param = data; | ||
1460 | |||
1461 | if (!dev_priv) { | ||
1462 | DRM_ERROR("%s called with no initialization\n", __func__); | ||
1463 | return -EINVAL; | ||
1464 | } | ||
1465 | |||
1466 | switch (param->param) { | ||
1467 | case I830_SETPARAM_USE_MI_BATCHBUFFER_START: | ||
1468 | dev_priv->use_mi_batchbuffer_start = param->value; | ||
1469 | break; | ||
1470 | default: | ||
1471 | return -EINVAL; | ||
1472 | } | ||
1473 | |||
1474 | return 0; | ||
1475 | } | ||
1476 | |||
1477 | int i830_driver_load(struct drm_device *dev, unsigned long flags) | ||
1478 | { | ||
1479 | /* i830 has 4 more counters */ | ||
1480 | dev->counters += 4; | ||
1481 | dev->types[6] = _DRM_STAT_IRQ; | ||
1482 | dev->types[7] = _DRM_STAT_PRIMARY; | ||
1483 | dev->types[8] = _DRM_STAT_SECONDARY; | ||
1484 | dev->types[9] = _DRM_STAT_DMA; | ||
1485 | |||
1486 | return 0; | ||
1487 | } | ||
1488 | |||
1489 | void i830_driver_lastclose(struct drm_device *dev) | ||
1490 | { | ||
1491 | i830_dma_cleanup(dev); | ||
1492 | } | ||
1493 | |||
1494 | void i830_driver_preclose(struct drm_device *dev, struct drm_file *file_priv) | ||
1495 | { | ||
1496 | if (dev->dev_private) { | ||
1497 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
1498 | if (dev_priv->page_flipping) | ||
1499 | i830_do_cleanup_pageflip(dev); | ||
1500 | } | ||
1501 | } | ||
1502 | |||
1503 | void i830_driver_reclaim_buffers_locked(struct drm_device *dev, struct drm_file *file_priv) | ||
1504 | { | ||
1505 | i830_reclaim_buffers(dev, file_priv); | ||
1506 | } | ||
1507 | |||
1508 | int i830_driver_dma_quiescent(struct drm_device *dev) | ||
1509 | { | ||
1510 | i830_dma_quiescent(dev); | ||
1511 | return 0; | ||
1512 | } | ||
1513 | |||
1514 | /* | ||
1515 | * call the drm_ioctl under the big kernel lock because | ||
1516 | * to lock against the i830_mmap_buffers function. | ||
1517 | */ | ||
1518 | long i830_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
1519 | { | ||
1520 | int ret; | ||
1521 | lock_kernel(); | ||
1522 | ret = drm_ioctl(file, cmd, arg); | ||
1523 | unlock_kernel(); | ||
1524 | return ret; | ||
1525 | } | ||
1526 | |||
1527 | struct drm_ioctl_desc i830_ioctls[] = { | ||
1528 | DRM_IOCTL_DEF_DRV(I830_INIT, i830_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), | ||
1529 | DRM_IOCTL_DEF_DRV(I830_VERTEX, i830_dma_vertex, DRM_AUTH|DRM_UNLOCKED), | ||
1530 | DRM_IOCTL_DEF_DRV(I830_CLEAR, i830_clear_bufs, DRM_AUTH|DRM_UNLOCKED), | ||
1531 | DRM_IOCTL_DEF_DRV(I830_FLUSH, i830_flush_ioctl, DRM_AUTH|DRM_UNLOCKED), | ||
1532 | DRM_IOCTL_DEF_DRV(I830_GETAGE, i830_getage, DRM_AUTH|DRM_UNLOCKED), | ||
1533 | DRM_IOCTL_DEF_DRV(I830_GETBUF, i830_getbuf, DRM_AUTH|DRM_UNLOCKED), | ||
1534 | DRM_IOCTL_DEF_DRV(I830_SWAP, i830_swap_bufs, DRM_AUTH|DRM_UNLOCKED), | ||
1535 | DRM_IOCTL_DEF_DRV(I830_COPY, i830_copybuf, DRM_AUTH|DRM_UNLOCKED), | ||
1536 | DRM_IOCTL_DEF_DRV(I830_DOCOPY, i830_docopy, DRM_AUTH|DRM_UNLOCKED), | ||
1537 | DRM_IOCTL_DEF_DRV(I830_FLIP, i830_flip_bufs, DRM_AUTH|DRM_UNLOCKED), | ||
1538 | DRM_IOCTL_DEF_DRV(I830_IRQ_EMIT, i830_irq_emit, DRM_AUTH|DRM_UNLOCKED), | ||
1539 | DRM_IOCTL_DEF_DRV(I830_IRQ_WAIT, i830_irq_wait, DRM_AUTH|DRM_UNLOCKED), | ||
1540 | DRM_IOCTL_DEF_DRV(I830_GETPARAM, i830_getparam, DRM_AUTH|DRM_UNLOCKED), | ||
1541 | DRM_IOCTL_DEF_DRV(I830_SETPARAM, i830_setparam, DRM_AUTH|DRM_UNLOCKED), | ||
1542 | }; | ||
1543 | |||
1544 | int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls); | ||
1545 | |||
1546 | /** | ||
1547 | * Determine if the device really is AGP or not. | ||
1548 | * | ||
1549 | * All Intel graphics chipsets are treated as AGP, even if they are really | ||
1550 | * PCI-e. | ||
1551 | * | ||
1552 | * \param dev The device to be tested. | ||
1553 | * | ||
1554 | * \returns | ||
1555 | * A value of 1 is always retured to indictate every i8xx is AGP. | ||
1556 | */ | ||
1557 | int i830_driver_device_is_agp(struct drm_device *dev) | ||
1558 | { | ||
1559 | return 1; | ||
1560 | } | ||
diff --git a/drivers/gpu/drm/i830/i830_drv.c b/drivers/gpu/drm/i830/i830_drv.c deleted file mode 100644 index f655ab7977d..00000000000 --- a/drivers/gpu/drm/i830/i830_drv.c +++ /dev/null | |||
@@ -1,107 +0,0 @@ | |||
1 | /* i830_drv.c -- I810 driver -*- linux-c -*- | ||
2 | * Created: Mon Dec 13 01:56:22 1999 by jhartmann@precisioninsight.com | ||
3 | * | ||
4 | * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. | ||
5 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | ||
6 | * All Rights Reserved. | ||
7 | * | ||
8 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
9 | * copy of this software and associated documentation files (the "Software"), | ||
10 | * to deal in the Software without restriction, including without limitation | ||
11 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
12 | * and/or sell copies of the Software, and to permit persons to whom the | ||
13 | * Software is furnished to do so, subject to the following conditions: | ||
14 | * | ||
15 | * The above copyright notice and this permission notice (including the next | ||
16 | * paragraph) shall be included in all copies or substantial portions of the | ||
17 | * Software. | ||
18 | * | ||
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
22 | * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
23 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
24 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
25 | * OTHER DEALINGS IN THE SOFTWARE. | ||
26 | * | ||
27 | * Authors: | ||
28 | * Rickard E. (Rik) Faith <faith@valinux.com> | ||
29 | * Jeff Hartmann <jhartmann@valinux.com> | ||
30 | * Gareth Hughes <gareth@valinux.com> | ||
31 | * Abraham vd Merwe <abraham@2d3d.co.za> | ||
32 | * Keith Whitwell <keith@tungstengraphics.com> | ||
33 | */ | ||
34 | |||
35 | #include "drmP.h" | ||
36 | #include "drm.h" | ||
37 | #include "i830_drm.h" | ||
38 | #include "i830_drv.h" | ||
39 | |||
40 | #include "drm_pciids.h" | ||
41 | |||
42 | static struct pci_device_id pciidlist[] = { | ||
43 | i830_PCI_IDS | ||
44 | }; | ||
45 | |||
46 | static struct drm_driver driver = { | ||
47 | .driver_features = | ||
48 | DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | | ||
49 | DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE, | ||
50 | #if USE_IRQS | ||
51 | .driver_features |= DRIVER_HAVE_IRQ | DRIVER_SHARED_IRQ, | ||
52 | #endif | ||
53 | .dev_priv_size = sizeof(drm_i830_buf_priv_t), | ||
54 | .load = i830_driver_load, | ||
55 | .lastclose = i830_driver_lastclose, | ||
56 | .preclose = i830_driver_preclose, | ||
57 | .device_is_agp = i830_driver_device_is_agp, | ||
58 | .reclaim_buffers_locked = i830_driver_reclaim_buffers_locked, | ||
59 | .dma_quiescent = i830_driver_dma_quiescent, | ||
60 | #if USE_IRQS | ||
61 | .irq_preinstall = i830_driver_irq_preinstall, | ||
62 | .irq_postinstall = i830_driver_irq_postinstall, | ||
63 | .irq_uninstall = i830_driver_irq_uninstall, | ||
64 | .irq_handler = i830_driver_irq_handler, | ||
65 | #endif | ||
66 | .ioctls = i830_ioctls, | ||
67 | .fops = { | ||
68 | .owner = THIS_MODULE, | ||
69 | .open = drm_open, | ||
70 | .release = drm_release, | ||
71 | .unlocked_ioctl = i830_ioctl, | ||
72 | .mmap = drm_mmap, | ||
73 | .poll = drm_poll, | ||
74 | .fasync = drm_fasync, | ||
75 | .llseek = noop_llseek, | ||
76 | }, | ||
77 | |||
78 | .pci_driver = { | ||
79 | .name = DRIVER_NAME, | ||
80 | .id_table = pciidlist, | ||
81 | }, | ||
82 | |||
83 | .name = DRIVER_NAME, | ||
84 | .desc = DRIVER_DESC, | ||
85 | .date = DRIVER_DATE, | ||
86 | .major = DRIVER_MAJOR, | ||
87 | .minor = DRIVER_MINOR, | ||
88 | .patchlevel = DRIVER_PATCHLEVEL, | ||
89 | }; | ||
90 | |||
91 | static int __init i830_init(void) | ||
92 | { | ||
93 | driver.num_ioctls = i830_max_ioctl; | ||
94 | return drm_init(&driver); | ||
95 | } | ||
96 | |||
97 | static void __exit i830_exit(void) | ||
98 | { | ||
99 | drm_exit(&driver); | ||
100 | } | ||
101 | |||
102 | module_init(i830_init); | ||
103 | module_exit(i830_exit); | ||
104 | |||
105 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
106 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
107 | MODULE_LICENSE("GPL and additional rights"); | ||
diff --git a/drivers/gpu/drm/i830/i830_drv.h b/drivers/gpu/drm/i830/i830_drv.h deleted file mode 100644 index 0df1c720560..00000000000 --- a/drivers/gpu/drm/i830/i830_drv.h +++ /dev/null | |||
@@ -1,295 +0,0 @@ | |||
1 | /* i830_drv.h -- Private header for the I830 driver -*- linux-c -*- | ||
2 | * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com | ||
3 | * | ||
4 | * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. | ||
5 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
9 | * copy of this software and associated documentation files (the "Software"), | ||
10 | * to deal in the Software without restriction, including without limitation | ||
11 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
12 | * and/or sell copies of the Software, and to permit persons to whom the | ||
13 | * Software is furnished to do so, subject to the following conditions: | ||
14 | * | ||
15 | * The above copyright notice and this permission notice (including the next | ||
16 | * paragraph) shall be included in all copies or substantial portions of the | ||
17 | * Software. | ||
18 | * | ||
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
22 | * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
23 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
24 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
25 | * DEALINGS IN THE SOFTWARE. | ||
26 | * | ||
27 | * Authors: Rickard E. (Rik) Faith <faith@valinux.com> | ||
28 | * Jeff Hartmann <jhartmann@valinux.com> | ||
29 | * | ||
30 | */ | ||
31 | |||
32 | #ifndef _I830_DRV_H_ | ||
33 | #define _I830_DRV_H_ | ||
34 | |||
35 | /* General customization: | ||
36 | */ | ||
37 | |||
38 | #define DRIVER_AUTHOR "VA Linux Systems Inc." | ||
39 | |||
40 | #define DRIVER_NAME "i830" | ||
41 | #define DRIVER_DESC "Intel 830M" | ||
42 | #define DRIVER_DATE "20021108" | ||
43 | |||
44 | /* Interface history: | ||
45 | * | ||
46 | * 1.1: Original. | ||
47 | * 1.2: ? | ||
48 | * 1.3: New irq emit/wait ioctls. | ||
49 | * New pageflip ioctl. | ||
50 | * New getparam ioctl. | ||
51 | * State for texunits 3&4 in sarea. | ||
52 | * New (alternative) layout for texture state. | ||
53 | */ | ||
54 | #define DRIVER_MAJOR 1 | ||
55 | #define DRIVER_MINOR 3 | ||
56 | #define DRIVER_PATCHLEVEL 2 | ||
57 | |||
58 | /* Driver will work either way: IRQ's save cpu time when waiting for | ||
59 | * the card, but are subject to subtle interactions between bios, | ||
60 | * hardware and the driver. | ||
61 | */ | ||
62 | /* XXX: Add vblank support? */ | ||
63 | #define USE_IRQS 0 | ||
64 | |||
65 | typedef struct drm_i830_buf_priv { | ||
66 | u32 *in_use; | ||
67 | int my_use_idx; | ||
68 | int currently_mapped; | ||
69 | void __user *virtual; | ||
70 | void *kernel_virtual; | ||
71 | drm_local_map_t map; | ||
72 | } drm_i830_buf_priv_t; | ||
73 | |||
74 | typedef struct _drm_i830_ring_buffer { | ||
75 | int tail_mask; | ||
76 | unsigned long Start; | ||
77 | unsigned long End; | ||
78 | unsigned long Size; | ||
79 | u8 *virtual_start; | ||
80 | int head; | ||
81 | int tail; | ||
82 | int space; | ||
83 | drm_local_map_t map; | ||
84 | } drm_i830_ring_buffer_t; | ||
85 | |||
86 | typedef struct drm_i830_private { | ||
87 | struct drm_local_map *sarea_map; | ||
88 | struct drm_local_map *mmio_map; | ||
89 | |||
90 | drm_i830_sarea_t *sarea_priv; | ||
91 | drm_i830_ring_buffer_t ring; | ||
92 | |||
93 | void *hw_status_page; | ||
94 | unsigned long counter; | ||
95 | |||
96 | dma_addr_t dma_status_page; | ||
97 | |||
98 | struct drm_buf *mmap_buffer; | ||
99 | |||
100 | u32 front_di1, back_di1, zi1; | ||
101 | |||
102 | int back_offset; | ||
103 | int depth_offset; | ||
104 | int front_offset; | ||
105 | int w, h; | ||
106 | int pitch; | ||
107 | int back_pitch; | ||
108 | int depth_pitch; | ||
109 | unsigned int cpp; | ||
110 | |||
111 | int do_boxes; | ||
112 | int dma_used; | ||
113 | |||
114 | int current_page; | ||
115 | int page_flipping; | ||
116 | |||
117 | wait_queue_head_t irq_queue; | ||
118 | atomic_t irq_received; | ||
119 | atomic_t irq_emitted; | ||
120 | |||
121 | int use_mi_batchbuffer_start; | ||
122 | |||
123 | } drm_i830_private_t; | ||
124 | |||
125 | long i830_ioctl(struct file *file, unsigned int cmd, unsigned long arg); | ||
126 | extern struct drm_ioctl_desc i830_ioctls[]; | ||
127 | extern int i830_max_ioctl; | ||
128 | |||
129 | /* i830_irq.c */ | ||
130 | extern int i830_irq_emit(struct drm_device *dev, void *data, | ||
131 | struct drm_file *file_priv); | ||
132 | extern int i830_irq_wait(struct drm_device *dev, void *data, | ||
133 | struct drm_file *file_priv); | ||
134 | |||
135 | extern irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS); | ||
136 | extern void i830_driver_irq_preinstall(struct drm_device *dev); | ||
137 | extern void i830_driver_irq_postinstall(struct drm_device *dev); | ||
138 | extern void i830_driver_irq_uninstall(struct drm_device *dev); | ||
139 | extern int i830_driver_load(struct drm_device *, unsigned long flags); | ||
140 | extern void i830_driver_preclose(struct drm_device *dev, | ||
141 | struct drm_file *file_priv); | ||
142 | extern void i830_driver_lastclose(struct drm_device *dev); | ||
143 | extern void i830_driver_reclaim_buffers_locked(struct drm_device *dev, | ||
144 | struct drm_file *file_priv); | ||
145 | extern int i830_driver_dma_quiescent(struct drm_device *dev); | ||
146 | extern int i830_driver_device_is_agp(struct drm_device *dev); | ||
147 | |||
148 | #define I830_READ(reg) DRM_READ32(dev_priv->mmio_map, reg) | ||
149 | #define I830_WRITE(reg, val) DRM_WRITE32(dev_priv->mmio_map, reg, val) | ||
150 | #define I830_READ16(reg) DRM_READ16(dev_priv->mmio_map, reg) | ||
151 | #define I830_WRITE16(reg, val) DRM_WRITE16(dev_priv->mmio_map, reg, val) | ||
152 | |||
153 | #define I830_VERBOSE 0 | ||
154 | |||
155 | #define RING_LOCALS unsigned int outring, ringmask, outcount; \ | ||
156 | volatile char *virt; | ||
157 | |||
158 | #define BEGIN_LP_RING(n) do { \ | ||
159 | if (I830_VERBOSE) \ | ||
160 | printk("BEGIN_LP_RING(%d)\n", (n)); \ | ||
161 | if (dev_priv->ring.space < n*4) \ | ||
162 | i830_wait_ring(dev, n*4, __func__); \ | ||
163 | outcount = 0; \ | ||
164 | outring = dev_priv->ring.tail; \ | ||
165 | ringmask = dev_priv->ring.tail_mask; \ | ||
166 | virt = dev_priv->ring.virtual_start; \ | ||
167 | } while (0) | ||
168 | |||
169 | #define OUT_RING(n) do { \ | ||
170 | if (I830_VERBOSE) \ | ||
171 | printk(" OUT_RING %x\n", (int)(n)); \ | ||
172 | *(volatile unsigned int *)(virt + outring) = n; \ | ||
173 | outcount++; \ | ||
174 | outring += 4; \ | ||
175 | outring &= ringmask; \ | ||
176 | } while (0) | ||
177 | |||
178 | #define ADVANCE_LP_RING() do { \ | ||
179 | if (I830_VERBOSE) \ | ||
180 | printk("ADVANCE_LP_RING %x\n", outring); \ | ||
181 | dev_priv->ring.tail = outring; \ | ||
182 | dev_priv->ring.space -= outcount * 4; \ | ||
183 | I830_WRITE(LP_RING + RING_TAIL, outring); \ | ||
184 | } while (0) | ||
185 | |||
186 | extern int i830_wait_ring(struct drm_device *dev, int n, const char *caller); | ||
187 | |||
188 | #define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23)) | ||
189 | #define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23)) | ||
190 | #define CMD_REPORT_HEAD (7<<23) | ||
191 | #define CMD_STORE_DWORD_IDX ((0x21<<23) | 0x1) | ||
192 | #define CMD_OP_BATCH_BUFFER ((0x0<<29)|(0x30<<23)|0x1) | ||
193 | |||
194 | #define STATE3D_LOAD_STATE_IMMEDIATE_2 ((0x3<<29)|(0x1d<<24)|(0x03<<16)) | ||
195 | #define LOAD_TEXTURE_MAP0 (1<<11) | ||
196 | |||
197 | #define INST_PARSER_CLIENT 0x00000000 | ||
198 | #define INST_OP_FLUSH 0x02000000 | ||
199 | #define INST_FLUSH_MAP_CACHE 0x00000001 | ||
200 | |||
201 | #define BB1_START_ADDR_MASK (~0x7) | ||
202 | #define BB1_PROTECTED (1<<0) | ||
203 | #define BB1_UNPROTECTED (0<<0) | ||
204 | #define BB2_END_ADDR_MASK (~0x7) | ||
205 | |||
206 | #define I830REG_HWSTAM 0x02098 | ||
207 | #define I830REG_INT_IDENTITY_R 0x020a4 | ||
208 | #define I830REG_INT_MASK_R 0x020a8 | ||
209 | #define I830REG_INT_ENABLE_R 0x020a0 | ||
210 | |||
211 | #define I830_IRQ_RESERVED ((1<<13)|(3<<2)) | ||
212 | |||
213 | #define LP_RING 0x2030 | ||
214 | #define HP_RING 0x2040 | ||
215 | #define RING_TAIL 0x00 | ||
216 | #define TAIL_ADDR 0x001FFFF8 | ||
217 | #define RING_HEAD 0x04 | ||
218 | #define HEAD_WRAP_COUNT 0xFFE00000 | ||
219 | #define HEAD_WRAP_ONE 0x00200000 | ||
220 | #define HEAD_ADDR 0x001FFFFC | ||
221 | #define RING_START 0x08 | ||
222 | #define START_ADDR 0x0xFFFFF000 | ||
223 | #define RING_LEN 0x0C | ||
224 | #define RING_NR_PAGES 0x001FF000 | ||
225 | #define RING_REPORT_MASK 0x00000006 | ||
226 | #define RING_REPORT_64K 0x00000002 | ||
227 | #define RING_REPORT_128K 0x00000004 | ||
228 | #define RING_NO_REPORT 0x00000000 | ||
229 | #define RING_VALID_MASK 0x00000001 | ||
230 | #define RING_VALID 0x00000001 | ||
231 | #define RING_INVALID 0x00000000 | ||
232 | |||
233 | #define GFX_OP_SCISSOR ((0x3<<29)|(0x1c<<24)|(0x10<<19)) | ||
234 | #define SC_UPDATE_SCISSOR (0x1<<1) | ||
235 | #define SC_ENABLE_MASK (0x1<<0) | ||
236 | #define SC_ENABLE (0x1<<0) | ||
237 | |||
238 | #define GFX_OP_SCISSOR_INFO ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1)) | ||
239 | #define SCI_YMIN_MASK (0xffff<<16) | ||
240 | #define SCI_XMIN_MASK (0xffff<<0) | ||
241 | #define SCI_YMAX_MASK (0xffff<<16) | ||
242 | #define SCI_XMAX_MASK (0xffff<<0) | ||
243 | |||
244 | #define GFX_OP_SCISSOR_ENABLE ((0x3<<29)|(0x1c<<24)|(0x10<<19)) | ||
245 | #define GFX_OP_SCISSOR_RECT ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1) | ||
246 | #define GFX_OP_COLOR_FACTOR ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0) | ||
247 | #define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16)) | ||
248 | #define GFX_OP_MAP_INFO ((0x3<<29)|(0x1d<<24)|0x4) | ||
249 | #define GFX_OP_DESTBUFFER_VARS ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0) | ||
250 | #define GFX_OP_DRAWRECT_INFO ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3)) | ||
251 | #define GFX_OP_PRIMITIVE ((0x3<<29)|(0x1f<<24)) | ||
252 | |||
253 | #define CMD_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1) | ||
254 | |||
255 | #define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2) | ||
256 | #define ASYNC_FLIP (1<<22) | ||
257 | |||
258 | #define CMD_3D (0x3<<29) | ||
259 | #define STATE3D_CONST_BLEND_COLOR_CMD (CMD_3D|(0x1d<<24)|(0x88<<16)) | ||
260 | #define STATE3D_MAP_COORD_SETBIND_CMD (CMD_3D|(0x1d<<24)|(0x02<<16)) | ||
261 | |||
262 | #define BR00_BITBLT_CLIENT 0x40000000 | ||
263 | #define BR00_OP_COLOR_BLT 0x10000000 | ||
264 | #define BR00_OP_SRC_COPY_BLT 0x10C00000 | ||
265 | #define BR13_SOLID_PATTERN 0x80000000 | ||
266 | |||
267 | #define BUF_3D_ID_COLOR_BACK (0x3<<24) | ||
268 | #define BUF_3D_ID_DEPTH (0x7<<24) | ||
269 | #define BUF_3D_USE_FENCE (1<<23) | ||
270 | #define BUF_3D_PITCH(x) (((x)/4)<<2) | ||
271 | |||
272 | #define CMD_OP_MAP_PALETTE_LOAD ((3<<29)|(0x1d<<24)|(0x82<<16)|255) | ||
273 | #define MAP_PALETTE_NUM(x) ((x<<8) & (1<<8)) | ||
274 | #define MAP_PALETTE_BOTH (1<<11) | ||
275 | |||
276 | #define XY_COLOR_BLT_CMD ((2<<29)|(0x50<<22)|0x4) | ||
277 | #define XY_COLOR_BLT_WRITE_ALPHA (1<<21) | ||
278 | #define XY_COLOR_BLT_WRITE_RGB (1<<20) | ||
279 | |||
280 | #define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6) | ||
281 | #define XY_SRC_COPY_BLT_WRITE_ALPHA (1<<21) | ||
282 | #define XY_SRC_COPY_BLT_WRITE_RGB (1<<20) | ||
283 | |||
284 | #define MI_BATCH_BUFFER ((0x30<<23)|1) | ||
285 | #define MI_BATCH_BUFFER_START (0x31<<23) | ||
286 | #define MI_BATCH_BUFFER_END (0xA<<23) | ||
287 | #define MI_BATCH_NON_SECURE (1) | ||
288 | |||
289 | #define MI_WAIT_FOR_EVENT ((0x3<<23)) | ||
290 | #define MI_WAIT_FOR_PLANE_A_FLIP (1<<2) | ||
291 | #define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1) | ||
292 | |||
293 | #define MI_LOAD_SCAN_LINES_INCL ((0x12<<23)) | ||
294 | |||
295 | #endif | ||
diff --git a/drivers/gpu/drm/i830/i830_irq.c b/drivers/gpu/drm/i830/i830_irq.c deleted file mode 100644 index d1a6b95d631..00000000000 --- a/drivers/gpu/drm/i830/i830_irq.c +++ /dev/null | |||
@@ -1,186 +0,0 @@ | |||
1 | /* i830_dma.c -- DMA support for the I830 -*- linux-c -*- | ||
2 | * | ||
3 | * Copyright 2002 Tungsten Graphics, Inc. | ||
4 | * All Rights Reserved. | ||
5 | * | ||
6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
7 | * copy of this software and associated documentation files (the "Software"), | ||
8 | * to deal in the Software without restriction, including without limitation | ||
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
11 | * Software is furnished to do so, subject to the following conditions: | ||
12 | * | ||
13 | * The above copyright notice and this permission notice (including the next | ||
14 | * paragraph) shall be included in all copies or substantial portions of the | ||
15 | * Software. | ||
16 | * | ||
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
20 | * TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
23 | * DEALINGS IN THE SOFTWARE. | ||
24 | * | ||
25 | * Authors: Keith Whitwell <keith@tungstengraphics.com> | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | #include "drmP.h" | ||
30 | #include "drm.h" | ||
31 | #include "i830_drm.h" | ||
32 | #include "i830_drv.h" | ||
33 | #include <linux/interrupt.h> /* For task queue support */ | ||
34 | #include <linux/delay.h> | ||
35 | |||
36 | irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS) | ||
37 | { | ||
38 | struct drm_device *dev = (struct drm_device *) arg; | ||
39 | drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private; | ||
40 | u16 temp; | ||
41 | |||
42 | temp = I830_READ16(I830REG_INT_IDENTITY_R); | ||
43 | DRM_DEBUG("%x\n", temp); | ||
44 | |||
45 | if (!(temp & 2)) | ||
46 | return IRQ_NONE; | ||
47 | |||
48 | I830_WRITE16(I830REG_INT_IDENTITY_R, temp); | ||
49 | |||
50 | atomic_inc(&dev_priv->irq_received); | ||
51 | wake_up_interruptible(&dev_priv->irq_queue); | ||
52 | |||
53 | return IRQ_HANDLED; | ||
54 | } | ||
55 | |||
56 | static int i830_emit_irq(struct drm_device *dev) | ||
57 | { | ||
58 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
59 | RING_LOCALS; | ||
60 | |||
61 | DRM_DEBUG("%s\n", __func__); | ||
62 | |||
63 | atomic_inc(&dev_priv->irq_emitted); | ||
64 | |||
65 | BEGIN_LP_RING(2); | ||
66 | OUT_RING(0); | ||
67 | OUT_RING(GFX_OP_USER_INTERRUPT); | ||
68 | ADVANCE_LP_RING(); | ||
69 | |||
70 | return atomic_read(&dev_priv->irq_emitted); | ||
71 | } | ||
72 | |||
73 | static int i830_wait_irq(struct drm_device *dev, int irq_nr) | ||
74 | { | ||
75 | drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private; | ||
76 | DECLARE_WAITQUEUE(entry, current); | ||
77 | unsigned long end = jiffies + HZ * 3; | ||
78 | int ret = 0; | ||
79 | |||
80 | DRM_DEBUG("%s\n", __func__); | ||
81 | |||
82 | if (atomic_read(&dev_priv->irq_received) >= irq_nr) | ||
83 | return 0; | ||
84 | |||
85 | dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT; | ||
86 | |||
87 | add_wait_queue(&dev_priv->irq_queue, &entry); | ||
88 | |||
89 | for (;;) { | ||
90 | __set_current_state(TASK_INTERRUPTIBLE); | ||
91 | if (atomic_read(&dev_priv->irq_received) >= irq_nr) | ||
92 | break; | ||
93 | if ((signed)(end - jiffies) <= 0) { | ||
94 | DRM_ERROR("timeout iir %x imr %x ier %x hwstam %x\n", | ||
95 | I830_READ16(I830REG_INT_IDENTITY_R), | ||
96 | I830_READ16(I830REG_INT_MASK_R), | ||
97 | I830_READ16(I830REG_INT_ENABLE_R), | ||
98 | I830_READ16(I830REG_HWSTAM)); | ||
99 | |||
100 | ret = -EBUSY; /* Lockup? Missed irq? */ | ||
101 | break; | ||
102 | } | ||
103 | schedule_timeout(HZ * 3); | ||
104 | if (signal_pending(current)) { | ||
105 | ret = -EINTR; | ||
106 | break; | ||
107 | } | ||
108 | } | ||
109 | |||
110 | __set_current_state(TASK_RUNNING); | ||
111 | remove_wait_queue(&dev_priv->irq_queue, &entry); | ||
112 | return ret; | ||
113 | } | ||
114 | |||
115 | /* Needs the lock as it touches the ring. | ||
116 | */ | ||
117 | int i830_irq_emit(struct drm_device *dev, void *data, | ||
118 | struct drm_file *file_priv) | ||
119 | { | ||
120 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
121 | drm_i830_irq_emit_t *emit = data; | ||
122 | int result; | ||
123 | |||
124 | LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
125 | |||
126 | if (!dev_priv) { | ||
127 | DRM_ERROR("%s called with no initialization\n", __func__); | ||
128 | return -EINVAL; | ||
129 | } | ||
130 | |||
131 | result = i830_emit_irq(dev); | ||
132 | |||
133 | if (copy_to_user(emit->irq_seq, &result, sizeof(int))) { | ||
134 | DRM_ERROR("copy_to_user\n"); | ||
135 | return -EFAULT; | ||
136 | } | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | /* Doesn't need the hardware lock. | ||
142 | */ | ||
143 | int i830_irq_wait(struct drm_device *dev, void *data, | ||
144 | struct drm_file *file_priv) | ||
145 | { | ||
146 | drm_i830_private_t *dev_priv = dev->dev_private; | ||
147 | drm_i830_irq_wait_t *irqwait = data; | ||
148 | |||
149 | if (!dev_priv) { | ||
150 | DRM_ERROR("%s called with no initialization\n", __func__); | ||
151 | return -EINVAL; | ||
152 | } | ||
153 | |||
154 | return i830_wait_irq(dev, irqwait->irq_seq); | ||
155 | } | ||
156 | |||
157 | /* drm_dma.h hooks | ||
158 | */ | ||
159 | void i830_driver_irq_preinstall(struct drm_device *dev) | ||
160 | { | ||
161 | drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private; | ||
162 | |||
163 | I830_WRITE16(I830REG_HWSTAM, 0xffff); | ||
164 | I830_WRITE16(I830REG_INT_MASK_R, 0x0); | ||
165 | I830_WRITE16(I830REG_INT_ENABLE_R, 0x0); | ||
166 | atomic_set(&dev_priv->irq_received, 0); | ||
167 | atomic_set(&dev_priv->irq_emitted, 0); | ||
168 | init_waitqueue_head(&dev_priv->irq_queue); | ||
169 | } | ||
170 | |||
171 | void i830_driver_irq_postinstall(struct drm_device *dev) | ||
172 | { | ||
173 | drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private; | ||
174 | |||
175 | I830_WRITE16(I830REG_INT_ENABLE_R, 0x2); | ||
176 | } | ||
177 | |||
178 | void i830_driver_irq_uninstall(struct drm_device *dev) | ||
179 | { | ||
180 | drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private; | ||
181 | if (!dev_priv) | ||
182 | return; | ||
183 | |||
184 | I830_WRITE16(I830REG_INT_MASK_R, 0xffff); | ||
185 | I830_WRITE16(I830REG_INT_ENABLE_R, 0x0); | ||
186 | } | ||
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 4ff9b6cc973..09e0327fc6c 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
@@ -326,21 +326,21 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data) | |||
326 | struct intel_crtc *crtc; | 326 | struct intel_crtc *crtc; |
327 | 327 | ||
328 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { | 328 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { |
329 | const char *pipe = crtc->pipe ? "B" : "A"; | 329 | const char pipe = pipe_name(crtc->pipe); |
330 | const char *plane = crtc->plane ? "B" : "A"; | 330 | const char plane = plane_name(crtc->plane); |
331 | struct intel_unpin_work *work; | 331 | struct intel_unpin_work *work; |
332 | 332 | ||
333 | spin_lock_irqsave(&dev->event_lock, flags); | 333 | spin_lock_irqsave(&dev->event_lock, flags); |
334 | work = crtc->unpin_work; | 334 | work = crtc->unpin_work; |
335 | if (work == NULL) { | 335 | if (work == NULL) { |
336 | seq_printf(m, "No flip due on pipe %s (plane %s)\n", | 336 | seq_printf(m, "No flip due on pipe %c (plane %c)\n", |
337 | pipe, plane); | 337 | pipe, plane); |
338 | } else { | 338 | } else { |
339 | if (!work->pending) { | 339 | if (!work->pending) { |
340 | seq_printf(m, "Flip queued on pipe %s (plane %s)\n", | 340 | seq_printf(m, "Flip queued on pipe %c (plane %c)\n", |
341 | pipe, plane); | 341 | pipe, plane); |
342 | } else { | 342 | } else { |
343 | seq_printf(m, "Flip pending (waiting for vsync) on pipe %s (plane %s)\n", | 343 | seq_printf(m, "Flip pending (waiting for vsync) on pipe %c (plane %c)\n", |
344 | pipe, plane); | 344 | pipe, plane); |
345 | } | 345 | } |
346 | if (work->enable_stall_check) | 346 | if (work->enable_stall_check) |
@@ -458,7 +458,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) | |||
458 | struct drm_info_node *node = (struct drm_info_node *) m->private; | 458 | struct drm_info_node *node = (struct drm_info_node *) m->private; |
459 | struct drm_device *dev = node->minor->dev; | 459 | struct drm_device *dev = node->minor->dev; |
460 | drm_i915_private_t *dev_priv = dev->dev_private; | 460 | drm_i915_private_t *dev_priv = dev->dev_private; |
461 | int ret, i; | 461 | int ret, i, pipe; |
462 | 462 | ||
463 | ret = mutex_lock_interruptible(&dev->struct_mutex); | 463 | ret = mutex_lock_interruptible(&dev->struct_mutex); |
464 | if (ret) | 464 | if (ret) |
@@ -471,10 +471,10 @@ static int i915_interrupt_info(struct seq_file *m, void *data) | |||
471 | I915_READ(IIR)); | 471 | I915_READ(IIR)); |
472 | seq_printf(m, "Interrupt mask: %08x\n", | 472 | seq_printf(m, "Interrupt mask: %08x\n", |
473 | I915_READ(IMR)); | 473 | I915_READ(IMR)); |
474 | seq_printf(m, "Pipe A stat: %08x\n", | 474 | for_each_pipe(pipe) |
475 | I915_READ(PIPEASTAT)); | 475 | seq_printf(m, "Pipe %c stat: %08x\n", |
476 | seq_printf(m, "Pipe B stat: %08x\n", | 476 | pipe_name(pipe), |
477 | I915_READ(PIPEBSTAT)); | 477 | I915_READ(PIPESTAT(pipe))); |
478 | } else { | 478 | } else { |
479 | seq_printf(m, "North Display Interrupt enable: %08x\n", | 479 | seq_printf(m, "North Display Interrupt enable: %08x\n", |
480 | I915_READ(DEIER)); | 480 | I915_READ(DEIER)); |
@@ -544,11 +544,11 @@ static int i915_hws_info(struct seq_file *m, void *data) | |||
544 | struct drm_device *dev = node->minor->dev; | 544 | struct drm_device *dev = node->minor->dev; |
545 | drm_i915_private_t *dev_priv = dev->dev_private; | 545 | drm_i915_private_t *dev_priv = dev->dev_private; |
546 | struct intel_ring_buffer *ring; | 546 | struct intel_ring_buffer *ring; |
547 | volatile u32 *hws; | 547 | const volatile u32 __iomem *hws; |
548 | int i; | 548 | int i; |
549 | 549 | ||
550 | ring = &dev_priv->ring[(uintptr_t)node->info_ent->data]; | 550 | ring = &dev_priv->ring[(uintptr_t)node->info_ent->data]; |
551 | hws = (volatile u32 *)ring->status_page.page_addr; | 551 | hws = (volatile u32 __iomem *)ring->status_page.page_addr; |
552 | if (hws == NULL) | 552 | if (hws == NULL) |
553 | return 0; | 553 | return 0; |
554 | 554 | ||
@@ -615,7 +615,7 @@ static int i915_ringbuffer_data(struct seq_file *m, void *data) | |||
615 | if (!ring->obj) { | 615 | if (!ring->obj) { |
616 | seq_printf(m, "No ringbuffer setup\n"); | 616 | seq_printf(m, "No ringbuffer setup\n"); |
617 | } else { | 617 | } else { |
618 | u8 *virt = ring->virtual_start; | 618 | const u8 __iomem *virt = ring->virtual_start; |
619 | uint32_t off; | 619 | uint32_t off; |
620 | 620 | ||
621 | for (off = 0; off < ring->size; off += 4) { | 621 | for (off = 0; off < ring->size; off += 4) { |
@@ -805,15 +805,20 @@ static int i915_error_state(struct seq_file *m, void *unused) | |||
805 | } | 805 | } |
806 | } | 806 | } |
807 | 807 | ||
808 | if (error->ringbuffer) { | 808 | for (i = 0; i < ARRAY_SIZE(error->ringbuffer); i++) { |
809 | struct drm_i915_error_object *obj = error->ringbuffer; | 809 | if (error->ringbuffer[i]) { |
810 | 810 | struct drm_i915_error_object *obj = error->ringbuffer[i]; | |
811 | seq_printf(m, "--- ringbuffer = 0x%08x\n", obj->gtt_offset); | 811 | seq_printf(m, "%s --- ringbuffer = 0x%08x\n", |
812 | offset = 0; | 812 | dev_priv->ring[i].name, |
813 | for (page = 0; page < obj->page_count; page++) { | 813 | obj->gtt_offset); |
814 | for (elt = 0; elt < PAGE_SIZE/4; elt++) { | 814 | offset = 0; |
815 | seq_printf(m, "%08x : %08x\n", offset, obj->pages[page][elt]); | 815 | for (page = 0; page < obj->page_count; page++) { |
816 | offset += 4; | 816 | for (elt = 0; elt < PAGE_SIZE/4; elt++) { |
817 | seq_printf(m, "%08x : %08x\n", | ||
818 | offset, | ||
819 | obj->pages[page][elt]); | ||
820 | offset += 4; | ||
821 | } | ||
817 | } | 822 | } |
818 | } | 823 | } |
819 | } | 824 | } |
@@ -862,19 +867,44 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused) | |||
862 | u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); | 867 | u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); |
863 | u32 rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS); | 868 | u32 rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS); |
864 | u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); | 869 | u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); |
870 | u32 rpstat; | ||
871 | u32 rpupei, rpcurup, rpprevup; | ||
872 | u32 rpdownei, rpcurdown, rpprevdown; | ||
865 | int max_freq; | 873 | int max_freq; |
866 | 874 | ||
867 | /* RPSTAT1 is in the GT power well */ | 875 | /* RPSTAT1 is in the GT power well */ |
868 | __gen6_gt_force_wake_get(dev_priv); | 876 | __gen6_gt_force_wake_get(dev_priv); |
869 | 877 | ||
878 | rpstat = I915_READ(GEN6_RPSTAT1); | ||
879 | rpupei = I915_READ(GEN6_RP_CUR_UP_EI); | ||
880 | rpcurup = I915_READ(GEN6_RP_CUR_UP); | ||
881 | rpprevup = I915_READ(GEN6_RP_PREV_UP); | ||
882 | rpdownei = I915_READ(GEN6_RP_CUR_DOWN_EI); | ||
883 | rpcurdown = I915_READ(GEN6_RP_CUR_DOWN); | ||
884 | rpprevdown = I915_READ(GEN6_RP_PREV_DOWN); | ||
885 | |||
870 | seq_printf(m, "GT_PERF_STATUS: 0x%08x\n", gt_perf_status); | 886 | seq_printf(m, "GT_PERF_STATUS: 0x%08x\n", gt_perf_status); |
871 | seq_printf(m, "RPSTAT1: 0x%08x\n", I915_READ(GEN6_RPSTAT1)); | 887 | seq_printf(m, "RPSTAT1: 0x%08x\n", rpstat); |
872 | seq_printf(m, "Render p-state ratio: %d\n", | 888 | seq_printf(m, "Render p-state ratio: %d\n", |
873 | (gt_perf_status & 0xff00) >> 8); | 889 | (gt_perf_status & 0xff00) >> 8); |
874 | seq_printf(m, "Render p-state VID: %d\n", | 890 | seq_printf(m, "Render p-state VID: %d\n", |
875 | gt_perf_status & 0xff); | 891 | gt_perf_status & 0xff); |
876 | seq_printf(m, "Render p-state limit: %d\n", | 892 | seq_printf(m, "Render p-state limit: %d\n", |
877 | rp_state_limits & 0xff); | 893 | rp_state_limits & 0xff); |
894 | seq_printf(m, "CAGF: %dMHz\n", ((rpstat & GEN6_CAGF_MASK) >> | ||
895 | GEN6_CAGF_SHIFT) * 100); | ||
896 | seq_printf(m, "RP CUR UP EI: %dus\n", rpupei & | ||
897 | GEN6_CURICONT_MASK); | ||
898 | seq_printf(m, "RP CUR UP: %dus\n", rpcurup & | ||
899 | GEN6_CURBSYTAVG_MASK); | ||
900 | seq_printf(m, "RP PREV UP: %dus\n", rpprevup & | ||
901 | GEN6_CURBSYTAVG_MASK); | ||
902 | seq_printf(m, "RP CUR DOWN EI: %dus\n", rpdownei & | ||
903 | GEN6_CURIAVG_MASK); | ||
904 | seq_printf(m, "RP CUR DOWN: %dus\n", rpcurdown & | ||
905 | GEN6_CURBSYTAVG_MASK); | ||
906 | seq_printf(m, "RP PREV DOWN: %dus\n", rpprevdown & | ||
907 | GEN6_CURBSYTAVG_MASK); | ||
878 | 908 | ||
879 | max_freq = (rp_state_cap & 0xff0000) >> 16; | 909 | max_freq = (rp_state_cap & 0xff0000) >> 16; |
880 | seq_printf(m, "Lowest (RPN) frequency: %dMHz\n", | 910 | seq_printf(m, "Lowest (RPN) frequency: %dMHz\n", |
@@ -1259,7 +1289,7 @@ static int i915_wedged_create(struct dentry *root, struct drm_minor *minor) | |||
1259 | } | 1289 | } |
1260 | 1290 | ||
1261 | static struct drm_info_list i915_debugfs_list[] = { | 1291 | static struct drm_info_list i915_debugfs_list[] = { |
1262 | {"i915_capabilities", i915_capabilities, 0, 0}, | 1292 | {"i915_capabilities", i915_capabilities, 0}, |
1263 | {"i915_gem_objects", i915_gem_object_info, 0}, | 1293 | {"i915_gem_objects", i915_gem_object_info, 0}, |
1264 | {"i915_gem_gtt", i915_gem_gtt_info, 0}, | 1294 | {"i915_gem_gtt", i915_gem_gtt_info, 0}, |
1265 | {"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST}, | 1295 | {"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST}, |
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index e33d9be7df3..72730377a01 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
@@ -43,6 +43,17 @@ | |||
43 | #include <linux/slab.h> | 43 | #include <linux/slab.h> |
44 | #include <acpi/video.h> | 44 | #include <acpi/video.h> |
45 | 45 | ||
46 | static void i915_write_hws_pga(struct drm_device *dev) | ||
47 | { | ||
48 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
49 | u32 addr; | ||
50 | |||
51 | addr = dev_priv->status_page_dmah->busaddr; | ||
52 | if (INTEL_INFO(dev)->gen >= 4) | ||
53 | addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0; | ||
54 | I915_WRITE(HWS_PGA, addr); | ||
55 | } | ||
56 | |||
46 | /** | 57 | /** |
47 | * Sets up the hardware status page for devices that need a physical address | 58 | * Sets up the hardware status page for devices that need a physical address |
48 | * in the register. | 59 | * in the register. |
@@ -60,16 +71,13 @@ static int i915_init_phys_hws(struct drm_device *dev) | |||
60 | DRM_ERROR("Can not allocate hardware status page\n"); | 71 | DRM_ERROR("Can not allocate hardware status page\n"); |
61 | return -ENOMEM; | 72 | return -ENOMEM; |
62 | } | 73 | } |
63 | ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr; | 74 | ring->status_page.page_addr = |
64 | dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr; | 75 | (void __force __iomem *)dev_priv->status_page_dmah->vaddr; |
65 | 76 | ||
66 | memset(ring->status_page.page_addr, 0, PAGE_SIZE); | 77 | memset_io(ring->status_page.page_addr, 0, PAGE_SIZE); |
67 | 78 | ||
68 | if (INTEL_INFO(dev)->gen >= 4) | 79 | i915_write_hws_pga(dev); |
69 | dev_priv->dma_status_page |= (dev_priv->dma_status_page >> 28) & | ||
70 | 0xf0; | ||
71 | 80 | ||
72 | I915_WRITE(HWS_PGA, dev_priv->dma_status_page); | ||
73 | DRM_DEBUG_DRIVER("Enabled hardware status page\n"); | 81 | DRM_DEBUG_DRIVER("Enabled hardware status page\n"); |
74 | return 0; | 82 | return 0; |
75 | } | 83 | } |
@@ -216,7 +224,7 @@ static int i915_dma_resume(struct drm_device * dev) | |||
216 | if (ring->status_page.gfx_addr != 0) | 224 | if (ring->status_page.gfx_addr != 0) |
217 | intel_ring_setup_status_page(ring); | 225 | intel_ring_setup_status_page(ring); |
218 | else | 226 | else |
219 | I915_WRITE(HWS_PGA, dev_priv->dma_status_page); | 227 | i915_write_hws_pga(dev); |
220 | 228 | ||
221 | DRM_DEBUG_DRIVER("Enabled hardware status page\n"); | 229 | DRM_DEBUG_DRIVER("Enabled hardware status page\n"); |
222 | 230 | ||
@@ -771,6 +779,9 @@ static int i915_getparam(struct drm_device *dev, void *data, | |||
771 | case I915_PARAM_HAS_EXEC_CONSTANTS: | 779 | case I915_PARAM_HAS_EXEC_CONSTANTS: |
772 | value = INTEL_INFO(dev)->gen >= 4; | 780 | value = INTEL_INFO(dev)->gen >= 4; |
773 | break; | 781 | break; |
782 | case I915_PARAM_HAS_RELAXED_DELTA: | ||
783 | value = 1; | ||
784 | break; | ||
774 | default: | 785 | default: |
775 | DRM_DEBUG_DRIVER("Unknown parameter %d\n", | 786 | DRM_DEBUG_DRIVER("Unknown parameter %d\n", |
776 | param->param); | 787 | param->param); |
@@ -859,8 +870,9 @@ static int i915_set_status_page(struct drm_device *dev, void *data, | |||
859 | " G33 hw status page\n"); | 870 | " G33 hw status page\n"); |
860 | return -ENOMEM; | 871 | return -ENOMEM; |
861 | } | 872 | } |
862 | ring->status_page.page_addr = dev_priv->hws_map.handle; | 873 | ring->status_page.page_addr = |
863 | memset(ring->status_page.page_addr, 0, PAGE_SIZE); | 874 | (void __force __iomem *)dev_priv->hws_map.handle; |
875 | memset_io(ring->status_page.page_addr, 0, PAGE_SIZE); | ||
864 | I915_WRITE(HWS_PGA, ring->status_page.gfx_addr); | 876 | I915_WRITE(HWS_PGA, ring->status_page.gfx_addr); |
865 | 877 | ||
866 | DRM_DEBUG_DRIVER("load hws HWS_PGA with gfx mem 0x%x\n", | 878 | DRM_DEBUG_DRIVER("load hws HWS_PGA with gfx mem 0x%x\n", |
@@ -2013,9 +2025,13 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
2013 | 2025 | ||
2014 | spin_lock_init(&dev_priv->irq_lock); | 2026 | spin_lock_init(&dev_priv->irq_lock); |
2015 | spin_lock_init(&dev_priv->error_lock); | 2027 | spin_lock_init(&dev_priv->error_lock); |
2016 | dev_priv->trace_irq_seqno = 0; | ||
2017 | 2028 | ||
2018 | ret = drm_vblank_init(dev, I915_NUM_PIPE); | 2029 | if (IS_MOBILE(dev) || !IS_GEN2(dev)) |
2030 | dev_priv->num_pipe = 2; | ||
2031 | else | ||
2032 | dev_priv->num_pipe = 1; | ||
2033 | |||
2034 | ret = drm_vblank_init(dev, dev_priv->num_pipe); | ||
2019 | if (ret) | 2035 | if (ret) |
2020 | goto out_gem_unload; | 2036 | goto out_gem_unload; |
2021 | 2037 | ||
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 22ec066adae..c34a8dd31d0 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
@@ -43,10 +43,13 @@ module_param_named(modeset, i915_modeset, int, 0400); | |||
43 | unsigned int i915_fbpercrtc = 0; | 43 | unsigned int i915_fbpercrtc = 0; |
44 | module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400); | 44 | module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400); |
45 | 45 | ||
46 | int i915_panel_ignore_lid = 0; | ||
47 | module_param_named(panel_ignore_lid, i915_panel_ignore_lid, int, 0600); | ||
48 | |||
46 | unsigned int i915_powersave = 1; | 49 | unsigned int i915_powersave = 1; |
47 | module_param_named(powersave, i915_powersave, int, 0600); | 50 | module_param_named(powersave, i915_powersave, int, 0600); |
48 | 51 | ||
49 | unsigned int i915_semaphores = 0; | 52 | unsigned int i915_semaphores = 1; |
50 | module_param_named(semaphores, i915_semaphores, int, 0600); | 53 | module_param_named(semaphores, i915_semaphores, int, 0600); |
51 | 54 | ||
52 | unsigned int i915_enable_rc6 = 0; | 55 | unsigned int i915_enable_rc6 = 0; |
@@ -58,7 +61,10 @@ module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400); | |||
58 | unsigned int i915_panel_use_ssc = 1; | 61 | unsigned int i915_panel_use_ssc = 1; |
59 | module_param_named(lvds_use_ssc, i915_panel_use_ssc, int, 0600); | 62 | module_param_named(lvds_use_ssc, i915_panel_use_ssc, int, 0600); |
60 | 63 | ||
61 | bool i915_try_reset = true; | 64 | int i915_vbt_sdvo_panel_type = -1; |
65 | module_param_named(vbt_sdvo_panel_type, i915_vbt_sdvo_panel_type, int, 0600); | ||
66 | |||
67 | static bool i915_try_reset = true; | ||
62 | module_param_named(reset, i915_try_reset, bool, 0600); | 68 | module_param_named(reset, i915_try_reset, bool, 0600); |
63 | 69 | ||
64 | static struct drm_driver driver; | 70 | static struct drm_driver driver; |
@@ -716,6 +722,9 @@ static struct drm_driver driver = { | |||
716 | .gem_init_object = i915_gem_init_object, | 722 | .gem_init_object = i915_gem_init_object, |
717 | .gem_free_object = i915_gem_free_object, | 723 | .gem_free_object = i915_gem_free_object, |
718 | .gem_vm_ops = &i915_gem_vm_ops, | 724 | .gem_vm_ops = &i915_gem_vm_ops, |
725 | .dumb_create = i915_gem_dumb_create, | ||
726 | .dumb_map_offset = i915_gem_mmap_gtt, | ||
727 | .dumb_destroy = i915_gem_dumb_destroy, | ||
719 | .ioctls = i915_ioctls, | 728 | .ioctls = i915_ioctls, |
720 | .fops = { | 729 | .fops = { |
721 | .owner = THIS_MODULE, | 730 | .owner = THIS_MODULE, |
@@ -732,14 +741,6 @@ static struct drm_driver driver = { | |||
732 | .llseek = noop_llseek, | 741 | .llseek = noop_llseek, |
733 | }, | 742 | }, |
734 | 743 | ||
735 | .pci_driver = { | ||
736 | .name = DRIVER_NAME, | ||
737 | .id_table = pciidlist, | ||
738 | .probe = i915_pci_probe, | ||
739 | .remove = i915_pci_remove, | ||
740 | .driver.pm = &i915_pm_ops, | ||
741 | }, | ||
742 | |||
743 | .name = DRIVER_NAME, | 744 | .name = DRIVER_NAME, |
744 | .desc = DRIVER_DESC, | 745 | .desc = DRIVER_DESC, |
745 | .date = DRIVER_DATE, | 746 | .date = DRIVER_DATE, |
@@ -748,6 +749,14 @@ static struct drm_driver driver = { | |||
748 | .patchlevel = DRIVER_PATCHLEVEL, | 749 | .patchlevel = DRIVER_PATCHLEVEL, |
749 | }; | 750 | }; |
750 | 751 | ||
752 | static struct pci_driver i915_pci_driver = { | ||
753 | .name = DRIVER_NAME, | ||
754 | .id_table = pciidlist, | ||
755 | .probe = i915_pci_probe, | ||
756 | .remove = i915_pci_remove, | ||
757 | .driver.pm = &i915_pm_ops, | ||
758 | }; | ||
759 | |||
751 | static int __init i915_init(void) | 760 | static int __init i915_init(void) |
752 | { | 761 | { |
753 | if (!intel_agp_enabled) { | 762 | if (!intel_agp_enabled) { |
@@ -781,12 +790,12 @@ static int __init i915_init(void) | |||
781 | if (!(driver.driver_features & DRIVER_MODESET)) | 790 | if (!(driver.driver_features & DRIVER_MODESET)) |
782 | driver.get_vblank_timestamp = NULL; | 791 | driver.get_vblank_timestamp = NULL; |
783 | 792 | ||
784 | return drm_init(&driver); | 793 | return drm_pci_init(&driver, &i915_pci_driver); |
785 | } | 794 | } |
786 | 795 | ||
787 | static void __exit i915_exit(void) | 796 | static void __exit i915_exit(void) |
788 | { | 797 | { |
789 | drm_exit(&driver); | 798 | drm_pci_exit(&driver, &i915_pci_driver); |
790 | } | 799 | } |
791 | 800 | ||
792 | module_init(i915_init); | 801 | module_init(i915_init); |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 456f4048483..449650545bb 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -49,17 +49,22 @@ | |||
49 | enum pipe { | 49 | enum pipe { |
50 | PIPE_A = 0, | 50 | PIPE_A = 0, |
51 | PIPE_B, | 51 | PIPE_B, |
52 | PIPE_C, | ||
53 | I915_MAX_PIPES | ||
52 | }; | 54 | }; |
55 | #define pipe_name(p) ((p) + 'A') | ||
53 | 56 | ||
54 | enum plane { | 57 | enum plane { |
55 | PLANE_A = 0, | 58 | PLANE_A = 0, |
56 | PLANE_B, | 59 | PLANE_B, |
60 | PLANE_C, | ||
57 | }; | 61 | }; |
58 | 62 | #define plane_name(p) ((p) + 'A') | |
59 | #define I915_NUM_PIPE 2 | ||
60 | 63 | ||
61 | #define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT)) | 64 | #define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT)) |
62 | 65 | ||
66 | #define for_each_pipe(p) for ((p) = 0; (p) < dev_priv->num_pipe; (p)++) | ||
67 | |||
63 | /* Interface history: | 68 | /* Interface history: |
64 | * | 69 | * |
65 | * 1.1: Original. | 70 | * 1.1: Original. |
@@ -75,10 +80,7 @@ enum plane { | |||
75 | #define DRIVER_PATCHLEVEL 0 | 80 | #define DRIVER_PATCHLEVEL 0 |
76 | 81 | ||
77 | #define WATCH_COHERENCY 0 | 82 | #define WATCH_COHERENCY 0 |
78 | #define WATCH_EXEC 0 | ||
79 | #define WATCH_RELOC 0 | ||
80 | #define WATCH_LISTS 0 | 83 | #define WATCH_LISTS 0 |
81 | #define WATCH_PWRITE 0 | ||
82 | 84 | ||
83 | #define I915_GEM_PHYS_CURSOR_0 1 | 85 | #define I915_GEM_PHYS_CURSOR_0 1 |
84 | #define I915_GEM_PHYS_CURSOR_1 2 | 86 | #define I915_GEM_PHYS_CURSOR_1 2 |
@@ -111,6 +113,7 @@ struct intel_opregion { | |||
111 | struct opregion_swsci *swsci; | 113 | struct opregion_swsci *swsci; |
112 | struct opregion_asle *asle; | 114 | struct opregion_asle *asle; |
113 | void *vbt; | 115 | void *vbt; |
116 | u32 __iomem *lid_state; | ||
114 | }; | 117 | }; |
115 | #define OPREGION_SIZE (8*1024) | 118 | #define OPREGION_SIZE (8*1024) |
116 | 119 | ||
@@ -144,8 +147,7 @@ struct intel_display_error_state; | |||
144 | struct drm_i915_error_state { | 147 | struct drm_i915_error_state { |
145 | u32 eir; | 148 | u32 eir; |
146 | u32 pgtbl_er; | 149 | u32 pgtbl_er; |
147 | u32 pipeastat; | 150 | u32 pipestat[I915_MAX_PIPES]; |
148 | u32 pipebstat; | ||
149 | u32 ipeir; | 151 | u32 ipeir; |
150 | u32 ipehr; | 152 | u32 ipehr; |
151 | u32 instdone; | 153 | u32 instdone; |
@@ -172,7 +174,7 @@ struct drm_i915_error_state { | |||
172 | int page_count; | 174 | int page_count; |
173 | u32 gtt_offset; | 175 | u32 gtt_offset; |
174 | u32 *pages[0]; | 176 | u32 *pages[0]; |
175 | } *ringbuffer, *batchbuffer[I915_NUM_RINGS]; | 177 | } *ringbuffer[I915_NUM_RINGS], *batchbuffer[I915_NUM_RINGS]; |
176 | struct drm_i915_error_buffer { | 178 | struct drm_i915_error_buffer { |
177 | u32 size; | 179 | u32 size; |
178 | u32 name; | 180 | u32 name; |
@@ -200,9 +202,7 @@ struct drm_i915_display_funcs { | |||
200 | void (*disable_fbc)(struct drm_device *dev); | 202 | void (*disable_fbc)(struct drm_device *dev); |
201 | int (*get_display_clock_speed)(struct drm_device *dev); | 203 | int (*get_display_clock_speed)(struct drm_device *dev); |
202 | int (*get_fifo_size)(struct drm_device *dev, int plane); | 204 | int (*get_fifo_size)(struct drm_device *dev, int plane); |
203 | void (*update_wm)(struct drm_device *dev, int planea_clock, | 205 | void (*update_wm)(struct drm_device *dev); |
204 | int planeb_clock, int sr_hdisplay, int sr_htotal, | ||
205 | int pixel_size); | ||
206 | /* clock updates for mode set */ | 206 | /* clock updates for mode set */ |
207 | /* cursor updates */ | 207 | /* cursor updates */ |
208 | /* render clock increase/decrease */ | 208 | /* render clock increase/decrease */ |
@@ -274,7 +274,6 @@ typedef struct drm_i915_private { | |||
274 | uint32_t next_seqno; | 274 | uint32_t next_seqno; |
275 | 275 | ||
276 | drm_dma_handle_t *status_page_dmah; | 276 | drm_dma_handle_t *status_page_dmah; |
277 | dma_addr_t dma_status_page; | ||
278 | uint32_t counter; | 277 | uint32_t counter; |
279 | drm_local_map_t hws_map; | 278 | drm_local_map_t hws_map; |
280 | struct drm_i915_gem_object *pwrctx; | 279 | struct drm_i915_gem_object *pwrctx; |
@@ -289,7 +288,6 @@ typedef struct drm_i915_private { | |||
289 | int page_flipping; | 288 | int page_flipping; |
290 | 289 | ||
291 | atomic_t irq_received; | 290 | atomic_t irq_received; |
292 | u32 trace_irq_seqno; | ||
293 | 291 | ||
294 | /* protects the irq masks */ | 292 | /* protects the irq masks */ |
295 | spinlock_t irq_lock; | 293 | spinlock_t irq_lock; |
@@ -324,8 +322,6 @@ typedef struct drm_i915_private { | |||
324 | int cfb_plane; | 322 | int cfb_plane; |
325 | int cfb_y; | 323 | int cfb_y; |
326 | 324 | ||
327 | int irq_enabled; | ||
328 | |||
329 | struct intel_opregion opregion; | 325 | struct intel_opregion opregion; |
330 | 326 | ||
331 | /* overlay */ | 327 | /* overlay */ |
@@ -387,7 +383,6 @@ typedef struct drm_i915_private { | |||
387 | u32 saveDSPACNTR; | 383 | u32 saveDSPACNTR; |
388 | u32 saveDSPBCNTR; | 384 | u32 saveDSPBCNTR; |
389 | u32 saveDSPARB; | 385 | u32 saveDSPARB; |
390 | u32 saveHWS; | ||
391 | u32 savePIPEACONF; | 386 | u32 savePIPEACONF; |
392 | u32 savePIPEBCONF; | 387 | u32 savePIPEBCONF; |
393 | u32 savePIPEASRC; | 388 | u32 savePIPEASRC; |
@@ -615,6 +610,12 @@ typedef struct drm_i915_private { | |||
615 | struct delayed_work retire_work; | 610 | struct delayed_work retire_work; |
616 | 611 | ||
617 | /** | 612 | /** |
613 | * Are we in a non-interruptible section of code like | ||
614 | * modesetting? | ||
615 | */ | ||
616 | bool interruptible; | ||
617 | |||
618 | /** | ||
618 | * Flag if the X Server, and thus DRM, is not currently in | 619 | * Flag if the X Server, and thus DRM, is not currently in |
619 | * control of the device. | 620 | * control of the device. |
620 | * | 621 | * |
@@ -652,6 +653,7 @@ typedef struct drm_i915_private { | |||
652 | unsigned int lvds_border_bits; | 653 | unsigned int lvds_border_bits; |
653 | /* Panel fitter placement and size for Ironlake+ */ | 654 | /* Panel fitter placement and size for Ironlake+ */ |
654 | u32 pch_pf_pos, pch_pf_size; | 655 | u32 pch_pf_pos, pch_pf_size; |
656 | int panel_t3, panel_t12; | ||
655 | 657 | ||
656 | struct drm_crtc *plane_to_crtc_mapping[2]; | 658 | struct drm_crtc *plane_to_crtc_mapping[2]; |
657 | struct drm_crtc *pipe_to_crtc_mapping[2]; | 659 | struct drm_crtc *pipe_to_crtc_mapping[2]; |
@@ -698,6 +700,8 @@ typedef struct drm_i915_private { | |||
698 | 700 | ||
699 | /* list of fbdev register on this device */ | 701 | /* list of fbdev register on this device */ |
700 | struct intel_fbdev *fbdev; | 702 | struct intel_fbdev *fbdev; |
703 | |||
704 | struct drm_property *broadcast_rgb_property; | ||
701 | } drm_i915_private_t; | 705 | } drm_i915_private_t; |
702 | 706 | ||
703 | struct drm_i915_gem_object { | 707 | struct drm_i915_gem_object { |
@@ -955,10 +959,12 @@ enum intel_chip_family { | |||
955 | extern struct drm_ioctl_desc i915_ioctls[]; | 959 | extern struct drm_ioctl_desc i915_ioctls[]; |
956 | extern int i915_max_ioctl; | 960 | extern int i915_max_ioctl; |
957 | extern unsigned int i915_fbpercrtc; | 961 | extern unsigned int i915_fbpercrtc; |
962 | extern int i915_panel_ignore_lid; | ||
958 | extern unsigned int i915_powersave; | 963 | extern unsigned int i915_powersave; |
959 | extern unsigned int i915_semaphores; | 964 | extern unsigned int i915_semaphores; |
960 | extern unsigned int i915_lvds_downclock; | 965 | extern unsigned int i915_lvds_downclock; |
961 | extern unsigned int i915_panel_use_ssc; | 966 | extern unsigned int i915_panel_use_ssc; |
967 | extern int i915_vbt_sdvo_panel_type; | ||
962 | extern unsigned int i915_enable_rc6; | 968 | extern unsigned int i915_enable_rc6; |
963 | 969 | ||
964 | extern int i915_suspend(struct drm_device *dev, pm_message_t state); | 970 | extern int i915_suspend(struct drm_device *dev, pm_message_t state); |
@@ -998,8 +1004,6 @@ extern int i915_irq_emit(struct drm_device *dev, void *data, | |||
998 | struct drm_file *file_priv); | 1004 | struct drm_file *file_priv); |
999 | extern int i915_irq_wait(struct drm_device *dev, void *data, | 1005 | extern int i915_irq_wait(struct drm_device *dev, void *data, |
1000 | struct drm_file *file_priv); | 1006 | struct drm_file *file_priv); |
1001 | void i915_trace_irq_get(struct drm_device *dev, u32 seqno); | ||
1002 | extern void i915_enable_interrupt (struct drm_device *dev); | ||
1003 | 1007 | ||
1004 | extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); | 1008 | extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); |
1005 | extern void i915_driver_irq_preinstall(struct drm_device * dev); | 1009 | extern void i915_driver_irq_preinstall(struct drm_device * dev); |
@@ -1051,7 +1055,6 @@ extern void i915_mem_takedown(struct mem_block **heap); | |||
1051 | extern void i915_mem_release(struct drm_device * dev, | 1055 | extern void i915_mem_release(struct drm_device * dev, |
1052 | struct drm_file *file_priv, struct mem_block *heap); | 1056 | struct drm_file *file_priv, struct mem_block *heap); |
1053 | /* i915_gem.c */ | 1057 | /* i915_gem.c */ |
1054 | int i915_gem_check_is_wedged(struct drm_device *dev); | ||
1055 | int i915_gem_init_ioctl(struct drm_device *dev, void *data, | 1058 | int i915_gem_init_ioctl(struct drm_device *dev, void *data, |
1056 | struct drm_file *file_priv); | 1059 | struct drm_file *file_priv); |
1057 | int i915_gem_create_ioctl(struct drm_device *dev, void *data, | 1060 | int i915_gem_create_ioctl(struct drm_device *dev, void *data, |
@@ -1094,8 +1097,7 @@ int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, | |||
1094 | struct drm_file *file_priv); | 1097 | struct drm_file *file_priv); |
1095 | void i915_gem_load(struct drm_device *dev); | 1098 | void i915_gem_load(struct drm_device *dev); |
1096 | int i915_gem_init_object(struct drm_gem_object *obj); | 1099 | int i915_gem_init_object(struct drm_gem_object *obj); |
1097 | int __must_check i915_gem_flush_ring(struct drm_device *dev, | 1100 | int __must_check i915_gem_flush_ring(struct intel_ring_buffer *ring, |
1098 | struct intel_ring_buffer *ring, | ||
1099 | uint32_t invalidate_domains, | 1101 | uint32_t invalidate_domains, |
1100 | uint32_t flush_domains); | 1102 | uint32_t flush_domains); |
1101 | struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, | 1103 | struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, |
@@ -1110,12 +1112,18 @@ void i915_gem_release_mmap(struct drm_i915_gem_object *obj); | |||
1110 | void i915_gem_lastclose(struct drm_device *dev); | 1112 | void i915_gem_lastclose(struct drm_device *dev); |
1111 | 1113 | ||
1112 | int __must_check i915_mutex_lock_interruptible(struct drm_device *dev); | 1114 | int __must_check i915_mutex_lock_interruptible(struct drm_device *dev); |
1113 | int __must_check i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj, | 1115 | int __must_check i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj); |
1114 | bool interruptible); | ||
1115 | void i915_gem_object_move_to_active(struct drm_i915_gem_object *obj, | 1116 | void i915_gem_object_move_to_active(struct drm_i915_gem_object *obj, |
1116 | struct intel_ring_buffer *ring, | 1117 | struct intel_ring_buffer *ring, |
1117 | u32 seqno); | 1118 | u32 seqno); |
1118 | 1119 | ||
1120 | int i915_gem_dumb_create(struct drm_file *file_priv, | ||
1121 | struct drm_device *dev, | ||
1122 | struct drm_mode_create_dumb *args); | ||
1123 | int i915_gem_mmap_gtt(struct drm_file *file_priv, struct drm_device *dev, | ||
1124 | uint32_t handle, uint64_t *offset); | ||
1125 | int i915_gem_dumb_destroy(struct drm_file *file_priv, struct drm_device *dev, | ||
1126 | uint32_t handle); | ||
1119 | /** | 1127 | /** |
1120 | * Returns true if seq1 is later than seq2. | 1128 | * Returns true if seq1 is later than seq2. |
1121 | */ | 1129 | */ |
@@ -1126,16 +1134,14 @@ i915_seqno_passed(uint32_t seq1, uint32_t seq2) | |||
1126 | } | 1134 | } |
1127 | 1135 | ||
1128 | static inline u32 | 1136 | static inline u32 |
1129 | i915_gem_next_request_seqno(struct drm_device *dev, | 1137 | i915_gem_next_request_seqno(struct intel_ring_buffer *ring) |
1130 | struct intel_ring_buffer *ring) | ||
1131 | { | 1138 | { |
1132 | drm_i915_private_t *dev_priv = dev->dev_private; | 1139 | drm_i915_private_t *dev_priv = ring->dev->dev_private; |
1133 | return ring->outstanding_lazy_request = dev_priv->next_seqno; | 1140 | return ring->outstanding_lazy_request = dev_priv->next_seqno; |
1134 | } | 1141 | } |
1135 | 1142 | ||
1136 | int __must_check i915_gem_object_get_fence(struct drm_i915_gem_object *obj, | 1143 | int __must_check i915_gem_object_get_fence(struct drm_i915_gem_object *obj, |
1137 | struct intel_ring_buffer *pipelined, | 1144 | struct intel_ring_buffer *pipelined); |
1138 | bool interruptible); | ||
1139 | int __must_check i915_gem_object_put_fence(struct drm_i915_gem_object *obj); | 1145 | int __must_check i915_gem_object_put_fence(struct drm_i915_gem_object *obj); |
1140 | 1146 | ||
1141 | void i915_gem_retire_requests(struct drm_device *dev); | 1147 | void i915_gem_retire_requests(struct drm_device *dev); |
@@ -1144,8 +1150,7 @@ void i915_gem_clflush_object(struct drm_i915_gem_object *obj); | |||
1144 | int __must_check i915_gem_object_set_domain(struct drm_i915_gem_object *obj, | 1150 | int __must_check i915_gem_object_set_domain(struct drm_i915_gem_object *obj, |
1145 | uint32_t read_domains, | 1151 | uint32_t read_domains, |
1146 | uint32_t write_domain); | 1152 | uint32_t write_domain); |
1147 | int __must_check i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj, | 1153 | int __must_check i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj); |
1148 | bool interruptible); | ||
1149 | int __must_check i915_gem_init_ringbuffer(struct drm_device *dev); | 1154 | int __must_check i915_gem_init_ringbuffer(struct drm_device *dev); |
1150 | void i915_gem_cleanup_ringbuffer(struct drm_device *dev); | 1155 | void i915_gem_cleanup_ringbuffer(struct drm_device *dev); |
1151 | void i915_gem_do_init(struct drm_device *dev, | 1156 | void i915_gem_do_init(struct drm_device *dev, |
@@ -1154,14 +1159,11 @@ void i915_gem_do_init(struct drm_device *dev, | |||
1154 | unsigned long end); | 1159 | unsigned long end); |
1155 | int __must_check i915_gpu_idle(struct drm_device *dev); | 1160 | int __must_check i915_gpu_idle(struct drm_device *dev); |
1156 | int __must_check i915_gem_idle(struct drm_device *dev); | 1161 | int __must_check i915_gem_idle(struct drm_device *dev); |
1157 | int __must_check i915_add_request(struct drm_device *dev, | 1162 | int __must_check i915_add_request(struct intel_ring_buffer *ring, |
1158 | struct drm_file *file_priv, | 1163 | struct drm_file *file, |
1159 | struct drm_i915_gem_request *request, | 1164 | struct drm_i915_gem_request *request); |
1160 | struct intel_ring_buffer *ring); | 1165 | int __must_check i915_wait_request(struct intel_ring_buffer *ring, |
1161 | int __must_check i915_do_wait_request(struct drm_device *dev, | 1166 | uint32_t seqno); |
1162 | uint32_t seqno, | ||
1163 | bool interruptible, | ||
1164 | struct intel_ring_buffer *ring); | ||
1165 | int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); | 1167 | int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); |
1166 | int __must_check | 1168 | int __must_check |
1167 | i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, | 1169 | i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, |
@@ -1313,7 +1315,7 @@ extern void intel_display_print_error_state(struct seq_file *m, | |||
1313 | #define __i915_read(x, y) \ | 1315 | #define __i915_read(x, y) \ |
1314 | static inline u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ | 1316 | static inline u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ |
1315 | u##x val = read##y(dev_priv->regs + reg); \ | 1317 | u##x val = read##y(dev_priv->regs + reg); \ |
1316 | trace_i915_reg_rw('R', reg, val, sizeof(val)); \ | 1318 | trace_i915_reg_rw(false, reg, val, sizeof(val)); \ |
1317 | return val; \ | 1319 | return val; \ |
1318 | } | 1320 | } |
1319 | __i915_read(8, b) | 1321 | __i915_read(8, b) |
@@ -1324,7 +1326,7 @@ __i915_read(64, q) | |||
1324 | 1326 | ||
1325 | #define __i915_write(x, y) \ | 1327 | #define __i915_write(x, y) \ |
1326 | static inline void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \ | 1328 | static inline void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \ |
1327 | trace_i915_reg_rw('W', reg, val, sizeof(val)); \ | 1329 | trace_i915_reg_rw(true, reg, val, sizeof(val)); \ |
1328 | write##y(val, dev_priv->regs + reg); \ | 1330 | write##y(val, dev_priv->regs + reg); \ |
1329 | } | 1331 | } |
1330 | __i915_write(8, b) | 1332 | __i915_write(8, b) |
@@ -1382,47 +1384,4 @@ static inline void i915_gt_write(struct drm_i915_private *dev_priv, | |||
1382 | __gen6_gt_wait_for_fifo(dev_priv); | 1384 | __gen6_gt_wait_for_fifo(dev_priv); |
1383 | I915_WRITE(reg, val); | 1385 | I915_WRITE(reg, val); |
1384 | } | 1386 | } |
1385 | |||
1386 | static inline void | ||
1387 | i915_write(struct drm_i915_private *dev_priv, u32 reg, u64 val, int len) | ||
1388 | { | ||
1389 | /* Trace down the write operation before the real write */ | ||
1390 | trace_i915_reg_rw('W', reg, val, len); | ||
1391 | switch (len) { | ||
1392 | case 8: | ||
1393 | writeq(val, dev_priv->regs + reg); | ||
1394 | break; | ||
1395 | case 4: | ||
1396 | writel(val, dev_priv->regs + reg); | ||
1397 | break; | ||
1398 | case 2: | ||
1399 | writew(val, dev_priv->regs + reg); | ||
1400 | break; | ||
1401 | case 1: | ||
1402 | writeb(val, dev_priv->regs + reg); | ||
1403 | break; | ||
1404 | } | ||
1405 | } | ||
1406 | |||
1407 | /** | ||
1408 | * Reads a dword out of the status page, which is written to from the command | ||
1409 | * queue by automatic updates, MI_REPORT_HEAD, MI_STORE_DATA_INDEX, or | ||
1410 | * MI_STORE_DATA_IMM. | ||
1411 | * | ||
1412 | * The following dwords have a reserved meaning: | ||
1413 | * 0x00: ISR copy, updated when an ISR bit not set in the HWSTAM changes. | ||
1414 | * 0x04: ring 0 head pointer | ||
1415 | * 0x05: ring 1 head pointer (915-class) | ||
1416 | * 0x06: ring 2 head pointer (915-class) | ||
1417 | * 0x10-0x1b: Context status DWords (GM45) | ||
1418 | * 0x1f: Last written status offset. (GM45) | ||
1419 | * | ||
1420 | * The area from dword 0x20 to 0x3ff is available for driver usage. | ||
1421 | */ | ||
1422 | #define READ_HWSP(dev_priv, reg) (((volatile u32 *)\ | ||
1423 | (LP_RING(dev_priv)->status_page.page_addr))[reg]) | ||
1424 | #define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, I915_BREADCRUMB_INDEX) | ||
1425 | #define I915_GEM_HWS_INDEX 0x20 | ||
1426 | #define I915_BREADCRUMB_INDEX 0x21 | ||
1427 | |||
1428 | #endif | 1387 | #endif |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 36e66cc5225..c4c2855d002 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -75,8 +75,8 @@ static void i915_gem_info_remove_obj(struct drm_i915_private *dev_priv, | |||
75 | dev_priv->mm.object_memory -= size; | 75 | dev_priv->mm.object_memory -= size; |
76 | } | 76 | } |
77 | 77 | ||
78 | int | 78 | static int |
79 | i915_gem_check_is_wedged(struct drm_device *dev) | 79 | i915_gem_wait_for_error(struct drm_device *dev) |
80 | { | 80 | { |
81 | struct drm_i915_private *dev_priv = dev->dev_private; | 81 | struct drm_i915_private *dev_priv = dev->dev_private; |
82 | struct completion *x = &dev_priv->error_completion; | 82 | struct completion *x = &dev_priv->error_completion; |
@@ -90,27 +90,24 @@ i915_gem_check_is_wedged(struct drm_device *dev) | |||
90 | if (ret) | 90 | if (ret) |
91 | return ret; | 91 | return ret; |
92 | 92 | ||
93 | /* Success, we reset the GPU! */ | 93 | if (atomic_read(&dev_priv->mm.wedged)) { |
94 | if (!atomic_read(&dev_priv->mm.wedged)) | 94 | /* GPU is hung, bump the completion count to account for |
95 | return 0; | 95 | * the token we just consumed so that we never hit zero and |
96 | 96 | * end up waiting upon a subsequent completion event that | |
97 | /* GPU is hung, bump the completion count to account for | 97 | * will never happen. |
98 | * the token we just consumed so that we never hit zero and | 98 | */ |
99 | * end up waiting upon a subsequent completion event that | 99 | spin_lock_irqsave(&x->wait.lock, flags); |
100 | * will never happen. | 100 | x->done++; |
101 | */ | 101 | spin_unlock_irqrestore(&x->wait.lock, flags); |
102 | spin_lock_irqsave(&x->wait.lock, flags); | 102 | } |
103 | x->done++; | 103 | return 0; |
104 | spin_unlock_irqrestore(&x->wait.lock, flags); | ||
105 | return -EIO; | ||
106 | } | 104 | } |
107 | 105 | ||
108 | int i915_mutex_lock_interruptible(struct drm_device *dev) | 106 | int i915_mutex_lock_interruptible(struct drm_device *dev) |
109 | { | 107 | { |
110 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
111 | int ret; | 108 | int ret; |
112 | 109 | ||
113 | ret = i915_gem_check_is_wedged(dev); | 110 | ret = i915_gem_wait_for_error(dev); |
114 | if (ret) | 111 | if (ret) |
115 | return ret; | 112 | return ret; |
116 | 113 | ||
@@ -118,11 +115,6 @@ int i915_mutex_lock_interruptible(struct drm_device *dev) | |||
118 | if (ret) | 115 | if (ret) |
119 | return ret; | 116 | return ret; |
120 | 117 | ||
121 | if (atomic_read(&dev_priv->mm.wedged)) { | ||
122 | mutex_unlock(&dev->struct_mutex); | ||
123 | return -EAGAIN; | ||
124 | } | ||
125 | |||
126 | WARN_ON(i915_verify_lists(dev)); | 118 | WARN_ON(i915_verify_lists(dev)); |
127 | return 0; | 119 | return 0; |
128 | } | 120 | } |
@@ -193,22 +185,20 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, | |||
193 | return 0; | 185 | return 0; |
194 | } | 186 | } |
195 | 187 | ||
196 | /** | 188 | static int |
197 | * Creates a new mm object and returns a handle to it. | 189 | i915_gem_create(struct drm_file *file, |
198 | */ | 190 | struct drm_device *dev, |
199 | int | 191 | uint64_t size, |
200 | i915_gem_create_ioctl(struct drm_device *dev, void *data, | 192 | uint32_t *handle_p) |
201 | struct drm_file *file) | ||
202 | { | 193 | { |
203 | struct drm_i915_gem_create *args = data; | ||
204 | struct drm_i915_gem_object *obj; | 194 | struct drm_i915_gem_object *obj; |
205 | int ret; | 195 | int ret; |
206 | u32 handle; | 196 | u32 handle; |
207 | 197 | ||
208 | args->size = roundup(args->size, PAGE_SIZE); | 198 | size = roundup(size, PAGE_SIZE); |
209 | 199 | ||
210 | /* Allocate the new object */ | 200 | /* Allocate the new object */ |
211 | obj = i915_gem_alloc_object(dev, args->size); | 201 | obj = i915_gem_alloc_object(dev, size); |
212 | if (obj == NULL) | 202 | if (obj == NULL) |
213 | return -ENOMEM; | 203 | return -ENOMEM; |
214 | 204 | ||
@@ -224,10 +214,41 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data, | |||
224 | drm_gem_object_unreference(&obj->base); | 214 | drm_gem_object_unreference(&obj->base); |
225 | trace_i915_gem_object_create(obj); | 215 | trace_i915_gem_object_create(obj); |
226 | 216 | ||
227 | args->handle = handle; | 217 | *handle_p = handle; |
228 | return 0; | 218 | return 0; |
229 | } | 219 | } |
230 | 220 | ||
221 | int | ||
222 | i915_gem_dumb_create(struct drm_file *file, | ||
223 | struct drm_device *dev, | ||
224 | struct drm_mode_create_dumb *args) | ||
225 | { | ||
226 | /* have to work out size/pitch and return them */ | ||
227 | args->pitch = ALIGN(args->width & ((args->bpp + 1) / 8), 64); | ||
228 | args->size = args->pitch * args->height; | ||
229 | return i915_gem_create(file, dev, | ||
230 | args->size, &args->handle); | ||
231 | } | ||
232 | |||
233 | int i915_gem_dumb_destroy(struct drm_file *file, | ||
234 | struct drm_device *dev, | ||
235 | uint32_t handle) | ||
236 | { | ||
237 | return drm_gem_handle_delete(file, handle); | ||
238 | } | ||
239 | |||
240 | /** | ||
241 | * Creates a new mm object and returns a handle to it. | ||
242 | */ | ||
243 | int | ||
244 | i915_gem_create_ioctl(struct drm_device *dev, void *data, | ||
245 | struct drm_file *file) | ||
246 | { | ||
247 | struct drm_i915_gem_create *args = data; | ||
248 | return i915_gem_create(file, dev, | ||
249 | args->size, &args->handle); | ||
250 | } | ||
251 | |||
231 | static int i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj) | 252 | static int i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj) |
232 | { | 253 | { |
233 | drm_i915_private_t *dev_priv = obj->base.dev->dev_private; | 254 | drm_i915_private_t *dev_priv = obj->base.dev->dev_private; |
@@ -514,7 +535,7 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, | |||
514 | return ret; | 535 | return ret; |
515 | 536 | ||
516 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); | 537 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); |
517 | if (obj == NULL) { | 538 | if (&obj->base == NULL) { |
518 | ret = -ENOENT; | 539 | ret = -ENOENT; |
519 | goto unlock; | 540 | goto unlock; |
520 | } | 541 | } |
@@ -526,6 +547,8 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, | |||
526 | goto out; | 547 | goto out; |
527 | } | 548 | } |
528 | 549 | ||
550 | trace_i915_gem_object_pread(obj, args->offset, args->size); | ||
551 | |||
529 | ret = i915_gem_object_set_cpu_read_domain_range(obj, | 552 | ret = i915_gem_object_set_cpu_read_domain_range(obj, |
530 | args->offset, | 553 | args->offset, |
531 | args->size); | 554 | args->size); |
@@ -955,7 +978,7 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, | |||
955 | return ret; | 978 | return ret; |
956 | 979 | ||
957 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); | 980 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); |
958 | if (obj == NULL) { | 981 | if (&obj->base == NULL) { |
959 | ret = -ENOENT; | 982 | ret = -ENOENT; |
960 | goto unlock; | 983 | goto unlock; |
961 | } | 984 | } |
@@ -967,6 +990,8 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, | |||
967 | goto out; | 990 | goto out; |
968 | } | 991 | } |
969 | 992 | ||
993 | trace_i915_gem_object_pwrite(obj, args->offset, args->size); | ||
994 | |||
970 | /* We can only do the GTT pwrite on untiled buffers, as otherwise | 995 | /* We can only do the GTT pwrite on untiled buffers, as otherwise |
971 | * it would end up going through the fenced access, and we'll get | 996 | * it would end up going through the fenced access, and we'll get |
972 | * different detiling behavior between reading and writing. | 997 | * different detiling behavior between reading and writing. |
@@ -1049,7 +1074,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, | |||
1049 | return ret; | 1074 | return ret; |
1050 | 1075 | ||
1051 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); | 1076 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); |
1052 | if (obj == NULL) { | 1077 | if (&obj->base == NULL) { |
1053 | ret = -ENOENT; | 1078 | ret = -ENOENT; |
1054 | goto unlock; | 1079 | goto unlock; |
1055 | } | 1080 | } |
@@ -1092,7 +1117,7 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, | |||
1092 | return ret; | 1117 | return ret; |
1093 | 1118 | ||
1094 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); | 1119 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); |
1095 | if (obj == NULL) { | 1120 | if (&obj->base == NULL) { |
1096 | ret = -ENOENT; | 1121 | ret = -ENOENT; |
1097 | goto unlock; | 1122 | goto unlock; |
1098 | } | 1123 | } |
@@ -1121,7 +1146,6 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data, | |||
1121 | struct drm_i915_private *dev_priv = dev->dev_private; | 1146 | struct drm_i915_private *dev_priv = dev->dev_private; |
1122 | struct drm_i915_gem_mmap *args = data; | 1147 | struct drm_i915_gem_mmap *args = data; |
1123 | struct drm_gem_object *obj; | 1148 | struct drm_gem_object *obj; |
1124 | loff_t offset; | ||
1125 | unsigned long addr; | 1149 | unsigned long addr; |
1126 | 1150 | ||
1127 | if (!(dev->driver->driver_features & DRIVER_GEM)) | 1151 | if (!(dev->driver->driver_features & DRIVER_GEM)) |
@@ -1136,8 +1160,6 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data, | |||
1136 | return -E2BIG; | 1160 | return -E2BIG; |
1137 | } | 1161 | } |
1138 | 1162 | ||
1139 | offset = args->offset; | ||
1140 | |||
1141 | down_write(¤t->mm->mmap_sem); | 1163 | down_write(¤t->mm->mmap_sem); |
1142 | addr = do_mmap(obj->filp, 0, args->size, | 1164 | addr = do_mmap(obj->filp, 0, args->size, |
1143 | PROT_READ | PROT_WRITE, MAP_SHARED, | 1165 | PROT_READ | PROT_WRITE, MAP_SHARED, |
@@ -1182,9 +1204,13 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
1182 | page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >> | 1204 | page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >> |
1183 | PAGE_SHIFT; | 1205 | PAGE_SHIFT; |
1184 | 1206 | ||
1185 | /* Now bind it into the GTT if needed */ | 1207 | ret = i915_mutex_lock_interruptible(dev); |
1186 | mutex_lock(&dev->struct_mutex); | 1208 | if (ret) |
1209 | goto out; | ||
1187 | 1210 | ||
1211 | trace_i915_gem_object_fault(obj, page_offset, true, write); | ||
1212 | |||
1213 | /* Now bind it into the GTT if needed */ | ||
1188 | if (!obj->map_and_fenceable) { | 1214 | if (!obj->map_and_fenceable) { |
1189 | ret = i915_gem_object_unbind(obj); | 1215 | ret = i915_gem_object_unbind(obj); |
1190 | if (ret) | 1216 | if (ret) |
@@ -1203,7 +1229,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
1203 | if (obj->tiling_mode == I915_TILING_NONE) | 1229 | if (obj->tiling_mode == I915_TILING_NONE) |
1204 | ret = i915_gem_object_put_fence(obj); | 1230 | ret = i915_gem_object_put_fence(obj); |
1205 | else | 1231 | else |
1206 | ret = i915_gem_object_get_fence(obj, NULL, true); | 1232 | ret = i915_gem_object_get_fence(obj, NULL); |
1207 | if (ret) | 1233 | if (ret) |
1208 | goto unlock; | 1234 | goto unlock; |
1209 | 1235 | ||
@@ -1219,12 +1245,21 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
1219 | ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn); | 1245 | ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn); |
1220 | unlock: | 1246 | unlock: |
1221 | mutex_unlock(&dev->struct_mutex); | 1247 | mutex_unlock(&dev->struct_mutex); |
1222 | 1248 | out: | |
1223 | switch (ret) { | 1249 | switch (ret) { |
1250 | case -EIO: | ||
1224 | case -EAGAIN: | 1251 | case -EAGAIN: |
1252 | /* Give the error handler a chance to run and move the | ||
1253 | * objects off the GPU active list. Next time we service the | ||
1254 | * fault, we should be able to transition the page into the | ||
1255 | * GTT without touching the GPU (and so avoid further | ||
1256 | * EIO/EGAIN). If the GPU is wedged, then there is no issue | ||
1257 | * with coherency, just lost writes. | ||
1258 | */ | ||
1225 | set_need_resched(); | 1259 | set_need_resched(); |
1226 | case 0: | 1260 | case 0: |
1227 | case -ERESTARTSYS: | 1261 | case -ERESTARTSYS: |
1262 | case -EINTR: | ||
1228 | return VM_FAULT_NOPAGE; | 1263 | return VM_FAULT_NOPAGE; |
1229 | case -ENOMEM: | 1264 | case -ENOMEM: |
1230 | return VM_FAULT_OOM; | 1265 | return VM_FAULT_OOM; |
@@ -1425,27 +1460,13 @@ i915_gem_get_unfenced_gtt_alignment(struct drm_i915_gem_object *obj) | |||
1425 | return tile_height * obj->stride * 2; | 1460 | return tile_height * obj->stride * 2; |
1426 | } | 1461 | } |
1427 | 1462 | ||
1428 | /** | ||
1429 | * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing | ||
1430 | * @dev: DRM device | ||
1431 | * @data: GTT mapping ioctl data | ||
1432 | * @file: GEM object info | ||
1433 | * | ||
1434 | * Simply returns the fake offset to userspace so it can mmap it. | ||
1435 | * The mmap call will end up in drm_gem_mmap(), which will set things | ||
1436 | * up so we can get faults in the handler above. | ||
1437 | * | ||
1438 | * The fault handler will take care of binding the object into the GTT | ||
1439 | * (since it may have been evicted to make room for something), allocating | ||
1440 | * a fence register, and mapping the appropriate aperture address into | ||
1441 | * userspace. | ||
1442 | */ | ||
1443 | int | 1463 | int |
1444 | i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, | 1464 | i915_gem_mmap_gtt(struct drm_file *file, |
1445 | struct drm_file *file) | 1465 | struct drm_device *dev, |
1466 | uint32_t handle, | ||
1467 | uint64_t *offset) | ||
1446 | { | 1468 | { |
1447 | struct drm_i915_private *dev_priv = dev->dev_private; | 1469 | struct drm_i915_private *dev_priv = dev->dev_private; |
1448 | struct drm_i915_gem_mmap_gtt *args = data; | ||
1449 | struct drm_i915_gem_object *obj; | 1470 | struct drm_i915_gem_object *obj; |
1450 | int ret; | 1471 | int ret; |
1451 | 1472 | ||
@@ -1456,8 +1477,8 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, | |||
1456 | if (ret) | 1477 | if (ret) |
1457 | return ret; | 1478 | return ret; |
1458 | 1479 | ||
1459 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); | 1480 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, handle)); |
1460 | if (obj == NULL) { | 1481 | if (&obj->base == NULL) { |
1461 | ret = -ENOENT; | 1482 | ret = -ENOENT; |
1462 | goto unlock; | 1483 | goto unlock; |
1463 | } | 1484 | } |
@@ -1479,7 +1500,7 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, | |||
1479 | goto out; | 1500 | goto out; |
1480 | } | 1501 | } |
1481 | 1502 | ||
1482 | args->offset = (u64)obj->base.map_list.hash.key << PAGE_SHIFT; | 1503 | *offset = (u64)obj->base.map_list.hash.key << PAGE_SHIFT; |
1483 | 1504 | ||
1484 | out: | 1505 | out: |
1485 | drm_gem_object_unreference(&obj->base); | 1506 | drm_gem_object_unreference(&obj->base); |
@@ -1488,6 +1509,34 @@ unlock: | |||
1488 | return ret; | 1509 | return ret; |
1489 | } | 1510 | } |
1490 | 1511 | ||
1512 | /** | ||
1513 | * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing | ||
1514 | * @dev: DRM device | ||
1515 | * @data: GTT mapping ioctl data | ||
1516 | * @file: GEM object info | ||
1517 | * | ||
1518 | * Simply returns the fake offset to userspace so it can mmap it. | ||
1519 | * The mmap call will end up in drm_gem_mmap(), which will set things | ||
1520 | * up so we can get faults in the handler above. | ||
1521 | * | ||
1522 | * The fault handler will take care of binding the object into the GTT | ||
1523 | * (since it may have been evicted to make room for something), allocating | ||
1524 | * a fence register, and mapping the appropriate aperture address into | ||
1525 | * userspace. | ||
1526 | */ | ||
1527 | int | ||
1528 | i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, | ||
1529 | struct drm_file *file) | ||
1530 | { | ||
1531 | struct drm_i915_gem_mmap_gtt *args = data; | ||
1532 | |||
1533 | if (!(dev->driver->driver_features & DRIVER_GEM)) | ||
1534 | return -ENODEV; | ||
1535 | |||
1536 | return i915_gem_mmap_gtt(file, dev, args->handle, &args->offset); | ||
1537 | } | ||
1538 | |||
1539 | |||
1491 | static int | 1540 | static int |
1492 | i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj, | 1541 | i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj, |
1493 | gfp_t gfpmask) | 1542 | gfp_t gfpmask) |
@@ -1669,9 +1718,8 @@ i915_gem_object_is_purgeable(struct drm_i915_gem_object *obj) | |||
1669 | } | 1718 | } |
1670 | 1719 | ||
1671 | static void | 1720 | static void |
1672 | i915_gem_process_flushing_list(struct drm_device *dev, | 1721 | i915_gem_process_flushing_list(struct intel_ring_buffer *ring, |
1673 | uint32_t flush_domains, | 1722 | uint32_t flush_domains) |
1674 | struct intel_ring_buffer *ring) | ||
1675 | { | 1723 | { |
1676 | struct drm_i915_gem_object *obj, *next; | 1724 | struct drm_i915_gem_object *obj, *next; |
1677 | 1725 | ||
@@ -1684,7 +1732,7 @@ i915_gem_process_flushing_list(struct drm_device *dev, | |||
1684 | obj->base.write_domain = 0; | 1732 | obj->base.write_domain = 0; |
1685 | list_del_init(&obj->gpu_write_list); | 1733 | list_del_init(&obj->gpu_write_list); |
1686 | i915_gem_object_move_to_active(obj, ring, | 1734 | i915_gem_object_move_to_active(obj, ring, |
1687 | i915_gem_next_request_seqno(dev, ring)); | 1735 | i915_gem_next_request_seqno(ring)); |
1688 | 1736 | ||
1689 | trace_i915_gem_object_change_domain(obj, | 1737 | trace_i915_gem_object_change_domain(obj, |
1690 | obj->base.read_domains, | 1738 | obj->base.read_domains, |
@@ -1694,27 +1742,22 @@ i915_gem_process_flushing_list(struct drm_device *dev, | |||
1694 | } | 1742 | } |
1695 | 1743 | ||
1696 | int | 1744 | int |
1697 | i915_add_request(struct drm_device *dev, | 1745 | i915_add_request(struct intel_ring_buffer *ring, |
1698 | struct drm_file *file, | 1746 | struct drm_file *file, |
1699 | struct drm_i915_gem_request *request, | 1747 | struct drm_i915_gem_request *request) |
1700 | struct intel_ring_buffer *ring) | ||
1701 | { | 1748 | { |
1702 | drm_i915_private_t *dev_priv = dev->dev_private; | 1749 | drm_i915_private_t *dev_priv = ring->dev->dev_private; |
1703 | struct drm_i915_file_private *file_priv = NULL; | ||
1704 | uint32_t seqno; | 1750 | uint32_t seqno; |
1705 | int was_empty; | 1751 | int was_empty; |
1706 | int ret; | 1752 | int ret; |
1707 | 1753 | ||
1708 | BUG_ON(request == NULL); | 1754 | BUG_ON(request == NULL); |
1709 | 1755 | ||
1710 | if (file != NULL) | ||
1711 | file_priv = file->driver_priv; | ||
1712 | |||
1713 | ret = ring->add_request(ring, &seqno); | 1756 | ret = ring->add_request(ring, &seqno); |
1714 | if (ret) | 1757 | if (ret) |
1715 | return ret; | 1758 | return ret; |
1716 | 1759 | ||
1717 | ring->outstanding_lazy_request = false; | 1760 | trace_i915_gem_request_add(ring, seqno); |
1718 | 1761 | ||
1719 | request->seqno = seqno; | 1762 | request->seqno = seqno; |
1720 | request->ring = ring; | 1763 | request->ring = ring; |
@@ -1722,7 +1765,9 @@ i915_add_request(struct drm_device *dev, | |||
1722 | was_empty = list_empty(&ring->request_list); | 1765 | was_empty = list_empty(&ring->request_list); |
1723 | list_add_tail(&request->list, &ring->request_list); | 1766 | list_add_tail(&request->list, &ring->request_list); |
1724 | 1767 | ||
1725 | if (file_priv) { | 1768 | if (file) { |
1769 | struct drm_i915_file_private *file_priv = file->driver_priv; | ||
1770 | |||
1726 | spin_lock(&file_priv->mm.lock); | 1771 | spin_lock(&file_priv->mm.lock); |
1727 | request->file_priv = file_priv; | 1772 | request->file_priv = file_priv; |
1728 | list_add_tail(&request->client_list, | 1773 | list_add_tail(&request->client_list, |
@@ -1730,6 +1775,8 @@ i915_add_request(struct drm_device *dev, | |||
1730 | spin_unlock(&file_priv->mm.lock); | 1775 | spin_unlock(&file_priv->mm.lock); |
1731 | } | 1776 | } |
1732 | 1777 | ||
1778 | ring->outstanding_lazy_request = false; | ||
1779 | |||
1733 | if (!dev_priv->mm.suspended) { | 1780 | if (!dev_priv->mm.suspended) { |
1734 | mod_timer(&dev_priv->hangcheck_timer, | 1781 | mod_timer(&dev_priv->hangcheck_timer, |
1735 | jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)); | 1782 | jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)); |
@@ -1846,18 +1893,15 @@ void i915_gem_reset(struct drm_device *dev) | |||
1846 | * This function clears the request list as sequence numbers are passed. | 1893 | * This function clears the request list as sequence numbers are passed. |
1847 | */ | 1894 | */ |
1848 | static void | 1895 | static void |
1849 | i915_gem_retire_requests_ring(struct drm_device *dev, | 1896 | i915_gem_retire_requests_ring(struct intel_ring_buffer *ring) |
1850 | struct intel_ring_buffer *ring) | ||
1851 | { | 1897 | { |
1852 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
1853 | uint32_t seqno; | 1898 | uint32_t seqno; |
1854 | int i; | 1899 | int i; |
1855 | 1900 | ||
1856 | if (!ring->status_page.page_addr || | 1901 | if (list_empty(&ring->request_list)) |
1857 | list_empty(&ring->request_list)) | ||
1858 | return; | 1902 | return; |
1859 | 1903 | ||
1860 | WARN_ON(i915_verify_lists(dev)); | 1904 | WARN_ON(i915_verify_lists(ring->dev)); |
1861 | 1905 | ||
1862 | seqno = ring->get_seqno(ring); | 1906 | seqno = ring->get_seqno(ring); |
1863 | 1907 | ||
@@ -1875,7 +1919,7 @@ i915_gem_retire_requests_ring(struct drm_device *dev, | |||
1875 | if (!i915_seqno_passed(seqno, request->seqno)) | 1919 | if (!i915_seqno_passed(seqno, request->seqno)) |
1876 | break; | 1920 | break; |
1877 | 1921 | ||
1878 | trace_i915_gem_request_retire(dev, request->seqno); | 1922 | trace_i915_gem_request_retire(ring, request->seqno); |
1879 | 1923 | ||
1880 | list_del(&request->list); | 1924 | list_del(&request->list); |
1881 | i915_gem_request_remove_from_client(request); | 1925 | i915_gem_request_remove_from_client(request); |
@@ -1901,13 +1945,13 @@ i915_gem_retire_requests_ring(struct drm_device *dev, | |||
1901 | i915_gem_object_move_to_inactive(obj); | 1945 | i915_gem_object_move_to_inactive(obj); |
1902 | } | 1946 | } |
1903 | 1947 | ||
1904 | if (unlikely (dev_priv->trace_irq_seqno && | 1948 | if (unlikely(ring->trace_irq_seqno && |
1905 | i915_seqno_passed(dev_priv->trace_irq_seqno, seqno))) { | 1949 | i915_seqno_passed(seqno, ring->trace_irq_seqno))) { |
1906 | ring->irq_put(ring); | 1950 | ring->irq_put(ring); |
1907 | dev_priv->trace_irq_seqno = 0; | 1951 | ring->trace_irq_seqno = 0; |
1908 | } | 1952 | } |
1909 | 1953 | ||
1910 | WARN_ON(i915_verify_lists(dev)); | 1954 | WARN_ON(i915_verify_lists(ring->dev)); |
1911 | } | 1955 | } |
1912 | 1956 | ||
1913 | void | 1957 | void |
@@ -1931,7 +1975,7 @@ i915_gem_retire_requests(struct drm_device *dev) | |||
1931 | } | 1975 | } |
1932 | 1976 | ||
1933 | for (i = 0; i < I915_NUM_RINGS; i++) | 1977 | for (i = 0; i < I915_NUM_RINGS; i++) |
1934 | i915_gem_retire_requests_ring(dev, &dev_priv->ring[i]); | 1978 | i915_gem_retire_requests_ring(&dev_priv->ring[i]); |
1935 | } | 1979 | } |
1936 | 1980 | ||
1937 | static void | 1981 | static void |
@@ -1965,11 +2009,11 @@ i915_gem_retire_work_handler(struct work_struct *work) | |||
1965 | struct drm_i915_gem_request *request; | 2009 | struct drm_i915_gem_request *request; |
1966 | int ret; | 2010 | int ret; |
1967 | 2011 | ||
1968 | ret = i915_gem_flush_ring(dev, ring, 0, | 2012 | ret = i915_gem_flush_ring(ring, |
1969 | I915_GEM_GPU_DOMAINS); | 2013 | 0, I915_GEM_GPU_DOMAINS); |
1970 | request = kzalloc(sizeof(*request), GFP_KERNEL); | 2014 | request = kzalloc(sizeof(*request), GFP_KERNEL); |
1971 | if (ret || request == NULL || | 2015 | if (ret || request == NULL || |
1972 | i915_add_request(dev, NULL, request, ring)) | 2016 | i915_add_request(ring, NULL, request)) |
1973 | kfree(request); | 2017 | kfree(request); |
1974 | } | 2018 | } |
1975 | 2019 | ||
@@ -1982,18 +2026,32 @@ i915_gem_retire_work_handler(struct work_struct *work) | |||
1982 | mutex_unlock(&dev->struct_mutex); | 2026 | mutex_unlock(&dev->struct_mutex); |
1983 | } | 2027 | } |
1984 | 2028 | ||
2029 | /** | ||
2030 | * Waits for a sequence number to be signaled, and cleans up the | ||
2031 | * request and object lists appropriately for that event. | ||
2032 | */ | ||
1985 | int | 2033 | int |
1986 | i915_do_wait_request(struct drm_device *dev, uint32_t seqno, | 2034 | i915_wait_request(struct intel_ring_buffer *ring, |
1987 | bool interruptible, struct intel_ring_buffer *ring) | 2035 | uint32_t seqno) |
1988 | { | 2036 | { |
1989 | drm_i915_private_t *dev_priv = dev->dev_private; | 2037 | drm_i915_private_t *dev_priv = ring->dev->dev_private; |
1990 | u32 ier; | 2038 | u32 ier; |
1991 | int ret = 0; | 2039 | int ret = 0; |
1992 | 2040 | ||
1993 | BUG_ON(seqno == 0); | 2041 | BUG_ON(seqno == 0); |
1994 | 2042 | ||
1995 | if (atomic_read(&dev_priv->mm.wedged)) | 2043 | if (atomic_read(&dev_priv->mm.wedged)) { |
1996 | return -EAGAIN; | 2044 | struct completion *x = &dev_priv->error_completion; |
2045 | bool recovery_complete; | ||
2046 | unsigned long flags; | ||
2047 | |||
2048 | /* Give the error handler a chance to run. */ | ||
2049 | spin_lock_irqsave(&x->wait.lock, flags); | ||
2050 | recovery_complete = x->done > 0; | ||
2051 | spin_unlock_irqrestore(&x->wait.lock, flags); | ||
2052 | |||
2053 | return recovery_complete ? -EIO : -EAGAIN; | ||
2054 | } | ||
1997 | 2055 | ||
1998 | if (seqno == ring->outstanding_lazy_request) { | 2056 | if (seqno == ring->outstanding_lazy_request) { |
1999 | struct drm_i915_gem_request *request; | 2057 | struct drm_i915_gem_request *request; |
@@ -2002,7 +2060,7 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, | |||
2002 | if (request == NULL) | 2060 | if (request == NULL) |
2003 | return -ENOMEM; | 2061 | return -ENOMEM; |
2004 | 2062 | ||
2005 | ret = i915_add_request(dev, NULL, request, ring); | 2063 | ret = i915_add_request(ring, NULL, request); |
2006 | if (ret) { | 2064 | if (ret) { |
2007 | kfree(request); | 2065 | kfree(request); |
2008 | return ret; | 2066 | return ret; |
@@ -2012,22 +2070,22 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, | |||
2012 | } | 2070 | } |
2013 | 2071 | ||
2014 | if (!i915_seqno_passed(ring->get_seqno(ring), seqno)) { | 2072 | if (!i915_seqno_passed(ring->get_seqno(ring), seqno)) { |
2015 | if (HAS_PCH_SPLIT(dev)) | 2073 | if (HAS_PCH_SPLIT(ring->dev)) |
2016 | ier = I915_READ(DEIER) | I915_READ(GTIER); | 2074 | ier = I915_READ(DEIER) | I915_READ(GTIER); |
2017 | else | 2075 | else |
2018 | ier = I915_READ(IER); | 2076 | ier = I915_READ(IER); |
2019 | if (!ier) { | 2077 | if (!ier) { |
2020 | DRM_ERROR("something (likely vbetool) disabled " | 2078 | DRM_ERROR("something (likely vbetool) disabled " |
2021 | "interrupts, re-enabling\n"); | 2079 | "interrupts, re-enabling\n"); |
2022 | i915_driver_irq_preinstall(dev); | 2080 | i915_driver_irq_preinstall(ring->dev); |
2023 | i915_driver_irq_postinstall(dev); | 2081 | i915_driver_irq_postinstall(ring->dev); |
2024 | } | 2082 | } |
2025 | 2083 | ||
2026 | trace_i915_gem_request_wait_begin(dev, seqno); | 2084 | trace_i915_gem_request_wait_begin(ring, seqno); |
2027 | 2085 | ||
2028 | ring->waiting_seqno = seqno; | 2086 | ring->waiting_seqno = seqno; |
2029 | if (ring->irq_get(ring)) { | 2087 | if (ring->irq_get(ring)) { |
2030 | if (interruptible) | 2088 | if (dev_priv->mm.interruptible) |
2031 | ret = wait_event_interruptible(ring->irq_queue, | 2089 | ret = wait_event_interruptible(ring->irq_queue, |
2032 | i915_seqno_passed(ring->get_seqno(ring), seqno) | 2090 | i915_seqno_passed(ring->get_seqno(ring), seqno) |
2033 | || atomic_read(&dev_priv->mm.wedged)); | 2091 | || atomic_read(&dev_priv->mm.wedged)); |
@@ -2043,7 +2101,7 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, | |||
2043 | ret = -EBUSY; | 2101 | ret = -EBUSY; |
2044 | ring->waiting_seqno = 0; | 2102 | ring->waiting_seqno = 0; |
2045 | 2103 | ||
2046 | trace_i915_gem_request_wait_end(dev, seqno); | 2104 | trace_i915_gem_request_wait_end(ring, seqno); |
2047 | } | 2105 | } |
2048 | if (atomic_read(&dev_priv->mm.wedged)) | 2106 | if (atomic_read(&dev_priv->mm.wedged)) |
2049 | ret = -EAGAIN; | 2107 | ret = -EAGAIN; |
@@ -2059,31 +2117,18 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, | |||
2059 | * a separate wait queue to handle that. | 2117 | * a separate wait queue to handle that. |
2060 | */ | 2118 | */ |
2061 | if (ret == 0) | 2119 | if (ret == 0) |
2062 | i915_gem_retire_requests_ring(dev, ring); | 2120 | i915_gem_retire_requests_ring(ring); |
2063 | 2121 | ||
2064 | return ret; | 2122 | return ret; |
2065 | } | 2123 | } |
2066 | 2124 | ||
2067 | /** | 2125 | /** |
2068 | * Waits for a sequence number to be signaled, and cleans up the | ||
2069 | * request and object lists appropriately for that event. | ||
2070 | */ | ||
2071 | static int | ||
2072 | i915_wait_request(struct drm_device *dev, uint32_t seqno, | ||
2073 | struct intel_ring_buffer *ring) | ||
2074 | { | ||
2075 | return i915_do_wait_request(dev, seqno, 1, ring); | ||
2076 | } | ||
2077 | |||
2078 | /** | ||
2079 | * Ensures that all rendering to the object has completed and the object is | 2126 | * Ensures that all rendering to the object has completed and the object is |
2080 | * safe to unbind from the GTT or access from the CPU. | 2127 | * safe to unbind from the GTT or access from the CPU. |
2081 | */ | 2128 | */ |
2082 | int | 2129 | int |
2083 | i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj, | 2130 | i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj) |
2084 | bool interruptible) | ||
2085 | { | 2131 | { |
2086 | struct drm_device *dev = obj->base.dev; | ||
2087 | int ret; | 2132 | int ret; |
2088 | 2133 | ||
2089 | /* This function only exists to support waiting for existing rendering, | 2134 | /* This function only exists to support waiting for existing rendering, |
@@ -2095,10 +2140,7 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj, | |||
2095 | * it. | 2140 | * it. |
2096 | */ | 2141 | */ |
2097 | if (obj->active) { | 2142 | if (obj->active) { |
2098 | ret = i915_do_wait_request(dev, | 2143 | ret = i915_wait_request(obj->ring, obj->last_rendering_seqno); |
2099 | obj->last_rendering_seqno, | ||
2100 | interruptible, | ||
2101 | obj->ring); | ||
2102 | if (ret) | 2144 | if (ret) |
2103 | return ret; | 2145 | return ret; |
2104 | } | 2146 | } |
@@ -2148,6 +2190,8 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj) | |||
2148 | if (ret == -ERESTARTSYS) | 2190 | if (ret == -ERESTARTSYS) |
2149 | return ret; | 2191 | return ret; |
2150 | 2192 | ||
2193 | trace_i915_gem_object_unbind(obj); | ||
2194 | |||
2151 | i915_gem_gtt_unbind_object(obj); | 2195 | i915_gem_gtt_unbind_object(obj); |
2152 | i915_gem_object_put_pages_gtt(obj); | 2196 | i915_gem_object_put_pages_gtt(obj); |
2153 | 2197 | ||
@@ -2163,29 +2207,27 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj) | |||
2163 | if (i915_gem_object_is_purgeable(obj)) | 2207 | if (i915_gem_object_is_purgeable(obj)) |
2164 | i915_gem_object_truncate(obj); | 2208 | i915_gem_object_truncate(obj); |
2165 | 2209 | ||
2166 | trace_i915_gem_object_unbind(obj); | ||
2167 | |||
2168 | return ret; | 2210 | return ret; |
2169 | } | 2211 | } |
2170 | 2212 | ||
2171 | int | 2213 | int |
2172 | i915_gem_flush_ring(struct drm_device *dev, | 2214 | i915_gem_flush_ring(struct intel_ring_buffer *ring, |
2173 | struct intel_ring_buffer *ring, | ||
2174 | uint32_t invalidate_domains, | 2215 | uint32_t invalidate_domains, |
2175 | uint32_t flush_domains) | 2216 | uint32_t flush_domains) |
2176 | { | 2217 | { |
2177 | int ret; | 2218 | int ret; |
2178 | 2219 | ||
2220 | trace_i915_gem_ring_flush(ring, invalidate_domains, flush_domains); | ||
2221 | |||
2179 | ret = ring->flush(ring, invalidate_domains, flush_domains); | 2222 | ret = ring->flush(ring, invalidate_domains, flush_domains); |
2180 | if (ret) | 2223 | if (ret) |
2181 | return ret; | 2224 | return ret; |
2182 | 2225 | ||
2183 | i915_gem_process_flushing_list(dev, flush_domains, ring); | 2226 | i915_gem_process_flushing_list(ring, flush_domains); |
2184 | return 0; | 2227 | return 0; |
2185 | } | 2228 | } |
2186 | 2229 | ||
2187 | static int i915_ring_idle(struct drm_device *dev, | 2230 | static int i915_ring_idle(struct intel_ring_buffer *ring) |
2188 | struct intel_ring_buffer *ring) | ||
2189 | { | 2231 | { |
2190 | int ret; | 2232 | int ret; |
2191 | 2233 | ||
@@ -2193,15 +2235,13 @@ static int i915_ring_idle(struct drm_device *dev, | |||
2193 | return 0; | 2235 | return 0; |
2194 | 2236 | ||
2195 | if (!list_empty(&ring->gpu_write_list)) { | 2237 | if (!list_empty(&ring->gpu_write_list)) { |
2196 | ret = i915_gem_flush_ring(dev, ring, | 2238 | ret = i915_gem_flush_ring(ring, |
2197 | I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS); | 2239 | I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS); |
2198 | if (ret) | 2240 | if (ret) |
2199 | return ret; | 2241 | return ret; |
2200 | } | 2242 | } |
2201 | 2243 | ||
2202 | return i915_wait_request(dev, | 2244 | return i915_wait_request(ring, i915_gem_next_request_seqno(ring)); |
2203 | i915_gem_next_request_seqno(dev, ring), | ||
2204 | ring); | ||
2205 | } | 2245 | } |
2206 | 2246 | ||
2207 | int | 2247 | int |
@@ -2218,7 +2258,7 @@ i915_gpu_idle(struct drm_device *dev) | |||
2218 | 2258 | ||
2219 | /* Flush everything onto the inactive list. */ | 2259 | /* Flush everything onto the inactive list. */ |
2220 | for (i = 0; i < I915_NUM_RINGS; i++) { | 2260 | for (i = 0; i < I915_NUM_RINGS; i++) { |
2221 | ret = i915_ring_idle(dev, &dev_priv->ring[i]); | 2261 | ret = i915_ring_idle(&dev_priv->ring[i]); |
2222 | if (ret) | 2262 | if (ret) |
2223 | return ret; | 2263 | return ret; |
2224 | } | 2264 | } |
@@ -2402,15 +2442,13 @@ static bool ring_passed_seqno(struct intel_ring_buffer *ring, u32 seqno) | |||
2402 | 2442 | ||
2403 | static int | 2443 | static int |
2404 | i915_gem_object_flush_fence(struct drm_i915_gem_object *obj, | 2444 | i915_gem_object_flush_fence(struct drm_i915_gem_object *obj, |
2405 | struct intel_ring_buffer *pipelined, | 2445 | struct intel_ring_buffer *pipelined) |
2406 | bool interruptible) | ||
2407 | { | 2446 | { |
2408 | int ret; | 2447 | int ret; |
2409 | 2448 | ||
2410 | if (obj->fenced_gpu_access) { | 2449 | if (obj->fenced_gpu_access) { |
2411 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) { | 2450 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) { |
2412 | ret = i915_gem_flush_ring(obj->base.dev, | 2451 | ret = i915_gem_flush_ring(obj->last_fenced_ring, |
2413 | obj->last_fenced_ring, | ||
2414 | 0, obj->base.write_domain); | 2452 | 0, obj->base.write_domain); |
2415 | if (ret) | 2453 | if (ret) |
2416 | return ret; | 2454 | return ret; |
@@ -2422,10 +2460,8 @@ i915_gem_object_flush_fence(struct drm_i915_gem_object *obj, | |||
2422 | if (obj->last_fenced_seqno && pipelined != obj->last_fenced_ring) { | 2460 | if (obj->last_fenced_seqno && pipelined != obj->last_fenced_ring) { |
2423 | if (!ring_passed_seqno(obj->last_fenced_ring, | 2461 | if (!ring_passed_seqno(obj->last_fenced_ring, |
2424 | obj->last_fenced_seqno)) { | 2462 | obj->last_fenced_seqno)) { |
2425 | ret = i915_do_wait_request(obj->base.dev, | 2463 | ret = i915_wait_request(obj->last_fenced_ring, |
2426 | obj->last_fenced_seqno, | 2464 | obj->last_fenced_seqno); |
2427 | interruptible, | ||
2428 | obj->last_fenced_ring); | ||
2429 | if (ret) | 2465 | if (ret) |
2430 | return ret; | 2466 | return ret; |
2431 | } | 2467 | } |
@@ -2451,7 +2487,7 @@ i915_gem_object_put_fence(struct drm_i915_gem_object *obj) | |||
2451 | if (obj->tiling_mode) | 2487 | if (obj->tiling_mode) |
2452 | i915_gem_release_mmap(obj); | 2488 | i915_gem_release_mmap(obj); |
2453 | 2489 | ||
2454 | ret = i915_gem_object_flush_fence(obj, NULL, true); | 2490 | ret = i915_gem_object_flush_fence(obj, NULL); |
2455 | if (ret) | 2491 | if (ret) |
2456 | return ret; | 2492 | return ret; |
2457 | 2493 | ||
@@ -2528,8 +2564,7 @@ i915_find_fence_reg(struct drm_device *dev, | |||
2528 | */ | 2564 | */ |
2529 | int | 2565 | int |
2530 | i915_gem_object_get_fence(struct drm_i915_gem_object *obj, | 2566 | i915_gem_object_get_fence(struct drm_i915_gem_object *obj, |
2531 | struct intel_ring_buffer *pipelined, | 2567 | struct intel_ring_buffer *pipelined) |
2532 | bool interruptible) | ||
2533 | { | 2568 | { |
2534 | struct drm_device *dev = obj->base.dev; | 2569 | struct drm_device *dev = obj->base.dev; |
2535 | struct drm_i915_private *dev_priv = dev->dev_private; | 2570 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -2551,10 +2586,8 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj, | |||
2551 | if (reg->setup_seqno) { | 2586 | if (reg->setup_seqno) { |
2552 | if (!ring_passed_seqno(obj->last_fenced_ring, | 2587 | if (!ring_passed_seqno(obj->last_fenced_ring, |
2553 | reg->setup_seqno)) { | 2588 | reg->setup_seqno)) { |
2554 | ret = i915_do_wait_request(obj->base.dev, | 2589 | ret = i915_wait_request(obj->last_fenced_ring, |
2555 | reg->setup_seqno, | 2590 | reg->setup_seqno); |
2556 | interruptible, | ||
2557 | obj->last_fenced_ring); | ||
2558 | if (ret) | 2591 | if (ret) |
2559 | return ret; | 2592 | return ret; |
2560 | } | 2593 | } |
@@ -2563,15 +2596,13 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj, | |||
2563 | } | 2596 | } |
2564 | } else if (obj->last_fenced_ring && | 2597 | } else if (obj->last_fenced_ring && |
2565 | obj->last_fenced_ring != pipelined) { | 2598 | obj->last_fenced_ring != pipelined) { |
2566 | ret = i915_gem_object_flush_fence(obj, | 2599 | ret = i915_gem_object_flush_fence(obj, pipelined); |
2567 | pipelined, | ||
2568 | interruptible); | ||
2569 | if (ret) | 2600 | if (ret) |
2570 | return ret; | 2601 | return ret; |
2571 | } else if (obj->tiling_changed) { | 2602 | } else if (obj->tiling_changed) { |
2572 | if (obj->fenced_gpu_access) { | 2603 | if (obj->fenced_gpu_access) { |
2573 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) { | 2604 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) { |
2574 | ret = i915_gem_flush_ring(obj->base.dev, obj->ring, | 2605 | ret = i915_gem_flush_ring(obj->ring, |
2575 | 0, obj->base.write_domain); | 2606 | 0, obj->base.write_domain); |
2576 | if (ret) | 2607 | if (ret) |
2577 | return ret; | 2608 | return ret; |
@@ -2588,7 +2619,7 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj, | |||
2588 | if (obj->tiling_changed) { | 2619 | if (obj->tiling_changed) { |
2589 | if (pipelined) { | 2620 | if (pipelined) { |
2590 | reg->setup_seqno = | 2621 | reg->setup_seqno = |
2591 | i915_gem_next_request_seqno(dev, pipelined); | 2622 | i915_gem_next_request_seqno(pipelined); |
2592 | obj->last_fenced_seqno = reg->setup_seqno; | 2623 | obj->last_fenced_seqno = reg->setup_seqno; |
2593 | obj->last_fenced_ring = pipelined; | 2624 | obj->last_fenced_ring = pipelined; |
2594 | } | 2625 | } |
@@ -2602,7 +2633,7 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj, | |||
2602 | if (reg == NULL) | 2633 | if (reg == NULL) |
2603 | return -ENOSPC; | 2634 | return -ENOSPC; |
2604 | 2635 | ||
2605 | ret = i915_gem_object_flush_fence(obj, pipelined, interruptible); | 2636 | ret = i915_gem_object_flush_fence(obj, pipelined); |
2606 | if (ret) | 2637 | if (ret) |
2607 | return ret; | 2638 | return ret; |
2608 | 2639 | ||
@@ -2614,9 +2645,7 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj, | |||
2614 | if (old->tiling_mode) | 2645 | if (old->tiling_mode) |
2615 | i915_gem_release_mmap(old); | 2646 | i915_gem_release_mmap(old); |
2616 | 2647 | ||
2617 | ret = i915_gem_object_flush_fence(old, | 2648 | ret = i915_gem_object_flush_fence(old, pipelined); |
2618 | pipelined, | ||
2619 | interruptible); | ||
2620 | if (ret) { | 2649 | if (ret) { |
2621 | drm_gem_object_unreference(&old->base); | 2650 | drm_gem_object_unreference(&old->base); |
2622 | return ret; | 2651 | return ret; |
@@ -2628,7 +2657,7 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj, | |||
2628 | old->fence_reg = I915_FENCE_REG_NONE; | 2657 | old->fence_reg = I915_FENCE_REG_NONE; |
2629 | old->last_fenced_ring = pipelined; | 2658 | old->last_fenced_ring = pipelined; |
2630 | old->last_fenced_seqno = | 2659 | old->last_fenced_seqno = |
2631 | pipelined ? i915_gem_next_request_seqno(dev, pipelined) : 0; | 2660 | pipelined ? i915_gem_next_request_seqno(pipelined) : 0; |
2632 | 2661 | ||
2633 | drm_gem_object_unreference(&old->base); | 2662 | drm_gem_object_unreference(&old->base); |
2634 | } else if (obj->last_fenced_seqno == 0) | 2663 | } else if (obj->last_fenced_seqno == 0) |
@@ -2640,7 +2669,7 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj, | |||
2640 | obj->last_fenced_ring = pipelined; | 2669 | obj->last_fenced_ring = pipelined; |
2641 | 2670 | ||
2642 | reg->setup_seqno = | 2671 | reg->setup_seqno = |
2643 | pipelined ? i915_gem_next_request_seqno(dev, pipelined) : 0; | 2672 | pipelined ? i915_gem_next_request_seqno(pipelined) : 0; |
2644 | obj->last_fenced_seqno = reg->setup_seqno; | 2673 | obj->last_fenced_seqno = reg->setup_seqno; |
2645 | 2674 | ||
2646 | update: | 2675 | update: |
@@ -2837,7 +2866,7 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj, | |||
2837 | 2866 | ||
2838 | obj->map_and_fenceable = mappable && fenceable; | 2867 | obj->map_and_fenceable = mappable && fenceable; |
2839 | 2868 | ||
2840 | trace_i915_gem_object_bind(obj, obj->gtt_offset, map_and_fenceable); | 2869 | trace_i915_gem_object_bind(obj, map_and_fenceable); |
2841 | return 0; | 2870 | return 0; |
2842 | } | 2871 | } |
2843 | 2872 | ||
@@ -2860,13 +2889,11 @@ i915_gem_clflush_object(struct drm_i915_gem_object *obj) | |||
2860 | static int | 2889 | static int |
2861 | i915_gem_object_flush_gpu_write_domain(struct drm_i915_gem_object *obj) | 2890 | i915_gem_object_flush_gpu_write_domain(struct drm_i915_gem_object *obj) |
2862 | { | 2891 | { |
2863 | struct drm_device *dev = obj->base.dev; | ||
2864 | |||
2865 | if ((obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0) | 2892 | if ((obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0) |
2866 | return 0; | 2893 | return 0; |
2867 | 2894 | ||
2868 | /* Queue the GPU write cache flushing we need. */ | 2895 | /* Queue the GPU write cache flushing we need. */ |
2869 | return i915_gem_flush_ring(dev, obj->ring, 0, obj->base.write_domain); | 2896 | return i915_gem_flush_ring(obj->ring, 0, obj->base.write_domain); |
2870 | } | 2897 | } |
2871 | 2898 | ||
2872 | /** Flushes the GTT write domain for the object if it's dirty. */ | 2899 | /** Flushes the GTT write domain for the object if it's dirty. */ |
@@ -2933,12 +2960,15 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write) | |||
2933 | if (obj->gtt_space == NULL) | 2960 | if (obj->gtt_space == NULL) |
2934 | return -EINVAL; | 2961 | return -EINVAL; |
2935 | 2962 | ||
2963 | if (obj->base.write_domain == I915_GEM_DOMAIN_GTT) | ||
2964 | return 0; | ||
2965 | |||
2936 | ret = i915_gem_object_flush_gpu_write_domain(obj); | 2966 | ret = i915_gem_object_flush_gpu_write_domain(obj); |
2937 | if (ret) | 2967 | if (ret) |
2938 | return ret; | 2968 | return ret; |
2939 | 2969 | ||
2940 | if (obj->pending_gpu_write || write) { | 2970 | if (obj->pending_gpu_write || write) { |
2941 | ret = i915_gem_object_wait_rendering(obj, true); | 2971 | ret = i915_gem_object_wait_rendering(obj); |
2942 | if (ret) | 2972 | if (ret) |
2943 | return ret; | 2973 | return ret; |
2944 | } | 2974 | } |
@@ -2988,7 +3018,7 @@ i915_gem_object_set_to_display_plane(struct drm_i915_gem_object *obj, | |||
2988 | 3018 | ||
2989 | /* Currently, we are always called from an non-interruptible context. */ | 3019 | /* Currently, we are always called from an non-interruptible context. */ |
2990 | if (pipelined != obj->ring) { | 3020 | if (pipelined != obj->ring) { |
2991 | ret = i915_gem_object_wait_rendering(obj, false); | 3021 | ret = i915_gem_object_wait_rendering(obj); |
2992 | if (ret) | 3022 | if (ret) |
2993 | return ret; | 3023 | return ret; |
2994 | } | 3024 | } |
@@ -3006,8 +3036,7 @@ i915_gem_object_set_to_display_plane(struct drm_i915_gem_object *obj, | |||
3006 | } | 3036 | } |
3007 | 3037 | ||
3008 | int | 3038 | int |
3009 | i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj, | 3039 | i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj) |
3010 | bool interruptible) | ||
3011 | { | 3040 | { |
3012 | int ret; | 3041 | int ret; |
3013 | 3042 | ||
@@ -3015,13 +3044,12 @@ i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj, | |||
3015 | return 0; | 3044 | return 0; |
3016 | 3045 | ||
3017 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) { | 3046 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) { |
3018 | ret = i915_gem_flush_ring(obj->base.dev, obj->ring, | 3047 | ret = i915_gem_flush_ring(obj->ring, 0, obj->base.write_domain); |
3019 | 0, obj->base.write_domain); | ||
3020 | if (ret) | 3048 | if (ret) |
3021 | return ret; | 3049 | return ret; |
3022 | } | 3050 | } |
3023 | 3051 | ||
3024 | return i915_gem_object_wait_rendering(obj, interruptible); | 3052 | return i915_gem_object_wait_rendering(obj); |
3025 | } | 3053 | } |
3026 | 3054 | ||
3027 | /** | 3055 | /** |
@@ -3036,11 +3064,14 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write) | |||
3036 | uint32_t old_write_domain, old_read_domains; | 3064 | uint32_t old_write_domain, old_read_domains; |
3037 | int ret; | 3065 | int ret; |
3038 | 3066 | ||
3067 | if (obj->base.write_domain == I915_GEM_DOMAIN_CPU) | ||
3068 | return 0; | ||
3069 | |||
3039 | ret = i915_gem_object_flush_gpu_write_domain(obj); | 3070 | ret = i915_gem_object_flush_gpu_write_domain(obj); |
3040 | if (ret) | 3071 | if (ret) |
3041 | return ret; | 3072 | return ret; |
3042 | 3073 | ||
3043 | ret = i915_gem_object_wait_rendering(obj, true); | 3074 | ret = i915_gem_object_wait_rendering(obj); |
3044 | if (ret) | 3075 | if (ret) |
3045 | return ret; | 3076 | return ret; |
3046 | 3077 | ||
@@ -3138,7 +3169,7 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_i915_gem_object *obj, | |||
3138 | if (ret) | 3169 | if (ret) |
3139 | return ret; | 3170 | return ret; |
3140 | 3171 | ||
3141 | ret = i915_gem_object_wait_rendering(obj, true); | 3172 | ret = i915_gem_object_wait_rendering(obj); |
3142 | if (ret) | 3173 | if (ret) |
3143 | return ret; | 3174 | return ret; |
3144 | 3175 | ||
@@ -3209,6 +3240,9 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) | |||
3209 | u32 seqno = 0; | 3240 | u32 seqno = 0; |
3210 | int ret; | 3241 | int ret; |
3211 | 3242 | ||
3243 | if (atomic_read(&dev_priv->mm.wedged)) | ||
3244 | return -EIO; | ||
3245 | |||
3212 | spin_lock(&file_priv->mm.lock); | 3246 | spin_lock(&file_priv->mm.lock); |
3213 | list_for_each_entry(request, &file_priv->mm.request_list, client_list) { | 3247 | list_for_each_entry(request, &file_priv->mm.request_list, client_list) { |
3214 | if (time_after_eq(request->emitted_jiffies, recent_enough)) | 3248 | if (time_after_eq(request->emitted_jiffies, recent_enough)) |
@@ -3324,7 +3358,7 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data, | |||
3324 | return ret; | 3358 | return ret; |
3325 | 3359 | ||
3326 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); | 3360 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); |
3327 | if (obj == NULL) { | 3361 | if (&obj->base == NULL) { |
3328 | ret = -ENOENT; | 3362 | ret = -ENOENT; |
3329 | goto unlock; | 3363 | goto unlock; |
3330 | } | 3364 | } |
@@ -3375,7 +3409,7 @@ i915_gem_unpin_ioctl(struct drm_device *dev, void *data, | |||
3375 | return ret; | 3409 | return ret; |
3376 | 3410 | ||
3377 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); | 3411 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); |
3378 | if (obj == NULL) { | 3412 | if (&obj->base == NULL) { |
3379 | ret = -ENOENT; | 3413 | ret = -ENOENT; |
3380 | goto unlock; | 3414 | goto unlock; |
3381 | } | 3415 | } |
@@ -3412,7 +3446,7 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
3412 | return ret; | 3446 | return ret; |
3413 | 3447 | ||
3414 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); | 3448 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); |
3415 | if (obj == NULL) { | 3449 | if (&obj->base == NULL) { |
3416 | ret = -ENOENT; | 3450 | ret = -ENOENT; |
3417 | goto unlock; | 3451 | goto unlock; |
3418 | } | 3452 | } |
@@ -3430,7 +3464,7 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
3430 | * flush earlier is beneficial. | 3464 | * flush earlier is beneficial. |
3431 | */ | 3465 | */ |
3432 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) { | 3466 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) { |
3433 | ret = i915_gem_flush_ring(dev, obj->ring, | 3467 | ret = i915_gem_flush_ring(obj->ring, |
3434 | 0, obj->base.write_domain); | 3468 | 0, obj->base.write_domain); |
3435 | } else if (obj->ring->outstanding_lazy_request == | 3469 | } else if (obj->ring->outstanding_lazy_request == |
3436 | obj->last_rendering_seqno) { | 3470 | obj->last_rendering_seqno) { |
@@ -3441,9 +3475,7 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
3441 | */ | 3475 | */ |
3442 | request = kzalloc(sizeof(*request), GFP_KERNEL); | 3476 | request = kzalloc(sizeof(*request), GFP_KERNEL); |
3443 | if (request) | 3477 | if (request) |
3444 | ret = i915_add_request(dev, | 3478 | ret = i915_add_request(obj->ring, NULL,request); |
3445 | NULL, request, | ||
3446 | obj->ring); | ||
3447 | else | 3479 | else |
3448 | ret = -ENOMEM; | 3480 | ret = -ENOMEM; |
3449 | } | 3481 | } |
@@ -3453,7 +3485,7 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
3453 | * are actually unmasked, and our working set ends up being | 3485 | * are actually unmasked, and our working set ends up being |
3454 | * larger than required. | 3486 | * larger than required. |
3455 | */ | 3487 | */ |
3456 | i915_gem_retire_requests_ring(dev, obj->ring); | 3488 | i915_gem_retire_requests_ring(obj->ring); |
3457 | 3489 | ||
3458 | args->busy = obj->active; | 3490 | args->busy = obj->active; |
3459 | } | 3491 | } |
@@ -3492,7 +3524,7 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data, | |||
3492 | return ret; | 3524 | return ret; |
3493 | 3525 | ||
3494 | obj = to_intel_bo(drm_gem_object_lookup(dev, file_priv, args->handle)); | 3526 | obj = to_intel_bo(drm_gem_object_lookup(dev, file_priv, args->handle)); |
3495 | if (obj == NULL) { | 3527 | if (&obj->base == NULL) { |
3496 | ret = -ENOENT; | 3528 | ret = -ENOENT; |
3497 | goto unlock; | 3529 | goto unlock; |
3498 | } | 3530 | } |
@@ -3583,6 +3615,8 @@ static void i915_gem_free_object_tail(struct drm_i915_gem_object *obj) | |||
3583 | kfree(obj->page_cpu_valid); | 3615 | kfree(obj->page_cpu_valid); |
3584 | kfree(obj->bit_17); | 3616 | kfree(obj->bit_17); |
3585 | kfree(obj); | 3617 | kfree(obj); |
3618 | |||
3619 | trace_i915_gem_object_destroy(obj); | ||
3586 | } | 3620 | } |
3587 | 3621 | ||
3588 | void i915_gem_free_object(struct drm_gem_object *gem_obj) | 3622 | void i915_gem_free_object(struct drm_gem_object *gem_obj) |
@@ -3590,8 +3624,6 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj) | |||
3590 | struct drm_i915_gem_object *obj = to_intel_bo(gem_obj); | 3624 | struct drm_i915_gem_object *obj = to_intel_bo(gem_obj); |
3591 | struct drm_device *dev = obj->base.dev; | 3625 | struct drm_device *dev = obj->base.dev; |
3592 | 3626 | ||
3593 | trace_i915_gem_object_destroy(obj); | ||
3594 | |||
3595 | while (obj->pin_count > 0) | 3627 | while (obj->pin_count > 0) |
3596 | i915_gem_object_unpin(obj); | 3628 | i915_gem_object_unpin(obj); |
3597 | 3629 | ||
@@ -3837,6 +3869,8 @@ i915_gem_load(struct drm_device *dev) | |||
3837 | i915_gem_detect_bit_6_swizzle(dev); | 3869 | i915_gem_detect_bit_6_swizzle(dev); |
3838 | init_waitqueue_head(&dev_priv->pending_flip_queue); | 3870 | init_waitqueue_head(&dev_priv->pending_flip_queue); |
3839 | 3871 | ||
3872 | dev_priv->mm.interruptible = true; | ||
3873 | |||
3840 | dev_priv->mm.inactive_shrinker.shrink = i915_gem_inactive_shrink; | 3874 | dev_priv->mm.inactive_shrinker.shrink = i915_gem_inactive_shrink; |
3841 | dev_priv->mm.inactive_shrinker.seeks = DEFAULT_SEEKS; | 3875 | dev_priv->mm.inactive_shrinker.seeks = DEFAULT_SEEKS; |
3842 | register_shrinker(&dev_priv->mm.inactive_shrinker); | 3876 | register_shrinker(&dev_priv->mm.inactive_shrinker); |
diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c index 29d014c48ca..8da1899bd24 100644 --- a/drivers/gpu/drm/i915/i915_gem_debug.c +++ b/drivers/gpu/drm/i915/i915_gem_debug.c | |||
@@ -134,51 +134,6 @@ i915_verify_lists(struct drm_device *dev) | |||
134 | } | 134 | } |
135 | #endif /* WATCH_INACTIVE */ | 135 | #endif /* WATCH_INACTIVE */ |
136 | 136 | ||
137 | |||
138 | #if WATCH_EXEC | WATCH_PWRITE | ||
139 | static void | ||
140 | i915_gem_dump_page(struct page *page, uint32_t start, uint32_t end, | ||
141 | uint32_t bias, uint32_t mark) | ||
142 | { | ||
143 | uint32_t *mem = kmap_atomic(page, KM_USER0); | ||
144 | int i; | ||
145 | for (i = start; i < end; i += 4) | ||
146 | DRM_INFO("%08x: %08x%s\n", | ||
147 | (int) (bias + i), mem[i / 4], | ||
148 | (bias + i == mark) ? " ********" : ""); | ||
149 | kunmap_atomic(mem, KM_USER0); | ||
150 | /* give syslog time to catch up */ | ||
151 | msleep(1); | ||
152 | } | ||
153 | |||
154 | void | ||
155 | i915_gem_dump_object(struct drm_i915_gem_object *obj, int len, | ||
156 | const char *where, uint32_t mark) | ||
157 | { | ||
158 | int page; | ||
159 | |||
160 | DRM_INFO("%s: object at offset %08x\n", where, obj->gtt_offset); | ||
161 | for (page = 0; page < (len + PAGE_SIZE-1) / PAGE_SIZE; page++) { | ||
162 | int page_len, chunk, chunk_len; | ||
163 | |||
164 | page_len = len - page * PAGE_SIZE; | ||
165 | if (page_len > PAGE_SIZE) | ||
166 | page_len = PAGE_SIZE; | ||
167 | |||
168 | for (chunk = 0; chunk < page_len; chunk += 128) { | ||
169 | chunk_len = page_len - chunk; | ||
170 | if (chunk_len > 128) | ||
171 | chunk_len = 128; | ||
172 | i915_gem_dump_page(obj->pages[page], | ||
173 | chunk, chunk + chunk_len, | ||
174 | obj->gtt_offset + | ||
175 | page * PAGE_SIZE, | ||
176 | mark); | ||
177 | } | ||
178 | } | ||
179 | } | ||
180 | #endif | ||
181 | |||
182 | #if WATCH_COHERENCY | 137 | #if WATCH_COHERENCY |
183 | void | 138 | void |
184 | i915_gem_object_check_coherency(struct drm_i915_gem_object *obj, int handle) | 139 | i915_gem_object_check_coherency(struct drm_i915_gem_object *obj, int handle) |
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index 3d39005540a..da05a2692a7 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "drm.h" | 30 | #include "drm.h" |
31 | #include "i915_drv.h" | 31 | #include "i915_drv.h" |
32 | #include "i915_drm.h" | 32 | #include "i915_drm.h" |
33 | #include "i915_trace.h" | ||
33 | 34 | ||
34 | static bool | 35 | static bool |
35 | mark_free(struct drm_i915_gem_object *obj, struct list_head *unwind) | 36 | mark_free(struct drm_i915_gem_object *obj, struct list_head *unwind) |
@@ -63,6 +64,8 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, | |||
63 | return 0; | 64 | return 0; |
64 | } | 65 | } |
65 | 66 | ||
67 | trace_i915_gem_evict(dev, min_size, alignment, mappable); | ||
68 | |||
66 | /* | 69 | /* |
67 | * The goal is to evict objects and amalgamate space in LRU order. | 70 | * The goal is to evict objects and amalgamate space in LRU order. |
68 | * The oldest idle objects reside on the inactive list, which is in | 71 | * The oldest idle objects reside on the inactive list, which is in |
@@ -189,6 +192,8 @@ i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only) | |||
189 | if (lists_empty) | 192 | if (lists_empty) |
190 | return -ENOSPC; | 193 | return -ENOSPC; |
191 | 194 | ||
195 | trace_i915_gem_evict_everything(dev, purgeable_only); | ||
196 | |||
192 | /* Flush everything (on to the inactive lists) and evict */ | 197 | /* Flush everything (on to the inactive lists) and evict */ |
193 | ret = i915_gpu_idle(dev); | 198 | ret = i915_gpu_idle(dev); |
194 | if (ret) | 199 | if (ret) |
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 50ab1614571..7ff7f933ddf 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c | |||
@@ -37,6 +37,7 @@ struct change_domains { | |||
37 | uint32_t invalidate_domains; | 37 | uint32_t invalidate_domains; |
38 | uint32_t flush_domains; | 38 | uint32_t flush_domains; |
39 | uint32_t flush_rings; | 39 | uint32_t flush_rings; |
40 | uint32_t flips; | ||
40 | }; | 41 | }; |
41 | 42 | ||
42 | /* | 43 | /* |
@@ -190,6 +191,9 @@ i915_gem_object_set_to_gpu_domain(struct drm_i915_gem_object *obj, | |||
190 | if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_GTT) | 191 | if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_GTT) |
191 | i915_gem_release_mmap(obj); | 192 | i915_gem_release_mmap(obj); |
192 | 193 | ||
194 | if (obj->base.pending_write_domain) | ||
195 | cd->flips |= atomic_read(&obj->pending_flip); | ||
196 | |||
193 | /* The actual obj->write_domain will be updated with | 197 | /* The actual obj->write_domain will be updated with |
194 | * pending_write_domain after we emit the accumulated flush for all | 198 | * pending_write_domain after we emit the accumulated flush for all |
195 | * of our domain changes in execbuffers (which clears objects' | 199 | * of our domain changes in execbuffers (which clears objects' |
@@ -282,21 +286,6 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, | |||
282 | 286 | ||
283 | target_offset = to_intel_bo(target_obj)->gtt_offset; | 287 | target_offset = to_intel_bo(target_obj)->gtt_offset; |
284 | 288 | ||
285 | #if WATCH_RELOC | ||
286 | DRM_INFO("%s: obj %p offset %08x target %d " | ||
287 | "read %08x write %08x gtt %08x " | ||
288 | "presumed %08x delta %08x\n", | ||
289 | __func__, | ||
290 | obj, | ||
291 | (int) reloc->offset, | ||
292 | (int) reloc->target_handle, | ||
293 | (int) reloc->read_domains, | ||
294 | (int) reloc->write_domain, | ||
295 | (int) target_offset, | ||
296 | (int) reloc->presumed_offset, | ||
297 | reloc->delta); | ||
298 | #endif | ||
299 | |||
300 | /* The target buffer should have appeared before us in the | 289 | /* The target buffer should have appeared before us in the |
301 | * exec_object list, so it should have a GTT space bound by now. | 290 | * exec_object list, so it should have a GTT space bound by now. |
302 | */ | 291 | */ |
@@ -365,16 +354,6 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, | |||
365 | return ret; | 354 | return ret; |
366 | } | 355 | } |
367 | 356 | ||
368 | /* and points to somewhere within the target object. */ | ||
369 | if (unlikely(reloc->delta >= target_obj->size)) { | ||
370 | DRM_ERROR("Relocation beyond target object bounds: " | ||
371 | "obj %p target %d delta %d size %d.\n", | ||
372 | obj, reloc->target_handle, | ||
373 | (int) reloc->delta, | ||
374 | (int) target_obj->size); | ||
375 | return ret; | ||
376 | } | ||
377 | |||
378 | reloc->delta += target_offset; | 357 | reloc->delta += target_offset; |
379 | if (obj->base.write_domain == I915_GEM_DOMAIN_CPU) { | 358 | if (obj->base.write_domain == I915_GEM_DOMAIN_CPU) { |
380 | uint32_t page_offset = reloc->offset & ~PAGE_MASK; | 359 | uint32_t page_offset = reloc->offset & ~PAGE_MASK; |
@@ -575,7 +554,7 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring, | |||
575 | 554 | ||
576 | if (has_fenced_gpu_access) { | 555 | if (has_fenced_gpu_access) { |
577 | if (need_fence) { | 556 | if (need_fence) { |
578 | ret = i915_gem_object_get_fence(obj, ring, 1); | 557 | ret = i915_gem_object_get_fence(obj, ring); |
579 | if (ret) | 558 | if (ret) |
580 | break; | 559 | break; |
581 | } else if (entry->flags & EXEC_OBJECT_NEEDS_FENCE && | 560 | } else if (entry->flags & EXEC_OBJECT_NEEDS_FENCE && |
@@ -690,11 +669,9 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, | |||
690 | /* reacquire the objects */ | 669 | /* reacquire the objects */ |
691 | eb_reset(eb); | 670 | eb_reset(eb); |
692 | for (i = 0; i < count; i++) { | 671 | for (i = 0; i < count; i++) { |
693 | struct drm_i915_gem_object *obj; | ||
694 | |||
695 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, | 672 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, |
696 | exec[i].handle)); | 673 | exec[i].handle)); |
697 | if (obj == NULL) { | 674 | if (&obj->base == NULL) { |
698 | DRM_ERROR("Invalid object handle %d at index %d\n", | 675 | DRM_ERROR("Invalid object handle %d at index %d\n", |
699 | exec[i].handle, i); | 676 | exec[i].handle, i); |
700 | ret = -ENOENT; | 677 | ret = -ENOENT; |
@@ -749,8 +726,7 @@ i915_gem_execbuffer_flush(struct drm_device *dev, | |||
749 | if ((flush_domains | invalidate_domains) & I915_GEM_GPU_DOMAINS) { | 726 | if ((flush_domains | invalidate_domains) & I915_GEM_GPU_DOMAINS) { |
750 | for (i = 0; i < I915_NUM_RINGS; i++) | 727 | for (i = 0; i < I915_NUM_RINGS; i++) |
751 | if (flush_rings & (1 << i)) { | 728 | if (flush_rings & (1 << i)) { |
752 | ret = i915_gem_flush_ring(dev, | 729 | ret = i915_gem_flush_ring(&dev_priv->ring[i], |
753 | &dev_priv->ring[i], | ||
754 | invalidate_domains, | 730 | invalidate_domains, |
755 | flush_domains); | 731 | flush_domains); |
756 | if (ret) | 732 | if (ret) |
@@ -774,7 +750,7 @@ i915_gem_execbuffer_sync_rings(struct drm_i915_gem_object *obj, | |||
774 | 750 | ||
775 | /* XXX gpu semaphores are implicated in various hard hangs on SNB */ | 751 | /* XXX gpu semaphores are implicated in various hard hangs on SNB */ |
776 | if (INTEL_INFO(obj->base.dev)->gen < 6 || !i915_semaphores) | 752 | if (INTEL_INFO(obj->base.dev)->gen < 6 || !i915_semaphores) |
777 | return i915_gem_object_wait_rendering(obj, true); | 753 | return i915_gem_object_wait_rendering(obj); |
778 | 754 | ||
779 | idx = intel_ring_sync_index(from, to); | 755 | idx = intel_ring_sync_index(from, to); |
780 | 756 | ||
@@ -789,7 +765,7 @@ i915_gem_execbuffer_sync_rings(struct drm_i915_gem_object *obj, | |||
789 | if (request == NULL) | 765 | if (request == NULL) |
790 | return -ENOMEM; | 766 | return -ENOMEM; |
791 | 767 | ||
792 | ret = i915_add_request(obj->base.dev, NULL, request, from); | 768 | ret = i915_add_request(from, NULL, request); |
793 | if (ret) { | 769 | if (ret) { |
794 | kfree(request); | 770 | kfree(request); |
795 | return ret; | 771 | return ret; |
@@ -803,6 +779,39 @@ i915_gem_execbuffer_sync_rings(struct drm_i915_gem_object *obj, | |||
803 | } | 779 | } |
804 | 780 | ||
805 | static int | 781 | static int |
782 | i915_gem_execbuffer_wait_for_flips(struct intel_ring_buffer *ring, u32 flips) | ||
783 | { | ||
784 | u32 plane, flip_mask; | ||
785 | int ret; | ||
786 | |||
787 | /* Check for any pending flips. As we only maintain a flip queue depth | ||
788 | * of 1, we can simply insert a WAIT for the next display flip prior | ||
789 | * to executing the batch and avoid stalling the CPU. | ||
790 | */ | ||
791 | |||
792 | for (plane = 0; flips >> plane; plane++) { | ||
793 | if (((flips >> plane) & 1) == 0) | ||
794 | continue; | ||
795 | |||
796 | if (plane) | ||
797 | flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; | ||
798 | else | ||
799 | flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; | ||
800 | |||
801 | ret = intel_ring_begin(ring, 2); | ||
802 | if (ret) | ||
803 | return ret; | ||
804 | |||
805 | intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask); | ||
806 | intel_ring_emit(ring, MI_NOOP); | ||
807 | intel_ring_advance(ring); | ||
808 | } | ||
809 | |||
810 | return 0; | ||
811 | } | ||
812 | |||
813 | |||
814 | static int | ||
806 | i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring, | 815 | i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring, |
807 | struct list_head *objects) | 816 | struct list_head *objects) |
808 | { | 817 | { |
@@ -810,19 +819,11 @@ i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring, | |||
810 | struct change_domains cd; | 819 | struct change_domains cd; |
811 | int ret; | 820 | int ret; |
812 | 821 | ||
813 | cd.invalidate_domains = 0; | 822 | memset(&cd, 0, sizeof(cd)); |
814 | cd.flush_domains = 0; | ||
815 | cd.flush_rings = 0; | ||
816 | list_for_each_entry(obj, objects, exec_list) | 823 | list_for_each_entry(obj, objects, exec_list) |
817 | i915_gem_object_set_to_gpu_domain(obj, ring, &cd); | 824 | i915_gem_object_set_to_gpu_domain(obj, ring, &cd); |
818 | 825 | ||
819 | if (cd.invalidate_domains | cd.flush_domains) { | 826 | if (cd.invalidate_domains | cd.flush_domains) { |
820 | #if WATCH_EXEC | ||
821 | DRM_INFO("%s: invalidate_domains %08x flush_domains %08x\n", | ||
822 | __func__, | ||
823 | cd.invalidate_domains, | ||
824 | cd.flush_domains); | ||
825 | #endif | ||
826 | ret = i915_gem_execbuffer_flush(ring->dev, | 827 | ret = i915_gem_execbuffer_flush(ring->dev, |
827 | cd.invalidate_domains, | 828 | cd.invalidate_domains, |
828 | cd.flush_domains, | 829 | cd.flush_domains, |
@@ -831,6 +832,12 @@ i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring, | |||
831 | return ret; | 832 | return ret; |
832 | } | 833 | } |
833 | 834 | ||
835 | if (cd.flips) { | ||
836 | ret = i915_gem_execbuffer_wait_for_flips(ring, cd.flips); | ||
837 | if (ret) | ||
838 | return ret; | ||
839 | } | ||
840 | |||
834 | list_for_each_entry(obj, objects, exec_list) { | 841 | list_for_each_entry(obj, objects, exec_list) { |
835 | ret = i915_gem_execbuffer_sync_rings(obj, ring); | 842 | ret = i915_gem_execbuffer_sync_rings(obj, ring); |
836 | if (ret) | 843 | if (ret) |
@@ -877,47 +884,6 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec, | |||
877 | return 0; | 884 | return 0; |
878 | } | 885 | } |
879 | 886 | ||
880 | static int | ||
881 | i915_gem_execbuffer_wait_for_flips(struct intel_ring_buffer *ring, | ||
882 | struct list_head *objects) | ||
883 | { | ||
884 | struct drm_i915_gem_object *obj; | ||
885 | int flips; | ||
886 | |||
887 | /* Check for any pending flips. As we only maintain a flip queue depth | ||
888 | * of 1, we can simply insert a WAIT for the next display flip prior | ||
889 | * to executing the batch and avoid stalling the CPU. | ||
890 | */ | ||
891 | flips = 0; | ||
892 | list_for_each_entry(obj, objects, exec_list) { | ||
893 | if (obj->base.write_domain) | ||
894 | flips |= atomic_read(&obj->pending_flip); | ||
895 | } | ||
896 | if (flips) { | ||
897 | int plane, flip_mask, ret; | ||
898 | |||
899 | for (plane = 0; flips >> plane; plane++) { | ||
900 | if (((flips >> plane) & 1) == 0) | ||
901 | continue; | ||
902 | |||
903 | if (plane) | ||
904 | flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; | ||
905 | else | ||
906 | flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; | ||
907 | |||
908 | ret = intel_ring_begin(ring, 2); | ||
909 | if (ret) | ||
910 | return ret; | ||
911 | |||
912 | intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask); | ||
913 | intel_ring_emit(ring, MI_NOOP); | ||
914 | intel_ring_advance(ring); | ||
915 | } | ||
916 | } | ||
917 | |||
918 | return 0; | ||
919 | } | ||
920 | |||
921 | static void | 887 | static void |
922 | i915_gem_execbuffer_move_to_active(struct list_head *objects, | 888 | i915_gem_execbuffer_move_to_active(struct list_head *objects, |
923 | struct intel_ring_buffer *ring, | 889 | struct intel_ring_buffer *ring, |
@@ -926,6 +892,10 @@ i915_gem_execbuffer_move_to_active(struct list_head *objects, | |||
926 | struct drm_i915_gem_object *obj; | 892 | struct drm_i915_gem_object *obj; |
927 | 893 | ||
928 | list_for_each_entry(obj, objects, exec_list) { | 894 | list_for_each_entry(obj, objects, exec_list) { |
895 | u32 old_read = obj->base.read_domains; | ||
896 | u32 old_write = obj->base.write_domain; | ||
897 | |||
898 | |||
929 | obj->base.read_domains = obj->base.pending_read_domains; | 899 | obj->base.read_domains = obj->base.pending_read_domains; |
930 | obj->base.write_domain = obj->base.pending_write_domain; | 900 | obj->base.write_domain = obj->base.pending_write_domain; |
931 | obj->fenced_gpu_access = obj->pending_fenced_gpu_access; | 901 | obj->fenced_gpu_access = obj->pending_fenced_gpu_access; |
@@ -939,9 +909,7 @@ i915_gem_execbuffer_move_to_active(struct list_head *objects, | |||
939 | intel_mark_busy(ring->dev, obj); | 909 | intel_mark_busy(ring->dev, obj); |
940 | } | 910 | } |
941 | 911 | ||
942 | trace_i915_gem_object_change_domain(obj, | 912 | trace_i915_gem_object_change_domain(obj, old_read, old_write); |
943 | obj->base.read_domains, | ||
944 | obj->base.write_domain); | ||
945 | } | 913 | } |
946 | } | 914 | } |
947 | 915 | ||
@@ -963,14 +931,14 @@ i915_gem_execbuffer_retire_commands(struct drm_device *dev, | |||
963 | if (INTEL_INFO(dev)->gen >= 4) | 931 | if (INTEL_INFO(dev)->gen >= 4) |
964 | invalidate |= I915_GEM_DOMAIN_SAMPLER; | 932 | invalidate |= I915_GEM_DOMAIN_SAMPLER; |
965 | if (ring->flush(ring, invalidate, 0)) { | 933 | if (ring->flush(ring, invalidate, 0)) { |
966 | i915_gem_next_request_seqno(dev, ring); | 934 | i915_gem_next_request_seqno(ring); |
967 | return; | 935 | return; |
968 | } | 936 | } |
969 | 937 | ||
970 | /* Add a breadcrumb for the completion of the batch buffer */ | 938 | /* Add a breadcrumb for the completion of the batch buffer */ |
971 | request = kzalloc(sizeof(*request), GFP_KERNEL); | 939 | request = kzalloc(sizeof(*request), GFP_KERNEL); |
972 | if (request == NULL || i915_add_request(dev, file, request, ring)) { | 940 | if (request == NULL || i915_add_request(ring, file, request)) { |
973 | i915_gem_next_request_seqno(dev, ring); | 941 | i915_gem_next_request_seqno(ring); |
974 | kfree(request); | 942 | kfree(request); |
975 | } | 943 | } |
976 | } | 944 | } |
@@ -1000,10 +968,6 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
1000 | if (ret) | 968 | if (ret) |
1001 | return ret; | 969 | return ret; |
1002 | 970 | ||
1003 | #if WATCH_EXEC | ||
1004 | DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", | ||
1005 | (int) args->buffers_ptr, args->buffer_count, args->batch_len); | ||
1006 | #endif | ||
1007 | switch (args->flags & I915_EXEC_RING_MASK) { | 971 | switch (args->flags & I915_EXEC_RING_MASK) { |
1008 | case I915_EXEC_DEFAULT: | 972 | case I915_EXEC_DEFAULT: |
1009 | case I915_EXEC_RENDER: | 973 | case I915_EXEC_RENDER: |
@@ -1113,7 +1077,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
1113 | 1077 | ||
1114 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, | 1078 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, |
1115 | exec[i].handle)); | 1079 | exec[i].handle)); |
1116 | if (obj == NULL) { | 1080 | if (&obj->base == NULL) { |
1117 | DRM_ERROR("Invalid object handle %d at index %d\n", | 1081 | DRM_ERROR("Invalid object handle %d at index %d\n", |
1118 | exec[i].handle, i); | 1082 | exec[i].handle, i); |
1119 | /* prevent error path from reading uninitialized data */ | 1083 | /* prevent error path from reading uninitialized data */ |
@@ -1170,11 +1134,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
1170 | if (ret) | 1134 | if (ret) |
1171 | goto err; | 1135 | goto err; |
1172 | 1136 | ||
1173 | ret = i915_gem_execbuffer_wait_for_flips(ring, &objects); | 1137 | seqno = i915_gem_next_request_seqno(ring); |
1174 | if (ret) | ||
1175 | goto err; | ||
1176 | |||
1177 | seqno = i915_gem_next_request_seqno(dev, ring); | ||
1178 | for (i = 0; i < ARRAY_SIZE(ring->sync_seqno); i++) { | 1138 | for (i = 0; i < ARRAY_SIZE(ring->sync_seqno); i++) { |
1179 | if (seqno < ring->sync_seqno[i]) { | 1139 | if (seqno < ring->sync_seqno[i]) { |
1180 | /* The GPU can not handle its semaphore value wrapping, | 1140 | /* The GPU can not handle its semaphore value wrapping, |
@@ -1189,6 +1149,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
1189 | } | 1149 | } |
1190 | } | 1150 | } |
1191 | 1151 | ||
1152 | trace_i915_gem_ring_dispatch(ring, seqno); | ||
1153 | |||
1192 | exec_start = batch_obj->gtt_offset + args->batch_start_offset; | 1154 | exec_start = batch_obj->gtt_offset + args->batch_start_offset; |
1193 | exec_len = args->batch_len; | 1155 | exec_len = args->batch_len; |
1194 | if (cliprects) { | 1156 | if (cliprects) { |
@@ -1245,11 +1207,6 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
1245 | struct drm_i915_gem_exec_object2 *exec2_list = NULL; | 1207 | struct drm_i915_gem_exec_object2 *exec2_list = NULL; |
1246 | int ret, i; | 1208 | int ret, i; |
1247 | 1209 | ||
1248 | #if WATCH_EXEC | ||
1249 | DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", | ||
1250 | (int) args->buffers_ptr, args->buffer_count, args->batch_len); | ||
1251 | #endif | ||
1252 | |||
1253 | if (args->buffer_count < 1) { | 1210 | if (args->buffer_count < 1) { |
1254 | DRM_ERROR("execbuf with %d buffers\n", args->buffer_count); | 1211 | DRM_ERROR("execbuf with %d buffers\n", args->buffer_count); |
1255 | return -EINVAL; | 1212 | return -EINVAL; |
@@ -1330,17 +1287,16 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data, | |||
1330 | struct drm_i915_gem_exec_object2 *exec2_list = NULL; | 1287 | struct drm_i915_gem_exec_object2 *exec2_list = NULL; |
1331 | int ret; | 1288 | int ret; |
1332 | 1289 | ||
1333 | #if WATCH_EXEC | ||
1334 | DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", | ||
1335 | (int) args->buffers_ptr, args->buffer_count, args->batch_len); | ||
1336 | #endif | ||
1337 | |||
1338 | if (args->buffer_count < 1) { | 1290 | if (args->buffer_count < 1) { |
1339 | DRM_ERROR("execbuf2 with %d buffers\n", args->buffer_count); | 1291 | DRM_ERROR("execbuf2 with %d buffers\n", args->buffer_count); |
1340 | return -EINVAL; | 1292 | return -EINVAL; |
1341 | } | 1293 | } |
1342 | 1294 | ||
1343 | exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count); | 1295 | exec2_list = kmalloc(sizeof(*exec2_list)*args->buffer_count, |
1296 | GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY); | ||
1297 | if (exec2_list == NULL) | ||
1298 | exec2_list = drm_malloc_ab(sizeof(*exec2_list), | ||
1299 | args->buffer_count); | ||
1344 | if (exec2_list == NULL) { | 1300 | if (exec2_list == NULL) { |
1345 | DRM_ERROR("Failed to allocate exec list for %d buffers\n", | 1301 | DRM_ERROR("Failed to allocate exec list for %d buffers\n", |
1346 | args->buffer_count); | 1302 | args->buffer_count); |
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index d64843e18df..281ad3d6115 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c | |||
@@ -284,14 +284,10 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, | |||
284 | struct drm_i915_gem_set_tiling *args = data; | 284 | struct drm_i915_gem_set_tiling *args = data; |
285 | drm_i915_private_t *dev_priv = dev->dev_private; | 285 | drm_i915_private_t *dev_priv = dev->dev_private; |
286 | struct drm_i915_gem_object *obj; | 286 | struct drm_i915_gem_object *obj; |
287 | int ret; | 287 | int ret = 0; |
288 | |||
289 | ret = i915_gem_check_is_wedged(dev); | ||
290 | if (ret) | ||
291 | return ret; | ||
292 | 288 | ||
293 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); | 289 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); |
294 | if (obj == NULL) | 290 | if (&obj->base == NULL) |
295 | return -ENOENT; | 291 | return -ENOENT; |
296 | 292 | ||
297 | if (!i915_tiling_ok(dev, | 293 | if (!i915_tiling_ok(dev, |
@@ -384,7 +380,7 @@ i915_gem_get_tiling(struct drm_device *dev, void *data, | |||
384 | struct drm_i915_gem_object *obj; | 380 | struct drm_i915_gem_object *obj; |
385 | 381 | ||
386 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); | 382 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); |
387 | if (obj == NULL) | 383 | if (&obj->base == NULL) |
388 | return -ENOENT; | 384 | return -ENOENT; |
389 | 385 | ||
390 | mutex_lock(&dev->struct_mutex); | 386 | mutex_lock(&dev->struct_mutex); |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 8a9e08bf1cf..188b497e507 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -85,21 +85,11 @@ ironlake_disable_display_irq(drm_i915_private_t *dev_priv, u32 mask) | |||
85 | } | 85 | } |
86 | } | 86 | } |
87 | 87 | ||
88 | static inline u32 | ||
89 | i915_pipestat(int pipe) | ||
90 | { | ||
91 | if (pipe == 0) | ||
92 | return PIPEASTAT; | ||
93 | if (pipe == 1) | ||
94 | return PIPEBSTAT; | ||
95 | BUG(); | ||
96 | } | ||
97 | |||
98 | void | 88 | void |
99 | i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask) | 89 | i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask) |
100 | { | 90 | { |
101 | if ((dev_priv->pipestat[pipe] & mask) != mask) { | 91 | if ((dev_priv->pipestat[pipe] & mask) != mask) { |
102 | u32 reg = i915_pipestat(pipe); | 92 | u32 reg = PIPESTAT(pipe); |
103 | 93 | ||
104 | dev_priv->pipestat[pipe] |= mask; | 94 | dev_priv->pipestat[pipe] |= mask; |
105 | /* Enable the interrupt, clear any pending status */ | 95 | /* Enable the interrupt, clear any pending status */ |
@@ -112,7 +102,7 @@ void | |||
112 | i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask) | 102 | i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask) |
113 | { | 103 | { |
114 | if ((dev_priv->pipestat[pipe] & mask) != 0) { | 104 | if ((dev_priv->pipestat[pipe] & mask) != 0) { |
115 | u32 reg = i915_pipestat(pipe); | 105 | u32 reg = PIPESTAT(pipe); |
116 | 106 | ||
117 | dev_priv->pipestat[pipe] &= ~mask; | 107 | dev_priv->pipestat[pipe] &= ~mask; |
118 | I915_WRITE(reg, dev_priv->pipestat[pipe]); | 108 | I915_WRITE(reg, dev_priv->pipestat[pipe]); |
@@ -171,12 +161,12 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) | |||
171 | 161 | ||
172 | if (!i915_pipe_enabled(dev, pipe)) { | 162 | if (!i915_pipe_enabled(dev, pipe)) { |
173 | DRM_DEBUG_DRIVER("trying to get vblank count for disabled " | 163 | DRM_DEBUG_DRIVER("trying to get vblank count for disabled " |
174 | "pipe %d\n", pipe); | 164 | "pipe %c\n", pipe_name(pipe)); |
175 | return 0; | 165 | return 0; |
176 | } | 166 | } |
177 | 167 | ||
178 | high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH; | 168 | high_frame = PIPEFRAME(pipe); |
179 | low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL; | 169 | low_frame = PIPEFRAMEPIXEL(pipe); |
180 | 170 | ||
181 | /* | 171 | /* |
182 | * High & low register fields aren't synchronized, so make sure | 172 | * High & low register fields aren't synchronized, so make sure |
@@ -197,11 +187,11 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) | |||
197 | u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) | 187 | u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) |
198 | { | 188 | { |
199 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 189 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
200 | int reg = pipe ? PIPEB_FRMCOUNT_GM45 : PIPEA_FRMCOUNT_GM45; | 190 | int reg = PIPE_FRMCOUNT_GM45(pipe); |
201 | 191 | ||
202 | if (!i915_pipe_enabled(dev, pipe)) { | 192 | if (!i915_pipe_enabled(dev, pipe)) { |
203 | DRM_DEBUG_DRIVER("trying to get vblank count for disabled " | 193 | DRM_DEBUG_DRIVER("trying to get vblank count for disabled " |
204 | "pipe %d\n", pipe); | 194 | "pipe %c\n", pipe_name(pipe)); |
205 | return 0; | 195 | return 0; |
206 | } | 196 | } |
207 | 197 | ||
@@ -219,7 +209,7 @@ int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, | |||
219 | 209 | ||
220 | if (!i915_pipe_enabled(dev, pipe)) { | 210 | if (!i915_pipe_enabled(dev, pipe)) { |
221 | DRM_DEBUG_DRIVER("trying to get scanoutpos for disabled " | 211 | DRM_DEBUG_DRIVER("trying to get scanoutpos for disabled " |
222 | "pipe %d\n", pipe); | 212 | "pipe %c\n", pipe_name(pipe)); |
223 | return 0; | 213 | return 0; |
224 | } | 214 | } |
225 | 215 | ||
@@ -367,7 +357,7 @@ static void notify_ring(struct drm_device *dev, | |||
367 | return; | 357 | return; |
368 | 358 | ||
369 | seqno = ring->get_seqno(ring); | 359 | seqno = ring->get_seqno(ring); |
370 | trace_i915_gem_request_complete(dev, seqno); | 360 | trace_i915_gem_request_complete(ring, seqno); |
371 | 361 | ||
372 | ring->irq_seqno = seqno; | 362 | ring->irq_seqno = seqno; |
373 | wake_up_all(&ring->irq_queue); | 363 | wake_up_all(&ring->irq_queue); |
@@ -419,6 +409,7 @@ static void pch_irq_handler(struct drm_device *dev) | |||
419 | { | 409 | { |
420 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 410 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
421 | u32 pch_iir; | 411 | u32 pch_iir; |
412 | int pipe; | ||
422 | 413 | ||
423 | pch_iir = I915_READ(SDEIIR); | 414 | pch_iir = I915_READ(SDEIIR); |
424 | 415 | ||
@@ -439,13 +430,11 @@ static void pch_irq_handler(struct drm_device *dev) | |||
439 | if (pch_iir & SDE_POISON) | 430 | if (pch_iir & SDE_POISON) |
440 | DRM_ERROR("PCH poison interrupt\n"); | 431 | DRM_ERROR("PCH poison interrupt\n"); |
441 | 432 | ||
442 | if (pch_iir & SDE_FDI_MASK) { | 433 | if (pch_iir & SDE_FDI_MASK) |
443 | u32 fdia, fdib; | 434 | for_each_pipe(pipe) |
444 | 435 | DRM_DEBUG_DRIVER(" pipe %c FDI IIR: 0x%08x\n", | |
445 | fdia = I915_READ(FDI_RXA_IIR); | 436 | pipe_name(pipe), |
446 | fdib = I915_READ(FDI_RXB_IIR); | 437 | I915_READ(FDI_RX_IIR(pipe))); |
447 | DRM_DEBUG_DRIVER("PCH FDI RX interrupt; FDI RXA IIR: 0x%08x, FDI RXB IIR: 0x%08x\n", fdia, fdib); | ||
448 | } | ||
449 | 438 | ||
450 | if (pch_iir & (SDE_TRANSB_CRC_DONE | SDE_TRANSA_CRC_DONE)) | 439 | if (pch_iir & (SDE_TRANSB_CRC_DONE | SDE_TRANSA_CRC_DONE)) |
451 | DRM_DEBUG_DRIVER("PCH transcoder CRC done interrupt\n"); | 440 | DRM_DEBUG_DRIVER("PCH transcoder CRC done interrupt\n"); |
@@ -650,9 +639,14 @@ static void | |||
650 | i915_error_state_free(struct drm_device *dev, | 639 | i915_error_state_free(struct drm_device *dev, |
651 | struct drm_i915_error_state *error) | 640 | struct drm_i915_error_state *error) |
652 | { | 641 | { |
653 | i915_error_object_free(error->batchbuffer[0]); | 642 | int i; |
654 | i915_error_object_free(error->batchbuffer[1]); | 643 | |
655 | i915_error_object_free(error->ringbuffer); | 644 | for (i = 0; i < ARRAY_SIZE(error->batchbuffer); i++) |
645 | i915_error_object_free(error->batchbuffer[i]); | ||
646 | |||
647 | for (i = 0; i < ARRAY_SIZE(error->ringbuffer); i++) | ||
648 | i915_error_object_free(error->ringbuffer[i]); | ||
649 | |||
656 | kfree(error->active_bo); | 650 | kfree(error->active_bo); |
657 | kfree(error->overlay); | 651 | kfree(error->overlay); |
658 | kfree(error); | 652 | kfree(error); |
@@ -767,7 +761,7 @@ static void i915_capture_error_state(struct drm_device *dev) | |||
767 | struct drm_i915_gem_object *obj; | 761 | struct drm_i915_gem_object *obj; |
768 | struct drm_i915_error_state *error; | 762 | struct drm_i915_error_state *error; |
769 | unsigned long flags; | 763 | unsigned long flags; |
770 | int i; | 764 | int i, pipe; |
771 | 765 | ||
772 | spin_lock_irqsave(&dev_priv->error_lock, flags); | 766 | spin_lock_irqsave(&dev_priv->error_lock, flags); |
773 | error = dev_priv->first_error; | 767 | error = dev_priv->first_error; |
@@ -775,19 +769,21 @@ static void i915_capture_error_state(struct drm_device *dev) | |||
775 | if (error) | 769 | if (error) |
776 | return; | 770 | return; |
777 | 771 | ||
772 | /* Account for pipe specific data like PIPE*STAT */ | ||
778 | error = kmalloc(sizeof(*error), GFP_ATOMIC); | 773 | error = kmalloc(sizeof(*error), GFP_ATOMIC); |
779 | if (!error) { | 774 | if (!error) { |
780 | DRM_DEBUG_DRIVER("out of memory, not capturing error state\n"); | 775 | DRM_DEBUG_DRIVER("out of memory, not capturing error state\n"); |
781 | return; | 776 | return; |
782 | } | 777 | } |
783 | 778 | ||
784 | DRM_DEBUG_DRIVER("generating error event\n"); | 779 | DRM_INFO("capturing error event; look for more information in /debug/dri/%d/i915_error_state\n", |
780 | dev->primary->index); | ||
785 | 781 | ||
786 | error->seqno = dev_priv->ring[RCS].get_seqno(&dev_priv->ring[RCS]); | 782 | error->seqno = dev_priv->ring[RCS].get_seqno(&dev_priv->ring[RCS]); |
787 | error->eir = I915_READ(EIR); | 783 | error->eir = I915_READ(EIR); |
788 | error->pgtbl_er = I915_READ(PGTBL_ER); | 784 | error->pgtbl_er = I915_READ(PGTBL_ER); |
789 | error->pipeastat = I915_READ(PIPEASTAT); | 785 | for_each_pipe(pipe) |
790 | error->pipebstat = I915_READ(PIPEBSTAT); | 786 | error->pipestat[pipe] = I915_READ(PIPESTAT(pipe)); |
791 | error->instpm = I915_READ(INSTPM); | 787 | error->instpm = I915_READ(INSTPM); |
792 | error->error = 0; | 788 | error->error = 0; |
793 | if (INTEL_INFO(dev)->gen >= 6) { | 789 | if (INTEL_INFO(dev)->gen >= 6) { |
@@ -826,15 +822,16 @@ static void i915_capture_error_state(struct drm_device *dev) | |||
826 | } | 822 | } |
827 | i915_gem_record_fences(dev, error); | 823 | i915_gem_record_fences(dev, error); |
828 | 824 | ||
829 | /* Record the active batchbuffers */ | 825 | /* Record the active batch and ring buffers */ |
830 | for (i = 0; i < I915_NUM_RINGS; i++) | 826 | for (i = 0; i < I915_NUM_RINGS; i++) { |
831 | error->batchbuffer[i] = | 827 | error->batchbuffer[i] = |
832 | i915_error_first_batchbuffer(dev_priv, | 828 | i915_error_first_batchbuffer(dev_priv, |
833 | &dev_priv->ring[i]); | 829 | &dev_priv->ring[i]); |
834 | 830 | ||
835 | /* Record the ringbuffer */ | 831 | error->ringbuffer[i] = |
836 | error->ringbuffer = i915_error_object_create(dev_priv, | 832 | i915_error_object_create(dev_priv, |
837 | dev_priv->ring[RCS].obj); | 833 | dev_priv->ring[i].obj); |
834 | } | ||
838 | 835 | ||
839 | /* Record buffers on the active and pinned lists. */ | 836 | /* Record buffers on the active and pinned lists. */ |
840 | error->active_bo = NULL; | 837 | error->active_bo = NULL; |
@@ -907,6 +904,7 @@ static void i915_report_and_clear_eir(struct drm_device *dev) | |||
907 | { | 904 | { |
908 | struct drm_i915_private *dev_priv = dev->dev_private; | 905 | struct drm_i915_private *dev_priv = dev->dev_private; |
909 | u32 eir = I915_READ(EIR); | 906 | u32 eir = I915_READ(EIR); |
907 | int pipe; | ||
910 | 908 | ||
911 | if (!eir) | 909 | if (!eir) |
912 | return; | 910 | return; |
@@ -955,14 +953,10 @@ static void i915_report_and_clear_eir(struct drm_device *dev) | |||
955 | } | 953 | } |
956 | 954 | ||
957 | if (eir & I915_ERROR_MEMORY_REFRESH) { | 955 | if (eir & I915_ERROR_MEMORY_REFRESH) { |
958 | u32 pipea_stats = I915_READ(PIPEASTAT); | 956 | printk(KERN_ERR "memory refresh error:\n"); |
959 | u32 pipeb_stats = I915_READ(PIPEBSTAT); | 957 | for_each_pipe(pipe) |
960 | 958 | printk(KERN_ERR "pipe %c stat: 0x%08x\n", | |
961 | printk(KERN_ERR "memory refresh error\n"); | 959 | pipe_name(pipe), I915_READ(PIPESTAT(pipe))); |
962 | printk(KERN_ERR "PIPEASTAT: 0x%08x\n", | ||
963 | pipea_stats); | ||
964 | printk(KERN_ERR "PIPEBSTAT: 0x%08x\n", | ||
965 | pipeb_stats); | ||
966 | /* pipestat has already been acked */ | 960 | /* pipestat has already been acked */ |
967 | } | 961 | } |
968 | if (eir & I915_ERROR_INSTRUCTION) { | 962 | if (eir & I915_ERROR_INSTRUCTION) { |
@@ -1076,10 +1070,10 @@ static void i915_pageflip_stall_check(struct drm_device *dev, int pipe) | |||
1076 | /* Potential stall - if we see that the flip has happened, assume a missed interrupt */ | 1070 | /* Potential stall - if we see that the flip has happened, assume a missed interrupt */ |
1077 | obj = work->pending_flip_obj; | 1071 | obj = work->pending_flip_obj; |
1078 | if (INTEL_INFO(dev)->gen >= 4) { | 1072 | if (INTEL_INFO(dev)->gen >= 4) { |
1079 | int dspsurf = intel_crtc->plane == 0 ? DSPASURF : DSPBSURF; | 1073 | int dspsurf = DSPSURF(intel_crtc->plane); |
1080 | stall_detected = I915_READ(dspsurf) == obj->gtt_offset; | 1074 | stall_detected = I915_READ(dspsurf) == obj->gtt_offset; |
1081 | } else { | 1075 | } else { |
1082 | int dspaddr = intel_crtc->plane == 0 ? DSPAADDR : DSPBADDR; | 1076 | int dspaddr = DSPADDR(intel_crtc->plane); |
1083 | stall_detected = I915_READ(dspaddr) == (obj->gtt_offset + | 1077 | stall_detected = I915_READ(dspaddr) == (obj->gtt_offset + |
1084 | crtc->y * crtc->fb->pitch + | 1078 | crtc->y * crtc->fb->pitch + |
1085 | crtc->x * crtc->fb->bits_per_pixel/8); | 1079 | crtc->x * crtc->fb->bits_per_pixel/8); |
@@ -1099,12 +1093,13 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
1099 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 1093 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
1100 | struct drm_i915_master_private *master_priv; | 1094 | struct drm_i915_master_private *master_priv; |
1101 | u32 iir, new_iir; | 1095 | u32 iir, new_iir; |
1102 | u32 pipea_stats, pipeb_stats; | 1096 | u32 pipe_stats[I915_MAX_PIPES]; |
1103 | u32 vblank_status; | 1097 | u32 vblank_status; |
1104 | int vblank = 0; | 1098 | int vblank = 0; |
1105 | unsigned long irqflags; | 1099 | unsigned long irqflags; |
1106 | int irq_received; | 1100 | int irq_received; |
1107 | int ret = IRQ_NONE; | 1101 | int ret = IRQ_NONE, pipe; |
1102 | bool blc_event = false; | ||
1108 | 1103 | ||
1109 | atomic_inc(&dev_priv->irq_received); | 1104 | atomic_inc(&dev_priv->irq_received); |
1110 | 1105 | ||
@@ -1127,27 +1122,23 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
1127 | * interrupts (for non-MSI). | 1122 | * interrupts (for non-MSI). |
1128 | */ | 1123 | */ |
1129 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); | 1124 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); |
1130 | pipea_stats = I915_READ(PIPEASTAT); | ||
1131 | pipeb_stats = I915_READ(PIPEBSTAT); | ||
1132 | |||
1133 | if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) | 1125 | if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) |
1134 | i915_handle_error(dev, false); | 1126 | i915_handle_error(dev, false); |
1135 | 1127 | ||
1136 | /* | 1128 | for_each_pipe(pipe) { |
1137 | * Clear the PIPE(A|B)STAT regs before the IIR | 1129 | int reg = PIPESTAT(pipe); |
1138 | */ | 1130 | pipe_stats[pipe] = I915_READ(reg); |
1139 | if (pipea_stats & 0x8000ffff) { | 1131 | |
1140 | if (pipea_stats & PIPE_FIFO_UNDERRUN_STATUS) | 1132 | /* |
1141 | DRM_DEBUG_DRIVER("pipe a underrun\n"); | 1133 | * Clear the PIPE*STAT regs before the IIR |
1142 | I915_WRITE(PIPEASTAT, pipea_stats); | 1134 | */ |
1143 | irq_received = 1; | 1135 | if (pipe_stats[pipe] & 0x8000ffff) { |
1144 | } | 1136 | if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) |
1145 | 1137 | DRM_DEBUG_DRIVER("pipe %c underrun\n", | |
1146 | if (pipeb_stats & 0x8000ffff) { | 1138 | pipe_name(pipe)); |
1147 | if (pipeb_stats & PIPE_FIFO_UNDERRUN_STATUS) | 1139 | I915_WRITE(reg, pipe_stats[pipe]); |
1148 | DRM_DEBUG_DRIVER("pipe b underrun\n"); | 1140 | irq_received = 1; |
1149 | I915_WRITE(PIPEBSTAT, pipeb_stats); | 1141 | } |
1150 | irq_received = 1; | ||
1151 | } | 1142 | } |
1152 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | 1143 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); |
1153 | 1144 | ||
@@ -1198,27 +1189,22 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
1198 | intel_finish_page_flip_plane(dev, 1); | 1189 | intel_finish_page_flip_plane(dev, 1); |
1199 | } | 1190 | } |
1200 | 1191 | ||
1201 | if (pipea_stats & vblank_status && | 1192 | for_each_pipe(pipe) { |
1202 | drm_handle_vblank(dev, 0)) { | 1193 | if (pipe_stats[pipe] & vblank_status && |
1203 | vblank++; | 1194 | drm_handle_vblank(dev, pipe)) { |
1204 | if (!dev_priv->flip_pending_is_done) { | 1195 | vblank++; |
1205 | i915_pageflip_stall_check(dev, 0); | 1196 | if (!dev_priv->flip_pending_is_done) { |
1206 | intel_finish_page_flip(dev, 0); | 1197 | i915_pageflip_stall_check(dev, pipe); |
1198 | intel_finish_page_flip(dev, pipe); | ||
1199 | } | ||
1207 | } | 1200 | } |
1208 | } | ||
1209 | 1201 | ||
1210 | if (pipeb_stats & vblank_status && | 1202 | if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) |
1211 | drm_handle_vblank(dev, 1)) { | 1203 | blc_event = true; |
1212 | vblank++; | ||
1213 | if (!dev_priv->flip_pending_is_done) { | ||
1214 | i915_pageflip_stall_check(dev, 1); | ||
1215 | intel_finish_page_flip(dev, 1); | ||
1216 | } | ||
1217 | } | 1204 | } |
1218 | 1205 | ||
1219 | if ((pipea_stats & PIPE_LEGACY_BLC_EVENT_STATUS) || | 1206 | |
1220 | (pipeb_stats & PIPE_LEGACY_BLC_EVENT_STATUS) || | 1207 | if (blc_event || (iir & I915_ASLE_INTERRUPT)) |
1221 | (iir & I915_ASLE_INTERRUPT)) | ||
1222 | intel_opregion_asle_intr(dev); | 1208 | intel_opregion_asle_intr(dev); |
1223 | 1209 | ||
1224 | /* With MSI, interrupts are only generated when iir | 1210 | /* With MSI, interrupts are only generated when iir |
@@ -1268,16 +1254,6 @@ static int i915_emit_irq(struct drm_device * dev) | |||
1268 | return dev_priv->counter; | 1254 | return dev_priv->counter; |
1269 | } | 1255 | } |
1270 | 1256 | ||
1271 | void i915_trace_irq_get(struct drm_device *dev, u32 seqno) | ||
1272 | { | ||
1273 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | ||
1274 | struct intel_ring_buffer *ring = LP_RING(dev_priv); | ||
1275 | |||
1276 | if (dev_priv->trace_irq_seqno == 0 && | ||
1277 | ring->irq_get(ring)) | ||
1278 | dev_priv->trace_irq_seqno = seqno; | ||
1279 | } | ||
1280 | |||
1281 | static int i915_wait_irq(struct drm_device * dev, int irq_nr) | 1257 | static int i915_wait_irq(struct drm_device * dev, int irq_nr) |
1282 | { | 1258 | { |
1283 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 1259 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
@@ -1377,7 +1353,12 @@ int i915_enable_vblank(struct drm_device *dev, int pipe) | |||
1377 | else | 1353 | else |
1378 | i915_enable_pipestat(dev_priv, pipe, | 1354 | i915_enable_pipestat(dev_priv, pipe, |
1379 | PIPE_VBLANK_INTERRUPT_ENABLE); | 1355 | PIPE_VBLANK_INTERRUPT_ENABLE); |
1356 | |||
1357 | /* maintain vblank delivery even in deep C-states */ | ||
1358 | if (dev_priv->info->gen == 3) | ||
1359 | I915_WRITE(INSTPM, INSTPM_AGPBUSY_DIS << 16); | ||
1380 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | 1360 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); |
1361 | |||
1381 | return 0; | 1362 | return 0; |
1382 | } | 1363 | } |
1383 | 1364 | ||
@@ -1390,6 +1371,10 @@ void i915_disable_vblank(struct drm_device *dev, int pipe) | |||
1390 | unsigned long irqflags; | 1371 | unsigned long irqflags; |
1391 | 1372 | ||
1392 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); | 1373 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); |
1374 | if (dev_priv->info->gen == 3) | ||
1375 | I915_WRITE(INSTPM, | ||
1376 | INSTPM_AGPBUSY_DIS << 16 | INSTPM_AGPBUSY_DIS); | ||
1377 | |||
1393 | if (HAS_PCH_SPLIT(dev)) | 1378 | if (HAS_PCH_SPLIT(dev)) |
1394 | ironlake_disable_display_irq(dev_priv, (pipe == 0) ? | 1379 | ironlake_disable_display_irq(dev_priv, (pipe == 0) ? |
1395 | DE_PIPEA_VBLANK: DE_PIPEB_VBLANK); | 1380 | DE_PIPEA_VBLANK: DE_PIPEB_VBLANK); |
@@ -1400,16 +1385,6 @@ void i915_disable_vblank(struct drm_device *dev, int pipe) | |||
1400 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | 1385 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); |
1401 | } | 1386 | } |
1402 | 1387 | ||
1403 | void i915_enable_interrupt (struct drm_device *dev) | ||
1404 | { | ||
1405 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1406 | |||
1407 | if (!HAS_PCH_SPLIT(dev)) | ||
1408 | intel_opregion_enable_asle(dev); | ||
1409 | dev_priv->irq_enabled = 1; | ||
1410 | } | ||
1411 | |||
1412 | |||
1413 | /* Set the vblank monitor pipe | 1388 | /* Set the vblank monitor pipe |
1414 | */ | 1389 | */ |
1415 | int i915_vblank_pipe_set(struct drm_device *dev, void *data, | 1390 | int i915_vblank_pipe_set(struct drm_device *dev, void *data, |
@@ -1646,12 +1621,16 @@ static int ironlake_irq_postinstall(struct drm_device *dev) | |||
1646 | POSTING_READ(GTIER); | 1621 | POSTING_READ(GTIER); |
1647 | 1622 | ||
1648 | if (HAS_PCH_CPT(dev)) { | 1623 | if (HAS_PCH_CPT(dev)) { |
1649 | hotplug_mask = SDE_CRT_HOTPLUG_CPT | SDE_PORTB_HOTPLUG_CPT | | 1624 | hotplug_mask = (SDE_CRT_HOTPLUG_CPT | |
1650 | SDE_PORTC_HOTPLUG_CPT | SDE_PORTD_HOTPLUG_CPT ; | 1625 | SDE_PORTB_HOTPLUG_CPT | |
1626 | SDE_PORTC_HOTPLUG_CPT | | ||
1627 | SDE_PORTD_HOTPLUG_CPT); | ||
1651 | } else { | 1628 | } else { |
1652 | hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG | | 1629 | hotplug_mask = (SDE_CRT_HOTPLUG | |
1653 | SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG; | 1630 | SDE_PORTB_HOTPLUG | |
1654 | hotplug_mask |= SDE_AUX_MASK; | 1631 | SDE_PORTC_HOTPLUG | |
1632 | SDE_PORTD_HOTPLUG | | ||
1633 | SDE_AUX_MASK); | ||
1655 | } | 1634 | } |
1656 | 1635 | ||
1657 | dev_priv->pch_irq_mask = ~hotplug_mask; | 1636 | dev_priv->pch_irq_mask = ~hotplug_mask; |
@@ -1674,6 +1653,7 @@ static int ironlake_irq_postinstall(struct drm_device *dev) | |||
1674 | void i915_driver_irq_preinstall(struct drm_device * dev) | 1653 | void i915_driver_irq_preinstall(struct drm_device * dev) |
1675 | { | 1654 | { |
1676 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 1655 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
1656 | int pipe; | ||
1677 | 1657 | ||
1678 | atomic_set(&dev_priv->irq_received, 0); | 1658 | atomic_set(&dev_priv->irq_received, 0); |
1679 | 1659 | ||
@@ -1691,8 +1671,8 @@ void i915_driver_irq_preinstall(struct drm_device * dev) | |||
1691 | } | 1671 | } |
1692 | 1672 | ||
1693 | I915_WRITE(HWSTAM, 0xeffe); | 1673 | I915_WRITE(HWSTAM, 0xeffe); |
1694 | I915_WRITE(PIPEASTAT, 0); | 1674 | for_each_pipe(pipe) |
1695 | I915_WRITE(PIPEBSTAT, 0); | 1675 | I915_WRITE(PIPESTAT(pipe), 0); |
1696 | I915_WRITE(IMR, 0xffffffff); | 1676 | I915_WRITE(IMR, 0xffffffff); |
1697 | I915_WRITE(IER, 0x0); | 1677 | I915_WRITE(IER, 0x0); |
1698 | POSTING_READ(IER); | 1678 | POSTING_READ(IER); |
@@ -1804,6 +1784,7 @@ static void ironlake_irq_uninstall(struct drm_device *dev) | |||
1804 | void i915_driver_irq_uninstall(struct drm_device * dev) | 1784 | void i915_driver_irq_uninstall(struct drm_device * dev) |
1805 | { | 1785 | { |
1806 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 1786 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
1787 | int pipe; | ||
1807 | 1788 | ||
1808 | if (!dev_priv) | 1789 | if (!dev_priv) |
1809 | return; | 1790 | return; |
@@ -1821,12 +1802,13 @@ void i915_driver_irq_uninstall(struct drm_device * dev) | |||
1821 | } | 1802 | } |
1822 | 1803 | ||
1823 | I915_WRITE(HWSTAM, 0xffffffff); | 1804 | I915_WRITE(HWSTAM, 0xffffffff); |
1824 | I915_WRITE(PIPEASTAT, 0); | 1805 | for_each_pipe(pipe) |
1825 | I915_WRITE(PIPEBSTAT, 0); | 1806 | I915_WRITE(PIPESTAT(pipe), 0); |
1826 | I915_WRITE(IMR, 0xffffffff); | 1807 | I915_WRITE(IMR, 0xffffffff); |
1827 | I915_WRITE(IER, 0x0); | 1808 | I915_WRITE(IER, 0x0); |
1828 | 1809 | ||
1829 | I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff); | 1810 | for_each_pipe(pipe) |
1830 | I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff); | 1811 | I915_WRITE(PIPESTAT(pipe), |
1812 | I915_READ(PIPESTAT(pipe)) & 0x8000ffff); | ||
1831 | I915_WRITE(IIR, I915_READ(IIR)); | 1813 | I915_WRITE(IIR, I915_READ(IIR)); |
1832 | } | 1814 | } |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2abe240dae5..f39ac3a0fa9 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -405,9 +405,12 @@ | |||
405 | #define I915_ERROR_INSTRUCTION (1<<0) | 405 | #define I915_ERROR_INSTRUCTION (1<<0) |
406 | #define INSTPM 0x020c0 | 406 | #define INSTPM 0x020c0 |
407 | #define INSTPM_SELF_EN (1<<12) /* 915GM only */ | 407 | #define INSTPM_SELF_EN (1<<12) /* 915GM only */ |
408 | #define INSTPM_AGPBUSY_DIS (1<<11) /* gen3: when disabled, pending interrupts | ||
409 | will not assert AGPBUSY# and will only | ||
410 | be delivered when out of C3. */ | ||
408 | #define ACTHD 0x020c8 | 411 | #define ACTHD 0x020c8 |
409 | #define FW_BLC 0x020d8 | 412 | #define FW_BLC 0x020d8 |
410 | #define FW_BLC2 0x020dc | 413 | #define FW_BLC2 0x020dc |
411 | #define FW_BLC_SELF 0x020e0 /* 915+ only */ | 414 | #define FW_BLC_SELF 0x020e0 /* 915+ only */ |
412 | #define FW_BLC_SELF_EN_MASK (1<<31) | 415 | #define FW_BLC_SELF_EN_MASK (1<<31) |
413 | #define FW_BLC_SELF_FIFO_MASK (1<<16) /* 945 only */ | 416 | #define FW_BLC_SELF_FIFO_MASK (1<<16) /* 945 only */ |
@@ -706,9 +709,9 @@ | |||
706 | #define VGA1_PD_P1_DIV_2 (1 << 13) | 709 | #define VGA1_PD_P1_DIV_2 (1 << 13) |
707 | #define VGA1_PD_P1_SHIFT 8 | 710 | #define VGA1_PD_P1_SHIFT 8 |
708 | #define VGA1_PD_P1_MASK (0x1f << 8) | 711 | #define VGA1_PD_P1_MASK (0x1f << 8) |
709 | #define DPLL_A 0x06014 | 712 | #define _DPLL_A 0x06014 |
710 | #define DPLL_B 0x06018 | 713 | #define _DPLL_B 0x06018 |
711 | #define DPLL(pipe) _PIPE(pipe, DPLL_A, DPLL_B) | 714 | #define DPLL(pipe) _PIPE(pipe, _DPLL_A, _DPLL_B) |
712 | #define DPLL_VCO_ENABLE (1 << 31) | 715 | #define DPLL_VCO_ENABLE (1 << 31) |
713 | #define DPLL_DVO_HIGH_SPEED (1 << 30) | 716 | #define DPLL_DVO_HIGH_SPEED (1 << 30) |
714 | #define DPLL_SYNCLOCK_ENABLE (1 << 29) | 717 | #define DPLL_SYNCLOCK_ENABLE (1 << 29) |
@@ -779,7 +782,7 @@ | |||
779 | #define SDVO_MULTIPLIER_MASK 0x000000ff | 782 | #define SDVO_MULTIPLIER_MASK 0x000000ff |
780 | #define SDVO_MULTIPLIER_SHIFT_HIRES 4 | 783 | #define SDVO_MULTIPLIER_SHIFT_HIRES 4 |
781 | #define SDVO_MULTIPLIER_SHIFT_VGA 0 | 784 | #define SDVO_MULTIPLIER_SHIFT_VGA 0 |
782 | #define DPLL_A_MD 0x0601c /* 965+ only */ | 785 | #define _DPLL_A_MD 0x0601c /* 965+ only */ |
783 | /* | 786 | /* |
784 | * UDI pixel divider, controlling how many pixels are stuffed into a packet. | 787 | * UDI pixel divider, controlling how many pixels are stuffed into a packet. |
785 | * | 788 | * |
@@ -816,14 +819,14 @@ | |||
816 | */ | 819 | */ |
817 | #define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f | 820 | #define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f |
818 | #define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0 | 821 | #define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0 |
819 | #define DPLL_B_MD 0x06020 /* 965+ only */ | 822 | #define _DPLL_B_MD 0x06020 /* 965+ only */ |
820 | #define DPLL_MD(pipe) _PIPE(pipe, DPLL_A_MD, DPLL_B_MD) | 823 | #define DPLL_MD(pipe) _PIPE(pipe, _DPLL_A_MD, _DPLL_B_MD) |
821 | #define FPA0 0x06040 | 824 | #define _FPA0 0x06040 |
822 | #define FPA1 0x06044 | 825 | #define _FPA1 0x06044 |
823 | #define FPB0 0x06048 | 826 | #define _FPB0 0x06048 |
824 | #define FPB1 0x0604c | 827 | #define _FPB1 0x0604c |
825 | #define FP0(pipe) _PIPE(pipe, FPA0, FPB0) | 828 | #define FP0(pipe) _PIPE(pipe, _FPA0, _FPB0) |
826 | #define FP1(pipe) _PIPE(pipe, FPA1, FPB1) | 829 | #define FP1(pipe) _PIPE(pipe, _FPA1, _FPB1) |
827 | #define FP_N_DIV_MASK 0x003f0000 | 830 | #define FP_N_DIV_MASK 0x003f0000 |
828 | #define FP_N_PINEVIEW_DIV_MASK 0x00ff0000 | 831 | #define FP_N_PINEVIEW_DIV_MASK 0x00ff0000 |
829 | #define FP_N_DIV_SHIFT 16 | 832 | #define FP_N_DIV_SHIFT 16 |
@@ -962,8 +965,9 @@ | |||
962 | * Palette regs | 965 | * Palette regs |
963 | */ | 966 | */ |
964 | 967 | ||
965 | #define PALETTE_A 0x0a000 | 968 | #define _PALETTE_A 0x0a000 |
966 | #define PALETTE_B 0x0a800 | 969 | #define _PALETTE_B 0x0a800 |
970 | #define PALETTE(pipe) _PIPE(pipe, _PALETTE_A, _PALETTE_B) | ||
967 | 971 | ||
968 | /* MCH MMIO space */ | 972 | /* MCH MMIO space */ |
969 | 973 | ||
@@ -1267,32 +1271,32 @@ | |||
1267 | */ | 1271 | */ |
1268 | 1272 | ||
1269 | /* Pipe A timing regs */ | 1273 | /* Pipe A timing regs */ |
1270 | #define HTOTAL_A 0x60000 | 1274 | #define _HTOTAL_A 0x60000 |
1271 | #define HBLANK_A 0x60004 | 1275 | #define _HBLANK_A 0x60004 |
1272 | #define HSYNC_A 0x60008 | 1276 | #define _HSYNC_A 0x60008 |
1273 | #define VTOTAL_A 0x6000c | 1277 | #define _VTOTAL_A 0x6000c |
1274 | #define VBLANK_A 0x60010 | 1278 | #define _VBLANK_A 0x60010 |
1275 | #define VSYNC_A 0x60014 | 1279 | #define _VSYNC_A 0x60014 |
1276 | #define PIPEASRC 0x6001c | 1280 | #define _PIPEASRC 0x6001c |
1277 | #define BCLRPAT_A 0x60020 | 1281 | #define _BCLRPAT_A 0x60020 |
1278 | 1282 | ||
1279 | /* Pipe B timing regs */ | 1283 | /* Pipe B timing regs */ |
1280 | #define HTOTAL_B 0x61000 | 1284 | #define _HTOTAL_B 0x61000 |
1281 | #define HBLANK_B 0x61004 | 1285 | #define _HBLANK_B 0x61004 |
1282 | #define HSYNC_B 0x61008 | 1286 | #define _HSYNC_B 0x61008 |
1283 | #define VTOTAL_B 0x6100c | 1287 | #define _VTOTAL_B 0x6100c |
1284 | #define VBLANK_B 0x61010 | 1288 | #define _VBLANK_B 0x61010 |
1285 | #define VSYNC_B 0x61014 | 1289 | #define _VSYNC_B 0x61014 |
1286 | #define PIPEBSRC 0x6101c | 1290 | #define _PIPEBSRC 0x6101c |
1287 | #define BCLRPAT_B 0x61020 | 1291 | #define _BCLRPAT_B 0x61020 |
1288 | 1292 | ||
1289 | #define HTOTAL(pipe) _PIPE(pipe, HTOTAL_A, HTOTAL_B) | 1293 | #define HTOTAL(pipe) _PIPE(pipe, _HTOTAL_A, _HTOTAL_B) |
1290 | #define HBLANK(pipe) _PIPE(pipe, HBLANK_A, HBLANK_B) | 1294 | #define HBLANK(pipe) _PIPE(pipe, _HBLANK_A, _HBLANK_B) |
1291 | #define HSYNC(pipe) _PIPE(pipe, HSYNC_A, HSYNC_B) | 1295 | #define HSYNC(pipe) _PIPE(pipe, _HSYNC_A, _HSYNC_B) |
1292 | #define VTOTAL(pipe) _PIPE(pipe, VTOTAL_A, VTOTAL_B) | 1296 | #define VTOTAL(pipe) _PIPE(pipe, _VTOTAL_A, _VTOTAL_B) |
1293 | #define VBLANK(pipe) _PIPE(pipe, VBLANK_A, VBLANK_B) | 1297 | #define VBLANK(pipe) _PIPE(pipe, _VBLANK_A, _VBLANK_B) |
1294 | #define VSYNC(pipe) _PIPE(pipe, VSYNC_A, VSYNC_B) | 1298 | #define VSYNC(pipe) _PIPE(pipe, _VSYNC_A, _VSYNC_B) |
1295 | #define BCLRPAT(pipe) _PIPE(pipe, BCLRPAT_A, BCLRPAT_B) | 1299 | #define BCLRPAT(pipe) _PIPE(pipe, _BCLRPAT_A, _BCLRPAT_B) |
1296 | 1300 | ||
1297 | /* VGA port control */ | 1301 | /* VGA port control */ |
1298 | #define ADPA 0x61100 | 1302 | #define ADPA 0x61100 |
@@ -1386,6 +1390,7 @@ | |||
1386 | #define SDVO_ENCODING_HDMI (0x2 << 10) | 1390 | #define SDVO_ENCODING_HDMI (0x2 << 10) |
1387 | /** Requird for HDMI operation */ | 1391 | /** Requird for HDMI operation */ |
1388 | #define SDVO_NULL_PACKETS_DURING_VSYNC (1 << 9) | 1392 | #define SDVO_NULL_PACKETS_DURING_VSYNC (1 << 9) |
1393 | #define SDVO_COLOR_RANGE_16_235 (1 << 8) | ||
1389 | #define SDVO_BORDER_ENABLE (1 << 7) | 1394 | #define SDVO_BORDER_ENABLE (1 << 7) |
1390 | #define SDVO_AUDIO_ENABLE (1 << 6) | 1395 | #define SDVO_AUDIO_ENABLE (1 << 6) |
1391 | /** New with 965, default is to be set */ | 1396 | /** New with 965, default is to be set */ |
@@ -1441,8 +1446,13 @@ | |||
1441 | #define LVDS_PORT_EN (1 << 31) | 1446 | #define LVDS_PORT_EN (1 << 31) |
1442 | /* Selects pipe B for LVDS data. Must be set on pre-965. */ | 1447 | /* Selects pipe B for LVDS data. Must be set on pre-965. */ |
1443 | #define LVDS_PIPEB_SELECT (1 << 30) | 1448 | #define LVDS_PIPEB_SELECT (1 << 30) |
1449 | #define LVDS_PIPE_MASK (1 << 30) | ||
1444 | /* LVDS dithering flag on 965/g4x platform */ | 1450 | /* LVDS dithering flag on 965/g4x platform */ |
1445 | #define LVDS_ENABLE_DITHER (1 << 25) | 1451 | #define LVDS_ENABLE_DITHER (1 << 25) |
1452 | /* LVDS sync polarity flags. Set to invert (i.e. negative) */ | ||
1453 | #define LVDS_VSYNC_POLARITY (1 << 21) | ||
1454 | #define LVDS_HSYNC_POLARITY (1 << 20) | ||
1455 | |||
1446 | /* Enable border for unscaled (or aspect-scaled) display */ | 1456 | /* Enable border for unscaled (or aspect-scaled) display */ |
1447 | #define LVDS_BORDER_ENABLE (1 << 15) | 1457 | #define LVDS_BORDER_ENABLE (1 << 15) |
1448 | /* | 1458 | /* |
@@ -1476,6 +1486,9 @@ | |||
1476 | #define LVDS_B0B3_POWER_DOWN (0 << 2) | 1486 | #define LVDS_B0B3_POWER_DOWN (0 << 2) |
1477 | #define LVDS_B0B3_POWER_UP (3 << 2) | 1487 | #define LVDS_B0B3_POWER_UP (3 << 2) |
1478 | 1488 | ||
1489 | #define LVDS_PIPE_ENABLED(V, P) \ | ||
1490 | (((V) & (LVDS_PIPE_MASK | LVDS_PORT_EN)) == ((P) << 30 | LVDS_PORT_EN)) | ||
1491 | |||
1479 | /* Video Data Island Packet control */ | 1492 | /* Video Data Island Packet control */ |
1480 | #define VIDEO_DIP_DATA 0x61178 | 1493 | #define VIDEO_DIP_DATA 0x61178 |
1481 | #define VIDEO_DIP_CTL 0x61170 | 1494 | #define VIDEO_DIP_CTL 0x61170 |
@@ -2064,6 +2077,10 @@ | |||
2064 | 2077 | ||
2065 | #define DP_PORT_EN (1 << 31) | 2078 | #define DP_PORT_EN (1 << 31) |
2066 | #define DP_PIPEB_SELECT (1 << 30) | 2079 | #define DP_PIPEB_SELECT (1 << 30) |
2080 | #define DP_PIPE_MASK (1 << 30) | ||
2081 | |||
2082 | #define DP_PIPE_ENABLED(V, P) \ | ||
2083 | (((V) & (DP_PIPE_MASK | DP_PORT_EN)) == ((P) << 30 | DP_PORT_EN)) | ||
2067 | 2084 | ||
2068 | /* Link training mode - select a suitable mode for each stage */ | 2085 | /* Link training mode - select a suitable mode for each stage */ |
2069 | #define DP_LINK_TRAIN_PAT_1 (0 << 28) | 2086 | #define DP_LINK_TRAIN_PAT_1 (0 << 28) |
@@ -2206,8 +2223,8 @@ | |||
2206 | * which is after the LUTs, so we want the bytes for our color format. | 2223 | * which is after the LUTs, so we want the bytes for our color format. |
2207 | * For our current usage, this is always 3, one byte for R, G and B. | 2224 | * For our current usage, this is always 3, one byte for R, G and B. |
2208 | */ | 2225 | */ |
2209 | #define PIPEA_GMCH_DATA_M 0x70050 | 2226 | #define _PIPEA_GMCH_DATA_M 0x70050 |
2210 | #define PIPEB_GMCH_DATA_M 0x71050 | 2227 | #define _PIPEB_GMCH_DATA_M 0x71050 |
2211 | 2228 | ||
2212 | /* Transfer unit size for display port - 1, default is 0x3f (for TU size 64) */ | 2229 | /* Transfer unit size for display port - 1, default is 0x3f (for TU size 64) */ |
2213 | #define PIPE_GMCH_DATA_M_TU_SIZE_MASK (0x3f << 25) | 2230 | #define PIPE_GMCH_DATA_M_TU_SIZE_MASK (0x3f << 25) |
@@ -2215,8 +2232,8 @@ | |||
2215 | 2232 | ||
2216 | #define PIPE_GMCH_DATA_M_MASK (0xffffff) | 2233 | #define PIPE_GMCH_DATA_M_MASK (0xffffff) |
2217 | 2234 | ||
2218 | #define PIPEA_GMCH_DATA_N 0x70054 | 2235 | #define _PIPEA_GMCH_DATA_N 0x70054 |
2219 | #define PIPEB_GMCH_DATA_N 0x71054 | 2236 | #define _PIPEB_GMCH_DATA_N 0x71054 |
2220 | #define PIPE_GMCH_DATA_N_MASK (0xffffff) | 2237 | #define PIPE_GMCH_DATA_N_MASK (0xffffff) |
2221 | 2238 | ||
2222 | /* | 2239 | /* |
@@ -2230,20 +2247,25 @@ | |||
2230 | * Attributes and VB-ID. | 2247 | * Attributes and VB-ID. |
2231 | */ | 2248 | */ |
2232 | 2249 | ||
2233 | #define PIPEA_DP_LINK_M 0x70060 | 2250 | #define _PIPEA_DP_LINK_M 0x70060 |
2234 | #define PIPEB_DP_LINK_M 0x71060 | 2251 | #define _PIPEB_DP_LINK_M 0x71060 |
2235 | #define PIPEA_DP_LINK_M_MASK (0xffffff) | 2252 | #define PIPEA_DP_LINK_M_MASK (0xffffff) |
2236 | 2253 | ||
2237 | #define PIPEA_DP_LINK_N 0x70064 | 2254 | #define _PIPEA_DP_LINK_N 0x70064 |
2238 | #define PIPEB_DP_LINK_N 0x71064 | 2255 | #define _PIPEB_DP_LINK_N 0x71064 |
2239 | #define PIPEA_DP_LINK_N_MASK (0xffffff) | 2256 | #define PIPEA_DP_LINK_N_MASK (0xffffff) |
2240 | 2257 | ||
2258 | #define PIPE_GMCH_DATA_M(pipe) _PIPE(pipe, _PIPEA_GMCH_DATA_M, _PIPEB_GMCH_DATA_M) | ||
2259 | #define PIPE_GMCH_DATA_N(pipe) _PIPE(pipe, _PIPEA_GMCH_DATA_N, _PIPEB_GMCH_DATA_N) | ||
2260 | #define PIPE_DP_LINK_M(pipe) _PIPE(pipe, _PIPEA_DP_LINK_M, _PIPEB_DP_LINK_M) | ||
2261 | #define PIPE_DP_LINK_N(pipe) _PIPE(pipe, _PIPEA_DP_LINK_N, _PIPEB_DP_LINK_N) | ||
2262 | |||
2241 | /* Display & cursor control */ | 2263 | /* Display & cursor control */ |
2242 | 2264 | ||
2243 | /* Pipe A */ | 2265 | /* Pipe A */ |
2244 | #define PIPEADSL 0x70000 | 2266 | #define _PIPEADSL 0x70000 |
2245 | #define DSL_LINEMASK 0x00000fff | 2267 | #define DSL_LINEMASK 0x00000fff |
2246 | #define PIPEACONF 0x70008 | 2268 | #define _PIPEACONF 0x70008 |
2247 | #define PIPECONF_ENABLE (1<<31) | 2269 | #define PIPECONF_ENABLE (1<<31) |
2248 | #define PIPECONF_DISABLE 0 | 2270 | #define PIPECONF_DISABLE 0 |
2249 | #define PIPECONF_DOUBLE_WIDE (1<<30) | 2271 | #define PIPECONF_DOUBLE_WIDE (1<<30) |
@@ -2269,7 +2291,7 @@ | |||
2269 | #define PIPECONF_DITHER_TYPE_ST1 (1<<2) | 2291 | #define PIPECONF_DITHER_TYPE_ST1 (1<<2) |
2270 | #define PIPECONF_DITHER_TYPE_ST2 (2<<2) | 2292 | #define PIPECONF_DITHER_TYPE_ST2 (2<<2) |
2271 | #define PIPECONF_DITHER_TYPE_TEMP (3<<2) | 2293 | #define PIPECONF_DITHER_TYPE_TEMP (3<<2) |
2272 | #define PIPEASTAT 0x70024 | 2294 | #define _PIPEASTAT 0x70024 |
2273 | #define PIPE_FIFO_UNDERRUN_STATUS (1UL<<31) | 2295 | #define PIPE_FIFO_UNDERRUN_STATUS (1UL<<31) |
2274 | #define PIPE_CRC_ERROR_ENABLE (1UL<<29) | 2296 | #define PIPE_CRC_ERROR_ENABLE (1UL<<29) |
2275 | #define PIPE_CRC_DONE_ENABLE (1UL<<28) | 2297 | #define PIPE_CRC_DONE_ENABLE (1UL<<28) |
@@ -2305,10 +2327,12 @@ | |||
2305 | #define PIPE_6BPC (2 << 5) | 2327 | #define PIPE_6BPC (2 << 5) |
2306 | #define PIPE_12BPC (3 << 5) | 2328 | #define PIPE_12BPC (3 << 5) |
2307 | 2329 | ||
2308 | #define PIPESRC(pipe) _PIPE(pipe, PIPEASRC, PIPEBSRC) | 2330 | #define PIPESRC(pipe) _PIPE(pipe, _PIPEASRC, _PIPEBSRC) |
2309 | #define PIPECONF(pipe) _PIPE(pipe, PIPEACONF, PIPEBCONF) | 2331 | #define PIPECONF(pipe) _PIPE(pipe, _PIPEACONF, _PIPEBCONF) |
2310 | #define PIPEDSL(pipe) _PIPE(pipe, PIPEADSL, PIPEBDSL) | 2332 | #define PIPEDSL(pipe) _PIPE(pipe, _PIPEADSL, _PIPEBDSL) |
2311 | #define PIPEFRAMEPIXEL(pipe) _PIPE(pipe, PIPEAFRAMEPIXEL, PIPEBFRAMEPIXEL) | 2333 | #define PIPEFRAME(pipe) _PIPE(pipe, _PIPEAFRAMEHIGH, _PIPEBFRAMEHIGH) |
2334 | #define PIPEFRAMEPIXEL(pipe) _PIPE(pipe, _PIPEAFRAMEPIXEL, _PIPEBFRAMEPIXEL) | ||
2335 | #define PIPESTAT(pipe) _PIPE(pipe, _PIPEASTAT, _PIPEBSTAT) | ||
2312 | 2336 | ||
2313 | #define DSPARB 0x70030 | 2337 | #define DSPARB 0x70030 |
2314 | #define DSPARB_CSTART_MASK (0x7f << 7) | 2338 | #define DSPARB_CSTART_MASK (0x7f << 7) |
@@ -2470,20 +2494,21 @@ | |||
2470 | * } while (high1 != high2); | 2494 | * } while (high1 != high2); |
2471 | * frame = (high1 << 8) | low1; | 2495 | * frame = (high1 << 8) | low1; |
2472 | */ | 2496 | */ |
2473 | #define PIPEAFRAMEHIGH 0x70040 | 2497 | #define _PIPEAFRAMEHIGH 0x70040 |
2474 | #define PIPE_FRAME_HIGH_MASK 0x0000ffff | 2498 | #define PIPE_FRAME_HIGH_MASK 0x0000ffff |
2475 | #define PIPE_FRAME_HIGH_SHIFT 0 | 2499 | #define PIPE_FRAME_HIGH_SHIFT 0 |
2476 | #define PIPEAFRAMEPIXEL 0x70044 | 2500 | #define _PIPEAFRAMEPIXEL 0x70044 |
2477 | #define PIPE_FRAME_LOW_MASK 0xff000000 | 2501 | #define PIPE_FRAME_LOW_MASK 0xff000000 |
2478 | #define PIPE_FRAME_LOW_SHIFT 24 | 2502 | #define PIPE_FRAME_LOW_SHIFT 24 |
2479 | #define PIPE_PIXEL_MASK 0x00ffffff | 2503 | #define PIPE_PIXEL_MASK 0x00ffffff |
2480 | #define PIPE_PIXEL_SHIFT 0 | 2504 | #define PIPE_PIXEL_SHIFT 0 |
2481 | /* GM45+ just has to be different */ | 2505 | /* GM45+ just has to be different */ |
2482 | #define PIPEA_FRMCOUNT_GM45 0x70040 | 2506 | #define _PIPEA_FRMCOUNT_GM45 0x70040 |
2483 | #define PIPEA_FLIPCOUNT_GM45 0x70044 | 2507 | #define _PIPEA_FLIPCOUNT_GM45 0x70044 |
2508 | #define PIPE_FRMCOUNT_GM45(pipe) _PIPE(pipe, _PIPEA_FRMCOUNT_GM45, _PIPEB_FRMCOUNT_GM45) | ||
2484 | 2509 | ||
2485 | /* Cursor A & B regs */ | 2510 | /* Cursor A & B regs */ |
2486 | #define CURACNTR 0x70080 | 2511 | #define _CURACNTR 0x70080 |
2487 | /* Old style CUR*CNTR flags (desktop 8xx) */ | 2512 | /* Old style CUR*CNTR flags (desktop 8xx) */ |
2488 | #define CURSOR_ENABLE 0x80000000 | 2513 | #define CURSOR_ENABLE 0x80000000 |
2489 | #define CURSOR_GAMMA_ENABLE 0x40000000 | 2514 | #define CURSOR_GAMMA_ENABLE 0x40000000 |
@@ -2504,23 +2529,23 @@ | |||
2504 | #define MCURSOR_PIPE_A 0x00 | 2529 | #define MCURSOR_PIPE_A 0x00 |
2505 | #define MCURSOR_PIPE_B (1 << 28) | 2530 | #define MCURSOR_PIPE_B (1 << 28) |
2506 | #define MCURSOR_GAMMA_ENABLE (1 << 26) | 2531 | #define MCURSOR_GAMMA_ENABLE (1 << 26) |
2507 | #define CURABASE 0x70084 | 2532 | #define _CURABASE 0x70084 |
2508 | #define CURAPOS 0x70088 | 2533 | #define _CURAPOS 0x70088 |
2509 | #define CURSOR_POS_MASK 0x007FF | 2534 | #define CURSOR_POS_MASK 0x007FF |
2510 | #define CURSOR_POS_SIGN 0x8000 | 2535 | #define CURSOR_POS_SIGN 0x8000 |
2511 | #define CURSOR_X_SHIFT 0 | 2536 | #define CURSOR_X_SHIFT 0 |
2512 | #define CURSOR_Y_SHIFT 16 | 2537 | #define CURSOR_Y_SHIFT 16 |
2513 | #define CURSIZE 0x700a0 | 2538 | #define CURSIZE 0x700a0 |
2514 | #define CURBCNTR 0x700c0 | 2539 | #define _CURBCNTR 0x700c0 |
2515 | #define CURBBASE 0x700c4 | 2540 | #define _CURBBASE 0x700c4 |
2516 | #define CURBPOS 0x700c8 | 2541 | #define _CURBPOS 0x700c8 |
2517 | 2542 | ||
2518 | #define CURCNTR(pipe) _PIPE(pipe, CURACNTR, CURBCNTR) | 2543 | #define CURCNTR(pipe) _PIPE(pipe, _CURACNTR, _CURBCNTR) |
2519 | #define CURBASE(pipe) _PIPE(pipe, CURABASE, CURBBASE) | 2544 | #define CURBASE(pipe) _PIPE(pipe, _CURABASE, _CURBBASE) |
2520 | #define CURPOS(pipe) _PIPE(pipe, CURAPOS, CURBPOS) | 2545 | #define CURPOS(pipe) _PIPE(pipe, _CURAPOS, _CURBPOS) |
2521 | 2546 | ||
2522 | /* Display A control */ | 2547 | /* Display A control */ |
2523 | #define DSPACNTR 0x70180 | 2548 | #define _DSPACNTR 0x70180 |
2524 | #define DISPLAY_PLANE_ENABLE (1<<31) | 2549 | #define DISPLAY_PLANE_ENABLE (1<<31) |
2525 | #define DISPLAY_PLANE_DISABLE 0 | 2550 | #define DISPLAY_PLANE_DISABLE 0 |
2526 | #define DISPPLANE_GAMMA_ENABLE (1<<30) | 2551 | #define DISPPLANE_GAMMA_ENABLE (1<<30) |
@@ -2534,9 +2559,10 @@ | |||
2534 | #define DISPPLANE_32BPP_30BIT_NO_ALPHA (0xa<<26) | 2559 | #define DISPPLANE_32BPP_30BIT_NO_ALPHA (0xa<<26) |
2535 | #define DISPPLANE_STEREO_ENABLE (1<<25) | 2560 | #define DISPPLANE_STEREO_ENABLE (1<<25) |
2536 | #define DISPPLANE_STEREO_DISABLE 0 | 2561 | #define DISPPLANE_STEREO_DISABLE 0 |
2537 | #define DISPPLANE_SEL_PIPE_MASK (1<<24) | 2562 | #define DISPPLANE_SEL_PIPE_SHIFT 24 |
2563 | #define DISPPLANE_SEL_PIPE_MASK (3<<DISPPLANE_SEL_PIPE_SHIFT) | ||
2538 | #define DISPPLANE_SEL_PIPE_A 0 | 2564 | #define DISPPLANE_SEL_PIPE_A 0 |
2539 | #define DISPPLANE_SEL_PIPE_B (1<<24) | 2565 | #define DISPPLANE_SEL_PIPE_B (1<<DISPPLANE_SEL_PIPE_SHIFT) |
2540 | #define DISPPLANE_SRC_KEY_ENABLE (1<<22) | 2566 | #define DISPPLANE_SRC_KEY_ENABLE (1<<22) |
2541 | #define DISPPLANE_SRC_KEY_DISABLE 0 | 2567 | #define DISPPLANE_SRC_KEY_DISABLE 0 |
2542 | #define DISPPLANE_LINE_DOUBLE (1<<20) | 2568 | #define DISPPLANE_LINE_DOUBLE (1<<20) |
@@ -2545,20 +2571,20 @@ | |||
2545 | #define DISPPLANE_STEREO_POLARITY_SECOND (1<<18) | 2571 | #define DISPPLANE_STEREO_POLARITY_SECOND (1<<18) |
2546 | #define DISPPLANE_TRICKLE_FEED_DISABLE (1<<14) /* Ironlake */ | 2572 | #define DISPPLANE_TRICKLE_FEED_DISABLE (1<<14) /* Ironlake */ |
2547 | #define DISPPLANE_TILED (1<<10) | 2573 | #define DISPPLANE_TILED (1<<10) |
2548 | #define DSPAADDR 0x70184 | 2574 | #define _DSPAADDR 0x70184 |
2549 | #define DSPASTRIDE 0x70188 | 2575 | #define _DSPASTRIDE 0x70188 |
2550 | #define DSPAPOS 0x7018C /* reserved */ | 2576 | #define _DSPAPOS 0x7018C /* reserved */ |
2551 | #define DSPASIZE 0x70190 | 2577 | #define _DSPASIZE 0x70190 |
2552 | #define DSPASURF 0x7019C /* 965+ only */ | 2578 | #define _DSPASURF 0x7019C /* 965+ only */ |
2553 | #define DSPATILEOFF 0x701A4 /* 965+ only */ | 2579 | #define _DSPATILEOFF 0x701A4 /* 965+ only */ |
2554 | 2580 | ||
2555 | #define DSPCNTR(plane) _PIPE(plane, DSPACNTR, DSPBCNTR) | 2581 | #define DSPCNTR(plane) _PIPE(plane, _DSPACNTR, _DSPBCNTR) |
2556 | #define DSPADDR(plane) _PIPE(plane, DSPAADDR, DSPBADDR) | 2582 | #define DSPADDR(plane) _PIPE(plane, _DSPAADDR, _DSPBADDR) |
2557 | #define DSPSTRIDE(plane) _PIPE(plane, DSPASTRIDE, DSPBSTRIDE) | 2583 | #define DSPSTRIDE(plane) _PIPE(plane, _DSPASTRIDE, _DSPBSTRIDE) |
2558 | #define DSPPOS(plane) _PIPE(plane, DSPAPOS, DSPBPOS) | 2584 | #define DSPPOS(plane) _PIPE(plane, _DSPAPOS, _DSPBPOS) |
2559 | #define DSPSIZE(plane) _PIPE(plane, DSPASIZE, DSPBSIZE) | 2585 | #define DSPSIZE(plane) _PIPE(plane, _DSPASIZE, _DSPBSIZE) |
2560 | #define DSPSURF(plane) _PIPE(plane, DSPASURF, DSPBSURF) | 2586 | #define DSPSURF(plane) _PIPE(plane, _DSPASURF, _DSPBSURF) |
2561 | #define DSPTILEOFF(plane) _PIPE(plane, DSPATILEOFF, DSPBTILEOFF) | 2587 | #define DSPTILEOFF(plane) _PIPE(plane, _DSPATILEOFF, _DSPBTILEOFF) |
2562 | 2588 | ||
2563 | /* VBIOS flags */ | 2589 | /* VBIOS flags */ |
2564 | #define SWF00 0x71410 | 2590 | #define SWF00 0x71410 |
@@ -2576,27 +2602,27 @@ | |||
2576 | #define SWF32 0x7241c | 2602 | #define SWF32 0x7241c |
2577 | 2603 | ||
2578 | /* Pipe B */ | 2604 | /* Pipe B */ |
2579 | #define PIPEBDSL 0x71000 | 2605 | #define _PIPEBDSL 0x71000 |
2580 | #define PIPEBCONF 0x71008 | 2606 | #define _PIPEBCONF 0x71008 |
2581 | #define PIPEBSTAT 0x71024 | 2607 | #define _PIPEBSTAT 0x71024 |
2582 | #define PIPEBFRAMEHIGH 0x71040 | 2608 | #define _PIPEBFRAMEHIGH 0x71040 |
2583 | #define PIPEBFRAMEPIXEL 0x71044 | 2609 | #define _PIPEBFRAMEPIXEL 0x71044 |
2584 | #define PIPEB_FRMCOUNT_GM45 0x71040 | 2610 | #define _PIPEB_FRMCOUNT_GM45 0x71040 |
2585 | #define PIPEB_FLIPCOUNT_GM45 0x71044 | 2611 | #define _PIPEB_FLIPCOUNT_GM45 0x71044 |
2586 | 2612 | ||
2587 | 2613 | ||
2588 | /* Display B control */ | 2614 | /* Display B control */ |
2589 | #define DSPBCNTR 0x71180 | 2615 | #define _DSPBCNTR 0x71180 |
2590 | #define DISPPLANE_ALPHA_TRANS_ENABLE (1<<15) | 2616 | #define DISPPLANE_ALPHA_TRANS_ENABLE (1<<15) |
2591 | #define DISPPLANE_ALPHA_TRANS_DISABLE 0 | 2617 | #define DISPPLANE_ALPHA_TRANS_DISABLE 0 |
2592 | #define DISPPLANE_SPRITE_ABOVE_DISPLAY 0 | 2618 | #define DISPPLANE_SPRITE_ABOVE_DISPLAY 0 |
2593 | #define DISPPLANE_SPRITE_ABOVE_OVERLAY (1) | 2619 | #define DISPPLANE_SPRITE_ABOVE_OVERLAY (1) |
2594 | #define DSPBADDR 0x71184 | 2620 | #define _DSPBADDR 0x71184 |
2595 | #define DSPBSTRIDE 0x71188 | 2621 | #define _DSPBSTRIDE 0x71188 |
2596 | #define DSPBPOS 0x7118C | 2622 | #define _DSPBPOS 0x7118C |
2597 | #define DSPBSIZE 0x71190 | 2623 | #define _DSPBSIZE 0x71190 |
2598 | #define DSPBSURF 0x7119C | 2624 | #define _DSPBSURF 0x7119C |
2599 | #define DSPBTILEOFF 0x711A4 | 2625 | #define _DSPBTILEOFF 0x711A4 |
2600 | 2626 | ||
2601 | /* VBIOS regs */ | 2627 | /* VBIOS regs */ |
2602 | #define VGACNTRL 0x71400 | 2628 | #define VGACNTRL 0x71400 |
@@ -2650,68 +2676,80 @@ | |||
2650 | #define FDI_PLL_FREQ_DISABLE_COUNT_LIMIT_MASK 0xff | 2676 | #define FDI_PLL_FREQ_DISABLE_COUNT_LIMIT_MASK 0xff |
2651 | 2677 | ||
2652 | 2678 | ||
2653 | #define PIPEA_DATA_M1 0x60030 | 2679 | #define _PIPEA_DATA_M1 0x60030 |
2654 | #define TU_SIZE(x) (((x)-1) << 25) /* default size 64 */ | 2680 | #define TU_SIZE(x) (((x)-1) << 25) /* default size 64 */ |
2655 | #define TU_SIZE_MASK 0x7e000000 | 2681 | #define TU_SIZE_MASK 0x7e000000 |
2656 | #define PIPE_DATA_M1_OFFSET 0 | 2682 | #define PIPE_DATA_M1_OFFSET 0 |
2657 | #define PIPEA_DATA_N1 0x60034 | 2683 | #define _PIPEA_DATA_N1 0x60034 |
2658 | #define PIPE_DATA_N1_OFFSET 0 | 2684 | #define PIPE_DATA_N1_OFFSET 0 |
2659 | 2685 | ||
2660 | #define PIPEA_DATA_M2 0x60038 | 2686 | #define _PIPEA_DATA_M2 0x60038 |
2661 | #define PIPE_DATA_M2_OFFSET 0 | 2687 | #define PIPE_DATA_M2_OFFSET 0 |
2662 | #define PIPEA_DATA_N2 0x6003c | 2688 | #define _PIPEA_DATA_N2 0x6003c |
2663 | #define PIPE_DATA_N2_OFFSET 0 | 2689 | #define PIPE_DATA_N2_OFFSET 0 |
2664 | 2690 | ||
2665 | #define PIPEA_LINK_M1 0x60040 | 2691 | #define _PIPEA_LINK_M1 0x60040 |
2666 | #define PIPE_LINK_M1_OFFSET 0 | 2692 | #define PIPE_LINK_M1_OFFSET 0 |
2667 | #define PIPEA_LINK_N1 0x60044 | 2693 | #define _PIPEA_LINK_N1 0x60044 |
2668 | #define PIPE_LINK_N1_OFFSET 0 | 2694 | #define PIPE_LINK_N1_OFFSET 0 |
2669 | 2695 | ||
2670 | #define PIPEA_LINK_M2 0x60048 | 2696 | #define _PIPEA_LINK_M2 0x60048 |
2671 | #define PIPE_LINK_M2_OFFSET 0 | 2697 | #define PIPE_LINK_M2_OFFSET 0 |
2672 | #define PIPEA_LINK_N2 0x6004c | 2698 | #define _PIPEA_LINK_N2 0x6004c |
2673 | #define PIPE_LINK_N2_OFFSET 0 | 2699 | #define PIPE_LINK_N2_OFFSET 0 |
2674 | 2700 | ||
2675 | /* PIPEB timing regs are same start from 0x61000 */ | 2701 | /* PIPEB timing regs are same start from 0x61000 */ |
2676 | 2702 | ||
2677 | #define PIPEB_DATA_M1 0x61030 | 2703 | #define _PIPEB_DATA_M1 0x61030 |
2678 | #define PIPEB_DATA_N1 0x61034 | 2704 | #define _PIPEB_DATA_N1 0x61034 |
2679 | 2705 | ||
2680 | #define PIPEB_DATA_M2 0x61038 | 2706 | #define _PIPEB_DATA_M2 0x61038 |
2681 | #define PIPEB_DATA_N2 0x6103c | 2707 | #define _PIPEB_DATA_N2 0x6103c |
2682 | 2708 | ||
2683 | #define PIPEB_LINK_M1 0x61040 | 2709 | #define _PIPEB_LINK_M1 0x61040 |
2684 | #define PIPEB_LINK_N1 0x61044 | 2710 | #define _PIPEB_LINK_N1 0x61044 |
2685 | 2711 | ||
2686 | #define PIPEB_LINK_M2 0x61048 | 2712 | #define _PIPEB_LINK_M2 0x61048 |
2687 | #define PIPEB_LINK_N2 0x6104c | 2713 | #define _PIPEB_LINK_N2 0x6104c |
2688 | 2714 | ||
2689 | #define PIPE_DATA_M1(pipe) _PIPE(pipe, PIPEA_DATA_M1, PIPEB_DATA_M1) | 2715 | #define PIPE_DATA_M1(pipe) _PIPE(pipe, _PIPEA_DATA_M1, _PIPEB_DATA_M1) |
2690 | #define PIPE_DATA_N1(pipe) _PIPE(pipe, PIPEA_DATA_N1, PIPEB_DATA_N1) | 2716 | #define PIPE_DATA_N1(pipe) _PIPE(pipe, _PIPEA_DATA_N1, _PIPEB_DATA_N1) |
2691 | #define PIPE_DATA_M2(pipe) _PIPE(pipe, PIPEA_DATA_M2, PIPEB_DATA_M2) | 2717 | #define PIPE_DATA_M2(pipe) _PIPE(pipe, _PIPEA_DATA_M2, _PIPEB_DATA_M2) |
2692 | #define PIPE_DATA_N2(pipe) _PIPE(pipe, PIPEA_DATA_N2, PIPEB_DATA_N2) | 2718 | #define PIPE_DATA_N2(pipe) _PIPE(pipe, _PIPEA_DATA_N2, _PIPEB_DATA_N2) |
2693 | #define PIPE_LINK_M1(pipe) _PIPE(pipe, PIPEA_LINK_M1, PIPEB_LINK_M1) | 2719 | #define PIPE_LINK_M1(pipe) _PIPE(pipe, _PIPEA_LINK_M1, _PIPEB_LINK_M1) |
2694 | #define PIPE_LINK_N1(pipe) _PIPE(pipe, PIPEA_LINK_N1, PIPEB_LINK_N1) | 2720 | #define PIPE_LINK_N1(pipe) _PIPE(pipe, _PIPEA_LINK_N1, _PIPEB_LINK_N1) |
2695 | #define PIPE_LINK_M2(pipe) _PIPE(pipe, PIPEA_LINK_M2, PIPEB_LINK_M2) | 2721 | #define PIPE_LINK_M2(pipe) _PIPE(pipe, _PIPEA_LINK_M2, _PIPEB_LINK_M2) |
2696 | #define PIPE_LINK_N2(pipe) _PIPE(pipe, PIPEA_LINK_N2, PIPEB_LINK_N2) | 2722 | #define PIPE_LINK_N2(pipe) _PIPE(pipe, _PIPEA_LINK_N2, _PIPEB_LINK_N2) |
2697 | 2723 | ||
2698 | /* CPU panel fitter */ | 2724 | /* CPU panel fitter */ |
2699 | #define PFA_CTL_1 0x68080 | 2725 | /* IVB+ has 3 fitters, 0 is 7x5 capable, the other two only 3x3 */ |
2700 | #define PFB_CTL_1 0x68880 | 2726 | #define _PFA_CTL_1 0x68080 |
2727 | #define _PFB_CTL_1 0x68880 | ||
2701 | #define PF_ENABLE (1<<31) | 2728 | #define PF_ENABLE (1<<31) |
2702 | #define PF_FILTER_MASK (3<<23) | 2729 | #define PF_FILTER_MASK (3<<23) |
2703 | #define PF_FILTER_PROGRAMMED (0<<23) | 2730 | #define PF_FILTER_PROGRAMMED (0<<23) |
2704 | #define PF_FILTER_MED_3x3 (1<<23) | 2731 | #define PF_FILTER_MED_3x3 (1<<23) |
2705 | #define PF_FILTER_EDGE_ENHANCE (2<<23) | 2732 | #define PF_FILTER_EDGE_ENHANCE (2<<23) |
2706 | #define PF_FILTER_EDGE_SOFTEN (3<<23) | 2733 | #define PF_FILTER_EDGE_SOFTEN (3<<23) |
2707 | #define PFA_WIN_SZ 0x68074 | 2734 | #define _PFA_WIN_SZ 0x68074 |
2708 | #define PFB_WIN_SZ 0x68874 | 2735 | #define _PFB_WIN_SZ 0x68874 |
2709 | #define PFA_WIN_POS 0x68070 | 2736 | #define _PFA_WIN_POS 0x68070 |
2710 | #define PFB_WIN_POS 0x68870 | 2737 | #define _PFB_WIN_POS 0x68870 |
2738 | #define _PFA_VSCALE 0x68084 | ||
2739 | #define _PFB_VSCALE 0x68884 | ||
2740 | #define _PFA_HSCALE 0x68090 | ||
2741 | #define _PFB_HSCALE 0x68890 | ||
2742 | |||
2743 | #define PF_CTL(pipe) _PIPE(pipe, _PFA_CTL_1, _PFB_CTL_1) | ||
2744 | #define PF_WIN_SZ(pipe) _PIPE(pipe, _PFA_WIN_SZ, _PFB_WIN_SZ) | ||
2745 | #define PF_WIN_POS(pipe) _PIPE(pipe, _PFA_WIN_POS, _PFB_WIN_POS) | ||
2746 | #define PF_VSCALE(pipe) _PIPE(pipe, _PFA_VSCALE, _PFB_VSCALE) | ||
2747 | #define PF_HSCALE(pipe) _PIPE(pipe, _PFA_HSCALE, _PFB_HSCALE) | ||
2711 | 2748 | ||
2712 | /* legacy palette */ | 2749 | /* legacy palette */ |
2713 | #define LGC_PALETTE_A 0x4a000 | 2750 | #define _LGC_PALETTE_A 0x4a000 |
2714 | #define LGC_PALETTE_B 0x4a800 | 2751 | #define _LGC_PALETTE_B 0x4a800 |
2752 | #define LGC_PALETTE(pipe) _PIPE(pipe, _LGC_PALETTE_A, _LGC_PALETTE_B) | ||
2715 | 2753 | ||
2716 | /* interrupts */ | 2754 | /* interrupts */ |
2717 | #define DE_MASTER_IRQ_CONTROL (1 << 31) | 2755 | #define DE_MASTER_IRQ_CONTROL (1 << 31) |
@@ -2877,17 +2915,17 @@ | |||
2877 | #define PCH_GMBUS4 0xc5110 | 2915 | #define PCH_GMBUS4 0xc5110 |
2878 | #define PCH_GMBUS5 0xc5120 | 2916 | #define PCH_GMBUS5 0xc5120 |
2879 | 2917 | ||
2880 | #define PCH_DPLL_A 0xc6014 | 2918 | #define _PCH_DPLL_A 0xc6014 |
2881 | #define PCH_DPLL_B 0xc6018 | 2919 | #define _PCH_DPLL_B 0xc6018 |
2882 | #define PCH_DPLL(pipe) _PIPE(pipe, PCH_DPLL_A, PCH_DPLL_B) | 2920 | #define PCH_DPLL(pipe) _PIPE(pipe, _PCH_DPLL_A, _PCH_DPLL_B) |
2883 | 2921 | ||
2884 | #define PCH_FPA0 0xc6040 | 2922 | #define _PCH_FPA0 0xc6040 |
2885 | #define FP_CB_TUNE (0x3<<22) | 2923 | #define FP_CB_TUNE (0x3<<22) |
2886 | #define PCH_FPA1 0xc6044 | 2924 | #define _PCH_FPA1 0xc6044 |
2887 | #define PCH_FPB0 0xc6048 | 2925 | #define _PCH_FPB0 0xc6048 |
2888 | #define PCH_FPB1 0xc604c | 2926 | #define _PCH_FPB1 0xc604c |
2889 | #define PCH_FP0(pipe) _PIPE(pipe, PCH_FPA0, PCH_FPB0) | 2927 | #define PCH_FP0(pipe) _PIPE(pipe, _PCH_FPA0, _PCH_FPB0) |
2890 | #define PCH_FP1(pipe) _PIPE(pipe, PCH_FPA1, PCH_FPB1) | 2928 | #define PCH_FP1(pipe) _PIPE(pipe, _PCH_FPA1, _PCH_FPB1) |
2891 | 2929 | ||
2892 | #define PCH_DPLL_TEST 0xc606c | 2930 | #define PCH_DPLL_TEST 0xc606c |
2893 | 2931 | ||
@@ -2906,6 +2944,7 @@ | |||
2906 | #define DREF_NONSPREAD_SOURCE_MASK (3<<9) | 2944 | #define DREF_NONSPREAD_SOURCE_MASK (3<<9) |
2907 | #define DREF_SUPERSPREAD_SOURCE_DISABLE (0<<7) | 2945 | #define DREF_SUPERSPREAD_SOURCE_DISABLE (0<<7) |
2908 | #define DREF_SUPERSPREAD_SOURCE_ENABLE (2<<7) | 2946 | #define DREF_SUPERSPREAD_SOURCE_ENABLE (2<<7) |
2947 | #define DREF_SUPERSPREAD_SOURCE_MASK (3<<7) | ||
2909 | #define DREF_SSC4_DOWNSPREAD (0<<6) | 2948 | #define DREF_SSC4_DOWNSPREAD (0<<6) |
2910 | #define DREF_SSC4_CENTERSPREAD (1<<6) | 2949 | #define DREF_SSC4_CENTERSPREAD (1<<6) |
2911 | #define DREF_SSC1_DISABLE (0<<1) | 2950 | #define DREF_SSC1_DISABLE (0<<1) |
@@ -2938,60 +2977,69 @@ | |||
2938 | 2977 | ||
2939 | /* transcoder */ | 2978 | /* transcoder */ |
2940 | 2979 | ||
2941 | #define TRANS_HTOTAL_A 0xe0000 | 2980 | #define _TRANS_HTOTAL_A 0xe0000 |
2942 | #define TRANS_HTOTAL_SHIFT 16 | 2981 | #define TRANS_HTOTAL_SHIFT 16 |
2943 | #define TRANS_HACTIVE_SHIFT 0 | 2982 | #define TRANS_HACTIVE_SHIFT 0 |
2944 | #define TRANS_HBLANK_A 0xe0004 | 2983 | #define _TRANS_HBLANK_A 0xe0004 |
2945 | #define TRANS_HBLANK_END_SHIFT 16 | 2984 | #define TRANS_HBLANK_END_SHIFT 16 |
2946 | #define TRANS_HBLANK_START_SHIFT 0 | 2985 | #define TRANS_HBLANK_START_SHIFT 0 |
2947 | #define TRANS_HSYNC_A 0xe0008 | 2986 | #define _TRANS_HSYNC_A 0xe0008 |
2948 | #define TRANS_HSYNC_END_SHIFT 16 | 2987 | #define TRANS_HSYNC_END_SHIFT 16 |
2949 | #define TRANS_HSYNC_START_SHIFT 0 | 2988 | #define TRANS_HSYNC_START_SHIFT 0 |
2950 | #define TRANS_VTOTAL_A 0xe000c | 2989 | #define _TRANS_VTOTAL_A 0xe000c |
2951 | #define TRANS_VTOTAL_SHIFT 16 | 2990 | #define TRANS_VTOTAL_SHIFT 16 |
2952 | #define TRANS_VACTIVE_SHIFT 0 | 2991 | #define TRANS_VACTIVE_SHIFT 0 |
2953 | #define TRANS_VBLANK_A 0xe0010 | 2992 | #define _TRANS_VBLANK_A 0xe0010 |
2954 | #define TRANS_VBLANK_END_SHIFT 16 | 2993 | #define TRANS_VBLANK_END_SHIFT 16 |
2955 | #define TRANS_VBLANK_START_SHIFT 0 | 2994 | #define TRANS_VBLANK_START_SHIFT 0 |
2956 | #define TRANS_VSYNC_A 0xe0014 | 2995 | #define _TRANS_VSYNC_A 0xe0014 |
2957 | #define TRANS_VSYNC_END_SHIFT 16 | 2996 | #define TRANS_VSYNC_END_SHIFT 16 |
2958 | #define TRANS_VSYNC_START_SHIFT 0 | 2997 | #define TRANS_VSYNC_START_SHIFT 0 |
2959 | 2998 | ||
2960 | #define TRANSA_DATA_M1 0xe0030 | 2999 | #define _TRANSA_DATA_M1 0xe0030 |
2961 | #define TRANSA_DATA_N1 0xe0034 | 3000 | #define _TRANSA_DATA_N1 0xe0034 |
2962 | #define TRANSA_DATA_M2 0xe0038 | 3001 | #define _TRANSA_DATA_M2 0xe0038 |
2963 | #define TRANSA_DATA_N2 0xe003c | 3002 | #define _TRANSA_DATA_N2 0xe003c |
2964 | #define TRANSA_DP_LINK_M1 0xe0040 | 3003 | #define _TRANSA_DP_LINK_M1 0xe0040 |
2965 | #define TRANSA_DP_LINK_N1 0xe0044 | 3004 | #define _TRANSA_DP_LINK_N1 0xe0044 |
2966 | #define TRANSA_DP_LINK_M2 0xe0048 | 3005 | #define _TRANSA_DP_LINK_M2 0xe0048 |
2967 | #define TRANSA_DP_LINK_N2 0xe004c | 3006 | #define _TRANSA_DP_LINK_N2 0xe004c |
2968 | 3007 | ||
2969 | #define TRANS_HTOTAL_B 0xe1000 | 3008 | #define _TRANS_HTOTAL_B 0xe1000 |
2970 | #define TRANS_HBLANK_B 0xe1004 | 3009 | #define _TRANS_HBLANK_B 0xe1004 |
2971 | #define TRANS_HSYNC_B 0xe1008 | 3010 | #define _TRANS_HSYNC_B 0xe1008 |
2972 | #define TRANS_VTOTAL_B 0xe100c | 3011 | #define _TRANS_VTOTAL_B 0xe100c |
2973 | #define TRANS_VBLANK_B 0xe1010 | 3012 | #define _TRANS_VBLANK_B 0xe1010 |
2974 | #define TRANS_VSYNC_B 0xe1014 | 3013 | #define _TRANS_VSYNC_B 0xe1014 |
2975 | 3014 | ||
2976 | #define TRANS_HTOTAL(pipe) _PIPE(pipe, TRANS_HTOTAL_A, TRANS_HTOTAL_B) | 3015 | #define TRANS_HTOTAL(pipe) _PIPE(pipe, _TRANS_HTOTAL_A, _TRANS_HTOTAL_B) |
2977 | #define TRANS_HBLANK(pipe) _PIPE(pipe, TRANS_HBLANK_A, TRANS_HBLANK_B) | 3016 | #define TRANS_HBLANK(pipe) _PIPE(pipe, _TRANS_HBLANK_A, _TRANS_HBLANK_B) |
2978 | #define TRANS_HSYNC(pipe) _PIPE(pipe, TRANS_HSYNC_A, TRANS_HSYNC_B) | 3017 | #define TRANS_HSYNC(pipe) _PIPE(pipe, _TRANS_HSYNC_A, _TRANS_HSYNC_B) |
2979 | #define TRANS_VTOTAL(pipe) _PIPE(pipe, TRANS_VTOTAL_A, TRANS_VTOTAL_B) | 3018 | #define TRANS_VTOTAL(pipe) _PIPE(pipe, _TRANS_VTOTAL_A, _TRANS_VTOTAL_B) |
2980 | #define TRANS_VBLANK(pipe) _PIPE(pipe, TRANS_VBLANK_A, TRANS_VBLANK_B) | 3019 | #define TRANS_VBLANK(pipe) _PIPE(pipe, _TRANS_VBLANK_A, _TRANS_VBLANK_B) |
2981 | #define TRANS_VSYNC(pipe) _PIPE(pipe, TRANS_VSYNC_A, TRANS_VSYNC_B) | 3020 | #define TRANS_VSYNC(pipe) _PIPE(pipe, _TRANS_VSYNC_A, _TRANS_VSYNC_B) |
2982 | 3021 | ||
2983 | #define TRANSB_DATA_M1 0xe1030 | 3022 | #define _TRANSB_DATA_M1 0xe1030 |
2984 | #define TRANSB_DATA_N1 0xe1034 | 3023 | #define _TRANSB_DATA_N1 0xe1034 |
2985 | #define TRANSB_DATA_M2 0xe1038 | 3024 | #define _TRANSB_DATA_M2 0xe1038 |
2986 | #define TRANSB_DATA_N2 0xe103c | 3025 | #define _TRANSB_DATA_N2 0xe103c |
2987 | #define TRANSB_DP_LINK_M1 0xe1040 | 3026 | #define _TRANSB_DP_LINK_M1 0xe1040 |
2988 | #define TRANSB_DP_LINK_N1 0xe1044 | 3027 | #define _TRANSB_DP_LINK_N1 0xe1044 |
2989 | #define TRANSB_DP_LINK_M2 0xe1048 | 3028 | #define _TRANSB_DP_LINK_M2 0xe1048 |
2990 | #define TRANSB_DP_LINK_N2 0xe104c | 3029 | #define _TRANSB_DP_LINK_N2 0xe104c |
2991 | 3030 | ||
2992 | #define TRANSACONF 0xf0008 | 3031 | #define TRANSDATA_M1(pipe) _PIPE(pipe, _TRANSA_DATA_M1, _TRANSB_DATA_M1) |
2993 | #define TRANSBCONF 0xf1008 | 3032 | #define TRANSDATA_N1(pipe) _PIPE(pipe, _TRANSA_DATA_N1, _TRANSB_DATA_N1) |
2994 | #define TRANSCONF(plane) _PIPE(plane, TRANSACONF, TRANSBCONF) | 3033 | #define TRANSDATA_M2(pipe) _PIPE(pipe, _TRANSA_DATA_M2, _TRANSB_DATA_M2) |
3034 | #define TRANSDATA_N2(pipe) _PIPE(pipe, _TRANSA_DATA_N2, _TRANSB_DATA_N2) | ||
3035 | #define TRANSDPLINK_M1(pipe) _PIPE(pipe, _TRANSA_DP_LINK_M1, _TRANSB_DP_LINK_M1) | ||
3036 | #define TRANSDPLINK_N1(pipe) _PIPE(pipe, _TRANSA_DP_LINK_N1, _TRANSB_DP_LINK_N1) | ||
3037 | #define TRANSDPLINK_M2(pipe) _PIPE(pipe, _TRANSA_DP_LINK_M2, _TRANSB_DP_LINK_M2) | ||
3038 | #define TRANSDPLINK_N2(pipe) _PIPE(pipe, _TRANSA_DP_LINK_N2, _TRANSB_DP_LINK_N2) | ||
3039 | |||
3040 | #define _TRANSACONF 0xf0008 | ||
3041 | #define _TRANSBCONF 0xf1008 | ||
3042 | #define TRANSCONF(plane) _PIPE(plane, _TRANSACONF, _TRANSBCONF) | ||
2995 | #define TRANS_DISABLE (0<<31) | 3043 | #define TRANS_DISABLE (0<<31) |
2996 | #define TRANS_ENABLE (1<<31) | 3044 | #define TRANS_ENABLE (1<<31) |
2997 | #define TRANS_STATE_MASK (1<<30) | 3045 | #define TRANS_STATE_MASK (1<<30) |
@@ -3009,18 +3057,19 @@ | |||
3009 | #define TRANS_6BPC (2<<5) | 3057 | #define TRANS_6BPC (2<<5) |
3010 | #define TRANS_12BPC (3<<5) | 3058 | #define TRANS_12BPC (3<<5) |
3011 | 3059 | ||
3012 | #define FDI_RXA_CHICKEN 0xc200c | 3060 | #define _FDI_RXA_CHICKEN 0xc200c |
3013 | #define FDI_RXB_CHICKEN 0xc2010 | 3061 | #define _FDI_RXB_CHICKEN 0xc2010 |
3014 | #define FDI_RX_PHASE_SYNC_POINTER_ENABLE (1) | 3062 | #define FDI_RX_PHASE_SYNC_POINTER_OVR (1<<1) |
3015 | #define FDI_RX_CHICKEN(pipe) _PIPE(pipe, FDI_RXA_CHICKEN, FDI_RXB_CHICKEN) | 3063 | #define FDI_RX_PHASE_SYNC_POINTER_EN (1<<0) |
3064 | #define FDI_RX_CHICKEN(pipe) _PIPE(pipe, _FDI_RXA_CHICKEN, _FDI_RXB_CHICKEN) | ||
3016 | 3065 | ||
3017 | #define SOUTH_DSPCLK_GATE_D 0xc2020 | 3066 | #define SOUTH_DSPCLK_GATE_D 0xc2020 |
3018 | #define PCH_DPLSUNIT_CLOCK_GATE_DISABLE (1<<29) | 3067 | #define PCH_DPLSUNIT_CLOCK_GATE_DISABLE (1<<29) |
3019 | 3068 | ||
3020 | /* CPU: FDI_TX */ | 3069 | /* CPU: FDI_TX */ |
3021 | #define FDI_TXA_CTL 0x60100 | 3070 | #define _FDI_TXA_CTL 0x60100 |
3022 | #define FDI_TXB_CTL 0x61100 | 3071 | #define _FDI_TXB_CTL 0x61100 |
3023 | #define FDI_TX_CTL(pipe) _PIPE(pipe, FDI_TXA_CTL, FDI_TXB_CTL) | 3072 | #define FDI_TX_CTL(pipe) _PIPE(pipe, _FDI_TXA_CTL, _FDI_TXB_CTL) |
3024 | #define FDI_TX_DISABLE (0<<31) | 3073 | #define FDI_TX_DISABLE (0<<31) |
3025 | #define FDI_TX_ENABLE (1<<31) | 3074 | #define FDI_TX_ENABLE (1<<31) |
3026 | #define FDI_LINK_TRAIN_PATTERN_1 (0<<28) | 3075 | #define FDI_LINK_TRAIN_PATTERN_1 (0<<28) |
@@ -3060,9 +3109,9 @@ | |||
3060 | #define FDI_SCRAMBLING_DISABLE (1<<7) | 3109 | #define FDI_SCRAMBLING_DISABLE (1<<7) |
3061 | 3110 | ||
3062 | /* FDI_RX, FDI_X is hard-wired to Transcoder_X */ | 3111 | /* FDI_RX, FDI_X is hard-wired to Transcoder_X */ |
3063 | #define FDI_RXA_CTL 0xf000c | 3112 | #define _FDI_RXA_CTL 0xf000c |
3064 | #define FDI_RXB_CTL 0xf100c | 3113 | #define _FDI_RXB_CTL 0xf100c |
3065 | #define FDI_RX_CTL(pipe) _PIPE(pipe, FDI_RXA_CTL, FDI_RXB_CTL) | 3114 | #define FDI_RX_CTL(pipe) _PIPE(pipe, _FDI_RXA_CTL, _FDI_RXB_CTL) |
3066 | #define FDI_RX_ENABLE (1<<31) | 3115 | #define FDI_RX_ENABLE (1<<31) |
3067 | /* train, dp width same as FDI_TX */ | 3116 | /* train, dp width same as FDI_TX */ |
3068 | #define FDI_DP_PORT_WIDTH_X8 (7<<19) | 3117 | #define FDI_DP_PORT_WIDTH_X8 (7<<19) |
@@ -3087,15 +3136,15 @@ | |||
3087 | #define FDI_LINK_TRAIN_NORMAL_CPT (3<<8) | 3136 | #define FDI_LINK_TRAIN_NORMAL_CPT (3<<8) |
3088 | #define FDI_LINK_TRAIN_PATTERN_MASK_CPT (3<<8) | 3137 | #define FDI_LINK_TRAIN_PATTERN_MASK_CPT (3<<8) |
3089 | 3138 | ||
3090 | #define FDI_RXA_MISC 0xf0010 | 3139 | #define _FDI_RXA_MISC 0xf0010 |
3091 | #define FDI_RXB_MISC 0xf1010 | 3140 | #define _FDI_RXB_MISC 0xf1010 |
3092 | #define FDI_RXA_TUSIZE1 0xf0030 | 3141 | #define _FDI_RXA_TUSIZE1 0xf0030 |
3093 | #define FDI_RXA_TUSIZE2 0xf0038 | 3142 | #define _FDI_RXA_TUSIZE2 0xf0038 |
3094 | #define FDI_RXB_TUSIZE1 0xf1030 | 3143 | #define _FDI_RXB_TUSIZE1 0xf1030 |
3095 | #define FDI_RXB_TUSIZE2 0xf1038 | 3144 | #define _FDI_RXB_TUSIZE2 0xf1038 |
3096 | #define FDI_RX_MISC(pipe) _PIPE(pipe, FDI_RXA_MISC, FDI_RXB_MISC) | 3145 | #define FDI_RX_MISC(pipe) _PIPE(pipe, _FDI_RXA_MISC, _FDI_RXB_MISC) |
3097 | #define FDI_RX_TUSIZE1(pipe) _PIPE(pipe, FDI_RXA_TUSIZE1, FDI_RXB_TUSIZE1) | 3146 | #define FDI_RX_TUSIZE1(pipe) _PIPE(pipe, _FDI_RXA_TUSIZE1, _FDI_RXB_TUSIZE1) |
3098 | #define FDI_RX_TUSIZE2(pipe) _PIPE(pipe, FDI_RXA_TUSIZE2, FDI_RXB_TUSIZE2) | 3147 | #define FDI_RX_TUSIZE2(pipe) _PIPE(pipe, _FDI_RXA_TUSIZE2, _FDI_RXB_TUSIZE2) |
3099 | 3148 | ||
3100 | /* FDI_RX interrupt register format */ | 3149 | /* FDI_RX interrupt register format */ |
3101 | #define FDI_RX_INTER_LANE_ALIGN (1<<10) | 3150 | #define FDI_RX_INTER_LANE_ALIGN (1<<10) |
@@ -3110,12 +3159,12 @@ | |||
3110 | #define FDI_RX_CROSS_CLOCK_OVERFLOW (1<<1) | 3159 | #define FDI_RX_CROSS_CLOCK_OVERFLOW (1<<1) |
3111 | #define FDI_RX_SYMBOL_QUEUE_OVERFLOW (1<<0) | 3160 | #define FDI_RX_SYMBOL_QUEUE_OVERFLOW (1<<0) |
3112 | 3161 | ||
3113 | #define FDI_RXA_IIR 0xf0014 | 3162 | #define _FDI_RXA_IIR 0xf0014 |
3114 | #define FDI_RXA_IMR 0xf0018 | 3163 | #define _FDI_RXA_IMR 0xf0018 |
3115 | #define FDI_RXB_IIR 0xf1014 | 3164 | #define _FDI_RXB_IIR 0xf1014 |
3116 | #define FDI_RXB_IMR 0xf1018 | 3165 | #define _FDI_RXB_IMR 0xf1018 |
3117 | #define FDI_RX_IIR(pipe) _PIPE(pipe, FDI_RXA_IIR, FDI_RXB_IIR) | 3166 | #define FDI_RX_IIR(pipe) _PIPE(pipe, _FDI_RXA_IIR, _FDI_RXB_IIR) |
3118 | #define FDI_RX_IMR(pipe) _PIPE(pipe, FDI_RXA_IMR, FDI_RXB_IMR) | 3167 | #define FDI_RX_IMR(pipe) _PIPE(pipe, _FDI_RXA_IMR, _FDI_RXB_IMR) |
3119 | 3168 | ||
3120 | #define FDI_PLL_CTL_1 0xfe000 | 3169 | #define FDI_PLL_CTL_1 0xfe000 |
3121 | #define FDI_PLL_CTL_2 0xfe004 | 3170 | #define FDI_PLL_CTL_2 0xfe004 |
@@ -3145,11 +3194,15 @@ | |||
3145 | #define ADPA_CRT_HOTPLUG_VOLREF_475MV (1<<17) | 3194 | #define ADPA_CRT_HOTPLUG_VOLREF_475MV (1<<17) |
3146 | #define ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16) | 3195 | #define ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16) |
3147 | 3196 | ||
3197 | #define ADPA_PIPE_ENABLED(V, P) \ | ||
3198 | (((V) & (ADPA_TRANS_SELECT_MASK | ADPA_DAC_ENABLE)) == ((P) << 30 | ADPA_DAC_ENABLE)) | ||
3199 | |||
3148 | /* or SDVOB */ | 3200 | /* or SDVOB */ |
3149 | #define HDMIB 0xe1140 | 3201 | #define HDMIB 0xe1140 |
3150 | #define PORT_ENABLE (1 << 31) | 3202 | #define PORT_ENABLE (1 << 31) |
3151 | #define TRANSCODER_A (0) | 3203 | #define TRANSCODER_A (0) |
3152 | #define TRANSCODER_B (1 << 30) | 3204 | #define TRANSCODER_B (1 << 30) |
3205 | #define TRANSCODER_MASK (1 << 30) | ||
3153 | #define COLOR_FORMAT_8bpc (0) | 3206 | #define COLOR_FORMAT_8bpc (0) |
3154 | #define COLOR_FORMAT_12bpc (3 << 26) | 3207 | #define COLOR_FORMAT_12bpc (3 << 26) |
3155 | #define SDVOB_HOTPLUG_ENABLE (1 << 23) | 3208 | #define SDVOB_HOTPLUG_ENABLE (1 << 23) |
@@ -3165,6 +3218,9 @@ | |||
3165 | #define HSYNC_ACTIVE_HIGH (1 << 3) | 3218 | #define HSYNC_ACTIVE_HIGH (1 << 3) |
3166 | #define PORT_DETECTED (1 << 2) | 3219 | #define PORT_DETECTED (1 << 2) |
3167 | 3220 | ||
3221 | #define HDMI_PIPE_ENABLED(V, P) \ | ||
3222 | (((V) & (TRANSCODER_MASK | PORT_ENABLE)) == ((P) << 30 | PORT_ENABLE)) | ||
3223 | |||
3168 | /* PCH SDVOB multiplex with HDMIB */ | 3224 | /* PCH SDVOB multiplex with HDMIB */ |
3169 | #define PCH_SDVOB HDMIB | 3225 | #define PCH_SDVOB HDMIB |
3170 | 3226 | ||
@@ -3240,6 +3296,7 @@ | |||
3240 | #define TRANS_DP_PORT_SEL_B (0<<29) | 3296 | #define TRANS_DP_PORT_SEL_B (0<<29) |
3241 | #define TRANS_DP_PORT_SEL_C (1<<29) | 3297 | #define TRANS_DP_PORT_SEL_C (1<<29) |
3242 | #define TRANS_DP_PORT_SEL_D (2<<29) | 3298 | #define TRANS_DP_PORT_SEL_D (2<<29) |
3299 | #define TRANS_DP_PORT_SEL_NONE (3<<29) | ||
3243 | #define TRANS_DP_PORT_SEL_MASK (3<<29) | 3300 | #define TRANS_DP_PORT_SEL_MASK (3<<29) |
3244 | #define TRANS_DP_AUDIO_ONLY (1<<26) | 3301 | #define TRANS_DP_AUDIO_ONLY (1<<26) |
3245 | #define TRANS_DP_ENH_FRAMING (1<<18) | 3302 | #define TRANS_DP_ENH_FRAMING (1<<18) |
@@ -3290,15 +3347,28 @@ | |||
3290 | #define GEN6_RP_DOWN_TIMEOUT 0xA010 | 3347 | #define GEN6_RP_DOWN_TIMEOUT 0xA010 |
3291 | #define GEN6_RP_INTERRUPT_LIMITS 0xA014 | 3348 | #define GEN6_RP_INTERRUPT_LIMITS 0xA014 |
3292 | #define GEN6_RPSTAT1 0xA01C | 3349 | #define GEN6_RPSTAT1 0xA01C |
3350 | #define GEN6_CAGF_SHIFT 8 | ||
3351 | #define GEN6_CAGF_MASK (0x7f << GEN6_CAGF_SHIFT) | ||
3293 | #define GEN6_RP_CONTROL 0xA024 | 3352 | #define GEN6_RP_CONTROL 0xA024 |
3294 | #define GEN6_RP_MEDIA_TURBO (1<<11) | 3353 | #define GEN6_RP_MEDIA_TURBO (1<<11) |
3295 | #define GEN6_RP_USE_NORMAL_FREQ (1<<9) | 3354 | #define GEN6_RP_USE_NORMAL_FREQ (1<<9) |
3296 | #define GEN6_RP_MEDIA_IS_GFX (1<<8) | 3355 | #define GEN6_RP_MEDIA_IS_GFX (1<<8) |
3297 | #define GEN6_RP_ENABLE (1<<7) | 3356 | #define GEN6_RP_ENABLE (1<<7) |
3298 | #define GEN6_RP_UP_BUSY_MAX (0x2<<3) | 3357 | #define GEN6_RP_UP_IDLE_MIN (0x1<<3) |
3299 | #define GEN6_RP_DOWN_BUSY_MIN (0x2<<0) | 3358 | #define GEN6_RP_UP_BUSY_AVG (0x2<<3) |
3359 | #define GEN6_RP_UP_BUSY_CONT (0x4<<3) | ||
3360 | #define GEN6_RP_DOWN_IDLE_CONT (0x1<<0) | ||
3300 | #define GEN6_RP_UP_THRESHOLD 0xA02C | 3361 | #define GEN6_RP_UP_THRESHOLD 0xA02C |
3301 | #define GEN6_RP_DOWN_THRESHOLD 0xA030 | 3362 | #define GEN6_RP_DOWN_THRESHOLD 0xA030 |
3363 | #define GEN6_RP_CUR_UP_EI 0xA050 | ||
3364 | #define GEN6_CURICONT_MASK 0xffffff | ||
3365 | #define GEN6_RP_CUR_UP 0xA054 | ||
3366 | #define GEN6_CURBSYTAVG_MASK 0xffffff | ||
3367 | #define GEN6_RP_PREV_UP 0xA058 | ||
3368 | #define GEN6_RP_CUR_DOWN_EI 0xA05C | ||
3369 | #define GEN6_CURIAVG_MASK 0xffffff | ||
3370 | #define GEN6_RP_CUR_DOWN 0xA060 | ||
3371 | #define GEN6_RP_PREV_DOWN 0xA064 | ||
3302 | #define GEN6_RP_UP_EI 0xA068 | 3372 | #define GEN6_RP_UP_EI 0xA068 |
3303 | #define GEN6_RP_DOWN_EI 0xA06C | 3373 | #define GEN6_RP_DOWN_EI 0xA06C |
3304 | #define GEN6_RP_IDLE_HYSTERSIS 0xA070 | 3374 | #define GEN6_RP_IDLE_HYSTERSIS 0xA070 |
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 0521ecf2601..7e992a8e909 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c | |||
@@ -34,11 +34,10 @@ static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe) | |||
34 | struct drm_i915_private *dev_priv = dev->dev_private; | 34 | struct drm_i915_private *dev_priv = dev->dev_private; |
35 | u32 dpll_reg; | 35 | u32 dpll_reg; |
36 | 36 | ||
37 | if (HAS_PCH_SPLIT(dev)) { | 37 | if (HAS_PCH_SPLIT(dev)) |
38 | dpll_reg = (pipe == PIPE_A) ? PCH_DPLL_A: PCH_DPLL_B; | 38 | dpll_reg = (pipe == PIPE_A) ? _PCH_DPLL_A : _PCH_DPLL_B; |
39 | } else { | 39 | else |
40 | dpll_reg = (pipe == PIPE_A) ? DPLL_A: DPLL_B; | 40 | dpll_reg = (pipe == PIPE_A) ? _DPLL_A : _DPLL_B; |
41 | } | ||
42 | 41 | ||
43 | return (I915_READ(dpll_reg) & DPLL_VCO_ENABLE); | 42 | return (I915_READ(dpll_reg) & DPLL_VCO_ENABLE); |
44 | } | 43 | } |
@@ -46,7 +45,7 @@ static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe) | |||
46 | static void i915_save_palette(struct drm_device *dev, enum pipe pipe) | 45 | static void i915_save_palette(struct drm_device *dev, enum pipe pipe) |
47 | { | 46 | { |
48 | struct drm_i915_private *dev_priv = dev->dev_private; | 47 | struct drm_i915_private *dev_priv = dev->dev_private; |
49 | unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B); | 48 | unsigned long reg = (pipe == PIPE_A ? _PALETTE_A : _PALETTE_B); |
50 | u32 *array; | 49 | u32 *array; |
51 | int i; | 50 | int i; |
52 | 51 | ||
@@ -54,7 +53,7 @@ static void i915_save_palette(struct drm_device *dev, enum pipe pipe) | |||
54 | return; | 53 | return; |
55 | 54 | ||
56 | if (HAS_PCH_SPLIT(dev)) | 55 | if (HAS_PCH_SPLIT(dev)) |
57 | reg = (pipe == PIPE_A) ? LGC_PALETTE_A : LGC_PALETTE_B; | 56 | reg = (pipe == PIPE_A) ? _LGC_PALETTE_A : _LGC_PALETTE_B; |
58 | 57 | ||
59 | if (pipe == PIPE_A) | 58 | if (pipe == PIPE_A) |
60 | array = dev_priv->save_palette_a; | 59 | array = dev_priv->save_palette_a; |
@@ -68,7 +67,7 @@ static void i915_save_palette(struct drm_device *dev, enum pipe pipe) | |||
68 | static void i915_restore_palette(struct drm_device *dev, enum pipe pipe) | 67 | static void i915_restore_palette(struct drm_device *dev, enum pipe pipe) |
69 | { | 68 | { |
70 | struct drm_i915_private *dev_priv = dev->dev_private; | 69 | struct drm_i915_private *dev_priv = dev->dev_private; |
71 | unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B); | 70 | unsigned long reg = (pipe == PIPE_A ? _PALETTE_A : _PALETTE_B); |
72 | u32 *array; | 71 | u32 *array; |
73 | int i; | 72 | int i; |
74 | 73 | ||
@@ -76,7 +75,7 @@ static void i915_restore_palette(struct drm_device *dev, enum pipe pipe) | |||
76 | return; | 75 | return; |
77 | 76 | ||
78 | if (HAS_PCH_SPLIT(dev)) | 77 | if (HAS_PCH_SPLIT(dev)) |
79 | reg = (pipe == PIPE_A) ? LGC_PALETTE_A : LGC_PALETTE_B; | 78 | reg = (pipe == PIPE_A) ? _LGC_PALETTE_A : _LGC_PALETTE_B; |
80 | 79 | ||
81 | if (pipe == PIPE_A) | 80 | if (pipe == PIPE_A) |
82 | array = dev_priv->save_palette_a; | 81 | array = dev_priv->save_palette_a; |
@@ -241,12 +240,12 @@ static void i915_save_modeset_reg(struct drm_device *dev) | |||
241 | return; | 240 | return; |
242 | 241 | ||
243 | /* Cursor state */ | 242 | /* Cursor state */ |
244 | dev_priv->saveCURACNTR = I915_READ(CURACNTR); | 243 | dev_priv->saveCURACNTR = I915_READ(_CURACNTR); |
245 | dev_priv->saveCURAPOS = I915_READ(CURAPOS); | 244 | dev_priv->saveCURAPOS = I915_READ(_CURAPOS); |
246 | dev_priv->saveCURABASE = I915_READ(CURABASE); | 245 | dev_priv->saveCURABASE = I915_READ(_CURABASE); |
247 | dev_priv->saveCURBCNTR = I915_READ(CURBCNTR); | 246 | dev_priv->saveCURBCNTR = I915_READ(_CURBCNTR); |
248 | dev_priv->saveCURBPOS = I915_READ(CURBPOS); | 247 | dev_priv->saveCURBPOS = I915_READ(_CURBPOS); |
249 | dev_priv->saveCURBBASE = I915_READ(CURBBASE); | 248 | dev_priv->saveCURBBASE = I915_READ(_CURBBASE); |
250 | if (IS_GEN2(dev)) | 249 | if (IS_GEN2(dev)) |
251 | dev_priv->saveCURSIZE = I915_READ(CURSIZE); | 250 | dev_priv->saveCURSIZE = I915_READ(CURSIZE); |
252 | 251 | ||
@@ -256,118 +255,118 @@ static void i915_save_modeset_reg(struct drm_device *dev) | |||
256 | } | 255 | } |
257 | 256 | ||
258 | /* Pipe & plane A info */ | 257 | /* Pipe & plane A info */ |
259 | dev_priv->savePIPEACONF = I915_READ(PIPEACONF); | 258 | dev_priv->savePIPEACONF = I915_READ(_PIPEACONF); |
260 | dev_priv->savePIPEASRC = I915_READ(PIPEASRC); | 259 | dev_priv->savePIPEASRC = I915_READ(_PIPEASRC); |
261 | if (HAS_PCH_SPLIT(dev)) { | 260 | if (HAS_PCH_SPLIT(dev)) { |
262 | dev_priv->saveFPA0 = I915_READ(PCH_FPA0); | 261 | dev_priv->saveFPA0 = I915_READ(_PCH_FPA0); |
263 | dev_priv->saveFPA1 = I915_READ(PCH_FPA1); | 262 | dev_priv->saveFPA1 = I915_READ(_PCH_FPA1); |
264 | dev_priv->saveDPLL_A = I915_READ(PCH_DPLL_A); | 263 | dev_priv->saveDPLL_A = I915_READ(_PCH_DPLL_A); |
265 | } else { | 264 | } else { |
266 | dev_priv->saveFPA0 = I915_READ(FPA0); | 265 | dev_priv->saveFPA0 = I915_READ(_FPA0); |
267 | dev_priv->saveFPA1 = I915_READ(FPA1); | 266 | dev_priv->saveFPA1 = I915_READ(_FPA1); |
268 | dev_priv->saveDPLL_A = I915_READ(DPLL_A); | 267 | dev_priv->saveDPLL_A = I915_READ(_DPLL_A); |
269 | } | 268 | } |
270 | if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) | 269 | if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) |
271 | dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD); | 270 | dev_priv->saveDPLL_A_MD = I915_READ(_DPLL_A_MD); |
272 | dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A); | 271 | dev_priv->saveHTOTAL_A = I915_READ(_HTOTAL_A); |
273 | dev_priv->saveHBLANK_A = I915_READ(HBLANK_A); | 272 | dev_priv->saveHBLANK_A = I915_READ(_HBLANK_A); |
274 | dev_priv->saveHSYNC_A = I915_READ(HSYNC_A); | 273 | dev_priv->saveHSYNC_A = I915_READ(_HSYNC_A); |
275 | dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A); | 274 | dev_priv->saveVTOTAL_A = I915_READ(_VTOTAL_A); |
276 | dev_priv->saveVBLANK_A = I915_READ(VBLANK_A); | 275 | dev_priv->saveVBLANK_A = I915_READ(_VBLANK_A); |
277 | dev_priv->saveVSYNC_A = I915_READ(VSYNC_A); | 276 | dev_priv->saveVSYNC_A = I915_READ(_VSYNC_A); |
278 | if (!HAS_PCH_SPLIT(dev)) | 277 | if (!HAS_PCH_SPLIT(dev)) |
279 | dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A); | 278 | dev_priv->saveBCLRPAT_A = I915_READ(_BCLRPAT_A); |
280 | 279 | ||
281 | if (HAS_PCH_SPLIT(dev)) { | 280 | if (HAS_PCH_SPLIT(dev)) { |
282 | dev_priv->savePIPEA_DATA_M1 = I915_READ(PIPEA_DATA_M1); | 281 | dev_priv->savePIPEA_DATA_M1 = I915_READ(_PIPEA_DATA_M1); |
283 | dev_priv->savePIPEA_DATA_N1 = I915_READ(PIPEA_DATA_N1); | 282 | dev_priv->savePIPEA_DATA_N1 = I915_READ(_PIPEA_DATA_N1); |
284 | dev_priv->savePIPEA_LINK_M1 = I915_READ(PIPEA_LINK_M1); | 283 | dev_priv->savePIPEA_LINK_M1 = I915_READ(_PIPEA_LINK_M1); |
285 | dev_priv->savePIPEA_LINK_N1 = I915_READ(PIPEA_LINK_N1); | 284 | dev_priv->savePIPEA_LINK_N1 = I915_READ(_PIPEA_LINK_N1); |
286 | 285 | ||
287 | dev_priv->saveFDI_TXA_CTL = I915_READ(FDI_TXA_CTL); | 286 | dev_priv->saveFDI_TXA_CTL = I915_READ(_FDI_TXA_CTL); |
288 | dev_priv->saveFDI_RXA_CTL = I915_READ(FDI_RXA_CTL); | 287 | dev_priv->saveFDI_RXA_CTL = I915_READ(_FDI_RXA_CTL); |
289 | 288 | ||
290 | dev_priv->savePFA_CTL_1 = I915_READ(PFA_CTL_1); | 289 | dev_priv->savePFA_CTL_1 = I915_READ(_PFA_CTL_1); |
291 | dev_priv->savePFA_WIN_SZ = I915_READ(PFA_WIN_SZ); | 290 | dev_priv->savePFA_WIN_SZ = I915_READ(_PFA_WIN_SZ); |
292 | dev_priv->savePFA_WIN_POS = I915_READ(PFA_WIN_POS); | 291 | dev_priv->savePFA_WIN_POS = I915_READ(_PFA_WIN_POS); |
293 | 292 | ||
294 | dev_priv->saveTRANSACONF = I915_READ(TRANSACONF); | 293 | dev_priv->saveTRANSACONF = I915_READ(_TRANSACONF); |
295 | dev_priv->saveTRANS_HTOTAL_A = I915_READ(TRANS_HTOTAL_A); | 294 | dev_priv->saveTRANS_HTOTAL_A = I915_READ(_TRANS_HTOTAL_A); |
296 | dev_priv->saveTRANS_HBLANK_A = I915_READ(TRANS_HBLANK_A); | 295 | dev_priv->saveTRANS_HBLANK_A = I915_READ(_TRANS_HBLANK_A); |
297 | dev_priv->saveTRANS_HSYNC_A = I915_READ(TRANS_HSYNC_A); | 296 | dev_priv->saveTRANS_HSYNC_A = I915_READ(_TRANS_HSYNC_A); |
298 | dev_priv->saveTRANS_VTOTAL_A = I915_READ(TRANS_VTOTAL_A); | 297 | dev_priv->saveTRANS_VTOTAL_A = I915_READ(_TRANS_VTOTAL_A); |
299 | dev_priv->saveTRANS_VBLANK_A = I915_READ(TRANS_VBLANK_A); | 298 | dev_priv->saveTRANS_VBLANK_A = I915_READ(_TRANS_VBLANK_A); |
300 | dev_priv->saveTRANS_VSYNC_A = I915_READ(TRANS_VSYNC_A); | 299 | dev_priv->saveTRANS_VSYNC_A = I915_READ(_TRANS_VSYNC_A); |
301 | } | 300 | } |
302 | 301 | ||
303 | dev_priv->saveDSPACNTR = I915_READ(DSPACNTR); | 302 | dev_priv->saveDSPACNTR = I915_READ(_DSPACNTR); |
304 | dev_priv->saveDSPASTRIDE = I915_READ(DSPASTRIDE); | 303 | dev_priv->saveDSPASTRIDE = I915_READ(_DSPASTRIDE); |
305 | dev_priv->saveDSPASIZE = I915_READ(DSPASIZE); | 304 | dev_priv->saveDSPASIZE = I915_READ(_DSPASIZE); |
306 | dev_priv->saveDSPAPOS = I915_READ(DSPAPOS); | 305 | dev_priv->saveDSPAPOS = I915_READ(_DSPAPOS); |
307 | dev_priv->saveDSPAADDR = I915_READ(DSPAADDR); | 306 | dev_priv->saveDSPAADDR = I915_READ(_DSPAADDR); |
308 | if (INTEL_INFO(dev)->gen >= 4) { | 307 | if (INTEL_INFO(dev)->gen >= 4) { |
309 | dev_priv->saveDSPASURF = I915_READ(DSPASURF); | 308 | dev_priv->saveDSPASURF = I915_READ(_DSPASURF); |
310 | dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF); | 309 | dev_priv->saveDSPATILEOFF = I915_READ(_DSPATILEOFF); |
311 | } | 310 | } |
312 | i915_save_palette(dev, PIPE_A); | 311 | i915_save_palette(dev, PIPE_A); |
313 | dev_priv->savePIPEASTAT = I915_READ(PIPEASTAT); | 312 | dev_priv->savePIPEASTAT = I915_READ(_PIPEASTAT); |
314 | 313 | ||
315 | /* Pipe & plane B info */ | 314 | /* Pipe & plane B info */ |
316 | dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF); | 315 | dev_priv->savePIPEBCONF = I915_READ(_PIPEBCONF); |
317 | dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC); | 316 | dev_priv->savePIPEBSRC = I915_READ(_PIPEBSRC); |
318 | if (HAS_PCH_SPLIT(dev)) { | 317 | if (HAS_PCH_SPLIT(dev)) { |
319 | dev_priv->saveFPB0 = I915_READ(PCH_FPB0); | 318 | dev_priv->saveFPB0 = I915_READ(_PCH_FPB0); |
320 | dev_priv->saveFPB1 = I915_READ(PCH_FPB1); | 319 | dev_priv->saveFPB1 = I915_READ(_PCH_FPB1); |
321 | dev_priv->saveDPLL_B = I915_READ(PCH_DPLL_B); | 320 | dev_priv->saveDPLL_B = I915_READ(_PCH_DPLL_B); |
322 | } else { | 321 | } else { |
323 | dev_priv->saveFPB0 = I915_READ(FPB0); | 322 | dev_priv->saveFPB0 = I915_READ(_FPB0); |
324 | dev_priv->saveFPB1 = I915_READ(FPB1); | 323 | dev_priv->saveFPB1 = I915_READ(_FPB1); |
325 | dev_priv->saveDPLL_B = I915_READ(DPLL_B); | 324 | dev_priv->saveDPLL_B = I915_READ(_DPLL_B); |
326 | } | 325 | } |
327 | if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) | 326 | if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) |
328 | dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD); | 327 | dev_priv->saveDPLL_B_MD = I915_READ(_DPLL_B_MD); |
329 | dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B); | 328 | dev_priv->saveHTOTAL_B = I915_READ(_HTOTAL_B); |
330 | dev_priv->saveHBLANK_B = I915_READ(HBLANK_B); | 329 | dev_priv->saveHBLANK_B = I915_READ(_HBLANK_B); |
331 | dev_priv->saveHSYNC_B = I915_READ(HSYNC_B); | 330 | dev_priv->saveHSYNC_B = I915_READ(_HSYNC_B); |
332 | dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B); | 331 | dev_priv->saveVTOTAL_B = I915_READ(_VTOTAL_B); |
333 | dev_priv->saveVBLANK_B = I915_READ(VBLANK_B); | 332 | dev_priv->saveVBLANK_B = I915_READ(_VBLANK_B); |
334 | dev_priv->saveVSYNC_B = I915_READ(VSYNC_B); | 333 | dev_priv->saveVSYNC_B = I915_READ(_VSYNC_B); |
335 | if (!HAS_PCH_SPLIT(dev)) | 334 | if (!HAS_PCH_SPLIT(dev)) |
336 | dev_priv->saveBCLRPAT_B = I915_READ(BCLRPAT_B); | 335 | dev_priv->saveBCLRPAT_B = I915_READ(_BCLRPAT_B); |
337 | 336 | ||
338 | if (HAS_PCH_SPLIT(dev)) { | 337 | if (HAS_PCH_SPLIT(dev)) { |
339 | dev_priv->savePIPEB_DATA_M1 = I915_READ(PIPEB_DATA_M1); | 338 | dev_priv->savePIPEB_DATA_M1 = I915_READ(_PIPEB_DATA_M1); |
340 | dev_priv->savePIPEB_DATA_N1 = I915_READ(PIPEB_DATA_N1); | 339 | dev_priv->savePIPEB_DATA_N1 = I915_READ(_PIPEB_DATA_N1); |
341 | dev_priv->savePIPEB_LINK_M1 = I915_READ(PIPEB_LINK_M1); | 340 | dev_priv->savePIPEB_LINK_M1 = I915_READ(_PIPEB_LINK_M1); |
342 | dev_priv->savePIPEB_LINK_N1 = I915_READ(PIPEB_LINK_N1); | 341 | dev_priv->savePIPEB_LINK_N1 = I915_READ(_PIPEB_LINK_N1); |
343 | 342 | ||
344 | dev_priv->saveFDI_TXB_CTL = I915_READ(FDI_TXB_CTL); | 343 | dev_priv->saveFDI_TXB_CTL = I915_READ(_FDI_TXB_CTL); |
345 | dev_priv->saveFDI_RXB_CTL = I915_READ(FDI_RXB_CTL); | 344 | dev_priv->saveFDI_RXB_CTL = I915_READ(_FDI_RXB_CTL); |
346 | 345 | ||
347 | dev_priv->savePFB_CTL_1 = I915_READ(PFB_CTL_1); | 346 | dev_priv->savePFB_CTL_1 = I915_READ(_PFB_CTL_1); |
348 | dev_priv->savePFB_WIN_SZ = I915_READ(PFB_WIN_SZ); | 347 | dev_priv->savePFB_WIN_SZ = I915_READ(_PFB_WIN_SZ); |
349 | dev_priv->savePFB_WIN_POS = I915_READ(PFB_WIN_POS); | 348 | dev_priv->savePFB_WIN_POS = I915_READ(_PFB_WIN_POS); |
350 | 349 | ||
351 | dev_priv->saveTRANSBCONF = I915_READ(TRANSBCONF); | 350 | dev_priv->saveTRANSBCONF = I915_READ(_TRANSBCONF); |
352 | dev_priv->saveTRANS_HTOTAL_B = I915_READ(TRANS_HTOTAL_B); | 351 | dev_priv->saveTRANS_HTOTAL_B = I915_READ(_TRANS_HTOTAL_B); |
353 | dev_priv->saveTRANS_HBLANK_B = I915_READ(TRANS_HBLANK_B); | 352 | dev_priv->saveTRANS_HBLANK_B = I915_READ(_TRANS_HBLANK_B); |
354 | dev_priv->saveTRANS_HSYNC_B = I915_READ(TRANS_HSYNC_B); | 353 | dev_priv->saveTRANS_HSYNC_B = I915_READ(_TRANS_HSYNC_B); |
355 | dev_priv->saveTRANS_VTOTAL_B = I915_READ(TRANS_VTOTAL_B); | 354 | dev_priv->saveTRANS_VTOTAL_B = I915_READ(_TRANS_VTOTAL_B); |
356 | dev_priv->saveTRANS_VBLANK_B = I915_READ(TRANS_VBLANK_B); | 355 | dev_priv->saveTRANS_VBLANK_B = I915_READ(_TRANS_VBLANK_B); |
357 | dev_priv->saveTRANS_VSYNC_B = I915_READ(TRANS_VSYNC_B); | 356 | dev_priv->saveTRANS_VSYNC_B = I915_READ(_TRANS_VSYNC_B); |
358 | } | 357 | } |
359 | 358 | ||
360 | dev_priv->saveDSPBCNTR = I915_READ(DSPBCNTR); | 359 | dev_priv->saveDSPBCNTR = I915_READ(_DSPBCNTR); |
361 | dev_priv->saveDSPBSTRIDE = I915_READ(DSPBSTRIDE); | 360 | dev_priv->saveDSPBSTRIDE = I915_READ(_DSPBSTRIDE); |
362 | dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE); | 361 | dev_priv->saveDSPBSIZE = I915_READ(_DSPBSIZE); |
363 | dev_priv->saveDSPBPOS = I915_READ(DSPBPOS); | 362 | dev_priv->saveDSPBPOS = I915_READ(_DSPBPOS); |
364 | dev_priv->saveDSPBADDR = I915_READ(DSPBADDR); | 363 | dev_priv->saveDSPBADDR = I915_READ(_DSPBADDR); |
365 | if (INTEL_INFO(dev)->gen >= 4) { | 364 | if (INTEL_INFO(dev)->gen >= 4) { |
366 | dev_priv->saveDSPBSURF = I915_READ(DSPBSURF); | 365 | dev_priv->saveDSPBSURF = I915_READ(_DSPBSURF); |
367 | dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF); | 366 | dev_priv->saveDSPBTILEOFF = I915_READ(_DSPBTILEOFF); |
368 | } | 367 | } |
369 | i915_save_palette(dev, PIPE_B); | 368 | i915_save_palette(dev, PIPE_B); |
370 | dev_priv->savePIPEBSTAT = I915_READ(PIPEBSTAT); | 369 | dev_priv->savePIPEBSTAT = I915_READ(_PIPEBSTAT); |
371 | 370 | ||
372 | /* Fences */ | 371 | /* Fences */ |
373 | switch (INTEL_INFO(dev)->gen) { | 372 | switch (INTEL_INFO(dev)->gen) { |
@@ -426,19 +425,19 @@ static void i915_restore_modeset_reg(struct drm_device *dev) | |||
426 | 425 | ||
427 | 426 | ||
428 | if (HAS_PCH_SPLIT(dev)) { | 427 | if (HAS_PCH_SPLIT(dev)) { |
429 | dpll_a_reg = PCH_DPLL_A; | 428 | dpll_a_reg = _PCH_DPLL_A; |
430 | dpll_b_reg = PCH_DPLL_B; | 429 | dpll_b_reg = _PCH_DPLL_B; |
431 | fpa0_reg = PCH_FPA0; | 430 | fpa0_reg = _PCH_FPA0; |
432 | fpb0_reg = PCH_FPB0; | 431 | fpb0_reg = _PCH_FPB0; |
433 | fpa1_reg = PCH_FPA1; | 432 | fpa1_reg = _PCH_FPA1; |
434 | fpb1_reg = PCH_FPB1; | 433 | fpb1_reg = _PCH_FPB1; |
435 | } else { | 434 | } else { |
436 | dpll_a_reg = DPLL_A; | 435 | dpll_a_reg = _DPLL_A; |
437 | dpll_b_reg = DPLL_B; | 436 | dpll_b_reg = _DPLL_B; |
438 | fpa0_reg = FPA0; | 437 | fpa0_reg = _FPA0; |
439 | fpb0_reg = FPB0; | 438 | fpb0_reg = _FPB0; |
440 | fpa1_reg = FPA1; | 439 | fpa1_reg = _FPA1; |
441 | fpb1_reg = FPB1; | 440 | fpb1_reg = _FPB1; |
442 | } | 441 | } |
443 | 442 | ||
444 | if (HAS_PCH_SPLIT(dev)) { | 443 | if (HAS_PCH_SPLIT(dev)) { |
@@ -461,60 +460,60 @@ static void i915_restore_modeset_reg(struct drm_device *dev) | |||
461 | POSTING_READ(dpll_a_reg); | 460 | POSTING_READ(dpll_a_reg); |
462 | udelay(150); | 461 | udelay(150); |
463 | if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { | 462 | if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { |
464 | I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD); | 463 | I915_WRITE(_DPLL_A_MD, dev_priv->saveDPLL_A_MD); |
465 | POSTING_READ(DPLL_A_MD); | 464 | POSTING_READ(_DPLL_A_MD); |
466 | } | 465 | } |
467 | udelay(150); | 466 | udelay(150); |
468 | 467 | ||
469 | /* Restore mode */ | 468 | /* Restore mode */ |
470 | I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A); | 469 | I915_WRITE(_HTOTAL_A, dev_priv->saveHTOTAL_A); |
471 | I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A); | 470 | I915_WRITE(_HBLANK_A, dev_priv->saveHBLANK_A); |
472 | I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A); | 471 | I915_WRITE(_HSYNC_A, dev_priv->saveHSYNC_A); |
473 | I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A); | 472 | I915_WRITE(_VTOTAL_A, dev_priv->saveVTOTAL_A); |
474 | I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A); | 473 | I915_WRITE(_VBLANK_A, dev_priv->saveVBLANK_A); |
475 | I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A); | 474 | I915_WRITE(_VSYNC_A, dev_priv->saveVSYNC_A); |
476 | if (!HAS_PCH_SPLIT(dev)) | 475 | if (!HAS_PCH_SPLIT(dev)) |
477 | I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A); | 476 | I915_WRITE(_BCLRPAT_A, dev_priv->saveBCLRPAT_A); |
478 | 477 | ||
479 | if (HAS_PCH_SPLIT(dev)) { | 478 | if (HAS_PCH_SPLIT(dev)) { |
480 | I915_WRITE(PIPEA_DATA_M1, dev_priv->savePIPEA_DATA_M1); | 479 | I915_WRITE(_PIPEA_DATA_M1, dev_priv->savePIPEA_DATA_M1); |
481 | I915_WRITE(PIPEA_DATA_N1, dev_priv->savePIPEA_DATA_N1); | 480 | I915_WRITE(_PIPEA_DATA_N1, dev_priv->savePIPEA_DATA_N1); |
482 | I915_WRITE(PIPEA_LINK_M1, dev_priv->savePIPEA_LINK_M1); | 481 | I915_WRITE(_PIPEA_LINK_M1, dev_priv->savePIPEA_LINK_M1); |
483 | I915_WRITE(PIPEA_LINK_N1, dev_priv->savePIPEA_LINK_N1); | 482 | I915_WRITE(_PIPEA_LINK_N1, dev_priv->savePIPEA_LINK_N1); |
484 | 483 | ||
485 | I915_WRITE(FDI_RXA_CTL, dev_priv->saveFDI_RXA_CTL); | 484 | I915_WRITE(_FDI_RXA_CTL, dev_priv->saveFDI_RXA_CTL); |
486 | I915_WRITE(FDI_TXA_CTL, dev_priv->saveFDI_TXA_CTL); | 485 | I915_WRITE(_FDI_TXA_CTL, dev_priv->saveFDI_TXA_CTL); |
487 | 486 | ||
488 | I915_WRITE(PFA_CTL_1, dev_priv->savePFA_CTL_1); | 487 | I915_WRITE(_PFA_CTL_1, dev_priv->savePFA_CTL_1); |
489 | I915_WRITE(PFA_WIN_SZ, dev_priv->savePFA_WIN_SZ); | 488 | I915_WRITE(_PFA_WIN_SZ, dev_priv->savePFA_WIN_SZ); |
490 | I915_WRITE(PFA_WIN_POS, dev_priv->savePFA_WIN_POS); | 489 | I915_WRITE(_PFA_WIN_POS, dev_priv->savePFA_WIN_POS); |
491 | 490 | ||
492 | I915_WRITE(TRANSACONF, dev_priv->saveTRANSACONF); | 491 | I915_WRITE(_TRANSACONF, dev_priv->saveTRANSACONF); |
493 | I915_WRITE(TRANS_HTOTAL_A, dev_priv->saveTRANS_HTOTAL_A); | 492 | I915_WRITE(_TRANS_HTOTAL_A, dev_priv->saveTRANS_HTOTAL_A); |
494 | I915_WRITE(TRANS_HBLANK_A, dev_priv->saveTRANS_HBLANK_A); | 493 | I915_WRITE(_TRANS_HBLANK_A, dev_priv->saveTRANS_HBLANK_A); |
495 | I915_WRITE(TRANS_HSYNC_A, dev_priv->saveTRANS_HSYNC_A); | 494 | I915_WRITE(_TRANS_HSYNC_A, dev_priv->saveTRANS_HSYNC_A); |
496 | I915_WRITE(TRANS_VTOTAL_A, dev_priv->saveTRANS_VTOTAL_A); | 495 | I915_WRITE(_TRANS_VTOTAL_A, dev_priv->saveTRANS_VTOTAL_A); |
497 | I915_WRITE(TRANS_VBLANK_A, dev_priv->saveTRANS_VBLANK_A); | 496 | I915_WRITE(_TRANS_VBLANK_A, dev_priv->saveTRANS_VBLANK_A); |
498 | I915_WRITE(TRANS_VSYNC_A, dev_priv->saveTRANS_VSYNC_A); | 497 | I915_WRITE(_TRANS_VSYNC_A, dev_priv->saveTRANS_VSYNC_A); |
499 | } | 498 | } |
500 | 499 | ||
501 | /* Restore plane info */ | 500 | /* Restore plane info */ |
502 | I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE); | 501 | I915_WRITE(_DSPASIZE, dev_priv->saveDSPASIZE); |
503 | I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS); | 502 | I915_WRITE(_DSPAPOS, dev_priv->saveDSPAPOS); |
504 | I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC); | 503 | I915_WRITE(_PIPEASRC, dev_priv->savePIPEASRC); |
505 | I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR); | 504 | I915_WRITE(_DSPAADDR, dev_priv->saveDSPAADDR); |
506 | I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE); | 505 | I915_WRITE(_DSPASTRIDE, dev_priv->saveDSPASTRIDE); |
507 | if (INTEL_INFO(dev)->gen >= 4) { | 506 | if (INTEL_INFO(dev)->gen >= 4) { |
508 | I915_WRITE(DSPASURF, dev_priv->saveDSPASURF); | 507 | I915_WRITE(_DSPASURF, dev_priv->saveDSPASURF); |
509 | I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF); | 508 | I915_WRITE(_DSPATILEOFF, dev_priv->saveDSPATILEOFF); |
510 | } | 509 | } |
511 | 510 | ||
512 | I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF); | 511 | I915_WRITE(_PIPEACONF, dev_priv->savePIPEACONF); |
513 | 512 | ||
514 | i915_restore_palette(dev, PIPE_A); | 513 | i915_restore_palette(dev, PIPE_A); |
515 | /* Enable the plane */ | 514 | /* Enable the plane */ |
516 | I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR); | 515 | I915_WRITE(_DSPACNTR, dev_priv->saveDSPACNTR); |
517 | I915_WRITE(DSPAADDR, I915_READ(DSPAADDR)); | 516 | I915_WRITE(_DSPAADDR, I915_READ(_DSPAADDR)); |
518 | 517 | ||
519 | /* Pipe & plane B info */ | 518 | /* Pipe & plane B info */ |
520 | if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) { | 519 | if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) { |
@@ -530,68 +529,68 @@ static void i915_restore_modeset_reg(struct drm_device *dev) | |||
530 | POSTING_READ(dpll_b_reg); | 529 | POSTING_READ(dpll_b_reg); |
531 | udelay(150); | 530 | udelay(150); |
532 | if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { | 531 | if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { |
533 | I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD); | 532 | I915_WRITE(_DPLL_B_MD, dev_priv->saveDPLL_B_MD); |
534 | POSTING_READ(DPLL_B_MD); | 533 | POSTING_READ(_DPLL_B_MD); |
535 | } | 534 | } |
536 | udelay(150); | 535 | udelay(150); |
537 | 536 | ||
538 | /* Restore mode */ | 537 | /* Restore mode */ |
539 | I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B); | 538 | I915_WRITE(_HTOTAL_B, dev_priv->saveHTOTAL_B); |
540 | I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B); | 539 | I915_WRITE(_HBLANK_B, dev_priv->saveHBLANK_B); |
541 | I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B); | 540 | I915_WRITE(_HSYNC_B, dev_priv->saveHSYNC_B); |
542 | I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B); | 541 | I915_WRITE(_VTOTAL_B, dev_priv->saveVTOTAL_B); |
543 | I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B); | 542 | I915_WRITE(_VBLANK_B, dev_priv->saveVBLANK_B); |
544 | I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B); | 543 | I915_WRITE(_VSYNC_B, dev_priv->saveVSYNC_B); |
545 | if (!HAS_PCH_SPLIT(dev)) | 544 | if (!HAS_PCH_SPLIT(dev)) |
546 | I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B); | 545 | I915_WRITE(_BCLRPAT_B, dev_priv->saveBCLRPAT_B); |
547 | 546 | ||
548 | if (HAS_PCH_SPLIT(dev)) { | 547 | if (HAS_PCH_SPLIT(dev)) { |
549 | I915_WRITE(PIPEB_DATA_M1, dev_priv->savePIPEB_DATA_M1); | 548 | I915_WRITE(_PIPEB_DATA_M1, dev_priv->savePIPEB_DATA_M1); |
550 | I915_WRITE(PIPEB_DATA_N1, dev_priv->savePIPEB_DATA_N1); | 549 | I915_WRITE(_PIPEB_DATA_N1, dev_priv->savePIPEB_DATA_N1); |
551 | I915_WRITE(PIPEB_LINK_M1, dev_priv->savePIPEB_LINK_M1); | 550 | I915_WRITE(_PIPEB_LINK_M1, dev_priv->savePIPEB_LINK_M1); |
552 | I915_WRITE(PIPEB_LINK_N1, dev_priv->savePIPEB_LINK_N1); | 551 | I915_WRITE(_PIPEB_LINK_N1, dev_priv->savePIPEB_LINK_N1); |
553 | 552 | ||
554 | I915_WRITE(FDI_RXB_CTL, dev_priv->saveFDI_RXB_CTL); | 553 | I915_WRITE(_FDI_RXB_CTL, dev_priv->saveFDI_RXB_CTL); |
555 | I915_WRITE(FDI_TXB_CTL, dev_priv->saveFDI_TXB_CTL); | 554 | I915_WRITE(_FDI_TXB_CTL, dev_priv->saveFDI_TXB_CTL); |
556 | 555 | ||
557 | I915_WRITE(PFB_CTL_1, dev_priv->savePFB_CTL_1); | 556 | I915_WRITE(_PFB_CTL_1, dev_priv->savePFB_CTL_1); |
558 | I915_WRITE(PFB_WIN_SZ, dev_priv->savePFB_WIN_SZ); | 557 | I915_WRITE(_PFB_WIN_SZ, dev_priv->savePFB_WIN_SZ); |
559 | I915_WRITE(PFB_WIN_POS, dev_priv->savePFB_WIN_POS); | 558 | I915_WRITE(_PFB_WIN_POS, dev_priv->savePFB_WIN_POS); |
560 | 559 | ||
561 | I915_WRITE(TRANSBCONF, dev_priv->saveTRANSBCONF); | 560 | I915_WRITE(_TRANSBCONF, dev_priv->saveTRANSBCONF); |
562 | I915_WRITE(TRANS_HTOTAL_B, dev_priv->saveTRANS_HTOTAL_B); | 561 | I915_WRITE(_TRANS_HTOTAL_B, dev_priv->saveTRANS_HTOTAL_B); |
563 | I915_WRITE(TRANS_HBLANK_B, dev_priv->saveTRANS_HBLANK_B); | 562 | I915_WRITE(_TRANS_HBLANK_B, dev_priv->saveTRANS_HBLANK_B); |
564 | I915_WRITE(TRANS_HSYNC_B, dev_priv->saveTRANS_HSYNC_B); | 563 | I915_WRITE(_TRANS_HSYNC_B, dev_priv->saveTRANS_HSYNC_B); |
565 | I915_WRITE(TRANS_VTOTAL_B, dev_priv->saveTRANS_VTOTAL_B); | 564 | I915_WRITE(_TRANS_VTOTAL_B, dev_priv->saveTRANS_VTOTAL_B); |
566 | I915_WRITE(TRANS_VBLANK_B, dev_priv->saveTRANS_VBLANK_B); | 565 | I915_WRITE(_TRANS_VBLANK_B, dev_priv->saveTRANS_VBLANK_B); |
567 | I915_WRITE(TRANS_VSYNC_B, dev_priv->saveTRANS_VSYNC_B); | 566 | I915_WRITE(_TRANS_VSYNC_B, dev_priv->saveTRANS_VSYNC_B); |
568 | } | 567 | } |
569 | 568 | ||
570 | /* Restore plane info */ | 569 | /* Restore plane info */ |
571 | I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE); | 570 | I915_WRITE(_DSPBSIZE, dev_priv->saveDSPBSIZE); |
572 | I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS); | 571 | I915_WRITE(_DSPBPOS, dev_priv->saveDSPBPOS); |
573 | I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC); | 572 | I915_WRITE(_PIPEBSRC, dev_priv->savePIPEBSRC); |
574 | I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR); | 573 | I915_WRITE(_DSPBADDR, dev_priv->saveDSPBADDR); |
575 | I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE); | 574 | I915_WRITE(_DSPBSTRIDE, dev_priv->saveDSPBSTRIDE); |
576 | if (INTEL_INFO(dev)->gen >= 4) { | 575 | if (INTEL_INFO(dev)->gen >= 4) { |
577 | I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF); | 576 | I915_WRITE(_DSPBSURF, dev_priv->saveDSPBSURF); |
578 | I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF); | 577 | I915_WRITE(_DSPBTILEOFF, dev_priv->saveDSPBTILEOFF); |
579 | } | 578 | } |
580 | 579 | ||
581 | I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF); | 580 | I915_WRITE(_PIPEBCONF, dev_priv->savePIPEBCONF); |
582 | 581 | ||
583 | i915_restore_palette(dev, PIPE_B); | 582 | i915_restore_palette(dev, PIPE_B); |
584 | /* Enable the plane */ | 583 | /* Enable the plane */ |
585 | I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR); | 584 | I915_WRITE(_DSPBCNTR, dev_priv->saveDSPBCNTR); |
586 | I915_WRITE(DSPBADDR, I915_READ(DSPBADDR)); | 585 | I915_WRITE(_DSPBADDR, I915_READ(_DSPBADDR)); |
587 | 586 | ||
588 | /* Cursor state */ | 587 | /* Cursor state */ |
589 | I915_WRITE(CURAPOS, dev_priv->saveCURAPOS); | 588 | I915_WRITE(_CURAPOS, dev_priv->saveCURAPOS); |
590 | I915_WRITE(CURACNTR, dev_priv->saveCURACNTR); | 589 | I915_WRITE(_CURACNTR, dev_priv->saveCURACNTR); |
591 | I915_WRITE(CURABASE, dev_priv->saveCURABASE); | 590 | I915_WRITE(_CURABASE, dev_priv->saveCURABASE); |
592 | I915_WRITE(CURBPOS, dev_priv->saveCURBPOS); | 591 | I915_WRITE(_CURBPOS, dev_priv->saveCURBPOS); |
593 | I915_WRITE(CURBCNTR, dev_priv->saveCURBCNTR); | 592 | I915_WRITE(_CURBCNTR, dev_priv->saveCURBCNTR); |
594 | I915_WRITE(CURBBASE, dev_priv->saveCURBBASE); | 593 | I915_WRITE(_CURBBASE, dev_priv->saveCURBBASE); |
595 | if (IS_GEN2(dev)) | 594 | if (IS_GEN2(dev)) |
596 | I915_WRITE(CURSIZE, dev_priv->saveCURSIZE); | 595 | I915_WRITE(CURSIZE, dev_priv->saveCURSIZE); |
597 | 596 | ||
@@ -653,14 +652,14 @@ void i915_save_display(struct drm_device *dev) | |||
653 | dev_priv->saveDP_B = I915_READ(DP_B); | 652 | dev_priv->saveDP_B = I915_READ(DP_B); |
654 | dev_priv->saveDP_C = I915_READ(DP_C); | 653 | dev_priv->saveDP_C = I915_READ(DP_C); |
655 | dev_priv->saveDP_D = I915_READ(DP_D); | 654 | dev_priv->saveDP_D = I915_READ(DP_D); |
656 | dev_priv->savePIPEA_GMCH_DATA_M = I915_READ(PIPEA_GMCH_DATA_M); | 655 | dev_priv->savePIPEA_GMCH_DATA_M = I915_READ(_PIPEA_GMCH_DATA_M); |
657 | dev_priv->savePIPEB_GMCH_DATA_M = I915_READ(PIPEB_GMCH_DATA_M); | 656 | dev_priv->savePIPEB_GMCH_DATA_M = I915_READ(_PIPEB_GMCH_DATA_M); |
658 | dev_priv->savePIPEA_GMCH_DATA_N = I915_READ(PIPEA_GMCH_DATA_N); | 657 | dev_priv->savePIPEA_GMCH_DATA_N = I915_READ(_PIPEA_GMCH_DATA_N); |
659 | dev_priv->savePIPEB_GMCH_DATA_N = I915_READ(PIPEB_GMCH_DATA_N); | 658 | dev_priv->savePIPEB_GMCH_DATA_N = I915_READ(_PIPEB_GMCH_DATA_N); |
660 | dev_priv->savePIPEA_DP_LINK_M = I915_READ(PIPEA_DP_LINK_M); | 659 | dev_priv->savePIPEA_DP_LINK_M = I915_READ(_PIPEA_DP_LINK_M); |
661 | dev_priv->savePIPEB_DP_LINK_M = I915_READ(PIPEB_DP_LINK_M); | 660 | dev_priv->savePIPEB_DP_LINK_M = I915_READ(_PIPEB_DP_LINK_M); |
662 | dev_priv->savePIPEA_DP_LINK_N = I915_READ(PIPEA_DP_LINK_N); | 661 | dev_priv->savePIPEA_DP_LINK_N = I915_READ(_PIPEA_DP_LINK_N); |
663 | dev_priv->savePIPEB_DP_LINK_N = I915_READ(PIPEB_DP_LINK_N); | 662 | dev_priv->savePIPEB_DP_LINK_N = I915_READ(_PIPEB_DP_LINK_N); |
664 | } | 663 | } |
665 | /* FIXME: save TV & SDVO state */ | 664 | /* FIXME: save TV & SDVO state */ |
666 | 665 | ||
@@ -699,14 +698,14 @@ void i915_restore_display(struct drm_device *dev) | |||
699 | 698 | ||
700 | /* Display port ratios (must be done before clock is set) */ | 699 | /* Display port ratios (must be done before clock is set) */ |
701 | if (SUPPORTS_INTEGRATED_DP(dev)) { | 700 | if (SUPPORTS_INTEGRATED_DP(dev)) { |
702 | I915_WRITE(PIPEA_GMCH_DATA_M, dev_priv->savePIPEA_GMCH_DATA_M); | 701 | I915_WRITE(_PIPEA_GMCH_DATA_M, dev_priv->savePIPEA_GMCH_DATA_M); |
703 | I915_WRITE(PIPEB_GMCH_DATA_M, dev_priv->savePIPEB_GMCH_DATA_M); | 702 | I915_WRITE(_PIPEB_GMCH_DATA_M, dev_priv->savePIPEB_GMCH_DATA_M); |
704 | I915_WRITE(PIPEA_GMCH_DATA_N, dev_priv->savePIPEA_GMCH_DATA_N); | 703 | I915_WRITE(_PIPEA_GMCH_DATA_N, dev_priv->savePIPEA_GMCH_DATA_N); |
705 | I915_WRITE(PIPEB_GMCH_DATA_N, dev_priv->savePIPEB_GMCH_DATA_N); | 704 | I915_WRITE(_PIPEB_GMCH_DATA_N, dev_priv->savePIPEB_GMCH_DATA_N); |
706 | I915_WRITE(PIPEA_DP_LINK_M, dev_priv->savePIPEA_DP_LINK_M); | 705 | I915_WRITE(_PIPEA_DP_LINK_M, dev_priv->savePIPEA_DP_LINK_M); |
707 | I915_WRITE(PIPEB_DP_LINK_M, dev_priv->savePIPEB_DP_LINK_M); | 706 | I915_WRITE(_PIPEB_DP_LINK_M, dev_priv->savePIPEB_DP_LINK_M); |
708 | I915_WRITE(PIPEA_DP_LINK_N, dev_priv->savePIPEA_DP_LINK_N); | 707 | I915_WRITE(_PIPEA_DP_LINK_N, dev_priv->savePIPEA_DP_LINK_N); |
709 | I915_WRITE(PIPEB_DP_LINK_N, dev_priv->savePIPEB_DP_LINK_N); | 708 | I915_WRITE(_PIPEB_DP_LINK_N, dev_priv->savePIPEB_DP_LINK_N); |
710 | } | 709 | } |
711 | 710 | ||
712 | /* This is only meaningful in non-KMS mode */ | 711 | /* This is only meaningful in non-KMS mode */ |
@@ -797,9 +796,6 @@ int i915_save_state(struct drm_device *dev) | |||
797 | 796 | ||
798 | pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB); | 797 | pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB); |
799 | 798 | ||
800 | /* Hardware status page */ | ||
801 | dev_priv->saveHWS = I915_READ(HWS_PGA); | ||
802 | |||
803 | i915_save_display(dev); | 799 | i915_save_display(dev); |
804 | 800 | ||
805 | /* Interrupt state */ | 801 | /* Interrupt state */ |
@@ -808,8 +804,8 @@ int i915_save_state(struct drm_device *dev) | |||
808 | dev_priv->saveDEIMR = I915_READ(DEIMR); | 804 | dev_priv->saveDEIMR = I915_READ(DEIMR); |
809 | dev_priv->saveGTIER = I915_READ(GTIER); | 805 | dev_priv->saveGTIER = I915_READ(GTIER); |
810 | dev_priv->saveGTIMR = I915_READ(GTIMR); | 806 | dev_priv->saveGTIMR = I915_READ(GTIMR); |
811 | dev_priv->saveFDI_RXA_IMR = I915_READ(FDI_RXA_IMR); | 807 | dev_priv->saveFDI_RXA_IMR = I915_READ(_FDI_RXA_IMR); |
812 | dev_priv->saveFDI_RXB_IMR = I915_READ(FDI_RXB_IMR); | 808 | dev_priv->saveFDI_RXB_IMR = I915_READ(_FDI_RXB_IMR); |
813 | dev_priv->saveMCHBAR_RENDER_STANDBY = | 809 | dev_priv->saveMCHBAR_RENDER_STANDBY = |
814 | I915_READ(RSTDBYCTL); | 810 | I915_READ(RSTDBYCTL); |
815 | } else { | 811 | } else { |
@@ -846,9 +842,6 @@ int i915_restore_state(struct drm_device *dev) | |||
846 | 842 | ||
847 | pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB); | 843 | pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB); |
848 | 844 | ||
849 | /* Hardware status page */ | ||
850 | I915_WRITE(HWS_PGA, dev_priv->saveHWS); | ||
851 | |||
852 | i915_restore_display(dev); | 845 | i915_restore_display(dev); |
853 | 846 | ||
854 | /* Interrupt state */ | 847 | /* Interrupt state */ |
@@ -857,11 +850,11 @@ int i915_restore_state(struct drm_device *dev) | |||
857 | I915_WRITE(DEIMR, dev_priv->saveDEIMR); | 850 | I915_WRITE(DEIMR, dev_priv->saveDEIMR); |
858 | I915_WRITE(GTIER, dev_priv->saveGTIER); | 851 | I915_WRITE(GTIER, dev_priv->saveGTIER); |
859 | I915_WRITE(GTIMR, dev_priv->saveGTIMR); | 852 | I915_WRITE(GTIMR, dev_priv->saveGTIMR); |
860 | I915_WRITE(FDI_RXA_IMR, dev_priv->saveFDI_RXA_IMR); | 853 | I915_WRITE(_FDI_RXA_IMR, dev_priv->saveFDI_RXA_IMR); |
861 | I915_WRITE(FDI_RXB_IMR, dev_priv->saveFDI_RXB_IMR); | 854 | I915_WRITE(_FDI_RXB_IMR, dev_priv->saveFDI_RXB_IMR); |
862 | } else { | 855 | } else { |
863 | I915_WRITE (IER, dev_priv->saveIER); | 856 | I915_WRITE(IER, dev_priv->saveIER); |
864 | I915_WRITE (IMR, dev_priv->saveIMR); | 857 | I915_WRITE(IMR, dev_priv->saveIMR); |
865 | } | 858 | } |
866 | 859 | ||
867 | /* Clock gating state */ | 860 | /* Clock gating state */ |
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index 7f0fc3ed61a..d623fefbfac 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h | |||
@@ -7,6 +7,7 @@ | |||
7 | 7 | ||
8 | #include <drm/drmP.h> | 8 | #include <drm/drmP.h> |
9 | #include "i915_drv.h" | 9 | #include "i915_drv.h" |
10 | #include "intel_ringbuffer.h" | ||
10 | 11 | ||
11 | #undef TRACE_SYSTEM | 12 | #undef TRACE_SYSTEM |
12 | #define TRACE_SYSTEM i915 | 13 | #define TRACE_SYSTEM i915 |
@@ -16,9 +17,7 @@ | |||
16 | /* object tracking */ | 17 | /* object tracking */ |
17 | 18 | ||
18 | TRACE_EVENT(i915_gem_object_create, | 19 | TRACE_EVENT(i915_gem_object_create, |
19 | |||
20 | TP_PROTO(struct drm_i915_gem_object *obj), | 20 | TP_PROTO(struct drm_i915_gem_object *obj), |
21 | |||
22 | TP_ARGS(obj), | 21 | TP_ARGS(obj), |
23 | 22 | ||
24 | TP_STRUCT__entry( | 23 | TP_STRUCT__entry( |
@@ -35,33 +34,51 @@ TRACE_EVENT(i915_gem_object_create, | |||
35 | ); | 34 | ); |
36 | 35 | ||
37 | TRACE_EVENT(i915_gem_object_bind, | 36 | TRACE_EVENT(i915_gem_object_bind, |
38 | 37 | TP_PROTO(struct drm_i915_gem_object *obj, bool mappable), | |
39 | TP_PROTO(struct drm_i915_gem_object *obj, u32 gtt_offset, bool mappable), | 38 | TP_ARGS(obj, mappable), |
40 | |||
41 | TP_ARGS(obj, gtt_offset, mappable), | ||
42 | 39 | ||
43 | TP_STRUCT__entry( | 40 | TP_STRUCT__entry( |
44 | __field(struct drm_i915_gem_object *, obj) | 41 | __field(struct drm_i915_gem_object *, obj) |
45 | __field(u32, gtt_offset) | 42 | __field(u32, offset) |
43 | __field(u32, size) | ||
46 | __field(bool, mappable) | 44 | __field(bool, mappable) |
47 | ), | 45 | ), |
48 | 46 | ||
49 | TP_fast_assign( | 47 | TP_fast_assign( |
50 | __entry->obj = obj; | 48 | __entry->obj = obj; |
51 | __entry->gtt_offset = gtt_offset; | 49 | __entry->offset = obj->gtt_space->start; |
50 | __entry->size = obj->gtt_space->size; | ||
52 | __entry->mappable = mappable; | 51 | __entry->mappable = mappable; |
53 | ), | 52 | ), |
54 | 53 | ||
55 | TP_printk("obj=%p, gtt_offset=%08x%s", | 54 | TP_printk("obj=%p, offset=%08x size=%x%s", |
56 | __entry->obj, __entry->gtt_offset, | 55 | __entry->obj, __entry->offset, __entry->size, |
57 | __entry->mappable ? ", mappable" : "") | 56 | __entry->mappable ? ", mappable" : "") |
58 | ); | 57 | ); |
59 | 58 | ||
60 | TRACE_EVENT(i915_gem_object_change_domain, | 59 | TRACE_EVENT(i915_gem_object_unbind, |
60 | TP_PROTO(struct drm_i915_gem_object *obj), | ||
61 | TP_ARGS(obj), | ||
62 | |||
63 | TP_STRUCT__entry( | ||
64 | __field(struct drm_i915_gem_object *, obj) | ||
65 | __field(u32, offset) | ||
66 | __field(u32, size) | ||
67 | ), | ||
61 | 68 | ||
62 | TP_PROTO(struct drm_i915_gem_object *obj, uint32_t old_read_domains, uint32_t old_write_domain), | 69 | TP_fast_assign( |
70 | __entry->obj = obj; | ||
71 | __entry->offset = obj->gtt_space->start; | ||
72 | __entry->size = obj->gtt_space->size; | ||
73 | ), | ||
63 | 74 | ||
64 | TP_ARGS(obj, old_read_domains, old_write_domain), | 75 | TP_printk("obj=%p, offset=%08x size=%x", |
76 | __entry->obj, __entry->offset, __entry->size) | ||
77 | ); | ||
78 | |||
79 | TRACE_EVENT(i915_gem_object_change_domain, | ||
80 | TP_PROTO(struct drm_i915_gem_object *obj, u32 old_read, u32 old_write), | ||
81 | TP_ARGS(obj, old_read, old_write), | ||
65 | 82 | ||
66 | TP_STRUCT__entry( | 83 | TP_STRUCT__entry( |
67 | __field(struct drm_i915_gem_object *, obj) | 84 | __field(struct drm_i915_gem_object *, obj) |
@@ -71,177 +88,264 @@ TRACE_EVENT(i915_gem_object_change_domain, | |||
71 | 88 | ||
72 | TP_fast_assign( | 89 | TP_fast_assign( |
73 | __entry->obj = obj; | 90 | __entry->obj = obj; |
74 | __entry->read_domains = obj->base.read_domains | (old_read_domains << 16); | 91 | __entry->read_domains = obj->base.read_domains | (old_read << 16); |
75 | __entry->write_domain = obj->base.write_domain | (old_write_domain << 16); | 92 | __entry->write_domain = obj->base.write_domain | (old_write << 16); |
76 | ), | 93 | ), |
77 | 94 | ||
78 | TP_printk("obj=%p, read=%04x, write=%04x", | 95 | TP_printk("obj=%p, read=%02x=>%02x, write=%02x=>%02x", |
79 | __entry->obj, | 96 | __entry->obj, |
80 | __entry->read_domains, __entry->write_domain) | 97 | __entry->read_domains >> 16, |
98 | __entry->read_domains & 0xffff, | ||
99 | __entry->write_domain >> 16, | ||
100 | __entry->write_domain & 0xffff) | ||
81 | ); | 101 | ); |
82 | 102 | ||
83 | DECLARE_EVENT_CLASS(i915_gem_object, | 103 | TRACE_EVENT(i915_gem_object_pwrite, |
104 | TP_PROTO(struct drm_i915_gem_object *obj, u32 offset, u32 len), | ||
105 | TP_ARGS(obj, offset, len), | ||
84 | 106 | ||
85 | TP_PROTO(struct drm_i915_gem_object *obj), | 107 | TP_STRUCT__entry( |
108 | __field(struct drm_i915_gem_object *, obj) | ||
109 | __field(u32, offset) | ||
110 | __field(u32, len) | ||
111 | ), | ||
86 | 112 | ||
87 | TP_ARGS(obj), | 113 | TP_fast_assign( |
114 | __entry->obj = obj; | ||
115 | __entry->offset = offset; | ||
116 | __entry->len = len; | ||
117 | ), | ||
118 | |||
119 | TP_printk("obj=%p, offset=%u, len=%u", | ||
120 | __entry->obj, __entry->offset, __entry->len) | ||
121 | ); | ||
122 | |||
123 | TRACE_EVENT(i915_gem_object_pread, | ||
124 | TP_PROTO(struct drm_i915_gem_object *obj, u32 offset, u32 len), | ||
125 | TP_ARGS(obj, offset, len), | ||
88 | 126 | ||
89 | TP_STRUCT__entry( | 127 | TP_STRUCT__entry( |
90 | __field(struct drm_i915_gem_object *, obj) | 128 | __field(struct drm_i915_gem_object *, obj) |
129 | __field(u32, offset) | ||
130 | __field(u32, len) | ||
91 | ), | 131 | ), |
92 | 132 | ||
93 | TP_fast_assign( | 133 | TP_fast_assign( |
94 | __entry->obj = obj; | 134 | __entry->obj = obj; |
135 | __entry->offset = offset; | ||
136 | __entry->len = len; | ||
95 | ), | 137 | ), |
96 | 138 | ||
97 | TP_printk("obj=%p", __entry->obj) | 139 | TP_printk("obj=%p, offset=%u, len=%u", |
140 | __entry->obj, __entry->offset, __entry->len) | ||
98 | ); | 141 | ); |
99 | 142 | ||
100 | DEFINE_EVENT(i915_gem_object, i915_gem_object_clflush, | 143 | TRACE_EVENT(i915_gem_object_fault, |
144 | TP_PROTO(struct drm_i915_gem_object *obj, u32 index, bool gtt, bool write), | ||
145 | TP_ARGS(obj, index, gtt, write), | ||
146 | |||
147 | TP_STRUCT__entry( | ||
148 | __field(struct drm_i915_gem_object *, obj) | ||
149 | __field(u32, index) | ||
150 | __field(bool, gtt) | ||
151 | __field(bool, write) | ||
152 | ), | ||
153 | |||
154 | TP_fast_assign( | ||
155 | __entry->obj = obj; | ||
156 | __entry->index = index; | ||
157 | __entry->gtt = gtt; | ||
158 | __entry->write = write; | ||
159 | ), | ||
101 | 160 | ||
161 | TP_printk("obj=%p, %s index=%u %s", | ||
162 | __entry->obj, | ||
163 | __entry->gtt ? "GTT" : "CPU", | ||
164 | __entry->index, | ||
165 | __entry->write ? ", writable" : "") | ||
166 | ); | ||
167 | |||
168 | DECLARE_EVENT_CLASS(i915_gem_object, | ||
102 | TP_PROTO(struct drm_i915_gem_object *obj), | 169 | TP_PROTO(struct drm_i915_gem_object *obj), |
170 | TP_ARGS(obj), | ||
103 | 171 | ||
104 | TP_ARGS(obj) | 172 | TP_STRUCT__entry( |
173 | __field(struct drm_i915_gem_object *, obj) | ||
174 | ), | ||
175 | |||
176 | TP_fast_assign( | ||
177 | __entry->obj = obj; | ||
178 | ), | ||
179 | |||
180 | TP_printk("obj=%p", __entry->obj) | ||
105 | ); | 181 | ); |
106 | 182 | ||
107 | DEFINE_EVENT(i915_gem_object, i915_gem_object_unbind, | 183 | DEFINE_EVENT(i915_gem_object, i915_gem_object_clflush, |
184 | TP_PROTO(struct drm_i915_gem_object *obj), | ||
185 | TP_ARGS(obj) | ||
186 | ); | ||
108 | 187 | ||
188 | DEFINE_EVENT(i915_gem_object, i915_gem_object_destroy, | ||
109 | TP_PROTO(struct drm_i915_gem_object *obj), | 189 | TP_PROTO(struct drm_i915_gem_object *obj), |
110 | |||
111 | TP_ARGS(obj) | 190 | TP_ARGS(obj) |
112 | ); | 191 | ); |
113 | 192 | ||
114 | DEFINE_EVENT(i915_gem_object, i915_gem_object_destroy, | 193 | TRACE_EVENT(i915_gem_evict, |
194 | TP_PROTO(struct drm_device *dev, u32 size, u32 align, bool mappable), | ||
195 | TP_ARGS(dev, size, align, mappable), | ||
115 | 196 | ||
116 | TP_PROTO(struct drm_i915_gem_object *obj), | 197 | TP_STRUCT__entry( |
198 | __field(u32, dev) | ||
199 | __field(u32, size) | ||
200 | __field(u32, align) | ||
201 | __field(bool, mappable) | ||
202 | ), | ||
117 | 203 | ||
118 | TP_ARGS(obj) | 204 | TP_fast_assign( |
205 | __entry->dev = dev->primary->index; | ||
206 | __entry->size = size; | ||
207 | __entry->align = align; | ||
208 | __entry->mappable = mappable; | ||
209 | ), | ||
210 | |||
211 | TP_printk("dev=%d, size=%d, align=%d %s", | ||
212 | __entry->dev, __entry->size, __entry->align, | ||
213 | __entry->mappable ? ", mappable" : "") | ||
119 | ); | 214 | ); |
120 | 215 | ||
121 | /* batch tracing */ | 216 | TRACE_EVENT(i915_gem_evict_everything, |
217 | TP_PROTO(struct drm_device *dev, bool purgeable), | ||
218 | TP_ARGS(dev, purgeable), | ||
122 | 219 | ||
123 | TRACE_EVENT(i915_gem_request_submit, | 220 | TP_STRUCT__entry( |
221 | __field(u32, dev) | ||
222 | __field(bool, purgeable) | ||
223 | ), | ||
224 | |||
225 | TP_fast_assign( | ||
226 | __entry->dev = dev->primary->index; | ||
227 | __entry->purgeable = purgeable; | ||
228 | ), | ||
124 | 229 | ||
125 | TP_PROTO(struct drm_device *dev, u32 seqno), | 230 | TP_printk("dev=%d%s", |
231 | __entry->dev, | ||
232 | __entry->purgeable ? ", purgeable only" : "") | ||
233 | ); | ||
126 | 234 | ||
127 | TP_ARGS(dev, seqno), | 235 | TRACE_EVENT(i915_gem_ring_dispatch, |
236 | TP_PROTO(struct intel_ring_buffer *ring, u32 seqno), | ||
237 | TP_ARGS(ring, seqno), | ||
128 | 238 | ||
129 | TP_STRUCT__entry( | 239 | TP_STRUCT__entry( |
130 | __field(u32, dev) | 240 | __field(u32, dev) |
241 | __field(u32, ring) | ||
131 | __field(u32, seqno) | 242 | __field(u32, seqno) |
132 | ), | 243 | ), |
133 | 244 | ||
134 | TP_fast_assign( | 245 | TP_fast_assign( |
135 | __entry->dev = dev->primary->index; | 246 | __entry->dev = ring->dev->primary->index; |
247 | __entry->ring = ring->id; | ||
136 | __entry->seqno = seqno; | 248 | __entry->seqno = seqno; |
137 | i915_trace_irq_get(dev, seqno); | 249 | i915_trace_irq_get(ring, seqno); |
138 | ), | 250 | ), |
139 | 251 | ||
140 | TP_printk("dev=%u, seqno=%u", __entry->dev, __entry->seqno) | 252 | TP_printk("dev=%u, ring=%u, seqno=%u", |
253 | __entry->dev, __entry->ring, __entry->seqno) | ||
141 | ); | 254 | ); |
142 | 255 | ||
143 | TRACE_EVENT(i915_gem_request_flush, | 256 | TRACE_EVENT(i915_gem_ring_flush, |
144 | 257 | TP_PROTO(struct intel_ring_buffer *ring, u32 invalidate, u32 flush), | |
145 | TP_PROTO(struct drm_device *dev, u32 seqno, | 258 | TP_ARGS(ring, invalidate, flush), |
146 | u32 flush_domains, u32 invalidate_domains), | ||
147 | |||
148 | TP_ARGS(dev, seqno, flush_domains, invalidate_domains), | ||
149 | 259 | ||
150 | TP_STRUCT__entry( | 260 | TP_STRUCT__entry( |
151 | __field(u32, dev) | 261 | __field(u32, dev) |
152 | __field(u32, seqno) | 262 | __field(u32, ring) |
153 | __field(u32, flush_domains) | 263 | __field(u32, invalidate) |
154 | __field(u32, invalidate_domains) | 264 | __field(u32, flush) |
155 | ), | 265 | ), |
156 | 266 | ||
157 | TP_fast_assign( | 267 | TP_fast_assign( |
158 | __entry->dev = dev->primary->index; | 268 | __entry->dev = ring->dev->primary->index; |
159 | __entry->seqno = seqno; | 269 | __entry->ring = ring->id; |
160 | __entry->flush_domains = flush_domains; | 270 | __entry->invalidate = invalidate; |
161 | __entry->invalidate_domains = invalidate_domains; | 271 | __entry->flush = flush; |
162 | ), | 272 | ), |
163 | 273 | ||
164 | TP_printk("dev=%u, seqno=%u, flush=%04x, invalidate=%04x", | 274 | TP_printk("dev=%u, ring=%x, invalidate=%04x, flush=%04x", |
165 | __entry->dev, __entry->seqno, | 275 | __entry->dev, __entry->ring, |
166 | __entry->flush_domains, __entry->invalidate_domains) | 276 | __entry->invalidate, __entry->flush) |
167 | ); | 277 | ); |
168 | 278 | ||
169 | DECLARE_EVENT_CLASS(i915_gem_request, | 279 | DECLARE_EVENT_CLASS(i915_gem_request, |
170 | 280 | TP_PROTO(struct intel_ring_buffer *ring, u32 seqno), | |
171 | TP_PROTO(struct drm_device *dev, u32 seqno), | 281 | TP_ARGS(ring, seqno), |
172 | |||
173 | TP_ARGS(dev, seqno), | ||
174 | 282 | ||
175 | TP_STRUCT__entry( | 283 | TP_STRUCT__entry( |
176 | __field(u32, dev) | 284 | __field(u32, dev) |
285 | __field(u32, ring) | ||
177 | __field(u32, seqno) | 286 | __field(u32, seqno) |
178 | ), | 287 | ), |
179 | 288 | ||
180 | TP_fast_assign( | 289 | TP_fast_assign( |
181 | __entry->dev = dev->primary->index; | 290 | __entry->dev = ring->dev->primary->index; |
291 | __entry->ring = ring->id; | ||
182 | __entry->seqno = seqno; | 292 | __entry->seqno = seqno; |
183 | ), | 293 | ), |
184 | 294 | ||
185 | TP_printk("dev=%u, seqno=%u", __entry->dev, __entry->seqno) | 295 | TP_printk("dev=%u, ring=%u, seqno=%u", |
296 | __entry->dev, __entry->ring, __entry->seqno) | ||
186 | ); | 297 | ); |
187 | 298 | ||
188 | DEFINE_EVENT(i915_gem_request, i915_gem_request_complete, | 299 | DEFINE_EVENT(i915_gem_request, i915_gem_request_add, |
189 | 300 | TP_PROTO(struct intel_ring_buffer *ring, u32 seqno), | |
190 | TP_PROTO(struct drm_device *dev, u32 seqno), | 301 | TP_ARGS(ring, seqno) |
302 | ); | ||
191 | 303 | ||
192 | TP_ARGS(dev, seqno) | 304 | DEFINE_EVENT(i915_gem_request, i915_gem_request_complete, |
305 | TP_PROTO(struct intel_ring_buffer *ring, u32 seqno), | ||
306 | TP_ARGS(ring, seqno) | ||
193 | ); | 307 | ); |
194 | 308 | ||
195 | DEFINE_EVENT(i915_gem_request, i915_gem_request_retire, | 309 | DEFINE_EVENT(i915_gem_request, i915_gem_request_retire, |
196 | 310 | TP_PROTO(struct intel_ring_buffer *ring, u32 seqno), | |
197 | TP_PROTO(struct drm_device *dev, u32 seqno), | 311 | TP_ARGS(ring, seqno) |
198 | |||
199 | TP_ARGS(dev, seqno) | ||
200 | ); | 312 | ); |
201 | 313 | ||
202 | DEFINE_EVENT(i915_gem_request, i915_gem_request_wait_begin, | 314 | DEFINE_EVENT(i915_gem_request, i915_gem_request_wait_begin, |
203 | 315 | TP_PROTO(struct intel_ring_buffer *ring, u32 seqno), | |
204 | TP_PROTO(struct drm_device *dev, u32 seqno), | 316 | TP_ARGS(ring, seqno) |
205 | |||
206 | TP_ARGS(dev, seqno) | ||
207 | ); | 317 | ); |
208 | 318 | ||
209 | DEFINE_EVENT(i915_gem_request, i915_gem_request_wait_end, | 319 | DEFINE_EVENT(i915_gem_request, i915_gem_request_wait_end, |
210 | 320 | TP_PROTO(struct intel_ring_buffer *ring, u32 seqno), | |
211 | TP_PROTO(struct drm_device *dev, u32 seqno), | 321 | TP_ARGS(ring, seqno) |
212 | |||
213 | TP_ARGS(dev, seqno) | ||
214 | ); | 322 | ); |
215 | 323 | ||
216 | DECLARE_EVENT_CLASS(i915_ring, | 324 | DECLARE_EVENT_CLASS(i915_ring, |
217 | 325 | TP_PROTO(struct intel_ring_buffer *ring), | |
218 | TP_PROTO(struct drm_device *dev), | 326 | TP_ARGS(ring), |
219 | |||
220 | TP_ARGS(dev), | ||
221 | 327 | ||
222 | TP_STRUCT__entry( | 328 | TP_STRUCT__entry( |
223 | __field(u32, dev) | 329 | __field(u32, dev) |
330 | __field(u32, ring) | ||
224 | ), | 331 | ), |
225 | 332 | ||
226 | TP_fast_assign( | 333 | TP_fast_assign( |
227 | __entry->dev = dev->primary->index; | 334 | __entry->dev = ring->dev->primary->index; |
335 | __entry->ring = ring->id; | ||
228 | ), | 336 | ), |
229 | 337 | ||
230 | TP_printk("dev=%u", __entry->dev) | 338 | TP_printk("dev=%u, ring=%u", __entry->dev, __entry->ring) |
231 | ); | 339 | ); |
232 | 340 | ||
233 | DEFINE_EVENT(i915_ring, i915_ring_wait_begin, | 341 | DEFINE_EVENT(i915_ring, i915_ring_wait_begin, |
234 | 342 | TP_PROTO(struct intel_ring_buffer *ring), | |
235 | TP_PROTO(struct drm_device *dev), | 343 | TP_ARGS(ring) |
236 | |||
237 | TP_ARGS(dev) | ||
238 | ); | 344 | ); |
239 | 345 | ||
240 | DEFINE_EVENT(i915_ring, i915_ring_wait_end, | 346 | DEFINE_EVENT(i915_ring, i915_ring_wait_end, |
241 | 347 | TP_PROTO(struct intel_ring_buffer *ring), | |
242 | TP_PROTO(struct drm_device *dev), | 348 | TP_ARGS(ring) |
243 | |||
244 | TP_ARGS(dev) | ||
245 | ); | 349 | ); |
246 | 350 | ||
247 | TRACE_EVENT(i915_flip_request, | 351 | TRACE_EVENT(i915_flip_request, |
@@ -281,26 +385,29 @@ TRACE_EVENT(i915_flip_complete, | |||
281 | ); | 385 | ); |
282 | 386 | ||
283 | TRACE_EVENT(i915_reg_rw, | 387 | TRACE_EVENT(i915_reg_rw, |
284 | TP_PROTO(int cmd, uint32_t reg, uint64_t val, int len), | 388 | TP_PROTO(bool write, u32 reg, u64 val, int len), |
285 | 389 | ||
286 | TP_ARGS(cmd, reg, val, len), | 390 | TP_ARGS(write, reg, val, len), |
287 | 391 | ||
288 | TP_STRUCT__entry( | 392 | TP_STRUCT__entry( |
289 | __field(int, cmd) | 393 | __field(u64, val) |
290 | __field(uint32_t, reg) | 394 | __field(u32, reg) |
291 | __field(uint64_t, val) | 395 | __field(u16, write) |
292 | __field(int, len) | 396 | __field(u16, len) |
293 | ), | 397 | ), |
294 | 398 | ||
295 | TP_fast_assign( | 399 | TP_fast_assign( |
296 | __entry->cmd = cmd; | 400 | __entry->val = (u64)val; |
297 | __entry->reg = reg; | 401 | __entry->reg = reg; |
298 | __entry->val = (uint64_t)val; | 402 | __entry->write = write; |
299 | __entry->len = len; | 403 | __entry->len = len; |
300 | ), | 404 | ), |
301 | 405 | ||
302 | TP_printk("cmd=%c, reg=0x%x, val=0x%llx, len=%d", | 406 | TP_printk("%s reg=0x%x, len=%d, val=(0x%x, 0x%x)", |
303 | __entry->cmd, __entry->reg, __entry->val, __entry->len) | 407 | __entry->write ? "write" : "read", |
408 | __entry->reg, __entry->len, | ||
409 | (u32)(__entry->val & 0xffffffff), | ||
410 | (u32)(__entry->val >> 32)) | ||
304 | ); | 411 | ); |
305 | 412 | ||
306 | #endif /* _I915_TRACE_H_ */ | 413 | #endif /* _I915_TRACE_H_ */ |
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 0b44956c336..fb5b4d426ae 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c | |||
@@ -226,29 +226,49 @@ static void | |||
226 | parse_sdvo_panel_data(struct drm_i915_private *dev_priv, | 226 | parse_sdvo_panel_data(struct drm_i915_private *dev_priv, |
227 | struct bdb_header *bdb) | 227 | struct bdb_header *bdb) |
228 | { | 228 | { |
229 | struct bdb_sdvo_lvds_options *sdvo_lvds_options; | ||
230 | struct lvds_dvo_timing *dvo_timing; | 229 | struct lvds_dvo_timing *dvo_timing; |
231 | struct drm_display_mode *panel_fixed_mode; | 230 | struct drm_display_mode *panel_fixed_mode; |
231 | int index; | ||
232 | 232 | ||
233 | sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS); | 233 | index = i915_vbt_sdvo_panel_type; |
234 | if (!sdvo_lvds_options) | 234 | if (index == -1) { |
235 | return; | 235 | struct bdb_sdvo_lvds_options *sdvo_lvds_options; |
236 | |||
237 | sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS); | ||
238 | if (!sdvo_lvds_options) | ||
239 | return; | ||
240 | |||
241 | index = sdvo_lvds_options->panel_type; | ||
242 | } | ||
236 | 243 | ||
237 | dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS); | 244 | dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS); |
238 | if (!dvo_timing) | 245 | if (!dvo_timing) |
239 | return; | 246 | return; |
240 | 247 | ||
241 | panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); | 248 | panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); |
242 | |||
243 | if (!panel_fixed_mode) | 249 | if (!panel_fixed_mode) |
244 | return; | 250 | return; |
245 | 251 | ||
246 | fill_detail_timing_data(panel_fixed_mode, | 252 | fill_detail_timing_data(panel_fixed_mode, dvo_timing + index); |
247 | dvo_timing + sdvo_lvds_options->panel_type); | ||
248 | 253 | ||
249 | dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode; | 254 | dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode; |
250 | 255 | ||
251 | return; | 256 | DRM_DEBUG_KMS("Found SDVO panel mode in BIOS VBT tables:\n"); |
257 | drm_mode_debug_printmodeline(panel_fixed_mode); | ||
258 | } | ||
259 | |||
260 | static int intel_bios_ssc_frequency(struct drm_device *dev, | ||
261 | bool alternate) | ||
262 | { | ||
263 | switch (INTEL_INFO(dev)->gen) { | ||
264 | case 2: | ||
265 | return alternate ? 66 : 48; | ||
266 | case 3: | ||
267 | case 4: | ||
268 | return alternate ? 100 : 96; | ||
269 | default: | ||
270 | return alternate ? 100 : 120; | ||
271 | } | ||
252 | } | 272 | } |
253 | 273 | ||
254 | static void | 274 | static void |
@@ -263,13 +283,8 @@ parse_general_features(struct drm_i915_private *dev_priv, | |||
263 | dev_priv->int_tv_support = general->int_tv_support; | 283 | dev_priv->int_tv_support = general->int_tv_support; |
264 | dev_priv->int_crt_support = general->int_crt_support; | 284 | dev_priv->int_crt_support = general->int_crt_support; |
265 | dev_priv->lvds_use_ssc = general->enable_ssc; | 285 | dev_priv->lvds_use_ssc = general->enable_ssc; |
266 | 286 | dev_priv->lvds_ssc_freq = | |
267 | if (IS_I85X(dev)) | 287 | intel_bios_ssc_frequency(dev, general->ssc_freq); |
268 | dev_priv->lvds_ssc_freq = general->ssc_freq ? 66 : 48; | ||
269 | else if (IS_GEN5(dev) || IS_GEN6(dev)) | ||
270 | dev_priv->lvds_ssc_freq = general->ssc_freq ? 100 : 120; | ||
271 | else | ||
272 | dev_priv->lvds_ssc_freq = general->ssc_freq ? 100 : 96; | ||
273 | } | 288 | } |
274 | } | 289 | } |
275 | 290 | ||
@@ -553,6 +568,8 @@ parse_device_mapping(struct drm_i915_private *dev_priv, | |||
553 | static void | 568 | static void |
554 | init_vbt_defaults(struct drm_i915_private *dev_priv) | 569 | init_vbt_defaults(struct drm_i915_private *dev_priv) |
555 | { | 570 | { |
571 | struct drm_device *dev = dev_priv->dev; | ||
572 | |||
556 | dev_priv->crt_ddc_pin = GMBUS_PORT_VGADDC; | 573 | dev_priv->crt_ddc_pin = GMBUS_PORT_VGADDC; |
557 | 574 | ||
558 | /* LFP panel data */ | 575 | /* LFP panel data */ |
@@ -565,7 +582,11 @@ init_vbt_defaults(struct drm_i915_private *dev_priv) | |||
565 | /* general features */ | 582 | /* general features */ |
566 | dev_priv->int_tv_support = 1; | 583 | dev_priv->int_tv_support = 1; |
567 | dev_priv->int_crt_support = 1; | 584 | dev_priv->int_crt_support = 1; |
568 | dev_priv->lvds_use_ssc = 0; | 585 | |
586 | /* Default to using SSC */ | ||
587 | dev_priv->lvds_use_ssc = 1; | ||
588 | dev_priv->lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1); | ||
589 | DRM_DEBUG("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq); | ||
569 | 590 | ||
570 | /* eDP data */ | 591 | /* eDP data */ |
571 | dev_priv->edp.bpp = 18; | 592 | dev_priv->edp.bpp = 18; |
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 8a77ff4a723..8342259f316 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c | |||
@@ -129,10 +129,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, | |||
129 | u32 adpa, dpll_md; | 129 | u32 adpa, dpll_md; |
130 | u32 adpa_reg; | 130 | u32 adpa_reg; |
131 | 131 | ||
132 | if (intel_crtc->pipe == 0) | 132 | dpll_md_reg = DPLL_MD(intel_crtc->pipe); |
133 | dpll_md_reg = DPLL_A_MD; | ||
134 | else | ||
135 | dpll_md_reg = DPLL_B_MD; | ||
136 | 133 | ||
137 | if (HAS_PCH_SPLIT(dev)) | 134 | if (HAS_PCH_SPLIT(dev)) |
138 | adpa_reg = PCH_ADPA; | 135 | adpa_reg = PCH_ADPA; |
@@ -160,17 +157,16 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, | |||
160 | adpa |= PORT_TRANS_A_SEL_CPT; | 157 | adpa |= PORT_TRANS_A_SEL_CPT; |
161 | else | 158 | else |
162 | adpa |= ADPA_PIPE_A_SELECT; | 159 | adpa |= ADPA_PIPE_A_SELECT; |
163 | if (!HAS_PCH_SPLIT(dev)) | ||
164 | I915_WRITE(BCLRPAT_A, 0); | ||
165 | } else { | 160 | } else { |
166 | if (HAS_PCH_CPT(dev)) | 161 | if (HAS_PCH_CPT(dev)) |
167 | adpa |= PORT_TRANS_B_SEL_CPT; | 162 | adpa |= PORT_TRANS_B_SEL_CPT; |
168 | else | 163 | else |
169 | adpa |= ADPA_PIPE_B_SELECT; | 164 | adpa |= ADPA_PIPE_B_SELECT; |
170 | if (!HAS_PCH_SPLIT(dev)) | ||
171 | I915_WRITE(BCLRPAT_B, 0); | ||
172 | } | 165 | } |
173 | 166 | ||
167 | if (!HAS_PCH_SPLIT(dev)) | ||
168 | I915_WRITE(BCLRPAT(intel_crtc->pipe), 0); | ||
169 | |||
174 | I915_WRITE(adpa_reg, adpa); | 170 | I915_WRITE(adpa_reg, adpa); |
175 | } | 171 | } |
176 | 172 | ||
@@ -353,21 +349,12 @@ intel_crt_load_detect(struct drm_crtc *crtc, struct intel_crt *crt) | |||
353 | 349 | ||
354 | DRM_DEBUG_KMS("starting load-detect on CRT\n"); | 350 | DRM_DEBUG_KMS("starting load-detect on CRT\n"); |
355 | 351 | ||
356 | if (pipe == 0) { | 352 | bclrpat_reg = BCLRPAT(pipe); |
357 | bclrpat_reg = BCLRPAT_A; | 353 | vtotal_reg = VTOTAL(pipe); |
358 | vtotal_reg = VTOTAL_A; | 354 | vblank_reg = VBLANK(pipe); |
359 | vblank_reg = VBLANK_A; | 355 | vsync_reg = VSYNC(pipe); |
360 | vsync_reg = VSYNC_A; | 356 | pipeconf_reg = PIPECONF(pipe); |
361 | pipeconf_reg = PIPEACONF; | 357 | pipe_dsl_reg = PIPEDSL(pipe); |
362 | pipe_dsl_reg = PIPEADSL; | ||
363 | } else { | ||
364 | bclrpat_reg = BCLRPAT_B; | ||
365 | vtotal_reg = VTOTAL_B; | ||
366 | vblank_reg = VBLANK_B; | ||
367 | vsync_reg = VSYNC_B; | ||
368 | pipeconf_reg = PIPEBCONF; | ||
369 | pipe_dsl_reg = PIPEBDSL; | ||
370 | } | ||
371 | 358 | ||
372 | save_bclrpat = I915_READ(bclrpat_reg); | 359 | save_bclrpat = I915_READ(bclrpat_reg); |
373 | save_vtotal = I915_READ(vtotal_reg); | 360 | save_vtotal = I915_READ(vtotal_reg); |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 49fb54fd9a1..3106c0dc838 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -989,7 +989,7 @@ intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, | |||
989 | void intel_wait_for_vblank(struct drm_device *dev, int pipe) | 989 | void intel_wait_for_vblank(struct drm_device *dev, int pipe) |
990 | { | 990 | { |
991 | struct drm_i915_private *dev_priv = dev->dev_private; | 991 | struct drm_i915_private *dev_priv = dev->dev_private; |
992 | int pipestat_reg = (pipe == 0 ? PIPEASTAT : PIPEBSTAT); | 992 | int pipestat_reg = PIPESTAT(pipe); |
993 | 993 | ||
994 | /* Clear existing vblank status. Note this will clear any other | 994 | /* Clear existing vblank status. Note this will clear any other |
995 | * sticky status fields as well. | 995 | * sticky status fields as well. |
@@ -1058,6 +1058,612 @@ void intel_wait_for_pipe_off(struct drm_device *dev, int pipe) | |||
1058 | } | 1058 | } |
1059 | } | 1059 | } |
1060 | 1060 | ||
1061 | static const char *state_string(bool enabled) | ||
1062 | { | ||
1063 | return enabled ? "on" : "off"; | ||
1064 | } | ||
1065 | |||
1066 | /* Only for pre-ILK configs */ | ||
1067 | static void assert_pll(struct drm_i915_private *dev_priv, | ||
1068 | enum pipe pipe, bool state) | ||
1069 | { | ||
1070 | int reg; | ||
1071 | u32 val; | ||
1072 | bool cur_state; | ||
1073 | |||
1074 | reg = DPLL(pipe); | ||
1075 | val = I915_READ(reg); | ||
1076 | cur_state = !!(val & DPLL_VCO_ENABLE); | ||
1077 | WARN(cur_state != state, | ||
1078 | "PLL state assertion failure (expected %s, current %s)\n", | ||
1079 | state_string(state), state_string(cur_state)); | ||
1080 | } | ||
1081 | #define assert_pll_enabled(d, p) assert_pll(d, p, true) | ||
1082 | #define assert_pll_disabled(d, p) assert_pll(d, p, false) | ||
1083 | |||
1084 | /* For ILK+ */ | ||
1085 | static void assert_pch_pll(struct drm_i915_private *dev_priv, | ||
1086 | enum pipe pipe, bool state) | ||
1087 | { | ||
1088 | int reg; | ||
1089 | u32 val; | ||
1090 | bool cur_state; | ||
1091 | |||
1092 | reg = PCH_DPLL(pipe); | ||
1093 | val = I915_READ(reg); | ||
1094 | cur_state = !!(val & DPLL_VCO_ENABLE); | ||
1095 | WARN(cur_state != state, | ||
1096 | "PCH PLL state assertion failure (expected %s, current %s)\n", | ||
1097 | state_string(state), state_string(cur_state)); | ||
1098 | } | ||
1099 | #define assert_pch_pll_enabled(d, p) assert_pch_pll(d, p, true) | ||
1100 | #define assert_pch_pll_disabled(d, p) assert_pch_pll(d, p, false) | ||
1101 | |||
1102 | static void assert_fdi_tx(struct drm_i915_private *dev_priv, | ||
1103 | enum pipe pipe, bool state) | ||
1104 | { | ||
1105 | int reg; | ||
1106 | u32 val; | ||
1107 | bool cur_state; | ||
1108 | |||
1109 | reg = FDI_TX_CTL(pipe); | ||
1110 | val = I915_READ(reg); | ||
1111 | cur_state = !!(val & FDI_TX_ENABLE); | ||
1112 | WARN(cur_state != state, | ||
1113 | "FDI TX state assertion failure (expected %s, current %s)\n", | ||
1114 | state_string(state), state_string(cur_state)); | ||
1115 | } | ||
1116 | #define assert_fdi_tx_enabled(d, p) assert_fdi_tx(d, p, true) | ||
1117 | #define assert_fdi_tx_disabled(d, p) assert_fdi_tx(d, p, false) | ||
1118 | |||
1119 | static void assert_fdi_rx(struct drm_i915_private *dev_priv, | ||
1120 | enum pipe pipe, bool state) | ||
1121 | { | ||
1122 | int reg; | ||
1123 | u32 val; | ||
1124 | bool cur_state; | ||
1125 | |||
1126 | reg = FDI_RX_CTL(pipe); | ||
1127 | val = I915_READ(reg); | ||
1128 | cur_state = !!(val & FDI_RX_ENABLE); | ||
1129 | WARN(cur_state != state, | ||
1130 | "FDI RX state assertion failure (expected %s, current %s)\n", | ||
1131 | state_string(state), state_string(cur_state)); | ||
1132 | } | ||
1133 | #define assert_fdi_rx_enabled(d, p) assert_fdi_rx(d, p, true) | ||
1134 | #define assert_fdi_rx_disabled(d, p) assert_fdi_rx(d, p, false) | ||
1135 | |||
1136 | static void assert_fdi_tx_pll_enabled(struct drm_i915_private *dev_priv, | ||
1137 | enum pipe pipe) | ||
1138 | { | ||
1139 | int reg; | ||
1140 | u32 val; | ||
1141 | |||
1142 | /* ILK FDI PLL is always enabled */ | ||
1143 | if (dev_priv->info->gen == 5) | ||
1144 | return; | ||
1145 | |||
1146 | reg = FDI_TX_CTL(pipe); | ||
1147 | val = I915_READ(reg); | ||
1148 | WARN(!(val & FDI_TX_PLL_ENABLE), "FDI TX PLL assertion failure, should be active but is disabled\n"); | ||
1149 | } | ||
1150 | |||
1151 | static void assert_fdi_rx_pll_enabled(struct drm_i915_private *dev_priv, | ||
1152 | enum pipe pipe) | ||
1153 | { | ||
1154 | int reg; | ||
1155 | u32 val; | ||
1156 | |||
1157 | reg = FDI_RX_CTL(pipe); | ||
1158 | val = I915_READ(reg); | ||
1159 | WARN(!(val & FDI_RX_PLL_ENABLE), "FDI RX PLL assertion failure, should be active but is disabled\n"); | ||
1160 | } | ||
1161 | |||
1162 | static void assert_panel_unlocked(struct drm_i915_private *dev_priv, | ||
1163 | enum pipe pipe) | ||
1164 | { | ||
1165 | int pp_reg, lvds_reg; | ||
1166 | u32 val; | ||
1167 | enum pipe panel_pipe = PIPE_A; | ||
1168 | bool locked = locked; | ||
1169 | |||
1170 | if (HAS_PCH_SPLIT(dev_priv->dev)) { | ||
1171 | pp_reg = PCH_PP_CONTROL; | ||
1172 | lvds_reg = PCH_LVDS; | ||
1173 | } else { | ||
1174 | pp_reg = PP_CONTROL; | ||
1175 | lvds_reg = LVDS; | ||
1176 | } | ||
1177 | |||
1178 | val = I915_READ(pp_reg); | ||
1179 | if (!(val & PANEL_POWER_ON) || | ||
1180 | ((val & PANEL_UNLOCK_REGS) == PANEL_UNLOCK_REGS)) | ||
1181 | locked = false; | ||
1182 | |||
1183 | if (I915_READ(lvds_reg) & LVDS_PIPEB_SELECT) | ||
1184 | panel_pipe = PIPE_B; | ||
1185 | |||
1186 | WARN(panel_pipe == pipe && locked, | ||
1187 | "panel assertion failure, pipe %c regs locked\n", | ||
1188 | pipe_name(pipe)); | ||
1189 | } | ||
1190 | |||
1191 | static void assert_pipe(struct drm_i915_private *dev_priv, | ||
1192 | enum pipe pipe, bool state) | ||
1193 | { | ||
1194 | int reg; | ||
1195 | u32 val; | ||
1196 | bool cur_state; | ||
1197 | |||
1198 | reg = PIPECONF(pipe); | ||
1199 | val = I915_READ(reg); | ||
1200 | cur_state = !!(val & PIPECONF_ENABLE); | ||
1201 | WARN(cur_state != state, | ||
1202 | "pipe %c assertion failure (expected %s, current %s)\n", | ||
1203 | pipe_name(pipe), state_string(state), state_string(cur_state)); | ||
1204 | } | ||
1205 | #define assert_pipe_enabled(d, p) assert_pipe(d, p, true) | ||
1206 | #define assert_pipe_disabled(d, p) assert_pipe(d, p, false) | ||
1207 | |||
1208 | static void assert_plane_enabled(struct drm_i915_private *dev_priv, | ||
1209 | enum plane plane) | ||
1210 | { | ||
1211 | int reg; | ||
1212 | u32 val; | ||
1213 | |||
1214 | reg = DSPCNTR(plane); | ||
1215 | val = I915_READ(reg); | ||
1216 | WARN(!(val & DISPLAY_PLANE_ENABLE), | ||
1217 | "plane %c assertion failure, should be active but is disabled\n", | ||
1218 | plane_name(plane)); | ||
1219 | } | ||
1220 | |||
1221 | static void assert_planes_disabled(struct drm_i915_private *dev_priv, | ||
1222 | enum pipe pipe) | ||
1223 | { | ||
1224 | int reg, i; | ||
1225 | u32 val; | ||
1226 | int cur_pipe; | ||
1227 | |||
1228 | /* Planes are fixed to pipes on ILK+ */ | ||
1229 | if (HAS_PCH_SPLIT(dev_priv->dev)) | ||
1230 | return; | ||
1231 | |||
1232 | /* Need to check both planes against the pipe */ | ||
1233 | for (i = 0; i < 2; i++) { | ||
1234 | reg = DSPCNTR(i); | ||
1235 | val = I915_READ(reg); | ||
1236 | cur_pipe = (val & DISPPLANE_SEL_PIPE_MASK) >> | ||
1237 | DISPPLANE_SEL_PIPE_SHIFT; | ||
1238 | WARN((val & DISPLAY_PLANE_ENABLE) && pipe == cur_pipe, | ||
1239 | "plane %c assertion failure, should be off on pipe %c but is still active\n", | ||
1240 | plane_name(i), pipe_name(pipe)); | ||
1241 | } | ||
1242 | } | ||
1243 | |||
1244 | static void assert_pch_refclk_enabled(struct drm_i915_private *dev_priv) | ||
1245 | { | ||
1246 | u32 val; | ||
1247 | bool enabled; | ||
1248 | |||
1249 | val = I915_READ(PCH_DREF_CONTROL); | ||
1250 | enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK | | ||
1251 | DREF_SUPERSPREAD_SOURCE_MASK)); | ||
1252 | WARN(!enabled, "PCH refclk assertion failure, should be active but is disabled\n"); | ||
1253 | } | ||
1254 | |||
1255 | static void assert_transcoder_disabled(struct drm_i915_private *dev_priv, | ||
1256 | enum pipe pipe) | ||
1257 | { | ||
1258 | int reg; | ||
1259 | u32 val; | ||
1260 | bool enabled; | ||
1261 | |||
1262 | reg = TRANSCONF(pipe); | ||
1263 | val = I915_READ(reg); | ||
1264 | enabled = !!(val & TRANS_ENABLE); | ||
1265 | WARN(enabled, | ||
1266 | "transcoder assertion failed, should be off on pipe %c but is still active\n", | ||
1267 | pipe_name(pipe)); | ||
1268 | } | ||
1269 | |||
1270 | static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv, | ||
1271 | enum pipe pipe, int reg) | ||
1272 | { | ||
1273 | u32 val = I915_READ(reg); | ||
1274 | WARN(DP_PIPE_ENABLED(val, pipe), | ||
1275 | "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n", | ||
1276 | reg, pipe_name(pipe)); | ||
1277 | } | ||
1278 | |||
1279 | static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, | ||
1280 | enum pipe pipe, int reg) | ||
1281 | { | ||
1282 | u32 val = I915_READ(reg); | ||
1283 | WARN(HDMI_PIPE_ENABLED(val, pipe), | ||
1284 | "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n", | ||
1285 | reg, pipe_name(pipe)); | ||
1286 | } | ||
1287 | |||
1288 | static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv, | ||
1289 | enum pipe pipe) | ||
1290 | { | ||
1291 | int reg; | ||
1292 | u32 val; | ||
1293 | |||
1294 | assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_B); | ||
1295 | assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_C); | ||
1296 | assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_D); | ||
1297 | |||
1298 | reg = PCH_ADPA; | ||
1299 | val = I915_READ(reg); | ||
1300 | WARN(ADPA_PIPE_ENABLED(val, pipe), | ||
1301 | "PCH VGA enabled on transcoder %c, should be disabled\n", | ||
1302 | pipe_name(pipe)); | ||
1303 | |||
1304 | reg = PCH_LVDS; | ||
1305 | val = I915_READ(reg); | ||
1306 | WARN(LVDS_PIPE_ENABLED(val, pipe), | ||
1307 | "PCH LVDS enabled on transcoder %c, should be disabled\n", | ||
1308 | pipe_name(pipe)); | ||
1309 | |||
1310 | assert_pch_hdmi_disabled(dev_priv, pipe, HDMIB); | ||
1311 | assert_pch_hdmi_disabled(dev_priv, pipe, HDMIC); | ||
1312 | assert_pch_hdmi_disabled(dev_priv, pipe, HDMID); | ||
1313 | } | ||
1314 | |||
1315 | /** | ||
1316 | * intel_enable_pll - enable a PLL | ||
1317 | * @dev_priv: i915 private structure | ||
1318 | * @pipe: pipe PLL to enable | ||
1319 | * | ||
1320 | * Enable @pipe's PLL so we can start pumping pixels from a plane. Check to | ||
1321 | * make sure the PLL reg is writable first though, since the panel write | ||
1322 | * protect mechanism may be enabled. | ||
1323 | * | ||
1324 | * Note! This is for pre-ILK only. | ||
1325 | */ | ||
1326 | static void intel_enable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) | ||
1327 | { | ||
1328 | int reg; | ||
1329 | u32 val; | ||
1330 | |||
1331 | /* No really, not for ILK+ */ | ||
1332 | BUG_ON(dev_priv->info->gen >= 5); | ||
1333 | |||
1334 | /* PLL is protected by panel, make sure we can write it */ | ||
1335 | if (IS_MOBILE(dev_priv->dev) && !IS_I830(dev_priv->dev)) | ||
1336 | assert_panel_unlocked(dev_priv, pipe); | ||
1337 | |||
1338 | reg = DPLL(pipe); | ||
1339 | val = I915_READ(reg); | ||
1340 | val |= DPLL_VCO_ENABLE; | ||
1341 | |||
1342 | /* We do this three times for luck */ | ||
1343 | I915_WRITE(reg, val); | ||
1344 | POSTING_READ(reg); | ||
1345 | udelay(150); /* wait for warmup */ | ||
1346 | I915_WRITE(reg, val); | ||
1347 | POSTING_READ(reg); | ||
1348 | udelay(150); /* wait for warmup */ | ||
1349 | I915_WRITE(reg, val); | ||
1350 | POSTING_READ(reg); | ||
1351 | udelay(150); /* wait for warmup */ | ||
1352 | } | ||
1353 | |||
1354 | /** | ||
1355 | * intel_disable_pll - disable a PLL | ||
1356 | * @dev_priv: i915 private structure | ||
1357 | * @pipe: pipe PLL to disable | ||
1358 | * | ||
1359 | * Disable the PLL for @pipe, making sure the pipe is off first. | ||
1360 | * | ||
1361 | * Note! This is for pre-ILK only. | ||
1362 | */ | ||
1363 | static void intel_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) | ||
1364 | { | ||
1365 | int reg; | ||
1366 | u32 val; | ||
1367 | |||
1368 | /* Don't disable pipe A or pipe A PLLs if needed */ | ||
1369 | if (pipe == PIPE_A && (dev_priv->quirks & QUIRK_PIPEA_FORCE)) | ||
1370 | return; | ||
1371 | |||
1372 | /* Make sure the pipe isn't still relying on us */ | ||
1373 | assert_pipe_disabled(dev_priv, pipe); | ||
1374 | |||
1375 | reg = DPLL(pipe); | ||
1376 | val = I915_READ(reg); | ||
1377 | val &= ~DPLL_VCO_ENABLE; | ||
1378 | I915_WRITE(reg, val); | ||
1379 | POSTING_READ(reg); | ||
1380 | } | ||
1381 | |||
1382 | /** | ||
1383 | * intel_enable_pch_pll - enable PCH PLL | ||
1384 | * @dev_priv: i915 private structure | ||
1385 | * @pipe: pipe PLL to enable | ||
1386 | * | ||
1387 | * The PCH PLL needs to be enabled before the PCH transcoder, since it | ||
1388 | * drives the transcoder clock. | ||
1389 | */ | ||
1390 | static void intel_enable_pch_pll(struct drm_i915_private *dev_priv, | ||
1391 | enum pipe pipe) | ||
1392 | { | ||
1393 | int reg; | ||
1394 | u32 val; | ||
1395 | |||
1396 | /* PCH only available on ILK+ */ | ||
1397 | BUG_ON(dev_priv->info->gen < 5); | ||
1398 | |||
1399 | /* PCH refclock must be enabled first */ | ||
1400 | assert_pch_refclk_enabled(dev_priv); | ||
1401 | |||
1402 | reg = PCH_DPLL(pipe); | ||
1403 | val = I915_READ(reg); | ||
1404 | val |= DPLL_VCO_ENABLE; | ||
1405 | I915_WRITE(reg, val); | ||
1406 | POSTING_READ(reg); | ||
1407 | udelay(200); | ||
1408 | } | ||
1409 | |||
1410 | static void intel_disable_pch_pll(struct drm_i915_private *dev_priv, | ||
1411 | enum pipe pipe) | ||
1412 | { | ||
1413 | int reg; | ||
1414 | u32 val; | ||
1415 | |||
1416 | /* PCH only available on ILK+ */ | ||
1417 | BUG_ON(dev_priv->info->gen < 5); | ||
1418 | |||
1419 | /* Make sure transcoder isn't still depending on us */ | ||
1420 | assert_transcoder_disabled(dev_priv, pipe); | ||
1421 | |||
1422 | reg = PCH_DPLL(pipe); | ||
1423 | val = I915_READ(reg); | ||
1424 | val &= ~DPLL_VCO_ENABLE; | ||
1425 | I915_WRITE(reg, val); | ||
1426 | POSTING_READ(reg); | ||
1427 | udelay(200); | ||
1428 | } | ||
1429 | |||
1430 | static void intel_enable_transcoder(struct drm_i915_private *dev_priv, | ||
1431 | enum pipe pipe) | ||
1432 | { | ||
1433 | int reg; | ||
1434 | u32 val; | ||
1435 | |||
1436 | /* PCH only available on ILK+ */ | ||
1437 | BUG_ON(dev_priv->info->gen < 5); | ||
1438 | |||
1439 | /* Make sure PCH DPLL is enabled */ | ||
1440 | assert_pch_pll_enabled(dev_priv, pipe); | ||
1441 | |||
1442 | /* FDI must be feeding us bits for PCH ports */ | ||
1443 | assert_fdi_tx_enabled(dev_priv, pipe); | ||
1444 | assert_fdi_rx_enabled(dev_priv, pipe); | ||
1445 | |||
1446 | reg = TRANSCONF(pipe); | ||
1447 | val = I915_READ(reg); | ||
1448 | /* | ||
1449 | * make the BPC in transcoder be consistent with | ||
1450 | * that in pipeconf reg. | ||
1451 | */ | ||
1452 | val &= ~PIPE_BPC_MASK; | ||
1453 | val |= I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK; | ||
1454 | I915_WRITE(reg, val | TRANS_ENABLE); | ||
1455 | if (wait_for(I915_READ(reg) & TRANS_STATE_ENABLE, 100)) | ||
1456 | DRM_ERROR("failed to enable transcoder %d\n", pipe); | ||
1457 | } | ||
1458 | |||
1459 | static void intel_disable_transcoder(struct drm_i915_private *dev_priv, | ||
1460 | enum pipe pipe) | ||
1461 | { | ||
1462 | int reg; | ||
1463 | u32 val; | ||
1464 | |||
1465 | /* FDI relies on the transcoder */ | ||
1466 | assert_fdi_tx_disabled(dev_priv, pipe); | ||
1467 | assert_fdi_rx_disabled(dev_priv, pipe); | ||
1468 | |||
1469 | /* Ports must be off as well */ | ||
1470 | assert_pch_ports_disabled(dev_priv, pipe); | ||
1471 | |||
1472 | reg = TRANSCONF(pipe); | ||
1473 | val = I915_READ(reg); | ||
1474 | val &= ~TRANS_ENABLE; | ||
1475 | I915_WRITE(reg, val); | ||
1476 | /* wait for PCH transcoder off, transcoder state */ | ||
1477 | if (wait_for((I915_READ(reg) & TRANS_STATE_ENABLE) == 0, 50)) | ||
1478 | DRM_ERROR("failed to disable transcoder\n"); | ||
1479 | } | ||
1480 | |||
1481 | /** | ||
1482 | * intel_enable_pipe - enable a pipe, asserting requirements | ||
1483 | * @dev_priv: i915 private structure | ||
1484 | * @pipe: pipe to enable | ||
1485 | * @pch_port: on ILK+, is this pipe driving a PCH port or not | ||
1486 | * | ||
1487 | * Enable @pipe, making sure that various hardware specific requirements | ||
1488 | * are met, if applicable, e.g. PLL enabled, LVDS pairs enabled, etc. | ||
1489 | * | ||
1490 | * @pipe should be %PIPE_A or %PIPE_B. | ||
1491 | * | ||
1492 | * Will wait until the pipe is actually running (i.e. first vblank) before | ||
1493 | * returning. | ||
1494 | */ | ||
1495 | static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, | ||
1496 | bool pch_port) | ||
1497 | { | ||
1498 | int reg; | ||
1499 | u32 val; | ||
1500 | |||
1501 | /* | ||
1502 | * A pipe without a PLL won't actually be able to drive bits from | ||
1503 | * a plane. On ILK+ the pipe PLLs are integrated, so we don't | ||
1504 | * need the check. | ||
1505 | */ | ||
1506 | if (!HAS_PCH_SPLIT(dev_priv->dev)) | ||
1507 | assert_pll_enabled(dev_priv, pipe); | ||
1508 | else { | ||
1509 | if (pch_port) { | ||
1510 | /* if driving the PCH, we need FDI enabled */ | ||
1511 | assert_fdi_rx_pll_enabled(dev_priv, pipe); | ||
1512 | assert_fdi_tx_pll_enabled(dev_priv, pipe); | ||
1513 | } | ||
1514 | /* FIXME: assert CPU port conditions for SNB+ */ | ||
1515 | } | ||
1516 | |||
1517 | reg = PIPECONF(pipe); | ||
1518 | val = I915_READ(reg); | ||
1519 | val |= PIPECONF_ENABLE; | ||
1520 | I915_WRITE(reg, val); | ||
1521 | POSTING_READ(reg); | ||
1522 | intel_wait_for_vblank(dev_priv->dev, pipe); | ||
1523 | } | ||
1524 | |||
1525 | /** | ||
1526 | * intel_disable_pipe - disable a pipe, asserting requirements | ||
1527 | * @dev_priv: i915 private structure | ||
1528 | * @pipe: pipe to disable | ||
1529 | * | ||
1530 | * Disable @pipe, making sure that various hardware specific requirements | ||
1531 | * are met, if applicable, e.g. plane disabled, panel fitter off, etc. | ||
1532 | * | ||
1533 | * @pipe should be %PIPE_A or %PIPE_B. | ||
1534 | * | ||
1535 | * Will wait until the pipe has shut down before returning. | ||
1536 | */ | ||
1537 | static void intel_disable_pipe(struct drm_i915_private *dev_priv, | ||
1538 | enum pipe pipe) | ||
1539 | { | ||
1540 | int reg; | ||
1541 | u32 val; | ||
1542 | |||
1543 | /* | ||
1544 | * Make sure planes won't keep trying to pump pixels to us, | ||
1545 | * or we might hang the display. | ||
1546 | */ | ||
1547 | assert_planes_disabled(dev_priv, pipe); | ||
1548 | |||
1549 | /* Don't disable pipe A or pipe A PLLs if needed */ | ||
1550 | if (pipe == PIPE_A && (dev_priv->quirks & QUIRK_PIPEA_FORCE)) | ||
1551 | return; | ||
1552 | |||
1553 | reg = PIPECONF(pipe); | ||
1554 | val = I915_READ(reg); | ||
1555 | val &= ~PIPECONF_ENABLE; | ||
1556 | I915_WRITE(reg, val); | ||
1557 | POSTING_READ(reg); | ||
1558 | intel_wait_for_pipe_off(dev_priv->dev, pipe); | ||
1559 | } | ||
1560 | |||
1561 | /** | ||
1562 | * intel_enable_plane - enable a display plane on a given pipe | ||
1563 | * @dev_priv: i915 private structure | ||
1564 | * @plane: plane to enable | ||
1565 | * @pipe: pipe being fed | ||
1566 | * | ||
1567 | * Enable @plane on @pipe, making sure that @pipe is running first. | ||
1568 | */ | ||
1569 | static void intel_enable_plane(struct drm_i915_private *dev_priv, | ||
1570 | enum plane plane, enum pipe pipe) | ||
1571 | { | ||
1572 | int reg; | ||
1573 | u32 val; | ||
1574 | |||
1575 | /* If the pipe isn't enabled, we can't pump pixels and may hang */ | ||
1576 | assert_pipe_enabled(dev_priv, pipe); | ||
1577 | |||
1578 | reg = DSPCNTR(plane); | ||
1579 | val = I915_READ(reg); | ||
1580 | val |= DISPLAY_PLANE_ENABLE; | ||
1581 | I915_WRITE(reg, val); | ||
1582 | POSTING_READ(reg); | ||
1583 | intel_wait_for_vblank(dev_priv->dev, pipe); | ||
1584 | } | ||
1585 | |||
1586 | /* | ||
1587 | * Plane regs are double buffered, going from enabled->disabled needs a | ||
1588 | * trigger in order to latch. The display address reg provides this. | ||
1589 | */ | ||
1590 | static void intel_flush_display_plane(struct drm_i915_private *dev_priv, | ||
1591 | enum plane plane) | ||
1592 | { | ||
1593 | u32 reg = DSPADDR(plane); | ||
1594 | I915_WRITE(reg, I915_READ(reg)); | ||
1595 | } | ||
1596 | |||
1597 | /** | ||
1598 | * intel_disable_plane - disable a display plane | ||
1599 | * @dev_priv: i915 private structure | ||
1600 | * @plane: plane to disable | ||
1601 | * @pipe: pipe consuming the data | ||
1602 | * | ||
1603 | * Disable @plane; should be an independent operation. | ||
1604 | */ | ||
1605 | static void intel_disable_plane(struct drm_i915_private *dev_priv, | ||
1606 | enum plane plane, enum pipe pipe) | ||
1607 | { | ||
1608 | int reg; | ||
1609 | u32 val; | ||
1610 | |||
1611 | reg = DSPCNTR(plane); | ||
1612 | val = I915_READ(reg); | ||
1613 | val &= ~DISPLAY_PLANE_ENABLE; | ||
1614 | I915_WRITE(reg, val); | ||
1615 | POSTING_READ(reg); | ||
1616 | intel_flush_display_plane(dev_priv, plane); | ||
1617 | intel_wait_for_vblank(dev_priv->dev, pipe); | ||
1618 | } | ||
1619 | |||
1620 | static void disable_pch_dp(struct drm_i915_private *dev_priv, | ||
1621 | enum pipe pipe, int reg) | ||
1622 | { | ||
1623 | u32 val = I915_READ(reg); | ||
1624 | if (DP_PIPE_ENABLED(val, pipe)) | ||
1625 | I915_WRITE(reg, val & ~DP_PORT_EN); | ||
1626 | } | ||
1627 | |||
1628 | static void disable_pch_hdmi(struct drm_i915_private *dev_priv, | ||
1629 | enum pipe pipe, int reg) | ||
1630 | { | ||
1631 | u32 val = I915_READ(reg); | ||
1632 | if (HDMI_PIPE_ENABLED(val, pipe)) | ||
1633 | I915_WRITE(reg, val & ~PORT_ENABLE); | ||
1634 | } | ||
1635 | |||
1636 | /* Disable any ports connected to this transcoder */ | ||
1637 | static void intel_disable_pch_ports(struct drm_i915_private *dev_priv, | ||
1638 | enum pipe pipe) | ||
1639 | { | ||
1640 | u32 reg, val; | ||
1641 | |||
1642 | val = I915_READ(PCH_PP_CONTROL); | ||
1643 | I915_WRITE(PCH_PP_CONTROL, val | PANEL_UNLOCK_REGS); | ||
1644 | |||
1645 | disable_pch_dp(dev_priv, pipe, PCH_DP_B); | ||
1646 | disable_pch_dp(dev_priv, pipe, PCH_DP_C); | ||
1647 | disable_pch_dp(dev_priv, pipe, PCH_DP_D); | ||
1648 | |||
1649 | reg = PCH_ADPA; | ||
1650 | val = I915_READ(reg); | ||
1651 | if (ADPA_PIPE_ENABLED(val, pipe)) | ||
1652 | I915_WRITE(reg, val & ~ADPA_DAC_ENABLE); | ||
1653 | |||
1654 | reg = PCH_LVDS; | ||
1655 | val = I915_READ(reg); | ||
1656 | if (LVDS_PIPE_ENABLED(val, pipe)) { | ||
1657 | I915_WRITE(reg, val & ~LVDS_PORT_EN); | ||
1658 | POSTING_READ(reg); | ||
1659 | udelay(100); | ||
1660 | } | ||
1661 | |||
1662 | disable_pch_hdmi(dev_priv, pipe, HDMIB); | ||
1663 | disable_pch_hdmi(dev_priv, pipe, HDMIC); | ||
1664 | disable_pch_hdmi(dev_priv, pipe, HDMID); | ||
1665 | } | ||
1666 | |||
1061 | static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) | 1667 | static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) |
1062 | { | 1668 | { |
1063 | struct drm_device *dev = crtc->dev; | 1669 | struct drm_device *dev = crtc->dev; |
@@ -1390,7 +1996,7 @@ static void intel_update_fbc(struct drm_device *dev) | |||
1390 | * - going to an unsupported config (interlace, pixel multiply, etc.) | 1996 | * - going to an unsupported config (interlace, pixel multiply, etc.) |
1391 | */ | 1997 | */ |
1392 | list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { | 1998 | list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { |
1393 | if (tmp_crtc->enabled) { | 1999 | if (tmp_crtc->enabled && tmp_crtc->fb) { |
1394 | if (crtc) { | 2000 | if (crtc) { |
1395 | DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); | 2001 | DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); |
1396 | dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES; | 2002 | dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES; |
@@ -1461,6 +2067,7 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev, | |||
1461 | struct drm_i915_gem_object *obj, | 2067 | struct drm_i915_gem_object *obj, |
1462 | struct intel_ring_buffer *pipelined) | 2068 | struct intel_ring_buffer *pipelined) |
1463 | { | 2069 | { |
2070 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1464 | u32 alignment; | 2071 | u32 alignment; |
1465 | int ret; | 2072 | int ret; |
1466 | 2073 | ||
@@ -1485,9 +2092,10 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev, | |||
1485 | BUG(); | 2092 | BUG(); |
1486 | } | 2093 | } |
1487 | 2094 | ||
2095 | dev_priv->mm.interruptible = false; | ||
1488 | ret = i915_gem_object_pin(obj, alignment, true); | 2096 | ret = i915_gem_object_pin(obj, alignment, true); |
1489 | if (ret) | 2097 | if (ret) |
1490 | return ret; | 2098 | goto err_interruptible; |
1491 | 2099 | ||
1492 | ret = i915_gem_object_set_to_display_plane(obj, pipelined); | 2100 | ret = i915_gem_object_set_to_display_plane(obj, pipelined); |
1493 | if (ret) | 2101 | if (ret) |
@@ -1499,15 +2107,18 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev, | |||
1499 | * a fence as the cost is not that onerous. | 2107 | * a fence as the cost is not that onerous. |
1500 | */ | 2108 | */ |
1501 | if (obj->tiling_mode != I915_TILING_NONE) { | 2109 | if (obj->tiling_mode != I915_TILING_NONE) { |
1502 | ret = i915_gem_object_get_fence(obj, pipelined, false); | 2110 | ret = i915_gem_object_get_fence(obj, pipelined); |
1503 | if (ret) | 2111 | if (ret) |
1504 | goto err_unpin; | 2112 | goto err_unpin; |
1505 | } | 2113 | } |
1506 | 2114 | ||
2115 | dev_priv->mm.interruptible = true; | ||
1507 | return 0; | 2116 | return 0; |
1508 | 2117 | ||
1509 | err_unpin: | 2118 | err_unpin: |
1510 | i915_gem_object_unpin(obj); | 2119 | i915_gem_object_unpin(obj); |
2120 | err_interruptible: | ||
2121 | dev_priv->mm.interruptible = true; | ||
1511 | return ret; | 2122 | return ret; |
1512 | } | 2123 | } |
1513 | 2124 | ||
@@ -1641,7 +2252,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, | |||
1641 | * This should only fail upon a hung GPU, in which case we | 2252 | * This should only fail upon a hung GPU, in which case we |
1642 | * can safely continue. | 2253 | * can safely continue. |
1643 | */ | 2254 | */ |
1644 | ret = i915_gem_object_flush_gpu(obj, false); | 2255 | ret = i915_gem_object_flush_gpu(obj); |
1645 | (void) ret; | 2256 | (void) ret; |
1646 | } | 2257 | } |
1647 | 2258 | ||
@@ -1753,8 +2364,13 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc) | |||
1753 | struct drm_i915_private *dev_priv = dev->dev_private; | 2364 | struct drm_i915_private *dev_priv = dev->dev_private; |
1754 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 2365 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
1755 | int pipe = intel_crtc->pipe; | 2366 | int pipe = intel_crtc->pipe; |
2367 | int plane = intel_crtc->plane; | ||
1756 | u32 reg, temp, tries; | 2368 | u32 reg, temp, tries; |
1757 | 2369 | ||
2370 | /* FDI needs bits from pipe & plane first */ | ||
2371 | assert_pipe_enabled(dev_priv, pipe); | ||
2372 | assert_plane_enabled(dev_priv, plane); | ||
2373 | |||
1758 | /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit | 2374 | /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit |
1759 | for train result */ | 2375 | for train result */ |
1760 | reg = FDI_RX_IMR(pipe); | 2376 | reg = FDI_RX_IMR(pipe); |
@@ -1784,7 +2400,11 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc) | |||
1784 | udelay(150); | 2400 | udelay(150); |
1785 | 2401 | ||
1786 | /* Ironlake workaround, enable clock pointer after FDI enable*/ | 2402 | /* Ironlake workaround, enable clock pointer after FDI enable*/ |
1787 | I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_ENABLE); | 2403 | if (HAS_PCH_IBX(dev)) { |
2404 | I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR); | ||
2405 | I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR | | ||
2406 | FDI_RX_PHASE_SYNC_POINTER_EN); | ||
2407 | } | ||
1788 | 2408 | ||
1789 | reg = FDI_RX_IIR(pipe); | 2409 | reg = FDI_RX_IIR(pipe); |
1790 | for (tries = 0; tries < 5; tries++) { | 2410 | for (tries = 0; tries < 5; tries++) { |
@@ -1834,7 +2454,7 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc) | |||
1834 | 2454 | ||
1835 | } | 2455 | } |
1836 | 2456 | ||
1837 | static const int const snb_b_fdi_train_param [] = { | 2457 | static const int snb_b_fdi_train_param [] = { |
1838 | FDI_LINK_TRAIN_400MV_0DB_SNB_B, | 2458 | FDI_LINK_TRAIN_400MV_0DB_SNB_B, |
1839 | FDI_LINK_TRAIN_400MV_6DB_SNB_B, | 2459 | FDI_LINK_TRAIN_400MV_6DB_SNB_B, |
1840 | FDI_LINK_TRAIN_600MV_3_5DB_SNB_B, | 2460 | FDI_LINK_TRAIN_600MV_3_5DB_SNB_B, |
@@ -2003,12 +2623,60 @@ static void ironlake_fdi_enable(struct drm_crtc *crtc) | |||
2003 | } | 2623 | } |
2004 | } | 2624 | } |
2005 | 2625 | ||
2006 | static void intel_flush_display_plane(struct drm_device *dev, | 2626 | static void ironlake_fdi_disable(struct drm_crtc *crtc) |
2007 | int plane) | ||
2008 | { | 2627 | { |
2628 | struct drm_device *dev = crtc->dev; | ||
2009 | struct drm_i915_private *dev_priv = dev->dev_private; | 2629 | struct drm_i915_private *dev_priv = dev->dev_private; |
2010 | u32 reg = DSPADDR(plane); | 2630 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
2011 | I915_WRITE(reg, I915_READ(reg)); | 2631 | int pipe = intel_crtc->pipe; |
2632 | u32 reg, temp; | ||
2633 | |||
2634 | /* disable CPU FDI tx and PCH FDI rx */ | ||
2635 | reg = FDI_TX_CTL(pipe); | ||
2636 | temp = I915_READ(reg); | ||
2637 | I915_WRITE(reg, temp & ~FDI_TX_ENABLE); | ||
2638 | POSTING_READ(reg); | ||
2639 | |||
2640 | reg = FDI_RX_CTL(pipe); | ||
2641 | temp = I915_READ(reg); | ||
2642 | temp &= ~(0x7 << 16); | ||
2643 | temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11; | ||
2644 | I915_WRITE(reg, temp & ~FDI_RX_ENABLE); | ||
2645 | |||
2646 | POSTING_READ(reg); | ||
2647 | udelay(100); | ||
2648 | |||
2649 | /* Ironlake workaround, disable clock pointer after downing FDI */ | ||
2650 | if (HAS_PCH_IBX(dev)) { | ||
2651 | I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR); | ||
2652 | I915_WRITE(FDI_RX_CHICKEN(pipe), | ||
2653 | I915_READ(FDI_RX_CHICKEN(pipe) & | ||
2654 | ~FDI_RX_PHASE_SYNC_POINTER_EN)); | ||
2655 | } | ||
2656 | |||
2657 | /* still set train pattern 1 */ | ||
2658 | reg = FDI_TX_CTL(pipe); | ||
2659 | temp = I915_READ(reg); | ||
2660 | temp &= ~FDI_LINK_TRAIN_NONE; | ||
2661 | temp |= FDI_LINK_TRAIN_PATTERN_1; | ||
2662 | I915_WRITE(reg, temp); | ||
2663 | |||
2664 | reg = FDI_RX_CTL(pipe); | ||
2665 | temp = I915_READ(reg); | ||
2666 | if (HAS_PCH_CPT(dev)) { | ||
2667 | temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; | ||
2668 | temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; | ||
2669 | } else { | ||
2670 | temp &= ~FDI_LINK_TRAIN_NONE; | ||
2671 | temp |= FDI_LINK_TRAIN_PATTERN_1; | ||
2672 | } | ||
2673 | /* BPC in FDI rx is consistent with that in PIPECONF */ | ||
2674 | temp &= ~(0x07 << 16); | ||
2675 | temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11; | ||
2676 | I915_WRITE(reg, temp); | ||
2677 | |||
2678 | POSTING_READ(reg); | ||
2679 | udelay(100); | ||
2012 | } | 2680 | } |
2013 | 2681 | ||
2014 | /* | 2682 | /* |
@@ -2070,114 +2738,21 @@ static bool intel_crtc_driving_pch(struct drm_crtc *crtc) | |||
2070 | return true; | 2738 | return true; |
2071 | } | 2739 | } |
2072 | 2740 | ||
2073 | static void ironlake_crtc_enable(struct drm_crtc *crtc) | 2741 | /* |
2742 | * Enable PCH resources required for PCH ports: | ||
2743 | * - PCH PLLs | ||
2744 | * - FDI training & RX/TX | ||
2745 | * - update transcoder timings | ||
2746 | * - DP transcoding bits | ||
2747 | * - transcoder | ||
2748 | */ | ||
2749 | static void ironlake_pch_enable(struct drm_crtc *crtc) | ||
2074 | { | 2750 | { |
2075 | struct drm_device *dev = crtc->dev; | 2751 | struct drm_device *dev = crtc->dev; |
2076 | struct drm_i915_private *dev_priv = dev->dev_private; | 2752 | struct drm_i915_private *dev_priv = dev->dev_private; |
2077 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 2753 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
2078 | int pipe = intel_crtc->pipe; | 2754 | int pipe = intel_crtc->pipe; |
2079 | int plane = intel_crtc->plane; | ||
2080 | u32 reg, temp; | 2755 | u32 reg, temp; |
2081 | bool is_pch_port = false; | ||
2082 | |||
2083 | if (intel_crtc->active) | ||
2084 | return; | ||
2085 | |||
2086 | intel_crtc->active = true; | ||
2087 | intel_update_watermarks(dev); | ||
2088 | |||
2089 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { | ||
2090 | temp = I915_READ(PCH_LVDS); | ||
2091 | if ((temp & LVDS_PORT_EN) == 0) | ||
2092 | I915_WRITE(PCH_LVDS, temp | LVDS_PORT_EN); | ||
2093 | } | ||
2094 | |||
2095 | is_pch_port = intel_crtc_driving_pch(crtc); | ||
2096 | |||
2097 | if (is_pch_port) | ||
2098 | ironlake_fdi_enable(crtc); | ||
2099 | else { | ||
2100 | /* disable CPU FDI tx and PCH FDI rx */ | ||
2101 | reg = FDI_TX_CTL(pipe); | ||
2102 | temp = I915_READ(reg); | ||
2103 | I915_WRITE(reg, temp & ~FDI_TX_ENABLE); | ||
2104 | POSTING_READ(reg); | ||
2105 | |||
2106 | reg = FDI_RX_CTL(pipe); | ||
2107 | temp = I915_READ(reg); | ||
2108 | temp &= ~(0x7 << 16); | ||
2109 | temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11; | ||
2110 | I915_WRITE(reg, temp & ~FDI_RX_ENABLE); | ||
2111 | |||
2112 | POSTING_READ(reg); | ||
2113 | udelay(100); | ||
2114 | |||
2115 | /* Ironlake workaround, disable clock pointer after downing FDI */ | ||
2116 | if (HAS_PCH_IBX(dev)) | ||
2117 | I915_WRITE(FDI_RX_CHICKEN(pipe), | ||
2118 | I915_READ(FDI_RX_CHICKEN(pipe) & | ||
2119 | ~FDI_RX_PHASE_SYNC_POINTER_ENABLE)); | ||
2120 | |||
2121 | /* still set train pattern 1 */ | ||
2122 | reg = FDI_TX_CTL(pipe); | ||
2123 | temp = I915_READ(reg); | ||
2124 | temp &= ~FDI_LINK_TRAIN_NONE; | ||
2125 | temp |= FDI_LINK_TRAIN_PATTERN_1; | ||
2126 | I915_WRITE(reg, temp); | ||
2127 | |||
2128 | reg = FDI_RX_CTL(pipe); | ||
2129 | temp = I915_READ(reg); | ||
2130 | if (HAS_PCH_CPT(dev)) { | ||
2131 | temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; | ||
2132 | temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; | ||
2133 | } else { | ||
2134 | temp &= ~FDI_LINK_TRAIN_NONE; | ||
2135 | temp |= FDI_LINK_TRAIN_PATTERN_1; | ||
2136 | } | ||
2137 | /* BPC in FDI rx is consistent with that in PIPECONF */ | ||
2138 | temp &= ~(0x07 << 16); | ||
2139 | temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11; | ||
2140 | I915_WRITE(reg, temp); | ||
2141 | |||
2142 | POSTING_READ(reg); | ||
2143 | udelay(100); | ||
2144 | } | ||
2145 | |||
2146 | /* Enable panel fitting for LVDS */ | ||
2147 | if (dev_priv->pch_pf_size && | ||
2148 | (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) || HAS_eDP)) { | ||
2149 | /* Force use of hard-coded filter coefficients | ||
2150 | * as some pre-programmed values are broken, | ||
2151 | * e.g. x201. | ||
2152 | */ | ||
2153 | I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1, | ||
2154 | PF_ENABLE | PF_FILTER_MED_3x3); | ||
2155 | I915_WRITE(pipe ? PFB_WIN_POS : PFA_WIN_POS, | ||
2156 | dev_priv->pch_pf_pos); | ||
2157 | I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ, | ||
2158 | dev_priv->pch_pf_size); | ||
2159 | } | ||
2160 | |||
2161 | /* Enable CPU pipe */ | ||
2162 | reg = PIPECONF(pipe); | ||
2163 | temp = I915_READ(reg); | ||
2164 | if ((temp & PIPECONF_ENABLE) == 0) { | ||
2165 | I915_WRITE(reg, temp | PIPECONF_ENABLE); | ||
2166 | POSTING_READ(reg); | ||
2167 | intel_wait_for_vblank(dev, intel_crtc->pipe); | ||
2168 | } | ||
2169 | |||
2170 | /* configure and enable CPU plane */ | ||
2171 | reg = DSPCNTR(plane); | ||
2172 | temp = I915_READ(reg); | ||
2173 | if ((temp & DISPLAY_PLANE_ENABLE) == 0) { | ||
2174 | I915_WRITE(reg, temp | DISPLAY_PLANE_ENABLE); | ||
2175 | intel_flush_display_plane(dev, plane); | ||
2176 | } | ||
2177 | |||
2178 | /* Skip the PCH stuff if possible */ | ||
2179 | if (!is_pch_port) | ||
2180 | goto done; | ||
2181 | 2756 | ||
2182 | /* For PCH output, training FDI link */ | 2757 | /* For PCH output, training FDI link */ |
2183 | if (IS_GEN6(dev)) | 2758 | if (IS_GEN6(dev)) |
@@ -2185,14 +2760,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) | |||
2185 | else | 2760 | else |
2186 | ironlake_fdi_link_train(crtc); | 2761 | ironlake_fdi_link_train(crtc); |
2187 | 2762 | ||
2188 | /* enable PCH DPLL */ | 2763 | intel_enable_pch_pll(dev_priv, pipe); |
2189 | reg = PCH_DPLL(pipe); | ||
2190 | temp = I915_READ(reg); | ||
2191 | if ((temp & DPLL_VCO_ENABLE) == 0) { | ||
2192 | I915_WRITE(reg, temp | DPLL_VCO_ENABLE); | ||
2193 | POSTING_READ(reg); | ||
2194 | udelay(200); | ||
2195 | } | ||
2196 | 2764 | ||
2197 | if (HAS_PCH_CPT(dev)) { | 2765 | if (HAS_PCH_CPT(dev)) { |
2198 | /* Be sure PCH DPLL SEL is set */ | 2766 | /* Be sure PCH DPLL SEL is set */ |
@@ -2204,7 +2772,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) | |||
2204 | I915_WRITE(PCH_DPLL_SEL, temp); | 2772 | I915_WRITE(PCH_DPLL_SEL, temp); |
2205 | } | 2773 | } |
2206 | 2774 | ||
2207 | /* set transcoder timing */ | 2775 | /* set transcoder timing, panel must allow it */ |
2776 | assert_panel_unlocked(dev_priv, pipe); | ||
2208 | I915_WRITE(TRANS_HTOTAL(pipe), I915_READ(HTOTAL(pipe))); | 2777 | I915_WRITE(TRANS_HTOTAL(pipe), I915_READ(HTOTAL(pipe))); |
2209 | I915_WRITE(TRANS_HBLANK(pipe), I915_READ(HBLANK(pipe))); | 2778 | I915_WRITE(TRANS_HBLANK(pipe), I915_READ(HBLANK(pipe))); |
2210 | I915_WRITE(TRANS_HSYNC(pipe), I915_READ(HSYNC(pipe))); | 2779 | I915_WRITE(TRANS_HSYNC(pipe), I915_READ(HSYNC(pipe))); |
@@ -2251,19 +2820,56 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) | |||
2251 | I915_WRITE(reg, temp); | 2820 | I915_WRITE(reg, temp); |
2252 | } | 2821 | } |
2253 | 2822 | ||
2254 | /* enable PCH transcoder */ | 2823 | intel_enable_transcoder(dev_priv, pipe); |
2255 | reg = TRANSCONF(pipe); | 2824 | } |
2256 | temp = I915_READ(reg); | 2825 | |
2257 | /* | 2826 | static void ironlake_crtc_enable(struct drm_crtc *crtc) |
2258 | * make the BPC in transcoder be consistent with | 2827 | { |
2259 | * that in pipeconf reg. | 2828 | struct drm_device *dev = crtc->dev; |
2260 | */ | 2829 | struct drm_i915_private *dev_priv = dev->dev_private; |
2261 | temp &= ~PIPE_BPC_MASK; | 2830 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
2262 | temp |= I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK; | 2831 | int pipe = intel_crtc->pipe; |
2263 | I915_WRITE(reg, temp | TRANS_ENABLE); | 2832 | int plane = intel_crtc->plane; |
2264 | if (wait_for(I915_READ(reg) & TRANS_STATE_ENABLE, 100)) | 2833 | u32 temp; |
2265 | DRM_ERROR("failed to enable transcoder %d\n", pipe); | 2834 | bool is_pch_port; |
2266 | done: | 2835 | |
2836 | if (intel_crtc->active) | ||
2837 | return; | ||
2838 | |||
2839 | intel_crtc->active = true; | ||
2840 | intel_update_watermarks(dev); | ||
2841 | |||
2842 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { | ||
2843 | temp = I915_READ(PCH_LVDS); | ||
2844 | if ((temp & LVDS_PORT_EN) == 0) | ||
2845 | I915_WRITE(PCH_LVDS, temp | LVDS_PORT_EN); | ||
2846 | } | ||
2847 | |||
2848 | is_pch_port = intel_crtc_driving_pch(crtc); | ||
2849 | |||
2850 | if (is_pch_port) | ||
2851 | ironlake_fdi_enable(crtc); | ||
2852 | else | ||
2853 | ironlake_fdi_disable(crtc); | ||
2854 | |||
2855 | /* Enable panel fitting for LVDS */ | ||
2856 | if (dev_priv->pch_pf_size && | ||
2857 | (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) || HAS_eDP)) { | ||
2858 | /* Force use of hard-coded filter coefficients | ||
2859 | * as some pre-programmed values are broken, | ||
2860 | * e.g. x201. | ||
2861 | */ | ||
2862 | I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3); | ||
2863 | I915_WRITE(PF_WIN_POS(pipe), dev_priv->pch_pf_pos); | ||
2864 | I915_WRITE(PF_WIN_SZ(pipe), dev_priv->pch_pf_size); | ||
2865 | } | ||
2866 | |||
2867 | intel_enable_pipe(dev_priv, pipe, is_pch_port); | ||
2868 | intel_enable_plane(dev_priv, plane, pipe); | ||
2869 | |||
2870 | if (is_pch_port) | ||
2871 | ironlake_pch_enable(crtc); | ||
2872 | |||
2267 | intel_crtc_load_lut(crtc); | 2873 | intel_crtc_load_lut(crtc); |
2268 | intel_update_fbc(dev); | 2874 | intel_update_fbc(dev); |
2269 | intel_crtc_update_cursor(crtc, true); | 2875 | intel_crtc_update_cursor(crtc, true); |
@@ -2285,116 +2891,58 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) | |||
2285 | drm_vblank_off(dev, pipe); | 2891 | drm_vblank_off(dev, pipe); |
2286 | intel_crtc_update_cursor(crtc, false); | 2892 | intel_crtc_update_cursor(crtc, false); |
2287 | 2893 | ||
2288 | /* Disable display plane */ | 2894 | intel_disable_plane(dev_priv, plane, pipe); |
2289 | reg = DSPCNTR(plane); | ||
2290 | temp = I915_READ(reg); | ||
2291 | if (temp & DISPLAY_PLANE_ENABLE) { | ||
2292 | I915_WRITE(reg, temp & ~DISPLAY_PLANE_ENABLE); | ||
2293 | intel_flush_display_plane(dev, plane); | ||
2294 | } | ||
2295 | 2895 | ||
2296 | if (dev_priv->cfb_plane == plane && | 2896 | if (dev_priv->cfb_plane == plane && |
2297 | dev_priv->display.disable_fbc) | 2897 | dev_priv->display.disable_fbc) |
2298 | dev_priv->display.disable_fbc(dev); | 2898 | dev_priv->display.disable_fbc(dev); |
2299 | 2899 | ||
2300 | /* disable cpu pipe, disable after all planes disabled */ | 2900 | intel_disable_pipe(dev_priv, pipe); |
2301 | reg = PIPECONF(pipe); | ||
2302 | temp = I915_READ(reg); | ||
2303 | if (temp & PIPECONF_ENABLE) { | ||
2304 | I915_WRITE(reg, temp & ~PIPECONF_ENABLE); | ||
2305 | POSTING_READ(reg); | ||
2306 | /* wait for cpu pipe off, pipe state */ | ||
2307 | intel_wait_for_pipe_off(dev, intel_crtc->pipe); | ||
2308 | } | ||
2309 | 2901 | ||
2310 | /* Disable PF */ | 2902 | /* Disable PF */ |
2311 | I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1, 0); | 2903 | I915_WRITE(PF_CTL(pipe), 0); |
2312 | I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ, 0); | 2904 | I915_WRITE(PF_WIN_SZ(pipe), 0); |
2313 | |||
2314 | /* disable CPU FDI tx and PCH FDI rx */ | ||
2315 | reg = FDI_TX_CTL(pipe); | ||
2316 | temp = I915_READ(reg); | ||
2317 | I915_WRITE(reg, temp & ~FDI_TX_ENABLE); | ||
2318 | POSTING_READ(reg); | ||
2319 | |||
2320 | reg = FDI_RX_CTL(pipe); | ||
2321 | temp = I915_READ(reg); | ||
2322 | temp &= ~(0x7 << 16); | ||
2323 | temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11; | ||
2324 | I915_WRITE(reg, temp & ~FDI_RX_ENABLE); | ||
2325 | |||
2326 | POSTING_READ(reg); | ||
2327 | udelay(100); | ||
2328 | |||
2329 | /* Ironlake workaround, disable clock pointer after downing FDI */ | ||
2330 | if (HAS_PCH_IBX(dev)) | ||
2331 | I915_WRITE(FDI_RX_CHICKEN(pipe), | ||
2332 | I915_READ(FDI_RX_CHICKEN(pipe) & | ||
2333 | ~FDI_RX_PHASE_SYNC_POINTER_ENABLE)); | ||
2334 | |||
2335 | /* still set train pattern 1 */ | ||
2336 | reg = FDI_TX_CTL(pipe); | ||
2337 | temp = I915_READ(reg); | ||
2338 | temp &= ~FDI_LINK_TRAIN_NONE; | ||
2339 | temp |= FDI_LINK_TRAIN_PATTERN_1; | ||
2340 | I915_WRITE(reg, temp); | ||
2341 | |||
2342 | reg = FDI_RX_CTL(pipe); | ||
2343 | temp = I915_READ(reg); | ||
2344 | if (HAS_PCH_CPT(dev)) { | ||
2345 | temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; | ||
2346 | temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; | ||
2347 | } else { | ||
2348 | temp &= ~FDI_LINK_TRAIN_NONE; | ||
2349 | temp |= FDI_LINK_TRAIN_PATTERN_1; | ||
2350 | } | ||
2351 | /* BPC in FDI rx is consistent with that in PIPECONF */ | ||
2352 | temp &= ~(0x07 << 16); | ||
2353 | temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11; | ||
2354 | I915_WRITE(reg, temp); | ||
2355 | 2905 | ||
2356 | POSTING_READ(reg); | 2906 | ironlake_fdi_disable(crtc); |
2357 | udelay(100); | ||
2358 | 2907 | ||
2359 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { | 2908 | /* This is a horrible layering violation; we should be doing this in |
2360 | temp = I915_READ(PCH_LVDS); | 2909 | * the connector/encoder ->prepare instead, but we don't always have |
2361 | if (temp & LVDS_PORT_EN) { | 2910 | * enough information there about the config to know whether it will |
2362 | I915_WRITE(PCH_LVDS, temp & ~LVDS_PORT_EN); | 2911 | * actually be necessary or just cause undesired flicker. |
2363 | POSTING_READ(PCH_LVDS); | 2912 | */ |
2364 | udelay(100); | 2913 | intel_disable_pch_ports(dev_priv, pipe); |
2365 | } | ||
2366 | } | ||
2367 | 2914 | ||
2368 | /* disable PCH transcoder */ | 2915 | intel_disable_transcoder(dev_priv, pipe); |
2369 | reg = TRANSCONF(plane); | ||
2370 | temp = I915_READ(reg); | ||
2371 | if (temp & TRANS_ENABLE) { | ||
2372 | I915_WRITE(reg, temp & ~TRANS_ENABLE); | ||
2373 | /* wait for PCH transcoder off, transcoder state */ | ||
2374 | if (wait_for((I915_READ(reg) & TRANS_STATE_ENABLE) == 0, 50)) | ||
2375 | DRM_ERROR("failed to disable transcoder\n"); | ||
2376 | } | ||
2377 | 2916 | ||
2378 | if (HAS_PCH_CPT(dev)) { | 2917 | if (HAS_PCH_CPT(dev)) { |
2379 | /* disable TRANS_DP_CTL */ | 2918 | /* disable TRANS_DP_CTL */ |
2380 | reg = TRANS_DP_CTL(pipe); | 2919 | reg = TRANS_DP_CTL(pipe); |
2381 | temp = I915_READ(reg); | 2920 | temp = I915_READ(reg); |
2382 | temp &= ~(TRANS_DP_OUTPUT_ENABLE | TRANS_DP_PORT_SEL_MASK); | 2921 | temp &= ~(TRANS_DP_OUTPUT_ENABLE | TRANS_DP_PORT_SEL_MASK); |
2922 | temp |= TRANS_DP_PORT_SEL_NONE; | ||
2383 | I915_WRITE(reg, temp); | 2923 | I915_WRITE(reg, temp); |
2384 | 2924 | ||
2385 | /* disable DPLL_SEL */ | 2925 | /* disable DPLL_SEL */ |
2386 | temp = I915_READ(PCH_DPLL_SEL); | 2926 | temp = I915_READ(PCH_DPLL_SEL); |
2387 | if (pipe == 0) | 2927 | switch (pipe) { |
2388 | temp &= ~(TRANSA_DPLL_ENABLE | TRANSA_DPLLB_SEL); | 2928 | case 0: |
2389 | else | 2929 | temp &= ~(TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL); |
2930 | break; | ||
2931 | case 1: | ||
2390 | temp &= ~(TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL); | 2932 | temp &= ~(TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL); |
2933 | break; | ||
2934 | case 2: | ||
2935 | /* FIXME: manage transcoder PLLs? */ | ||
2936 | temp &= ~(TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL); | ||
2937 | break; | ||
2938 | default: | ||
2939 | BUG(); /* wtf */ | ||
2940 | } | ||
2391 | I915_WRITE(PCH_DPLL_SEL, temp); | 2941 | I915_WRITE(PCH_DPLL_SEL, temp); |
2392 | } | 2942 | } |
2393 | 2943 | ||
2394 | /* disable PCH DPLL */ | 2944 | /* disable PCH DPLL */ |
2395 | reg = PCH_DPLL(pipe); | 2945 | intel_disable_pch_pll(dev_priv, pipe); |
2396 | temp = I915_READ(reg); | ||
2397 | I915_WRITE(reg, temp & ~DPLL_VCO_ENABLE); | ||
2398 | 2946 | ||
2399 | /* Switch from PCDclk to Rawclk */ | 2947 | /* Switch from PCDclk to Rawclk */ |
2400 | reg = FDI_RX_CTL(pipe); | 2948 | reg = FDI_RX_CTL(pipe); |
@@ -2451,9 +2999,12 @@ static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable) | |||
2451 | { | 2999 | { |
2452 | if (!enable && intel_crtc->overlay) { | 3000 | if (!enable && intel_crtc->overlay) { |
2453 | struct drm_device *dev = intel_crtc->base.dev; | 3001 | struct drm_device *dev = intel_crtc->base.dev; |
3002 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
2454 | 3003 | ||
2455 | mutex_lock(&dev->struct_mutex); | 3004 | mutex_lock(&dev->struct_mutex); |
2456 | (void) intel_overlay_switch_off(intel_crtc->overlay, false); | 3005 | dev_priv->mm.interruptible = false; |
3006 | (void) intel_overlay_switch_off(intel_crtc->overlay); | ||
3007 | dev_priv->mm.interruptible = true; | ||
2457 | mutex_unlock(&dev->struct_mutex); | 3008 | mutex_unlock(&dev->struct_mutex); |
2458 | } | 3009 | } |
2459 | 3010 | ||
@@ -2469,7 +3020,6 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) | |||
2469 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 3020 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
2470 | int pipe = intel_crtc->pipe; | 3021 | int pipe = intel_crtc->pipe; |
2471 | int plane = intel_crtc->plane; | 3022 | int plane = intel_crtc->plane; |
2472 | u32 reg, temp; | ||
2473 | 3023 | ||
2474 | if (intel_crtc->active) | 3024 | if (intel_crtc->active) |
2475 | return; | 3025 | return; |
@@ -2477,42 +3027,9 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) | |||
2477 | intel_crtc->active = true; | 3027 | intel_crtc->active = true; |
2478 | intel_update_watermarks(dev); | 3028 | intel_update_watermarks(dev); |
2479 | 3029 | ||
2480 | /* Enable the DPLL */ | 3030 | intel_enable_pll(dev_priv, pipe); |
2481 | reg = DPLL(pipe); | 3031 | intel_enable_pipe(dev_priv, pipe, false); |
2482 | temp = I915_READ(reg); | 3032 | intel_enable_plane(dev_priv, plane, pipe); |
2483 | if ((temp & DPLL_VCO_ENABLE) == 0) { | ||
2484 | I915_WRITE(reg, temp); | ||
2485 | |||
2486 | /* Wait for the clocks to stabilize. */ | ||
2487 | POSTING_READ(reg); | ||
2488 | udelay(150); | ||
2489 | |||
2490 | I915_WRITE(reg, temp | DPLL_VCO_ENABLE); | ||
2491 | |||
2492 | /* Wait for the clocks to stabilize. */ | ||
2493 | POSTING_READ(reg); | ||
2494 | udelay(150); | ||
2495 | |||
2496 | I915_WRITE(reg, temp | DPLL_VCO_ENABLE); | ||
2497 | |||
2498 | /* Wait for the clocks to stabilize. */ | ||
2499 | POSTING_READ(reg); | ||
2500 | udelay(150); | ||
2501 | } | ||
2502 | |||
2503 | /* Enable the pipe */ | ||
2504 | reg = PIPECONF(pipe); | ||
2505 | temp = I915_READ(reg); | ||
2506 | if ((temp & PIPECONF_ENABLE) == 0) | ||
2507 | I915_WRITE(reg, temp | PIPECONF_ENABLE); | ||
2508 | |||
2509 | /* Enable the plane */ | ||
2510 | reg = DSPCNTR(plane); | ||
2511 | temp = I915_READ(reg); | ||
2512 | if ((temp & DISPLAY_PLANE_ENABLE) == 0) { | ||
2513 | I915_WRITE(reg, temp | DISPLAY_PLANE_ENABLE); | ||
2514 | intel_flush_display_plane(dev, plane); | ||
2515 | } | ||
2516 | 3033 | ||
2517 | intel_crtc_load_lut(crtc); | 3034 | intel_crtc_load_lut(crtc); |
2518 | intel_update_fbc(dev); | 3035 | intel_update_fbc(dev); |
@@ -2529,7 +3046,6 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) | |||
2529 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 3046 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
2530 | int pipe = intel_crtc->pipe; | 3047 | int pipe = intel_crtc->pipe; |
2531 | int plane = intel_crtc->plane; | 3048 | int plane = intel_crtc->plane; |
2532 | u32 reg, temp; | ||
2533 | 3049 | ||
2534 | if (!intel_crtc->active) | 3050 | if (!intel_crtc->active) |
2535 | return; | 3051 | return; |
@@ -2544,45 +3060,10 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) | |||
2544 | dev_priv->display.disable_fbc) | 3060 | dev_priv->display.disable_fbc) |
2545 | dev_priv->display.disable_fbc(dev); | 3061 | dev_priv->display.disable_fbc(dev); |
2546 | 3062 | ||
2547 | /* Disable display plane */ | 3063 | intel_disable_plane(dev_priv, plane, pipe); |
2548 | reg = DSPCNTR(plane); | 3064 | intel_disable_pipe(dev_priv, pipe); |
2549 | temp = I915_READ(reg); | 3065 | intel_disable_pll(dev_priv, pipe); |
2550 | if (temp & DISPLAY_PLANE_ENABLE) { | ||
2551 | I915_WRITE(reg, temp & ~DISPLAY_PLANE_ENABLE); | ||
2552 | /* Flush the plane changes */ | ||
2553 | intel_flush_display_plane(dev, plane); | ||
2554 | |||
2555 | /* Wait for vblank for the disable to take effect */ | ||
2556 | if (IS_GEN2(dev)) | ||
2557 | intel_wait_for_vblank(dev, pipe); | ||
2558 | } | ||
2559 | |||
2560 | /* Don't disable pipe A or pipe A PLLs if needed */ | ||
2561 | if (pipe == 0 && (dev_priv->quirks & QUIRK_PIPEA_FORCE)) | ||
2562 | goto done; | ||
2563 | |||
2564 | /* Next, disable display pipes */ | ||
2565 | reg = PIPECONF(pipe); | ||
2566 | temp = I915_READ(reg); | ||
2567 | if (temp & PIPECONF_ENABLE) { | ||
2568 | I915_WRITE(reg, temp & ~PIPECONF_ENABLE); | ||
2569 | |||
2570 | /* Wait for the pipe to turn off */ | ||
2571 | POSTING_READ(reg); | ||
2572 | intel_wait_for_pipe_off(dev, pipe); | ||
2573 | } | ||
2574 | |||
2575 | reg = DPLL(pipe); | ||
2576 | temp = I915_READ(reg); | ||
2577 | if (temp & DPLL_VCO_ENABLE) { | ||
2578 | I915_WRITE(reg, temp & ~DPLL_VCO_ENABLE); | ||
2579 | |||
2580 | /* Wait for the clocks to turn off. */ | ||
2581 | POSTING_READ(reg); | ||
2582 | udelay(150); | ||
2583 | } | ||
2584 | 3066 | ||
2585 | done: | ||
2586 | intel_crtc->active = false; | 3067 | intel_crtc->active = false; |
2587 | intel_update_fbc(dev); | 3068 | intel_update_fbc(dev); |
2588 | intel_update_watermarks(dev); | 3069 | intel_update_watermarks(dev); |
@@ -2644,7 +3125,7 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
2644 | master_priv->sarea_priv->pipeB_h = enabled ? crtc->mode.vdisplay : 0; | 3125 | master_priv->sarea_priv->pipeB_h = enabled ? crtc->mode.vdisplay : 0; |
2645 | break; | 3126 | break; |
2646 | default: | 3127 | default: |
2647 | DRM_ERROR("Can't update pipe %d in SAREA\n", pipe); | 3128 | DRM_ERROR("Can't update pipe %c in SAREA\n", pipe_name(pipe)); |
2648 | break; | 3129 | break; |
2649 | } | 3130 | } |
2650 | } | 3131 | } |
@@ -2841,77 +3322,77 @@ struct intel_watermark_params { | |||
2841 | }; | 3322 | }; |
2842 | 3323 | ||
2843 | /* Pineview has different values for various configs */ | 3324 | /* Pineview has different values for various configs */ |
2844 | static struct intel_watermark_params pineview_display_wm = { | 3325 | static const struct intel_watermark_params pineview_display_wm = { |
2845 | PINEVIEW_DISPLAY_FIFO, | 3326 | PINEVIEW_DISPLAY_FIFO, |
2846 | PINEVIEW_MAX_WM, | 3327 | PINEVIEW_MAX_WM, |
2847 | PINEVIEW_DFT_WM, | 3328 | PINEVIEW_DFT_WM, |
2848 | PINEVIEW_GUARD_WM, | 3329 | PINEVIEW_GUARD_WM, |
2849 | PINEVIEW_FIFO_LINE_SIZE | 3330 | PINEVIEW_FIFO_LINE_SIZE |
2850 | }; | 3331 | }; |
2851 | static struct intel_watermark_params pineview_display_hplloff_wm = { | 3332 | static const struct intel_watermark_params pineview_display_hplloff_wm = { |
2852 | PINEVIEW_DISPLAY_FIFO, | 3333 | PINEVIEW_DISPLAY_FIFO, |
2853 | PINEVIEW_MAX_WM, | 3334 | PINEVIEW_MAX_WM, |
2854 | PINEVIEW_DFT_HPLLOFF_WM, | 3335 | PINEVIEW_DFT_HPLLOFF_WM, |
2855 | PINEVIEW_GUARD_WM, | 3336 | PINEVIEW_GUARD_WM, |
2856 | PINEVIEW_FIFO_LINE_SIZE | 3337 | PINEVIEW_FIFO_LINE_SIZE |
2857 | }; | 3338 | }; |
2858 | static struct intel_watermark_params pineview_cursor_wm = { | 3339 | static const struct intel_watermark_params pineview_cursor_wm = { |
2859 | PINEVIEW_CURSOR_FIFO, | 3340 | PINEVIEW_CURSOR_FIFO, |
2860 | PINEVIEW_CURSOR_MAX_WM, | 3341 | PINEVIEW_CURSOR_MAX_WM, |
2861 | PINEVIEW_CURSOR_DFT_WM, | 3342 | PINEVIEW_CURSOR_DFT_WM, |
2862 | PINEVIEW_CURSOR_GUARD_WM, | 3343 | PINEVIEW_CURSOR_GUARD_WM, |
2863 | PINEVIEW_FIFO_LINE_SIZE, | 3344 | PINEVIEW_FIFO_LINE_SIZE, |
2864 | }; | 3345 | }; |
2865 | static struct intel_watermark_params pineview_cursor_hplloff_wm = { | 3346 | static const struct intel_watermark_params pineview_cursor_hplloff_wm = { |
2866 | PINEVIEW_CURSOR_FIFO, | 3347 | PINEVIEW_CURSOR_FIFO, |
2867 | PINEVIEW_CURSOR_MAX_WM, | 3348 | PINEVIEW_CURSOR_MAX_WM, |
2868 | PINEVIEW_CURSOR_DFT_WM, | 3349 | PINEVIEW_CURSOR_DFT_WM, |
2869 | PINEVIEW_CURSOR_GUARD_WM, | 3350 | PINEVIEW_CURSOR_GUARD_WM, |
2870 | PINEVIEW_FIFO_LINE_SIZE | 3351 | PINEVIEW_FIFO_LINE_SIZE |
2871 | }; | 3352 | }; |
2872 | static struct intel_watermark_params g4x_wm_info = { | 3353 | static const struct intel_watermark_params g4x_wm_info = { |
2873 | G4X_FIFO_SIZE, | 3354 | G4X_FIFO_SIZE, |
2874 | G4X_MAX_WM, | 3355 | G4X_MAX_WM, |
2875 | G4X_MAX_WM, | 3356 | G4X_MAX_WM, |
2876 | 2, | 3357 | 2, |
2877 | G4X_FIFO_LINE_SIZE, | 3358 | G4X_FIFO_LINE_SIZE, |
2878 | }; | 3359 | }; |
2879 | static struct intel_watermark_params g4x_cursor_wm_info = { | 3360 | static const struct intel_watermark_params g4x_cursor_wm_info = { |
2880 | I965_CURSOR_FIFO, | 3361 | I965_CURSOR_FIFO, |
2881 | I965_CURSOR_MAX_WM, | 3362 | I965_CURSOR_MAX_WM, |
2882 | I965_CURSOR_DFT_WM, | 3363 | I965_CURSOR_DFT_WM, |
2883 | 2, | 3364 | 2, |
2884 | G4X_FIFO_LINE_SIZE, | 3365 | G4X_FIFO_LINE_SIZE, |
2885 | }; | 3366 | }; |
2886 | static struct intel_watermark_params i965_cursor_wm_info = { | 3367 | static const struct intel_watermark_params i965_cursor_wm_info = { |
2887 | I965_CURSOR_FIFO, | 3368 | I965_CURSOR_FIFO, |
2888 | I965_CURSOR_MAX_WM, | 3369 | I965_CURSOR_MAX_WM, |
2889 | I965_CURSOR_DFT_WM, | 3370 | I965_CURSOR_DFT_WM, |
2890 | 2, | 3371 | 2, |
2891 | I915_FIFO_LINE_SIZE, | 3372 | I915_FIFO_LINE_SIZE, |
2892 | }; | 3373 | }; |
2893 | static struct intel_watermark_params i945_wm_info = { | 3374 | static const struct intel_watermark_params i945_wm_info = { |
2894 | I945_FIFO_SIZE, | 3375 | I945_FIFO_SIZE, |
2895 | I915_MAX_WM, | 3376 | I915_MAX_WM, |
2896 | 1, | 3377 | 1, |
2897 | 2, | 3378 | 2, |
2898 | I915_FIFO_LINE_SIZE | 3379 | I915_FIFO_LINE_SIZE |
2899 | }; | 3380 | }; |
2900 | static struct intel_watermark_params i915_wm_info = { | 3381 | static const struct intel_watermark_params i915_wm_info = { |
2901 | I915_FIFO_SIZE, | 3382 | I915_FIFO_SIZE, |
2902 | I915_MAX_WM, | 3383 | I915_MAX_WM, |
2903 | 1, | 3384 | 1, |
2904 | 2, | 3385 | 2, |
2905 | I915_FIFO_LINE_SIZE | 3386 | I915_FIFO_LINE_SIZE |
2906 | }; | 3387 | }; |
2907 | static struct intel_watermark_params i855_wm_info = { | 3388 | static const struct intel_watermark_params i855_wm_info = { |
2908 | I855GM_FIFO_SIZE, | 3389 | I855GM_FIFO_SIZE, |
2909 | I915_MAX_WM, | 3390 | I915_MAX_WM, |
2910 | 1, | 3391 | 1, |
2911 | 2, | 3392 | 2, |
2912 | I830_FIFO_LINE_SIZE | 3393 | I830_FIFO_LINE_SIZE |
2913 | }; | 3394 | }; |
2914 | static struct intel_watermark_params i830_wm_info = { | 3395 | static const struct intel_watermark_params i830_wm_info = { |
2915 | I830_FIFO_SIZE, | 3396 | I830_FIFO_SIZE, |
2916 | I915_MAX_WM, | 3397 | I915_MAX_WM, |
2917 | 1, | 3398 | 1, |
@@ -2919,31 +3400,28 @@ static struct intel_watermark_params i830_wm_info = { | |||
2919 | I830_FIFO_LINE_SIZE | 3400 | I830_FIFO_LINE_SIZE |
2920 | }; | 3401 | }; |
2921 | 3402 | ||
2922 | static struct intel_watermark_params ironlake_display_wm_info = { | 3403 | static const struct intel_watermark_params ironlake_display_wm_info = { |
2923 | ILK_DISPLAY_FIFO, | 3404 | ILK_DISPLAY_FIFO, |
2924 | ILK_DISPLAY_MAXWM, | 3405 | ILK_DISPLAY_MAXWM, |
2925 | ILK_DISPLAY_DFTWM, | 3406 | ILK_DISPLAY_DFTWM, |
2926 | 2, | 3407 | 2, |
2927 | ILK_FIFO_LINE_SIZE | 3408 | ILK_FIFO_LINE_SIZE |
2928 | }; | 3409 | }; |
2929 | 3410 | static const struct intel_watermark_params ironlake_cursor_wm_info = { | |
2930 | static struct intel_watermark_params ironlake_cursor_wm_info = { | ||
2931 | ILK_CURSOR_FIFO, | 3411 | ILK_CURSOR_FIFO, |
2932 | ILK_CURSOR_MAXWM, | 3412 | ILK_CURSOR_MAXWM, |
2933 | ILK_CURSOR_DFTWM, | 3413 | ILK_CURSOR_DFTWM, |
2934 | 2, | 3414 | 2, |
2935 | ILK_FIFO_LINE_SIZE | 3415 | ILK_FIFO_LINE_SIZE |
2936 | }; | 3416 | }; |
2937 | 3417 | static const struct intel_watermark_params ironlake_display_srwm_info = { | |
2938 | static struct intel_watermark_params ironlake_display_srwm_info = { | ||
2939 | ILK_DISPLAY_SR_FIFO, | 3418 | ILK_DISPLAY_SR_FIFO, |
2940 | ILK_DISPLAY_MAX_SRWM, | 3419 | ILK_DISPLAY_MAX_SRWM, |
2941 | ILK_DISPLAY_DFT_SRWM, | 3420 | ILK_DISPLAY_DFT_SRWM, |
2942 | 2, | 3421 | 2, |
2943 | ILK_FIFO_LINE_SIZE | 3422 | ILK_FIFO_LINE_SIZE |
2944 | }; | 3423 | }; |
2945 | 3424 | static const struct intel_watermark_params ironlake_cursor_srwm_info = { | |
2946 | static struct intel_watermark_params ironlake_cursor_srwm_info = { | ||
2947 | ILK_CURSOR_SR_FIFO, | 3425 | ILK_CURSOR_SR_FIFO, |
2948 | ILK_CURSOR_MAX_SRWM, | 3426 | ILK_CURSOR_MAX_SRWM, |
2949 | ILK_CURSOR_DFT_SRWM, | 3427 | ILK_CURSOR_DFT_SRWM, |
@@ -2951,31 +3429,28 @@ static struct intel_watermark_params ironlake_cursor_srwm_info = { | |||
2951 | ILK_FIFO_LINE_SIZE | 3429 | ILK_FIFO_LINE_SIZE |
2952 | }; | 3430 | }; |
2953 | 3431 | ||
2954 | static struct intel_watermark_params sandybridge_display_wm_info = { | 3432 | static const struct intel_watermark_params sandybridge_display_wm_info = { |
2955 | SNB_DISPLAY_FIFO, | 3433 | SNB_DISPLAY_FIFO, |
2956 | SNB_DISPLAY_MAXWM, | 3434 | SNB_DISPLAY_MAXWM, |
2957 | SNB_DISPLAY_DFTWM, | 3435 | SNB_DISPLAY_DFTWM, |
2958 | 2, | 3436 | 2, |
2959 | SNB_FIFO_LINE_SIZE | 3437 | SNB_FIFO_LINE_SIZE |
2960 | }; | 3438 | }; |
2961 | 3439 | static const struct intel_watermark_params sandybridge_cursor_wm_info = { | |
2962 | static struct intel_watermark_params sandybridge_cursor_wm_info = { | ||
2963 | SNB_CURSOR_FIFO, | 3440 | SNB_CURSOR_FIFO, |
2964 | SNB_CURSOR_MAXWM, | 3441 | SNB_CURSOR_MAXWM, |
2965 | SNB_CURSOR_DFTWM, | 3442 | SNB_CURSOR_DFTWM, |
2966 | 2, | 3443 | 2, |
2967 | SNB_FIFO_LINE_SIZE | 3444 | SNB_FIFO_LINE_SIZE |
2968 | }; | 3445 | }; |
2969 | 3446 | static const struct intel_watermark_params sandybridge_display_srwm_info = { | |
2970 | static struct intel_watermark_params sandybridge_display_srwm_info = { | ||
2971 | SNB_DISPLAY_SR_FIFO, | 3447 | SNB_DISPLAY_SR_FIFO, |
2972 | SNB_DISPLAY_MAX_SRWM, | 3448 | SNB_DISPLAY_MAX_SRWM, |
2973 | SNB_DISPLAY_DFT_SRWM, | 3449 | SNB_DISPLAY_DFT_SRWM, |
2974 | 2, | 3450 | 2, |
2975 | SNB_FIFO_LINE_SIZE | 3451 | SNB_FIFO_LINE_SIZE |
2976 | }; | 3452 | }; |
2977 | 3453 | static const struct intel_watermark_params sandybridge_cursor_srwm_info = { | |
2978 | static struct intel_watermark_params sandybridge_cursor_srwm_info = { | ||
2979 | SNB_CURSOR_SR_FIFO, | 3454 | SNB_CURSOR_SR_FIFO, |
2980 | SNB_CURSOR_MAX_SRWM, | 3455 | SNB_CURSOR_MAX_SRWM, |
2981 | SNB_CURSOR_DFT_SRWM, | 3456 | SNB_CURSOR_DFT_SRWM, |
@@ -3003,7 +3478,8 @@ static struct intel_watermark_params sandybridge_cursor_srwm_info = { | |||
3003 | * will occur, and a display engine hang could result. | 3478 | * will occur, and a display engine hang could result. |
3004 | */ | 3479 | */ |
3005 | static unsigned long intel_calculate_wm(unsigned long clock_in_khz, | 3480 | static unsigned long intel_calculate_wm(unsigned long clock_in_khz, |
3006 | struct intel_watermark_params *wm, | 3481 | const struct intel_watermark_params *wm, |
3482 | int fifo_size, | ||
3007 | int pixel_size, | 3483 | int pixel_size, |
3008 | unsigned long latency_ns) | 3484 | unsigned long latency_ns) |
3009 | { | 3485 | { |
@@ -3021,7 +3497,7 @@ static unsigned long intel_calculate_wm(unsigned long clock_in_khz, | |||
3021 | 3497 | ||
3022 | DRM_DEBUG_KMS("FIFO entries required for mode: %d\n", entries_required); | 3498 | DRM_DEBUG_KMS("FIFO entries required for mode: %d\n", entries_required); |
3023 | 3499 | ||
3024 | wm_size = wm->fifo_size - (entries_required + wm->guard_size); | 3500 | wm_size = fifo_size - (entries_required + wm->guard_size); |
3025 | 3501 | ||
3026 | DRM_DEBUG_KMS("FIFO watermark level: %d\n", wm_size); | 3502 | DRM_DEBUG_KMS("FIFO watermark level: %d\n", wm_size); |
3027 | 3503 | ||
@@ -3194,15 +3670,28 @@ static int i830_get_fifo_size(struct drm_device *dev, int plane) | |||
3194 | return size; | 3670 | return size; |
3195 | } | 3671 | } |
3196 | 3672 | ||
3197 | static void pineview_update_wm(struct drm_device *dev, int planea_clock, | 3673 | static struct drm_crtc *single_enabled_crtc(struct drm_device *dev) |
3198 | int planeb_clock, int sr_hdisplay, int unused, | 3674 | { |
3199 | int pixel_size) | 3675 | struct drm_crtc *crtc, *enabled = NULL; |
3676 | |||
3677 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||
3678 | if (crtc->enabled && crtc->fb) { | ||
3679 | if (enabled) | ||
3680 | return NULL; | ||
3681 | enabled = crtc; | ||
3682 | } | ||
3683 | } | ||
3684 | |||
3685 | return enabled; | ||
3686 | } | ||
3687 | |||
3688 | static void pineview_update_wm(struct drm_device *dev) | ||
3200 | { | 3689 | { |
3201 | struct drm_i915_private *dev_priv = dev->dev_private; | 3690 | struct drm_i915_private *dev_priv = dev->dev_private; |
3691 | struct drm_crtc *crtc; | ||
3202 | const struct cxsr_latency *latency; | 3692 | const struct cxsr_latency *latency; |
3203 | u32 reg; | 3693 | u32 reg; |
3204 | unsigned long wm; | 3694 | unsigned long wm; |
3205 | int sr_clock; | ||
3206 | 3695 | ||
3207 | latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->is_ddr3, | 3696 | latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->is_ddr3, |
3208 | dev_priv->fsb_freq, dev_priv->mem_freq); | 3697 | dev_priv->fsb_freq, dev_priv->mem_freq); |
@@ -3212,11 +3701,14 @@ static void pineview_update_wm(struct drm_device *dev, int planea_clock, | |||
3212 | return; | 3701 | return; |
3213 | } | 3702 | } |
3214 | 3703 | ||
3215 | if (!planea_clock || !planeb_clock) { | 3704 | crtc = single_enabled_crtc(dev); |
3216 | sr_clock = planea_clock ? planea_clock : planeb_clock; | 3705 | if (crtc) { |
3706 | int clock = crtc->mode.clock; | ||
3707 | int pixel_size = crtc->fb->bits_per_pixel / 8; | ||
3217 | 3708 | ||
3218 | /* Display SR */ | 3709 | /* Display SR */ |
3219 | wm = intel_calculate_wm(sr_clock, &pineview_display_wm, | 3710 | wm = intel_calculate_wm(clock, &pineview_display_wm, |
3711 | pineview_display_wm.fifo_size, | ||
3220 | pixel_size, latency->display_sr); | 3712 | pixel_size, latency->display_sr); |
3221 | reg = I915_READ(DSPFW1); | 3713 | reg = I915_READ(DSPFW1); |
3222 | reg &= ~DSPFW_SR_MASK; | 3714 | reg &= ~DSPFW_SR_MASK; |
@@ -3225,7 +3717,8 @@ static void pineview_update_wm(struct drm_device *dev, int planea_clock, | |||
3225 | DRM_DEBUG_KMS("DSPFW1 register is %x\n", reg); | 3717 | DRM_DEBUG_KMS("DSPFW1 register is %x\n", reg); |
3226 | 3718 | ||
3227 | /* cursor SR */ | 3719 | /* cursor SR */ |
3228 | wm = intel_calculate_wm(sr_clock, &pineview_cursor_wm, | 3720 | wm = intel_calculate_wm(clock, &pineview_cursor_wm, |
3721 | pineview_display_wm.fifo_size, | ||
3229 | pixel_size, latency->cursor_sr); | 3722 | pixel_size, latency->cursor_sr); |
3230 | reg = I915_READ(DSPFW3); | 3723 | reg = I915_READ(DSPFW3); |
3231 | reg &= ~DSPFW_CURSOR_SR_MASK; | 3724 | reg &= ~DSPFW_CURSOR_SR_MASK; |
@@ -3233,7 +3726,8 @@ static void pineview_update_wm(struct drm_device *dev, int planea_clock, | |||
3233 | I915_WRITE(DSPFW3, reg); | 3726 | I915_WRITE(DSPFW3, reg); |
3234 | 3727 | ||
3235 | /* Display HPLL off SR */ | 3728 | /* Display HPLL off SR */ |
3236 | wm = intel_calculate_wm(sr_clock, &pineview_display_hplloff_wm, | 3729 | wm = intel_calculate_wm(clock, &pineview_display_hplloff_wm, |
3730 | pineview_display_hplloff_wm.fifo_size, | ||
3237 | pixel_size, latency->display_hpll_disable); | 3731 | pixel_size, latency->display_hpll_disable); |
3238 | reg = I915_READ(DSPFW3); | 3732 | reg = I915_READ(DSPFW3); |
3239 | reg &= ~DSPFW_HPLL_SR_MASK; | 3733 | reg &= ~DSPFW_HPLL_SR_MASK; |
@@ -3241,7 +3735,8 @@ static void pineview_update_wm(struct drm_device *dev, int planea_clock, | |||
3241 | I915_WRITE(DSPFW3, reg); | 3735 | I915_WRITE(DSPFW3, reg); |
3242 | 3736 | ||
3243 | /* cursor HPLL off SR */ | 3737 | /* cursor HPLL off SR */ |
3244 | wm = intel_calculate_wm(sr_clock, &pineview_cursor_hplloff_wm, | 3738 | wm = intel_calculate_wm(clock, &pineview_cursor_hplloff_wm, |
3739 | pineview_display_hplloff_wm.fifo_size, | ||
3245 | pixel_size, latency->cursor_hpll_disable); | 3740 | pixel_size, latency->cursor_hpll_disable); |
3246 | reg = I915_READ(DSPFW3); | 3741 | reg = I915_READ(DSPFW3); |
3247 | reg &= ~DSPFW_HPLL_CURSOR_MASK; | 3742 | reg &= ~DSPFW_HPLL_CURSOR_MASK; |
@@ -3259,125 +3754,229 @@ static void pineview_update_wm(struct drm_device *dev, int planea_clock, | |||
3259 | } | 3754 | } |
3260 | } | 3755 | } |
3261 | 3756 | ||
3262 | static void g4x_update_wm(struct drm_device *dev, int planea_clock, | 3757 | static bool g4x_compute_wm0(struct drm_device *dev, |
3263 | int planeb_clock, int sr_hdisplay, int sr_htotal, | 3758 | int plane, |
3264 | int pixel_size) | 3759 | const struct intel_watermark_params *display, |
3760 | int display_latency_ns, | ||
3761 | const struct intel_watermark_params *cursor, | ||
3762 | int cursor_latency_ns, | ||
3763 | int *plane_wm, | ||
3764 | int *cursor_wm) | ||
3265 | { | 3765 | { |
3266 | struct drm_i915_private *dev_priv = dev->dev_private; | 3766 | struct drm_crtc *crtc; |
3267 | int total_size, cacheline_size; | 3767 | int htotal, hdisplay, clock, pixel_size; |
3268 | int planea_wm, planeb_wm, cursora_wm, cursorb_wm, cursor_sr; | 3768 | int line_time_us, line_count; |
3269 | struct intel_watermark_params planea_params, planeb_params; | 3769 | int entries, tlb_miss; |
3270 | unsigned long line_time_us; | ||
3271 | int sr_clock, sr_entries = 0, entries_required; | ||
3272 | 3770 | ||
3273 | /* Create copies of the base settings for each pipe */ | 3771 | crtc = intel_get_crtc_for_plane(dev, plane); |
3274 | planea_params = planeb_params = g4x_wm_info; | 3772 | if (crtc->fb == NULL || !crtc->enabled) |
3773 | return false; | ||
3275 | 3774 | ||
3276 | /* Grab a couple of global values before we overwrite them */ | 3775 | htotal = crtc->mode.htotal; |
3277 | total_size = planea_params.fifo_size; | 3776 | hdisplay = crtc->mode.hdisplay; |
3278 | cacheline_size = planea_params.cacheline_size; | 3777 | clock = crtc->mode.clock; |
3778 | pixel_size = crtc->fb->bits_per_pixel / 8; | ||
3279 | 3779 | ||
3280 | /* | 3780 | /* Use the small buffer method to calculate plane watermark */ |
3281 | * Note: we need to make sure we don't overflow for various clock & | 3781 | entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000; |
3282 | * latency values. | 3782 | tlb_miss = display->fifo_size*display->cacheline_size - hdisplay * 8; |
3283 | * clocks go from a few thousand to several hundred thousand. | 3783 | if (tlb_miss > 0) |
3284 | * latency is usually a few thousand | 3784 | entries += tlb_miss; |
3285 | */ | 3785 | entries = DIV_ROUND_UP(entries, display->cacheline_size); |
3286 | entries_required = ((planea_clock / 1000) * pixel_size * latency_ns) / | 3786 | *plane_wm = entries + display->guard_size; |
3287 | 1000; | 3787 | if (*plane_wm > (int)display->max_wm) |
3288 | entries_required = DIV_ROUND_UP(entries_required, G4X_FIFO_LINE_SIZE); | 3788 | *plane_wm = display->max_wm; |
3289 | planea_wm = entries_required + planea_params.guard_size; | ||
3290 | 3789 | ||
3291 | entries_required = ((planeb_clock / 1000) * pixel_size * latency_ns) / | 3790 | /* Use the large buffer method to calculate cursor watermark */ |
3292 | 1000; | 3791 | line_time_us = ((htotal * 1000) / clock); |
3293 | entries_required = DIV_ROUND_UP(entries_required, G4X_FIFO_LINE_SIZE); | 3792 | line_count = (cursor_latency_ns / line_time_us + 1000) / 1000; |
3294 | planeb_wm = entries_required + planeb_params.guard_size; | 3793 | entries = line_count * 64 * pixel_size; |
3794 | tlb_miss = cursor->fifo_size*cursor->cacheline_size - hdisplay * 8; | ||
3795 | if (tlb_miss > 0) | ||
3796 | entries += tlb_miss; | ||
3797 | entries = DIV_ROUND_UP(entries, cursor->cacheline_size); | ||
3798 | *cursor_wm = entries + cursor->guard_size; | ||
3799 | if (*cursor_wm > (int)cursor->max_wm) | ||
3800 | *cursor_wm = (int)cursor->max_wm; | ||
3295 | 3801 | ||
3296 | cursora_wm = cursorb_wm = 16; | 3802 | return true; |
3297 | cursor_sr = 32; | 3803 | } |
3298 | 3804 | ||
3299 | DRM_DEBUG("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm); | 3805 | /* |
3806 | * Check the wm result. | ||
3807 | * | ||
3808 | * If any calculated watermark values is larger than the maximum value that | ||
3809 | * can be programmed into the associated watermark register, that watermark | ||
3810 | * must be disabled. | ||
3811 | */ | ||
3812 | static bool g4x_check_srwm(struct drm_device *dev, | ||
3813 | int display_wm, int cursor_wm, | ||
3814 | const struct intel_watermark_params *display, | ||
3815 | const struct intel_watermark_params *cursor) | ||
3816 | { | ||
3817 | DRM_DEBUG_KMS("SR watermark: display plane %d, cursor %d\n", | ||
3818 | display_wm, cursor_wm); | ||
3300 | 3819 | ||
3301 | /* Calc sr entries for one plane configs */ | 3820 | if (display_wm > display->max_wm) { |
3302 | if (sr_hdisplay && (!planea_clock || !planeb_clock)) { | 3821 | DRM_DEBUG_KMS("display watermark is too large(%d), disabling\n", |
3303 | /* self-refresh has much higher latency */ | 3822 | display_wm, display->max_wm); |
3304 | static const int sr_latency_ns = 12000; | 3823 | return false; |
3824 | } | ||
3305 | 3825 | ||
3306 | sr_clock = planea_clock ? planea_clock : planeb_clock; | 3826 | if (cursor_wm > cursor->max_wm) { |
3307 | line_time_us = ((sr_htotal * 1000) / sr_clock); | 3827 | DRM_DEBUG_KMS("cursor watermark is too large(%d), disabling\n", |
3828 | cursor_wm, cursor->max_wm); | ||
3829 | return false; | ||
3830 | } | ||
3308 | 3831 | ||
3309 | /* Use ns/us then divide to preserve precision */ | 3832 | if (!(display_wm || cursor_wm)) { |
3310 | sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * | 3833 | DRM_DEBUG_KMS("SR latency is 0, disabling\n"); |
3311 | pixel_size * sr_hdisplay; | 3834 | return false; |
3312 | sr_entries = DIV_ROUND_UP(sr_entries, cacheline_size); | 3835 | } |
3313 | |||
3314 | entries_required = (((sr_latency_ns / line_time_us) + | ||
3315 | 1000) / 1000) * pixel_size * 64; | ||
3316 | entries_required = DIV_ROUND_UP(entries_required, | ||
3317 | g4x_cursor_wm_info.cacheline_size); | ||
3318 | cursor_sr = entries_required + g4x_cursor_wm_info.guard_size; | ||
3319 | |||
3320 | if (cursor_sr > g4x_cursor_wm_info.max_wm) | ||
3321 | cursor_sr = g4x_cursor_wm_info.max_wm; | ||
3322 | DRM_DEBUG_KMS("self-refresh watermark: display plane %d " | ||
3323 | "cursor %d\n", sr_entries, cursor_sr); | ||
3324 | 3836 | ||
3325 | I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN); | 3837 | return true; |
3326 | } else { | 3838 | } |
3327 | /* Turn off self refresh if both pipes are enabled */ | 3839 | |
3328 | I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF) | 3840 | static bool g4x_compute_srwm(struct drm_device *dev, |
3329 | & ~FW_BLC_SELF_EN); | 3841 | int plane, |
3842 | int latency_ns, | ||
3843 | const struct intel_watermark_params *display, | ||
3844 | const struct intel_watermark_params *cursor, | ||
3845 | int *display_wm, int *cursor_wm) | ||
3846 | { | ||
3847 | struct drm_crtc *crtc; | ||
3848 | int hdisplay, htotal, pixel_size, clock; | ||
3849 | unsigned long line_time_us; | ||
3850 | int line_count, line_size; | ||
3851 | int small, large; | ||
3852 | int entries; | ||
3853 | |||
3854 | if (!latency_ns) { | ||
3855 | *display_wm = *cursor_wm = 0; | ||
3856 | return false; | ||
3330 | } | 3857 | } |
3331 | 3858 | ||
3332 | DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, SR %d\n", | 3859 | crtc = intel_get_crtc_for_plane(dev, plane); |
3333 | planea_wm, planeb_wm, sr_entries); | 3860 | hdisplay = crtc->mode.hdisplay; |
3861 | htotal = crtc->mode.htotal; | ||
3862 | clock = crtc->mode.clock; | ||
3863 | pixel_size = crtc->fb->bits_per_pixel / 8; | ||
3334 | 3864 | ||
3335 | planea_wm &= 0x3f; | 3865 | line_time_us = (htotal * 1000) / clock; |
3336 | planeb_wm &= 0x3f; | 3866 | line_count = (latency_ns / line_time_us + 1000) / 1000; |
3867 | line_size = hdisplay * pixel_size; | ||
3337 | 3868 | ||
3338 | I915_WRITE(DSPFW1, (sr_entries << DSPFW_SR_SHIFT) | | 3869 | /* Use the minimum of the small and large buffer method for primary */ |
3870 | small = ((clock * pixel_size / 1000) * latency_ns) / 1000; | ||
3871 | large = line_count * line_size; | ||
3872 | |||
3873 | entries = DIV_ROUND_UP(min(small, large), display->cacheline_size); | ||
3874 | *display_wm = entries + display->guard_size; | ||
3875 | |||
3876 | /* calculate the self-refresh watermark for display cursor */ | ||
3877 | entries = line_count * pixel_size * 64; | ||
3878 | entries = DIV_ROUND_UP(entries, cursor->cacheline_size); | ||
3879 | *cursor_wm = entries + cursor->guard_size; | ||
3880 | |||
3881 | return g4x_check_srwm(dev, | ||
3882 | *display_wm, *cursor_wm, | ||
3883 | display, cursor); | ||
3884 | } | ||
3885 | |||
3886 | static inline bool single_plane_enabled(unsigned int mask) | ||
3887 | { | ||
3888 | return mask && (mask & -mask) == 0; | ||
3889 | } | ||
3890 | |||
3891 | static void g4x_update_wm(struct drm_device *dev) | ||
3892 | { | ||
3893 | static const int sr_latency_ns = 12000; | ||
3894 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
3895 | int planea_wm, planeb_wm, cursora_wm, cursorb_wm; | ||
3896 | int plane_sr, cursor_sr; | ||
3897 | unsigned int enabled = 0; | ||
3898 | |||
3899 | if (g4x_compute_wm0(dev, 0, | ||
3900 | &g4x_wm_info, latency_ns, | ||
3901 | &g4x_cursor_wm_info, latency_ns, | ||
3902 | &planea_wm, &cursora_wm)) | ||
3903 | enabled |= 1; | ||
3904 | |||
3905 | if (g4x_compute_wm0(dev, 1, | ||
3906 | &g4x_wm_info, latency_ns, | ||
3907 | &g4x_cursor_wm_info, latency_ns, | ||
3908 | &planeb_wm, &cursorb_wm)) | ||
3909 | enabled |= 2; | ||
3910 | |||
3911 | plane_sr = cursor_sr = 0; | ||
3912 | if (single_plane_enabled(enabled) && | ||
3913 | g4x_compute_srwm(dev, ffs(enabled) - 1, | ||
3914 | sr_latency_ns, | ||
3915 | &g4x_wm_info, | ||
3916 | &g4x_cursor_wm_info, | ||
3917 | &plane_sr, &cursor_sr)) | ||
3918 | I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN); | ||
3919 | else | ||
3920 | I915_WRITE(FW_BLC_SELF, | ||
3921 | I915_READ(FW_BLC_SELF) & ~FW_BLC_SELF_EN); | ||
3922 | |||
3923 | DRM_DEBUG_KMS("Setting FIFO watermarks - A: plane=%d, cursor=%d, B: plane=%d, cursor=%d, SR: plane=%d, cursor=%d\n", | ||
3924 | planea_wm, cursora_wm, | ||
3925 | planeb_wm, cursorb_wm, | ||
3926 | plane_sr, cursor_sr); | ||
3927 | |||
3928 | I915_WRITE(DSPFW1, | ||
3929 | (plane_sr << DSPFW_SR_SHIFT) | | ||
3339 | (cursorb_wm << DSPFW_CURSORB_SHIFT) | | 3930 | (cursorb_wm << DSPFW_CURSORB_SHIFT) | |
3340 | (planeb_wm << DSPFW_PLANEB_SHIFT) | planea_wm); | 3931 | (planeb_wm << DSPFW_PLANEB_SHIFT) | |
3341 | I915_WRITE(DSPFW2, (I915_READ(DSPFW2) & DSPFW_CURSORA_MASK) | | 3932 | planea_wm); |
3933 | I915_WRITE(DSPFW2, | ||
3934 | (I915_READ(DSPFW2) & DSPFW_CURSORA_MASK) | | ||
3342 | (cursora_wm << DSPFW_CURSORA_SHIFT)); | 3935 | (cursora_wm << DSPFW_CURSORA_SHIFT)); |
3343 | /* HPLL off in SR has some issues on G4x... disable it */ | 3936 | /* HPLL off in SR has some issues on G4x... disable it */ |
3344 | I915_WRITE(DSPFW3, (I915_READ(DSPFW3) & ~DSPFW_HPLL_SR_EN) | | 3937 | I915_WRITE(DSPFW3, |
3938 | (I915_READ(DSPFW3) & ~DSPFW_HPLL_SR_EN) | | ||
3345 | (cursor_sr << DSPFW_CURSOR_SR_SHIFT)); | 3939 | (cursor_sr << DSPFW_CURSOR_SR_SHIFT)); |
3346 | } | 3940 | } |
3347 | 3941 | ||
3348 | static void i965_update_wm(struct drm_device *dev, int planea_clock, | 3942 | static void i965_update_wm(struct drm_device *dev) |
3349 | int planeb_clock, int sr_hdisplay, int sr_htotal, | ||
3350 | int pixel_size) | ||
3351 | { | 3943 | { |
3352 | struct drm_i915_private *dev_priv = dev->dev_private; | 3944 | struct drm_i915_private *dev_priv = dev->dev_private; |
3353 | unsigned long line_time_us; | 3945 | struct drm_crtc *crtc; |
3354 | int sr_clock, sr_entries, srwm = 1; | 3946 | int srwm = 1; |
3355 | int cursor_sr = 16; | 3947 | int cursor_sr = 16; |
3356 | 3948 | ||
3357 | /* Calc sr entries for one plane configs */ | 3949 | /* Calc sr entries for one plane configs */ |
3358 | if (sr_hdisplay && (!planea_clock || !planeb_clock)) { | 3950 | crtc = single_enabled_crtc(dev); |
3951 | if (crtc) { | ||
3359 | /* self-refresh has much higher latency */ | 3952 | /* self-refresh has much higher latency */ |
3360 | static const int sr_latency_ns = 12000; | 3953 | static const int sr_latency_ns = 12000; |
3954 | int clock = crtc->mode.clock; | ||
3955 | int htotal = crtc->mode.htotal; | ||
3956 | int hdisplay = crtc->mode.hdisplay; | ||
3957 | int pixel_size = crtc->fb->bits_per_pixel / 8; | ||
3958 | unsigned long line_time_us; | ||
3959 | int entries; | ||
3361 | 3960 | ||
3362 | sr_clock = planea_clock ? planea_clock : planeb_clock; | 3961 | line_time_us = ((htotal * 1000) / clock); |
3363 | line_time_us = ((sr_htotal * 1000) / sr_clock); | ||
3364 | 3962 | ||
3365 | /* Use ns/us then divide to preserve precision */ | 3963 | /* Use ns/us then divide to preserve precision */ |
3366 | sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * | 3964 | entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * |
3367 | pixel_size * sr_hdisplay; | 3965 | pixel_size * hdisplay; |
3368 | sr_entries = DIV_ROUND_UP(sr_entries, I915_FIFO_LINE_SIZE); | 3966 | entries = DIV_ROUND_UP(entries, I915_FIFO_LINE_SIZE); |
3369 | DRM_DEBUG("self-refresh entries: %d\n", sr_entries); | 3967 | srwm = I965_FIFO_SIZE - entries; |
3370 | srwm = I965_FIFO_SIZE - sr_entries; | ||
3371 | if (srwm < 0) | 3968 | if (srwm < 0) |
3372 | srwm = 1; | 3969 | srwm = 1; |
3373 | srwm &= 0x1ff; | 3970 | srwm &= 0x1ff; |
3971 | DRM_DEBUG_KMS("self-refresh entries: %d, wm: %d\n", | ||
3972 | entries, srwm); | ||
3374 | 3973 | ||
3375 | sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * | 3974 | entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * |
3376 | pixel_size * 64; | 3975 | pixel_size * 64; |
3377 | sr_entries = DIV_ROUND_UP(sr_entries, | 3976 | entries = DIV_ROUND_UP(entries, |
3378 | i965_cursor_wm_info.cacheline_size); | 3977 | i965_cursor_wm_info.cacheline_size); |
3379 | cursor_sr = i965_cursor_wm_info.fifo_size - | 3978 | cursor_sr = i965_cursor_wm_info.fifo_size - |
3380 | (sr_entries + i965_cursor_wm_info.guard_size); | 3979 | (entries + i965_cursor_wm_info.guard_size); |
3381 | 3980 | ||
3382 | if (cursor_sr > i965_cursor_wm_info.max_wm) | 3981 | if (cursor_sr > i965_cursor_wm_info.max_wm) |
3383 | cursor_sr = i965_cursor_wm_info.max_wm; | 3982 | cursor_sr = i965_cursor_wm_info.max_wm; |
@@ -3398,46 +3997,56 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock, | |||
3398 | srwm); | 3997 | srwm); |
3399 | 3998 | ||
3400 | /* 965 has limitations... */ | 3999 | /* 965 has limitations... */ |
3401 | I915_WRITE(DSPFW1, (srwm << DSPFW_SR_SHIFT) | (8 << 16) | (8 << 8) | | 4000 | I915_WRITE(DSPFW1, (srwm << DSPFW_SR_SHIFT) | |
3402 | (8 << 0)); | 4001 | (8 << 16) | (8 << 8) | (8 << 0)); |
3403 | I915_WRITE(DSPFW2, (8 << 8) | (8 << 0)); | 4002 | I915_WRITE(DSPFW2, (8 << 8) | (8 << 0)); |
3404 | /* update cursor SR watermark */ | 4003 | /* update cursor SR watermark */ |
3405 | I915_WRITE(DSPFW3, (cursor_sr << DSPFW_CURSOR_SR_SHIFT)); | 4004 | I915_WRITE(DSPFW3, (cursor_sr << DSPFW_CURSOR_SR_SHIFT)); |
3406 | } | 4005 | } |
3407 | 4006 | ||
3408 | static void i9xx_update_wm(struct drm_device *dev, int planea_clock, | 4007 | static void i9xx_update_wm(struct drm_device *dev) |
3409 | int planeb_clock, int sr_hdisplay, int sr_htotal, | ||
3410 | int pixel_size) | ||
3411 | { | 4008 | { |
3412 | struct drm_i915_private *dev_priv = dev->dev_private; | 4009 | struct drm_i915_private *dev_priv = dev->dev_private; |
4010 | const struct intel_watermark_params *wm_info; | ||
3413 | uint32_t fwater_lo; | 4011 | uint32_t fwater_lo; |
3414 | uint32_t fwater_hi; | 4012 | uint32_t fwater_hi; |
3415 | int total_size, cacheline_size, cwm, srwm = 1; | 4013 | int cwm, srwm = 1; |
4014 | int fifo_size; | ||
3416 | int planea_wm, planeb_wm; | 4015 | int planea_wm, planeb_wm; |
3417 | struct intel_watermark_params planea_params, planeb_params; | 4016 | struct drm_crtc *crtc, *enabled = NULL; |
3418 | unsigned long line_time_us; | ||
3419 | int sr_clock, sr_entries = 0; | ||
3420 | 4017 | ||
3421 | /* Create copies of the base settings for each pipe */ | 4018 | if (IS_I945GM(dev)) |
3422 | if (IS_CRESTLINE(dev) || IS_I945GM(dev)) | 4019 | wm_info = &i945_wm_info; |
3423 | planea_params = planeb_params = i945_wm_info; | ||
3424 | else if (!IS_GEN2(dev)) | 4020 | else if (!IS_GEN2(dev)) |
3425 | planea_params = planeb_params = i915_wm_info; | 4021 | wm_info = &i915_wm_info; |
3426 | else | 4022 | else |
3427 | planea_params = planeb_params = i855_wm_info; | 4023 | wm_info = &i855_wm_info; |
3428 | 4024 | ||
3429 | /* Grab a couple of global values before we overwrite them */ | 4025 | fifo_size = dev_priv->display.get_fifo_size(dev, 0); |
3430 | total_size = planea_params.fifo_size; | 4026 | crtc = intel_get_crtc_for_plane(dev, 0); |
3431 | cacheline_size = planea_params.cacheline_size; | 4027 | if (crtc->enabled && crtc->fb) { |
3432 | 4028 | planea_wm = intel_calculate_wm(crtc->mode.clock, | |
3433 | /* Update per-plane FIFO sizes */ | 4029 | wm_info, fifo_size, |
3434 | planea_params.fifo_size = dev_priv->display.get_fifo_size(dev, 0); | 4030 | crtc->fb->bits_per_pixel / 8, |
3435 | planeb_params.fifo_size = dev_priv->display.get_fifo_size(dev, 1); | 4031 | latency_ns); |
4032 | enabled = crtc; | ||
4033 | } else | ||
4034 | planea_wm = fifo_size - wm_info->guard_size; | ||
4035 | |||
4036 | fifo_size = dev_priv->display.get_fifo_size(dev, 1); | ||
4037 | crtc = intel_get_crtc_for_plane(dev, 1); | ||
4038 | if (crtc->enabled && crtc->fb) { | ||
4039 | planeb_wm = intel_calculate_wm(crtc->mode.clock, | ||
4040 | wm_info, fifo_size, | ||
4041 | crtc->fb->bits_per_pixel / 8, | ||
4042 | latency_ns); | ||
4043 | if (enabled == NULL) | ||
4044 | enabled = crtc; | ||
4045 | else | ||
4046 | enabled = NULL; | ||
4047 | } else | ||
4048 | planeb_wm = fifo_size - wm_info->guard_size; | ||
3436 | 4049 | ||
3437 | planea_wm = intel_calculate_wm(planea_clock, &planea_params, | ||
3438 | pixel_size, latency_ns); | ||
3439 | planeb_wm = intel_calculate_wm(planeb_clock, &planeb_params, | ||
3440 | pixel_size, latency_ns); | ||
3441 | DRM_DEBUG_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm); | 4050 | DRM_DEBUG_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm); |
3442 | 4051 | ||
3443 | /* | 4052 | /* |
@@ -3445,39 +4054,39 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock, | |||
3445 | */ | 4054 | */ |
3446 | cwm = 2; | 4055 | cwm = 2; |
3447 | 4056 | ||
4057 | /* Play safe and disable self-refresh before adjusting watermarks. */ | ||
4058 | if (IS_I945G(dev) || IS_I945GM(dev)) | ||
4059 | I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | 0); | ||
4060 | else if (IS_I915GM(dev)) | ||
4061 | I915_WRITE(INSTPM, I915_READ(INSTPM) & ~INSTPM_SELF_EN); | ||
4062 | |||
3448 | /* Calc sr entries for one plane configs */ | 4063 | /* Calc sr entries for one plane configs */ |
3449 | if (HAS_FW_BLC(dev) && sr_hdisplay && | 4064 | if (HAS_FW_BLC(dev) && enabled) { |
3450 | (!planea_clock || !planeb_clock)) { | ||
3451 | /* self-refresh has much higher latency */ | 4065 | /* self-refresh has much higher latency */ |
3452 | static const int sr_latency_ns = 6000; | 4066 | static const int sr_latency_ns = 6000; |
4067 | int clock = enabled->mode.clock; | ||
4068 | int htotal = enabled->mode.htotal; | ||
4069 | int hdisplay = enabled->mode.hdisplay; | ||
4070 | int pixel_size = enabled->fb->bits_per_pixel / 8; | ||
4071 | unsigned long line_time_us; | ||
4072 | int entries; | ||
3453 | 4073 | ||
3454 | sr_clock = planea_clock ? planea_clock : planeb_clock; | 4074 | line_time_us = (htotal * 1000) / clock; |
3455 | line_time_us = ((sr_htotal * 1000) / sr_clock); | ||
3456 | 4075 | ||
3457 | /* Use ns/us then divide to preserve precision */ | 4076 | /* Use ns/us then divide to preserve precision */ |
3458 | sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * | 4077 | entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) * |
3459 | pixel_size * sr_hdisplay; | 4078 | pixel_size * hdisplay; |
3460 | sr_entries = DIV_ROUND_UP(sr_entries, cacheline_size); | 4079 | entries = DIV_ROUND_UP(entries, wm_info->cacheline_size); |
3461 | DRM_DEBUG_KMS("self-refresh entries: %d\n", sr_entries); | 4080 | DRM_DEBUG_KMS("self-refresh entries: %d\n", entries); |
3462 | srwm = total_size - sr_entries; | 4081 | srwm = wm_info->fifo_size - entries; |
3463 | if (srwm < 0) | 4082 | if (srwm < 0) |
3464 | srwm = 1; | 4083 | srwm = 1; |
3465 | 4084 | ||
3466 | if (IS_I945G(dev) || IS_I945GM(dev)) | 4085 | if (IS_I945G(dev) || IS_I945GM(dev)) |
3467 | I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_FIFO_MASK | (srwm & 0xff)); | 4086 | I915_WRITE(FW_BLC_SELF, |
3468 | else if (IS_I915GM(dev)) { | 4087 | FW_BLC_SELF_FIFO_MASK | (srwm & 0xff)); |
3469 | /* 915M has a smaller SRWM field */ | 4088 | else if (IS_I915GM(dev)) |
3470 | I915_WRITE(FW_BLC_SELF, srwm & 0x3f); | 4089 | I915_WRITE(FW_BLC_SELF, srwm & 0x3f); |
3471 | I915_WRITE(INSTPM, I915_READ(INSTPM) | INSTPM_SELF_EN); | ||
3472 | } | ||
3473 | } else { | ||
3474 | /* Turn off self refresh if both pipes are enabled */ | ||
3475 | if (IS_I945G(dev) || IS_I945GM(dev)) { | ||
3476 | I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF) | ||
3477 | & ~FW_BLC_SELF_EN); | ||
3478 | } else if (IS_I915GM(dev)) { | ||
3479 | I915_WRITE(INSTPM, I915_READ(INSTPM) & ~INSTPM_SELF_EN); | ||
3480 | } | ||
3481 | } | 4090 | } |
3482 | 4091 | ||
3483 | DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n", | 4092 | DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n", |
@@ -3492,19 +4101,36 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock, | |||
3492 | 4101 | ||
3493 | I915_WRITE(FW_BLC, fwater_lo); | 4102 | I915_WRITE(FW_BLC, fwater_lo); |
3494 | I915_WRITE(FW_BLC2, fwater_hi); | 4103 | I915_WRITE(FW_BLC2, fwater_hi); |
4104 | |||
4105 | if (HAS_FW_BLC(dev)) { | ||
4106 | if (enabled) { | ||
4107 | if (IS_I945G(dev) || IS_I945GM(dev)) | ||
4108 | I915_WRITE(FW_BLC_SELF, | ||
4109 | FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN); | ||
4110 | else if (IS_I915GM(dev)) | ||
4111 | I915_WRITE(INSTPM, I915_READ(INSTPM) | INSTPM_SELF_EN); | ||
4112 | DRM_DEBUG_KMS("memory self refresh enabled\n"); | ||
4113 | } else | ||
4114 | DRM_DEBUG_KMS("memory self refresh disabled\n"); | ||
4115 | } | ||
3495 | } | 4116 | } |
3496 | 4117 | ||
3497 | static void i830_update_wm(struct drm_device *dev, int planea_clock, int unused, | 4118 | static void i830_update_wm(struct drm_device *dev) |
3498 | int unused2, int unused3, int pixel_size) | ||
3499 | { | 4119 | { |
3500 | struct drm_i915_private *dev_priv = dev->dev_private; | 4120 | struct drm_i915_private *dev_priv = dev->dev_private; |
3501 | uint32_t fwater_lo = I915_READ(FW_BLC) & ~0xfff; | 4121 | struct drm_crtc *crtc; |
4122 | uint32_t fwater_lo; | ||
3502 | int planea_wm; | 4123 | int planea_wm; |
3503 | 4124 | ||
3504 | i830_wm_info.fifo_size = dev_priv->display.get_fifo_size(dev, 0); | 4125 | crtc = single_enabled_crtc(dev); |
4126 | if (crtc == NULL) | ||
4127 | return; | ||
3505 | 4128 | ||
3506 | planea_wm = intel_calculate_wm(planea_clock, &i830_wm_info, | 4129 | planea_wm = intel_calculate_wm(crtc->mode.clock, &i830_wm_info, |
3507 | pixel_size, latency_ns); | 4130 | dev_priv->display.get_fifo_size(dev, 0), |
4131 | crtc->fb->bits_per_pixel / 8, | ||
4132 | latency_ns); | ||
4133 | fwater_lo = I915_READ(FW_BLC) & ~0xfff; | ||
3508 | fwater_lo |= (3<<8) | planea_wm; | 4134 | fwater_lo |= (3<<8) | planea_wm; |
3509 | 4135 | ||
3510 | DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d\n", planea_wm); | 4136 | DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d\n", planea_wm); |
@@ -3613,15 +4239,15 @@ static bool ironlake_check_srwm(struct drm_device *dev, int level, | |||
3613 | /* | 4239 | /* |
3614 | * Compute watermark values of WM[1-3], | 4240 | * Compute watermark values of WM[1-3], |
3615 | */ | 4241 | */ |
3616 | static bool ironlake_compute_srwm(struct drm_device *dev, int level, | 4242 | static bool ironlake_compute_srwm(struct drm_device *dev, int level, int plane, |
3617 | int hdisplay, int htotal, | 4243 | int latency_ns, |
3618 | int pixel_size, int clock, int latency_ns, | ||
3619 | const struct intel_watermark_params *display, | 4244 | const struct intel_watermark_params *display, |
3620 | const struct intel_watermark_params *cursor, | 4245 | const struct intel_watermark_params *cursor, |
3621 | int *fbc_wm, int *display_wm, int *cursor_wm) | 4246 | int *fbc_wm, int *display_wm, int *cursor_wm) |
3622 | { | 4247 | { |
3623 | 4248 | struct drm_crtc *crtc; | |
3624 | unsigned long line_time_us; | 4249 | unsigned long line_time_us; |
4250 | int hdisplay, htotal, pixel_size, clock; | ||
3625 | int line_count, line_size; | 4251 | int line_count, line_size; |
3626 | int small, large; | 4252 | int small, large; |
3627 | int entries; | 4253 | int entries; |
@@ -3631,6 +4257,12 @@ static bool ironlake_compute_srwm(struct drm_device *dev, int level, | |||
3631 | return false; | 4257 | return false; |
3632 | } | 4258 | } |
3633 | 4259 | ||
4260 | crtc = intel_get_crtc_for_plane(dev, plane); | ||
4261 | hdisplay = crtc->mode.hdisplay; | ||
4262 | htotal = crtc->mode.htotal; | ||
4263 | clock = crtc->mode.clock; | ||
4264 | pixel_size = crtc->fb->bits_per_pixel / 8; | ||
4265 | |||
3634 | line_time_us = (htotal * 1000) / clock; | 4266 | line_time_us = (htotal * 1000) / clock; |
3635 | line_count = (latency_ns / line_time_us + 1000) / 1000; | 4267 | line_count = (latency_ns / line_time_us + 1000) / 1000; |
3636 | line_size = hdisplay * pixel_size; | 4268 | line_size = hdisplay * pixel_size; |
@@ -3658,14 +4290,11 @@ static bool ironlake_compute_srwm(struct drm_device *dev, int level, | |||
3658 | display, cursor); | 4290 | display, cursor); |
3659 | } | 4291 | } |
3660 | 4292 | ||
3661 | static void ironlake_update_wm(struct drm_device *dev, | 4293 | static void ironlake_update_wm(struct drm_device *dev) |
3662 | int planea_clock, int planeb_clock, | ||
3663 | int hdisplay, int htotal, | ||
3664 | int pixel_size) | ||
3665 | { | 4294 | { |
3666 | struct drm_i915_private *dev_priv = dev->dev_private; | 4295 | struct drm_i915_private *dev_priv = dev->dev_private; |
3667 | int fbc_wm, plane_wm, cursor_wm, enabled; | 4296 | int fbc_wm, plane_wm, cursor_wm; |
3668 | int clock; | 4297 | unsigned int enabled; |
3669 | 4298 | ||
3670 | enabled = 0; | 4299 | enabled = 0; |
3671 | if (ironlake_compute_wm0(dev, 0, | 4300 | if (ironlake_compute_wm0(dev, 0, |
@@ -3679,7 +4308,7 @@ static void ironlake_update_wm(struct drm_device *dev, | |||
3679 | DRM_DEBUG_KMS("FIFO watermarks For pipe A -" | 4308 | DRM_DEBUG_KMS("FIFO watermarks For pipe A -" |
3680 | " plane %d, " "cursor: %d\n", | 4309 | " plane %d, " "cursor: %d\n", |
3681 | plane_wm, cursor_wm); | 4310 | plane_wm, cursor_wm); |
3682 | enabled++; | 4311 | enabled |= 1; |
3683 | } | 4312 | } |
3684 | 4313 | ||
3685 | if (ironlake_compute_wm0(dev, 1, | 4314 | if (ironlake_compute_wm0(dev, 1, |
@@ -3693,7 +4322,7 @@ static void ironlake_update_wm(struct drm_device *dev, | |||
3693 | DRM_DEBUG_KMS("FIFO watermarks For pipe B -" | 4322 | DRM_DEBUG_KMS("FIFO watermarks For pipe B -" |
3694 | " plane %d, cursor: %d\n", | 4323 | " plane %d, cursor: %d\n", |
3695 | plane_wm, cursor_wm); | 4324 | plane_wm, cursor_wm); |
3696 | enabled++; | 4325 | enabled |= 2; |
3697 | } | 4326 | } |
3698 | 4327 | ||
3699 | /* | 4328 | /* |
@@ -3704,14 +4333,13 @@ static void ironlake_update_wm(struct drm_device *dev, | |||
3704 | I915_WRITE(WM2_LP_ILK, 0); | 4333 | I915_WRITE(WM2_LP_ILK, 0); |
3705 | I915_WRITE(WM1_LP_ILK, 0); | 4334 | I915_WRITE(WM1_LP_ILK, 0); |
3706 | 4335 | ||
3707 | if (enabled != 1) | 4336 | if (!single_plane_enabled(enabled)) |
3708 | return; | 4337 | return; |
3709 | 4338 | enabled = ffs(enabled) - 1; | |
3710 | clock = planea_clock ? planea_clock : planeb_clock; | ||
3711 | 4339 | ||
3712 | /* WM1 */ | 4340 | /* WM1 */ |
3713 | if (!ironlake_compute_srwm(dev, 1, hdisplay, htotal, pixel_size, | 4341 | if (!ironlake_compute_srwm(dev, 1, enabled, |
3714 | clock, ILK_READ_WM1_LATENCY() * 500, | 4342 | ILK_READ_WM1_LATENCY() * 500, |
3715 | &ironlake_display_srwm_info, | 4343 | &ironlake_display_srwm_info, |
3716 | &ironlake_cursor_srwm_info, | 4344 | &ironlake_cursor_srwm_info, |
3717 | &fbc_wm, &plane_wm, &cursor_wm)) | 4345 | &fbc_wm, &plane_wm, &cursor_wm)) |
@@ -3725,8 +4353,8 @@ static void ironlake_update_wm(struct drm_device *dev, | |||
3725 | cursor_wm); | 4353 | cursor_wm); |
3726 | 4354 | ||
3727 | /* WM2 */ | 4355 | /* WM2 */ |
3728 | if (!ironlake_compute_srwm(dev, 2, hdisplay, htotal, pixel_size, | 4356 | if (!ironlake_compute_srwm(dev, 2, enabled, |
3729 | clock, ILK_READ_WM2_LATENCY() * 500, | 4357 | ILK_READ_WM2_LATENCY() * 500, |
3730 | &ironlake_display_srwm_info, | 4358 | &ironlake_display_srwm_info, |
3731 | &ironlake_cursor_srwm_info, | 4359 | &ironlake_cursor_srwm_info, |
3732 | &fbc_wm, &plane_wm, &cursor_wm)) | 4360 | &fbc_wm, &plane_wm, &cursor_wm)) |
@@ -3745,15 +4373,12 @@ static void ironlake_update_wm(struct drm_device *dev, | |||
3745 | */ | 4373 | */ |
3746 | } | 4374 | } |
3747 | 4375 | ||
3748 | static void sandybridge_update_wm(struct drm_device *dev, | 4376 | static void sandybridge_update_wm(struct drm_device *dev) |
3749 | int planea_clock, int planeb_clock, | ||
3750 | int hdisplay, int htotal, | ||
3751 | int pixel_size) | ||
3752 | { | 4377 | { |
3753 | struct drm_i915_private *dev_priv = dev->dev_private; | 4378 | struct drm_i915_private *dev_priv = dev->dev_private; |
3754 | int latency = SNB_READ_WM0_LATENCY() * 100; /* In unit 0.1us */ | 4379 | int latency = SNB_READ_WM0_LATENCY() * 100; /* In unit 0.1us */ |
3755 | int fbc_wm, plane_wm, cursor_wm, enabled; | 4380 | int fbc_wm, plane_wm, cursor_wm; |
3756 | int clock; | 4381 | unsigned int enabled; |
3757 | 4382 | ||
3758 | enabled = 0; | 4383 | enabled = 0; |
3759 | if (ironlake_compute_wm0(dev, 0, | 4384 | if (ironlake_compute_wm0(dev, 0, |
@@ -3765,7 +4390,7 @@ static void sandybridge_update_wm(struct drm_device *dev, | |||
3765 | DRM_DEBUG_KMS("FIFO watermarks For pipe A -" | 4390 | DRM_DEBUG_KMS("FIFO watermarks For pipe A -" |
3766 | " plane %d, " "cursor: %d\n", | 4391 | " plane %d, " "cursor: %d\n", |
3767 | plane_wm, cursor_wm); | 4392 | plane_wm, cursor_wm); |
3768 | enabled++; | 4393 | enabled |= 1; |
3769 | } | 4394 | } |
3770 | 4395 | ||
3771 | if (ironlake_compute_wm0(dev, 1, | 4396 | if (ironlake_compute_wm0(dev, 1, |
@@ -3777,7 +4402,7 @@ static void sandybridge_update_wm(struct drm_device *dev, | |||
3777 | DRM_DEBUG_KMS("FIFO watermarks For pipe B -" | 4402 | DRM_DEBUG_KMS("FIFO watermarks For pipe B -" |
3778 | " plane %d, cursor: %d\n", | 4403 | " plane %d, cursor: %d\n", |
3779 | plane_wm, cursor_wm); | 4404 | plane_wm, cursor_wm); |
3780 | enabled++; | 4405 | enabled |= 2; |
3781 | } | 4406 | } |
3782 | 4407 | ||
3783 | /* | 4408 | /* |
@@ -3794,14 +4419,13 @@ static void sandybridge_update_wm(struct drm_device *dev, | |||
3794 | I915_WRITE(WM2_LP_ILK, 0); | 4419 | I915_WRITE(WM2_LP_ILK, 0); |
3795 | I915_WRITE(WM1_LP_ILK, 0); | 4420 | I915_WRITE(WM1_LP_ILK, 0); |
3796 | 4421 | ||
3797 | if (enabled != 1) | 4422 | if (!single_plane_enabled(enabled)) |
3798 | return; | 4423 | return; |
3799 | 4424 | enabled = ffs(enabled) - 1; | |
3800 | clock = planea_clock ? planea_clock : planeb_clock; | ||
3801 | 4425 | ||
3802 | /* WM1 */ | 4426 | /* WM1 */ |
3803 | if (!ironlake_compute_srwm(dev, 1, hdisplay, htotal, pixel_size, | 4427 | if (!ironlake_compute_srwm(dev, 1, enabled, |
3804 | clock, SNB_READ_WM1_LATENCY() * 500, | 4428 | SNB_READ_WM1_LATENCY() * 500, |
3805 | &sandybridge_display_srwm_info, | 4429 | &sandybridge_display_srwm_info, |
3806 | &sandybridge_cursor_srwm_info, | 4430 | &sandybridge_cursor_srwm_info, |
3807 | &fbc_wm, &plane_wm, &cursor_wm)) | 4431 | &fbc_wm, &plane_wm, &cursor_wm)) |
@@ -3815,9 +4439,8 @@ static void sandybridge_update_wm(struct drm_device *dev, | |||
3815 | cursor_wm); | 4439 | cursor_wm); |
3816 | 4440 | ||
3817 | /* WM2 */ | 4441 | /* WM2 */ |
3818 | if (!ironlake_compute_srwm(dev, 2, | 4442 | if (!ironlake_compute_srwm(dev, 2, enabled, |
3819 | hdisplay, htotal, pixel_size, | 4443 | SNB_READ_WM2_LATENCY() * 500, |
3820 | clock, SNB_READ_WM2_LATENCY() * 500, | ||
3821 | &sandybridge_display_srwm_info, | 4444 | &sandybridge_display_srwm_info, |
3822 | &sandybridge_cursor_srwm_info, | 4445 | &sandybridge_cursor_srwm_info, |
3823 | &fbc_wm, &plane_wm, &cursor_wm)) | 4446 | &fbc_wm, &plane_wm, &cursor_wm)) |
@@ -3831,9 +4454,8 @@ static void sandybridge_update_wm(struct drm_device *dev, | |||
3831 | cursor_wm); | 4454 | cursor_wm); |
3832 | 4455 | ||
3833 | /* WM3 */ | 4456 | /* WM3 */ |
3834 | if (!ironlake_compute_srwm(dev, 3, | 4457 | if (!ironlake_compute_srwm(dev, 3, enabled, |
3835 | hdisplay, htotal, pixel_size, | 4458 | SNB_READ_WM3_LATENCY() * 500, |
3836 | clock, SNB_READ_WM3_LATENCY() * 500, | ||
3837 | &sandybridge_display_srwm_info, | 4459 | &sandybridge_display_srwm_info, |
3838 | &sandybridge_cursor_srwm_info, | 4460 | &sandybridge_cursor_srwm_info, |
3839 | &fbc_wm, &plane_wm, &cursor_wm)) | 4461 | &fbc_wm, &plane_wm, &cursor_wm)) |
@@ -3882,44 +4504,9 @@ static void sandybridge_update_wm(struct drm_device *dev, | |||
3882 | static void intel_update_watermarks(struct drm_device *dev) | 4504 | static void intel_update_watermarks(struct drm_device *dev) |
3883 | { | 4505 | { |
3884 | struct drm_i915_private *dev_priv = dev->dev_private; | 4506 | struct drm_i915_private *dev_priv = dev->dev_private; |
3885 | struct drm_crtc *crtc; | ||
3886 | int sr_hdisplay = 0; | ||
3887 | unsigned long planea_clock = 0, planeb_clock = 0, sr_clock = 0; | ||
3888 | int enabled = 0, pixel_size = 0; | ||
3889 | int sr_htotal = 0; | ||
3890 | |||
3891 | if (!dev_priv->display.update_wm) | ||
3892 | return; | ||
3893 | 4507 | ||
3894 | /* Get the clock config from both planes */ | 4508 | if (dev_priv->display.update_wm) |
3895 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | 4509 | dev_priv->display.update_wm(dev); |
3896 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
3897 | if (intel_crtc->active) { | ||
3898 | enabled++; | ||
3899 | if (intel_crtc->plane == 0) { | ||
3900 | DRM_DEBUG_KMS("plane A (pipe %d) clock: %d\n", | ||
3901 | intel_crtc->pipe, crtc->mode.clock); | ||
3902 | planea_clock = crtc->mode.clock; | ||
3903 | } else { | ||
3904 | DRM_DEBUG_KMS("plane B (pipe %d) clock: %d\n", | ||
3905 | intel_crtc->pipe, crtc->mode.clock); | ||
3906 | planeb_clock = crtc->mode.clock; | ||
3907 | } | ||
3908 | sr_hdisplay = crtc->mode.hdisplay; | ||
3909 | sr_clock = crtc->mode.clock; | ||
3910 | sr_htotal = crtc->mode.htotal; | ||
3911 | if (crtc->fb) | ||
3912 | pixel_size = crtc->fb->bits_per_pixel / 8; | ||
3913 | else | ||
3914 | pixel_size = 4; /* by default */ | ||
3915 | } | ||
3916 | } | ||
3917 | |||
3918 | if (enabled <= 0) | ||
3919 | return; | ||
3920 | |||
3921 | dev_priv->display.update_wm(dev, planea_clock, planeb_clock, | ||
3922 | sr_hdisplay, sr_htotal, pixel_size); | ||
3923 | } | 4510 | } |
3924 | 4511 | ||
3925 | static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) | 4512 | static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) |
@@ -3951,6 +4538,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
3951 | int ret; | 4538 | int ret; |
3952 | struct fdi_m_n m_n = {0}; | 4539 | struct fdi_m_n m_n = {0}; |
3953 | u32 reg, temp; | 4540 | u32 reg, temp; |
4541 | u32 lvds_sync = 0; | ||
3954 | int target_clock; | 4542 | int target_clock; |
3955 | 4543 | ||
3956 | drm_vblank_pre_modeset(dev, pipe); | 4544 | drm_vblank_pre_modeset(dev, pipe); |
@@ -4322,9 +4910,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
4322 | pipeconf &= ~PIPECONF_DOUBLE_WIDE; | 4910 | pipeconf &= ~PIPECONF_DOUBLE_WIDE; |
4323 | } | 4911 | } |
4324 | 4912 | ||
4325 | dspcntr |= DISPLAY_PLANE_ENABLE; | 4913 | if (!HAS_PCH_SPLIT(dev)) |
4326 | pipeconf |= PIPECONF_ENABLE; | 4914 | dpll |= DPLL_VCO_ENABLE; |
4327 | dpll |= DPLL_VCO_ENABLE; | ||
4328 | 4915 | ||
4329 | DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); | 4916 | DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); |
4330 | drm_mode_debug_printmodeline(mode); | 4917 | drm_mode_debug_printmodeline(mode); |
@@ -4350,10 +4937,20 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
4350 | /* enable transcoder DPLL */ | 4937 | /* enable transcoder DPLL */ |
4351 | if (HAS_PCH_CPT(dev)) { | 4938 | if (HAS_PCH_CPT(dev)) { |
4352 | temp = I915_READ(PCH_DPLL_SEL); | 4939 | temp = I915_READ(PCH_DPLL_SEL); |
4353 | if (pipe == 0) | 4940 | switch (pipe) { |
4941 | case 0: | ||
4354 | temp |= TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL; | 4942 | temp |= TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL; |
4355 | else | 4943 | break; |
4944 | case 1: | ||
4356 | temp |= TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL; | 4945 | temp |= TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL; |
4946 | break; | ||
4947 | case 2: | ||
4948 | /* FIXME: manage transcoder PLLs? */ | ||
4949 | temp |= TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL; | ||
4950 | break; | ||
4951 | default: | ||
4952 | BUG(); | ||
4953 | } | ||
4357 | I915_WRITE(PCH_DPLL_SEL, temp); | 4954 | I915_WRITE(PCH_DPLL_SEL, temp); |
4358 | 4955 | ||
4359 | POSTING_READ(PCH_DPLL_SEL); | 4956 | POSTING_READ(PCH_DPLL_SEL); |
@@ -4403,6 +5000,22 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
4403 | else | 5000 | else |
4404 | temp &= ~LVDS_ENABLE_DITHER; | 5001 | temp &= ~LVDS_ENABLE_DITHER; |
4405 | } | 5002 | } |
5003 | if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) | ||
5004 | lvds_sync |= LVDS_HSYNC_POLARITY; | ||
5005 | if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) | ||
5006 | lvds_sync |= LVDS_VSYNC_POLARITY; | ||
5007 | if ((temp & (LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY)) | ||
5008 | != lvds_sync) { | ||
5009 | char flags[2] = "-+"; | ||
5010 | DRM_INFO("Changing LVDS panel from " | ||
5011 | "(%chsync, %cvsync) to (%chsync, %cvsync)\n", | ||
5012 | flags[!(temp & LVDS_HSYNC_POLARITY)], | ||
5013 | flags[!(temp & LVDS_VSYNC_POLARITY)], | ||
5014 | flags[!(lvds_sync & LVDS_HSYNC_POLARITY)], | ||
5015 | flags[!(lvds_sync & LVDS_VSYNC_POLARITY)]); | ||
5016 | temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY); | ||
5017 | temp |= lvds_sync; | ||
5018 | } | ||
4406 | I915_WRITE(reg, temp); | 5019 | I915_WRITE(reg, temp); |
4407 | } | 5020 | } |
4408 | 5021 | ||
@@ -4420,17 +5033,10 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
4420 | intel_dp_set_m_n(crtc, mode, adjusted_mode); | 5033 | intel_dp_set_m_n(crtc, mode, adjusted_mode); |
4421 | } else if (HAS_PCH_SPLIT(dev)) { | 5034 | } else if (HAS_PCH_SPLIT(dev)) { |
4422 | /* For non-DP output, clear any trans DP clock recovery setting.*/ | 5035 | /* For non-DP output, clear any trans DP clock recovery setting.*/ |
4423 | if (pipe == 0) { | 5036 | I915_WRITE(TRANSDATA_M1(pipe), 0); |
4424 | I915_WRITE(TRANSA_DATA_M1, 0); | 5037 | I915_WRITE(TRANSDATA_N1(pipe), 0); |
4425 | I915_WRITE(TRANSA_DATA_N1, 0); | 5038 | I915_WRITE(TRANSDPLINK_M1(pipe), 0); |
4426 | I915_WRITE(TRANSA_DP_LINK_M1, 0); | 5039 | I915_WRITE(TRANSDPLINK_N1(pipe), 0); |
4427 | I915_WRITE(TRANSA_DP_LINK_N1, 0); | ||
4428 | } else { | ||
4429 | I915_WRITE(TRANSB_DATA_M1, 0); | ||
4430 | I915_WRITE(TRANSB_DATA_N1, 0); | ||
4431 | I915_WRITE(TRANSB_DP_LINK_M1, 0); | ||
4432 | I915_WRITE(TRANSB_DP_LINK_N1, 0); | ||
4433 | } | ||
4434 | } | 5040 | } |
4435 | 5041 | ||
4436 | if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) { | 5042 | if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) { |
@@ -4533,6 +5139,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
4533 | 5139 | ||
4534 | I915_WRITE(PIPECONF(pipe), pipeconf); | 5140 | I915_WRITE(PIPECONF(pipe), pipeconf); |
4535 | POSTING_READ(PIPECONF(pipe)); | 5141 | POSTING_READ(PIPECONF(pipe)); |
5142 | if (!HAS_PCH_SPLIT(dev)) | ||
5143 | intel_enable_pipe(dev_priv, pipe, false); | ||
4536 | 5144 | ||
4537 | intel_wait_for_vblank(dev, pipe); | 5145 | intel_wait_for_vblank(dev, pipe); |
4538 | 5146 | ||
@@ -4543,6 +5151,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
4543 | } | 5151 | } |
4544 | 5152 | ||
4545 | I915_WRITE(DSPCNTR(plane), dspcntr); | 5153 | I915_WRITE(DSPCNTR(plane), dspcntr); |
5154 | POSTING_READ(DSPCNTR(plane)); | ||
5155 | if (!HAS_PCH_SPLIT(dev)) | ||
5156 | intel_enable_plane(dev_priv, plane, pipe); | ||
4546 | 5157 | ||
4547 | ret = intel_pipe_set_base(crtc, x, y, old_fb); | 5158 | ret = intel_pipe_set_base(crtc, x, y, old_fb); |
4548 | 5159 | ||
@@ -4559,7 +5170,7 @@ void intel_crtc_load_lut(struct drm_crtc *crtc) | |||
4559 | struct drm_device *dev = crtc->dev; | 5170 | struct drm_device *dev = crtc->dev; |
4560 | struct drm_i915_private *dev_priv = dev->dev_private; | 5171 | struct drm_i915_private *dev_priv = dev->dev_private; |
4561 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 5172 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
4562 | int palreg = (intel_crtc->pipe == 0) ? PALETTE_A : PALETTE_B; | 5173 | int palreg = PALETTE(intel_crtc->pipe); |
4563 | int i; | 5174 | int i; |
4564 | 5175 | ||
4565 | /* The clocks have to be on to load the palette. */ | 5176 | /* The clocks have to be on to load the palette. */ |
@@ -4568,8 +5179,7 @@ void intel_crtc_load_lut(struct drm_crtc *crtc) | |||
4568 | 5179 | ||
4569 | /* use legacy palette for Ironlake */ | 5180 | /* use legacy palette for Ironlake */ |
4570 | if (HAS_PCH_SPLIT(dev)) | 5181 | if (HAS_PCH_SPLIT(dev)) |
4571 | palreg = (intel_crtc->pipe == 0) ? LGC_PALETTE_A : | 5182 | palreg = LGC_PALETTE(intel_crtc->pipe); |
4572 | LGC_PALETTE_B; | ||
4573 | 5183 | ||
4574 | for (i = 0; i < 256; i++) { | 5184 | for (i = 0; i < 256; i++) { |
4575 | I915_WRITE(palreg + 4 * i, | 5185 | I915_WRITE(palreg + 4 * i, |
@@ -4590,12 +5200,12 @@ static void i845_update_cursor(struct drm_crtc *crtc, u32 base) | |||
4590 | if (intel_crtc->cursor_visible == visible) | 5200 | if (intel_crtc->cursor_visible == visible) |
4591 | return; | 5201 | return; |
4592 | 5202 | ||
4593 | cntl = I915_READ(CURACNTR); | 5203 | cntl = I915_READ(_CURACNTR); |
4594 | if (visible) { | 5204 | if (visible) { |
4595 | /* On these chipsets we can only modify the base whilst | 5205 | /* On these chipsets we can only modify the base whilst |
4596 | * the cursor is disabled. | 5206 | * the cursor is disabled. |
4597 | */ | 5207 | */ |
4598 | I915_WRITE(CURABASE, base); | 5208 | I915_WRITE(_CURABASE, base); |
4599 | 5209 | ||
4600 | cntl &= ~(CURSOR_FORMAT_MASK); | 5210 | cntl &= ~(CURSOR_FORMAT_MASK); |
4601 | /* XXX width must be 64, stride 256 => 0x00 << 28 */ | 5211 | /* XXX width must be 64, stride 256 => 0x00 << 28 */ |
@@ -4604,7 +5214,7 @@ static void i845_update_cursor(struct drm_crtc *crtc, u32 base) | |||
4604 | CURSOR_FORMAT_ARGB; | 5214 | CURSOR_FORMAT_ARGB; |
4605 | } else | 5215 | } else |
4606 | cntl &= ~(CURSOR_ENABLE | CURSOR_GAMMA_ENABLE); | 5216 | cntl &= ~(CURSOR_ENABLE | CURSOR_GAMMA_ENABLE); |
4607 | I915_WRITE(CURACNTR, cntl); | 5217 | I915_WRITE(_CURACNTR, cntl); |
4608 | 5218 | ||
4609 | intel_crtc->cursor_visible = visible; | 5219 | intel_crtc->cursor_visible = visible; |
4610 | } | 5220 | } |
@@ -4618,7 +5228,7 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base) | |||
4618 | bool visible = base != 0; | 5228 | bool visible = base != 0; |
4619 | 5229 | ||
4620 | if (intel_crtc->cursor_visible != visible) { | 5230 | if (intel_crtc->cursor_visible != visible) { |
4621 | uint32_t cntl = I915_READ(pipe == 0 ? CURACNTR : CURBCNTR); | 5231 | uint32_t cntl = I915_READ(CURCNTR(pipe)); |
4622 | if (base) { | 5232 | if (base) { |
4623 | cntl &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT); | 5233 | cntl &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT); |
4624 | cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; | 5234 | cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; |
@@ -4627,12 +5237,12 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base) | |||
4627 | cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE); | 5237 | cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE); |
4628 | cntl |= CURSOR_MODE_DISABLE; | 5238 | cntl |= CURSOR_MODE_DISABLE; |
4629 | } | 5239 | } |
4630 | I915_WRITE(pipe == 0 ? CURACNTR : CURBCNTR, cntl); | 5240 | I915_WRITE(CURCNTR(pipe), cntl); |
4631 | 5241 | ||
4632 | intel_crtc->cursor_visible = visible; | 5242 | intel_crtc->cursor_visible = visible; |
4633 | } | 5243 | } |
4634 | /* and commit changes on next vblank */ | 5244 | /* and commit changes on next vblank */ |
4635 | I915_WRITE(pipe == 0 ? CURABASE : CURBBASE, base); | 5245 | I915_WRITE(CURBASE(pipe), base); |
4636 | } | 5246 | } |
4637 | 5247 | ||
4638 | /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */ | 5248 | /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */ |
@@ -4682,7 +5292,7 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, | |||
4682 | if (!visible && !intel_crtc->cursor_visible) | 5292 | if (!visible && !intel_crtc->cursor_visible) |
4683 | return; | 5293 | return; |
4684 | 5294 | ||
4685 | I915_WRITE(pipe == 0 ? CURAPOS : CURBPOS, pos); | 5295 | I915_WRITE(CURPOS(pipe), pos); |
4686 | if (IS_845G(dev) || IS_I865G(dev)) | 5296 | if (IS_845G(dev) || IS_I865G(dev)) |
4687 | i845_update_cursor(crtc, base); | 5297 | i845_update_cursor(crtc, base); |
4688 | else | 5298 | else |
@@ -4722,7 +5332,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, | |||
4722 | } | 5332 | } |
4723 | 5333 | ||
4724 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, handle)); | 5334 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, handle)); |
4725 | if (!obj) | 5335 | if (&obj->base == NULL) |
4726 | return -ENOENT; | 5336 | return -ENOENT; |
4727 | 5337 | ||
4728 | if (obj->base.size < width * height * 4) { | 5338 | if (obj->base.size < width * height * 4) { |
@@ -4988,14 +5598,14 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc) | |||
4988 | struct drm_i915_private *dev_priv = dev->dev_private; | 5598 | struct drm_i915_private *dev_priv = dev->dev_private; |
4989 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 5599 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
4990 | int pipe = intel_crtc->pipe; | 5600 | int pipe = intel_crtc->pipe; |
4991 | u32 dpll = I915_READ((pipe == 0) ? DPLL_A : DPLL_B); | 5601 | u32 dpll = I915_READ(DPLL(pipe)); |
4992 | u32 fp; | 5602 | u32 fp; |
4993 | intel_clock_t clock; | 5603 | intel_clock_t clock; |
4994 | 5604 | ||
4995 | if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) | 5605 | if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) |
4996 | fp = I915_READ((pipe == 0) ? FPA0 : FPB0); | 5606 | fp = FP0(pipe); |
4997 | else | 5607 | else |
4998 | fp = I915_READ((pipe == 0) ? FPA1 : FPB1); | 5608 | fp = FP1(pipe); |
4999 | 5609 | ||
5000 | clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT; | 5610 | clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT; |
5001 | if (IS_PINEVIEW(dev)) { | 5611 | if (IS_PINEVIEW(dev)) { |
@@ -5077,10 +5687,10 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, | |||
5077 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 5687 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
5078 | int pipe = intel_crtc->pipe; | 5688 | int pipe = intel_crtc->pipe; |
5079 | struct drm_display_mode *mode; | 5689 | struct drm_display_mode *mode; |
5080 | int htot = I915_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B); | 5690 | int htot = I915_READ(HTOTAL(pipe)); |
5081 | int hsync = I915_READ((pipe == 0) ? HSYNC_A : HSYNC_B); | 5691 | int hsync = I915_READ(HSYNC(pipe)); |
5082 | int vtot = I915_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B); | 5692 | int vtot = I915_READ(VTOTAL(pipe)); |
5083 | int vsync = I915_READ((pipe == 0) ? VSYNC_A : VSYNC_B); | 5693 | int vsync = I915_READ(VSYNC(pipe)); |
5084 | 5694 | ||
5085 | mode = kzalloc(sizeof(*mode), GFP_KERNEL); | 5695 | mode = kzalloc(sizeof(*mode), GFP_KERNEL); |
5086 | if (!mode) | 5696 | if (!mode) |
@@ -5189,7 +5799,7 @@ static void intel_decrease_pllclock(struct drm_crtc *crtc) | |||
5189 | drm_i915_private_t *dev_priv = dev->dev_private; | 5799 | drm_i915_private_t *dev_priv = dev->dev_private; |
5190 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 5800 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
5191 | int pipe = intel_crtc->pipe; | 5801 | int pipe = intel_crtc->pipe; |
5192 | int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; | 5802 | int dpll_reg = DPLL(pipe); |
5193 | int dpll = I915_READ(dpll_reg); | 5803 | int dpll = I915_READ(dpll_reg); |
5194 | 5804 | ||
5195 | if (HAS_PCH_SPLIT(dev)) | 5805 | if (HAS_PCH_SPLIT(dev)) |
@@ -5237,7 +5847,6 @@ static void intel_idle_update(struct work_struct *work) | |||
5237 | struct drm_device *dev = dev_priv->dev; | 5847 | struct drm_device *dev = dev_priv->dev; |
5238 | struct drm_crtc *crtc; | 5848 | struct drm_crtc *crtc; |
5239 | struct intel_crtc *intel_crtc; | 5849 | struct intel_crtc *intel_crtc; |
5240 | int enabled = 0; | ||
5241 | 5850 | ||
5242 | if (!i915_powersave) | 5851 | if (!i915_powersave) |
5243 | return; | 5852 | return; |
@@ -5251,16 +5860,11 @@ static void intel_idle_update(struct work_struct *work) | |||
5251 | if (!crtc->fb) | 5860 | if (!crtc->fb) |
5252 | continue; | 5861 | continue; |
5253 | 5862 | ||
5254 | enabled++; | ||
5255 | intel_crtc = to_intel_crtc(crtc); | 5863 | intel_crtc = to_intel_crtc(crtc); |
5256 | if (!intel_crtc->busy) | 5864 | if (!intel_crtc->busy) |
5257 | intel_decrease_pllclock(crtc); | 5865 | intel_decrease_pllclock(crtc); |
5258 | } | 5866 | } |
5259 | 5867 | ||
5260 | if ((enabled == 1) && (IS_I945G(dev) || IS_I945GM(dev))) { | ||
5261 | DRM_DEBUG_DRIVER("enable memory self refresh on 945\n"); | ||
5262 | I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN); | ||
5263 | } | ||
5264 | 5868 | ||
5265 | mutex_unlock(&dev->struct_mutex); | 5869 | mutex_unlock(&dev->struct_mutex); |
5266 | } | 5870 | } |
@@ -5285,17 +5889,9 @@ void intel_mark_busy(struct drm_device *dev, struct drm_i915_gem_object *obj) | |||
5285 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 5889 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
5286 | return; | 5890 | return; |
5287 | 5891 | ||
5288 | if (!dev_priv->busy) { | 5892 | if (!dev_priv->busy) |
5289 | if (IS_I945G(dev) || IS_I945GM(dev)) { | ||
5290 | u32 fw_blc_self; | ||
5291 | |||
5292 | DRM_DEBUG_DRIVER("disable memory self refresh on 945\n"); | ||
5293 | fw_blc_self = I915_READ(FW_BLC_SELF); | ||
5294 | fw_blc_self &= ~FW_BLC_SELF_EN; | ||
5295 | I915_WRITE(FW_BLC_SELF, fw_blc_self | FW_BLC_SELF_EN_MASK); | ||
5296 | } | ||
5297 | dev_priv->busy = true; | 5893 | dev_priv->busy = true; |
5298 | } else | 5894 | else |
5299 | mod_timer(&dev_priv->idle_timer, jiffies + | 5895 | mod_timer(&dev_priv->idle_timer, jiffies + |
5300 | msecs_to_jiffies(GPU_IDLE_TIMEOUT)); | 5896 | msecs_to_jiffies(GPU_IDLE_TIMEOUT)); |
5301 | 5897 | ||
@@ -5307,14 +5903,6 @@ void intel_mark_busy(struct drm_device *dev, struct drm_i915_gem_object *obj) | |||
5307 | intel_fb = to_intel_framebuffer(crtc->fb); | 5903 | intel_fb = to_intel_framebuffer(crtc->fb); |
5308 | if (intel_fb->obj == obj) { | 5904 | if (intel_fb->obj == obj) { |
5309 | if (!intel_crtc->busy) { | 5905 | if (!intel_crtc->busy) { |
5310 | if (IS_I945G(dev) || IS_I945GM(dev)) { | ||
5311 | u32 fw_blc_self; | ||
5312 | |||
5313 | DRM_DEBUG_DRIVER("disable memory self refresh on 945\n"); | ||
5314 | fw_blc_self = I915_READ(FW_BLC_SELF); | ||
5315 | fw_blc_self &= ~FW_BLC_SELF_EN; | ||
5316 | I915_WRITE(FW_BLC_SELF, fw_blc_self | FW_BLC_SELF_EN_MASK); | ||
5317 | } | ||
5318 | /* Non-busy -> busy, upclock */ | 5906 | /* Non-busy -> busy, upclock */ |
5319 | intel_increase_pllclock(crtc); | 5907 | intel_increase_pllclock(crtc); |
5320 | intel_crtc->busy = true; | 5908 | intel_crtc->busy = true; |
@@ -5592,7 +6180,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
5592 | * pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE; | 6180 | * pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE; |
5593 | */ | 6181 | */ |
5594 | pf = 0; | 6182 | pf = 0; |
5595 | pipesrc = I915_READ(pipe == 0 ? PIPEASRC : PIPEBSRC) & 0x0fff0fff; | 6183 | pipesrc = I915_READ(PIPESRC(pipe)) & 0x0fff0fff; |
5596 | OUT_RING(pf | pipesrc); | 6184 | OUT_RING(pf | pipesrc); |
5597 | break; | 6185 | break; |
5598 | 6186 | ||
@@ -5602,8 +6190,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
5602 | OUT_RING(fb->pitch | obj->tiling_mode); | 6190 | OUT_RING(fb->pitch | obj->tiling_mode); |
5603 | OUT_RING(obj->gtt_offset); | 6191 | OUT_RING(obj->gtt_offset); |
5604 | 6192 | ||
5605 | pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE; | 6193 | pf = I915_READ(PF_CTL(pipe)) & PF_ENABLE; |
5606 | pipesrc = I915_READ(pipe == 0 ? PIPEASRC : PIPEBSRC) & 0x0fff0fff; | 6194 | pipesrc = I915_READ(PIPESRC(pipe)) & 0x0fff0fff; |
5607 | OUT_RING(pf | pipesrc); | 6195 | OUT_RING(pf | pipesrc); |
5608 | break; | 6196 | break; |
5609 | } | 6197 | } |
@@ -5692,22 +6280,8 @@ static void intel_sanitize_modesetting(struct drm_device *dev, | |||
5692 | pipe = !pipe; | 6280 | pipe = !pipe; |
5693 | 6281 | ||
5694 | /* Disable the plane and wait for it to stop reading from the pipe. */ | 6282 | /* Disable the plane and wait for it to stop reading from the pipe. */ |
5695 | I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE); | 6283 | intel_disable_plane(dev_priv, plane, pipe); |
5696 | intel_flush_display_plane(dev, plane); | 6284 | intel_disable_pipe(dev_priv, pipe); |
5697 | |||
5698 | if (IS_GEN2(dev)) | ||
5699 | intel_wait_for_vblank(dev, pipe); | ||
5700 | |||
5701 | if (pipe == 0 && (dev_priv->quirks & QUIRK_PIPEA_FORCE)) | ||
5702 | return; | ||
5703 | |||
5704 | /* Switch off the pipe. */ | ||
5705 | reg = PIPECONF(pipe); | ||
5706 | val = I915_READ(reg); | ||
5707 | if (val & PIPECONF_ENABLE) { | ||
5708 | I915_WRITE(reg, val & ~PIPECONF_ENABLE); | ||
5709 | intel_wait_for_pipe_off(dev, pipe); | ||
5710 | } | ||
5711 | } | 6285 | } |
5712 | 6286 | ||
5713 | static void intel_crtc_init(struct drm_device *dev, int pipe) | 6287 | static void intel_crtc_init(struct drm_device *dev, int pipe) |
@@ -5997,7 +6571,7 @@ intel_user_framebuffer_create(struct drm_device *dev, | |||
5997 | int ret; | 6571 | int ret; |
5998 | 6572 | ||
5999 | obj = to_intel_bo(drm_gem_object_lookup(dev, filp, mode_cmd->handle)); | 6573 | obj = to_intel_bo(drm_gem_object_lookup(dev, filp, mode_cmd->handle)); |
6000 | if (!obj) | 6574 | if (&obj->base == NULL) |
6001 | return ERR_PTR(-ENOENT); | 6575 | return ERR_PTR(-ENOENT); |
6002 | 6576 | ||
6003 | intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); | 6577 | intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); |
@@ -6319,18 +6893,18 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
6319 | I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, | 6893 | I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, |
6320 | 18 << 24 | | 6894 | 18 << 24 | |
6321 | 6 << 16); | 6895 | 6 << 16); |
6322 | I915_WRITE(GEN6_RP_UP_THRESHOLD, 90000); | 6896 | I915_WRITE(GEN6_RP_UP_THRESHOLD, 10000); |
6323 | I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 100000); | 6897 | I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 1000000); |
6324 | I915_WRITE(GEN6_RP_UP_EI, 100000); | 6898 | I915_WRITE(GEN6_RP_UP_EI, 100000); |
6325 | I915_WRITE(GEN6_RP_DOWN_EI, 300000); | 6899 | I915_WRITE(GEN6_RP_DOWN_EI, 5000000); |
6326 | I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); | 6900 | I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); |
6327 | I915_WRITE(GEN6_RP_CONTROL, | 6901 | I915_WRITE(GEN6_RP_CONTROL, |
6328 | GEN6_RP_MEDIA_TURBO | | 6902 | GEN6_RP_MEDIA_TURBO | |
6329 | GEN6_RP_USE_NORMAL_FREQ | | 6903 | GEN6_RP_USE_NORMAL_FREQ | |
6330 | GEN6_RP_MEDIA_IS_GFX | | 6904 | GEN6_RP_MEDIA_IS_GFX | |
6331 | GEN6_RP_ENABLE | | 6905 | GEN6_RP_ENABLE | |
6332 | GEN6_RP_UP_BUSY_MAX | | 6906 | GEN6_RP_UP_BUSY_AVG | |
6333 | GEN6_RP_DOWN_BUSY_MIN); | 6907 | GEN6_RP_DOWN_IDLE_CONT); |
6334 | 6908 | ||
6335 | if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0, | 6909 | if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0, |
6336 | 500)) | 6910 | 500)) |
@@ -6386,6 +6960,7 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
6386 | void intel_enable_clock_gating(struct drm_device *dev) | 6960 | void intel_enable_clock_gating(struct drm_device *dev) |
6387 | { | 6961 | { |
6388 | struct drm_i915_private *dev_priv = dev->dev_private; | 6962 | struct drm_i915_private *dev_priv = dev->dev_private; |
6963 | int pipe; | ||
6389 | 6964 | ||
6390 | /* | 6965 | /* |
6391 | * Disable clock gating reported to work incorrectly according to the | 6966 | * Disable clock gating reported to work incorrectly according to the |
@@ -6495,12 +7070,10 @@ void intel_enable_clock_gating(struct drm_device *dev) | |||
6495 | ILK_DPARB_CLK_GATE | | 7070 | ILK_DPARB_CLK_GATE | |
6496 | ILK_DPFD_CLK_GATE); | 7071 | ILK_DPFD_CLK_GATE); |
6497 | 7072 | ||
6498 | I915_WRITE(DSPACNTR, | 7073 | for_each_pipe(pipe) |
6499 | I915_READ(DSPACNTR) | | 7074 | I915_WRITE(DSPCNTR(pipe), |
6500 | DISPPLANE_TRICKLE_FEED_DISABLE); | 7075 | I915_READ(DSPCNTR(pipe)) | |
6501 | I915_WRITE(DSPBCNTR, | 7076 | DISPPLANE_TRICKLE_FEED_DISABLE); |
6502 | I915_READ(DSPBCNTR) | | ||
6503 | DISPPLANE_TRICKLE_FEED_DISABLE); | ||
6504 | } | 7077 | } |
6505 | } else if (IS_G4X(dev)) { | 7078 | } else if (IS_G4X(dev)) { |
6506 | uint32_t dspclk_gate; | 7079 | uint32_t dspclk_gate; |
@@ -6855,10 +7428,6 @@ void intel_modeset_init(struct drm_device *dev) | |||
6855 | } | 7428 | } |
6856 | dev->mode_config.fb_base = dev->agp->base; | 7429 | dev->mode_config.fb_base = dev->agp->base; |
6857 | 7430 | ||
6858 | if (IS_MOBILE(dev) || !IS_GEN2(dev)) | ||
6859 | dev_priv->num_pipe = 2; | ||
6860 | else | ||
6861 | dev_priv->num_pipe = 1; | ||
6862 | DRM_DEBUG_KMS("%d display pipe%s available.\n", | 7431 | DRM_DEBUG_KMS("%d display pipe%s available.\n", |
6863 | dev_priv->num_pipe, dev_priv->num_pipe > 1 ? "s" : ""); | 7432 | dev_priv->num_pipe, dev_priv->num_pipe > 1 ? "s" : ""); |
6864 | 7433 | ||
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 51cb4e36997..d29e33f815d 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -49,6 +49,7 @@ struct intel_dp { | |||
49 | uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]; | 49 | uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]; |
50 | bool has_audio; | 50 | bool has_audio; |
51 | int force_audio; | 51 | int force_audio; |
52 | uint32_t color_range; | ||
52 | int dpms_mode; | 53 | int dpms_mode; |
53 | uint8_t link_bw; | 54 | uint8_t link_bw; |
54 | uint8_t lane_count; | 55 | uint8_t lane_count; |
@@ -685,6 +686,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
685 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 686 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
686 | int lane_count = 4, bpp = 24; | 687 | int lane_count = 4, bpp = 24; |
687 | struct intel_dp_m_n m_n; | 688 | struct intel_dp_m_n m_n; |
689 | int pipe = intel_crtc->pipe; | ||
688 | 690 | ||
689 | /* | 691 | /* |
690 | * Find the lane count in the intel_encoder private | 692 | * Find the lane count in the intel_encoder private |
@@ -715,39 +717,19 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
715 | mode->clock, adjusted_mode->clock, &m_n); | 717 | mode->clock, adjusted_mode->clock, &m_n); |
716 | 718 | ||
717 | if (HAS_PCH_SPLIT(dev)) { | 719 | if (HAS_PCH_SPLIT(dev)) { |
718 | if (intel_crtc->pipe == 0) { | 720 | I915_WRITE(TRANSDATA_M1(pipe), |
719 | I915_WRITE(TRANSA_DATA_M1, | 721 | ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | |
720 | ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | | 722 | m_n.gmch_m); |
721 | m_n.gmch_m); | 723 | I915_WRITE(TRANSDATA_N1(pipe), m_n.gmch_n); |
722 | I915_WRITE(TRANSA_DATA_N1, m_n.gmch_n); | 724 | I915_WRITE(TRANSDPLINK_M1(pipe), m_n.link_m); |
723 | I915_WRITE(TRANSA_DP_LINK_M1, m_n.link_m); | 725 | I915_WRITE(TRANSDPLINK_N1(pipe), m_n.link_n); |
724 | I915_WRITE(TRANSA_DP_LINK_N1, m_n.link_n); | ||
725 | } else { | ||
726 | I915_WRITE(TRANSB_DATA_M1, | ||
727 | ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | | ||
728 | m_n.gmch_m); | ||
729 | I915_WRITE(TRANSB_DATA_N1, m_n.gmch_n); | ||
730 | I915_WRITE(TRANSB_DP_LINK_M1, m_n.link_m); | ||
731 | I915_WRITE(TRANSB_DP_LINK_N1, m_n.link_n); | ||
732 | } | ||
733 | } else { | 726 | } else { |
734 | if (intel_crtc->pipe == 0) { | 727 | I915_WRITE(PIPE_GMCH_DATA_M(pipe), |
735 | I915_WRITE(PIPEA_GMCH_DATA_M, | 728 | ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | |
736 | ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | | 729 | m_n.gmch_m); |
737 | m_n.gmch_m); | 730 | I915_WRITE(PIPE_GMCH_DATA_N(pipe), m_n.gmch_n); |
738 | I915_WRITE(PIPEA_GMCH_DATA_N, | 731 | I915_WRITE(PIPE_DP_LINK_M(pipe), m_n.link_m); |
739 | m_n.gmch_n); | 732 | I915_WRITE(PIPE_DP_LINK_N(pipe), m_n.link_n); |
740 | I915_WRITE(PIPEA_DP_LINK_M, m_n.link_m); | ||
741 | I915_WRITE(PIPEA_DP_LINK_N, m_n.link_n); | ||
742 | } else { | ||
743 | I915_WRITE(PIPEB_GMCH_DATA_M, | ||
744 | ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | | ||
745 | m_n.gmch_m); | ||
746 | I915_WRITE(PIPEB_GMCH_DATA_N, | ||
747 | m_n.gmch_n); | ||
748 | I915_WRITE(PIPEB_DP_LINK_M, m_n.link_m); | ||
749 | I915_WRITE(PIPEB_DP_LINK_N, m_n.link_n); | ||
750 | } | ||
751 | } | 733 | } |
752 | } | 734 | } |
753 | 735 | ||
@@ -760,8 +742,8 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
760 | struct drm_crtc *crtc = intel_dp->base.base.crtc; | 742 | struct drm_crtc *crtc = intel_dp->base.base.crtc; |
761 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 743 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
762 | 744 | ||
763 | intel_dp->DP = (DP_VOLTAGE_0_4 | | 745 | intel_dp->DP = DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; |
764 | DP_PRE_EMPHASIS_0); | 746 | intel_dp->DP |= intel_dp->color_range; |
765 | 747 | ||
766 | if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) | 748 | if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) |
767 | intel_dp->DP |= DP_SYNC_HS_HIGH; | 749 | intel_dp->DP |= DP_SYNC_HS_HIGH; |
@@ -813,6 +795,40 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
813 | } | 795 | } |
814 | } | 796 | } |
815 | 797 | ||
798 | static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp) | ||
799 | { | ||
800 | struct drm_device *dev = intel_dp->base.base.dev; | ||
801 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
802 | u32 pp; | ||
803 | |||
804 | /* | ||
805 | * If the panel wasn't on, make sure there's not a currently | ||
806 | * active PP sequence before enabling AUX VDD. | ||
807 | */ | ||
808 | if (!(I915_READ(PCH_PP_STATUS) & PP_ON)) | ||
809 | msleep(dev_priv->panel_t3); | ||
810 | |||
811 | pp = I915_READ(PCH_PP_CONTROL); | ||
812 | pp |= EDP_FORCE_VDD; | ||
813 | I915_WRITE(PCH_PP_CONTROL, pp); | ||
814 | POSTING_READ(PCH_PP_CONTROL); | ||
815 | } | ||
816 | |||
817 | static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp) | ||
818 | { | ||
819 | struct drm_device *dev = intel_dp->base.base.dev; | ||
820 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
821 | u32 pp; | ||
822 | |||
823 | pp = I915_READ(PCH_PP_CONTROL); | ||
824 | pp &= ~EDP_FORCE_VDD; | ||
825 | I915_WRITE(PCH_PP_CONTROL, pp); | ||
826 | POSTING_READ(PCH_PP_CONTROL); | ||
827 | |||
828 | /* Make sure sequencer is idle before allowing subsequent activity */ | ||
829 | msleep(dev_priv->panel_t12); | ||
830 | } | ||
831 | |||
816 | /* Returns true if the panel was already on when called */ | 832 | /* Returns true if the panel was already on when called */ |
817 | static bool ironlake_edp_panel_on (struct intel_dp *intel_dp) | 833 | static bool ironlake_edp_panel_on (struct intel_dp *intel_dp) |
818 | { | 834 | { |
@@ -834,11 +850,6 @@ static bool ironlake_edp_panel_on (struct intel_dp *intel_dp) | |||
834 | I915_WRITE(PCH_PP_CONTROL, pp); | 850 | I915_WRITE(PCH_PP_CONTROL, pp); |
835 | POSTING_READ(PCH_PP_CONTROL); | 851 | POSTING_READ(PCH_PP_CONTROL); |
836 | 852 | ||
837 | /* Ouch. We need to wait here for some panels, like Dell e6510 | ||
838 | * https://bugs.freedesktop.org/show_bug.cgi?id=29278i | ||
839 | */ | ||
840 | msleep(300); | ||
841 | |||
842 | if (wait_for((I915_READ(PCH_PP_STATUS) & idle_on_mask) == idle_on_mask, | 853 | if (wait_for((I915_READ(PCH_PP_STATUS) & idle_on_mask) == idle_on_mask, |
843 | 5000)) | 854 | 5000)) |
844 | DRM_ERROR("panel on wait timed out: 0x%08x\n", | 855 | DRM_ERROR("panel on wait timed out: 0x%08x\n", |
@@ -875,11 +886,6 @@ static void ironlake_edp_panel_off (struct drm_device *dev) | |||
875 | pp |= PANEL_POWER_RESET; /* restore panel reset bit */ | 886 | pp |= PANEL_POWER_RESET; /* restore panel reset bit */ |
876 | I915_WRITE(PCH_PP_CONTROL, pp); | 887 | I915_WRITE(PCH_PP_CONTROL, pp); |
877 | POSTING_READ(PCH_PP_CONTROL); | 888 | POSTING_READ(PCH_PP_CONTROL); |
878 | |||
879 | /* Ouch. We need to wait here for some panels, like Dell e6510 | ||
880 | * https://bugs.freedesktop.org/show_bug.cgi?id=29278i | ||
881 | */ | ||
882 | msleep(300); | ||
883 | } | 889 | } |
884 | 890 | ||
885 | static void ironlake_edp_backlight_on (struct drm_device *dev) | 891 | static void ironlake_edp_backlight_on (struct drm_device *dev) |
@@ -945,7 +951,7 @@ static void intel_dp_prepare(struct drm_encoder *encoder) | |||
945 | 951 | ||
946 | if (is_edp(intel_dp)) { | 952 | if (is_edp(intel_dp)) { |
947 | ironlake_edp_backlight_off(dev); | 953 | ironlake_edp_backlight_off(dev); |
948 | ironlake_edp_panel_on(intel_dp); | 954 | ironlake_edp_panel_off(dev); |
949 | if (!is_pch_edp(intel_dp)) | 955 | if (!is_pch_edp(intel_dp)) |
950 | ironlake_edp_pll_on(encoder); | 956 | ironlake_edp_pll_on(encoder); |
951 | else | 957 | else |
@@ -959,10 +965,15 @@ static void intel_dp_commit(struct drm_encoder *encoder) | |||
959 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); | 965 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
960 | struct drm_device *dev = encoder->dev; | 966 | struct drm_device *dev = encoder->dev; |
961 | 967 | ||
968 | if (is_edp(intel_dp)) | ||
969 | ironlake_edp_panel_vdd_on(intel_dp); | ||
970 | |||
962 | intel_dp_start_link_train(intel_dp); | 971 | intel_dp_start_link_train(intel_dp); |
963 | 972 | ||
964 | if (is_edp(intel_dp)) | 973 | if (is_edp(intel_dp)) { |
965 | ironlake_edp_panel_on(intel_dp); | 974 | ironlake_edp_panel_on(intel_dp); |
975 | ironlake_edp_panel_vdd_off(intel_dp); | ||
976 | } | ||
966 | 977 | ||
967 | intel_dp_complete_link_train(intel_dp); | 978 | intel_dp_complete_link_train(intel_dp); |
968 | 979 | ||
@@ -988,9 +999,13 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) | |||
988 | ironlake_edp_pll_off(encoder); | 999 | ironlake_edp_pll_off(encoder); |
989 | } else { | 1000 | } else { |
990 | if (is_edp(intel_dp)) | 1001 | if (is_edp(intel_dp)) |
991 | ironlake_edp_panel_on(intel_dp); | 1002 | ironlake_edp_panel_vdd_on(intel_dp); |
992 | if (!(dp_reg & DP_PORT_EN)) { | 1003 | if (!(dp_reg & DP_PORT_EN)) { |
993 | intel_dp_start_link_train(intel_dp); | 1004 | intel_dp_start_link_train(intel_dp); |
1005 | if (is_edp(intel_dp)) { | ||
1006 | ironlake_edp_panel_on(intel_dp); | ||
1007 | ironlake_edp_panel_vdd_off(intel_dp); | ||
1008 | } | ||
994 | intel_dp_complete_link_train(intel_dp); | 1009 | intel_dp_complete_link_train(intel_dp); |
995 | } | 1010 | } |
996 | if (is_edp(intel_dp)) | 1011 | if (is_edp(intel_dp)) |
@@ -1508,9 +1523,13 @@ ironlake_dp_detect(struct intel_dp *intel_dp) | |||
1508 | { | 1523 | { |
1509 | enum drm_connector_status status; | 1524 | enum drm_connector_status status; |
1510 | 1525 | ||
1511 | /* Can't disconnect eDP */ | 1526 | /* Can't disconnect eDP, but you can close the lid... */ |
1512 | if (is_edp(intel_dp)) | 1527 | if (is_edp(intel_dp)) { |
1513 | return connector_status_connected; | 1528 | status = intel_panel_detect(intel_dp->base.base.dev); |
1529 | if (status == connector_status_unknown) | ||
1530 | status = connector_status_connected; | ||
1531 | return status; | ||
1532 | } | ||
1514 | 1533 | ||
1515 | status = connector_status_disconnected; | 1534 | status = connector_status_disconnected; |
1516 | if (intel_dp_aux_native_read(intel_dp, | 1535 | if (intel_dp_aux_native_read(intel_dp, |
@@ -1662,6 +1681,7 @@ intel_dp_set_property(struct drm_connector *connector, | |||
1662 | struct drm_property *property, | 1681 | struct drm_property *property, |
1663 | uint64_t val) | 1682 | uint64_t val) |
1664 | { | 1683 | { |
1684 | struct drm_i915_private *dev_priv = connector->dev->dev_private; | ||
1665 | struct intel_dp *intel_dp = intel_attached_dp(connector); | 1685 | struct intel_dp *intel_dp = intel_attached_dp(connector); |
1666 | int ret; | 1686 | int ret; |
1667 | 1687 | ||
@@ -1690,6 +1710,14 @@ intel_dp_set_property(struct drm_connector *connector, | |||
1690 | goto done; | 1710 | goto done; |
1691 | } | 1711 | } |
1692 | 1712 | ||
1713 | if (property == dev_priv->broadcast_rgb_property) { | ||
1714 | if (val == !!intel_dp->color_range) | ||
1715 | return 0; | ||
1716 | |||
1717 | intel_dp->color_range = val ? DP_COLOR_RANGE_16_235 : 0; | ||
1718 | goto done; | ||
1719 | } | ||
1720 | |||
1693 | return -EINVAL; | 1721 | return -EINVAL; |
1694 | 1722 | ||
1695 | done: | 1723 | done: |
@@ -1809,6 +1837,8 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect | |||
1809 | intel_dp->force_audio_property->values[1] = 1; | 1837 | intel_dp->force_audio_property->values[1] = 1; |
1810 | drm_connector_attach_property(connector, intel_dp->force_audio_property, 0); | 1838 | drm_connector_attach_property(connector, intel_dp->force_audio_property, 0); |
1811 | } | 1839 | } |
1840 | |||
1841 | intel_attach_broadcast_rgb_property(connector); | ||
1812 | } | 1842 | } |
1813 | 1843 | ||
1814 | void | 1844 | void |
@@ -1826,6 +1856,9 @@ intel_dp_init(struct drm_device *dev, int output_reg) | |||
1826 | if (!intel_dp) | 1856 | if (!intel_dp) |
1827 | return; | 1857 | return; |
1828 | 1858 | ||
1859 | intel_dp->output_reg = output_reg; | ||
1860 | intel_dp->dpms_mode = -1; | ||
1861 | |||
1829 | intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); | 1862 | intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); |
1830 | if (!intel_connector) { | 1863 | if (!intel_connector) { |
1831 | kfree(intel_dp); | 1864 | kfree(intel_dp); |
@@ -1865,10 +1898,6 @@ intel_dp_init(struct drm_device *dev, int output_reg) | |||
1865 | connector->interlace_allowed = true; | 1898 | connector->interlace_allowed = true; |
1866 | connector->doublescan_allowed = 0; | 1899 | connector->doublescan_allowed = 0; |
1867 | 1900 | ||
1868 | intel_dp->output_reg = output_reg; | ||
1869 | intel_dp->has_audio = false; | ||
1870 | intel_dp->dpms_mode = DRM_MODE_DPMS_ON; | ||
1871 | |||
1872 | drm_encoder_init(dev, &intel_encoder->base, &intel_dp_enc_funcs, | 1901 | drm_encoder_init(dev, &intel_encoder->base, &intel_dp_enc_funcs, |
1873 | DRM_MODE_ENCODER_TMDS); | 1902 | DRM_MODE_ENCODER_TMDS); |
1874 | drm_encoder_helper_add(&intel_encoder->base, &intel_dp_helper_funcs); | 1903 | drm_encoder_helper_add(&intel_encoder->base, &intel_dp_helper_funcs); |
@@ -1906,21 +1935,33 @@ intel_dp_init(struct drm_device *dev, int output_reg) | |||
1906 | /* Cache some DPCD data in the eDP case */ | 1935 | /* Cache some DPCD data in the eDP case */ |
1907 | if (is_edp(intel_dp)) { | 1936 | if (is_edp(intel_dp)) { |
1908 | int ret; | 1937 | int ret; |
1909 | bool was_on; | 1938 | u32 pp_on, pp_div; |
1910 | 1939 | ||
1911 | was_on = ironlake_edp_panel_on(intel_dp); | 1940 | pp_on = I915_READ(PCH_PP_ON_DELAYS); |
1941 | pp_div = I915_READ(PCH_PP_DIVISOR); | ||
1942 | |||
1943 | /* Get T3 & T12 values (note: VESA not bspec terminology) */ | ||
1944 | dev_priv->panel_t3 = (pp_on & 0x1fff0000) >> 16; | ||
1945 | dev_priv->panel_t3 /= 10; /* t3 in 100us units */ | ||
1946 | dev_priv->panel_t12 = pp_div & 0xf; | ||
1947 | dev_priv->panel_t12 *= 100; /* t12 in 100ms units */ | ||
1948 | |||
1949 | ironlake_edp_panel_vdd_on(intel_dp); | ||
1912 | ret = intel_dp_aux_native_read(intel_dp, DP_DPCD_REV, | 1950 | ret = intel_dp_aux_native_read(intel_dp, DP_DPCD_REV, |
1913 | intel_dp->dpcd, | 1951 | intel_dp->dpcd, |
1914 | sizeof(intel_dp->dpcd)); | 1952 | sizeof(intel_dp->dpcd)); |
1953 | ironlake_edp_panel_vdd_off(intel_dp); | ||
1915 | if (ret == sizeof(intel_dp->dpcd)) { | 1954 | if (ret == sizeof(intel_dp->dpcd)) { |
1916 | if (intel_dp->dpcd[0] >= 0x11) | 1955 | if (intel_dp->dpcd[0] >= 0x11) |
1917 | dev_priv->no_aux_handshake = intel_dp->dpcd[3] & | 1956 | dev_priv->no_aux_handshake = intel_dp->dpcd[3] & |
1918 | DP_NO_AUX_HANDSHAKE_LINK_TRAINING; | 1957 | DP_NO_AUX_HANDSHAKE_LINK_TRAINING; |
1919 | } else { | 1958 | } else { |
1959 | /* if this fails, presume the device is a ghost */ | ||
1920 | DRM_ERROR("failed to retrieve link info\n"); | 1960 | DRM_ERROR("failed to retrieve link info\n"); |
1961 | intel_dp_destroy(&intel_connector->base); | ||
1962 | intel_dp_encoder_destroy(&intel_dp->base.base); | ||
1963 | return; | ||
1921 | } | 1964 | } |
1922 | if (!was_on) | ||
1923 | ironlake_edp_panel_off(dev); | ||
1924 | } | 1965 | } |
1925 | 1966 | ||
1926 | intel_encoder->hot_plug = intel_dp_hot_plug; | 1967 | intel_encoder->hot_plug = intel_dp_hot_plug; |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 2c431049963..5daa991cb28 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -217,6 +217,13 @@ intel_get_crtc_for_pipe(struct drm_device *dev, int pipe) | |||
217 | return dev_priv->pipe_to_crtc_mapping[pipe]; | 217 | return dev_priv->pipe_to_crtc_mapping[pipe]; |
218 | } | 218 | } |
219 | 219 | ||
220 | static inline struct drm_crtc * | ||
221 | intel_get_crtc_for_plane(struct drm_device *dev, int plane) | ||
222 | { | ||
223 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
224 | return dev_priv->plane_to_crtc_mapping[plane]; | ||
225 | } | ||
226 | |||
220 | struct intel_unpin_work { | 227 | struct intel_unpin_work { |
221 | struct work_struct work; | 228 | struct work_struct work; |
222 | struct drm_device *dev; | 229 | struct drm_device *dev; |
@@ -230,6 +237,8 @@ struct intel_unpin_work { | |||
230 | int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter); | 237 | int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter); |
231 | extern bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus); | 238 | extern bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus); |
232 | 239 | ||
240 | extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector); | ||
241 | |||
233 | extern void intel_crt_init(struct drm_device *dev); | 242 | extern void intel_crt_init(struct drm_device *dev); |
234 | extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg); | 243 | extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg); |
235 | void intel_dip_infoframe_csum(struct dip_infoframe *avi_if); | 244 | void intel_dip_infoframe_csum(struct dip_infoframe *avi_if); |
@@ -260,6 +269,7 @@ extern void intel_panel_set_backlight(struct drm_device *dev, u32 level); | |||
260 | extern void intel_panel_setup_backlight(struct drm_device *dev); | 269 | extern void intel_panel_setup_backlight(struct drm_device *dev); |
261 | extern void intel_panel_enable_backlight(struct drm_device *dev); | 270 | extern void intel_panel_enable_backlight(struct drm_device *dev); |
262 | extern void intel_panel_disable_backlight(struct drm_device *dev); | 271 | extern void intel_panel_disable_backlight(struct drm_device *dev); |
272 | extern enum drm_connector_status intel_panel_detect(struct drm_device *dev); | ||
263 | 273 | ||
264 | extern void intel_crtc_load_lut(struct drm_crtc *crtc); | 274 | extern void intel_crtc_load_lut(struct drm_crtc *crtc); |
265 | extern void intel_encoder_prepare (struct drm_encoder *encoder); | 275 | extern void intel_encoder_prepare (struct drm_encoder *encoder); |
@@ -321,8 +331,7 @@ extern void intel_finish_page_flip_plane(struct drm_device *dev, int plane); | |||
321 | 331 | ||
322 | extern void intel_setup_overlay(struct drm_device *dev); | 332 | extern void intel_setup_overlay(struct drm_device *dev); |
323 | extern void intel_cleanup_overlay(struct drm_device *dev); | 333 | extern void intel_cleanup_overlay(struct drm_device *dev); |
324 | extern int intel_overlay_switch_off(struct intel_overlay *overlay, | 334 | extern int intel_overlay_switch_off(struct intel_overlay *overlay); |
325 | bool interruptible); | ||
326 | extern int intel_overlay_put_image(struct drm_device *dev, void *data, | 335 | extern int intel_overlay_put_image(struct drm_device *dev, void *data, |
327 | struct drm_file *file_priv); | 336 | struct drm_file *file_priv); |
328 | extern int intel_overlay_attrs(struct drm_device *dev, void *data, | 337 | extern int intel_overlay_attrs(struct drm_device *dev, void *data, |
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index ea373283c93..6eda1b51c63 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c | |||
@@ -178,7 +178,7 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder, | |||
178 | int pipe = intel_crtc->pipe; | 178 | int pipe = intel_crtc->pipe; |
179 | u32 dvo_val; | 179 | u32 dvo_val; |
180 | u32 dvo_reg = intel_dvo->dev.dvo_reg, dvo_srcdim_reg; | 180 | u32 dvo_reg = intel_dvo->dev.dvo_reg, dvo_srcdim_reg; |
181 | int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; | 181 | int dpll_reg = DPLL(pipe); |
182 | 182 | ||
183 | switch (dvo_reg) { | 183 | switch (dvo_reg) { |
184 | case DVOA: | 184 | case DVOA: |
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index c635c9e357b..f289b864297 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
@@ -41,6 +41,7 @@ struct intel_hdmi { | |||
41 | struct intel_encoder base; | 41 | struct intel_encoder base; |
42 | u32 sdvox_reg; | 42 | u32 sdvox_reg; |
43 | int ddc_bus; | 43 | int ddc_bus; |
44 | uint32_t color_range; | ||
44 | bool has_hdmi_sink; | 45 | bool has_hdmi_sink; |
45 | bool has_audio; | 46 | bool has_audio; |
46 | int force_audio; | 47 | int force_audio; |
@@ -124,6 +125,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, | |||
124 | u32 sdvox; | 125 | u32 sdvox; |
125 | 126 | ||
126 | sdvox = SDVO_ENCODING_HDMI | SDVO_BORDER_ENABLE; | 127 | sdvox = SDVO_ENCODING_HDMI | SDVO_BORDER_ENABLE; |
128 | sdvox |= intel_hdmi->color_range; | ||
127 | if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) | 129 | if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) |
128 | sdvox |= SDVO_VSYNC_ACTIVE_HIGH; | 130 | sdvox |= SDVO_VSYNC_ACTIVE_HIGH; |
129 | if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) | 131 | if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) |
@@ -278,6 +280,7 @@ intel_hdmi_set_property(struct drm_connector *connector, | |||
278 | uint64_t val) | 280 | uint64_t val) |
279 | { | 281 | { |
280 | struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); | 282 | struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); |
283 | struct drm_i915_private *dev_priv = connector->dev->dev_private; | ||
281 | int ret; | 284 | int ret; |
282 | 285 | ||
283 | ret = drm_connector_property_set_value(connector, property, val); | 286 | ret = drm_connector_property_set_value(connector, property, val); |
@@ -305,6 +308,14 @@ intel_hdmi_set_property(struct drm_connector *connector, | |||
305 | goto done; | 308 | goto done; |
306 | } | 309 | } |
307 | 310 | ||
311 | if (property == dev_priv->broadcast_rgb_property) { | ||
312 | if (val == !!intel_hdmi->color_range) | ||
313 | return 0; | ||
314 | |||
315 | intel_hdmi->color_range = val ? SDVO_COLOR_RANGE_16_235 : 0; | ||
316 | goto done; | ||
317 | } | ||
318 | |||
308 | return -EINVAL; | 319 | return -EINVAL; |
309 | 320 | ||
310 | done: | 321 | done: |
@@ -363,6 +374,8 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c | |||
363 | intel_hdmi->force_audio_property->values[1] = 1; | 374 | intel_hdmi->force_audio_property->values[1] = 1; |
364 | drm_connector_attach_property(connector, intel_hdmi->force_audio_property, 0); | 375 | drm_connector_attach_property(connector, intel_hdmi->force_audio_property, 0); |
365 | } | 376 | } |
377 | |||
378 | intel_attach_broadcast_rgb_property(connector); | ||
366 | } | 379 | } |
367 | 380 | ||
368 | void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) | 381 | void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) |
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index 58040f68ed7..82d04c5899d 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c | |||
@@ -384,7 +384,8 @@ int intel_setup_gmbus(struct drm_device *dev) | |||
384 | bus->reg0 = i | GMBUS_RATE_100KHZ; | 384 | bus->reg0 = i | GMBUS_RATE_100KHZ; |
385 | 385 | ||
386 | /* XXX force bit banging until GMBUS is fully debugged */ | 386 | /* XXX force bit banging until GMBUS is fully debugged */ |
387 | bus->force_bit = intel_gpio_create(dev_priv, i); | 387 | if (IS_GEN2(dev)) |
388 | bus->force_bit = intel_gpio_create(dev_priv, i); | ||
388 | } | 389 | } |
389 | 390 | ||
390 | intel_i2c_reset(dev_priv->dev); | 391 | intel_i2c_reset(dev_priv->dev); |
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index bcdba7bd5cf..1a311ad0111 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
@@ -231,6 +231,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
231 | struct intel_lvds *intel_lvds = to_intel_lvds(encoder); | 231 | struct intel_lvds *intel_lvds = to_intel_lvds(encoder); |
232 | struct drm_encoder *tmp_encoder; | 232 | struct drm_encoder *tmp_encoder; |
233 | u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; | 233 | u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; |
234 | int pipe; | ||
234 | 235 | ||
235 | /* Should never happen!! */ | 236 | /* Should never happen!! */ |
236 | if (INTEL_INFO(dev)->gen < 4 && intel_crtc->pipe == 0) { | 237 | if (INTEL_INFO(dev)->gen < 4 && intel_crtc->pipe == 0) { |
@@ -277,8 +278,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
277 | * to register description and PRM. | 278 | * to register description and PRM. |
278 | * Change the value here to see the borders for debugging | 279 | * Change the value here to see the borders for debugging |
279 | */ | 280 | */ |
280 | I915_WRITE(BCLRPAT_A, 0); | 281 | for_each_pipe(pipe) |
281 | I915_WRITE(BCLRPAT_B, 0); | 282 | I915_WRITE(BCLRPAT(pipe), 0); |
282 | 283 | ||
283 | switch (intel_lvds->fitting_mode) { | 284 | switch (intel_lvds->fitting_mode) { |
284 | case DRM_MODE_SCALE_CENTER: | 285 | case DRM_MODE_SCALE_CENTER: |
@@ -474,6 +475,10 @@ intel_lvds_detect(struct drm_connector *connector, bool force) | |||
474 | struct drm_device *dev = connector->dev; | 475 | struct drm_device *dev = connector->dev; |
475 | enum drm_connector_status status = connector_status_connected; | 476 | enum drm_connector_status status = connector_status_connected; |
476 | 477 | ||
478 | status = intel_panel_detect(dev); | ||
479 | if (status != connector_status_unknown) | ||
480 | return status; | ||
481 | |||
477 | /* ACPI lid methods were generally unreliable in this generation, so | 482 | /* ACPI lid methods were generally unreliable in this generation, so |
478 | * don't even bother. | 483 | * don't even bother. |
479 | */ | 484 | */ |
@@ -496,7 +501,7 @@ static int intel_lvds_get_modes(struct drm_connector *connector) | |||
496 | return drm_add_edid_modes(connector, intel_lvds->edid); | 501 | return drm_add_edid_modes(connector, intel_lvds->edid); |
497 | 502 | ||
498 | mode = drm_mode_duplicate(dev, intel_lvds->fixed_mode); | 503 | mode = drm_mode_duplicate(dev, intel_lvds->fixed_mode); |
499 | if (mode == 0) | 504 | if (mode == NULL) |
500 | return 0; | 505 | return 0; |
501 | 506 | ||
502 | drm_mode_probed_add(connector, mode); | 507 | drm_mode_probed_add(connector, mode); |
diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c index f70b7cf32bf..9034dd8f33c 100644 --- a/drivers/gpu/drm/i915/intel_modes.c +++ b/drivers/gpu/drm/i915/intel_modes.c | |||
@@ -80,3 +80,33 @@ int intel_ddc_get_modes(struct drm_connector *connector, | |||
80 | 80 | ||
81 | return ret; | 81 | return ret; |
82 | } | 82 | } |
83 | |||
84 | static const char *broadcast_rgb_names[] = { | ||
85 | "Full", | ||
86 | "Limited 16:235", | ||
87 | }; | ||
88 | |||
89 | void | ||
90 | intel_attach_broadcast_rgb_property(struct drm_connector *connector) | ||
91 | { | ||
92 | struct drm_device *dev = connector->dev; | ||
93 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
94 | struct drm_property *prop; | ||
95 | int i; | ||
96 | |||
97 | prop = dev_priv->broadcast_rgb_property; | ||
98 | if (prop == NULL) { | ||
99 | prop = drm_property_create(dev, DRM_MODE_PROP_ENUM, | ||
100 | "Broadcast RGB", | ||
101 | ARRAY_SIZE(broadcast_rgb_names)); | ||
102 | if (prop == NULL) | ||
103 | return; | ||
104 | |||
105 | for (i = 0; i < ARRAY_SIZE(broadcast_rgb_names); i++) | ||
106 | drm_property_add_enum(prop, i, i, broadcast_rgb_names[i]); | ||
107 | |||
108 | dev_priv->broadcast_rgb_property = prop; | ||
109 | } | ||
110 | |||
111 | drm_connector_attach_property(connector, prop, 0); | ||
112 | } | ||
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index 64fd64443ca..d2c71042290 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c | |||
@@ -39,6 +39,8 @@ | |||
39 | 39 | ||
40 | #define OPREGION_HEADER_OFFSET 0 | 40 | #define OPREGION_HEADER_OFFSET 0 |
41 | #define OPREGION_ACPI_OFFSET 0x100 | 41 | #define OPREGION_ACPI_OFFSET 0x100 |
42 | #define ACPI_CLID 0x01ac /* current lid state indicator */ | ||
43 | #define ACPI_CDCK 0x01b0 /* current docking state indicator */ | ||
42 | #define OPREGION_SWSCI_OFFSET 0x200 | 44 | #define OPREGION_SWSCI_OFFSET 0x200 |
43 | #define OPREGION_ASLE_OFFSET 0x300 | 45 | #define OPREGION_ASLE_OFFSET 0x300 |
44 | #define OPREGION_VBT_OFFSET 0x400 | 46 | #define OPREGION_VBT_OFFSET 0x400 |
@@ -489,6 +491,8 @@ int intel_opregion_setup(struct drm_device *dev) | |||
489 | opregion->header = base; | 491 | opregion->header = base; |
490 | opregion->vbt = base + OPREGION_VBT_OFFSET; | 492 | opregion->vbt = base + OPREGION_VBT_OFFSET; |
491 | 493 | ||
494 | opregion->lid_state = base + ACPI_CLID; | ||
495 | |||
492 | mboxes = opregion->header->mboxes; | 496 | mboxes = opregion->header->mboxes; |
493 | if (mboxes & MBOX_ACPI) { | 497 | if (mboxes & MBOX_ACPI) { |
494 | DRM_DEBUG_DRIVER("Public ACPI methods supported\n"); | 498 | DRM_DEBUG_DRIVER("Public ACPI methods supported\n"); |
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 3fbb98b948d..a670c006982 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c | |||
@@ -213,7 +213,6 @@ static void intel_overlay_unmap_regs(struct intel_overlay *overlay, | |||
213 | 213 | ||
214 | static int intel_overlay_do_wait_request(struct intel_overlay *overlay, | 214 | static int intel_overlay_do_wait_request(struct intel_overlay *overlay, |
215 | struct drm_i915_gem_request *request, | 215 | struct drm_i915_gem_request *request, |
216 | bool interruptible, | ||
217 | void (*tail)(struct intel_overlay *)) | 216 | void (*tail)(struct intel_overlay *)) |
218 | { | 217 | { |
219 | struct drm_device *dev = overlay->dev; | 218 | struct drm_device *dev = overlay->dev; |
@@ -221,16 +220,14 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay, | |||
221 | int ret; | 220 | int ret; |
222 | 221 | ||
223 | BUG_ON(overlay->last_flip_req); | 222 | BUG_ON(overlay->last_flip_req); |
224 | ret = i915_add_request(dev, NULL, request, LP_RING(dev_priv)); | 223 | ret = i915_add_request(LP_RING(dev_priv), NULL, request); |
225 | if (ret) { | 224 | if (ret) { |
226 | kfree(request); | 225 | kfree(request); |
227 | return ret; | 226 | return ret; |
228 | } | 227 | } |
229 | overlay->last_flip_req = request->seqno; | 228 | overlay->last_flip_req = request->seqno; |
230 | overlay->flip_tail = tail; | 229 | overlay->flip_tail = tail; |
231 | ret = i915_do_wait_request(dev, | 230 | ret = i915_wait_request(LP_RING(dev_priv), overlay->last_flip_req); |
232 | overlay->last_flip_req, true, | ||
233 | LP_RING(dev_priv)); | ||
234 | if (ret) | 231 | if (ret) |
235 | return ret; | 232 | return ret; |
236 | 233 | ||
@@ -256,7 +253,7 @@ i830_activate_pipe_a(struct drm_device *dev) | |||
256 | return 0; | 253 | return 0; |
257 | 254 | ||
258 | /* most i8xx have pipe a forced on, so don't trust dpms mode */ | 255 | /* most i8xx have pipe a forced on, so don't trust dpms mode */ |
259 | if (I915_READ(PIPEACONF) & PIPECONF_ENABLE) | 256 | if (I915_READ(_PIPEACONF) & PIPECONF_ENABLE) |
260 | return 0; | 257 | return 0; |
261 | 258 | ||
262 | crtc_funcs = crtc->base.helper_private; | 259 | crtc_funcs = crtc->base.helper_private; |
@@ -322,7 +319,7 @@ static int intel_overlay_on(struct intel_overlay *overlay) | |||
322 | OUT_RING(MI_NOOP); | 319 | OUT_RING(MI_NOOP); |
323 | ADVANCE_LP_RING(); | 320 | ADVANCE_LP_RING(); |
324 | 321 | ||
325 | ret = intel_overlay_do_wait_request(overlay, request, true, NULL); | 322 | ret = intel_overlay_do_wait_request(overlay, request, NULL); |
326 | out: | 323 | out: |
327 | if (pipe_a_quirk) | 324 | if (pipe_a_quirk) |
328 | i830_deactivate_pipe_a(dev); | 325 | i830_deactivate_pipe_a(dev); |
@@ -364,7 +361,7 @@ static int intel_overlay_continue(struct intel_overlay *overlay, | |||
364 | OUT_RING(flip_addr); | 361 | OUT_RING(flip_addr); |
365 | ADVANCE_LP_RING(); | 362 | ADVANCE_LP_RING(); |
366 | 363 | ||
367 | ret = i915_add_request(dev, NULL, request, LP_RING(dev_priv)); | 364 | ret = i915_add_request(LP_RING(dev_priv), NULL, request); |
368 | if (ret) { | 365 | if (ret) { |
369 | kfree(request); | 366 | kfree(request); |
370 | return ret; | 367 | return ret; |
@@ -401,8 +398,7 @@ static void intel_overlay_off_tail(struct intel_overlay *overlay) | |||
401 | } | 398 | } |
402 | 399 | ||
403 | /* overlay needs to be disabled in OCMD reg */ | 400 | /* overlay needs to be disabled in OCMD reg */ |
404 | static int intel_overlay_off(struct intel_overlay *overlay, | 401 | static int intel_overlay_off(struct intel_overlay *overlay) |
405 | bool interruptible) | ||
406 | { | 402 | { |
407 | struct drm_device *dev = overlay->dev; | 403 | struct drm_device *dev = overlay->dev; |
408 | struct drm_i915_private *dev_priv = dev->dev_private; | 404 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -437,14 +433,13 @@ static int intel_overlay_off(struct intel_overlay *overlay, | |||
437 | OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); | 433 | OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); |
438 | ADVANCE_LP_RING(); | 434 | ADVANCE_LP_RING(); |
439 | 435 | ||
440 | return intel_overlay_do_wait_request(overlay, request, interruptible, | 436 | return intel_overlay_do_wait_request(overlay, request, |
441 | intel_overlay_off_tail); | 437 | intel_overlay_off_tail); |
442 | } | 438 | } |
443 | 439 | ||
444 | /* recover from an interruption due to a signal | 440 | /* recover from an interruption due to a signal |
445 | * We have to be careful not to repeat work forever an make forward progess. */ | 441 | * We have to be careful not to repeat work forever an make forward progess. */ |
446 | static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay, | 442 | static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay) |
447 | bool interruptible) | ||
448 | { | 443 | { |
449 | struct drm_device *dev = overlay->dev; | 444 | struct drm_device *dev = overlay->dev; |
450 | drm_i915_private_t *dev_priv = dev->dev_private; | 445 | drm_i915_private_t *dev_priv = dev->dev_private; |
@@ -453,8 +448,7 @@ static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay, | |||
453 | if (overlay->last_flip_req == 0) | 448 | if (overlay->last_flip_req == 0) |
454 | return 0; | 449 | return 0; |
455 | 450 | ||
456 | ret = i915_do_wait_request(dev, overlay->last_flip_req, | 451 | ret = i915_wait_request(LP_RING(dev_priv), overlay->last_flip_req); |
457 | interruptible, LP_RING(dev_priv)); | ||
458 | if (ret) | 452 | if (ret) |
459 | return ret; | 453 | return ret; |
460 | 454 | ||
@@ -499,7 +493,7 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay) | |||
499 | OUT_RING(MI_NOOP); | 493 | OUT_RING(MI_NOOP); |
500 | ADVANCE_LP_RING(); | 494 | ADVANCE_LP_RING(); |
501 | 495 | ||
502 | ret = intel_overlay_do_wait_request(overlay, request, true, | 496 | ret = intel_overlay_do_wait_request(overlay, request, |
503 | intel_overlay_release_old_vid_tail); | 497 | intel_overlay_release_old_vid_tail); |
504 | if (ret) | 498 | if (ret) |
505 | return ret; | 499 | return ret; |
@@ -868,8 +862,7 @@ out_unpin: | |||
868 | return ret; | 862 | return ret; |
869 | } | 863 | } |
870 | 864 | ||
871 | int intel_overlay_switch_off(struct intel_overlay *overlay, | 865 | int intel_overlay_switch_off(struct intel_overlay *overlay) |
872 | bool interruptible) | ||
873 | { | 866 | { |
874 | struct overlay_registers *regs; | 867 | struct overlay_registers *regs; |
875 | struct drm_device *dev = overlay->dev; | 868 | struct drm_device *dev = overlay->dev; |
@@ -878,7 +871,7 @@ int intel_overlay_switch_off(struct intel_overlay *overlay, | |||
878 | BUG_ON(!mutex_is_locked(&dev->struct_mutex)); | 871 | BUG_ON(!mutex_is_locked(&dev->struct_mutex)); |
879 | BUG_ON(!mutex_is_locked(&dev->mode_config.mutex)); | 872 | BUG_ON(!mutex_is_locked(&dev->mode_config.mutex)); |
880 | 873 | ||
881 | ret = intel_overlay_recover_from_interrupt(overlay, interruptible); | 874 | ret = intel_overlay_recover_from_interrupt(overlay); |
882 | if (ret != 0) | 875 | if (ret != 0) |
883 | return ret; | 876 | return ret; |
884 | 877 | ||
@@ -893,7 +886,7 @@ int intel_overlay_switch_off(struct intel_overlay *overlay, | |||
893 | regs->OCMD = 0; | 886 | regs->OCMD = 0; |
894 | intel_overlay_unmap_regs(overlay, regs); | 887 | intel_overlay_unmap_regs(overlay, regs); |
895 | 888 | ||
896 | ret = intel_overlay_off(overlay, interruptible); | 889 | ret = intel_overlay_off(overlay); |
897 | if (ret != 0) | 890 | if (ret != 0) |
898 | return ret; | 891 | return ret; |
899 | 892 | ||
@@ -1135,7 +1128,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, | |||
1135 | mutex_lock(&dev->mode_config.mutex); | 1128 | mutex_lock(&dev->mode_config.mutex); |
1136 | mutex_lock(&dev->struct_mutex); | 1129 | mutex_lock(&dev->struct_mutex); |
1137 | 1130 | ||
1138 | ret = intel_overlay_switch_off(overlay, true); | 1131 | ret = intel_overlay_switch_off(overlay); |
1139 | 1132 | ||
1140 | mutex_unlock(&dev->struct_mutex); | 1133 | mutex_unlock(&dev->struct_mutex); |
1141 | mutex_unlock(&dev->mode_config.mutex); | 1134 | mutex_unlock(&dev->mode_config.mutex); |
@@ -1157,7 +1150,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, | |||
1157 | 1150 | ||
1158 | new_bo = to_intel_bo(drm_gem_object_lookup(dev, file_priv, | 1151 | new_bo = to_intel_bo(drm_gem_object_lookup(dev, file_priv, |
1159 | put_image_rec->bo_handle)); | 1152 | put_image_rec->bo_handle)); |
1160 | if (!new_bo) { | 1153 | if (&new_bo->base == NULL) { |
1161 | ret = -ENOENT; | 1154 | ret = -ENOENT; |
1162 | goto out_free; | 1155 | goto out_free; |
1163 | } | 1156 | } |
@@ -1171,13 +1164,13 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, | |||
1171 | goto out_unlock; | 1164 | goto out_unlock; |
1172 | } | 1165 | } |
1173 | 1166 | ||
1174 | ret = intel_overlay_recover_from_interrupt(overlay, true); | 1167 | ret = intel_overlay_recover_from_interrupt(overlay); |
1175 | if (ret != 0) | 1168 | if (ret != 0) |
1176 | goto out_unlock; | 1169 | goto out_unlock; |
1177 | 1170 | ||
1178 | if (overlay->crtc != crtc) { | 1171 | if (overlay->crtc != crtc) { |
1179 | struct drm_display_mode *mode = &crtc->base.mode; | 1172 | struct drm_display_mode *mode = &crtc->base.mode; |
1180 | ret = intel_overlay_switch_off(overlay, true); | 1173 | ret = intel_overlay_switch_off(overlay); |
1181 | if (ret != 0) | 1174 | if (ret != 0) |
1182 | goto out_unlock; | 1175 | goto out_unlock; |
1183 | 1176 | ||
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index f8f86e57df2..a06ff07a4d3 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c | |||
@@ -280,3 +280,28 @@ void intel_panel_setup_backlight(struct drm_device *dev) | |||
280 | dev_priv->backlight_level = intel_panel_get_backlight(dev); | 280 | dev_priv->backlight_level = intel_panel_get_backlight(dev); |
281 | dev_priv->backlight_enabled = dev_priv->backlight_level != 0; | 281 | dev_priv->backlight_enabled = dev_priv->backlight_level != 0; |
282 | } | 282 | } |
283 | |||
284 | enum drm_connector_status | ||
285 | intel_panel_detect(struct drm_device *dev) | ||
286 | { | ||
287 | #if 0 | ||
288 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
289 | #endif | ||
290 | |||
291 | if (i915_panel_ignore_lid) | ||
292 | return i915_panel_ignore_lid > 0 ? | ||
293 | connector_status_connected : | ||
294 | connector_status_disconnected; | ||
295 | |||
296 | /* opregion lid state on HP 2540p is wrong at boot up, | ||
297 | * appears to be either the BIOS or Linux ACPI fault */ | ||
298 | #if 0 | ||
299 | /* Assume that the BIOS does not lie through the OpRegion... */ | ||
300 | if (dev_priv->opregion.lid_state) | ||
301 | return ioread32(dev_priv->opregion.lid_state) & 0x1 ? | ||
302 | connector_status_connected : | ||
303 | connector_status_disconnected; | ||
304 | #endif | ||
305 | |||
306 | return connector_status_unknown; | ||
307 | } | ||
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 445f27efe67..789c47801ba 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
@@ -62,18 +62,9 @@ render_ring_flush(struct intel_ring_buffer *ring, | |||
62 | u32 flush_domains) | 62 | u32 flush_domains) |
63 | { | 63 | { |
64 | struct drm_device *dev = ring->dev; | 64 | struct drm_device *dev = ring->dev; |
65 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
66 | u32 cmd; | 65 | u32 cmd; |
67 | int ret; | 66 | int ret; |
68 | 67 | ||
69 | #if WATCH_EXEC | ||
70 | DRM_INFO("%s: invalidate %08x flush %08x\n", __func__, | ||
71 | invalidate_domains, flush_domains); | ||
72 | #endif | ||
73 | |||
74 | trace_i915_gem_request_flush(dev, dev_priv->next_seqno, | ||
75 | invalidate_domains, flush_domains); | ||
76 | |||
77 | if ((invalidate_domains | flush_domains) & I915_GEM_GPU_DOMAINS) { | 68 | if ((invalidate_domains | flush_domains) & I915_GEM_GPU_DOMAINS) { |
78 | /* | 69 | /* |
79 | * read/write caches: | 70 | * read/write caches: |
@@ -122,9 +113,6 @@ render_ring_flush(struct intel_ring_buffer *ring, | |||
122 | (IS_G4X(dev) || IS_GEN5(dev))) | 113 | (IS_G4X(dev) || IS_GEN5(dev))) |
123 | cmd |= MI_INVALIDATE_ISP; | 114 | cmd |= MI_INVALIDATE_ISP; |
124 | 115 | ||
125 | #if WATCH_EXEC | ||
126 | DRM_INFO("%s: queue flush %08x to ring\n", __func__, cmd); | ||
127 | #endif | ||
128 | ret = intel_ring_begin(ring, 2); | 116 | ret = intel_ring_begin(ring, 2); |
129 | if (ret) | 117 | if (ret) |
130 | return ret; | 118 | return ret; |
@@ -612,7 +600,6 @@ ring_add_request(struct intel_ring_buffer *ring, | |||
612 | intel_ring_emit(ring, MI_USER_INTERRUPT); | 600 | intel_ring_emit(ring, MI_USER_INTERRUPT); |
613 | intel_ring_advance(ring); | 601 | intel_ring_advance(ring); |
614 | 602 | ||
615 | DRM_DEBUG_DRIVER("%s %d\n", ring->name, seqno); | ||
616 | *result = seqno; | 603 | *result = seqno; |
617 | return 0; | 604 | return 0; |
618 | } | 605 | } |
@@ -715,11 +702,8 @@ render_ring_dispatch_execbuffer(struct intel_ring_buffer *ring, | |||
715 | u32 offset, u32 len) | 702 | u32 offset, u32 len) |
716 | { | 703 | { |
717 | struct drm_device *dev = ring->dev; | 704 | struct drm_device *dev = ring->dev; |
718 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
719 | int ret; | 705 | int ret; |
720 | 706 | ||
721 | trace_i915_gem_request_submit(dev, dev_priv->next_seqno + 1); | ||
722 | |||
723 | if (IS_I830(dev) || IS_845G(dev)) { | 707 | if (IS_I830(dev) || IS_845G(dev)) { |
724 | ret = intel_ring_begin(ring, 4); | 708 | ret = intel_ring_begin(ring, 4); |
725 | if (ret) | 709 | if (ret) |
@@ -894,6 +878,10 @@ void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring) | |||
894 | /* Disable the ring buffer. The ring must be idle at this point */ | 878 | /* Disable the ring buffer. The ring must be idle at this point */ |
895 | dev_priv = ring->dev->dev_private; | 879 | dev_priv = ring->dev->dev_private; |
896 | ret = intel_wait_ring_buffer(ring, ring->size - 8); | 880 | ret = intel_wait_ring_buffer(ring, ring->size - 8); |
881 | if (ret) | ||
882 | DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n", | ||
883 | ring->name, ret); | ||
884 | |||
897 | I915_WRITE_CTL(ring, 0); | 885 | I915_WRITE_CTL(ring, 0); |
898 | 886 | ||
899 | drm_core_ioremapfree(&ring->map, ring->dev); | 887 | drm_core_ioremapfree(&ring->map, ring->dev); |
@@ -950,13 +938,13 @@ int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n) | |||
950 | return 0; | 938 | return 0; |
951 | } | 939 | } |
952 | 940 | ||
953 | trace_i915_ring_wait_begin (dev); | 941 | trace_i915_ring_wait_begin(ring); |
954 | end = jiffies + 3 * HZ; | 942 | end = jiffies + 3 * HZ; |
955 | do { | 943 | do { |
956 | ring->head = I915_READ_HEAD(ring); | 944 | ring->head = I915_READ_HEAD(ring); |
957 | ring->space = ring_space(ring); | 945 | ring->space = ring_space(ring); |
958 | if (ring->space >= n) { | 946 | if (ring->space >= n) { |
959 | trace_i915_ring_wait_end(dev); | 947 | trace_i915_ring_wait_end(ring); |
960 | return 0; | 948 | return 0; |
961 | } | 949 | } |
962 | 950 | ||
@@ -970,16 +958,20 @@ int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n) | |||
970 | if (atomic_read(&dev_priv->mm.wedged)) | 958 | if (atomic_read(&dev_priv->mm.wedged)) |
971 | return -EAGAIN; | 959 | return -EAGAIN; |
972 | } while (!time_after(jiffies, end)); | 960 | } while (!time_after(jiffies, end)); |
973 | trace_i915_ring_wait_end (dev); | 961 | trace_i915_ring_wait_end(ring); |
974 | return -EBUSY; | 962 | return -EBUSY; |
975 | } | 963 | } |
976 | 964 | ||
977 | int intel_ring_begin(struct intel_ring_buffer *ring, | 965 | int intel_ring_begin(struct intel_ring_buffer *ring, |
978 | int num_dwords) | 966 | int num_dwords) |
979 | { | 967 | { |
968 | struct drm_i915_private *dev_priv = ring->dev->dev_private; | ||
980 | int n = 4*num_dwords; | 969 | int n = 4*num_dwords; |
981 | int ret; | 970 | int ret; |
982 | 971 | ||
972 | if (unlikely(atomic_read(&dev_priv->mm.wedged))) | ||
973 | return -EIO; | ||
974 | |||
983 | if (unlikely(ring->tail + n > ring->effective_size)) { | 975 | if (unlikely(ring->tail + n > ring->effective_size)) { |
984 | ret = intel_wrap_ring_buffer(ring); | 976 | ret = intel_wrap_ring_buffer(ring); |
985 | if (unlikely(ret)) | 977 | if (unlikely(ret)) |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 34306865a5d..f23cc5f037a 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h | |||
@@ -44,7 +44,7 @@ struct intel_ring_buffer { | |||
44 | RING_BLT = 0x4, | 44 | RING_BLT = 0x4, |
45 | } id; | 45 | } id; |
46 | u32 mmio_base; | 46 | u32 mmio_base; |
47 | void *virtual_start; | 47 | void __iomem *virtual_start; |
48 | struct drm_device *dev; | 48 | struct drm_device *dev; |
49 | struct drm_i915_gem_object *obj; | 49 | struct drm_i915_gem_object *obj; |
50 | 50 | ||
@@ -59,6 +59,7 @@ struct intel_ring_buffer { | |||
59 | u32 irq_refcount; | 59 | u32 irq_refcount; |
60 | u32 irq_mask; | 60 | u32 irq_mask; |
61 | u32 irq_seqno; /* last seq seem at irq time */ | 61 | u32 irq_seqno; /* last seq seem at irq time */ |
62 | u32 trace_irq_seqno; | ||
62 | u32 waiting_seqno; | 63 | u32 waiting_seqno; |
63 | u32 sync_seqno[I915_NUM_RINGS-1]; | 64 | u32 sync_seqno[I915_NUM_RINGS-1]; |
64 | bool __must_check (*irq_get)(struct intel_ring_buffer *ring); | 65 | bool __must_check (*irq_get)(struct intel_ring_buffer *ring); |
@@ -142,6 +143,26 @@ intel_read_status_page(struct intel_ring_buffer *ring, | |||
142 | return ioread32(ring->status_page.page_addr + reg); | 143 | return ioread32(ring->status_page.page_addr + reg); |
143 | } | 144 | } |
144 | 145 | ||
146 | /** | ||
147 | * Reads a dword out of the status page, which is written to from the command | ||
148 | * queue by automatic updates, MI_REPORT_HEAD, MI_STORE_DATA_INDEX, or | ||
149 | * MI_STORE_DATA_IMM. | ||
150 | * | ||
151 | * The following dwords have a reserved meaning: | ||
152 | * 0x00: ISR copy, updated when an ISR bit not set in the HWSTAM changes. | ||
153 | * 0x04: ring 0 head pointer | ||
154 | * 0x05: ring 1 head pointer (915-class) | ||
155 | * 0x06: ring 2 head pointer (915-class) | ||
156 | * 0x10-0x1b: Context status DWords (GM45) | ||
157 | * 0x1f: Last written status offset. (GM45) | ||
158 | * | ||
159 | * The area from dword 0x20 to 0x3ff is available for driver usage. | ||
160 | */ | ||
161 | #define READ_HWSP(dev_priv, reg) intel_read_status_page(LP_RING(dev_priv), reg) | ||
162 | #define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, I915_BREADCRUMB_INDEX) | ||
163 | #define I915_GEM_HWS_INDEX 0x20 | ||
164 | #define I915_BREADCRUMB_INDEX 0x21 | ||
165 | |||
145 | void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring); | 166 | void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring); |
146 | int __must_check intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n); | 167 | int __must_check intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n); |
147 | int __must_check intel_ring_begin(struct intel_ring_buffer *ring, int n); | 168 | int __must_check intel_ring_begin(struct intel_ring_buffer *ring, int n); |
@@ -167,6 +188,12 @@ int intel_init_blt_ring_buffer(struct drm_device *dev); | |||
167 | u32 intel_ring_get_active_head(struct intel_ring_buffer *ring); | 188 | u32 intel_ring_get_active_head(struct intel_ring_buffer *ring); |
168 | void intel_ring_setup_status_page(struct intel_ring_buffer *ring); | 189 | void intel_ring_setup_status_page(struct intel_ring_buffer *ring); |
169 | 190 | ||
191 | static inline void i915_trace_irq_get(struct intel_ring_buffer *ring, u32 seqno) | ||
192 | { | ||
193 | if (ring->trace_irq_seqno == 0 && ring->irq_get(ring)) | ||
194 | ring->trace_irq_seqno = seqno; | ||
195 | } | ||
196 | |||
170 | /* DRI warts */ | 197 | /* DRI warts */ |
171 | int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size); | 198 | int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size); |
172 | 199 | ||
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 7c50cdce84f..4324f33212d 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
@@ -93,6 +93,12 @@ struct intel_sdvo { | |||
93 | uint16_t attached_output; | 93 | uint16_t attached_output; |
94 | 94 | ||
95 | /** | 95 | /** |
96 | * This is used to select the color range of RBG outputs in HDMI mode. | ||
97 | * It is only valid when using TMDS encoding and 8 bit per color mode. | ||
98 | */ | ||
99 | uint32_t color_range; | ||
100 | |||
101 | /** | ||
96 | * This is set if we're going to treat the device as TV-out. | 102 | * This is set if we're going to treat the device as TV-out. |
97 | * | 103 | * |
98 | * While we have these nice friendly flags for output types that ought | 104 | * While we have these nice friendly flags for output types that ought |
@@ -585,6 +591,7 @@ static bool intel_sdvo_get_trained_inputs(struct intel_sdvo *intel_sdvo, bool *i | |||
585 | { | 591 | { |
586 | struct intel_sdvo_get_trained_inputs_response response; | 592 | struct intel_sdvo_get_trained_inputs_response response; |
587 | 593 | ||
594 | BUILD_BUG_ON(sizeof(response) != 1); | ||
588 | if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_TRAINED_INPUTS, | 595 | if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_TRAINED_INPUTS, |
589 | &response, sizeof(response))) | 596 | &response, sizeof(response))) |
590 | return false; | 597 | return false; |
@@ -632,6 +639,7 @@ static bool intel_sdvo_get_input_pixel_clock_range(struct intel_sdvo *intel_sdvo | |||
632 | { | 639 | { |
633 | struct intel_sdvo_pixel_clock_range clocks; | 640 | struct intel_sdvo_pixel_clock_range clocks; |
634 | 641 | ||
642 | BUILD_BUG_ON(sizeof(clocks) != 4); | ||
635 | if (!intel_sdvo_get_value(intel_sdvo, | 643 | if (!intel_sdvo_get_value(intel_sdvo, |
636 | SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE, | 644 | SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE, |
637 | &clocks, sizeof(clocks))) | 645 | &clocks, sizeof(clocks))) |
@@ -699,6 +707,8 @@ intel_sdvo_create_preferred_input_timing(struct intel_sdvo *intel_sdvo, | |||
699 | static bool intel_sdvo_get_preferred_input_timing(struct intel_sdvo *intel_sdvo, | 707 | static bool intel_sdvo_get_preferred_input_timing(struct intel_sdvo *intel_sdvo, |
700 | struct intel_sdvo_dtd *dtd) | 708 | struct intel_sdvo_dtd *dtd) |
701 | { | 709 | { |
710 | BUILD_BUG_ON(sizeof(dtd->part1) != 8); | ||
711 | BUILD_BUG_ON(sizeof(dtd->part2) != 8); | ||
702 | return intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1, | 712 | return intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1, |
703 | &dtd->part1, sizeof(dtd->part1)) && | 713 | &dtd->part1, sizeof(dtd->part1)) && |
704 | intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2, | 714 | intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2, |
@@ -796,6 +806,7 @@ static bool intel_sdvo_check_supp_encode(struct intel_sdvo *intel_sdvo) | |||
796 | { | 806 | { |
797 | struct intel_sdvo_encode encode; | 807 | struct intel_sdvo_encode encode; |
798 | 808 | ||
809 | BUILD_BUG_ON(sizeof(encode) != 2); | ||
799 | return intel_sdvo_get_value(intel_sdvo, | 810 | return intel_sdvo_get_value(intel_sdvo, |
800 | SDVO_CMD_GET_SUPP_ENCODE, | 811 | SDVO_CMD_GET_SUPP_ENCODE, |
801 | &encode, sizeof(encode)); | 812 | &encode, sizeof(encode)); |
@@ -1051,6 +1062,8 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, | |||
1051 | /* Set the SDVO control regs. */ | 1062 | /* Set the SDVO control regs. */ |
1052 | if (INTEL_INFO(dev)->gen >= 4) { | 1063 | if (INTEL_INFO(dev)->gen >= 4) { |
1053 | sdvox = 0; | 1064 | sdvox = 0; |
1065 | if (intel_sdvo->is_hdmi) | ||
1066 | sdvox |= intel_sdvo->color_range; | ||
1054 | if (INTEL_INFO(dev)->gen < 5) | 1067 | if (INTEL_INFO(dev)->gen < 5) |
1055 | sdvox |= SDVO_BORDER_ENABLE; | 1068 | sdvox |= SDVO_BORDER_ENABLE; |
1056 | if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) | 1069 | if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) |
@@ -1162,6 +1175,7 @@ static int intel_sdvo_mode_valid(struct drm_connector *connector, | |||
1162 | 1175 | ||
1163 | static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct intel_sdvo_caps *caps) | 1176 | static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct intel_sdvo_caps *caps) |
1164 | { | 1177 | { |
1178 | BUILD_BUG_ON(sizeof(*caps) != 8); | ||
1165 | if (!intel_sdvo_get_value(intel_sdvo, | 1179 | if (!intel_sdvo_get_value(intel_sdvo, |
1166 | SDVO_CMD_GET_DEVICE_CAPS, | 1180 | SDVO_CMD_GET_DEVICE_CAPS, |
1167 | caps, sizeof(*caps))) | 1181 | caps, sizeof(*caps))) |
@@ -1268,33 +1282,9 @@ void intel_sdvo_set_hotplug(struct drm_connector *connector, int on) | |||
1268 | static bool | 1282 | static bool |
1269 | intel_sdvo_multifunc_encoder(struct intel_sdvo *intel_sdvo) | 1283 | intel_sdvo_multifunc_encoder(struct intel_sdvo *intel_sdvo) |
1270 | { | 1284 | { |
1271 | int caps = 0; | 1285 | /* Is there more than one type of output? */ |
1272 | 1286 | int caps = intel_sdvo->caps.output_flags & 0xf; | |
1273 | if (intel_sdvo->caps.output_flags & | 1287 | return caps & -caps; |
1274 | (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) | ||
1275 | caps++; | ||
1276 | if (intel_sdvo->caps.output_flags & | ||
1277 | (SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1)) | ||
1278 | caps++; | ||
1279 | if (intel_sdvo->caps.output_flags & | ||
1280 | (SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_SVID1)) | ||
1281 | caps++; | ||
1282 | if (intel_sdvo->caps.output_flags & | ||
1283 | (SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_CVBS1)) | ||
1284 | caps++; | ||
1285 | if (intel_sdvo->caps.output_flags & | ||
1286 | (SDVO_OUTPUT_YPRPB0 | SDVO_OUTPUT_YPRPB1)) | ||
1287 | caps++; | ||
1288 | |||
1289 | if (intel_sdvo->caps.output_flags & | ||
1290 | (SDVO_OUTPUT_SCART0 | SDVO_OUTPUT_SCART1)) | ||
1291 | caps++; | ||
1292 | |||
1293 | if (intel_sdvo->caps.output_flags & | ||
1294 | (SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1)) | ||
1295 | caps++; | ||
1296 | |||
1297 | return (caps > 1); | ||
1298 | } | 1288 | } |
1299 | 1289 | ||
1300 | static struct edid * | 1290 | static struct edid * |
@@ -1482,7 +1472,7 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) | |||
1482 | * Note! This is in reply order (see loop in get_tv_modes). | 1472 | * Note! This is in reply order (see loop in get_tv_modes). |
1483 | * XXX: all 60Hz refresh? | 1473 | * XXX: all 60Hz refresh? |
1484 | */ | 1474 | */ |
1485 | struct drm_display_mode sdvo_tv_modes[] = { | 1475 | static const struct drm_display_mode sdvo_tv_modes[] = { |
1486 | { DRM_MODE("320x200", DRM_MODE_TYPE_DRIVER, 5815, 320, 321, 384, | 1476 | { DRM_MODE("320x200", DRM_MODE_TYPE_DRIVER, 5815, 320, 321, 384, |
1487 | 416, 0, 200, 201, 232, 233, 0, | 1477 | 416, 0, 200, 201, 232, 233, 0, |
1488 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | 1478 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
@@ -1713,6 +1703,7 @@ intel_sdvo_set_property(struct drm_connector *connector, | |||
1713 | { | 1703 | { |
1714 | struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); | 1704 | struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); |
1715 | struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); | 1705 | struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); |
1706 | struct drm_i915_private *dev_priv = connector->dev->dev_private; | ||
1716 | uint16_t temp_value; | 1707 | uint16_t temp_value; |
1717 | uint8_t cmd; | 1708 | uint8_t cmd; |
1718 | int ret; | 1709 | int ret; |
@@ -1742,6 +1733,14 @@ intel_sdvo_set_property(struct drm_connector *connector, | |||
1742 | goto done; | 1733 | goto done; |
1743 | } | 1734 | } |
1744 | 1735 | ||
1736 | if (property == dev_priv->broadcast_rgb_property) { | ||
1737 | if (val == !!intel_sdvo->color_range) | ||
1738 | return 0; | ||
1739 | |||
1740 | intel_sdvo->color_range = val ? SDVO_COLOR_RANGE_16_235 : 0; | ||
1741 | goto done; | ||
1742 | } | ||
1743 | |||
1745 | #define CHECK_PROPERTY(name, NAME) \ | 1744 | #define CHECK_PROPERTY(name, NAME) \ |
1746 | if (intel_sdvo_connector->name == property) { \ | 1745 | if (intel_sdvo_connector->name == property) { \ |
1747 | if (intel_sdvo_connector->cur_##name == temp_value) return 0; \ | 1746 | if (intel_sdvo_connector->cur_##name == temp_value) return 0; \ |
@@ -2046,6 +2045,9 @@ intel_sdvo_add_hdmi_properties(struct intel_sdvo_connector *connector) | |||
2046 | drm_connector_attach_property(&connector->base.base, | 2045 | drm_connector_attach_property(&connector->base.base, |
2047 | connector->force_audio_property, 0); | 2046 | connector->force_audio_property, 0); |
2048 | } | 2047 | } |
2048 | |||
2049 | if (INTEL_INFO(dev)->gen >= 4 && IS_MOBILE(dev)) | ||
2050 | intel_attach_broadcast_rgb_property(&connector->base.base); | ||
2049 | } | 2051 | } |
2050 | 2052 | ||
2051 | static bool | 2053 | static bool |
@@ -2268,6 +2270,7 @@ static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo, | |||
2268 | if (!intel_sdvo_set_target_output(intel_sdvo, type)) | 2270 | if (!intel_sdvo_set_target_output(intel_sdvo, type)) |
2269 | return false; | 2271 | return false; |
2270 | 2272 | ||
2273 | BUILD_BUG_ON(sizeof(format) != 6); | ||
2271 | if (!intel_sdvo_get_value(intel_sdvo, | 2274 | if (!intel_sdvo_get_value(intel_sdvo, |
2272 | SDVO_CMD_GET_SUPPORTED_TV_FORMATS, | 2275 | SDVO_CMD_GET_SUPPORTED_TV_FORMATS, |
2273 | &format, sizeof(format))) | 2276 | &format, sizeof(format))) |
@@ -2474,6 +2477,8 @@ static bool intel_sdvo_create_enhance_property(struct intel_sdvo *intel_sdvo, | |||
2474 | uint16_t response; | 2477 | uint16_t response; |
2475 | } enhancements; | 2478 | } enhancements; |
2476 | 2479 | ||
2480 | BUILD_BUG_ON(sizeof(enhancements) != 2); | ||
2481 | |||
2477 | enhancements.response = 0; | 2482 | enhancements.response = 0; |
2478 | intel_sdvo_get_value(intel_sdvo, | 2483 | intel_sdvo_get_value(intel_sdvo, |
2479 | SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS, | 2484 | SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS, |
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index fe4a53a50b8..4256b8ef394 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c | |||
@@ -1006,6 +1006,7 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
1006 | const struct video_levels *video_levels; | 1006 | const struct video_levels *video_levels; |
1007 | const struct color_conversion *color_conversion; | 1007 | const struct color_conversion *color_conversion; |
1008 | bool burst_ena; | 1008 | bool burst_ena; |
1009 | int pipe = intel_crtc->pipe; | ||
1009 | 1010 | ||
1010 | if (!tv_mode) | 1011 | if (!tv_mode) |
1011 | return; /* can't happen (mode_prepare prevents this) */ | 1012 | return; /* can't happen (mode_prepare prevents this) */ |
@@ -1149,14 +1150,11 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
1149 | ((video_levels->black << TV_BLACK_LEVEL_SHIFT) | | 1150 | ((video_levels->black << TV_BLACK_LEVEL_SHIFT) | |
1150 | (video_levels->blank << TV_BLANK_LEVEL_SHIFT))); | 1151 | (video_levels->blank << TV_BLANK_LEVEL_SHIFT))); |
1151 | { | 1152 | { |
1152 | int pipeconf_reg = (intel_crtc->pipe == 0) ? | 1153 | int pipeconf_reg = PIPECONF(pipe); |
1153 | PIPEACONF : PIPEBCONF; | 1154 | int dspcntr_reg = DSPCNTR(pipe); |
1154 | int dspcntr_reg = (intel_crtc->plane == 0) ? | ||
1155 | DSPACNTR : DSPBCNTR; | ||
1156 | int pipeconf = I915_READ(pipeconf_reg); | 1155 | int pipeconf = I915_READ(pipeconf_reg); |
1157 | int dspcntr = I915_READ(dspcntr_reg); | 1156 | int dspcntr = I915_READ(dspcntr_reg); |
1158 | int dspbase_reg = (intel_crtc->plane == 0) ? | 1157 | int dspbase_reg = DSPADDR(pipe); |
1159 | DSPAADDR : DSPBADDR; | ||
1160 | int xpos = 0x0, ypos = 0x0; | 1158 | int xpos = 0x0, ypos = 0x0; |
1161 | unsigned int xsize, ysize; | 1159 | unsigned int xsize, ysize; |
1162 | /* Pipe must be off here */ | 1160 | /* Pipe must be off here */ |
diff --git a/drivers/gpu/drm/mga/mga_dma.c b/drivers/gpu/drm/mga/mga_dma.c index 08868ac3048..1e1eb1d7e97 100644 --- a/drivers/gpu/drm/mga/mga_dma.c +++ b/drivers/gpu/drm/mga/mga_dma.c | |||
@@ -703,7 +703,7 @@ static int mga_do_pci_dma_bootstrap(struct drm_device *dev, | |||
703 | static int mga_do_dma_bootstrap(struct drm_device *dev, | 703 | static int mga_do_dma_bootstrap(struct drm_device *dev, |
704 | drm_mga_dma_bootstrap_t *dma_bs) | 704 | drm_mga_dma_bootstrap_t *dma_bs) |
705 | { | 705 | { |
706 | const int is_agp = (dma_bs->agp_mode != 0) && drm_device_is_agp(dev); | 706 | const int is_agp = (dma_bs->agp_mode != 0) && drm_pci_device_is_agp(dev); |
707 | int err; | 707 | int err; |
708 | drm_mga_private_t *const dev_priv = | 708 | drm_mga_private_t *const dev_priv = |
709 | (drm_mga_private_t *) dev->dev_private; | 709 | (drm_mga_private_t *) dev->dev_private; |
diff --git a/drivers/gpu/drm/mga/mga_drv.c b/drivers/gpu/drm/mga/mga_drv.c index 0aaf5f67a43..42d31874edf 100644 --- a/drivers/gpu/drm/mga/mga_drv.c +++ b/drivers/gpu/drm/mga/mga_drv.c | |||
@@ -75,10 +75,6 @@ static struct drm_driver driver = { | |||
75 | #endif | 75 | #endif |
76 | .llseek = noop_llseek, | 76 | .llseek = noop_llseek, |
77 | }, | 77 | }, |
78 | .pci_driver = { | ||
79 | .name = DRIVER_NAME, | ||
80 | .id_table = pciidlist, | ||
81 | }, | ||
82 | 78 | ||
83 | .name = DRIVER_NAME, | 79 | .name = DRIVER_NAME, |
84 | .desc = DRIVER_DESC, | 80 | .desc = DRIVER_DESC, |
@@ -88,15 +84,20 @@ static struct drm_driver driver = { | |||
88 | .patchlevel = DRIVER_PATCHLEVEL, | 84 | .patchlevel = DRIVER_PATCHLEVEL, |
89 | }; | 85 | }; |
90 | 86 | ||
87 | static struct pci_driver mga_pci_driver = { | ||
88 | .name = DRIVER_NAME, | ||
89 | .id_table = pciidlist, | ||
90 | }; | ||
91 | |||
91 | static int __init mga_init(void) | 92 | static int __init mga_init(void) |
92 | { | 93 | { |
93 | driver.num_ioctls = mga_max_ioctl; | 94 | driver.num_ioctls = mga_max_ioctl; |
94 | return drm_init(&driver); | 95 | return drm_pci_init(&driver, &mga_pci_driver); |
95 | } | 96 | } |
96 | 97 | ||
97 | static void __exit mga_exit(void) | 98 | static void __exit mga_exit(void) |
98 | { | 99 | { |
99 | drm_exit(&driver); | 100 | drm_pci_exit(&driver, &mga_pci_driver); |
100 | } | 101 | } |
101 | 102 | ||
102 | module_init(mga_init); | 103 | module_init(mga_init); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 6bdab891c64..8314a49b6b9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c | |||
@@ -282,7 +282,7 @@ static void still_alive(void) | |||
282 | { | 282 | { |
283 | #if 0 | 283 | #if 0 |
284 | sync(); | 284 | sync(); |
285 | msleep(2); | 285 | mdelay(2); |
286 | #endif | 286 | #endif |
287 | } | 287 | } |
288 | 288 | ||
@@ -1904,7 +1904,7 @@ init_condition_time(struct nvbios *bios, uint16_t offset, | |||
1904 | BIOSLOG(bios, "0x%04X: " | 1904 | BIOSLOG(bios, "0x%04X: " |
1905 | "Condition not met, sleeping for 20ms\n", | 1905 | "Condition not met, sleeping for 20ms\n", |
1906 | offset); | 1906 | offset); |
1907 | msleep(20); | 1907 | mdelay(20); |
1908 | } | 1908 | } |
1909 | } | 1909 | } |
1910 | 1910 | ||
@@ -1938,7 +1938,7 @@ init_ltime(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
1938 | BIOSLOG(bios, "0x%04X: Sleeping for 0x%04X milliseconds\n", | 1938 | BIOSLOG(bios, "0x%04X: Sleeping for 0x%04X milliseconds\n", |
1939 | offset, time); | 1939 | offset, time); |
1940 | 1940 | ||
1941 | msleep(time); | 1941 | mdelay(time); |
1942 | 1942 | ||
1943 | return 3; | 1943 | return 3; |
1944 | } | 1944 | } |
@@ -2962,7 +2962,7 @@ init_time(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
2962 | if (time < 1000) | 2962 | if (time < 1000) |
2963 | udelay(time); | 2963 | udelay(time); |
2964 | else | 2964 | else |
2965 | msleep((time + 900) / 1000); | 2965 | mdelay((time + 900) / 1000); |
2966 | 2966 | ||
2967 | return 3; | 2967 | return 3; |
2968 | } | 2968 | } |
@@ -3856,7 +3856,7 @@ static int call_lvds_manufacturer_script(struct drm_device *dev, struct dcb_entr | |||
3856 | 3856 | ||
3857 | if (script == LVDS_PANEL_OFF) { | 3857 | if (script == LVDS_PANEL_OFF) { |
3858 | /* off-on delay in ms */ | 3858 | /* off-on delay in ms */ |
3859 | msleep(ROM16(bios->data[bios->fp.xlated_entry + 7])); | 3859 | mdelay(ROM16(bios->data[bios->fp.xlated_entry + 7])); |
3860 | } | 3860 | } |
3861 | #ifdef __powerpc__ | 3861 | #ifdef __powerpc__ |
3862 | /* Powerbook specific quirks */ | 3862 | /* Powerbook specific quirks */ |
@@ -5950,6 +5950,11 @@ apply_dcb_connector_quirks(struct nvbios *bios, int idx) | |||
5950 | } | 5950 | } |
5951 | } | 5951 | } |
5952 | 5952 | ||
5953 | static const u8 hpd_gpio[16] = { | ||
5954 | 0xff, 0x07, 0x08, 0xff, 0xff, 0x51, 0x52, 0xff, | ||
5955 | 0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0x5f, 0x60, | ||
5956 | }; | ||
5957 | |||
5953 | static void | 5958 | static void |
5954 | parse_dcb_connector_table(struct nvbios *bios) | 5959 | parse_dcb_connector_table(struct nvbios *bios) |
5955 | { | 5960 | { |
@@ -5986,23 +5991,9 @@ parse_dcb_connector_table(struct nvbios *bios) | |||
5986 | 5991 | ||
5987 | cte->type = (cte->entry & 0x000000ff) >> 0; | 5992 | cte->type = (cte->entry & 0x000000ff) >> 0; |
5988 | cte->index2 = (cte->entry & 0x00000f00) >> 8; | 5993 | cte->index2 = (cte->entry & 0x00000f00) >> 8; |
5989 | switch (cte->entry & 0x00033000) { | 5994 | |
5990 | case 0x00001000: | 5995 | cte->gpio_tag = ffs((cte->entry & 0x07033000) >> 12); |
5991 | cte->gpio_tag = 0x07; | 5996 | cte->gpio_tag = hpd_gpio[cte->gpio_tag]; |
5992 | break; | ||
5993 | case 0x00002000: | ||
5994 | cte->gpio_tag = 0x08; | ||
5995 | break; | ||
5996 | case 0x00010000: | ||
5997 | cte->gpio_tag = 0x51; | ||
5998 | break; | ||
5999 | case 0x00020000: | ||
6000 | cte->gpio_tag = 0x52; | ||
6001 | break; | ||
6002 | default: | ||
6003 | cte->gpio_tag = 0xff; | ||
6004 | break; | ||
6005 | } | ||
6006 | 5997 | ||
6007 | if (cte->type == 0xff) | 5998 | if (cte->type == 0xff) |
6008 | continue; | 5999 | continue; |
@@ -6702,11 +6693,11 @@ nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table, | |||
6702 | struct nvbios *bios = &dev_priv->vbios; | 6693 | struct nvbios *bios = &dev_priv->vbios; |
6703 | struct init_exec iexec = { true, false }; | 6694 | struct init_exec iexec = { true, false }; |
6704 | 6695 | ||
6705 | mutex_lock(&bios->lock); | 6696 | spin_lock_bh(&bios->lock); |
6706 | bios->display.output = dcbent; | 6697 | bios->display.output = dcbent; |
6707 | parse_init_table(bios, table, &iexec); | 6698 | parse_init_table(bios, table, &iexec); |
6708 | bios->display.output = NULL; | 6699 | bios->display.output = NULL; |
6709 | mutex_unlock(&bios->lock); | 6700 | spin_unlock_bh(&bios->lock); |
6710 | } | 6701 | } |
6711 | 6702 | ||
6712 | static bool NVInitVBIOS(struct drm_device *dev) | 6703 | static bool NVInitVBIOS(struct drm_device *dev) |
@@ -6715,7 +6706,7 @@ static bool NVInitVBIOS(struct drm_device *dev) | |||
6715 | struct nvbios *bios = &dev_priv->vbios; | 6706 | struct nvbios *bios = &dev_priv->vbios; |
6716 | 6707 | ||
6717 | memset(bios, 0, sizeof(struct nvbios)); | 6708 | memset(bios, 0, sizeof(struct nvbios)); |
6718 | mutex_init(&bios->lock); | 6709 | spin_lock_init(&bios->lock); |
6719 | bios->dev = dev; | 6710 | bios->dev = dev; |
6720 | 6711 | ||
6721 | if (!NVShadowVBIOS(dev, bios->data)) | 6712 | if (!NVShadowVBIOS(dev, bios->data)) |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h index 50a648e01c4..8a54fa7edf5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h | |||
@@ -251,7 +251,7 @@ struct nvbios { | |||
251 | uint8_t digital_min_front_porch; | 251 | uint8_t digital_min_front_porch; |
252 | bool fp_no_ddc; | 252 | bool fp_no_ddc; |
253 | 253 | ||
254 | struct mutex lock; | 254 | spinlock_t lock; |
255 | 255 | ||
256 | uint8_t data[NV_PROM_SIZE]; | 256 | uint8_t data[NV_PROM_SIZE]; |
257 | unsigned int length; | 257 | unsigned int length; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index a52184007f5..2ad49cbf7c8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c | |||
@@ -57,8 +57,8 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo) | |||
57 | } | 57 | } |
58 | 58 | ||
59 | static void | 59 | static void |
60 | nouveau_bo_fixup_align(struct nouveau_bo *nvbo, int *align, int *size, | 60 | nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags, |
61 | int *page_shift) | 61 | int *align, int *size, int *page_shift) |
62 | { | 62 | { |
63 | struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev); | 63 | struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev); |
64 | 64 | ||
@@ -83,7 +83,7 @@ nouveau_bo_fixup_align(struct nouveau_bo *nvbo, int *align, int *size, | |||
83 | } | 83 | } |
84 | } else { | 84 | } else { |
85 | if (likely(dev_priv->chan_vm)) { | 85 | if (likely(dev_priv->chan_vm)) { |
86 | if (*size > 256 * 1024) | 86 | if (!(flags & TTM_PL_FLAG_TT) && *size > 256 * 1024) |
87 | *page_shift = dev_priv->chan_vm->lpg_shift; | 87 | *page_shift = dev_priv->chan_vm->lpg_shift; |
88 | else | 88 | else |
89 | *page_shift = dev_priv->chan_vm->spg_shift; | 89 | *page_shift = dev_priv->chan_vm->spg_shift; |
@@ -101,8 +101,7 @@ nouveau_bo_fixup_align(struct nouveau_bo *nvbo, int *align, int *size, | |||
101 | int | 101 | int |
102 | nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, | 102 | nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, |
103 | int size, int align, uint32_t flags, uint32_t tile_mode, | 103 | int size, int align, uint32_t flags, uint32_t tile_mode, |
104 | uint32_t tile_flags, bool no_vm, bool mappable, | 104 | uint32_t tile_flags, struct nouveau_bo **pnvbo) |
105 | struct nouveau_bo **pnvbo) | ||
106 | { | 105 | { |
107 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 106 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
108 | struct nouveau_bo *nvbo; | 107 | struct nouveau_bo *nvbo; |
@@ -113,16 +112,14 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, | |||
113 | return -ENOMEM; | 112 | return -ENOMEM; |
114 | INIT_LIST_HEAD(&nvbo->head); | 113 | INIT_LIST_HEAD(&nvbo->head); |
115 | INIT_LIST_HEAD(&nvbo->entry); | 114 | INIT_LIST_HEAD(&nvbo->entry); |
116 | nvbo->mappable = mappable; | ||
117 | nvbo->no_vm = no_vm; | ||
118 | nvbo->tile_mode = tile_mode; | 115 | nvbo->tile_mode = tile_mode; |
119 | nvbo->tile_flags = tile_flags; | 116 | nvbo->tile_flags = tile_flags; |
120 | nvbo->bo.bdev = &dev_priv->ttm.bdev; | 117 | nvbo->bo.bdev = &dev_priv->ttm.bdev; |
121 | 118 | ||
122 | nouveau_bo_fixup_align(nvbo, &align, &size, &page_shift); | 119 | nouveau_bo_fixup_align(nvbo, flags, &align, &size, &page_shift); |
123 | align >>= PAGE_SHIFT; | 120 | align >>= PAGE_SHIFT; |
124 | 121 | ||
125 | if (!nvbo->no_vm && dev_priv->chan_vm) { | 122 | if (dev_priv->chan_vm) { |
126 | ret = nouveau_vm_get(dev_priv->chan_vm, size, page_shift, | 123 | ret = nouveau_vm_get(dev_priv->chan_vm, size, page_shift, |
127 | NV_MEM_ACCESS_RW, &nvbo->vma); | 124 | NV_MEM_ACCESS_RW, &nvbo->vma); |
128 | if (ret) { | 125 | if (ret) { |
@@ -144,11 +141,8 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, | |||
144 | } | 141 | } |
145 | nvbo->channel = NULL; | 142 | nvbo->channel = NULL; |
146 | 143 | ||
147 | if (nvbo->vma.node) { | 144 | if (nvbo->vma.node) |
148 | if (nvbo->bo.mem.mem_type == TTM_PL_VRAM) | 145 | nvbo->bo.offset = nvbo->vma.offset; |
149 | nvbo->bo.offset = nvbo->vma.offset; | ||
150 | } | ||
151 | |||
152 | *pnvbo = nvbo; | 146 | *pnvbo = nvbo; |
153 | return 0; | 147 | return 0; |
154 | } | 148 | } |
@@ -318,11 +312,8 @@ nouveau_bo_validate(struct nouveau_bo *nvbo, bool interruptible, | |||
318 | if (ret) | 312 | if (ret) |
319 | return ret; | 313 | return ret; |
320 | 314 | ||
321 | if (nvbo->vma.node) { | 315 | if (nvbo->vma.node) |
322 | if (nvbo->bo.mem.mem_type == TTM_PL_VRAM) | 316 | nvbo->bo.offset = nvbo->vma.offset; |
323 | nvbo->bo.offset = nvbo->vma.offset; | ||
324 | } | ||
325 | |||
326 | return 0; | 317 | return 0; |
327 | } | 318 | } |
328 | 319 | ||
@@ -385,7 +376,8 @@ nouveau_bo_create_ttm_backend_entry(struct ttm_bo_device *bdev) | |||
385 | case NOUVEAU_GART_AGP: | 376 | case NOUVEAU_GART_AGP: |
386 | return ttm_agp_backend_init(bdev, dev->agp->bridge); | 377 | return ttm_agp_backend_init(bdev, dev->agp->bridge); |
387 | #endif | 378 | #endif |
388 | case NOUVEAU_GART_SGDMA: | 379 | case NOUVEAU_GART_PDMA: |
380 | case NOUVEAU_GART_HW: | ||
389 | return nouveau_sgdma_init_ttm(dev); | 381 | return nouveau_sgdma_init_ttm(dev); |
390 | default: | 382 | default: |
391 | NV_ERROR(dev, "Unknown GART type %d\n", | 383 | NV_ERROR(dev, "Unknown GART type %d\n", |
@@ -431,7 +423,10 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, | |||
431 | man->default_caching = TTM_PL_FLAG_WC; | 423 | man->default_caching = TTM_PL_FLAG_WC; |
432 | break; | 424 | break; |
433 | case TTM_PL_TT: | 425 | case TTM_PL_TT: |
434 | man->func = &ttm_bo_manager_func; | 426 | if (dev_priv->card_type >= NV_50) |
427 | man->func = &nouveau_gart_manager; | ||
428 | else | ||
429 | man->func = &ttm_bo_manager_func; | ||
435 | switch (dev_priv->gart_info.type) { | 430 | switch (dev_priv->gart_info.type) { |
436 | case NOUVEAU_GART_AGP: | 431 | case NOUVEAU_GART_AGP: |
437 | man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; | 432 | man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; |
@@ -439,7 +434,8 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, | |||
439 | TTM_PL_FLAG_WC; | 434 | TTM_PL_FLAG_WC; |
440 | man->default_caching = TTM_PL_FLAG_WC; | 435 | man->default_caching = TTM_PL_FLAG_WC; |
441 | break; | 436 | break; |
442 | case NOUVEAU_GART_SGDMA: | 437 | case NOUVEAU_GART_PDMA: |
438 | case NOUVEAU_GART_HW: | ||
443 | man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | | 439 | man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | |
444 | TTM_MEMTYPE_FLAG_CMA; | 440 | TTM_MEMTYPE_FLAG_CMA; |
445 | man->available_caching = TTM_PL_MASK_CACHING; | 441 | man->available_caching = TTM_PL_MASK_CACHING; |
@@ -501,45 +497,22 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan, | |||
501 | return ret; | 497 | return ret; |
502 | } | 498 | } |
503 | 499 | ||
504 | static inline uint32_t | ||
505 | nouveau_bo_mem_ctxdma(struct ttm_buffer_object *bo, | ||
506 | struct nouveau_channel *chan, struct ttm_mem_reg *mem) | ||
507 | { | ||
508 | struct nouveau_bo *nvbo = nouveau_bo(bo); | ||
509 | |||
510 | if (nvbo->no_vm) { | ||
511 | if (mem->mem_type == TTM_PL_TT) | ||
512 | return NvDmaGART; | ||
513 | return NvDmaVRAM; | ||
514 | } | ||
515 | |||
516 | if (mem->mem_type == TTM_PL_TT) | ||
517 | return chan->gart_handle; | ||
518 | return chan->vram_handle; | ||
519 | } | ||
520 | |||
521 | static int | 500 | static int |
522 | nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, | 501 | nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, |
523 | struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) | 502 | struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) |
524 | { | 503 | { |
525 | struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); | 504 | struct nouveau_mem *old_node = old_mem->mm_node; |
505 | struct nouveau_mem *new_node = new_mem->mm_node; | ||
526 | struct nouveau_bo *nvbo = nouveau_bo(bo); | 506 | struct nouveau_bo *nvbo = nouveau_bo(bo); |
527 | u64 src_offset = old_mem->start << PAGE_SHIFT; | ||
528 | u64 dst_offset = new_mem->start << PAGE_SHIFT; | ||
529 | u32 page_count = new_mem->num_pages; | 507 | u32 page_count = new_mem->num_pages; |
508 | u64 src_offset, dst_offset; | ||
530 | int ret; | 509 | int ret; |
531 | 510 | ||
532 | if (!nvbo->no_vm) { | 511 | src_offset = old_node->tmp_vma.offset; |
533 | if (old_mem->mem_type == TTM_PL_VRAM) | 512 | if (new_node->tmp_vma.node) |
534 | src_offset = nvbo->vma.offset; | 513 | dst_offset = new_node->tmp_vma.offset; |
535 | else | 514 | else |
536 | src_offset += dev_priv->gart_info.aper_base; | 515 | dst_offset = nvbo->vma.offset; |
537 | |||
538 | if (new_mem->mem_type == TTM_PL_VRAM) | ||
539 | dst_offset = nvbo->vma.offset; | ||
540 | else | ||
541 | dst_offset += dev_priv->gart_info.aper_base; | ||
542 | } | ||
543 | 516 | ||
544 | page_count = new_mem->num_pages; | 517 | page_count = new_mem->num_pages; |
545 | while (page_count) { | 518 | while (page_count) { |
@@ -574,33 +547,18 @@ static int | |||
574 | nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, | 547 | nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, |
575 | struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) | 548 | struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) |
576 | { | 549 | { |
577 | struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); | 550 | struct nouveau_mem *old_node = old_mem->mm_node; |
551 | struct nouveau_mem *new_node = new_mem->mm_node; | ||
578 | struct nouveau_bo *nvbo = nouveau_bo(bo); | 552 | struct nouveau_bo *nvbo = nouveau_bo(bo); |
579 | u64 length = (new_mem->num_pages << PAGE_SHIFT); | 553 | u64 length = (new_mem->num_pages << PAGE_SHIFT); |
580 | u64 src_offset, dst_offset; | 554 | u64 src_offset, dst_offset; |
581 | int ret; | 555 | int ret; |
582 | 556 | ||
583 | src_offset = old_mem->start << PAGE_SHIFT; | 557 | src_offset = old_node->tmp_vma.offset; |
584 | dst_offset = new_mem->start << PAGE_SHIFT; | 558 | if (new_node->tmp_vma.node) |
585 | if (!nvbo->no_vm) { | 559 | dst_offset = new_node->tmp_vma.offset; |
586 | if (old_mem->mem_type == TTM_PL_VRAM) | 560 | else |
587 | src_offset = nvbo->vma.offset; | 561 | dst_offset = nvbo->vma.offset; |
588 | else | ||
589 | src_offset += dev_priv->gart_info.aper_base; | ||
590 | |||
591 | if (new_mem->mem_type == TTM_PL_VRAM) | ||
592 | dst_offset = nvbo->vma.offset; | ||
593 | else | ||
594 | dst_offset += dev_priv->gart_info.aper_base; | ||
595 | } | ||
596 | |||
597 | ret = RING_SPACE(chan, 3); | ||
598 | if (ret) | ||
599 | return ret; | ||
600 | |||
601 | BEGIN_RING(chan, NvSubM2MF, 0x0184, 2); | ||
602 | OUT_RING (chan, nouveau_bo_mem_ctxdma(bo, chan, old_mem)); | ||
603 | OUT_RING (chan, nouveau_bo_mem_ctxdma(bo, chan, new_mem)); | ||
604 | 562 | ||
605 | while (length) { | 563 | while (length) { |
606 | u32 amount, stride, height; | 564 | u32 amount, stride, height; |
@@ -681,6 +639,15 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, | |||
681 | return 0; | 639 | return 0; |
682 | } | 640 | } |
683 | 641 | ||
642 | static inline uint32_t | ||
643 | nouveau_bo_mem_ctxdma(struct ttm_buffer_object *bo, | ||
644 | struct nouveau_channel *chan, struct ttm_mem_reg *mem) | ||
645 | { | ||
646 | if (mem->mem_type == TTM_PL_TT) | ||
647 | return chan->gart_handle; | ||
648 | return chan->vram_handle; | ||
649 | } | ||
650 | |||
684 | static int | 651 | static int |
685 | nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, | 652 | nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, |
686 | struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) | 653 | struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) |
@@ -734,15 +701,43 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, | |||
734 | { | 701 | { |
735 | struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); | 702 | struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); |
736 | struct nouveau_bo *nvbo = nouveau_bo(bo); | 703 | struct nouveau_bo *nvbo = nouveau_bo(bo); |
704 | struct ttm_mem_reg *old_mem = &bo->mem; | ||
737 | struct nouveau_channel *chan; | 705 | struct nouveau_channel *chan; |
738 | int ret; | 706 | int ret; |
739 | 707 | ||
740 | chan = nvbo->channel; | 708 | chan = nvbo->channel; |
741 | if (!chan || nvbo->no_vm) { | 709 | if (!chan) { |
742 | chan = dev_priv->channel; | 710 | chan = dev_priv->channel; |
743 | mutex_lock_nested(&chan->mutex, NOUVEAU_KCHANNEL_MUTEX); | 711 | mutex_lock_nested(&chan->mutex, NOUVEAU_KCHANNEL_MUTEX); |
744 | } | 712 | } |
745 | 713 | ||
714 | /* create temporary vma for old memory, this will get cleaned | ||
715 | * up after ttm destroys the ttm_mem_reg | ||
716 | */ | ||
717 | if (dev_priv->card_type >= NV_50) { | ||
718 | struct nouveau_mem *node = old_mem->mm_node; | ||
719 | if (!node->tmp_vma.node) { | ||
720 | u32 page_shift = nvbo->vma.node->type; | ||
721 | if (old_mem->mem_type == TTM_PL_TT) | ||
722 | page_shift = nvbo->vma.vm->spg_shift; | ||
723 | |||
724 | ret = nouveau_vm_get(chan->vm, | ||
725 | old_mem->num_pages << PAGE_SHIFT, | ||
726 | page_shift, NV_MEM_ACCESS_RO, | ||
727 | &node->tmp_vma); | ||
728 | if (ret) | ||
729 | goto out; | ||
730 | } | ||
731 | |||
732 | if (old_mem->mem_type == TTM_PL_VRAM) | ||
733 | nouveau_vm_map(&node->tmp_vma, node); | ||
734 | else { | ||
735 | nouveau_vm_map_sg(&node->tmp_vma, 0, | ||
736 | old_mem->num_pages << PAGE_SHIFT, | ||
737 | node, node->pages); | ||
738 | } | ||
739 | } | ||
740 | |||
746 | if (dev_priv->card_type < NV_50) | 741 | if (dev_priv->card_type < NV_50) |
747 | ret = nv04_bo_move_m2mf(chan, bo, &bo->mem, new_mem); | 742 | ret = nv04_bo_move_m2mf(chan, bo, &bo->mem, new_mem); |
748 | else | 743 | else |
@@ -756,6 +751,7 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, | |||
756 | no_wait_gpu, new_mem); | 751 | no_wait_gpu, new_mem); |
757 | } | 752 | } |
758 | 753 | ||
754 | out: | ||
759 | if (chan == dev_priv->channel) | 755 | if (chan == dev_priv->channel) |
760 | mutex_unlock(&chan->mutex); | 756 | mutex_unlock(&chan->mutex); |
761 | return ret; | 757 | return ret; |
@@ -766,6 +762,7 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr, | |||
766 | bool no_wait_reserve, bool no_wait_gpu, | 762 | bool no_wait_reserve, bool no_wait_gpu, |
767 | struct ttm_mem_reg *new_mem) | 763 | struct ttm_mem_reg *new_mem) |
768 | { | 764 | { |
765 | struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); | ||
769 | u32 placement_memtype = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING; | 766 | u32 placement_memtype = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING; |
770 | struct ttm_placement placement; | 767 | struct ttm_placement placement; |
771 | struct ttm_mem_reg tmp_mem; | 768 | struct ttm_mem_reg tmp_mem; |
@@ -785,7 +782,23 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr, | |||
785 | if (ret) | 782 | if (ret) |
786 | goto out; | 783 | goto out; |
787 | 784 | ||
785 | if (dev_priv->card_type >= NV_50) { | ||
786 | struct nouveau_bo *nvbo = nouveau_bo(bo); | ||
787 | struct nouveau_mem *node = tmp_mem.mm_node; | ||
788 | struct nouveau_vma *vma = &nvbo->vma; | ||
789 | if (vma->node->type != vma->vm->spg_shift) | ||
790 | vma = &node->tmp_vma; | ||
791 | nouveau_vm_map_sg(vma, 0, tmp_mem.num_pages << PAGE_SHIFT, | ||
792 | node, node->pages); | ||
793 | } | ||
794 | |||
788 | ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait_reserve, no_wait_gpu, &tmp_mem); | 795 | ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait_reserve, no_wait_gpu, &tmp_mem); |
796 | |||
797 | if (dev_priv->card_type >= NV_50) { | ||
798 | struct nouveau_bo *nvbo = nouveau_bo(bo); | ||
799 | nouveau_vm_unmap(&nvbo->vma); | ||
800 | } | ||
801 | |||
789 | if (ret) | 802 | if (ret) |
790 | goto out; | 803 | goto out; |
791 | 804 | ||
@@ -828,6 +841,36 @@ out: | |||
828 | return ret; | 841 | return ret; |
829 | } | 842 | } |
830 | 843 | ||
844 | static void | ||
845 | nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) | ||
846 | { | ||
847 | struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); | ||
848 | struct nouveau_mem *node = new_mem->mm_node; | ||
849 | struct nouveau_bo *nvbo = nouveau_bo(bo); | ||
850 | struct nouveau_vma *vma = &nvbo->vma; | ||
851 | struct nouveau_vm *vm = vma->vm; | ||
852 | |||
853 | if (dev_priv->card_type < NV_50) | ||
854 | return; | ||
855 | |||
856 | switch (new_mem->mem_type) { | ||
857 | case TTM_PL_VRAM: | ||
858 | nouveau_vm_map(vma, node); | ||
859 | break; | ||
860 | case TTM_PL_TT: | ||
861 | if (vma->node->type != vm->spg_shift) { | ||
862 | nouveau_vm_unmap(vma); | ||
863 | vma = &node->tmp_vma; | ||
864 | } | ||
865 | nouveau_vm_map_sg(vma, 0, new_mem->num_pages << PAGE_SHIFT, | ||
866 | node, node->pages); | ||
867 | break; | ||
868 | default: | ||
869 | nouveau_vm_unmap(&nvbo->vma); | ||
870 | break; | ||
871 | } | ||
872 | } | ||
873 | |||
831 | static int | 874 | static int |
832 | nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem, | 875 | nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem, |
833 | struct nouveau_tile_reg **new_tile) | 876 | struct nouveau_tile_reg **new_tile) |
@@ -835,19 +878,13 @@ nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem, | |||
835 | struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); | 878 | struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); |
836 | struct drm_device *dev = dev_priv->dev; | 879 | struct drm_device *dev = dev_priv->dev; |
837 | struct nouveau_bo *nvbo = nouveau_bo(bo); | 880 | struct nouveau_bo *nvbo = nouveau_bo(bo); |
838 | uint64_t offset; | 881 | u64 offset = new_mem->start << PAGE_SHIFT; |
839 | 882 | ||
840 | if (nvbo->no_vm || new_mem->mem_type != TTM_PL_VRAM) { | 883 | *new_tile = NULL; |
841 | /* Nothing to do. */ | 884 | if (new_mem->mem_type != TTM_PL_VRAM) |
842 | *new_tile = NULL; | ||
843 | return 0; | 885 | return 0; |
844 | } | ||
845 | |||
846 | offset = new_mem->start << PAGE_SHIFT; | ||
847 | 886 | ||
848 | if (dev_priv->chan_vm) { | 887 | if (dev_priv->card_type >= NV_10) { |
849 | nouveau_vm_map(&nvbo->vma, new_mem->mm_node); | ||
850 | } else if (dev_priv->card_type >= NV_10) { | ||
851 | *new_tile = nv10_mem_set_tiling(dev, offset, new_mem->size, | 888 | *new_tile = nv10_mem_set_tiling(dev, offset, new_mem->size, |
852 | nvbo->tile_mode, | 889 | nvbo->tile_mode, |
853 | nvbo->tile_flags); | 890 | nvbo->tile_flags); |
@@ -864,11 +901,8 @@ nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo, | |||
864 | struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); | 901 | struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); |
865 | struct drm_device *dev = dev_priv->dev; | 902 | struct drm_device *dev = dev_priv->dev; |
866 | 903 | ||
867 | if (dev_priv->card_type >= NV_10 && | 904 | nv10_mem_put_tile_region(dev, *old_tile, bo->sync_obj); |
868 | dev_priv->card_type < NV_50) { | 905 | *old_tile = new_tile; |
869 | nv10_mem_put_tile_region(dev, *old_tile, bo->sync_obj); | ||
870 | *old_tile = new_tile; | ||
871 | } | ||
872 | } | 906 | } |
873 | 907 | ||
874 | static int | 908 | static int |
@@ -882,9 +916,11 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr, | |||
882 | struct nouveau_tile_reg *new_tile = NULL; | 916 | struct nouveau_tile_reg *new_tile = NULL; |
883 | int ret = 0; | 917 | int ret = 0; |
884 | 918 | ||
885 | ret = nouveau_bo_vm_bind(bo, new_mem, &new_tile); | 919 | if (dev_priv->card_type < NV_50) { |
886 | if (ret) | 920 | ret = nouveau_bo_vm_bind(bo, new_mem, &new_tile); |
887 | return ret; | 921 | if (ret) |
922 | return ret; | ||
923 | } | ||
888 | 924 | ||
889 | /* Fake bo copy. */ | 925 | /* Fake bo copy. */ |
890 | if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) { | 926 | if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) { |
@@ -915,10 +951,12 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr, | |||
915 | ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); | 951 | ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); |
916 | 952 | ||
917 | out: | 953 | out: |
918 | if (ret) | 954 | if (dev_priv->card_type < NV_50) { |
919 | nouveau_bo_vm_cleanup(bo, NULL, &new_tile); | 955 | if (ret) |
920 | else | 956 | nouveau_bo_vm_cleanup(bo, NULL, &new_tile); |
921 | nouveau_bo_vm_cleanup(bo, new_tile, &nvbo->tile); | 957 | else |
958 | nouveau_bo_vm_cleanup(bo, new_tile, &nvbo->tile); | ||
959 | } | ||
922 | 960 | ||
923 | return ret; | 961 | return ret; |
924 | } | 962 | } |
@@ -959,7 +997,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) | |||
959 | break; | 997 | break; |
960 | case TTM_PL_VRAM: | 998 | case TTM_PL_VRAM: |
961 | { | 999 | { |
962 | struct nouveau_vram *vram = mem->mm_node; | 1000 | struct nouveau_mem *node = mem->mm_node; |
963 | u8 page_shift; | 1001 | u8 page_shift; |
964 | 1002 | ||
965 | if (!dev_priv->bar1_vm) { | 1003 | if (!dev_priv->bar1_vm) { |
@@ -970,23 +1008,23 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) | |||
970 | } | 1008 | } |
971 | 1009 | ||
972 | if (dev_priv->card_type == NV_C0) | 1010 | if (dev_priv->card_type == NV_C0) |
973 | page_shift = vram->page_shift; | 1011 | page_shift = node->page_shift; |
974 | else | 1012 | else |
975 | page_shift = 12; | 1013 | page_shift = 12; |
976 | 1014 | ||
977 | ret = nouveau_vm_get(dev_priv->bar1_vm, mem->bus.size, | 1015 | ret = nouveau_vm_get(dev_priv->bar1_vm, mem->bus.size, |
978 | page_shift, NV_MEM_ACCESS_RW, | 1016 | page_shift, NV_MEM_ACCESS_RW, |
979 | &vram->bar_vma); | 1017 | &node->bar_vma); |
980 | if (ret) | 1018 | if (ret) |
981 | return ret; | 1019 | return ret; |
982 | 1020 | ||
983 | nouveau_vm_map(&vram->bar_vma, vram); | 1021 | nouveau_vm_map(&node->bar_vma, node); |
984 | if (ret) { | 1022 | if (ret) { |
985 | nouveau_vm_put(&vram->bar_vma); | 1023 | nouveau_vm_put(&node->bar_vma); |
986 | return ret; | 1024 | return ret; |
987 | } | 1025 | } |
988 | 1026 | ||
989 | mem->bus.offset = vram->bar_vma.offset; | 1027 | mem->bus.offset = node->bar_vma.offset; |
990 | if (dev_priv->card_type == NV_50) /*XXX*/ | 1028 | if (dev_priv->card_type == NV_50) /*XXX*/ |
991 | mem->bus.offset -= 0x0020000000ULL; | 1029 | mem->bus.offset -= 0x0020000000ULL; |
992 | mem->bus.base = pci_resource_start(dev->pdev, 1); | 1030 | mem->bus.base = pci_resource_start(dev->pdev, 1); |
@@ -1003,16 +1041,16 @@ static void | |||
1003 | nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) | 1041 | nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) |
1004 | { | 1042 | { |
1005 | struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev); | 1043 | struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev); |
1006 | struct nouveau_vram *vram = mem->mm_node; | 1044 | struct nouveau_mem *node = mem->mm_node; |
1007 | 1045 | ||
1008 | if (!dev_priv->bar1_vm || mem->mem_type != TTM_PL_VRAM) | 1046 | if (!dev_priv->bar1_vm || mem->mem_type != TTM_PL_VRAM) |
1009 | return; | 1047 | return; |
1010 | 1048 | ||
1011 | if (!vram->bar_vma.node) | 1049 | if (!node->bar_vma.node) |
1012 | return; | 1050 | return; |
1013 | 1051 | ||
1014 | nouveau_vm_unmap(&vram->bar_vma); | 1052 | nouveau_vm_unmap(&node->bar_vma); |
1015 | nouveau_vm_put(&vram->bar_vma); | 1053 | nouveau_vm_put(&node->bar_vma); |
1016 | } | 1054 | } |
1017 | 1055 | ||
1018 | static int | 1056 | static int |
@@ -1062,6 +1100,7 @@ struct ttm_bo_driver nouveau_bo_driver = { | |||
1062 | .invalidate_caches = nouveau_bo_invalidate_caches, | 1100 | .invalidate_caches = nouveau_bo_invalidate_caches, |
1063 | .init_mem_type = nouveau_bo_init_mem_type, | 1101 | .init_mem_type = nouveau_bo_init_mem_type, |
1064 | .evict_flags = nouveau_bo_evict_flags, | 1102 | .evict_flags = nouveau_bo_evict_flags, |
1103 | .move_notify = nouveau_bo_move_ntfy, | ||
1065 | .move = nouveau_bo_move, | 1104 | .move = nouveau_bo_move, |
1066 | .verify_access = nouveau_bo_verify_access, | 1105 | .verify_access = nouveau_bo_verify_access, |
1067 | .sync_obj_signaled = __nouveau_fence_signalled, | 1106 | .sync_obj_signaled = __nouveau_fence_signalled, |
diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c index 3960d66d7ab..3837090d66a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c | |||
@@ -35,7 +35,7 @@ nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan) | |||
35 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 35 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
36 | struct nouveau_bo *pb = chan->pushbuf_bo; | 36 | struct nouveau_bo *pb = chan->pushbuf_bo; |
37 | struct nouveau_gpuobj *pushbuf = NULL; | 37 | struct nouveau_gpuobj *pushbuf = NULL; |
38 | int ret; | 38 | int ret = 0; |
39 | 39 | ||
40 | if (dev_priv->card_type >= NV_50) { | 40 | if (dev_priv->card_type >= NV_50) { |
41 | if (dev_priv->card_type < NV_C0) { | 41 | if (dev_priv->card_type < NV_C0) { |
@@ -90,8 +90,7 @@ nouveau_channel_user_pushbuf_alloc(struct drm_device *dev) | |||
90 | else | 90 | else |
91 | location = TTM_PL_FLAG_TT; | 91 | location = TTM_PL_FLAG_TT; |
92 | 92 | ||
93 | ret = nouveau_bo_new(dev, NULL, 65536, 0, location, 0, 0x0000, false, | 93 | ret = nouveau_bo_new(dev, NULL, 65536, 0, location, 0, 0x0000, &pushbuf); |
94 | true, &pushbuf); | ||
95 | if (ret) { | 94 | if (ret) { |
96 | NV_ERROR(dev, "error allocating DMA push buffer: %d\n", ret); | 95 | NV_ERROR(dev, "error allocating DMA push buffer: %d\n", ret); |
97 | return NULL; | 96 | return NULL; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 505c6bfb4d7..764c15d537b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include "nouveau_hw.h" | 32 | #include "nouveau_hw.h" |
33 | #include "nouveau_crtc.h" | 33 | #include "nouveau_crtc.h" |
34 | #include "nouveau_dma.h" | 34 | #include "nouveau_dma.h" |
35 | #include "nv50_display.h" | ||
35 | 36 | ||
36 | static void | 37 | static void |
37 | nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb) | 38 | nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb) |
@@ -61,18 +62,59 @@ static const struct drm_framebuffer_funcs nouveau_framebuffer_funcs = { | |||
61 | }; | 62 | }; |
62 | 63 | ||
63 | int | 64 | int |
64 | nouveau_framebuffer_init(struct drm_device *dev, struct nouveau_framebuffer *nouveau_fb, | 65 | nouveau_framebuffer_init(struct drm_device *dev, |
65 | struct drm_mode_fb_cmd *mode_cmd, struct nouveau_bo *nvbo) | 66 | struct nouveau_framebuffer *nv_fb, |
67 | struct drm_mode_fb_cmd *mode_cmd, | ||
68 | struct nouveau_bo *nvbo) | ||
66 | { | 69 | { |
70 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
71 | struct drm_framebuffer *fb = &nv_fb->base; | ||
67 | int ret; | 72 | int ret; |
68 | 73 | ||
69 | ret = drm_framebuffer_init(dev, &nouveau_fb->base, &nouveau_framebuffer_funcs); | 74 | ret = drm_framebuffer_init(dev, fb, &nouveau_framebuffer_funcs); |
70 | if (ret) { | 75 | if (ret) { |
71 | return ret; | 76 | return ret; |
72 | } | 77 | } |
73 | 78 | ||
74 | drm_helper_mode_fill_fb_struct(&nouveau_fb->base, mode_cmd); | 79 | drm_helper_mode_fill_fb_struct(fb, mode_cmd); |
75 | nouveau_fb->nvbo = nvbo; | 80 | nv_fb->nvbo = nvbo; |
81 | |||
82 | if (dev_priv->card_type >= NV_50) { | ||
83 | u32 tile_flags = nouveau_bo_tile_layout(nvbo); | ||
84 | if (tile_flags == 0x7a00 || | ||
85 | tile_flags == 0xfe00) | ||
86 | nv_fb->r_dma = NvEvoFB32; | ||
87 | else | ||
88 | if (tile_flags == 0x7000) | ||
89 | nv_fb->r_dma = NvEvoFB16; | ||
90 | else | ||
91 | nv_fb->r_dma = NvEvoVRAM_LP; | ||
92 | |||
93 | switch (fb->depth) { | ||
94 | case 8: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_8; break; | ||
95 | case 15: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_15; break; | ||
96 | case 16: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_16; break; | ||
97 | case 24: | ||
98 | case 32: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_24; break; | ||
99 | case 30: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_30; break; | ||
100 | default: | ||
101 | NV_ERROR(dev, "unknown depth %d\n", fb->depth); | ||
102 | return -EINVAL; | ||
103 | } | ||
104 | |||
105 | if (dev_priv->chipset == 0x50) | ||
106 | nv_fb->r_format |= (tile_flags << 8); | ||
107 | |||
108 | if (!tile_flags) | ||
109 | nv_fb->r_pitch = 0x00100000 | fb->pitch; | ||
110 | else { | ||
111 | u32 mode = nvbo->tile_mode; | ||
112 | if (dev_priv->card_type >= NV_C0) | ||
113 | mode >>= 4; | ||
114 | nv_fb->r_pitch = ((fb->pitch / 4) << 4) | mode; | ||
115 | } | ||
116 | } | ||
117 | |||
76 | return 0; | 118 | return 0; |
77 | } | 119 | } |
78 | 120 | ||
@@ -182,6 +224,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan, | |||
182 | struct nouveau_page_flip_state *s, | 224 | struct nouveau_page_flip_state *s, |
183 | struct nouveau_fence **pfence) | 225 | struct nouveau_fence **pfence) |
184 | { | 226 | { |
227 | struct drm_nouveau_private *dev_priv = chan->dev->dev_private; | ||
185 | struct drm_device *dev = chan->dev; | 228 | struct drm_device *dev = chan->dev; |
186 | unsigned long flags; | 229 | unsigned long flags; |
187 | int ret; | 230 | int ret; |
@@ -201,9 +244,12 @@ nouveau_page_flip_emit(struct nouveau_channel *chan, | |||
201 | if (ret) | 244 | if (ret) |
202 | goto fail; | 245 | goto fail; |
203 | 246 | ||
204 | BEGIN_RING(chan, NvSubSw, NV_SW_PAGE_FLIP, 1); | 247 | if (dev_priv->card_type < NV_C0) |
205 | OUT_RING(chan, 0); | 248 | BEGIN_RING(chan, NvSubSw, NV_SW_PAGE_FLIP, 1); |
206 | FIRE_RING(chan); | 249 | else |
250 | BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0500, 1); | ||
251 | OUT_RING (chan, 0); | ||
252 | FIRE_RING (chan); | ||
207 | 253 | ||
208 | ret = nouveau_fence_new(chan, pfence, true); | 254 | ret = nouveau_fence_new(chan, pfence, true); |
209 | if (ret) | 255 | if (ret) |
@@ -244,7 +290,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, | |||
244 | 290 | ||
245 | /* Initialize a page flip struct */ | 291 | /* Initialize a page flip struct */ |
246 | *s = (struct nouveau_page_flip_state) | 292 | *s = (struct nouveau_page_flip_state) |
247 | { { }, s->event, nouveau_crtc(crtc)->index, | 293 | { { }, event, nouveau_crtc(crtc)->index, |
248 | fb->bits_per_pixel, fb->pitch, crtc->x, crtc->y, | 294 | fb->bits_per_pixel, fb->pitch, crtc->x, crtc->y, |
249 | new_bo->bo.offset }; | 295 | new_bo->bo.offset }; |
250 | 296 | ||
@@ -255,6 +301,14 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, | |||
255 | mutex_lock(&chan->mutex); | 301 | mutex_lock(&chan->mutex); |
256 | 302 | ||
257 | /* Emit a page flip */ | 303 | /* Emit a page flip */ |
304 | if (dev_priv->card_type >= NV_50) { | ||
305 | ret = nv50_display_flip_next(crtc, fb, chan); | ||
306 | if (ret) { | ||
307 | nouveau_channel_put(&chan); | ||
308 | goto fail_unreserve; | ||
309 | } | ||
310 | } | ||
311 | |||
258 | ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); | 312 | ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); |
259 | nouveau_channel_put(&chan); | 313 | nouveau_channel_put(&chan); |
260 | if (ret) | 314 | if (ret) |
@@ -305,7 +359,8 @@ nouveau_finish_page_flip(struct nouveau_channel *chan, | |||
305 | } | 359 | } |
306 | 360 | ||
307 | list_del(&s->head); | 361 | list_del(&s->head); |
308 | *ps = *s; | 362 | if (ps) |
363 | *ps = *s; | ||
309 | kfree(s); | 364 | kfree(s); |
310 | 365 | ||
311 | spin_unlock_irqrestore(&dev->event_lock, flags); | 366 | spin_unlock_irqrestore(&dev->event_lock, flags); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c index b368ed74aad..ce38e97b942 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.c +++ b/drivers/gpu/drm/nouveau/nouveau_dma.c | |||
@@ -97,13 +97,15 @@ nouveau_dma_init(struct nouveau_channel *chan) | |||
97 | OUT_RING(chan, 0); | 97 | OUT_RING(chan, 0); |
98 | 98 | ||
99 | /* Initialise NV_MEMORY_TO_MEMORY_FORMAT */ | 99 | /* Initialise NV_MEMORY_TO_MEMORY_FORMAT */ |
100 | ret = RING_SPACE(chan, 4); | 100 | ret = RING_SPACE(chan, 6); |
101 | if (ret) | 101 | if (ret) |
102 | return ret; | 102 | return ret; |
103 | BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NAME, 1); | 103 | BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NAME, 1); |
104 | OUT_RING(chan, NvM2MF); | 104 | OUT_RING (chan, NvM2MF); |
105 | BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1); | 105 | BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 3); |
106 | OUT_RING(chan, NvNotify0); | 106 | OUT_RING (chan, NvNotify0); |
107 | OUT_RING (chan, chan->vram_handle); | ||
108 | OUT_RING (chan, chan->gart_handle); | ||
107 | 109 | ||
108 | /* Sit back and pray the channel works.. */ | 110 | /* Sit back and pray the channel works.. */ |
109 | FIRE_RING(chan); | 111 | FIRE_RING(chan); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.h b/drivers/gpu/drm/nouveau/nouveau_dma.h index c36f1763fea..23d4edf992b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.h +++ b/drivers/gpu/drm/nouveau/nouveau_dma.h | |||
@@ -61,8 +61,6 @@ enum { | |||
61 | NvM2MF = 0x80000001, | 61 | NvM2MF = 0x80000001, |
62 | NvDmaFB = 0x80000002, | 62 | NvDmaFB = 0x80000002, |
63 | NvDmaTT = 0x80000003, | 63 | NvDmaTT = 0x80000003, |
64 | NvDmaVRAM = 0x80000004, | ||
65 | NvDmaGART = 0x80000005, | ||
66 | NvNotify0 = 0x80000006, | 64 | NvNotify0 = 0x80000006, |
67 | Nv2D = 0x80000007, | 65 | Nv2D = 0x80000007, |
68 | NvCtxSurf2D = 0x80000008, | 66 | NvCtxSurf2D = 0x80000008, |
@@ -73,12 +71,15 @@ enum { | |||
73 | NvImageBlit = 0x8000000d, | 71 | NvImageBlit = 0x8000000d, |
74 | NvSw = 0x8000000e, | 72 | NvSw = 0x8000000e, |
75 | NvSema = 0x8000000f, | 73 | NvSema = 0x8000000f, |
74 | NvEvoSema0 = 0x80000010, | ||
75 | NvEvoSema1 = 0x80000011, | ||
76 | 76 | ||
77 | /* G80+ display objects */ | 77 | /* G80+ display objects */ |
78 | NvEvoVRAM = 0x01000000, | 78 | NvEvoVRAM = 0x01000000, |
79 | NvEvoFB16 = 0x01000001, | 79 | NvEvoFB16 = 0x01000001, |
80 | NvEvoFB32 = 0x01000002, | 80 | NvEvoFB32 = 0x01000002, |
81 | NvEvoVRAM_LP = 0x01000003 | 81 | NvEvoVRAM_LP = 0x01000003, |
82 | NvEvoSync = 0xcafe0000 | ||
82 | }; | 83 | }; |
83 | 84 | ||
84 | #define NV_MEMORY_TO_MEMORY_FORMAT 0x00000039 | 85 | #define NV_MEMORY_TO_MEMORY_FORMAT 0x00000039 |
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 38d599554bc..7beb82a0315 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c | |||
@@ -175,7 +175,6 @@ nouveau_dp_link_train_adjust(struct drm_encoder *encoder, uint8_t *config) | |||
175 | { | 175 | { |
176 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 176 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); |
177 | struct drm_device *dev = encoder->dev; | 177 | struct drm_device *dev = encoder->dev; |
178 | struct bit_displayport_encoder_table_entry *dpse; | ||
179 | struct bit_displayport_encoder_table *dpe; | 178 | struct bit_displayport_encoder_table *dpe; |
180 | int ret, i, dpe_headerlen, vs = 0, pre = 0; | 179 | int ret, i, dpe_headerlen, vs = 0, pre = 0; |
181 | uint8_t request[2]; | 180 | uint8_t request[2]; |
@@ -183,7 +182,6 @@ nouveau_dp_link_train_adjust(struct drm_encoder *encoder, uint8_t *config) | |||
183 | dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); | 182 | dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); |
184 | if (!dpe) | 183 | if (!dpe) |
185 | return false; | 184 | return false; |
186 | dpse = (void *)((char *)dpe + dpe_headerlen); | ||
187 | 185 | ||
188 | ret = auxch_rd(encoder, DP_ADJUST_REQUEST_LANE0_1, request, 2); | 186 | ret = auxch_rd(encoder, DP_ADJUST_REQUEST_LANE0_1, request, 2); |
189 | if (ret) | 187 | if (ret) |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index f658a04eecf..155ebdcbf06 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c | |||
@@ -408,14 +408,6 @@ static struct drm_driver driver = { | |||
408 | #endif | 408 | #endif |
409 | .llseek = noop_llseek, | 409 | .llseek = noop_llseek, |
410 | }, | 410 | }, |
411 | .pci_driver = { | ||
412 | .name = DRIVER_NAME, | ||
413 | .id_table = pciidlist, | ||
414 | .probe = nouveau_pci_probe, | ||
415 | .remove = nouveau_pci_remove, | ||
416 | .suspend = nouveau_pci_suspend, | ||
417 | .resume = nouveau_pci_resume | ||
418 | }, | ||
419 | 411 | ||
420 | .gem_init_object = nouveau_gem_object_new, | 412 | .gem_init_object = nouveau_gem_object_new, |
421 | .gem_free_object = nouveau_gem_object_del, | 413 | .gem_free_object = nouveau_gem_object_del, |
@@ -432,6 +424,15 @@ static struct drm_driver driver = { | |||
432 | .patchlevel = DRIVER_PATCHLEVEL, | 424 | .patchlevel = DRIVER_PATCHLEVEL, |
433 | }; | 425 | }; |
434 | 426 | ||
427 | static struct pci_driver nouveau_pci_driver = { | ||
428 | .name = DRIVER_NAME, | ||
429 | .id_table = pciidlist, | ||
430 | .probe = nouveau_pci_probe, | ||
431 | .remove = nouveau_pci_remove, | ||
432 | .suspend = nouveau_pci_suspend, | ||
433 | .resume = nouveau_pci_resume | ||
434 | }; | ||
435 | |||
435 | static int __init nouveau_init(void) | 436 | static int __init nouveau_init(void) |
436 | { | 437 | { |
437 | driver.num_ioctls = nouveau_max_ioctl; | 438 | driver.num_ioctls = nouveau_max_ioctl; |
@@ -449,7 +450,7 @@ static int __init nouveau_init(void) | |||
449 | return 0; | 450 | return 0; |
450 | 451 | ||
451 | nouveau_register_dsm_handler(); | 452 | nouveau_register_dsm_handler(); |
452 | return drm_init(&driver); | 453 | return drm_pci_init(&driver, &nouveau_pci_driver); |
453 | } | 454 | } |
454 | 455 | ||
455 | static void __exit nouveau_exit(void) | 456 | static void __exit nouveau_exit(void) |
@@ -457,7 +458,7 @@ static void __exit nouveau_exit(void) | |||
457 | if (!nouveau_modeset) | 458 | if (!nouveau_modeset) |
458 | return; | 459 | return; |
459 | 460 | ||
460 | drm_exit(&driver); | 461 | drm_pci_exit(&driver, &nouveau_pci_driver); |
461 | nouveau_unregister_dsm_handler(); | 462 | nouveau_unregister_dsm_handler(); |
462 | } | 463 | } |
463 | 464 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 982d70b1272..06111887b78 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h | |||
@@ -57,7 +57,7 @@ struct nouveau_fpriv { | |||
57 | #include "nouveau_util.h" | 57 | #include "nouveau_util.h" |
58 | 58 | ||
59 | struct nouveau_grctx; | 59 | struct nouveau_grctx; |
60 | struct nouveau_vram; | 60 | struct nouveau_mem; |
61 | #include "nouveau_vm.h" | 61 | #include "nouveau_vm.h" |
62 | 62 | ||
63 | #define MAX_NUM_DCB_ENTRIES 16 | 63 | #define MAX_NUM_DCB_ENTRIES 16 |
@@ -65,13 +65,16 @@ struct nouveau_vram; | |||
65 | #define NOUVEAU_MAX_CHANNEL_NR 128 | 65 | #define NOUVEAU_MAX_CHANNEL_NR 128 |
66 | #define NOUVEAU_MAX_TILE_NR 15 | 66 | #define NOUVEAU_MAX_TILE_NR 15 |
67 | 67 | ||
68 | struct nouveau_vram { | 68 | struct nouveau_mem { |
69 | struct drm_device *dev; | 69 | struct drm_device *dev; |
70 | 70 | ||
71 | struct nouveau_vma bar_vma; | 71 | struct nouveau_vma bar_vma; |
72 | struct nouveau_vma tmp_vma; | ||
72 | u8 page_shift; | 73 | u8 page_shift; |
73 | 74 | ||
75 | struct drm_mm_node *tag; | ||
74 | struct list_head regions; | 76 | struct list_head regions; |
77 | dma_addr_t *pages; | ||
75 | u32 memtype; | 78 | u32 memtype; |
76 | u64 offset; | 79 | u64 offset; |
77 | u64 size; | 80 | u64 size; |
@@ -90,6 +93,7 @@ struct nouveau_tile_reg { | |||
90 | struct nouveau_bo { | 93 | struct nouveau_bo { |
91 | struct ttm_buffer_object bo; | 94 | struct ttm_buffer_object bo; |
92 | struct ttm_placement placement; | 95 | struct ttm_placement placement; |
96 | u32 valid_domains; | ||
93 | u32 placements[3]; | 97 | u32 placements[3]; |
94 | u32 busy_placements[3]; | 98 | u32 busy_placements[3]; |
95 | struct ttm_bo_kmap_obj kmap; | 99 | struct ttm_bo_kmap_obj kmap; |
@@ -104,8 +108,6 @@ struct nouveau_bo { | |||
104 | struct nouveau_channel *channel; | 108 | struct nouveau_channel *channel; |
105 | 109 | ||
106 | struct nouveau_vma vma; | 110 | struct nouveau_vma vma; |
107 | bool mappable; | ||
108 | bool no_vm; | ||
109 | 111 | ||
110 | uint32_t tile_mode; | 112 | uint32_t tile_mode; |
111 | uint32_t tile_flags; | 113 | uint32_t tile_flags; |
@@ -387,6 +389,7 @@ struct nouveau_pgraph_engine { | |||
387 | }; | 389 | }; |
388 | 390 | ||
389 | struct nouveau_display_engine { | 391 | struct nouveau_display_engine { |
392 | void *priv; | ||
390 | int (*early_init)(struct drm_device *); | 393 | int (*early_init)(struct drm_device *); |
391 | void (*late_takedown)(struct drm_device *); | 394 | void (*late_takedown)(struct drm_device *); |
392 | int (*create)(struct drm_device *); | 395 | int (*create)(struct drm_device *); |
@@ -509,8 +512,8 @@ struct nouveau_crypt_engine { | |||
509 | struct nouveau_vram_engine { | 512 | struct nouveau_vram_engine { |
510 | int (*init)(struct drm_device *); | 513 | int (*init)(struct drm_device *); |
511 | int (*get)(struct drm_device *, u64, u32 align, u32 size_nc, | 514 | int (*get)(struct drm_device *, u64, u32 align, u32 size_nc, |
512 | u32 type, struct nouveau_vram **); | 515 | u32 type, struct nouveau_mem **); |
513 | void (*put)(struct drm_device *, struct nouveau_vram **); | 516 | void (*put)(struct drm_device *, struct nouveau_mem **); |
514 | 517 | ||
515 | bool (*flags_valid)(struct drm_device *, u32 tile_flags); | 518 | bool (*flags_valid)(struct drm_device *, u32 tile_flags); |
516 | }; | 519 | }; |
@@ -652,8 +655,6 @@ struct drm_nouveau_private { | |||
652 | /* interrupt handling */ | 655 | /* interrupt handling */ |
653 | void (*irq_handler[32])(struct drm_device *); | 656 | void (*irq_handler[32])(struct drm_device *); |
654 | bool msi_enabled; | 657 | bool msi_enabled; |
655 | struct workqueue_struct *wq; | ||
656 | struct work_struct irq_work; | ||
657 | 658 | ||
658 | struct list_head vbl_waiting; | 659 | struct list_head vbl_waiting; |
659 | 660 | ||
@@ -691,15 +692,22 @@ struct drm_nouveau_private { | |||
691 | struct { | 692 | struct { |
692 | enum { | 693 | enum { |
693 | NOUVEAU_GART_NONE = 0, | 694 | NOUVEAU_GART_NONE = 0, |
694 | NOUVEAU_GART_AGP, | 695 | NOUVEAU_GART_AGP, /* AGP */ |
695 | NOUVEAU_GART_SGDMA | 696 | NOUVEAU_GART_PDMA, /* paged dma object */ |
697 | NOUVEAU_GART_HW /* on-chip gart/vm */ | ||
696 | } type; | 698 | } type; |
697 | uint64_t aper_base; | 699 | uint64_t aper_base; |
698 | uint64_t aper_size; | 700 | uint64_t aper_size; |
699 | uint64_t aper_free; | 701 | uint64_t aper_free; |
700 | 702 | ||
703 | struct ttm_backend_func *func; | ||
704 | |||
705 | struct { | ||
706 | struct page *page; | ||
707 | dma_addr_t addr; | ||
708 | } dummy; | ||
709 | |||
701 | struct nouveau_gpuobj *sg_ctxdma; | 710 | struct nouveau_gpuobj *sg_ctxdma; |
702 | struct nouveau_vma vma; | ||
703 | } gart_info; | 711 | } gart_info; |
704 | 712 | ||
705 | /* nv10-nv40 tiling regions */ | 713 | /* nv10-nv40 tiling regions */ |
@@ -740,14 +748,6 @@ struct drm_nouveau_private { | |||
740 | 748 | ||
741 | struct backlight_device *backlight; | 749 | struct backlight_device *backlight; |
742 | 750 | ||
743 | struct nouveau_channel *evo; | ||
744 | u32 evo_alloc; | ||
745 | struct { | ||
746 | struct dcb_entry *dcb; | ||
747 | u16 script; | ||
748 | u32 pclk; | ||
749 | } evo_irq; | ||
750 | |||
751 | struct { | 751 | struct { |
752 | struct dentry *channel_root; | 752 | struct dentry *channel_root; |
753 | } debugfs; | 753 | } debugfs; |
@@ -847,6 +847,7 @@ extern void nv10_mem_put_tile_region(struct drm_device *dev, | |||
847 | struct nouveau_tile_reg *tile, | 847 | struct nouveau_tile_reg *tile, |
848 | struct nouveau_fence *fence); | 848 | struct nouveau_fence *fence); |
849 | extern const struct ttm_mem_type_manager_func nouveau_vram_manager; | 849 | extern const struct ttm_mem_type_manager_func nouveau_vram_manager; |
850 | extern const struct ttm_mem_type_manager_func nouveau_gart_manager; | ||
850 | 851 | ||
851 | /* nouveau_notifier.c */ | 852 | /* nouveau_notifier.c */ |
852 | extern int nouveau_notifier_init_channel(struct nouveau_channel *); | 853 | extern int nouveau_notifier_init_channel(struct nouveau_channel *); |
@@ -1076,7 +1077,7 @@ extern void nv40_fb_set_tile_region(struct drm_device *dev, int i); | |||
1076 | /* nv50_fb.c */ | 1077 | /* nv50_fb.c */ |
1077 | extern int nv50_fb_init(struct drm_device *); | 1078 | extern int nv50_fb_init(struct drm_device *); |
1078 | extern void nv50_fb_takedown(struct drm_device *); | 1079 | extern void nv50_fb_takedown(struct drm_device *); |
1079 | extern void nv50_fb_vm_trap(struct drm_device *, int display, const char *); | 1080 | extern void nv50_fb_vm_trap(struct drm_device *, int display); |
1080 | 1081 | ||
1081 | /* nvc0_fb.c */ | 1082 | /* nvc0_fb.c */ |
1082 | extern int nvc0_fb_init(struct drm_device *); | 1083 | extern int nvc0_fb_init(struct drm_device *); |
@@ -1295,7 +1296,7 @@ extern struct ttm_bo_driver nouveau_bo_driver; | |||
1295 | extern int nouveau_bo_new(struct drm_device *, struct nouveau_channel *, | 1296 | extern int nouveau_bo_new(struct drm_device *, struct nouveau_channel *, |
1296 | int size, int align, uint32_t flags, | 1297 | int size, int align, uint32_t flags, |
1297 | uint32_t tile_mode, uint32_t tile_flags, | 1298 | uint32_t tile_mode, uint32_t tile_flags, |
1298 | bool no_vm, bool mappable, struct nouveau_bo **); | 1299 | struct nouveau_bo **); |
1299 | extern int nouveau_bo_pin(struct nouveau_bo *, uint32_t flags); | 1300 | extern int nouveau_bo_pin(struct nouveau_bo *, uint32_t flags); |
1300 | extern int nouveau_bo_unpin(struct nouveau_bo *); | 1301 | extern int nouveau_bo_unpin(struct nouveau_bo *); |
1301 | extern int nouveau_bo_map(struct nouveau_bo *); | 1302 | extern int nouveau_bo_map(struct nouveau_bo *); |
@@ -1356,9 +1357,9 @@ static inline struct nouveau_fence *nouveau_fence_ref(struct nouveau_fence *obj) | |||
1356 | 1357 | ||
1357 | /* nouveau_gem.c */ | 1358 | /* nouveau_gem.c */ |
1358 | extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *, | 1359 | extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *, |
1359 | int size, int align, uint32_t flags, | 1360 | int size, int align, uint32_t domain, |
1360 | uint32_t tile_mode, uint32_t tile_flags, | 1361 | uint32_t tile_mode, uint32_t tile_flags, |
1361 | bool no_vm, bool mappable, struct nouveau_bo **); | 1362 | struct nouveau_bo **); |
1362 | extern int nouveau_gem_object_new(struct drm_gem_object *); | 1363 | extern int nouveau_gem_object_new(struct drm_gem_object *); |
1363 | extern void nouveau_gem_object_del(struct drm_gem_object *); | 1364 | extern void nouveau_gem_object_del(struct drm_gem_object *); |
1364 | extern int nouveau_gem_ioctl_new(struct drm_device *, void *, | 1365 | extern int nouveau_gem_ioctl_new(struct drm_device *, void *, |
diff --git a/drivers/gpu/drm/nouveau/nouveau_fb.h b/drivers/gpu/drm/nouveau/nouveau_fb.h index d432134b71e..a3a88ad00f8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fb.h +++ b/drivers/gpu/drm/nouveau/nouveau_fb.h | |||
@@ -30,6 +30,9 @@ | |||
30 | struct nouveau_framebuffer { | 30 | struct nouveau_framebuffer { |
31 | struct drm_framebuffer base; | 31 | struct drm_framebuffer base; |
32 | struct nouveau_bo *nvbo; | 32 | struct nouveau_bo *nvbo; |
33 | u32 r_dma; | ||
34 | u32 r_format; | ||
35 | u32 r_pitch; | ||
33 | }; | 36 | }; |
34 | 37 | ||
35 | static inline struct nouveau_framebuffer * | 38 | static inline struct nouveau_framebuffer * |
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 60769d2f9a6..889c4454682 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c | |||
@@ -296,8 +296,8 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, | |||
296 | size = mode_cmd.pitch * mode_cmd.height; | 296 | size = mode_cmd.pitch * mode_cmd.height; |
297 | size = roundup(size, PAGE_SIZE); | 297 | size = roundup(size, PAGE_SIZE); |
298 | 298 | ||
299 | ret = nouveau_gem_new(dev, dev_priv->channel, size, 0, TTM_PL_FLAG_VRAM, | 299 | ret = nouveau_gem_new(dev, dev_priv->channel, size, 0, |
300 | 0, 0x0000, false, true, &nvbo); | 300 | NOUVEAU_GEM_DOMAIN_VRAM, 0, 0x0000, &nvbo); |
301 | if (ret) { | 301 | if (ret) { |
302 | NV_ERROR(dev, "failed to allocate framebuffer\n"); | 302 | NV_ERROR(dev, "failed to allocate framebuffer\n"); |
303 | goto out; | 303 | goto out; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 221b8462ea3..4b9f4493c9f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c | |||
@@ -27,13 +27,15 @@ | |||
27 | #include "drmP.h" | 27 | #include "drmP.h" |
28 | #include "drm.h" | 28 | #include "drm.h" |
29 | 29 | ||
30 | #include <linux/ktime.h> | ||
31 | #include <linux/hrtimer.h> | ||
32 | |||
30 | #include "nouveau_drv.h" | 33 | #include "nouveau_drv.h" |
31 | #include "nouveau_ramht.h" | 34 | #include "nouveau_ramht.h" |
32 | #include "nouveau_dma.h" | 35 | #include "nouveau_dma.h" |
33 | 36 | ||
34 | #define USE_REFCNT(dev) (nouveau_private(dev)->chipset >= 0x10) | 37 | #define USE_REFCNT(dev) (nouveau_private(dev)->chipset >= 0x10) |
35 | #define USE_SEMA(dev) (nouveau_private(dev)->chipset >= 0x17 && \ | 38 | #define USE_SEMA(dev) (nouveau_private(dev)->chipset >= 0x17) |
36 | nouveau_private(dev)->card_type < NV_C0) | ||
37 | 39 | ||
38 | struct nouveau_fence { | 40 | struct nouveau_fence { |
39 | struct nouveau_channel *channel; | 41 | struct nouveau_channel *channel; |
@@ -230,7 +232,8 @@ int | |||
230 | __nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) | 232 | __nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) |
231 | { | 233 | { |
232 | unsigned long timeout = jiffies + (3 * DRM_HZ); | 234 | unsigned long timeout = jiffies + (3 * DRM_HZ); |
233 | unsigned long sleep_time = jiffies + 1; | 235 | unsigned long sleep_time = NSEC_PER_MSEC / 1000; |
236 | ktime_t t; | ||
234 | int ret = 0; | 237 | int ret = 0; |
235 | 238 | ||
236 | while (1) { | 239 | while (1) { |
@@ -244,8 +247,13 @@ __nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) | |||
244 | 247 | ||
245 | __set_current_state(intr ? TASK_INTERRUPTIBLE | 248 | __set_current_state(intr ? TASK_INTERRUPTIBLE |
246 | : TASK_UNINTERRUPTIBLE); | 249 | : TASK_UNINTERRUPTIBLE); |
247 | if (lazy && time_after_eq(jiffies, sleep_time)) | 250 | if (lazy) { |
248 | schedule_timeout(1); | 251 | t = ktime_set(0, sleep_time); |
252 | schedule_hrtimeout(&t, HRTIMER_MODE_REL); | ||
253 | sleep_time *= 2; | ||
254 | if (sleep_time > NSEC_PER_MSEC) | ||
255 | sleep_time = NSEC_PER_MSEC; | ||
256 | } | ||
249 | 257 | ||
250 | if (intr && signal_pending(current)) { | 258 | if (intr && signal_pending(current)) { |
251 | ret = -ERESTARTSYS; | 259 | ret = -ERESTARTSYS; |
@@ -259,11 +267,12 @@ __nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) | |||
259 | } | 267 | } |
260 | 268 | ||
261 | static struct nouveau_semaphore * | 269 | static struct nouveau_semaphore * |
262 | alloc_semaphore(struct drm_device *dev) | 270 | semaphore_alloc(struct drm_device *dev) |
263 | { | 271 | { |
264 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 272 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
265 | struct nouveau_semaphore *sema; | 273 | struct nouveau_semaphore *sema; |
266 | int ret; | 274 | int size = (dev_priv->chipset < 0x84) ? 4 : 16; |
275 | int ret, i; | ||
267 | 276 | ||
268 | if (!USE_SEMA(dev)) | 277 | if (!USE_SEMA(dev)) |
269 | return NULL; | 278 | return NULL; |
@@ -277,9 +286,9 @@ alloc_semaphore(struct drm_device *dev) | |||
277 | goto fail; | 286 | goto fail; |
278 | 287 | ||
279 | spin_lock(&dev_priv->fence.lock); | 288 | spin_lock(&dev_priv->fence.lock); |
280 | sema->mem = drm_mm_search_free(&dev_priv->fence.heap, 4, 0, 0); | 289 | sema->mem = drm_mm_search_free(&dev_priv->fence.heap, size, 0, 0); |
281 | if (sema->mem) | 290 | if (sema->mem) |
282 | sema->mem = drm_mm_get_block_atomic(sema->mem, 4, 0); | 291 | sema->mem = drm_mm_get_block_atomic(sema->mem, size, 0); |
283 | spin_unlock(&dev_priv->fence.lock); | 292 | spin_unlock(&dev_priv->fence.lock); |
284 | 293 | ||
285 | if (!sema->mem) | 294 | if (!sema->mem) |
@@ -287,7 +296,8 @@ alloc_semaphore(struct drm_device *dev) | |||
287 | 296 | ||
288 | kref_init(&sema->ref); | 297 | kref_init(&sema->ref); |
289 | sema->dev = dev; | 298 | sema->dev = dev; |
290 | nouveau_bo_wr32(dev_priv->fence.bo, sema->mem->start / 4, 0); | 299 | for (i = sema->mem->start; i < sema->mem->start + size; i += 4) |
300 | nouveau_bo_wr32(dev_priv->fence.bo, i / 4, 0); | ||
291 | 301 | ||
292 | return sema; | 302 | return sema; |
293 | fail: | 303 | fail: |
@@ -296,7 +306,7 @@ fail: | |||
296 | } | 306 | } |
297 | 307 | ||
298 | static void | 308 | static void |
299 | free_semaphore(struct kref *ref) | 309 | semaphore_free(struct kref *ref) |
300 | { | 310 | { |
301 | struct nouveau_semaphore *sema = | 311 | struct nouveau_semaphore *sema = |
302 | container_of(ref, struct nouveau_semaphore, ref); | 312 | container_of(ref, struct nouveau_semaphore, ref); |
@@ -318,61 +328,107 @@ semaphore_work(void *priv, bool signalled) | |||
318 | if (unlikely(!signalled)) | 328 | if (unlikely(!signalled)) |
319 | nouveau_bo_wr32(dev_priv->fence.bo, sema->mem->start / 4, 1); | 329 | nouveau_bo_wr32(dev_priv->fence.bo, sema->mem->start / 4, 1); |
320 | 330 | ||
321 | kref_put(&sema->ref, free_semaphore); | 331 | kref_put(&sema->ref, semaphore_free); |
322 | } | 332 | } |
323 | 333 | ||
324 | static int | 334 | static int |
325 | emit_semaphore(struct nouveau_channel *chan, int method, | 335 | semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema) |
326 | struct nouveau_semaphore *sema) | ||
327 | { | 336 | { |
328 | struct drm_nouveau_private *dev_priv = sema->dev->dev_private; | 337 | struct drm_nouveau_private *dev_priv = chan->dev->dev_private; |
329 | struct nouveau_fence *fence; | 338 | struct nouveau_fence *fence = NULL; |
330 | bool smart = (dev_priv->card_type >= NV_50); | ||
331 | int ret; | 339 | int ret; |
332 | 340 | ||
333 | ret = RING_SPACE(chan, smart ? 8 : 4); | 341 | if (dev_priv->chipset < 0x84) { |
342 | ret = RING_SPACE(chan, 3); | ||
343 | if (ret) | ||
344 | return ret; | ||
345 | |||
346 | BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 2); | ||
347 | OUT_RING (chan, sema->mem->start); | ||
348 | OUT_RING (chan, 1); | ||
349 | } else | ||
350 | if (dev_priv->chipset < 0xc0) { | ||
351 | struct nouveau_vma *vma = &dev_priv->fence.bo->vma; | ||
352 | u64 offset = vma->offset + sema->mem->start; | ||
353 | |||
354 | ret = RING_SPACE(chan, 5); | ||
355 | if (ret) | ||
356 | return ret; | ||
357 | |||
358 | BEGIN_RING(chan, NvSubSw, 0x0010, 4); | ||
359 | OUT_RING (chan, upper_32_bits(offset)); | ||
360 | OUT_RING (chan, lower_32_bits(offset)); | ||
361 | OUT_RING (chan, 1); | ||
362 | OUT_RING (chan, 1); /* ACQUIRE_EQ */ | ||
363 | } else { | ||
364 | struct nouveau_vma *vma = &dev_priv->fence.bo->vma; | ||
365 | u64 offset = vma->offset + sema->mem->start; | ||
366 | |||
367 | ret = RING_SPACE(chan, 5); | ||
368 | if (ret) | ||
369 | return ret; | ||
370 | |||
371 | BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); | ||
372 | OUT_RING (chan, upper_32_bits(offset)); | ||
373 | OUT_RING (chan, lower_32_bits(offset)); | ||
374 | OUT_RING (chan, 1); | ||
375 | OUT_RING (chan, 0x1001); /* ACQUIRE_EQ */ | ||
376 | } | ||
377 | |||
378 | /* Delay semaphore destruction until its work is done */ | ||
379 | ret = nouveau_fence_new(chan, &fence, true); | ||
334 | if (ret) | 380 | if (ret) |
335 | return ret; | 381 | return ret; |
336 | 382 | ||
337 | if (smart) { | 383 | kref_get(&sema->ref); |
338 | BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); | 384 | nouveau_fence_work(fence, semaphore_work, sema); |
339 | OUT_RING(chan, NvSema); | 385 | nouveau_fence_unref(&fence); |
340 | } | 386 | return 0; |
341 | BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 1); | 387 | } |
342 | OUT_RING(chan, sema->mem->start); | 388 | |
343 | 389 | static int | |
344 | if (smart && method == NV_SW_SEMAPHORE_ACQUIRE) { | 390 | semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema) |
345 | /* | 391 | { |
346 | * NV50 tries to be too smart and context-switch | 392 | struct drm_nouveau_private *dev_priv = chan->dev->dev_private; |
347 | * between semaphores instead of doing a "first come, | 393 | struct nouveau_fence *fence = NULL; |
348 | * first served" strategy like previous cards | 394 | int ret; |
349 | * do. | 395 | |
350 | * | 396 | if (dev_priv->chipset < 0x84) { |
351 | * That's bad because the ACQUIRE latency can get as | 397 | ret = RING_SPACE(chan, 4); |
352 | * large as the PFIFO context time slice in the | 398 | if (ret) |
353 | * typical DRI2 case where you have several | 399 | return ret; |
354 | * outstanding semaphores at the same moment. | 400 | |
355 | * | 401 | BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 1); |
356 | * If we're going to ACQUIRE, force the card to | 402 | OUT_RING (chan, sema->mem->start); |
357 | * context switch before, just in case the matching | 403 | BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_RELEASE, 1); |
358 | * RELEASE is already scheduled to be executed in | 404 | OUT_RING (chan, 1); |
359 | * another channel. | 405 | } else |
360 | */ | 406 | if (dev_priv->chipset < 0xc0) { |
361 | BEGIN_RING(chan, NvSubSw, NV_SW_YIELD, 1); | 407 | struct nouveau_vma *vma = &dev_priv->fence.bo->vma; |
362 | OUT_RING(chan, 0); | 408 | u64 offset = vma->offset + sema->mem->start; |
363 | } | 409 | |
410 | ret = RING_SPACE(chan, 5); | ||
411 | if (ret) | ||
412 | return ret; | ||
413 | |||
414 | BEGIN_RING(chan, NvSubSw, 0x0010, 4); | ||
415 | OUT_RING (chan, upper_32_bits(offset)); | ||
416 | OUT_RING (chan, lower_32_bits(offset)); | ||
417 | OUT_RING (chan, 1); | ||
418 | OUT_RING (chan, 2); /* RELEASE */ | ||
419 | } else { | ||
420 | struct nouveau_vma *vma = &dev_priv->fence.bo->vma; | ||
421 | u64 offset = vma->offset + sema->mem->start; | ||
364 | 422 | ||
365 | BEGIN_RING(chan, NvSubSw, method, 1); | 423 | ret = RING_SPACE(chan, 5); |
366 | OUT_RING(chan, 1); | 424 | if (ret) |
367 | 425 | return ret; | |
368 | if (smart && method == NV_SW_SEMAPHORE_RELEASE) { | 426 | |
369 | /* | 427 | BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); |
370 | * Force the card to context switch, there may be | 428 | OUT_RING (chan, upper_32_bits(offset)); |
371 | * another channel waiting for the semaphore we just | 429 | OUT_RING (chan, lower_32_bits(offset)); |
372 | * released. | 430 | OUT_RING (chan, 1); |
373 | */ | 431 | OUT_RING (chan, 0x1002); /* RELEASE */ |
374 | BEGIN_RING(chan, NvSubSw, NV_SW_YIELD, 1); | ||
375 | OUT_RING(chan, 0); | ||
376 | } | 432 | } |
377 | 433 | ||
378 | /* Delay semaphore destruction until its work is done */ | 434 | /* Delay semaphore destruction until its work is done */ |
@@ -383,7 +439,6 @@ emit_semaphore(struct nouveau_channel *chan, int method, | |||
383 | kref_get(&sema->ref); | 439 | kref_get(&sema->ref); |
384 | nouveau_fence_work(fence, semaphore_work, sema); | 440 | nouveau_fence_work(fence, semaphore_work, sema); |
385 | nouveau_fence_unref(&fence); | 441 | nouveau_fence_unref(&fence); |
386 | |||
387 | return 0; | 442 | return 0; |
388 | } | 443 | } |
389 | 444 | ||
@@ -400,7 +455,7 @@ nouveau_fence_sync(struct nouveau_fence *fence, | |||
400 | nouveau_fence_signalled(fence))) | 455 | nouveau_fence_signalled(fence))) |
401 | goto out; | 456 | goto out; |
402 | 457 | ||
403 | sema = alloc_semaphore(dev); | 458 | sema = semaphore_alloc(dev); |
404 | if (!sema) { | 459 | if (!sema) { |
405 | /* Early card or broken userspace, fall back to | 460 | /* Early card or broken userspace, fall back to |
406 | * software sync. */ | 461 | * software sync. */ |
@@ -418,17 +473,17 @@ nouveau_fence_sync(struct nouveau_fence *fence, | |||
418 | } | 473 | } |
419 | 474 | ||
420 | /* Make wchan wait until it gets signalled */ | 475 | /* Make wchan wait until it gets signalled */ |
421 | ret = emit_semaphore(wchan, NV_SW_SEMAPHORE_ACQUIRE, sema); | 476 | ret = semaphore_acquire(wchan, sema); |
422 | if (ret) | 477 | if (ret) |
423 | goto out_unlock; | 478 | goto out_unlock; |
424 | 479 | ||
425 | /* Signal the semaphore from chan */ | 480 | /* Signal the semaphore from chan */ |
426 | ret = emit_semaphore(chan, NV_SW_SEMAPHORE_RELEASE, sema); | 481 | ret = semaphore_release(chan, sema); |
427 | 482 | ||
428 | out_unlock: | 483 | out_unlock: |
429 | mutex_unlock(&chan->mutex); | 484 | mutex_unlock(&chan->mutex); |
430 | out_unref: | 485 | out_unref: |
431 | kref_put(&sema->ref, free_semaphore); | 486 | kref_put(&sema->ref, semaphore_free); |
432 | out: | 487 | out: |
433 | if (chan) | 488 | if (chan) |
434 | nouveau_channel_put_unlocked(&chan); | 489 | nouveau_channel_put_unlocked(&chan); |
@@ -449,22 +504,23 @@ nouveau_fence_channel_init(struct nouveau_channel *chan) | |||
449 | struct nouveau_gpuobj *obj = NULL; | 504 | struct nouveau_gpuobj *obj = NULL; |
450 | int ret; | 505 | int ret; |
451 | 506 | ||
507 | if (dev_priv->card_type >= NV_C0) | ||
508 | goto out_initialised; | ||
509 | |||
452 | /* Create an NV_SW object for various sync purposes */ | 510 | /* Create an NV_SW object for various sync purposes */ |
453 | ret = nouveau_gpuobj_gr_new(chan, NvSw, NV_SW); | 511 | ret = nouveau_gpuobj_gr_new(chan, NvSw, NV_SW); |
454 | if (ret) | 512 | if (ret) |
455 | return ret; | 513 | return ret; |
456 | 514 | ||
457 | /* we leave subchannel empty for nvc0 */ | 515 | /* we leave subchannel empty for nvc0 */ |
458 | if (dev_priv->card_type < NV_C0) { | 516 | ret = RING_SPACE(chan, 2); |
459 | ret = RING_SPACE(chan, 2); | 517 | if (ret) |
460 | if (ret) | 518 | return ret; |
461 | return ret; | 519 | BEGIN_RING(chan, NvSubSw, 0, 1); |
462 | BEGIN_RING(chan, NvSubSw, 0, 1); | 520 | OUT_RING(chan, NvSw); |
463 | OUT_RING(chan, NvSw); | ||
464 | } | ||
465 | 521 | ||
466 | /* Create a DMA object for the shared cross-channel sync area. */ | 522 | /* Create a DMA object for the shared cross-channel sync area. */ |
467 | if (USE_SEMA(dev)) { | 523 | if (USE_SEMA(dev) && dev_priv->chipset < 0x84) { |
468 | struct ttm_mem_reg *mem = &dev_priv->fence.bo->bo.mem; | 524 | struct ttm_mem_reg *mem = &dev_priv->fence.bo->bo.mem; |
469 | 525 | ||
470 | ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, | 526 | ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, |
@@ -484,14 +540,20 @@ nouveau_fence_channel_init(struct nouveau_channel *chan) | |||
484 | return ret; | 540 | return ret; |
485 | BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); | 541 | BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); |
486 | OUT_RING(chan, NvSema); | 542 | OUT_RING(chan, NvSema); |
543 | } else { | ||
544 | ret = RING_SPACE(chan, 2); | ||
545 | if (ret) | ||
546 | return ret; | ||
547 | BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); | ||
548 | OUT_RING (chan, chan->vram_handle); /* whole VM */ | ||
487 | } | 549 | } |
488 | 550 | ||
489 | FIRE_RING(chan); | 551 | FIRE_RING(chan); |
490 | 552 | ||
553 | out_initialised: | ||
491 | INIT_LIST_HEAD(&chan->fence.pending); | 554 | INIT_LIST_HEAD(&chan->fence.pending); |
492 | spin_lock_init(&chan->fence.lock); | 555 | spin_lock_init(&chan->fence.lock); |
493 | atomic_set(&chan->fence.last_sequence_irq, 0); | 556 | atomic_set(&chan->fence.last_sequence_irq, 0); |
494 | |||
495 | return 0; | 557 | return 0; |
496 | } | 558 | } |
497 | 559 | ||
@@ -519,12 +581,13 @@ int | |||
519 | nouveau_fence_init(struct drm_device *dev) | 581 | nouveau_fence_init(struct drm_device *dev) |
520 | { | 582 | { |
521 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 583 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
584 | int size = (dev_priv->chipset < 0x84) ? 4096 : 16384; | ||
522 | int ret; | 585 | int ret; |
523 | 586 | ||
524 | /* Create a shared VRAM heap for cross-channel sync. */ | 587 | /* Create a shared VRAM heap for cross-channel sync. */ |
525 | if (USE_SEMA(dev)) { | 588 | if (USE_SEMA(dev)) { |
526 | ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, | 589 | ret = nouveau_bo_new(dev, NULL, size, 0, TTM_PL_FLAG_VRAM, |
527 | 0, 0, false, true, &dev_priv->fence.bo); | 590 | 0, 0, &dev_priv->fence.bo); |
528 | if (ret) | 591 | if (ret) |
529 | return ret; | 592 | return ret; |
530 | 593 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 506c508b7ed..e8b04f4aed7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c | |||
@@ -61,19 +61,36 @@ nouveau_gem_object_del(struct drm_gem_object *gem) | |||
61 | 61 | ||
62 | int | 62 | int |
63 | nouveau_gem_new(struct drm_device *dev, struct nouveau_channel *chan, | 63 | nouveau_gem_new(struct drm_device *dev, struct nouveau_channel *chan, |
64 | int size, int align, uint32_t flags, uint32_t tile_mode, | 64 | int size, int align, uint32_t domain, uint32_t tile_mode, |
65 | uint32_t tile_flags, bool no_vm, bool mappable, | 65 | uint32_t tile_flags, struct nouveau_bo **pnvbo) |
66 | struct nouveau_bo **pnvbo) | ||
67 | { | 66 | { |
67 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
68 | struct nouveau_bo *nvbo; | 68 | struct nouveau_bo *nvbo; |
69 | u32 flags = 0; | ||
69 | int ret; | 70 | int ret; |
70 | 71 | ||
72 | if (domain & NOUVEAU_GEM_DOMAIN_VRAM) | ||
73 | flags |= TTM_PL_FLAG_VRAM; | ||
74 | if (domain & NOUVEAU_GEM_DOMAIN_GART) | ||
75 | flags |= TTM_PL_FLAG_TT; | ||
76 | if (!flags || domain & NOUVEAU_GEM_DOMAIN_CPU) | ||
77 | flags |= TTM_PL_FLAG_SYSTEM; | ||
78 | |||
71 | ret = nouveau_bo_new(dev, chan, size, align, flags, tile_mode, | 79 | ret = nouveau_bo_new(dev, chan, size, align, flags, tile_mode, |
72 | tile_flags, no_vm, mappable, pnvbo); | 80 | tile_flags, pnvbo); |
73 | if (ret) | 81 | if (ret) |
74 | return ret; | 82 | return ret; |
75 | nvbo = *pnvbo; | 83 | nvbo = *pnvbo; |
76 | 84 | ||
85 | /* we restrict allowed domains on nv50+ to only the types | ||
86 | * that were requested at creation time. not possibly on | ||
87 | * earlier chips without busting the ABI. | ||
88 | */ | ||
89 | nvbo->valid_domains = NOUVEAU_GEM_DOMAIN_VRAM | | ||
90 | NOUVEAU_GEM_DOMAIN_GART; | ||
91 | if (dev_priv->card_type >= NV_50) | ||
92 | nvbo->valid_domains &= domain; | ||
93 | |||
77 | nvbo->gem = drm_gem_object_alloc(dev, nvbo->bo.mem.size); | 94 | nvbo->gem = drm_gem_object_alloc(dev, nvbo->bo.mem.size); |
78 | if (!nvbo->gem) { | 95 | if (!nvbo->gem) { |
79 | nouveau_bo_ref(NULL, pnvbo); | 96 | nouveau_bo_ref(NULL, pnvbo); |
@@ -97,7 +114,7 @@ nouveau_gem_info(struct drm_gem_object *gem, struct drm_nouveau_gem_info *rep) | |||
97 | 114 | ||
98 | rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT; | 115 | rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT; |
99 | rep->offset = nvbo->bo.offset; | 116 | rep->offset = nvbo->bo.offset; |
100 | rep->map_handle = nvbo->mappable ? nvbo->bo.addr_space_offset : 0; | 117 | rep->map_handle = nvbo->bo.addr_space_offset; |
101 | rep->tile_mode = nvbo->tile_mode; | 118 | rep->tile_mode = nvbo->tile_mode; |
102 | rep->tile_flags = nvbo->tile_flags; | 119 | rep->tile_flags = nvbo->tile_flags; |
103 | return 0; | 120 | return 0; |
@@ -111,19 +128,11 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, | |||
111 | struct drm_nouveau_gem_new *req = data; | 128 | struct drm_nouveau_gem_new *req = data; |
112 | struct nouveau_bo *nvbo = NULL; | 129 | struct nouveau_bo *nvbo = NULL; |
113 | struct nouveau_channel *chan = NULL; | 130 | struct nouveau_channel *chan = NULL; |
114 | uint32_t flags = 0; | ||
115 | int ret = 0; | 131 | int ret = 0; |
116 | 132 | ||
117 | if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL)) | 133 | if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL)) |
118 | dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping; | 134 | dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping; |
119 | 135 | ||
120 | if (req->info.domain & NOUVEAU_GEM_DOMAIN_VRAM) | ||
121 | flags |= TTM_PL_FLAG_VRAM; | ||
122 | if (req->info.domain & NOUVEAU_GEM_DOMAIN_GART) | ||
123 | flags |= TTM_PL_FLAG_TT; | ||
124 | if (!flags || req->info.domain & NOUVEAU_GEM_DOMAIN_CPU) | ||
125 | flags |= TTM_PL_FLAG_SYSTEM; | ||
126 | |||
127 | if (!dev_priv->engine.vram.flags_valid(dev, req->info.tile_flags)) { | 136 | if (!dev_priv->engine.vram.flags_valid(dev, req->info.tile_flags)) { |
128 | NV_ERROR(dev, "bad page flags: 0x%08x\n", req->info.tile_flags); | 137 | NV_ERROR(dev, "bad page flags: 0x%08x\n", req->info.tile_flags); |
129 | return -EINVAL; | 138 | return -EINVAL; |
@@ -135,10 +144,9 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, | |||
135 | return PTR_ERR(chan); | 144 | return PTR_ERR(chan); |
136 | } | 145 | } |
137 | 146 | ||
138 | ret = nouveau_gem_new(dev, chan, req->info.size, req->align, flags, | 147 | ret = nouveau_gem_new(dev, chan, req->info.size, req->align, |
139 | req->info.tile_mode, req->info.tile_flags, false, | 148 | req->info.domain, req->info.tile_mode, |
140 | (req->info.domain & NOUVEAU_GEM_DOMAIN_MAPPABLE), | 149 | req->info.tile_flags, &nvbo); |
141 | &nvbo); | ||
142 | if (chan) | 150 | if (chan) |
143 | nouveau_channel_put(&chan); | 151 | nouveau_channel_put(&chan); |
144 | if (ret) | 152 | if (ret) |
@@ -161,7 +169,7 @@ nouveau_gem_set_domain(struct drm_gem_object *gem, uint32_t read_domains, | |||
161 | { | 169 | { |
162 | struct nouveau_bo *nvbo = gem->driver_private; | 170 | struct nouveau_bo *nvbo = gem->driver_private; |
163 | struct ttm_buffer_object *bo = &nvbo->bo; | 171 | struct ttm_buffer_object *bo = &nvbo->bo; |
164 | uint32_t domains = valid_domains & | 172 | uint32_t domains = valid_domains & nvbo->valid_domains & |
165 | (write_domains ? write_domains : read_domains); | 173 | (write_domains ? write_domains : read_domains); |
166 | uint32_t pref_flags = 0, valid_flags = 0; | 174 | uint32_t pref_flags = 0, valid_flags = 0; |
167 | 175 | ||
@@ -592,7 +600,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, | |||
592 | if (push[i].bo_index >= req->nr_buffers) { | 600 | if (push[i].bo_index >= req->nr_buffers) { |
593 | NV_ERROR(dev, "push %d buffer not in list\n", i); | 601 | NV_ERROR(dev, "push %d buffer not in list\n", i); |
594 | ret = -EINVAL; | 602 | ret = -EINVAL; |
595 | goto out; | 603 | goto out_prevalid; |
596 | } | 604 | } |
597 | 605 | ||
598 | bo[push[i].bo_index].read_domains |= (1 << 31); | 606 | bo[push[i].bo_index].read_domains |= (1 << 31); |
@@ -604,7 +612,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, | |||
604 | if (ret) { | 612 | if (ret) { |
605 | if (ret != -ERESTARTSYS) | 613 | if (ret != -ERESTARTSYS) |
606 | NV_ERROR(dev, "validate: %d\n", ret); | 614 | NV_ERROR(dev, "validate: %d\n", ret); |
607 | goto out; | 615 | goto out_prevalid; |
608 | } | 616 | } |
609 | 617 | ||
610 | /* Apply any relocations that are required */ | 618 | /* Apply any relocations that are required */ |
@@ -697,6 +705,8 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, | |||
697 | out: | 705 | out: |
698 | validate_fini(&op, fence); | 706 | validate_fini(&op, fence); |
699 | nouveau_fence_unref(&fence); | 707 | nouveau_fence_unref(&fence); |
708 | |||
709 | out_prevalid: | ||
700 | kfree(bo); | 710 | kfree(bo); |
701 | kfree(push); | 711 | kfree(push); |
702 | 712 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index b0fb9bdcddb..2683377f413 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c | |||
@@ -152,7 +152,6 @@ nouveau_mem_vram_fini(struct drm_device *dev) | |||
152 | { | 152 | { |
153 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 153 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
154 | 154 | ||
155 | nouveau_bo_unpin(dev_priv->vga_ram); | ||
156 | nouveau_bo_ref(NULL, &dev_priv->vga_ram); | 155 | nouveau_bo_ref(NULL, &dev_priv->vga_ram); |
157 | 156 | ||
158 | ttm_bo_device_release(&dev_priv->ttm.bdev); | 157 | ttm_bo_device_release(&dev_priv->ttm.bdev); |
@@ -393,11 +392,17 @@ nouveau_mem_vram_init(struct drm_device *dev) | |||
393 | struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; | 392 | struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; |
394 | int ret, dma_bits; | 393 | int ret, dma_bits; |
395 | 394 | ||
396 | if (dev_priv->card_type >= NV_50 && | 395 | dma_bits = 32; |
397 | pci_dma_supported(dev->pdev, DMA_BIT_MASK(40))) | 396 | if (dev_priv->card_type >= NV_50) { |
398 | dma_bits = 40; | 397 | if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(40))) |
399 | else | 398 | dma_bits = 40; |
400 | dma_bits = 32; | 399 | } else |
400 | if (drm_pci_device_is_pcie(dev) && | ||
401 | dev_priv->chipset != 0x40 && | ||
402 | dev_priv->chipset != 0x45) { | ||
403 | if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(39))) | ||
404 | dma_bits = 39; | ||
405 | } | ||
401 | 406 | ||
402 | ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(dma_bits)); | 407 | ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(dma_bits)); |
403 | if (ret) | 408 | if (ret) |
@@ -419,14 +424,32 @@ nouveau_mem_vram_init(struct drm_device *dev) | |||
419 | } | 424 | } |
420 | 425 | ||
421 | /* reserve space at end of VRAM for PRAMIN */ | 426 | /* reserve space at end of VRAM for PRAMIN */ |
422 | if (dev_priv->chipset == 0x40 || dev_priv->chipset == 0x47 || | 427 | if (dev_priv->card_type >= NV_50) { |
423 | dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b) | 428 | dev_priv->ramin_rsvd_vram = 1 * 1024 * 1024; |
424 | dev_priv->ramin_rsvd_vram = (2 * 1024 * 1024); | 429 | } else |
425 | else | 430 | if (dev_priv->card_type >= NV_40) { |
426 | if (dev_priv->card_type >= NV_40) | 431 | u32 vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8); |
427 | dev_priv->ramin_rsvd_vram = (1 * 1024 * 1024); | 432 | u32 rsvd; |
428 | else | 433 | |
429 | dev_priv->ramin_rsvd_vram = (512 * 1024); | 434 | /* estimate grctx size, the magics come from nv40_grctx.c */ |
435 | if (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs; | ||
436 | else if (dev_priv->chipset < 0x43) rsvd = 0x4f00 * vs; | ||
437 | else if (nv44_graph_class(dev)) rsvd = 0x4980 * vs; | ||
438 | else rsvd = 0x4a40 * vs; | ||
439 | rsvd += 16 * 1024; | ||
440 | rsvd *= dev_priv->engine.fifo.channels; | ||
441 | |||
442 | /* pciegart table */ | ||
443 | if (drm_pci_device_is_pcie(dev)) | ||
444 | rsvd += 512 * 1024; | ||
445 | |||
446 | /* object storage */ | ||
447 | rsvd += 512 * 1024; | ||
448 | |||
449 | dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096); | ||
450 | } else { | ||
451 | dev_priv->ramin_rsvd_vram = 512 * 1024; | ||
452 | } | ||
430 | 453 | ||
431 | ret = dev_priv->engine.vram.init(dev); | 454 | ret = dev_priv->engine.vram.init(dev); |
432 | if (ret) | 455 | if (ret) |
@@ -455,13 +478,17 @@ nouveau_mem_vram_init(struct drm_device *dev) | |||
455 | return ret; | 478 | return ret; |
456 | } | 479 | } |
457 | 480 | ||
458 | ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM, | 481 | if (dev_priv->card_type < NV_50) { |
459 | 0, 0, true, true, &dev_priv->vga_ram); | 482 | ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM, |
460 | if (ret == 0) | 483 | 0, 0, &dev_priv->vga_ram); |
461 | ret = nouveau_bo_pin(dev_priv->vga_ram, TTM_PL_FLAG_VRAM); | 484 | if (ret == 0) |
462 | if (ret) { | 485 | ret = nouveau_bo_pin(dev_priv->vga_ram, |
463 | NV_WARN(dev, "failed to reserve VGA memory\n"); | 486 | TTM_PL_FLAG_VRAM); |
464 | nouveau_bo_ref(NULL, &dev_priv->vga_ram); | 487 | |
488 | if (ret) { | ||
489 | NV_WARN(dev, "failed to reserve VGA memory\n"); | ||
490 | nouveau_bo_ref(NULL, &dev_priv->vga_ram); | ||
491 | } | ||
465 | } | 492 | } |
466 | 493 | ||
467 | dev_priv->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 1), | 494 | dev_priv->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 1), |
@@ -480,7 +507,7 @@ nouveau_mem_gart_init(struct drm_device *dev) | |||
480 | dev_priv->gart_info.type = NOUVEAU_GART_NONE; | 507 | dev_priv->gart_info.type = NOUVEAU_GART_NONE; |
481 | 508 | ||
482 | #if !defined(__powerpc__) && !defined(__ia64__) | 509 | #if !defined(__powerpc__) && !defined(__ia64__) |
483 | if (drm_device_is_agp(dev) && dev->agp && nouveau_agpmode) { | 510 | if (drm_pci_device_is_agp(dev) && dev->agp && nouveau_agpmode) { |
484 | ret = nouveau_mem_init_agp(dev); | 511 | ret = nouveau_mem_init_agp(dev); |
485 | if (ret) | 512 | if (ret) |
486 | NV_ERROR(dev, "Error initialising AGP: %d\n", ret); | 513 | NV_ERROR(dev, "Error initialising AGP: %d\n", ret); |
@@ -666,13 +693,14 @@ nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long p_size | |||
666 | { | 693 | { |
667 | struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); | 694 | struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); |
668 | struct nouveau_mm *mm; | 695 | struct nouveau_mm *mm; |
669 | u32 b_size; | 696 | u64 size, block, rsvd; |
670 | int ret; | 697 | int ret; |
671 | 698 | ||
672 | p_size = (p_size << PAGE_SHIFT) >> 12; | 699 | rsvd = (256 * 1024); /* vga memory */ |
673 | b_size = dev_priv->vram_rblock_size >> 12; | 700 | size = (p_size << PAGE_SHIFT) - rsvd; |
701 | block = dev_priv->vram_rblock_size; | ||
674 | 702 | ||
675 | ret = nouveau_mm_init(&mm, 0, p_size, b_size); | 703 | ret = nouveau_mm_init(&mm, rsvd >> 12, size >> 12, block >> 12); |
676 | if (ret) | 704 | if (ret) |
677 | return ret; | 705 | return ret; |
678 | 706 | ||
@@ -700,9 +728,15 @@ nouveau_vram_manager_del(struct ttm_mem_type_manager *man, | |||
700 | { | 728 | { |
701 | struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); | 729 | struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); |
702 | struct nouveau_vram_engine *vram = &dev_priv->engine.vram; | 730 | struct nouveau_vram_engine *vram = &dev_priv->engine.vram; |
731 | struct nouveau_mem *node = mem->mm_node; | ||
703 | struct drm_device *dev = dev_priv->dev; | 732 | struct drm_device *dev = dev_priv->dev; |
704 | 733 | ||
705 | vram->put(dev, (struct nouveau_vram **)&mem->mm_node); | 734 | if (node->tmp_vma.node) { |
735 | nouveau_vm_unmap(&node->tmp_vma); | ||
736 | nouveau_vm_put(&node->tmp_vma); | ||
737 | } | ||
738 | |||
739 | vram->put(dev, (struct nouveau_mem **)&mem->mm_node); | ||
706 | } | 740 | } |
707 | 741 | ||
708 | static int | 742 | static int |
@@ -715,7 +749,7 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, | |||
715 | struct nouveau_vram_engine *vram = &dev_priv->engine.vram; | 749 | struct nouveau_vram_engine *vram = &dev_priv->engine.vram; |
716 | struct drm_device *dev = dev_priv->dev; | 750 | struct drm_device *dev = dev_priv->dev; |
717 | struct nouveau_bo *nvbo = nouveau_bo(bo); | 751 | struct nouveau_bo *nvbo = nouveau_bo(bo); |
718 | struct nouveau_vram *node; | 752 | struct nouveau_mem *node; |
719 | u32 size_nc = 0; | 753 | u32 size_nc = 0; |
720 | int ret; | 754 | int ret; |
721 | 755 | ||
@@ -724,7 +758,7 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, | |||
724 | 758 | ||
725 | ret = vram->get(dev, mem->num_pages << PAGE_SHIFT, | 759 | ret = vram->get(dev, mem->num_pages << PAGE_SHIFT, |
726 | mem->page_alignment << PAGE_SHIFT, size_nc, | 760 | mem->page_alignment << PAGE_SHIFT, size_nc, |
727 | (nvbo->tile_flags >> 8) & 0xff, &node); | 761 | (nvbo->tile_flags >> 8) & 0x3ff, &node); |
728 | if (ret) { | 762 | if (ret) { |
729 | mem->mm_node = NULL; | 763 | mem->mm_node = NULL; |
730 | return (ret == -ENOSPC) ? 0 : ret; | 764 | return (ret == -ENOSPC) ? 0 : ret; |
@@ -771,3 +805,84 @@ const struct ttm_mem_type_manager_func nouveau_vram_manager = { | |||
771 | nouveau_vram_manager_del, | 805 | nouveau_vram_manager_del, |
772 | nouveau_vram_manager_debug | 806 | nouveau_vram_manager_debug |
773 | }; | 807 | }; |
808 | |||
809 | static int | ||
810 | nouveau_gart_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) | ||
811 | { | ||
812 | return 0; | ||
813 | } | ||
814 | |||
815 | static int | ||
816 | nouveau_gart_manager_fini(struct ttm_mem_type_manager *man) | ||
817 | { | ||
818 | return 0; | ||
819 | } | ||
820 | |||
821 | static void | ||
822 | nouveau_gart_manager_del(struct ttm_mem_type_manager *man, | ||
823 | struct ttm_mem_reg *mem) | ||
824 | { | ||
825 | struct nouveau_mem *node = mem->mm_node; | ||
826 | |||
827 | if (node->tmp_vma.node) { | ||
828 | nouveau_vm_unmap(&node->tmp_vma); | ||
829 | nouveau_vm_put(&node->tmp_vma); | ||
830 | } | ||
831 | mem->mm_node = NULL; | ||
832 | } | ||
833 | |||
834 | static int | ||
835 | nouveau_gart_manager_new(struct ttm_mem_type_manager *man, | ||
836 | struct ttm_buffer_object *bo, | ||
837 | struct ttm_placement *placement, | ||
838 | struct ttm_mem_reg *mem) | ||
839 | { | ||
840 | struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); | ||
841 | struct nouveau_bo *nvbo = nouveau_bo(bo); | ||
842 | struct nouveau_vma *vma = &nvbo->vma; | ||
843 | struct nouveau_vm *vm = vma->vm; | ||
844 | struct nouveau_mem *node; | ||
845 | int ret; | ||
846 | |||
847 | if (unlikely((mem->num_pages << PAGE_SHIFT) >= | ||
848 | dev_priv->gart_info.aper_size)) | ||
849 | return -ENOMEM; | ||
850 | |||
851 | node = kzalloc(sizeof(*node), GFP_KERNEL); | ||
852 | if (!node) | ||
853 | return -ENOMEM; | ||
854 | |||
855 | /* This node must be for evicting large-paged VRAM | ||
856 | * to system memory. Due to a nv50 limitation of | ||
857 | * not being able to mix large/small pages within | ||
858 | * the same PDE, we need to create a temporary | ||
859 | * small-paged VMA for the eviction. | ||
860 | */ | ||
861 | if (vma->node->type != vm->spg_shift) { | ||
862 | ret = nouveau_vm_get(vm, (u64)vma->node->length << 12, | ||
863 | vm->spg_shift, NV_MEM_ACCESS_RW, | ||
864 | &node->tmp_vma); | ||
865 | if (ret) { | ||
866 | kfree(node); | ||
867 | return ret; | ||
868 | } | ||
869 | } | ||
870 | |||
871 | node->page_shift = nvbo->vma.node->type; | ||
872 | mem->mm_node = node; | ||
873 | mem->start = 0; | ||
874 | return 0; | ||
875 | } | ||
876 | |||
877 | void | ||
878 | nouveau_gart_manager_debug(struct ttm_mem_type_manager *man, const char *prefix) | ||
879 | { | ||
880 | } | ||
881 | |||
882 | const struct ttm_mem_type_manager_func nouveau_gart_manager = { | ||
883 | nouveau_gart_manager_init, | ||
884 | nouveau_gart_manager_fini, | ||
885 | nouveau_gart_manager_new, | ||
886 | nouveau_gart_manager_del, | ||
887 | nouveau_gart_manager_debug | ||
888 | }; | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_mm.h b/drivers/gpu/drm/nouveau/nouveau_mm.h index 798eaf39691..1f7483aae9a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mm.h +++ b/drivers/gpu/drm/nouveau/nouveau_mm.h | |||
@@ -53,13 +53,13 @@ void nouveau_mm_put(struct nouveau_mm *, struct nouveau_mm_node *); | |||
53 | 53 | ||
54 | int nv50_vram_init(struct drm_device *); | 54 | int nv50_vram_init(struct drm_device *); |
55 | int nv50_vram_new(struct drm_device *, u64 size, u32 align, u32 size_nc, | 55 | int nv50_vram_new(struct drm_device *, u64 size, u32 align, u32 size_nc, |
56 | u32 memtype, struct nouveau_vram **); | 56 | u32 memtype, struct nouveau_mem **); |
57 | void nv50_vram_del(struct drm_device *, struct nouveau_vram **); | 57 | void nv50_vram_del(struct drm_device *, struct nouveau_mem **); |
58 | bool nv50_vram_flags_valid(struct drm_device *, u32 tile_flags); | 58 | bool nv50_vram_flags_valid(struct drm_device *, u32 tile_flags); |
59 | 59 | ||
60 | int nvc0_vram_init(struct drm_device *); | 60 | int nvc0_vram_init(struct drm_device *); |
61 | int nvc0_vram_new(struct drm_device *, u64 size, u32 align, u32 ncmin, | 61 | int nvc0_vram_new(struct drm_device *, u64 size, u32 align, u32 ncmin, |
62 | u32 memtype, struct nouveau_vram **); | 62 | u32 memtype, struct nouveau_mem **); |
63 | bool nvc0_vram_flags_valid(struct drm_device *, u32 tile_flags); | 63 | bool nvc0_vram_flags_valid(struct drm_device *, u32 tile_flags); |
64 | 64 | ||
65 | #endif | 65 | #endif |
diff --git a/drivers/gpu/drm/nouveau/nouveau_notifier.c b/drivers/gpu/drm/nouveau/nouveau_notifier.c index 5ea167623a8..7ba3fc0b30c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_notifier.c +++ b/drivers/gpu/drm/nouveau/nouveau_notifier.c | |||
@@ -39,12 +39,11 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan) | |||
39 | int ret; | 39 | int ret; |
40 | 40 | ||
41 | if (nouveau_vram_notify) | 41 | if (nouveau_vram_notify) |
42 | flags = TTM_PL_FLAG_VRAM; | 42 | flags = NOUVEAU_GEM_DOMAIN_VRAM; |
43 | else | 43 | else |
44 | flags = TTM_PL_FLAG_TT; | 44 | flags = NOUVEAU_GEM_DOMAIN_GART; |
45 | 45 | ||
46 | ret = nouveau_gem_new(dev, NULL, PAGE_SIZE, 0, flags, | 46 | ret = nouveau_gem_new(dev, NULL, PAGE_SIZE, 0, flags, 0, 0, &ntfy); |
47 | 0, 0x0000, false, true, &ntfy); | ||
48 | if (ret) | 47 | if (ret) |
49 | return ret; | 48 | return ret; |
50 | 49 | ||
@@ -100,6 +99,7 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, | |||
100 | uint32_t *b_offset) | 99 | uint32_t *b_offset) |
101 | { | 100 | { |
102 | struct drm_device *dev = chan->dev; | 101 | struct drm_device *dev = chan->dev; |
102 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
103 | struct nouveau_gpuobj *nobj = NULL; | 103 | struct nouveau_gpuobj *nobj = NULL; |
104 | struct drm_mm_node *mem; | 104 | struct drm_mm_node *mem; |
105 | uint32_t offset; | 105 | uint32_t offset; |
@@ -114,11 +114,16 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, | |||
114 | return -ENOMEM; | 114 | return -ENOMEM; |
115 | } | 115 | } |
116 | 116 | ||
117 | if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM) | 117 | if (dev_priv->card_type < NV_50) { |
118 | target = NV_MEM_TARGET_VRAM; | 118 | if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM) |
119 | else | 119 | target = NV_MEM_TARGET_VRAM; |
120 | target = NV_MEM_TARGET_GART; | 120 | else |
121 | offset = chan->notifier_bo->bo.mem.start << PAGE_SHIFT; | 121 | target = NV_MEM_TARGET_GART; |
122 | offset = chan->notifier_bo->bo.mem.start << PAGE_SHIFT; | ||
123 | } else { | ||
124 | target = NV_MEM_TARGET_VM; | ||
125 | offset = chan->notifier_bo->vma.offset; | ||
126 | } | ||
122 | offset += mem->start; | 127 | offset += mem->start; |
123 | 128 | ||
124 | ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, offset, | 129 | ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, offset, |
diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c index 30b6544467c..4f00c87ed86 100644 --- a/drivers/gpu/drm/nouveau/nouveau_object.c +++ b/drivers/gpu/drm/nouveau/nouveau_object.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include "nouveau_drm.h" | 36 | #include "nouveau_drm.h" |
37 | #include "nouveau_ramht.h" | 37 | #include "nouveau_ramht.h" |
38 | #include "nouveau_vm.h" | 38 | #include "nouveau_vm.h" |
39 | #include "nv50_display.h" | ||
39 | 40 | ||
40 | struct nouveau_gpuobj_method { | 41 | struct nouveau_gpuobj_method { |
41 | struct list_head head; | 42 | struct list_head head; |
@@ -490,16 +491,22 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, u64 base, | |||
490 | } | 491 | } |
491 | 492 | ||
492 | if (target == NV_MEM_TARGET_GART) { | 493 | if (target == NV_MEM_TARGET_GART) { |
493 | if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) { | 494 | struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma; |
494 | target = NV_MEM_TARGET_PCI_NOSNOOP; | 495 | |
495 | base += dev_priv->gart_info.aper_base; | 496 | if (dev_priv->gart_info.type == NOUVEAU_GART_PDMA) { |
496 | } else | 497 | if (base == 0) { |
497 | if (base != 0) { | 498 | nouveau_gpuobj_ref(gart, pobj); |
498 | base = nouveau_sgdma_get_physical(dev, base); | 499 | return 0; |
500 | } | ||
501 | |||
502 | base = nouveau_sgdma_get_physical(dev, base); | ||
499 | target = NV_MEM_TARGET_PCI; | 503 | target = NV_MEM_TARGET_PCI; |
500 | } else { | 504 | } else { |
501 | nouveau_gpuobj_ref(dev_priv->gart_info.sg_ctxdma, pobj); | 505 | base += dev_priv->gart_info.aper_base; |
502 | return 0; | 506 | if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) |
507 | target = NV_MEM_TARGET_PCI_NOSNOOP; | ||
508 | else | ||
509 | target = NV_MEM_TARGET_PCI; | ||
503 | } | 510 | } |
504 | } | 511 | } |
505 | 512 | ||
@@ -776,7 +783,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, | |||
776 | struct drm_device *dev = chan->dev; | 783 | struct drm_device *dev = chan->dev; |
777 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 784 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
778 | struct nouveau_gpuobj *vram = NULL, *tt = NULL; | 785 | struct nouveau_gpuobj *vram = NULL, *tt = NULL; |
779 | int ret; | 786 | int ret, i; |
780 | 787 | ||
781 | NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); | 788 | NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); |
782 | 789 | ||
@@ -841,6 +848,25 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, | |||
841 | nouveau_gpuobj_ref(NULL, &ramht); | 848 | nouveau_gpuobj_ref(NULL, &ramht); |
842 | if (ret) | 849 | if (ret) |
843 | return ret; | 850 | return ret; |
851 | |||
852 | /* dma objects for display sync channel semaphore blocks */ | ||
853 | for (i = 0; i < 2; i++) { | ||
854 | struct nouveau_gpuobj *sem = NULL; | ||
855 | struct nv50_display_crtc *dispc = | ||
856 | &nv50_display(dev)->crtc[i]; | ||
857 | u64 offset = dispc->sem.bo->bo.mem.start << PAGE_SHIFT; | ||
858 | |||
859 | ret = nouveau_gpuobj_dma_new(chan, 0x3d, offset, 0xfff, | ||
860 | NV_MEM_ACCESS_RW, | ||
861 | NV_MEM_TARGET_VRAM, &sem); | ||
862 | if (ret) | ||
863 | return ret; | ||
864 | |||
865 | ret = nouveau_ramht_insert(chan, NvEvoSema0 + i, sem); | ||
866 | nouveau_gpuobj_ref(NULL, &sem); | ||
867 | if (ret) | ||
868 | return ret; | ||
869 | } | ||
844 | } | 870 | } |
845 | 871 | ||
846 | /* VRAM ctxdma */ | 872 | /* VRAM ctxdma */ |
@@ -909,7 +935,7 @@ nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan) | |||
909 | nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd); | 935 | nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd); |
910 | nouveau_gpuobj_ref(NULL, &chan->vm_pd); | 936 | nouveau_gpuobj_ref(NULL, &chan->vm_pd); |
911 | 937 | ||
912 | if (chan->ramin_heap.free_stack.next) | 938 | if (drm_mm_initialized(&chan->ramin_heap)) |
913 | drm_mm_takedown(&chan->ramin_heap); | 939 | drm_mm_takedown(&chan->ramin_heap); |
914 | nouveau_gpuobj_ref(NULL, &chan->ramin); | 940 | nouveau_gpuobj_ref(NULL, &chan->ramin); |
915 | } | 941 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_ramht.c b/drivers/gpu/drm/nouveau/nouveau_ramht.c index bef3e691041..a24a81f5a89 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ramht.c +++ b/drivers/gpu/drm/nouveau/nouveau_ramht.c | |||
@@ -114,7 +114,9 @@ nouveau_ramht_insert(struct nouveau_channel *chan, u32 handle, | |||
114 | (gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT); | 114 | (gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT); |
115 | } else { | 115 | } else { |
116 | if (gpuobj->engine == NVOBJ_ENGINE_DISPLAY) { | 116 | if (gpuobj->engine == NVOBJ_ENGINE_DISPLAY) { |
117 | ctx = (gpuobj->cinst << 10) | chan->id; | 117 | ctx = (gpuobj->cinst << 10) | |
118 | (chan->id << 28) | | ||
119 | chan->id; /* HASH_TAG */ | ||
118 | } else { | 120 | } else { |
119 | ctx = (gpuobj->cinst >> 4) | | 121 | ctx = (gpuobj->cinst >> 4) | |
120 | ((gpuobj->engine << | 122 | ((gpuobj->engine << |
diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index 9a250eb5309..a33fe401928 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c | |||
@@ -12,6 +12,7 @@ struct nouveau_sgdma_be { | |||
12 | struct drm_device *dev; | 12 | struct drm_device *dev; |
13 | 13 | ||
14 | dma_addr_t *pages; | 14 | dma_addr_t *pages; |
15 | bool *ttm_alloced; | ||
15 | unsigned nr_pages; | 16 | unsigned nr_pages; |
16 | 17 | ||
17 | u64 offset; | 18 | u64 offset; |
@@ -20,7 +21,8 @@ struct nouveau_sgdma_be { | |||
20 | 21 | ||
21 | static int | 22 | static int |
22 | nouveau_sgdma_populate(struct ttm_backend *be, unsigned long num_pages, | 23 | nouveau_sgdma_populate(struct ttm_backend *be, unsigned long num_pages, |
23 | struct page **pages, struct page *dummy_read_page) | 24 | struct page **pages, struct page *dummy_read_page, |
25 | dma_addr_t *dma_addrs) | ||
24 | { | 26 | { |
25 | struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; | 27 | struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; |
26 | struct drm_device *dev = nvbe->dev; | 28 | struct drm_device *dev = nvbe->dev; |
@@ -34,15 +36,25 @@ nouveau_sgdma_populate(struct ttm_backend *be, unsigned long num_pages, | |||
34 | if (!nvbe->pages) | 36 | if (!nvbe->pages) |
35 | return -ENOMEM; | 37 | return -ENOMEM; |
36 | 38 | ||
39 | nvbe->ttm_alloced = kmalloc(sizeof(bool) * num_pages, GFP_KERNEL); | ||
40 | if (!nvbe->ttm_alloced) | ||
41 | return -ENOMEM; | ||
42 | |||
37 | nvbe->nr_pages = 0; | 43 | nvbe->nr_pages = 0; |
38 | while (num_pages--) { | 44 | while (num_pages--) { |
39 | nvbe->pages[nvbe->nr_pages] = | 45 | if (dma_addrs[nvbe->nr_pages] != DMA_ERROR_CODE) { |
40 | pci_map_page(dev->pdev, pages[nvbe->nr_pages], 0, | 46 | nvbe->pages[nvbe->nr_pages] = |
47 | dma_addrs[nvbe->nr_pages]; | ||
48 | nvbe->ttm_alloced[nvbe->nr_pages] = true; | ||
49 | } else { | ||
50 | nvbe->pages[nvbe->nr_pages] = | ||
51 | pci_map_page(dev->pdev, pages[nvbe->nr_pages], 0, | ||
41 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | 52 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); |
42 | if (pci_dma_mapping_error(dev->pdev, | 53 | if (pci_dma_mapping_error(dev->pdev, |
43 | nvbe->pages[nvbe->nr_pages])) { | 54 | nvbe->pages[nvbe->nr_pages])) { |
44 | be->func->clear(be); | 55 | be->func->clear(be); |
45 | return -EFAULT; | 56 | return -EFAULT; |
57 | } | ||
46 | } | 58 | } |
47 | 59 | ||
48 | nvbe->nr_pages++; | 60 | nvbe->nr_pages++; |
@@ -65,17 +77,36 @@ nouveau_sgdma_clear(struct ttm_backend *be) | |||
65 | be->func->unbind(be); | 77 | be->func->unbind(be); |
66 | 78 | ||
67 | while (nvbe->nr_pages--) { | 79 | while (nvbe->nr_pages--) { |
68 | pci_unmap_page(dev->pdev, nvbe->pages[nvbe->nr_pages], | 80 | if (!nvbe->ttm_alloced[nvbe->nr_pages]) |
81 | pci_unmap_page(dev->pdev, nvbe->pages[nvbe->nr_pages], | ||
69 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | 82 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); |
70 | } | 83 | } |
71 | kfree(nvbe->pages); | 84 | kfree(nvbe->pages); |
85 | kfree(nvbe->ttm_alloced); | ||
72 | nvbe->pages = NULL; | 86 | nvbe->pages = NULL; |
87 | nvbe->ttm_alloced = NULL; | ||
73 | nvbe->nr_pages = 0; | 88 | nvbe->nr_pages = 0; |
74 | } | 89 | } |
75 | } | 90 | } |
76 | 91 | ||
92 | static void | ||
93 | nouveau_sgdma_destroy(struct ttm_backend *be) | ||
94 | { | ||
95 | struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; | ||
96 | |||
97 | if (be) { | ||
98 | NV_DEBUG(nvbe->dev, "\n"); | ||
99 | |||
100 | if (nvbe) { | ||
101 | if (nvbe->pages) | ||
102 | be->func->clear(be); | ||
103 | kfree(nvbe); | ||
104 | } | ||
105 | } | ||
106 | } | ||
107 | |||
77 | static int | 108 | static int |
78 | nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) | 109 | nv04_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) |
79 | { | 110 | { |
80 | struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; | 111 | struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; |
81 | struct drm_device *dev = nvbe->dev; | 112 | struct drm_device *dev = nvbe->dev; |
@@ -102,7 +133,7 @@ nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) | |||
102 | } | 133 | } |
103 | 134 | ||
104 | static int | 135 | static int |
105 | nouveau_sgdma_unbind(struct ttm_backend *be) | 136 | nv04_sgdma_unbind(struct ttm_backend *be) |
106 | { | 137 | { |
107 | struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; | 138 | struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; |
108 | struct drm_device *dev = nvbe->dev; | 139 | struct drm_device *dev = nvbe->dev; |
@@ -125,59 +156,245 @@ nouveau_sgdma_unbind(struct ttm_backend *be) | |||
125 | return 0; | 156 | return 0; |
126 | } | 157 | } |
127 | 158 | ||
159 | static struct ttm_backend_func nv04_sgdma_backend = { | ||
160 | .populate = nouveau_sgdma_populate, | ||
161 | .clear = nouveau_sgdma_clear, | ||
162 | .bind = nv04_sgdma_bind, | ||
163 | .unbind = nv04_sgdma_unbind, | ||
164 | .destroy = nouveau_sgdma_destroy | ||
165 | }; | ||
166 | |||
128 | static void | 167 | static void |
129 | nouveau_sgdma_destroy(struct ttm_backend *be) | 168 | nv41_sgdma_flush(struct nouveau_sgdma_be *nvbe) |
169 | { | ||
170 | struct drm_device *dev = nvbe->dev; | ||
171 | |||
172 | nv_wr32(dev, 0x100810, 0x00000022); | ||
173 | if (!nv_wait(dev, 0x100810, 0x00000100, 0x00000100)) | ||
174 | NV_ERROR(dev, "vm flush timeout: 0x%08x\n", | ||
175 | nv_rd32(dev, 0x100810)); | ||
176 | nv_wr32(dev, 0x100810, 0x00000000); | ||
177 | } | ||
178 | |||
179 | static int | ||
180 | nv41_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) | ||
130 | { | 181 | { |
131 | struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; | 182 | struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; |
183 | struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; | ||
184 | struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma; | ||
185 | dma_addr_t *list = nvbe->pages; | ||
186 | u32 pte = mem->start << 2; | ||
187 | u32 cnt = nvbe->nr_pages; | ||
132 | 188 | ||
133 | if (be) { | 189 | nvbe->offset = mem->start << PAGE_SHIFT; |
134 | NV_DEBUG(nvbe->dev, "\n"); | ||
135 | 190 | ||
136 | if (nvbe) { | 191 | while (cnt--) { |
137 | if (nvbe->pages) | 192 | nv_wo32(pgt, pte, (*list++ >> 7) | 1); |
138 | be->func->clear(be); | 193 | pte += 4; |
139 | kfree(nvbe); | 194 | } |
195 | |||
196 | nv41_sgdma_flush(nvbe); | ||
197 | nvbe->bound = true; | ||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | static int | ||
202 | nv41_sgdma_unbind(struct ttm_backend *be) | ||
203 | { | ||
204 | struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; | ||
205 | struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; | ||
206 | struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma; | ||
207 | u32 pte = (nvbe->offset >> 12) << 2; | ||
208 | u32 cnt = nvbe->nr_pages; | ||
209 | |||
210 | while (cnt--) { | ||
211 | nv_wo32(pgt, pte, 0x00000000); | ||
212 | pte += 4; | ||
213 | } | ||
214 | |||
215 | nv41_sgdma_flush(nvbe); | ||
216 | nvbe->bound = false; | ||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static struct ttm_backend_func nv41_sgdma_backend = { | ||
221 | .populate = nouveau_sgdma_populate, | ||
222 | .clear = nouveau_sgdma_clear, | ||
223 | .bind = nv41_sgdma_bind, | ||
224 | .unbind = nv41_sgdma_unbind, | ||
225 | .destroy = nouveau_sgdma_destroy | ||
226 | }; | ||
227 | |||
228 | static void | ||
229 | nv44_sgdma_flush(struct nouveau_sgdma_be *nvbe) | ||
230 | { | ||
231 | struct drm_device *dev = nvbe->dev; | ||
232 | |||
233 | nv_wr32(dev, 0x100814, (nvbe->nr_pages - 1) << 12); | ||
234 | nv_wr32(dev, 0x100808, nvbe->offset | 0x20); | ||
235 | if (!nv_wait(dev, 0x100808, 0x00000001, 0x00000001)) | ||
236 | NV_ERROR(dev, "gart flush timeout: 0x%08x\n", | ||
237 | nv_rd32(dev, 0x100808)); | ||
238 | nv_wr32(dev, 0x100808, 0x00000000); | ||
239 | } | ||
240 | |||
241 | static void | ||
242 | nv44_sgdma_fill(struct nouveau_gpuobj *pgt, dma_addr_t *list, u32 base, u32 cnt) | ||
243 | { | ||
244 | struct drm_nouveau_private *dev_priv = pgt->dev->dev_private; | ||
245 | dma_addr_t dummy = dev_priv->gart_info.dummy.addr; | ||
246 | u32 pte, tmp[4]; | ||
247 | |||
248 | pte = base >> 2; | ||
249 | base &= ~0x0000000f; | ||
250 | |||
251 | tmp[0] = nv_ro32(pgt, base + 0x0); | ||
252 | tmp[1] = nv_ro32(pgt, base + 0x4); | ||
253 | tmp[2] = nv_ro32(pgt, base + 0x8); | ||
254 | tmp[3] = nv_ro32(pgt, base + 0xc); | ||
255 | while (cnt--) { | ||
256 | u32 addr = list ? (*list++ >> 12) : (dummy >> 12); | ||
257 | switch (pte++ & 0x3) { | ||
258 | case 0: | ||
259 | tmp[0] &= ~0x07ffffff; | ||
260 | tmp[0] |= addr; | ||
261 | break; | ||
262 | case 1: | ||
263 | tmp[0] &= ~0xf8000000; | ||
264 | tmp[0] |= addr << 27; | ||
265 | tmp[1] &= ~0x003fffff; | ||
266 | tmp[1] |= addr >> 5; | ||
267 | break; | ||
268 | case 2: | ||
269 | tmp[1] &= ~0xffc00000; | ||
270 | tmp[1] |= addr << 22; | ||
271 | tmp[2] &= ~0x0001ffff; | ||
272 | tmp[2] |= addr >> 10; | ||
273 | break; | ||
274 | case 3: | ||
275 | tmp[2] &= ~0xfffe0000; | ||
276 | tmp[2] |= addr << 17; | ||
277 | tmp[3] &= ~0x00000fff; | ||
278 | tmp[3] |= addr >> 15; | ||
279 | break; | ||
140 | } | 280 | } |
141 | } | 281 | } |
282 | |||
283 | tmp[3] |= 0x40000000; | ||
284 | |||
285 | nv_wo32(pgt, base + 0x0, tmp[0]); | ||
286 | nv_wo32(pgt, base + 0x4, tmp[1]); | ||
287 | nv_wo32(pgt, base + 0x8, tmp[2]); | ||
288 | nv_wo32(pgt, base + 0xc, tmp[3]); | ||
142 | } | 289 | } |
143 | 290 | ||
144 | static int | 291 | static int |
145 | nv50_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) | 292 | nv44_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) |
146 | { | 293 | { |
147 | struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; | 294 | struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; |
148 | struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; | 295 | struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; |
296 | struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma; | ||
297 | dma_addr_t *list = nvbe->pages; | ||
298 | u32 pte = mem->start << 2, tmp[4]; | ||
299 | u32 cnt = nvbe->nr_pages; | ||
300 | int i; | ||
149 | 301 | ||
150 | nvbe->offset = mem->start << PAGE_SHIFT; | 302 | nvbe->offset = mem->start << PAGE_SHIFT; |
151 | 303 | ||
152 | nouveau_vm_map_sg(&dev_priv->gart_info.vma, nvbe->offset, | 304 | if (pte & 0x0000000c) { |
153 | nvbe->nr_pages << PAGE_SHIFT, nvbe->pages); | 305 | u32 max = 4 - ((pte >> 2) & 0x3); |
306 | u32 part = (cnt > max) ? max : cnt; | ||
307 | nv44_sgdma_fill(pgt, list, pte, part); | ||
308 | pte += (part << 2); | ||
309 | list += part; | ||
310 | cnt -= part; | ||
311 | } | ||
312 | |||
313 | while (cnt >= 4) { | ||
314 | for (i = 0; i < 4; i++) | ||
315 | tmp[i] = *list++ >> 12; | ||
316 | nv_wo32(pgt, pte + 0x0, tmp[0] >> 0 | tmp[1] << 27); | ||
317 | nv_wo32(pgt, pte + 0x4, tmp[1] >> 5 | tmp[2] << 22); | ||
318 | nv_wo32(pgt, pte + 0x8, tmp[2] >> 10 | tmp[3] << 17); | ||
319 | nv_wo32(pgt, pte + 0xc, tmp[3] >> 15 | 0x40000000); | ||
320 | pte += 0x10; | ||
321 | cnt -= 4; | ||
322 | } | ||
323 | |||
324 | if (cnt) | ||
325 | nv44_sgdma_fill(pgt, list, pte, cnt); | ||
326 | |||
327 | nv44_sgdma_flush(nvbe); | ||
154 | nvbe->bound = true; | 328 | nvbe->bound = true; |
155 | return 0; | 329 | return 0; |
156 | } | 330 | } |
157 | 331 | ||
158 | static int | 332 | static int |
159 | nv50_sgdma_unbind(struct ttm_backend *be) | 333 | nv44_sgdma_unbind(struct ttm_backend *be) |
160 | { | 334 | { |
161 | struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; | 335 | struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; |
162 | struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; | 336 | struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; |
337 | struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma; | ||
338 | u32 pte = (nvbe->offset >> 12) << 2; | ||
339 | u32 cnt = nvbe->nr_pages; | ||
340 | |||
341 | if (pte & 0x0000000c) { | ||
342 | u32 max = 4 - ((pte >> 2) & 0x3); | ||
343 | u32 part = (cnt > max) ? max : cnt; | ||
344 | nv44_sgdma_fill(pgt, NULL, pte, part); | ||
345 | pte += (part << 2); | ||
346 | cnt -= part; | ||
347 | } | ||
163 | 348 | ||
164 | if (!nvbe->bound) | 349 | while (cnt >= 4) { |
165 | return 0; | 350 | nv_wo32(pgt, pte + 0x0, 0x00000000); |
351 | nv_wo32(pgt, pte + 0x4, 0x00000000); | ||
352 | nv_wo32(pgt, pte + 0x8, 0x00000000); | ||
353 | nv_wo32(pgt, pte + 0xc, 0x00000000); | ||
354 | pte += 0x10; | ||
355 | cnt -= 4; | ||
356 | } | ||
357 | |||
358 | if (cnt) | ||
359 | nv44_sgdma_fill(pgt, NULL, pte, cnt); | ||
166 | 360 | ||
167 | nouveau_vm_unmap_at(&dev_priv->gart_info.vma, nvbe->offset, | 361 | nv44_sgdma_flush(nvbe); |
168 | nvbe->nr_pages << PAGE_SHIFT); | ||
169 | nvbe->bound = false; | 362 | nvbe->bound = false; |
170 | return 0; | 363 | return 0; |
171 | } | 364 | } |
172 | 365 | ||
173 | static struct ttm_backend_func nouveau_sgdma_backend = { | 366 | static struct ttm_backend_func nv44_sgdma_backend = { |
174 | .populate = nouveau_sgdma_populate, | 367 | .populate = nouveau_sgdma_populate, |
175 | .clear = nouveau_sgdma_clear, | 368 | .clear = nouveau_sgdma_clear, |
176 | .bind = nouveau_sgdma_bind, | 369 | .bind = nv44_sgdma_bind, |
177 | .unbind = nouveau_sgdma_unbind, | 370 | .unbind = nv44_sgdma_unbind, |
178 | .destroy = nouveau_sgdma_destroy | 371 | .destroy = nouveau_sgdma_destroy |
179 | }; | 372 | }; |
180 | 373 | ||
374 | static int | ||
375 | nv50_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) | ||
376 | { | ||
377 | struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; | ||
378 | struct nouveau_mem *node = mem->mm_node; | ||
379 | /* noop: bound in move_notify() */ | ||
380 | node->pages = nvbe->pages; | ||
381 | nvbe->pages = (dma_addr_t *)node; | ||
382 | nvbe->bound = true; | ||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | static int | ||
387 | nv50_sgdma_unbind(struct ttm_backend *be) | ||
388 | { | ||
389 | struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; | ||
390 | struct nouveau_mem *node = (struct nouveau_mem *)nvbe->pages; | ||
391 | /* noop: unbound in move_notify() */ | ||
392 | nvbe->pages = node->pages; | ||
393 | node->pages = NULL; | ||
394 | nvbe->bound = false; | ||
395 | return 0; | ||
396 | } | ||
397 | |||
181 | static struct ttm_backend_func nv50_sgdma_backend = { | 398 | static struct ttm_backend_func nv50_sgdma_backend = { |
182 | .populate = nouveau_sgdma_populate, | 399 | .populate = nouveau_sgdma_populate, |
183 | .clear = nouveau_sgdma_clear, | 400 | .clear = nouveau_sgdma_clear, |
@@ -198,10 +415,7 @@ nouveau_sgdma_init_ttm(struct drm_device *dev) | |||
198 | 415 | ||
199 | nvbe->dev = dev; | 416 | nvbe->dev = dev; |
200 | 417 | ||
201 | if (dev_priv->card_type < NV_50) | 418 | nvbe->backend.func = dev_priv->gart_info.func; |
202 | nvbe->backend.func = &nouveau_sgdma_backend; | ||
203 | else | ||
204 | nvbe->backend.func = &nv50_sgdma_backend; | ||
205 | return &nvbe->backend; | 419 | return &nvbe->backend; |
206 | } | 420 | } |
207 | 421 | ||
@@ -210,21 +424,64 @@ nouveau_sgdma_init(struct drm_device *dev) | |||
210 | { | 424 | { |
211 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 425 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
212 | struct nouveau_gpuobj *gpuobj = NULL; | 426 | struct nouveau_gpuobj *gpuobj = NULL; |
213 | uint32_t aper_size, obj_size; | 427 | u32 aper_size, align; |
214 | int i, ret; | 428 | int ret; |
215 | 429 | ||
216 | if (dev_priv->card_type < NV_50) { | 430 | if (dev_priv->card_type >= NV_50 || drm_pci_device_is_pcie(dev)) |
217 | if(dev_priv->ramin_rsvd_vram < 2 * 1024 * 1024) | 431 | aper_size = 512 * 1024 * 1024; |
218 | aper_size = 64 * 1024 * 1024; | 432 | else |
219 | else | 433 | aper_size = 64 * 1024 * 1024; |
220 | aper_size = 512 * 1024 * 1024; | 434 | |
435 | /* Dear NVIDIA, NV44+ would like proper present bits in PTEs for | ||
436 | * christmas. The cards before it have them, the cards after | ||
437 | * it have them, why is NV44 so unloved? | ||
438 | */ | ||
439 | dev_priv->gart_info.dummy.page = alloc_page(GFP_DMA32 | GFP_KERNEL); | ||
440 | if (!dev_priv->gart_info.dummy.page) | ||
441 | return -ENOMEM; | ||
442 | |||
443 | dev_priv->gart_info.dummy.addr = | ||
444 | pci_map_page(dev->pdev, dev_priv->gart_info.dummy.page, | ||
445 | 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | ||
446 | if (pci_dma_mapping_error(dev->pdev, dev_priv->gart_info.dummy.addr)) { | ||
447 | NV_ERROR(dev, "error mapping dummy page\n"); | ||
448 | __free_page(dev_priv->gart_info.dummy.page); | ||
449 | dev_priv->gart_info.dummy.page = NULL; | ||
450 | return -ENOMEM; | ||
451 | } | ||
452 | |||
453 | if (dev_priv->card_type >= NV_50) { | ||
454 | dev_priv->gart_info.aper_base = 0; | ||
455 | dev_priv->gart_info.aper_size = aper_size; | ||
456 | dev_priv->gart_info.type = NOUVEAU_GART_HW; | ||
457 | dev_priv->gart_info.func = &nv50_sgdma_backend; | ||
458 | } else | ||
459 | if (drm_pci_device_is_pcie(dev) && | ||
460 | dev_priv->chipset != 0x40 && dev_priv->chipset != 0x45) { | ||
461 | if (nv44_graph_class(dev)) { | ||
462 | dev_priv->gart_info.func = &nv44_sgdma_backend; | ||
463 | align = 512 * 1024; | ||
464 | } else { | ||
465 | dev_priv->gart_info.func = &nv41_sgdma_backend; | ||
466 | align = 16; | ||
467 | } | ||
221 | 468 | ||
222 | obj_size = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 4; | 469 | ret = nouveau_gpuobj_new(dev, NULL, aper_size / 1024, align, |
223 | obj_size += 8; /* ctxdma header */ | 470 | NVOBJ_FLAG_ZERO_ALLOC | |
471 | NVOBJ_FLAG_ZERO_FREE, &gpuobj); | ||
472 | if (ret) { | ||
473 | NV_ERROR(dev, "Error creating sgdma object: %d\n", ret); | ||
474 | return ret; | ||
475 | } | ||
224 | 476 | ||
225 | ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16, | 477 | dev_priv->gart_info.sg_ctxdma = gpuobj; |
226 | NVOBJ_FLAG_ZERO_ALLOC | | 478 | dev_priv->gart_info.aper_base = 0; |
227 | NVOBJ_FLAG_ZERO_FREE, &gpuobj); | 479 | dev_priv->gart_info.aper_size = aper_size; |
480 | dev_priv->gart_info.type = NOUVEAU_GART_HW; | ||
481 | } else { | ||
482 | ret = nouveau_gpuobj_new(dev, NULL, (aper_size / 1024) + 8, 16, | ||
483 | NVOBJ_FLAG_ZERO_ALLOC | | ||
484 | NVOBJ_FLAG_ZERO_FREE, &gpuobj); | ||
228 | if (ret) { | 485 | if (ret) { |
229 | NV_ERROR(dev, "Error creating sgdma object: %d\n", ret); | 486 | NV_ERROR(dev, "Error creating sgdma object: %d\n", ret); |
230 | return ret; | 487 | return ret; |
@@ -236,25 +493,14 @@ nouveau_sgdma_init(struct drm_device *dev) | |||
236 | (0 << 14) /* RW */ | | 493 | (0 << 14) /* RW */ | |
237 | (2 << 16) /* PCI */); | 494 | (2 << 16) /* PCI */); |
238 | nv_wo32(gpuobj, 4, aper_size - 1); | 495 | nv_wo32(gpuobj, 4, aper_size - 1); |
239 | for (i = 2; i < 2 + (aper_size >> 12); i++) | ||
240 | nv_wo32(gpuobj, i * 4, 0x00000000); | ||
241 | 496 | ||
242 | dev_priv->gart_info.sg_ctxdma = gpuobj; | 497 | dev_priv->gart_info.sg_ctxdma = gpuobj; |
243 | dev_priv->gart_info.aper_base = 0; | 498 | dev_priv->gart_info.aper_base = 0; |
244 | dev_priv->gart_info.aper_size = aper_size; | 499 | dev_priv->gart_info.aper_size = aper_size; |
245 | } else | 500 | dev_priv->gart_info.type = NOUVEAU_GART_PDMA; |
246 | if (dev_priv->chan_vm) { | 501 | dev_priv->gart_info.func = &nv04_sgdma_backend; |
247 | ret = nouveau_vm_get(dev_priv->chan_vm, 512 * 1024 * 1024, | ||
248 | 12, NV_MEM_ACCESS_RW, | ||
249 | &dev_priv->gart_info.vma); | ||
250 | if (ret) | ||
251 | return ret; | ||
252 | |||
253 | dev_priv->gart_info.aper_base = dev_priv->gart_info.vma.offset; | ||
254 | dev_priv->gart_info.aper_size = 512 * 1024 * 1024; | ||
255 | } | 502 | } |
256 | 503 | ||
257 | dev_priv->gart_info.type = NOUVEAU_GART_SGDMA; | ||
258 | return 0; | 504 | return 0; |
259 | } | 505 | } |
260 | 506 | ||
@@ -264,7 +510,13 @@ nouveau_sgdma_takedown(struct drm_device *dev) | |||
264 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 510 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
265 | 511 | ||
266 | nouveau_gpuobj_ref(NULL, &dev_priv->gart_info.sg_ctxdma); | 512 | nouveau_gpuobj_ref(NULL, &dev_priv->gart_info.sg_ctxdma); |
267 | nouveau_vm_put(&dev_priv->gart_info.vma); | 513 | |
514 | if (dev_priv->gart_info.dummy.page) { | ||
515 | pci_unmap_page(dev->pdev, dev_priv->gart_info.dummy.addr, | ||
516 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | ||
517 | __free_page(dev_priv->gart_info.dummy.page); | ||
518 | dev_priv->gart_info.dummy.page = NULL; | ||
519 | } | ||
268 | } | 520 | } |
269 | 521 | ||
270 | uint32_t | 522 | uint32_t |
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index a54fc431fe9..05294910e13 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c | |||
@@ -544,7 +544,6 @@ static int | |||
544 | nouveau_card_init_channel(struct drm_device *dev) | 544 | nouveau_card_init_channel(struct drm_device *dev) |
545 | { | 545 | { |
546 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 546 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
547 | struct nouveau_gpuobj *gpuobj = NULL; | ||
548 | int ret; | 547 | int ret; |
549 | 548 | ||
550 | ret = nouveau_channel_alloc(dev, &dev_priv->channel, | 549 | ret = nouveau_channel_alloc(dev, &dev_priv->channel, |
@@ -552,41 +551,8 @@ nouveau_card_init_channel(struct drm_device *dev) | |||
552 | if (ret) | 551 | if (ret) |
553 | return ret; | 552 | return ret; |
554 | 553 | ||
555 | /* no dma objects on fermi... */ | ||
556 | if (dev_priv->card_type >= NV_C0) | ||
557 | goto out_done; | ||
558 | |||
559 | ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, | ||
560 | 0, dev_priv->vram_size, | ||
561 | NV_MEM_ACCESS_RW, NV_MEM_TARGET_VRAM, | ||
562 | &gpuobj); | ||
563 | if (ret) | ||
564 | goto out_err; | ||
565 | |||
566 | ret = nouveau_ramht_insert(dev_priv->channel, NvDmaVRAM, gpuobj); | ||
567 | nouveau_gpuobj_ref(NULL, &gpuobj); | ||
568 | if (ret) | ||
569 | goto out_err; | ||
570 | |||
571 | ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, | ||
572 | 0, dev_priv->gart_info.aper_size, | ||
573 | NV_MEM_ACCESS_RW, NV_MEM_TARGET_GART, | ||
574 | &gpuobj); | ||
575 | if (ret) | ||
576 | goto out_err; | ||
577 | |||
578 | ret = nouveau_ramht_insert(dev_priv->channel, NvDmaGART, gpuobj); | ||
579 | nouveau_gpuobj_ref(NULL, &gpuobj); | ||
580 | if (ret) | ||
581 | goto out_err; | ||
582 | |||
583 | out_done: | ||
584 | mutex_unlock(&dev_priv->channel->mutex); | 554 | mutex_unlock(&dev_priv->channel->mutex); |
585 | return 0; | 555 | return 0; |
586 | |||
587 | out_err: | ||
588 | nouveau_channel_put(&dev_priv->channel); | ||
589 | return ret; | ||
590 | } | 556 | } |
591 | 557 | ||
592 | static void nouveau_switcheroo_set_state(struct pci_dev *pdev, | 558 | static void nouveau_switcheroo_set_state(struct pci_dev *pdev, |
@@ -929,12 +895,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
929 | NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n", | 895 | NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n", |
930 | dev->pci_vendor, dev->pci_device, dev->pdev->class); | 896 | dev->pci_vendor, dev->pci_device, dev->pdev->class); |
931 | 897 | ||
932 | dev_priv->wq = create_workqueue("nouveau"); | ||
933 | if (!dev_priv->wq) { | ||
934 | ret = -EINVAL; | ||
935 | goto err_priv; | ||
936 | } | ||
937 | |||
938 | /* resource 0 is mmio regs */ | 898 | /* resource 0 is mmio regs */ |
939 | /* resource 1 is linear FB */ | 899 | /* resource 1 is linear FB */ |
940 | /* resource 2 is RAMIN (mmio regs + 0x1000000) */ | 900 | /* resource 2 is RAMIN (mmio regs + 0x1000000) */ |
@@ -947,7 +907,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
947 | NV_ERROR(dev, "Unable to initialize the mmio mapping. " | 907 | NV_ERROR(dev, "Unable to initialize the mmio mapping. " |
948 | "Please report your setup to " DRIVER_EMAIL "\n"); | 908 | "Please report your setup to " DRIVER_EMAIL "\n"); |
949 | ret = -EINVAL; | 909 | ret = -EINVAL; |
950 | goto err_wq; | 910 | goto err_priv; |
951 | } | 911 | } |
952 | NV_DEBUG(dev, "regs mapped ok at 0x%llx\n", | 912 | NV_DEBUG(dev, "regs mapped ok at 0x%llx\n", |
953 | (unsigned long long)mmio_start_offs); | 913 | (unsigned long long)mmio_start_offs); |
@@ -1054,8 +1014,6 @@ err_ramin: | |||
1054 | iounmap(dev_priv->ramin); | 1014 | iounmap(dev_priv->ramin); |
1055 | err_mmio: | 1015 | err_mmio: |
1056 | iounmap(dev_priv->mmio); | 1016 | iounmap(dev_priv->mmio); |
1057 | err_wq: | ||
1058 | destroy_workqueue(dev_priv->wq); | ||
1059 | err_priv: | 1017 | err_priv: |
1060 | kfree(dev_priv); | 1018 | kfree(dev_priv); |
1061 | dev->dev_private = NULL; | 1019 | dev->dev_private = NULL; |
@@ -1103,9 +1061,9 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data, | |||
1103 | getparam->value = dev->pci_device; | 1061 | getparam->value = dev->pci_device; |
1104 | break; | 1062 | break; |
1105 | case NOUVEAU_GETPARAM_BUS_TYPE: | 1063 | case NOUVEAU_GETPARAM_BUS_TYPE: |
1106 | if (drm_device_is_agp(dev)) | 1064 | if (drm_pci_device_is_agp(dev)) |
1107 | getparam->value = NV_AGP; | 1065 | getparam->value = NV_AGP; |
1108 | else if (drm_device_is_pcie(dev)) | 1066 | else if (drm_pci_device_is_pcie(dev)) |
1109 | getparam->value = NV_PCIE; | 1067 | getparam->value = NV_PCIE; |
1110 | else | 1068 | else |
1111 | getparam->value = NV_PCI; | 1069 | getparam->value = NV_PCI; |
@@ -1126,7 +1084,7 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data, | |||
1126 | getparam->value = 1; | 1084 | getparam->value = 1; |
1127 | break; | 1085 | break; |
1128 | case NOUVEAU_GETPARAM_HAS_PAGEFLIP: | 1086 | case NOUVEAU_GETPARAM_HAS_PAGEFLIP: |
1129 | getparam->value = (dev_priv->card_type < NV_50); | 1087 | getparam->value = 1; |
1130 | break; | 1088 | break; |
1131 | case NOUVEAU_GETPARAM_GRAPH_UNITS: | 1089 | case NOUVEAU_GETPARAM_GRAPH_UNITS: |
1132 | /* NV40 and NV50 versions are quite different, but register | 1090 | /* NV40 and NV50 versions are quite different, but register |
diff --git a/drivers/gpu/drm/nouveau/nouveau_temp.c b/drivers/gpu/drm/nouveau/nouveau_temp.c index 8d9968e1cba..649b0413b09 100644 --- a/drivers/gpu/drm/nouveau/nouveau_temp.c +++ b/drivers/gpu/drm/nouveau/nouveau_temp.c | |||
@@ -239,11 +239,9 @@ static bool | |||
239 | probe_monitoring_device(struct nouveau_i2c_chan *i2c, | 239 | probe_monitoring_device(struct nouveau_i2c_chan *i2c, |
240 | struct i2c_board_info *info) | 240 | struct i2c_board_info *info) |
241 | { | 241 | { |
242 | char modalias[16] = "i2c:"; | ||
243 | struct i2c_client *client; | 242 | struct i2c_client *client; |
244 | 243 | ||
245 | strlcat(modalias, info->type, sizeof(modalias)); | 244 | request_module("%s%s", I2C_MODULE_PREFIX, info->type); |
246 | request_module(modalias); | ||
247 | 245 | ||
248 | client = i2c_new_device(&i2c->adapter, info); | 246 | client = i2c_new_device(&i2c->adapter, info); |
249 | if (!client) | 247 | if (!client) |
diff --git a/drivers/gpu/drm/nouveau/nouveau_util.c b/drivers/gpu/drm/nouveau/nouveau_util.c index fbe0fb13bc1..e51b51503ba 100644 --- a/drivers/gpu/drm/nouveau/nouveau_util.c +++ b/drivers/gpu/drm/nouveau/nouveau_util.c | |||
@@ -47,18 +47,27 @@ nouveau_bitfield_print(const struct nouveau_bitfield *bf, u32 value) | |||
47 | printk(" (unknown bits 0x%08x)", value); | 47 | printk(" (unknown bits 0x%08x)", value); |
48 | } | 48 | } |
49 | 49 | ||
50 | void | 50 | const struct nouveau_enum * |
51 | nouveau_enum_print(const struct nouveau_enum *en, u32 value) | 51 | nouveau_enum_find(const struct nouveau_enum *en, u32 value) |
52 | { | 52 | { |
53 | while (en->name) { | 53 | while (en->name) { |
54 | if (value == en->value) { | 54 | if (en->value == value) |
55 | printk("%s", en->name); | 55 | return en; |
56 | return; | ||
57 | } | ||
58 | |||
59 | en++; | 56 | en++; |
60 | } | 57 | } |
61 | 58 | ||
59 | return NULL; | ||
60 | } | ||
61 | |||
62 | void | ||
63 | nouveau_enum_print(const struct nouveau_enum *en, u32 value) | ||
64 | { | ||
65 | en = nouveau_enum_find(en, value); | ||
66 | if (en) { | ||
67 | printk("%s", en->name); | ||
68 | return; | ||
69 | } | ||
70 | |||
62 | printk("(unknown enum 0x%08x)", value); | 71 | printk("(unknown enum 0x%08x)", value); |
63 | } | 72 | } |
64 | 73 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_util.h b/drivers/gpu/drm/nouveau/nouveau_util.h index d9ceaea26f4..b97719fbb73 100644 --- a/drivers/gpu/drm/nouveau/nouveau_util.h +++ b/drivers/gpu/drm/nouveau/nouveau_util.h | |||
@@ -36,10 +36,14 @@ struct nouveau_bitfield { | |||
36 | struct nouveau_enum { | 36 | struct nouveau_enum { |
37 | u32 value; | 37 | u32 value; |
38 | const char *name; | 38 | const char *name; |
39 | void *data; | ||
39 | }; | 40 | }; |
40 | 41 | ||
41 | void nouveau_bitfield_print(const struct nouveau_bitfield *, u32 value); | 42 | void nouveau_bitfield_print(const struct nouveau_bitfield *, u32 value); |
42 | void nouveau_enum_print(const struct nouveau_enum *, u32 value); | 43 | void nouveau_enum_print(const struct nouveau_enum *, u32 value); |
44 | const struct nouveau_enum * | ||
45 | nouveau_enum_find(const struct nouveau_enum *, u32 value); | ||
46 | |||
43 | int nouveau_ratelimit(void); | 47 | int nouveau_ratelimit(void); |
44 | 48 | ||
45 | #endif | 49 | #endif |
diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.c b/drivers/gpu/drm/nouveau/nouveau_vm.c index 97d82aedf86..0059e6f58a8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vm.c +++ b/drivers/gpu/drm/nouveau/nouveau_vm.c | |||
@@ -28,7 +28,7 @@ | |||
28 | #include "nouveau_vm.h" | 28 | #include "nouveau_vm.h" |
29 | 29 | ||
30 | void | 30 | void |
31 | nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram) | 31 | nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node) |
32 | { | 32 | { |
33 | struct nouveau_vm *vm = vma->vm; | 33 | struct nouveau_vm *vm = vma->vm; |
34 | struct nouveau_mm_node *r; | 34 | struct nouveau_mm_node *r; |
@@ -40,7 +40,8 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram) | |||
40 | u32 max = 1 << (vm->pgt_bits - bits); | 40 | u32 max = 1 << (vm->pgt_bits - bits); |
41 | u32 end, len; | 41 | u32 end, len; |
42 | 42 | ||
43 | list_for_each_entry(r, &vram->regions, rl_entry) { | 43 | delta = 0; |
44 | list_for_each_entry(r, &node->regions, rl_entry) { | ||
44 | u64 phys = (u64)r->offset << 12; | 45 | u64 phys = (u64)r->offset << 12; |
45 | u32 num = r->length >> bits; | 46 | u32 num = r->length >> bits; |
46 | 47 | ||
@@ -52,7 +53,7 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram) | |||
52 | end = max; | 53 | end = max; |
53 | len = end - pte; | 54 | len = end - pte; |
54 | 55 | ||
55 | vm->map(vma, pgt, vram, pte, len, phys); | 56 | vm->map(vma, pgt, node, pte, len, phys, delta); |
56 | 57 | ||
57 | num -= len; | 58 | num -= len; |
58 | pte += len; | 59 | pte += len; |
@@ -60,6 +61,8 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram) | |||
60 | pde++; | 61 | pde++; |
61 | pte = 0; | 62 | pte = 0; |
62 | } | 63 | } |
64 | |||
65 | delta += (u64)len << vma->node->type; | ||
63 | } | 66 | } |
64 | } | 67 | } |
65 | 68 | ||
@@ -67,14 +70,14 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram) | |||
67 | } | 70 | } |
68 | 71 | ||
69 | void | 72 | void |
70 | nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_vram *vram) | 73 | nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_mem *node) |
71 | { | 74 | { |
72 | nouveau_vm_map_at(vma, 0, vram); | 75 | nouveau_vm_map_at(vma, 0, node); |
73 | } | 76 | } |
74 | 77 | ||
75 | void | 78 | void |
76 | nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, | 79 | nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, |
77 | dma_addr_t *list) | 80 | struct nouveau_mem *mem, dma_addr_t *list) |
78 | { | 81 | { |
79 | struct nouveau_vm *vm = vma->vm; | 82 | struct nouveau_vm *vm = vma->vm; |
80 | int big = vma->node->type != vm->spg_shift; | 83 | int big = vma->node->type != vm->spg_shift; |
@@ -94,7 +97,7 @@ nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, | |||
94 | end = max; | 97 | end = max; |
95 | len = end - pte; | 98 | len = end - pte; |
96 | 99 | ||
97 | vm->map_sg(vma, pgt, pte, list, len); | 100 | vm->map_sg(vma, pgt, mem, pte, len, list); |
98 | 101 | ||
99 | num -= len; | 102 | num -= len; |
100 | pte += len; | 103 | pte += len; |
@@ -311,18 +314,7 @@ nouveau_vm_new(struct drm_device *dev, u64 offset, u64 length, u64 mm_offset, | |||
311 | vm->spg_shift = 12; | 314 | vm->spg_shift = 12; |
312 | vm->lpg_shift = 17; | 315 | vm->lpg_shift = 17; |
313 | pgt_bits = 27; | 316 | pgt_bits = 27; |
314 | 317 | block = 4096; | |
315 | /* Should be 4096 everywhere, this is a hack that's | ||
316 | * currently necessary to avoid an elusive bug that | ||
317 | * causes corruption when mixing small/large pages | ||
318 | */ | ||
319 | if (length < (1ULL << 40)) | ||
320 | block = 4096; | ||
321 | else { | ||
322 | block = (1 << pgt_bits); | ||
323 | if (length < block) | ||
324 | block = length; | ||
325 | } | ||
326 | } else { | 318 | } else { |
327 | kfree(vm); | 319 | kfree(vm); |
328 | return -ENOSYS; | 320 | return -ENOSYS; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.h b/drivers/gpu/drm/nouveau/nouveau_vm.h index e1193515771..2e06b55cfdc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vm.h +++ b/drivers/gpu/drm/nouveau/nouveau_vm.h | |||
@@ -67,9 +67,10 @@ struct nouveau_vm { | |||
67 | void (*map_pgt)(struct nouveau_gpuobj *pgd, u32 pde, | 67 | void (*map_pgt)(struct nouveau_gpuobj *pgd, u32 pde, |
68 | struct nouveau_gpuobj *pgt[2]); | 68 | struct nouveau_gpuobj *pgt[2]); |
69 | void (*map)(struct nouveau_vma *, struct nouveau_gpuobj *, | 69 | void (*map)(struct nouveau_vma *, struct nouveau_gpuobj *, |
70 | struct nouveau_vram *, u32 pte, u32 cnt, u64 phys); | 70 | struct nouveau_mem *, u32 pte, u32 cnt, |
71 | u64 phys, u64 delta); | ||
71 | void (*map_sg)(struct nouveau_vma *, struct nouveau_gpuobj *, | 72 | void (*map_sg)(struct nouveau_vma *, struct nouveau_gpuobj *, |
72 | u32 pte, dma_addr_t *, u32 cnt); | 73 | struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); |
73 | void (*unmap)(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt); | 74 | void (*unmap)(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt); |
74 | void (*flush)(struct nouveau_vm *); | 75 | void (*flush)(struct nouveau_vm *); |
75 | }; | 76 | }; |
@@ -82,20 +83,20 @@ int nouveau_vm_ref(struct nouveau_vm *, struct nouveau_vm **, | |||
82 | int nouveau_vm_get(struct nouveau_vm *, u64 size, u32 page_shift, | 83 | int nouveau_vm_get(struct nouveau_vm *, u64 size, u32 page_shift, |
83 | u32 access, struct nouveau_vma *); | 84 | u32 access, struct nouveau_vma *); |
84 | void nouveau_vm_put(struct nouveau_vma *); | 85 | void nouveau_vm_put(struct nouveau_vma *); |
85 | void nouveau_vm_map(struct nouveau_vma *, struct nouveau_vram *); | 86 | void nouveau_vm_map(struct nouveau_vma *, struct nouveau_mem *); |
86 | void nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_vram *); | 87 | void nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_mem *); |
87 | void nouveau_vm_unmap(struct nouveau_vma *); | 88 | void nouveau_vm_unmap(struct nouveau_vma *); |
88 | void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length); | 89 | void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length); |
89 | void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length, | 90 | void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length, |
90 | dma_addr_t *); | 91 | struct nouveau_mem *, dma_addr_t *); |
91 | 92 | ||
92 | /* nv50_vm.c */ | 93 | /* nv50_vm.c */ |
93 | void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, | 94 | void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, |
94 | struct nouveau_gpuobj *pgt[2]); | 95 | struct nouveau_gpuobj *pgt[2]); |
95 | void nv50_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *, | 96 | void nv50_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *, |
96 | struct nouveau_vram *, u32 pte, u32 cnt, u64 phys); | 97 | struct nouveau_mem *, u32 pte, u32 cnt, u64 phys, u64 delta); |
97 | void nv50_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *, | 98 | void nv50_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *, |
98 | u32 pte, dma_addr_t *, u32 cnt); | 99 | struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); |
99 | void nv50_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt); | 100 | void nv50_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt); |
100 | void nv50_vm_flush(struct nouveau_vm *); | 101 | void nv50_vm_flush(struct nouveau_vm *); |
101 | void nv50_vm_flush_engine(struct drm_device *, int engine); | 102 | void nv50_vm_flush_engine(struct drm_device *, int engine); |
@@ -104,9 +105,9 @@ void nv50_vm_flush_engine(struct drm_device *, int engine); | |||
104 | void nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, | 105 | void nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, |
105 | struct nouveau_gpuobj *pgt[2]); | 106 | struct nouveau_gpuobj *pgt[2]); |
106 | void nvc0_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *, | 107 | void nvc0_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *, |
107 | struct nouveau_vram *, u32 pte, u32 cnt, u64 phys); | 108 | struct nouveau_mem *, u32 pte, u32 cnt, u64 phys, u64 delta); |
108 | void nvc0_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *, | 109 | void nvc0_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *, |
109 | u32 pte, dma_addr_t *, u32 cnt); | 110 | struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); |
110 | void nvc0_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt); | 111 | void nvc0_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt); |
111 | void nvc0_vm_flush(struct nouveau_vm *); | 112 | void nvc0_vm_flush(struct nouveau_vm *); |
112 | 113 | ||
diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c index 297505eb98d..a260fbbe3d9 100644 --- a/drivers/gpu/drm/nouveau/nv04_crtc.c +++ b/drivers/gpu/drm/nouveau/nv04_crtc.c | |||
@@ -1031,7 +1031,7 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num) | |||
1031 | drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); | 1031 | drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); |
1032 | 1032 | ||
1033 | ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, | 1033 | ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, |
1034 | 0, 0x0000, false, true, &nv_crtc->cursor.nvbo); | 1034 | 0, 0x0000, &nv_crtc->cursor.nvbo); |
1035 | if (!ret) { | 1035 | if (!ret) { |
1036 | ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); | 1036 | ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); |
1037 | if (!ret) | 1037 | if (!ret) |
diff --git a/drivers/gpu/drm/nouveau/nv04_fifo.c b/drivers/gpu/drm/nouveau/nv04_fifo.c index f89d104698d..db465a3ee1b 100644 --- a/drivers/gpu/drm/nouveau/nv04_fifo.c +++ b/drivers/gpu/drm/nouveau/nv04_fifo.c | |||
@@ -379,6 +379,15 @@ out: | |||
379 | return handled; | 379 | return handled; |
380 | } | 380 | } |
381 | 381 | ||
382 | static const char *nv_dma_state_err(u32 state) | ||
383 | { | ||
384 | static const char * const desc[] = { | ||
385 | "NONE", "CALL_SUBR_ACTIVE", "INVALID_MTHD", "RET_SUBR_INACTIVE", | ||
386 | "INVALID_CMD", "IB_EMPTY"/* NV50+ */, "MEM_FAULT", "UNK" | ||
387 | }; | ||
388 | return desc[(state >> 29) & 0x7]; | ||
389 | } | ||
390 | |||
382 | void | 391 | void |
383 | nv04_fifo_isr(struct drm_device *dev) | 392 | nv04_fifo_isr(struct drm_device *dev) |
384 | { | 393 | { |
@@ -460,9 +469,10 @@ nv04_fifo_isr(struct drm_device *dev) | |||
460 | if (nouveau_ratelimit()) | 469 | if (nouveau_ratelimit()) |
461 | NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%02x%08x " | 470 | NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%02x%08x " |
462 | "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x " | 471 | "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x " |
463 | "State 0x%08x Push 0x%08x\n", | 472 | "State 0x%08x (err: %s) Push 0x%08x\n", |
464 | chid, ho_get, dma_get, ho_put, | 473 | chid, ho_get, dma_get, ho_put, |
465 | dma_put, ib_get, ib_put, state, | 474 | dma_put, ib_get, ib_put, state, |
475 | nv_dma_state_err(state), | ||
466 | push); | 476 | push); |
467 | 477 | ||
468 | /* METHOD_COUNT, in DMA_STATE on earlier chipsets */ | 478 | /* METHOD_COUNT, in DMA_STATE on earlier chipsets */ |
@@ -476,8 +486,9 @@ nv04_fifo_isr(struct drm_device *dev) | |||
476 | } | 486 | } |
477 | } else { | 487 | } else { |
478 | NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%08x " | 488 | NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%08x " |
479 | "Put 0x%08x State 0x%08x Push 0x%08x\n", | 489 | "Put 0x%08x State 0x%08x (err: %s) Push 0x%08x\n", |
480 | chid, dma_get, dma_put, state, push); | 490 | chid, dma_get, dma_put, state, |
491 | nv_dma_state_err(state), push); | ||
481 | 492 | ||
482 | if (dma_get != dma_put) | 493 | if (dma_get != dma_put) |
483 | nv_wr32(dev, 0x003244, dma_put); | 494 | nv_wr32(dev, 0x003244, dma_put); |
@@ -505,7 +516,7 @@ nv04_fifo_isr(struct drm_device *dev) | |||
505 | 516 | ||
506 | if (dev_priv->card_type == NV_50) { | 517 | if (dev_priv->card_type == NV_50) { |
507 | if (status & 0x00000010) { | 518 | if (status & 0x00000010) { |
508 | nv50_fb_vm_trap(dev, 1, "PFIFO_BAR_FAULT"); | 519 | nv50_fb_vm_trap(dev, nouveau_ratelimit()); |
509 | status &= ~0x00000010; | 520 | status &= ~0x00000010; |
510 | nv_wr32(dev, 0x002100, 0x00000010); | 521 | nv_wr32(dev, 0x002100, 0x00000010); |
511 | } | 522 | } |
diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c b/drivers/gpu/drm/nouveau/nv17_tv.c index 28119fd19d0..3900cebba56 100644 --- a/drivers/gpu/drm/nouveau/nv17_tv.c +++ b/drivers/gpu/drm/nouveau/nv17_tv.c | |||
@@ -197,10 +197,12 @@ static int nv17_tv_get_ld_modes(struct drm_encoder *encoder, | |||
197 | struct drm_connector *connector) | 197 | struct drm_connector *connector) |
198 | { | 198 | { |
199 | struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); | 199 | struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); |
200 | struct drm_display_mode *mode, *tv_mode; | 200 | const struct drm_display_mode *tv_mode; |
201 | int n = 0; | 201 | int n = 0; |
202 | 202 | ||
203 | for (tv_mode = nv17_tv_modes; tv_mode->hdisplay; tv_mode++) { | 203 | for (tv_mode = nv17_tv_modes; tv_mode->hdisplay; tv_mode++) { |
204 | struct drm_display_mode *mode; | ||
205 | |||
204 | mode = drm_mode_duplicate(encoder->dev, tv_mode); | 206 | mode = drm_mode_duplicate(encoder->dev, tv_mode); |
205 | 207 | ||
206 | mode->clock = tv_norm->tv_enc_mode.vrefresh * | 208 | mode->clock = tv_norm->tv_enc_mode.vrefresh * |
diff --git a/drivers/gpu/drm/nouveau/nv17_tv.h b/drivers/gpu/drm/nouveau/nv17_tv.h index 6bf03840f9e..622e7222168 100644 --- a/drivers/gpu/drm/nouveau/nv17_tv.h +++ b/drivers/gpu/drm/nouveau/nv17_tv.h | |||
@@ -112,7 +112,7 @@ extern struct nv17_tv_norm_params { | |||
112 | } nv17_tv_norms[NUM_TV_NORMS]; | 112 | } nv17_tv_norms[NUM_TV_NORMS]; |
113 | #define get_tv_norm(enc) (&nv17_tv_norms[to_tv_enc(enc)->tv_norm]) | 113 | #define get_tv_norm(enc) (&nv17_tv_norms[to_tv_enc(enc)->tv_norm]) |
114 | 114 | ||
115 | extern struct drm_display_mode nv17_tv_modes[]; | 115 | extern const struct drm_display_mode nv17_tv_modes[]; |
116 | 116 | ||
117 | static inline int interpolate(int y0, int y1, int y2, int x) | 117 | static inline int interpolate(int y0, int y1, int y2, int x) |
118 | { | 118 | { |
diff --git a/drivers/gpu/drm/nouveau/nv17_tv_modes.c b/drivers/gpu/drm/nouveau/nv17_tv_modes.c index 9d3893c50a4..4d1d29f6030 100644 --- a/drivers/gpu/drm/nouveau/nv17_tv_modes.c +++ b/drivers/gpu/drm/nouveau/nv17_tv_modes.c | |||
@@ -438,7 +438,7 @@ void nv17_tv_state_load(struct drm_device *dev, struct nv17_tv_state *state) | |||
438 | 438 | ||
439 | /* Timings similar to the ones the blob sets */ | 439 | /* Timings similar to the ones the blob sets */ |
440 | 440 | ||
441 | struct drm_display_mode nv17_tv_modes[] = { | 441 | const struct drm_display_mode nv17_tv_modes[] = { |
442 | { DRM_MODE("320x200", DRM_MODE_TYPE_DRIVER, 0, | 442 | { DRM_MODE("320x200", DRM_MODE_TYPE_DRIVER, 0, |
443 | 320, 344, 392, 560, 0, 200, 200, 202, 220, 0, | 443 | 320, 344, 392, 560, 0, 200, 200, 202, 220, 0, |
444 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC | 444 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
diff --git a/drivers/gpu/drm/nouveau/nv40_fb.c b/drivers/gpu/drm/nouveau/nv40_fb.c index f3d9c0505f7..f0ac2a768c6 100644 --- a/drivers/gpu/drm/nouveau/nv40_fb.c +++ b/drivers/gpu/drm/nouveau/nv40_fb.c | |||
@@ -24,6 +24,53 @@ nv40_fb_set_tile_region(struct drm_device *dev, int i) | |||
24 | } | 24 | } |
25 | } | 25 | } |
26 | 26 | ||
27 | static void | ||
28 | nv40_fb_init_gart(struct drm_device *dev) | ||
29 | { | ||
30 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
31 | struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma; | ||
32 | |||
33 | if (dev_priv->gart_info.type != NOUVEAU_GART_HW) { | ||
34 | nv_wr32(dev, 0x100800, 0x00000001); | ||
35 | return; | ||
36 | } | ||
37 | |||
38 | nv_wr32(dev, 0x100800, gart->pinst | 0x00000002); | ||
39 | nv_mask(dev, 0x10008c, 0x00000100, 0x00000100); | ||
40 | nv_wr32(dev, 0x100820, 0x00000000); | ||
41 | } | ||
42 | |||
43 | static void | ||
44 | nv44_fb_init_gart(struct drm_device *dev) | ||
45 | { | ||
46 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
47 | struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma; | ||
48 | u32 vinst; | ||
49 | |||
50 | if (dev_priv->gart_info.type != NOUVEAU_GART_HW) { | ||
51 | nv_wr32(dev, 0x100850, 0x80000000); | ||
52 | nv_wr32(dev, 0x100800, 0x00000001); | ||
53 | return; | ||
54 | } | ||
55 | |||
56 | /* calculate vram address of this PRAMIN block, object | ||
57 | * must be allocated on 512KiB alignment, and not exceed | ||
58 | * a total size of 512KiB for this to work correctly | ||
59 | */ | ||
60 | vinst = nv_rd32(dev, 0x10020c); | ||
61 | vinst -= ((gart->pinst >> 19) + 1) << 19; | ||
62 | |||
63 | nv_wr32(dev, 0x100850, 0x80000000); | ||
64 | nv_wr32(dev, 0x100818, dev_priv->gart_info.dummy.addr); | ||
65 | |||
66 | nv_wr32(dev, 0x100804, dev_priv->gart_info.aper_size); | ||
67 | nv_wr32(dev, 0x100850, 0x00008000); | ||
68 | nv_mask(dev, 0x10008c, 0x00000200, 0x00000200); | ||
69 | nv_wr32(dev, 0x100820, 0x00000000); | ||
70 | nv_wr32(dev, 0x10082c, 0x00000001); | ||
71 | nv_wr32(dev, 0x100800, vinst | 0x00000010); | ||
72 | } | ||
73 | |||
27 | int | 74 | int |
28 | nv40_fb_init(struct drm_device *dev) | 75 | nv40_fb_init(struct drm_device *dev) |
29 | { | 76 | { |
@@ -32,12 +79,12 @@ nv40_fb_init(struct drm_device *dev) | |||
32 | uint32_t tmp; | 79 | uint32_t tmp; |
33 | int i; | 80 | int i; |
34 | 81 | ||
35 | /* This is strictly a NV4x register (don't know about NV5x). */ | 82 | if (dev_priv->chipset != 0x40 && dev_priv->chipset != 0x45) { |
36 | /* The blob sets these to all kinds of values, and they mess up our setup. */ | 83 | if (nv44_graph_class(dev)) |
37 | /* I got value 0x52802 instead. For some cards the blob even sets it back to 0x1. */ | 84 | nv44_fb_init_gart(dev); |
38 | /* Note: the blob doesn't read this value, so i'm pretty sure this is safe for all cards. */ | 85 | else |
39 | /* Any idea what this is? */ | 86 | nv40_fb_init_gart(dev); |
40 | nv_wr32(dev, NV40_PFB_UNK_800, 0x1); | 87 | } |
41 | 88 | ||
42 | switch (dev_priv->chipset) { | 89 | switch (dev_priv->chipset) { |
43 | case 0x40: | 90 | case 0x40: |
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c index 9023c4dbb44..2b9984027f4 100644 --- a/drivers/gpu/drm/nouveau/nv50_crtc.c +++ b/drivers/gpu/drm/nouveau/nv50_crtc.c | |||
@@ -65,7 +65,7 @@ nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked) | |||
65 | { | 65 | { |
66 | struct drm_device *dev = nv_crtc->base.dev; | 66 | struct drm_device *dev = nv_crtc->base.dev; |
67 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 67 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
68 | struct nouveau_channel *evo = dev_priv->evo; | 68 | struct nouveau_channel *evo = nv50_display(dev)->master; |
69 | int index = nv_crtc->index, ret; | 69 | int index = nv_crtc->index, ret; |
70 | 70 | ||
71 | NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); | 71 | NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); |
@@ -135,8 +135,7 @@ static int | |||
135 | nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool on, bool update) | 135 | nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool on, bool update) |
136 | { | 136 | { |
137 | struct drm_device *dev = nv_crtc->base.dev; | 137 | struct drm_device *dev = nv_crtc->base.dev; |
138 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 138 | struct nouveau_channel *evo = nv50_display(dev)->master; |
139 | struct nouveau_channel *evo = dev_priv->evo; | ||
140 | int ret; | 139 | int ret; |
141 | 140 | ||
142 | NV_DEBUG_KMS(dev, "\n"); | 141 | NV_DEBUG_KMS(dev, "\n"); |
@@ -186,8 +185,7 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, int scaling_mode, bool update) | |||
186 | struct nouveau_connector *nv_connector = | 185 | struct nouveau_connector *nv_connector = |
187 | nouveau_crtc_connector_get(nv_crtc); | 186 | nouveau_crtc_connector_get(nv_crtc); |
188 | struct drm_device *dev = nv_crtc->base.dev; | 187 | struct drm_device *dev = nv_crtc->base.dev; |
189 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 188 | struct nouveau_channel *evo = nv50_display(dev)->master; |
190 | struct nouveau_channel *evo = dev_priv->evo; | ||
191 | struct drm_display_mode *native_mode = NULL; | 189 | struct drm_display_mode *native_mode = NULL; |
192 | struct drm_display_mode *mode = &nv_crtc->base.mode; | 190 | struct drm_display_mode *mode = &nv_crtc->base.mode; |
193 | uint32_t outX, outY, horiz, vert; | 191 | uint32_t outX, outY, horiz, vert; |
@@ -445,6 +443,42 @@ nv50_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
445 | { | 443 | { |
446 | } | 444 | } |
447 | 445 | ||
446 | static int | ||
447 | nv50_crtc_wait_complete(struct drm_crtc *crtc) | ||
448 | { | ||
449 | struct drm_device *dev = crtc->dev; | ||
450 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
451 | struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; | ||
452 | struct nv50_display *disp = nv50_display(dev); | ||
453 | struct nouveau_channel *evo = disp->master; | ||
454 | u64 start; | ||
455 | int ret; | ||
456 | |||
457 | ret = RING_SPACE(evo, 6); | ||
458 | if (ret) | ||
459 | return ret; | ||
460 | BEGIN_RING(evo, 0, 0x0084, 1); | ||
461 | OUT_RING (evo, 0x80000000); | ||
462 | BEGIN_RING(evo, 0, 0x0080, 1); | ||
463 | OUT_RING (evo, 0); | ||
464 | BEGIN_RING(evo, 0, 0x0084, 1); | ||
465 | OUT_RING (evo, 0x00000000); | ||
466 | |||
467 | nv_wo32(disp->ntfy, 0x000, 0x00000000); | ||
468 | FIRE_RING (evo); | ||
469 | |||
470 | start = ptimer->read(dev); | ||
471 | do { | ||
472 | nv_wr32(dev, 0x61002c, 0x370); | ||
473 | nv_wr32(dev, 0x000140, 1); | ||
474 | |||
475 | if (nv_ro32(disp->ntfy, 0x000)) | ||
476 | return 0; | ||
477 | } while (ptimer->read(dev) - start < 2000000000ULL); | ||
478 | |||
479 | return -EBUSY; | ||
480 | } | ||
481 | |||
448 | static void | 482 | static void |
449 | nv50_crtc_prepare(struct drm_crtc *crtc) | 483 | nv50_crtc_prepare(struct drm_crtc *crtc) |
450 | { | 484 | { |
@@ -453,6 +487,7 @@ nv50_crtc_prepare(struct drm_crtc *crtc) | |||
453 | 487 | ||
454 | NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); | 488 | NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); |
455 | 489 | ||
490 | nv50_display_flip_stop(crtc); | ||
456 | drm_vblank_pre_modeset(dev, nv_crtc->index); | 491 | drm_vblank_pre_modeset(dev, nv_crtc->index); |
457 | nv50_crtc_blank(nv_crtc, true); | 492 | nv50_crtc_blank(nv_crtc, true); |
458 | } | 493 | } |
@@ -461,24 +496,14 @@ static void | |||
461 | nv50_crtc_commit(struct drm_crtc *crtc) | 496 | nv50_crtc_commit(struct drm_crtc *crtc) |
462 | { | 497 | { |
463 | struct drm_device *dev = crtc->dev; | 498 | struct drm_device *dev = crtc->dev; |
464 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
465 | struct nouveau_channel *evo = dev_priv->evo; | ||
466 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 499 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |
467 | int ret; | ||
468 | 500 | ||
469 | NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); | 501 | NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); |
470 | 502 | ||
471 | nv50_crtc_blank(nv_crtc, false); | 503 | nv50_crtc_blank(nv_crtc, false); |
472 | drm_vblank_post_modeset(dev, nv_crtc->index); | 504 | drm_vblank_post_modeset(dev, nv_crtc->index); |
473 | 505 | nv50_crtc_wait_complete(crtc); | |
474 | ret = RING_SPACE(evo, 2); | 506 | nv50_display_flip_next(crtc, crtc->fb, NULL); |
475 | if (ret) { | ||
476 | NV_ERROR(dev, "no space while committing crtc\n"); | ||
477 | return; | ||
478 | } | ||
479 | BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); | ||
480 | OUT_RING (evo, 0); | ||
481 | FIRE_RING (evo); | ||
482 | } | 507 | } |
483 | 508 | ||
484 | static bool | 509 | static bool |
@@ -491,15 +516,15 @@ nv50_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
491 | static int | 516 | static int |
492 | nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, | 517 | nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, |
493 | struct drm_framebuffer *passed_fb, | 518 | struct drm_framebuffer *passed_fb, |
494 | int x, int y, bool update, bool atomic) | 519 | int x, int y, bool atomic) |
495 | { | 520 | { |
496 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 521 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |
497 | struct drm_device *dev = nv_crtc->base.dev; | 522 | struct drm_device *dev = nv_crtc->base.dev; |
498 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 523 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
499 | struct nouveau_channel *evo = dev_priv->evo; | 524 | struct nouveau_channel *evo = nv50_display(dev)->master; |
500 | struct drm_framebuffer *drm_fb = nv_crtc->base.fb; | 525 | struct drm_framebuffer *drm_fb = nv_crtc->base.fb; |
501 | struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb); | 526 | struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb); |
502 | int ret, format; | 527 | int ret; |
503 | 528 | ||
504 | NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); | 529 | NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); |
505 | 530 | ||
@@ -525,28 +550,6 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, | |||
525 | } | 550 | } |
526 | } | 551 | } |
527 | 552 | ||
528 | switch (drm_fb->depth) { | ||
529 | case 8: | ||
530 | format = NV50_EVO_CRTC_FB_DEPTH_8; | ||
531 | break; | ||
532 | case 15: | ||
533 | format = NV50_EVO_CRTC_FB_DEPTH_15; | ||
534 | break; | ||
535 | case 16: | ||
536 | format = NV50_EVO_CRTC_FB_DEPTH_16; | ||
537 | break; | ||
538 | case 24: | ||
539 | case 32: | ||
540 | format = NV50_EVO_CRTC_FB_DEPTH_24; | ||
541 | break; | ||
542 | case 30: | ||
543 | format = NV50_EVO_CRTC_FB_DEPTH_30; | ||
544 | break; | ||
545 | default: | ||
546 | NV_ERROR(dev, "unknown depth %d\n", drm_fb->depth); | ||
547 | return -EINVAL; | ||
548 | } | ||
549 | |||
550 | nv_crtc->fb.offset = fb->nvbo->bo.mem.start << PAGE_SHIFT; | 553 | nv_crtc->fb.offset = fb->nvbo->bo.mem.start << PAGE_SHIFT; |
551 | nv_crtc->fb.tile_flags = nouveau_bo_tile_layout(fb->nvbo); | 554 | nv_crtc->fb.tile_flags = nouveau_bo_tile_layout(fb->nvbo); |
552 | nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8; | 555 | nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8; |
@@ -556,14 +559,7 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, | |||
556 | return ret; | 559 | return ret; |
557 | 560 | ||
558 | BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_DMA), 1); | 561 | BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_DMA), 1); |
559 | if (nv_crtc->fb.tile_flags == 0x7a00 || | 562 | OUT_RING (evo, fb->r_dma); |
560 | nv_crtc->fb.tile_flags == 0xfe00) | ||
561 | OUT_RING(evo, NvEvoFB32); | ||
562 | else | ||
563 | if (nv_crtc->fb.tile_flags == 0x7000) | ||
564 | OUT_RING(evo, NvEvoFB16); | ||
565 | else | ||
566 | OUT_RING(evo, NvEvoVRAM_LP); | ||
567 | } | 563 | } |
568 | 564 | ||
569 | ret = RING_SPACE(evo, 12); | 565 | ret = RING_SPACE(evo, 12); |
@@ -571,45 +567,26 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, | |||
571 | return ret; | 567 | return ret; |
572 | 568 | ||
573 | BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_OFFSET), 5); | 569 | BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_OFFSET), 5); |
574 | OUT_RING(evo, nv_crtc->fb.offset >> 8); | 570 | OUT_RING (evo, nv_crtc->fb.offset >> 8); |
575 | OUT_RING(evo, 0); | 571 | OUT_RING (evo, 0); |
576 | OUT_RING(evo, (drm_fb->height << 16) | drm_fb->width); | 572 | OUT_RING (evo, (drm_fb->height << 16) | drm_fb->width); |
577 | if (!nv_crtc->fb.tile_flags) { | 573 | OUT_RING (evo, fb->r_pitch); |
578 | OUT_RING(evo, drm_fb->pitch | (1 << 20)); | 574 | OUT_RING (evo, fb->r_format); |
579 | } else { | ||
580 | u32 tile_mode = fb->nvbo->tile_mode; | ||
581 | if (dev_priv->card_type >= NV_C0) | ||
582 | tile_mode >>= 4; | ||
583 | OUT_RING(evo, ((drm_fb->pitch / 4) << 4) | tile_mode); | ||
584 | } | ||
585 | if (dev_priv->chipset == 0x50) | ||
586 | OUT_RING(evo, (nv_crtc->fb.tile_flags << 8) | format); | ||
587 | else | ||
588 | OUT_RING(evo, format); | ||
589 | 575 | ||
590 | BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CLUT_MODE), 1); | 576 | BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CLUT_MODE), 1); |
591 | OUT_RING(evo, fb->base.depth == 8 ? | 577 | OUT_RING (evo, fb->base.depth == 8 ? |
592 | NV50_EVO_CRTC_CLUT_MODE_OFF : NV50_EVO_CRTC_CLUT_MODE_ON); | 578 | NV50_EVO_CRTC_CLUT_MODE_OFF : NV50_EVO_CRTC_CLUT_MODE_ON); |
593 | 579 | ||
594 | BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, COLOR_CTRL), 1); | 580 | BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, COLOR_CTRL), 1); |
595 | OUT_RING(evo, NV50_EVO_CRTC_COLOR_CTRL_COLOR); | 581 | OUT_RING (evo, NV50_EVO_CRTC_COLOR_CTRL_COLOR); |
596 | BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_POS), 1); | 582 | BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_POS), 1); |
597 | OUT_RING(evo, (y << 16) | x); | 583 | OUT_RING (evo, (y << 16) | x); |
598 | 584 | ||
599 | if (nv_crtc->lut.depth != fb->base.depth) { | 585 | if (nv_crtc->lut.depth != fb->base.depth) { |
600 | nv_crtc->lut.depth = fb->base.depth; | 586 | nv_crtc->lut.depth = fb->base.depth; |
601 | nv50_crtc_lut_load(crtc); | 587 | nv50_crtc_lut_load(crtc); |
602 | } | 588 | } |
603 | 589 | ||
604 | if (update) { | ||
605 | ret = RING_SPACE(evo, 2); | ||
606 | if (ret) | ||
607 | return ret; | ||
608 | BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); | ||
609 | OUT_RING(evo, 0); | ||
610 | FIRE_RING(evo); | ||
611 | } | ||
612 | |||
613 | return 0; | 590 | return 0; |
614 | } | 591 | } |
615 | 592 | ||
@@ -619,8 +596,7 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
619 | struct drm_framebuffer *old_fb) | 596 | struct drm_framebuffer *old_fb) |
620 | { | 597 | { |
621 | struct drm_device *dev = crtc->dev; | 598 | struct drm_device *dev = crtc->dev; |
622 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 599 | struct nouveau_channel *evo = nv50_display(dev)->master; |
623 | struct nouveau_channel *evo = dev_priv->evo; | ||
624 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 600 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |
625 | struct nouveau_connector *nv_connector = NULL; | 601 | struct nouveau_connector *nv_connector = NULL; |
626 | uint32_t hsync_dur, vsync_dur, hsync_start_to_end, vsync_start_to_end; | 602 | uint32_t hsync_dur, vsync_dur, hsync_start_to_end, vsync_start_to_end; |
@@ -700,14 +676,25 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
700 | nv_crtc->set_dither(nv_crtc, nv_connector->use_dithering, false); | 676 | nv_crtc->set_dither(nv_crtc, nv_connector->use_dithering, false); |
701 | nv_crtc->set_scale(nv_crtc, nv_connector->scaling_mode, false); | 677 | nv_crtc->set_scale(nv_crtc, nv_connector->scaling_mode, false); |
702 | 678 | ||
703 | return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false, false); | 679 | return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false); |
704 | } | 680 | } |
705 | 681 | ||
706 | static int | 682 | static int |
707 | nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, | 683 | nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, |
708 | struct drm_framebuffer *old_fb) | 684 | struct drm_framebuffer *old_fb) |
709 | { | 685 | { |
710 | return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, true, false); | 686 | int ret; |
687 | |||
688 | nv50_display_flip_stop(crtc); | ||
689 | ret = nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false); | ||
690 | if (ret) | ||
691 | return ret; | ||
692 | |||
693 | ret = nv50_crtc_wait_complete(crtc); | ||
694 | if (ret) | ||
695 | return ret; | ||
696 | |||
697 | return nv50_display_flip_next(crtc, crtc->fb, NULL); | ||
711 | } | 698 | } |
712 | 699 | ||
713 | static int | 700 | static int |
@@ -715,7 +702,14 @@ nv50_crtc_mode_set_base_atomic(struct drm_crtc *crtc, | |||
715 | struct drm_framebuffer *fb, | 702 | struct drm_framebuffer *fb, |
716 | int x, int y, enum mode_set_atomic state) | 703 | int x, int y, enum mode_set_atomic state) |
717 | { | 704 | { |
718 | return nv50_crtc_do_mode_set_base(crtc, fb, x, y, true, true); | 705 | int ret; |
706 | |||
707 | nv50_display_flip_stop(crtc); | ||
708 | ret = nv50_crtc_do_mode_set_base(crtc, fb, x, y, true); | ||
709 | if (ret) | ||
710 | return ret; | ||
711 | |||
712 | return nv50_crtc_wait_complete(crtc); | ||
719 | } | 713 | } |
720 | 714 | ||
721 | static const struct drm_crtc_helper_funcs nv50_crtc_helper_funcs = { | 715 | static const struct drm_crtc_helper_funcs nv50_crtc_helper_funcs = { |
@@ -758,7 +752,7 @@ nv50_crtc_create(struct drm_device *dev, int index) | |||
758 | nv_crtc->lut.depth = 0; | 752 | nv_crtc->lut.depth = 0; |
759 | 753 | ||
760 | ret = nouveau_bo_new(dev, NULL, 4096, 0x100, TTM_PL_FLAG_VRAM, | 754 | ret = nouveau_bo_new(dev, NULL, 4096, 0x100, TTM_PL_FLAG_VRAM, |
761 | 0, 0x0000, false, true, &nv_crtc->lut.nvbo); | 755 | 0, 0x0000, &nv_crtc->lut.nvbo); |
762 | if (!ret) { | 756 | if (!ret) { |
763 | ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM); | 757 | ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM); |
764 | if (!ret) | 758 | if (!ret) |
@@ -784,7 +778,7 @@ nv50_crtc_create(struct drm_device *dev, int index) | |||
784 | drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); | 778 | drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); |
785 | 779 | ||
786 | ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, | 780 | ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, |
787 | 0, 0x0000, false, true, &nv_crtc->cursor.nvbo); | 781 | 0, 0x0000, &nv_crtc->cursor.nvbo); |
788 | if (!ret) { | 782 | if (!ret) { |
789 | ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); | 783 | ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); |
790 | if (!ret) | 784 | if (!ret) |
diff --git a/drivers/gpu/drm/nouveau/nv50_cursor.c b/drivers/gpu/drm/nouveau/nv50_cursor.c index 1b9ce3021aa..9752c35bb84 100644 --- a/drivers/gpu/drm/nouveau/nv50_cursor.c +++ b/drivers/gpu/drm/nouveau/nv50_cursor.c | |||
@@ -36,9 +36,9 @@ | |||
36 | static void | 36 | static void |
37 | nv50_cursor_show(struct nouveau_crtc *nv_crtc, bool update) | 37 | nv50_cursor_show(struct nouveau_crtc *nv_crtc, bool update) |
38 | { | 38 | { |
39 | struct drm_nouveau_private *dev_priv = nv_crtc->base.dev->dev_private; | ||
40 | struct nouveau_channel *evo = dev_priv->evo; | ||
41 | struct drm_device *dev = nv_crtc->base.dev; | 39 | struct drm_device *dev = nv_crtc->base.dev; |
40 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
41 | struct nouveau_channel *evo = nv50_display(dev)->master; | ||
42 | int ret; | 42 | int ret; |
43 | 43 | ||
44 | NV_DEBUG_KMS(dev, "\n"); | 44 | NV_DEBUG_KMS(dev, "\n"); |
@@ -71,9 +71,9 @@ nv50_cursor_show(struct nouveau_crtc *nv_crtc, bool update) | |||
71 | static void | 71 | static void |
72 | nv50_cursor_hide(struct nouveau_crtc *nv_crtc, bool update) | 72 | nv50_cursor_hide(struct nouveau_crtc *nv_crtc, bool update) |
73 | { | 73 | { |
74 | struct drm_nouveau_private *dev_priv = nv_crtc->base.dev->dev_private; | ||
75 | struct nouveau_channel *evo = dev_priv->evo; | ||
76 | struct drm_device *dev = nv_crtc->base.dev; | 74 | struct drm_device *dev = nv_crtc->base.dev; |
75 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
76 | struct nouveau_channel *evo = nv50_display(dev)->master; | ||
77 | int ret; | 77 | int ret; |
78 | 78 | ||
79 | NV_DEBUG_KMS(dev, "\n"); | 79 | NV_DEBUG_KMS(dev, "\n"); |
diff --git a/drivers/gpu/drm/nouveau/nv50_dac.c b/drivers/gpu/drm/nouveau/nv50_dac.c index 875414b09ad..808f3ec8f82 100644 --- a/drivers/gpu/drm/nouveau/nv50_dac.c +++ b/drivers/gpu/drm/nouveau/nv50_dac.c | |||
@@ -41,8 +41,7 @@ nv50_dac_disconnect(struct drm_encoder *encoder) | |||
41 | { | 41 | { |
42 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 42 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); |
43 | struct drm_device *dev = encoder->dev; | 43 | struct drm_device *dev = encoder->dev; |
44 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 44 | struct nouveau_channel *evo = nv50_display(dev)->master; |
45 | struct nouveau_channel *evo = dev_priv->evo; | ||
46 | int ret; | 45 | int ret; |
47 | 46 | ||
48 | if (!nv_encoder->crtc) | 47 | if (!nv_encoder->crtc) |
@@ -216,8 +215,7 @@ nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
216 | { | 215 | { |
217 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 216 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); |
218 | struct drm_device *dev = encoder->dev; | 217 | struct drm_device *dev = encoder->dev; |
219 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 218 | struct nouveau_channel *evo = nv50_display(dev)->master; |
220 | struct nouveau_channel *evo = dev_priv->evo; | ||
221 | struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); | 219 | struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); |
222 | uint32_t mode_ctl = 0, mode_ctl2 = 0; | 220 | uint32_t mode_ctl = 0, mode_ctl2 = 0; |
223 | int ret; | 221 | int ret; |
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 7cc94ed9ed9..75a376cc342 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c | |||
@@ -24,6 +24,7 @@ | |||
24 | * | 24 | * |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) | ||
27 | #include "nv50_display.h" | 28 | #include "nv50_display.h" |
28 | #include "nouveau_crtc.h" | 29 | #include "nouveau_crtc.h" |
29 | #include "nouveau_encoder.h" | 30 | #include "nouveau_encoder.h" |
@@ -34,6 +35,7 @@ | |||
34 | #include "drm_crtc_helper.h" | 35 | #include "drm_crtc_helper.h" |
35 | 36 | ||
36 | static void nv50_display_isr(struct drm_device *); | 37 | static void nv50_display_isr(struct drm_device *); |
38 | static void nv50_display_bh(unsigned long); | ||
37 | 39 | ||
38 | static inline int | 40 | static inline int |
39 | nv50_sor_nr(struct drm_device *dev) | 41 | nv50_sor_nr(struct drm_device *dev) |
@@ -172,16 +174,16 @@ nv50_display_init(struct drm_device *dev) | |||
172 | ret = nv50_evo_init(dev); | 174 | ret = nv50_evo_init(dev); |
173 | if (ret) | 175 | if (ret) |
174 | return ret; | 176 | return ret; |
175 | evo = dev_priv->evo; | 177 | evo = nv50_display(dev)->master; |
176 | 178 | ||
177 | nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->vinst >> 8) | 9); | 179 | nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->vinst >> 8) | 9); |
178 | 180 | ||
179 | ret = RING_SPACE(evo, 11); | 181 | ret = RING_SPACE(evo, 15); |
180 | if (ret) | 182 | if (ret) |
181 | return ret; | 183 | return ret; |
182 | BEGIN_RING(evo, 0, NV50_EVO_UNK84, 2); | 184 | BEGIN_RING(evo, 0, NV50_EVO_UNK84, 2); |
183 | OUT_RING(evo, NV50_EVO_UNK84_NOTIFY_DISABLED); | 185 | OUT_RING(evo, NV50_EVO_UNK84_NOTIFY_DISABLED); |
184 | OUT_RING(evo, NV50_EVO_DMA_NOTIFY_HANDLE_NONE); | 186 | OUT_RING(evo, NvEvoSync); |
185 | BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, FB_DMA), 1); | 187 | BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, FB_DMA), 1); |
186 | OUT_RING(evo, NV50_EVO_CRTC_FB_DMA_HANDLE_NONE); | 188 | OUT_RING(evo, NV50_EVO_CRTC_FB_DMA_HANDLE_NONE); |
187 | BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK0800), 1); | 189 | BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK0800), 1); |
@@ -190,6 +192,11 @@ nv50_display_init(struct drm_device *dev) | |||
190 | OUT_RING(evo, 0); | 192 | OUT_RING(evo, 0); |
191 | BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK082C), 1); | 193 | BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK082C), 1); |
192 | OUT_RING(evo, 0); | 194 | OUT_RING(evo, 0); |
195 | /* required to make display sync channels not hate life */ | ||
196 | BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK900), 1); | ||
197 | OUT_RING (evo, 0x00000311); | ||
198 | BEGIN_RING(evo, 0, NV50_EVO_CRTC(1, UNK900), 1); | ||
199 | OUT_RING (evo, 0x00000311); | ||
193 | FIRE_RING(evo); | 200 | FIRE_RING(evo); |
194 | if (!nv_wait(dev, 0x640004, 0xffffffff, evo->dma.put << 2)) | 201 | if (!nv_wait(dev, 0x640004, 0xffffffff, evo->dma.put << 2)) |
195 | NV_ERROR(dev, "evo pushbuf stalled\n"); | 202 | NV_ERROR(dev, "evo pushbuf stalled\n"); |
@@ -201,6 +208,8 @@ nv50_display_init(struct drm_device *dev) | |||
201 | static int nv50_display_disable(struct drm_device *dev) | 208 | static int nv50_display_disable(struct drm_device *dev) |
202 | { | 209 | { |
203 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 210 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
211 | struct nv50_display *disp = nv50_display(dev); | ||
212 | struct nouveau_channel *evo = disp->master; | ||
204 | struct drm_crtc *drm_crtc; | 213 | struct drm_crtc *drm_crtc; |
205 | int ret, i; | 214 | int ret, i; |
206 | 215 | ||
@@ -212,12 +221,12 @@ static int nv50_display_disable(struct drm_device *dev) | |||
212 | nv50_crtc_blank(crtc, true); | 221 | nv50_crtc_blank(crtc, true); |
213 | } | 222 | } |
214 | 223 | ||
215 | ret = RING_SPACE(dev_priv->evo, 2); | 224 | ret = RING_SPACE(evo, 2); |
216 | if (ret == 0) { | 225 | if (ret == 0) { |
217 | BEGIN_RING(dev_priv->evo, 0, NV50_EVO_UPDATE, 1); | 226 | BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); |
218 | OUT_RING(dev_priv->evo, 0); | 227 | OUT_RING(evo, 0); |
219 | } | 228 | } |
220 | FIRE_RING(dev_priv->evo); | 229 | FIRE_RING(evo); |
221 | 230 | ||
222 | /* Almost like ack'ing a vblank interrupt, maybe in the spirit of | 231 | /* Almost like ack'ing a vblank interrupt, maybe in the spirit of |
223 | * cleaning up? | 232 | * cleaning up? |
@@ -267,10 +276,16 @@ int nv50_display_create(struct drm_device *dev) | |||
267 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 276 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
268 | struct dcb_table *dcb = &dev_priv->vbios.dcb; | 277 | struct dcb_table *dcb = &dev_priv->vbios.dcb; |
269 | struct drm_connector *connector, *ct; | 278 | struct drm_connector *connector, *ct; |
279 | struct nv50_display *priv; | ||
270 | int ret, i; | 280 | int ret, i; |
271 | 281 | ||
272 | NV_DEBUG_KMS(dev, "\n"); | 282 | NV_DEBUG_KMS(dev, "\n"); |
273 | 283 | ||
284 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
285 | if (!priv) | ||
286 | return -ENOMEM; | ||
287 | dev_priv->engine.display.priv = priv; | ||
288 | |||
274 | /* init basic kernel modesetting */ | 289 | /* init basic kernel modesetting */ |
275 | drm_mode_config_init(dev); | 290 | drm_mode_config_init(dev); |
276 | 291 | ||
@@ -330,7 +345,7 @@ int nv50_display_create(struct drm_device *dev) | |||
330 | } | 345 | } |
331 | } | 346 | } |
332 | 347 | ||
333 | INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh); | 348 | tasklet_init(&priv->tasklet, nv50_display_bh, (unsigned long)dev); |
334 | nouveau_irq_register(dev, 26, nv50_display_isr); | 349 | nouveau_irq_register(dev, 26, nv50_display_isr); |
335 | 350 | ||
336 | ret = nv50_display_init(dev); | 351 | ret = nv50_display_init(dev); |
@@ -345,12 +360,131 @@ int nv50_display_create(struct drm_device *dev) | |||
345 | void | 360 | void |
346 | nv50_display_destroy(struct drm_device *dev) | 361 | nv50_display_destroy(struct drm_device *dev) |
347 | { | 362 | { |
363 | struct nv50_display *disp = nv50_display(dev); | ||
364 | |||
348 | NV_DEBUG_KMS(dev, "\n"); | 365 | NV_DEBUG_KMS(dev, "\n"); |
349 | 366 | ||
350 | drm_mode_config_cleanup(dev); | 367 | drm_mode_config_cleanup(dev); |
351 | 368 | ||
352 | nv50_display_disable(dev); | 369 | nv50_display_disable(dev); |
353 | nouveau_irq_unregister(dev, 26); | 370 | nouveau_irq_unregister(dev, 26); |
371 | kfree(disp); | ||
372 | } | ||
373 | |||
374 | void | ||
375 | nv50_display_flip_stop(struct drm_crtc *crtc) | ||
376 | { | ||
377 | struct nv50_display *disp = nv50_display(crtc->dev); | ||
378 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||
379 | struct nv50_display_crtc *dispc = &disp->crtc[nv_crtc->index]; | ||
380 | struct nouveau_channel *evo = dispc->sync; | ||
381 | int ret; | ||
382 | |||
383 | ret = RING_SPACE(evo, 8); | ||
384 | if (ret) { | ||
385 | WARN_ON(1); | ||
386 | return; | ||
387 | } | ||
388 | |||
389 | BEGIN_RING(evo, 0, 0x0084, 1); | ||
390 | OUT_RING (evo, 0x00000000); | ||
391 | BEGIN_RING(evo, 0, 0x0094, 1); | ||
392 | OUT_RING (evo, 0x00000000); | ||
393 | BEGIN_RING(evo, 0, 0x00c0, 1); | ||
394 | OUT_RING (evo, 0x00000000); | ||
395 | BEGIN_RING(evo, 0, 0x0080, 1); | ||
396 | OUT_RING (evo, 0x00000000); | ||
397 | FIRE_RING (evo); | ||
398 | } | ||
399 | |||
400 | int | ||
401 | nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, | ||
402 | struct nouveau_channel *chan) | ||
403 | { | ||
404 | struct drm_nouveau_private *dev_priv = crtc->dev->dev_private; | ||
405 | struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb); | ||
406 | struct nv50_display *disp = nv50_display(crtc->dev); | ||
407 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||
408 | struct nv50_display_crtc *dispc = &disp->crtc[nv_crtc->index]; | ||
409 | struct nouveau_channel *evo = dispc->sync; | ||
410 | int ret; | ||
411 | |||
412 | ret = RING_SPACE(evo, 24); | ||
413 | if (unlikely(ret)) | ||
414 | return ret; | ||
415 | |||
416 | /* synchronise with the rendering channel, if necessary */ | ||
417 | if (likely(chan)) { | ||
418 | u64 offset = dispc->sem.bo->vma.offset + dispc->sem.offset; | ||
419 | |||
420 | ret = RING_SPACE(chan, 10); | ||
421 | if (ret) { | ||
422 | WIND_RING(evo); | ||
423 | return ret; | ||
424 | } | ||
425 | |||
426 | if (dev_priv->chipset < 0xc0) { | ||
427 | BEGIN_RING(chan, NvSubSw, 0x0060, 2); | ||
428 | OUT_RING (chan, NvEvoSema0 + nv_crtc->index); | ||
429 | OUT_RING (chan, dispc->sem.offset); | ||
430 | BEGIN_RING(chan, NvSubSw, 0x006c, 1); | ||
431 | OUT_RING (chan, 0xf00d0000 | dispc->sem.value); | ||
432 | BEGIN_RING(chan, NvSubSw, 0x0064, 2); | ||
433 | OUT_RING (chan, dispc->sem.offset ^ 0x10); | ||
434 | OUT_RING (chan, 0x74b1e000); | ||
435 | BEGIN_RING(chan, NvSubSw, 0x0060, 1); | ||
436 | if (dev_priv->chipset < 0x84) | ||
437 | OUT_RING (chan, NvSema); | ||
438 | else | ||
439 | OUT_RING (chan, chan->vram_handle); | ||
440 | } else { | ||
441 | BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); | ||
442 | OUT_RING (chan, upper_32_bits(offset)); | ||
443 | OUT_RING (chan, lower_32_bits(offset)); | ||
444 | OUT_RING (chan, 0xf00d0000 | dispc->sem.value); | ||
445 | OUT_RING (chan, 0x1002); | ||
446 | BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); | ||
447 | OUT_RING (chan, upper_32_bits(offset)); | ||
448 | OUT_RING (chan, lower_32_bits(offset ^ 0x10)); | ||
449 | OUT_RING (chan, 0x74b1e000); | ||
450 | OUT_RING (chan, 0x1001); | ||
451 | } | ||
452 | FIRE_RING (chan); | ||
453 | } else { | ||
454 | nouveau_bo_wr32(dispc->sem.bo, dispc->sem.offset / 4, | ||
455 | 0xf00d0000 | dispc->sem.value); | ||
456 | } | ||
457 | |||
458 | /* queue the flip on the crtc's "display sync" channel */ | ||
459 | BEGIN_RING(evo, 0, 0x0100, 1); | ||
460 | OUT_RING (evo, 0xfffe0000); | ||
461 | BEGIN_RING(evo, 0, 0x0084, 5); | ||
462 | OUT_RING (evo, chan ? 0x00000100 : 0x00000010); | ||
463 | OUT_RING (evo, dispc->sem.offset); | ||
464 | OUT_RING (evo, 0xf00d0000 | dispc->sem.value); | ||
465 | OUT_RING (evo, 0x74b1e000); | ||
466 | OUT_RING (evo, NvEvoSync); | ||
467 | BEGIN_RING(evo, 0, 0x00a0, 2); | ||
468 | OUT_RING (evo, 0x00000000); | ||
469 | OUT_RING (evo, 0x00000000); | ||
470 | BEGIN_RING(evo, 0, 0x00c0, 1); | ||
471 | OUT_RING (evo, nv_fb->r_dma); | ||
472 | BEGIN_RING(evo, 0, 0x0110, 2); | ||
473 | OUT_RING (evo, 0x00000000); | ||
474 | OUT_RING (evo, 0x00000000); | ||
475 | BEGIN_RING(evo, 0, 0x0800, 5); | ||
476 | OUT_RING (evo, (nv_fb->nvbo->bo.mem.start << PAGE_SHIFT) >> 8); | ||
477 | OUT_RING (evo, 0); | ||
478 | OUT_RING (evo, (fb->height << 16) | fb->width); | ||
479 | OUT_RING (evo, nv_fb->r_pitch); | ||
480 | OUT_RING (evo, nv_fb->r_format); | ||
481 | BEGIN_RING(evo, 0, 0x0080, 1); | ||
482 | OUT_RING (evo, 0x00000000); | ||
483 | FIRE_RING (evo); | ||
484 | |||
485 | dispc->sem.offset ^= 0x10; | ||
486 | dispc->sem.value++; | ||
487 | return 0; | ||
354 | } | 488 | } |
355 | 489 | ||
356 | static u16 | 490 | static u16 |
@@ -466,11 +600,12 @@ static void | |||
466 | nv50_display_unk10_handler(struct drm_device *dev) | 600 | nv50_display_unk10_handler(struct drm_device *dev) |
467 | { | 601 | { |
468 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 602 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
603 | struct nv50_display *disp = nv50_display(dev); | ||
469 | u32 unk30 = nv_rd32(dev, 0x610030), mc; | 604 | u32 unk30 = nv_rd32(dev, 0x610030), mc; |
470 | int i, crtc, or, type = OUTPUT_ANY; | 605 | int i, crtc, or, type = OUTPUT_ANY; |
471 | 606 | ||
472 | NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); | 607 | NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); |
473 | dev_priv->evo_irq.dcb = NULL; | 608 | disp->irq.dcb = NULL; |
474 | 609 | ||
475 | nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) & ~8); | 610 | nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) & ~8); |
476 | 611 | ||
@@ -541,7 +676,7 @@ nv50_display_unk10_handler(struct drm_device *dev) | |||
541 | 676 | ||
542 | if (dcb->type == type && (dcb->or & (1 << or))) { | 677 | if (dcb->type == type && (dcb->or & (1 << or))) { |
543 | nouveau_bios_run_display_table(dev, dcb, 0, -1); | 678 | nouveau_bios_run_display_table(dev, dcb, 0, -1); |
544 | dev_priv->evo_irq.dcb = dcb; | 679 | disp->irq.dcb = dcb; |
545 | goto ack; | 680 | goto ack; |
546 | } | 681 | } |
547 | } | 682 | } |
@@ -587,15 +722,16 @@ static void | |||
587 | nv50_display_unk20_handler(struct drm_device *dev) | 722 | nv50_display_unk20_handler(struct drm_device *dev) |
588 | { | 723 | { |
589 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 724 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
590 | u32 unk30 = nv_rd32(dev, 0x610030), tmp, pclk, script, mc; | 725 | struct nv50_display *disp = nv50_display(dev); |
726 | u32 unk30 = nv_rd32(dev, 0x610030), tmp, pclk, script, mc = 0; | ||
591 | struct dcb_entry *dcb; | 727 | struct dcb_entry *dcb; |
592 | int i, crtc, or, type = OUTPUT_ANY; | 728 | int i, crtc, or, type = OUTPUT_ANY; |
593 | 729 | ||
594 | NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); | 730 | NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); |
595 | dcb = dev_priv->evo_irq.dcb; | 731 | dcb = disp->irq.dcb; |
596 | if (dcb) { | 732 | if (dcb) { |
597 | nouveau_bios_run_display_table(dev, dcb, 0, -2); | 733 | nouveau_bios_run_display_table(dev, dcb, 0, -2); |
598 | dev_priv->evo_irq.dcb = NULL; | 734 | disp->irq.dcb = NULL; |
599 | } | 735 | } |
600 | 736 | ||
601 | /* CRTC clock change requested? */ | 737 | /* CRTC clock change requested? */ |
@@ -692,9 +828,9 @@ nv50_display_unk20_handler(struct drm_device *dev) | |||
692 | nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL2(or), 0); | 828 | nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL2(or), 0); |
693 | } | 829 | } |
694 | 830 | ||
695 | dev_priv->evo_irq.dcb = dcb; | 831 | disp->irq.dcb = dcb; |
696 | dev_priv->evo_irq.pclk = pclk; | 832 | disp->irq.pclk = pclk; |
697 | dev_priv->evo_irq.script = script; | 833 | disp->irq.script = script; |
698 | 834 | ||
699 | ack: | 835 | ack: |
700 | nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK20); | 836 | nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK20); |
@@ -735,13 +871,13 @@ nv50_display_unk40_dp_set_tmds(struct drm_device *dev, struct dcb_entry *dcb) | |||
735 | static void | 871 | static void |
736 | nv50_display_unk40_handler(struct drm_device *dev) | 872 | nv50_display_unk40_handler(struct drm_device *dev) |
737 | { | 873 | { |
738 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 874 | struct nv50_display *disp = nv50_display(dev); |
739 | struct dcb_entry *dcb = dev_priv->evo_irq.dcb; | 875 | struct dcb_entry *dcb = disp->irq.dcb; |
740 | u16 script = dev_priv->evo_irq.script; | 876 | u16 script = disp->irq.script; |
741 | u32 unk30 = nv_rd32(dev, 0x610030), pclk = dev_priv->evo_irq.pclk; | 877 | u32 unk30 = nv_rd32(dev, 0x610030), pclk = disp->irq.pclk; |
742 | 878 | ||
743 | NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); | 879 | NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); |
744 | dev_priv->evo_irq.dcb = NULL; | 880 | disp->irq.dcb = NULL; |
745 | if (!dcb) | 881 | if (!dcb) |
746 | goto ack; | 882 | goto ack; |
747 | 883 | ||
@@ -754,12 +890,10 @@ ack: | |||
754 | nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) | 8); | 890 | nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) | 8); |
755 | } | 891 | } |
756 | 892 | ||
757 | void | 893 | static void |
758 | nv50_display_irq_handler_bh(struct work_struct *work) | 894 | nv50_display_bh(unsigned long data) |
759 | { | 895 | { |
760 | struct drm_nouveau_private *dev_priv = | 896 | struct drm_device *dev = (struct drm_device *)data; |
761 | container_of(work, struct drm_nouveau_private, irq_work); | ||
762 | struct drm_device *dev = dev_priv->dev; | ||
763 | 897 | ||
764 | for (;;) { | 898 | for (;;) { |
765 | uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0); | 899 | uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0); |
@@ -807,7 +941,7 @@ nv50_display_error_handler(struct drm_device *dev) | |||
807 | static void | 941 | static void |
808 | nv50_display_isr(struct drm_device *dev) | 942 | nv50_display_isr(struct drm_device *dev) |
809 | { | 943 | { |
810 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 944 | struct nv50_display *disp = nv50_display(dev); |
811 | uint32_t delayed = 0; | 945 | uint32_t delayed = 0; |
812 | 946 | ||
813 | while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) { | 947 | while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) { |
@@ -835,8 +969,7 @@ nv50_display_isr(struct drm_device *dev) | |||
835 | NV50_PDISPLAY_INTR_1_CLK_UNK40)); | 969 | NV50_PDISPLAY_INTR_1_CLK_UNK40)); |
836 | if (clock) { | 970 | if (clock) { |
837 | nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); | 971 | nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); |
838 | if (!work_pending(&dev_priv->irq_work)) | 972 | tasklet_schedule(&disp->tasklet); |
839 | queue_work(dev_priv->wq, &dev_priv->irq_work); | ||
840 | delayed |= clock; | 973 | delayed |= clock; |
841 | intr1 &= ~clock; | 974 | intr1 &= ~clock; |
842 | } | 975 | } |
diff --git a/drivers/gpu/drm/nouveau/nv50_display.h b/drivers/gpu/drm/nouveau/nv50_display.h index f0e30b78ef6..c2da503a22a 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.h +++ b/drivers/gpu/drm/nouveau/nv50_display.h | |||
@@ -35,7 +35,36 @@ | |||
35 | #include "nouveau_crtc.h" | 35 | #include "nouveau_crtc.h" |
36 | #include "nv50_evo.h" | 36 | #include "nv50_evo.h" |
37 | 37 | ||
38 | void nv50_display_irq_handler_bh(struct work_struct *work); | 38 | struct nv50_display_crtc { |
39 | struct nouveau_channel *sync; | ||
40 | struct { | ||
41 | struct nouveau_bo *bo; | ||
42 | u32 offset; | ||
43 | u16 value; | ||
44 | } sem; | ||
45 | }; | ||
46 | |||
47 | struct nv50_display { | ||
48 | struct nouveau_channel *master; | ||
49 | struct nouveau_gpuobj *ntfy; | ||
50 | |||
51 | struct nv50_display_crtc crtc[2]; | ||
52 | |||
53 | struct tasklet_struct tasklet; | ||
54 | struct { | ||
55 | struct dcb_entry *dcb; | ||
56 | u16 script; | ||
57 | u32 pclk; | ||
58 | } irq; | ||
59 | }; | ||
60 | |||
61 | static inline struct nv50_display * | ||
62 | nv50_display(struct drm_device *dev) | ||
63 | { | ||
64 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
65 | return dev_priv->engine.display.priv; | ||
66 | } | ||
67 | |||
39 | int nv50_display_early_init(struct drm_device *dev); | 68 | int nv50_display_early_init(struct drm_device *dev); |
40 | void nv50_display_late_takedown(struct drm_device *dev); | 69 | void nv50_display_late_takedown(struct drm_device *dev); |
41 | int nv50_display_create(struct drm_device *dev); | 70 | int nv50_display_create(struct drm_device *dev); |
@@ -44,4 +73,15 @@ void nv50_display_destroy(struct drm_device *dev); | |||
44 | int nv50_crtc_blank(struct nouveau_crtc *, bool blank); | 73 | int nv50_crtc_blank(struct nouveau_crtc *, bool blank); |
45 | int nv50_crtc_set_clock(struct drm_device *, int head, int pclk); | 74 | int nv50_crtc_set_clock(struct drm_device *, int head, int pclk); |
46 | 75 | ||
76 | int nv50_display_flip_next(struct drm_crtc *, struct drm_framebuffer *, | ||
77 | struct nouveau_channel *chan); | ||
78 | void nv50_display_flip_stop(struct drm_crtc *); | ||
79 | |||
80 | int nv50_evo_init(struct drm_device *dev); | ||
81 | void nv50_evo_fini(struct drm_device *dev); | ||
82 | void nv50_evo_dmaobj_init(struct nouveau_gpuobj *, u32 memtype, u64 base, | ||
83 | u64 size); | ||
84 | int nv50_evo_dmaobj_new(struct nouveau_channel *, u32 handle, u32 memtype, | ||
85 | u64 base, u64 size, struct nouveau_gpuobj **); | ||
86 | |||
47 | #endif /* __NV50_DISPLAY_H__ */ | 87 | #endif /* __NV50_DISPLAY_H__ */ |
diff --git a/drivers/gpu/drm/nouveau/nv50_evo.c b/drivers/gpu/drm/nouveau/nv50_evo.c index 0ea090f4244..a2cfaa691e9 100644 --- a/drivers/gpu/drm/nouveau/nv50_evo.c +++ b/drivers/gpu/drm/nouveau/nv50_evo.c | |||
@@ -27,20 +27,17 @@ | |||
27 | #include "nouveau_drv.h" | 27 | #include "nouveau_drv.h" |
28 | #include "nouveau_dma.h" | 28 | #include "nouveau_dma.h" |
29 | #include "nouveau_ramht.h" | 29 | #include "nouveau_ramht.h" |
30 | #include "nv50_display.h" | ||
30 | 31 | ||
31 | static void | 32 | static void |
32 | nv50_evo_channel_del(struct nouveau_channel **pevo) | 33 | nv50_evo_channel_del(struct nouveau_channel **pevo) |
33 | { | 34 | { |
34 | struct drm_nouveau_private *dev_priv; | ||
35 | struct nouveau_channel *evo = *pevo; | 35 | struct nouveau_channel *evo = *pevo; |
36 | 36 | ||
37 | if (!evo) | 37 | if (!evo) |
38 | return; | 38 | return; |
39 | *pevo = NULL; | 39 | *pevo = NULL; |
40 | 40 | ||
41 | dev_priv = evo->dev->dev_private; | ||
42 | dev_priv->evo_alloc &= ~(1 << evo->id); | ||
43 | |||
44 | nouveau_gpuobj_channel_takedown(evo); | 41 | nouveau_gpuobj_channel_takedown(evo); |
45 | nouveau_bo_unmap(evo->pushbuf_bo); | 42 | nouveau_bo_unmap(evo->pushbuf_bo); |
46 | nouveau_bo_ref(NULL, &evo->pushbuf_bo); | 43 | nouveau_bo_ref(NULL, &evo->pushbuf_bo); |
@@ -51,42 +48,61 @@ nv50_evo_channel_del(struct nouveau_channel **pevo) | |||
51 | kfree(evo); | 48 | kfree(evo); |
52 | } | 49 | } |
53 | 50 | ||
51 | void | ||
52 | nv50_evo_dmaobj_init(struct nouveau_gpuobj *obj, u32 memtype, u64 base, u64 size) | ||
53 | { | ||
54 | struct drm_nouveau_private *dev_priv = obj->dev->dev_private; | ||
55 | u32 flags5; | ||
56 | |||
57 | if (dev_priv->chipset < 0xc0) { | ||
58 | /* not supported on 0x50, specified in format mthd */ | ||
59 | if (dev_priv->chipset == 0x50) | ||
60 | memtype = 0; | ||
61 | flags5 = 0x00010000; | ||
62 | } else { | ||
63 | if (memtype & 0x80000000) | ||
64 | flags5 = 0x00000000; /* large pages */ | ||
65 | else | ||
66 | flags5 = 0x00020000; | ||
67 | } | ||
68 | |||
69 | nv50_gpuobj_dma_init(obj, 0, 0x3d, base, size, NV_MEM_TARGET_VRAM, | ||
70 | NV_MEM_ACCESS_RW, (memtype >> 8) & 0xff, 0); | ||
71 | nv_wo32(obj, 0x14, flags5); | ||
72 | dev_priv->engine.instmem.flush(obj->dev); | ||
73 | } | ||
74 | |||
54 | int | 75 | int |
55 | nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 class, u32 name, | 76 | nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 handle, u32 memtype, |
56 | u32 tile_flags, u32 magic_flags, u32 offset, u32 limit, | 77 | u64 base, u64 size, struct nouveau_gpuobj **pobj) |
57 | u32 flags5) | ||
58 | { | 78 | { |
59 | struct drm_nouveau_private *dev_priv = evo->dev->dev_private; | 79 | struct nv50_display *disp = nv50_display(evo->dev); |
60 | struct drm_device *dev = evo->dev; | ||
61 | struct nouveau_gpuobj *obj = NULL; | 80 | struct nouveau_gpuobj *obj = NULL; |
62 | int ret; | 81 | int ret; |
63 | 82 | ||
64 | ret = nouveau_gpuobj_new(dev, dev_priv->evo, 6*4, 32, 0, &obj); | 83 | ret = nouveau_gpuobj_new(evo->dev, disp->master, 6*4, 32, 0, &obj); |
65 | if (ret) | 84 | if (ret) |
66 | return ret; | 85 | return ret; |
67 | obj->engine = NVOBJ_ENGINE_DISPLAY; | 86 | obj->engine = NVOBJ_ENGINE_DISPLAY; |
68 | 87 | ||
69 | nv_wo32(obj, 0, (tile_flags << 22) | (magic_flags << 16) | class); | 88 | nv50_evo_dmaobj_init(obj, memtype, base, size); |
70 | nv_wo32(obj, 4, limit); | ||
71 | nv_wo32(obj, 8, offset); | ||
72 | nv_wo32(obj, 12, 0x00000000); | ||
73 | nv_wo32(obj, 16, 0x00000000); | ||
74 | nv_wo32(obj, 20, flags5); | ||
75 | dev_priv->engine.instmem.flush(dev); | ||
76 | 89 | ||
77 | ret = nouveau_ramht_insert(evo, name, obj); | 90 | ret = nouveau_ramht_insert(evo, handle, obj); |
78 | nouveau_gpuobj_ref(NULL, &obj); | 91 | if (ret) |
79 | if (ret) { | 92 | goto out; |
80 | return ret; | ||
81 | } | ||
82 | 93 | ||
83 | return 0; | 94 | if (pobj) |
95 | nouveau_gpuobj_ref(obj, pobj); | ||
96 | out: | ||
97 | nouveau_gpuobj_ref(NULL, &obj); | ||
98 | return ret; | ||
84 | } | 99 | } |
85 | 100 | ||
86 | static int | 101 | static int |
87 | nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pevo) | 102 | nv50_evo_channel_new(struct drm_device *dev, int chid, |
103 | struct nouveau_channel **pevo) | ||
88 | { | 104 | { |
89 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 105 | struct nv50_display *disp = nv50_display(dev); |
90 | struct nouveau_channel *evo; | 106 | struct nouveau_channel *evo; |
91 | int ret; | 107 | int ret; |
92 | 108 | ||
@@ -95,25 +111,13 @@ nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pevo) | |||
95 | return -ENOMEM; | 111 | return -ENOMEM; |
96 | *pevo = evo; | 112 | *pevo = evo; |
97 | 113 | ||
98 | for (evo->id = 0; evo->id < 5; evo->id++) { | 114 | evo->id = chid; |
99 | if (dev_priv->evo_alloc & (1 << evo->id)) | ||
100 | continue; | ||
101 | |||
102 | dev_priv->evo_alloc |= (1 << evo->id); | ||
103 | break; | ||
104 | } | ||
105 | |||
106 | if (evo->id == 5) { | ||
107 | kfree(evo); | ||
108 | return -ENODEV; | ||
109 | } | ||
110 | |||
111 | evo->dev = dev; | 115 | evo->dev = dev; |
112 | evo->user_get = 4; | 116 | evo->user_get = 4; |
113 | evo->user_put = 0; | 117 | evo->user_put = 0; |
114 | 118 | ||
115 | ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0, | 119 | ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0, |
116 | false, true, &evo->pushbuf_bo); | 120 | &evo->pushbuf_bo); |
117 | if (ret == 0) | 121 | if (ret == 0) |
118 | ret = nouveau_bo_pin(evo->pushbuf_bo, TTM_PL_FLAG_VRAM); | 122 | ret = nouveau_bo_pin(evo->pushbuf_bo, TTM_PL_FLAG_VRAM); |
119 | if (ret) { | 123 | if (ret) { |
@@ -138,8 +142,8 @@ nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pevo) | |||
138 | } | 142 | } |
139 | 143 | ||
140 | /* bind primary evo channel's ramht to the channel */ | 144 | /* bind primary evo channel's ramht to the channel */ |
141 | if (dev_priv->evo && evo != dev_priv->evo) | 145 | if (disp->master && evo != disp->master) |
142 | nouveau_ramht_ref(dev_priv->evo->ramht, &evo->ramht, NULL); | 146 | nouveau_ramht_ref(disp->master->ramht, &evo->ramht, NULL); |
143 | 147 | ||
144 | return 0; | 148 | return 0; |
145 | } | 149 | } |
@@ -212,21 +216,39 @@ nv50_evo_channel_fini(struct nouveau_channel *evo) | |||
212 | } | 216 | } |
213 | } | 217 | } |
214 | 218 | ||
219 | static void | ||
220 | nv50_evo_destroy(struct drm_device *dev) | ||
221 | { | ||
222 | struct nv50_display *disp = nv50_display(dev); | ||
223 | int i; | ||
224 | |||
225 | for (i = 0; i < 2; i++) { | ||
226 | if (disp->crtc[i].sem.bo) { | ||
227 | nouveau_bo_unmap(disp->crtc[i].sem.bo); | ||
228 | nouveau_bo_ref(NULL, &disp->crtc[i].sem.bo); | ||
229 | } | ||
230 | nv50_evo_channel_del(&disp->crtc[i].sync); | ||
231 | } | ||
232 | nouveau_gpuobj_ref(NULL, &disp->ntfy); | ||
233 | nv50_evo_channel_del(&disp->master); | ||
234 | } | ||
235 | |||
215 | static int | 236 | static int |
216 | nv50_evo_create(struct drm_device *dev) | 237 | nv50_evo_create(struct drm_device *dev) |
217 | { | 238 | { |
218 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 239 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
240 | struct nv50_display *disp = nv50_display(dev); | ||
219 | struct nouveau_gpuobj *ramht = NULL; | 241 | struct nouveau_gpuobj *ramht = NULL; |
220 | struct nouveau_channel *evo; | 242 | struct nouveau_channel *evo; |
221 | int ret; | 243 | int ret, i, j; |
222 | 244 | ||
223 | /* create primary evo channel, the one we use for modesetting | 245 | /* create primary evo channel, the one we use for modesetting |
224 | * purporses | 246 | * purporses |
225 | */ | 247 | */ |
226 | ret = nv50_evo_channel_new(dev, &dev_priv->evo); | 248 | ret = nv50_evo_channel_new(dev, 0, &disp->master); |
227 | if (ret) | 249 | if (ret) |
228 | return ret; | 250 | return ret; |
229 | evo = dev_priv->evo; | 251 | evo = disp->master; |
230 | 252 | ||
231 | /* setup object management on it, any other evo channel will | 253 | /* setup object management on it, any other evo channel will |
232 | * use this also as there's no per-channel support on the | 254 | * use this also as there's no per-channel support on the |
@@ -236,109 +258,167 @@ nv50_evo_create(struct drm_device *dev) | |||
236 | NVOBJ_FLAG_ZERO_ALLOC, &evo->ramin); | 258 | NVOBJ_FLAG_ZERO_ALLOC, &evo->ramin); |
237 | if (ret) { | 259 | if (ret) { |
238 | NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret); | 260 | NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret); |
239 | nv50_evo_channel_del(&dev_priv->evo); | 261 | goto err; |
240 | return ret; | ||
241 | } | 262 | } |
242 | 263 | ||
243 | ret = drm_mm_init(&evo->ramin_heap, 0, 32768); | 264 | ret = drm_mm_init(&evo->ramin_heap, 0, 32768); |
244 | if (ret) { | 265 | if (ret) { |
245 | NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret); | 266 | NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret); |
246 | nv50_evo_channel_del(&dev_priv->evo); | 267 | goto err; |
247 | return ret; | ||
248 | } | 268 | } |
249 | 269 | ||
250 | ret = nouveau_gpuobj_new(dev, evo, 4096, 16, 0, &ramht); | 270 | ret = nouveau_gpuobj_new(dev, evo, 4096, 16, 0, &ramht); |
251 | if (ret) { | 271 | if (ret) { |
252 | NV_ERROR(dev, "Unable to allocate EVO RAMHT: %d\n", ret); | 272 | NV_ERROR(dev, "Unable to allocate EVO RAMHT: %d\n", ret); |
253 | nv50_evo_channel_del(&dev_priv->evo); | 273 | goto err; |
254 | return ret; | ||
255 | } | 274 | } |
256 | 275 | ||
257 | ret = nouveau_ramht_new(dev, ramht, &evo->ramht); | 276 | ret = nouveau_ramht_new(dev, ramht, &evo->ramht); |
258 | nouveau_gpuobj_ref(NULL, &ramht); | 277 | nouveau_gpuobj_ref(NULL, &ramht); |
259 | if (ret) { | 278 | if (ret) |
260 | nv50_evo_channel_del(&dev_priv->evo); | 279 | goto err; |
261 | return ret; | 280 | |
262 | } | 281 | /* not sure exactly what this is.. |
282 | * | ||
283 | * the first dword of the structure is used by nvidia to wait on | ||
284 | * full completion of an EVO "update" command. | ||
285 | * | ||
286 | * method 0x8c on the master evo channel will fill a lot more of | ||
287 | * this structure with some undefined info | ||
288 | */ | ||
289 | ret = nouveau_gpuobj_new(dev, disp->master, 0x1000, 0, | ||
290 | NVOBJ_FLAG_ZERO_ALLOC, &disp->ntfy); | ||
291 | if (ret) | ||
292 | goto err; | ||
293 | |||
294 | ret = nv50_evo_dmaobj_new(disp->master, NvEvoSync, 0x0000, | ||
295 | disp->ntfy->vinst, disp->ntfy->size, NULL); | ||
296 | if (ret) | ||
297 | goto err; | ||
263 | 298 | ||
264 | /* create some default objects for the scanout memtypes we support */ | 299 | /* create some default objects for the scanout memtypes we support */ |
265 | if (dev_priv->card_type >= NV_C0) { | 300 | ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM, 0x0000, |
266 | ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB32, 0xfe, 0x19, | 301 | 0, dev_priv->vram_size, NULL); |
267 | 0, 0xffffffff, 0x00000000); | 302 | if (ret) |
268 | if (ret) { | 303 | goto err; |
269 | nv50_evo_channel_del(&dev_priv->evo); | ||
270 | return ret; | ||
271 | } | ||
272 | 304 | ||
273 | ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM, 0, 0x19, | 305 | ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM_LP, 0x80000000, |
274 | 0, dev_priv->vram_size, 0x00020000); | 306 | 0, dev_priv->vram_size, NULL); |
275 | if (ret) { | 307 | if (ret) |
276 | nv50_evo_channel_del(&dev_priv->evo); | 308 | goto err; |
277 | return ret; | ||
278 | } | ||
279 | 309 | ||
280 | ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM_LP, 0, 0x19, | 310 | ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB32, 0x80000000 | |
281 | 0, dev_priv->vram_size, 0x00000000); | 311 | (dev_priv->chipset < 0xc0 ? 0x7a00 : 0xfe00), |
282 | if (ret) { | 312 | 0, dev_priv->vram_size, NULL); |
283 | nv50_evo_channel_del(&dev_priv->evo); | 313 | if (ret) |
284 | return ret; | 314 | goto err; |
285 | } | ||
286 | } else { | ||
287 | ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB16, 0x70, 0x19, | ||
288 | 0, 0xffffffff, 0x00010000); | ||
289 | if (ret) { | ||
290 | nv50_evo_channel_del(&dev_priv->evo); | ||
291 | return ret; | ||
292 | } | ||
293 | 315 | ||
316 | ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB16, 0x80000000 | | ||
317 | (dev_priv->chipset < 0xc0 ? 0x7000 : 0xfe00), | ||
318 | 0, dev_priv->vram_size, NULL); | ||
319 | if (ret) | ||
320 | goto err; | ||
294 | 321 | ||
295 | ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB32, 0x7a, 0x19, | 322 | /* create "display sync" channels and other structures we need |
296 | 0, 0xffffffff, 0x00010000); | 323 | * to implement page flipping |
297 | if (ret) { | 324 | */ |
298 | nv50_evo_channel_del(&dev_priv->evo); | 325 | for (i = 0; i < 2; i++) { |
299 | return ret; | 326 | struct nv50_display_crtc *dispc = &disp->crtc[i]; |
300 | } | 327 | u64 offset; |
301 | 328 | ||
302 | ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM, 0, 0x19, | 329 | ret = nv50_evo_channel_new(dev, 1 + i, &dispc->sync); |
303 | 0, dev_priv->vram_size, 0x00010000); | 330 | if (ret) |
304 | if (ret) { | 331 | goto err; |
305 | nv50_evo_channel_del(&dev_priv->evo); | 332 | |
306 | return ret; | 333 | ret = nouveau_bo_new(dev, NULL, 4096, 0x1000, TTM_PL_FLAG_VRAM, |
334 | 0, 0x0000, &dispc->sem.bo); | ||
335 | if (!ret) { | ||
336 | offset = dispc->sem.bo->bo.mem.start << PAGE_SHIFT; | ||
337 | |||
338 | ret = nouveau_bo_pin(dispc->sem.bo, TTM_PL_FLAG_VRAM); | ||
339 | if (!ret) | ||
340 | ret = nouveau_bo_map(dispc->sem.bo); | ||
341 | if (ret) | ||
342 | nouveau_bo_ref(NULL, &dispc->sem.bo); | ||
307 | } | 343 | } |
308 | 344 | ||
309 | ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM_LP, 0, 0x19, | 345 | if (ret) |
310 | 0, dev_priv->vram_size, 0x00010000); | 346 | goto err; |
311 | if (ret) { | 347 | |
312 | nv50_evo_channel_del(&dev_priv->evo); | 348 | ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoSync, 0x0000, |
313 | return ret; | 349 | offset, 4096, NULL); |
314 | } | 350 | if (ret) |
351 | goto err; | ||
352 | |||
353 | ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoVRAM_LP, 0x80000000, | ||
354 | 0, dev_priv->vram_size, NULL); | ||
355 | if (ret) | ||
356 | goto err; | ||
357 | |||
358 | ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB32, 0x80000000 | | ||
359 | (dev_priv->chipset < 0xc0 ? | ||
360 | 0x7a00 : 0xfe00), | ||
361 | 0, dev_priv->vram_size, NULL); | ||
362 | if (ret) | ||
363 | goto err; | ||
364 | |||
365 | ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB16, 0x80000000 | | ||
366 | (dev_priv->chipset < 0xc0 ? | ||
367 | 0x7000 : 0xfe00), | ||
368 | 0, dev_priv->vram_size, NULL); | ||
369 | if (ret) | ||
370 | goto err; | ||
371 | |||
372 | for (j = 0; j < 4096; j += 4) | ||
373 | nouveau_bo_wr32(dispc->sem.bo, j / 4, 0x74b1e000); | ||
374 | dispc->sem.offset = 0; | ||
315 | } | 375 | } |
316 | 376 | ||
317 | return 0; | 377 | return 0; |
378 | |||
379 | err: | ||
380 | nv50_evo_destroy(dev); | ||
381 | return ret; | ||
318 | } | 382 | } |
319 | 383 | ||
320 | int | 384 | int |
321 | nv50_evo_init(struct drm_device *dev) | 385 | nv50_evo_init(struct drm_device *dev) |
322 | { | 386 | { |
323 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 387 | struct nv50_display *disp = nv50_display(dev); |
324 | int ret; | 388 | int ret, i; |
325 | 389 | ||
326 | if (!dev_priv->evo) { | 390 | if (!disp->master) { |
327 | ret = nv50_evo_create(dev); | 391 | ret = nv50_evo_create(dev); |
328 | if (ret) | 392 | if (ret) |
329 | return ret; | 393 | return ret; |
330 | } | 394 | } |
331 | 395 | ||
332 | return nv50_evo_channel_init(dev_priv->evo); | 396 | ret = nv50_evo_channel_init(disp->master); |
397 | if (ret) | ||
398 | return ret; | ||
399 | |||
400 | for (i = 0; i < 2; i++) { | ||
401 | ret = nv50_evo_channel_init(disp->crtc[i].sync); | ||
402 | if (ret) | ||
403 | return ret; | ||
404 | } | ||
405 | |||
406 | return 0; | ||
333 | } | 407 | } |
334 | 408 | ||
335 | void | 409 | void |
336 | nv50_evo_fini(struct drm_device *dev) | 410 | nv50_evo_fini(struct drm_device *dev) |
337 | { | 411 | { |
338 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 412 | struct nv50_display *disp = nv50_display(dev); |
413 | int i; | ||
339 | 414 | ||
340 | if (dev_priv->evo) { | 415 | for (i = 0; i < 2; i++) { |
341 | nv50_evo_channel_fini(dev_priv->evo); | 416 | if (disp->crtc[i].sync) |
342 | nv50_evo_channel_del(&dev_priv->evo); | 417 | nv50_evo_channel_fini(disp->crtc[i].sync); |
343 | } | 418 | } |
419 | |||
420 | if (disp->master) | ||
421 | nv50_evo_channel_fini(disp->master); | ||
422 | |||
423 | nv50_evo_destroy(dev); | ||
344 | } | 424 | } |
diff --git a/drivers/gpu/drm/nouveau/nv50_evo.h b/drivers/gpu/drm/nouveau/nv50_evo.h index aa4f0d3cea8..3860ca62cb1 100644 --- a/drivers/gpu/drm/nouveau/nv50_evo.h +++ b/drivers/gpu/drm/nouveau/nv50_evo.h | |||
@@ -27,12 +27,6 @@ | |||
27 | #ifndef __NV50_EVO_H__ | 27 | #ifndef __NV50_EVO_H__ |
28 | #define __NV50_EVO_H__ | 28 | #define __NV50_EVO_H__ |
29 | 29 | ||
30 | int nv50_evo_init(struct drm_device *dev); | ||
31 | void nv50_evo_fini(struct drm_device *dev); | ||
32 | int nv50_evo_dmaobj_new(struct nouveau_channel *, u32 class, u32 name, | ||
33 | u32 tile_flags, u32 magic_flags, | ||
34 | u32 offset, u32 limit); | ||
35 | |||
36 | #define NV50_EVO_UPDATE 0x00000080 | 30 | #define NV50_EVO_UPDATE 0x00000080 |
37 | #define NV50_EVO_UNK84 0x00000084 | 31 | #define NV50_EVO_UNK84 0x00000084 |
38 | #define NV50_EVO_UNK84_NOTIFY 0x40000000 | 32 | #define NV50_EVO_UNK84_NOTIFY 0x40000000 |
@@ -119,5 +113,7 @@ int nv50_evo_dmaobj_new(struct nouveau_channel *, u32 class, u32 name, | |||
119 | /* Both of these are needed, otherwise nothing happens. */ | 113 | /* Both of these are needed, otherwise nothing happens. */ |
120 | #define NV50_EVO_CRTC_SCALE_RES1 0x000008d8 | 114 | #define NV50_EVO_CRTC_SCALE_RES1 0x000008d8 |
121 | #define NV50_EVO_CRTC_SCALE_RES2 0x000008dc | 115 | #define NV50_EVO_CRTC_SCALE_RES2 0x000008dc |
116 | #define NV50_EVO_CRTC_UNK900 0x00000900 | ||
117 | #define NV50_EVO_CRTC_UNK904 0x00000904 | ||
122 | 118 | ||
123 | #endif | 119 | #endif |
diff --git a/drivers/gpu/drm/nouveau/nv50_fb.c b/drivers/gpu/drm/nouveau/nv50_fb.c index 50290dea0ac..bdd2afe2920 100644 --- a/drivers/gpu/drm/nouveau/nv50_fb.c +++ b/drivers/gpu/drm/nouveau/nv50_fb.c | |||
@@ -8,31 +8,61 @@ struct nv50_fb_priv { | |||
8 | dma_addr_t r100c08; | 8 | dma_addr_t r100c08; |
9 | }; | 9 | }; |
10 | 10 | ||
11 | static void | ||
12 | nv50_fb_destroy(struct drm_device *dev) | ||
13 | { | ||
14 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
15 | struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; | ||
16 | struct nv50_fb_priv *priv = pfb->priv; | ||
17 | |||
18 | if (drm_mm_initialized(&pfb->tag_heap)) | ||
19 | drm_mm_takedown(&pfb->tag_heap); | ||
20 | |||
21 | if (priv->r100c08_page) { | ||
22 | pci_unmap_page(dev->pdev, priv->r100c08, PAGE_SIZE, | ||
23 | PCI_DMA_BIDIRECTIONAL); | ||
24 | __free_page(priv->r100c08_page); | ||
25 | } | ||
26 | |||
27 | kfree(priv); | ||
28 | pfb->priv = NULL; | ||
29 | } | ||
30 | |||
11 | static int | 31 | static int |
12 | nv50_fb_create(struct drm_device *dev) | 32 | nv50_fb_create(struct drm_device *dev) |
13 | { | 33 | { |
14 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 34 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
35 | struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; | ||
15 | struct nv50_fb_priv *priv; | 36 | struct nv50_fb_priv *priv; |
37 | u32 tagmem; | ||
38 | int ret; | ||
16 | 39 | ||
17 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 40 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
18 | if (!priv) | 41 | if (!priv) |
19 | return -ENOMEM; | 42 | return -ENOMEM; |
43 | pfb->priv = priv; | ||
20 | 44 | ||
21 | priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO); | 45 | priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO); |
22 | if (!priv->r100c08_page) { | 46 | if (!priv->r100c08_page) { |
23 | kfree(priv); | 47 | nv50_fb_destroy(dev); |
24 | return -ENOMEM; | 48 | return -ENOMEM; |
25 | } | 49 | } |
26 | 50 | ||
27 | priv->r100c08 = pci_map_page(dev->pdev, priv->r100c08_page, 0, | 51 | priv->r100c08 = pci_map_page(dev->pdev, priv->r100c08_page, 0, |
28 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | 52 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); |
29 | if (pci_dma_mapping_error(dev->pdev, priv->r100c08)) { | 53 | if (pci_dma_mapping_error(dev->pdev, priv->r100c08)) { |
30 | __free_page(priv->r100c08_page); | 54 | nv50_fb_destroy(dev); |
31 | kfree(priv); | ||
32 | return -EFAULT; | 55 | return -EFAULT; |
33 | } | 56 | } |
34 | 57 | ||
35 | dev_priv->engine.fb.priv = priv; | 58 | tagmem = nv_rd32(dev, 0x100320); |
59 | NV_DEBUG(dev, "%d tags available\n", tagmem); | ||
60 | ret = drm_mm_init(&pfb->tag_heap, 0, tagmem); | ||
61 | if (ret) { | ||
62 | nv50_fb_destroy(dev); | ||
63 | return ret; | ||
64 | } | ||
65 | |||
36 | return 0; | 66 | return 0; |
37 | } | 67 | } |
38 | 68 | ||
@@ -81,26 +111,112 @@ nv50_fb_init(struct drm_device *dev) | |||
81 | void | 111 | void |
82 | nv50_fb_takedown(struct drm_device *dev) | 112 | nv50_fb_takedown(struct drm_device *dev) |
83 | { | 113 | { |
84 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 114 | nv50_fb_destroy(dev); |
85 | struct nv50_fb_priv *priv; | 115 | } |
86 | 116 | ||
87 | priv = dev_priv->engine.fb.priv; | 117 | static struct nouveau_enum vm_dispatch_subclients[] = { |
88 | if (!priv) | 118 | { 0x00000000, "GRCTX", NULL }, |
89 | return; | 119 | { 0x00000001, "NOTIFY", NULL }, |
90 | dev_priv->engine.fb.priv = NULL; | 120 | { 0x00000002, "QUERY", NULL }, |
121 | { 0x00000003, "COND", NULL }, | ||
122 | { 0x00000004, "M2M_IN", NULL }, | ||
123 | { 0x00000005, "M2M_OUT", NULL }, | ||
124 | { 0x00000006, "M2M_NOTIFY", NULL }, | ||
125 | {} | ||
126 | }; | ||
91 | 127 | ||
92 | pci_unmap_page(dev->pdev, priv->r100c08, PAGE_SIZE, | 128 | static struct nouveau_enum vm_ccache_subclients[] = { |
93 | PCI_DMA_BIDIRECTIONAL); | 129 | { 0x00000000, "CB", NULL }, |
94 | __free_page(priv->r100c08_page); | 130 | { 0x00000001, "TIC", NULL }, |
95 | kfree(priv); | 131 | { 0x00000002, "TSC", NULL }, |
96 | } | 132 | {} |
133 | }; | ||
134 | |||
135 | static struct nouveau_enum vm_prop_subclients[] = { | ||
136 | { 0x00000000, "RT0", NULL }, | ||
137 | { 0x00000001, "RT1", NULL }, | ||
138 | { 0x00000002, "RT2", NULL }, | ||
139 | { 0x00000003, "RT3", NULL }, | ||
140 | { 0x00000004, "RT4", NULL }, | ||
141 | { 0x00000005, "RT5", NULL }, | ||
142 | { 0x00000006, "RT6", NULL }, | ||
143 | { 0x00000007, "RT7", NULL }, | ||
144 | { 0x00000008, "ZETA", NULL }, | ||
145 | { 0x00000009, "LOCAL", NULL }, | ||
146 | { 0x0000000a, "GLOBAL", NULL }, | ||
147 | { 0x0000000b, "STACK", NULL }, | ||
148 | { 0x0000000c, "DST2D", NULL }, | ||
149 | {} | ||
150 | }; | ||
151 | |||
152 | static struct nouveau_enum vm_pfifo_subclients[] = { | ||
153 | { 0x00000000, "PUSHBUF", NULL }, | ||
154 | { 0x00000001, "SEMAPHORE", NULL }, | ||
155 | {} | ||
156 | }; | ||
157 | |||
158 | static struct nouveau_enum vm_bar_subclients[] = { | ||
159 | { 0x00000000, "FB", NULL }, | ||
160 | { 0x00000001, "IN", NULL }, | ||
161 | {} | ||
162 | }; | ||
163 | |||
164 | static struct nouveau_enum vm_client[] = { | ||
165 | { 0x00000000, "STRMOUT", NULL }, | ||
166 | { 0x00000003, "DISPATCH", vm_dispatch_subclients }, | ||
167 | { 0x00000004, "PFIFO_WRITE", NULL }, | ||
168 | { 0x00000005, "CCACHE", vm_ccache_subclients }, | ||
169 | { 0x00000006, "PPPP", NULL }, | ||
170 | { 0x00000007, "CLIPID", NULL }, | ||
171 | { 0x00000008, "PFIFO_READ", NULL }, | ||
172 | { 0x00000009, "VFETCH", NULL }, | ||
173 | { 0x0000000a, "TEXTURE", NULL }, | ||
174 | { 0x0000000b, "PROP", vm_prop_subclients }, | ||
175 | { 0x0000000c, "PVP", NULL }, | ||
176 | { 0x0000000d, "PBSP", NULL }, | ||
177 | { 0x0000000e, "PCRYPT", NULL }, | ||
178 | { 0x0000000f, "PCOUNTER", NULL }, | ||
179 | { 0x00000011, "PDAEMON", NULL }, | ||
180 | {} | ||
181 | }; | ||
182 | |||
183 | static struct nouveau_enum vm_engine[] = { | ||
184 | { 0x00000000, "PGRAPH", NULL }, | ||
185 | { 0x00000001, "PVP", NULL }, | ||
186 | { 0x00000004, "PEEPHOLE", NULL }, | ||
187 | { 0x00000005, "PFIFO", vm_pfifo_subclients }, | ||
188 | { 0x00000006, "BAR", vm_bar_subclients }, | ||
189 | { 0x00000008, "PPPP", NULL }, | ||
190 | { 0x00000009, "PBSP", NULL }, | ||
191 | { 0x0000000a, "PCRYPT", NULL }, | ||
192 | { 0x0000000b, "PCOUNTER", NULL }, | ||
193 | { 0x0000000c, "SEMAPHORE_BG", NULL }, | ||
194 | { 0x0000000d, "PCOPY", NULL }, | ||
195 | { 0x0000000e, "PDAEMON", NULL }, | ||
196 | {} | ||
197 | }; | ||
198 | |||
199 | static struct nouveau_enum vm_fault[] = { | ||
200 | { 0x00000000, "PT_NOT_PRESENT", NULL }, | ||
201 | { 0x00000001, "PT_TOO_SHORT", NULL }, | ||
202 | { 0x00000002, "PAGE_NOT_PRESENT", NULL }, | ||
203 | { 0x00000003, "PAGE_SYSTEM_ONLY", NULL }, | ||
204 | { 0x00000004, "PAGE_READ_ONLY", NULL }, | ||
205 | { 0x00000006, "NULL_DMAOBJ", NULL }, | ||
206 | { 0x00000007, "WRONG_MEMTYPE", NULL }, | ||
207 | { 0x0000000b, "VRAM_LIMIT", NULL }, | ||
208 | { 0x0000000f, "DMAOBJ_LIMIT", NULL }, | ||
209 | {} | ||
210 | }; | ||
97 | 211 | ||
98 | void | 212 | void |
99 | nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name) | 213 | nv50_fb_vm_trap(struct drm_device *dev, int display) |
100 | { | 214 | { |
101 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 215 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
216 | const struct nouveau_enum *en, *cl; | ||
102 | unsigned long flags; | 217 | unsigned long flags; |
103 | u32 trap[6], idx, chinst; | 218 | u32 trap[6], idx, chinst; |
219 | u8 st0, st1, st2, st3; | ||
104 | int i, ch; | 220 | int i, ch; |
105 | 221 | ||
106 | idx = nv_rd32(dev, 0x100c90); | 222 | idx = nv_rd32(dev, 0x100c90); |
@@ -117,8 +233,8 @@ nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name) | |||
117 | if (!display) | 233 | if (!display) |
118 | return; | 234 | return; |
119 | 235 | ||
236 | /* lookup channel id */ | ||
120 | chinst = (trap[2] << 16) | trap[1]; | 237 | chinst = (trap[2] << 16) | trap[1]; |
121 | |||
122 | spin_lock_irqsave(&dev_priv->channels.lock, flags); | 238 | spin_lock_irqsave(&dev_priv->channels.lock, flags); |
123 | for (ch = 0; ch < dev_priv->engine.fifo.channels; ch++) { | 239 | for (ch = 0; ch < dev_priv->engine.fifo.channels; ch++) { |
124 | struct nouveau_channel *chan = dev_priv->channels.ptr[ch]; | 240 | struct nouveau_channel *chan = dev_priv->channels.ptr[ch]; |
@@ -131,9 +247,48 @@ nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name) | |||
131 | } | 247 | } |
132 | spin_unlock_irqrestore(&dev_priv->channels.lock, flags); | 248 | spin_unlock_irqrestore(&dev_priv->channels.lock, flags); |
133 | 249 | ||
134 | NV_INFO(dev, "%s - VM: Trapped %s at %02x%04x%04x status %08x " | 250 | /* decode status bits into something more useful */ |
135 | "channel %d (0x%08x)\n", | 251 | if (dev_priv->chipset < 0xa3 || |
136 | name, (trap[5] & 0x100 ? "read" : "write"), | 252 | dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) { |
137 | trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, | 253 | st0 = (trap[0] & 0x0000000f) >> 0; |
138 | trap[0], ch, chinst); | 254 | st1 = (trap[0] & 0x000000f0) >> 4; |
255 | st2 = (trap[0] & 0x00000f00) >> 8; | ||
256 | st3 = (trap[0] & 0x0000f000) >> 12; | ||
257 | } else { | ||
258 | st0 = (trap[0] & 0x000000ff) >> 0; | ||
259 | st1 = (trap[0] & 0x0000ff00) >> 8; | ||
260 | st2 = (trap[0] & 0x00ff0000) >> 16; | ||
261 | st3 = (trap[0] & 0xff000000) >> 24; | ||
262 | } | ||
263 | |||
264 | NV_INFO(dev, "VM: trapped %s at 0x%02x%04x%04x on ch %d [0x%08x] ", | ||
265 | (trap[5] & 0x00000100) ? "read" : "write", | ||
266 | trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, ch, chinst); | ||
267 | |||
268 | en = nouveau_enum_find(vm_engine, st0); | ||
269 | if (en) | ||
270 | printk("%s/", en->name); | ||
271 | else | ||
272 | printk("%02x/", st0); | ||
273 | |||
274 | cl = nouveau_enum_find(vm_client, st2); | ||
275 | if (cl) | ||
276 | printk("%s/", cl->name); | ||
277 | else | ||
278 | printk("%02x/", st2); | ||
279 | |||
280 | if (cl && cl->data) cl = nouveau_enum_find(cl->data, st3); | ||
281 | else if (en && en->data) cl = nouveau_enum_find(en->data, st3); | ||
282 | else cl = NULL; | ||
283 | if (cl) | ||
284 | printk("%s", cl->name); | ||
285 | else | ||
286 | printk("%02x", st3); | ||
287 | |||
288 | printk(" reason: "); | ||
289 | en = nouveau_enum_find(vm_fault, st1); | ||
290 | if (en) | ||
291 | printk("%s\n", en->name); | ||
292 | else | ||
293 | printk("0x%08x\n", st1); | ||
139 | } | 294 | } |
diff --git a/drivers/gpu/drm/nouveau/nv50_fifo.c b/drivers/gpu/drm/nouveau/nv50_fifo.c index 8dd04c5dac6..c34a074f7ea 100644 --- a/drivers/gpu/drm/nouveau/nv50_fifo.c +++ b/drivers/gpu/drm/nouveau/nv50_fifo.c | |||
@@ -149,6 +149,7 @@ nv50_fifo_init_regs(struct drm_device *dev) | |||
149 | nv_wr32(dev, 0x3204, 0); | 149 | nv_wr32(dev, 0x3204, 0); |
150 | nv_wr32(dev, 0x3210, 0); | 150 | nv_wr32(dev, 0x3210, 0); |
151 | nv_wr32(dev, 0x3270, 0); | 151 | nv_wr32(dev, 0x3270, 0); |
152 | nv_wr32(dev, 0x2044, 0x01003fff); | ||
152 | 153 | ||
153 | /* Enable dummy channels setup by nv50_instmem.c */ | 154 | /* Enable dummy channels setup by nv50_instmem.c */ |
154 | nv50_fifo_channel_enable(dev, 0); | 155 | nv50_fifo_channel_enable(dev, 0); |
@@ -273,7 +274,7 @@ nv50_fifo_create_context(struct nouveau_channel *chan) | |||
273 | nv_wo32(ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | | 274 | nv_wo32(ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | |
274 | (4 << 24) /* SEARCH_FULL */ | | 275 | (4 << 24) /* SEARCH_FULL */ | |
275 | (chan->ramht->gpuobj->cinst >> 4)); | 276 | (chan->ramht->gpuobj->cinst >> 4)); |
276 | nv_wo32(ramfc, 0x44, 0x2101ffff); | 277 | nv_wo32(ramfc, 0x44, 0x01003fff); |
277 | nv_wo32(ramfc, 0x60, 0x7fffffff); | 278 | nv_wo32(ramfc, 0x60, 0x7fffffff); |
278 | nv_wo32(ramfc, 0x40, 0x00000000); | 279 | nv_wo32(ramfc, 0x40, 0x00000000); |
279 | nv_wo32(ramfc, 0x7c, 0x30000001); | 280 | nv_wo32(ramfc, 0x7c, 0x30000001); |
diff --git a/drivers/gpu/drm/nouveau/nv50_gpio.c b/drivers/gpu/drm/nouveau/nv50_gpio.c index 6b149c0cc06..d4f4206dad7 100644 --- a/drivers/gpu/drm/nouveau/nv50_gpio.c +++ b/drivers/gpu/drm/nouveau/nv50_gpio.c | |||
@@ -137,6 +137,7 @@ nv50_gpio_irq_unregister(struct drm_device *dev, enum dcb_gpio_tag tag, | |||
137 | struct nv50_gpio_priv *priv = pgpio->priv; | 137 | struct nv50_gpio_priv *priv = pgpio->priv; |
138 | struct nv50_gpio_handler *gpioh, *tmp; | 138 | struct nv50_gpio_handler *gpioh, *tmp; |
139 | struct dcb_gpio_entry *gpio; | 139 | struct dcb_gpio_entry *gpio; |
140 | LIST_HEAD(tofree); | ||
140 | unsigned long flags; | 141 | unsigned long flags; |
141 | 142 | ||
142 | gpio = nouveau_bios_gpio_entry(dev, tag); | 143 | gpio = nouveau_bios_gpio_entry(dev, tag); |
@@ -149,10 +150,14 @@ nv50_gpio_irq_unregister(struct drm_device *dev, enum dcb_gpio_tag tag, | |||
149 | gpioh->handler != handler || | 150 | gpioh->handler != handler || |
150 | gpioh->data != data) | 151 | gpioh->data != data) |
151 | continue; | 152 | continue; |
152 | list_del(&gpioh->head); | 153 | list_move(&gpioh->head, &tofree); |
153 | kfree(gpioh); | ||
154 | } | 154 | } |
155 | spin_unlock_irqrestore(&priv->lock, flags); | 155 | spin_unlock_irqrestore(&priv->lock, flags); |
156 | |||
157 | list_for_each_entry_safe(gpioh, tmp, &tofree, head) { | ||
158 | flush_work_sync(&gpioh->work); | ||
159 | kfree(gpioh); | ||
160 | } | ||
156 | } | 161 | } |
157 | 162 | ||
158 | bool | 163 | bool |
@@ -205,7 +210,6 @@ nv50_gpio_init(struct drm_device *dev) | |||
205 | { | 210 | { |
206 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 211 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
207 | struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; | 212 | struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; |
208 | struct nv50_gpio_priv *priv; | ||
209 | int ret; | 213 | int ret; |
210 | 214 | ||
211 | if (!pgpio->priv) { | 215 | if (!pgpio->priv) { |
@@ -213,7 +217,6 @@ nv50_gpio_init(struct drm_device *dev) | |||
213 | if (ret) | 217 | if (ret) |
214 | return ret; | 218 | return ret; |
215 | } | 219 | } |
216 | priv = pgpio->priv; | ||
217 | 220 | ||
218 | /* disable, and ack any pending gpio interrupts */ | 221 | /* disable, and ack any pending gpio interrupts */ |
219 | nv_wr32(dev, 0xe050, 0x00000000); | 222 | nv_wr32(dev, 0xe050, 0x00000000); |
@@ -293,7 +296,7 @@ nv50_gpio_isr(struct drm_device *dev) | |||
293 | continue; | 296 | continue; |
294 | gpioh->inhibit = true; | 297 | gpioh->inhibit = true; |
295 | 298 | ||
296 | queue_work(dev_priv->wq, &gpioh->work); | 299 | schedule_work(&gpioh->work); |
297 | } | 300 | } |
298 | spin_unlock(&priv->lock); | 301 | spin_unlock(&priv->lock); |
299 | } | 302 | } |
diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c index 37e21d2be95..8675b00caf1 100644 --- a/drivers/gpu/drm/nouveau/nv50_graph.c +++ b/drivers/gpu/drm/nouveau/nv50_graph.c | |||
@@ -95,13 +95,41 @@ nv50_graph_init_regs__nv(struct drm_device *dev) | |||
95 | } | 95 | } |
96 | 96 | ||
97 | static void | 97 | static void |
98 | nv50_graph_init_regs(struct drm_device *dev) | 98 | nv50_graph_init_zcull(struct drm_device *dev) |
99 | { | 99 | { |
100 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
101 | int i; | ||
102 | |||
100 | NV_DEBUG(dev, "\n"); | 103 | NV_DEBUG(dev, "\n"); |
101 | 104 | ||
102 | nv_wr32(dev, NV04_PGRAPH_DEBUG_3, | 105 | switch (dev_priv->chipset & 0xf0) { |
103 | (1 << 2) /* HW_CONTEXT_SWITCH_ENABLED */); | 106 | case 0x50: |
104 | nv_wr32(dev, 0x402ca8, 0x800); | 107 | case 0x80: |
108 | case 0x90: | ||
109 | nv_wr32(dev, 0x402ca8, 0x00000800); | ||
110 | break; | ||
111 | case 0xa0: | ||
112 | default: | ||
113 | nv_wr32(dev, 0x402cc0, 0x00000000); | ||
114 | if (dev_priv->chipset == 0xa0 || | ||
115 | dev_priv->chipset == 0xaa || | ||
116 | dev_priv->chipset == 0xac) { | ||
117 | nv_wr32(dev, 0x402ca8, 0x00000802); | ||
118 | } else { | ||
119 | nv_wr32(dev, 0x402cc0, 0x00000000); | ||
120 | nv_wr32(dev, 0x402ca8, 0x00000002); | ||
121 | } | ||
122 | |||
123 | break; | ||
124 | } | ||
125 | |||
126 | /* zero out zcull regions */ | ||
127 | for (i = 0; i < 8; i++) { | ||
128 | nv_wr32(dev, 0x402c20 + (i * 8), 0x00000000); | ||
129 | nv_wr32(dev, 0x402c24 + (i * 8), 0x00000000); | ||
130 | nv_wr32(dev, 0x402c28 + (i * 8), 0x00000000); | ||
131 | nv_wr32(dev, 0x402c2c + (i * 8), 0x00000000); | ||
132 | } | ||
105 | } | 133 | } |
106 | 134 | ||
107 | static int | 135 | static int |
@@ -136,6 +164,7 @@ nv50_graph_init_ctxctl(struct drm_device *dev) | |||
136 | } | 164 | } |
137 | kfree(cp); | 165 | kfree(cp); |
138 | 166 | ||
167 | nv_wr32(dev, 0x40008c, 0x00000004); /* HW_CTX_SWITCH_ENABLED */ | ||
139 | nv_wr32(dev, 0x400320, 4); | 168 | nv_wr32(dev, 0x400320, 4); |
140 | nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0); | 169 | nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0); |
141 | nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, 0); | 170 | nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, 0); |
@@ -151,7 +180,7 @@ nv50_graph_init(struct drm_device *dev) | |||
151 | 180 | ||
152 | nv50_graph_init_reset(dev); | 181 | nv50_graph_init_reset(dev); |
153 | nv50_graph_init_regs__nv(dev); | 182 | nv50_graph_init_regs__nv(dev); |
154 | nv50_graph_init_regs(dev); | 183 | nv50_graph_init_zcull(dev); |
155 | 184 | ||
156 | ret = nv50_graph_init_ctxctl(dev); | 185 | ret = nv50_graph_init_ctxctl(dev); |
157 | if (ret) | 186 | if (ret) |
@@ -409,12 +438,7 @@ static int | |||
409 | nv50_graph_nvsw_mthd_page_flip(struct nouveau_channel *chan, | 438 | nv50_graph_nvsw_mthd_page_flip(struct nouveau_channel *chan, |
410 | u32 class, u32 mthd, u32 data) | 439 | u32 class, u32 mthd, u32 data) |
411 | { | 440 | { |
412 | struct nouveau_page_flip_state s; | 441 | nouveau_finish_page_flip(chan, NULL); |
413 | |||
414 | if (!nouveau_finish_page_flip(chan, &s)) { | ||
415 | /* XXX - Do something here */ | ||
416 | } | ||
417 | |||
418 | return 0; | 442 | return 0; |
419 | } | 443 | } |
420 | 444 | ||
@@ -526,11 +550,11 @@ nv86_graph_tlb_flush(struct drm_device *dev) | |||
526 | 550 | ||
527 | static struct nouveau_enum nv50_mp_exec_error_names[] = | 551 | static struct nouveau_enum nv50_mp_exec_error_names[] = |
528 | { | 552 | { |
529 | { 3, "STACK_UNDERFLOW" }, | 553 | { 3, "STACK_UNDERFLOW", NULL }, |
530 | { 4, "QUADON_ACTIVE" }, | 554 | { 4, "QUADON_ACTIVE", NULL }, |
531 | { 8, "TIMEOUT" }, | 555 | { 8, "TIMEOUT", NULL }, |
532 | { 0x10, "INVALID_OPCODE" }, | 556 | { 0x10, "INVALID_OPCODE", NULL }, |
533 | { 0x40, "BREAKPOINT" }, | 557 | { 0x40, "BREAKPOINT", NULL }, |
534 | {} | 558 | {} |
535 | }; | 559 | }; |
536 | 560 | ||
@@ -558,47 +582,47 @@ static struct nouveau_bitfield nv50_graph_trap_ccache[] = { | |||
558 | 582 | ||
559 | /* There must be a *lot* of these. Will take some time to gather them up. */ | 583 | /* There must be a *lot* of these. Will take some time to gather them up. */ |
560 | struct nouveau_enum nv50_data_error_names[] = { | 584 | struct nouveau_enum nv50_data_error_names[] = { |
561 | { 0x00000003, "INVALID_QUERY_OR_TEXTURE" }, | 585 | { 0x00000003, "INVALID_QUERY_OR_TEXTURE", NULL }, |
562 | { 0x00000004, "INVALID_VALUE" }, | 586 | { 0x00000004, "INVALID_VALUE", NULL }, |
563 | { 0x00000005, "INVALID_ENUM" }, | 587 | { 0x00000005, "INVALID_ENUM", NULL }, |
564 | { 0x00000008, "INVALID_OBJECT" }, | 588 | { 0x00000008, "INVALID_OBJECT", NULL }, |
565 | { 0x00000009, "READ_ONLY_OBJECT" }, | 589 | { 0x00000009, "READ_ONLY_OBJECT", NULL }, |
566 | { 0x0000000a, "SUPERVISOR_OBJECT" }, | 590 | { 0x0000000a, "SUPERVISOR_OBJECT", NULL }, |
567 | { 0x0000000b, "INVALID_ADDRESS_ALIGNMENT" }, | 591 | { 0x0000000b, "INVALID_ADDRESS_ALIGNMENT", NULL }, |
568 | { 0x0000000c, "INVALID_BITFIELD" }, | 592 | { 0x0000000c, "INVALID_BITFIELD", NULL }, |
569 | { 0x0000000d, "BEGIN_END_ACTIVE" }, | 593 | { 0x0000000d, "BEGIN_END_ACTIVE", NULL }, |
570 | { 0x0000000e, "SEMANTIC_COLOR_BACK_OVER_LIMIT" }, | 594 | { 0x0000000e, "SEMANTIC_COLOR_BACK_OVER_LIMIT", NULL }, |
571 | { 0x0000000f, "VIEWPORT_ID_NEEDS_GP" }, | 595 | { 0x0000000f, "VIEWPORT_ID_NEEDS_GP", NULL }, |
572 | { 0x00000010, "RT_DOUBLE_BIND" }, | 596 | { 0x00000010, "RT_DOUBLE_BIND", NULL }, |
573 | { 0x00000011, "RT_TYPES_MISMATCH" }, | 597 | { 0x00000011, "RT_TYPES_MISMATCH", NULL }, |
574 | { 0x00000012, "RT_LINEAR_WITH_ZETA" }, | 598 | { 0x00000012, "RT_LINEAR_WITH_ZETA", NULL }, |
575 | { 0x00000015, "FP_TOO_FEW_REGS" }, | 599 | { 0x00000015, "FP_TOO_FEW_REGS", NULL }, |
576 | { 0x00000016, "ZETA_FORMAT_CSAA_MISMATCH" }, | 600 | { 0x00000016, "ZETA_FORMAT_CSAA_MISMATCH", NULL }, |
577 | { 0x00000017, "RT_LINEAR_WITH_MSAA" }, | 601 | { 0x00000017, "RT_LINEAR_WITH_MSAA", NULL }, |
578 | { 0x00000018, "FP_INTERPOLANT_START_OVER_LIMIT" }, | 602 | { 0x00000018, "FP_INTERPOLANT_START_OVER_LIMIT", NULL }, |
579 | { 0x00000019, "SEMANTIC_LAYER_OVER_LIMIT" }, | 603 | { 0x00000019, "SEMANTIC_LAYER_OVER_LIMIT", NULL }, |
580 | { 0x0000001a, "RT_INVALID_ALIGNMENT" }, | 604 | { 0x0000001a, "RT_INVALID_ALIGNMENT", NULL }, |
581 | { 0x0000001b, "SAMPLER_OVER_LIMIT" }, | 605 | { 0x0000001b, "SAMPLER_OVER_LIMIT", NULL }, |
582 | { 0x0000001c, "TEXTURE_OVER_LIMIT" }, | 606 | { 0x0000001c, "TEXTURE_OVER_LIMIT", NULL }, |
583 | { 0x0000001e, "GP_TOO_MANY_OUTPUTS" }, | 607 | { 0x0000001e, "GP_TOO_MANY_OUTPUTS", NULL }, |
584 | { 0x0000001f, "RT_BPP128_WITH_MS8" }, | 608 | { 0x0000001f, "RT_BPP128_WITH_MS8", NULL }, |
585 | { 0x00000021, "Z_OUT_OF_BOUNDS" }, | 609 | { 0x00000021, "Z_OUT_OF_BOUNDS", NULL }, |
586 | { 0x00000023, "XY_OUT_OF_BOUNDS" }, | 610 | { 0x00000023, "XY_OUT_OF_BOUNDS", NULL }, |
587 | { 0x00000027, "CP_MORE_PARAMS_THAN_SHARED" }, | 611 | { 0x00000027, "CP_MORE_PARAMS_THAN_SHARED", NULL }, |
588 | { 0x00000028, "CP_NO_REG_SPACE_STRIPED" }, | 612 | { 0x00000028, "CP_NO_REG_SPACE_STRIPED", NULL }, |
589 | { 0x00000029, "CP_NO_REG_SPACE_PACKED" }, | 613 | { 0x00000029, "CP_NO_REG_SPACE_PACKED", NULL }, |
590 | { 0x0000002a, "CP_NOT_ENOUGH_WARPS" }, | 614 | { 0x0000002a, "CP_NOT_ENOUGH_WARPS", NULL }, |
591 | { 0x0000002b, "CP_BLOCK_SIZE_MISMATCH" }, | 615 | { 0x0000002b, "CP_BLOCK_SIZE_MISMATCH", NULL }, |
592 | { 0x0000002c, "CP_NOT_ENOUGH_LOCAL_WARPS" }, | 616 | { 0x0000002c, "CP_NOT_ENOUGH_LOCAL_WARPS", NULL }, |
593 | { 0x0000002d, "CP_NOT_ENOUGH_STACK_WARPS" }, | 617 | { 0x0000002d, "CP_NOT_ENOUGH_STACK_WARPS", NULL }, |
594 | { 0x0000002e, "CP_NO_BLOCKDIM_LATCH" }, | 618 | { 0x0000002e, "CP_NO_BLOCKDIM_LATCH", NULL }, |
595 | { 0x00000031, "ENG2D_FORMAT_MISMATCH" }, | 619 | { 0x00000031, "ENG2D_FORMAT_MISMATCH", NULL }, |
596 | { 0x0000003f, "PRIMITIVE_ID_NEEDS_GP" }, | 620 | { 0x0000003f, "PRIMITIVE_ID_NEEDS_GP", NULL }, |
597 | { 0x00000044, "SEMANTIC_VIEWPORT_OVER_LIMIT" }, | 621 | { 0x00000044, "SEMANTIC_VIEWPORT_OVER_LIMIT", NULL }, |
598 | { 0x00000045, "SEMANTIC_COLOR_FRONT_OVER_LIMIT" }, | 622 | { 0x00000045, "SEMANTIC_COLOR_FRONT_OVER_LIMIT", NULL }, |
599 | { 0x00000046, "LAYER_ID_NEEDS_GP" }, | 623 | { 0x00000046, "LAYER_ID_NEEDS_GP", NULL }, |
600 | { 0x00000047, "SEMANTIC_CLIP_OVER_LIMIT" }, | 624 | { 0x00000047, "SEMANTIC_CLIP_OVER_LIMIT", NULL }, |
601 | { 0x00000048, "SEMANTIC_PTSZ_OVER_LIMIT" }, | 625 | { 0x00000048, "SEMANTIC_PTSZ_OVER_LIMIT", NULL }, |
602 | {} | 626 | {} |
603 | }; | 627 | }; |
604 | 628 | ||
@@ -678,7 +702,6 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, | |||
678 | tps++; | 702 | tps++; |
679 | switch (type) { | 703 | switch (type) { |
680 | case 6: /* texture error... unknown for now */ | 704 | case 6: /* texture error... unknown for now */ |
681 | nv50_fb_vm_trap(dev, display, name); | ||
682 | if (display) { | 705 | if (display) { |
683 | NV_ERROR(dev, "magic set %d:\n", i); | 706 | NV_ERROR(dev, "magic set %d:\n", i); |
684 | for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4) | 707 | for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4) |
@@ -701,7 +724,6 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, | |||
701 | uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14); | 724 | uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14); |
702 | uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18); | 725 | uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18); |
703 | uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c); | 726 | uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c); |
704 | nv50_fb_vm_trap(dev, display, name); | ||
705 | /* 2d engine destination */ | 727 | /* 2d engine destination */ |
706 | if (ustatus & 0x00000010) { | 728 | if (ustatus & 0x00000010) { |
707 | if (display) { | 729 | if (display) { |
@@ -912,10 +934,10 @@ nv50_pgraph_trap_handler(struct drm_device *dev, u32 display, u64 inst, u32 chid | |||
912 | printk("\n"); | 934 | printk("\n"); |
913 | NV_INFO(dev, "PGRAPH - TRAP_CCACHE %08x %08x %08x %08x" | 935 | NV_INFO(dev, "PGRAPH - TRAP_CCACHE %08x %08x %08x %08x" |
914 | " %08x %08x %08x\n", | 936 | " %08x %08x %08x\n", |
915 | nv_rd32(dev, 0x405800), nv_rd32(dev, 0x405804), | 937 | nv_rd32(dev, 0x405000), nv_rd32(dev, 0x405004), |
916 | nv_rd32(dev, 0x405808), nv_rd32(dev, 0x40580c), | 938 | nv_rd32(dev, 0x405008), nv_rd32(dev, 0x40500c), |
917 | nv_rd32(dev, 0x405810), nv_rd32(dev, 0x405814), | 939 | nv_rd32(dev, 0x405010), nv_rd32(dev, 0x405014), |
918 | nv_rd32(dev, 0x40581c)); | 940 | nv_rd32(dev, 0x40501c)); |
919 | 941 | ||
920 | } | 942 | } |
921 | 943 | ||
@@ -1044,6 +1066,7 @@ nv50_graph_isr(struct drm_device *dev) | |||
1044 | NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) subc %d " | 1066 | NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) subc %d " |
1045 | "class 0x%04x mthd 0x%04x data 0x%08x\n", | 1067 | "class 0x%04x mthd 0x%04x data 0x%08x\n", |
1046 | chid, inst, subc, class, mthd, data); | 1068 | chid, inst, subc, class, mthd, data); |
1069 | nv50_fb_vm_trap(dev, 1); | ||
1047 | } | 1070 | } |
1048 | } | 1071 | } |
1049 | 1072 | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c index e57caa2a00e..a6f8aa651fc 100644 --- a/drivers/gpu/drm/nouveau/nv50_instmem.c +++ b/drivers/gpu/drm/nouveau/nv50_instmem.c | |||
@@ -56,7 +56,7 @@ nv50_channel_del(struct nouveau_channel **pchan) | |||
56 | nouveau_gpuobj_ref(NULL, &chan->ramfc); | 56 | nouveau_gpuobj_ref(NULL, &chan->ramfc); |
57 | nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd); | 57 | nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd); |
58 | nouveau_gpuobj_ref(NULL, &chan->vm_pd); | 58 | nouveau_gpuobj_ref(NULL, &chan->vm_pd); |
59 | if (chan->ramin_heap.free_stack.next) | 59 | if (drm_mm_initialized(&chan->ramin_heap)) |
60 | drm_mm_takedown(&chan->ramin_heap); | 60 | drm_mm_takedown(&chan->ramin_heap); |
61 | nouveau_gpuobj_ref(NULL, &chan->ramin); | 61 | nouveau_gpuobj_ref(NULL, &chan->ramin); |
62 | kfree(chan); | 62 | kfree(chan); |
@@ -259,7 +259,7 @@ nv50_instmem_takedown(struct drm_device *dev) | |||
259 | nouveau_gpuobj_ref(NULL, &dev_priv->bar3_vm->pgt[0].obj[0]); | 259 | nouveau_gpuobj_ref(NULL, &dev_priv->bar3_vm->pgt[0].obj[0]); |
260 | nouveau_vm_ref(NULL, &dev_priv->bar3_vm, NULL); | 260 | nouveau_vm_ref(NULL, &dev_priv->bar3_vm, NULL); |
261 | 261 | ||
262 | if (dev_priv->ramin_heap.free_stack.next) | 262 | if (drm_mm_initialized(&dev_priv->ramin_heap)) |
263 | drm_mm_takedown(&dev_priv->ramin_heap); | 263 | drm_mm_takedown(&dev_priv->ramin_heap); |
264 | 264 | ||
265 | dev_priv->engine.instmem.priv = NULL; | 265 | dev_priv->engine.instmem.priv = NULL; |
@@ -300,7 +300,7 @@ nv50_instmem_resume(struct drm_device *dev) | |||
300 | } | 300 | } |
301 | 301 | ||
302 | struct nv50_gpuobj_node { | 302 | struct nv50_gpuobj_node { |
303 | struct nouveau_vram *vram; | 303 | struct nouveau_mem *vram; |
304 | struct nouveau_vma chan_vma; | 304 | struct nouveau_vma chan_vma; |
305 | u32 align; | 305 | u32 align; |
306 | }; | 306 | }; |
diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c index b4a5ecb199f..c25c5938642 100644 --- a/drivers/gpu/drm/nouveau/nv50_sor.c +++ b/drivers/gpu/drm/nouveau/nv50_sor.c | |||
@@ -41,8 +41,7 @@ nv50_sor_disconnect(struct drm_encoder *encoder) | |||
41 | { | 41 | { |
42 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 42 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); |
43 | struct drm_device *dev = encoder->dev; | 43 | struct drm_device *dev = encoder->dev; |
44 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 44 | struct nouveau_channel *evo = nv50_display(dev)->master; |
45 | struct nouveau_channel *evo = dev_priv->evo; | ||
46 | int ret; | 45 | int ret; |
47 | 46 | ||
48 | if (!nv_encoder->crtc) | 47 | if (!nv_encoder->crtc) |
@@ -184,8 +183,7 @@ static void | |||
184 | nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, | 183 | nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, |
185 | struct drm_display_mode *adjusted_mode) | 184 | struct drm_display_mode *adjusted_mode) |
186 | { | 185 | { |
187 | struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; | 186 | struct nouveau_channel *evo = nv50_display(encoder->dev)->master; |
188 | struct nouveau_channel *evo = dev_priv->evo; | ||
189 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 187 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); |
190 | struct drm_device *dev = encoder->dev; | 188 | struct drm_device *dev = encoder->dev; |
191 | struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); | 189 | struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); |
diff --git a/drivers/gpu/drm/nouveau/nv50_vm.c b/drivers/gpu/drm/nouveau/nv50_vm.c index 6144156f255..4fd3432b5b8 100644 --- a/drivers/gpu/drm/nouveau/nv50_vm.c +++ b/drivers/gpu/drm/nouveau/nv50_vm.c | |||
@@ -31,7 +31,6 @@ void | |||
31 | nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, | 31 | nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, |
32 | struct nouveau_gpuobj *pgt[2]) | 32 | struct nouveau_gpuobj *pgt[2]) |
33 | { | 33 | { |
34 | struct drm_nouveau_private *dev_priv = pgd->dev->dev_private; | ||
35 | u64 phys = 0xdeadcafe00000000ULL; | 34 | u64 phys = 0xdeadcafe00000000ULL; |
36 | u32 coverage = 0; | 35 | u32 coverage = 0; |
37 | 36 | ||
@@ -58,10 +57,9 @@ nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, | |||
58 | } | 57 | } |
59 | 58 | ||
60 | static inline u64 | 59 | static inline u64 |
61 | nv50_vm_addr(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, | 60 | nv50_vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target) |
62 | u64 phys, u32 memtype, u32 target) | ||
63 | { | 61 | { |
64 | struct drm_nouveau_private *dev_priv = pgt->dev->dev_private; | 62 | struct drm_nouveau_private *dev_priv = vma->vm->dev->dev_private; |
65 | 63 | ||
66 | phys |= 1; /* present */ | 64 | phys |= 1; /* present */ |
67 | phys |= (u64)memtype << 40; | 65 | phys |= (u64)memtype << 40; |
@@ -85,12 +83,13 @@ nv50_vm_addr(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, | |||
85 | 83 | ||
86 | void | 84 | void |
87 | nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, | 85 | nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, |
88 | struct nouveau_vram *mem, u32 pte, u32 cnt, u64 phys) | 86 | struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta) |
89 | { | 87 | { |
88 | u32 comp = (mem->memtype & 0x180) >> 7; | ||
90 | u32 block; | 89 | u32 block; |
91 | int i; | 90 | int i; |
92 | 91 | ||
93 | phys = nv50_vm_addr(vma, pgt, phys, mem->memtype, 0); | 92 | phys = nv50_vm_addr(vma, phys, mem->memtype, 0); |
94 | pte <<= 3; | 93 | pte <<= 3; |
95 | cnt <<= 3; | 94 | cnt <<= 3; |
96 | 95 | ||
@@ -107,6 +106,11 @@ nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, | |||
107 | 106 | ||
108 | phys += block << (vma->node->type - 3); | 107 | phys += block << (vma->node->type - 3); |
109 | cnt -= block; | 108 | cnt -= block; |
109 | if (comp) { | ||
110 | u32 tag = mem->tag->start + ((delta >> 16) * comp); | ||
111 | offset_h |= (tag << 17); | ||
112 | delta += block << (vma->node->type - 3); | ||
113 | } | ||
110 | 114 | ||
111 | while (block) { | 115 | while (block) { |
112 | nv_wo32(pgt, pte + 0, offset_l); | 116 | nv_wo32(pgt, pte + 0, offset_l); |
@@ -119,11 +123,11 @@ nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, | |||
119 | 123 | ||
120 | void | 124 | void |
121 | nv50_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, | 125 | nv50_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, |
122 | u32 pte, dma_addr_t *list, u32 cnt) | 126 | struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) |
123 | { | 127 | { |
124 | pte <<= 3; | 128 | pte <<= 3; |
125 | while (cnt--) { | 129 | while (cnt--) { |
126 | u64 phys = nv50_vm_addr(vma, pgt, (u64)*list++, 0, 2); | 130 | u64 phys = nv50_vm_addr(vma, (u64)*list++, mem->memtype, 2); |
127 | nv_wo32(pgt, pte + 0, lower_32_bits(phys)); | 131 | nv_wo32(pgt, pte + 0, lower_32_bits(phys)); |
128 | nv_wo32(pgt, pte + 4, upper_32_bits(phys)); | 132 | nv_wo32(pgt, pte + 4, upper_32_bits(phys)); |
129 | pte += 8; | 133 | pte += 8; |
diff --git a/drivers/gpu/drm/nouveau/nv50_vram.c b/drivers/gpu/drm/nouveau/nv50_vram.c index 58e98ad3634..ffbc3d8cf5b 100644 --- a/drivers/gpu/drm/nouveau/nv50_vram.c +++ b/drivers/gpu/drm/nouveau/nv50_vram.c | |||
@@ -48,42 +48,49 @@ nv50_vram_flags_valid(struct drm_device *dev, u32 tile_flags) | |||
48 | } | 48 | } |
49 | 49 | ||
50 | void | 50 | void |
51 | nv50_vram_del(struct drm_device *dev, struct nouveau_vram **pvram) | 51 | nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem) |
52 | { | 52 | { |
53 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 53 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
54 | struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; | 54 | struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; |
55 | struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM]; | 55 | struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM]; |
56 | struct nouveau_mm *mm = man->priv; | 56 | struct nouveau_mm *mm = man->priv; |
57 | struct nouveau_mm_node *this; | 57 | struct nouveau_mm_node *this; |
58 | struct nouveau_vram *vram; | 58 | struct nouveau_mem *mem; |
59 | 59 | ||
60 | vram = *pvram; | 60 | mem = *pmem; |
61 | *pvram = NULL; | 61 | *pmem = NULL; |
62 | if (unlikely(vram == NULL)) | 62 | if (unlikely(mem == NULL)) |
63 | return; | 63 | return; |
64 | 64 | ||
65 | mutex_lock(&mm->mutex); | 65 | mutex_lock(&mm->mutex); |
66 | while (!list_empty(&vram->regions)) { | 66 | while (!list_empty(&mem->regions)) { |
67 | this = list_first_entry(&vram->regions, struct nouveau_mm_node, rl_entry); | 67 | this = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); |
68 | 68 | ||
69 | list_del(&this->rl_entry); | 69 | list_del(&this->rl_entry); |
70 | nouveau_mm_put(mm, this); | 70 | nouveau_mm_put(mm, this); |
71 | } | 71 | } |
72 | |||
73 | if (mem->tag) { | ||
74 | drm_mm_put_block(mem->tag); | ||
75 | mem->tag = NULL; | ||
76 | } | ||
72 | mutex_unlock(&mm->mutex); | 77 | mutex_unlock(&mm->mutex); |
73 | 78 | ||
74 | kfree(vram); | 79 | kfree(mem); |
75 | } | 80 | } |
76 | 81 | ||
77 | int | 82 | int |
78 | nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc, | 83 | nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc, |
79 | u32 type, struct nouveau_vram **pvram) | 84 | u32 memtype, struct nouveau_mem **pmem) |
80 | { | 85 | { |
81 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 86 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
82 | struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; | 87 | struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; |
83 | struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM]; | 88 | struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM]; |
84 | struct nouveau_mm *mm = man->priv; | 89 | struct nouveau_mm *mm = man->priv; |
85 | struct nouveau_mm_node *r; | 90 | struct nouveau_mm_node *r; |
86 | struct nouveau_vram *vram; | 91 | struct nouveau_mem *mem; |
92 | int comp = (memtype & 0x300) >> 8; | ||
93 | int type = (memtype & 0x07f); | ||
87 | int ret; | 94 | int ret; |
88 | 95 | ||
89 | if (!types[type]) | 96 | if (!types[type]) |
@@ -92,32 +99,46 @@ nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc, | |||
92 | align >>= 12; | 99 | align >>= 12; |
93 | size_nc >>= 12; | 100 | size_nc >>= 12; |
94 | 101 | ||
95 | vram = kzalloc(sizeof(*vram), GFP_KERNEL); | 102 | mem = kzalloc(sizeof(*mem), GFP_KERNEL); |
96 | if (!vram) | 103 | if (!mem) |
97 | return -ENOMEM; | 104 | return -ENOMEM; |
98 | 105 | ||
99 | INIT_LIST_HEAD(&vram->regions); | ||
100 | vram->dev = dev_priv->dev; | ||
101 | vram->memtype = type; | ||
102 | vram->size = size; | ||
103 | |||
104 | mutex_lock(&mm->mutex); | 106 | mutex_lock(&mm->mutex); |
107 | if (comp) { | ||
108 | if (align == 16) { | ||
109 | struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; | ||
110 | int n = (size >> 4) * comp; | ||
111 | |||
112 | mem->tag = drm_mm_search_free(&pfb->tag_heap, n, 0, 0); | ||
113 | if (mem->tag) | ||
114 | mem->tag = drm_mm_get_block(mem->tag, n, 0); | ||
115 | } | ||
116 | |||
117 | if (unlikely(!mem->tag)) | ||
118 | comp = 0; | ||
119 | } | ||
120 | |||
121 | INIT_LIST_HEAD(&mem->regions); | ||
122 | mem->dev = dev_priv->dev; | ||
123 | mem->memtype = (comp << 7) | type; | ||
124 | mem->size = size; | ||
125 | |||
105 | do { | 126 | do { |
106 | ret = nouveau_mm_get(mm, types[type], size, size_nc, align, &r); | 127 | ret = nouveau_mm_get(mm, types[type], size, size_nc, align, &r); |
107 | if (ret) { | 128 | if (ret) { |
108 | mutex_unlock(&mm->mutex); | 129 | mutex_unlock(&mm->mutex); |
109 | nv50_vram_del(dev, &vram); | 130 | nv50_vram_del(dev, &mem); |
110 | return ret; | 131 | return ret; |
111 | } | 132 | } |
112 | 133 | ||
113 | list_add_tail(&r->rl_entry, &vram->regions); | 134 | list_add_tail(&r->rl_entry, &mem->regions); |
114 | size -= r->length; | 135 | size -= r->length; |
115 | } while (size); | 136 | } while (size); |
116 | mutex_unlock(&mm->mutex); | 137 | mutex_unlock(&mm->mutex); |
117 | 138 | ||
118 | r = list_first_entry(&vram->regions, struct nouveau_mm_node, rl_entry); | 139 | r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); |
119 | vram->offset = (u64)r->offset << 12; | 140 | mem->offset = (u64)r->offset << 12; |
120 | *pvram = vram; | 141 | *pmem = mem; |
121 | return 0; | 142 | return 0; |
122 | } | 143 | } |
123 | 144 | ||
diff --git a/drivers/gpu/drm/nouveau/nv84_crypt.c b/drivers/gpu/drm/nouveau/nv84_crypt.c index ec18ae1c388..fabc7fd30b1 100644 --- a/drivers/gpu/drm/nouveau/nv84_crypt.c +++ b/drivers/gpu/drm/nouveau/nv84_crypt.c | |||
@@ -136,5 +136,5 @@ nv84_crypt_isr(struct drm_device *dev) | |||
136 | nv_wr32(dev, 0x102130, stat); | 136 | nv_wr32(dev, 0x102130, stat); |
137 | nv_wr32(dev, 0x10200c, 0x10); | 137 | nv_wr32(dev, 0x10200c, 0x10); |
138 | 138 | ||
139 | nv50_fb_vm_trap(dev, show, "PCRYPT"); | 139 | nv50_fb_vm_trap(dev, show); |
140 | } | 140 | } |
diff --git a/drivers/gpu/drm/nouveau/nvc0_fifo.c b/drivers/gpu/drm/nouveau/nvc0_fifo.c index e6f92c541db..2886f2726a9 100644 --- a/drivers/gpu/drm/nouveau/nvc0_fifo.c +++ b/drivers/gpu/drm/nouveau/nvc0_fifo.c | |||
@@ -116,7 +116,7 @@ nvc0_fifo_create_context(struct nouveau_channel *chan) | |||
116 | 116 | ||
117 | /* allocate vram for control regs, map into polling area */ | 117 | /* allocate vram for control regs, map into polling area */ |
118 | ret = nouveau_bo_new(dev, NULL, 0x1000, 0, TTM_PL_FLAG_VRAM, | 118 | ret = nouveau_bo_new(dev, NULL, 0x1000, 0, TTM_PL_FLAG_VRAM, |
119 | 0, 0, true, true, &fifoch->user); | 119 | 0, 0, &fifoch->user); |
120 | if (ret) | 120 | if (ret) |
121 | goto error; | 121 | goto error; |
122 | 122 | ||
@@ -418,6 +418,12 @@ nvc0_fifo_isr(struct drm_device *dev) | |||
418 | { | 418 | { |
419 | u32 stat = nv_rd32(dev, 0x002100); | 419 | u32 stat = nv_rd32(dev, 0x002100); |
420 | 420 | ||
421 | if (stat & 0x00000100) { | ||
422 | NV_INFO(dev, "PFIFO: unknown status 0x00000100\n"); | ||
423 | nv_wr32(dev, 0x002100, 0x00000100); | ||
424 | stat &= ~0x00000100; | ||
425 | } | ||
426 | |||
421 | if (stat & 0x10000000) { | 427 | if (stat & 0x10000000) { |
422 | u32 units = nv_rd32(dev, 0x00259c); | 428 | u32 units = nv_rd32(dev, 0x00259c); |
423 | u32 u = units; | 429 | u32 u = units; |
@@ -446,10 +452,15 @@ nvc0_fifo_isr(struct drm_device *dev) | |||
446 | stat &= ~0x20000000; | 452 | stat &= ~0x20000000; |
447 | } | 453 | } |
448 | 454 | ||
455 | if (stat & 0x40000000) { | ||
456 | NV_INFO(dev, "PFIFO: unknown status 0x40000000\n"); | ||
457 | nv_mask(dev, 0x002a00, 0x00000000, 0x00000000); | ||
458 | stat &= ~0x40000000; | ||
459 | } | ||
460 | |||
449 | if (stat) { | 461 | if (stat) { |
450 | NV_INFO(dev, "PFIFO: unhandled status 0x%08x\n", stat); | 462 | NV_INFO(dev, "PFIFO: unhandled status 0x%08x\n", stat); |
451 | nv_wr32(dev, 0x002100, stat); | 463 | nv_wr32(dev, 0x002100, stat); |
464 | nv_wr32(dev, 0x002140, 0); | ||
452 | } | 465 | } |
453 | |||
454 | nv_wr32(dev, 0x2140, 0); | ||
455 | } | 466 | } |
diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c index eb18a7e89f5..3de9b721d8d 100644 --- a/drivers/gpu/drm/nouveau/nvc0_graph.c +++ b/drivers/gpu/drm/nouveau/nvc0_graph.c | |||
@@ -299,6 +299,14 @@ nvc0_graph_takedown(struct drm_device *dev) | |||
299 | } | 299 | } |
300 | 300 | ||
301 | static int | 301 | static int |
302 | nvc0_graph_mthd_page_flip(struct nouveau_channel *chan, | ||
303 | u32 class, u32 mthd, u32 data) | ||
304 | { | ||
305 | nouveau_finish_page_flip(chan, NULL); | ||
306 | return 0; | ||
307 | } | ||
308 | |||
309 | static int | ||
302 | nvc0_graph_create(struct drm_device *dev) | 310 | nvc0_graph_create(struct drm_device *dev) |
303 | { | 311 | { |
304 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 312 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
@@ -395,6 +403,7 @@ nvc0_graph_create(struct drm_device *dev) | |||
395 | nouveau_irq_register(dev, 25, nvc0_runk140_isr); | 403 | nouveau_irq_register(dev, 25, nvc0_runk140_isr); |
396 | NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */ | 404 | NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */ |
397 | NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */ | 405 | NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */ |
406 | NVOBJ_MTHD (dev, 0x9039, 0x0500, nvc0_graph_mthd_page_flip); | ||
398 | NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */ | 407 | NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */ |
399 | NVOBJ_CLASS(dev, 0x90c0, GR); /* COMPUTE */ | 408 | NVOBJ_CLASS(dev, 0x90c0, GR); /* COMPUTE */ |
400 | return 0; | 409 | return 0; |
@@ -640,7 +649,6 @@ nvc0_graph_init(struct drm_device *dev) | |||
640 | { | 649 | { |
641 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 650 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
642 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; | 651 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; |
643 | struct nvc0_graph_priv *priv; | ||
644 | int ret; | 652 | int ret; |
645 | 653 | ||
646 | dev_priv->engine.graph.accel_blocked = true; | 654 | dev_priv->engine.graph.accel_blocked = true; |
@@ -665,7 +673,6 @@ nvc0_graph_init(struct drm_device *dev) | |||
665 | if (ret) | 673 | if (ret) |
666 | return ret; | 674 | return ret; |
667 | } | 675 | } |
668 | priv = pgraph->priv; | ||
669 | 676 | ||
670 | nvc0_graph_init_obj418880(dev); | 677 | nvc0_graph_init_obj418880(dev); |
671 | nvc0_graph_init_regs(dev); | 678 | nvc0_graph_init_regs(dev); |
@@ -730,9 +737,12 @@ nvc0_graph_isr(struct drm_device *dev) | |||
730 | u32 class = nv_rd32(dev, 0x404200 + (subc * 4)); | 737 | u32 class = nv_rd32(dev, 0x404200 + (subc * 4)); |
731 | 738 | ||
732 | if (stat & 0x00000010) { | 739 | if (stat & 0x00000010) { |
733 | NV_INFO(dev, "PGRAPH: ILLEGAL_MTHD ch %d [0x%010llx] subc %d " | 740 | if (nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) { |
734 | "class 0x%04x mthd 0x%04x data 0x%08x\n", | 741 | NV_INFO(dev, "PGRAPH: ILLEGAL_MTHD ch %d [0x%010llx] " |
735 | chid, inst, subc, class, mthd, data); | 742 | "subc %d class 0x%04x mthd 0x%04x " |
743 | "data 0x%08x\n", | ||
744 | chid, inst, subc, class, mthd, data); | ||
745 | } | ||
736 | nv_wr32(dev, 0x400100, 0x00000010); | 746 | nv_wr32(dev, 0x400100, 0x00000010); |
737 | stat &= ~0x00000010; | 747 | stat &= ~0x00000010; |
738 | } | 748 | } |
diff --git a/drivers/gpu/drm/nouveau/nvc0_instmem.c b/drivers/gpu/drm/nouveau/nvc0_instmem.c index c0909174905..82357d2df1f 100644 --- a/drivers/gpu/drm/nouveau/nvc0_instmem.c +++ b/drivers/gpu/drm/nouveau/nvc0_instmem.c | |||
@@ -67,7 +67,7 @@ nvc0_channel_del(struct nouveau_channel **pchan) | |||
67 | return; | 67 | return; |
68 | 68 | ||
69 | nouveau_vm_ref(NULL, &chan->vm, NULL); | 69 | nouveau_vm_ref(NULL, &chan->vm, NULL); |
70 | if (chan->ramin_heap.free_stack.next) | 70 | if (drm_mm_initialized(&chan->ramin_heap)) |
71 | drm_mm_takedown(&chan->ramin_heap); | 71 | drm_mm_takedown(&chan->ramin_heap); |
72 | nouveau_gpuobj_ref(NULL, &chan->ramin); | 72 | nouveau_gpuobj_ref(NULL, &chan->ramin); |
73 | kfree(chan); | 73 | kfree(chan); |
diff --git a/drivers/gpu/drm/nouveau/nvc0_vm.c b/drivers/gpu/drm/nouveau/nvc0_vm.c index e4e83c2caf5..69af0ba7edd 100644 --- a/drivers/gpu/drm/nouveau/nvc0_vm.c +++ b/drivers/gpu/drm/nouveau/nvc0_vm.c | |||
@@ -59,7 +59,7 @@ nvc0_vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target) | |||
59 | 59 | ||
60 | void | 60 | void |
61 | nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, | 61 | nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, |
62 | struct nouveau_vram *mem, u32 pte, u32 cnt, u64 phys) | 62 | struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta) |
63 | { | 63 | { |
64 | u32 next = 1 << (vma->node->type - 8); | 64 | u32 next = 1 << (vma->node->type - 8); |
65 | 65 | ||
@@ -75,11 +75,11 @@ nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, | |||
75 | 75 | ||
76 | void | 76 | void |
77 | nvc0_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, | 77 | nvc0_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, |
78 | u32 pte, dma_addr_t *list, u32 cnt) | 78 | struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) |
79 | { | 79 | { |
80 | pte <<= 3; | 80 | pte <<= 3; |
81 | while (cnt--) { | 81 | while (cnt--) { |
82 | u64 phys = nvc0_vm_addr(vma, *list++, 0, 5); | 82 | u64 phys = nvc0_vm_addr(vma, *list++, mem->memtype, 5); |
83 | nv_wo32(pgt, pte + 0, lower_32_bits(phys)); | 83 | nv_wo32(pgt, pte + 0, lower_32_bits(phys)); |
84 | nv_wo32(pgt, pte + 4, upper_32_bits(phys)); | 84 | nv_wo32(pgt, pte + 4, upper_32_bits(phys)); |
85 | pte += 8; | 85 | pte += 8; |
diff --git a/drivers/gpu/drm/nouveau/nvc0_vram.c b/drivers/gpu/drm/nouveau/nvc0_vram.c index 858eda5dedd..67c6ec6f34e 100644 --- a/drivers/gpu/drm/nouveau/nvc0_vram.c +++ b/drivers/gpu/drm/nouveau/nvc0_vram.c | |||
@@ -26,64 +26,78 @@ | |||
26 | #include "nouveau_drv.h" | 26 | #include "nouveau_drv.h" |
27 | #include "nouveau_mm.h" | 27 | #include "nouveau_mm.h" |
28 | 28 | ||
29 | /* 0 = unsupported | ||
30 | * 1 = non-compressed | ||
31 | * 3 = compressed | ||
32 | */ | ||
33 | static const u8 types[256] = { | ||
34 | 1, 1, 3, 3, 3, 3, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, | ||
35 | 0, 1, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, | ||
36 | 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, | ||
37 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, | ||
38 | 3, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
39 | 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
40 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
41 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, | ||
42 | 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 1, 1, 1, 1, 0, | ||
43 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
44 | 0, 0, 0, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0, | ||
45 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, | ||
46 | 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, | ||
47 | 3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 3, | ||
48 | 3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 3, 0, | ||
49 | 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 1, 0 | ||
50 | }; | ||
51 | |||
29 | bool | 52 | bool |
30 | nvc0_vram_flags_valid(struct drm_device *dev, u32 tile_flags) | 53 | nvc0_vram_flags_valid(struct drm_device *dev, u32 tile_flags) |
31 | { | 54 | { |
32 | switch (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) { | 55 | u8 memtype = (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) >> 8; |
33 | case 0x0000: | 56 | return likely((types[memtype] == 1)); |
34 | case 0xfe00: | ||
35 | case 0xdb00: | ||
36 | case 0x1100: | ||
37 | return true; | ||
38 | default: | ||
39 | break; | ||
40 | } | ||
41 | |||
42 | return false; | ||
43 | } | 57 | } |
44 | 58 | ||
45 | int | 59 | int |
46 | nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin, | 60 | nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin, |
47 | u32 type, struct nouveau_vram **pvram) | 61 | u32 type, struct nouveau_mem **pmem) |
48 | { | 62 | { |
49 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 63 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
50 | struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; | 64 | struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; |
51 | struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM]; | 65 | struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM]; |
52 | struct nouveau_mm *mm = man->priv; | 66 | struct nouveau_mm *mm = man->priv; |
53 | struct nouveau_mm_node *r; | 67 | struct nouveau_mm_node *r; |
54 | struct nouveau_vram *vram; | 68 | struct nouveau_mem *mem; |
55 | int ret; | 69 | int ret; |
56 | 70 | ||
57 | size >>= 12; | 71 | size >>= 12; |
58 | align >>= 12; | 72 | align >>= 12; |
59 | ncmin >>= 12; | 73 | ncmin >>= 12; |
60 | 74 | ||
61 | vram = kzalloc(sizeof(*vram), GFP_KERNEL); | 75 | mem = kzalloc(sizeof(*mem), GFP_KERNEL); |
62 | if (!vram) | 76 | if (!mem) |
63 | return -ENOMEM; | 77 | return -ENOMEM; |
64 | 78 | ||
65 | INIT_LIST_HEAD(&vram->regions); | 79 | INIT_LIST_HEAD(&mem->regions); |
66 | vram->dev = dev_priv->dev; | 80 | mem->dev = dev_priv->dev; |
67 | vram->memtype = type; | 81 | mem->memtype = (type & 0xff); |
68 | vram->size = size; | 82 | mem->size = size; |
69 | 83 | ||
70 | mutex_lock(&mm->mutex); | 84 | mutex_lock(&mm->mutex); |
71 | do { | 85 | do { |
72 | ret = nouveau_mm_get(mm, 1, size, ncmin, align, &r); | 86 | ret = nouveau_mm_get(mm, 1, size, ncmin, align, &r); |
73 | if (ret) { | 87 | if (ret) { |
74 | mutex_unlock(&mm->mutex); | 88 | mutex_unlock(&mm->mutex); |
75 | nv50_vram_del(dev, &vram); | 89 | nv50_vram_del(dev, &mem); |
76 | return ret; | 90 | return ret; |
77 | } | 91 | } |
78 | 92 | ||
79 | list_add_tail(&r->rl_entry, &vram->regions); | 93 | list_add_tail(&r->rl_entry, &mem->regions); |
80 | size -= r->length; | 94 | size -= r->length; |
81 | } while (size); | 95 | } while (size); |
82 | mutex_unlock(&mm->mutex); | 96 | mutex_unlock(&mm->mutex); |
83 | 97 | ||
84 | r = list_first_entry(&vram->regions, struct nouveau_mm_node, rl_entry); | 98 | r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); |
85 | vram->offset = (u64)r->offset << 12; | 99 | mem->offset = (u64)r->offset << 12; |
86 | *pvram = vram; | 100 | *pmem = mem; |
87 | return 0; | 101 | return 0; |
88 | } | 102 | } |
89 | 103 | ||
diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c index 18c3c71e41b..b9e8efd2b75 100644 --- a/drivers/gpu/drm/r128/r128_drv.c +++ b/drivers/gpu/drm/r128/r128_drv.c | |||
@@ -71,10 +71,7 @@ static struct drm_driver driver = { | |||
71 | #endif | 71 | #endif |
72 | .llseek = noop_llseek, | 72 | .llseek = noop_llseek, |
73 | }, | 73 | }, |
74 | .pci_driver = { | 74 | |
75 | .name = DRIVER_NAME, | ||
76 | .id_table = pciidlist, | ||
77 | }, | ||
78 | 75 | ||
79 | .name = DRIVER_NAME, | 76 | .name = DRIVER_NAME, |
80 | .desc = DRIVER_DESC, | 77 | .desc = DRIVER_DESC, |
@@ -89,16 +86,21 @@ int r128_driver_load(struct drm_device *dev, unsigned long flags) | |||
89 | return drm_vblank_init(dev, 1); | 86 | return drm_vblank_init(dev, 1); |
90 | } | 87 | } |
91 | 88 | ||
89 | static struct pci_driver r128_pci_driver = { | ||
90 | .name = DRIVER_NAME, | ||
91 | .id_table = pciidlist, | ||
92 | }; | ||
93 | |||
92 | static int __init r128_init(void) | 94 | static int __init r128_init(void) |
93 | { | 95 | { |
94 | driver.num_ioctls = r128_max_ioctl; | 96 | driver.num_ioctls = r128_max_ioctl; |
95 | 97 | ||
96 | return drm_init(&driver); | 98 | return drm_pci_init(&driver, &r128_pci_driver); |
97 | } | 99 | } |
98 | 100 | ||
99 | static void __exit r128_exit(void) | 101 | static void __exit r128_exit(void) |
100 | { | 102 | { |
101 | drm_exit(&driver); | 103 | drm_pci_exit(&driver, &r128_pci_driver); |
102 | } | 104 | } |
103 | 105 | ||
104 | module_init(r128_init); | 106 | module_init(r128_init); |
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile index e47eecfc2df..3896ef81110 100644 --- a/drivers/gpu/drm/radeon/Makefile +++ b/drivers/gpu/drm/radeon/Makefile | |||
@@ -36,6 +36,9 @@ $(obj)/r600_reg_safe.h: $(src)/reg_srcs/r600 $(obj)/mkregtable | |||
36 | $(obj)/evergreen_reg_safe.h: $(src)/reg_srcs/evergreen $(obj)/mkregtable | 36 | $(obj)/evergreen_reg_safe.h: $(src)/reg_srcs/evergreen $(obj)/mkregtable |
37 | $(call if_changed,mkregtable) | 37 | $(call if_changed,mkregtable) |
38 | 38 | ||
39 | $(obj)/cayman_reg_safe.h: $(src)/reg_srcs/cayman $(obj)/mkregtable | ||
40 | $(call if_changed,mkregtable) | ||
41 | |||
39 | $(obj)/r100.o: $(obj)/r100_reg_safe.h $(obj)/rn50_reg_safe.h | 42 | $(obj)/r100.o: $(obj)/r100_reg_safe.h $(obj)/rn50_reg_safe.h |
40 | 43 | ||
41 | $(obj)/r200.o: $(obj)/r200_reg_safe.h | 44 | $(obj)/r200.o: $(obj)/r200_reg_safe.h |
@@ -50,7 +53,7 @@ $(obj)/rs600.o: $(obj)/rs600_reg_safe.h | |||
50 | 53 | ||
51 | $(obj)/r600_cs.o: $(obj)/r600_reg_safe.h | 54 | $(obj)/r600_cs.o: $(obj)/r600_reg_safe.h |
52 | 55 | ||
53 | $(obj)/evergreen_cs.o: $(obj)/evergreen_reg_safe.h | 56 | $(obj)/evergreen_cs.o: $(obj)/evergreen_reg_safe.h $(obj)/cayman_reg_safe.h |
54 | 57 | ||
55 | radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o \ | 58 | radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o \ |
56 | radeon_irq.o r300_cmdbuf.o r600_cp.o | 59 | radeon_irq.o r300_cmdbuf.o r600_cp.o |
@@ -66,7 +69,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \ | |||
66 | r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \ | 69 | r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \ |
67 | r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \ | 70 | r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \ |
68 | evergreen.o evergreen_cs.o evergreen_blit_shaders.o evergreen_blit_kms.o \ | 71 | evergreen.o evergreen_cs.o evergreen_blit_shaders.o evergreen_blit_kms.o \ |
69 | radeon_trace_points.o ni.o | 72 | radeon_trace_points.o ni.o cayman_blit_shaders.o |
70 | 73 | ||
71 | radeon-$(CONFIG_COMPAT) += radeon_ioc32.o | 74 | radeon-$(CONFIG_COMPAT) += radeon_ioc32.o |
72 | radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o | 75 | radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o |
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index a4e5e53e0a6..3cd3234ba0a 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
@@ -61,8 +61,8 @@ static void atombios_overscan_setup(struct drm_crtc *crtc, | |||
61 | args.usOverscanLeft = cpu_to_le16((adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2); | 61 | args.usOverscanLeft = cpu_to_le16((adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2); |
62 | args.usOverscanRight = cpu_to_le16((adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2); | 62 | args.usOverscanRight = cpu_to_le16((adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2); |
63 | } else if (a2 > a1) { | 63 | } else if (a2 > a1) { |
64 | args.usOverscanLeft = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2); | 64 | args.usOverscanTop = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2); |
65 | args.usOverscanRight = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2); | 65 | args.usOverscanBottom = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2); |
66 | } | 66 | } |
67 | break; | 67 | break; |
68 | case RMX_FULL: | 68 | case RMX_FULL: |
@@ -1026,7 +1026,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, | |||
1026 | * just update base pointers | 1026 | * just update base pointers |
1027 | */ | 1027 | */ |
1028 | obj = radeon_fb->obj; | 1028 | obj = radeon_fb->obj; |
1029 | rbo = obj->driver_private; | 1029 | rbo = gem_to_radeon_bo(obj); |
1030 | r = radeon_bo_reserve(rbo, false); | 1030 | r = radeon_bo_reserve(rbo, false); |
1031 | if (unlikely(r != 0)) | 1031 | if (unlikely(r != 0)) |
1032 | return r; | 1032 | return r; |
@@ -1135,7 +1135,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, | |||
1135 | 1135 | ||
1136 | if (!atomic && fb && fb != crtc->fb) { | 1136 | if (!atomic && fb && fb != crtc->fb) { |
1137 | radeon_fb = to_radeon_framebuffer(fb); | 1137 | radeon_fb = to_radeon_framebuffer(fb); |
1138 | rbo = radeon_fb->obj->driver_private; | 1138 | rbo = gem_to_radeon_bo(radeon_fb->obj); |
1139 | r = radeon_bo_reserve(rbo, false); | 1139 | r = radeon_bo_reserve(rbo, false); |
1140 | if (unlikely(r != 0)) | 1140 | if (unlikely(r != 0)) |
1141 | return r; | 1141 | return r; |
@@ -1181,7 +1181,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, | |||
1181 | } | 1181 | } |
1182 | 1182 | ||
1183 | obj = radeon_fb->obj; | 1183 | obj = radeon_fb->obj; |
1184 | rbo = obj->driver_private; | 1184 | rbo = gem_to_radeon_bo(obj); |
1185 | r = radeon_bo_reserve(rbo, false); | 1185 | r = radeon_bo_reserve(rbo, false); |
1186 | if (unlikely(r != 0)) | 1186 | if (unlikely(r != 0)) |
1187 | return r; | 1187 | return r; |
@@ -1292,7 +1292,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, | |||
1292 | 1292 | ||
1293 | if (!atomic && fb && fb != crtc->fb) { | 1293 | if (!atomic && fb && fb != crtc->fb) { |
1294 | radeon_fb = to_radeon_framebuffer(fb); | 1294 | radeon_fb = to_radeon_framebuffer(fb); |
1295 | rbo = radeon_fb->obj->driver_private; | 1295 | rbo = gem_to_radeon_bo(radeon_fb->obj); |
1296 | r = radeon_bo_reserve(rbo, false); | 1296 | r = radeon_bo_reserve(rbo, false); |
1297 | if (unlikely(r != 0)) | 1297 | if (unlikely(r != 0)) |
1298 | return r; | 1298 | return r; |
diff --git a/drivers/gpu/drm/radeon/cayman_blit_shaders.c b/drivers/gpu/drm/radeon/cayman_blit_shaders.c new file mode 100644 index 00000000000..e148ab04b80 --- /dev/null +++ b/drivers/gpu/drm/radeon/cayman_blit_shaders.c | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Advanced Micro Devices, 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 (including the next | ||
12 | * paragraph) shall be included in all copies or substantial portions of the | ||
13 | * Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
19 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
21 | * DEALINGS IN THE SOFTWARE. | ||
22 | * | ||
23 | * Authors: | ||
24 | * Alex Deucher <alexander.deucher@amd.com> | ||
25 | */ | ||
26 | |||
27 | #include <linux/types.h> | ||
28 | #include <linux/kernel.h> | ||
29 | |||
30 | /* | ||
31 | * evergreen cards need to use the 3D engine to blit data which requires | ||
32 | * quite a bit of hw state setup. Rather than pull the whole 3D driver | ||
33 | * (which normally generates the 3D state) into the DRM, we opt to use | ||
34 | * statically generated state tables. The regsiter state and shaders | ||
35 | * were hand generated to support blitting functionality. See the 3D | ||
36 | * driver or documentation for descriptions of the registers and | ||
37 | * shader instructions. | ||
38 | */ | ||
39 | |||
40 | const u32 cayman_default_state[] = | ||
41 | { | ||
42 | /* XXX fill in additional blit state */ | ||
43 | |||
44 | 0xc0026900, | ||
45 | 0x00000316, | ||
46 | 0x0000000e, /* VGT_VERTEX_REUSE_BLOCK_CNTL */ | ||
47 | 0x00000010, /* */ | ||
48 | |||
49 | 0xc0026900, | ||
50 | 0x000000d9, | ||
51 | 0x00000000, /* CP_RINGID */ | ||
52 | 0x00000000, /* CP_VMID */ | ||
53 | }; | ||
54 | |||
55 | const u32 cayman_default_size = ARRAY_SIZE(cayman_default_state); | ||
diff --git a/drivers/gpu/drm/radeon/cayman_blit_shaders.h b/drivers/gpu/drm/radeon/cayman_blit_shaders.h new file mode 100644 index 00000000000..33b75e5d0fa --- /dev/null +++ b/drivers/gpu/drm/radeon/cayman_blit_shaders.h | |||
@@ -0,0 +1,32 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Advanced Micro Devices, 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 (including the next | ||
12 | * paragraph) shall be included in all copies or substantial portions of the | ||
13 | * Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
19 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
21 | * DEALINGS IN THE SOFTWARE. | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifndef CAYMAN_BLIT_SHADERS_H | ||
26 | #define CAYMAN_BLIT_SHADERS_H | ||
27 | |||
28 | extern const u32 cayman_default_state[]; | ||
29 | |||
30 | extern const u32 cayman_default_size; | ||
31 | |||
32 | #endif | ||
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 6140ea1de45..b9427e689cf 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
@@ -804,7 +804,7 @@ void evergreen_bandwidth_update(struct radeon_device *rdev) | |||
804 | } | 804 | } |
805 | } | 805 | } |
806 | 806 | ||
807 | static int evergreen_mc_wait_for_idle(struct radeon_device *rdev) | 807 | int evergreen_mc_wait_for_idle(struct radeon_device *rdev) |
808 | { | 808 | { |
809 | unsigned i; | 809 | unsigned i; |
810 | u32 tmp; | 810 | u32 tmp; |
@@ -957,7 +957,7 @@ void evergreen_agp_enable(struct radeon_device *rdev) | |||
957 | WREG32(VM_CONTEXT1_CNTL, 0); | 957 | WREG32(VM_CONTEXT1_CNTL, 0); |
958 | } | 958 | } |
959 | 959 | ||
960 | static void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save) | 960 | void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save) |
961 | { | 961 | { |
962 | save->vga_control[0] = RREG32(D1VGA_CONTROL); | 962 | save->vga_control[0] = RREG32(D1VGA_CONTROL); |
963 | save->vga_control[1] = RREG32(D2VGA_CONTROL); | 963 | save->vga_control[1] = RREG32(D2VGA_CONTROL); |
@@ -1011,7 +1011,7 @@ static void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_sa | |||
1011 | WREG32(EVERGREEN_D6VGA_CONTROL, 0); | 1011 | WREG32(EVERGREEN_D6VGA_CONTROL, 0); |
1012 | } | 1012 | } |
1013 | 1013 | ||
1014 | static void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) | 1014 | void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) |
1015 | { | 1015 | { |
1016 | WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET, | 1016 | WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET, |
1017 | upper_32_bits(rdev->mc.vram_start)); | 1017 | upper_32_bits(rdev->mc.vram_start)); |
@@ -1108,7 +1108,7 @@ static void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_ | |||
1108 | WREG32(VGA_RENDER_CONTROL, save->vga_render_control); | 1108 | WREG32(VGA_RENDER_CONTROL, save->vga_render_control); |
1109 | } | 1109 | } |
1110 | 1110 | ||
1111 | static void evergreen_mc_program(struct radeon_device *rdev) | 1111 | void evergreen_mc_program(struct radeon_device *rdev) |
1112 | { | 1112 | { |
1113 | struct evergreen_mc_save save; | 1113 | struct evergreen_mc_save save; |
1114 | u32 tmp; | 1114 | u32 tmp; |
@@ -2576,7 +2576,7 @@ void evergreen_irq_disable(struct radeon_device *rdev) | |||
2576 | evergreen_disable_interrupt_state(rdev); | 2576 | evergreen_disable_interrupt_state(rdev); |
2577 | } | 2577 | } |
2578 | 2578 | ||
2579 | static void evergreen_irq_suspend(struct radeon_device *rdev) | 2579 | void evergreen_irq_suspend(struct radeon_device *rdev) |
2580 | { | 2580 | { |
2581 | evergreen_irq_disable(rdev); | 2581 | evergreen_irq_disable(rdev); |
2582 | r600_rlc_stop(rdev); | 2582 | r600_rlc_stop(rdev); |
@@ -2899,7 +2899,7 @@ static int evergreen_startup(struct radeon_device *rdev) | |||
2899 | return r; | 2899 | return r; |
2900 | } | 2900 | } |
2901 | } | 2901 | } |
2902 | r = btc_mc_load_microcode(rdev); | 2902 | r = ni_mc_load_microcode(rdev); |
2903 | if (r) { | 2903 | if (r) { |
2904 | DRM_ERROR("Failed to load MC firmware!\n"); | 2904 | DRM_ERROR("Failed to load MC firmware!\n"); |
2905 | return r; | 2905 | return r; |
@@ -2981,7 +2981,7 @@ int evergreen_resume(struct radeon_device *rdev) | |||
2981 | 2981 | ||
2982 | r = evergreen_startup(rdev); | 2982 | r = evergreen_startup(rdev); |
2983 | if (r) { | 2983 | if (r) { |
2984 | DRM_ERROR("r600 startup failed on resume\n"); | 2984 | DRM_ERROR("evergreen startup failed on resume\n"); |
2985 | return r; | 2985 | return r; |
2986 | } | 2986 | } |
2987 | 2987 | ||
@@ -3061,7 +3061,7 @@ int evergreen_init(struct radeon_device *rdev) | |||
3061 | } | 3061 | } |
3062 | /* Must be an ATOMBIOS */ | 3062 | /* Must be an ATOMBIOS */ |
3063 | if (!rdev->is_atom_bios) { | 3063 | if (!rdev->is_atom_bios) { |
3064 | dev_err(rdev->dev, "Expecting atombios for R600 GPU\n"); | 3064 | dev_err(rdev->dev, "Expecting atombios for evergreen GPU\n"); |
3065 | return -EINVAL; | 3065 | return -EINVAL; |
3066 | } | 3066 | } |
3067 | r = radeon_atombios_init(rdev); | 3067 | r = radeon_atombios_init(rdev); |
diff --git a/drivers/gpu/drm/radeon/evergreen_blit_kms.c b/drivers/gpu/drm/radeon/evergreen_blit_kms.c index 2be698e78ff..ba06a69c6de 100644 --- a/drivers/gpu/drm/radeon/evergreen_blit_kms.c +++ b/drivers/gpu/drm/radeon/evergreen_blit_kms.c | |||
@@ -579,7 +579,7 @@ int evergreen_blit_init(struct radeon_device *rdev) | |||
579 | obj_size += evergreen_ps_size * 4; | 579 | obj_size += evergreen_ps_size * 4; |
580 | obj_size = ALIGN(obj_size, 256); | 580 | obj_size = ALIGN(obj_size, 256); |
581 | 581 | ||
582 | r = radeon_bo_create(rdev, NULL, obj_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, | 582 | r = radeon_bo_create(rdev, obj_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, |
583 | &rdev->r600_blit.shader_obj); | 583 | &rdev->r600_blit.shader_obj); |
584 | if (r) { | 584 | if (r) { |
585 | DRM_ERROR("evergreen failed to allocate shader\n"); | 585 | DRM_ERROR("evergreen failed to allocate shader\n"); |
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 345a75a03c9..5e4f9f876d4 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "radeon.h" | 29 | #include "radeon.h" |
30 | #include "evergreend.h" | 30 | #include "evergreend.h" |
31 | #include "evergreen_reg_safe.h" | 31 | #include "evergreen_reg_safe.h" |
32 | #include "cayman_reg_safe.h" | ||
32 | 33 | ||
33 | static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p, | 34 | static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p, |
34 | struct radeon_cs_reloc **cs_reloc); | 35 | struct radeon_cs_reloc **cs_reloc); |
@@ -425,18 +426,28 @@ static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u3 | |||
425 | { | 426 | { |
426 | struct evergreen_cs_track *track = (struct evergreen_cs_track *)p->track; | 427 | struct evergreen_cs_track *track = (struct evergreen_cs_track *)p->track; |
427 | struct radeon_cs_reloc *reloc; | 428 | struct radeon_cs_reloc *reloc; |
428 | u32 last_reg = ARRAY_SIZE(evergreen_reg_safe_bm); | 429 | u32 last_reg; |
429 | u32 m, i, tmp, *ib; | 430 | u32 m, i, tmp, *ib; |
430 | int r; | 431 | int r; |
431 | 432 | ||
433 | if (p->rdev->family >= CHIP_CAYMAN) | ||
434 | last_reg = ARRAY_SIZE(cayman_reg_safe_bm); | ||
435 | else | ||
436 | last_reg = ARRAY_SIZE(evergreen_reg_safe_bm); | ||
437 | |||
432 | i = (reg >> 7); | 438 | i = (reg >> 7); |
433 | if (i > last_reg) { | 439 | if (i > last_reg) { |
434 | dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); | 440 | dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); |
435 | return -EINVAL; | 441 | return -EINVAL; |
436 | } | 442 | } |
437 | m = 1 << ((reg >> 2) & 31); | 443 | m = 1 << ((reg >> 2) & 31); |
438 | if (!(evergreen_reg_safe_bm[i] & m)) | 444 | if (p->rdev->family >= CHIP_CAYMAN) { |
439 | return 0; | 445 | if (!(cayman_reg_safe_bm[i] & m)) |
446 | return 0; | ||
447 | } else { | ||
448 | if (!(evergreen_reg_safe_bm[i] & m)) | ||
449 | return 0; | ||
450 | } | ||
440 | ib = p->ib->ptr; | 451 | ib = p->ib->ptr; |
441 | switch (reg) { | 452 | switch (reg) { |
442 | /* force following reg to 0 in an attemp to disable out buffer | 453 | /* force following reg to 0 in an attemp to disable out buffer |
@@ -468,12 +479,42 @@ static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u3 | |||
468 | case SQ_VSTMP_RING_ITEMSIZE: | 479 | case SQ_VSTMP_RING_ITEMSIZE: |
469 | case VGT_TF_RING_SIZE: | 480 | case VGT_TF_RING_SIZE: |
470 | /* get value to populate the IB don't remove */ | 481 | /* get value to populate the IB don't remove */ |
471 | tmp =radeon_get_ib_value(p, idx); | 482 | /*tmp =radeon_get_ib_value(p, idx); |
472 | ib[idx] = 0; | 483 | ib[idx] = 0;*/ |
484 | break; | ||
485 | case SQ_ESGS_RING_BASE: | ||
486 | case SQ_GSVS_RING_BASE: | ||
487 | case SQ_ESTMP_RING_BASE: | ||
488 | case SQ_GSTMP_RING_BASE: | ||
489 | case SQ_HSTMP_RING_BASE: | ||
490 | case SQ_LSTMP_RING_BASE: | ||
491 | case SQ_PSTMP_RING_BASE: | ||
492 | case SQ_VSTMP_RING_BASE: | ||
493 | r = evergreen_cs_packet_next_reloc(p, &reloc); | ||
494 | if (r) { | ||
495 | dev_warn(p->dev, "bad SET_CONTEXT_REG " | ||
496 | "0x%04X\n", reg); | ||
497 | return -EINVAL; | ||
498 | } | ||
499 | ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); | ||
473 | break; | 500 | break; |
474 | case DB_DEPTH_CONTROL: | 501 | case DB_DEPTH_CONTROL: |
475 | track->db_depth_control = radeon_get_ib_value(p, idx); | 502 | track->db_depth_control = radeon_get_ib_value(p, idx); |
476 | break; | 503 | break; |
504 | case CAYMAN_DB_EQAA: | ||
505 | if (p->rdev->family < CHIP_CAYMAN) { | ||
506 | dev_warn(p->dev, "bad SET_CONTEXT_REG " | ||
507 | "0x%04X\n", reg); | ||
508 | return -EINVAL; | ||
509 | } | ||
510 | break; | ||
511 | case CAYMAN_DB_DEPTH_INFO: | ||
512 | if (p->rdev->family < CHIP_CAYMAN) { | ||
513 | dev_warn(p->dev, "bad SET_CONTEXT_REG " | ||
514 | "0x%04X\n", reg); | ||
515 | return -EINVAL; | ||
516 | } | ||
517 | break; | ||
477 | case DB_Z_INFO: | 518 | case DB_Z_INFO: |
478 | r = evergreen_cs_packet_next_reloc(p, &reloc); | 519 | r = evergreen_cs_packet_next_reloc(p, &reloc); |
479 | if (r) { | 520 | if (r) { |
@@ -559,9 +600,23 @@ static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u3 | |||
559 | track->cb_shader_mask = radeon_get_ib_value(p, idx); | 600 | track->cb_shader_mask = radeon_get_ib_value(p, idx); |
560 | break; | 601 | break; |
561 | case PA_SC_AA_CONFIG: | 602 | case PA_SC_AA_CONFIG: |
603 | if (p->rdev->family >= CHIP_CAYMAN) { | ||
604 | dev_warn(p->dev, "bad SET_CONTEXT_REG " | ||
605 | "0x%04X\n", reg); | ||
606 | return -EINVAL; | ||
607 | } | ||
562 | tmp = radeon_get_ib_value(p, idx) & MSAA_NUM_SAMPLES_MASK; | 608 | tmp = radeon_get_ib_value(p, idx) & MSAA_NUM_SAMPLES_MASK; |
563 | track->nsamples = 1 << tmp; | 609 | track->nsamples = 1 << tmp; |
564 | break; | 610 | break; |
611 | case CAYMAN_PA_SC_AA_CONFIG: | ||
612 | if (p->rdev->family < CHIP_CAYMAN) { | ||
613 | dev_warn(p->dev, "bad SET_CONTEXT_REG " | ||
614 | "0x%04X\n", reg); | ||
615 | return -EINVAL; | ||
616 | } | ||
617 | tmp = radeon_get_ib_value(p, idx) & CAYMAN_MSAA_NUM_SAMPLES_MASK; | ||
618 | track->nsamples = 1 << tmp; | ||
619 | break; | ||
565 | case CB_COLOR0_VIEW: | 620 | case CB_COLOR0_VIEW: |
566 | case CB_COLOR1_VIEW: | 621 | case CB_COLOR1_VIEW: |
567 | case CB_COLOR2_VIEW: | 622 | case CB_COLOR2_VIEW: |
@@ -942,6 +997,37 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, | |||
942 | idx_value = radeon_get_ib_value(p, idx); | 997 | idx_value = radeon_get_ib_value(p, idx); |
943 | 998 | ||
944 | switch (pkt->opcode) { | 999 | switch (pkt->opcode) { |
1000 | case PACKET3_SET_PREDICATION: | ||
1001 | { | ||
1002 | int pred_op; | ||
1003 | int tmp; | ||
1004 | if (pkt->count != 1) { | ||
1005 | DRM_ERROR("bad SET PREDICATION\n"); | ||
1006 | return -EINVAL; | ||
1007 | } | ||
1008 | |||
1009 | tmp = radeon_get_ib_value(p, idx + 1); | ||
1010 | pred_op = (tmp >> 16) & 0x7; | ||
1011 | |||
1012 | /* for the clear predicate operation */ | ||
1013 | if (pred_op == 0) | ||
1014 | return 0; | ||
1015 | |||
1016 | if (pred_op > 2) { | ||
1017 | DRM_ERROR("bad SET PREDICATION operation %d\n", pred_op); | ||
1018 | return -EINVAL; | ||
1019 | } | ||
1020 | |||
1021 | r = evergreen_cs_packet_next_reloc(p, &reloc); | ||
1022 | if (r) { | ||
1023 | DRM_ERROR("bad SET PREDICATION\n"); | ||
1024 | return -EINVAL; | ||
1025 | } | ||
1026 | |||
1027 | ib[idx + 0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff); | ||
1028 | ib[idx + 1] = tmp + (upper_32_bits(reloc->lobj.gpu_offset) & 0xff); | ||
1029 | } | ||
1030 | break; | ||
945 | case PACKET3_CONTEXT_CONTROL: | 1031 | case PACKET3_CONTEXT_CONTROL: |
946 | if (pkt->count != 1) { | 1032 | if (pkt->count != 1) { |
947 | DRM_ERROR("bad CONTEXT_CONTROL\n"); | 1033 | DRM_ERROR("bad CONTEXT_CONTROL\n"); |
@@ -956,6 +1042,16 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, | |||
956 | return -EINVAL; | 1042 | return -EINVAL; |
957 | } | 1043 | } |
958 | break; | 1044 | break; |
1045 | case CAYMAN_PACKET3_DEALLOC_STATE: | ||
1046 | if (p->rdev->family < CHIP_CAYMAN) { | ||
1047 | DRM_ERROR("bad PACKET3_DEALLOC_STATE\n"); | ||
1048 | return -EINVAL; | ||
1049 | } | ||
1050 | if (pkt->count) { | ||
1051 | DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n"); | ||
1052 | return -EINVAL; | ||
1053 | } | ||
1054 | break; | ||
959 | case PACKET3_INDEX_BASE: | 1055 | case PACKET3_INDEX_BASE: |
960 | if (pkt->count != 1) { | 1056 | if (pkt->count != 1) { |
961 | DRM_ERROR("bad INDEX_BASE\n"); | 1057 | DRM_ERROR("bad INDEX_BASE\n"); |
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index eb4acf4528f..9aaa3f0c937 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h | |||
@@ -755,13 +755,21 @@ | |||
755 | 755 | ||
756 | #define SQ_CONST_MEM_BASE 0x8df8 | 756 | #define SQ_CONST_MEM_BASE 0x8df8 |
757 | 757 | ||
758 | #define SQ_ESGS_RING_BASE 0x8c40 | ||
758 | #define SQ_ESGS_RING_SIZE 0x8c44 | 759 | #define SQ_ESGS_RING_SIZE 0x8c44 |
760 | #define SQ_GSVS_RING_BASE 0x8c48 | ||
759 | #define SQ_GSVS_RING_SIZE 0x8c4c | 761 | #define SQ_GSVS_RING_SIZE 0x8c4c |
762 | #define SQ_ESTMP_RING_BASE 0x8c50 | ||
760 | #define SQ_ESTMP_RING_SIZE 0x8c54 | 763 | #define SQ_ESTMP_RING_SIZE 0x8c54 |
764 | #define SQ_GSTMP_RING_BASE 0x8c58 | ||
761 | #define SQ_GSTMP_RING_SIZE 0x8c5c | 765 | #define SQ_GSTMP_RING_SIZE 0x8c5c |
766 | #define SQ_VSTMP_RING_BASE 0x8c60 | ||
762 | #define SQ_VSTMP_RING_SIZE 0x8c64 | 767 | #define SQ_VSTMP_RING_SIZE 0x8c64 |
768 | #define SQ_PSTMP_RING_BASE 0x8c68 | ||
763 | #define SQ_PSTMP_RING_SIZE 0x8c6c | 769 | #define SQ_PSTMP_RING_SIZE 0x8c6c |
770 | #define SQ_LSTMP_RING_BASE 0x8e10 | ||
764 | #define SQ_LSTMP_RING_SIZE 0x8e14 | 771 | #define SQ_LSTMP_RING_SIZE 0x8e14 |
772 | #define SQ_HSTMP_RING_BASE 0x8e18 | ||
765 | #define SQ_HSTMP_RING_SIZE 0x8e1c | 773 | #define SQ_HSTMP_RING_SIZE 0x8e1c |
766 | #define VGT_TF_RING_SIZE 0x8988 | 774 | #define VGT_TF_RING_SIZE 0x8988 |
767 | 775 | ||
@@ -1093,5 +1101,14 @@ | |||
1093 | #define SQ_TEX_RESOURCE_WORD6_0 0x30018 | 1101 | #define SQ_TEX_RESOURCE_WORD6_0 0x30018 |
1094 | #define SQ_TEX_RESOURCE_WORD7_0 0x3001c | 1102 | #define SQ_TEX_RESOURCE_WORD7_0 0x3001c |
1095 | 1103 | ||
1104 | /* cayman 3D regs */ | ||
1105 | #define CAYMAN_VGT_OFFCHIP_LDS_BASE 0x89B0 | ||
1106 | #define CAYMAN_DB_EQAA 0x28804 | ||
1107 | #define CAYMAN_DB_DEPTH_INFO 0x2803C | ||
1108 | #define CAYMAN_PA_SC_AA_CONFIG 0x28BE0 | ||
1109 | #define CAYMAN_MSAA_NUM_SAMPLES_SHIFT 0 | ||
1110 | #define CAYMAN_MSAA_NUM_SAMPLES_MASK 0x7 | ||
1111 | /* cayman packet3 addition */ | ||
1112 | #define CAYMAN_PACKET3_DEALLOC_STATE 0x14 | ||
1096 | 1113 | ||
1097 | #endif | 1114 | #endif |
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 5e0bef80ad7..7aade20f63a 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c | |||
@@ -31,12 +31,25 @@ | |||
31 | #include "nid.h" | 31 | #include "nid.h" |
32 | #include "atom.h" | 32 | #include "atom.h" |
33 | #include "ni_reg.h" | 33 | #include "ni_reg.h" |
34 | #include "cayman_blit_shaders.h" | ||
35 | |||
36 | extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save); | ||
37 | extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save); | ||
38 | extern int evergreen_mc_wait_for_idle(struct radeon_device *rdev); | ||
39 | extern void evergreen_mc_program(struct radeon_device *rdev); | ||
40 | extern void evergreen_irq_suspend(struct radeon_device *rdev); | ||
41 | extern int evergreen_mc_init(struct radeon_device *rdev); | ||
34 | 42 | ||
35 | #define EVERGREEN_PFP_UCODE_SIZE 1120 | 43 | #define EVERGREEN_PFP_UCODE_SIZE 1120 |
36 | #define EVERGREEN_PM4_UCODE_SIZE 1376 | 44 | #define EVERGREEN_PM4_UCODE_SIZE 1376 |
37 | #define EVERGREEN_RLC_UCODE_SIZE 768 | 45 | #define EVERGREEN_RLC_UCODE_SIZE 768 |
38 | #define BTC_MC_UCODE_SIZE 6024 | 46 | #define BTC_MC_UCODE_SIZE 6024 |
39 | 47 | ||
48 | #define CAYMAN_PFP_UCODE_SIZE 2176 | ||
49 | #define CAYMAN_PM4_UCODE_SIZE 2176 | ||
50 | #define CAYMAN_RLC_UCODE_SIZE 1024 | ||
51 | #define CAYMAN_MC_UCODE_SIZE 6037 | ||
52 | |||
40 | /* Firmware Names */ | 53 | /* Firmware Names */ |
41 | MODULE_FIRMWARE("radeon/BARTS_pfp.bin"); | 54 | MODULE_FIRMWARE("radeon/BARTS_pfp.bin"); |
42 | MODULE_FIRMWARE("radeon/BARTS_me.bin"); | 55 | MODULE_FIRMWARE("radeon/BARTS_me.bin"); |
@@ -48,6 +61,10 @@ MODULE_FIRMWARE("radeon/TURKS_mc.bin"); | |||
48 | MODULE_FIRMWARE("radeon/CAICOS_pfp.bin"); | 61 | MODULE_FIRMWARE("radeon/CAICOS_pfp.bin"); |
49 | MODULE_FIRMWARE("radeon/CAICOS_me.bin"); | 62 | MODULE_FIRMWARE("radeon/CAICOS_me.bin"); |
50 | MODULE_FIRMWARE("radeon/CAICOS_mc.bin"); | 63 | MODULE_FIRMWARE("radeon/CAICOS_mc.bin"); |
64 | MODULE_FIRMWARE("radeon/CAYMAN_pfp.bin"); | ||
65 | MODULE_FIRMWARE("radeon/CAYMAN_me.bin"); | ||
66 | MODULE_FIRMWARE("radeon/CAYMAN_mc.bin"); | ||
67 | MODULE_FIRMWARE("radeon/CAYMAN_rlc.bin"); | ||
51 | 68 | ||
52 | #define BTC_IO_MC_REGS_SIZE 29 | 69 | #define BTC_IO_MC_REGS_SIZE 29 |
53 | 70 | ||
@@ -147,12 +164,44 @@ static const u32 caicos_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = { | |||
147 | {0x0000009f, 0x00916a00} | 164 | {0x0000009f, 0x00916a00} |
148 | }; | 165 | }; |
149 | 166 | ||
150 | int btc_mc_load_microcode(struct radeon_device *rdev) | 167 | static const u32 cayman_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = { |
168 | {0x00000077, 0xff010100}, | ||
169 | {0x00000078, 0x00000000}, | ||
170 | {0x00000079, 0x00001434}, | ||
171 | {0x0000007a, 0xcc08ec08}, | ||
172 | {0x0000007b, 0x00040000}, | ||
173 | {0x0000007c, 0x000080c0}, | ||
174 | {0x0000007d, 0x09000000}, | ||
175 | {0x0000007e, 0x00210404}, | ||
176 | {0x00000081, 0x08a8e800}, | ||
177 | {0x00000082, 0x00030444}, | ||
178 | {0x00000083, 0x00000000}, | ||
179 | {0x00000085, 0x00000001}, | ||
180 | {0x00000086, 0x00000002}, | ||
181 | {0x00000087, 0x48490000}, | ||
182 | {0x00000088, 0x20244647}, | ||
183 | {0x00000089, 0x00000005}, | ||
184 | {0x0000008b, 0x66030000}, | ||
185 | {0x0000008c, 0x00006603}, | ||
186 | {0x0000008d, 0x00000100}, | ||
187 | {0x0000008f, 0x00001c0a}, | ||
188 | {0x00000090, 0xff000001}, | ||
189 | {0x00000094, 0x00101101}, | ||
190 | {0x00000095, 0x00000fff}, | ||
191 | {0x00000096, 0x00116fff}, | ||
192 | {0x00000097, 0x60010000}, | ||
193 | {0x00000098, 0x10010000}, | ||
194 | {0x00000099, 0x00006000}, | ||
195 | {0x0000009a, 0x00001000}, | ||
196 | {0x0000009f, 0x00976b00} | ||
197 | }; | ||
198 | |||
199 | int ni_mc_load_microcode(struct radeon_device *rdev) | ||
151 | { | 200 | { |
152 | const __be32 *fw_data; | 201 | const __be32 *fw_data; |
153 | u32 mem_type, running, blackout = 0; | 202 | u32 mem_type, running, blackout = 0; |
154 | u32 *io_mc_regs; | 203 | u32 *io_mc_regs; |
155 | int i; | 204 | int i, ucode_size, regs_size; |
156 | 205 | ||
157 | if (!rdev->mc_fw) | 206 | if (!rdev->mc_fw) |
158 | return -EINVAL; | 207 | return -EINVAL; |
@@ -160,13 +209,24 @@ int btc_mc_load_microcode(struct radeon_device *rdev) | |||
160 | switch (rdev->family) { | 209 | switch (rdev->family) { |
161 | case CHIP_BARTS: | 210 | case CHIP_BARTS: |
162 | io_mc_regs = (u32 *)&barts_io_mc_regs; | 211 | io_mc_regs = (u32 *)&barts_io_mc_regs; |
212 | ucode_size = BTC_MC_UCODE_SIZE; | ||
213 | regs_size = BTC_IO_MC_REGS_SIZE; | ||
163 | break; | 214 | break; |
164 | case CHIP_TURKS: | 215 | case CHIP_TURKS: |
165 | io_mc_regs = (u32 *)&turks_io_mc_regs; | 216 | io_mc_regs = (u32 *)&turks_io_mc_regs; |
217 | ucode_size = BTC_MC_UCODE_SIZE; | ||
218 | regs_size = BTC_IO_MC_REGS_SIZE; | ||
166 | break; | 219 | break; |
167 | case CHIP_CAICOS: | 220 | case CHIP_CAICOS: |
168 | default: | 221 | default: |
169 | io_mc_regs = (u32 *)&caicos_io_mc_regs; | 222 | io_mc_regs = (u32 *)&caicos_io_mc_regs; |
223 | ucode_size = BTC_MC_UCODE_SIZE; | ||
224 | regs_size = BTC_IO_MC_REGS_SIZE; | ||
225 | break; | ||
226 | case CHIP_CAYMAN: | ||
227 | io_mc_regs = (u32 *)&cayman_io_mc_regs; | ||
228 | ucode_size = CAYMAN_MC_UCODE_SIZE; | ||
229 | regs_size = BTC_IO_MC_REGS_SIZE; | ||
170 | break; | 230 | break; |
171 | } | 231 | } |
172 | 232 | ||
@@ -184,13 +244,13 @@ int btc_mc_load_microcode(struct radeon_device *rdev) | |||
184 | WREG32(MC_SEQ_SUP_CNTL, 0x00000010); | 244 | WREG32(MC_SEQ_SUP_CNTL, 0x00000010); |
185 | 245 | ||
186 | /* load mc io regs */ | 246 | /* load mc io regs */ |
187 | for (i = 0; i < BTC_IO_MC_REGS_SIZE; i++) { | 247 | for (i = 0; i < regs_size; i++) { |
188 | WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]); | 248 | WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]); |
189 | WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]); | 249 | WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]); |
190 | } | 250 | } |
191 | /* load the MC ucode */ | 251 | /* load the MC ucode */ |
192 | fw_data = (const __be32 *)rdev->mc_fw->data; | 252 | fw_data = (const __be32 *)rdev->mc_fw->data; |
193 | for (i = 0; i < BTC_MC_UCODE_SIZE; i++) | 253 | for (i = 0; i < ucode_size; i++) |
194 | WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++)); | 254 | WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++)); |
195 | 255 | ||
196 | /* put the engine back into the active state */ | 256 | /* put the engine back into the active state */ |
@@ -231,23 +291,38 @@ int ni_init_microcode(struct radeon_device *rdev) | |||
231 | case CHIP_BARTS: | 291 | case CHIP_BARTS: |
232 | chip_name = "BARTS"; | 292 | chip_name = "BARTS"; |
233 | rlc_chip_name = "BTC"; | 293 | rlc_chip_name = "BTC"; |
294 | pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4; | ||
295 | me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4; | ||
296 | rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4; | ||
297 | mc_req_size = BTC_MC_UCODE_SIZE * 4; | ||
234 | break; | 298 | break; |
235 | case CHIP_TURKS: | 299 | case CHIP_TURKS: |
236 | chip_name = "TURKS"; | 300 | chip_name = "TURKS"; |
237 | rlc_chip_name = "BTC"; | 301 | rlc_chip_name = "BTC"; |
302 | pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4; | ||
303 | me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4; | ||
304 | rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4; | ||
305 | mc_req_size = BTC_MC_UCODE_SIZE * 4; | ||
238 | break; | 306 | break; |
239 | case CHIP_CAICOS: | 307 | case CHIP_CAICOS: |
240 | chip_name = "CAICOS"; | 308 | chip_name = "CAICOS"; |
241 | rlc_chip_name = "BTC"; | 309 | rlc_chip_name = "BTC"; |
310 | pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4; | ||
311 | me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4; | ||
312 | rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4; | ||
313 | mc_req_size = BTC_MC_UCODE_SIZE * 4; | ||
314 | break; | ||
315 | case CHIP_CAYMAN: | ||
316 | chip_name = "CAYMAN"; | ||
317 | rlc_chip_name = "CAYMAN"; | ||
318 | pfp_req_size = CAYMAN_PFP_UCODE_SIZE * 4; | ||
319 | me_req_size = CAYMAN_PM4_UCODE_SIZE * 4; | ||
320 | rlc_req_size = CAYMAN_RLC_UCODE_SIZE * 4; | ||
321 | mc_req_size = CAYMAN_MC_UCODE_SIZE * 4; | ||
242 | break; | 322 | break; |
243 | default: BUG(); | 323 | default: BUG(); |
244 | } | 324 | } |
245 | 325 | ||
246 | pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4; | ||
247 | me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4; | ||
248 | rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4; | ||
249 | mc_req_size = BTC_MC_UCODE_SIZE * 4; | ||
250 | |||
251 | DRM_INFO("Loading %s Microcode\n", chip_name); | 326 | DRM_INFO("Loading %s Microcode\n", chip_name); |
252 | 327 | ||
253 | snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name); | 328 | snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name); |
@@ -314,3 +389,1204 @@ out: | |||
314 | return err; | 389 | return err; |
315 | } | 390 | } |
316 | 391 | ||
392 | /* | ||
393 | * Core functions | ||
394 | */ | ||
395 | static u32 cayman_get_tile_pipe_to_backend_map(struct radeon_device *rdev, | ||
396 | u32 num_tile_pipes, | ||
397 | u32 num_backends_per_asic, | ||
398 | u32 *backend_disable_mask_per_asic, | ||
399 | u32 num_shader_engines) | ||
400 | { | ||
401 | u32 backend_map = 0; | ||
402 | u32 enabled_backends_mask = 0; | ||
403 | u32 enabled_backends_count = 0; | ||
404 | u32 num_backends_per_se; | ||
405 | u32 cur_pipe; | ||
406 | u32 swizzle_pipe[CAYMAN_MAX_PIPES]; | ||
407 | u32 cur_backend = 0; | ||
408 | u32 i; | ||
409 | bool force_no_swizzle; | ||
410 | |||
411 | /* force legal values */ | ||
412 | if (num_tile_pipes < 1) | ||
413 | num_tile_pipes = 1; | ||
414 | if (num_tile_pipes > rdev->config.cayman.max_tile_pipes) | ||
415 | num_tile_pipes = rdev->config.cayman.max_tile_pipes; | ||
416 | if (num_shader_engines < 1) | ||
417 | num_shader_engines = 1; | ||
418 | if (num_shader_engines > rdev->config.cayman.max_shader_engines) | ||
419 | num_shader_engines = rdev->config.cayman.max_shader_engines; | ||
420 | if (num_backends_per_asic > num_shader_engines) | ||
421 | num_backends_per_asic = num_shader_engines; | ||
422 | if (num_backends_per_asic > (rdev->config.cayman.max_backends_per_se * num_shader_engines)) | ||
423 | num_backends_per_asic = rdev->config.cayman.max_backends_per_se * num_shader_engines; | ||
424 | |||
425 | /* make sure we have the same number of backends per se */ | ||
426 | num_backends_per_asic = ALIGN(num_backends_per_asic, num_shader_engines); | ||
427 | /* set up the number of backends per se */ | ||
428 | num_backends_per_se = num_backends_per_asic / num_shader_engines; | ||
429 | if (num_backends_per_se > rdev->config.cayman.max_backends_per_se) { | ||
430 | num_backends_per_se = rdev->config.cayman.max_backends_per_se; | ||
431 | num_backends_per_asic = num_backends_per_se * num_shader_engines; | ||
432 | } | ||
433 | |||
434 | /* create enable mask and count for enabled backends */ | ||
435 | for (i = 0; i < CAYMAN_MAX_BACKENDS; ++i) { | ||
436 | if (((*backend_disable_mask_per_asic >> i) & 1) == 0) { | ||
437 | enabled_backends_mask |= (1 << i); | ||
438 | ++enabled_backends_count; | ||
439 | } | ||
440 | if (enabled_backends_count == num_backends_per_asic) | ||
441 | break; | ||
442 | } | ||
443 | |||
444 | /* force the backends mask to match the current number of backends */ | ||
445 | if (enabled_backends_count != num_backends_per_asic) { | ||
446 | u32 this_backend_enabled; | ||
447 | u32 shader_engine; | ||
448 | u32 backend_per_se; | ||
449 | |||
450 | enabled_backends_mask = 0; | ||
451 | enabled_backends_count = 0; | ||
452 | *backend_disable_mask_per_asic = CAYMAN_MAX_BACKENDS_MASK; | ||
453 | for (i = 0; i < CAYMAN_MAX_BACKENDS; ++i) { | ||
454 | /* calc the current se */ | ||
455 | shader_engine = i / rdev->config.cayman.max_backends_per_se; | ||
456 | /* calc the backend per se */ | ||
457 | backend_per_se = i % rdev->config.cayman.max_backends_per_se; | ||
458 | /* default to not enabled */ | ||
459 | this_backend_enabled = 0; | ||
460 | if ((shader_engine < num_shader_engines) && | ||
461 | (backend_per_se < num_backends_per_se)) | ||
462 | this_backend_enabled = 1; | ||
463 | if (this_backend_enabled) { | ||
464 | enabled_backends_mask |= (1 << i); | ||
465 | *backend_disable_mask_per_asic &= ~(1 << i); | ||
466 | ++enabled_backends_count; | ||
467 | } | ||
468 | } | ||
469 | } | ||
470 | |||
471 | |||
472 | memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * CAYMAN_MAX_PIPES); | ||
473 | switch (rdev->family) { | ||
474 | case CHIP_CAYMAN: | ||
475 | force_no_swizzle = true; | ||
476 | break; | ||
477 | default: | ||
478 | force_no_swizzle = false; | ||
479 | break; | ||
480 | } | ||
481 | if (force_no_swizzle) { | ||
482 | bool last_backend_enabled = false; | ||
483 | |||
484 | force_no_swizzle = false; | ||
485 | for (i = 0; i < CAYMAN_MAX_BACKENDS; ++i) { | ||
486 | if (((enabled_backends_mask >> i) & 1) == 1) { | ||
487 | if (last_backend_enabled) | ||
488 | force_no_swizzle = true; | ||
489 | last_backend_enabled = true; | ||
490 | } else | ||
491 | last_backend_enabled = false; | ||
492 | } | ||
493 | } | ||
494 | |||
495 | switch (num_tile_pipes) { | ||
496 | case 1: | ||
497 | case 3: | ||
498 | case 5: | ||
499 | case 7: | ||
500 | DRM_ERROR("odd number of pipes!\n"); | ||
501 | break; | ||
502 | case 2: | ||
503 | swizzle_pipe[0] = 0; | ||
504 | swizzle_pipe[1] = 1; | ||
505 | break; | ||
506 | case 4: | ||
507 | if (force_no_swizzle) { | ||
508 | swizzle_pipe[0] = 0; | ||
509 | swizzle_pipe[1] = 1; | ||
510 | swizzle_pipe[2] = 2; | ||
511 | swizzle_pipe[3] = 3; | ||
512 | } else { | ||
513 | swizzle_pipe[0] = 0; | ||
514 | swizzle_pipe[1] = 2; | ||
515 | swizzle_pipe[2] = 1; | ||
516 | swizzle_pipe[3] = 3; | ||
517 | } | ||
518 | break; | ||
519 | case 6: | ||
520 | if (force_no_swizzle) { | ||
521 | swizzle_pipe[0] = 0; | ||
522 | swizzle_pipe[1] = 1; | ||
523 | swizzle_pipe[2] = 2; | ||
524 | swizzle_pipe[3] = 3; | ||
525 | swizzle_pipe[4] = 4; | ||
526 | swizzle_pipe[5] = 5; | ||
527 | } else { | ||
528 | swizzle_pipe[0] = 0; | ||
529 | swizzle_pipe[1] = 2; | ||
530 | swizzle_pipe[2] = 4; | ||
531 | swizzle_pipe[3] = 1; | ||
532 | swizzle_pipe[4] = 3; | ||
533 | swizzle_pipe[5] = 5; | ||
534 | } | ||
535 | break; | ||
536 | case 8: | ||
537 | if (force_no_swizzle) { | ||
538 | swizzle_pipe[0] = 0; | ||
539 | swizzle_pipe[1] = 1; | ||
540 | swizzle_pipe[2] = 2; | ||
541 | swizzle_pipe[3] = 3; | ||
542 | swizzle_pipe[4] = 4; | ||
543 | swizzle_pipe[5] = 5; | ||
544 | swizzle_pipe[6] = 6; | ||
545 | swizzle_pipe[7] = 7; | ||
546 | } else { | ||
547 | swizzle_pipe[0] = 0; | ||
548 | swizzle_pipe[1] = 2; | ||
549 | swizzle_pipe[2] = 4; | ||
550 | swizzle_pipe[3] = 6; | ||
551 | swizzle_pipe[4] = 1; | ||
552 | swizzle_pipe[5] = 3; | ||
553 | swizzle_pipe[6] = 5; | ||
554 | swizzle_pipe[7] = 7; | ||
555 | } | ||
556 | break; | ||
557 | } | ||
558 | |||
559 | for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) { | ||
560 | while (((1 << cur_backend) & enabled_backends_mask) == 0) | ||
561 | cur_backend = (cur_backend + 1) % CAYMAN_MAX_BACKENDS; | ||
562 | |||
563 | backend_map |= (((cur_backend & 0xf) << (swizzle_pipe[cur_pipe] * 4))); | ||
564 | |||
565 | cur_backend = (cur_backend + 1) % CAYMAN_MAX_BACKENDS; | ||
566 | } | ||
567 | |||
568 | return backend_map; | ||
569 | } | ||
570 | |||
571 | static void cayman_program_channel_remap(struct radeon_device *rdev) | ||
572 | { | ||
573 | u32 tcp_chan_steer_lo, tcp_chan_steer_hi, mc_shared_chremap, tmp; | ||
574 | |||
575 | tmp = RREG32(MC_SHARED_CHMAP); | ||
576 | switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) { | ||
577 | case 0: | ||
578 | case 1: | ||
579 | case 2: | ||
580 | case 3: | ||
581 | default: | ||
582 | /* default mapping */ | ||
583 | mc_shared_chremap = 0x00fac688; | ||
584 | break; | ||
585 | } | ||
586 | |||
587 | switch (rdev->family) { | ||
588 | case CHIP_CAYMAN: | ||
589 | default: | ||
590 | //tcp_chan_steer_lo = 0x54763210 | ||
591 | tcp_chan_steer_lo = 0x76543210; | ||
592 | tcp_chan_steer_hi = 0x0000ba98; | ||
593 | break; | ||
594 | } | ||
595 | |||
596 | WREG32(TCP_CHAN_STEER_LO, tcp_chan_steer_lo); | ||
597 | WREG32(TCP_CHAN_STEER_HI, tcp_chan_steer_hi); | ||
598 | WREG32(MC_SHARED_CHREMAP, mc_shared_chremap); | ||
599 | } | ||
600 | |||
601 | static u32 cayman_get_disable_mask_per_asic(struct radeon_device *rdev, | ||
602 | u32 disable_mask_per_se, | ||
603 | u32 max_disable_mask_per_se, | ||
604 | u32 num_shader_engines) | ||
605 | { | ||
606 | u32 disable_field_width_per_se = r600_count_pipe_bits(disable_mask_per_se); | ||
607 | u32 disable_mask_per_asic = disable_mask_per_se & max_disable_mask_per_se; | ||
608 | |||
609 | if (num_shader_engines == 1) | ||
610 | return disable_mask_per_asic; | ||
611 | else if (num_shader_engines == 2) | ||
612 | return disable_mask_per_asic | (disable_mask_per_asic << disable_field_width_per_se); | ||
613 | else | ||
614 | return 0xffffffff; | ||
615 | } | ||
616 | |||
617 | static void cayman_gpu_init(struct radeon_device *rdev) | ||
618 | { | ||
619 | u32 cc_rb_backend_disable = 0; | ||
620 | u32 cc_gc_shader_pipe_config; | ||
621 | u32 gb_addr_config = 0; | ||
622 | u32 mc_shared_chmap, mc_arb_ramcfg; | ||
623 | u32 gb_backend_map; | ||
624 | u32 cgts_tcc_disable; | ||
625 | u32 sx_debug_1; | ||
626 | u32 smx_dc_ctl0; | ||
627 | u32 gc_user_shader_pipe_config; | ||
628 | u32 gc_user_rb_backend_disable; | ||
629 | u32 cgts_user_tcc_disable; | ||
630 | u32 cgts_sm_ctrl_reg; | ||
631 | u32 hdp_host_path_cntl; | ||
632 | u32 tmp; | ||
633 | int i, j; | ||
634 | |||
635 | switch (rdev->family) { | ||
636 | case CHIP_CAYMAN: | ||
637 | default: | ||
638 | rdev->config.cayman.max_shader_engines = 2; | ||
639 | rdev->config.cayman.max_pipes_per_simd = 4; | ||
640 | rdev->config.cayman.max_tile_pipes = 8; | ||
641 | rdev->config.cayman.max_simds_per_se = 12; | ||
642 | rdev->config.cayman.max_backends_per_se = 4; | ||
643 | rdev->config.cayman.max_texture_channel_caches = 8; | ||
644 | rdev->config.cayman.max_gprs = 256; | ||
645 | rdev->config.cayman.max_threads = 256; | ||
646 | rdev->config.cayman.max_gs_threads = 32; | ||
647 | rdev->config.cayman.max_stack_entries = 512; | ||
648 | rdev->config.cayman.sx_num_of_sets = 8; | ||
649 | rdev->config.cayman.sx_max_export_size = 256; | ||
650 | rdev->config.cayman.sx_max_export_pos_size = 64; | ||
651 | rdev->config.cayman.sx_max_export_smx_size = 192; | ||
652 | rdev->config.cayman.max_hw_contexts = 8; | ||
653 | rdev->config.cayman.sq_num_cf_insts = 2; | ||
654 | |||
655 | rdev->config.cayman.sc_prim_fifo_size = 0x100; | ||
656 | rdev->config.cayman.sc_hiz_tile_fifo_size = 0x30; | ||
657 | rdev->config.cayman.sc_earlyz_tile_fifo_size = 0x130; | ||
658 | break; | ||
659 | } | ||
660 | |||
661 | /* Initialize HDP */ | ||
662 | for (i = 0, j = 0; i < 32; i++, j += 0x18) { | ||
663 | WREG32((0x2c14 + j), 0x00000000); | ||
664 | WREG32((0x2c18 + j), 0x00000000); | ||
665 | WREG32((0x2c1c + j), 0x00000000); | ||
666 | WREG32((0x2c20 + j), 0x00000000); | ||
667 | WREG32((0x2c24 + j), 0x00000000); | ||
668 | } | ||
669 | |||
670 | WREG32(GRBM_CNTL, GRBM_READ_TIMEOUT(0xff)); | ||
671 | |||
672 | mc_shared_chmap = RREG32(MC_SHARED_CHMAP); | ||
673 | mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); | ||
674 | |||
675 | cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE); | ||
676 | cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG); | ||
677 | cgts_tcc_disable = RREG32(CGTS_TCC_DISABLE); | ||
678 | gc_user_rb_backend_disable = RREG32(GC_USER_RB_BACKEND_DISABLE); | ||
679 | gc_user_shader_pipe_config = RREG32(GC_USER_SHADER_PIPE_CONFIG); | ||
680 | cgts_user_tcc_disable = RREG32(CGTS_USER_TCC_DISABLE); | ||
681 | |||
682 | rdev->config.cayman.num_shader_engines = rdev->config.cayman.max_shader_engines; | ||
683 | tmp = ((~gc_user_shader_pipe_config) & INACTIVE_QD_PIPES_MASK) >> INACTIVE_QD_PIPES_SHIFT; | ||
684 | rdev->config.cayman.num_shader_pipes_per_simd = r600_count_pipe_bits(tmp); | ||
685 | rdev->config.cayman.num_tile_pipes = rdev->config.cayman.max_tile_pipes; | ||
686 | tmp = ((~gc_user_shader_pipe_config) & INACTIVE_SIMDS_MASK) >> INACTIVE_SIMDS_SHIFT; | ||
687 | rdev->config.cayman.num_simds_per_se = r600_count_pipe_bits(tmp); | ||
688 | tmp = ((~gc_user_rb_backend_disable) & BACKEND_DISABLE_MASK) >> BACKEND_DISABLE_SHIFT; | ||
689 | rdev->config.cayman.num_backends_per_se = r600_count_pipe_bits(tmp); | ||
690 | tmp = (gc_user_rb_backend_disable & BACKEND_DISABLE_MASK) >> BACKEND_DISABLE_SHIFT; | ||
691 | rdev->config.cayman.backend_disable_mask_per_asic = | ||
692 | cayman_get_disable_mask_per_asic(rdev, tmp, CAYMAN_MAX_BACKENDS_PER_SE_MASK, | ||
693 | rdev->config.cayman.num_shader_engines); | ||
694 | rdev->config.cayman.backend_map = | ||
695 | cayman_get_tile_pipe_to_backend_map(rdev, rdev->config.cayman.num_tile_pipes, | ||
696 | rdev->config.cayman.num_backends_per_se * | ||
697 | rdev->config.cayman.num_shader_engines, | ||
698 | &rdev->config.cayman.backend_disable_mask_per_asic, | ||
699 | rdev->config.cayman.num_shader_engines); | ||
700 | tmp = ((~cgts_user_tcc_disable) & TCC_DISABLE_MASK) >> TCC_DISABLE_SHIFT; | ||
701 | rdev->config.cayman.num_texture_channel_caches = r600_count_pipe_bits(tmp); | ||
702 | tmp = (mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT; | ||
703 | rdev->config.cayman.mem_max_burst_length_bytes = (tmp + 1) * 256; | ||
704 | if (rdev->config.cayman.mem_max_burst_length_bytes > 512) | ||
705 | rdev->config.cayman.mem_max_burst_length_bytes = 512; | ||
706 | tmp = (mc_arb_ramcfg & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT; | ||
707 | rdev->config.cayman.mem_row_size_in_kb = (4 * (1 << (8 + tmp))) / 1024; | ||
708 | if (rdev->config.cayman.mem_row_size_in_kb > 4) | ||
709 | rdev->config.cayman.mem_row_size_in_kb = 4; | ||
710 | /* XXX use MC settings? */ | ||
711 | rdev->config.cayman.shader_engine_tile_size = 32; | ||
712 | rdev->config.cayman.num_gpus = 1; | ||
713 | rdev->config.cayman.multi_gpu_tile_size = 64; | ||
714 | |||
715 | //gb_addr_config = 0x02011003 | ||
716 | #if 0 | ||
717 | gb_addr_config = RREG32(GB_ADDR_CONFIG); | ||
718 | #else | ||
719 | gb_addr_config = 0; | ||
720 | switch (rdev->config.cayman.num_tile_pipes) { | ||
721 | case 1: | ||
722 | default: | ||
723 | gb_addr_config |= NUM_PIPES(0); | ||
724 | break; | ||
725 | case 2: | ||
726 | gb_addr_config |= NUM_PIPES(1); | ||
727 | break; | ||
728 | case 4: | ||
729 | gb_addr_config |= NUM_PIPES(2); | ||
730 | break; | ||
731 | case 8: | ||
732 | gb_addr_config |= NUM_PIPES(3); | ||
733 | break; | ||
734 | } | ||
735 | |||
736 | tmp = (rdev->config.cayman.mem_max_burst_length_bytes / 256) - 1; | ||
737 | gb_addr_config |= PIPE_INTERLEAVE_SIZE(tmp); | ||
738 | gb_addr_config |= NUM_SHADER_ENGINES(rdev->config.cayman.num_shader_engines - 1); | ||
739 | tmp = (rdev->config.cayman.shader_engine_tile_size / 16) - 1; | ||
740 | gb_addr_config |= SHADER_ENGINE_TILE_SIZE(tmp); | ||
741 | switch (rdev->config.cayman.num_gpus) { | ||
742 | case 1: | ||
743 | default: | ||
744 | gb_addr_config |= NUM_GPUS(0); | ||
745 | break; | ||
746 | case 2: | ||
747 | gb_addr_config |= NUM_GPUS(1); | ||
748 | break; | ||
749 | case 4: | ||
750 | gb_addr_config |= NUM_GPUS(2); | ||
751 | break; | ||
752 | } | ||
753 | switch (rdev->config.cayman.multi_gpu_tile_size) { | ||
754 | case 16: | ||
755 | gb_addr_config |= MULTI_GPU_TILE_SIZE(0); | ||
756 | break; | ||
757 | case 32: | ||
758 | default: | ||
759 | gb_addr_config |= MULTI_GPU_TILE_SIZE(1); | ||
760 | break; | ||
761 | case 64: | ||
762 | gb_addr_config |= MULTI_GPU_TILE_SIZE(2); | ||
763 | break; | ||
764 | case 128: | ||
765 | gb_addr_config |= MULTI_GPU_TILE_SIZE(3); | ||
766 | break; | ||
767 | } | ||
768 | switch (rdev->config.cayman.mem_row_size_in_kb) { | ||
769 | case 1: | ||
770 | default: | ||
771 | gb_addr_config |= ROW_SIZE(0); | ||
772 | break; | ||
773 | case 2: | ||
774 | gb_addr_config |= ROW_SIZE(1); | ||
775 | break; | ||
776 | case 4: | ||
777 | gb_addr_config |= ROW_SIZE(2); | ||
778 | break; | ||
779 | } | ||
780 | #endif | ||
781 | |||
782 | tmp = (gb_addr_config & NUM_PIPES_MASK) >> NUM_PIPES_SHIFT; | ||
783 | rdev->config.cayman.num_tile_pipes = (1 << tmp); | ||
784 | tmp = (gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT; | ||
785 | rdev->config.cayman.mem_max_burst_length_bytes = (tmp + 1) * 256; | ||
786 | tmp = (gb_addr_config & NUM_SHADER_ENGINES_MASK) >> NUM_SHADER_ENGINES_SHIFT; | ||
787 | rdev->config.cayman.num_shader_engines = tmp + 1; | ||
788 | tmp = (gb_addr_config & NUM_GPUS_MASK) >> NUM_GPUS_SHIFT; | ||
789 | rdev->config.cayman.num_gpus = tmp + 1; | ||
790 | tmp = (gb_addr_config & MULTI_GPU_TILE_SIZE_MASK) >> MULTI_GPU_TILE_SIZE_SHIFT; | ||
791 | rdev->config.cayman.multi_gpu_tile_size = 1 << tmp; | ||
792 | tmp = (gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT; | ||
793 | rdev->config.cayman.mem_row_size_in_kb = 1 << tmp; | ||
794 | |||
795 | //gb_backend_map = 0x76541032; | ||
796 | #if 0 | ||
797 | gb_backend_map = RREG32(GB_BACKEND_MAP); | ||
798 | #else | ||
799 | gb_backend_map = | ||
800 | cayman_get_tile_pipe_to_backend_map(rdev, rdev->config.cayman.num_tile_pipes, | ||
801 | rdev->config.cayman.num_backends_per_se * | ||
802 | rdev->config.cayman.num_shader_engines, | ||
803 | &rdev->config.cayman.backend_disable_mask_per_asic, | ||
804 | rdev->config.cayman.num_shader_engines); | ||
805 | #endif | ||
806 | /* setup tiling info dword. gb_addr_config is not adequate since it does | ||
807 | * not have bank info, so create a custom tiling dword. | ||
808 | * bits 3:0 num_pipes | ||
809 | * bits 7:4 num_banks | ||
810 | * bits 11:8 group_size | ||
811 | * bits 15:12 row_size | ||
812 | */ | ||
813 | rdev->config.cayman.tile_config = 0; | ||
814 | switch (rdev->config.cayman.num_tile_pipes) { | ||
815 | case 1: | ||
816 | default: | ||
817 | rdev->config.cayman.tile_config |= (0 << 0); | ||
818 | break; | ||
819 | case 2: | ||
820 | rdev->config.cayman.tile_config |= (1 << 0); | ||
821 | break; | ||
822 | case 4: | ||
823 | rdev->config.cayman.tile_config |= (2 << 0); | ||
824 | break; | ||
825 | case 8: | ||
826 | rdev->config.cayman.tile_config |= (3 << 0); | ||
827 | break; | ||
828 | } | ||
829 | rdev->config.cayman.tile_config |= | ||
830 | ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4; | ||
831 | rdev->config.cayman.tile_config |= | ||
832 | (gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT; | ||
833 | rdev->config.cayman.tile_config |= | ||
834 | ((gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT) << 12; | ||
835 | |||
836 | WREG32(GB_BACKEND_MAP, gb_backend_map); | ||
837 | WREG32(GB_ADDR_CONFIG, gb_addr_config); | ||
838 | WREG32(DMIF_ADDR_CONFIG, gb_addr_config); | ||
839 | WREG32(HDP_ADDR_CONFIG, gb_addr_config); | ||
840 | |||
841 | cayman_program_channel_remap(rdev); | ||
842 | |||
843 | /* primary versions */ | ||
844 | WREG32(CC_RB_BACKEND_DISABLE, cc_rb_backend_disable); | ||
845 | WREG32(CC_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable); | ||
846 | WREG32(CC_GC_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); | ||
847 | |||
848 | WREG32(CGTS_TCC_DISABLE, cgts_tcc_disable); | ||
849 | WREG32(CGTS_SYS_TCC_DISABLE, cgts_tcc_disable); | ||
850 | |||
851 | /* user versions */ | ||
852 | WREG32(GC_USER_RB_BACKEND_DISABLE, cc_rb_backend_disable); | ||
853 | WREG32(GC_USER_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable); | ||
854 | WREG32(GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); | ||
855 | |||
856 | WREG32(CGTS_USER_SYS_TCC_DISABLE, cgts_tcc_disable); | ||
857 | WREG32(CGTS_USER_TCC_DISABLE, cgts_tcc_disable); | ||
858 | |||
859 | /* reprogram the shader complex */ | ||
860 | cgts_sm_ctrl_reg = RREG32(CGTS_SM_CTRL_REG); | ||
861 | for (i = 0; i < 16; i++) | ||
862 | WREG32(CGTS_SM_CTRL_REG, OVERRIDE); | ||
863 | WREG32(CGTS_SM_CTRL_REG, cgts_sm_ctrl_reg); | ||
864 | |||
865 | /* set HW defaults for 3D engine */ | ||
866 | WREG32(CP_MEQ_THRESHOLDS, MEQ1_START(0x30) | MEQ2_START(0x60)); | ||
867 | |||
868 | sx_debug_1 = RREG32(SX_DEBUG_1); | ||
869 | sx_debug_1 |= ENABLE_NEW_SMX_ADDRESS; | ||
870 | WREG32(SX_DEBUG_1, sx_debug_1); | ||
871 | |||
872 | smx_dc_ctl0 = RREG32(SMX_DC_CTL0); | ||
873 | smx_dc_ctl0 &= ~NUMBER_OF_SETS(0x1ff); | ||
874 | smx_dc_ctl0 |= NUMBER_OF_SETS(rdev->config.evergreen.sx_num_of_sets); | ||
875 | WREG32(SMX_DC_CTL0, smx_dc_ctl0); | ||
876 | |||
877 | WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(4) | CRC_SIMD_ID_WADDR_DISABLE); | ||
878 | |||
879 | /* need to be explicitly zero-ed */ | ||
880 | WREG32(VGT_OFFCHIP_LDS_BASE, 0); | ||
881 | WREG32(SQ_LSTMP_RING_BASE, 0); | ||
882 | WREG32(SQ_HSTMP_RING_BASE, 0); | ||
883 | WREG32(SQ_ESTMP_RING_BASE, 0); | ||
884 | WREG32(SQ_GSTMP_RING_BASE, 0); | ||
885 | WREG32(SQ_VSTMP_RING_BASE, 0); | ||
886 | WREG32(SQ_PSTMP_RING_BASE, 0); | ||
887 | |||
888 | WREG32(TA_CNTL_AUX, DISABLE_CUBE_ANISO); | ||
889 | |||
890 | WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_size / 4) - 1) | | ||
891 | POSITION_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_pos_size / 4) - 1) | | ||
892 | SMX_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_smx_size / 4) - 1))); | ||
893 | |||
894 | WREG32(PA_SC_FIFO_SIZE, (SC_PRIM_FIFO_SIZE(rdev->config.evergreen.sc_prim_fifo_size) | | ||
895 | SC_HIZ_TILE_FIFO_SIZE(rdev->config.evergreen.sc_hiz_tile_fifo_size) | | ||
896 | SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.evergreen.sc_earlyz_tile_fifo_size))); | ||
897 | |||
898 | |||
899 | WREG32(VGT_NUM_INSTANCES, 1); | ||
900 | |||
901 | WREG32(CP_PERFMON_CNTL, 0); | ||
902 | |||
903 | WREG32(SQ_MS_FIFO_SIZES, (CACHE_FIFO_SIZE(16 * rdev->config.evergreen.sq_num_cf_insts) | | ||
904 | FETCH_FIFO_HIWATER(0x4) | | ||
905 | DONE_FIFO_HIWATER(0xe0) | | ||
906 | ALU_UPDATE_FIFO_HIWATER(0x8))); | ||
907 | |||
908 | WREG32(SQ_GPR_RESOURCE_MGMT_1, NUM_CLAUSE_TEMP_GPRS(4)); | ||
909 | WREG32(SQ_CONFIG, (VC_ENABLE | | ||
910 | EXPORT_SRC_C | | ||
911 | GFX_PRIO(0) | | ||
912 | CS1_PRIO(0) | | ||
913 | CS2_PRIO(1))); | ||
914 | WREG32(SQ_DYN_GPR_CNTL_PS_FLUSH_REQ, DYN_GPR_ENABLE); | ||
915 | |||
916 | WREG32(PA_SC_FORCE_EOV_MAX_CNTS, (FORCE_EOV_MAX_CLK_CNT(4095) | | ||
917 | FORCE_EOV_MAX_REZ_CNT(255))); | ||
918 | |||
919 | WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(VC_AND_TC) | | ||
920 | AUTO_INVLD_EN(ES_AND_GS_AUTO)); | ||
921 | |||
922 | WREG32(VGT_GS_VERTEX_REUSE, 16); | ||
923 | WREG32(PA_SC_LINE_STIPPLE_STATE, 0); | ||
924 | |||
925 | WREG32(CB_PERF_CTR0_SEL_0, 0); | ||
926 | WREG32(CB_PERF_CTR0_SEL_1, 0); | ||
927 | WREG32(CB_PERF_CTR1_SEL_0, 0); | ||
928 | WREG32(CB_PERF_CTR1_SEL_1, 0); | ||
929 | WREG32(CB_PERF_CTR2_SEL_0, 0); | ||
930 | WREG32(CB_PERF_CTR2_SEL_1, 0); | ||
931 | WREG32(CB_PERF_CTR3_SEL_0, 0); | ||
932 | WREG32(CB_PERF_CTR3_SEL_1, 0); | ||
933 | |||
934 | hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL); | ||
935 | WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl); | ||
936 | |||
937 | WREG32(PA_CL_ENHANCE, CLIP_VTX_REORDER_ENA | NUM_CLIP_SEQ(3)); | ||
938 | |||
939 | udelay(50); | ||
940 | } | ||
941 | |||
942 | /* | ||
943 | * GART | ||
944 | */ | ||
945 | void cayman_pcie_gart_tlb_flush(struct radeon_device *rdev) | ||
946 | { | ||
947 | /* flush hdp cache */ | ||
948 | WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); | ||
949 | |||
950 | /* bits 0-7 are the VM contexts0-7 */ | ||
951 | WREG32(VM_INVALIDATE_REQUEST, 1); | ||
952 | } | ||
953 | |||
954 | int cayman_pcie_gart_enable(struct radeon_device *rdev) | ||
955 | { | ||
956 | int r; | ||
957 | |||
958 | if (rdev->gart.table.vram.robj == NULL) { | ||
959 | dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); | ||
960 | return -EINVAL; | ||
961 | } | ||
962 | r = radeon_gart_table_vram_pin(rdev); | ||
963 | if (r) | ||
964 | return r; | ||
965 | radeon_gart_restore(rdev); | ||
966 | /* Setup TLB control */ | ||
967 | WREG32(MC_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB | | ||
968 | ENABLE_L1_FRAGMENT_PROCESSING | | ||
969 | SYSTEM_ACCESS_MODE_NOT_IN_SYS | | ||
970 | SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU); | ||
971 | /* Setup L2 cache */ | ||
972 | WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | | ||
973 | ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | | ||
974 | ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE | | ||
975 | EFFECTIVE_L2_QUEUE_SIZE(7) | | ||
976 | CONTEXT1_IDENTITY_ACCESS_MODE(1)); | ||
977 | WREG32(VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS | INVALIDATE_L2_CACHE); | ||
978 | WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY | | ||
979 | L2_CACHE_BIGK_FRAGMENT_SIZE(6)); | ||
980 | /* setup context0 */ | ||
981 | WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); | ||
982 | WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12); | ||
983 | WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12); | ||
984 | WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, | ||
985 | (u32)(rdev->dummy_page.addr >> 12)); | ||
986 | WREG32(VM_CONTEXT0_CNTL2, 0); | ||
987 | WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) | | ||
988 | RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); | ||
989 | /* disable context1-7 */ | ||
990 | WREG32(VM_CONTEXT1_CNTL2, 0); | ||
991 | WREG32(VM_CONTEXT1_CNTL, 0); | ||
992 | |||
993 | cayman_pcie_gart_tlb_flush(rdev); | ||
994 | rdev->gart.ready = true; | ||
995 | return 0; | ||
996 | } | ||
997 | |||
998 | void cayman_pcie_gart_disable(struct radeon_device *rdev) | ||
999 | { | ||
1000 | int r; | ||
1001 | |||
1002 | /* Disable all tables */ | ||
1003 | WREG32(VM_CONTEXT0_CNTL, 0); | ||
1004 | WREG32(VM_CONTEXT1_CNTL, 0); | ||
1005 | /* Setup TLB control */ | ||
1006 | WREG32(MC_VM_MX_L1_TLB_CNTL, ENABLE_L1_FRAGMENT_PROCESSING | | ||
1007 | SYSTEM_ACCESS_MODE_NOT_IN_SYS | | ||
1008 | SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU); | ||
1009 | /* Setup L2 cache */ | ||
1010 | WREG32(VM_L2_CNTL, ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | | ||
1011 | ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE | | ||
1012 | EFFECTIVE_L2_QUEUE_SIZE(7) | | ||
1013 | CONTEXT1_IDENTITY_ACCESS_MODE(1)); | ||
1014 | WREG32(VM_L2_CNTL2, 0); | ||
1015 | WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY | | ||
1016 | L2_CACHE_BIGK_FRAGMENT_SIZE(6)); | ||
1017 | if (rdev->gart.table.vram.robj) { | ||
1018 | r = radeon_bo_reserve(rdev->gart.table.vram.robj, false); | ||
1019 | if (likely(r == 0)) { | ||
1020 | radeon_bo_kunmap(rdev->gart.table.vram.robj); | ||
1021 | radeon_bo_unpin(rdev->gart.table.vram.robj); | ||
1022 | radeon_bo_unreserve(rdev->gart.table.vram.robj); | ||
1023 | } | ||
1024 | } | ||
1025 | } | ||
1026 | |||
1027 | void cayman_pcie_gart_fini(struct radeon_device *rdev) | ||
1028 | { | ||
1029 | cayman_pcie_gart_disable(rdev); | ||
1030 | radeon_gart_table_vram_free(rdev); | ||
1031 | radeon_gart_fini(rdev); | ||
1032 | } | ||
1033 | |||
1034 | /* | ||
1035 | * CP. | ||
1036 | */ | ||
1037 | static void cayman_cp_enable(struct radeon_device *rdev, bool enable) | ||
1038 | { | ||
1039 | if (enable) | ||
1040 | WREG32(CP_ME_CNTL, 0); | ||
1041 | else { | ||
1042 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); | ||
1043 | WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT)); | ||
1044 | WREG32(SCRATCH_UMSK, 0); | ||
1045 | } | ||
1046 | } | ||
1047 | |||
1048 | static int cayman_cp_load_microcode(struct radeon_device *rdev) | ||
1049 | { | ||
1050 | const __be32 *fw_data; | ||
1051 | int i; | ||
1052 | |||
1053 | if (!rdev->me_fw || !rdev->pfp_fw) | ||
1054 | return -EINVAL; | ||
1055 | |||
1056 | cayman_cp_enable(rdev, false); | ||
1057 | |||
1058 | fw_data = (const __be32 *)rdev->pfp_fw->data; | ||
1059 | WREG32(CP_PFP_UCODE_ADDR, 0); | ||
1060 | for (i = 0; i < CAYMAN_PFP_UCODE_SIZE; i++) | ||
1061 | WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++)); | ||
1062 | WREG32(CP_PFP_UCODE_ADDR, 0); | ||
1063 | |||
1064 | fw_data = (const __be32 *)rdev->me_fw->data; | ||
1065 | WREG32(CP_ME_RAM_WADDR, 0); | ||
1066 | for (i = 0; i < CAYMAN_PM4_UCODE_SIZE; i++) | ||
1067 | WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++)); | ||
1068 | |||
1069 | WREG32(CP_PFP_UCODE_ADDR, 0); | ||
1070 | WREG32(CP_ME_RAM_WADDR, 0); | ||
1071 | WREG32(CP_ME_RAM_RADDR, 0); | ||
1072 | return 0; | ||
1073 | } | ||
1074 | |||
1075 | static int cayman_cp_start(struct radeon_device *rdev) | ||
1076 | { | ||
1077 | int r, i; | ||
1078 | |||
1079 | r = radeon_ring_lock(rdev, 7); | ||
1080 | if (r) { | ||
1081 | DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); | ||
1082 | return r; | ||
1083 | } | ||
1084 | radeon_ring_write(rdev, PACKET3(PACKET3_ME_INITIALIZE, 5)); | ||
1085 | radeon_ring_write(rdev, 0x1); | ||
1086 | radeon_ring_write(rdev, 0x0); | ||
1087 | radeon_ring_write(rdev, rdev->config.cayman.max_hw_contexts - 1); | ||
1088 | radeon_ring_write(rdev, PACKET3_ME_INITIALIZE_DEVICE_ID(1)); | ||
1089 | radeon_ring_write(rdev, 0); | ||
1090 | radeon_ring_write(rdev, 0); | ||
1091 | radeon_ring_unlock_commit(rdev); | ||
1092 | |||
1093 | cayman_cp_enable(rdev, true); | ||
1094 | |||
1095 | r = radeon_ring_lock(rdev, cayman_default_size + 19); | ||
1096 | if (r) { | ||
1097 | DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); | ||
1098 | return r; | ||
1099 | } | ||
1100 | |||
1101 | /* setup clear context state */ | ||
1102 | radeon_ring_write(rdev, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); | ||
1103 | radeon_ring_write(rdev, PACKET3_PREAMBLE_BEGIN_CLEAR_STATE); | ||
1104 | |||
1105 | for (i = 0; i < cayman_default_size; i++) | ||
1106 | radeon_ring_write(rdev, cayman_default_state[i]); | ||
1107 | |||
1108 | radeon_ring_write(rdev, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); | ||
1109 | radeon_ring_write(rdev, PACKET3_PREAMBLE_END_CLEAR_STATE); | ||
1110 | |||
1111 | /* set clear context state */ | ||
1112 | radeon_ring_write(rdev, PACKET3(PACKET3_CLEAR_STATE, 0)); | ||
1113 | radeon_ring_write(rdev, 0); | ||
1114 | |||
1115 | /* SQ_VTX_BASE_VTX_LOC */ | ||
1116 | radeon_ring_write(rdev, 0xc0026f00); | ||
1117 | radeon_ring_write(rdev, 0x00000000); | ||
1118 | radeon_ring_write(rdev, 0x00000000); | ||
1119 | radeon_ring_write(rdev, 0x00000000); | ||
1120 | |||
1121 | /* Clear consts */ | ||
1122 | radeon_ring_write(rdev, 0xc0036f00); | ||
1123 | radeon_ring_write(rdev, 0x00000bc4); | ||
1124 | radeon_ring_write(rdev, 0xffffffff); | ||
1125 | radeon_ring_write(rdev, 0xffffffff); | ||
1126 | radeon_ring_write(rdev, 0xffffffff); | ||
1127 | |||
1128 | radeon_ring_write(rdev, 0xc0026900); | ||
1129 | radeon_ring_write(rdev, 0x00000316); | ||
1130 | radeon_ring_write(rdev, 0x0000000e); /* VGT_VERTEX_REUSE_BLOCK_CNTL */ | ||
1131 | radeon_ring_write(rdev, 0x00000010); /* */ | ||
1132 | |||
1133 | radeon_ring_unlock_commit(rdev); | ||
1134 | |||
1135 | /* XXX init other rings */ | ||
1136 | |||
1137 | return 0; | ||
1138 | } | ||
1139 | |||
1140 | static void cayman_cp_fini(struct radeon_device *rdev) | ||
1141 | { | ||
1142 | cayman_cp_enable(rdev, false); | ||
1143 | radeon_ring_fini(rdev); | ||
1144 | } | ||
1145 | |||
1146 | int cayman_cp_resume(struct radeon_device *rdev) | ||
1147 | { | ||
1148 | u32 tmp; | ||
1149 | u32 rb_bufsz; | ||
1150 | int r; | ||
1151 | |||
1152 | /* Reset cp; if cp is reset, then PA, SH, VGT also need to be reset */ | ||
1153 | WREG32(GRBM_SOFT_RESET, (SOFT_RESET_CP | | ||
1154 | SOFT_RESET_PA | | ||
1155 | SOFT_RESET_SH | | ||
1156 | SOFT_RESET_VGT | | ||
1157 | SOFT_RESET_SX)); | ||
1158 | RREG32(GRBM_SOFT_RESET); | ||
1159 | mdelay(15); | ||
1160 | WREG32(GRBM_SOFT_RESET, 0); | ||
1161 | RREG32(GRBM_SOFT_RESET); | ||
1162 | |||
1163 | WREG32(CP_SEM_WAIT_TIMER, 0x4); | ||
1164 | |||
1165 | /* Set the write pointer delay */ | ||
1166 | WREG32(CP_RB_WPTR_DELAY, 0); | ||
1167 | |||
1168 | WREG32(CP_DEBUG, (1 << 27)); | ||
1169 | |||
1170 | /* ring 0 - compute and gfx */ | ||
1171 | /* Set ring buffer size */ | ||
1172 | rb_bufsz = drm_order(rdev->cp.ring_size / 8); | ||
1173 | tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; | ||
1174 | #ifdef __BIG_ENDIAN | ||
1175 | tmp |= BUF_SWAP_32BIT; | ||
1176 | #endif | ||
1177 | WREG32(CP_RB0_CNTL, tmp); | ||
1178 | |||
1179 | /* Initialize the ring buffer's read and write pointers */ | ||
1180 | WREG32(CP_RB0_CNTL, tmp | RB_RPTR_WR_ENA); | ||
1181 | WREG32(CP_RB0_WPTR, 0); | ||
1182 | |||
1183 | /* set the wb address wether it's enabled or not */ | ||
1184 | WREG32(CP_RB0_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC); | ||
1185 | WREG32(CP_RB0_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF); | ||
1186 | WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF); | ||
1187 | |||
1188 | if (rdev->wb.enabled) | ||
1189 | WREG32(SCRATCH_UMSK, 0xff); | ||
1190 | else { | ||
1191 | tmp |= RB_NO_UPDATE; | ||
1192 | WREG32(SCRATCH_UMSK, 0); | ||
1193 | } | ||
1194 | |||
1195 | mdelay(1); | ||
1196 | WREG32(CP_RB0_CNTL, tmp); | ||
1197 | |||
1198 | WREG32(CP_RB0_BASE, rdev->cp.gpu_addr >> 8); | ||
1199 | |||
1200 | rdev->cp.rptr = RREG32(CP_RB0_RPTR); | ||
1201 | rdev->cp.wptr = RREG32(CP_RB0_WPTR); | ||
1202 | |||
1203 | /* ring1 - compute only */ | ||
1204 | /* Set ring buffer size */ | ||
1205 | rb_bufsz = drm_order(rdev->cp1.ring_size / 8); | ||
1206 | tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; | ||
1207 | #ifdef __BIG_ENDIAN | ||
1208 | tmp |= BUF_SWAP_32BIT; | ||
1209 | #endif | ||
1210 | WREG32(CP_RB1_CNTL, tmp); | ||
1211 | |||
1212 | /* Initialize the ring buffer's read and write pointers */ | ||
1213 | WREG32(CP_RB1_CNTL, tmp | RB_RPTR_WR_ENA); | ||
1214 | WREG32(CP_RB1_WPTR, 0); | ||
1215 | |||
1216 | /* set the wb address wether it's enabled or not */ | ||
1217 | WREG32(CP_RB1_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFFFFFFFC); | ||
1218 | WREG32(CP_RB1_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFF); | ||
1219 | |||
1220 | mdelay(1); | ||
1221 | WREG32(CP_RB1_CNTL, tmp); | ||
1222 | |||
1223 | WREG32(CP_RB1_BASE, rdev->cp1.gpu_addr >> 8); | ||
1224 | |||
1225 | rdev->cp1.rptr = RREG32(CP_RB1_RPTR); | ||
1226 | rdev->cp1.wptr = RREG32(CP_RB1_WPTR); | ||
1227 | |||
1228 | /* ring2 - compute only */ | ||
1229 | /* Set ring buffer size */ | ||
1230 | rb_bufsz = drm_order(rdev->cp2.ring_size / 8); | ||
1231 | tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; | ||
1232 | #ifdef __BIG_ENDIAN | ||
1233 | tmp |= BUF_SWAP_32BIT; | ||
1234 | #endif | ||
1235 | WREG32(CP_RB2_CNTL, tmp); | ||
1236 | |||
1237 | /* Initialize the ring buffer's read and write pointers */ | ||
1238 | WREG32(CP_RB2_CNTL, tmp | RB_RPTR_WR_ENA); | ||
1239 | WREG32(CP_RB2_WPTR, 0); | ||
1240 | |||
1241 | /* set the wb address wether it's enabled or not */ | ||
1242 | WREG32(CP_RB2_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFFFFFFFC); | ||
1243 | WREG32(CP_RB2_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFF); | ||
1244 | |||
1245 | mdelay(1); | ||
1246 | WREG32(CP_RB2_CNTL, tmp); | ||
1247 | |||
1248 | WREG32(CP_RB2_BASE, rdev->cp2.gpu_addr >> 8); | ||
1249 | |||
1250 | rdev->cp2.rptr = RREG32(CP_RB2_RPTR); | ||
1251 | rdev->cp2.wptr = RREG32(CP_RB2_WPTR); | ||
1252 | |||
1253 | /* start the rings */ | ||
1254 | cayman_cp_start(rdev); | ||
1255 | rdev->cp.ready = true; | ||
1256 | rdev->cp1.ready = true; | ||
1257 | rdev->cp2.ready = true; | ||
1258 | /* this only test cp0 */ | ||
1259 | r = radeon_ring_test(rdev); | ||
1260 | if (r) { | ||
1261 | rdev->cp.ready = false; | ||
1262 | rdev->cp1.ready = false; | ||
1263 | rdev->cp2.ready = false; | ||
1264 | return r; | ||
1265 | } | ||
1266 | |||
1267 | return 0; | ||
1268 | } | ||
1269 | |||
1270 | bool cayman_gpu_is_lockup(struct radeon_device *rdev) | ||
1271 | { | ||
1272 | u32 srbm_status; | ||
1273 | u32 grbm_status; | ||
1274 | u32 grbm_status_se0, grbm_status_se1; | ||
1275 | struct r100_gpu_lockup *lockup = &rdev->config.cayman.lockup; | ||
1276 | int r; | ||
1277 | |||
1278 | srbm_status = RREG32(SRBM_STATUS); | ||
1279 | grbm_status = RREG32(GRBM_STATUS); | ||
1280 | grbm_status_se0 = RREG32(GRBM_STATUS_SE0); | ||
1281 | grbm_status_se1 = RREG32(GRBM_STATUS_SE1); | ||
1282 | if (!(grbm_status & GUI_ACTIVE)) { | ||
1283 | r100_gpu_lockup_update(lockup, &rdev->cp); | ||
1284 | return false; | ||
1285 | } | ||
1286 | /* force CP activities */ | ||
1287 | r = radeon_ring_lock(rdev, 2); | ||
1288 | if (!r) { | ||
1289 | /* PACKET2 NOP */ | ||
1290 | radeon_ring_write(rdev, 0x80000000); | ||
1291 | radeon_ring_write(rdev, 0x80000000); | ||
1292 | radeon_ring_unlock_commit(rdev); | ||
1293 | } | ||
1294 | /* XXX deal with CP0,1,2 */ | ||
1295 | rdev->cp.rptr = RREG32(CP_RB0_RPTR); | ||
1296 | return r100_gpu_cp_is_lockup(rdev, lockup, &rdev->cp); | ||
1297 | } | ||
1298 | |||
1299 | static int cayman_gpu_soft_reset(struct radeon_device *rdev) | ||
1300 | { | ||
1301 | struct evergreen_mc_save save; | ||
1302 | u32 grbm_reset = 0; | ||
1303 | |||
1304 | if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) | ||
1305 | return 0; | ||
1306 | |||
1307 | dev_info(rdev->dev, "GPU softreset \n"); | ||
1308 | dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n", | ||
1309 | RREG32(GRBM_STATUS)); | ||
1310 | dev_info(rdev->dev, " GRBM_STATUS_SE0=0x%08X\n", | ||
1311 | RREG32(GRBM_STATUS_SE0)); | ||
1312 | dev_info(rdev->dev, " GRBM_STATUS_SE1=0x%08X\n", | ||
1313 | RREG32(GRBM_STATUS_SE1)); | ||
1314 | dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", | ||
1315 | RREG32(SRBM_STATUS)); | ||
1316 | evergreen_mc_stop(rdev, &save); | ||
1317 | if (evergreen_mc_wait_for_idle(rdev)) { | ||
1318 | dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); | ||
1319 | } | ||
1320 | /* Disable CP parsing/prefetching */ | ||
1321 | WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT); | ||
1322 | |||
1323 | /* reset all the gfx blocks */ | ||
1324 | grbm_reset = (SOFT_RESET_CP | | ||
1325 | SOFT_RESET_CB | | ||
1326 | SOFT_RESET_DB | | ||
1327 | SOFT_RESET_GDS | | ||
1328 | SOFT_RESET_PA | | ||
1329 | SOFT_RESET_SC | | ||
1330 | SOFT_RESET_SPI | | ||
1331 | SOFT_RESET_SH | | ||
1332 | SOFT_RESET_SX | | ||
1333 | SOFT_RESET_TC | | ||
1334 | SOFT_RESET_TA | | ||
1335 | SOFT_RESET_VGT | | ||
1336 | SOFT_RESET_IA); | ||
1337 | |||
1338 | dev_info(rdev->dev, " GRBM_SOFT_RESET=0x%08X\n", grbm_reset); | ||
1339 | WREG32(GRBM_SOFT_RESET, grbm_reset); | ||
1340 | (void)RREG32(GRBM_SOFT_RESET); | ||
1341 | udelay(50); | ||
1342 | WREG32(GRBM_SOFT_RESET, 0); | ||
1343 | (void)RREG32(GRBM_SOFT_RESET); | ||
1344 | /* Wait a little for things to settle down */ | ||
1345 | udelay(50); | ||
1346 | dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n", | ||
1347 | RREG32(GRBM_STATUS)); | ||
1348 | dev_info(rdev->dev, " GRBM_STATUS_SE0=0x%08X\n", | ||
1349 | RREG32(GRBM_STATUS_SE0)); | ||
1350 | dev_info(rdev->dev, " GRBM_STATUS_SE1=0x%08X\n", | ||
1351 | RREG32(GRBM_STATUS_SE1)); | ||
1352 | dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", | ||
1353 | RREG32(SRBM_STATUS)); | ||
1354 | evergreen_mc_resume(rdev, &save); | ||
1355 | return 0; | ||
1356 | } | ||
1357 | |||
1358 | int cayman_asic_reset(struct radeon_device *rdev) | ||
1359 | { | ||
1360 | return cayman_gpu_soft_reset(rdev); | ||
1361 | } | ||
1362 | |||
1363 | static int cayman_startup(struct radeon_device *rdev) | ||
1364 | { | ||
1365 | int r; | ||
1366 | |||
1367 | if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) { | ||
1368 | r = ni_init_microcode(rdev); | ||
1369 | if (r) { | ||
1370 | DRM_ERROR("Failed to load firmware!\n"); | ||
1371 | return r; | ||
1372 | } | ||
1373 | } | ||
1374 | r = ni_mc_load_microcode(rdev); | ||
1375 | if (r) { | ||
1376 | DRM_ERROR("Failed to load MC firmware!\n"); | ||
1377 | return r; | ||
1378 | } | ||
1379 | |||
1380 | evergreen_mc_program(rdev); | ||
1381 | r = cayman_pcie_gart_enable(rdev); | ||
1382 | if (r) | ||
1383 | return r; | ||
1384 | cayman_gpu_init(rdev); | ||
1385 | |||
1386 | #if 0 | ||
1387 | r = cayman_blit_init(rdev); | ||
1388 | if (r) { | ||
1389 | cayman_blit_fini(rdev); | ||
1390 | rdev->asic->copy = NULL; | ||
1391 | dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); | ||
1392 | } | ||
1393 | #endif | ||
1394 | |||
1395 | /* allocate wb buffer */ | ||
1396 | r = radeon_wb_init(rdev); | ||
1397 | if (r) | ||
1398 | return r; | ||
1399 | |||
1400 | /* Enable IRQ */ | ||
1401 | r = r600_irq_init(rdev); | ||
1402 | if (r) { | ||
1403 | DRM_ERROR("radeon: IH init failed (%d).\n", r); | ||
1404 | radeon_irq_kms_fini(rdev); | ||
1405 | return r; | ||
1406 | } | ||
1407 | evergreen_irq_set(rdev); | ||
1408 | |||
1409 | r = radeon_ring_init(rdev, rdev->cp.ring_size); | ||
1410 | if (r) | ||
1411 | return r; | ||
1412 | r = cayman_cp_load_microcode(rdev); | ||
1413 | if (r) | ||
1414 | return r; | ||
1415 | r = cayman_cp_resume(rdev); | ||
1416 | if (r) | ||
1417 | return r; | ||
1418 | |||
1419 | return 0; | ||
1420 | } | ||
1421 | |||
1422 | int cayman_resume(struct radeon_device *rdev) | ||
1423 | { | ||
1424 | int r; | ||
1425 | |||
1426 | /* Do not reset GPU before posting, on rv770 hw unlike on r500 hw, | ||
1427 | * posting will perform necessary task to bring back GPU into good | ||
1428 | * shape. | ||
1429 | */ | ||
1430 | /* post card */ | ||
1431 | atom_asic_init(rdev->mode_info.atom_context); | ||
1432 | |||
1433 | r = cayman_startup(rdev); | ||
1434 | if (r) { | ||
1435 | DRM_ERROR("cayman startup failed on resume\n"); | ||
1436 | return r; | ||
1437 | } | ||
1438 | |||
1439 | r = r600_ib_test(rdev); | ||
1440 | if (r) { | ||
1441 | DRM_ERROR("radeon: failled testing IB (%d).\n", r); | ||
1442 | return r; | ||
1443 | } | ||
1444 | |||
1445 | return r; | ||
1446 | |||
1447 | } | ||
1448 | |||
1449 | int cayman_suspend(struct radeon_device *rdev) | ||
1450 | { | ||
1451 | /* int r; */ | ||
1452 | |||
1453 | /* FIXME: we should wait for ring to be empty */ | ||
1454 | cayman_cp_enable(rdev, false); | ||
1455 | rdev->cp.ready = false; | ||
1456 | evergreen_irq_suspend(rdev); | ||
1457 | radeon_wb_disable(rdev); | ||
1458 | cayman_pcie_gart_disable(rdev); | ||
1459 | |||
1460 | #if 0 | ||
1461 | /* unpin shaders bo */ | ||
1462 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); | ||
1463 | if (likely(r == 0)) { | ||
1464 | radeon_bo_unpin(rdev->r600_blit.shader_obj); | ||
1465 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | ||
1466 | } | ||
1467 | #endif | ||
1468 | return 0; | ||
1469 | } | ||
1470 | |||
1471 | /* Plan is to move initialization in that function and use | ||
1472 | * helper function so that radeon_device_init pretty much | ||
1473 | * do nothing more than calling asic specific function. This | ||
1474 | * should also allow to remove a bunch of callback function | ||
1475 | * like vram_info. | ||
1476 | */ | ||
1477 | int cayman_init(struct radeon_device *rdev) | ||
1478 | { | ||
1479 | int r; | ||
1480 | |||
1481 | /* This don't do much */ | ||
1482 | r = radeon_gem_init(rdev); | ||
1483 | if (r) | ||
1484 | return r; | ||
1485 | /* Read BIOS */ | ||
1486 | if (!radeon_get_bios(rdev)) { | ||
1487 | if (ASIC_IS_AVIVO(rdev)) | ||
1488 | return -EINVAL; | ||
1489 | } | ||
1490 | /* Must be an ATOMBIOS */ | ||
1491 | if (!rdev->is_atom_bios) { | ||
1492 | dev_err(rdev->dev, "Expecting atombios for cayman GPU\n"); | ||
1493 | return -EINVAL; | ||
1494 | } | ||
1495 | r = radeon_atombios_init(rdev); | ||
1496 | if (r) | ||
1497 | return r; | ||
1498 | |||
1499 | /* Post card if necessary */ | ||
1500 | if (!radeon_card_posted(rdev)) { | ||
1501 | if (!rdev->bios) { | ||
1502 | dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n"); | ||
1503 | return -EINVAL; | ||
1504 | } | ||
1505 | DRM_INFO("GPU not posted. posting now...\n"); | ||
1506 | atom_asic_init(rdev->mode_info.atom_context); | ||
1507 | } | ||
1508 | /* Initialize scratch registers */ | ||
1509 | r600_scratch_init(rdev); | ||
1510 | /* Initialize surface registers */ | ||
1511 | radeon_surface_init(rdev); | ||
1512 | /* Initialize clocks */ | ||
1513 | radeon_get_clock_info(rdev->ddev); | ||
1514 | /* Fence driver */ | ||
1515 | r = radeon_fence_driver_init(rdev); | ||
1516 | if (r) | ||
1517 | return r; | ||
1518 | /* initialize memory controller */ | ||
1519 | r = evergreen_mc_init(rdev); | ||
1520 | if (r) | ||
1521 | return r; | ||
1522 | /* Memory manager */ | ||
1523 | r = radeon_bo_init(rdev); | ||
1524 | if (r) | ||
1525 | return r; | ||
1526 | |||
1527 | r = radeon_irq_kms_init(rdev); | ||
1528 | if (r) | ||
1529 | return r; | ||
1530 | |||
1531 | rdev->cp.ring_obj = NULL; | ||
1532 | r600_ring_init(rdev, 1024 * 1024); | ||
1533 | |||
1534 | rdev->ih.ring_obj = NULL; | ||
1535 | r600_ih_ring_init(rdev, 64 * 1024); | ||
1536 | |||
1537 | r = r600_pcie_gart_init(rdev); | ||
1538 | if (r) | ||
1539 | return r; | ||
1540 | |||
1541 | rdev->accel_working = true; | ||
1542 | r = cayman_startup(rdev); | ||
1543 | if (r) { | ||
1544 | dev_err(rdev->dev, "disabling GPU acceleration\n"); | ||
1545 | cayman_cp_fini(rdev); | ||
1546 | r600_irq_fini(rdev); | ||
1547 | radeon_wb_fini(rdev); | ||
1548 | radeon_irq_kms_fini(rdev); | ||
1549 | cayman_pcie_gart_fini(rdev); | ||
1550 | rdev->accel_working = false; | ||
1551 | } | ||
1552 | if (rdev->accel_working) { | ||
1553 | r = radeon_ib_pool_init(rdev); | ||
1554 | if (r) { | ||
1555 | DRM_ERROR("radeon: failed initializing IB pool (%d).\n", r); | ||
1556 | rdev->accel_working = false; | ||
1557 | } | ||
1558 | r = r600_ib_test(rdev); | ||
1559 | if (r) { | ||
1560 | DRM_ERROR("radeon: failed testing IB (%d).\n", r); | ||
1561 | rdev->accel_working = false; | ||
1562 | } | ||
1563 | } | ||
1564 | |||
1565 | /* Don't start up if the MC ucode is missing. | ||
1566 | * The default clocks and voltages before the MC ucode | ||
1567 | * is loaded are not suffient for advanced operations. | ||
1568 | */ | ||
1569 | if (!rdev->mc_fw) { | ||
1570 | DRM_ERROR("radeon: MC ucode required for NI+.\n"); | ||
1571 | return -EINVAL; | ||
1572 | } | ||
1573 | |||
1574 | return 0; | ||
1575 | } | ||
1576 | |||
1577 | void cayman_fini(struct radeon_device *rdev) | ||
1578 | { | ||
1579 | /* cayman_blit_fini(rdev); */ | ||
1580 | cayman_cp_fini(rdev); | ||
1581 | r600_irq_fini(rdev); | ||
1582 | radeon_wb_fini(rdev); | ||
1583 | radeon_irq_kms_fini(rdev); | ||
1584 | cayman_pcie_gart_fini(rdev); | ||
1585 | radeon_gem_fini(rdev); | ||
1586 | radeon_fence_driver_fini(rdev); | ||
1587 | radeon_bo_fini(rdev); | ||
1588 | radeon_atombios_fini(rdev); | ||
1589 | kfree(rdev->bios); | ||
1590 | rdev->bios = NULL; | ||
1591 | } | ||
1592 | |||
diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h index f7b445390e0..0f9a08b53fb 100644 --- a/drivers/gpu/drm/radeon/nid.h +++ b/drivers/gpu/drm/radeon/nid.h | |||
@@ -24,7 +24,101 @@ | |||
24 | #ifndef NI_H | 24 | #ifndef NI_H |
25 | #define NI_H | 25 | #define NI_H |
26 | 26 | ||
27 | #define CAYMAN_MAX_SH_GPRS 256 | ||
28 | #define CAYMAN_MAX_TEMP_GPRS 16 | ||
29 | #define CAYMAN_MAX_SH_THREADS 256 | ||
30 | #define CAYMAN_MAX_SH_STACK_ENTRIES 4096 | ||
31 | #define CAYMAN_MAX_FRC_EOV_CNT 16384 | ||
32 | #define CAYMAN_MAX_BACKENDS 8 | ||
33 | #define CAYMAN_MAX_BACKENDS_MASK 0xFF | ||
34 | #define CAYMAN_MAX_BACKENDS_PER_SE_MASK 0xF | ||
35 | #define CAYMAN_MAX_SIMDS 16 | ||
36 | #define CAYMAN_MAX_SIMDS_MASK 0xFFFF | ||
37 | #define CAYMAN_MAX_SIMDS_PER_SE_MASK 0xFFF | ||
38 | #define CAYMAN_MAX_PIPES 8 | ||
39 | #define CAYMAN_MAX_PIPES_MASK 0xFF | ||
40 | #define CAYMAN_MAX_LDS_NUM 0xFFFF | ||
41 | #define CAYMAN_MAX_TCC 16 | ||
42 | #define CAYMAN_MAX_TCC_MASK 0xFF | ||
43 | |||
44 | #define DMIF_ADDR_CONFIG 0xBD4 | ||
45 | #define SRBM_STATUS 0x0E50 | ||
46 | |||
47 | #define VM_CONTEXT0_REQUEST_RESPONSE 0x1470 | ||
48 | #define REQUEST_TYPE(x) (((x) & 0xf) << 0) | ||
49 | #define RESPONSE_TYPE_MASK 0x000000F0 | ||
50 | #define RESPONSE_TYPE_SHIFT 4 | ||
51 | #define VM_L2_CNTL 0x1400 | ||
52 | #define ENABLE_L2_CACHE (1 << 0) | ||
53 | #define ENABLE_L2_FRAGMENT_PROCESSING (1 << 1) | ||
54 | #define ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE (1 << 9) | ||
55 | #define ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE (1 << 10) | ||
56 | #define EFFECTIVE_L2_QUEUE_SIZE(x) (((x) & 7) << 14) | ||
57 | #define CONTEXT1_IDENTITY_ACCESS_MODE(x) (((x) & 3) << 18) | ||
58 | /* CONTEXT1_IDENTITY_ACCESS_MODE | ||
59 | * 0 physical = logical | ||
60 | * 1 logical via context1 page table | ||
61 | * 2 inside identity aperture use translation, outside physical = logical | ||
62 | * 3 inside identity aperture physical = logical, outside use translation | ||
63 | */ | ||
64 | #define VM_L2_CNTL2 0x1404 | ||
65 | #define INVALIDATE_ALL_L1_TLBS (1 << 0) | ||
66 | #define INVALIDATE_L2_CACHE (1 << 1) | ||
67 | #define VM_L2_CNTL3 0x1408 | ||
68 | #define BANK_SELECT(x) ((x) << 0) | ||
69 | #define CACHE_UPDATE_MODE(x) ((x) << 6) | ||
70 | #define L2_CACHE_BIGK_ASSOCIATIVITY (1 << 20) | ||
71 | #define L2_CACHE_BIGK_FRAGMENT_SIZE(x) ((x) << 15) | ||
72 | #define VM_L2_STATUS 0x140C | ||
73 | #define L2_BUSY (1 << 0) | ||
74 | #define VM_CONTEXT0_CNTL 0x1410 | ||
75 | #define ENABLE_CONTEXT (1 << 0) | ||
76 | #define PAGE_TABLE_DEPTH(x) (((x) & 3) << 1) | ||
77 | #define RANGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 4) | ||
78 | #define VM_CONTEXT1_CNTL 0x1414 | ||
79 | #define VM_CONTEXT0_CNTL2 0x1430 | ||
80 | #define VM_CONTEXT1_CNTL2 0x1434 | ||
81 | #define VM_INVALIDATE_REQUEST 0x1478 | ||
82 | #define VM_INVALIDATE_RESPONSE 0x147c | ||
83 | #define VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR 0x1518 | ||
84 | #define VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR 0x151c | ||
85 | #define VM_CONTEXT0_PAGE_TABLE_BASE_ADDR 0x153C | ||
86 | #define VM_CONTEXT0_PAGE_TABLE_START_ADDR 0x155C | ||
87 | #define VM_CONTEXT0_PAGE_TABLE_END_ADDR 0x157C | ||
88 | |||
89 | #define MC_SHARED_CHMAP 0x2004 | ||
90 | #define NOOFCHAN_SHIFT 12 | ||
91 | #define NOOFCHAN_MASK 0x00003000 | ||
92 | #define MC_SHARED_CHREMAP 0x2008 | ||
93 | |||
94 | #define MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2034 | ||
95 | #define MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2038 | ||
96 | #define MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x203C | ||
97 | #define MC_VM_MX_L1_TLB_CNTL 0x2064 | ||
98 | #define ENABLE_L1_TLB (1 << 0) | ||
99 | #define ENABLE_L1_FRAGMENT_PROCESSING (1 << 1) | ||
100 | #define SYSTEM_ACCESS_MODE_PA_ONLY (0 << 3) | ||
101 | #define SYSTEM_ACCESS_MODE_USE_SYS_MAP (1 << 3) | ||
102 | #define SYSTEM_ACCESS_MODE_IN_SYS (2 << 3) | ||
103 | #define SYSTEM_ACCESS_MODE_NOT_IN_SYS (3 << 3) | ||
104 | #define SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU (0 << 5) | ||
105 | #define ENABLE_ADVANCED_DRIVER_MODEL (1 << 6) | ||
106 | |||
27 | #define MC_SHARED_BLACKOUT_CNTL 0x20ac | 107 | #define MC_SHARED_BLACKOUT_CNTL 0x20ac |
108 | #define MC_ARB_RAMCFG 0x2760 | ||
109 | #define NOOFBANK_SHIFT 0 | ||
110 | #define NOOFBANK_MASK 0x00000003 | ||
111 | #define NOOFRANK_SHIFT 2 | ||
112 | #define NOOFRANK_MASK 0x00000004 | ||
113 | #define NOOFROWS_SHIFT 3 | ||
114 | #define NOOFROWS_MASK 0x00000038 | ||
115 | #define NOOFCOLS_SHIFT 6 | ||
116 | #define NOOFCOLS_MASK 0x000000C0 | ||
117 | #define CHANSIZE_SHIFT 8 | ||
118 | #define CHANSIZE_MASK 0x00000100 | ||
119 | #define BURSTLENGTH_SHIFT 9 | ||
120 | #define BURSTLENGTH_MASK 0x00000200 | ||
121 | #define CHANSIZE_OVERRIDE (1 << 11) | ||
28 | #define MC_SEQ_SUP_CNTL 0x28c8 | 122 | #define MC_SEQ_SUP_CNTL 0x28c8 |
29 | #define RUN_MASK (1 << 0) | 123 | #define RUN_MASK (1 << 0) |
30 | #define MC_SEQ_SUP_PGM 0x28cc | 124 | #define MC_SEQ_SUP_PGM 0x28cc |
@@ -37,5 +131,406 @@ | |||
37 | #define MC_SEQ_IO_DEBUG_INDEX 0x2a44 | 131 | #define MC_SEQ_IO_DEBUG_INDEX 0x2a44 |
38 | #define MC_SEQ_IO_DEBUG_DATA 0x2a48 | 132 | #define MC_SEQ_IO_DEBUG_DATA 0x2a48 |
39 | 133 | ||
134 | #define HDP_HOST_PATH_CNTL 0x2C00 | ||
135 | #define HDP_NONSURFACE_BASE 0x2C04 | ||
136 | #define HDP_NONSURFACE_INFO 0x2C08 | ||
137 | #define HDP_NONSURFACE_SIZE 0x2C0C | ||
138 | #define HDP_ADDR_CONFIG 0x2F48 | ||
139 | |||
140 | #define CC_SYS_RB_BACKEND_DISABLE 0x3F88 | ||
141 | #define GC_USER_SYS_RB_BACKEND_DISABLE 0x3F8C | ||
142 | #define CGTS_SYS_TCC_DISABLE 0x3F90 | ||
143 | #define CGTS_USER_SYS_TCC_DISABLE 0x3F94 | ||
144 | |||
145 | #define CONFIG_MEMSIZE 0x5428 | ||
146 | |||
147 | #define HDP_MEM_COHERENCY_FLUSH_CNTL 0x5480 | ||
148 | #define HDP_REG_COHERENCY_FLUSH_CNTL 0x54A0 | ||
149 | |||
150 | #define GRBM_CNTL 0x8000 | ||
151 | #define GRBM_READ_TIMEOUT(x) ((x) << 0) | ||
152 | #define GRBM_STATUS 0x8010 | ||
153 | #define CMDFIFO_AVAIL_MASK 0x0000000F | ||
154 | #define RING2_RQ_PENDING (1 << 4) | ||
155 | #define SRBM_RQ_PENDING (1 << 5) | ||
156 | #define RING1_RQ_PENDING (1 << 6) | ||
157 | #define CF_RQ_PENDING (1 << 7) | ||
158 | #define PF_RQ_PENDING (1 << 8) | ||
159 | #define GDS_DMA_RQ_PENDING (1 << 9) | ||
160 | #define GRBM_EE_BUSY (1 << 10) | ||
161 | #define SX_CLEAN (1 << 11) | ||
162 | #define DB_CLEAN (1 << 12) | ||
163 | #define CB_CLEAN (1 << 13) | ||
164 | #define TA_BUSY (1 << 14) | ||
165 | #define GDS_BUSY (1 << 15) | ||
166 | #define VGT_BUSY_NO_DMA (1 << 16) | ||
167 | #define VGT_BUSY (1 << 17) | ||
168 | #define IA_BUSY_NO_DMA (1 << 18) | ||
169 | #define IA_BUSY (1 << 19) | ||
170 | #define SX_BUSY (1 << 20) | ||
171 | #define SH_BUSY (1 << 21) | ||
172 | #define SPI_BUSY (1 << 22) | ||
173 | #define SC_BUSY (1 << 24) | ||
174 | #define PA_BUSY (1 << 25) | ||
175 | #define DB_BUSY (1 << 26) | ||
176 | #define CP_COHERENCY_BUSY (1 << 28) | ||
177 | #define CP_BUSY (1 << 29) | ||
178 | #define CB_BUSY (1 << 30) | ||
179 | #define GUI_ACTIVE (1 << 31) | ||
180 | #define GRBM_STATUS_SE0 0x8014 | ||
181 | #define GRBM_STATUS_SE1 0x8018 | ||
182 | #define SE_SX_CLEAN (1 << 0) | ||
183 | #define SE_DB_CLEAN (1 << 1) | ||
184 | #define SE_CB_CLEAN (1 << 2) | ||
185 | #define SE_VGT_BUSY (1 << 23) | ||
186 | #define SE_PA_BUSY (1 << 24) | ||
187 | #define SE_TA_BUSY (1 << 25) | ||
188 | #define SE_SX_BUSY (1 << 26) | ||
189 | #define SE_SPI_BUSY (1 << 27) | ||
190 | #define SE_SH_BUSY (1 << 28) | ||
191 | #define SE_SC_BUSY (1 << 29) | ||
192 | #define SE_DB_BUSY (1 << 30) | ||
193 | #define SE_CB_BUSY (1 << 31) | ||
194 | #define GRBM_SOFT_RESET 0x8020 | ||
195 | #define SOFT_RESET_CP (1 << 0) | ||
196 | #define SOFT_RESET_CB (1 << 1) | ||
197 | #define SOFT_RESET_DB (1 << 3) | ||
198 | #define SOFT_RESET_GDS (1 << 4) | ||
199 | #define SOFT_RESET_PA (1 << 5) | ||
200 | #define SOFT_RESET_SC (1 << 6) | ||
201 | #define SOFT_RESET_SPI (1 << 8) | ||
202 | #define SOFT_RESET_SH (1 << 9) | ||
203 | #define SOFT_RESET_SX (1 << 10) | ||
204 | #define SOFT_RESET_TC (1 << 11) | ||
205 | #define SOFT_RESET_TA (1 << 12) | ||
206 | #define SOFT_RESET_VGT (1 << 14) | ||
207 | #define SOFT_RESET_IA (1 << 15) | ||
208 | |||
209 | #define SCRATCH_REG0 0x8500 | ||
210 | #define SCRATCH_REG1 0x8504 | ||
211 | #define SCRATCH_REG2 0x8508 | ||
212 | #define SCRATCH_REG3 0x850C | ||
213 | #define SCRATCH_REG4 0x8510 | ||
214 | #define SCRATCH_REG5 0x8514 | ||
215 | #define SCRATCH_REG6 0x8518 | ||
216 | #define SCRATCH_REG7 0x851C | ||
217 | #define SCRATCH_UMSK 0x8540 | ||
218 | #define SCRATCH_ADDR 0x8544 | ||
219 | #define CP_SEM_WAIT_TIMER 0x85BC | ||
220 | #define CP_ME_CNTL 0x86D8 | ||
221 | #define CP_ME_HALT (1 << 28) | ||
222 | #define CP_PFP_HALT (1 << 26) | ||
223 | #define CP_RB2_RPTR 0x86f8 | ||
224 | #define CP_RB1_RPTR 0x86fc | ||
225 | #define CP_RB0_RPTR 0x8700 | ||
226 | #define CP_RB_WPTR_DELAY 0x8704 | ||
227 | #define CP_MEQ_THRESHOLDS 0x8764 | ||
228 | #define MEQ1_START(x) ((x) << 0) | ||
229 | #define MEQ2_START(x) ((x) << 8) | ||
230 | #define CP_PERFMON_CNTL 0x87FC | ||
231 | |||
232 | #define VGT_CACHE_INVALIDATION 0x88C4 | ||
233 | #define CACHE_INVALIDATION(x) ((x) << 0) | ||
234 | #define VC_ONLY 0 | ||
235 | #define TC_ONLY 1 | ||
236 | #define VC_AND_TC 2 | ||
237 | #define AUTO_INVLD_EN(x) ((x) << 6) | ||
238 | #define NO_AUTO 0 | ||
239 | #define ES_AUTO 1 | ||
240 | #define GS_AUTO 2 | ||
241 | #define ES_AND_GS_AUTO 3 | ||
242 | #define VGT_GS_VERTEX_REUSE 0x88D4 | ||
243 | |||
244 | #define CC_GC_SHADER_PIPE_CONFIG 0x8950 | ||
245 | #define GC_USER_SHADER_PIPE_CONFIG 0x8954 | ||
246 | #define INACTIVE_QD_PIPES(x) ((x) << 8) | ||
247 | #define INACTIVE_QD_PIPES_MASK 0x0000FF00 | ||
248 | #define INACTIVE_QD_PIPES_SHIFT 8 | ||
249 | #define INACTIVE_SIMDS(x) ((x) << 16) | ||
250 | #define INACTIVE_SIMDS_MASK 0xFFFF0000 | ||
251 | #define INACTIVE_SIMDS_SHIFT 16 | ||
252 | |||
253 | #define VGT_PRIMITIVE_TYPE 0x8958 | ||
254 | #define VGT_NUM_INSTANCES 0x8974 | ||
255 | #define VGT_TF_RING_SIZE 0x8988 | ||
256 | #define VGT_OFFCHIP_LDS_BASE 0x89b4 | ||
257 | |||
258 | #define PA_SC_LINE_STIPPLE_STATE 0x8B10 | ||
259 | #define PA_CL_ENHANCE 0x8A14 | ||
260 | #define CLIP_VTX_REORDER_ENA (1 << 0) | ||
261 | #define NUM_CLIP_SEQ(x) ((x) << 1) | ||
262 | #define PA_SC_FIFO_SIZE 0x8BCC | ||
263 | #define SC_PRIM_FIFO_SIZE(x) ((x) << 0) | ||
264 | #define SC_HIZ_TILE_FIFO_SIZE(x) ((x) << 12) | ||
265 | #define SC_EARLYZ_TILE_FIFO_SIZE(x) ((x) << 20) | ||
266 | #define PA_SC_FORCE_EOV_MAX_CNTS 0x8B24 | ||
267 | #define FORCE_EOV_MAX_CLK_CNT(x) ((x) << 0) | ||
268 | #define FORCE_EOV_MAX_REZ_CNT(x) ((x) << 16) | ||
269 | |||
270 | #define SQ_CONFIG 0x8C00 | ||
271 | #define VC_ENABLE (1 << 0) | ||
272 | #define EXPORT_SRC_C (1 << 1) | ||
273 | #define GFX_PRIO(x) ((x) << 2) | ||
274 | #define CS1_PRIO(x) ((x) << 4) | ||
275 | #define CS2_PRIO(x) ((x) << 6) | ||
276 | #define SQ_GPR_RESOURCE_MGMT_1 0x8C04 | ||
277 | #define NUM_PS_GPRS(x) ((x) << 0) | ||
278 | #define NUM_VS_GPRS(x) ((x) << 16) | ||
279 | #define NUM_CLAUSE_TEMP_GPRS(x) ((x) << 28) | ||
280 | #define SQ_ESGS_RING_SIZE 0x8c44 | ||
281 | #define SQ_GSVS_RING_SIZE 0x8c4c | ||
282 | #define SQ_ESTMP_RING_BASE 0x8c50 | ||
283 | #define SQ_ESTMP_RING_SIZE 0x8c54 | ||
284 | #define SQ_GSTMP_RING_BASE 0x8c58 | ||
285 | #define SQ_GSTMP_RING_SIZE 0x8c5c | ||
286 | #define SQ_VSTMP_RING_BASE 0x8c60 | ||
287 | #define SQ_VSTMP_RING_SIZE 0x8c64 | ||
288 | #define SQ_PSTMP_RING_BASE 0x8c68 | ||
289 | #define SQ_PSTMP_RING_SIZE 0x8c6c | ||
290 | #define SQ_MS_FIFO_SIZES 0x8CF0 | ||
291 | #define CACHE_FIFO_SIZE(x) ((x) << 0) | ||
292 | #define FETCH_FIFO_HIWATER(x) ((x) << 8) | ||
293 | #define DONE_FIFO_HIWATER(x) ((x) << 16) | ||
294 | #define ALU_UPDATE_FIFO_HIWATER(x) ((x) << 24) | ||
295 | #define SQ_LSTMP_RING_BASE 0x8e10 | ||
296 | #define SQ_LSTMP_RING_SIZE 0x8e14 | ||
297 | #define SQ_HSTMP_RING_BASE 0x8e18 | ||
298 | #define SQ_HSTMP_RING_SIZE 0x8e1c | ||
299 | #define SQ_DYN_GPR_CNTL_PS_FLUSH_REQ 0x8D8C | ||
300 | #define DYN_GPR_ENABLE (1 << 8) | ||
301 | #define SQ_CONST_MEM_BASE 0x8df8 | ||
302 | |||
303 | #define SX_EXPORT_BUFFER_SIZES 0x900C | ||
304 | #define COLOR_BUFFER_SIZE(x) ((x) << 0) | ||
305 | #define POSITION_BUFFER_SIZE(x) ((x) << 8) | ||
306 | #define SMX_BUFFER_SIZE(x) ((x) << 16) | ||
307 | #define SX_DEBUG_1 0x9058 | ||
308 | #define ENABLE_NEW_SMX_ADDRESS (1 << 16) | ||
309 | |||
310 | #define SPI_CONFIG_CNTL 0x9100 | ||
311 | #define GPR_WRITE_PRIORITY(x) ((x) << 0) | ||
312 | #define SPI_CONFIG_CNTL_1 0x913C | ||
313 | #define VTX_DONE_DELAY(x) ((x) << 0) | ||
314 | #define INTERP_ONE_PRIM_PER_ROW (1 << 4) | ||
315 | #define CRC_SIMD_ID_WADDR_DISABLE (1 << 8) | ||
316 | |||
317 | #define CGTS_TCC_DISABLE 0x9148 | ||
318 | #define CGTS_USER_TCC_DISABLE 0x914C | ||
319 | #define TCC_DISABLE_MASK 0xFFFF0000 | ||
320 | #define TCC_DISABLE_SHIFT 16 | ||
321 | #define CGTS_SM_CTRL_REG 0x915C | ||
322 | #define OVERRIDE (1 << 21) | ||
323 | |||
324 | #define TA_CNTL_AUX 0x9508 | ||
325 | #define DISABLE_CUBE_WRAP (1 << 0) | ||
326 | #define DISABLE_CUBE_ANISO (1 << 1) | ||
327 | |||
328 | #define TCP_CHAN_STEER_LO 0x960c | ||
329 | #define TCP_CHAN_STEER_HI 0x9610 | ||
330 | |||
331 | #define CC_RB_BACKEND_DISABLE 0x98F4 | ||
332 | #define BACKEND_DISABLE(x) ((x) << 16) | ||
333 | #define GB_ADDR_CONFIG 0x98F8 | ||
334 | #define NUM_PIPES(x) ((x) << 0) | ||
335 | #define NUM_PIPES_MASK 0x00000007 | ||
336 | #define NUM_PIPES_SHIFT 0 | ||
337 | #define PIPE_INTERLEAVE_SIZE(x) ((x) << 4) | ||
338 | #define PIPE_INTERLEAVE_SIZE_MASK 0x00000070 | ||
339 | #define PIPE_INTERLEAVE_SIZE_SHIFT 4 | ||
340 | #define BANK_INTERLEAVE_SIZE(x) ((x) << 8) | ||
341 | #define NUM_SHADER_ENGINES(x) ((x) << 12) | ||
342 | #define NUM_SHADER_ENGINES_MASK 0x00003000 | ||
343 | #define NUM_SHADER_ENGINES_SHIFT 12 | ||
344 | #define SHADER_ENGINE_TILE_SIZE(x) ((x) << 16) | ||
345 | #define SHADER_ENGINE_TILE_SIZE_MASK 0x00070000 | ||
346 | #define SHADER_ENGINE_TILE_SIZE_SHIFT 16 | ||
347 | #define NUM_GPUS(x) ((x) << 20) | ||
348 | #define NUM_GPUS_MASK 0x00700000 | ||
349 | #define NUM_GPUS_SHIFT 20 | ||
350 | #define MULTI_GPU_TILE_SIZE(x) ((x) << 24) | ||
351 | #define MULTI_GPU_TILE_SIZE_MASK 0x03000000 | ||
352 | #define MULTI_GPU_TILE_SIZE_SHIFT 24 | ||
353 | #define ROW_SIZE(x) ((x) << 28) | ||
354 | #define ROW_SIZE_MASK 0x30000007 | ||
355 | #define ROW_SIZE_SHIFT 28 | ||
356 | #define NUM_LOWER_PIPES(x) ((x) << 30) | ||
357 | #define NUM_LOWER_PIPES_MASK 0x40000000 | ||
358 | #define NUM_LOWER_PIPES_SHIFT 30 | ||
359 | #define GB_BACKEND_MAP 0x98FC | ||
360 | |||
361 | #define CB_PERF_CTR0_SEL_0 0x9A20 | ||
362 | #define CB_PERF_CTR0_SEL_1 0x9A24 | ||
363 | #define CB_PERF_CTR1_SEL_0 0x9A28 | ||
364 | #define CB_PERF_CTR1_SEL_1 0x9A2C | ||
365 | #define CB_PERF_CTR2_SEL_0 0x9A30 | ||
366 | #define CB_PERF_CTR2_SEL_1 0x9A34 | ||
367 | #define CB_PERF_CTR3_SEL_0 0x9A38 | ||
368 | #define CB_PERF_CTR3_SEL_1 0x9A3C | ||
369 | |||
370 | #define GC_USER_RB_BACKEND_DISABLE 0x9B7C | ||
371 | #define BACKEND_DISABLE_MASK 0x00FF0000 | ||
372 | #define BACKEND_DISABLE_SHIFT 16 | ||
373 | |||
374 | #define SMX_DC_CTL0 0xA020 | ||
375 | #define USE_HASH_FUNCTION (1 << 0) | ||
376 | #define NUMBER_OF_SETS(x) ((x) << 1) | ||
377 | #define FLUSH_ALL_ON_EVENT (1 << 10) | ||
378 | #define STALL_ON_EVENT (1 << 11) | ||
379 | #define SMX_EVENT_CTL 0xA02C | ||
380 | #define ES_FLUSH_CTL(x) ((x) << 0) | ||
381 | #define GS_FLUSH_CTL(x) ((x) << 3) | ||
382 | #define ACK_FLUSH_CTL(x) ((x) << 6) | ||
383 | #define SYNC_FLUSH_CTL (1 << 8) | ||
384 | |||
385 | #define CP_RB0_BASE 0xC100 | ||
386 | #define CP_RB0_CNTL 0xC104 | ||
387 | #define RB_BUFSZ(x) ((x) << 0) | ||
388 | #define RB_BLKSZ(x) ((x) << 8) | ||
389 | #define RB_NO_UPDATE (1 << 27) | ||
390 | #define RB_RPTR_WR_ENA (1 << 31) | ||
391 | #define BUF_SWAP_32BIT (2 << 16) | ||
392 | #define CP_RB0_RPTR_ADDR 0xC10C | ||
393 | #define CP_RB0_RPTR_ADDR_HI 0xC110 | ||
394 | #define CP_RB0_WPTR 0xC114 | ||
395 | #define CP_RB1_BASE 0xC180 | ||
396 | #define CP_RB1_CNTL 0xC184 | ||
397 | #define CP_RB1_RPTR_ADDR 0xC188 | ||
398 | #define CP_RB1_RPTR_ADDR_HI 0xC18C | ||
399 | #define CP_RB1_WPTR 0xC190 | ||
400 | #define CP_RB2_BASE 0xC194 | ||
401 | #define CP_RB2_CNTL 0xC198 | ||
402 | #define CP_RB2_RPTR_ADDR 0xC19C | ||
403 | #define CP_RB2_RPTR_ADDR_HI 0xC1A0 | ||
404 | #define CP_RB2_WPTR 0xC1A4 | ||
405 | #define CP_PFP_UCODE_ADDR 0xC150 | ||
406 | #define CP_PFP_UCODE_DATA 0xC154 | ||
407 | #define CP_ME_RAM_RADDR 0xC158 | ||
408 | #define CP_ME_RAM_WADDR 0xC15C | ||
409 | #define CP_ME_RAM_DATA 0xC160 | ||
410 | #define CP_DEBUG 0xC1FC | ||
411 | |||
412 | /* | ||
413 | * PM4 | ||
414 | */ | ||
415 | #define PACKET_TYPE0 0 | ||
416 | #define PACKET_TYPE1 1 | ||
417 | #define PACKET_TYPE2 2 | ||
418 | #define PACKET_TYPE3 3 | ||
419 | |||
420 | #define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3) | ||
421 | #define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF) | ||
422 | #define CP_PACKET0_GET_REG(h) (((h) & 0xFFFF) << 2) | ||
423 | #define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF) | ||
424 | #define PACKET0(reg, n) ((PACKET_TYPE0 << 30) | \ | ||
425 | (((reg) >> 2) & 0xFFFF) | \ | ||
426 | ((n) & 0x3FFF) << 16) | ||
427 | #define CP_PACKET2 0x80000000 | ||
428 | #define PACKET2_PAD_SHIFT 0 | ||
429 | #define PACKET2_PAD_MASK (0x3fffffff << 0) | ||
430 | |||
431 | #define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v))) | ||
432 | |||
433 | #define PACKET3(op, n) ((PACKET_TYPE3 << 30) | \ | ||
434 | (((op) & 0xFF) << 8) | \ | ||
435 | ((n) & 0x3FFF) << 16) | ||
436 | |||
437 | /* Packet 3 types */ | ||
438 | #define PACKET3_NOP 0x10 | ||
439 | #define PACKET3_SET_BASE 0x11 | ||
440 | #define PACKET3_CLEAR_STATE 0x12 | ||
441 | #define PACKET3_INDEX_BUFFER_SIZE 0x13 | ||
442 | #define PACKET3_DEALLOC_STATE 0x14 | ||
443 | #define PACKET3_DISPATCH_DIRECT 0x15 | ||
444 | #define PACKET3_DISPATCH_INDIRECT 0x16 | ||
445 | #define PACKET3_INDIRECT_BUFFER_END 0x17 | ||
446 | #define PACKET3_SET_PREDICATION 0x20 | ||
447 | #define PACKET3_REG_RMW 0x21 | ||
448 | #define PACKET3_COND_EXEC 0x22 | ||
449 | #define PACKET3_PRED_EXEC 0x23 | ||
450 | #define PACKET3_DRAW_INDIRECT 0x24 | ||
451 | #define PACKET3_DRAW_INDEX_INDIRECT 0x25 | ||
452 | #define PACKET3_INDEX_BASE 0x26 | ||
453 | #define PACKET3_DRAW_INDEX_2 0x27 | ||
454 | #define PACKET3_CONTEXT_CONTROL 0x28 | ||
455 | #define PACKET3_DRAW_INDEX_OFFSET 0x29 | ||
456 | #define PACKET3_INDEX_TYPE 0x2A | ||
457 | #define PACKET3_DRAW_INDEX 0x2B | ||
458 | #define PACKET3_DRAW_INDEX_AUTO 0x2D | ||
459 | #define PACKET3_DRAW_INDEX_IMMD 0x2E | ||
460 | #define PACKET3_NUM_INSTANCES 0x2F | ||
461 | #define PACKET3_DRAW_INDEX_MULTI_AUTO 0x30 | ||
462 | #define PACKET3_INDIRECT_BUFFER 0x32 | ||
463 | #define PACKET3_STRMOUT_BUFFER_UPDATE 0x34 | ||
464 | #define PACKET3_DRAW_INDEX_OFFSET_2 0x35 | ||
465 | #define PACKET3_DRAW_INDEX_MULTI_ELEMENT 0x36 | ||
466 | #define PACKET3_WRITE_DATA 0x37 | ||
467 | #define PACKET3_MEM_SEMAPHORE 0x39 | ||
468 | #define PACKET3_MPEG_INDEX 0x3A | ||
469 | #define PACKET3_WAIT_REG_MEM 0x3C | ||
470 | #define PACKET3_MEM_WRITE 0x3D | ||
471 | #define PACKET3_SURFACE_SYNC 0x43 | ||
472 | # define PACKET3_CB0_DEST_BASE_ENA (1 << 6) | ||
473 | # define PACKET3_CB1_DEST_BASE_ENA (1 << 7) | ||
474 | # define PACKET3_CB2_DEST_BASE_ENA (1 << 8) | ||
475 | # define PACKET3_CB3_DEST_BASE_ENA (1 << 9) | ||
476 | # define PACKET3_CB4_DEST_BASE_ENA (1 << 10) | ||
477 | # define PACKET3_CB5_DEST_BASE_ENA (1 << 11) | ||
478 | # define PACKET3_CB6_DEST_BASE_ENA (1 << 12) | ||
479 | # define PACKET3_CB7_DEST_BASE_ENA (1 << 13) | ||
480 | # define PACKET3_DB_DEST_BASE_ENA (1 << 14) | ||
481 | # define PACKET3_CB8_DEST_BASE_ENA (1 << 15) | ||
482 | # define PACKET3_CB9_DEST_BASE_ENA (1 << 16) | ||
483 | # define PACKET3_CB10_DEST_BASE_ENA (1 << 17) | ||
484 | # define PACKET3_CB11_DEST_BASE_ENA (1 << 18) | ||
485 | # define PACKET3_FULL_CACHE_ENA (1 << 20) | ||
486 | # define PACKET3_TC_ACTION_ENA (1 << 23) | ||
487 | # define PACKET3_CB_ACTION_ENA (1 << 25) | ||
488 | # define PACKET3_DB_ACTION_ENA (1 << 26) | ||
489 | # define PACKET3_SH_ACTION_ENA (1 << 27) | ||
490 | # define PACKET3_SX_ACTION_ENA (1 << 28) | ||
491 | #define PACKET3_ME_INITIALIZE 0x44 | ||
492 | #define PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16) | ||
493 | #define PACKET3_COND_WRITE 0x45 | ||
494 | #define PACKET3_EVENT_WRITE 0x46 | ||
495 | #define PACKET3_EVENT_WRITE_EOP 0x47 | ||
496 | #define PACKET3_EVENT_WRITE_EOS 0x48 | ||
497 | #define PACKET3_PREAMBLE_CNTL 0x4A | ||
498 | # define PACKET3_PREAMBLE_BEGIN_CLEAR_STATE (2 << 28) | ||
499 | # define PACKET3_PREAMBLE_END_CLEAR_STATE (3 << 28) | ||
500 | #define PACKET3_ALU_PS_CONST_BUFFER_COPY 0x4C | ||
501 | #define PACKET3_ALU_VS_CONST_BUFFER_COPY 0x4D | ||
502 | #define PACKET3_ALU_PS_CONST_UPDATE 0x4E | ||
503 | #define PACKET3_ALU_VS_CONST_UPDATE 0x4F | ||
504 | #define PACKET3_ONE_REG_WRITE 0x57 | ||
505 | #define PACKET3_SET_CONFIG_REG 0x68 | ||
506 | #define PACKET3_SET_CONFIG_REG_START 0x00008000 | ||
507 | #define PACKET3_SET_CONFIG_REG_END 0x0000ac00 | ||
508 | #define PACKET3_SET_CONTEXT_REG 0x69 | ||
509 | #define PACKET3_SET_CONTEXT_REG_START 0x00028000 | ||
510 | #define PACKET3_SET_CONTEXT_REG_END 0x00029000 | ||
511 | #define PACKET3_SET_ALU_CONST 0x6A | ||
512 | /* alu const buffers only; no reg file */ | ||
513 | #define PACKET3_SET_BOOL_CONST 0x6B | ||
514 | #define PACKET3_SET_BOOL_CONST_START 0x0003a500 | ||
515 | #define PACKET3_SET_BOOL_CONST_END 0x0003a518 | ||
516 | #define PACKET3_SET_LOOP_CONST 0x6C | ||
517 | #define PACKET3_SET_LOOP_CONST_START 0x0003a200 | ||
518 | #define PACKET3_SET_LOOP_CONST_END 0x0003a500 | ||
519 | #define PACKET3_SET_RESOURCE 0x6D | ||
520 | #define PACKET3_SET_RESOURCE_START 0x00030000 | ||
521 | #define PACKET3_SET_RESOURCE_END 0x00038000 | ||
522 | #define PACKET3_SET_SAMPLER 0x6E | ||
523 | #define PACKET3_SET_SAMPLER_START 0x0003c000 | ||
524 | #define PACKET3_SET_SAMPLER_END 0x0003c600 | ||
525 | #define PACKET3_SET_CTL_CONST 0x6F | ||
526 | #define PACKET3_SET_CTL_CONST_START 0x0003cff0 | ||
527 | #define PACKET3_SET_CTL_CONST_END 0x0003ff0c | ||
528 | #define PACKET3_SET_RESOURCE_OFFSET 0x70 | ||
529 | #define PACKET3_SET_ALU_CONST_VS 0x71 | ||
530 | #define PACKET3_SET_ALU_CONST_DI 0x72 | ||
531 | #define PACKET3_SET_CONTEXT_REG_INDIRECT 0x73 | ||
532 | #define PACKET3_SET_RESOURCE_INDIRECT 0x74 | ||
533 | #define PACKET3_SET_APPEND_CNT 0x75 | ||
534 | |||
40 | #endif | 535 | #endif |
41 | 536 | ||
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 9b3fad23b76..12fdebf9aed 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #define EVERGREEN_PFP_UCODE_SIZE 1120 | 47 | #define EVERGREEN_PFP_UCODE_SIZE 1120 |
48 | #define EVERGREEN_PM4_UCODE_SIZE 1376 | 48 | #define EVERGREEN_PM4_UCODE_SIZE 1376 |
49 | #define EVERGREEN_RLC_UCODE_SIZE 768 | 49 | #define EVERGREEN_RLC_UCODE_SIZE 768 |
50 | #define CAYMAN_RLC_UCODE_SIZE 1024 | ||
50 | 51 | ||
51 | /* Firmware Names */ | 52 | /* Firmware Names */ |
52 | MODULE_FIRMWARE("radeon/R600_pfp.bin"); | 53 | MODULE_FIRMWARE("radeon/R600_pfp.bin"); |
@@ -2739,7 +2740,7 @@ static int r600_ih_ring_alloc(struct radeon_device *rdev) | |||
2739 | 2740 | ||
2740 | /* Allocate ring buffer */ | 2741 | /* Allocate ring buffer */ |
2741 | if (rdev->ih.ring_obj == NULL) { | 2742 | if (rdev->ih.ring_obj == NULL) { |
2742 | r = radeon_bo_create(rdev, NULL, rdev->ih.ring_size, | 2743 | r = radeon_bo_create(rdev, rdev->ih.ring_size, |
2743 | PAGE_SIZE, true, | 2744 | PAGE_SIZE, true, |
2744 | RADEON_GEM_DOMAIN_GTT, | 2745 | RADEON_GEM_DOMAIN_GTT, |
2745 | &rdev->ih.ring_obj); | 2746 | &rdev->ih.ring_obj); |
@@ -2820,13 +2821,20 @@ static int r600_rlc_init(struct radeon_device *rdev) | |||
2820 | WREG32(RLC_HB_CNTL, 0); | 2821 | WREG32(RLC_HB_CNTL, 0); |
2821 | WREG32(RLC_HB_RPTR, 0); | 2822 | WREG32(RLC_HB_RPTR, 0); |
2822 | WREG32(RLC_HB_WPTR, 0); | 2823 | WREG32(RLC_HB_WPTR, 0); |
2823 | WREG32(RLC_HB_WPTR_LSB_ADDR, 0); | 2824 | if (rdev->family <= CHIP_CAICOS) { |
2824 | WREG32(RLC_HB_WPTR_MSB_ADDR, 0); | 2825 | WREG32(RLC_HB_WPTR_LSB_ADDR, 0); |
2826 | WREG32(RLC_HB_WPTR_MSB_ADDR, 0); | ||
2827 | } | ||
2825 | WREG32(RLC_MC_CNTL, 0); | 2828 | WREG32(RLC_MC_CNTL, 0); |
2826 | WREG32(RLC_UCODE_CNTL, 0); | 2829 | WREG32(RLC_UCODE_CNTL, 0); |
2827 | 2830 | ||
2828 | fw_data = (const __be32 *)rdev->rlc_fw->data; | 2831 | fw_data = (const __be32 *)rdev->rlc_fw->data; |
2829 | if (rdev->family >= CHIP_CEDAR) { | 2832 | if (rdev->family >= CHIP_CAYMAN) { |
2833 | for (i = 0; i < CAYMAN_RLC_UCODE_SIZE; i++) { | ||
2834 | WREG32(RLC_UCODE_ADDR, i); | ||
2835 | WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); | ||
2836 | } | ||
2837 | } else if (rdev->family >= CHIP_CEDAR) { | ||
2830 | for (i = 0; i < EVERGREEN_RLC_UCODE_SIZE; i++) { | 2838 | for (i = 0; i < EVERGREEN_RLC_UCODE_SIZE; i++) { |
2831 | WREG32(RLC_UCODE_ADDR, i); | 2839 | WREG32(RLC_UCODE_ADDR, i); |
2832 | WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); | 2840 | WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); |
diff --git a/drivers/gpu/drm/radeon/r600_audio.c b/drivers/gpu/drm/radeon/r600_audio.c index b5443fe1c1d..846fae57639 100644 --- a/drivers/gpu/drm/radeon/r600_audio.c +++ b/drivers/gpu/drm/radeon/r600_audio.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include "drmP.h" | 26 | #include "drmP.h" |
27 | #include "radeon.h" | 27 | #include "radeon.h" |
28 | #include "radeon_reg.h" | 28 | #include "radeon_reg.h" |
29 | #include "radeon_asic.h" | ||
29 | #include "atom.h" | 30 | #include "atom.h" |
30 | 31 | ||
31 | #define AUDIO_TIMER_INTERVALL 100 /* 1/10 sekund should be enough */ | 32 | #define AUDIO_TIMER_INTERVALL 100 /* 1/10 sekund should be enough */ |
diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c index df68d91e819..9aa74c3f8cb 100644 --- a/drivers/gpu/drm/radeon/r600_blit_kms.c +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c | |||
@@ -512,7 +512,7 @@ int r600_blit_init(struct radeon_device *rdev) | |||
512 | obj_size += r6xx_ps_size * 4; | 512 | obj_size += r6xx_ps_size * 4; |
513 | obj_size = ALIGN(obj_size, 256); | 513 | obj_size = ALIGN(obj_size, 256); |
514 | 514 | ||
515 | r = radeon_bo_create(rdev, NULL, obj_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, | 515 | r = radeon_bo_create(rdev, obj_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, |
516 | &rdev->r600_blit.shader_obj); | 516 | &rdev->r600_blit.shader_obj); |
517 | if (r) { | 517 | if (r) { |
518 | DRM_ERROR("r600 failed to allocate shader\n"); | 518 | DRM_ERROR("r600 failed to allocate shader\n"); |
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 153095fba62..0a0848f0346 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c | |||
@@ -71,75 +71,167 @@ struct r600_cs_track { | |||
71 | u64 db_bo_mc; | 71 | u64 db_bo_mc; |
72 | }; | 72 | }; |
73 | 73 | ||
74 | #define FMT_8_BIT(fmt, vc) [fmt] = { 1, 1, 1, vc } | ||
75 | #define FMT_16_BIT(fmt, vc) [fmt] = { 1, 1, 2, vc } | ||
76 | #define FMT_24_BIT(fmt) [fmt] = { 1, 1, 3, 0 } | ||
77 | #define FMT_32_BIT(fmt, vc) [fmt] = { 1, 1, 4, vc } | ||
78 | #define FMT_48_BIT(fmt) [fmt] = { 1, 1, 6, 0 } | ||
79 | #define FMT_64_BIT(fmt, vc) [fmt] = { 1, 1, 8, vc } | ||
80 | #define FMT_96_BIT(fmt) [fmt] = { 1, 1, 12, 0 } | ||
81 | #define FMT_128_BIT(fmt, vc) [fmt] = { 1, 1, 16, vc } | ||
82 | |||
83 | struct gpu_formats { | ||
84 | unsigned blockwidth; | ||
85 | unsigned blockheight; | ||
86 | unsigned blocksize; | ||
87 | unsigned valid_color; | ||
88 | }; | ||
89 | |||
90 | static const struct gpu_formats color_formats_table[] = { | ||
91 | /* 8 bit */ | ||
92 | FMT_8_BIT(V_038004_COLOR_8, 1), | ||
93 | FMT_8_BIT(V_038004_COLOR_4_4, 1), | ||
94 | FMT_8_BIT(V_038004_COLOR_3_3_2, 1), | ||
95 | FMT_8_BIT(V_038004_FMT_1, 0), | ||
96 | |||
97 | /* 16-bit */ | ||
98 | FMT_16_BIT(V_038004_COLOR_16, 1), | ||
99 | FMT_16_BIT(V_038004_COLOR_16_FLOAT, 1), | ||
100 | FMT_16_BIT(V_038004_COLOR_8_8, 1), | ||
101 | FMT_16_BIT(V_038004_COLOR_5_6_5, 1), | ||
102 | FMT_16_BIT(V_038004_COLOR_6_5_5, 1), | ||
103 | FMT_16_BIT(V_038004_COLOR_1_5_5_5, 1), | ||
104 | FMT_16_BIT(V_038004_COLOR_4_4_4_4, 1), | ||
105 | FMT_16_BIT(V_038004_COLOR_5_5_5_1, 1), | ||
106 | |||
107 | /* 24-bit */ | ||
108 | FMT_24_BIT(V_038004_FMT_8_8_8), | ||
109 | |||
110 | /* 32-bit */ | ||
111 | FMT_32_BIT(V_038004_COLOR_32, 1), | ||
112 | FMT_32_BIT(V_038004_COLOR_32_FLOAT, 1), | ||
113 | FMT_32_BIT(V_038004_COLOR_16_16, 1), | ||
114 | FMT_32_BIT(V_038004_COLOR_16_16_FLOAT, 1), | ||
115 | FMT_32_BIT(V_038004_COLOR_8_24, 1), | ||
116 | FMT_32_BIT(V_038004_COLOR_8_24_FLOAT, 1), | ||
117 | FMT_32_BIT(V_038004_COLOR_24_8, 1), | ||
118 | FMT_32_BIT(V_038004_COLOR_24_8_FLOAT, 1), | ||
119 | FMT_32_BIT(V_038004_COLOR_10_11_11, 1), | ||
120 | FMT_32_BIT(V_038004_COLOR_10_11_11_FLOAT, 1), | ||
121 | FMT_32_BIT(V_038004_COLOR_11_11_10, 1), | ||
122 | FMT_32_BIT(V_038004_COLOR_11_11_10_FLOAT, 1), | ||
123 | FMT_32_BIT(V_038004_COLOR_2_10_10_10, 1), | ||
124 | FMT_32_BIT(V_038004_COLOR_8_8_8_8, 1), | ||
125 | FMT_32_BIT(V_038004_COLOR_10_10_10_2, 1), | ||
126 | FMT_32_BIT(V_038004_FMT_5_9_9_9_SHAREDEXP, 0), | ||
127 | FMT_32_BIT(V_038004_FMT_32_AS_8, 0), | ||
128 | FMT_32_BIT(V_038004_FMT_32_AS_8_8, 0), | ||
129 | |||
130 | /* 48-bit */ | ||
131 | FMT_48_BIT(V_038004_FMT_16_16_16), | ||
132 | FMT_48_BIT(V_038004_FMT_16_16_16_FLOAT), | ||
133 | |||
134 | /* 64-bit */ | ||
135 | FMT_64_BIT(V_038004_COLOR_X24_8_32_FLOAT, 1), | ||
136 | FMT_64_BIT(V_038004_COLOR_32_32, 1), | ||
137 | FMT_64_BIT(V_038004_COLOR_32_32_FLOAT, 1), | ||
138 | FMT_64_BIT(V_038004_COLOR_16_16_16_16, 1), | ||
139 | FMT_64_BIT(V_038004_COLOR_16_16_16_16_FLOAT, 1), | ||
140 | |||
141 | FMT_96_BIT(V_038004_FMT_32_32_32), | ||
142 | FMT_96_BIT(V_038004_FMT_32_32_32_FLOAT), | ||
143 | |||
144 | /* 128-bit */ | ||
145 | FMT_128_BIT(V_038004_COLOR_32_32_32_32, 1), | ||
146 | FMT_128_BIT(V_038004_COLOR_32_32_32_32_FLOAT, 1), | ||
147 | |||
148 | [V_038004_FMT_GB_GR] = { 2, 1, 4, 0 }, | ||
149 | [V_038004_FMT_BG_RG] = { 2, 1, 4, 0 }, | ||
150 | |||
151 | /* block compressed formats */ | ||
152 | [V_038004_FMT_BC1] = { 4, 4, 8, 0 }, | ||
153 | [V_038004_FMT_BC2] = { 4, 4, 16, 0 }, | ||
154 | [V_038004_FMT_BC3] = { 4, 4, 16, 0 }, | ||
155 | [V_038004_FMT_BC4] = { 4, 4, 8, 0 }, | ||
156 | [V_038004_FMT_BC5] = { 4, 4, 16, 0}, | ||
157 | |||
158 | }; | ||
159 | |||
160 | static inline bool fmt_is_valid_color(u32 format) | ||
161 | { | ||
162 | if (format >= ARRAY_SIZE(color_formats_table)) | ||
163 | return false; | ||
164 | |||
165 | if (color_formats_table[format].valid_color) | ||
166 | return true; | ||
167 | |||
168 | return false; | ||
169 | } | ||
170 | |||
171 | static inline bool fmt_is_valid_texture(u32 format) | ||
172 | { | ||
173 | if (format >= ARRAY_SIZE(color_formats_table)) | ||
174 | return false; | ||
175 | |||
176 | if (color_formats_table[format].blockwidth > 0) | ||
177 | return true; | ||
178 | |||
179 | return false; | ||
180 | } | ||
181 | |||
182 | static inline int fmt_get_blocksize(u32 format) | ||
183 | { | ||
184 | if (format >= ARRAY_SIZE(color_formats_table)) | ||
185 | return 0; | ||
186 | |||
187 | return color_formats_table[format].blocksize; | ||
188 | } | ||
189 | |||
190 | static inline int fmt_get_nblocksx(u32 format, u32 w) | ||
191 | { | ||
192 | unsigned bw; | ||
193 | |||
194 | if (format >= ARRAY_SIZE(color_formats_table)) | ||
195 | return 0; | ||
196 | |||
197 | bw = color_formats_table[format].blockwidth; | ||
198 | if (bw == 0) | ||
199 | return 0; | ||
200 | |||
201 | return (w + bw - 1) / bw; | ||
202 | } | ||
203 | |||
204 | static inline int fmt_get_nblocksy(u32 format, u32 h) | ||
205 | { | ||
206 | unsigned bh; | ||
207 | |||
208 | if (format >= ARRAY_SIZE(color_formats_table)) | ||
209 | return 0; | ||
210 | |||
211 | bh = color_formats_table[format].blockheight; | ||
212 | if (bh == 0) | ||
213 | return 0; | ||
214 | |||
215 | return (h + bh - 1) / bh; | ||
216 | } | ||
217 | |||
74 | static inline int r600_bpe_from_format(u32 *bpe, u32 format) | 218 | static inline int r600_bpe_from_format(u32 *bpe, u32 format) |
75 | { | 219 | { |
76 | switch (format) { | 220 | unsigned res; |
77 | case V_038004_COLOR_8: | 221 | |
78 | case V_038004_COLOR_4_4: | 222 | if (format >= ARRAY_SIZE(color_formats_table)) |
79 | case V_038004_COLOR_3_3_2: | 223 | goto fail; |
80 | case V_038004_FMT_1: | 224 | |
81 | *bpe = 1; | 225 | res = color_formats_table[format].blocksize; |
82 | break; | 226 | if (res == 0) |
83 | case V_038004_COLOR_16: | 227 | goto fail; |
84 | case V_038004_COLOR_16_FLOAT: | 228 | |
85 | case V_038004_COLOR_8_8: | 229 | *bpe = res; |
86 | case V_038004_COLOR_5_6_5: | ||
87 | case V_038004_COLOR_6_5_5: | ||
88 | case V_038004_COLOR_1_5_5_5: | ||
89 | case V_038004_COLOR_4_4_4_4: | ||
90 | case V_038004_COLOR_5_5_5_1: | ||
91 | *bpe = 2; | ||
92 | break; | ||
93 | case V_038004_FMT_8_8_8: | ||
94 | *bpe = 3; | ||
95 | break; | ||
96 | case V_038004_COLOR_32: | ||
97 | case V_038004_COLOR_32_FLOAT: | ||
98 | case V_038004_COLOR_16_16: | ||
99 | case V_038004_COLOR_16_16_FLOAT: | ||
100 | case V_038004_COLOR_8_24: | ||
101 | case V_038004_COLOR_8_24_FLOAT: | ||
102 | case V_038004_COLOR_24_8: | ||
103 | case V_038004_COLOR_24_8_FLOAT: | ||
104 | case V_038004_COLOR_10_11_11: | ||
105 | case V_038004_COLOR_10_11_11_FLOAT: | ||
106 | case V_038004_COLOR_11_11_10: | ||
107 | case V_038004_COLOR_11_11_10_FLOAT: | ||
108 | case V_038004_COLOR_2_10_10_10: | ||
109 | case V_038004_COLOR_8_8_8_8: | ||
110 | case V_038004_COLOR_10_10_10_2: | ||
111 | case V_038004_FMT_5_9_9_9_SHAREDEXP: | ||
112 | case V_038004_FMT_32_AS_8: | ||
113 | case V_038004_FMT_32_AS_8_8: | ||
114 | *bpe = 4; | ||
115 | break; | ||
116 | case V_038004_COLOR_X24_8_32_FLOAT: | ||
117 | case V_038004_COLOR_32_32: | ||
118 | case V_038004_COLOR_32_32_FLOAT: | ||
119 | case V_038004_COLOR_16_16_16_16: | ||
120 | case V_038004_COLOR_16_16_16_16_FLOAT: | ||
121 | *bpe = 8; | ||
122 | break; | ||
123 | case V_038004_FMT_16_16_16: | ||
124 | case V_038004_FMT_16_16_16_FLOAT: | ||
125 | *bpe = 6; | ||
126 | break; | ||
127 | case V_038004_FMT_32_32_32: | ||
128 | case V_038004_FMT_32_32_32_FLOAT: | ||
129 | *bpe = 12; | ||
130 | break; | ||
131 | case V_038004_COLOR_32_32_32_32: | ||
132 | case V_038004_COLOR_32_32_32_32_FLOAT: | ||
133 | *bpe = 16; | ||
134 | break; | ||
135 | case V_038004_FMT_GB_GR: | ||
136 | case V_038004_FMT_BG_RG: | ||
137 | case V_038004_COLOR_INVALID: | ||
138 | default: | ||
139 | *bpe = 16; | ||
140 | return -EINVAL; | ||
141 | } | ||
142 | return 0; | 230 | return 0; |
231 | |||
232 | fail: | ||
233 | *bpe = 16; | ||
234 | return -EINVAL; | ||
143 | } | 235 | } |
144 | 236 | ||
145 | struct array_mode_checker { | 237 | struct array_mode_checker { |
@@ -148,7 +240,7 @@ struct array_mode_checker { | |||
148 | u32 nbanks; | 240 | u32 nbanks; |
149 | u32 npipes; | 241 | u32 npipes; |
150 | u32 nsamples; | 242 | u32 nsamples; |
151 | u32 bpe; | 243 | u32 blocksize; |
152 | }; | 244 | }; |
153 | 245 | ||
154 | /* returns alignment in pixels for pitch/height/depth and bytes for base */ | 246 | /* returns alignment in pixels for pitch/height/depth and bytes for base */ |
@@ -162,7 +254,7 @@ static inline int r600_get_array_mode_alignment(struct array_mode_checker *value | |||
162 | u32 tile_height = 8; | 254 | u32 tile_height = 8; |
163 | u32 macro_tile_width = values->nbanks; | 255 | u32 macro_tile_width = values->nbanks; |
164 | u32 macro_tile_height = values->npipes; | 256 | u32 macro_tile_height = values->npipes; |
165 | u32 tile_bytes = tile_width * tile_height * values->bpe * values->nsamples; | 257 | u32 tile_bytes = tile_width * tile_height * values->blocksize * values->nsamples; |
166 | u32 macro_tile_bytes = macro_tile_width * macro_tile_height * tile_bytes; | 258 | u32 macro_tile_bytes = macro_tile_width * macro_tile_height * tile_bytes; |
167 | 259 | ||
168 | switch (values->array_mode) { | 260 | switch (values->array_mode) { |
@@ -174,7 +266,7 @@ static inline int r600_get_array_mode_alignment(struct array_mode_checker *value | |||
174 | *base_align = 1; | 266 | *base_align = 1; |
175 | break; | 267 | break; |
176 | case ARRAY_LINEAR_ALIGNED: | 268 | case ARRAY_LINEAR_ALIGNED: |
177 | *pitch_align = max((u32)64, (u32)(values->group_size / values->bpe)); | 269 | *pitch_align = max((u32)64, (u32)(values->group_size / values->blocksize)); |
178 | *height_align = tile_height; | 270 | *height_align = tile_height; |
179 | *depth_align = 1; | 271 | *depth_align = 1; |
180 | *base_align = values->group_size; | 272 | *base_align = values->group_size; |
@@ -182,7 +274,7 @@ static inline int r600_get_array_mode_alignment(struct array_mode_checker *value | |||
182 | case ARRAY_1D_TILED_THIN1: | 274 | case ARRAY_1D_TILED_THIN1: |
183 | *pitch_align = max((u32)tile_width, | 275 | *pitch_align = max((u32)tile_width, |
184 | (u32)(values->group_size / | 276 | (u32)(values->group_size / |
185 | (tile_height * values->bpe * values->nsamples))); | 277 | (tile_height * values->blocksize * values->nsamples))); |
186 | *height_align = tile_height; | 278 | *height_align = tile_height; |
187 | *depth_align = 1; | 279 | *depth_align = 1; |
188 | *base_align = values->group_size; | 280 | *base_align = values->group_size; |
@@ -190,12 +282,12 @@ static inline int r600_get_array_mode_alignment(struct array_mode_checker *value | |||
190 | case ARRAY_2D_TILED_THIN1: | 282 | case ARRAY_2D_TILED_THIN1: |
191 | *pitch_align = max((u32)macro_tile_width, | 283 | *pitch_align = max((u32)macro_tile_width, |
192 | (u32)(((values->group_size / tile_height) / | 284 | (u32)(((values->group_size / tile_height) / |
193 | (values->bpe * values->nsamples)) * | 285 | (values->blocksize * values->nsamples)) * |
194 | values->nbanks)) * tile_width; | 286 | values->nbanks)) * tile_width; |
195 | *height_align = macro_tile_height * tile_height; | 287 | *height_align = macro_tile_height * tile_height; |
196 | *depth_align = 1; | 288 | *depth_align = 1; |
197 | *base_align = max(macro_tile_bytes, | 289 | *base_align = max(macro_tile_bytes, |
198 | (*pitch_align) * values->bpe * (*height_align) * values->nsamples); | 290 | (*pitch_align) * values->blocksize * (*height_align) * values->nsamples); |
199 | break; | 291 | break; |
200 | default: | 292 | default: |
201 | return -EINVAL; | 293 | return -EINVAL; |
@@ -234,21 +326,22 @@ static void r600_cs_track_init(struct r600_cs_track *track) | |||
234 | static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) | 326 | static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) |
235 | { | 327 | { |
236 | struct r600_cs_track *track = p->track; | 328 | struct r600_cs_track *track = p->track; |
237 | u32 bpe = 0, slice_tile_max, size, tmp; | 329 | u32 slice_tile_max, size, tmp; |
238 | u32 height, height_align, pitch, pitch_align, depth_align; | 330 | u32 height, height_align, pitch, pitch_align, depth_align; |
239 | u64 base_offset, base_align; | 331 | u64 base_offset, base_align; |
240 | struct array_mode_checker array_check; | 332 | struct array_mode_checker array_check; |
241 | volatile u32 *ib = p->ib->ptr; | 333 | volatile u32 *ib = p->ib->ptr; |
242 | unsigned array_mode; | 334 | unsigned array_mode; |
243 | 335 | u32 format; | |
244 | if (G_0280A0_TILE_MODE(track->cb_color_info[i])) { | 336 | if (G_0280A0_TILE_MODE(track->cb_color_info[i])) { |
245 | dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n"); | 337 | dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n"); |
246 | return -EINVAL; | 338 | return -EINVAL; |
247 | } | 339 | } |
248 | size = radeon_bo_size(track->cb_color_bo[i]) - track->cb_color_bo_offset[i]; | 340 | size = radeon_bo_size(track->cb_color_bo[i]) - track->cb_color_bo_offset[i]; |
249 | if (r600_bpe_from_format(&bpe, G_0280A0_FORMAT(track->cb_color_info[i]))) { | 341 | format = G_0280A0_FORMAT(track->cb_color_info[i]); |
342 | if (!fmt_is_valid_color(format)) { | ||
250 | dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08X)\n", | 343 | dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08X)\n", |
251 | __func__, __LINE__, G_0280A0_FORMAT(track->cb_color_info[i]), | 344 | __func__, __LINE__, format, |
252 | i, track->cb_color_info[i]); | 345 | i, track->cb_color_info[i]); |
253 | return -EINVAL; | 346 | return -EINVAL; |
254 | } | 347 | } |
@@ -267,7 +360,7 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) | |||
267 | array_check.nbanks = track->nbanks; | 360 | array_check.nbanks = track->nbanks; |
268 | array_check.npipes = track->npipes; | 361 | array_check.npipes = track->npipes; |
269 | array_check.nsamples = track->nsamples; | 362 | array_check.nsamples = track->nsamples; |
270 | array_check.bpe = bpe; | 363 | array_check.blocksize = fmt_get_blocksize(format); |
271 | if (r600_get_array_mode_alignment(&array_check, | 364 | if (r600_get_array_mode_alignment(&array_check, |
272 | &pitch_align, &height_align, &depth_align, &base_align)) { | 365 | &pitch_align, &height_align, &depth_align, &base_align)) { |
273 | dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__, | 366 | dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__, |
@@ -311,7 +404,7 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) | |||
311 | } | 404 | } |
312 | 405 | ||
313 | /* check offset */ | 406 | /* check offset */ |
314 | tmp = height * pitch * bpe; | 407 | tmp = fmt_get_nblocksy(format, height) * fmt_get_nblocksx(format, pitch) * fmt_get_blocksize(format); |
315 | if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) { | 408 | if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) { |
316 | if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) { | 409 | if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) { |
317 | /* the initial DDX does bad things with the CB size occasionally */ | 410 | /* the initial DDX does bad things with the CB size occasionally */ |
@@ -436,7 +529,7 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) | |||
436 | array_check.nbanks = track->nbanks; | 529 | array_check.nbanks = track->nbanks; |
437 | array_check.npipes = track->npipes; | 530 | array_check.npipes = track->npipes; |
438 | array_check.nsamples = track->nsamples; | 531 | array_check.nsamples = track->nsamples; |
439 | array_check.bpe = bpe; | 532 | array_check.blocksize = bpe; |
440 | if (r600_get_array_mode_alignment(&array_check, | 533 | if (r600_get_array_mode_alignment(&array_check, |
441 | &pitch_align, &height_align, &depth_align, &base_align)) { | 534 | &pitch_align, &height_align, &depth_align, &base_align)) { |
442 | dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__, | 535 | dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__, |
@@ -1113,39 +1206,61 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx | |||
1113 | return 0; | 1206 | return 0; |
1114 | } | 1207 | } |
1115 | 1208 | ||
1116 | static inline unsigned minify(unsigned size, unsigned levels) | 1209 | static inline unsigned mip_minify(unsigned size, unsigned level) |
1117 | { | 1210 | { |
1118 | size = size >> levels; | 1211 | unsigned val; |
1119 | if (size < 1) | 1212 | |
1120 | size = 1; | 1213 | val = max(1U, size >> level); |
1121 | return size; | 1214 | if (level > 0) |
1215 | val = roundup_pow_of_two(val); | ||
1216 | return val; | ||
1122 | } | 1217 | } |
1123 | 1218 | ||
1124 | static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned nlevels, | 1219 | static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned llevel, |
1125 | unsigned w0, unsigned h0, unsigned d0, unsigned bpe, | 1220 | unsigned w0, unsigned h0, unsigned d0, unsigned format, |
1126 | unsigned pitch_align, | 1221 | unsigned block_align, unsigned height_align, unsigned base_align, |
1127 | unsigned *l0_size, unsigned *mipmap_size) | 1222 | unsigned *l0_size, unsigned *mipmap_size) |
1128 | { | 1223 | { |
1129 | unsigned offset, i, level, face; | 1224 | unsigned offset, i, level; |
1130 | unsigned width, height, depth, rowstride, size; | 1225 | unsigned width, height, depth, size; |
1131 | 1226 | unsigned blocksize; | |
1132 | w0 = minify(w0, 0); | 1227 | unsigned nbx, nby; |
1133 | h0 = minify(h0, 0); | 1228 | unsigned nlevels = llevel - blevel + 1; |
1134 | d0 = minify(d0, 0); | 1229 | |
1230 | *l0_size = -1; | ||
1231 | blocksize = fmt_get_blocksize(format); | ||
1232 | |||
1233 | w0 = mip_minify(w0, 0); | ||
1234 | h0 = mip_minify(h0, 0); | ||
1235 | d0 = mip_minify(d0, 0); | ||
1135 | for(i = 0, offset = 0, level = blevel; i < nlevels; i++, level++) { | 1236 | for(i = 0, offset = 0, level = blevel; i < nlevels; i++, level++) { |
1136 | width = minify(w0, i); | 1237 | width = mip_minify(w0, i); |
1137 | height = minify(h0, i); | 1238 | nbx = fmt_get_nblocksx(format, width); |
1138 | depth = minify(d0, i); | 1239 | |
1139 | for(face = 0; face < nfaces; face++) { | 1240 | nbx = round_up(nbx, block_align); |
1140 | rowstride = ALIGN((width * bpe), pitch_align); | 1241 | |
1141 | size = height * rowstride * depth; | 1242 | height = mip_minify(h0, i); |
1142 | offset += size; | 1243 | nby = fmt_get_nblocksy(format, height); |
1143 | offset = (offset + 0x1f) & ~0x1f; | 1244 | nby = round_up(nby, height_align); |
1144 | } | 1245 | |
1246 | depth = mip_minify(d0, i); | ||
1247 | |||
1248 | size = nbx * nby * blocksize; | ||
1249 | if (nfaces) | ||
1250 | size *= nfaces; | ||
1251 | else | ||
1252 | size *= depth; | ||
1253 | |||
1254 | if (i == 0) | ||
1255 | *l0_size = size; | ||
1256 | |||
1257 | if (i == 0 || i == 1) | ||
1258 | offset = round_up(offset, base_align); | ||
1259 | |||
1260 | offset += size; | ||
1145 | } | 1261 | } |
1146 | *l0_size = ALIGN((w0 * bpe), pitch_align) * h0 * d0; | ||
1147 | *mipmap_size = offset; | 1262 | *mipmap_size = offset; |
1148 | if (!nlevels) | 1263 | if (llevel == 0) |
1149 | *mipmap_size = *l0_size; | 1264 | *mipmap_size = *l0_size; |
1150 | if (!blevel) | 1265 | if (!blevel) |
1151 | *mipmap_size -= *l0_size; | 1266 | *mipmap_size -= *l0_size; |
@@ -1169,11 +1284,13 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i | |||
1169 | u32 tiling_flags) | 1284 | u32 tiling_flags) |
1170 | { | 1285 | { |
1171 | struct r600_cs_track *track = p->track; | 1286 | struct r600_cs_track *track = p->track; |
1172 | u32 nfaces, nlevels, blevel, w0, h0, d0, bpe = 0; | 1287 | u32 nfaces, llevel, blevel, w0, h0, d0; |
1173 | u32 word0, word1, l0_size, mipmap_size; | 1288 | u32 word0, word1, l0_size, mipmap_size, word2, word3; |
1174 | u32 height_align, pitch, pitch_align, depth_align; | 1289 | u32 height_align, pitch, pitch_align, depth_align; |
1290 | u32 array, barray, larray; | ||
1175 | u64 base_align; | 1291 | u64 base_align; |
1176 | struct array_mode_checker array_check; | 1292 | struct array_mode_checker array_check; |
1293 | u32 format; | ||
1177 | 1294 | ||
1178 | /* on legacy kernel we don't perform advanced check */ | 1295 | /* on legacy kernel we don't perform advanced check */ |
1179 | if (p->rdev == NULL) | 1296 | if (p->rdev == NULL) |
@@ -1199,19 +1316,25 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i | |||
1199 | case V_038000_SQ_TEX_DIM_3D: | 1316 | case V_038000_SQ_TEX_DIM_3D: |
1200 | break; | 1317 | break; |
1201 | case V_038000_SQ_TEX_DIM_CUBEMAP: | 1318 | case V_038000_SQ_TEX_DIM_CUBEMAP: |
1202 | nfaces = 6; | 1319 | if (p->family >= CHIP_RV770) |
1320 | nfaces = 8; | ||
1321 | else | ||
1322 | nfaces = 6; | ||
1203 | break; | 1323 | break; |
1204 | case V_038000_SQ_TEX_DIM_1D_ARRAY: | 1324 | case V_038000_SQ_TEX_DIM_1D_ARRAY: |
1205 | case V_038000_SQ_TEX_DIM_2D_ARRAY: | 1325 | case V_038000_SQ_TEX_DIM_2D_ARRAY: |
1326 | array = 1; | ||
1327 | break; | ||
1206 | case V_038000_SQ_TEX_DIM_2D_MSAA: | 1328 | case V_038000_SQ_TEX_DIM_2D_MSAA: |
1207 | case V_038000_SQ_TEX_DIM_2D_ARRAY_MSAA: | 1329 | case V_038000_SQ_TEX_DIM_2D_ARRAY_MSAA: |
1208 | default: | 1330 | default: |
1209 | dev_warn(p->dev, "this kernel doesn't support %d texture dim\n", G_038000_DIM(word0)); | 1331 | dev_warn(p->dev, "this kernel doesn't support %d texture dim\n", G_038000_DIM(word0)); |
1210 | return -EINVAL; | 1332 | return -EINVAL; |
1211 | } | 1333 | } |
1212 | if (r600_bpe_from_format(&bpe, G_038004_DATA_FORMAT(word1))) { | 1334 | format = G_038004_DATA_FORMAT(word1); |
1335 | if (!fmt_is_valid_texture(format)) { | ||
1213 | dev_warn(p->dev, "%s:%d texture invalid format %d\n", | 1336 | dev_warn(p->dev, "%s:%d texture invalid format %d\n", |
1214 | __func__, __LINE__, G_038004_DATA_FORMAT(word1)); | 1337 | __func__, __LINE__, format); |
1215 | return -EINVAL; | 1338 | return -EINVAL; |
1216 | } | 1339 | } |
1217 | 1340 | ||
@@ -1222,7 +1345,7 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i | |||
1222 | array_check.nbanks = track->nbanks; | 1345 | array_check.nbanks = track->nbanks; |
1223 | array_check.npipes = track->npipes; | 1346 | array_check.npipes = track->npipes; |
1224 | array_check.nsamples = 1; | 1347 | array_check.nsamples = 1; |
1225 | array_check.bpe = bpe; | 1348 | array_check.blocksize = fmt_get_blocksize(format); |
1226 | if (r600_get_array_mode_alignment(&array_check, | 1349 | if (r600_get_array_mode_alignment(&array_check, |
1227 | &pitch_align, &height_align, &depth_align, &base_align)) { | 1350 | &pitch_align, &height_align, &depth_align, &base_align)) { |
1228 | dev_warn(p->dev, "%s:%d tex array mode (%d) invalid\n", | 1351 | dev_warn(p->dev, "%s:%d tex array mode (%d) invalid\n", |
@@ -1248,25 +1371,34 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i | |||
1248 | return -EINVAL; | 1371 | return -EINVAL; |
1249 | } | 1372 | } |
1250 | 1373 | ||
1374 | word2 = radeon_get_ib_value(p, idx + 2) << 8; | ||
1375 | word3 = radeon_get_ib_value(p, idx + 3) << 8; | ||
1376 | |||
1251 | word0 = radeon_get_ib_value(p, idx + 4); | 1377 | word0 = radeon_get_ib_value(p, idx + 4); |
1252 | word1 = radeon_get_ib_value(p, idx + 5); | 1378 | word1 = radeon_get_ib_value(p, idx + 5); |
1253 | blevel = G_038010_BASE_LEVEL(word0); | 1379 | blevel = G_038010_BASE_LEVEL(word0); |
1254 | nlevels = G_038014_LAST_LEVEL(word1); | 1380 | llevel = G_038014_LAST_LEVEL(word1); |
1255 | r600_texture_size(nfaces, blevel, nlevels, w0, h0, d0, bpe, | 1381 | if (array == 1) { |
1256 | (pitch_align * bpe), | 1382 | barray = G_038014_BASE_ARRAY(word1); |
1383 | larray = G_038014_LAST_ARRAY(word1); | ||
1384 | |||
1385 | nfaces = larray - barray + 1; | ||
1386 | } | ||
1387 | r600_texture_size(nfaces, blevel, llevel, w0, h0, d0, format, | ||
1388 | pitch_align, height_align, base_align, | ||
1257 | &l0_size, &mipmap_size); | 1389 | &l0_size, &mipmap_size); |
1258 | /* using get ib will give us the offset into the texture bo */ | 1390 | /* using get ib will give us the offset into the texture bo */ |
1259 | word0 = radeon_get_ib_value(p, idx + 2) << 8; | 1391 | if ((l0_size + word2) > radeon_bo_size(texture)) { |
1260 | if ((l0_size + word0) > radeon_bo_size(texture)) { | ||
1261 | dev_warn(p->dev, "texture bo too small (%d %d %d %d -> %d have %ld)\n", | 1392 | dev_warn(p->dev, "texture bo too small (%d %d %d %d -> %d have %ld)\n", |
1262 | w0, h0, bpe, word0, l0_size, radeon_bo_size(texture)); | 1393 | w0, h0, format, word2, l0_size, radeon_bo_size(texture)); |
1394 | dev_warn(p->dev, "alignments %d %d %d %lld\n", pitch, pitch_align, height_align, base_align); | ||
1263 | return -EINVAL; | 1395 | return -EINVAL; |
1264 | } | 1396 | } |
1265 | /* using get ib will give us the offset into the mipmap bo */ | 1397 | /* using get ib will give us the offset into the mipmap bo */ |
1266 | word0 = radeon_get_ib_value(p, idx + 3) << 8; | 1398 | word3 = radeon_get_ib_value(p, idx + 3) << 8; |
1267 | if ((mipmap_size + word0) > radeon_bo_size(mipmap)) { | 1399 | if ((mipmap_size + word3) > radeon_bo_size(mipmap)) { |
1268 | /*dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n", | 1400 | /*dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n", |
1269 | w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture));*/ | 1401 | w0, h0, format, blevel, nlevels, word3, mipmap_size, radeon_bo_size(texture));*/ |
1270 | } | 1402 | } |
1271 | return 0; | 1403 | return 0; |
1272 | } | 1404 | } |
@@ -1289,6 +1421,38 @@ static int r600_packet3_check(struct radeon_cs_parser *p, | |||
1289 | idx_value = radeon_get_ib_value(p, idx); | 1421 | idx_value = radeon_get_ib_value(p, idx); |
1290 | 1422 | ||
1291 | switch (pkt->opcode) { | 1423 | switch (pkt->opcode) { |
1424 | case PACKET3_SET_PREDICATION: | ||
1425 | { | ||
1426 | int pred_op; | ||
1427 | int tmp; | ||
1428 | if (pkt->count != 1) { | ||
1429 | DRM_ERROR("bad SET PREDICATION\n"); | ||
1430 | return -EINVAL; | ||
1431 | } | ||
1432 | |||
1433 | tmp = radeon_get_ib_value(p, idx + 1); | ||
1434 | pred_op = (tmp >> 16) & 0x7; | ||
1435 | |||
1436 | /* for the clear predicate operation */ | ||
1437 | if (pred_op == 0) | ||
1438 | return 0; | ||
1439 | |||
1440 | if (pred_op > 2) { | ||
1441 | DRM_ERROR("bad SET PREDICATION operation %d\n", pred_op); | ||
1442 | return -EINVAL; | ||
1443 | } | ||
1444 | |||
1445 | r = r600_cs_packet_next_reloc(p, &reloc); | ||
1446 | if (r) { | ||
1447 | DRM_ERROR("bad SET PREDICATION\n"); | ||
1448 | return -EINVAL; | ||
1449 | } | ||
1450 | |||
1451 | ib[idx + 0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff); | ||
1452 | ib[idx + 1] = tmp + (upper_32_bits(reloc->lobj.gpu_offset) & 0xff); | ||
1453 | } | ||
1454 | break; | ||
1455 | |||
1292 | case PACKET3_START_3D_CMDBUF: | 1456 | case PACKET3_START_3D_CMDBUF: |
1293 | if (p->family >= CHIP_RV770 || pkt->count) { | 1457 | if (p->family >= CHIP_RV770 || pkt->count) { |
1294 | DRM_ERROR("bad START_3D\n"); | 1458 | DRM_ERROR("bad START_3D\n"); |
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index e6a58ed48dc..50db6d62eec 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include "drmP.h" | 26 | #include "drmP.h" |
27 | #include "radeon_drm.h" | 27 | #include "radeon_drm.h" |
28 | #include "radeon.h" | 28 | #include "radeon.h" |
29 | #include "radeon_asic.h" | ||
29 | #include "atom.h" | 30 | #include "atom.h" |
30 | 31 | ||
31 | /* | 32 | /* |
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 04bac0bbd3e..b2b944bcd05 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h | |||
@@ -1304,6 +1304,11 @@ | |||
1304 | #define V_038004_FMT_16_16_16_FLOAT 0x0000002E | 1304 | #define V_038004_FMT_16_16_16_FLOAT 0x0000002E |
1305 | #define V_038004_FMT_32_32_32 0x0000002F | 1305 | #define V_038004_FMT_32_32_32 0x0000002F |
1306 | #define V_038004_FMT_32_32_32_FLOAT 0x00000030 | 1306 | #define V_038004_FMT_32_32_32_FLOAT 0x00000030 |
1307 | #define V_038004_FMT_BC1 0x00000031 | ||
1308 | #define V_038004_FMT_BC2 0x00000032 | ||
1309 | #define V_038004_FMT_BC3 0x00000033 | ||
1310 | #define V_038004_FMT_BC4 0x00000034 | ||
1311 | #define V_038004_FMT_BC5 0x00000035 | ||
1307 | #define R_038010_SQ_TEX_RESOURCE_WORD4_0 0x038010 | 1312 | #define R_038010_SQ_TEX_RESOURCE_WORD4_0 0x038010 |
1308 | #define S_038010_FORMAT_COMP_X(x) (((x) & 0x3) << 0) | 1313 | #define S_038010_FORMAT_COMP_X(x) (((x) & 0x3) << 0) |
1309 | #define G_038010_FORMAT_COMP_X(x) (((x) >> 0) & 0x3) | 1314 | #define G_038010_FORMAT_COMP_X(x) (((x) >> 0) & 0x3) |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 6b342949511..cfe3af1a793 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -258,8 +258,9 @@ struct radeon_bo { | |||
258 | int surface_reg; | 258 | int surface_reg; |
259 | /* Constant after initialization */ | 259 | /* Constant after initialization */ |
260 | struct radeon_device *rdev; | 260 | struct radeon_device *rdev; |
261 | struct drm_gem_object *gobj; | 261 | struct drm_gem_object gem_base; |
262 | }; | 262 | }; |
263 | #define gem_to_radeon_bo(gobj) container_of((gobj), struct radeon_bo, gem_base) | ||
263 | 264 | ||
264 | struct radeon_bo_list { | 265 | struct radeon_bo_list { |
265 | struct ttm_validate_buffer tv; | 266 | struct ttm_validate_buffer tv; |
@@ -288,6 +289,15 @@ int radeon_gem_object_pin(struct drm_gem_object *obj, uint32_t pin_domain, | |||
288 | uint64_t *gpu_addr); | 289 | uint64_t *gpu_addr); |
289 | void radeon_gem_object_unpin(struct drm_gem_object *obj); | 290 | void radeon_gem_object_unpin(struct drm_gem_object *obj); |
290 | 291 | ||
292 | int radeon_mode_dumb_create(struct drm_file *file_priv, | ||
293 | struct drm_device *dev, | ||
294 | struct drm_mode_create_dumb *args); | ||
295 | int radeon_mode_dumb_mmap(struct drm_file *filp, | ||
296 | struct drm_device *dev, | ||
297 | uint32_t handle, uint64_t *offset_p); | ||
298 | int radeon_mode_dumb_destroy(struct drm_file *file_priv, | ||
299 | struct drm_device *dev, | ||
300 | uint32_t handle); | ||
291 | 301 | ||
292 | /* | 302 | /* |
293 | * GART structures, functions & helpers | 303 | * GART structures, functions & helpers |
@@ -319,6 +329,7 @@ struct radeon_gart { | |||
319 | union radeon_gart_table table; | 329 | union radeon_gart_table table; |
320 | struct page **pages; | 330 | struct page **pages; |
321 | dma_addr_t *pages_addr; | 331 | dma_addr_t *pages_addr; |
332 | bool *ttm_alloced; | ||
322 | bool ready; | 333 | bool ready; |
323 | }; | 334 | }; |
324 | 335 | ||
@@ -331,7 +342,8 @@ void radeon_gart_fini(struct radeon_device *rdev); | |||
331 | void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, | 342 | void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, |
332 | int pages); | 343 | int pages); |
333 | int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, | 344 | int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, |
334 | int pages, struct page **pagelist); | 345 | int pages, struct page **pagelist, |
346 | dma_addr_t *dma_addr); | ||
335 | 347 | ||
336 | 348 | ||
337 | /* | 349 | /* |
@@ -651,6 +663,8 @@ struct radeon_wb { | |||
651 | 663 | ||
652 | #define RADEON_WB_SCRATCH_OFFSET 0 | 664 | #define RADEON_WB_SCRATCH_OFFSET 0 |
653 | #define RADEON_WB_CP_RPTR_OFFSET 1024 | 665 | #define RADEON_WB_CP_RPTR_OFFSET 1024 |
666 | #define RADEON_WB_CP1_RPTR_OFFSET 1280 | ||
667 | #define RADEON_WB_CP2_RPTR_OFFSET 1536 | ||
654 | #define R600_WB_IH_WPTR_OFFSET 2048 | 668 | #define R600_WB_IH_WPTR_OFFSET 2048 |
655 | #define R600_WB_EVENT_OFFSET 3072 | 669 | #define R600_WB_EVENT_OFFSET 3072 |
656 | 670 | ||
@@ -1037,12 +1051,52 @@ struct evergreen_asic { | |||
1037 | struct r100_gpu_lockup lockup; | 1051 | struct r100_gpu_lockup lockup; |
1038 | }; | 1052 | }; |
1039 | 1053 | ||
1054 | struct cayman_asic { | ||
1055 | unsigned max_shader_engines; | ||
1056 | unsigned max_pipes_per_simd; | ||
1057 | unsigned max_tile_pipes; | ||
1058 | unsigned max_simds_per_se; | ||
1059 | unsigned max_backends_per_se; | ||
1060 | unsigned max_texture_channel_caches; | ||
1061 | unsigned max_gprs; | ||
1062 | unsigned max_threads; | ||
1063 | unsigned max_gs_threads; | ||
1064 | unsigned max_stack_entries; | ||
1065 | unsigned sx_num_of_sets; | ||
1066 | unsigned sx_max_export_size; | ||
1067 | unsigned sx_max_export_pos_size; | ||
1068 | unsigned sx_max_export_smx_size; | ||
1069 | unsigned max_hw_contexts; | ||
1070 | unsigned sq_num_cf_insts; | ||
1071 | unsigned sc_prim_fifo_size; | ||
1072 | unsigned sc_hiz_tile_fifo_size; | ||
1073 | unsigned sc_earlyz_tile_fifo_size; | ||
1074 | |||
1075 | unsigned num_shader_engines; | ||
1076 | unsigned num_shader_pipes_per_simd; | ||
1077 | unsigned num_tile_pipes; | ||
1078 | unsigned num_simds_per_se; | ||
1079 | unsigned num_backends_per_se; | ||
1080 | unsigned backend_disable_mask_per_asic; | ||
1081 | unsigned backend_map; | ||
1082 | unsigned num_texture_channel_caches; | ||
1083 | unsigned mem_max_burst_length_bytes; | ||
1084 | unsigned mem_row_size_in_kb; | ||
1085 | unsigned shader_engine_tile_size; | ||
1086 | unsigned num_gpus; | ||
1087 | unsigned multi_gpu_tile_size; | ||
1088 | |||
1089 | unsigned tile_config; | ||
1090 | struct r100_gpu_lockup lockup; | ||
1091 | }; | ||
1092 | |||
1040 | union radeon_asic_config { | 1093 | union radeon_asic_config { |
1041 | struct r300_asic r300; | 1094 | struct r300_asic r300; |
1042 | struct r100_asic r100; | 1095 | struct r100_asic r100; |
1043 | struct r600_asic r600; | 1096 | struct r600_asic r600; |
1044 | struct rv770_asic rv770; | 1097 | struct rv770_asic rv770; |
1045 | struct evergreen_asic evergreen; | 1098 | struct evergreen_asic evergreen; |
1099 | struct cayman_asic cayman; | ||
1046 | }; | 1100 | }; |
1047 | 1101 | ||
1048 | /* | 1102 | /* |
@@ -1133,6 +1187,9 @@ struct radeon_device { | |||
1133 | struct radeon_mman mman; | 1187 | struct radeon_mman mman; |
1134 | struct radeon_fence_driver fence_drv; | 1188 | struct radeon_fence_driver fence_drv; |
1135 | struct radeon_cp cp; | 1189 | struct radeon_cp cp; |
1190 | /* cayman compute rings */ | ||
1191 | struct radeon_cp cp1; | ||
1192 | struct radeon_cp cp2; | ||
1136 | struct radeon_ib_pool ib_pool; | 1193 | struct radeon_ib_pool ib_pool; |
1137 | struct radeon_irq irq; | 1194 | struct radeon_irq irq; |
1138 | struct radeon_asic *asic; | 1195 | struct radeon_asic *asic; |
@@ -1185,19 +1242,6 @@ int radeon_device_init(struct radeon_device *rdev, | |||
1185 | void radeon_device_fini(struct radeon_device *rdev); | 1242 | void radeon_device_fini(struct radeon_device *rdev); |
1186 | int radeon_gpu_wait_for_idle(struct radeon_device *rdev); | 1243 | int radeon_gpu_wait_for_idle(struct radeon_device *rdev); |
1187 | 1244 | ||
1188 | /* r600 blit */ | ||
1189 | int r600_blit_prepare_copy(struct radeon_device *rdev, int size_bytes); | ||
1190 | void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence); | ||
1191 | void r600_kms_blit_copy(struct radeon_device *rdev, | ||
1192 | u64 src_gpu_addr, u64 dst_gpu_addr, | ||
1193 | int size_bytes); | ||
1194 | /* evergreen blit */ | ||
1195 | int evergreen_blit_prepare_copy(struct radeon_device *rdev, int size_bytes); | ||
1196 | void evergreen_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence); | ||
1197 | void evergreen_kms_blit_copy(struct radeon_device *rdev, | ||
1198 | u64 src_gpu_addr, u64 dst_gpu_addr, | ||
1199 | int size_bytes); | ||
1200 | |||
1201 | static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg) | 1245 | static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg) |
1202 | { | 1246 | { |
1203 | if (reg < rdev->rmmio_size) | 1247 | if (reg < rdev->rmmio_size) |
@@ -1449,62 +1493,15 @@ extern int radeon_resume_kms(struct drm_device *dev); | |||
1449 | extern int radeon_suspend_kms(struct drm_device *dev, pm_message_t state); | 1493 | extern int radeon_suspend_kms(struct drm_device *dev, pm_message_t state); |
1450 | extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size); | 1494 | extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size); |
1451 | 1495 | ||
1452 | /* r600, rv610, rv630, rv620, rv635, rv670, rs780, rs880 */ | 1496 | /* |
1453 | extern bool r600_card_posted(struct radeon_device *rdev); | 1497 | * r600 functions used by radeon_encoder.c |
1454 | extern void r600_cp_stop(struct radeon_device *rdev); | 1498 | */ |
1455 | extern int r600_cp_start(struct radeon_device *rdev); | ||
1456 | extern void r600_ring_init(struct radeon_device *rdev, unsigned ring_size); | ||
1457 | extern int r600_cp_resume(struct radeon_device *rdev); | ||
1458 | extern void r600_cp_fini(struct radeon_device *rdev); | ||
1459 | extern int r600_count_pipe_bits(uint32_t val); | ||
1460 | extern int r600_mc_wait_for_idle(struct radeon_device *rdev); | ||
1461 | extern int r600_pcie_gart_init(struct radeon_device *rdev); | ||
1462 | extern void r600_pcie_gart_tlb_flush(struct radeon_device *rdev); | ||
1463 | extern int r600_ib_test(struct radeon_device *rdev); | ||
1464 | extern int r600_ring_test(struct radeon_device *rdev); | ||
1465 | extern void r600_scratch_init(struct radeon_device *rdev); | ||
1466 | extern int r600_blit_init(struct radeon_device *rdev); | ||
1467 | extern void r600_blit_fini(struct radeon_device *rdev); | ||
1468 | extern int r600_init_microcode(struct radeon_device *rdev); | ||
1469 | extern int r600_asic_reset(struct radeon_device *rdev); | ||
1470 | /* r600 irq */ | ||
1471 | extern int r600_irq_init(struct radeon_device *rdev); | ||
1472 | extern void r600_irq_fini(struct radeon_device *rdev); | ||
1473 | extern void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size); | ||
1474 | extern int r600_irq_set(struct radeon_device *rdev); | ||
1475 | extern void r600_irq_suspend(struct radeon_device *rdev); | ||
1476 | extern void r600_disable_interrupts(struct radeon_device *rdev); | ||
1477 | extern void r600_rlc_stop(struct radeon_device *rdev); | ||
1478 | /* r600 audio */ | ||
1479 | extern int r600_audio_init(struct radeon_device *rdev); | ||
1480 | extern int r600_audio_tmds_index(struct drm_encoder *encoder); | ||
1481 | extern void r600_audio_set_clock(struct drm_encoder *encoder, int clock); | ||
1482 | extern int r600_audio_channels(struct radeon_device *rdev); | ||
1483 | extern int r600_audio_bits_per_sample(struct radeon_device *rdev); | ||
1484 | extern int r600_audio_rate(struct radeon_device *rdev); | ||
1485 | extern uint8_t r600_audio_status_bits(struct radeon_device *rdev); | ||
1486 | extern uint8_t r600_audio_category_code(struct radeon_device *rdev); | ||
1487 | extern void r600_audio_schedule_polling(struct radeon_device *rdev); | ||
1488 | extern void r600_audio_enable_polling(struct drm_encoder *encoder); | ||
1489 | extern void r600_audio_disable_polling(struct drm_encoder *encoder); | ||
1490 | extern void r600_audio_fini(struct radeon_device *rdev); | ||
1491 | extern void r600_hdmi_init(struct drm_encoder *encoder); | ||
1492 | extern void r600_hdmi_enable(struct drm_encoder *encoder); | 1499 | extern void r600_hdmi_enable(struct drm_encoder *encoder); |
1493 | extern void r600_hdmi_disable(struct drm_encoder *encoder); | 1500 | extern void r600_hdmi_disable(struct drm_encoder *encoder); |
1494 | extern void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode); | 1501 | extern void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode); |
1495 | extern int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder); | ||
1496 | extern void r600_hdmi_update_audio_settings(struct drm_encoder *encoder); | ||
1497 | |||
1498 | extern void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); | ||
1499 | extern void r700_cp_stop(struct radeon_device *rdev); | ||
1500 | extern void r700_cp_fini(struct radeon_device *rdev); | ||
1501 | extern void evergreen_disable_interrupt_state(struct radeon_device *rdev); | ||
1502 | extern int evergreen_irq_set(struct radeon_device *rdev); | ||
1503 | extern int evergreen_blit_init(struct radeon_device *rdev); | ||
1504 | extern void evergreen_blit_fini(struct radeon_device *rdev); | ||
1505 | 1502 | ||
1506 | extern int ni_init_microcode(struct radeon_device *rdev); | 1503 | extern int ni_init_microcode(struct radeon_device *rdev); |
1507 | extern int btc_mc_load_microcode(struct radeon_device *rdev); | 1504 | extern int ni_mc_load_microcode(struct radeon_device *rdev); |
1508 | 1505 | ||
1509 | /* radeon_acpi.c */ | 1506 | /* radeon_acpi.c */ |
1510 | #if defined(CONFIG_ACPI) | 1507 | #if defined(CONFIG_ACPI) |
@@ -1513,14 +1510,6 @@ extern int radeon_acpi_init(struct radeon_device *rdev); | |||
1513 | static inline int radeon_acpi_init(struct radeon_device *rdev) { return 0; } | 1510 | static inline int radeon_acpi_init(struct radeon_device *rdev) { return 0; } |
1514 | #endif | 1511 | #endif |
1515 | 1512 | ||
1516 | /* evergreen */ | ||
1517 | struct evergreen_mc_save { | ||
1518 | u32 vga_control[6]; | ||
1519 | u32 vga_render_control; | ||
1520 | u32 vga_hdp_control; | ||
1521 | u32 crtc_control[6]; | ||
1522 | }; | ||
1523 | |||
1524 | #include "radeon_object.h" | 1513 | #include "radeon_object.h" |
1525 | 1514 | ||
1526 | #endif | 1515 | #endif |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 793c5e6026a..eb888ee5f67 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c | |||
@@ -885,6 +885,52 @@ static struct radeon_asic btc_asic = { | |||
885 | .post_page_flip = &evergreen_post_page_flip, | 885 | .post_page_flip = &evergreen_post_page_flip, |
886 | }; | 886 | }; |
887 | 887 | ||
888 | static struct radeon_asic cayman_asic = { | ||
889 | .init = &cayman_init, | ||
890 | .fini = &cayman_fini, | ||
891 | .suspend = &cayman_suspend, | ||
892 | .resume = &cayman_resume, | ||
893 | .cp_commit = &r600_cp_commit, | ||
894 | .gpu_is_lockup = &cayman_gpu_is_lockup, | ||
895 | .asic_reset = &cayman_asic_reset, | ||
896 | .vga_set_state = &r600_vga_set_state, | ||
897 | .gart_tlb_flush = &cayman_pcie_gart_tlb_flush, | ||
898 | .gart_set_page = &rs600_gart_set_page, | ||
899 | .ring_test = &r600_ring_test, | ||
900 | .ring_ib_execute = &evergreen_ring_ib_execute, | ||
901 | .irq_set = &evergreen_irq_set, | ||
902 | .irq_process = &evergreen_irq_process, | ||
903 | .get_vblank_counter = &evergreen_get_vblank_counter, | ||
904 | .fence_ring_emit = &r600_fence_ring_emit, | ||
905 | .cs_parse = &evergreen_cs_parse, | ||
906 | .copy_blit = NULL, | ||
907 | .copy_dma = NULL, | ||
908 | .copy = NULL, | ||
909 | .get_engine_clock = &radeon_atom_get_engine_clock, | ||
910 | .set_engine_clock = &radeon_atom_set_engine_clock, | ||
911 | .get_memory_clock = &radeon_atom_get_memory_clock, | ||
912 | .set_memory_clock = &radeon_atom_set_memory_clock, | ||
913 | .get_pcie_lanes = NULL, | ||
914 | .set_pcie_lanes = NULL, | ||
915 | .set_clock_gating = NULL, | ||
916 | .set_surface_reg = r600_set_surface_reg, | ||
917 | .clear_surface_reg = r600_clear_surface_reg, | ||
918 | .bandwidth_update = &evergreen_bandwidth_update, | ||
919 | .hpd_init = &evergreen_hpd_init, | ||
920 | .hpd_fini = &evergreen_hpd_fini, | ||
921 | .hpd_sense = &evergreen_hpd_sense, | ||
922 | .hpd_set_polarity = &evergreen_hpd_set_polarity, | ||
923 | .gui_idle = &r600_gui_idle, | ||
924 | .pm_misc = &evergreen_pm_misc, | ||
925 | .pm_prepare = &evergreen_pm_prepare, | ||
926 | .pm_finish = &evergreen_pm_finish, | ||
927 | .pm_init_profile = &r600_pm_init_profile, | ||
928 | .pm_get_dynpm_state = &r600_pm_get_dynpm_state, | ||
929 | .pre_page_flip = &evergreen_pre_page_flip, | ||
930 | .page_flip = &evergreen_page_flip, | ||
931 | .post_page_flip = &evergreen_post_page_flip, | ||
932 | }; | ||
933 | |||
888 | int radeon_asic_init(struct radeon_device *rdev) | 934 | int radeon_asic_init(struct radeon_device *rdev) |
889 | { | 935 | { |
890 | radeon_register_accessor_init(rdev); | 936 | radeon_register_accessor_init(rdev); |
@@ -977,6 +1023,9 @@ int radeon_asic_init(struct radeon_device *rdev) | |||
977 | case CHIP_CAICOS: | 1023 | case CHIP_CAICOS: |
978 | rdev->asic = &btc_asic; | 1024 | rdev->asic = &btc_asic; |
979 | break; | 1025 | break; |
1026 | case CHIP_CAYMAN: | ||
1027 | rdev->asic = &cayman_asic; | ||
1028 | break; | ||
980 | default: | 1029 | default: |
981 | /* FIXME: not supported yet */ | 1030 | /* FIXME: not supported yet */ |
982 | return -EINVAL; | 1031 | return -EINVAL; |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index c59bd98a202..3d7a0d7c6a9 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h | |||
@@ -57,8 +57,6 @@ int r100_init(struct radeon_device *rdev); | |||
57 | void r100_fini(struct radeon_device *rdev); | 57 | void r100_fini(struct radeon_device *rdev); |
58 | int r100_suspend(struct radeon_device *rdev); | 58 | int r100_suspend(struct radeon_device *rdev); |
59 | int r100_resume(struct radeon_device *rdev); | 59 | int r100_resume(struct radeon_device *rdev); |
60 | uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg); | ||
61 | void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); | ||
62 | void r100_vga_set_state(struct radeon_device *rdev, bool state); | 60 | void r100_vga_set_state(struct radeon_device *rdev, bool state); |
63 | bool r100_gpu_is_lockup(struct radeon_device *rdev); | 61 | bool r100_gpu_is_lockup(struct radeon_device *rdev); |
64 | int r100_asic_reset(struct radeon_device *rdev); | 62 | int r100_asic_reset(struct radeon_device *rdev); |
@@ -164,8 +162,6 @@ extern void r300_fence_ring_emit(struct radeon_device *rdev, | |||
164 | extern int r300_cs_parse(struct radeon_cs_parser *p); | 162 | extern int r300_cs_parse(struct radeon_cs_parser *p); |
165 | extern void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev); | 163 | extern void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev); |
166 | extern int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); | 164 | extern int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); |
167 | extern uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg); | ||
168 | extern void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); | ||
169 | extern void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes); | 165 | extern void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes); |
170 | extern int rv370_get_pcie_lanes(struct radeon_device *rdev); | 166 | extern int rv370_get_pcie_lanes(struct radeon_device *rdev); |
171 | extern void r300_set_reg_safe(struct radeon_device *rdev); | 167 | extern void r300_set_reg_safe(struct radeon_device *rdev); |
@@ -208,7 +204,6 @@ void rs400_gart_adjust_size(struct radeon_device *rdev); | |||
208 | void rs400_gart_disable(struct radeon_device *rdev); | 204 | void rs400_gart_disable(struct radeon_device *rdev); |
209 | void rs400_gart_fini(struct radeon_device *rdev); | 205 | void rs400_gart_fini(struct radeon_device *rdev); |
210 | 206 | ||
211 | |||
212 | /* | 207 | /* |
213 | * rs600. | 208 | * rs600. |
214 | */ | 209 | */ |
@@ -270,8 +265,6 @@ void rv515_fini(struct radeon_device *rdev); | |||
270 | uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg); | 265 | uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg); |
271 | void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); | 266 | void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); |
272 | void rv515_ring_start(struct radeon_device *rdev); | 267 | void rv515_ring_start(struct radeon_device *rdev); |
273 | uint32_t rv515_pcie_rreg(struct radeon_device *rdev, uint32_t reg); | ||
274 | void rv515_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); | ||
275 | void rv515_bandwidth_update(struct radeon_device *rdev); | 268 | void rv515_bandwidth_update(struct radeon_device *rdev); |
276 | int rv515_resume(struct radeon_device *rdev); | 269 | int rv515_resume(struct radeon_device *rdev); |
277 | int rv515_suspend(struct radeon_device *rdev); | 270 | int rv515_suspend(struct radeon_device *rdev); |
@@ -307,14 +300,13 @@ void r600_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); | |||
307 | int r600_cs_parse(struct radeon_cs_parser *p); | 300 | int r600_cs_parse(struct radeon_cs_parser *p); |
308 | void r600_fence_ring_emit(struct radeon_device *rdev, | 301 | void r600_fence_ring_emit(struct radeon_device *rdev, |
309 | struct radeon_fence *fence); | 302 | struct radeon_fence *fence); |
310 | int r600_irq_process(struct radeon_device *rdev); | ||
311 | int r600_irq_set(struct radeon_device *rdev); | ||
312 | bool r600_gpu_is_lockup(struct radeon_device *rdev); | 303 | bool r600_gpu_is_lockup(struct radeon_device *rdev); |
313 | int r600_asic_reset(struct radeon_device *rdev); | 304 | int r600_asic_reset(struct radeon_device *rdev); |
314 | int r600_set_surface_reg(struct radeon_device *rdev, int reg, | 305 | int r600_set_surface_reg(struct radeon_device *rdev, int reg, |
315 | uint32_t tiling_flags, uint32_t pitch, | 306 | uint32_t tiling_flags, uint32_t pitch, |
316 | uint32_t offset, uint32_t obj_size); | 307 | uint32_t offset, uint32_t obj_size); |
317 | void r600_clear_surface_reg(struct radeon_device *rdev, int reg); | 308 | void r600_clear_surface_reg(struct radeon_device *rdev, int reg); |
309 | int r600_ib_test(struct radeon_device *rdev); | ||
318 | void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); | 310 | void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); |
319 | int r600_ring_test(struct radeon_device *rdev); | 311 | int r600_ring_test(struct radeon_device *rdev); |
320 | int r600_copy_blit(struct radeon_device *rdev, | 312 | int r600_copy_blit(struct radeon_device *rdev, |
@@ -333,6 +325,50 @@ extern void rs780_pm_init_profile(struct radeon_device *rdev); | |||
333 | extern void r600_pm_get_dynpm_state(struct radeon_device *rdev); | 325 | extern void r600_pm_get_dynpm_state(struct radeon_device *rdev); |
334 | extern void r600_set_pcie_lanes(struct radeon_device *rdev, int lanes); | 326 | extern void r600_set_pcie_lanes(struct radeon_device *rdev, int lanes); |
335 | extern int r600_get_pcie_lanes(struct radeon_device *rdev); | 327 | extern int r600_get_pcie_lanes(struct radeon_device *rdev); |
328 | bool r600_card_posted(struct radeon_device *rdev); | ||
329 | void r600_cp_stop(struct radeon_device *rdev); | ||
330 | int r600_cp_start(struct radeon_device *rdev); | ||
331 | void r600_ring_init(struct radeon_device *rdev, unsigned ring_size); | ||
332 | int r600_cp_resume(struct radeon_device *rdev); | ||
333 | void r600_cp_fini(struct radeon_device *rdev); | ||
334 | int r600_count_pipe_bits(uint32_t val); | ||
335 | int r600_mc_wait_for_idle(struct radeon_device *rdev); | ||
336 | int r600_pcie_gart_init(struct radeon_device *rdev); | ||
337 | void r600_scratch_init(struct radeon_device *rdev); | ||
338 | int r600_blit_init(struct radeon_device *rdev); | ||
339 | void r600_blit_fini(struct radeon_device *rdev); | ||
340 | int r600_init_microcode(struct radeon_device *rdev); | ||
341 | /* r600 irq */ | ||
342 | int r600_irq_process(struct radeon_device *rdev); | ||
343 | int r600_irq_init(struct radeon_device *rdev); | ||
344 | void r600_irq_fini(struct radeon_device *rdev); | ||
345 | void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size); | ||
346 | int r600_irq_set(struct radeon_device *rdev); | ||
347 | void r600_irq_suspend(struct radeon_device *rdev); | ||
348 | void r600_disable_interrupts(struct radeon_device *rdev); | ||
349 | void r600_rlc_stop(struct radeon_device *rdev); | ||
350 | /* r600 audio */ | ||
351 | int r600_audio_init(struct radeon_device *rdev); | ||
352 | int r600_audio_tmds_index(struct drm_encoder *encoder); | ||
353 | void r600_audio_set_clock(struct drm_encoder *encoder, int clock); | ||
354 | int r600_audio_channels(struct radeon_device *rdev); | ||
355 | int r600_audio_bits_per_sample(struct radeon_device *rdev); | ||
356 | int r600_audio_rate(struct radeon_device *rdev); | ||
357 | uint8_t r600_audio_status_bits(struct radeon_device *rdev); | ||
358 | uint8_t r600_audio_category_code(struct radeon_device *rdev); | ||
359 | void r600_audio_schedule_polling(struct radeon_device *rdev); | ||
360 | void r600_audio_enable_polling(struct drm_encoder *encoder); | ||
361 | void r600_audio_disable_polling(struct drm_encoder *encoder); | ||
362 | void r600_audio_fini(struct radeon_device *rdev); | ||
363 | void r600_hdmi_init(struct drm_encoder *encoder); | ||
364 | int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder); | ||
365 | void r600_hdmi_update_audio_settings(struct drm_encoder *encoder); | ||
366 | /* r600 blit */ | ||
367 | int r600_blit_prepare_copy(struct radeon_device *rdev, int size_bytes); | ||
368 | void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence); | ||
369 | void r600_kms_blit_copy(struct radeon_device *rdev, | ||
370 | u64 src_gpu_addr, u64 dst_gpu_addr, | ||
371 | int size_bytes); | ||
336 | 372 | ||
337 | /* | 373 | /* |
338 | * rv770,rv730,rv710,rv740 | 374 | * rv770,rv730,rv710,rv740 |
@@ -341,12 +377,21 @@ int rv770_init(struct radeon_device *rdev); | |||
341 | void rv770_fini(struct radeon_device *rdev); | 377 | void rv770_fini(struct radeon_device *rdev); |
342 | int rv770_suspend(struct radeon_device *rdev); | 378 | int rv770_suspend(struct radeon_device *rdev); |
343 | int rv770_resume(struct radeon_device *rdev); | 379 | int rv770_resume(struct radeon_device *rdev); |
344 | extern void rv770_pm_misc(struct radeon_device *rdev); | 380 | void rv770_pm_misc(struct radeon_device *rdev); |
345 | extern u32 rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); | 381 | u32 rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); |
382 | void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); | ||
383 | void r700_cp_stop(struct radeon_device *rdev); | ||
384 | void r700_cp_fini(struct radeon_device *rdev); | ||
346 | 385 | ||
347 | /* | 386 | /* |
348 | * evergreen | 387 | * evergreen |
349 | */ | 388 | */ |
389 | struct evergreen_mc_save { | ||
390 | u32 vga_control[6]; | ||
391 | u32 vga_render_control; | ||
392 | u32 vga_hdp_control; | ||
393 | u32 crtc_control[6]; | ||
394 | }; | ||
350 | void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev); | 395 | void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev); |
351 | int evergreen_init(struct radeon_device *rdev); | 396 | int evergreen_init(struct radeon_device *rdev); |
352 | void evergreen_fini(struct radeon_device *rdev); | 397 | void evergreen_fini(struct radeon_device *rdev); |
@@ -374,5 +419,25 @@ extern void evergreen_pm_finish(struct radeon_device *rdev); | |||
374 | extern void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc); | 419 | extern void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc); |
375 | extern u32 evergreen_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); | 420 | extern u32 evergreen_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); |
376 | extern void evergreen_post_page_flip(struct radeon_device *rdev, int crtc); | 421 | extern void evergreen_post_page_flip(struct radeon_device *rdev, int crtc); |
422 | void evergreen_disable_interrupt_state(struct radeon_device *rdev); | ||
423 | int evergreen_blit_init(struct radeon_device *rdev); | ||
424 | void evergreen_blit_fini(struct radeon_device *rdev); | ||
425 | /* evergreen blit */ | ||
426 | int evergreen_blit_prepare_copy(struct radeon_device *rdev, int size_bytes); | ||
427 | void evergreen_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence); | ||
428 | void evergreen_kms_blit_copy(struct radeon_device *rdev, | ||
429 | u64 src_gpu_addr, u64 dst_gpu_addr, | ||
430 | int size_bytes); | ||
431 | |||
432 | /* | ||
433 | * cayman | ||
434 | */ | ||
435 | void cayman_pcie_gart_tlb_flush(struct radeon_device *rdev); | ||
436 | int cayman_init(struct radeon_device *rdev); | ||
437 | void cayman_fini(struct radeon_device *rdev); | ||
438 | int cayman_suspend(struct radeon_device *rdev); | ||
439 | int cayman_resume(struct radeon_device *rdev); | ||
440 | bool cayman_gpu_is_lockup(struct radeon_device *rdev); | ||
441 | int cayman_asic_reset(struct radeon_device *rdev); | ||
377 | 442 | ||
378 | #endif | 443 | #endif |
diff --git a/drivers/gpu/drm/radeon/radeon_benchmark.c b/drivers/gpu/drm/radeon/radeon_benchmark.c index c558685cc63..10191d9372d 100644 --- a/drivers/gpu/drm/radeon/radeon_benchmark.c +++ b/drivers/gpu/drm/radeon/radeon_benchmark.c | |||
@@ -41,7 +41,7 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize, | |||
41 | 41 | ||
42 | size = bsize; | 42 | size = bsize; |
43 | n = 1024; | 43 | n = 1024; |
44 | r = radeon_bo_create(rdev, NULL, size, PAGE_SIZE, true, sdomain, &sobj); | 44 | r = radeon_bo_create(rdev, size, PAGE_SIZE, true, sdomain, &sobj); |
45 | if (r) { | 45 | if (r) { |
46 | goto out_cleanup; | 46 | goto out_cleanup; |
47 | } | 47 | } |
@@ -53,7 +53,7 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize, | |||
53 | if (r) { | 53 | if (r) { |
54 | goto out_cleanup; | 54 | goto out_cleanup; |
55 | } | 55 | } |
56 | r = radeon_bo_create(rdev, NULL, size, PAGE_SIZE, true, ddomain, &dobj); | 56 | r = radeon_bo_create(rdev, size, PAGE_SIZE, true, ddomain, &dobj); |
57 | if (r) { | 57 | if (r) { |
58 | goto out_cleanup; | 58 | goto out_cleanup; |
59 | } | 59 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 22b7e3dc0ec..3f3c9aac46c 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
@@ -972,7 +972,16 @@ static int radeon_dvi_mode_valid(struct drm_connector *connector, | |||
972 | (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) || | 972 | (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) || |
973 | (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_B)) | 973 | (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_B)) |
974 | return MODE_OK; | 974 | return MODE_OK; |
975 | else | 975 | else if (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_A) { |
976 | if (ASIC_IS_DCE3(rdev)) { | ||
977 | /* HDMI 1.3+ supports max clock of 340 Mhz */ | ||
978 | if (mode->clock > 340000) | ||
979 | return MODE_CLOCK_HIGH; | ||
980 | else | ||
981 | return MODE_OK; | ||
982 | } else | ||
983 | return MODE_CLOCK_HIGH; | ||
984 | } else | ||
976 | return MODE_CLOCK_HIGH; | 985 | return MODE_CLOCK_HIGH; |
977 | } | 986 | } |
978 | return MODE_OK; | 987 | return MODE_OK; |
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index eb6b9eed734..3d599e33b9c 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c | |||
@@ -2113,9 +2113,9 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags) | |||
2113 | break; | 2113 | break; |
2114 | } | 2114 | } |
2115 | 2115 | ||
2116 | if (drm_device_is_agp(dev)) | 2116 | if (drm_pci_device_is_agp(dev)) |
2117 | dev_priv->flags |= RADEON_IS_AGP; | 2117 | dev_priv->flags |= RADEON_IS_AGP; |
2118 | else if (drm_device_is_pcie(dev)) | 2118 | else if (drm_pci_device_is_pcie(dev)) |
2119 | dev_priv->flags |= RADEON_IS_PCIE; | 2119 | dev_priv->flags |= RADEON_IS_PCIE; |
2120 | else | 2120 | else |
2121 | dev_priv->flags |= RADEON_IS_PCI; | 2121 | dev_priv->flags |= RADEON_IS_PCI; |
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 35b5eb8fbe2..8c191694187 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c | |||
@@ -75,7 +75,7 @@ int radeon_cs_parser_relocs(struct radeon_cs_parser *p) | |||
75 | return -ENOENT; | 75 | return -ENOENT; |
76 | } | 76 | } |
77 | p->relocs_ptr[i] = &p->relocs[i]; | 77 | p->relocs_ptr[i] = &p->relocs[i]; |
78 | p->relocs[i].robj = p->relocs[i].gobj->driver_private; | 78 | p->relocs[i].robj = gem_to_radeon_bo(p->relocs[i].gobj); |
79 | p->relocs[i].lobj.bo = p->relocs[i].robj; | 79 | p->relocs[i].lobj.bo = p->relocs[i].robj; |
80 | p->relocs[i].lobj.wdomain = r->write_domain; | 80 | p->relocs[i].lobj.wdomain = r->write_domain; |
81 | p->relocs[i].lobj.rdomain = r->read_domains; | 81 | p->relocs[i].lobj.rdomain = r->read_domains; |
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 4954e2d6ffa..f0209be7a34 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
@@ -85,6 +85,7 @@ static const char radeon_family_name[][16] = { | |||
85 | "BARTS", | 85 | "BARTS", |
86 | "TURKS", | 86 | "TURKS", |
87 | "CAICOS", | 87 | "CAICOS", |
88 | "CAYMAN", | ||
88 | "LAST", | 89 | "LAST", |
89 | }; | 90 | }; |
90 | 91 | ||
@@ -184,7 +185,7 @@ int radeon_wb_init(struct radeon_device *rdev) | |||
184 | int r; | 185 | int r; |
185 | 186 | ||
186 | if (rdev->wb.wb_obj == NULL) { | 187 | if (rdev->wb.wb_obj == NULL) { |
187 | r = radeon_bo_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, PAGE_SIZE, true, | 188 | r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE, PAGE_SIZE, true, |
188 | RADEON_GEM_DOMAIN_GTT, &rdev->wb.wb_obj); | 189 | RADEON_GEM_DOMAIN_GTT, &rdev->wb.wb_obj); |
189 | if (r) { | 190 | if (r) { |
190 | dev_warn(rdev->dev, "(%d) create WB bo failed\n", r); | 191 | dev_warn(rdev->dev, "(%d) create WB bo failed\n", r); |
@@ -860,7 +861,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) | |||
860 | if (rfb == NULL || rfb->obj == NULL) { | 861 | if (rfb == NULL || rfb->obj == NULL) { |
861 | continue; | 862 | continue; |
862 | } | 863 | } |
863 | robj = rfb->obj->driver_private; | 864 | robj = gem_to_radeon_bo(rfb->obj); |
864 | /* don't unpin kernel fb objects */ | 865 | /* don't unpin kernel fb objects */ |
865 | if (!radeon_fbdev_robj_is_fb(rdev, robj)) { | 866 | if (!radeon_fbdev_robj_is_fb(rdev, robj)) { |
866 | r = radeon_bo_reserve(robj, false); | 867 | r = radeon_bo_reserve(robj, false); |
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 3e7e7f9eb78..4be58793dc1 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
@@ -371,7 +371,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, | |||
371 | new_radeon_fb = to_radeon_framebuffer(fb); | 371 | new_radeon_fb = to_radeon_framebuffer(fb); |
372 | /* schedule unpin of the old buffer */ | 372 | /* schedule unpin of the old buffer */ |
373 | obj = old_radeon_fb->obj; | 373 | obj = old_radeon_fb->obj; |
374 | rbo = obj->driver_private; | 374 | rbo = gem_to_radeon_bo(obj); |
375 | work->old_rbo = rbo; | 375 | work->old_rbo = rbo; |
376 | INIT_WORK(&work->work, radeon_unpin_work_func); | 376 | INIT_WORK(&work->work, radeon_unpin_work_func); |
377 | 377 | ||
@@ -391,7 +391,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, | |||
391 | 391 | ||
392 | /* pin the new buffer */ | 392 | /* pin the new buffer */ |
393 | obj = new_radeon_fb->obj; | 393 | obj = new_radeon_fb->obj; |
394 | rbo = obj->driver_private; | 394 | rbo = gem_to_radeon_bo(obj); |
395 | 395 | ||
396 | DRM_DEBUG_DRIVER("flip-ioctl() cur_fbo = %p, cur_bbo = %p\n", | 396 | DRM_DEBUG_DRIVER("flip-ioctl() cur_fbo = %p, cur_bbo = %p\n", |
397 | work->old_rbo, rbo); | 397 | work->old_rbo, rbo); |
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 275b26a708d..63d2de8771d 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c | |||
@@ -49,9 +49,10 @@ | |||
49 | * - 2.6.0 - add tiling config query (r6xx+), add initial HiZ support (r300->r500) | 49 | * - 2.6.0 - add tiling config query (r6xx+), add initial HiZ support (r300->r500) |
50 | * 2.7.0 - fixups for r600 2D tiling support. (no external ABI change), add eg dyn gpr regs | 50 | * 2.7.0 - fixups for r600 2D tiling support. (no external ABI change), add eg dyn gpr regs |
51 | * 2.8.0 - pageflip support, r500 US_FORMAT regs. r500 ARGB2101010 colorbuf, r300->r500 CMASK, clock crystal query | 51 | * 2.8.0 - pageflip support, r500 US_FORMAT regs. r500 ARGB2101010 colorbuf, r300->r500 CMASK, clock crystal query |
52 | * 2.9.0 - r600 tiling (s3tc,rgtc) working, SET_PREDICATION packet 3 on r600 + eg, backend query | ||
52 | */ | 53 | */ |
53 | #define KMS_DRIVER_MAJOR 2 | 54 | #define KMS_DRIVER_MAJOR 2 |
54 | #define KMS_DRIVER_MINOR 8 | 55 | #define KMS_DRIVER_MINOR 9 |
55 | #define KMS_DRIVER_PATCHLEVEL 0 | 56 | #define KMS_DRIVER_PATCHLEVEL 0 |
56 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); | 57 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); |
57 | int radeon_driver_unload_kms(struct drm_device *dev); | 58 | int radeon_driver_unload_kms(struct drm_device *dev); |
@@ -84,6 +85,16 @@ extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, | |||
84 | extern struct drm_ioctl_desc radeon_ioctls_kms[]; | 85 | extern struct drm_ioctl_desc radeon_ioctls_kms[]; |
85 | extern int radeon_max_kms_ioctl; | 86 | extern int radeon_max_kms_ioctl; |
86 | int radeon_mmap(struct file *filp, struct vm_area_struct *vma); | 87 | int radeon_mmap(struct file *filp, struct vm_area_struct *vma); |
88 | int radeon_mode_dumb_mmap(struct drm_file *filp, | ||
89 | struct drm_device *dev, | ||
90 | uint32_t handle, uint64_t *offset_p); | ||
91 | int radeon_mode_dumb_create(struct drm_file *file_priv, | ||
92 | struct drm_device *dev, | ||
93 | struct drm_mode_create_dumb *args); | ||
94 | int radeon_mode_dumb_destroy(struct drm_file *file_priv, | ||
95 | struct drm_device *dev, | ||
96 | uint32_t handle); | ||
97 | |||
87 | #if defined(CONFIG_DEBUG_FS) | 98 | #if defined(CONFIG_DEBUG_FS) |
88 | int radeon_debugfs_init(struct drm_minor *minor); | 99 | int radeon_debugfs_init(struct drm_minor *minor); |
89 | void radeon_debugfs_cleanup(struct drm_minor *minor); | 100 | void radeon_debugfs_cleanup(struct drm_minor *minor); |
@@ -228,11 +239,6 @@ static struct drm_driver driver_old = { | |||
228 | .llseek = noop_llseek, | 239 | .llseek = noop_llseek, |
229 | }, | 240 | }, |
230 | 241 | ||
231 | .pci_driver = { | ||
232 | .name = DRIVER_NAME, | ||
233 | .id_table = pciidlist, | ||
234 | }, | ||
235 | |||
236 | .name = DRIVER_NAME, | 242 | .name = DRIVER_NAME, |
237 | .desc = DRIVER_DESC, | 243 | .desc = DRIVER_DESC, |
238 | .date = DRIVER_DATE, | 244 | .date = DRIVER_DATE, |
@@ -322,6 +328,9 @@ static struct drm_driver kms_driver = { | |||
322 | .gem_init_object = radeon_gem_object_init, | 328 | .gem_init_object = radeon_gem_object_init, |
323 | .gem_free_object = radeon_gem_object_free, | 329 | .gem_free_object = radeon_gem_object_free, |
324 | .dma_ioctl = radeon_dma_ioctl_kms, | 330 | .dma_ioctl = radeon_dma_ioctl_kms, |
331 | .dumb_create = radeon_mode_dumb_create, | ||
332 | .dumb_map_offset = radeon_mode_dumb_mmap, | ||
333 | .dumb_destroy = radeon_mode_dumb_destroy, | ||
325 | .fops = { | 334 | .fops = { |
326 | .owner = THIS_MODULE, | 335 | .owner = THIS_MODULE, |
327 | .open = drm_open, | 336 | .open = drm_open, |
@@ -336,15 +345,6 @@ static struct drm_driver kms_driver = { | |||
336 | #endif | 345 | #endif |
337 | }, | 346 | }, |
338 | 347 | ||
339 | .pci_driver = { | ||
340 | .name = DRIVER_NAME, | ||
341 | .id_table = pciidlist, | ||
342 | .probe = radeon_pci_probe, | ||
343 | .remove = radeon_pci_remove, | ||
344 | .suspend = radeon_pci_suspend, | ||
345 | .resume = radeon_pci_resume, | ||
346 | }, | ||
347 | |||
348 | .name = DRIVER_NAME, | 348 | .name = DRIVER_NAME, |
349 | .desc = DRIVER_DESC, | 349 | .desc = DRIVER_DESC, |
350 | .date = DRIVER_DATE, | 350 | .date = DRIVER_DATE, |
@@ -354,15 +354,32 @@ static struct drm_driver kms_driver = { | |||
354 | }; | 354 | }; |
355 | 355 | ||
356 | static struct drm_driver *driver; | 356 | static struct drm_driver *driver; |
357 | static struct pci_driver *pdriver; | ||
358 | |||
359 | static struct pci_driver radeon_pci_driver = { | ||
360 | .name = DRIVER_NAME, | ||
361 | .id_table = pciidlist, | ||
362 | }; | ||
363 | |||
364 | static struct pci_driver radeon_kms_pci_driver = { | ||
365 | .name = DRIVER_NAME, | ||
366 | .id_table = pciidlist, | ||
367 | .probe = radeon_pci_probe, | ||
368 | .remove = radeon_pci_remove, | ||
369 | .suspend = radeon_pci_suspend, | ||
370 | .resume = radeon_pci_resume, | ||
371 | }; | ||
357 | 372 | ||
358 | static int __init radeon_init(void) | 373 | static int __init radeon_init(void) |
359 | { | 374 | { |
360 | driver = &driver_old; | 375 | driver = &driver_old; |
376 | pdriver = &radeon_pci_driver; | ||
361 | driver->num_ioctls = radeon_max_ioctl; | 377 | driver->num_ioctls = radeon_max_ioctl; |
362 | #ifdef CONFIG_VGA_CONSOLE | 378 | #ifdef CONFIG_VGA_CONSOLE |
363 | if (vgacon_text_force() && radeon_modeset == -1) { | 379 | if (vgacon_text_force() && radeon_modeset == -1) { |
364 | DRM_INFO("VGACON disable radeon kernel modesetting.\n"); | 380 | DRM_INFO("VGACON disable radeon kernel modesetting.\n"); |
365 | driver = &driver_old; | 381 | driver = &driver_old; |
382 | pdriver = &radeon_pci_driver; | ||
366 | driver->driver_features &= ~DRIVER_MODESET; | 383 | driver->driver_features &= ~DRIVER_MODESET; |
367 | radeon_modeset = 0; | 384 | radeon_modeset = 0; |
368 | } | 385 | } |
@@ -380,18 +397,19 @@ static int __init radeon_init(void) | |||
380 | if (radeon_modeset == 1) { | 397 | if (radeon_modeset == 1) { |
381 | DRM_INFO("radeon kernel modesetting enabled.\n"); | 398 | DRM_INFO("radeon kernel modesetting enabled.\n"); |
382 | driver = &kms_driver; | 399 | driver = &kms_driver; |
400 | pdriver = &radeon_kms_pci_driver; | ||
383 | driver->driver_features |= DRIVER_MODESET; | 401 | driver->driver_features |= DRIVER_MODESET; |
384 | driver->num_ioctls = radeon_max_kms_ioctl; | 402 | driver->num_ioctls = radeon_max_kms_ioctl; |
385 | radeon_register_atpx_handler(); | 403 | radeon_register_atpx_handler(); |
386 | } | 404 | } |
387 | /* if the vga console setting is enabled still | 405 | /* if the vga console setting is enabled still |
388 | * let modprobe override it */ | 406 | * let modprobe override it */ |
389 | return drm_init(driver); | 407 | return drm_pci_init(driver, pdriver); |
390 | } | 408 | } |
391 | 409 | ||
392 | static void __exit radeon_exit(void) | 410 | static void __exit radeon_exit(void) |
393 | { | 411 | { |
394 | drm_exit(driver); | 412 | drm_pci_exit(driver, pdriver); |
395 | radeon_unregister_atpx_handler(); | 413 | radeon_unregister_atpx_handler(); |
396 | } | 414 | } |
397 | 415 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_family.h b/drivers/gpu/drm/radeon/radeon_family.h index 1ca55eb09ad..6f1d9e563e7 100644 --- a/drivers/gpu/drm/radeon/radeon_family.h +++ b/drivers/gpu/drm/radeon/radeon_family.h | |||
@@ -84,6 +84,7 @@ enum radeon_family { | |||
84 | CHIP_BARTS, | 84 | CHIP_BARTS, |
85 | CHIP_TURKS, | 85 | CHIP_TURKS, |
86 | CHIP_CAICOS, | 86 | CHIP_CAICOS, |
87 | CHIP_CAYMAN, | ||
87 | CHIP_LAST, | 88 | CHIP_LAST, |
88 | }; | 89 | }; |
89 | 90 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index cc44bdfec80..0b7b486c97e 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c | |||
@@ -64,7 +64,7 @@ static struct fb_ops radeonfb_ops = { | |||
64 | }; | 64 | }; |
65 | 65 | ||
66 | 66 | ||
67 | static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled) | 67 | int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled) |
68 | { | 68 | { |
69 | int aligned = width; | 69 | int aligned = width; |
70 | int align_large = (ASIC_IS_AVIVO(rdev)) || tiled; | 70 | int align_large = (ASIC_IS_AVIVO(rdev)) || tiled; |
@@ -90,7 +90,7 @@ static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bo | |||
90 | 90 | ||
91 | static void radeonfb_destroy_pinned_object(struct drm_gem_object *gobj) | 91 | static void radeonfb_destroy_pinned_object(struct drm_gem_object *gobj) |
92 | { | 92 | { |
93 | struct radeon_bo *rbo = gobj->driver_private; | 93 | struct radeon_bo *rbo = gem_to_radeon_bo(gobj); |
94 | int ret; | 94 | int ret; |
95 | 95 | ||
96 | ret = radeon_bo_reserve(rbo, false); | 96 | ret = radeon_bo_reserve(rbo, false); |
@@ -131,7 +131,7 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev, | |||
131 | aligned_size); | 131 | aligned_size); |
132 | return -ENOMEM; | 132 | return -ENOMEM; |
133 | } | 133 | } |
134 | rbo = gobj->driver_private; | 134 | rbo = gem_to_radeon_bo(gobj); |
135 | 135 | ||
136 | if (fb_tiled) | 136 | if (fb_tiled) |
137 | tiling_flags = RADEON_TILING_MACRO; | 137 | tiling_flags = RADEON_TILING_MACRO; |
@@ -205,7 +205,7 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev, | |||
205 | mode_cmd.depth = sizes->surface_depth; | 205 | mode_cmd.depth = sizes->surface_depth; |
206 | 206 | ||
207 | ret = radeonfb_create_pinned_object(rfbdev, &mode_cmd, &gobj); | 207 | ret = radeonfb_create_pinned_object(rfbdev, &mode_cmd, &gobj); |
208 | rbo = gobj->driver_private; | 208 | rbo = gem_to_radeon_bo(gobj); |
209 | 209 | ||
210 | /* okay we have an object now allocate the framebuffer */ | 210 | /* okay we have an object now allocate the framebuffer */ |
211 | info = framebuffer_alloc(0, device); | 211 | info = framebuffer_alloc(0, device); |
@@ -406,14 +406,14 @@ int radeon_fbdev_total_size(struct radeon_device *rdev) | |||
406 | struct radeon_bo *robj; | 406 | struct radeon_bo *robj; |
407 | int size = 0; | 407 | int size = 0; |
408 | 408 | ||
409 | robj = rdev->mode_info.rfbdev->rfb.obj->driver_private; | 409 | robj = gem_to_radeon_bo(rdev->mode_info.rfbdev->rfb.obj); |
410 | size += radeon_bo_size(robj); | 410 | size += radeon_bo_size(robj); |
411 | return size; | 411 | return size; |
412 | } | 412 | } |
413 | 413 | ||
414 | bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj) | 414 | bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj) |
415 | { | 415 | { |
416 | if (robj == rdev->mode_info.rfbdev->rfb.obj->driver_private) | 416 | if (robj == gem_to_radeon_bo(rdev->mode_info.rfbdev->rfb.obj)) |
417 | return true; | 417 | return true; |
418 | return false; | 418 | return false; |
419 | } | 419 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index 65016117d95..f0534ef2f33 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c | |||
@@ -78,7 +78,7 @@ int radeon_gart_table_vram_alloc(struct radeon_device *rdev) | |||
78 | int r; | 78 | int r; |
79 | 79 | ||
80 | if (rdev->gart.table.vram.robj == NULL) { | 80 | if (rdev->gart.table.vram.robj == NULL) { |
81 | r = radeon_bo_create(rdev, NULL, rdev->gart.table_size, | 81 | r = radeon_bo_create(rdev, rdev->gart.table_size, |
82 | PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, | 82 | PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, |
83 | &rdev->gart.table.vram.robj); | 83 | &rdev->gart.table.vram.robj); |
84 | if (r) { | 84 | if (r) { |
@@ -149,8 +149,9 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, | |||
149 | p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); | 149 | p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); |
150 | for (i = 0; i < pages; i++, p++) { | 150 | for (i = 0; i < pages; i++, p++) { |
151 | if (rdev->gart.pages[p]) { | 151 | if (rdev->gart.pages[p]) { |
152 | pci_unmap_page(rdev->pdev, rdev->gart.pages_addr[p], | 152 | if (!rdev->gart.ttm_alloced[p]) |
153 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | 153 | pci_unmap_page(rdev->pdev, rdev->gart.pages_addr[p], |
154 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | ||
154 | rdev->gart.pages[p] = NULL; | 155 | rdev->gart.pages[p] = NULL; |
155 | rdev->gart.pages_addr[p] = rdev->dummy_page.addr; | 156 | rdev->gart.pages_addr[p] = rdev->dummy_page.addr; |
156 | page_base = rdev->gart.pages_addr[p]; | 157 | page_base = rdev->gart.pages_addr[p]; |
@@ -165,7 +166,7 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, | |||
165 | } | 166 | } |
166 | 167 | ||
167 | int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, | 168 | int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, |
168 | int pages, struct page **pagelist) | 169 | int pages, struct page **pagelist, dma_addr_t *dma_addr) |
169 | { | 170 | { |
170 | unsigned t; | 171 | unsigned t; |
171 | unsigned p; | 172 | unsigned p; |
@@ -180,15 +181,22 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, | |||
180 | p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); | 181 | p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); |
181 | 182 | ||
182 | for (i = 0; i < pages; i++, p++) { | 183 | for (i = 0; i < pages; i++, p++) { |
183 | /* we need to support large memory configurations */ | 184 | /* On TTM path, we only use the DMA API if TTM_PAGE_FLAG_DMA32 |
184 | /* assume that unbind have already been call on the range */ | 185 | * is requested. */ |
185 | rdev->gart.pages_addr[p] = pci_map_page(rdev->pdev, pagelist[i], | 186 | if (dma_addr[i] != DMA_ERROR_CODE) { |
187 | rdev->gart.ttm_alloced[p] = true; | ||
188 | rdev->gart.pages_addr[p] = dma_addr[i]; | ||
189 | } else { | ||
190 | /* we need to support large memory configurations */ | ||
191 | /* assume that unbind have already been call on the range */ | ||
192 | rdev->gart.pages_addr[p] = pci_map_page(rdev->pdev, pagelist[i], | ||
186 | 0, PAGE_SIZE, | 193 | 0, PAGE_SIZE, |
187 | PCI_DMA_BIDIRECTIONAL); | 194 | PCI_DMA_BIDIRECTIONAL); |
188 | if (pci_dma_mapping_error(rdev->pdev, rdev->gart.pages_addr[p])) { | 195 | if (pci_dma_mapping_error(rdev->pdev, rdev->gart.pages_addr[p])) { |
189 | /* FIXME: failed to map page (return -ENOMEM?) */ | 196 | /* FIXME: failed to map page (return -ENOMEM?) */ |
190 | radeon_gart_unbind(rdev, offset, pages); | 197 | radeon_gart_unbind(rdev, offset, pages); |
191 | return -ENOMEM; | 198 | return -ENOMEM; |
199 | } | ||
192 | } | 200 | } |
193 | rdev->gart.pages[p] = pagelist[i]; | 201 | rdev->gart.pages[p] = pagelist[i]; |
194 | page_base = rdev->gart.pages_addr[p]; | 202 | page_base = rdev->gart.pages_addr[p]; |
@@ -251,6 +259,12 @@ int radeon_gart_init(struct radeon_device *rdev) | |||
251 | radeon_gart_fini(rdev); | 259 | radeon_gart_fini(rdev); |
252 | return -ENOMEM; | 260 | return -ENOMEM; |
253 | } | 261 | } |
262 | rdev->gart.ttm_alloced = kzalloc(sizeof(bool) * | ||
263 | rdev->gart.num_cpu_pages, GFP_KERNEL); | ||
264 | if (rdev->gart.ttm_alloced == NULL) { | ||
265 | radeon_gart_fini(rdev); | ||
266 | return -ENOMEM; | ||
267 | } | ||
254 | /* set GART entry to point to the dummy page by default */ | 268 | /* set GART entry to point to the dummy page by default */ |
255 | for (i = 0; i < rdev->gart.num_cpu_pages; i++) { | 269 | for (i = 0; i < rdev->gart.num_cpu_pages; i++) { |
256 | rdev->gart.pages_addr[i] = rdev->dummy_page.addr; | 270 | rdev->gart.pages_addr[i] = rdev->dummy_page.addr; |
@@ -267,6 +281,8 @@ void radeon_gart_fini(struct radeon_device *rdev) | |||
267 | rdev->gart.ready = false; | 281 | rdev->gart.ready = false; |
268 | kfree(rdev->gart.pages); | 282 | kfree(rdev->gart.pages); |
269 | kfree(rdev->gart.pages_addr); | 283 | kfree(rdev->gart.pages_addr); |
284 | kfree(rdev->gart.ttm_alloced); | ||
270 | rdev->gart.pages = NULL; | 285 | rdev->gart.pages = NULL; |
271 | rdev->gart.pages_addr = NULL; | 286 | rdev->gart.pages_addr = NULL; |
287 | rdev->gart.ttm_alloced = NULL; | ||
272 | } | 288 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index 1fe95dfe48c..723cd19cd22 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c | |||
@@ -32,21 +32,18 @@ | |||
32 | 32 | ||
33 | int radeon_gem_object_init(struct drm_gem_object *obj) | 33 | int radeon_gem_object_init(struct drm_gem_object *obj) |
34 | { | 34 | { |
35 | /* we do nothings here */ | 35 | BUG(); |
36 | |||
36 | return 0; | 37 | return 0; |
37 | } | 38 | } |
38 | 39 | ||
39 | void radeon_gem_object_free(struct drm_gem_object *gobj) | 40 | void radeon_gem_object_free(struct drm_gem_object *gobj) |
40 | { | 41 | { |
41 | struct radeon_bo *robj = gobj->driver_private; | 42 | struct radeon_bo *robj = gem_to_radeon_bo(gobj); |
42 | 43 | ||
43 | gobj->driver_private = NULL; | ||
44 | if (robj) { | 44 | if (robj) { |
45 | radeon_bo_unref(&robj); | 45 | radeon_bo_unref(&robj); |
46 | } | 46 | } |
47 | |||
48 | drm_gem_object_release(gobj); | ||
49 | kfree(gobj); | ||
50 | } | 47 | } |
51 | 48 | ||
52 | int radeon_gem_object_create(struct radeon_device *rdev, int size, | 49 | int radeon_gem_object_create(struct radeon_device *rdev, int size, |
@@ -54,36 +51,34 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size, | |||
54 | bool discardable, bool kernel, | 51 | bool discardable, bool kernel, |
55 | struct drm_gem_object **obj) | 52 | struct drm_gem_object **obj) |
56 | { | 53 | { |
57 | struct drm_gem_object *gobj; | ||
58 | struct radeon_bo *robj; | 54 | struct radeon_bo *robj; |
59 | int r; | 55 | int r; |
60 | 56 | ||
61 | *obj = NULL; | 57 | *obj = NULL; |
62 | gobj = drm_gem_object_alloc(rdev->ddev, size); | ||
63 | if (!gobj) { | ||
64 | return -ENOMEM; | ||
65 | } | ||
66 | /* At least align on page size */ | 58 | /* At least align on page size */ |
67 | if (alignment < PAGE_SIZE) { | 59 | if (alignment < PAGE_SIZE) { |
68 | alignment = PAGE_SIZE; | 60 | alignment = PAGE_SIZE; |
69 | } | 61 | } |
70 | r = radeon_bo_create(rdev, gobj, size, alignment, kernel, initial_domain, &robj); | 62 | r = radeon_bo_create(rdev, size, alignment, kernel, initial_domain, &robj); |
71 | if (r) { | 63 | if (r) { |
72 | if (r != -ERESTARTSYS) | 64 | if (r != -ERESTARTSYS) |
73 | DRM_ERROR("Failed to allocate GEM object (%d, %d, %u, %d)\n", | 65 | DRM_ERROR("Failed to allocate GEM object (%d, %d, %u, %d)\n", |
74 | size, initial_domain, alignment, r); | 66 | size, initial_domain, alignment, r); |
75 | drm_gem_object_unreference_unlocked(gobj); | ||
76 | return r; | 67 | return r; |
77 | } | 68 | } |
78 | gobj->driver_private = robj; | 69 | *obj = &robj->gem_base; |
79 | *obj = gobj; | 70 | |
71 | mutex_lock(&rdev->gem.mutex); | ||
72 | list_add_tail(&robj->list, &rdev->gem.objects); | ||
73 | mutex_unlock(&rdev->gem.mutex); | ||
74 | |||
80 | return 0; | 75 | return 0; |
81 | } | 76 | } |
82 | 77 | ||
83 | int radeon_gem_object_pin(struct drm_gem_object *obj, uint32_t pin_domain, | 78 | int radeon_gem_object_pin(struct drm_gem_object *obj, uint32_t pin_domain, |
84 | uint64_t *gpu_addr) | 79 | uint64_t *gpu_addr) |
85 | { | 80 | { |
86 | struct radeon_bo *robj = obj->driver_private; | 81 | struct radeon_bo *robj = gem_to_radeon_bo(obj); |
87 | int r; | 82 | int r; |
88 | 83 | ||
89 | r = radeon_bo_reserve(robj, false); | 84 | r = radeon_bo_reserve(robj, false); |
@@ -96,7 +91,7 @@ int radeon_gem_object_pin(struct drm_gem_object *obj, uint32_t pin_domain, | |||
96 | 91 | ||
97 | void radeon_gem_object_unpin(struct drm_gem_object *obj) | 92 | void radeon_gem_object_unpin(struct drm_gem_object *obj) |
98 | { | 93 | { |
99 | struct radeon_bo *robj = obj->driver_private; | 94 | struct radeon_bo *robj = gem_to_radeon_bo(obj); |
100 | int r; | 95 | int r; |
101 | 96 | ||
102 | r = radeon_bo_reserve(robj, false); | 97 | r = radeon_bo_reserve(robj, false); |
@@ -114,7 +109,7 @@ int radeon_gem_set_domain(struct drm_gem_object *gobj, | |||
114 | int r; | 109 | int r; |
115 | 110 | ||
116 | /* FIXME: reeimplement */ | 111 | /* FIXME: reeimplement */ |
117 | robj = gobj->driver_private; | 112 | robj = gem_to_radeon_bo(gobj); |
118 | /* work out where to validate the buffer to */ | 113 | /* work out where to validate the buffer to */ |
119 | domain = wdomain; | 114 | domain = wdomain; |
120 | if (!domain) { | 115 | if (!domain) { |
@@ -231,7 +226,7 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, | |||
231 | if (gobj == NULL) { | 226 | if (gobj == NULL) { |
232 | return -ENOENT; | 227 | return -ENOENT; |
233 | } | 228 | } |
234 | robj = gobj->driver_private; | 229 | robj = gem_to_radeon_bo(gobj); |
235 | 230 | ||
236 | r = radeon_gem_set_domain(gobj, args->read_domains, args->write_domain); | 231 | r = radeon_gem_set_domain(gobj, args->read_domains, args->write_domain); |
237 | 232 | ||
@@ -239,23 +234,31 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, | |||
239 | return r; | 234 | return r; |
240 | } | 235 | } |
241 | 236 | ||
242 | int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data, | 237 | int radeon_mode_dumb_mmap(struct drm_file *filp, |
243 | struct drm_file *filp) | 238 | struct drm_device *dev, |
239 | uint32_t handle, uint64_t *offset_p) | ||
244 | { | 240 | { |
245 | struct drm_radeon_gem_mmap *args = data; | ||
246 | struct drm_gem_object *gobj; | 241 | struct drm_gem_object *gobj; |
247 | struct radeon_bo *robj; | 242 | struct radeon_bo *robj; |
248 | 243 | ||
249 | gobj = drm_gem_object_lookup(dev, filp, args->handle); | 244 | gobj = drm_gem_object_lookup(dev, filp, handle); |
250 | if (gobj == NULL) { | 245 | if (gobj == NULL) { |
251 | return -ENOENT; | 246 | return -ENOENT; |
252 | } | 247 | } |
253 | robj = gobj->driver_private; | 248 | robj = gem_to_radeon_bo(gobj); |
254 | args->addr_ptr = radeon_bo_mmap_offset(robj); | 249 | *offset_p = radeon_bo_mmap_offset(robj); |
255 | drm_gem_object_unreference_unlocked(gobj); | 250 | drm_gem_object_unreference_unlocked(gobj); |
256 | return 0; | 251 | return 0; |
257 | } | 252 | } |
258 | 253 | ||
254 | int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data, | ||
255 | struct drm_file *filp) | ||
256 | { | ||
257 | struct drm_radeon_gem_mmap *args = data; | ||
258 | |||
259 | return radeon_mode_dumb_mmap(filp, dev, args->handle, &args->addr_ptr); | ||
260 | } | ||
261 | |||
259 | int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, | 262 | int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, |
260 | struct drm_file *filp) | 263 | struct drm_file *filp) |
261 | { | 264 | { |
@@ -269,7 +272,7 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
269 | if (gobj == NULL) { | 272 | if (gobj == NULL) { |
270 | return -ENOENT; | 273 | return -ENOENT; |
271 | } | 274 | } |
272 | robj = gobj->driver_private; | 275 | robj = gem_to_radeon_bo(gobj); |
273 | r = radeon_bo_wait(robj, &cur_placement, true); | 276 | r = radeon_bo_wait(robj, &cur_placement, true); |
274 | switch (cur_placement) { | 277 | switch (cur_placement) { |
275 | case TTM_PL_VRAM: | 278 | case TTM_PL_VRAM: |
@@ -299,7 +302,7 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, | |||
299 | if (gobj == NULL) { | 302 | if (gobj == NULL) { |
300 | return -ENOENT; | 303 | return -ENOENT; |
301 | } | 304 | } |
302 | robj = gobj->driver_private; | 305 | robj = gem_to_radeon_bo(gobj); |
303 | r = radeon_bo_wait(robj, NULL, false); | 306 | r = radeon_bo_wait(robj, NULL, false); |
304 | /* callback hw specific functions if any */ | 307 | /* callback hw specific functions if any */ |
305 | if (robj->rdev->asic->ioctl_wait_idle) | 308 | if (robj->rdev->asic->ioctl_wait_idle) |
@@ -320,7 +323,7 @@ int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data, | |||
320 | gobj = drm_gem_object_lookup(dev, filp, args->handle); | 323 | gobj = drm_gem_object_lookup(dev, filp, args->handle); |
321 | if (gobj == NULL) | 324 | if (gobj == NULL) |
322 | return -ENOENT; | 325 | return -ENOENT; |
323 | robj = gobj->driver_private; | 326 | robj = gem_to_radeon_bo(gobj); |
324 | r = radeon_bo_set_tiling_flags(robj, args->tiling_flags, args->pitch); | 327 | r = radeon_bo_set_tiling_flags(robj, args->tiling_flags, args->pitch); |
325 | drm_gem_object_unreference_unlocked(gobj); | 328 | drm_gem_object_unreference_unlocked(gobj); |
326 | return r; | 329 | return r; |
@@ -338,7 +341,7 @@ int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data, | |||
338 | gobj = drm_gem_object_lookup(dev, filp, args->handle); | 341 | gobj = drm_gem_object_lookup(dev, filp, args->handle); |
339 | if (gobj == NULL) | 342 | if (gobj == NULL) |
340 | return -ENOENT; | 343 | return -ENOENT; |
341 | rbo = gobj->driver_private; | 344 | rbo = gem_to_radeon_bo(gobj); |
342 | r = radeon_bo_reserve(rbo, false); | 345 | r = radeon_bo_reserve(rbo, false); |
343 | if (unlikely(r != 0)) | 346 | if (unlikely(r != 0)) |
344 | goto out; | 347 | goto out; |
@@ -348,3 +351,38 @@ out: | |||
348 | drm_gem_object_unreference_unlocked(gobj); | 351 | drm_gem_object_unreference_unlocked(gobj); |
349 | return r; | 352 | return r; |
350 | } | 353 | } |
354 | |||
355 | int radeon_mode_dumb_create(struct drm_file *file_priv, | ||
356 | struct drm_device *dev, | ||
357 | struct drm_mode_create_dumb *args) | ||
358 | { | ||
359 | struct radeon_device *rdev = dev->dev_private; | ||
360 | struct drm_gem_object *gobj; | ||
361 | int r; | ||
362 | |||
363 | args->pitch = radeon_align_pitch(rdev, args->width, args->bpp, 0) * ((args->bpp + 1) / 8); | ||
364 | args->size = args->pitch * args->height; | ||
365 | args->size = ALIGN(args->size, PAGE_SIZE); | ||
366 | |||
367 | r = radeon_gem_object_create(rdev, args->size, 0, | ||
368 | RADEON_GEM_DOMAIN_VRAM, | ||
369 | false, ttm_bo_type_device, | ||
370 | &gobj); | ||
371 | if (r) | ||
372 | return -ENOMEM; | ||
373 | |||
374 | r = drm_gem_handle_create(file_priv, gobj, &args->handle); | ||
375 | if (r) { | ||
376 | drm_gem_object_unreference_unlocked(gobj); | ||
377 | return r; | ||
378 | } | ||
379 | drm_gem_object_handle_unreference_unlocked(gobj); | ||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | int radeon_mode_dumb_destroy(struct drm_file *file_priv, | ||
384 | struct drm_device *dev, | ||
385 | uint32_t handle) | ||
386 | { | ||
387 | return drm_gem_handle_delete(file_priv, handle); | ||
388 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 8387d32caaa..bf7d4c06145 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c | |||
@@ -58,9 +58,9 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) | |||
58 | dev->dev_private = (void *)rdev; | 58 | dev->dev_private = (void *)rdev; |
59 | 59 | ||
60 | /* update BUS flag */ | 60 | /* update BUS flag */ |
61 | if (drm_device_is_agp(dev)) { | 61 | if (drm_pci_device_is_agp(dev)) { |
62 | flags |= RADEON_IS_AGP; | 62 | flags |= RADEON_IS_AGP; |
63 | } else if (drm_device_is_pcie(dev)) { | 63 | } else if (drm_pci_device_is_pcie(dev)) { |
64 | flags |= RADEON_IS_PCIE; | 64 | flags |= RADEON_IS_PCIE; |
65 | } else { | 65 | } else { |
66 | flags |= RADEON_IS_PCI; | 66 | flags |= RADEON_IS_PCI; |
@@ -169,7 +169,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
169 | value = rdev->accel_working; | 169 | value = rdev->accel_working; |
170 | break; | 170 | break; |
171 | case RADEON_INFO_TILING_CONFIG: | 171 | case RADEON_INFO_TILING_CONFIG: |
172 | if (rdev->family >= CHIP_CEDAR) | 172 | if (rdev->family >= CHIP_CAYMAN) |
173 | value = rdev->config.cayman.tile_config; | ||
174 | else if (rdev->family >= CHIP_CEDAR) | ||
173 | value = rdev->config.evergreen.tile_config; | 175 | value = rdev->config.evergreen.tile_config; |
174 | else if (rdev->family >= CHIP_RV770) | 176 | else if (rdev->family >= CHIP_RV770) |
175 | value = rdev->config.rv770.tile_config; | 177 | value = rdev->config.rv770.tile_config; |
@@ -205,6 +207,20 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
205 | /* return clock value in KHz */ | 207 | /* return clock value in KHz */ |
206 | value = rdev->clock.spll.reference_freq * 10; | 208 | value = rdev->clock.spll.reference_freq * 10; |
207 | break; | 209 | break; |
210 | case RADEON_INFO_NUM_BACKENDS: | ||
211 | if (rdev->family >= CHIP_CAYMAN) | ||
212 | value = rdev->config.cayman.max_backends_per_se * | ||
213 | rdev->config.cayman.max_shader_engines; | ||
214 | else if (rdev->family >= CHIP_CEDAR) | ||
215 | value = rdev->config.evergreen.max_backends; | ||
216 | else if (rdev->family >= CHIP_RV770) | ||
217 | value = rdev->config.rv770.max_backends; | ||
218 | else if (rdev->family >= CHIP_R600) | ||
219 | value = rdev->config.r600.max_backends; | ||
220 | else { | ||
221 | return -EINVAL; | ||
222 | } | ||
223 | break; | ||
208 | default: | 224 | default: |
209 | DRM_DEBUG_KMS("Invalid request %d\n", info->request); | 225 | DRM_DEBUG_KMS("Invalid request %d\n", info->request); |
210 | return -EINVAL; | 226 | return -EINVAL; |
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 78968b738e8..66c9af1b3d9 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c | |||
@@ -415,7 +415,7 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc, | |||
415 | 415 | ||
416 | /* Pin framebuffer & get tilling informations */ | 416 | /* Pin framebuffer & get tilling informations */ |
417 | obj = radeon_fb->obj; | 417 | obj = radeon_fb->obj; |
418 | rbo = obj->driver_private; | 418 | rbo = gem_to_radeon_bo(obj); |
419 | r = radeon_bo_reserve(rbo, false); | 419 | r = radeon_bo_reserve(rbo, false); |
420 | if (unlikely(r != 0)) | 420 | if (unlikely(r != 0)) |
421 | return r; | 421 | return r; |
@@ -521,7 +521,7 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc, | |||
521 | 521 | ||
522 | if (!atomic && fb && fb != crtc->fb) { | 522 | if (!atomic && fb && fb != crtc->fb) { |
523 | radeon_fb = to_radeon_framebuffer(fb); | 523 | radeon_fb = to_radeon_framebuffer(fb); |
524 | rbo = radeon_fb->obj->driver_private; | 524 | rbo = gem_to_radeon_bo(radeon_fb->obj); |
525 | r = radeon_bo_reserve(rbo, false); | 525 | r = radeon_bo_reserve(rbo, false); |
526 | if (unlikely(r != 0)) | 526 | if (unlikely(r != 0)) |
527 | return r; | 527 | return r; |
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index a670caaee29..5067d18d000 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
@@ -676,4 +676,5 @@ void radeon_fb_output_poll_changed(struct radeon_device *rdev); | |||
676 | 676 | ||
677 | void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id); | 677 | void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id); |
678 | 678 | ||
679 | int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled); | ||
679 | #endif | 680 | #endif |
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 7d6b8e88f74..976c3b1b1b6 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c | |||
@@ -55,6 +55,7 @@ static void radeon_ttm_bo_destroy(struct ttm_buffer_object *tbo) | |||
55 | list_del_init(&bo->list); | 55 | list_del_init(&bo->list); |
56 | mutex_unlock(&bo->rdev->gem.mutex); | 56 | mutex_unlock(&bo->rdev->gem.mutex); |
57 | radeon_bo_clear_surface_reg(bo); | 57 | radeon_bo_clear_surface_reg(bo); |
58 | drm_gem_object_release(&bo->gem_base); | ||
58 | kfree(bo); | 59 | kfree(bo); |
59 | } | 60 | } |
60 | 61 | ||
@@ -86,7 +87,7 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) | |||
86 | rbo->placement.num_busy_placement = c; | 87 | rbo->placement.num_busy_placement = c; |
87 | } | 88 | } |
88 | 89 | ||
89 | int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj, | 90 | int radeon_bo_create(struct radeon_device *rdev, |
90 | unsigned long size, int byte_align, bool kernel, u32 domain, | 91 | unsigned long size, int byte_align, bool kernel, u32 domain, |
91 | struct radeon_bo **bo_ptr) | 92 | struct radeon_bo **bo_ptr) |
92 | { | 93 | { |
@@ -96,6 +97,8 @@ int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj, | |||
96 | unsigned long max_size = 0; | 97 | unsigned long max_size = 0; |
97 | int r; | 98 | int r; |
98 | 99 | ||
100 | size = ALIGN(size, PAGE_SIZE); | ||
101 | |||
99 | if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) { | 102 | if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) { |
100 | rdev->mman.bdev.dev_mapping = rdev->ddev->dev_mapping; | 103 | rdev->mman.bdev.dev_mapping = rdev->ddev->dev_mapping; |
101 | } | 104 | } |
@@ -118,8 +121,13 @@ retry: | |||
118 | bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL); | 121 | bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL); |
119 | if (bo == NULL) | 122 | if (bo == NULL) |
120 | return -ENOMEM; | 123 | return -ENOMEM; |
124 | r = drm_gem_object_init(rdev->ddev, &bo->gem_base, size); | ||
125 | if (unlikely(r)) { | ||
126 | kfree(bo); | ||
127 | return r; | ||
128 | } | ||
121 | bo->rdev = rdev; | 129 | bo->rdev = rdev; |
122 | bo->gobj = gobj; | 130 | bo->gem_base.driver_private = NULL; |
123 | bo->surface_reg = -1; | 131 | bo->surface_reg = -1; |
124 | INIT_LIST_HEAD(&bo->list); | 132 | INIT_LIST_HEAD(&bo->list); |
125 | radeon_ttm_placement_from_domain(bo, domain); | 133 | radeon_ttm_placement_from_domain(bo, domain); |
@@ -142,12 +150,9 @@ retry: | |||
142 | return r; | 150 | return r; |
143 | } | 151 | } |
144 | *bo_ptr = bo; | 152 | *bo_ptr = bo; |
145 | if (gobj) { | 153 | |
146 | mutex_lock(&bo->rdev->gem.mutex); | ||
147 | list_add_tail(&bo->list, &rdev->gem.objects); | ||
148 | mutex_unlock(&bo->rdev->gem.mutex); | ||
149 | } | ||
150 | trace_radeon_bo_create(bo); | 154 | trace_radeon_bo_create(bo); |
155 | |||
151 | return 0; | 156 | return 0; |
152 | } | 157 | } |
153 | 158 | ||
@@ -260,7 +265,6 @@ int radeon_bo_evict_vram(struct radeon_device *rdev) | |||
260 | void radeon_bo_force_delete(struct radeon_device *rdev) | 265 | void radeon_bo_force_delete(struct radeon_device *rdev) |
261 | { | 266 | { |
262 | struct radeon_bo *bo, *n; | 267 | struct radeon_bo *bo, *n; |
263 | struct drm_gem_object *gobj; | ||
264 | 268 | ||
265 | if (list_empty(&rdev->gem.objects)) { | 269 | if (list_empty(&rdev->gem.objects)) { |
266 | return; | 270 | return; |
@@ -268,16 +272,14 @@ void radeon_bo_force_delete(struct radeon_device *rdev) | |||
268 | dev_err(rdev->dev, "Userspace still has active objects !\n"); | 272 | dev_err(rdev->dev, "Userspace still has active objects !\n"); |
269 | list_for_each_entry_safe(bo, n, &rdev->gem.objects, list) { | 273 | list_for_each_entry_safe(bo, n, &rdev->gem.objects, list) { |
270 | mutex_lock(&rdev->ddev->struct_mutex); | 274 | mutex_lock(&rdev->ddev->struct_mutex); |
271 | gobj = bo->gobj; | ||
272 | dev_err(rdev->dev, "%p %p %lu %lu force free\n", | 275 | dev_err(rdev->dev, "%p %p %lu %lu force free\n", |
273 | gobj, bo, (unsigned long)gobj->size, | 276 | &bo->gem_base, bo, (unsigned long)bo->gem_base.size, |
274 | *((unsigned long *)&gobj->refcount)); | 277 | *((unsigned long *)&bo->gem_base.refcount)); |
275 | mutex_lock(&bo->rdev->gem.mutex); | 278 | mutex_lock(&bo->rdev->gem.mutex); |
276 | list_del_init(&bo->list); | 279 | list_del_init(&bo->list); |
277 | mutex_unlock(&bo->rdev->gem.mutex); | 280 | mutex_unlock(&bo->rdev->gem.mutex); |
278 | radeon_bo_unref(&bo); | 281 | /* this should unref the ttm bo */ |
279 | gobj->driver_private = NULL; | 282 | drm_gem_object_unreference(&bo->gem_base); |
280 | drm_gem_object_unreference(gobj); | ||
281 | mutex_unlock(&rdev->ddev->struct_mutex); | 283 | mutex_unlock(&rdev->ddev->struct_mutex); |
282 | } | 284 | } |
283 | } | 285 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h index 22d4c237dea..7f8e778dba4 100644 --- a/drivers/gpu/drm/radeon/radeon_object.h +++ b/drivers/gpu/drm/radeon/radeon_object.h | |||
@@ -137,10 +137,9 @@ static inline int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type, | |||
137 | } | 137 | } |
138 | 138 | ||
139 | extern int radeon_bo_create(struct radeon_device *rdev, | 139 | extern int radeon_bo_create(struct radeon_device *rdev, |
140 | struct drm_gem_object *gobj, unsigned long size, | 140 | unsigned long size, int byte_align, |
141 | int byte_align, | 141 | bool kernel, u32 domain, |
142 | bool kernel, u32 domain, | 142 | struct radeon_bo **bo_ptr); |
143 | struct radeon_bo **bo_ptr); | ||
144 | extern int radeon_bo_kmap(struct radeon_bo *bo, void **ptr); | 143 | extern int radeon_bo_kmap(struct radeon_bo *bo, void **ptr); |
145 | extern void radeon_bo_kunmap(struct radeon_bo *bo); | 144 | extern void radeon_bo_kunmap(struct radeon_bo *bo); |
146 | extern void radeon_bo_unref(struct radeon_bo **bo); | 145 | extern void radeon_bo_unref(struct radeon_bo **bo); |
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index 06e79822a2b..992d99d13fc 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c | |||
@@ -175,7 +175,7 @@ int radeon_ib_pool_init(struct radeon_device *rdev) | |||
175 | return 0; | 175 | return 0; |
176 | INIT_LIST_HEAD(&rdev->ib_pool.bogus_ib); | 176 | INIT_LIST_HEAD(&rdev->ib_pool.bogus_ib); |
177 | /* Allocate 1M object buffer */ | 177 | /* Allocate 1M object buffer */ |
178 | r = radeon_bo_create(rdev, NULL, RADEON_IB_POOL_SIZE*64*1024, | 178 | r = radeon_bo_create(rdev, RADEON_IB_POOL_SIZE*64*1024, |
179 | PAGE_SIZE, true, RADEON_GEM_DOMAIN_GTT, | 179 | PAGE_SIZE, true, RADEON_GEM_DOMAIN_GTT, |
180 | &rdev->ib_pool.robj); | 180 | &rdev->ib_pool.robj); |
181 | if (r) { | 181 | if (r) { |
@@ -332,7 +332,7 @@ int radeon_ring_init(struct radeon_device *rdev, unsigned ring_size) | |||
332 | rdev->cp.ring_size = ring_size; | 332 | rdev->cp.ring_size = ring_size; |
333 | /* Allocate ring buffer */ | 333 | /* Allocate ring buffer */ |
334 | if (rdev->cp.ring_obj == NULL) { | 334 | if (rdev->cp.ring_obj == NULL) { |
335 | r = radeon_bo_create(rdev, NULL, rdev->cp.ring_size, PAGE_SIZE, true, | 335 | r = radeon_bo_create(rdev, rdev->cp.ring_size, PAGE_SIZE, true, |
336 | RADEON_GEM_DOMAIN_GTT, | 336 | RADEON_GEM_DOMAIN_GTT, |
337 | &rdev->cp.ring_obj); | 337 | &rdev->cp.ring_obj); |
338 | if (r) { | 338 | if (r) { |
diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c index 5b44f652145..dee4a0c1b4b 100644 --- a/drivers/gpu/drm/radeon/radeon_test.c +++ b/drivers/gpu/drm/radeon/radeon_test.c | |||
@@ -52,7 +52,7 @@ void radeon_test_moves(struct radeon_device *rdev) | |||
52 | goto out_cleanup; | 52 | goto out_cleanup; |
53 | } | 53 | } |
54 | 54 | ||
55 | r = radeon_bo_create(rdev, NULL, size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, | 55 | r = radeon_bo_create(rdev, size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, |
56 | &vram_obj); | 56 | &vram_obj); |
57 | if (r) { | 57 | if (r) { |
58 | DRM_ERROR("Failed to create VRAM object\n"); | 58 | DRM_ERROR("Failed to create VRAM object\n"); |
@@ -71,7 +71,7 @@ void radeon_test_moves(struct radeon_device *rdev) | |||
71 | void **gtt_start, **gtt_end; | 71 | void **gtt_start, **gtt_end; |
72 | void **vram_start, **vram_end; | 72 | void **vram_start, **vram_end; |
73 | 73 | ||
74 | r = radeon_bo_create(rdev, NULL, size, PAGE_SIZE, true, | 74 | r = radeon_bo_create(rdev, size, PAGE_SIZE, true, |
75 | RADEON_GEM_DOMAIN_GTT, gtt_obj + i); | 75 | RADEON_GEM_DOMAIN_GTT, gtt_obj + i); |
76 | if (r) { | 76 | if (r) { |
77 | DRM_ERROR("Failed to create GTT object %d\n", i); | 77 | DRM_ERROR("Failed to create GTT object %d\n", i); |
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 8389b4c63d1..60125ddba1e 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c | |||
@@ -529,7 +529,7 @@ int radeon_ttm_init(struct radeon_device *rdev) | |||
529 | DRM_ERROR("Failed initializing VRAM heap.\n"); | 529 | DRM_ERROR("Failed initializing VRAM heap.\n"); |
530 | return r; | 530 | return r; |
531 | } | 531 | } |
532 | r = radeon_bo_create(rdev, NULL, 256 * 1024, PAGE_SIZE, true, | 532 | r = radeon_bo_create(rdev, 256 * 1024, PAGE_SIZE, true, |
533 | RADEON_GEM_DOMAIN_VRAM, | 533 | RADEON_GEM_DOMAIN_VRAM, |
534 | &rdev->stollen_vga_memory); | 534 | &rdev->stollen_vga_memory); |
535 | if (r) { | 535 | if (r) { |
@@ -661,6 +661,7 @@ struct radeon_ttm_backend { | |||
661 | unsigned long num_pages; | 661 | unsigned long num_pages; |
662 | struct page **pages; | 662 | struct page **pages; |
663 | struct page *dummy_read_page; | 663 | struct page *dummy_read_page; |
664 | dma_addr_t *dma_addrs; | ||
664 | bool populated; | 665 | bool populated; |
665 | bool bound; | 666 | bool bound; |
666 | unsigned offset; | 667 | unsigned offset; |
@@ -669,12 +670,14 @@ struct radeon_ttm_backend { | |||
669 | static int radeon_ttm_backend_populate(struct ttm_backend *backend, | 670 | static int radeon_ttm_backend_populate(struct ttm_backend *backend, |
670 | unsigned long num_pages, | 671 | unsigned long num_pages, |
671 | struct page **pages, | 672 | struct page **pages, |
672 | struct page *dummy_read_page) | 673 | struct page *dummy_read_page, |
674 | dma_addr_t *dma_addrs) | ||
673 | { | 675 | { |
674 | struct radeon_ttm_backend *gtt; | 676 | struct radeon_ttm_backend *gtt; |
675 | 677 | ||
676 | gtt = container_of(backend, struct radeon_ttm_backend, backend); | 678 | gtt = container_of(backend, struct radeon_ttm_backend, backend); |
677 | gtt->pages = pages; | 679 | gtt->pages = pages; |
680 | gtt->dma_addrs = dma_addrs; | ||
678 | gtt->num_pages = num_pages; | 681 | gtt->num_pages = num_pages; |
679 | gtt->dummy_read_page = dummy_read_page; | 682 | gtt->dummy_read_page = dummy_read_page; |
680 | gtt->populated = true; | 683 | gtt->populated = true; |
@@ -687,6 +690,7 @@ static void radeon_ttm_backend_clear(struct ttm_backend *backend) | |||
687 | 690 | ||
688 | gtt = container_of(backend, struct radeon_ttm_backend, backend); | 691 | gtt = container_of(backend, struct radeon_ttm_backend, backend); |
689 | gtt->pages = NULL; | 692 | gtt->pages = NULL; |
693 | gtt->dma_addrs = NULL; | ||
690 | gtt->num_pages = 0; | 694 | gtt->num_pages = 0; |
691 | gtt->dummy_read_page = NULL; | 695 | gtt->dummy_read_page = NULL; |
692 | gtt->populated = false; | 696 | gtt->populated = false; |
@@ -707,7 +711,7 @@ static int radeon_ttm_backend_bind(struct ttm_backend *backend, | |||
707 | gtt->num_pages, bo_mem, backend); | 711 | gtt->num_pages, bo_mem, backend); |
708 | } | 712 | } |
709 | r = radeon_gart_bind(gtt->rdev, gtt->offset, | 713 | r = radeon_gart_bind(gtt->rdev, gtt->offset, |
710 | gtt->num_pages, gtt->pages); | 714 | gtt->num_pages, gtt->pages, gtt->dma_addrs); |
711 | if (r) { | 715 | if (r) { |
712 | DRM_ERROR("failed to bind %lu pages at 0x%08X\n", | 716 | DRM_ERROR("failed to bind %lu pages at 0x%08X\n", |
713 | gtt->num_pages, gtt->offset); | 717 | gtt->num_pages, gtt->offset); |
diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman new file mode 100644 index 00000000000..6334f8ac120 --- /dev/null +++ b/drivers/gpu/drm/radeon/reg_srcs/cayman | |||
@@ -0,0 +1,619 @@ | |||
1 | cayman 0x9400 | ||
2 | 0x0000802C GRBM_GFX_INDEX | ||
3 | 0x000088B0 VGT_VTX_VECT_EJECT_REG | ||
4 | 0x000088C4 VGT_CACHE_INVALIDATION | ||
5 | 0x000088D4 VGT_GS_VERTEX_REUSE | ||
6 | 0x00008958 VGT_PRIMITIVE_TYPE | ||
7 | 0x0000895C VGT_INDEX_TYPE | ||
8 | 0x00008970 VGT_NUM_INDICES | ||
9 | 0x00008974 VGT_NUM_INSTANCES | ||
10 | 0x00008990 VGT_COMPUTE_DIM_X | ||
11 | 0x00008994 VGT_COMPUTE_DIM_Y | ||
12 | 0x00008998 VGT_COMPUTE_DIM_Z | ||
13 | 0x0000899C VGT_COMPUTE_START_X | ||
14 | 0x000089A0 VGT_COMPUTE_START_Y | ||
15 | 0x000089A4 VGT_COMPUTE_START_Z | ||
16 | 0x000089A8 VGT_COMPUTE_INDEX | ||
17 | 0x000089AC VGT_COMPUTE_THREAD_GOURP_SIZE | ||
18 | 0x000089B0 VGT_HS_OFFCHIP_PARAM | ||
19 | 0x00008A14 PA_CL_ENHANCE | ||
20 | 0x00008A60 PA_SC_LINE_STIPPLE_VALUE | ||
21 | 0x00008B10 PA_SC_LINE_STIPPLE_STATE | ||
22 | 0x00008BF0 PA_SC_ENHANCE | ||
23 | 0x00008D8C SQ_DYN_GPR_CNTL_PS_FLUSH_REQ | ||
24 | 0x00008D94 SQ_DYN_GPR_SIMD_LOCK_EN | ||
25 | 0x00008C00 SQ_CONFIG | ||
26 | 0x00008C04 SQ_GPR_RESOURCE_MGMT_1 | ||
27 | 0x00008C10 SQ_GLOBAL_GPR_RESOURCE_MGMT_1 | ||
28 | 0x00008C14 SQ_GLOBAL_GPR_RESOURCE_MGMT_2 | ||
29 | 0x00008DF8 SQ_CONST_MEM_BASE | ||
30 | 0x00008E20 SQ_STATIC_THREAD_MGMT_1 | ||
31 | 0x00008E24 SQ_STATIC_THREAD_MGMT_2 | ||
32 | 0x00008E28 SQ_STATIC_THREAD_MGMT_3 | ||
33 | 0x00008E48 SQ_EX_ALLOC_TABLE_SLOTS | ||
34 | 0x00009100 SPI_CONFIG_CNTL | ||
35 | 0x0000913C SPI_CONFIG_CNTL_1 | ||
36 | 0x00009830 DB_DEBUG | ||
37 | 0x00009834 DB_DEBUG2 | ||
38 | 0x00009838 DB_DEBUG3 | ||
39 | 0x0000983C DB_DEBUG4 | ||
40 | 0x00009854 DB_WATERMARKS | ||
41 | 0x0000A400 TD_PS_BORDER_COLOR_INDEX | ||
42 | 0x0000A404 TD_PS_BORDER_COLOR_RED | ||
43 | 0x0000A408 TD_PS_BORDER_COLOR_GREEN | ||
44 | 0x0000A40C TD_PS_BORDER_COLOR_BLUE | ||
45 | 0x0000A410 TD_PS_BORDER_COLOR_ALPHA | ||
46 | 0x0000A414 TD_VS_BORDER_COLOR_INDEX | ||
47 | 0x0000A418 TD_VS_BORDER_COLOR_RED | ||
48 | 0x0000A41C TD_VS_BORDER_COLOR_GREEN | ||
49 | 0x0000A420 TD_VS_BORDER_COLOR_BLUE | ||
50 | 0x0000A424 TD_VS_BORDER_COLOR_ALPHA | ||
51 | 0x0000A428 TD_GS_BORDER_COLOR_INDEX | ||
52 | 0x0000A42C TD_GS_BORDER_COLOR_RED | ||
53 | 0x0000A430 TD_GS_BORDER_COLOR_GREEN | ||
54 | 0x0000A434 TD_GS_BORDER_COLOR_BLUE | ||
55 | 0x0000A438 TD_GS_BORDER_COLOR_ALPHA | ||
56 | 0x0000A43C TD_HS_BORDER_COLOR_INDEX | ||
57 | 0x0000A440 TD_HS_BORDER_COLOR_RED | ||
58 | 0x0000A444 TD_HS_BORDER_COLOR_GREEN | ||
59 | 0x0000A448 TD_HS_BORDER_COLOR_BLUE | ||
60 | 0x0000A44C TD_HS_BORDER_COLOR_ALPHA | ||
61 | 0x0000A450 TD_LS_BORDER_COLOR_INDEX | ||
62 | 0x0000A454 TD_LS_BORDER_COLOR_RED | ||
63 | 0x0000A458 TD_LS_BORDER_COLOR_GREEN | ||
64 | 0x0000A45C TD_LS_BORDER_COLOR_BLUE | ||
65 | 0x0000A460 TD_LS_BORDER_COLOR_ALPHA | ||
66 | 0x0000A464 TD_CS_BORDER_COLOR_INDEX | ||
67 | 0x0000A468 TD_CS_BORDER_COLOR_RED | ||
68 | 0x0000A46C TD_CS_BORDER_COLOR_GREEN | ||
69 | 0x0000A470 TD_CS_BORDER_COLOR_BLUE | ||
70 | 0x0000A474 TD_CS_BORDER_COLOR_ALPHA | ||
71 | 0x00028000 DB_RENDER_CONTROL | ||
72 | 0x00028004 DB_COUNT_CONTROL | ||
73 | 0x0002800C DB_RENDER_OVERRIDE | ||
74 | 0x00028010 DB_RENDER_OVERRIDE2 | ||
75 | 0x00028028 DB_STENCIL_CLEAR | ||
76 | 0x0002802C DB_DEPTH_CLEAR | ||
77 | 0x00028030 PA_SC_SCREEN_SCISSOR_TL | ||
78 | 0x00028034 PA_SC_SCREEN_SCISSOR_BR | ||
79 | 0x0002805C DB_DEPTH_SLICE | ||
80 | 0x00028140 SQ_ALU_CONST_BUFFER_SIZE_PS_0 | ||
81 | 0x00028144 SQ_ALU_CONST_BUFFER_SIZE_PS_1 | ||
82 | 0x00028148 SQ_ALU_CONST_BUFFER_SIZE_PS_2 | ||
83 | 0x0002814C SQ_ALU_CONST_BUFFER_SIZE_PS_3 | ||
84 | 0x00028150 SQ_ALU_CONST_BUFFER_SIZE_PS_4 | ||
85 | 0x00028154 SQ_ALU_CONST_BUFFER_SIZE_PS_5 | ||
86 | 0x00028158 SQ_ALU_CONST_BUFFER_SIZE_PS_6 | ||
87 | 0x0002815C SQ_ALU_CONST_BUFFER_SIZE_PS_7 | ||
88 | 0x00028160 SQ_ALU_CONST_BUFFER_SIZE_PS_8 | ||
89 | 0x00028164 SQ_ALU_CONST_BUFFER_SIZE_PS_9 | ||
90 | 0x00028168 SQ_ALU_CONST_BUFFER_SIZE_PS_10 | ||
91 | 0x0002816C SQ_ALU_CONST_BUFFER_SIZE_PS_11 | ||
92 | 0x00028170 SQ_ALU_CONST_BUFFER_SIZE_PS_12 | ||
93 | 0x00028174 SQ_ALU_CONST_BUFFER_SIZE_PS_13 | ||
94 | 0x00028178 SQ_ALU_CONST_BUFFER_SIZE_PS_14 | ||
95 | 0x0002817C SQ_ALU_CONST_BUFFER_SIZE_PS_15 | ||
96 | 0x00028180 SQ_ALU_CONST_BUFFER_SIZE_VS_0 | ||
97 | 0x00028184 SQ_ALU_CONST_BUFFER_SIZE_VS_1 | ||
98 | 0x00028188 SQ_ALU_CONST_BUFFER_SIZE_VS_2 | ||
99 | 0x0002818C SQ_ALU_CONST_BUFFER_SIZE_VS_3 | ||
100 | 0x00028190 SQ_ALU_CONST_BUFFER_SIZE_VS_4 | ||
101 | 0x00028194 SQ_ALU_CONST_BUFFER_SIZE_VS_5 | ||
102 | 0x00028198 SQ_ALU_CONST_BUFFER_SIZE_VS_6 | ||
103 | 0x0002819C SQ_ALU_CONST_BUFFER_SIZE_VS_7 | ||
104 | 0x000281A0 SQ_ALU_CONST_BUFFER_SIZE_VS_8 | ||
105 | 0x000281A4 SQ_ALU_CONST_BUFFER_SIZE_VS_9 | ||
106 | 0x000281A8 SQ_ALU_CONST_BUFFER_SIZE_VS_10 | ||
107 | 0x000281AC SQ_ALU_CONST_BUFFER_SIZE_VS_11 | ||
108 | 0x000281B0 SQ_ALU_CONST_BUFFER_SIZE_VS_12 | ||
109 | 0x000281B4 SQ_ALU_CONST_BUFFER_SIZE_VS_13 | ||
110 | 0x000281B8 SQ_ALU_CONST_BUFFER_SIZE_VS_14 | ||
111 | 0x000281BC SQ_ALU_CONST_BUFFER_SIZE_VS_15 | ||
112 | 0x000281C0 SQ_ALU_CONST_BUFFER_SIZE_GS_0 | ||
113 | 0x000281C4 SQ_ALU_CONST_BUFFER_SIZE_GS_1 | ||
114 | 0x000281C8 SQ_ALU_CONST_BUFFER_SIZE_GS_2 | ||
115 | 0x000281CC SQ_ALU_CONST_BUFFER_SIZE_GS_3 | ||
116 | 0x000281D0 SQ_ALU_CONST_BUFFER_SIZE_GS_4 | ||
117 | 0x000281D4 SQ_ALU_CONST_BUFFER_SIZE_GS_5 | ||
118 | 0x000281D8 SQ_ALU_CONST_BUFFER_SIZE_GS_6 | ||
119 | 0x000281DC SQ_ALU_CONST_BUFFER_SIZE_GS_7 | ||
120 | 0x000281E0 SQ_ALU_CONST_BUFFER_SIZE_GS_8 | ||
121 | 0x000281E4 SQ_ALU_CONST_BUFFER_SIZE_GS_9 | ||
122 | 0x000281E8 SQ_ALU_CONST_BUFFER_SIZE_GS_10 | ||
123 | 0x000281EC SQ_ALU_CONST_BUFFER_SIZE_GS_11 | ||
124 | 0x000281F0 SQ_ALU_CONST_BUFFER_SIZE_GS_12 | ||
125 | 0x000281F4 SQ_ALU_CONST_BUFFER_SIZE_GS_13 | ||
126 | 0x000281F8 SQ_ALU_CONST_BUFFER_SIZE_GS_14 | ||
127 | 0x000281FC SQ_ALU_CONST_BUFFER_SIZE_GS_15 | ||
128 | 0x00028200 PA_SC_WINDOW_OFFSET | ||
129 | 0x00028204 PA_SC_WINDOW_SCISSOR_TL | ||
130 | 0x00028208 PA_SC_WINDOW_SCISSOR_BR | ||
131 | 0x0002820C PA_SC_CLIPRECT_RULE | ||
132 | 0x00028210 PA_SC_CLIPRECT_0_TL | ||
133 | 0x00028214 PA_SC_CLIPRECT_0_BR | ||
134 | 0x00028218 PA_SC_CLIPRECT_1_TL | ||
135 | 0x0002821C PA_SC_CLIPRECT_1_BR | ||
136 | 0x00028220 PA_SC_CLIPRECT_2_TL | ||
137 | 0x00028224 PA_SC_CLIPRECT_2_BR | ||
138 | 0x00028228 PA_SC_CLIPRECT_3_TL | ||
139 | 0x0002822C PA_SC_CLIPRECT_3_BR | ||
140 | 0x00028230 PA_SC_EDGERULE | ||
141 | 0x00028234 PA_SU_HARDWARE_SCREEN_OFFSET | ||
142 | 0x00028240 PA_SC_GENERIC_SCISSOR_TL | ||
143 | 0x00028244 PA_SC_GENERIC_SCISSOR_BR | ||
144 | 0x00028250 PA_SC_VPORT_SCISSOR_0_TL | ||
145 | 0x00028254 PA_SC_VPORT_SCISSOR_0_BR | ||
146 | 0x00028258 PA_SC_VPORT_SCISSOR_1_TL | ||
147 | 0x0002825C PA_SC_VPORT_SCISSOR_1_BR | ||
148 | 0x00028260 PA_SC_VPORT_SCISSOR_2_TL | ||
149 | 0x00028264 PA_SC_VPORT_SCISSOR_2_BR | ||
150 | 0x00028268 PA_SC_VPORT_SCISSOR_3_TL | ||
151 | 0x0002826C PA_SC_VPORT_SCISSOR_3_BR | ||
152 | 0x00028270 PA_SC_VPORT_SCISSOR_4_TL | ||
153 | 0x00028274 PA_SC_VPORT_SCISSOR_4_BR | ||
154 | 0x00028278 PA_SC_VPORT_SCISSOR_5_TL | ||
155 | 0x0002827C PA_SC_VPORT_SCISSOR_5_BR | ||
156 | 0x00028280 PA_SC_VPORT_SCISSOR_6_TL | ||
157 | 0x00028284 PA_SC_VPORT_SCISSOR_6_BR | ||
158 | 0x00028288 PA_SC_VPORT_SCISSOR_7_TL | ||
159 | 0x0002828C PA_SC_VPORT_SCISSOR_7_BR | ||
160 | 0x00028290 PA_SC_VPORT_SCISSOR_8_TL | ||
161 | 0x00028294 PA_SC_VPORT_SCISSOR_8_BR | ||
162 | 0x00028298 PA_SC_VPORT_SCISSOR_9_TL | ||
163 | 0x0002829C PA_SC_VPORT_SCISSOR_9_BR | ||
164 | 0x000282A0 PA_SC_VPORT_SCISSOR_10_TL | ||
165 | 0x000282A4 PA_SC_VPORT_SCISSOR_10_BR | ||
166 | 0x000282A8 PA_SC_VPORT_SCISSOR_11_TL | ||
167 | 0x000282AC PA_SC_VPORT_SCISSOR_11_BR | ||
168 | 0x000282B0 PA_SC_VPORT_SCISSOR_12_TL | ||
169 | 0x000282B4 PA_SC_VPORT_SCISSOR_12_BR | ||
170 | 0x000282B8 PA_SC_VPORT_SCISSOR_13_TL | ||
171 | 0x000282BC PA_SC_VPORT_SCISSOR_13_BR | ||
172 | 0x000282C0 PA_SC_VPORT_SCISSOR_14_TL | ||
173 | 0x000282C4 PA_SC_VPORT_SCISSOR_14_BR | ||
174 | 0x000282C8 PA_SC_VPORT_SCISSOR_15_TL | ||
175 | 0x000282CC PA_SC_VPORT_SCISSOR_15_BR | ||
176 | 0x000282D0 PA_SC_VPORT_ZMIN_0 | ||
177 | 0x000282D4 PA_SC_VPORT_ZMAX_0 | ||
178 | 0x000282D8 PA_SC_VPORT_ZMIN_1 | ||
179 | 0x000282DC PA_SC_VPORT_ZMAX_1 | ||
180 | 0x000282E0 PA_SC_VPORT_ZMIN_2 | ||
181 | 0x000282E4 PA_SC_VPORT_ZMAX_2 | ||
182 | 0x000282E8 PA_SC_VPORT_ZMIN_3 | ||
183 | 0x000282EC PA_SC_VPORT_ZMAX_3 | ||
184 | 0x000282F0 PA_SC_VPORT_ZMIN_4 | ||
185 | 0x000282F4 PA_SC_VPORT_ZMAX_4 | ||
186 | 0x000282F8 PA_SC_VPORT_ZMIN_5 | ||
187 | 0x000282FC PA_SC_VPORT_ZMAX_5 | ||
188 | 0x00028300 PA_SC_VPORT_ZMIN_6 | ||
189 | 0x00028304 PA_SC_VPORT_ZMAX_6 | ||
190 | 0x00028308 PA_SC_VPORT_ZMIN_7 | ||
191 | 0x0002830C PA_SC_VPORT_ZMAX_7 | ||
192 | 0x00028310 PA_SC_VPORT_ZMIN_8 | ||
193 | 0x00028314 PA_SC_VPORT_ZMAX_8 | ||
194 | 0x00028318 PA_SC_VPORT_ZMIN_9 | ||
195 | 0x0002831C PA_SC_VPORT_ZMAX_9 | ||
196 | 0x00028320 PA_SC_VPORT_ZMIN_10 | ||
197 | 0x00028324 PA_SC_VPORT_ZMAX_10 | ||
198 | 0x00028328 PA_SC_VPORT_ZMIN_11 | ||
199 | 0x0002832C PA_SC_VPORT_ZMAX_11 | ||
200 | 0x00028330 PA_SC_VPORT_ZMIN_12 | ||
201 | 0x00028334 PA_SC_VPORT_ZMAX_12 | ||
202 | 0x00028338 PA_SC_VPORT_ZMIN_13 | ||
203 | 0x0002833C PA_SC_VPORT_ZMAX_13 | ||
204 | 0x00028340 PA_SC_VPORT_ZMIN_14 | ||
205 | 0x00028344 PA_SC_VPORT_ZMAX_14 | ||
206 | 0x00028348 PA_SC_VPORT_ZMIN_15 | ||
207 | 0x0002834C PA_SC_VPORT_ZMAX_15 | ||
208 | 0x00028350 SX_MISC | ||
209 | 0x00028354 SX_SURFACE_SYNC | ||
210 | 0x00028380 SQ_VTX_SEMANTIC_0 | ||
211 | 0x00028384 SQ_VTX_SEMANTIC_1 | ||
212 | 0x00028388 SQ_VTX_SEMANTIC_2 | ||
213 | 0x0002838C SQ_VTX_SEMANTIC_3 | ||
214 | 0x00028390 SQ_VTX_SEMANTIC_4 | ||
215 | 0x00028394 SQ_VTX_SEMANTIC_5 | ||
216 | 0x00028398 SQ_VTX_SEMANTIC_6 | ||
217 | 0x0002839C SQ_VTX_SEMANTIC_7 | ||
218 | 0x000283A0 SQ_VTX_SEMANTIC_8 | ||
219 | 0x000283A4 SQ_VTX_SEMANTIC_9 | ||
220 | 0x000283A8 SQ_VTX_SEMANTIC_10 | ||
221 | 0x000283AC SQ_VTX_SEMANTIC_11 | ||
222 | 0x000283B0 SQ_VTX_SEMANTIC_12 | ||
223 | 0x000283B4 SQ_VTX_SEMANTIC_13 | ||
224 | 0x000283B8 SQ_VTX_SEMANTIC_14 | ||
225 | 0x000283BC SQ_VTX_SEMANTIC_15 | ||
226 | 0x000283C0 SQ_VTX_SEMANTIC_16 | ||
227 | 0x000283C4 SQ_VTX_SEMANTIC_17 | ||
228 | 0x000283C8 SQ_VTX_SEMANTIC_18 | ||
229 | 0x000283CC SQ_VTX_SEMANTIC_19 | ||
230 | 0x000283D0 SQ_VTX_SEMANTIC_20 | ||
231 | 0x000283D4 SQ_VTX_SEMANTIC_21 | ||
232 | 0x000283D8 SQ_VTX_SEMANTIC_22 | ||
233 | 0x000283DC SQ_VTX_SEMANTIC_23 | ||
234 | 0x000283E0 SQ_VTX_SEMANTIC_24 | ||
235 | 0x000283E4 SQ_VTX_SEMANTIC_25 | ||
236 | 0x000283E8 SQ_VTX_SEMANTIC_26 | ||
237 | 0x000283EC SQ_VTX_SEMANTIC_27 | ||
238 | 0x000283F0 SQ_VTX_SEMANTIC_28 | ||
239 | 0x000283F4 SQ_VTX_SEMANTIC_29 | ||
240 | 0x000283F8 SQ_VTX_SEMANTIC_30 | ||
241 | 0x000283FC SQ_VTX_SEMANTIC_31 | ||
242 | 0x00028400 VGT_MAX_VTX_INDX | ||
243 | 0x00028404 VGT_MIN_VTX_INDX | ||
244 | 0x00028408 VGT_INDX_OFFSET | ||
245 | 0x0002840C VGT_MULTI_PRIM_IB_RESET_INDX | ||
246 | 0x00028410 SX_ALPHA_TEST_CONTROL | ||
247 | 0x00028414 CB_BLEND_RED | ||
248 | 0x00028418 CB_BLEND_GREEN | ||
249 | 0x0002841C CB_BLEND_BLUE | ||
250 | 0x00028420 CB_BLEND_ALPHA | ||
251 | 0x00028430 DB_STENCILREFMASK | ||
252 | 0x00028434 DB_STENCILREFMASK_BF | ||
253 | 0x00028438 SX_ALPHA_REF | ||
254 | 0x0002843C PA_CL_VPORT_XSCALE_0 | ||
255 | 0x00028440 PA_CL_VPORT_XOFFSET_0 | ||
256 | 0x00028444 PA_CL_VPORT_YSCALE_0 | ||
257 | 0x00028448 PA_CL_VPORT_YOFFSET_0 | ||
258 | 0x0002844C PA_CL_VPORT_ZSCALE_0 | ||
259 | 0x00028450 PA_CL_VPORT_ZOFFSET_0 | ||
260 | 0x00028454 PA_CL_VPORT_XSCALE_1 | ||
261 | 0x00028458 PA_CL_VPORT_XOFFSET_1 | ||
262 | 0x0002845C PA_CL_VPORT_YSCALE_1 | ||
263 | 0x00028460 PA_CL_VPORT_YOFFSET_1 | ||
264 | 0x00028464 PA_CL_VPORT_ZSCALE_1 | ||
265 | 0x00028468 PA_CL_VPORT_ZOFFSET_1 | ||
266 | 0x0002846C PA_CL_VPORT_XSCALE_2 | ||
267 | 0x00028470 PA_CL_VPORT_XOFFSET_2 | ||
268 | 0x00028474 PA_CL_VPORT_YSCALE_2 | ||
269 | 0x00028478 PA_CL_VPORT_YOFFSET_2 | ||
270 | 0x0002847C PA_CL_VPORT_ZSCALE_2 | ||
271 | 0x00028480 PA_CL_VPORT_ZOFFSET_2 | ||
272 | 0x00028484 PA_CL_VPORT_XSCALE_3 | ||
273 | 0x00028488 PA_CL_VPORT_XOFFSET_3 | ||
274 | 0x0002848C PA_CL_VPORT_YSCALE_3 | ||
275 | 0x00028490 PA_CL_VPORT_YOFFSET_3 | ||
276 | 0x00028494 PA_CL_VPORT_ZSCALE_3 | ||
277 | 0x00028498 PA_CL_VPORT_ZOFFSET_3 | ||
278 | 0x0002849C PA_CL_VPORT_XSCALE_4 | ||
279 | 0x000284A0 PA_CL_VPORT_XOFFSET_4 | ||
280 | 0x000284A4 PA_CL_VPORT_YSCALE_4 | ||
281 | 0x000284A8 PA_CL_VPORT_YOFFSET_4 | ||
282 | 0x000284AC PA_CL_VPORT_ZSCALE_4 | ||
283 | 0x000284B0 PA_CL_VPORT_ZOFFSET_4 | ||
284 | 0x000284B4 PA_CL_VPORT_XSCALE_5 | ||
285 | 0x000284B8 PA_CL_VPORT_XOFFSET_5 | ||
286 | 0x000284BC PA_CL_VPORT_YSCALE_5 | ||
287 | 0x000284C0 PA_CL_VPORT_YOFFSET_5 | ||
288 | 0x000284C4 PA_CL_VPORT_ZSCALE_5 | ||
289 | 0x000284C8 PA_CL_VPORT_ZOFFSET_5 | ||
290 | 0x000284CC PA_CL_VPORT_XSCALE_6 | ||
291 | 0x000284D0 PA_CL_VPORT_XOFFSET_6 | ||
292 | 0x000284D4 PA_CL_VPORT_YSCALE_6 | ||
293 | 0x000284D8 PA_CL_VPORT_YOFFSET_6 | ||
294 | 0x000284DC PA_CL_VPORT_ZSCALE_6 | ||
295 | 0x000284E0 PA_CL_VPORT_ZOFFSET_6 | ||
296 | 0x000284E4 PA_CL_VPORT_XSCALE_7 | ||
297 | 0x000284E8 PA_CL_VPORT_XOFFSET_7 | ||
298 | 0x000284EC PA_CL_VPORT_YSCALE_7 | ||
299 | 0x000284F0 PA_CL_VPORT_YOFFSET_7 | ||
300 | 0x000284F4 PA_CL_VPORT_ZSCALE_7 | ||
301 | 0x000284F8 PA_CL_VPORT_ZOFFSET_7 | ||
302 | 0x000284FC PA_CL_VPORT_XSCALE_8 | ||
303 | 0x00028500 PA_CL_VPORT_XOFFSET_8 | ||
304 | 0x00028504 PA_CL_VPORT_YSCALE_8 | ||
305 | 0x00028508 PA_CL_VPORT_YOFFSET_8 | ||
306 | 0x0002850C PA_CL_VPORT_ZSCALE_8 | ||
307 | 0x00028510 PA_CL_VPORT_ZOFFSET_8 | ||
308 | 0x00028514 PA_CL_VPORT_XSCALE_9 | ||
309 | 0x00028518 PA_CL_VPORT_XOFFSET_9 | ||
310 | 0x0002851C PA_CL_VPORT_YSCALE_9 | ||
311 | 0x00028520 PA_CL_VPORT_YOFFSET_9 | ||
312 | 0x00028524 PA_CL_VPORT_ZSCALE_9 | ||
313 | 0x00028528 PA_CL_VPORT_ZOFFSET_9 | ||
314 | 0x0002852C PA_CL_VPORT_XSCALE_10 | ||
315 | 0x00028530 PA_CL_VPORT_XOFFSET_10 | ||
316 | 0x00028534 PA_CL_VPORT_YSCALE_10 | ||
317 | 0x00028538 PA_CL_VPORT_YOFFSET_10 | ||
318 | 0x0002853C PA_CL_VPORT_ZSCALE_10 | ||
319 | 0x00028540 PA_CL_VPORT_ZOFFSET_10 | ||
320 | 0x00028544 PA_CL_VPORT_XSCALE_11 | ||
321 | 0x00028548 PA_CL_VPORT_XOFFSET_11 | ||
322 | 0x0002854C PA_CL_VPORT_YSCALE_11 | ||
323 | 0x00028550 PA_CL_VPORT_YOFFSET_11 | ||
324 | 0x00028554 PA_CL_VPORT_ZSCALE_11 | ||
325 | 0x00028558 PA_CL_VPORT_ZOFFSET_11 | ||
326 | 0x0002855C PA_CL_VPORT_XSCALE_12 | ||
327 | 0x00028560 PA_CL_VPORT_XOFFSET_12 | ||
328 | 0x00028564 PA_CL_VPORT_YSCALE_12 | ||
329 | 0x00028568 PA_CL_VPORT_YOFFSET_12 | ||
330 | 0x0002856C PA_CL_VPORT_ZSCALE_12 | ||
331 | 0x00028570 PA_CL_VPORT_ZOFFSET_12 | ||
332 | 0x00028574 PA_CL_VPORT_XSCALE_13 | ||
333 | 0x00028578 PA_CL_VPORT_XOFFSET_13 | ||
334 | 0x0002857C PA_CL_VPORT_YSCALE_13 | ||
335 | 0x00028580 PA_CL_VPORT_YOFFSET_13 | ||
336 | 0x00028584 PA_CL_VPORT_ZSCALE_13 | ||
337 | 0x00028588 PA_CL_VPORT_ZOFFSET_13 | ||
338 | 0x0002858C PA_CL_VPORT_XSCALE_14 | ||
339 | 0x00028590 PA_CL_VPORT_XOFFSET_14 | ||
340 | 0x00028594 PA_CL_VPORT_YSCALE_14 | ||
341 | 0x00028598 PA_CL_VPORT_YOFFSET_14 | ||
342 | 0x0002859C PA_CL_VPORT_ZSCALE_14 | ||
343 | 0x000285A0 PA_CL_VPORT_ZOFFSET_14 | ||
344 | 0x000285A4 PA_CL_VPORT_XSCALE_15 | ||
345 | 0x000285A8 PA_CL_VPORT_XOFFSET_15 | ||
346 | 0x000285AC PA_CL_VPORT_YSCALE_15 | ||
347 | 0x000285B0 PA_CL_VPORT_YOFFSET_15 | ||
348 | 0x000285B4 PA_CL_VPORT_ZSCALE_15 | ||
349 | 0x000285B8 PA_CL_VPORT_ZOFFSET_15 | ||
350 | 0x000285BC PA_CL_UCP_0_X | ||
351 | 0x000285C0 PA_CL_UCP_0_Y | ||
352 | 0x000285C4 PA_CL_UCP_0_Z | ||
353 | 0x000285C8 PA_CL_UCP_0_W | ||
354 | 0x000285CC PA_CL_UCP_1_X | ||
355 | 0x000285D0 PA_CL_UCP_1_Y | ||
356 | 0x000285D4 PA_CL_UCP_1_Z | ||
357 | 0x000285D8 PA_CL_UCP_1_W | ||
358 | 0x000285DC PA_CL_UCP_2_X | ||
359 | 0x000285E0 PA_CL_UCP_2_Y | ||
360 | 0x000285E4 PA_CL_UCP_2_Z | ||
361 | 0x000285E8 PA_CL_UCP_2_W | ||
362 | 0x000285EC PA_CL_UCP_3_X | ||
363 | 0x000285F0 PA_CL_UCP_3_Y | ||
364 | 0x000285F4 PA_CL_UCP_3_Z | ||
365 | 0x000285F8 PA_CL_UCP_3_W | ||
366 | 0x000285FC PA_CL_UCP_4_X | ||
367 | 0x00028600 PA_CL_UCP_4_Y | ||
368 | 0x00028604 PA_CL_UCP_4_Z | ||
369 | 0x00028608 PA_CL_UCP_4_W | ||
370 | 0x0002860C PA_CL_UCP_5_X | ||
371 | 0x00028610 PA_CL_UCP_5_Y | ||
372 | 0x00028614 PA_CL_UCP_5_Z | ||
373 | 0x00028618 PA_CL_UCP_5_W | ||
374 | 0x0002861C SPI_VS_OUT_ID_0 | ||
375 | 0x00028620 SPI_VS_OUT_ID_1 | ||
376 | 0x00028624 SPI_VS_OUT_ID_2 | ||
377 | 0x00028628 SPI_VS_OUT_ID_3 | ||
378 | 0x0002862C SPI_VS_OUT_ID_4 | ||
379 | 0x00028630 SPI_VS_OUT_ID_5 | ||
380 | 0x00028634 SPI_VS_OUT_ID_6 | ||
381 | 0x00028638 SPI_VS_OUT_ID_7 | ||
382 | 0x0002863C SPI_VS_OUT_ID_8 | ||
383 | 0x00028640 SPI_VS_OUT_ID_9 | ||
384 | 0x00028644 SPI_PS_INPUT_CNTL_0 | ||
385 | 0x00028648 SPI_PS_INPUT_CNTL_1 | ||
386 | 0x0002864C SPI_PS_INPUT_CNTL_2 | ||
387 | 0x00028650 SPI_PS_INPUT_CNTL_3 | ||
388 | 0x00028654 SPI_PS_INPUT_CNTL_4 | ||
389 | 0x00028658 SPI_PS_INPUT_CNTL_5 | ||
390 | 0x0002865C SPI_PS_INPUT_CNTL_6 | ||
391 | 0x00028660 SPI_PS_INPUT_CNTL_7 | ||
392 | 0x00028664 SPI_PS_INPUT_CNTL_8 | ||
393 | 0x00028668 SPI_PS_INPUT_CNTL_9 | ||
394 | 0x0002866C SPI_PS_INPUT_CNTL_10 | ||
395 | 0x00028670 SPI_PS_INPUT_CNTL_11 | ||
396 | 0x00028674 SPI_PS_INPUT_CNTL_12 | ||
397 | 0x00028678 SPI_PS_INPUT_CNTL_13 | ||
398 | 0x0002867C SPI_PS_INPUT_CNTL_14 | ||
399 | 0x00028680 SPI_PS_INPUT_CNTL_15 | ||
400 | 0x00028684 SPI_PS_INPUT_CNTL_16 | ||
401 | 0x00028688 SPI_PS_INPUT_CNTL_17 | ||
402 | 0x0002868C SPI_PS_INPUT_CNTL_18 | ||
403 | 0x00028690 SPI_PS_INPUT_CNTL_19 | ||
404 | 0x00028694 SPI_PS_INPUT_CNTL_20 | ||
405 | 0x00028698 SPI_PS_INPUT_CNTL_21 | ||
406 | 0x0002869C SPI_PS_INPUT_CNTL_22 | ||
407 | 0x000286A0 SPI_PS_INPUT_CNTL_23 | ||
408 | 0x000286A4 SPI_PS_INPUT_CNTL_24 | ||
409 | 0x000286A8 SPI_PS_INPUT_CNTL_25 | ||
410 | 0x000286AC SPI_PS_INPUT_CNTL_26 | ||
411 | 0x000286B0 SPI_PS_INPUT_CNTL_27 | ||
412 | 0x000286B4 SPI_PS_INPUT_CNTL_28 | ||
413 | 0x000286B8 SPI_PS_INPUT_CNTL_29 | ||
414 | 0x000286BC SPI_PS_INPUT_CNTL_30 | ||
415 | 0x000286C0 SPI_PS_INPUT_CNTL_31 | ||
416 | 0x000286C4 SPI_VS_OUT_CONFIG | ||
417 | 0x000286C8 SPI_THREAD_GROUPING | ||
418 | 0x000286CC SPI_PS_IN_CONTROL_0 | ||
419 | 0x000286D0 SPI_PS_IN_CONTROL_1 | ||
420 | 0x000286D4 SPI_INTERP_CONTROL_0 | ||
421 | 0x000286D8 SPI_INPUT_Z | ||
422 | 0x000286DC SPI_FOG_CNTL | ||
423 | 0x000286E0 SPI_BARYC_CNTL | ||
424 | 0x000286E4 SPI_PS_IN_CONTROL_2 | ||
425 | 0x000286E8 SPI_COMPUTE_INPUT_CNTL | ||
426 | 0x000286EC SPI_COMPUTE_NUM_THREAD_X | ||
427 | 0x000286F0 SPI_COMPUTE_NUM_THREAD_Y | ||
428 | 0x000286F4 SPI_COMPUTE_NUM_THREAD_Z | ||
429 | 0x000286F8 SPI_GPR_MGMT | ||
430 | 0x000286FC SPI_LDS_MGMT | ||
431 | 0x00028700 SPI_STACK_MGMT | ||
432 | 0x00028704 SPI_WAVE_MGMT_1 | ||
433 | 0x00028708 SPI_WAVE_MGMT_2 | ||
434 | 0x00028724 GDS_ADDR_SIZE | ||
435 | 0x00028780 CB_BLEND0_CONTROL | ||
436 | 0x00028784 CB_BLEND1_CONTROL | ||
437 | 0x00028788 CB_BLEND2_CONTROL | ||
438 | 0x0002878C CB_BLEND3_CONTROL | ||
439 | 0x00028790 CB_BLEND4_CONTROL | ||
440 | 0x00028794 CB_BLEND5_CONTROL | ||
441 | 0x00028798 CB_BLEND6_CONTROL | ||
442 | 0x0002879C CB_BLEND7_CONTROL | ||
443 | 0x000287CC CS_COPY_STATE | ||
444 | 0x000287D0 GFX_COPY_STATE | ||
445 | 0x000287D4 PA_CL_POINT_X_RAD | ||
446 | 0x000287D8 PA_CL_POINT_Y_RAD | ||
447 | 0x000287DC PA_CL_POINT_SIZE | ||
448 | 0x000287E0 PA_CL_POINT_CULL_RAD | ||
449 | 0x00028808 CB_COLOR_CONTROL | ||
450 | 0x0002880C DB_SHADER_CONTROL | ||
451 | 0x00028810 PA_CL_CLIP_CNTL | ||
452 | 0x00028814 PA_SU_SC_MODE_CNTL | ||
453 | 0x00028818 PA_CL_VTE_CNTL | ||
454 | 0x0002881C PA_CL_VS_OUT_CNTL | ||
455 | 0x00028820 PA_CL_NANINF_CNTL | ||
456 | 0x00028824 PA_SU_LINE_STIPPLE_CNTL | ||
457 | 0x00028828 PA_SU_LINE_STIPPLE_SCALE | ||
458 | 0x0002882C PA_SU_PRIM_FILTER_CNTL | ||
459 | 0x00028844 SQ_PGM_RESOURCES_PS | ||
460 | 0x00028848 SQ_PGM_RESOURCES_2_PS | ||
461 | 0x0002884C SQ_PGM_EXPORTS_PS | ||
462 | 0x00028860 SQ_PGM_RESOURCES_VS | ||
463 | 0x00028864 SQ_PGM_RESOURCES_2_VS | ||
464 | 0x00028878 SQ_PGM_RESOURCES_GS | ||
465 | 0x0002887C SQ_PGM_RESOURCES_2_GS | ||
466 | 0x00028890 SQ_PGM_RESOURCES_ES | ||
467 | 0x00028894 SQ_PGM_RESOURCES_2_ES | ||
468 | 0x000288A8 SQ_PGM_RESOURCES_FS | ||
469 | 0x000288BC SQ_PGM_RESOURCES_HS | ||
470 | 0x000288C0 SQ_PGM_RESOURCES_2_HS | ||
471 | 0x000288D4 SQ_PGM_RESOURCES_LS | ||
472 | 0x000288D8 SQ_PGM_RESOURCES_2_LS | ||
473 | 0x000288E8 SQ_LDS_ALLOC | ||
474 | 0x000288EC SQ_LDS_ALLOC_PS | ||
475 | 0x000288F0 SQ_VTX_SEMANTIC_CLEAR | ||
476 | 0x00028A00 PA_SU_POINT_SIZE | ||
477 | 0x00028A04 PA_SU_POINT_MINMAX | ||
478 | 0x00028A08 PA_SU_LINE_CNTL | ||
479 | 0x00028A0C PA_SC_LINE_STIPPLE | ||
480 | 0x00028A10 VGT_OUTPUT_PATH_CNTL | ||
481 | 0x00028A14 VGT_HOS_CNTL | ||
482 | 0x00028A18 VGT_HOS_MAX_TESS_LEVEL | ||
483 | 0x00028A1C VGT_HOS_MIN_TESS_LEVEL | ||
484 | 0x00028A20 VGT_HOS_REUSE_DEPTH | ||
485 | 0x00028A24 VGT_GROUP_PRIM_TYPE | ||
486 | 0x00028A28 VGT_GROUP_FIRST_DECR | ||
487 | 0x00028A2C VGT_GROUP_DECR | ||
488 | 0x00028A30 VGT_GROUP_VECT_0_CNTL | ||
489 | 0x00028A34 VGT_GROUP_VECT_1_CNTL | ||
490 | 0x00028A38 VGT_GROUP_VECT_0_FMT_CNTL | ||
491 | 0x00028A3C VGT_GROUP_VECT_1_FMT_CNTL | ||
492 | 0x00028A40 VGT_GS_MODE | ||
493 | 0x00028A48 PA_SC_MODE_CNTL_0 | ||
494 | 0x00028A4C PA_SC_MODE_CNTL_1 | ||
495 | 0x00028A50 VGT_ENHANCE | ||
496 | 0x00028A54 VGT_GS_PER_ES | ||
497 | 0x00028A58 VGT_ES_PER_GS | ||
498 | 0x00028A5C VGT_GS_PER_VS | ||
499 | 0x00028A6C VGT_GS_OUT_PRIM_TYPE | ||
500 | 0x00028A70 IA_ENHANCE | ||
501 | 0x00028A84 VGT_PRIMITIVEID_EN | ||
502 | 0x00028A94 VGT_MULTI_PRIM_IB_RESET_EN | ||
503 | 0x00028AA0 VGT_INSTANCE_STEP_RATE_0 | ||
504 | 0x00028AA4 VGT_INSTANCE_STEP_RATE_1 | ||
505 | 0x00028AA8 IA_MULTI_VGT_PARAM | ||
506 | 0x00028AB4 VGT_REUSE_OFF | ||
507 | 0x00028AB8 VGT_VTX_CNT_EN | ||
508 | 0x00028ABC DB_HTILE_SURFACE | ||
509 | 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 | ||
510 | 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 | ||
511 | 0x00028AC8 DB_PRELOAD_CONTROL | ||
512 | 0x00028B38 VGT_GS_MAX_VERT_OUT | ||
513 | 0x00028B54 VGT_SHADER_STAGES_EN | ||
514 | 0x00028B58 VGT_LS_HS_CONFIG | ||
515 | 0x00028B6C VGT_TF_PARAM | ||
516 | 0x00028B70 DB_ALPHA_TO_MASK | ||
517 | 0x00028B74 VGT_DISPATCH_INITIATOR | ||
518 | 0x00028B78 PA_SU_POLY_OFFSET_DB_FMT_CNTL | ||
519 | 0x00028B7C PA_SU_POLY_OFFSET_CLAMP | ||
520 | 0x00028B80 PA_SU_POLY_OFFSET_FRONT_SCALE | ||
521 | 0x00028B84 PA_SU_POLY_OFFSET_FRONT_OFFSET | ||
522 | 0x00028B88 PA_SU_POLY_OFFSET_BACK_SCALE | ||
523 | 0x00028B8C PA_SU_POLY_OFFSET_BACK_OFFSET | ||
524 | 0x00028B74 VGT_GS_INSTANCE_CNT | ||
525 | 0x00028BD4 PA_SC_CENTROID_PRIORITY_0 | ||
526 | 0x00028BD8 PA_SC_CENTROID_PRIORITY_1 | ||
527 | 0x00028BDC PA_SC_LINE_CNTL | ||
528 | 0x00028BE4 PA_SU_VTX_CNTL | ||
529 | 0x00028BE8 PA_CL_GB_VERT_CLIP_ADJ | ||
530 | 0x00028BEC PA_CL_GB_VERT_DISC_ADJ | ||
531 | 0x00028BF0 PA_CL_GB_HORZ_CLIP_ADJ | ||
532 | 0x00028BF4 PA_CL_GB_HORZ_DISC_ADJ | ||
533 | 0x00028BF8 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y0_0 | ||
534 | 0x00028BFC PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y0_1 | ||
535 | 0x00028C00 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y0_2 | ||
536 | 0x00028C04 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y0_3 | ||
537 | 0x00028C08 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y0_0 | ||
538 | 0x00028C0C PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y0_1 | ||
539 | 0x00028C10 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y0_2 | ||
540 | 0x00028C14 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y0_3 | ||
541 | 0x00028C18 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y1_0 | ||
542 | 0x00028C1C PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y1_1 | ||
543 | 0x00028C20 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y1_2 | ||
544 | 0x00028C24 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y1_3 | ||
545 | 0x00028C28 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y1_0 | ||
546 | 0x00028C2C PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y1_1 | ||
547 | 0x00028C30 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y1_2 | ||
548 | 0x00028C34 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y1_3 | ||
549 | 0x00028C38 PA_SC_AA_MASK_X0_Y0_X1_Y0 | ||
550 | 0x00028C3C PA_SC_AA_MASK_X0_Y1_X1_Y1 | ||
551 | 0x00028C8C CB_COLOR0_CLEAR_WORD0 | ||
552 | 0x00028C90 CB_COLOR0_CLEAR_WORD1 | ||
553 | 0x00028C94 CB_COLOR0_CLEAR_WORD2 | ||
554 | 0x00028C98 CB_COLOR0_CLEAR_WORD3 | ||
555 | 0x00028CC8 CB_COLOR1_CLEAR_WORD0 | ||
556 | 0x00028CCC CB_COLOR1_CLEAR_WORD1 | ||
557 | 0x00028CD0 CB_COLOR1_CLEAR_WORD2 | ||
558 | 0x00028CD4 CB_COLOR1_CLEAR_WORD3 | ||
559 | 0x00028D04 CB_COLOR2_CLEAR_WORD0 | ||
560 | 0x00028D08 CB_COLOR2_CLEAR_WORD1 | ||
561 | 0x00028D0C CB_COLOR2_CLEAR_WORD2 | ||
562 | 0x00028D10 CB_COLOR2_CLEAR_WORD3 | ||
563 | 0x00028D40 CB_COLOR3_CLEAR_WORD0 | ||
564 | 0x00028D44 CB_COLOR3_CLEAR_WORD1 | ||
565 | 0x00028D48 CB_COLOR3_CLEAR_WORD2 | ||
566 | 0x00028D4C CB_COLOR3_CLEAR_WORD3 | ||
567 | 0x00028D7C CB_COLOR4_CLEAR_WORD0 | ||
568 | 0x00028D80 CB_COLOR4_CLEAR_WORD1 | ||
569 | 0x00028D84 CB_COLOR4_CLEAR_WORD2 | ||
570 | 0x00028D88 CB_COLOR4_CLEAR_WORD3 | ||
571 | 0x00028DB8 CB_COLOR5_CLEAR_WORD0 | ||
572 | 0x00028DBC CB_COLOR5_CLEAR_WORD1 | ||
573 | 0x00028DC0 CB_COLOR5_CLEAR_WORD2 | ||
574 | 0x00028DC4 CB_COLOR5_CLEAR_WORD3 | ||
575 | 0x00028DF4 CB_COLOR6_CLEAR_WORD0 | ||
576 | 0x00028DF8 CB_COLOR6_CLEAR_WORD1 | ||
577 | 0x00028DFC CB_COLOR6_CLEAR_WORD2 | ||
578 | 0x00028E00 CB_COLOR6_CLEAR_WORD3 | ||
579 | 0x00028E30 CB_COLOR7_CLEAR_WORD0 | ||
580 | 0x00028E34 CB_COLOR7_CLEAR_WORD1 | ||
581 | 0x00028E38 CB_COLOR7_CLEAR_WORD2 | ||
582 | 0x00028E3C CB_COLOR7_CLEAR_WORD3 | ||
583 | 0x00028F80 SQ_ALU_CONST_BUFFER_SIZE_HS_0 | ||
584 | 0x00028F84 SQ_ALU_CONST_BUFFER_SIZE_HS_1 | ||
585 | 0x00028F88 SQ_ALU_CONST_BUFFER_SIZE_HS_2 | ||
586 | 0x00028F8C SQ_ALU_CONST_BUFFER_SIZE_HS_3 | ||
587 | 0x00028F90 SQ_ALU_CONST_BUFFER_SIZE_HS_4 | ||
588 | 0x00028F94 SQ_ALU_CONST_BUFFER_SIZE_HS_5 | ||
589 | 0x00028F98 SQ_ALU_CONST_BUFFER_SIZE_HS_6 | ||
590 | 0x00028F9C SQ_ALU_CONST_BUFFER_SIZE_HS_7 | ||
591 | 0x00028FA0 SQ_ALU_CONST_BUFFER_SIZE_HS_8 | ||
592 | 0x00028FA4 SQ_ALU_CONST_BUFFER_SIZE_HS_9 | ||
593 | 0x00028FA8 SQ_ALU_CONST_BUFFER_SIZE_HS_10 | ||
594 | 0x00028FAC SQ_ALU_CONST_BUFFER_SIZE_HS_11 | ||
595 | 0x00028FB0 SQ_ALU_CONST_BUFFER_SIZE_HS_12 | ||
596 | 0x00028FB4 SQ_ALU_CONST_BUFFER_SIZE_HS_13 | ||
597 | 0x00028FB8 SQ_ALU_CONST_BUFFER_SIZE_HS_14 | ||
598 | 0x00028FBC SQ_ALU_CONST_BUFFER_SIZE_HS_15 | ||
599 | 0x00028FC0 SQ_ALU_CONST_BUFFER_SIZE_LS_0 | ||
600 | 0x00028FC4 SQ_ALU_CONST_BUFFER_SIZE_LS_1 | ||
601 | 0x00028FC8 SQ_ALU_CONST_BUFFER_SIZE_LS_2 | ||
602 | 0x00028FCC SQ_ALU_CONST_BUFFER_SIZE_LS_3 | ||
603 | 0x00028FD0 SQ_ALU_CONST_BUFFER_SIZE_LS_4 | ||
604 | 0x00028FD4 SQ_ALU_CONST_BUFFER_SIZE_LS_5 | ||
605 | 0x00028FD8 SQ_ALU_CONST_BUFFER_SIZE_LS_6 | ||
606 | 0x00028FDC SQ_ALU_CONST_BUFFER_SIZE_LS_7 | ||
607 | 0x00028FE0 SQ_ALU_CONST_BUFFER_SIZE_LS_8 | ||
608 | 0x00028FE4 SQ_ALU_CONST_BUFFER_SIZE_LS_9 | ||
609 | 0x00028FE8 SQ_ALU_CONST_BUFFER_SIZE_LS_10 | ||
610 | 0x00028FEC SQ_ALU_CONST_BUFFER_SIZE_LS_11 | ||
611 | 0x00028FF0 SQ_ALU_CONST_BUFFER_SIZE_LS_12 | ||
612 | 0x00028FF4 SQ_ALU_CONST_BUFFER_SIZE_LS_13 | ||
613 | 0x00028FF8 SQ_ALU_CONST_BUFFER_SIZE_LS_14 | ||
614 | 0x00028FFC SQ_ALU_CONST_BUFFER_SIZE_LS_15 | ||
615 | 0x0003CFF0 SQ_VTX_BASE_VTX_LOC | ||
616 | 0x0003CFF4 SQ_VTX_START_INST_LOC | ||
617 | 0x0003FF00 SQ_TEX_SAMPLER_CLEAR | ||
618 | 0x0003FF04 SQ_TEX_RESOURCE_CLEAR | ||
619 | 0x0003FF08 SQ_LOOP_BOOL_CLEAR | ||
diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen index 9177f919183..7e1637176e0 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/evergreen +++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen | |||
@@ -1,4 +1,5 @@ | |||
1 | evergreen 0x9400 | 1 | evergreen 0x9400 |
2 | 0x0000802C GRBM_GFX_INDEX | ||
2 | 0x00008040 WAIT_UNTIL | 3 | 0x00008040 WAIT_UNTIL |
3 | 0x00008044 WAIT_UNTIL_POLL_CNTL | 4 | 0x00008044 WAIT_UNTIL_POLL_CNTL |
4 | 0x00008048 WAIT_UNTIL_POLL_MASK | 5 | 0x00008048 WAIT_UNTIL_POLL_MASK |
@@ -220,6 +221,7 @@ evergreen 0x9400 | |||
220 | 0x00028348 PA_SC_VPORT_ZMIN_15 | 221 | 0x00028348 PA_SC_VPORT_ZMIN_15 |
221 | 0x0002834C PA_SC_VPORT_ZMAX_15 | 222 | 0x0002834C PA_SC_VPORT_ZMAX_15 |
222 | 0x00028350 SX_MISC | 223 | 0x00028350 SX_MISC |
224 | 0x00028354 SX_SURFACE_SYNC | ||
223 | 0x00028380 SQ_VTX_SEMANTIC_0 | 225 | 0x00028380 SQ_VTX_SEMANTIC_0 |
224 | 0x00028384 SQ_VTX_SEMANTIC_1 | 226 | 0x00028384 SQ_VTX_SEMANTIC_1 |
225 | 0x00028388 SQ_VTX_SEMANTIC_2 | 227 | 0x00028388 SQ_VTX_SEMANTIC_2 |
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 714ad45757d..4cc7b717fed 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c | |||
@@ -1003,7 +1003,7 @@ static int rv770_vram_scratch_init(struct radeon_device *rdev) | |||
1003 | u64 gpu_addr; | 1003 | u64 gpu_addr; |
1004 | 1004 | ||
1005 | if (rdev->vram_scratch.robj == NULL) { | 1005 | if (rdev->vram_scratch.robj == NULL) { |
1006 | r = radeon_bo_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, | 1006 | r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE, |
1007 | PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, | 1007 | PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, |
1008 | &rdev->vram_scratch.robj); | 1008 | &rdev->vram_scratch.robj); |
1009 | if (r) { | 1009 | if (r) { |
diff --git a/drivers/gpu/drm/savage/savage_drv.c b/drivers/gpu/drm/savage/savage_drv.c index fa64d25d424..6464490b240 100644 --- a/drivers/gpu/drm/savage/savage_drv.c +++ b/drivers/gpu/drm/savage/savage_drv.c | |||
@@ -55,11 +55,6 @@ static struct drm_driver driver = { | |||
55 | .llseek = noop_llseek, | 55 | .llseek = noop_llseek, |
56 | }, | 56 | }, |
57 | 57 | ||
58 | .pci_driver = { | ||
59 | .name = DRIVER_NAME, | ||
60 | .id_table = pciidlist, | ||
61 | }, | ||
62 | |||
63 | .name = DRIVER_NAME, | 58 | .name = DRIVER_NAME, |
64 | .desc = DRIVER_DESC, | 59 | .desc = DRIVER_DESC, |
65 | .date = DRIVER_DATE, | 60 | .date = DRIVER_DATE, |
@@ -68,15 +63,20 @@ static struct drm_driver driver = { | |||
68 | .patchlevel = DRIVER_PATCHLEVEL, | 63 | .patchlevel = DRIVER_PATCHLEVEL, |
69 | }; | 64 | }; |
70 | 65 | ||
66 | static struct pci_driver savage_pci_driver = { | ||
67 | .name = DRIVER_NAME, | ||
68 | .id_table = pciidlist, | ||
69 | }; | ||
70 | |||
71 | static int __init savage_init(void) | 71 | static int __init savage_init(void) |
72 | { | 72 | { |
73 | driver.num_ioctls = savage_max_ioctl; | 73 | driver.num_ioctls = savage_max_ioctl; |
74 | return drm_init(&driver); | 74 | return drm_pci_init(&driver, &savage_pci_driver); |
75 | } | 75 | } |
76 | 76 | ||
77 | static void __exit savage_exit(void) | 77 | static void __exit savage_exit(void) |
78 | { | 78 | { |
79 | drm_exit(&driver); | 79 | drm_pci_exit(&driver, &savage_pci_driver); |
80 | } | 80 | } |
81 | 81 | ||
82 | module_init(savage_init); | 82 | module_init(savage_init); |
diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c index 4caf5d01cfd..46d5be6e97e 100644 --- a/drivers/gpu/drm/sis/sis_drv.c +++ b/drivers/gpu/drm/sis/sis_drv.c | |||
@@ -82,10 +82,6 @@ static struct drm_driver driver = { | |||
82 | .fasync = drm_fasync, | 82 | .fasync = drm_fasync, |
83 | .llseek = noop_llseek, | 83 | .llseek = noop_llseek, |
84 | }, | 84 | }, |
85 | .pci_driver = { | ||
86 | .name = DRIVER_NAME, | ||
87 | .id_table = pciidlist, | ||
88 | }, | ||
89 | 85 | ||
90 | .name = DRIVER_NAME, | 86 | .name = DRIVER_NAME, |
91 | .desc = DRIVER_DESC, | 87 | .desc = DRIVER_DESC, |
@@ -95,15 +91,20 @@ static struct drm_driver driver = { | |||
95 | .patchlevel = DRIVER_PATCHLEVEL, | 91 | .patchlevel = DRIVER_PATCHLEVEL, |
96 | }; | 92 | }; |
97 | 93 | ||
94 | static struct pci_driver sis_pci_driver = { | ||
95 | .name = DRIVER_NAME, | ||
96 | .id_table = pciidlist, | ||
97 | }; | ||
98 | |||
98 | static int __init sis_init(void) | 99 | static int __init sis_init(void) |
99 | { | 100 | { |
100 | driver.num_ioctls = sis_max_ioctl; | 101 | driver.num_ioctls = sis_max_ioctl; |
101 | return drm_init(&driver); | 102 | return drm_pci_init(&driver, &sis_pci_driver); |
102 | } | 103 | } |
103 | 104 | ||
104 | static void __exit sis_exit(void) | 105 | static void __exit sis_exit(void) |
105 | { | 106 | { |
106 | drm_exit(&driver); | 107 | drm_pci_exit(&driver, &sis_pci_driver); |
107 | } | 108 | } |
108 | 109 | ||
109 | module_init(sis_init); | 110 | module_init(sis_init); |
diff --git a/drivers/gpu/drm/tdfx/tdfx_drv.c b/drivers/gpu/drm/tdfx/tdfx_drv.c index b70fa91d761..8bf98810a8d 100644 --- a/drivers/gpu/drm/tdfx/tdfx_drv.c +++ b/drivers/gpu/drm/tdfx/tdfx_drv.c | |||
@@ -52,10 +52,6 @@ static struct drm_driver driver = { | |||
52 | .fasync = drm_fasync, | 52 | .fasync = drm_fasync, |
53 | .llseek = noop_llseek, | 53 | .llseek = noop_llseek, |
54 | }, | 54 | }, |
55 | .pci_driver = { | ||
56 | .name = DRIVER_NAME, | ||
57 | .id_table = pciidlist, | ||
58 | }, | ||
59 | 55 | ||
60 | .name = DRIVER_NAME, | 56 | .name = DRIVER_NAME, |
61 | .desc = DRIVER_DESC, | 57 | .desc = DRIVER_DESC, |
@@ -65,14 +61,19 @@ static struct drm_driver driver = { | |||
65 | .patchlevel = DRIVER_PATCHLEVEL, | 61 | .patchlevel = DRIVER_PATCHLEVEL, |
66 | }; | 62 | }; |
67 | 63 | ||
64 | static struct pci_driver tdfx_pci_driver = { | ||
65 | .name = DRIVER_NAME, | ||
66 | .id_table = pciidlist, | ||
67 | }; | ||
68 | |||
68 | static int __init tdfx_init(void) | 69 | static int __init tdfx_init(void) |
69 | { | 70 | { |
70 | return drm_init(&driver); | 71 | return drm_pci_init(&driver, &tdfx_pci_driver); |
71 | } | 72 | } |
72 | 73 | ||
73 | static void __exit tdfx_exit(void) | 74 | static void __exit tdfx_exit(void) |
74 | { | 75 | { |
75 | drm_exit(&driver); | 76 | drm_pci_exit(&driver, &tdfx_pci_driver); |
76 | } | 77 | } |
77 | 78 | ||
78 | module_init(tdfx_init); | 79 | module_init(tdfx_init); |
diff --git a/drivers/gpu/drm/ttm/ttm_agp_backend.c b/drivers/gpu/drm/ttm/ttm_agp_backend.c index f999e36f30b..1c4a72f681c 100644 --- a/drivers/gpu/drm/ttm/ttm_agp_backend.c +++ b/drivers/gpu/drm/ttm/ttm_agp_backend.c | |||
@@ -47,7 +47,8 @@ struct ttm_agp_backend { | |||
47 | 47 | ||
48 | static int ttm_agp_populate(struct ttm_backend *backend, | 48 | static int ttm_agp_populate(struct ttm_backend *backend, |
49 | unsigned long num_pages, struct page **pages, | 49 | unsigned long num_pages, struct page **pages, |
50 | struct page *dummy_read_page) | 50 | struct page *dummy_read_page, |
51 | dma_addr_t *dma_addrs) | ||
51 | { | 52 | { |
52 | struct ttm_agp_backend *agp_be = | 53 | struct ttm_agp_backend *agp_be = |
53 | container_of(backend, struct ttm_agp_backend, backend); | 54 | container_of(backend, struct ttm_agp_backend, backend); |
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index af61fc29e84..0b6a55ac2f8 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c | |||
@@ -406,11 +406,12 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, | |||
406 | } | 406 | } |
407 | 407 | ||
408 | if (bo->mem.mem_type == TTM_PL_SYSTEM) { | 408 | if (bo->mem.mem_type == TTM_PL_SYSTEM) { |
409 | if (bdev->driver->move_notify) | ||
410 | bdev->driver->move_notify(bo, mem); | ||
409 | bo->mem = *mem; | 411 | bo->mem = *mem; |
410 | mem->mm_node = NULL; | 412 | mem->mm_node = NULL; |
411 | goto moved; | 413 | goto moved; |
412 | } | 414 | } |
413 | |||
414 | } | 415 | } |
415 | 416 | ||
416 | if (bdev->driver->move_notify) | 417 | if (bdev->driver->move_notify) |
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c index b1e02fffd3c..737a2a2e46a 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/mm.h> | 38 | #include <linux/mm.h> |
39 | #include <linux/seq_file.h> /* for seq_printf */ | 39 | #include <linux/seq_file.h> /* for seq_printf */ |
40 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
41 | #include <linux/dma-mapping.h> | ||
41 | 42 | ||
42 | #include <asm/atomic.h> | 43 | #include <asm/atomic.h> |
43 | 44 | ||
@@ -662,7 +663,8 @@ out: | |||
662 | * cached pages. | 663 | * cached pages. |
663 | */ | 664 | */ |
664 | int ttm_get_pages(struct list_head *pages, int flags, | 665 | int ttm_get_pages(struct list_head *pages, int flags, |
665 | enum ttm_caching_state cstate, unsigned count) | 666 | enum ttm_caching_state cstate, unsigned count, |
667 | dma_addr_t *dma_address) | ||
666 | { | 668 | { |
667 | struct ttm_page_pool *pool = ttm_get_pool(flags, cstate); | 669 | struct ttm_page_pool *pool = ttm_get_pool(flags, cstate); |
668 | struct page *p = NULL; | 670 | struct page *p = NULL; |
@@ -681,14 +683,22 @@ int ttm_get_pages(struct list_head *pages, int flags, | |||
681 | gfp_flags |= GFP_HIGHUSER; | 683 | gfp_flags |= GFP_HIGHUSER; |
682 | 684 | ||
683 | for (r = 0; r < count; ++r) { | 685 | for (r = 0; r < count; ++r) { |
684 | p = alloc_page(gfp_flags); | 686 | if ((flags & TTM_PAGE_FLAG_DMA32) && dma_address) { |
687 | void *addr; | ||
688 | addr = dma_alloc_coherent(NULL, PAGE_SIZE, | ||
689 | &dma_address[r], | ||
690 | gfp_flags); | ||
691 | if (addr == NULL) | ||
692 | return -ENOMEM; | ||
693 | p = virt_to_page(addr); | ||
694 | } else | ||
695 | p = alloc_page(gfp_flags); | ||
685 | if (!p) { | 696 | if (!p) { |
686 | 697 | ||
687 | printk(KERN_ERR TTM_PFX | 698 | printk(KERN_ERR TTM_PFX |
688 | "Unable to allocate page."); | 699 | "Unable to allocate page."); |
689 | return -ENOMEM; | 700 | return -ENOMEM; |
690 | } | 701 | } |
691 | |||
692 | list_add(&p->lru, pages); | 702 | list_add(&p->lru, pages); |
693 | } | 703 | } |
694 | return 0; | 704 | return 0; |
@@ -720,7 +730,7 @@ int ttm_get_pages(struct list_head *pages, int flags, | |||
720 | printk(KERN_ERR TTM_PFX | 730 | printk(KERN_ERR TTM_PFX |
721 | "Failed to allocate extra pages " | 731 | "Failed to allocate extra pages " |
722 | "for large request."); | 732 | "for large request."); |
723 | ttm_put_pages(pages, 0, flags, cstate); | 733 | ttm_put_pages(pages, 0, flags, cstate, NULL); |
724 | return r; | 734 | return r; |
725 | } | 735 | } |
726 | } | 736 | } |
@@ -731,17 +741,29 @@ int ttm_get_pages(struct list_head *pages, int flags, | |||
731 | 741 | ||
732 | /* Put all pages in pages list to correct pool to wait for reuse */ | 742 | /* Put all pages in pages list to correct pool to wait for reuse */ |
733 | void ttm_put_pages(struct list_head *pages, unsigned page_count, int flags, | 743 | void ttm_put_pages(struct list_head *pages, unsigned page_count, int flags, |
734 | enum ttm_caching_state cstate) | 744 | enum ttm_caching_state cstate, dma_addr_t *dma_address) |
735 | { | 745 | { |
736 | unsigned long irq_flags; | 746 | unsigned long irq_flags; |
737 | struct ttm_page_pool *pool = ttm_get_pool(flags, cstate); | 747 | struct ttm_page_pool *pool = ttm_get_pool(flags, cstate); |
738 | struct page *p, *tmp; | 748 | struct page *p, *tmp; |
749 | unsigned r; | ||
739 | 750 | ||
740 | if (pool == NULL) { | 751 | if (pool == NULL) { |
741 | /* No pool for this memory type so free the pages */ | 752 | /* No pool for this memory type so free the pages */ |
742 | 753 | ||
754 | r = page_count-1; | ||
743 | list_for_each_entry_safe(p, tmp, pages, lru) { | 755 | list_for_each_entry_safe(p, tmp, pages, lru) { |
744 | __free_page(p); | 756 | if ((flags & TTM_PAGE_FLAG_DMA32) && dma_address) { |
757 | void *addr = page_address(p); | ||
758 | WARN_ON(!addr || !dma_address[r]); | ||
759 | if (addr) | ||
760 | dma_free_coherent(NULL, PAGE_SIZE, | ||
761 | addr, | ||
762 | dma_address[r]); | ||
763 | dma_address[r] = 0; | ||
764 | } else | ||
765 | __free_page(p); | ||
766 | r--; | ||
745 | } | 767 | } |
746 | /* Make the pages list empty */ | 768 | /* Make the pages list empty */ |
747 | INIT_LIST_HEAD(pages); | 769 | INIT_LIST_HEAD(pages); |
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index af789dc869b..86d5b1745a4 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c | |||
@@ -49,12 +49,16 @@ static int ttm_tt_swapin(struct ttm_tt *ttm); | |||
49 | static void ttm_tt_alloc_page_directory(struct ttm_tt *ttm) | 49 | static void ttm_tt_alloc_page_directory(struct ttm_tt *ttm) |
50 | { | 50 | { |
51 | ttm->pages = drm_calloc_large(ttm->num_pages, sizeof(*ttm->pages)); | 51 | ttm->pages = drm_calloc_large(ttm->num_pages, sizeof(*ttm->pages)); |
52 | ttm->dma_address = drm_calloc_large(ttm->num_pages, | ||
53 | sizeof(*ttm->dma_address)); | ||
52 | } | 54 | } |
53 | 55 | ||
54 | static void ttm_tt_free_page_directory(struct ttm_tt *ttm) | 56 | static void ttm_tt_free_page_directory(struct ttm_tt *ttm) |
55 | { | 57 | { |
56 | drm_free_large(ttm->pages); | 58 | drm_free_large(ttm->pages); |
57 | ttm->pages = NULL; | 59 | ttm->pages = NULL; |
60 | drm_free_large(ttm->dma_address); | ||
61 | ttm->dma_address = NULL; | ||
58 | } | 62 | } |
59 | 63 | ||
60 | static void ttm_tt_free_user_pages(struct ttm_tt *ttm) | 64 | static void ttm_tt_free_user_pages(struct ttm_tt *ttm) |
@@ -105,7 +109,8 @@ static struct page *__ttm_tt_get_page(struct ttm_tt *ttm, int index) | |||
105 | 109 | ||
106 | INIT_LIST_HEAD(&h); | 110 | INIT_LIST_HEAD(&h); |
107 | 111 | ||
108 | ret = ttm_get_pages(&h, ttm->page_flags, ttm->caching_state, 1); | 112 | ret = ttm_get_pages(&h, ttm->page_flags, ttm->caching_state, 1, |
113 | &ttm->dma_address[index]); | ||
109 | 114 | ||
110 | if (ret != 0) | 115 | if (ret != 0) |
111 | return NULL; | 116 | return NULL; |
@@ -164,7 +169,7 @@ int ttm_tt_populate(struct ttm_tt *ttm) | |||
164 | } | 169 | } |
165 | 170 | ||
166 | be->func->populate(be, ttm->num_pages, ttm->pages, | 171 | be->func->populate(be, ttm->num_pages, ttm->pages, |
167 | ttm->dummy_read_page); | 172 | ttm->dummy_read_page, ttm->dma_address); |
168 | ttm->state = tt_unbound; | 173 | ttm->state = tt_unbound; |
169 | return 0; | 174 | return 0; |
170 | } | 175 | } |
@@ -298,7 +303,8 @@ static void ttm_tt_free_alloced_pages(struct ttm_tt *ttm) | |||
298 | count++; | 303 | count++; |
299 | } | 304 | } |
300 | } | 305 | } |
301 | ttm_put_pages(&h, count, ttm->page_flags, ttm->caching_state); | 306 | ttm_put_pages(&h, count, ttm->page_flags, ttm->caching_state, |
307 | ttm->dma_address); | ||
302 | ttm->state = tt_unpopulated; | 308 | ttm->state = tt_unpopulated; |
303 | ttm->first_himem_page = ttm->num_pages; | 309 | ttm->first_himem_page = ttm->num_pages; |
304 | ttm->last_lomem_page = -1; | 310 | ttm->last_lomem_page = -1; |
diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c index e1ff4e7a6eb..920a55214bc 100644 --- a/drivers/gpu/drm/via/via_drv.c +++ b/drivers/gpu/drm/via/via_drv.c | |||
@@ -62,10 +62,6 @@ static struct drm_driver driver = { | |||
62 | .fasync = drm_fasync, | 62 | .fasync = drm_fasync, |
63 | .llseek = noop_llseek, | 63 | .llseek = noop_llseek, |
64 | }, | 64 | }, |
65 | .pci_driver = { | ||
66 | .name = DRIVER_NAME, | ||
67 | .id_table = pciidlist, | ||
68 | }, | ||
69 | 65 | ||
70 | .name = DRIVER_NAME, | 66 | .name = DRIVER_NAME, |
71 | .desc = DRIVER_DESC, | 67 | .desc = DRIVER_DESC, |
@@ -75,16 +71,21 @@ static struct drm_driver driver = { | |||
75 | .patchlevel = DRIVER_PATCHLEVEL, | 71 | .patchlevel = DRIVER_PATCHLEVEL, |
76 | }; | 72 | }; |
77 | 73 | ||
74 | static struct pci_driver via_pci_driver = { | ||
75 | .name = DRIVER_NAME, | ||
76 | .id_table = pciidlist, | ||
77 | }; | ||
78 | |||
78 | static int __init via_init(void) | 79 | static int __init via_init(void) |
79 | { | 80 | { |
80 | driver.num_ioctls = via_max_ioctl; | 81 | driver.num_ioctls = via_max_ioctl; |
81 | via_init_command_verifier(); | 82 | via_init_command_verifier(); |
82 | return drm_init(&driver); | 83 | return drm_pci_init(&driver, &via_pci_driver); |
83 | } | 84 | } |
84 | 85 | ||
85 | static void __exit via_exit(void) | 86 | static void __exit via_exit(void) |
86 | { | 87 | { |
87 | drm_exit(&driver); | 88 | drm_pci_exit(&driver, &via_pci_driver); |
88 | } | 89 | } |
89 | 90 | ||
90 | module_init(via_init); | 91 | module_init(via_init); |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c index 80bc37b274e..87e43e0733b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c | |||
@@ -102,7 +102,8 @@ struct vmw_ttm_backend { | |||
102 | 102 | ||
103 | static int vmw_ttm_populate(struct ttm_backend *backend, | 103 | static int vmw_ttm_populate(struct ttm_backend *backend, |
104 | unsigned long num_pages, struct page **pages, | 104 | unsigned long num_pages, struct page **pages, |
105 | struct page *dummy_read_page) | 105 | struct page *dummy_read_page, |
106 | dma_addr_t *dma_addrs) | ||
106 | { | 107 | { |
107 | struct vmw_ttm_backend *vmw_be = | 108 | struct vmw_ttm_backend *vmw_be = |
108 | container_of(backend, struct vmw_ttm_backend, backend); | 109 | container_of(backend, struct vmw_ttm_backend, backend); |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 10ca97ee020..96949b93d92 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | |||
@@ -909,15 +909,6 @@ static struct drm_driver driver = { | |||
909 | #endif | 909 | #endif |
910 | .llseek = noop_llseek, | 910 | .llseek = noop_llseek, |
911 | }, | 911 | }, |
912 | .pci_driver = { | ||
913 | .name = VMWGFX_DRIVER_NAME, | ||
914 | .id_table = vmw_pci_id_list, | ||
915 | .probe = vmw_probe, | ||
916 | .remove = vmw_remove, | ||
917 | .driver = { | ||
918 | .pm = &vmw_pm_ops | ||
919 | } | ||
920 | }, | ||
921 | .name = VMWGFX_DRIVER_NAME, | 912 | .name = VMWGFX_DRIVER_NAME, |
922 | .desc = VMWGFX_DRIVER_DESC, | 913 | .desc = VMWGFX_DRIVER_DESC, |
923 | .date = VMWGFX_DRIVER_DATE, | 914 | .date = VMWGFX_DRIVER_DATE, |
@@ -926,6 +917,16 @@ static struct drm_driver driver = { | |||
926 | .patchlevel = VMWGFX_DRIVER_PATCHLEVEL | 917 | .patchlevel = VMWGFX_DRIVER_PATCHLEVEL |
927 | }; | 918 | }; |
928 | 919 | ||
920 | static struct pci_driver vmw_pci_driver = { | ||
921 | .name = VMWGFX_DRIVER_NAME, | ||
922 | .id_table = vmw_pci_id_list, | ||
923 | .probe = vmw_probe, | ||
924 | .remove = vmw_remove, | ||
925 | .driver = { | ||
926 | .pm = &vmw_pm_ops | ||
927 | } | ||
928 | }; | ||
929 | |||
929 | static int vmw_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 930 | static int vmw_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
930 | { | 931 | { |
931 | return drm_get_pci_dev(pdev, ent, &driver); | 932 | return drm_get_pci_dev(pdev, ent, &driver); |
@@ -934,7 +935,7 @@ static int vmw_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
934 | static int __init vmwgfx_init(void) | 935 | static int __init vmwgfx_init(void) |
935 | { | 936 | { |
936 | int ret; | 937 | int ret; |
937 | ret = drm_init(&driver); | 938 | ret = drm_pci_init(&driver, &vmw_pci_driver); |
938 | if (ret) | 939 | if (ret) |
939 | DRM_ERROR("Failed initializing DRM.\n"); | 940 | DRM_ERROR("Failed initializing DRM.\n"); |
940 | return ret; | 941 | return ret; |
@@ -942,7 +943,7 @@ static int __init vmwgfx_init(void) | |||
942 | 943 | ||
943 | static void __exit vmwgfx_exit(void) | 944 | static void __exit vmwgfx_exit(void) |
944 | { | 945 | { |
945 | drm_exit(&driver); | 946 | drm_pci_exit(&driver, &vmw_pci_driver); |
946 | } | 947 | } |
947 | 948 | ||
948 | module_init(vmwgfx_init); | 949 | module_init(vmwgfx_init); |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 29113c9b26a..b3a2cd5118d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | |||
@@ -345,7 +345,7 @@ static enum drm_connector_status | |||
345 | return connector_status_disconnected; | 345 | return connector_status_disconnected; |
346 | } | 346 | } |
347 | 347 | ||
348 | static struct drm_display_mode vmw_ldu_connector_builtin[] = { | 348 | static const struct drm_display_mode vmw_ldu_connector_builtin[] = { |
349 | /* 640x480@60Hz */ | 349 | /* 640x480@60Hz */ |
350 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656, | 350 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656, |
351 | 752, 800, 0, 480, 489, 492, 525, 0, | 351 | 752, 800, 0, 480, 489, 492, 525, 0, |
@@ -429,7 +429,6 @@ static int vmw_ldu_connector_fill_modes(struct drm_connector *connector, | |||
429 | struct drm_device *dev = connector->dev; | 429 | struct drm_device *dev = connector->dev; |
430 | struct vmw_private *dev_priv = vmw_priv(dev); | 430 | struct vmw_private *dev_priv = vmw_priv(dev); |
431 | struct drm_display_mode *mode = NULL; | 431 | struct drm_display_mode *mode = NULL; |
432 | struct drm_display_mode *bmode; | ||
433 | struct drm_display_mode prefmode = { DRM_MODE("preferred", | 432 | struct drm_display_mode prefmode = { DRM_MODE("preferred", |
434 | DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, | 433 | DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, |
435 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 434 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
@@ -459,6 +458,8 @@ static int vmw_ldu_connector_fill_modes(struct drm_connector *connector, | |||
459 | } | 458 | } |
460 | 459 | ||
461 | for (i = 0; vmw_ldu_connector_builtin[i].type != 0; i++) { | 460 | for (i = 0; vmw_ldu_connector_builtin[i].type != 0; i++) { |
461 | const struct drm_display_mode *bmode; | ||
462 | |||
462 | bmode = &vmw_ldu_connector_builtin[i]; | 463 | bmode = &vmw_ldu_connector_builtin[i]; |
463 | if (bmode->hdisplay > max_width || | 464 | if (bmode->hdisplay > max_width || |
464 | bmode->vdisplay > max_height) | 465 | bmode->vdisplay > max_height) |