diff options
Diffstat (limited to 'drivers/gpu/drm')
51 files changed, 482 insertions, 206 deletions
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 7ef1b673e1be..133b4132983e 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c | |||
@@ -121,6 +121,8 @@ int drm_open(struct inode *inode, struct file *filp) | |||
121 | int minor_id = iminor(inode); | 121 | int minor_id = iminor(inode); |
122 | struct drm_minor *minor; | 122 | struct drm_minor *minor; |
123 | int retcode = 0; | 123 | int retcode = 0; |
124 | int need_setup = 0; | ||
125 | struct address_space *old_mapping; | ||
124 | 126 | ||
125 | minor = idr_find(&drm_minors_idr, minor_id); | 127 | minor = idr_find(&drm_minors_idr, minor_id); |
126 | if (!minor) | 128 | if (!minor) |
@@ -132,23 +134,37 @@ int drm_open(struct inode *inode, struct file *filp) | |||
132 | if (drm_device_is_unplugged(dev)) | 134 | if (drm_device_is_unplugged(dev)) |
133 | return -ENODEV; | 135 | return -ENODEV; |
134 | 136 | ||
137 | if (!dev->open_count++) | ||
138 | need_setup = 1; | ||
139 | mutex_lock(&dev->struct_mutex); | ||
140 | old_mapping = dev->dev_mapping; | ||
141 | if (old_mapping == NULL) | ||
142 | dev->dev_mapping = &inode->i_data; | ||
143 | /* ihold ensures nobody can remove inode with our i_data */ | ||
144 | ihold(container_of(dev->dev_mapping, struct inode, i_data)); | ||
145 | inode->i_mapping = dev->dev_mapping; | ||
146 | filp->f_mapping = dev->dev_mapping; | ||
147 | mutex_unlock(&dev->struct_mutex); | ||
148 | |||
135 | retcode = drm_open_helper(inode, filp, dev); | 149 | retcode = drm_open_helper(inode, filp, dev); |
136 | if (!retcode) { | 150 | if (retcode) |
137 | atomic_inc(&dev->counts[_DRM_STAT_OPENS]); | 151 | goto err_undo; |
138 | if (!dev->open_count++) | 152 | atomic_inc(&dev->counts[_DRM_STAT_OPENS]); |
139 | retcode = drm_setup(dev); | 153 | if (need_setup) { |
140 | } | 154 | retcode = drm_setup(dev); |
141 | if (!retcode) { | 155 | if (retcode) |
142 | mutex_lock(&dev->struct_mutex); | 156 | goto err_undo; |
143 | if (dev->dev_mapping == NULL) | ||
144 | dev->dev_mapping = &inode->i_data; | ||
145 | /* ihold ensures nobody can remove inode with our i_data */ | ||
146 | ihold(container_of(dev->dev_mapping, struct inode, i_data)); | ||
147 | inode->i_mapping = dev->dev_mapping; | ||
148 | filp->f_mapping = dev->dev_mapping; | ||
149 | mutex_unlock(&dev->struct_mutex); | ||
150 | } | 157 | } |
158 | return 0; | ||
151 | 159 | ||
160 | err_undo: | ||
161 | mutex_lock(&dev->struct_mutex); | ||
162 | filp->f_mapping = old_mapping; | ||
163 | inode->i_mapping = old_mapping; | ||
164 | iput(container_of(dev->dev_mapping, struct inode, i_data)); | ||
165 | dev->dev_mapping = old_mapping; | ||
166 | mutex_unlock(&dev->struct_mutex); | ||
167 | dev->open_count--; | ||
152 | return retcode; | 168 | return retcode; |
153 | } | 169 | } |
154 | EXPORT_SYMBOL(drm_open); | 170 | EXPORT_SYMBOL(drm_open); |
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 59a26e577b57..fc345d4ebb03 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config DRM_EXYNOS | 1 | config DRM_EXYNOS |
2 | tristate "DRM Support for Samsung SoC EXYNOS Series" | 2 | tristate "DRM Support for Samsung SoC EXYNOS Series" |
3 | depends on DRM && PLAT_SAMSUNG | 3 | depends on DRM && (PLAT_SAMSUNG || ARCH_MULTIPLATFORM) |
4 | select DRM_KMS_HELPER | 4 | select DRM_KMS_HELPER |
5 | select FB_CFB_FILLRECT | 5 | select FB_CFB_FILLRECT |
6 | select FB_CFB_COPYAREA | 6 | select FB_CFB_COPYAREA |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c index 18c271862ca8..0f68a2872673 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_connector.c +++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c | |||
@@ -374,6 +374,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev, | |||
374 | exynos_connector->encoder_id = encoder->base.id; | 374 | exynos_connector->encoder_id = encoder->base.id; |
375 | exynos_connector->manager = manager; | 375 | exynos_connector->manager = manager; |
376 | exynos_connector->dpms = DRM_MODE_DPMS_OFF; | 376 | exynos_connector->dpms = DRM_MODE_DPMS_OFF; |
377 | connector->dpms = DRM_MODE_DPMS_OFF; | ||
377 | connector->encoder = encoder; | 378 | connector->encoder = encoder; |
378 | 379 | ||
379 | err = drm_mode_connector_attach_encoder(connector, encoder); | 380 | err = drm_mode_connector_attach_encoder(connector, encoder); |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index e51503fbaf2b..f2df06c603f7 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c | |||
@@ -43,12 +43,14 @@ | |||
43 | * @manager: specific encoder has its own manager to control a hardware | 43 | * @manager: specific encoder has its own manager to control a hardware |
44 | * appropriately and we can access a hardware drawing on this manager. | 44 | * appropriately and we can access a hardware drawing on this manager. |
45 | * @dpms: store the encoder dpms value. | 45 | * @dpms: store the encoder dpms value. |
46 | * @updated: indicate whether overlay data updating is needed or not. | ||
46 | */ | 47 | */ |
47 | struct exynos_drm_encoder { | 48 | struct exynos_drm_encoder { |
48 | struct drm_crtc *old_crtc; | 49 | struct drm_crtc *old_crtc; |
49 | struct drm_encoder drm_encoder; | 50 | struct drm_encoder drm_encoder; |
50 | struct exynos_drm_manager *manager; | 51 | struct exynos_drm_manager *manager; |
51 | int dpms; | 52 | int dpms; |
53 | bool updated; | ||
52 | }; | 54 | }; |
53 | 55 | ||
54 | static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode) | 56 | static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode) |
@@ -85,7 +87,9 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
85 | switch (mode) { | 87 | switch (mode) { |
86 | case DRM_MODE_DPMS_ON: | 88 | case DRM_MODE_DPMS_ON: |
87 | if (manager_ops && manager_ops->apply) | 89 | if (manager_ops && manager_ops->apply) |
88 | manager_ops->apply(manager->dev); | 90 | if (!exynos_encoder->updated) |
91 | manager_ops->apply(manager->dev); | ||
92 | |||
89 | exynos_drm_connector_power(encoder, mode); | 93 | exynos_drm_connector_power(encoder, mode); |
90 | exynos_encoder->dpms = mode; | 94 | exynos_encoder->dpms = mode; |
91 | break; | 95 | break; |
@@ -94,6 +98,7 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
94 | case DRM_MODE_DPMS_OFF: | 98 | case DRM_MODE_DPMS_OFF: |
95 | exynos_drm_connector_power(encoder, mode); | 99 | exynos_drm_connector_power(encoder, mode); |
96 | exynos_encoder->dpms = mode; | 100 | exynos_encoder->dpms = mode; |
101 | exynos_encoder->updated = false; | ||
97 | break; | 102 | break; |
98 | default: | 103 | default: |
99 | DRM_ERROR("unspecified mode %d\n", mode); | 104 | DRM_ERROR("unspecified mode %d\n", mode); |
@@ -205,13 +210,28 @@ static void exynos_drm_encoder_prepare(struct drm_encoder *encoder) | |||
205 | 210 | ||
206 | static void exynos_drm_encoder_commit(struct drm_encoder *encoder) | 211 | static void exynos_drm_encoder_commit(struct drm_encoder *encoder) |
207 | { | 212 | { |
208 | struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); | 213 | struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); |
214 | struct exynos_drm_manager *manager = exynos_encoder->manager; | ||
209 | struct exynos_drm_manager_ops *manager_ops = manager->ops; | 215 | struct exynos_drm_manager_ops *manager_ops = manager->ops; |
210 | 216 | ||
211 | DRM_DEBUG_KMS("%s\n", __FILE__); | 217 | DRM_DEBUG_KMS("%s\n", __FILE__); |
212 | 218 | ||
213 | if (manager_ops && manager_ops->commit) | 219 | if (manager_ops && manager_ops->commit) |
214 | manager_ops->commit(manager->dev); | 220 | manager_ops->commit(manager->dev); |
221 | |||
222 | /* | ||
223 | * this will avoid one issue that overlay data is updated to | ||
224 | * real hardware two times. | ||
225 | * And this variable will be used to check if the data was | ||
226 | * already updated or not by exynos_drm_encoder_dpms function. | ||
227 | */ | ||
228 | exynos_encoder->updated = true; | ||
229 | |||
230 | /* | ||
231 | * In case of setcrtc, there is no way to update encoder's dpms | ||
232 | * so update it here. | ||
233 | */ | ||
234 | exynos_encoder->dpms = DRM_MODE_DPMS_ON; | ||
215 | } | 235 | } |
216 | 236 | ||
217 | static void exynos_drm_encoder_disable(struct drm_encoder *encoder) | 237 | static void exynos_drm_encoder_disable(struct drm_encoder *encoder) |
@@ -401,19 +421,6 @@ void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data) | |||
401 | manager_ops->dpms(manager->dev, mode); | 421 | manager_ops->dpms(manager->dev, mode); |
402 | 422 | ||
403 | /* | 423 | /* |
404 | * set current mode to new one so that data aren't updated into | ||
405 | * registers by drm_helper_connector_dpms two times. | ||
406 | * | ||
407 | * in case that drm_crtc_helper_set_mode() is called, | ||
408 | * overlay_ops->commit() and manager_ops->commit() callbacks | ||
409 | * can be called two times, first at drm_crtc_helper_set_mode() | ||
410 | * and second at drm_helper_connector_dpms(). | ||
411 | * so with this setting, when drm_helper_connector_dpms() is called | ||
412 | * encoder->funcs->dpms() will be ignored. | ||
413 | */ | ||
414 | exynos_encoder->dpms = mode; | ||
415 | |||
416 | /* | ||
417 | * if this condition is ok then it means that the crtc is already | 424 | * if this condition is ok then it means that the crtc is already |
418 | * detached from encoder and last function for detaching is properly | 425 | * detached from encoder and last function for detaching is properly |
419 | * done, so clear pipe from manager to prevent repeated call. | 426 | * done, so clear pipe from manager to prevent repeated call. |
@@ -506,6 +513,6 @@ void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data) | |||
506 | * because the setting for disabling the overlay will be updated | 513 | * because the setting for disabling the overlay will be updated |
507 | * at vsync. | 514 | * at vsync. |
508 | */ | 515 | */ |
509 | if (overlay_ops->wait_for_vblank) | 516 | if (overlay_ops && overlay_ops->wait_for_vblank) |
510 | overlay_ops->wait_for_vblank(manager->dev); | 517 | overlay_ops->wait_for_vblank(manager->dev); |
511 | } | 518 | } |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index 67eb6ba56edf..e7466c4414cb 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c | |||
@@ -87,7 +87,8 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, | |||
87 | 87 | ||
88 | dev->mode_config.fb_base = (resource_size_t)buffer->dma_addr; | 88 | dev->mode_config.fb_base = (resource_size_t)buffer->dma_addr; |
89 | fbi->screen_base = buffer->kvaddr + offset; | 89 | fbi->screen_base = buffer->kvaddr + offset; |
90 | fbi->fix.smem_start = (unsigned long)(buffer->dma_addr + offset); | 90 | fbi->fix.smem_start = (unsigned long)(page_to_phys(buffer->pages[0]) + |
91 | offset); | ||
91 | fbi->screen_size = size; | 92 | fbi->screen_size = size; |
92 | fbi->fix.smem_len = size; | 93 | fbi->fix.smem_len = size; |
93 | 94 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 130a2b510d4a..e08478f19f1a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c | |||
@@ -61,11 +61,11 @@ struct fimd_driver_data { | |||
61 | unsigned int timing_base; | 61 | unsigned int timing_base; |
62 | }; | 62 | }; |
63 | 63 | ||
64 | struct fimd_driver_data exynos4_fimd_driver_data = { | 64 | static struct fimd_driver_data exynos4_fimd_driver_data = { |
65 | .timing_base = 0x0, | 65 | .timing_base = 0x0, |
66 | }; | 66 | }; |
67 | 67 | ||
68 | struct fimd_driver_data exynos5_fimd_driver_data = { | 68 | static struct fimd_driver_data exynos5_fimd_driver_data = { |
69 | .timing_base = 0x20000, | 69 | .timing_base = 0x20000, |
70 | }; | 70 | }; |
71 | 71 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index 60b877a388c2..862ca1eb2102 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c | |||
@@ -204,7 +204,6 @@ exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
204 | return ret; | 204 | return ret; |
205 | 205 | ||
206 | plane->crtc = crtc; | 206 | plane->crtc = crtc; |
207 | plane->fb = crtc->fb; | ||
208 | 207 | ||
209 | exynos_plane_commit(plane); | 208 | exynos_plane_commit(plane); |
210 | exynos_plane_dpms(plane, DRM_MODE_DPMS_ON); | 209 | exynos_plane_dpms(plane, DRM_MODE_DPMS_ON); |
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 614b2e9ac462..e7fbb823fd8e 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c | |||
@@ -1142,7 +1142,7 @@ static int __devinit mixer_probe(struct platform_device *pdev) | |||
1142 | const struct of_device_id *match; | 1142 | const struct of_device_id *match; |
1143 | match = of_match_node(of_match_ptr(mixer_match_types), | 1143 | match = of_match_node(of_match_ptr(mixer_match_types), |
1144 | pdev->dev.of_node); | 1144 | pdev->dev.of_node); |
1145 | drv = match->data; | 1145 | drv = (struct mixer_drv_data *)match->data; |
1146 | } else { | 1146 | } else { |
1147 | drv = (struct mixer_drv_data *) | 1147 | drv = (struct mixer_drv_data *) |
1148 | platform_get_device_id(pdev)->driver_data; | 1148 | platform_get_device_id(pdev)->driver_data; |
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index c9bfd83dde64..61ae104dca8c 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
@@ -1505,7 +1505,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
1505 | goto put_gmch; | 1505 | goto put_gmch; |
1506 | } | 1506 | } |
1507 | 1507 | ||
1508 | i915_kick_out_firmware_fb(dev_priv); | 1508 | if (drm_core_check_feature(dev, DRIVER_MODESET)) |
1509 | i915_kick_out_firmware_fb(dev_priv); | ||
1509 | 1510 | ||
1510 | pci_set_master(dev->pdev); | 1511 | pci_set_master(dev->pdev); |
1511 | 1512 | ||
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 0ed6baff4b0c..56846ed5ee55 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c | |||
@@ -499,12 +499,8 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) | |||
499 | 499 | ||
500 | edp = find_section(bdb, BDB_EDP); | 500 | edp = find_section(bdb, BDB_EDP); |
501 | if (!edp) { | 501 | if (!edp) { |
502 | if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp.support) { | 502 | if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp.support) |
503 | DRM_DEBUG_KMS("No eDP BDB found but eDP panel " | 503 | DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported.\n"); |
504 | "supported, assume %dbpp panel color " | ||
505 | "depth.\n", | ||
506 | dev_priv->edp.bpp); | ||
507 | } | ||
508 | return; | 504 | return; |
509 | } | 505 | } |
510 | 506 | ||
@@ -657,9 +653,6 @@ init_vbt_defaults(struct drm_i915_private *dev_priv) | |||
657 | dev_priv->lvds_use_ssc = 1; | 653 | dev_priv->lvds_use_ssc = 1; |
658 | dev_priv->lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1); | 654 | dev_priv->lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1); |
659 | DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq); | 655 | DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq); |
660 | |||
661 | /* eDP data */ | ||
662 | dev_priv->edp.bpp = 18; | ||
663 | } | 656 | } |
664 | 657 | ||
665 | static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id) | 658 | static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id) |
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index f78061af7045..6345878ae1e7 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c | |||
@@ -143,7 +143,7 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode) | |||
143 | int old_dpms; | 143 | int old_dpms; |
144 | 144 | ||
145 | /* PCH platforms and VLV only support on/off. */ | 145 | /* PCH platforms and VLV only support on/off. */ |
146 | if (INTEL_INFO(dev)->gen < 5 && mode != DRM_MODE_DPMS_ON) | 146 | if (INTEL_INFO(dev)->gen >= 5 && mode != DRM_MODE_DPMS_ON) |
147 | mode = DRM_MODE_DPMS_OFF; | 147 | mode = DRM_MODE_DPMS_OFF; |
148 | 148 | ||
149 | if (mode == connector->dpms) | 149 | if (mode == connector->dpms) |
@@ -729,7 +729,7 @@ void intel_crt_init(struct drm_device *dev) | |||
729 | 729 | ||
730 | crt->base.type = INTEL_OUTPUT_ANALOG; | 730 | crt->base.type = INTEL_OUTPUT_ANALOG; |
731 | crt->base.cloneable = true; | 731 | crt->base.cloneable = true; |
732 | if (IS_HASWELL(dev)) | 732 | if (IS_HASWELL(dev) || IS_I830(dev)) |
733 | crt->base.crtc_mask = (1 << 0); | 733 | crt->base.crtc_mask = (1 << 0); |
734 | else | 734 | else |
735 | crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); | 735 | crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 461a637f1ef7..b426d44a2b05 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -3841,6 +3841,17 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, | |||
3841 | } | 3841 | } |
3842 | } | 3842 | } |
3843 | 3843 | ||
3844 | if (intel_encoder->type == INTEL_OUTPUT_EDP) { | ||
3845 | /* Use VBT settings if we have an eDP panel */ | ||
3846 | unsigned int edp_bpc = dev_priv->edp.bpp / 3; | ||
3847 | |||
3848 | if (edp_bpc && edp_bpc < display_bpc) { | ||
3849 | DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc); | ||
3850 | display_bpc = edp_bpc; | ||
3851 | } | ||
3852 | continue; | ||
3853 | } | ||
3854 | |||
3844 | /* | 3855 | /* |
3845 | * HDMI is either 12 or 8, so if the display lets 10bpc sneak | 3856 | * HDMI is either 12 or 8, so if the display lets 10bpc sneak |
3846 | * through, clamp it down. (Note: >12bpc will be caught below.) | 3857 | * through, clamp it down. (Note: >12bpc will be caught below.) |
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 495625914e4a..d7bc817f51a0 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c | |||
@@ -341,9 +341,17 @@ static int intel_overlay_off(struct intel_overlay *overlay) | |||
341 | intel_ring_emit(ring, flip_addr); | 341 | intel_ring_emit(ring, flip_addr); |
342 | intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); | 342 | intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); |
343 | /* turn overlay off */ | 343 | /* turn overlay off */ |
344 | intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF); | 344 | if (IS_I830(dev)) { |
345 | intel_ring_emit(ring, flip_addr); | 345 | /* Workaround: Don't disable the overlay fully, since otherwise |
346 | intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); | 346 | * it dies on the next OVERLAY_ON cmd. */ |
347 | intel_ring_emit(ring, MI_NOOP); | ||
348 | intel_ring_emit(ring, MI_NOOP); | ||
349 | intel_ring_emit(ring, MI_NOOP); | ||
350 | } else { | ||
351 | intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF); | ||
352 | intel_ring_emit(ring, flip_addr); | ||
353 | intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); | ||
354 | } | ||
347 | intel_ring_advance(ring); | 355 | intel_ring_advance(ring); |
348 | 356 | ||
349 | return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail); | 357 | return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail); |
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index e019b2369861..e2aacd329545 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c | |||
@@ -435,7 +435,7 @@ int intel_panel_setup_backlight(struct drm_device *dev) | |||
435 | props.type = BACKLIGHT_RAW; | 435 | props.type = BACKLIGHT_RAW; |
436 | props.max_brightness = _intel_panel_get_max_backlight(dev); | 436 | props.max_brightness = _intel_panel_get_max_backlight(dev); |
437 | if (props.max_brightness == 0) { | 437 | if (props.max_brightness == 0) { |
438 | DRM_ERROR("Failed to get maximum backlight value\n"); | 438 | DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n"); |
439 | return -ENODEV; | 439 | return -ENODEV; |
440 | } | 440 | } |
441 | dev_priv->backlight = | 441 | dev_priv->backlight = |
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 72f41aaa71ff..442968f8b201 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
@@ -2373,15 +2373,9 @@ int intel_enable_rc6(const struct drm_device *dev) | |||
2373 | if (i915_enable_rc6 >= 0) | 2373 | if (i915_enable_rc6 >= 0) |
2374 | return i915_enable_rc6; | 2374 | return i915_enable_rc6; |
2375 | 2375 | ||
2376 | if (INTEL_INFO(dev)->gen == 5) { | 2376 | /* Disable RC6 on Ironlake */ |
2377 | #ifdef CONFIG_INTEL_IOMMU | 2377 | if (INTEL_INFO(dev)->gen == 5) |
2378 | /* Disable rc6 on ilk if VT-d is on. */ | 2378 | return 0; |
2379 | if (intel_iommu_gfx_mapped) | ||
2380 | return false; | ||
2381 | #endif | ||
2382 | DRM_DEBUG_DRIVER("Ironlake: only RC6 available\n"); | ||
2383 | return INTEL_RC6_ENABLE; | ||
2384 | } | ||
2385 | 2379 | ||
2386 | if (IS_HASWELL(dev)) { | 2380 | if (IS_HASWELL(dev)) { |
2387 | DRM_DEBUG_DRIVER("Haswell: only RC6 available\n"); | 2381 | DRM_DEBUG_DRIVER("Haswell: only RC6 available\n"); |
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index c01d97db0061..a6ac0b416964 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
@@ -894,6 +894,45 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo) | |||
894 | } | 894 | } |
895 | #endif | 895 | #endif |
896 | 896 | ||
897 | static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo, | ||
898 | unsigned if_index, uint8_t tx_rate, | ||
899 | uint8_t *data, unsigned length) | ||
900 | { | ||
901 | uint8_t set_buf_index[2] = { if_index, 0 }; | ||
902 | uint8_t hbuf_size, tmp[8]; | ||
903 | int i; | ||
904 | |||
905 | if (!intel_sdvo_set_value(intel_sdvo, | ||
906 | SDVO_CMD_SET_HBUF_INDEX, | ||
907 | set_buf_index, 2)) | ||
908 | return false; | ||
909 | |||
910 | if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HBUF_INFO, | ||
911 | &hbuf_size, 1)) | ||
912 | return false; | ||
913 | |||
914 | /* Buffer size is 0 based, hooray! */ | ||
915 | hbuf_size++; | ||
916 | |||
917 | DRM_DEBUG_KMS("writing sdvo hbuf: %i, hbuf_size %i, hbuf_size: %i\n", | ||
918 | if_index, length, hbuf_size); | ||
919 | |||
920 | for (i = 0; i < hbuf_size; i += 8) { | ||
921 | memset(tmp, 0, 8); | ||
922 | if (i < length) | ||
923 | memcpy(tmp, data + i, min_t(unsigned, 8, length - i)); | ||
924 | |||
925 | if (!intel_sdvo_set_value(intel_sdvo, | ||
926 | SDVO_CMD_SET_HBUF_DATA, | ||
927 | tmp, 8)) | ||
928 | return false; | ||
929 | } | ||
930 | |||
931 | return intel_sdvo_set_value(intel_sdvo, | ||
932 | SDVO_CMD_SET_HBUF_TXRATE, | ||
933 | &tx_rate, 1); | ||
934 | } | ||
935 | |||
897 | static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) | 936 | static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) |
898 | { | 937 | { |
899 | struct dip_infoframe avi_if = { | 938 | struct dip_infoframe avi_if = { |
@@ -901,11 +940,7 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) | |||
901 | .ver = DIP_VERSION_AVI, | 940 | .ver = DIP_VERSION_AVI, |
902 | .len = DIP_LEN_AVI, | 941 | .len = DIP_LEN_AVI, |
903 | }; | 942 | }; |
904 | uint8_t tx_rate = SDVO_HBUF_TX_VSYNC; | ||
905 | uint8_t set_buf_index[2] = { 1, 0 }; | ||
906 | uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)]; | 943 | uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)]; |
907 | uint64_t *data = (uint64_t *)sdvo_data; | ||
908 | unsigned i; | ||
909 | 944 | ||
910 | intel_dip_infoframe_csum(&avi_if); | 945 | intel_dip_infoframe_csum(&avi_if); |
911 | 946 | ||
@@ -915,22 +950,9 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) | |||
915 | sdvo_data[3] = avi_if.checksum; | 950 | sdvo_data[3] = avi_if.checksum; |
916 | memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi)); | 951 | memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi)); |
917 | 952 | ||
918 | if (!intel_sdvo_set_value(intel_sdvo, | 953 | return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF, |
919 | SDVO_CMD_SET_HBUF_INDEX, | 954 | SDVO_HBUF_TX_VSYNC, |
920 | set_buf_index, 2)) | 955 | sdvo_data, sizeof(sdvo_data)); |
921 | return false; | ||
922 | |||
923 | for (i = 0; i < sizeof(sdvo_data); i += 8) { | ||
924 | if (!intel_sdvo_set_value(intel_sdvo, | ||
925 | SDVO_CMD_SET_HBUF_DATA, | ||
926 | data, 8)) | ||
927 | return false; | ||
928 | data++; | ||
929 | } | ||
930 | |||
931 | return intel_sdvo_set_value(intel_sdvo, | ||
932 | SDVO_CMD_SET_HBUF_TXRATE, | ||
933 | &tx_rate, 1); | ||
934 | } | 956 | } |
935 | 957 | ||
936 | static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo) | 958 | static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo) |
@@ -2179,7 +2201,6 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) | |||
2179 | connector->connector_type = DRM_MODE_CONNECTOR_HDMIA; | 2201 | connector->connector_type = DRM_MODE_CONNECTOR_HDMIA; |
2180 | intel_sdvo->is_hdmi = true; | 2202 | intel_sdvo->is_hdmi = true; |
2181 | } | 2203 | } |
2182 | intel_sdvo->base.cloneable = true; | ||
2183 | 2204 | ||
2184 | intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); | 2205 | intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); |
2185 | if (intel_sdvo->is_hdmi) | 2206 | if (intel_sdvo->is_hdmi) |
@@ -2210,7 +2231,6 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type) | |||
2210 | 2231 | ||
2211 | intel_sdvo->is_tv = true; | 2232 | intel_sdvo->is_tv = true; |
2212 | intel_sdvo->base.needs_tv_clock = true; | 2233 | intel_sdvo->base.needs_tv_clock = true; |
2213 | intel_sdvo->base.cloneable = false; | ||
2214 | 2234 | ||
2215 | intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); | 2235 | intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); |
2216 | 2236 | ||
@@ -2253,8 +2273,6 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device) | |||
2253 | intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1; | 2273 | intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1; |
2254 | } | 2274 | } |
2255 | 2275 | ||
2256 | intel_sdvo->base.cloneable = true; | ||
2257 | |||
2258 | intel_sdvo_connector_init(intel_sdvo_connector, | 2276 | intel_sdvo_connector_init(intel_sdvo_connector, |
2259 | intel_sdvo); | 2277 | intel_sdvo); |
2260 | return true; | 2278 | return true; |
@@ -2285,9 +2303,6 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) | |||
2285 | intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1; | 2303 | intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1; |
2286 | } | 2304 | } |
2287 | 2305 | ||
2288 | /* SDVO LVDS is not cloneable because the input mode gets adjusted by the encoder */ | ||
2289 | intel_sdvo->base.cloneable = false; | ||
2290 | |||
2291 | intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); | 2306 | intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); |
2292 | if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector)) | 2307 | if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector)) |
2293 | goto err; | 2308 | goto err; |
@@ -2360,6 +2375,18 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags) | |||
2360 | return true; | 2375 | return true; |
2361 | } | 2376 | } |
2362 | 2377 | ||
2378 | static void intel_sdvo_output_cleanup(struct intel_sdvo *intel_sdvo) | ||
2379 | { | ||
2380 | struct drm_device *dev = intel_sdvo->base.base.dev; | ||
2381 | struct drm_connector *connector, *tmp; | ||
2382 | |||
2383 | list_for_each_entry_safe(connector, tmp, | ||
2384 | &dev->mode_config.connector_list, head) { | ||
2385 | if (intel_attached_encoder(connector) == &intel_sdvo->base) | ||
2386 | intel_sdvo_destroy(connector); | ||
2387 | } | ||
2388 | } | ||
2389 | |||
2363 | static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo, | 2390 | static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo, |
2364 | struct intel_sdvo_connector *intel_sdvo_connector, | 2391 | struct intel_sdvo_connector *intel_sdvo_connector, |
2365 | int type) | 2392 | int type) |
@@ -2683,9 +2710,20 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) | |||
2683 | intel_sdvo->caps.output_flags) != true) { | 2710 | intel_sdvo->caps.output_flags) != true) { |
2684 | DRM_DEBUG_KMS("SDVO output failed to setup on %s\n", | 2711 | DRM_DEBUG_KMS("SDVO output failed to setup on %s\n", |
2685 | SDVO_NAME(intel_sdvo)); | 2712 | SDVO_NAME(intel_sdvo)); |
2686 | goto err; | 2713 | /* Output_setup can leave behind connectors! */ |
2714 | goto err_output; | ||
2687 | } | 2715 | } |
2688 | 2716 | ||
2717 | /* | ||
2718 | * Cloning SDVO with anything is often impossible, since the SDVO | ||
2719 | * encoder can request a special input timing mode. And even if that's | ||
2720 | * not the case we have evidence that cloning a plain unscaled mode with | ||
2721 | * VGA doesn't really work. Furthermore the cloning flags are way too | ||
2722 | * simplistic anyway to express such constraints, so just give up on | ||
2723 | * cloning for SDVO encoders. | ||
2724 | */ | ||
2725 | intel_sdvo->base.cloneable = false; | ||
2726 | |||
2689 | /* Only enable the hotplug irq if we need it, to work around noisy | 2727 | /* Only enable the hotplug irq if we need it, to work around noisy |
2690 | * hotplug lines. | 2728 | * hotplug lines. |
2691 | */ | 2729 | */ |
@@ -2696,12 +2734,12 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) | |||
2696 | 2734 | ||
2697 | /* Set the input timing to the screen. Assume always input 0. */ | 2735 | /* Set the input timing to the screen. Assume always input 0. */ |
2698 | if (!intel_sdvo_set_target_input(intel_sdvo)) | 2736 | if (!intel_sdvo_set_target_input(intel_sdvo)) |
2699 | goto err; | 2737 | goto err_output; |
2700 | 2738 | ||
2701 | if (!intel_sdvo_get_input_pixel_clock_range(intel_sdvo, | 2739 | if (!intel_sdvo_get_input_pixel_clock_range(intel_sdvo, |
2702 | &intel_sdvo->pixel_clock_min, | 2740 | &intel_sdvo->pixel_clock_min, |
2703 | &intel_sdvo->pixel_clock_max)) | 2741 | &intel_sdvo->pixel_clock_max)) |
2704 | goto err; | 2742 | goto err_output; |
2705 | 2743 | ||
2706 | DRM_DEBUG_KMS("%s device VID/DID: %02X:%02X.%02X, " | 2744 | DRM_DEBUG_KMS("%s device VID/DID: %02X:%02X.%02X, " |
2707 | "clock range %dMHz - %dMHz, " | 2745 | "clock range %dMHz - %dMHz, " |
@@ -2721,6 +2759,9 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) | |||
2721 | (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N'); | 2759 | (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N'); |
2722 | return true; | 2760 | return true; |
2723 | 2761 | ||
2762 | err_output: | ||
2763 | intel_sdvo_output_cleanup(intel_sdvo); | ||
2764 | |||
2724 | err: | 2765 | err: |
2725 | drm_encoder_cleanup(&intel_encoder->base); | 2766 | drm_encoder_cleanup(&intel_encoder->base); |
2726 | i2c_del_adapter(&intel_sdvo->ddc); | 2767 | i2c_del_adapter(&intel_sdvo->ddc); |
diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h index 9d030142ee43..770bdd6ecd9f 100644 --- a/drivers/gpu/drm/i915/intel_sdvo_regs.h +++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h | |||
@@ -708,6 +708,8 @@ struct intel_sdvo_enhancements_arg { | |||
708 | #define SDVO_CMD_SET_AUDIO_STAT 0x91 | 708 | #define SDVO_CMD_SET_AUDIO_STAT 0x91 |
709 | #define SDVO_CMD_GET_AUDIO_STAT 0x92 | 709 | #define SDVO_CMD_GET_AUDIO_STAT 0x92 |
710 | #define SDVO_CMD_SET_HBUF_INDEX 0x93 | 710 | #define SDVO_CMD_SET_HBUF_INDEX 0x93 |
711 | #define SDVO_HBUF_INDEX_ELD 0 | ||
712 | #define SDVO_HBUF_INDEX_AVI_IF 1 | ||
711 | #define SDVO_CMD_GET_HBUF_INDEX 0x94 | 713 | #define SDVO_CMD_GET_HBUF_INDEX 0x94 |
712 | #define SDVO_CMD_GET_HBUF_INFO 0x95 | 714 | #define SDVO_CMD_GET_HBUF_INFO 0x95 |
713 | #define SDVO_CMD_SET_HBUF_AV_SPLIT 0x96 | 715 | #define SDVO_CMD_SET_HBUF_AV_SPLIT 0x96 |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c index 16a9afb1060b..15b182c84ce8 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c | |||
@@ -22,6 +22,8 @@ | |||
22 | * Authors: Ben Skeggs | 22 | * Authors: Ben Skeggs |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <subdev/bar.h> | ||
26 | |||
25 | #include <engine/software.h> | 27 | #include <engine/software.h> |
26 | #include <engine/disp.h> | 28 | #include <engine/disp.h> |
27 | 29 | ||
@@ -37,6 +39,7 @@ nv50_disp_sclass[] = { | |||
37 | static void | 39 | static void |
38 | nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc) | 40 | nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc) |
39 | { | 41 | { |
42 | struct nouveau_bar *bar = nouveau_bar(priv); | ||
40 | struct nouveau_disp *disp = &priv->base; | 43 | struct nouveau_disp *disp = &priv->base; |
41 | struct nouveau_software_chan *chan, *temp; | 44 | struct nouveau_software_chan *chan, *temp; |
42 | unsigned long flags; | 45 | unsigned long flags; |
@@ -46,19 +49,25 @@ nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc) | |||
46 | if (chan->vblank.crtc != crtc) | 49 | if (chan->vblank.crtc != crtc) |
47 | continue; | 50 | continue; |
48 | 51 | ||
49 | nv_wr32(priv, 0x001704, chan->vblank.channel); | 52 | if (nv_device(priv)->chipset >= 0xc0) { |
50 | nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma); | 53 | nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel); |
51 | 54 | bar->flush(bar); | |
52 | if (nv_device(priv)->chipset == 0x50) { | 55 | nv_wr32(priv, 0x06000c, |
53 | nv_wr32(priv, 0x001570, chan->vblank.offset); | 56 | upper_32_bits(chan->vblank.offset)); |
54 | nv_wr32(priv, 0x001574, chan->vblank.value); | 57 | nv_wr32(priv, 0x060010, |
58 | lower_32_bits(chan->vblank.offset)); | ||
59 | nv_wr32(priv, 0x060014, chan->vblank.value); | ||
55 | } else { | 60 | } else { |
56 | if (nv_device(priv)->chipset >= 0xc0) { | 61 | nv_wr32(priv, 0x001704, chan->vblank.channel); |
57 | nv_wr32(priv, 0x06000c, | 62 | nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma); |
58 | upper_32_bits(chan->vblank.offset)); | 63 | bar->flush(bar); |
64 | if (nv_device(priv)->chipset == 0x50) { | ||
65 | nv_wr32(priv, 0x001570, chan->vblank.offset); | ||
66 | nv_wr32(priv, 0x001574, chan->vblank.value); | ||
67 | } else { | ||
68 | nv_wr32(priv, 0x060010, chan->vblank.offset); | ||
69 | nv_wr32(priv, 0x060014, chan->vblank.value); | ||
59 | } | 70 | } |
60 | nv_wr32(priv, 0x060010, chan->vblank.offset); | ||
61 | nv_wr32(priv, 0x060014, chan->vblank.value); | ||
62 | } | 71 | } |
63 | 72 | ||
64 | list_del(&chan->vblank.head); | 73 | list_del(&chan->vblank.head); |
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c index e45035efb8ca..7bbb1e1b7a8d 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c | |||
@@ -669,21 +669,27 @@ nv40_grctx_fill(struct nouveau_device *device, struct nouveau_gpuobj *mem) | |||
669 | }); | 669 | }); |
670 | } | 670 | } |
671 | 671 | ||
672 | void | 672 | int |
673 | nv40_grctx_init(struct nouveau_device *device, u32 *size) | 673 | nv40_grctx_init(struct nouveau_device *device, u32 *size) |
674 | { | 674 | { |
675 | u32 ctxprog[256], i; | 675 | u32 *ctxprog = kmalloc(256 * 4, GFP_KERNEL), i; |
676 | struct nouveau_grctx ctx = { | 676 | struct nouveau_grctx ctx = { |
677 | .device = device, | 677 | .device = device, |
678 | .mode = NOUVEAU_GRCTX_PROG, | 678 | .mode = NOUVEAU_GRCTX_PROG, |
679 | .data = ctxprog, | 679 | .data = ctxprog, |
680 | .ctxprog_max = ARRAY_SIZE(ctxprog) | 680 | .ctxprog_max = 256, |
681 | }; | 681 | }; |
682 | 682 | ||
683 | if (!ctxprog) | ||
684 | return -ENOMEM; | ||
685 | |||
683 | nv40_grctx_generate(&ctx); | 686 | nv40_grctx_generate(&ctx); |
684 | 687 | ||
685 | nv_wr32(device, 0x400324, 0); | 688 | nv_wr32(device, 0x400324, 0); |
686 | for (i = 0; i < ctx.ctxprog_len; i++) | 689 | for (i = 0; i < ctx.ctxprog_len; i++) |
687 | nv_wr32(device, 0x400328, ctxprog[i]); | 690 | nv_wr32(device, 0x400328, ctxprog[i]); |
688 | *size = ctx.ctxvals_pos * 4; | 691 | *size = ctx.ctxvals_pos * 4; |
692 | |||
693 | kfree(ctxprog); | ||
694 | return 0; | ||
689 | } | 695 | } |
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c index 8d0021049ec0..cc6574eeb80e 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c | |||
@@ -156,8 +156,8 @@ nv40_graph_context_ctor(struct nouveau_object *parent, | |||
156 | static int | 156 | static int |
157 | nv40_graph_context_fini(struct nouveau_object *object, bool suspend) | 157 | nv40_graph_context_fini(struct nouveau_object *object, bool suspend) |
158 | { | 158 | { |
159 | struct nv04_graph_priv *priv = (void *)object->engine; | 159 | struct nv40_graph_priv *priv = (void *)object->engine; |
160 | struct nv04_graph_chan *chan = (void *)object; | 160 | struct nv40_graph_chan *chan = (void *)object; |
161 | u32 inst = 0x01000000 | nv_gpuobj(chan)->addr >> 4; | 161 | u32 inst = 0x01000000 | nv_gpuobj(chan)->addr >> 4; |
162 | int ret = 0; | 162 | int ret = 0; |
163 | 163 | ||
@@ -346,7 +346,9 @@ nv40_graph_init(struct nouveau_object *object) | |||
346 | return ret; | 346 | return ret; |
347 | 347 | ||
348 | /* generate and upload context program */ | 348 | /* generate and upload context program */ |
349 | nv40_grctx_init(nv_device(priv), &priv->size); | 349 | ret = nv40_grctx_init(nv_device(priv), &priv->size); |
350 | if (ret) | ||
351 | return ret; | ||
350 | 352 | ||
351 | /* No context present currently */ | 353 | /* No context present currently */ |
352 | nv_wr32(priv, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); | 354 | nv_wr32(priv, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); |
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h index d2ac975afc2e..7da35a4e7970 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h | |||
@@ -15,7 +15,7 @@ nv44_graph_class(void *priv) | |||
15 | return !(0x0baf & (1 << (device->chipset & 0x0f))); | 15 | return !(0x0baf & (1 << (device->chipset & 0x0f))); |
16 | } | 16 | } |
17 | 17 | ||
18 | void nv40_grctx_init(struct nouveau_device *, u32 *size); | 18 | int nv40_grctx_init(struct nouveau_device *, u32 *size); |
19 | void nv40_grctx_fill(struct nouveau_device *, struct nouveau_gpuobj *); | 19 | void nv40_grctx_fill(struct nouveau_device *, struct nouveau_gpuobj *); |
20 | 20 | ||
21 | #endif | 21 | #endif |
diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c index 12418574efea..f7c581ad1991 100644 --- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c | |||
@@ -38,7 +38,7 @@ struct nv40_mpeg_priv { | |||
38 | }; | 38 | }; |
39 | 39 | ||
40 | struct nv40_mpeg_chan { | 40 | struct nv40_mpeg_chan { |
41 | struct nouveau_mpeg base; | 41 | struct nouveau_mpeg_chan base; |
42 | }; | 42 | }; |
43 | 43 | ||
44 | /******************************************************************************* | 44 | /******************************************************************************* |
diff --git a/drivers/gpu/drm/nouveau/core/include/core/object.h b/drivers/gpu/drm/nouveau/core/include/core/object.h index 818feabbf4a0..486f1a9217fd 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/object.h +++ b/drivers/gpu/drm/nouveau/core/include/core/object.h | |||
@@ -175,14 +175,18 @@ nv_mo32(void *obj, u32 addr, u32 mask, u32 data) | |||
175 | return temp; | 175 | return temp; |
176 | } | 176 | } |
177 | 177 | ||
178 | static inline bool | 178 | static inline int |
179 | nv_strncmp(void *obj, u32 addr, u32 len, const char *str) | 179 | nv_memcmp(void *obj, u32 addr, const char *str, u32 len) |
180 | { | 180 | { |
181 | unsigned char c1, c2; | ||
182 | |||
181 | while (len--) { | 183 | while (len--) { |
182 | if (nv_ro08(obj, addr++) != *(str++)) | 184 | c1 = nv_ro08(obj, addr++); |
183 | return false; | 185 | c2 = *(str++); |
186 | if (c1 != c2) | ||
187 | return c1 - c2; | ||
184 | } | 188 | } |
185 | return true; | 189 | return 0; |
186 | } | 190 | } |
187 | 191 | ||
188 | #endif | 192 | #endif |
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/clock.h b/drivers/gpu/drm/nouveau/core/include/subdev/clock.h index 39e73b91d360..41b7a6a76f19 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/clock.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/clock.h | |||
@@ -54,6 +54,7 @@ int nv04_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *, | |||
54 | int clk, struct nouveau_pll_vals *); | 54 | int clk, struct nouveau_pll_vals *); |
55 | int nv04_clock_pll_prog(struct nouveau_clock *, u32 reg1, | 55 | int nv04_clock_pll_prog(struct nouveau_clock *, u32 reg1, |
56 | struct nouveau_pll_vals *); | 56 | struct nouveau_pll_vals *); |
57 | 57 | int nva3_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *, | |
58 | int clk, struct nouveau_pll_vals *); | ||
58 | 59 | ||
59 | #endif | 60 | #endif |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c b/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c index 7d750382a833..c51197157749 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c | |||
@@ -64,7 +64,7 @@ dcb_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) | |||
64 | } | 64 | } |
65 | } else | 65 | } else |
66 | if (*ver >= 0x15) { | 66 | if (*ver >= 0x15) { |
67 | if (!nv_strncmp(bios, dcb - 7, 7, "DEV_REC")) { | 67 | if (!nv_memcmp(bios, dcb - 7, "DEV_REC", 7)) { |
68 | u16 i2c = nv_ro16(bios, dcb + 2); | 68 | u16 i2c = nv_ro16(bios, dcb + 2); |
69 | *hdr = 4; | 69 | *hdr = 4; |
70 | *cnt = (i2c - dcb) / 10; | 70 | *cnt = (i2c - dcb) / 10; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c index cc8d7d162d7c..9068c98b96f6 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c | |||
@@ -66,6 +66,24 @@ nva3_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) | |||
66 | return ret; | 66 | return ret; |
67 | } | 67 | } |
68 | 68 | ||
69 | int | ||
70 | nva3_clock_pll_calc(struct nouveau_clock *clock, struct nvbios_pll *info, | ||
71 | int clk, struct nouveau_pll_vals *pv) | ||
72 | { | ||
73 | int ret, N, M, P; | ||
74 | |||
75 | ret = nva3_pll_calc(clock, info, clk, &N, NULL, &M, &P); | ||
76 | |||
77 | if (ret > 0) { | ||
78 | pv->refclk = info->refclk; | ||
79 | pv->N1 = N; | ||
80 | pv->M1 = M; | ||
81 | pv->log2P = P; | ||
82 | } | ||
83 | return ret; | ||
84 | } | ||
85 | |||
86 | |||
69 | static int | 87 | static int |
70 | nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | 88 | nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, |
71 | struct nouveau_oclass *oclass, void *data, u32 size, | 89 | struct nouveau_oclass *oclass, void *data, u32 size, |
@@ -80,6 +98,7 @@ nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
80 | return ret; | 98 | return ret; |
81 | 99 | ||
82 | priv->base.pll_set = nva3_clock_pll_set; | 100 | priv->base.pll_set = nva3_clock_pll_set; |
101 | priv->base.pll_calc = nva3_clock_pll_calc; | ||
83 | return 0; | 102 | return 0; |
84 | } | 103 | } |
85 | 104 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c index 5ccce0b17bf3..f6962c9b6c36 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c | |||
@@ -79,6 +79,7 @@ nvc0_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
79 | return ret; | 79 | return ret; |
80 | 80 | ||
81 | priv->base.pll_set = nvc0_clock_pll_set; | 81 | priv->base.pll_set = nvc0_clock_pll_set; |
82 | priv->base.pll_calc = nva3_clock_pll_calc; | ||
82 | return 0; | 83 | return 0; |
83 | } | 84 | } |
84 | 85 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c index 49050d991e75..9474cfca6e4c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c | |||
@@ -67,7 +67,7 @@ nv41_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) | |||
67 | static void | 67 | static void |
68 | nv41_vm_flush(struct nouveau_vm *vm) | 68 | nv41_vm_flush(struct nouveau_vm *vm) |
69 | { | 69 | { |
70 | struct nv04_vm_priv *priv = (void *)vm->vmm; | 70 | struct nv04_vmmgr_priv *priv = (void *)vm->vmm; |
71 | 71 | ||
72 | mutex_lock(&nv_subdev(priv)->mutex); | 72 | mutex_lock(&nv_subdev(priv)->mutex); |
73 | nv_wr32(priv, 0x100810, 0x00000022); | 73 | nv_wr32(priv, 0x100810, 0x00000022); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c index cc79c796afee..cbf1fc60a386 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c | |||
@@ -241,6 +241,10 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) | |||
241 | 241 | ||
242 | if (unlikely(!abi16)) | 242 | if (unlikely(!abi16)) |
243 | return -ENOMEM; | 243 | return -ENOMEM; |
244 | |||
245 | if (!drm->channel) | ||
246 | return nouveau_abi16_put(abi16, -ENODEV); | ||
247 | |||
244 | client = nv_client(abi16->client); | 248 | client = nv_client(abi16->client); |
245 | 249 | ||
246 | if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0) | 250 | if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0) |
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 9a6e2cb282dc..d3595b23434a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c | |||
@@ -355,7 +355,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) | |||
355 | * valid - it's not (rh#613284) | 355 | * valid - it's not (rh#613284) |
356 | */ | 356 | */ |
357 | if (nv_encoder->dcb->lvdsconf.use_acpi_for_edid) { | 357 | if (nv_encoder->dcb->lvdsconf.use_acpi_for_edid) { |
358 | if (!(nv_connector->edid = nouveau_acpi_edid(dev, connector))) { | 358 | if ((nv_connector->edid = nouveau_acpi_edid(dev, connector))) { |
359 | status = connector_status_connected; | 359 | status = connector_status_connected; |
360 | goto out; | 360 | goto out; |
361 | } | 361 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 0910125cbbc3..8503b2ea570a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c | |||
@@ -129,7 +129,8 @@ nouveau_accel_init(struct nouveau_drm *drm) | |||
129 | 129 | ||
130 | /* initialise synchronisation routines */ | 130 | /* initialise synchronisation routines */ |
131 | if (device->card_type < NV_10) ret = nv04_fence_create(drm); | 131 | if (device->card_type < NV_10) ret = nv04_fence_create(drm); |
132 | else if (device->chipset < 0x84) ret = nv10_fence_create(drm); | 132 | else if (device->card_type < NV_50) ret = nv10_fence_create(drm); |
133 | else if (device->chipset < 0x84) ret = nv50_fence_create(drm); | ||
133 | else if (device->card_type < NV_C0) ret = nv84_fence_create(drm); | 134 | else if (device->card_type < NV_C0) ret = nv84_fence_create(drm); |
134 | else ret = nvc0_fence_create(drm); | 135 | else ret = nvc0_fence_create(drm); |
135 | if (ret) { | 136 | if (ret) { |
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 2e566e123e9e..24d932f53203 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
@@ -1697,34 +1697,22 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) | |||
1697 | DRM_ERROR("unable to allocate a PPLL\n"); | 1697 | DRM_ERROR("unable to allocate a PPLL\n"); |
1698 | return ATOM_PPLL_INVALID; | 1698 | return ATOM_PPLL_INVALID; |
1699 | } else { | 1699 | } else { |
1700 | if (ASIC_IS_AVIVO(rdev)) { | 1700 | /* on pre-R5xx asics, the crtc to pll mapping is hardcoded */ |
1701 | /* in DP mode, the DP ref clock can come from either PPLL | 1701 | /* some atombios (observed in some DCE2/DCE3) code have a bug, |
1702 | * depending on the asic: | 1702 | * the matching btw pll and crtc is done through |
1703 | * DCE3: PPLL1 or PPLL2 | 1703 | * PCLK_CRTC[1|2]_CNTL (0x480/0x484) but atombios code use the |
1704 | */ | 1704 | * pll (1 or 2) to select which register to write. ie if using |
1705 | if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) { | 1705 | * pll1 it will use PCLK_CRTC1_CNTL (0x480) and if using pll2 |
1706 | /* use the same PPLL for all DP monitors */ | 1706 | * it will use PCLK_CRTC2_CNTL (0x484), it then use crtc id to |
1707 | pll = radeon_get_shared_dp_ppll(crtc); | 1707 | * choose which value to write. Which is reverse order from |
1708 | if (pll != ATOM_PPLL_INVALID) | 1708 | * register logic. So only case that works is when pllid is |
1709 | return pll; | 1709 | * same as crtcid or when both pll and crtc are enabled and |
1710 | } else { | 1710 | * both use same clock. |
1711 | /* use the same PPLL for all monitors with the same clock */ | 1711 | * |
1712 | pll = radeon_get_shared_nondp_ppll(crtc); | 1712 | * So just return crtc id as if crtc and pll were hard linked |
1713 | if (pll != ATOM_PPLL_INVALID) | 1713 | * together even if they aren't |
1714 | return pll; | 1714 | */ |
1715 | } | 1715 | return radeon_crtc->crtc_id; |
1716 | /* all other cases */ | ||
1717 | pll_in_use = radeon_get_pll_use_mask(crtc); | ||
1718 | if (!(pll_in_use & (1 << ATOM_PPLL1))) | ||
1719 | return ATOM_PPLL1; | ||
1720 | if (!(pll_in_use & (1 << ATOM_PPLL2))) | ||
1721 | return ATOM_PPLL2; | ||
1722 | DRM_ERROR("unable to allocate a PPLL\n"); | ||
1723 | return ATOM_PPLL_INVALID; | ||
1724 | } else { | ||
1725 | /* on pre-R5xx asics, the crtc to pll mapping is hardcoded */ | ||
1726 | return radeon_crtc->crtc_id; | ||
1727 | } | ||
1728 | } | 1716 | } |
1729 | } | 1717 | } |
1730 | 1718 | ||
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index ba498f8e47a2..010bae19554a 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c | |||
@@ -1625,7 +1625,7 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) | |||
1625 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); | 1625 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); |
1626 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); | 1626 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); |
1627 | /* some early dce3.2 boards have a bug in their transmitter control table */ | 1627 | /* some early dce3.2 boards have a bug in their transmitter control table */ |
1628 | if ((rdev->family != CHIP_RV710) || (rdev->family != CHIP_RV730)) | 1628 | if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730)) |
1629 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); | 1629 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); |
1630 | } | 1630 | } |
1631 | if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { | 1631 | if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { |
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 14313ad43b76..219942c660d7 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
@@ -1330,6 +1330,8 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav | |||
1330 | break; | 1330 | break; |
1331 | udelay(1); | 1331 | udelay(1); |
1332 | } | 1332 | } |
1333 | } else { | ||
1334 | save->crtc_enabled[i] = false; | ||
1333 | } | 1335 | } |
1334 | } | 1336 | } |
1335 | 1337 | ||
@@ -1372,7 +1374,7 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s | |||
1372 | WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN); | 1374 | WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN); |
1373 | 1375 | ||
1374 | for (i = 0; i < rdev->num_crtc; i++) { | 1376 | for (i = 0; i < rdev->num_crtc; i++) { |
1375 | if (save->crtc_enabled) { | 1377 | if (save->crtc_enabled[i]) { |
1376 | if (ASIC_IS_DCE6(rdev)) { | 1378 | if (ASIC_IS_DCE6(rdev)) { |
1377 | tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); | 1379 | tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); |
1378 | tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; | 1380 | tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; |
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 30271b641913..c042e497e450 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c | |||
@@ -264,7 +264,7 @@ static int evergreen_surface_check_2d(struct radeon_cs_parser *p, | |||
264 | /* macro tile width & height */ | 264 | /* macro tile width & height */ |
265 | palign = (8 * surf->bankw * track->npipes) * surf->mtilea; | 265 | palign = (8 * surf->bankw * track->npipes) * surf->mtilea; |
266 | halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea; | 266 | halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea; |
267 | mtileb = (palign / 8) * (halign / 8) * tileb;; | 267 | mtileb = (palign / 8) * (halign / 8) * tileb; |
268 | mtile_pr = surf->nbx / palign; | 268 | mtile_pr = surf->nbx / palign; |
269 | mtile_ps = (mtile_pr * surf->nby) / halign; | 269 | mtile_ps = (mtile_pr * surf->nby) / halign; |
270 | surf->layer_size = mtile_ps * mtileb * slice_pt; | 270 | surf->layer_size = mtile_ps * mtileb * slice_pt; |
@@ -2725,6 +2725,9 @@ static bool evergreen_vm_reg_valid(u32 reg) | |||
2725 | /* check config regs */ | 2725 | /* check config regs */ |
2726 | switch (reg) { | 2726 | switch (reg) { |
2727 | case GRBM_GFX_INDEX: | 2727 | case GRBM_GFX_INDEX: |
2728 | case CP_STRMOUT_CNTL: | ||
2729 | case CP_COHER_CNTL: | ||
2730 | case CP_COHER_SIZE: | ||
2728 | case VGT_VTX_VECT_EJECT_REG: | 2731 | case VGT_VTX_VECT_EJECT_REG: |
2729 | case VGT_CACHE_INVALIDATION: | 2732 | case VGT_CACHE_INVALIDATION: |
2730 | case VGT_GS_VERTEX_REUSE: | 2733 | case VGT_GS_VERTEX_REUSE: |
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index df542f1a5dfb..2bc0f6a1b428 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h | |||
@@ -91,6 +91,10 @@ | |||
91 | #define FB_READ_EN (1 << 0) | 91 | #define FB_READ_EN (1 << 0) |
92 | #define FB_WRITE_EN (1 << 1) | 92 | #define FB_WRITE_EN (1 << 1) |
93 | 93 | ||
94 | #define CP_STRMOUT_CNTL 0x84FC | ||
95 | |||
96 | #define CP_COHER_CNTL 0x85F0 | ||
97 | #define CP_COHER_SIZE 0x85F4 | ||
94 | #define CP_COHER_BASE 0x85F8 | 98 | #define CP_COHER_BASE 0x85F8 |
95 | #define CP_STALLED_STAT1 0x8674 | 99 | #define CP_STALLED_STAT1 0x8674 |
96 | #define CP_STALLED_STAT2 0x8678 | 100 | #define CP_STALLED_STAT2 0x8678 |
diff --git a/drivers/gpu/drm/radeon/radeon_agp.c b/drivers/gpu/drm/radeon/radeon_agp.c index 10ea17a6b2a6..42433344cb1b 100644 --- a/drivers/gpu/drm/radeon/radeon_agp.c +++ b/drivers/gpu/drm/radeon/radeon_agp.c | |||
@@ -69,9 +69,12 @@ static struct radeon_agpmode_quirk radeon_agpmode_quirk_list[] = { | |||
69 | /* Intel 82830 830 Chipset Host Bridge / Mobility M6 LY Needs AGPMode 2 (fdo #17360)*/ | 69 | /* Intel 82830 830 Chipset Host Bridge / Mobility M6 LY Needs AGPMode 2 (fdo #17360)*/ |
70 | { PCI_VENDOR_ID_INTEL, 0x3575, PCI_VENDOR_ID_ATI, 0x4c59, | 70 | { PCI_VENDOR_ID_INTEL, 0x3575, PCI_VENDOR_ID_ATI, 0x4c59, |
71 | PCI_VENDOR_ID_DELL, 0x00e3, 2}, | 71 | PCI_VENDOR_ID_DELL, 0x00e3, 2}, |
72 | /* Intel 82852/82855 host bridge / Mobility FireGL 9000 R250 Needs AGPMode 1 (lp #296617) */ | 72 | /* Intel 82852/82855 host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 (lp #296617) */ |
73 | { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4c66, | 73 | { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4c66, |
74 | PCI_VENDOR_ID_DELL, 0x0149, 1}, | 74 | PCI_VENDOR_ID_DELL, 0x0149, 1}, |
75 | /* Intel 82855PM host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 for suspend/resume */ | ||
76 | { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c66, | ||
77 | PCI_VENDOR_ID_IBM, 0x0531, 1}, | ||
75 | /* Intel 82852/82855 host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (deb #467460) */ | 78 | /* Intel 82852/82855 host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (deb #467460) */ |
76 | { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50, | 79 | { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50, |
77 | 0x1025, 0x0061, 1}, | 80 | 0x1025, 0x0061, 1}, |
diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 37f6a907aea4..15f5ded65e0c 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c | |||
@@ -352,9 +352,9 @@ static int radeon_atpx_switchto(enum vga_switcheroo_client_id id) | |||
352 | } | 352 | } |
353 | 353 | ||
354 | /** | 354 | /** |
355 | * radeon_atpx_switchto - switch to the requested GPU | 355 | * radeon_atpx_power_state - power down/up the requested GPU |
356 | * | 356 | * |
357 | * @id: GPU to switch to | 357 | * @id: GPU to power down/up |
358 | * @state: requested power state (0 = off, 1 = on) | 358 | * @state: requested power state (0 = off, 1 = on) |
359 | * | 359 | * |
360 | * Execute the necessary ATPX function to power down/up the discrete GPU | 360 | * Execute the necessary ATPX function to power down/up the discrete GPU |
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 67cfc1795ecd..b884c362a8c2 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
@@ -941,7 +941,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) | |||
941 | struct drm_mode_object *obj; | 941 | struct drm_mode_object *obj; |
942 | int i; | 942 | int i; |
943 | enum drm_connector_status ret = connector_status_disconnected; | 943 | enum drm_connector_status ret = connector_status_disconnected; |
944 | bool dret = false; | 944 | bool dret = false, broken_edid = false; |
945 | 945 | ||
946 | if (!force && radeon_check_hpd_status_unchanged(connector)) | 946 | if (!force && radeon_check_hpd_status_unchanged(connector)) |
947 | return connector->status; | 947 | return connector->status; |
@@ -965,6 +965,9 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) | |||
965 | ret = connector_status_disconnected; | 965 | ret = connector_status_disconnected; |
966 | DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector)); | 966 | DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector)); |
967 | radeon_connector->ddc_bus = NULL; | 967 | radeon_connector->ddc_bus = NULL; |
968 | } else { | ||
969 | ret = connector_status_connected; | ||
970 | broken_edid = true; /* defer use_digital to later */ | ||
968 | } | 971 | } |
969 | } else { | 972 | } else { |
970 | radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); | 973 | radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); |
@@ -1047,13 +1050,24 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) | |||
1047 | 1050 | ||
1048 | encoder_funcs = encoder->helper_private; | 1051 | encoder_funcs = encoder->helper_private; |
1049 | if (encoder_funcs->detect) { | 1052 | if (encoder_funcs->detect) { |
1050 | if (ret != connector_status_connected) { | 1053 | if (!broken_edid) { |
1051 | ret = encoder_funcs->detect(encoder, connector); | 1054 | if (ret != connector_status_connected) { |
1052 | if (ret == connector_status_connected) { | 1055 | /* deal with analog monitors without DDC */ |
1053 | radeon_connector->use_digital = false; | 1056 | ret = encoder_funcs->detect(encoder, connector); |
1057 | if (ret == connector_status_connected) { | ||
1058 | radeon_connector->use_digital = false; | ||
1059 | } | ||
1060 | if (ret != connector_status_disconnected) | ||
1061 | radeon_connector->detected_by_load = true; | ||
1054 | } | 1062 | } |
1055 | if (ret != connector_status_disconnected) | 1063 | } else { |
1056 | radeon_connector->detected_by_load = true; | 1064 | enum drm_connector_status lret; |
1065 | /* assume digital unless load detected otherwise */ | ||
1066 | radeon_connector->use_digital = true; | ||
1067 | lret = encoder_funcs->detect(encoder, connector); | ||
1068 | DRM_DEBUG_KMS("load_detect %x returned: %x\n",encoder->encoder_type,lret); | ||
1069 | if (lret == connector_status_connected) | ||
1070 | radeon_connector->use_digital = false; | ||
1057 | } | 1071 | } |
1058 | break; | 1072 | break; |
1059 | } | 1073 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 5677a424b585..6857cb4efb76 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c | |||
@@ -295,6 +295,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
295 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | 295 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
296 | struct drm_device *dev = crtc->dev; | 296 | struct drm_device *dev = crtc->dev; |
297 | struct radeon_device *rdev = dev->dev_private; | 297 | struct radeon_device *rdev = dev->dev_private; |
298 | uint32_t crtc_ext_cntl = 0; | ||
298 | uint32_t mask; | 299 | uint32_t mask; |
299 | 300 | ||
300 | if (radeon_crtc->crtc_id) | 301 | if (radeon_crtc->crtc_id) |
@@ -307,6 +308,16 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
307 | RADEON_CRTC_VSYNC_DIS | | 308 | RADEON_CRTC_VSYNC_DIS | |
308 | RADEON_CRTC_HSYNC_DIS); | 309 | RADEON_CRTC_HSYNC_DIS); |
309 | 310 | ||
311 | /* | ||
312 | * On all dual CRTC GPUs this bit controls the CRTC of the primary DAC. | ||
313 | * Therefore it is set in the DAC DMPS function. | ||
314 | * This is different for GPU's with a single CRTC but a primary and a | ||
315 | * TV DAC: here it controls the single CRTC no matter where it is | ||
316 | * routed. Therefore we set it here. | ||
317 | */ | ||
318 | if (rdev->flags & RADEON_SINGLE_CRTC) | ||
319 | crtc_ext_cntl = RADEON_CRTC_CRT_ON; | ||
320 | |||
310 | switch (mode) { | 321 | switch (mode) { |
311 | case DRM_MODE_DPMS_ON: | 322 | case DRM_MODE_DPMS_ON: |
312 | radeon_crtc->enabled = true; | 323 | radeon_crtc->enabled = true; |
@@ -317,7 +328,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
317 | else { | 328 | else { |
318 | WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN | | 329 | WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN | |
319 | RADEON_CRTC_DISP_REQ_EN_B)); | 330 | RADEON_CRTC_DISP_REQ_EN_B)); |
320 | WREG32_P(RADEON_CRTC_EXT_CNTL, 0, ~mask); | 331 | WREG32_P(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl, ~(mask | crtc_ext_cntl)); |
321 | } | 332 | } |
322 | drm_vblank_post_modeset(dev, radeon_crtc->crtc_id); | 333 | drm_vblank_post_modeset(dev, radeon_crtc->crtc_id); |
323 | radeon_crtc_load_lut(crtc); | 334 | radeon_crtc_load_lut(crtc); |
@@ -331,7 +342,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
331 | else { | 342 | else { |
332 | WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN | | 343 | WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN | |
333 | RADEON_CRTC_DISP_REQ_EN_B)); | 344 | RADEON_CRTC_DISP_REQ_EN_B)); |
334 | WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~mask); | 345 | WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~(mask | crtc_ext_cntl)); |
335 | } | 346 | } |
336 | radeon_crtc->enabled = false; | 347 | radeon_crtc->enabled = false; |
337 | /* adjust pm to dpms changes AFTER disabling crtcs */ | 348 | /* adjust pm to dpms changes AFTER disabling crtcs */ |
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 0063df9d166d..f5ba2241dacc 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c | |||
@@ -537,7 +537,9 @@ static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode | |||
537 | break; | 537 | break; |
538 | } | 538 | } |
539 | 539 | ||
540 | WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); | 540 | /* handled in radeon_crtc_dpms() */ |
541 | if (!(rdev->flags & RADEON_SINGLE_CRTC)) | ||
542 | WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); | ||
541 | WREG32(RADEON_DAC_CNTL, dac_cntl); | 543 | WREG32(RADEON_DAC_CNTL, dac_cntl); |
542 | WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); | 544 | WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); |
543 | 545 | ||
@@ -662,6 +664,8 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc | |||
662 | 664 | ||
663 | if (ASIC_IS_R300(rdev)) | 665 | if (ASIC_IS_R300(rdev)) |
664 | tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT); | 666 | tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT); |
667 | else if (ASIC_IS_RV100(rdev)) | ||
668 | tmp |= (0x1ac << RADEON_DAC_FORCE_DATA_SHIFT); | ||
665 | else | 669 | else |
666 | tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT); | 670 | tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT); |
667 | 671 | ||
@@ -671,6 +675,7 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc | |||
671 | tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN; | 675 | tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN; |
672 | WREG32(RADEON_DAC_CNTL, tmp); | 676 | WREG32(RADEON_DAC_CNTL, tmp); |
673 | 677 | ||
678 | tmp = dac_macro_cntl; | ||
674 | tmp &= ~(RADEON_DAC_PDWN_R | | 679 | tmp &= ~(RADEON_DAC_PDWN_R | |
675 | RADEON_DAC_PDWN_G | | 680 | RADEON_DAC_PDWN_G | |
676 | RADEON_DAC_PDWN_B); | 681 | RADEON_DAC_PDWN_B); |
@@ -1092,7 +1097,8 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode) | |||
1092 | } else { | 1097 | } else { |
1093 | if (is_tv) | 1098 | if (is_tv) |
1094 | WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl); | 1099 | WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl); |
1095 | else | 1100 | /* handled in radeon_crtc_dpms() */ |
1101 | else if (!(rdev->flags & RADEON_SINGLE_CRTC)) | ||
1096 | WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); | 1102 | WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); |
1097 | WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); | 1103 | WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); |
1098 | } | 1104 | } |
@@ -1416,13 +1422,104 @@ static bool radeon_legacy_tv_detect(struct drm_encoder *encoder, | |||
1416 | return found; | 1422 | return found; |
1417 | } | 1423 | } |
1418 | 1424 | ||
1425 | static bool radeon_legacy_ext_dac_detect(struct drm_encoder *encoder, | ||
1426 | struct drm_connector *connector) | ||
1427 | { | ||
1428 | struct drm_device *dev = encoder->dev; | ||
1429 | struct radeon_device *rdev = dev->dev_private; | ||
1430 | uint32_t gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl; | ||
1431 | uint32_t disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c; | ||
1432 | uint32_t disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f; | ||
1433 | uint32_t tmp, crtc2_h_total_disp, crtc2_v_total_disp; | ||
1434 | uint32_t crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid; | ||
1435 | bool found = false; | ||
1436 | int i; | ||
1437 | |||
1438 | /* save the regs we need */ | ||
1439 | gpio_monid = RREG32(RADEON_GPIO_MONID); | ||
1440 | fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); | ||
1441 | disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); | ||
1442 | crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); | ||
1443 | disp_lin_trans_grph_a = RREG32(RADEON_DISP_LIN_TRANS_GRPH_A); | ||
1444 | disp_lin_trans_grph_b = RREG32(RADEON_DISP_LIN_TRANS_GRPH_B); | ||
1445 | disp_lin_trans_grph_c = RREG32(RADEON_DISP_LIN_TRANS_GRPH_C); | ||
1446 | disp_lin_trans_grph_d = RREG32(RADEON_DISP_LIN_TRANS_GRPH_D); | ||
1447 | disp_lin_trans_grph_e = RREG32(RADEON_DISP_LIN_TRANS_GRPH_E); | ||
1448 | disp_lin_trans_grph_f = RREG32(RADEON_DISP_LIN_TRANS_GRPH_F); | ||
1449 | crtc2_h_total_disp = RREG32(RADEON_CRTC2_H_TOTAL_DISP); | ||
1450 | crtc2_v_total_disp = RREG32(RADEON_CRTC2_V_TOTAL_DISP); | ||
1451 | crtc2_h_sync_strt_wid = RREG32(RADEON_CRTC2_H_SYNC_STRT_WID); | ||
1452 | crtc2_v_sync_strt_wid = RREG32(RADEON_CRTC2_V_SYNC_STRT_WID); | ||
1453 | |||
1454 | tmp = RREG32(RADEON_GPIO_MONID); | ||
1455 | tmp &= ~RADEON_GPIO_A_0; | ||
1456 | WREG32(RADEON_GPIO_MONID, tmp); | ||
1457 | |||
1458 | WREG32(RADEON_FP2_GEN_CNTL, (RADEON_FP2_ON | | ||
1459 | RADEON_FP2_PANEL_FORMAT | | ||
1460 | R200_FP2_SOURCE_SEL_TRANS_UNIT | | ||
1461 | RADEON_FP2_DVO_EN | | ||
1462 | R200_FP2_DVO_RATE_SEL_SDR)); | ||
1463 | |||
1464 | WREG32(RADEON_DISP_OUTPUT_CNTL, (RADEON_DISP_DAC_SOURCE_RMX | | ||
1465 | RADEON_DISP_TRANS_MATRIX_GRAPHICS)); | ||
1466 | |||
1467 | WREG32(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_EN | | ||
1468 | RADEON_CRTC2_DISP_REQ_EN_B)); | ||
1469 | |||
1470 | WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000); | ||
1471 | WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0); | ||
1472 | WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000); | ||
1473 | WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0); | ||
1474 | WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000); | ||
1475 | WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0); | ||
1476 | |||
1477 | WREG32(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008); | ||
1478 | WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800); | ||
1479 | WREG32(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001); | ||
1480 | WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080); | ||
1481 | |||
1482 | for (i = 0; i < 200; i++) { | ||
1483 | tmp = RREG32(RADEON_GPIO_MONID); | ||
1484 | if (tmp & RADEON_GPIO_Y_0) | ||
1485 | found = true; | ||
1486 | |||
1487 | if (found) | ||
1488 | break; | ||
1489 | |||
1490 | if (!drm_can_sleep()) | ||
1491 | mdelay(1); | ||
1492 | else | ||
1493 | msleep(1); | ||
1494 | } | ||
1495 | |||
1496 | /* restore the regs we used */ | ||
1497 | WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a); | ||
1498 | WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b); | ||
1499 | WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c); | ||
1500 | WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d); | ||
1501 | WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e); | ||
1502 | WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f); | ||
1503 | WREG32(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp); | ||
1504 | WREG32(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp); | ||
1505 | WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid); | ||
1506 | WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid); | ||
1507 | WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); | ||
1508 | WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); | ||
1509 | WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); | ||
1510 | WREG32(RADEON_GPIO_MONID, gpio_monid); | ||
1511 | |||
1512 | return found; | ||
1513 | } | ||
1514 | |||
1419 | static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder, | 1515 | static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder, |
1420 | struct drm_connector *connector) | 1516 | struct drm_connector *connector) |
1421 | { | 1517 | { |
1422 | struct drm_device *dev = encoder->dev; | 1518 | struct drm_device *dev = encoder->dev; |
1423 | struct radeon_device *rdev = dev->dev_private; | 1519 | struct radeon_device *rdev = dev->dev_private; |
1424 | uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl; | 1520 | uint32_t crtc2_gen_cntl = 0, tv_dac_cntl, dac_cntl2, dac_ext_cntl; |
1425 | uint32_t disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp; | 1521 | uint32_t gpiopad_a = 0, pixclks_cntl, tmp; |
1522 | uint32_t disp_output_cntl = 0, disp_hw_debug = 0, crtc_ext_cntl = 0; | ||
1426 | enum drm_connector_status found = connector_status_disconnected; | 1523 | enum drm_connector_status found = connector_status_disconnected; |
1427 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 1524 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
1428 | struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; | 1525 | struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; |
@@ -1459,12 +1556,27 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder | |||
1459 | return connector_status_disconnected; | 1556 | return connector_status_disconnected; |
1460 | } | 1557 | } |
1461 | 1558 | ||
1559 | /* R200 uses an external DAC for secondary DAC */ | ||
1560 | if (rdev->family == CHIP_R200) { | ||
1561 | if (radeon_legacy_ext_dac_detect(encoder, connector)) | ||
1562 | found = connector_status_connected; | ||
1563 | return found; | ||
1564 | } | ||
1565 | |||
1462 | /* save the regs we need */ | 1566 | /* save the regs we need */ |
1463 | pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL); | 1567 | pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL); |
1464 | gpiopad_a = ASIC_IS_R300(rdev) ? RREG32(RADEON_GPIOPAD_A) : 0; | 1568 | |
1465 | disp_output_cntl = ASIC_IS_R300(rdev) ? RREG32(RADEON_DISP_OUTPUT_CNTL) : 0; | 1569 | if (rdev->flags & RADEON_SINGLE_CRTC) { |
1466 | disp_hw_debug = ASIC_IS_R300(rdev) ? 0 : RREG32(RADEON_DISP_HW_DEBUG); | 1570 | crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); |
1467 | crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); | 1571 | } else { |
1572 | if (ASIC_IS_R300(rdev)) { | ||
1573 | gpiopad_a = RREG32(RADEON_GPIOPAD_A); | ||
1574 | disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); | ||
1575 | } else { | ||
1576 | disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG); | ||
1577 | } | ||
1578 | crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); | ||
1579 | } | ||
1468 | tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); | 1580 | tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); |
1469 | dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL); | 1581 | dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL); |
1470 | dac_cntl2 = RREG32(RADEON_DAC_CNTL2); | 1582 | dac_cntl2 = RREG32(RADEON_DAC_CNTL2); |
@@ -1473,22 +1585,24 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder | |||
1473 | | RADEON_PIX2CLK_DAC_ALWAYS_ONb); | 1585 | | RADEON_PIX2CLK_DAC_ALWAYS_ONb); |
1474 | WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); | 1586 | WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); |
1475 | 1587 | ||
1476 | if (ASIC_IS_R300(rdev)) | 1588 | if (rdev->flags & RADEON_SINGLE_CRTC) { |
1477 | WREG32_P(RADEON_GPIOPAD_A, 1, ~1); | 1589 | tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON; |
1478 | 1590 | WREG32(RADEON_CRTC_EXT_CNTL, tmp); | |
1479 | tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK; | ||
1480 | tmp |= RADEON_CRTC2_CRT2_ON | | ||
1481 | (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT); | ||
1482 | |||
1483 | WREG32(RADEON_CRTC2_GEN_CNTL, tmp); | ||
1484 | |||
1485 | if (ASIC_IS_R300(rdev)) { | ||
1486 | tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; | ||
1487 | tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; | ||
1488 | WREG32(RADEON_DISP_OUTPUT_CNTL, tmp); | ||
1489 | } else { | 1591 | } else { |
1490 | tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL; | 1592 | tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK; |
1491 | WREG32(RADEON_DISP_HW_DEBUG, tmp); | 1593 | tmp |= RADEON_CRTC2_CRT2_ON | |
1594 | (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT); | ||
1595 | WREG32(RADEON_CRTC2_GEN_CNTL, tmp); | ||
1596 | |||
1597 | if (ASIC_IS_R300(rdev)) { | ||
1598 | WREG32_P(RADEON_GPIOPAD_A, 1, ~1); | ||
1599 | tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; | ||
1600 | tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; | ||
1601 | WREG32(RADEON_DISP_OUTPUT_CNTL, tmp); | ||
1602 | } else { | ||
1603 | tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL; | ||
1604 | WREG32(RADEON_DISP_HW_DEBUG, tmp); | ||
1605 | } | ||
1492 | } | 1606 | } |
1493 | 1607 | ||
1494 | tmp = RADEON_TV_DAC_NBLANK | | 1608 | tmp = RADEON_TV_DAC_NBLANK | |
@@ -1530,14 +1644,19 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder | |||
1530 | WREG32(RADEON_DAC_CNTL2, dac_cntl2); | 1644 | WREG32(RADEON_DAC_CNTL2, dac_cntl2); |
1531 | WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl); | 1645 | WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl); |
1532 | WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); | 1646 | WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); |
1533 | WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); | ||
1534 | 1647 | ||
1535 | if (ASIC_IS_R300(rdev)) { | 1648 | if (rdev->flags & RADEON_SINGLE_CRTC) { |
1536 | WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); | 1649 | WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); |
1537 | WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1); | ||
1538 | } else { | 1650 | } else { |
1539 | WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); | 1651 | WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); |
1652 | if (ASIC_IS_R300(rdev)) { | ||
1653 | WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); | ||
1654 | WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1); | ||
1655 | } else { | ||
1656 | WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); | ||
1657 | } | ||
1540 | } | 1658 | } |
1659 | |||
1541 | WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); | 1660 | WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); |
1542 | 1661 | ||
1543 | return found; | 1662 | return found; |
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index b0db712060fb..4422d630b33b 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
@@ -2474,6 +2474,7 @@ static bool si_vm_reg_valid(u32 reg) | |||
2474 | /* check config regs */ | 2474 | /* check config regs */ |
2475 | switch (reg) { | 2475 | switch (reg) { |
2476 | case GRBM_GFX_INDEX: | 2476 | case GRBM_GFX_INDEX: |
2477 | case CP_STRMOUT_CNTL: | ||
2477 | case VGT_VTX_VECT_EJECT_REG: | 2478 | case VGT_VTX_VECT_EJECT_REG: |
2478 | case VGT_CACHE_INVALIDATION: | 2479 | case VGT_CACHE_INVALIDATION: |
2479 | case VGT_ESGS_RING_SIZE: | 2480 | case VGT_ESGS_RING_SIZE: |
diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 7d2a20e56577..a8871afc5b4e 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h | |||
@@ -424,6 +424,7 @@ | |||
424 | # define RDERR_INT_ENABLE (1 << 0) | 424 | # define RDERR_INT_ENABLE (1 << 0) |
425 | # define GUI_IDLE_INT_ENABLE (1 << 19) | 425 | # define GUI_IDLE_INT_ENABLE (1 << 19) |
426 | 426 | ||
427 | #define CP_STRMOUT_CNTL 0x84FC | ||
427 | #define SCRATCH_REG0 0x8500 | 428 | #define SCRATCH_REG0 0x8500 |
428 | #define SCRATCH_REG1 0x8504 | 429 | #define SCRATCH_REG1 0x8504 |
429 | #define SCRATCH_REG2 0x8508 | 430 | #define SCRATCH_REG2 0x8508 |
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c index 860dc4813e99..bd2a3b40cd12 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c | |||
@@ -749,7 +749,10 @@ static int ttm_get_pages(struct page **pages, unsigned npages, int flags, | |||
749 | /* clear the pages coming from the pool if requested */ | 749 | /* clear the pages coming from the pool if requested */ |
750 | if (flags & TTM_PAGE_FLAG_ZERO_ALLOC) { | 750 | if (flags & TTM_PAGE_FLAG_ZERO_ALLOC) { |
751 | list_for_each_entry(p, &plist, lru) { | 751 | list_for_each_entry(p, &plist, lru) { |
752 | clear_page(page_address(p)); | 752 | if (PageHighMem(p)) |
753 | clear_highpage(p); | ||
754 | else | ||
755 | clear_page(page_address(p)); | ||
753 | } | 756 | } |
754 | } | 757 | } |
755 | 758 | ||
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index bf8260133ea9..7d759a430294 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c | |||
@@ -308,9 +308,7 @@ int ttm_tt_swapin(struct ttm_tt *ttm) | |||
308 | if (unlikely(to_page == NULL)) | 308 | if (unlikely(to_page == NULL)) |
309 | goto out_err; | 309 | goto out_err; |
310 | 310 | ||
311 | preempt_disable(); | ||
312 | copy_highpage(to_page, from_page); | 311 | copy_highpage(to_page, from_page); |
313 | preempt_enable(); | ||
314 | page_cache_release(from_page); | 312 | page_cache_release(from_page); |
315 | } | 313 | } |
316 | 314 | ||
@@ -358,9 +356,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage) | |||
358 | ret = PTR_ERR(to_page); | 356 | ret = PTR_ERR(to_page); |
359 | goto out_err; | 357 | goto out_err; |
360 | } | 358 | } |
361 | preempt_disable(); | ||
362 | copy_highpage(to_page, from_page); | 359 | copy_highpage(to_page, from_page); |
363 | preempt_enable(); | ||
364 | set_page_dirty(to_page); | 360 | set_page_dirty(to_page); |
365 | mark_page_accessed(to_page); | 361 | mark_page_accessed(to_page); |
366 | page_cache_release(to_page); | 362 | page_cache_release(to_page); |
diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index fccd361f7b50..87aa5f5d3c88 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h | |||
@@ -104,7 +104,7 @@ udl_fb_user_fb_create(struct drm_device *dev, | |||
104 | 104 | ||
105 | int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, | 105 | int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, |
106 | const char *front, char **urb_buf_ptr, | 106 | const char *front, char **urb_buf_ptr, |
107 | u32 byte_offset, u32 byte_width, | 107 | u32 byte_offset, u32 device_byte_offset, u32 byte_width, |
108 | int *ident_ptr, int *sent_ptr); | 108 | int *ident_ptr, int *sent_ptr); |
109 | 109 | ||
110 | int udl_dumb_create(struct drm_file *file_priv, | 110 | int udl_dumb_create(struct drm_file *file_priv, |
diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index 69a2b16f42a6..d4ab3beaada0 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c | |||
@@ -114,9 +114,10 @@ static void udlfb_dpy_deferred_io(struct fb_info *info, | |||
114 | list_for_each_entry(cur, &fbdefio->pagelist, lru) { | 114 | list_for_each_entry(cur, &fbdefio->pagelist, lru) { |
115 | 115 | ||
116 | if (udl_render_hline(dev, (ufbdev->ufb.base.bits_per_pixel / 8), | 116 | if (udl_render_hline(dev, (ufbdev->ufb.base.bits_per_pixel / 8), |
117 | &urb, (char *) info->fix.smem_start, | 117 | &urb, (char *) info->fix.smem_start, |
118 | &cmd, cur->index << PAGE_SHIFT, | 118 | &cmd, cur->index << PAGE_SHIFT, |
119 | PAGE_SIZE, &bytes_identical, &bytes_sent)) | 119 | cur->index << PAGE_SHIFT, |
120 | PAGE_SIZE, &bytes_identical, &bytes_sent)) | ||
120 | goto error; | 121 | goto error; |
121 | bytes_rendered += PAGE_SIZE; | 122 | bytes_rendered += PAGE_SIZE; |
122 | } | 123 | } |
@@ -187,10 +188,11 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, | |||
187 | for (i = y; i < y + height ; i++) { | 188 | for (i = y; i < y + height ; i++) { |
188 | const int line_offset = fb->base.pitches[0] * i; | 189 | const int line_offset = fb->base.pitches[0] * i; |
189 | const int byte_offset = line_offset + (x * bpp); | 190 | const int byte_offset = line_offset + (x * bpp); |
190 | 191 | const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp); | |
191 | if (udl_render_hline(dev, bpp, &urb, | 192 | if (udl_render_hline(dev, bpp, &urb, |
192 | (char *) fb->obj->vmapping, | 193 | (char *) fb->obj->vmapping, |
193 | &cmd, byte_offset, width * bpp, | 194 | &cmd, byte_offset, dev_byte_offset, |
195 | width * bpp, | ||
194 | &bytes_identical, &bytes_sent)) | 196 | &bytes_identical, &bytes_sent)) |
195 | goto error; | 197 | goto error; |
196 | } | 198 | } |
diff --git a/drivers/gpu/drm/udl/udl_transfer.c b/drivers/gpu/drm/udl/udl_transfer.c index dc095526ffb7..142fee5f983f 100644 --- a/drivers/gpu/drm/udl/udl_transfer.c +++ b/drivers/gpu/drm/udl/udl_transfer.c | |||
@@ -213,11 +213,12 @@ static void udl_compress_hline16( | |||
213 | */ | 213 | */ |
214 | int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, | 214 | int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, |
215 | const char *front, char **urb_buf_ptr, | 215 | const char *front, char **urb_buf_ptr, |
216 | u32 byte_offset, u32 byte_width, | 216 | u32 byte_offset, u32 device_byte_offset, |
217 | u32 byte_width, | ||
217 | int *ident_ptr, int *sent_ptr) | 218 | int *ident_ptr, int *sent_ptr) |
218 | { | 219 | { |
219 | const u8 *line_start, *line_end, *next_pixel; | 220 | const u8 *line_start, *line_end, *next_pixel; |
220 | u32 base16 = 0 + (byte_offset / bpp) * 2; | 221 | u32 base16 = 0 + (device_byte_offset / bpp) * 2; |
221 | struct urb *urb = *urb_ptr; | 222 | struct urb *urb = *urb_ptr; |
222 | u8 *cmd = *urb_buf_ptr; | 223 | u8 *cmd = *urb_buf_ptr; |
223 | u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length; | 224 | u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length; |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c index 3ce68a2e312d..d1498bfd7873 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c | |||
@@ -306,7 +306,7 @@ void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin) | |||
306 | 306 | ||
307 | BUG_ON(!atomic_read(&bo->reserved)); | 307 | BUG_ON(!atomic_read(&bo->reserved)); |
308 | BUG_ON(old_mem_type != TTM_PL_VRAM && | 308 | BUG_ON(old_mem_type != TTM_PL_VRAM && |
309 | old_mem_type != VMW_PL_FLAG_GMR); | 309 | old_mem_type != VMW_PL_GMR); |
310 | 310 | ||
311 | pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED; | 311 | pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED; |
312 | if (pin) | 312 | if (pin) |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index ed3c1e7ddde9..2dd185e42f21 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | |||
@@ -1098,6 +1098,11 @@ static void vmw_pm_complete(struct device *kdev) | |||
1098 | struct drm_device *dev = pci_get_drvdata(pdev); | 1098 | struct drm_device *dev = pci_get_drvdata(pdev); |
1099 | struct vmw_private *dev_priv = vmw_priv(dev); | 1099 | struct vmw_private *dev_priv = vmw_priv(dev); |
1100 | 1100 | ||
1101 | mutex_lock(&dev_priv->hw_mutex); | ||
1102 | vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2); | ||
1103 | (void) vmw_read(dev_priv, SVGA_REG_ID); | ||
1104 | mutex_unlock(&dev_priv->hw_mutex); | ||
1105 | |||
1101 | /** | 1106 | /** |
1102 | * Reclaim 3d reference held by fbdev and potentially | 1107 | * Reclaim 3d reference held by fbdev and potentially |
1103 | * start fifo. | 1108 | * start fifo. |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index b07ca2e4d04b..7290811f89be 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c | |||
@@ -110,6 +110,8 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data, | |||
110 | memcpy_fromio(bounce, &fifo_mem[SVGA_FIFO_3D_CAPS], size); | 110 | memcpy_fromio(bounce, &fifo_mem[SVGA_FIFO_3D_CAPS], size); |
111 | 111 | ||
112 | ret = copy_to_user(buffer, bounce, size); | 112 | ret = copy_to_user(buffer, bounce, size); |
113 | if (ret) | ||
114 | ret = -EFAULT; | ||
113 | vfree(bounce); | 115 | vfree(bounce); |
114 | 116 | ||
115 | if (unlikely(ret != 0)) | 117 | if (unlikely(ret != 0)) |