diff options
53 files changed, 1058 insertions, 914 deletions
diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 702c4474919c..677a02553ec0 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl | |||
| @@ -2287,6 +2287,11 @@ void intel_crt_init(struct drm_device *dev) | |||
| 2287 | !Edrivers/gpu/drm/drm_crtc_helper.c | 2287 | !Edrivers/gpu/drm/drm_crtc_helper.c |
| 2288 | </sect2> | 2288 | </sect2> |
| 2289 | <sect2> | 2289 | <sect2> |
| 2290 | <title>Output Probing Helper Functions Reference</title> | ||
| 2291 | !Pdrivers/gpu/drm/drm_probe_helper.c output probing helper overview | ||
| 2292 | !Edrivers/gpu/drm/drm_probe_helper.c | ||
| 2293 | </sect2> | ||
| 2294 | <sect2> | ||
| 2290 | <title>fbdev Helper Functions Reference</title> | 2295 | <title>fbdev Helper Functions Reference</title> |
| 2291 | !Pdrivers/gpu/drm/drm_fb_helper.c fbdev helpers | 2296 | !Pdrivers/gpu/drm/drm_fb_helper.c fbdev helpers |
| 2292 | !Edrivers/gpu/drm/drm_fb_helper.c | 2297 | !Edrivers/gpu/drm/drm_fb_helper.c |
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 9d25dbbe6771..48e38ba22783 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile | |||
| @@ -23,7 +23,7 @@ drm-$(CONFIG_DRM_PANEL) += drm_panel.o | |||
| 23 | 23 | ||
| 24 | drm-usb-y := drm_usb.o | 24 | drm-usb-y := drm_usb.o |
| 25 | 25 | ||
| 26 | drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o | 26 | drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o |
| 27 | drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o | 27 | drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o |
| 28 | drm_kms_helper-$(CONFIG_DRM_KMS_FB_HELPER) += drm_fb_helper.o | 28 | drm_kms_helper-$(CONFIG_DRM_KMS_FB_HELPER) += drm_fb_helper.o |
| 29 | drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o | 29 | drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o |
diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c index 977cfb35837a..635f6ffc27c2 100644 --- a/drivers/gpu/drm/ast/ast_post.c +++ b/drivers/gpu/drm/ast/ast_post.c | |||
| @@ -572,7 +572,7 @@ static u32 cbr_scan2(struct ast_private *ast) | |||
| 572 | for (loop = 0; loop < CBR_PASSNUM2; loop++) { | 572 | for (loop = 0; loop < CBR_PASSNUM2; loop++) { |
| 573 | if ((data = cbr_test2(ast)) != 0) { | 573 | if ((data = cbr_test2(ast)) != 0) { |
| 574 | data2 &= data; | 574 | data2 &= data; |
| 575 | if (!data) | 575 | if (!data2) |
| 576 | return 0; | 576 | return 0; |
| 577 | break; | 577 | break; |
| 578 | } | 578 | } |
diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h index 741965c001a6..7eb52dd44b01 100644 --- a/drivers/gpu/drm/bochs/bochs.h +++ b/drivers/gpu/drm/bochs/bochs.h | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | #include <linux/io.h> | 1 | #include <linux/io.h> |
| 2 | #include <linux/fb.h> | 2 | #include <linux/fb.h> |
| 3 | #include <linux/console.h> | ||
| 3 | 4 | ||
| 4 | #include <drm/drmP.h> | 5 | #include <drm/drmP.h> |
| 5 | #include <drm/drm_crtc.h> | 6 | #include <drm/drm_crtc.h> |
| @@ -87,8 +88,6 @@ struct bochs_device { | |||
| 87 | struct bochs_framebuffer gfb; | 88 | struct bochs_framebuffer gfb; |
| 88 | struct drm_fb_helper helper; | 89 | struct drm_fb_helper helper; |
| 89 | int size; | 90 | int size; |
| 90 | int x1, y1, x2, y2; /* dirty rect */ | ||
| 91 | spinlock_t dirty_lock; | ||
| 92 | bool initialized; | 91 | bool initialized; |
| 93 | } fb; | 92 | } fb; |
| 94 | }; | 93 | }; |
diff --git a/drivers/gpu/drm/bochs/bochs_drv.c b/drivers/gpu/drm/bochs/bochs_drv.c index 395bba261c9a..9c13df29fd20 100644 --- a/drivers/gpu/drm/bochs/bochs_drv.c +++ b/drivers/gpu/drm/bochs/bochs_drv.c | |||
| @@ -95,6 +95,49 @@ static struct drm_driver bochs_driver = { | |||
| 95 | }; | 95 | }; |
| 96 | 96 | ||
| 97 | /* ---------------------------------------------------------------------- */ | 97 | /* ---------------------------------------------------------------------- */ |
| 98 | /* pm interface */ | ||
| 99 | |||
| 100 | static int bochs_pm_suspend(struct device *dev) | ||
| 101 | { | ||
| 102 | struct pci_dev *pdev = to_pci_dev(dev); | ||
| 103 | struct drm_device *drm_dev = pci_get_drvdata(pdev); | ||
| 104 | struct bochs_device *bochs = drm_dev->dev_private; | ||
| 105 | |||
| 106 | drm_kms_helper_poll_disable(drm_dev); | ||
| 107 | |||
| 108 | if (bochs->fb.initialized) { | ||
| 109 | console_lock(); | ||
| 110 | fb_set_suspend(bochs->fb.helper.fbdev, 1); | ||
| 111 | console_unlock(); | ||
| 112 | } | ||
| 113 | |||
| 114 | return 0; | ||
| 115 | } | ||
| 116 | |||
| 117 | static int bochs_pm_resume(struct device *dev) | ||
| 118 | { | ||
| 119 | struct pci_dev *pdev = to_pci_dev(dev); | ||
| 120 | struct drm_device *drm_dev = pci_get_drvdata(pdev); | ||
| 121 | struct bochs_device *bochs = drm_dev->dev_private; | ||
| 122 | |||
| 123 | drm_helper_resume_force_mode(drm_dev); | ||
| 124 | |||
| 125 | if (bochs->fb.initialized) { | ||
| 126 | console_lock(); | ||
| 127 | fb_set_suspend(bochs->fb.helper.fbdev, 0); | ||
| 128 | console_unlock(); | ||
| 129 | } | ||
| 130 | |||
| 131 | drm_kms_helper_poll_enable(drm_dev); | ||
| 132 | return 0; | ||
| 133 | } | ||
| 134 | |||
| 135 | static const struct dev_pm_ops bochs_pm_ops = { | ||
| 136 | SET_SYSTEM_SLEEP_PM_OPS(bochs_pm_suspend, | ||
| 137 | bochs_pm_resume) | ||
| 138 | }; | ||
| 139 | |||
| 140 | /* ---------------------------------------------------------------------- */ | ||
| 98 | /* pci interface */ | 141 | /* pci interface */ |
| 99 | 142 | ||
| 100 | static int bochs_kick_out_firmware_fb(struct pci_dev *pdev) | 143 | static int bochs_kick_out_firmware_fb(struct pci_dev *pdev) |
| @@ -155,6 +198,7 @@ static struct pci_driver bochs_pci_driver = { | |||
| 155 | .id_table = bochs_pci_tbl, | 198 | .id_table = bochs_pci_tbl, |
| 156 | .probe = bochs_pci_probe, | 199 | .probe = bochs_pci_probe, |
| 157 | .remove = bochs_pci_remove, | 200 | .remove = bochs_pci_remove, |
| 201 | .driver.pm = &bochs_pm_ops, | ||
| 158 | }; | 202 | }; |
| 159 | 203 | ||
| 160 | /* ---------------------------------------------------------------------- */ | 204 | /* ---------------------------------------------------------------------- */ |
diff --git a/drivers/gpu/drm/bochs/bochs_fbdev.c b/drivers/gpu/drm/bochs/bochs_fbdev.c index 4da5206b7cc9..561b84474122 100644 --- a/drivers/gpu/drm/bochs/bochs_fbdev.c +++ b/drivers/gpu/drm/bochs/bochs_fbdev.c | |||
| @@ -190,7 +190,6 @@ int bochs_fbdev_init(struct bochs_device *bochs) | |||
| 190 | int ret; | 190 | int ret; |
| 191 | 191 | ||
| 192 | bochs->fb.helper.funcs = &bochs_fb_helper_funcs; | 192 | bochs->fb.helper.funcs = &bochs_fb_helper_funcs; |
| 193 | spin_lock_init(&bochs->fb.dirty_lock); | ||
| 194 | 193 | ||
| 195 | ret = drm_fb_helper_init(bochs->dev, &bochs->fb.helper, | 194 | ret = drm_fb_helper_init(bochs->dev, &bochs->fb.helper, |
| 196 | 1, 1); | 195 | 1, 1); |
diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c index 953fc8aea69c..08ce520f61a5 100644 --- a/drivers/gpu/drm/cirrus/cirrus_drv.c +++ b/drivers/gpu/drm/cirrus/cirrus_drv.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
| 12 | #include <linux/console.h> | 12 | #include <linux/console.h> |
| 13 | #include <drm/drmP.h> | 13 | #include <drm/drmP.h> |
| 14 | #include <drm/drm_crtc_helper.h> | ||
| 14 | 15 | ||
| 15 | #include "cirrus_drv.h" | 16 | #include "cirrus_drv.h" |
| 16 | 17 | ||
| @@ -75,6 +76,41 @@ static void cirrus_pci_remove(struct pci_dev *pdev) | |||
| 75 | drm_put_dev(dev); | 76 | drm_put_dev(dev); |
| 76 | } | 77 | } |
| 77 | 78 | ||
| 79 | static int cirrus_pm_suspend(struct device *dev) | ||
| 80 | { | ||
| 81 | struct pci_dev *pdev = to_pci_dev(dev); | ||
| 82 | struct drm_device *drm_dev = pci_get_drvdata(pdev); | ||
| 83 | struct cirrus_device *cdev = drm_dev->dev_private; | ||
| 84 | |||
| 85 | drm_kms_helper_poll_disable(drm_dev); | ||
| 86 | |||
| 87 | if (cdev->mode_info.gfbdev) { | ||
| 88 | console_lock(); | ||
| 89 | fb_set_suspend(cdev->mode_info.gfbdev->helper.fbdev, 1); | ||
| 90 | console_unlock(); | ||
| 91 | } | ||
| 92 | |||
| 93 | return 0; | ||
| 94 | } | ||
| 95 | |||
| 96 | static int cirrus_pm_resume(struct device *dev) | ||
| 97 | { | ||
| 98 | struct pci_dev *pdev = to_pci_dev(dev); | ||
| 99 | struct drm_device *drm_dev = pci_get_drvdata(pdev); | ||
| 100 | struct cirrus_device *cdev = drm_dev->dev_private; | ||
| 101 | |||
| 102 | drm_helper_resume_force_mode(drm_dev); | ||
| 103 | |||
| 104 | if (cdev->mode_info.gfbdev) { | ||
| 105 | console_lock(); | ||
| 106 | fb_set_suspend(cdev->mode_info.gfbdev->helper.fbdev, 0); | ||
| 107 | console_unlock(); | ||
| 108 | } | ||
| 109 | |||
| 110 | drm_kms_helper_poll_enable(drm_dev); | ||
| 111 | return 0; | ||
| 112 | } | ||
| 113 | |||
| 78 | static const struct file_operations cirrus_driver_fops = { | 114 | static const struct file_operations cirrus_driver_fops = { |
| 79 | .owner = THIS_MODULE, | 115 | .owner = THIS_MODULE, |
| 80 | .open = drm_open, | 116 | .open = drm_open, |
| @@ -103,11 +139,17 @@ static struct drm_driver driver = { | |||
| 103 | .dumb_destroy = drm_gem_dumb_destroy, | 139 | .dumb_destroy = drm_gem_dumb_destroy, |
| 104 | }; | 140 | }; |
| 105 | 141 | ||
| 142 | static const struct dev_pm_ops cirrus_pm_ops = { | ||
| 143 | SET_SYSTEM_SLEEP_PM_OPS(cirrus_pm_suspend, | ||
| 144 | cirrus_pm_resume) | ||
| 145 | }; | ||
| 146 | |||
| 106 | static struct pci_driver cirrus_pci_driver = { | 147 | static struct pci_driver cirrus_pci_driver = { |
| 107 | .name = DRIVER_NAME, | 148 | .name = DRIVER_NAME, |
| 108 | .id_table = pciidlist, | 149 | .id_table = pciidlist, |
| 109 | .probe = cirrus_pci_probe, | 150 | .probe = cirrus_pci_probe, |
| 110 | .remove = cirrus_pci_remove, | 151 | .remove = cirrus_pci_remove, |
| 152 | .driver.pm = &cirrus_pm_ops, | ||
| 111 | }; | 153 | }; |
| 112 | 154 | ||
| 113 | static int __init cirrus_init(void) | 155 | static int __init cirrus_init(void) |
diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index 2d64aea83df2..f59433b7610c 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c | |||
| @@ -308,6 +308,9 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc, | |||
| 308 | 308 | ||
| 309 | WREG_HDR(hdr); | 309 | WREG_HDR(hdr); |
| 310 | cirrus_crtc_do_set_base(crtc, old_fb, x, y, 0); | 310 | cirrus_crtc_do_set_base(crtc, old_fb, x, y, 0); |
| 311 | |||
| 312 | /* Unblank (needed on S3 resume, vgabios doesn't do it then) */ | ||
| 313 | outb(0x20, 0x3c0); | ||
| 311 | return 0; | 314 | return 0; |
| 312 | } | 315 | } |
| 313 | 316 | ||
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index c43825e8f5c1..df281b54db01 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
| @@ -72,147 +72,6 @@ void drm_helper_move_panel_connectors_to_head(struct drm_device *dev) | |||
| 72 | } | 72 | } |
| 73 | EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head); | 73 | EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head); |
| 74 | 74 | ||
| 75 | static bool drm_kms_helper_poll = true; | ||
| 76 | module_param_named(poll, drm_kms_helper_poll, bool, 0600); | ||
| 77 | |||
| 78 | static void drm_mode_validate_flag(struct drm_connector *connector, | ||
| 79 | int flags) | ||
| 80 | { | ||
| 81 | struct drm_display_mode *mode; | ||
| 82 | |||
| 83 | if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE | | ||
| 84 | DRM_MODE_FLAG_3D_MASK)) | ||
| 85 | return; | ||
| 86 | |||
| 87 | list_for_each_entry(mode, &connector->modes, head) { | ||
| 88 | if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && | ||
| 89 | !(flags & DRM_MODE_FLAG_INTERLACE)) | ||
| 90 | mode->status = MODE_NO_INTERLACE; | ||
| 91 | if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) && | ||
| 92 | !(flags & DRM_MODE_FLAG_DBLSCAN)) | ||
| 93 | mode->status = MODE_NO_DBLESCAN; | ||
| 94 | if ((mode->flags & DRM_MODE_FLAG_3D_MASK) && | ||
| 95 | !(flags & DRM_MODE_FLAG_3D_MASK)) | ||
| 96 | mode->status = MODE_NO_STEREO; | ||
| 97 | } | ||
| 98 | |||
| 99 | return; | ||
| 100 | } | ||
| 101 | |||
| 102 | /** | ||
| 103 | * drm_helper_probe_single_connector_modes - get complete set of display modes | ||
| 104 | * @connector: connector to probe | ||
| 105 | * @maxX: max width for modes | ||
| 106 | * @maxY: max height for modes | ||
| 107 | * | ||
| 108 | * Based on the helper callbacks implemented by @connector try to detect all | ||
| 109 | * valid modes. Modes will first be added to the connector's probed_modes list, | ||
| 110 | * then culled (based on validity and the @maxX, @maxY parameters) and put into | ||
| 111 | * the normal modes list. | ||
| 112 | * | ||
| 113 | * Intended to be use as a generic implementation of the ->fill_modes() | ||
| 114 | * @connector vfunc for drivers that use the crtc helpers for output mode | ||
| 115 | * filtering and detection. | ||
| 116 | * | ||
| 117 | * Returns: | ||
| 118 | * The number of modes found on @connector. | ||
| 119 | */ | ||
| 120 | int drm_helper_probe_single_connector_modes(struct drm_connector *connector, | ||
| 121 | uint32_t maxX, uint32_t maxY) | ||
| 122 | { | ||
| 123 | struct drm_device *dev = connector->dev; | ||
| 124 | struct drm_display_mode *mode; | ||
| 125 | struct drm_connector_helper_funcs *connector_funcs = | ||
| 126 | connector->helper_private; | ||
| 127 | int count = 0; | ||
| 128 | int mode_flags = 0; | ||
| 129 | bool verbose_prune = true; | ||
| 130 | |||
| 131 | WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); | ||
| 132 | |||
| 133 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, | ||
| 134 | drm_get_connector_name(connector)); | ||
| 135 | /* set all modes to the unverified state */ | ||
| 136 | list_for_each_entry(mode, &connector->modes, head) | ||
| 137 | mode->status = MODE_UNVERIFIED; | ||
| 138 | |||
| 139 | if (connector->force) { | ||
| 140 | if (connector->force == DRM_FORCE_ON) | ||
| 141 | connector->status = connector_status_connected; | ||
| 142 | else | ||
| 143 | connector->status = connector_status_disconnected; | ||
| 144 | if (connector->funcs->force) | ||
| 145 | connector->funcs->force(connector); | ||
| 146 | } else { | ||
| 147 | connector->status = connector->funcs->detect(connector, true); | ||
| 148 | } | ||
| 149 | |||
| 150 | /* Re-enable polling in case the global poll config changed. */ | ||
| 151 | if (drm_kms_helper_poll != dev->mode_config.poll_running) | ||
| 152 | drm_kms_helper_poll_enable(dev); | ||
| 153 | |||
| 154 | dev->mode_config.poll_running = drm_kms_helper_poll; | ||
| 155 | |||
| 156 | if (connector->status == connector_status_disconnected) { | ||
| 157 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n", | ||
| 158 | connector->base.id, drm_get_connector_name(connector)); | ||
| 159 | drm_mode_connector_update_edid_property(connector, NULL); | ||
| 160 | verbose_prune = false; | ||
| 161 | goto prune; | ||
| 162 | } | ||
| 163 | |||
| 164 | #ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE | ||
| 165 | count = drm_load_edid_firmware(connector); | ||
| 166 | if (count == 0) | ||
| 167 | #endif | ||
| 168 | count = (*connector_funcs->get_modes)(connector); | ||
| 169 | |||
| 170 | if (count == 0 && connector->status == connector_status_connected) | ||
| 171 | count = drm_add_modes_noedid(connector, 1024, 768); | ||
| 172 | if (count == 0) | ||
| 173 | goto prune; | ||
| 174 | |||
| 175 | drm_mode_connector_list_update(connector); | ||
| 176 | |||
| 177 | if (maxX && maxY) | ||
| 178 | drm_mode_validate_size(dev, &connector->modes, maxX, maxY); | ||
| 179 | |||
| 180 | if (connector->interlace_allowed) | ||
| 181 | mode_flags |= DRM_MODE_FLAG_INTERLACE; | ||
| 182 | if (connector->doublescan_allowed) | ||
| 183 | mode_flags |= DRM_MODE_FLAG_DBLSCAN; | ||
| 184 | if (connector->stereo_allowed) | ||
| 185 | mode_flags |= DRM_MODE_FLAG_3D_MASK; | ||
| 186 | drm_mode_validate_flag(connector, mode_flags); | ||
| 187 | |||
| 188 | list_for_each_entry(mode, &connector->modes, head) { | ||
| 189 | if (mode->status == MODE_OK) | ||
| 190 | mode->status = connector_funcs->mode_valid(connector, | ||
| 191 | mode); | ||
| 192 | } | ||
| 193 | |||
| 194 | prune: | ||
| 195 | drm_mode_prune_invalid(dev, &connector->modes, verbose_prune); | ||
| 196 | |||
| 197 | if (list_empty(&connector->modes)) | ||
| 198 | return 0; | ||
| 199 | |||
| 200 | list_for_each_entry(mode, &connector->modes, head) | ||
| 201 | mode->vrefresh = drm_mode_vrefresh(mode); | ||
| 202 | |||
| 203 | drm_mode_sort(&connector->modes); | ||
| 204 | |||
| 205 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id, | ||
| 206 | drm_get_connector_name(connector)); | ||
| 207 | list_for_each_entry(mode, &connector->modes, head) { | ||
| 208 | drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); | ||
| 209 | drm_mode_debug_printmodeline(mode); | ||
| 210 | } | ||
| 211 | |||
| 212 | return count; | ||
| 213 | } | ||
| 214 | EXPORT_SYMBOL(drm_helper_probe_single_connector_modes); | ||
| 215 | |||
| 216 | /** | 75 | /** |
| 217 | * drm_helper_encoder_in_use - check if a given encoder is in use | 76 | * drm_helper_encoder_in_use - check if a given encoder is in use |
| 218 | * @encoder: encoder to check | 77 | * @encoder: encoder to check |
| @@ -1020,232 +879,3 @@ void drm_helper_resume_force_mode(struct drm_device *dev) | |||
| 1020 | drm_modeset_unlock_all(dev); | 879 | drm_modeset_unlock_all(dev); |
| 1021 | } | 880 | } |
| 1022 | EXPORT_SYMBOL(drm_helper_resume_force_mode); | 881 | EXPORT_SYMBOL(drm_helper_resume_force_mode); |
| 1023 | |||
| 1024 | /** | ||
| 1025 | * drm_kms_helper_hotplug_event - fire off KMS hotplug events | ||
| 1026 | * @dev: drm_device whose connector state changed | ||
| 1027 | * | ||
| 1028 | * This function fires off the uevent for userspace and also calls the | ||
| 1029 | * output_poll_changed function, which is most commonly used to inform the fbdev | ||
| 1030 | * emulation code and allow it to update the fbcon output configuration. | ||
| 1031 | * | ||
| 1032 | * Drivers should call this from their hotplug handling code when a change is | ||
| 1033 | * detected. Note that this function does not do any output detection of its | ||
| 1034 | * own, like drm_helper_hpd_irq_event() does - this is assumed to be done by the | ||
| 1035 | * driver already. | ||
| 1036 | * | ||
| 1037 | * This function must be called from process context with no mode | ||
| 1038 | * setting locks held. | ||
| 1039 | */ | ||
| 1040 | void drm_kms_helper_hotplug_event(struct drm_device *dev) | ||
| 1041 | { | ||
| 1042 | /* send a uevent + call fbdev */ | ||
| 1043 | drm_sysfs_hotplug_event(dev); | ||
| 1044 | if (dev->mode_config.funcs->output_poll_changed) | ||
| 1045 | dev->mode_config.funcs->output_poll_changed(dev); | ||
| 1046 | } | ||
| 1047 | EXPORT_SYMBOL(drm_kms_helper_hotplug_event); | ||
| 1048 | |||
| 1049 | #define DRM_OUTPUT_POLL_PERIOD (10*HZ) | ||
| 1050 | static void output_poll_execute(struct work_struct *work) | ||
| 1051 | { | ||
| 1052 | struct delayed_work *delayed_work = to_delayed_work(work); | ||
| 1053 | struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_work); | ||
| 1054 | struct drm_connector *connector; | ||
| 1055 | enum drm_connector_status old_status; | ||
| 1056 | bool repoll = false, changed = false; | ||
| 1057 | |||
| 1058 | if (!drm_kms_helper_poll) | ||
| 1059 | return; | ||
| 1060 | |||
| 1061 | mutex_lock(&dev->mode_config.mutex); | ||
| 1062 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
| 1063 | |||
| 1064 | /* Ignore forced connectors. */ | ||
| 1065 | if (connector->force) | ||
| 1066 | continue; | ||
| 1067 | |||
| 1068 | /* Ignore HPD capable connectors and connectors where we don't | ||
| 1069 | * want any hotplug detection at all for polling. */ | ||
| 1070 | if (!connector->polled || connector->polled == DRM_CONNECTOR_POLL_HPD) | ||
| 1071 | continue; | ||
| 1072 | |||
| 1073 | repoll = true; | ||
| 1074 | |||
| 1075 | old_status = connector->status; | ||
| 1076 | /* if we are connected and don't want to poll for disconnect | ||
| 1077 | skip it */ | ||
| 1078 | if (old_status == connector_status_connected && | ||
| 1079 | !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT)) | ||
| 1080 | continue; | ||
| 1081 | |||
| 1082 | connector->status = connector->funcs->detect(connector, false); | ||
| 1083 | if (old_status != connector->status) { | ||
| 1084 | const char *old, *new; | ||
| 1085 | |||
| 1086 | old = drm_get_connector_status_name(old_status); | ||
| 1087 | new = drm_get_connector_status_name(connector->status); | ||
| 1088 | |||
| 1089 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] " | ||
| 1090 | "status updated from %s to %s\n", | ||
| 1091 | connector->base.id, | ||
| 1092 | drm_get_connector_name(connector), | ||
| 1093 | old, new); | ||
| 1094 | |||
| 1095 | changed = true; | ||
| 1096 | } | ||
| 1097 | } | ||
| 1098 | |||
| 1099 | mutex_unlock(&dev->mode_config.mutex); | ||
| 1100 | |||
| 1101 | if (changed) | ||
| 1102 | drm_kms_helper_hotplug_event(dev); | ||
| 1103 | |||
| 1104 | if (repoll) | ||
| 1105 | schedule_delayed_work(delayed_work, DRM_OUTPUT_POLL_PERIOD); | ||
| 1106 | } | ||
| 1107 | |||
| 1108 | /** | ||
| 1109 | * drm_kms_helper_poll_disable - disable output polling | ||
| 1110 | * @dev: drm_device | ||
| 1111 | * | ||
| 1112 | * This function disables the output polling work. | ||
| 1113 | * | ||
| 1114 | * Drivers can call this helper from their device suspend implementation. It is | ||
| 1115 | * not an error to call this even when output polling isn't enabled or arlready | ||
| 1116 | * disabled. | ||
| 1117 | */ | ||
| 1118 | void drm_kms_helper_poll_disable(struct drm_device *dev) | ||
| 1119 | { | ||
| 1120 | if (!dev->mode_config.poll_enabled) | ||
| 1121 | return; | ||
| 1122 | cancel_delayed_work_sync(&dev->mode_config.output_poll_work); | ||
| 1123 | } | ||
| 1124 | EXPORT_SYMBOL(drm_kms_helper_poll_disable); | ||
| 1125 | |||
| 1126 | /** | ||
| 1127 | * drm_kms_helper_poll_enable - re-enable output polling. | ||
| 1128 | * @dev: drm_device | ||
| 1129 | * | ||
| 1130 | * This function re-enables the output polling work. | ||
| 1131 | * | ||
| 1132 | * Drivers can call this helper from their device resume implementation. It is | ||
| 1133 | * an error to call this when the output polling support has not yet been set | ||
| 1134 | * up. | ||
| 1135 | */ | ||
| 1136 | void drm_kms_helper_poll_enable(struct drm_device *dev) | ||
| 1137 | { | ||
| 1138 | bool poll = false; | ||
| 1139 | struct drm_connector *connector; | ||
| 1140 | |||
| 1141 | if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll) | ||
| 1142 | return; | ||
| 1143 | |||
| 1144 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
| 1145 | if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | | ||
| 1146 | DRM_CONNECTOR_POLL_DISCONNECT)) | ||
| 1147 | poll = true; | ||
| 1148 | } | ||
| 1149 | |||
| 1150 | if (poll) | ||
| 1151 | schedule_delayed_work(&dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD); | ||
| 1152 | } | ||
| 1153 | EXPORT_SYMBOL(drm_kms_helper_poll_enable); | ||
| 1154 | |||
| 1155 | /** | ||
| 1156 | * drm_kms_helper_poll_init - initialize and enable output polling | ||
| 1157 | * @dev: drm_device | ||
| 1158 | * | ||
| 1159 | * This function intializes and then also enables output polling support for | ||
| 1160 | * @dev. Drivers which do not have reliable hotplug support in hardware can use | ||
| 1161 | * this helper infrastructure to regularly poll such connectors for changes in | ||
| 1162 | * their connection state. | ||
| 1163 | * | ||
| 1164 | * Drivers can control which connectors are polled by setting the | ||
| 1165 | * DRM_CONNECTOR_POLL_CONNECT and DRM_CONNECTOR_POLL_DISCONNECT flags. On | ||
| 1166 | * connectors where probing live outputs can result in visual distortion drivers | ||
| 1167 | * should not set the DRM_CONNECTOR_POLL_DISCONNECT flag to avoid this. | ||
| 1168 | * Connectors which have no flag or only DRM_CONNECTOR_POLL_HPD set are | ||
| 1169 | * completely ignored by the polling logic. | ||
| 1170 | * | ||
| 1171 | * Note that a connector can be both polled and probed from the hotplug handler, | ||
| 1172 | * in case the hotplug interrupt is known to be unreliable. | ||
| 1173 | */ | ||
| 1174 | void drm_kms_helper_poll_init(struct drm_device *dev) | ||
| 1175 | { | ||
| 1176 | INIT_DELAYED_WORK(&dev->mode_config.output_poll_work, output_poll_execute); | ||
| 1177 | dev->mode_config.poll_enabled = true; | ||
| 1178 | |||
| 1179 | drm_kms_helper_poll_enable(dev); | ||
| 1180 | } | ||
| 1181 | EXPORT_SYMBOL(drm_kms_helper_poll_init); | ||
| 1182 | |||
| 1183 | /** | ||
| 1184 | * drm_kms_helper_poll_fini - disable output polling and clean it up | ||
| 1185 | * @dev: drm_device | ||
| 1186 | */ | ||
| 1187 | void drm_kms_helper_poll_fini(struct drm_device *dev) | ||
| 1188 | { | ||
| 1189 | drm_kms_helper_poll_disable(dev); | ||
| 1190 | } | ||
| 1191 | EXPORT_SYMBOL(drm_kms_helper_poll_fini); | ||
| 1192 | |||
| 1193 | /** | ||
| 1194 | * drm_helper_hpd_irq_event - hotplug processing | ||
| 1195 | * @dev: drm_device | ||
| 1196 | * | ||
| 1197 | * Drivers can use this helper function to run a detect cycle on all connectors | ||
| 1198 | * which have the DRM_CONNECTOR_POLL_HPD flag set in their &polled member. All | ||
| 1199 | * other connectors are ignored, which is useful to avoid reprobing fixed | ||
| 1200 | * panels. | ||
| 1201 | * | ||
| 1202 | * This helper function is useful for drivers which can't or don't track hotplug | ||
| 1203 | * interrupts for each connector. | ||
| 1204 | * | ||
| 1205 | * Drivers which support hotplug interrupts for each connector individually and | ||
| 1206 | * which have a more fine-grained detect logic should bypass this code and | ||
| 1207 | * directly call drm_kms_helper_hotplug_event() in case the connector state | ||
| 1208 | * changed. | ||
| 1209 | * | ||
| 1210 | * This function must be called from process context with no mode | ||
| 1211 | * setting locks held. | ||
| 1212 | * | ||
| 1213 | * Note that a connector can be both polled and probed from the hotplug handler, | ||
| 1214 | * in case the hotplug interrupt is known to be unreliable. | ||
| 1215 | */ | ||
| 1216 | bool drm_helper_hpd_irq_event(struct drm_device *dev) | ||
| 1217 | { | ||
| 1218 | struct drm_connector *connector; | ||
| 1219 | enum drm_connector_status old_status; | ||
| 1220 | bool changed = false; | ||
| 1221 | |||
| 1222 | if (!dev->mode_config.poll_enabled) | ||
| 1223 | return false; | ||
| 1224 | |||
| 1225 | mutex_lock(&dev->mode_config.mutex); | ||
| 1226 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
| 1227 | |||
| 1228 | /* Only handle HPD capable connectors. */ | ||
| 1229 | if (!(connector->polled & DRM_CONNECTOR_POLL_HPD)) | ||
| 1230 | continue; | ||
| 1231 | |||
| 1232 | old_status = connector->status; | ||
| 1233 | |||
| 1234 | connector->status = connector->funcs->detect(connector, false); | ||
| 1235 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n", | ||
| 1236 | connector->base.id, | ||
| 1237 | drm_get_connector_name(connector), | ||
| 1238 | drm_get_connector_status_name(old_status), | ||
| 1239 | drm_get_connector_status_name(connector->status)); | ||
| 1240 | if (old_status != connector->status) | ||
| 1241 | changed = true; | ||
| 1242 | } | ||
| 1243 | |||
| 1244 | mutex_unlock(&dev->mode_config.mutex); | ||
| 1245 | |||
| 1246 | if (changed) | ||
| 1247 | drm_kms_helper_hotplug_event(dev); | ||
| 1248 | |||
| 1249 | return changed; | ||
| 1250 | } | ||
| 1251 | EXPORT_SYMBOL(drm_helper_hpd_irq_event); | ||
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 27671489477d..4b6e6f3ba0a1 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c | |||
| @@ -577,7 +577,9 @@ static u32 drm_dp_i2c_functionality(struct i2c_adapter *adapter) | |||
| 577 | 577 | ||
| 578 | /* | 578 | /* |
| 579 | * Transfer a single I2C-over-AUX message and handle various error conditions, | 579 | * Transfer a single I2C-over-AUX message and handle various error conditions, |
| 580 | * retrying the transaction as appropriate. | 580 | * retrying the transaction as appropriate. It is assumed that the |
| 581 | * aux->transfer function does not modify anything in the msg other than the | ||
| 582 | * reply field. | ||
| 581 | */ | 583 | */ |
| 582 | static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) | 584 | static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) |
| 583 | { | 585 | { |
| @@ -665,11 +667,26 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, | |||
| 665 | { | 667 | { |
| 666 | struct drm_dp_aux *aux = adapter->algo_data; | 668 | struct drm_dp_aux *aux = adapter->algo_data; |
| 667 | unsigned int i, j; | 669 | unsigned int i, j; |
| 670 | struct drm_dp_aux_msg msg; | ||
| 671 | int err = 0; | ||
| 668 | 672 | ||
| 669 | for (i = 0; i < num; i++) { | 673 | memset(&msg, 0, sizeof(msg)); |
| 670 | struct drm_dp_aux_msg msg; | ||
| 671 | int err; | ||
| 672 | 674 | ||
| 675 | for (i = 0; i < num; i++) { | ||
| 676 | msg.address = msgs[i].addr; | ||
| 677 | msg.request = (msgs[i].flags & I2C_M_RD) ? | ||
| 678 | DP_AUX_I2C_READ : | ||
| 679 | DP_AUX_I2C_WRITE; | ||
| 680 | msg.request |= DP_AUX_I2C_MOT; | ||
| 681 | /* Send a bare address packet to start the transaction. | ||
| 682 | * Zero sized messages specify an address only (bare | ||
| 683 | * address) transaction. | ||
| 684 | */ | ||
| 685 | msg.buffer = NULL; | ||
| 686 | msg.size = 0; | ||
| 687 | err = drm_dp_i2c_do_msg(aux, &msg); | ||
| 688 | if (err < 0) | ||
| 689 | break; | ||
| 673 | /* | 690 | /* |
| 674 | * Many hardware implementations support FIFOs larger than a | 691 | * Many hardware implementations support FIFOs larger than a |
| 675 | * single byte, but it has been empirically determined that | 692 | * single byte, but it has been empirically determined that |
| @@ -678,30 +695,28 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, | |||
| 678 | * transferred byte-by-byte. | 695 | * transferred byte-by-byte. |
| 679 | */ | 696 | */ |
| 680 | for (j = 0; j < msgs[i].len; j++) { | 697 | for (j = 0; j < msgs[i].len; j++) { |
| 681 | memset(&msg, 0, sizeof(msg)); | ||
| 682 | msg.address = msgs[i].addr; | ||
| 683 | |||
| 684 | msg.request = (msgs[i].flags & I2C_M_RD) ? | ||
| 685 | DP_AUX_I2C_READ : | ||
| 686 | DP_AUX_I2C_WRITE; | ||
| 687 | |||
| 688 | /* | ||
| 689 | * All messages except the last one are middle-of- | ||
| 690 | * transfer messages. | ||
| 691 | */ | ||
| 692 | if ((i < num - 1) || (j < msgs[i].len - 1)) | ||
| 693 | msg.request |= DP_AUX_I2C_MOT; | ||
| 694 | |||
| 695 | msg.buffer = msgs[i].buf + j; | 698 | msg.buffer = msgs[i].buf + j; |
| 696 | msg.size = 1; | 699 | msg.size = 1; |
| 697 | 700 | ||
| 698 | err = drm_dp_i2c_do_msg(aux, &msg); | 701 | err = drm_dp_i2c_do_msg(aux, &msg); |
| 699 | if (err < 0) | 702 | if (err < 0) |
| 700 | return err; | 703 | break; |
| 701 | } | 704 | } |
| 705 | if (err < 0) | ||
| 706 | break; | ||
| 702 | } | 707 | } |
| 708 | if (err >= 0) | ||
| 709 | err = num; | ||
| 710 | /* Send a bare address packet to close out the transaction. | ||
| 711 | * Zero sized messages specify an address only (bare | ||
| 712 | * address) transaction. | ||
| 713 | */ | ||
| 714 | msg.request &= ~DP_AUX_I2C_MOT; | ||
| 715 | msg.buffer = NULL; | ||
| 716 | msg.size = 0; | ||
| 717 | (void)drm_dp_i2c_do_msg(aux, &msg); | ||
| 703 | 718 | ||
| 704 | return num; | 719 | return err; |
| 705 | } | 720 | } |
| 706 | 721 | ||
| 707 | static const struct i2c_algorithm drm_dp_i2c_algo = { | 722 | static const struct i2c_algorithm drm_dp_i2c_algo = { |
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 71e2d3fcd6ee..04a209e2b66d 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c | |||
| @@ -207,8 +207,6 @@ int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node) | |||
| 207 | return 0; | 207 | return 0; |
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | WARN(1, "no hole found for node 0x%lx + 0x%lx\n", | ||
| 211 | node->start, node->size); | ||
| 212 | return -ENOSPC; | 210 | return -ENOSPC; |
| 213 | } | 211 | } |
| 214 | EXPORT_SYMBOL(drm_mm_reserve_node); | 212 | EXPORT_SYMBOL(drm_mm_reserve_node); |
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index e768d35ff22e..d2b1c03b3d71 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c | |||
| @@ -203,9 +203,9 @@ EXPORT_SYMBOL(drm_primary_helper_update); | |||
| 203 | * | 203 | * |
| 204 | * Provides a default plane disable handler for primary planes. This is handler | 204 | * Provides a default plane disable handler for primary planes. This is handler |
| 205 | * is called in response to a userspace SetPlane operation on the plane with a | 205 | * is called in response to a userspace SetPlane operation on the plane with a |
| 206 | * NULL framebuffer parameter. We call the driver's modeset handler with a NULL | 206 | * NULL framebuffer parameter. It unconditionally fails the disable call with |
| 207 | * framebuffer to disable the CRTC if no other planes are currently enabled. | 207 | * -EINVAL the only way to disable the primary plane without driver support is |
| 208 | * If other planes are still enabled on the same CRTC, we return -EBUSY. | 208 | * to disable the entier CRTC. Which does not match the plane ->disable hook. |
| 209 | * | 209 | * |
| 210 | * Note that some hardware may be able to disable the primary plane without | 210 | * Note that some hardware may be able to disable the primary plane without |
| 211 | * disabling the whole CRTC. Drivers for such hardware should provide their | 211 | * disabling the whole CRTC. Drivers for such hardware should provide their |
| @@ -214,34 +214,11 @@ EXPORT_SYMBOL(drm_primary_helper_update); | |||
| 214 | * disabled primary plane). | 214 | * disabled primary plane). |
| 215 | * | 215 | * |
| 216 | * RETURNS: | 216 | * RETURNS: |
| 217 | * Zero on success, error code on failure | 217 | * Unconditionally returns -EINVAL. |
| 218 | */ | 218 | */ |
| 219 | int drm_primary_helper_disable(struct drm_plane *plane) | 219 | int drm_primary_helper_disable(struct drm_plane *plane) |
| 220 | { | 220 | { |
| 221 | struct drm_plane *p; | 221 | return -EINVAL; |
| 222 | struct drm_mode_set set = { | ||
| 223 | .crtc = plane->crtc, | ||
| 224 | .fb = NULL, | ||
| 225 | }; | ||
| 226 | |||
| 227 | if (plane->crtc == NULL || plane->fb == NULL) | ||
| 228 | /* Already disabled */ | ||
| 229 | return 0; | ||
| 230 | |||
| 231 | list_for_each_entry(p, &plane->dev->mode_config.plane_list, head) | ||
| 232 | if (p != plane && p->fb) { | ||
| 233 | DRM_DEBUG_KMS("Cannot disable primary plane while other planes are still active on CRTC.\n"); | ||
| 234 | return -EBUSY; | ||
| 235 | } | ||
| 236 | |||
| 237 | /* | ||
| 238 | * N.B. We call set_config() directly here rather than | ||
| 239 | * drm_mode_set_config_internal() since drm_mode_setplane() already | ||
| 240 | * handles the basic refcounting and we don't need the special | ||
| 241 | * cross-CRTC refcounting (no chance of stealing connectors from | ||
| 242 | * other CRTC's with this update). | ||
| 243 | */ | ||
| 244 | return plane->crtc->funcs->set_config(&set); | ||
| 245 | } | 222 | } |
| 246 | EXPORT_SYMBOL(drm_primary_helper_disable); | 223 | EXPORT_SYMBOL(drm_primary_helper_disable); |
| 247 | 224 | ||
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c new file mode 100644 index 000000000000..e70f54d4a581 --- /dev/null +++ b/drivers/gpu/drm/drm_probe_helper.c | |||
| @@ -0,0 +1,426 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2006-2008 Intel Corporation | ||
| 3 | * Copyright (c) 2007 Dave Airlie <airlied@linux.ie> | ||
| 4 | * | ||
| 5 | * DRM core CRTC related functions | ||
| 6 | * | ||
| 7 | * Permission to use, copy, modify, distribute, and sell this software and its | ||
| 8 | * documentation for any purpose is hereby granted without fee, provided that | ||
| 9 | * the above copyright notice appear in all copies and that both that copyright | ||
| 10 | * notice and this permission notice appear in supporting documentation, and | ||
| 11 | * that the name of the copyright holders not be used in advertising or | ||
| 12 | * publicity pertaining to distribution of the software without specific, | ||
| 13 | * written prior permission. The copyright holders make no representations | ||
| 14 | * about the suitability of this software for any purpose. It is provided "as | ||
| 15 | * is" without express or implied warranty. | ||
| 16 | * | ||
| 17 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | ||
| 18 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | ||
| 19 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR | ||
| 20 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | ||
| 21 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | ||
| 22 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | ||
| 23 | * OF THIS SOFTWARE. | ||
| 24 | * | ||
| 25 | * Authors: | ||
| 26 | * Keith Packard | ||
| 27 | * Eric Anholt <eric@anholt.net> | ||
| 28 | * Dave Airlie <airlied@linux.ie> | ||
| 29 | * Jesse Barnes <jesse.barnes@intel.com> | ||
| 30 | */ | ||
| 31 | |||
| 32 | #include <linux/export.h> | ||
| 33 | #include <linux/moduleparam.h> | ||
| 34 | |||
| 35 | #include <drm/drmP.h> | ||
| 36 | #include <drm/drm_crtc.h> | ||
| 37 | #include <drm/drm_fourcc.h> | ||
| 38 | #include <drm/drm_crtc_helper.h> | ||
| 39 | #include <drm/drm_fb_helper.h> | ||
| 40 | #include <drm/drm_edid.h> | ||
| 41 | |||
| 42 | /** | ||
| 43 | * DOC: output probing helper overview | ||
| 44 | * | ||
| 45 | * This library provides some helper code for output probing. It provides an | ||
| 46 | * implementation of the core connector->fill_modes interface with | ||
| 47 | * drm_helper_probe_single_connector_modes. | ||
| 48 | * | ||
| 49 | * It also provides support for polling connectors with a work item and for | ||
| 50 | * generic hotplug interrupt handling where the driver doesn't or cannot keep | ||
| 51 | * track of a per-connector hpd interrupt. | ||
| 52 | * | ||
| 53 | * This helper library can be used independently of the modeset helper library. | ||
| 54 | * Drivers can also overwrite different parts e.g. use their own hotplug | ||
| 55 | * handling code to avoid probing unrelated outputs. | ||
| 56 | */ | ||
| 57 | |||
| 58 | static bool drm_kms_helper_poll = true; | ||
| 59 | module_param_named(poll, drm_kms_helper_poll, bool, 0600); | ||
| 60 | |||
| 61 | static void drm_mode_validate_flag(struct drm_connector *connector, | ||
| 62 | int flags) | ||
| 63 | { | ||
| 64 | struct drm_display_mode *mode; | ||
| 65 | |||
| 66 | if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE | | ||
| 67 | DRM_MODE_FLAG_3D_MASK)) | ||
| 68 | return; | ||
| 69 | |||
| 70 | list_for_each_entry(mode, &connector->modes, head) { | ||
| 71 | if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && | ||
| 72 | !(flags & DRM_MODE_FLAG_INTERLACE)) | ||
| 73 | mode->status = MODE_NO_INTERLACE; | ||
| 74 | if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) && | ||
| 75 | !(flags & DRM_MODE_FLAG_DBLSCAN)) | ||
| 76 | mode->status = MODE_NO_DBLESCAN; | ||
| 77 | if ((mode->flags & DRM_MODE_FLAG_3D_MASK) && | ||
| 78 | !(flags & DRM_MODE_FLAG_3D_MASK)) | ||
| 79 | mode->status = MODE_NO_STEREO; | ||
| 80 | } | ||
| 81 | |||
| 82 | return; | ||
| 83 | } | ||
| 84 | |||
| 85 | /** | ||
| 86 | * drm_helper_probe_single_connector_modes - get complete set of display modes | ||
| 87 | * @connector: connector to probe | ||
| 88 | * @maxX: max width for modes | ||
| 89 | * @maxY: max height for modes | ||
| 90 | * | ||
| 91 | * Based on the helper callbacks implemented by @connector try to detect all | ||
| 92 | * valid modes. Modes will first be added to the connector's probed_modes list, | ||
| 93 | * then culled (based on validity and the @maxX, @maxY parameters) and put into | ||
| 94 | * the normal modes list. | ||
| 95 | * | ||
| 96 | * Intended to be use as a generic implementation of the ->fill_modes() | ||
| 97 | * @connector vfunc for drivers that use the crtc helpers for output mode | ||
| 98 | * filtering and detection. | ||
| 99 | * | ||
| 100 | * Returns: | ||
| 101 | * The number of modes found on @connector. | ||
| 102 | */ | ||
| 103 | int drm_helper_probe_single_connector_modes(struct drm_connector *connector, | ||
| 104 | uint32_t maxX, uint32_t maxY) | ||
| 105 | { | ||
| 106 | struct drm_device *dev = connector->dev; | ||
| 107 | struct drm_display_mode *mode; | ||
| 108 | struct drm_connector_helper_funcs *connector_funcs = | ||
| 109 | connector->helper_private; | ||
| 110 | int count = 0; | ||
| 111 | int mode_flags = 0; | ||
| 112 | bool verbose_prune = true; | ||
| 113 | |||
| 114 | WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); | ||
| 115 | |||
| 116 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, | ||
| 117 | drm_get_connector_name(connector)); | ||
| 118 | /* set all modes to the unverified state */ | ||
| 119 | list_for_each_entry(mode, &connector->modes, head) | ||
| 120 | mode->status = MODE_UNVERIFIED; | ||
| 121 | |||
| 122 | if (connector->force) { | ||
| 123 | if (connector->force == DRM_FORCE_ON) | ||
| 124 | connector->status = connector_status_connected; | ||
| 125 | else | ||
| 126 | connector->status = connector_status_disconnected; | ||
| 127 | if (connector->funcs->force) | ||
| 128 | connector->funcs->force(connector); | ||
| 129 | } else { | ||
| 130 | connector->status = connector->funcs->detect(connector, true); | ||
| 131 | } | ||
| 132 | |||
| 133 | /* Re-enable polling in case the global poll config changed. */ | ||
| 134 | if (drm_kms_helper_poll != dev->mode_config.poll_running) | ||
| 135 | drm_kms_helper_poll_enable(dev); | ||
| 136 | |||
| 137 | dev->mode_config.poll_running = drm_kms_helper_poll; | ||
| 138 | |||
| 139 | if (connector->status == connector_status_disconnected) { | ||
| 140 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n", | ||
| 141 | connector->base.id, drm_get_connector_name(connector)); | ||
| 142 | drm_mode_connector_update_edid_property(connector, NULL); | ||
| 143 | verbose_prune = false; | ||
| 144 | goto prune; | ||
| 145 | } | ||
| 146 | |||
| 147 | #ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE | ||
| 148 | count = drm_load_edid_firmware(connector); | ||
| 149 | if (count == 0) | ||
| 150 | #endif | ||
| 151 | count = (*connector_funcs->get_modes)(connector); | ||
| 152 | |||
| 153 | if (count == 0 && connector->status == connector_status_connected) | ||
| 154 | count = drm_add_modes_noedid(connector, 1024, 768); | ||
| 155 | if (count == 0) | ||
| 156 | goto prune; | ||
| 157 | |||
| 158 | drm_mode_connector_list_update(connector); | ||
| 159 | |||
| 160 | if (maxX && maxY) | ||
| 161 | drm_mode_validate_size(dev, &connector->modes, maxX, maxY); | ||
| 162 | |||
| 163 | if (connector->interlace_allowed) | ||
| 164 | mode_flags |= DRM_MODE_FLAG_INTERLACE; | ||
| 165 | if (connector->doublescan_allowed) | ||
| 166 | mode_flags |= DRM_MODE_FLAG_DBLSCAN; | ||
| 167 | if (connector->stereo_allowed) | ||
| 168 | mode_flags |= DRM_MODE_FLAG_3D_MASK; | ||
| 169 | drm_mode_validate_flag(connector, mode_flags); | ||
| 170 | |||
| 171 | list_for_each_entry(mode, &connector->modes, head) { | ||
| 172 | if (mode->status == MODE_OK) | ||
| 173 | mode->status = connector_funcs->mode_valid(connector, | ||
| 174 | mode); | ||
| 175 | } | ||
| 176 | |||
| 177 | prune: | ||
| 178 | drm_mode_prune_invalid(dev, &connector->modes, verbose_prune); | ||
| 179 | |||
| 180 | if (list_empty(&connector->modes)) | ||
| 181 | return 0; | ||
| 182 | |||
| 183 | list_for_each_entry(mode, &connector->modes, head) | ||
| 184 | mode->vrefresh = drm_mode_vrefresh(mode); | ||
| 185 | |||
| 186 | drm_mode_sort(&connector->modes); | ||
| 187 | |||
| 188 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id, | ||
| 189 | drm_get_connector_name(connector)); | ||
| 190 | list_for_each_entry(mode, &connector->modes, head) { | ||
| 191 | drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); | ||
| 192 | drm_mode_debug_printmodeline(mode); | ||
| 193 | } | ||
| 194 | |||
| 195 | return count; | ||
| 196 | } | ||
| 197 | EXPORT_SYMBOL(drm_helper_probe_single_connector_modes); | ||
| 198 | |||
| 199 | /** | ||
| 200 | * drm_kms_helper_hotplug_event - fire off KMS hotplug events | ||
| 201 | * @dev: drm_device whose connector state changed | ||
| 202 | * | ||
| 203 | * This function fires off the uevent for userspace and also calls the | ||
| 204 | * output_poll_changed function, which is most commonly used to inform the fbdev | ||
| 205 | * emulation code and allow it to update the fbcon output configuration. | ||
| 206 | * | ||
| 207 | * Drivers should call this from their hotplug handling code when a change is | ||
| 208 | * detected. Note that this function does not do any output detection of its | ||
| 209 | * own, like drm_helper_hpd_irq_event() does - this is assumed to be done by the | ||
| 210 | * driver already. | ||
| 211 | * | ||
| 212 | * This function must be called from process context with no mode | ||
| 213 | * setting locks held. | ||
| 214 | */ | ||
| 215 | void drm_kms_helper_hotplug_event(struct drm_device *dev) | ||
| 216 | { | ||
| 217 | /* send a uevent + call fbdev */ | ||
| 218 | drm_sysfs_hotplug_event(dev); | ||
| 219 | if (dev->mode_config.funcs->output_poll_changed) | ||
| 220 | dev->mode_config.funcs->output_poll_changed(dev); | ||
| 221 | } | ||
| 222 | EXPORT_SYMBOL(drm_kms_helper_hotplug_event); | ||
| 223 | |||
| 224 | #define DRM_OUTPUT_POLL_PERIOD (10*HZ) | ||
| 225 | static void output_poll_execute(struct work_struct *work) | ||
| 226 | { | ||
| 227 | struct delayed_work *delayed_work = to_delayed_work(work); | ||
| 228 | struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_work); | ||
| 229 | struct drm_connector *connector; | ||
| 230 | enum drm_connector_status old_status; | ||
| 231 | bool repoll = false, changed = false; | ||
| 232 | |||
| 233 | if (!drm_kms_helper_poll) | ||
| 234 | return; | ||
| 235 | |||
| 236 | mutex_lock(&dev->mode_config.mutex); | ||
| 237 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
| 238 | |||
| 239 | /* Ignore forced connectors. */ | ||
| 240 | if (connector->force) | ||
| 241 | continue; | ||
| 242 | |||
| 243 | /* Ignore HPD capable connectors and connectors where we don't | ||
| 244 | * want any hotplug detection at all for polling. */ | ||
| 245 | if (!connector->polled || connector->polled == DRM_CONNECTOR_POLL_HPD) | ||
| 246 | continue; | ||
| 247 | |||
| 248 | repoll = true; | ||
| 249 | |||
| 250 | old_status = connector->status; | ||
| 251 | /* if we are connected and don't want to poll for disconnect | ||
| 252 | skip it */ | ||
| 253 | if (old_status == connector_status_connected && | ||
| 254 | !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT)) | ||
| 255 | continue; | ||
| 256 | |||
| 257 | connector->status = connector->funcs->detect(connector, false); | ||
| 258 | if (old_status != connector->status) { | ||
| 259 | const char *old, *new; | ||
| 260 | |||
| 261 | old = drm_get_connector_status_name(old_status); | ||
| 262 | new = drm_get_connector_status_name(connector->status); | ||
| 263 | |||
| 264 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] " | ||
| 265 | "status updated from %s to %s\n", | ||
| 266 | connector->base.id, | ||
| 267 | drm_get_connector_name(connector), | ||
| 268 | old, new); | ||
| 269 | |||
| 270 | changed = true; | ||
| 271 | } | ||
| 272 | } | ||
| 273 | |||
| 274 | mutex_unlock(&dev->mode_config.mutex); | ||
| 275 | |||
| 276 | if (changed) | ||
| 277 | drm_kms_helper_hotplug_event(dev); | ||
| 278 | |||
| 279 | if (repoll) | ||
| 280 | schedule_delayed_work(delayed_work, DRM_OUTPUT_POLL_PERIOD); | ||
| 281 | } | ||
| 282 | |||
| 283 | /** | ||
| 284 | * drm_kms_helper_poll_disable - disable output polling | ||
| 285 | * @dev: drm_device | ||
| 286 | * | ||
| 287 | * This function disables the output polling work. | ||
| 288 | * | ||
| 289 | * Drivers can call this helper from their device suspend implementation. It is | ||
| 290 | * not an error to call this even when output polling isn't enabled or arlready | ||
| 291 | * disabled. | ||
| 292 | */ | ||
| 293 | void drm_kms_helper_poll_disable(struct drm_device *dev) | ||
| 294 | { | ||
| 295 | if (!dev->mode_config.poll_enabled) | ||
| 296 | return; | ||
| 297 | cancel_delayed_work_sync(&dev->mode_config.output_poll_work); | ||
| 298 | } | ||
| 299 | EXPORT_SYMBOL(drm_kms_helper_poll_disable); | ||
| 300 | |||
| 301 | /** | ||
| 302 | * drm_kms_helper_poll_enable - re-enable output polling. | ||
| 303 | * @dev: drm_device | ||
| 304 | * | ||
| 305 | * This function re-enables the output polling work. | ||
| 306 | * | ||
| 307 | * Drivers can call this helper from their device resume implementation. It is | ||
| 308 | * an error to call this when the output polling support has not yet been set | ||
| 309 | * up. | ||
| 310 | */ | ||
| 311 | void drm_kms_helper_poll_enable(struct drm_device *dev) | ||
| 312 | { | ||
| 313 | bool poll = false; | ||
| 314 | struct drm_connector *connector; | ||
| 315 | |||
| 316 | if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll) | ||
| 317 | return; | ||
| 318 | |||
| 319 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
| 320 | if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | | ||
| 321 | DRM_CONNECTOR_POLL_DISCONNECT)) | ||
| 322 | poll = true; | ||
| 323 | } | ||
| 324 | |||
| 325 | if (poll) | ||
| 326 | schedule_delayed_work(&dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD); | ||
| 327 | } | ||
| 328 | EXPORT_SYMBOL(drm_kms_helper_poll_enable); | ||
| 329 | |||
| 330 | /** | ||
| 331 | * drm_kms_helper_poll_init - initialize and enable output polling | ||
| 332 | * @dev: drm_device | ||
| 333 | * | ||
| 334 | * This function intializes and then also enables output polling support for | ||
| 335 | * @dev. Drivers which do not have reliable hotplug support in hardware can use | ||
| 336 | * this helper infrastructure to regularly poll such connectors for changes in | ||
| 337 | * their connection state. | ||
| 338 | * | ||
| 339 | * Drivers can control which connectors are polled by setting the | ||
| 340 | * DRM_CONNECTOR_POLL_CONNECT and DRM_CONNECTOR_POLL_DISCONNECT flags. On | ||
| 341 | * connectors where probing live outputs can result in visual distortion drivers | ||
| 342 | * should not set the DRM_CONNECTOR_POLL_DISCONNECT flag to avoid this. | ||
| 343 | * Connectors which have no flag or only DRM_CONNECTOR_POLL_HPD set are | ||
| 344 | * completely ignored by the polling logic. | ||
| 345 | * | ||
| 346 | * Note that a connector can be both polled and probed from the hotplug handler, | ||
| 347 | * in case the hotplug interrupt is known to be unreliable. | ||
| 348 | */ | ||
| 349 | void drm_kms_helper_poll_init(struct drm_device *dev) | ||
| 350 | { | ||
| 351 | INIT_DELAYED_WORK(&dev->mode_config.output_poll_work, output_poll_execute); | ||
| 352 | dev->mode_config.poll_enabled = true; | ||
| 353 | |||
| 354 | drm_kms_helper_poll_enable(dev); | ||
| 355 | } | ||
| 356 | EXPORT_SYMBOL(drm_kms_helper_poll_init); | ||
| 357 | |||
| 358 | /** | ||
| 359 | * drm_kms_helper_poll_fini - disable output polling and clean it up | ||
| 360 | * @dev: drm_device | ||
| 361 | */ | ||
| 362 | void drm_kms_helper_poll_fini(struct drm_device *dev) | ||
| 363 | { | ||
| 364 | drm_kms_helper_poll_disable(dev); | ||
| 365 | } | ||
| 366 | EXPORT_SYMBOL(drm_kms_helper_poll_fini); | ||
| 367 | |||
| 368 | /** | ||
| 369 | * drm_helper_hpd_irq_event - hotplug processing | ||
| 370 | * @dev: drm_device | ||
| 371 | * | ||
| 372 | * Drivers can use this helper function to run a detect cycle on all connectors | ||
| 373 | * which have the DRM_CONNECTOR_POLL_HPD flag set in their &polled member. All | ||
| 374 | * other connectors are ignored, which is useful to avoid reprobing fixed | ||
| 375 | * panels. | ||
| 376 | * | ||
| 377 | * This helper function is useful for drivers which can't or don't track hotplug | ||
| 378 | * interrupts for each connector. | ||
| 379 | * | ||
| 380 | * Drivers which support hotplug interrupts for each connector individually and | ||
| 381 | * which have a more fine-grained detect logic should bypass this code and | ||
| 382 | * directly call drm_kms_helper_hotplug_event() in case the connector state | ||
| 383 | * changed. | ||
| 384 | * | ||
| 385 | * This function must be called from process context with no mode | ||
| 386 | * setting locks held. | ||
| 387 | * | ||
| 388 | * Note that a connector can be both polled and probed from the hotplug handler, | ||
| 389 | * in case the hotplug interrupt is known to be unreliable. | ||
| 390 | */ | ||
| 391 | bool drm_helper_hpd_irq_event(struct drm_device *dev) | ||
| 392 | { | ||
| 393 | struct drm_connector *connector; | ||
| 394 | enum drm_connector_status old_status; | ||
| 395 | bool changed = false; | ||
| 396 | |||
| 397 | if (!dev->mode_config.poll_enabled) | ||
| 398 | return false; | ||
| 399 | |||
| 400 | mutex_lock(&dev->mode_config.mutex); | ||
| 401 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
| 402 | |||
| 403 | /* Only handle HPD capable connectors. */ | ||
| 404 | if (!(connector->polled & DRM_CONNECTOR_POLL_HPD)) | ||
| 405 | continue; | ||
| 406 | |||
| 407 | old_status = connector->status; | ||
| 408 | |||
| 409 | connector->status = connector->funcs->detect(connector, false); | ||
| 410 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n", | ||
| 411 | connector->base.id, | ||
| 412 | drm_get_connector_name(connector), | ||
| 413 | drm_get_connector_status_name(old_status), | ||
| 414 | drm_get_connector_status_name(connector->status)); | ||
| 415 | if (old_status != connector->status) | ||
| 416 | changed = true; | ||
| 417 | } | ||
| 418 | |||
| 419 | mutex_unlock(&dev->mode_config.mutex); | ||
| 420 | |||
| 421 | if (changed) | ||
| 422 | drm_kms_helper_hotplug_event(dev); | ||
| 423 | |||
| 424 | return changed; | ||
| 425 | } | ||
| 426 | EXPORT_SYMBOL(drm_helper_hpd_irq_event); | ||
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0905cd915589..ec82f6bff122 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -1308,6 +1308,7 @@ struct intel_vbt_data { | |||
| 1308 | 1308 | ||
| 1309 | struct { | 1309 | struct { |
| 1310 | u16 pwm_freq_hz; | 1310 | u16 pwm_freq_hz; |
| 1311 | bool present; | ||
| 1311 | bool active_low_pwm; | 1312 | bool active_low_pwm; |
| 1312 | } backlight; | 1313 | } backlight; |
| 1313 | 1314 | ||
| @@ -2431,20 +2432,18 @@ int i915_gem_context_open(struct drm_device *dev, struct drm_file *file); | |||
| 2431 | int i915_gem_context_enable(struct drm_i915_private *dev_priv); | 2432 | int i915_gem_context_enable(struct drm_i915_private *dev_priv); |
| 2432 | void i915_gem_context_close(struct drm_device *dev, struct drm_file *file); | 2433 | void i915_gem_context_close(struct drm_device *dev, struct drm_file *file); |
| 2433 | int i915_switch_context(struct intel_ring_buffer *ring, | 2434 | int i915_switch_context(struct intel_ring_buffer *ring, |
| 2434 | struct drm_file *file, struct i915_hw_context *to); | 2435 | struct i915_hw_context *to); |
| 2435 | struct i915_hw_context * | 2436 | struct i915_hw_context * |
| 2436 | i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id); | 2437 | i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id); |
| 2437 | void i915_gem_context_free(struct kref *ctx_ref); | 2438 | void i915_gem_context_free(struct kref *ctx_ref); |
| 2438 | static inline void i915_gem_context_reference(struct i915_hw_context *ctx) | 2439 | static inline void i915_gem_context_reference(struct i915_hw_context *ctx) |
| 2439 | { | 2440 | { |
| 2440 | if (ctx->obj && HAS_HW_CONTEXTS(ctx->obj->base.dev)) | 2441 | kref_get(&ctx->ref); |
| 2441 | kref_get(&ctx->ref); | ||
| 2442 | } | 2442 | } |
| 2443 | 2443 | ||
| 2444 | static inline void i915_gem_context_unreference(struct i915_hw_context *ctx) | 2444 | static inline void i915_gem_context_unreference(struct i915_hw_context *ctx) |
| 2445 | { | 2445 | { |
| 2446 | if (ctx->obj && HAS_HW_CONTEXTS(ctx->obj->base.dev)) | 2446 | kref_put(&ctx->ref, i915_gem_context_free); |
| 2447 | kref_put(&ctx->ref, i915_gem_context_free); | ||
| 2448 | } | 2447 | } |
| 2449 | 2448 | ||
| 2450 | static inline bool i915_gem_context_is_default(const struct i915_hw_context *c) | 2449 | static inline bool i915_gem_context_is_default(const struct i915_hw_context *c) |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6370a761d137..2871ce75f438 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -2790,7 +2790,7 @@ int i915_gpu_idle(struct drm_device *dev) | |||
| 2790 | 2790 | ||
| 2791 | /* Flush everything onto the inactive list. */ | 2791 | /* Flush everything onto the inactive list. */ |
| 2792 | for_each_ring(ring, dev_priv, i) { | 2792 | for_each_ring(ring, dev_priv, i) { |
| 2793 | ret = i915_switch_context(ring, NULL, ring->default_context); | 2793 | ret = i915_switch_context(ring, ring->default_context); |
| 2794 | if (ret) | 2794 | if (ret) |
| 2795 | return ret; | 2795 | return ret; |
| 2796 | 2796 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 6043062ffce7..d72db15afa02 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c | |||
| @@ -96,9 +96,6 @@ | |||
| 96 | #define GEN6_CONTEXT_ALIGN (64<<10) | 96 | #define GEN6_CONTEXT_ALIGN (64<<10) |
| 97 | #define GEN7_CONTEXT_ALIGN 4096 | 97 | #define GEN7_CONTEXT_ALIGN 4096 |
| 98 | 98 | ||
| 99 | static int do_switch(struct intel_ring_buffer *ring, | ||
| 100 | struct i915_hw_context *to); | ||
| 101 | |||
| 102 | static void do_ppgtt_cleanup(struct i915_hw_ppgtt *ppgtt) | 99 | static void do_ppgtt_cleanup(struct i915_hw_ppgtt *ppgtt) |
| 103 | { | 100 | { |
| 104 | struct drm_device *dev = ppgtt->base.dev; | 101 | struct drm_device *dev = ppgtt->base.dev; |
| @@ -185,13 +182,15 @@ void i915_gem_context_free(struct kref *ctx_ref) | |||
| 185 | typeof(*ctx), ref); | 182 | typeof(*ctx), ref); |
| 186 | struct i915_hw_ppgtt *ppgtt = NULL; | 183 | struct i915_hw_ppgtt *ppgtt = NULL; |
| 187 | 184 | ||
| 188 | /* We refcount even the aliasing PPGTT to keep the code symmetric */ | 185 | if (ctx->obj) { |
| 189 | if (USES_PPGTT(ctx->obj->base.dev)) | 186 | /* We refcount even the aliasing PPGTT to keep the code symmetric */ |
| 190 | ppgtt = ctx_to_ppgtt(ctx); | 187 | if (USES_PPGTT(ctx->obj->base.dev)) |
| 188 | ppgtt = ctx_to_ppgtt(ctx); | ||
| 191 | 189 | ||
| 192 | /* XXX: Free up the object before tearing down the address space, in | 190 | /* XXX: Free up the object before tearing down the address space, in |
| 193 | * case we're bound in the PPGTT */ | 191 | * case we're bound in the PPGTT */ |
| 194 | drm_gem_object_unreference(&ctx->obj->base); | 192 | drm_gem_object_unreference(&ctx->obj->base); |
| 193 | } | ||
| 195 | 194 | ||
| 196 | if (ppgtt) | 195 | if (ppgtt) |
| 197 | kref_put(&ppgtt->ref, ppgtt_release); | 196 | kref_put(&ppgtt->ref, ppgtt_release); |
| @@ -232,32 +231,32 @@ __create_hw_context(struct drm_device *dev, | |||
| 232 | return ERR_PTR(-ENOMEM); | 231 | return ERR_PTR(-ENOMEM); |
| 233 | 232 | ||
| 234 | kref_init(&ctx->ref); | 233 | kref_init(&ctx->ref); |
| 235 | ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size); | 234 | list_add_tail(&ctx->link, &dev_priv->context_list); |
| 236 | INIT_LIST_HEAD(&ctx->link); | ||
| 237 | if (ctx->obj == NULL) { | ||
| 238 | kfree(ctx); | ||
| 239 | DRM_DEBUG_DRIVER("Context object allocated failed\n"); | ||
| 240 | return ERR_PTR(-ENOMEM); | ||
| 241 | } | ||
| 242 | 235 | ||
| 243 | if (INTEL_INFO(dev)->gen >= 7) { | 236 | if (dev_priv->hw_context_size) { |
| 244 | ret = i915_gem_object_set_cache_level(ctx->obj, | 237 | ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size); |
| 245 | I915_CACHE_L3_LLC); | 238 | if (ctx->obj == NULL) { |
| 246 | /* Failure shouldn't ever happen this early */ | 239 | ret = -ENOMEM; |
| 247 | if (WARN_ON(ret)) | ||
| 248 | goto err_out; | 240 | goto err_out; |
| 249 | } | 241 | } |
| 250 | 242 | ||
| 251 | list_add_tail(&ctx->link, &dev_priv->context_list); | 243 | if (INTEL_INFO(dev)->gen >= 7) { |
| 244 | ret = i915_gem_object_set_cache_level(ctx->obj, | ||
| 245 | I915_CACHE_L3_LLC); | ||
| 246 | /* Failure shouldn't ever happen this early */ | ||
| 247 | if (WARN_ON(ret)) | ||
| 248 | goto err_out; | ||
| 249 | } | ||
| 250 | } | ||
| 252 | 251 | ||
| 253 | /* Default context will never have a file_priv */ | 252 | /* Default context will never have a file_priv */ |
| 254 | if (file_priv == NULL) | 253 | if (file_priv != NULL) { |
| 255 | return ctx; | 254 | ret = idr_alloc(&file_priv->context_idr, ctx, |
| 256 | 255 | DEFAULT_CONTEXT_ID, 0, GFP_KERNEL); | |
| 257 | ret = idr_alloc(&file_priv->context_idr, ctx, DEFAULT_CONTEXT_ID, 0, | 256 | if (ret < 0) |
| 258 | GFP_KERNEL); | 257 | goto err_out; |
| 259 | if (ret < 0) | 258 | } else |
| 260 | goto err_out; | 259 | ret = DEFAULT_CONTEXT_ID; |
| 261 | 260 | ||
| 262 | ctx->file_priv = file_priv; | 261 | ctx->file_priv = file_priv; |
| 263 | ctx->id = ret; | 262 | ctx->id = ret; |
| @@ -294,7 +293,7 @@ i915_gem_create_context(struct drm_device *dev, | |||
| 294 | if (IS_ERR(ctx)) | 293 | if (IS_ERR(ctx)) |
| 295 | return ctx; | 294 | return ctx; |
| 296 | 295 | ||
| 297 | if (is_global_default_ctx) { | 296 | if (is_global_default_ctx && ctx->obj) { |
| 298 | /* We may need to do things with the shrinker which | 297 | /* We may need to do things with the shrinker which |
| 299 | * require us to immediately switch back to the default | 298 | * require us to immediately switch back to the default |
| 300 | * context. This can cause a problem as pinning the | 299 | * context. This can cause a problem as pinning the |
| @@ -342,7 +341,7 @@ i915_gem_create_context(struct drm_device *dev, | |||
| 342 | return ctx; | 341 | return ctx; |
| 343 | 342 | ||
| 344 | err_unpin: | 343 | err_unpin: |
| 345 | if (is_global_default_ctx) | 344 | if (is_global_default_ctx && ctx->obj) |
| 346 | i915_gem_object_ggtt_unpin(ctx->obj); | 345 | i915_gem_object_ggtt_unpin(ctx->obj); |
| 347 | err_destroy: | 346 | err_destroy: |
| 348 | i915_gem_context_unreference(ctx); | 347 | i915_gem_context_unreference(ctx); |
| @@ -352,32 +351,22 @@ err_destroy: | |||
| 352 | void i915_gem_context_reset(struct drm_device *dev) | 351 | void i915_gem_context_reset(struct drm_device *dev) |
| 353 | { | 352 | { |
| 354 | struct drm_i915_private *dev_priv = dev->dev_private; | 353 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 355 | struct intel_ring_buffer *ring; | ||
| 356 | int i; | 354 | int i; |
| 357 | 355 | ||
| 358 | if (!HAS_HW_CONTEXTS(dev)) | ||
| 359 | return; | ||
| 360 | |||
| 361 | /* Prevent the hardware from restoring the last context (which hung) on | 356 | /* Prevent the hardware from restoring the last context (which hung) on |
| 362 | * the next switch */ | 357 | * the next switch */ |
| 363 | for (i = 0; i < I915_NUM_RINGS; i++) { | 358 | for (i = 0; i < I915_NUM_RINGS; i++) { |
| 364 | struct i915_hw_context *dctx; | 359 | struct intel_ring_buffer *ring = &dev_priv->ring[i]; |
| 365 | if (!(INTEL_INFO(dev)->ring_mask & (1<<i))) | 360 | struct i915_hw_context *dctx = ring->default_context; |
| 366 | continue; | ||
| 367 | 361 | ||
| 368 | /* Do a fake switch to the default context */ | 362 | /* Do a fake switch to the default context */ |
| 369 | ring = &dev_priv->ring[i]; | 363 | if (ring->last_context == dctx) |
| 370 | dctx = ring->default_context; | ||
| 371 | if (WARN_ON(!dctx)) | ||
| 372 | continue; | 364 | continue; |
| 373 | 365 | ||
| 374 | if (!ring->last_context) | 366 | if (!ring->last_context) |
| 375 | continue; | 367 | continue; |
| 376 | 368 | ||
| 377 | if (ring->last_context == dctx) | 369 | if (dctx->obj && i == RCS) { |
| 378 | continue; | ||
| 379 | |||
| 380 | if (i == RCS) { | ||
| 381 | WARN_ON(i915_gem_obj_ggtt_pin(dctx->obj, | 370 | WARN_ON(i915_gem_obj_ggtt_pin(dctx->obj, |
| 382 | get_context_alignment(dev), 0)); | 371 | get_context_alignment(dev), 0)); |
| 383 | /* Fake a finish/inactive */ | 372 | /* Fake a finish/inactive */ |
| @@ -394,44 +383,35 @@ void i915_gem_context_reset(struct drm_device *dev) | |||
| 394 | int i915_gem_context_init(struct drm_device *dev) | 383 | int i915_gem_context_init(struct drm_device *dev) |
| 395 | { | 384 | { |
| 396 | struct drm_i915_private *dev_priv = dev->dev_private; | 385 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 397 | struct intel_ring_buffer *ring; | 386 | struct i915_hw_context *ctx; |
| 398 | int i; | 387 | int i; |
| 399 | 388 | ||
| 400 | if (!HAS_HW_CONTEXTS(dev)) | ||
| 401 | return 0; | ||
| 402 | |||
| 403 | /* Init should only be called once per module load. Eventually the | 389 | /* Init should only be called once per module load. Eventually the |
| 404 | * restriction on the context_disabled check can be loosened. */ | 390 | * restriction on the context_disabled check can be loosened. */ |
| 405 | if (WARN_ON(dev_priv->ring[RCS].default_context)) | 391 | if (WARN_ON(dev_priv->ring[RCS].default_context)) |
| 406 | return 0; | 392 | return 0; |
| 407 | 393 | ||
| 408 | dev_priv->hw_context_size = round_up(get_context_size(dev), 4096); | 394 | if (HAS_HW_CONTEXTS(dev)) { |
| 409 | 395 | dev_priv->hw_context_size = round_up(get_context_size(dev), 4096); | |
| 410 | if (dev_priv->hw_context_size > (1<<20)) { | 396 | if (dev_priv->hw_context_size > (1<<20)) { |
| 411 | DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size\n"); | 397 | DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size %d\n", |
| 412 | return -E2BIG; | 398 | dev_priv->hw_context_size); |
| 399 | dev_priv->hw_context_size = 0; | ||
| 400 | } | ||
| 413 | } | 401 | } |
| 414 | 402 | ||
| 415 | dev_priv->ring[RCS].default_context = | 403 | ctx = i915_gem_create_context(dev, NULL, USES_PPGTT(dev)); |
| 416 | i915_gem_create_context(dev, NULL, USES_PPGTT(dev)); | 404 | if (IS_ERR(ctx)) { |
| 417 | 405 | DRM_ERROR("Failed to create default global context (error %ld)\n", | |
| 418 | if (IS_ERR_OR_NULL(dev_priv->ring[RCS].default_context)) { | 406 | PTR_ERR(ctx)); |
| 419 | DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed %ld\n", | 407 | return PTR_ERR(ctx); |
| 420 | PTR_ERR(dev_priv->ring[RCS].default_context)); | ||
| 421 | return PTR_ERR(dev_priv->ring[RCS].default_context); | ||
| 422 | } | 408 | } |
| 423 | 409 | ||
| 424 | for (i = RCS + 1; i < I915_NUM_RINGS; i++) { | 410 | /* NB: RCS will hold a ref for all rings */ |
| 425 | if (!(INTEL_INFO(dev)->ring_mask & (1<<i))) | 411 | for (i = 0; i < I915_NUM_RINGS; i++) |
| 426 | continue; | 412 | dev_priv->ring[i].default_context = ctx; |
| 427 | |||
| 428 | ring = &dev_priv->ring[i]; | ||
| 429 | 413 | ||
| 430 | /* NB: RCS will hold a ref for all rings */ | 414 | DRM_DEBUG_DRIVER("%s context support initialized\n", dev_priv->hw_context_size ? "HW" : "fake"); |
| 431 | ring->default_context = dev_priv->ring[RCS].default_context; | ||
| 432 | } | ||
| 433 | |||
| 434 | DRM_DEBUG_DRIVER("HW context support initialized\n"); | ||
| 435 | return 0; | 415 | return 0; |
| 436 | } | 416 | } |
| 437 | 417 | ||
| @@ -441,33 +421,30 @@ void i915_gem_context_fini(struct drm_device *dev) | |||
| 441 | struct i915_hw_context *dctx = dev_priv->ring[RCS].default_context; | 421 | struct i915_hw_context *dctx = dev_priv->ring[RCS].default_context; |
| 442 | int i; | 422 | int i; |
| 443 | 423 | ||
| 444 | if (!HAS_HW_CONTEXTS(dev)) | 424 | if (dctx->obj) { |
| 445 | return; | 425 | /* The only known way to stop the gpu from accessing the hw context is |
| 446 | 426 | * to reset it. Do this as the very last operation to avoid confusing | |
| 447 | /* The only known way to stop the gpu from accessing the hw context is | 427 | * other code, leading to spurious errors. */ |
| 448 | * to reset it. Do this as the very last operation to avoid confusing | 428 | intel_gpu_reset(dev); |
| 449 | * other code, leading to spurious errors. */ | 429 | |
| 450 | intel_gpu_reset(dev); | 430 | /* When default context is created and switched to, base object refcount |
| 451 | 431 | * will be 2 (+1 from object creation and +1 from do_switch()). | |
| 452 | /* When default context is created and switched to, base object refcount | 432 | * i915_gem_context_fini() will be called after gpu_idle() has switched |
| 453 | * will be 2 (+1 from object creation and +1 from do_switch()). | 433 | * to default context. So we need to unreference the base object once |
| 454 | * i915_gem_context_fini() will be called after gpu_idle() has switched | 434 | * to offset the do_switch part, so that i915_gem_context_unreference() |
| 455 | * to default context. So we need to unreference the base object once | 435 | * can then free the base object correctly. */ |
| 456 | * to offset the do_switch part, so that i915_gem_context_unreference() | 436 | WARN_ON(!dev_priv->ring[RCS].last_context); |
| 457 | * can then free the base object correctly. */ | 437 | if (dev_priv->ring[RCS].last_context == dctx) { |
| 458 | WARN_ON(!dev_priv->ring[RCS].last_context); | 438 | /* Fake switch to NULL context */ |
| 459 | if (dev_priv->ring[RCS].last_context == dctx) { | 439 | WARN_ON(dctx->obj->active); |
| 460 | /* Fake switch to NULL context */ | 440 | i915_gem_object_ggtt_unpin(dctx->obj); |
| 461 | WARN_ON(dctx->obj->active); | 441 | i915_gem_context_unreference(dctx); |
| 462 | i915_gem_object_ggtt_unpin(dctx->obj); | 442 | dev_priv->ring[RCS].last_context = NULL; |
| 463 | i915_gem_context_unreference(dctx); | 443 | } |
| 464 | dev_priv->ring[RCS].last_context = NULL; | ||
| 465 | } | 444 | } |
| 466 | 445 | ||
| 467 | for (i = 0; i < I915_NUM_RINGS; i++) { | 446 | for (i = 0; i < I915_NUM_RINGS; i++) { |
| 468 | struct intel_ring_buffer *ring = &dev_priv->ring[i]; | 447 | struct intel_ring_buffer *ring = &dev_priv->ring[i]; |
| 469 | if (!(INTEL_INFO(dev)->ring_mask & (1<<i))) | ||
| 470 | continue; | ||
| 471 | 448 | ||
| 472 | if (ring->last_context) | 449 | if (ring->last_context) |
| 473 | i915_gem_context_unreference(ring->last_context); | 450 | i915_gem_context_unreference(ring->last_context); |
| @@ -478,7 +455,6 @@ void i915_gem_context_fini(struct drm_device *dev) | |||
| 478 | 455 | ||
| 479 | i915_gem_object_ggtt_unpin(dctx->obj); | 456 | i915_gem_object_ggtt_unpin(dctx->obj); |
| 480 | i915_gem_context_unreference(dctx); | 457 | i915_gem_context_unreference(dctx); |
| 481 | dev_priv->mm.aliasing_ppgtt = NULL; | ||
| 482 | } | 458 | } |
| 483 | 459 | ||
| 484 | int i915_gem_context_enable(struct drm_i915_private *dev_priv) | 460 | int i915_gem_context_enable(struct drm_i915_private *dev_priv) |
| @@ -486,9 +462,6 @@ int i915_gem_context_enable(struct drm_i915_private *dev_priv) | |||
| 486 | struct intel_ring_buffer *ring; | 462 | struct intel_ring_buffer *ring; |
| 487 | int ret, i; | 463 | int ret, i; |
| 488 | 464 | ||
| 489 | if (!HAS_HW_CONTEXTS(dev_priv->dev)) | ||
| 490 | return 0; | ||
| 491 | |||
| 492 | /* This is the only place the aliasing PPGTT gets enabled, which means | 465 | /* This is the only place the aliasing PPGTT gets enabled, which means |
| 493 | * it has to happen before we bail on reset */ | 466 | * it has to happen before we bail on reset */ |
| 494 | if (dev_priv->mm.aliasing_ppgtt) { | 467 | if (dev_priv->mm.aliasing_ppgtt) { |
| @@ -503,7 +476,7 @@ int i915_gem_context_enable(struct drm_i915_private *dev_priv) | |||
| 503 | BUG_ON(!dev_priv->ring[RCS].default_context); | 476 | BUG_ON(!dev_priv->ring[RCS].default_context); |
| 504 | 477 | ||
| 505 | for_each_ring(ring, dev_priv, i) { | 478 | for_each_ring(ring, dev_priv, i) { |
| 506 | ret = do_switch(ring, ring->default_context); | 479 | ret = i915_switch_context(ring, ring->default_context); |
| 507 | if (ret) | 480 | if (ret) |
| 508 | return ret; | 481 | return ret; |
| 509 | } | 482 | } |
| @@ -526,19 +499,6 @@ static int context_idr_cleanup(int id, void *p, void *data) | |||
| 526 | int i915_gem_context_open(struct drm_device *dev, struct drm_file *file) | 499 | int i915_gem_context_open(struct drm_device *dev, struct drm_file *file) |
| 527 | { | 500 | { |
| 528 | struct drm_i915_file_private *file_priv = file->driver_priv; | 501 | struct drm_i915_file_private *file_priv = file->driver_priv; |
| 529 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 530 | |||
| 531 | if (!HAS_HW_CONTEXTS(dev)) { | ||
| 532 | /* Cheat for hang stats */ | ||
| 533 | file_priv->private_default_ctx = | ||
| 534 | kzalloc(sizeof(struct i915_hw_context), GFP_KERNEL); | ||
| 535 | |||
| 536 | if (file_priv->private_default_ctx == NULL) | ||
| 537 | return -ENOMEM; | ||
| 538 | |||
| 539 | file_priv->private_default_ctx->vm = &dev_priv->gtt.base; | ||
| 540 | return 0; | ||
| 541 | } | ||
| 542 | 502 | ||
| 543 | idr_init(&file_priv->context_idr); | 503 | idr_init(&file_priv->context_idr); |
| 544 | 504 | ||
| @@ -559,14 +519,10 @@ void i915_gem_context_close(struct drm_device *dev, struct drm_file *file) | |||
| 559 | { | 519 | { |
| 560 | struct drm_i915_file_private *file_priv = file->driver_priv; | 520 | struct drm_i915_file_private *file_priv = file->driver_priv; |
| 561 | 521 | ||
| 562 | if (!HAS_HW_CONTEXTS(dev)) { | ||
| 563 | kfree(file_priv->private_default_ctx); | ||
| 564 | return; | ||
| 565 | } | ||
| 566 | |||
| 567 | idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL); | 522 | idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL); |
| 568 | i915_gem_context_unreference(file_priv->private_default_ctx); | ||
| 569 | idr_destroy(&file_priv->context_idr); | 523 | idr_destroy(&file_priv->context_idr); |
| 524 | |||
| 525 | i915_gem_context_unreference(file_priv->private_default_ctx); | ||
| 570 | } | 526 | } |
| 571 | 527 | ||
| 572 | struct i915_hw_context * | 528 | struct i915_hw_context * |
| @@ -574,9 +530,6 @@ i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id) | |||
| 574 | { | 530 | { |
| 575 | struct i915_hw_context *ctx; | 531 | struct i915_hw_context *ctx; |
| 576 | 532 | ||
| 577 | if (!HAS_HW_CONTEXTS(file_priv->dev_priv->dev)) | ||
| 578 | return file_priv->private_default_ctx; | ||
| 579 | |||
| 580 | ctx = (struct i915_hw_context *)idr_find(&file_priv->context_idr, id); | 533 | ctx = (struct i915_hw_context *)idr_find(&file_priv->context_idr, id); |
| 581 | if (!ctx) | 534 | if (!ctx) |
| 582 | return ERR_PTR(-ENOENT); | 535 | return ERR_PTR(-ENOENT); |
| @@ -758,7 +711,6 @@ unpin_out: | |||
| 758 | /** | 711 | /** |
| 759 | * i915_switch_context() - perform a GPU context switch. | 712 | * i915_switch_context() - perform a GPU context switch. |
| 760 | * @ring: ring for which we'll execute the context switch | 713 | * @ring: ring for which we'll execute the context switch |
| 761 | * @file_priv: file_priv associated with the context, may be NULL | ||
| 762 | * @to: the context to switch to | 714 | * @to: the context to switch to |
| 763 | * | 715 | * |
| 764 | * The context life cycle is simple. The context refcount is incremented and | 716 | * The context life cycle is simple. The context refcount is incremented and |
| @@ -767,24 +719,30 @@ unpin_out: | |||
| 767 | * object while letting the normal object tracking destroy the backing BO. | 719 | * object while letting the normal object tracking destroy the backing BO. |
| 768 | */ | 720 | */ |
| 769 | int i915_switch_context(struct intel_ring_buffer *ring, | 721 | int i915_switch_context(struct intel_ring_buffer *ring, |
| 770 | struct drm_file *file, | ||
| 771 | struct i915_hw_context *to) | 722 | struct i915_hw_context *to) |
| 772 | { | 723 | { |
| 773 | struct drm_i915_private *dev_priv = ring->dev->dev_private; | 724 | struct drm_i915_private *dev_priv = ring->dev->dev_private; |
| 774 | 725 | ||
| 775 | WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); | 726 | WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); |
| 776 | 727 | ||
| 777 | BUG_ON(file && to == NULL); | 728 | if (to->obj == NULL) { /* We have the fake context */ |
| 778 | 729 | if (to != ring->last_context) { | |
| 779 | /* We have the fake context */ | 730 | i915_gem_context_reference(to); |
| 780 | if (!HAS_HW_CONTEXTS(ring->dev)) { | 731 | if (ring->last_context) |
| 781 | ring->last_context = to; | 732 | i915_gem_context_unreference(ring->last_context); |
| 733 | ring->last_context = to; | ||
| 734 | } | ||
| 782 | return 0; | 735 | return 0; |
| 783 | } | 736 | } |
| 784 | 737 | ||
| 785 | return do_switch(ring, to); | 738 | return do_switch(ring, to); |
| 786 | } | 739 | } |
| 787 | 740 | ||
| 741 | static bool hw_context_enabled(struct drm_device *dev) | ||
| 742 | { | ||
| 743 | return to_i915(dev)->hw_context_size; | ||
| 744 | } | ||
| 745 | |||
| 788 | int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, | 746 | int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, |
| 789 | struct drm_file *file) | 747 | struct drm_file *file) |
| 790 | { | 748 | { |
| @@ -793,7 +751,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, | |||
| 793 | struct i915_hw_context *ctx; | 751 | struct i915_hw_context *ctx; |
| 794 | int ret; | 752 | int ret; |
| 795 | 753 | ||
| 796 | if (!HAS_HW_CONTEXTS(dev)) | 754 | if (!hw_context_enabled(dev)) |
| 797 | return -ENODEV; | 755 | return -ENODEV; |
| 798 | 756 | ||
| 799 | ret = i915_mutex_lock_interruptible(dev); | 757 | ret = i915_mutex_lock_interruptible(dev); |
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 7447160155a3..2c9d9cbaf653 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c | |||
| @@ -1221,7 +1221,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
| 1221 | if (ret) | 1221 | if (ret) |
| 1222 | goto err; | 1222 | goto err; |
| 1223 | 1223 | ||
| 1224 | ret = i915_switch_context(ring, file, ctx); | 1224 | ret = i915_switch_context(ring, ctx); |
| 1225 | if (ret) | 1225 | if (ret) |
| 1226 | goto err; | 1226 | goto err; |
| 1227 | 1227 | ||
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 4867f4cc0938..fa486c5fbb02 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c | |||
| @@ -287,6 +287,9 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb) | |||
| 287 | const struct bdb_lfp_backlight_data *backlight_data; | 287 | const struct bdb_lfp_backlight_data *backlight_data; |
| 288 | const struct bdb_lfp_backlight_data_entry *entry; | 288 | const struct bdb_lfp_backlight_data_entry *entry; |
| 289 | 289 | ||
| 290 | /* Err to enabling backlight if no backlight block. */ | ||
| 291 | dev_priv->vbt.backlight.present = true; | ||
| 292 | |||
| 290 | backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT); | 293 | backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT); |
| 291 | if (!backlight_data) | 294 | if (!backlight_data) |
| 292 | return; | 295 | return; |
| @@ -299,6 +302,13 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb) | |||
| 299 | 302 | ||
| 300 | entry = &backlight_data->data[panel_type]; | 303 | entry = &backlight_data->data[panel_type]; |
| 301 | 304 | ||
| 305 | dev_priv->vbt.backlight.present = entry->type == BDB_BACKLIGHT_TYPE_PWM; | ||
| 306 | if (!dev_priv->vbt.backlight.present) { | ||
| 307 | DRM_DEBUG_KMS("PWM backlight not present in VBT (type %u)\n", | ||
| 308 | entry->type); | ||
| 309 | return; | ||
| 310 | } | ||
| 311 | |||
| 302 | dev_priv->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz; | 312 | dev_priv->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz; |
| 303 | dev_priv->vbt.backlight.active_low_pwm = entry->active_low_pwm; | 313 | dev_priv->vbt.backlight.active_low_pwm = entry->active_low_pwm; |
| 304 | DRM_DEBUG_KMS("VBT backlight PWM modulation frequency %u Hz, " | 314 | DRM_DEBUG_KMS("VBT backlight PWM modulation frequency %u Hz, " |
diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 83b7629e4367..f27f7b282465 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h | |||
| @@ -374,6 +374,9 @@ struct bdb_lvds_lfp_data { | |||
| 374 | struct bdb_lvds_lfp_data_entry data[16]; | 374 | struct bdb_lvds_lfp_data_entry data[16]; |
| 375 | } __packed; | 375 | } __packed; |
| 376 | 376 | ||
| 377 | #define BDB_BACKLIGHT_TYPE_NONE 0 | ||
| 378 | #define BDB_BACKLIGHT_TYPE_PWM 2 | ||
| 379 | |||
| 377 | struct bdb_lfp_backlight_data_entry { | 380 | struct bdb_lfp_backlight_data_entry { |
| 378 | u8 type:2; | 381 | u8 type:2; |
| 379 | u8 active_low_pwm:1; | 382 | u8 active_low_pwm:1; |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index a0dad1a2f819..d2a55884ad52 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
| @@ -575,7 +575,8 @@ out: | |||
| 575 | return ret; | 575 | return ret; |
| 576 | } | 576 | } |
| 577 | 577 | ||
| 578 | #define HEADER_SIZE 4 | 578 | #define BARE_ADDRESS_SIZE 3 |
| 579 | #define HEADER_SIZE (BARE_ADDRESS_SIZE + 1) | ||
| 579 | static ssize_t | 580 | static ssize_t |
| 580 | intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) | 581 | intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) |
| 581 | { | 582 | { |
| @@ -592,7 +593,7 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) | |||
| 592 | switch (msg->request & ~DP_AUX_I2C_MOT) { | 593 | switch (msg->request & ~DP_AUX_I2C_MOT) { |
| 593 | case DP_AUX_NATIVE_WRITE: | 594 | case DP_AUX_NATIVE_WRITE: |
| 594 | case DP_AUX_I2C_WRITE: | 595 | case DP_AUX_I2C_WRITE: |
| 595 | txsize = HEADER_SIZE + msg->size; | 596 | txsize = msg->size ? HEADER_SIZE + msg->size : BARE_ADDRESS_SIZE; |
| 596 | rxsize = 1; | 597 | rxsize = 1; |
| 597 | 598 | ||
| 598 | if (WARN_ON(txsize > 20)) | 599 | if (WARN_ON(txsize > 20)) |
| @@ -611,7 +612,7 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) | |||
| 611 | 612 | ||
| 612 | case DP_AUX_NATIVE_READ: | 613 | case DP_AUX_NATIVE_READ: |
| 613 | case DP_AUX_I2C_READ: | 614 | case DP_AUX_I2C_READ: |
| 614 | txsize = HEADER_SIZE; | 615 | txsize = msg->size ? HEADER_SIZE : BARE_ADDRESS_SIZE; |
| 615 | rxsize = msg->size + 1; | 616 | rxsize = msg->size + 1; |
| 616 | 617 | ||
| 617 | if (WARN_ON(rxsize > 20)) | 618 | if (WARN_ON(rxsize > 20)) |
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index cb058408c70e..0eead16aeda7 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c | |||
| @@ -1065,6 +1065,11 @@ int intel_panel_setup_backlight(struct drm_connector *connector) | |||
| 1065 | unsigned long flags; | 1065 | unsigned long flags; |
| 1066 | int ret; | 1066 | int ret; |
| 1067 | 1067 | ||
| 1068 | if (!dev_priv->vbt.backlight.present) { | ||
| 1069 | DRM_DEBUG_KMS("native backlight control not available per VBT\n"); | ||
| 1070 | return 0; | ||
| 1071 | } | ||
| 1072 | |||
| 1068 | /* set level and max in panel struct */ | 1073 | /* set level and max in panel struct */ |
| 1069 | spin_lock_irqsave(&dev_priv->backlight_lock, flags); | 1074 | spin_lock_irqsave(&dev_priv->backlight_lock, flags); |
| 1070 | ret = dev_priv->display.setup_backlight(intel_connector); | 1075 | ret = dev_priv->display.setup_backlight(intel_connector); |
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 5874716774a7..19e94c3edc19 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
| @@ -1545,6 +1545,16 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) | |||
| 1545 | 1545 | ||
| 1546 | DRM_DEBUG_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm); | 1546 | DRM_DEBUG_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm); |
| 1547 | 1547 | ||
| 1548 | if (IS_I915GM(dev) && enabled) { | ||
| 1549 | struct intel_framebuffer *fb; | ||
| 1550 | |||
| 1551 | fb = to_intel_framebuffer(enabled->primary->fb); | ||
| 1552 | |||
| 1553 | /* self-refresh seems busted with untiled */ | ||
| 1554 | if (fb->obj->tiling_mode == I915_TILING_NONE) | ||
| 1555 | enabled = NULL; | ||
| 1556 | } | ||
| 1557 | |||
| 1548 | /* | 1558 | /* |
| 1549 | * Overlay gets an aggressive default since video jitter is bad. | 1559 | * Overlay gets an aggressive default since video jitter is bad. |
| 1550 | */ | 1560 | */ |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c index e9df94f96d78..fb0b6b2d1427 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c | |||
| @@ -109,7 +109,7 @@ nouveau_bios_shadow_pramin(struct nouveau_bios *bios) | |||
| 109 | return; | 109 | return; |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | addr = (u64)(addr >> 8) << 8; | 112 | addr = (addr & 0xffffff00) << 8; |
| 113 | if (!addr) { | 113 | if (!addr) { |
| 114 | addr = (u64)nv_rd32(bios, 0x001700) << 16; | 114 | addr = (u64)nv_rd32(bios, 0x001700) << 16; |
| 115 | addr += 0xf0000; | 115 | addr += 0xf0000; |
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 355157e4f78d..e3c47a8005ff 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c | |||
| @@ -33,6 +33,7 @@ struct omap_crtc { | |||
| 33 | int pipe; | 33 | int pipe; |
| 34 | enum omap_channel channel; | 34 | enum omap_channel channel; |
| 35 | struct omap_overlay_manager_info info; | 35 | struct omap_overlay_manager_info info; |
| 36 | struct drm_encoder *current_encoder; | ||
| 36 | 37 | ||
| 37 | /* | 38 | /* |
| 38 | * Temporary: eventually this will go away, but it is needed | 39 | * Temporary: eventually this will go away, but it is needed |
| @@ -120,13 +121,25 @@ static void omap_crtc_start_update(struct omap_overlay_manager *mgr) | |||
| 120 | { | 121 | { |
| 121 | } | 122 | } |
| 122 | 123 | ||
| 124 | static void set_enabled(struct drm_crtc *crtc, bool enable); | ||
| 125 | |||
| 123 | static int omap_crtc_enable(struct omap_overlay_manager *mgr) | 126 | static int omap_crtc_enable(struct omap_overlay_manager *mgr) |
| 124 | { | 127 | { |
| 128 | struct omap_crtc *omap_crtc = omap_crtcs[mgr->id]; | ||
| 129 | |||
| 130 | dispc_mgr_setup(omap_crtc->channel, &omap_crtc->info); | ||
| 131 | dispc_mgr_set_timings(omap_crtc->channel, | ||
| 132 | &omap_crtc->timings); | ||
| 133 | set_enabled(&omap_crtc->base, true); | ||
| 134 | |||
| 125 | return 0; | 135 | return 0; |
| 126 | } | 136 | } |
| 127 | 137 | ||
| 128 | static void omap_crtc_disable(struct omap_overlay_manager *mgr) | 138 | static void omap_crtc_disable(struct omap_overlay_manager *mgr) |
| 129 | { | 139 | { |
| 140 | struct omap_crtc *omap_crtc = omap_crtcs[mgr->id]; | ||
| 141 | |||
| 142 | set_enabled(&omap_crtc->base, false); | ||
| 130 | } | 143 | } |
| 131 | 144 | ||
| 132 | static void omap_crtc_set_timings(struct omap_overlay_manager *mgr, | 145 | static void omap_crtc_set_timings(struct omap_overlay_manager *mgr, |
| @@ -184,7 +197,6 @@ static void omap_crtc_destroy(struct drm_crtc *crtc) | |||
| 184 | WARN_ON(omap_crtc->apply_irq.registered); | 197 | WARN_ON(omap_crtc->apply_irq.registered); |
| 185 | omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); | 198 | omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); |
| 186 | 199 | ||
| 187 | omap_crtc->plane->funcs->destroy(omap_crtc->plane); | ||
| 188 | drm_crtc_cleanup(crtc); | 200 | drm_crtc_cleanup(crtc); |
| 189 | 201 | ||
| 190 | kfree(omap_crtc); | 202 | kfree(omap_crtc); |
| @@ -338,17 +350,23 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, | |||
| 338 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | 350 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); |
| 339 | struct drm_plane *primary = crtc->primary; | 351 | struct drm_plane *primary = crtc->primary; |
| 340 | struct drm_gem_object *bo; | 352 | struct drm_gem_object *bo; |
| 353 | unsigned long flags; | ||
| 341 | 354 | ||
| 342 | DBG("%d -> %d (event=%p)", primary->fb ? primary->fb->base.id : -1, | 355 | DBG("%d -> %d (event=%p)", primary->fb ? primary->fb->base.id : -1, |
| 343 | fb->base.id, event); | 356 | fb->base.id, event); |
| 344 | 357 | ||
| 358 | spin_lock_irqsave(&dev->event_lock, flags); | ||
| 359 | |||
| 345 | if (omap_crtc->old_fb) { | 360 | if (omap_crtc->old_fb) { |
| 361 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
| 346 | dev_err(dev->dev, "already a pending flip\n"); | 362 | dev_err(dev->dev, "already a pending flip\n"); |
| 347 | return -EINVAL; | 363 | return -EINVAL; |
| 348 | } | 364 | } |
| 349 | 365 | ||
| 350 | omap_crtc->event = event; | 366 | omap_crtc->event = event; |
| 351 | primary->fb = fb; | 367 | omap_crtc->old_fb = primary->fb = fb; |
| 368 | |||
| 369 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
| 352 | 370 | ||
| 353 | /* | 371 | /* |
| 354 | * Hold a reference temporarily until the crtc is updated | 372 | * Hold a reference temporarily until the crtc is updated |
| @@ -528,38 +546,46 @@ static void set_enabled(struct drm_crtc *crtc, bool enable) | |||
| 528 | struct drm_device *dev = crtc->dev; | 546 | struct drm_device *dev = crtc->dev; |
| 529 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | 547 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); |
| 530 | enum omap_channel channel = omap_crtc->channel; | 548 | enum omap_channel channel = omap_crtc->channel; |
| 531 | struct omap_irq_wait *wait = NULL; | 549 | struct omap_irq_wait *wait; |
| 550 | u32 framedone_irq, vsync_irq; | ||
| 551 | int ret; | ||
| 532 | 552 | ||
| 533 | if (dispc_mgr_is_enabled(channel) == enable) | 553 | if (dispc_mgr_is_enabled(channel) == enable) |
| 534 | return; | 554 | return; |
| 535 | 555 | ||
| 536 | /* ignore sync-lost irqs during enable/disable */ | 556 | /* |
| 557 | * Digit output produces some sync lost interrupts during the first | ||
| 558 | * frame when enabling, so we need to ignore those. | ||
| 559 | */ | ||
| 537 | omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); | 560 | omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); |
| 538 | 561 | ||
| 539 | if (dispc_mgr_get_framedone_irq(channel)) { | 562 | framedone_irq = dispc_mgr_get_framedone_irq(channel); |
| 540 | if (!enable) { | 563 | vsync_irq = dispc_mgr_get_vsync_irq(channel); |
| 541 | wait = omap_irq_wait_init(dev, | 564 | |
| 542 | dispc_mgr_get_framedone_irq(channel), 1); | 565 | if (enable) { |
| 543 | } | 566 | wait = omap_irq_wait_init(dev, vsync_irq, 1); |
| 544 | } else { | 567 | } else { |
| 545 | /* | 568 | /* |
| 546 | * When we disable digit output, we need to wait until fields | 569 | * When we disable the digit output, we need to wait for |
| 547 | * are done. Otherwise the DSS is still working, and turning | 570 | * FRAMEDONE to know that DISPC has finished with the output. |
| 548 | * off the clocks prevents DSS from going to OFF mode. And when | 571 | * |
| 549 | * enabling, we need to wait for the extra sync losts | 572 | * OMAP2/3 does not have FRAMEDONE irq for digit output, and in |
| 573 | * that case we need to use vsync interrupt, and wait for both | ||
| 574 | * even and odd frames. | ||
| 550 | */ | 575 | */ |
| 551 | wait = omap_irq_wait_init(dev, | 576 | |
| 552 | dispc_mgr_get_vsync_irq(channel), 2); | 577 | if (framedone_irq) |
| 578 | wait = omap_irq_wait_init(dev, framedone_irq, 1); | ||
| 579 | else | ||
| 580 | wait = omap_irq_wait_init(dev, vsync_irq, 2); | ||
| 553 | } | 581 | } |
| 554 | 582 | ||
| 555 | dispc_mgr_enable(channel, enable); | 583 | dispc_mgr_enable(channel, enable); |
| 556 | 584 | ||
| 557 | if (wait) { | 585 | ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100)); |
| 558 | int ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100)); | 586 | if (ret) { |
| 559 | if (ret) { | 587 | dev_err(dev->dev, "%s: timeout waiting for %s\n", |
| 560 | dev_err(dev->dev, "%s: timeout waiting for %s\n", | 588 | omap_crtc->name, enable ? "enable" : "disable"); |
| 561 | omap_crtc->name, enable ? "enable" : "disable"); | ||
| 562 | } | ||
| 563 | } | 589 | } |
| 564 | 590 | ||
| 565 | omap_irq_register(crtc->dev, &omap_crtc->error_irq); | 591 | omap_irq_register(crtc->dev, &omap_crtc->error_irq); |
| @@ -586,8 +612,12 @@ static void omap_crtc_pre_apply(struct omap_drm_apply *apply) | |||
| 586 | } | 612 | } |
| 587 | } | 613 | } |
| 588 | 614 | ||
| 615 | if (omap_crtc->current_encoder && encoder != omap_crtc->current_encoder) | ||
| 616 | omap_encoder_set_enabled(omap_crtc->current_encoder, false); | ||
| 617 | |||
| 618 | omap_crtc->current_encoder = encoder; | ||
| 619 | |||
| 589 | if (!omap_crtc->enabled) { | 620 | if (!omap_crtc->enabled) { |
| 590 | set_enabled(&omap_crtc->base, false); | ||
| 591 | if (encoder) | 621 | if (encoder) |
| 592 | omap_encoder_set_enabled(encoder, false); | 622 | omap_encoder_set_enabled(encoder, false); |
| 593 | } else { | 623 | } else { |
| @@ -596,13 +626,7 @@ static void omap_crtc_pre_apply(struct omap_drm_apply *apply) | |||
| 596 | omap_encoder_update(encoder, omap_crtc->mgr, | 626 | omap_encoder_update(encoder, omap_crtc->mgr, |
| 597 | &omap_crtc->timings); | 627 | &omap_crtc->timings); |
| 598 | omap_encoder_set_enabled(encoder, true); | 628 | omap_encoder_set_enabled(encoder, true); |
| 599 | omap_crtc->full_update = false; | ||
| 600 | } | 629 | } |
| 601 | |||
| 602 | dispc_mgr_setup(omap_crtc->channel, &omap_crtc->info); | ||
| 603 | dispc_mgr_set_timings(omap_crtc->channel, | ||
| 604 | &omap_crtc->timings); | ||
| 605 | set_enabled(&omap_crtc->base, true); | ||
| 606 | } | 630 | } |
| 607 | 631 | ||
| 608 | omap_crtc->full_update = false; | 632 | omap_crtc->full_update = false; |
| @@ -613,10 +637,30 @@ static void omap_crtc_post_apply(struct omap_drm_apply *apply) | |||
| 613 | /* nothing needed for post-apply */ | 637 | /* nothing needed for post-apply */ |
| 614 | } | 638 | } |
| 615 | 639 | ||
| 640 | void omap_crtc_flush(struct drm_crtc *crtc) | ||
| 641 | { | ||
| 642 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | ||
| 643 | int loops = 0; | ||
| 644 | |||
| 645 | while (!list_empty(&omap_crtc->pending_applies) || | ||
| 646 | !list_empty(&omap_crtc->queued_applies) || | ||
| 647 | omap_crtc->event || omap_crtc->old_fb) { | ||
| 648 | |||
| 649 | if (++loops > 10) { | ||
| 650 | dev_err(crtc->dev->dev, | ||
| 651 | "omap_crtc_flush() timeout\n"); | ||
| 652 | break; | ||
| 653 | } | ||
| 654 | |||
| 655 | schedule_timeout_uninterruptible(msecs_to_jiffies(20)); | ||
| 656 | } | ||
| 657 | } | ||
| 658 | |||
| 616 | static const char *channel_names[] = { | 659 | static const char *channel_names[] = { |
| 617 | [OMAP_DSS_CHANNEL_LCD] = "lcd", | 660 | [OMAP_DSS_CHANNEL_LCD] = "lcd", |
| 618 | [OMAP_DSS_CHANNEL_DIGIT] = "tv", | 661 | [OMAP_DSS_CHANNEL_DIGIT] = "tv", |
| 619 | [OMAP_DSS_CHANNEL_LCD2] = "lcd2", | 662 | [OMAP_DSS_CHANNEL_LCD2] = "lcd2", |
| 663 | [OMAP_DSS_CHANNEL_LCD3] = "lcd3", | ||
| 620 | }; | 664 | }; |
| 621 | 665 | ||
| 622 | void omap_crtc_pre_init(void) | 666 | void omap_crtc_pre_init(void) |
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index bf39fcc49e0f..c8270e4b26f3 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c | |||
| @@ -513,12 +513,18 @@ static int dev_load(struct drm_device *dev, unsigned long flags) | |||
| 513 | static int dev_unload(struct drm_device *dev) | 513 | static int dev_unload(struct drm_device *dev) |
| 514 | { | 514 | { |
| 515 | struct omap_drm_private *priv = dev->dev_private; | 515 | struct omap_drm_private *priv = dev->dev_private; |
| 516 | int i; | ||
| 516 | 517 | ||
| 517 | DBG("unload: dev=%p", dev); | 518 | DBG("unload: dev=%p", dev); |
| 518 | 519 | ||
| 519 | drm_kms_helper_poll_fini(dev); | 520 | drm_kms_helper_poll_fini(dev); |
| 520 | 521 | ||
| 521 | omap_fbdev_free(dev); | 522 | omap_fbdev_free(dev); |
| 523 | |||
| 524 | /* flush crtcs so the fbs get released */ | ||
| 525 | for (i = 0; i < priv->num_crtcs; i++) | ||
| 526 | omap_crtc_flush(priv->crtcs[i]); | ||
| 527 | |||
| 522 | omap_modeset_free(dev); | 528 | omap_modeset_free(dev); |
| 523 | omap_gem_deinit(dev); | 529 | omap_gem_deinit(dev); |
| 524 | 530 | ||
| @@ -696,10 +702,11 @@ static int pdev_remove(struct platform_device *device) | |||
| 696 | { | 702 | { |
| 697 | DBG(""); | 703 | DBG(""); |
| 698 | 704 | ||
| 705 | drm_put_dev(platform_get_drvdata(device)); | ||
| 706 | |||
| 699 | omap_disconnect_dssdevs(); | 707 | omap_disconnect_dssdevs(); |
| 700 | omap_crtc_pre_uninit(); | 708 | omap_crtc_pre_uninit(); |
| 701 | 709 | ||
| 702 | drm_put_dev(platform_get_drvdata(device)); | ||
| 703 | return 0; | 710 | return 0; |
| 704 | } | 711 | } |
| 705 | 712 | ||
| @@ -726,18 +733,33 @@ static struct platform_driver pdev = { | |||
| 726 | 733 | ||
| 727 | static int __init omap_drm_init(void) | 734 | static int __init omap_drm_init(void) |
| 728 | { | 735 | { |
| 736 | int r; | ||
| 737 | |||
| 729 | DBG("init"); | 738 | DBG("init"); |
| 730 | if (platform_driver_register(&omap_dmm_driver)) { | 739 | |
| 731 | /* we can continue on without DMM.. so not fatal */ | 740 | r = platform_driver_register(&omap_dmm_driver); |
| 732 | dev_err(NULL, "DMM registration failed\n"); | 741 | if (r) { |
| 742 | pr_err("DMM driver registration failed\n"); | ||
| 743 | return r; | ||
| 744 | } | ||
| 745 | |||
| 746 | r = platform_driver_register(&pdev); | ||
| 747 | if (r) { | ||
| 748 | pr_err("omapdrm driver registration failed\n"); | ||
| 749 | platform_driver_unregister(&omap_dmm_driver); | ||
| 750 | return r; | ||
| 733 | } | 751 | } |
| 734 | return platform_driver_register(&pdev); | 752 | |
| 753 | return 0; | ||
| 735 | } | 754 | } |
| 736 | 755 | ||
| 737 | static void __exit omap_drm_fini(void) | 756 | static void __exit omap_drm_fini(void) |
| 738 | { | 757 | { |
| 739 | DBG("fini"); | 758 | DBG("fini"); |
| 759 | |||
| 740 | platform_driver_unregister(&pdev); | 760 | platform_driver_unregister(&pdev); |
| 761 | |||
| 762 | platform_driver_unregister(&omap_dmm_driver); | ||
| 741 | } | 763 | } |
| 742 | 764 | ||
| 743 | /* need late_initcall() so we load after dss_driver's are loaded */ | 765 | /* need late_initcall() so we load after dss_driver's are loaded */ |
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index 428b2981fd68..284b80fc3c54 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h | |||
| @@ -163,6 +163,7 @@ void omap_crtc_pre_init(void); | |||
| 163 | void omap_crtc_pre_uninit(void); | 163 | void omap_crtc_pre_uninit(void); |
| 164 | struct drm_crtc *omap_crtc_init(struct drm_device *dev, | 164 | struct drm_crtc *omap_crtc_init(struct drm_device *dev, |
| 165 | struct drm_plane *plane, enum omap_channel channel, int id); | 165 | struct drm_plane *plane, enum omap_channel channel, int id); |
| 166 | void omap_crtc_flush(struct drm_crtc *crtc); | ||
| 166 | 167 | ||
| 167 | struct drm_plane *omap_plane_init(struct drm_device *dev, | 168 | struct drm_plane *omap_plane_init(struct drm_device *dev, |
| 168 | int plane_id, bool private_plane); | 169 | int plane_id, bool private_plane); |
diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c index d2b8c49bfb4a..8b019602ffe6 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.c +++ b/drivers/gpu/drm/omapdrm/omap_fb.c | |||
| @@ -218,6 +218,20 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, | |||
| 218 | info->rotation_type = OMAP_DSS_ROT_TILER; | 218 | info->rotation_type = OMAP_DSS_ROT_TILER; |
| 219 | info->screen_width = omap_gem_tiled_stride(plane->bo, orient); | 219 | info->screen_width = omap_gem_tiled_stride(plane->bo, orient); |
| 220 | } else { | 220 | } else { |
| 221 | switch (win->rotation & 0xf) { | ||
| 222 | case 0: | ||
| 223 | case BIT(DRM_ROTATE_0): | ||
| 224 | /* OK */ | ||
| 225 | break; | ||
| 226 | |||
| 227 | default: | ||
| 228 | dev_warn(fb->dev->dev, | ||
| 229 | "rotation '%d' ignored for non-tiled fb\n", | ||
| 230 | win->rotation); | ||
| 231 | win->rotation = 0; | ||
| 232 | break; | ||
| 233 | } | ||
| 234 | |||
| 221 | info->paddr = get_linear_addr(plane, format, 0, x, y); | 235 | info->paddr = get_linear_addr(plane, format, 0, x, y); |
| 222 | info->rotation_type = OMAP_DSS_ROT_DMA; | 236 | info->rotation_type = OMAP_DSS_ROT_DMA; |
| 223 | info->screen_width = plane->pitch; | 237 | info->screen_width = plane->pitch; |
diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c index 002988d09021..1388ca7f87e8 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.c +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c | |||
| @@ -371,6 +371,9 @@ void omap_fbdev_free(struct drm_device *dev) | |||
| 371 | 371 | ||
| 372 | fbdev = to_omap_fbdev(priv->fbdev); | 372 | fbdev = to_omap_fbdev(priv->fbdev); |
| 373 | 373 | ||
| 374 | /* release the ref taken in omap_fbdev_create() */ | ||
| 375 | omap_gem_put_paddr(fbdev->bo); | ||
| 376 | |||
| 374 | /* this will free the backing object */ | 377 | /* this will free the backing object */ |
| 375 | if (fbdev->fb) { | 378 | if (fbdev->fb) { |
| 376 | drm_framebuffer_unregister_private(fbdev->fb); | 379 | drm_framebuffer_unregister_private(fbdev->fb); |
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index c8d972763889..95dbce286a41 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c | |||
| @@ -980,12 +980,9 @@ int omap_gem_resume(struct device *dev) | |||
| 980 | #ifdef CONFIG_DEBUG_FS | 980 | #ifdef CONFIG_DEBUG_FS |
| 981 | void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m) | 981 | void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m) |
| 982 | { | 982 | { |
| 983 | struct drm_device *dev = obj->dev; | ||
| 984 | struct omap_gem_object *omap_obj = to_omap_bo(obj); | 983 | struct omap_gem_object *omap_obj = to_omap_bo(obj); |
| 985 | uint64_t off; | 984 | uint64_t off; |
| 986 | 985 | ||
| 987 | WARN_ON(!mutex_is_locked(&dev->struct_mutex)); | ||
| 988 | |||
| 989 | off = drm_vma_node_start(&obj->vma_node); | 986 | off = drm_vma_node_start(&obj->vma_node); |
| 990 | 987 | ||
| 991 | seq_printf(m, "%08x: %2d (%2d) %08llx %08Zx (%2d) %p %4d", | 988 | seq_printf(m, "%08x: %2d (%2d) %08llx %08Zx (%2d) %p %4d", |
| @@ -1050,10 +1047,10 @@ static inline bool is_waiting(struct omap_gem_sync_waiter *waiter) | |||
| 1050 | { | 1047 | { |
| 1051 | struct omap_gem_object *omap_obj = waiter->omap_obj; | 1048 | struct omap_gem_object *omap_obj = waiter->omap_obj; |
| 1052 | if ((waiter->op & OMAP_GEM_READ) && | 1049 | if ((waiter->op & OMAP_GEM_READ) && |
| 1053 | (omap_obj->sync->read_complete < waiter->read_target)) | 1050 | (omap_obj->sync->write_complete < waiter->write_target)) |
| 1054 | return true; | 1051 | return true; |
| 1055 | if ((waiter->op & OMAP_GEM_WRITE) && | 1052 | if ((waiter->op & OMAP_GEM_WRITE) && |
| 1056 | (omap_obj->sync->write_complete < waiter->write_target)) | 1053 | (omap_obj->sync->read_complete < waiter->read_target)) |
| 1057 | return true; | 1054 | return true; |
| 1058 | return false; | 1055 | return false; |
| 1059 | } | 1056 | } |
| @@ -1229,6 +1226,8 @@ int omap_gem_op_async(struct drm_gem_object *obj, enum omap_gem_op op, | |||
| 1229 | } | 1226 | } |
| 1230 | 1227 | ||
| 1231 | spin_unlock(&sync_lock); | 1228 | spin_unlock(&sync_lock); |
| 1229 | |||
| 1230 | kfree(waiter); | ||
| 1232 | } | 1231 | } |
| 1233 | 1232 | ||
| 1234 | /* no waiting.. */ | 1233 | /* no waiting.. */ |
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 046d5e660c04..3cf31ee59aac 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c | |||
| @@ -225,6 +225,11 @@ int omap_plane_mode_set(struct drm_plane *plane, | |||
| 225 | omap_plane->apply_done_cb.arg = arg; | 225 | omap_plane->apply_done_cb.arg = arg; |
| 226 | } | 226 | } |
| 227 | 227 | ||
| 228 | if (plane->fb) | ||
| 229 | drm_framebuffer_unreference(plane->fb); | ||
| 230 | |||
| 231 | drm_framebuffer_reference(fb); | ||
| 232 | |||
| 228 | plane->fb = fb; | 233 | plane->fb = fb; |
| 229 | plane->crtc = crtc; | 234 | plane->crtc = crtc; |
| 230 | 235 | ||
| @@ -241,10 +246,13 @@ static int omap_plane_update(struct drm_plane *plane, | |||
| 241 | struct omap_plane *omap_plane = to_omap_plane(plane); | 246 | struct omap_plane *omap_plane = to_omap_plane(plane); |
| 242 | omap_plane->enabled = true; | 247 | omap_plane->enabled = true; |
| 243 | 248 | ||
| 244 | if (plane->fb) | 249 | /* omap_plane_mode_set() takes adjusted src */ |
| 245 | drm_framebuffer_unreference(plane->fb); | 250 | switch (omap_plane->win.rotation & 0xf) { |
| 246 | 251 | case BIT(DRM_ROTATE_90): | |
| 247 | drm_framebuffer_reference(fb); | 252 | case BIT(DRM_ROTATE_270): |
| 253 | swap(src_w, src_h); | ||
| 254 | break; | ||
| 255 | } | ||
| 248 | 256 | ||
| 249 | return omap_plane_mode_set(plane, crtc, fb, | 257 | return omap_plane_mode_set(plane, crtc, fb, |
| 250 | crtc_x, crtc_y, crtc_w, crtc_h, | 258 | crtc_x, crtc_y, crtc_w, crtc_h, |
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 8b0ab170cef9..15936524f226 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c | |||
| @@ -142,7 +142,8 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, | |||
| 142 | return recv_bytes; | 142 | return recv_bytes; |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | #define HEADER_SIZE 4 | 145 | #define BARE_ADDRESS_SIZE 3 |
| 146 | #define HEADER_SIZE (BARE_ADDRESS_SIZE + 1) | ||
| 146 | 147 | ||
| 147 | static ssize_t | 148 | static ssize_t |
| 148 | radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) | 149 | radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) |
| @@ -160,13 +161,19 @@ radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) | |||
| 160 | tx_buf[0] = msg->address & 0xff; | 161 | tx_buf[0] = msg->address & 0xff; |
| 161 | tx_buf[1] = msg->address >> 8; | 162 | tx_buf[1] = msg->address >> 8; |
| 162 | tx_buf[2] = msg->request << 4; | 163 | tx_buf[2] = msg->request << 4; |
| 163 | tx_buf[3] = msg->size - 1; | 164 | tx_buf[3] = msg->size ? (msg->size - 1) : 0; |
| 164 | 165 | ||
| 165 | switch (msg->request & ~DP_AUX_I2C_MOT) { | 166 | switch (msg->request & ~DP_AUX_I2C_MOT) { |
| 166 | case DP_AUX_NATIVE_WRITE: | 167 | case DP_AUX_NATIVE_WRITE: |
| 167 | case DP_AUX_I2C_WRITE: | 168 | case DP_AUX_I2C_WRITE: |
| 169 | /* tx_size needs to be 4 even for bare address packets since the atom | ||
| 170 | * table needs the info in tx_buf[3]. | ||
| 171 | */ | ||
| 168 | tx_size = HEADER_SIZE + msg->size; | 172 | tx_size = HEADER_SIZE + msg->size; |
| 169 | tx_buf[3] |= tx_size << 4; | 173 | if (msg->size == 0) |
| 174 | tx_buf[3] |= BARE_ADDRESS_SIZE << 4; | ||
| 175 | else | ||
| 176 | tx_buf[3] |= tx_size << 4; | ||
| 170 | memcpy(tx_buf + HEADER_SIZE, msg->buffer, msg->size); | 177 | memcpy(tx_buf + HEADER_SIZE, msg->buffer, msg->size); |
| 171 | ret = radeon_process_aux_ch(chan, | 178 | ret = radeon_process_aux_ch(chan, |
| 172 | tx_buf, tx_size, NULL, 0, delay, &ack); | 179 | tx_buf, tx_size, NULL, 0, delay, &ack); |
| @@ -176,8 +183,14 @@ radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) | |||
| 176 | break; | 183 | break; |
| 177 | case DP_AUX_NATIVE_READ: | 184 | case DP_AUX_NATIVE_READ: |
| 178 | case DP_AUX_I2C_READ: | 185 | case DP_AUX_I2C_READ: |
| 186 | /* tx_size needs to be 4 even for bare address packets since the atom | ||
| 187 | * table needs the info in tx_buf[3]. | ||
| 188 | */ | ||
| 179 | tx_size = HEADER_SIZE; | 189 | tx_size = HEADER_SIZE; |
| 180 | tx_buf[3] |= tx_size << 4; | 190 | if (msg->size == 0) |
| 191 | tx_buf[3] |= BARE_ADDRESS_SIZE << 4; | ||
| 192 | else | ||
| 193 | tx_buf[3] |= tx_size << 4; | ||
| 181 | ret = radeon_process_aux_ch(chan, | 194 | ret = radeon_process_aux_ch(chan, |
| 182 | tx_buf, tx_size, msg->buffer, msg->size, delay, &ack); | 195 | tx_buf, tx_size, msg->buffer, msg->size, delay, &ack); |
| 183 | break; | 196 | break; |
| @@ -186,7 +199,7 @@ radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) | |||
| 186 | break; | 199 | break; |
| 187 | } | 200 | } |
| 188 | 201 | ||
| 189 | if (ret > 0) | 202 | if (ret >= 0) |
| 190 | msg->reply = ack >> 4; | 203 | msg->reply = ack >> 4; |
| 191 | 204 | ||
| 192 | return ret; | 205 | return ret; |
| @@ -194,98 +207,15 @@ radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) | |||
| 194 | 207 | ||
| 195 | void radeon_dp_aux_init(struct radeon_connector *radeon_connector) | 208 | void radeon_dp_aux_init(struct radeon_connector *radeon_connector) |
| 196 | { | 209 | { |
| 197 | struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; | ||
| 198 | |||
| 199 | dig_connector->dp_i2c_bus->aux.dev = radeon_connector->base.kdev; | ||
| 200 | dig_connector->dp_i2c_bus->aux.transfer = radeon_dp_aux_transfer; | ||
| 201 | } | ||
| 202 | |||
| 203 | int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, | ||
| 204 | u8 write_byte, u8 *read_byte) | ||
| 205 | { | ||
| 206 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
| 207 | struct radeon_i2c_chan *auxch = i2c_get_adapdata(adapter); | ||
| 208 | u16 address = algo_data->address; | ||
| 209 | u8 msg[5]; | ||
| 210 | u8 reply[2]; | ||
| 211 | unsigned retry; | ||
| 212 | int msg_bytes; | ||
| 213 | int reply_bytes = 1; | ||
| 214 | int ret; | 210 | int ret; |
| 215 | u8 ack; | ||
| 216 | |||
| 217 | /* Set up the address */ | ||
| 218 | msg[0] = address; | ||
| 219 | msg[1] = address >> 8; | ||
| 220 | |||
| 221 | /* Set up the command byte */ | ||
| 222 | if (mode & MODE_I2C_READ) { | ||
| 223 | msg[2] = DP_AUX_I2C_READ << 4; | ||
| 224 | msg_bytes = 4; | ||
| 225 | msg[3] = msg_bytes << 4; | ||
| 226 | } else { | ||
| 227 | msg[2] = DP_AUX_I2C_WRITE << 4; | ||
| 228 | msg_bytes = 5; | ||
| 229 | msg[3] = msg_bytes << 4; | ||
| 230 | msg[4] = write_byte; | ||
| 231 | } | ||
| 232 | |||
| 233 | /* special handling for start/stop */ | ||
| 234 | if (mode & (MODE_I2C_START | MODE_I2C_STOP)) | ||
| 235 | msg[3] = 3 << 4; | ||
| 236 | |||
| 237 | /* Set MOT bit for all but stop */ | ||
| 238 | if ((mode & MODE_I2C_STOP) == 0) | ||
| 239 | msg[2] |= DP_AUX_I2C_MOT << 4; | ||
| 240 | |||
| 241 | for (retry = 0; retry < 7; retry++) { | ||
| 242 | ret = radeon_process_aux_ch(auxch, | ||
| 243 | msg, msg_bytes, reply, reply_bytes, 0, &ack); | ||
| 244 | if (ret == -EBUSY) | ||
| 245 | continue; | ||
| 246 | else if (ret < 0) { | ||
| 247 | DRM_DEBUG_KMS("aux_ch failed %d\n", ret); | ||
| 248 | return ret; | ||
| 249 | } | ||
| 250 | |||
| 251 | switch ((ack >> 4) & DP_AUX_NATIVE_REPLY_MASK) { | ||
| 252 | case DP_AUX_NATIVE_REPLY_ACK: | ||
| 253 | /* I2C-over-AUX Reply field is only valid | ||
| 254 | * when paired with AUX ACK. | ||
| 255 | */ | ||
| 256 | break; | ||
| 257 | case DP_AUX_NATIVE_REPLY_NACK: | ||
| 258 | DRM_DEBUG_KMS("aux_ch native nack\n"); | ||
| 259 | return -EREMOTEIO; | ||
| 260 | case DP_AUX_NATIVE_REPLY_DEFER: | ||
| 261 | DRM_DEBUG_KMS("aux_ch native defer\n"); | ||
| 262 | usleep_range(500, 600); | ||
| 263 | continue; | ||
| 264 | default: | ||
| 265 | DRM_ERROR("aux_ch invalid native reply 0x%02x\n", ack); | ||
| 266 | return -EREMOTEIO; | ||
| 267 | } | ||
| 268 | 211 | ||
| 269 | switch ((ack >> 4) & DP_AUX_I2C_REPLY_MASK) { | 212 | radeon_connector->ddc_bus->aux.dev = radeon_connector->base.kdev; |
| 270 | case DP_AUX_I2C_REPLY_ACK: | 213 | radeon_connector->ddc_bus->aux.transfer = radeon_dp_aux_transfer; |
| 271 | if (mode == MODE_I2C_READ) | 214 | ret = drm_dp_aux_register_i2c_bus(&radeon_connector->ddc_bus->aux); |
| 272 | *read_byte = reply[0]; | 215 | if (!ret) |
| 273 | return ret; | 216 | radeon_connector->ddc_bus->has_aux = true; |
| 274 | case DP_AUX_I2C_REPLY_NACK: | ||
| 275 | DRM_DEBUG_KMS("aux_i2c nack\n"); | ||
| 276 | return -EREMOTEIO; | ||
| 277 | case DP_AUX_I2C_REPLY_DEFER: | ||
| 278 | DRM_DEBUG_KMS("aux_i2c defer\n"); | ||
| 279 | usleep_range(400, 500); | ||
| 280 | break; | ||
| 281 | default: | ||
| 282 | DRM_ERROR("aux_i2c invalid reply 0x%02x\n", ack); | ||
| 283 | return -EREMOTEIO; | ||
| 284 | } | ||
| 285 | } | ||
| 286 | 217 | ||
| 287 | DRM_DEBUG_KMS("aux i2c too many retries, giving up\n"); | 218 | WARN(ret, "drm_dp_aux_register_i2c_bus() failed with error %d\n", ret); |
| 288 | return -EREMOTEIO; | ||
| 289 | } | 219 | } |
| 290 | 220 | ||
| 291 | /***** general DP utility functions *****/ | 221 | /***** general DP utility functions *****/ |
| @@ -420,12 +350,11 @@ static u8 radeon_dp_encoder_service(struct radeon_device *rdev, | |||
| 420 | 350 | ||
| 421 | u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector) | 351 | u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector) |
| 422 | { | 352 | { |
| 423 | struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; | ||
| 424 | struct drm_device *dev = radeon_connector->base.dev; | 353 | struct drm_device *dev = radeon_connector->base.dev; |
| 425 | struct radeon_device *rdev = dev->dev_private; | 354 | struct radeon_device *rdev = dev->dev_private; |
| 426 | 355 | ||
| 427 | return radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_GET_SINK_TYPE, 0, | 356 | return radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_GET_SINK_TYPE, 0, |
| 428 | dig_connector->dp_i2c_bus->rec.i2c_id, 0); | 357 | radeon_connector->ddc_bus->rec.i2c_id, 0); |
| 429 | } | 358 | } |
| 430 | 359 | ||
| 431 | static void radeon_dp_probe_oui(struct radeon_connector *radeon_connector) | 360 | static void radeon_dp_probe_oui(struct radeon_connector *radeon_connector) |
| @@ -436,11 +365,11 @@ static void radeon_dp_probe_oui(struct radeon_connector *radeon_connector) | |||
| 436 | if (!(dig_connector->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT)) | 365 | if (!(dig_connector->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT)) |
| 437 | return; | 366 | return; |
| 438 | 367 | ||
| 439 | if (drm_dp_dpcd_read(&dig_connector->dp_i2c_bus->aux, DP_SINK_OUI, buf, 3)) | 368 | if (drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_SINK_OUI, buf, 3)) |
| 440 | DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n", | 369 | DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n", |
| 441 | buf[0], buf[1], buf[2]); | 370 | buf[0], buf[1], buf[2]); |
| 442 | 371 | ||
| 443 | if (drm_dp_dpcd_read(&dig_connector->dp_i2c_bus->aux, DP_BRANCH_OUI, buf, 3)) | 372 | if (drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_BRANCH_OUI, buf, 3)) |
| 444 | DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n", | 373 | DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n", |
| 445 | buf[0], buf[1], buf[2]); | 374 | buf[0], buf[1], buf[2]); |
| 446 | } | 375 | } |
| @@ -451,7 +380,7 @@ bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector) | |||
| 451 | u8 msg[DP_DPCD_SIZE]; | 380 | u8 msg[DP_DPCD_SIZE]; |
| 452 | int ret, i; | 381 | int ret, i; |
| 453 | 382 | ||
| 454 | ret = drm_dp_dpcd_read(&dig_connector->dp_i2c_bus->aux, DP_DPCD_REV, msg, | 383 | ret = drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_DPCD_REV, msg, |
| 455 | DP_DPCD_SIZE); | 384 | DP_DPCD_SIZE); |
| 456 | if (ret > 0) { | 385 | if (ret > 0) { |
| 457 | memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE); | 386 | memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE); |
| @@ -489,7 +418,7 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder, | |||
| 489 | 418 | ||
| 490 | if (dp_bridge != ENCODER_OBJECT_ID_NONE) { | 419 | if (dp_bridge != ENCODER_OBJECT_ID_NONE) { |
| 491 | /* DP bridge chips */ | 420 | /* DP bridge chips */ |
| 492 | drm_dp_dpcd_readb(&dig_connector->dp_i2c_bus->aux, | 421 | drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, |
| 493 | DP_EDP_CONFIGURATION_CAP, &tmp); | 422 | DP_EDP_CONFIGURATION_CAP, &tmp); |
| 494 | if (tmp & 1) | 423 | if (tmp & 1) |
| 495 | panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; | 424 | panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; |
| @@ -500,7 +429,7 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder, | |||
| 500 | panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; | 429 | panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; |
| 501 | } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { | 430 | } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { |
| 502 | /* eDP */ | 431 | /* eDP */ |
| 503 | drm_dp_dpcd_readb(&dig_connector->dp_i2c_bus->aux, | 432 | drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, |
| 504 | DP_EDP_CONFIGURATION_CAP, &tmp); | 433 | DP_EDP_CONFIGURATION_CAP, &tmp); |
| 505 | if (tmp & 1) | 434 | if (tmp & 1) |
| 506 | panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; | 435 | panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; |
| @@ -554,7 +483,8 @@ bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector) | |||
| 554 | u8 link_status[DP_LINK_STATUS_SIZE]; | 483 | u8 link_status[DP_LINK_STATUS_SIZE]; |
| 555 | struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; | 484 | struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; |
| 556 | 485 | ||
| 557 | if (drm_dp_dpcd_read_link_status(&dig->dp_i2c_bus->aux, link_status) <= 0) | 486 | if (drm_dp_dpcd_read_link_status(&radeon_connector->ddc_bus->aux, link_status) |
| 487 | <= 0) | ||
| 558 | return false; | 488 | return false; |
| 559 | if (drm_dp_channel_eq_ok(link_status, dig->dp_lane_count)) | 489 | if (drm_dp_channel_eq_ok(link_status, dig->dp_lane_count)) |
| 560 | return false; | 490 | return false; |
| @@ -574,7 +504,7 @@ void radeon_dp_set_rx_power_state(struct drm_connector *connector, | |||
| 574 | 504 | ||
| 575 | /* power up/down the sink */ | 505 | /* power up/down the sink */ |
| 576 | if (dig_connector->dpcd[0] >= 0x11) { | 506 | if (dig_connector->dpcd[0] >= 0x11) { |
| 577 | drm_dp_dpcd_writeb(&dig_connector->dp_i2c_bus->aux, | 507 | drm_dp_dpcd_writeb(&radeon_connector->ddc_bus->aux, |
| 578 | DP_SET_POWER, power_state); | 508 | DP_SET_POWER, power_state); |
| 579 | usleep_range(1000, 2000); | 509 | usleep_range(1000, 2000); |
| 580 | } | 510 | } |
| @@ -878,7 +808,7 @@ void radeon_dp_link_train(struct drm_encoder *encoder, | |||
| 878 | else | 808 | else |
| 879 | dp_info.enc_id |= ATOM_DP_CONFIG_LINK_A; | 809 | dp_info.enc_id |= ATOM_DP_CONFIG_LINK_A; |
| 880 | 810 | ||
| 881 | drm_dp_dpcd_readb(&dig_connector->dp_i2c_bus->aux, DP_MAX_LANE_COUNT, &tmp); | 811 | drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, DP_MAX_LANE_COUNT, &tmp); |
| 882 | if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED)) | 812 | if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED)) |
| 883 | dp_info.tp3_supported = true; | 813 | dp_info.tp3_supported = true; |
| 884 | else | 814 | else |
| @@ -890,7 +820,7 @@ void radeon_dp_link_train(struct drm_encoder *encoder, | |||
| 890 | dp_info.connector = connector; | 820 | dp_info.connector = connector; |
| 891 | dp_info.dp_lane_count = dig_connector->dp_lane_count; | 821 | dp_info.dp_lane_count = dig_connector->dp_lane_count; |
| 892 | dp_info.dp_clock = dig_connector->dp_clock; | 822 | dp_info.dp_clock = dig_connector->dp_clock; |
| 893 | dp_info.aux = &dig_connector->dp_i2c_bus->aux; | 823 | dp_info.aux = &radeon_connector->ddc_bus->aux; |
| 894 | 824 | ||
| 895 | if (radeon_dp_link_train_init(&dp_info)) | 825 | if (radeon_dp_link_train_init(&dp_info)) |
| 896 | goto done; | 826 | goto done; |
diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index cad89a977527..10dae4106c08 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c | |||
| @@ -21,8 +21,10 @@ | |||
| 21 | * | 21 | * |
| 22 | */ | 22 | */ |
| 23 | 23 | ||
| 24 | #include <linux/firmware.h> | ||
| 24 | #include "drmP.h" | 25 | #include "drmP.h" |
| 25 | #include "radeon.h" | 26 | #include "radeon.h" |
| 27 | #include "radeon_ucode.h" | ||
| 26 | #include "cikd.h" | 28 | #include "cikd.h" |
| 27 | #include "r600_dpm.h" | 29 | #include "r600_dpm.h" |
| 28 | #include "ci_dpm.h" | 30 | #include "ci_dpm.h" |
| @@ -202,24 +204,29 @@ static void ci_initialize_powertune_defaults(struct radeon_device *rdev) | |||
| 202 | struct ci_power_info *pi = ci_get_pi(rdev); | 204 | struct ci_power_info *pi = ci_get_pi(rdev); |
| 203 | 205 | ||
| 204 | switch (rdev->pdev->device) { | 206 | switch (rdev->pdev->device) { |
| 207 | case 0x6649: | ||
| 205 | case 0x6650: | 208 | case 0x6650: |
| 209 | case 0x6651: | ||
| 206 | case 0x6658: | 210 | case 0x6658: |
| 207 | case 0x665C: | 211 | case 0x665C: |
| 212 | case 0x665D: | ||
| 208 | default: | 213 | default: |
| 209 | pi->powertune_defaults = &defaults_bonaire_xt; | 214 | pi->powertune_defaults = &defaults_bonaire_xt; |
| 210 | break; | 215 | break; |
| 211 | case 0x6651: | ||
| 212 | case 0x665D: | ||
| 213 | pi->powertune_defaults = &defaults_bonaire_pro; | ||
| 214 | break; | ||
| 215 | case 0x6640: | 216 | case 0x6640: |
| 216 | pi->powertune_defaults = &defaults_saturn_xt; | ||
| 217 | break; | ||
| 218 | case 0x6641: | 217 | case 0x6641: |
| 219 | pi->powertune_defaults = &defaults_saturn_pro; | 218 | case 0x6646: |
| 219 | case 0x6647: | ||
| 220 | pi->powertune_defaults = &defaults_saturn_xt; | ||
| 220 | break; | 221 | break; |
| 221 | case 0x67B8: | 222 | case 0x67B8: |
| 222 | case 0x67B0: | 223 | case 0x67B0: |
| 224 | pi->powertune_defaults = &defaults_hawaii_xt; | ||
| 225 | break; | ||
| 226 | case 0x67BA: | ||
| 227 | case 0x67B1: | ||
| 228 | pi->powertune_defaults = &defaults_hawaii_pro; | ||
| 229 | break; | ||
| 223 | case 0x67A0: | 230 | case 0x67A0: |
| 224 | case 0x67A1: | 231 | case 0x67A1: |
| 225 | case 0x67A2: | 232 | case 0x67A2: |
| @@ -228,11 +235,7 @@ static void ci_initialize_powertune_defaults(struct radeon_device *rdev) | |||
| 228 | case 0x67AA: | 235 | case 0x67AA: |
| 229 | case 0x67B9: | 236 | case 0x67B9: |
| 230 | case 0x67BE: | 237 | case 0x67BE: |
| 231 | pi->powertune_defaults = &defaults_hawaii_xt; | 238 | pi->powertune_defaults = &defaults_bonaire_xt; |
| 232 | break; | ||
| 233 | case 0x67BA: | ||
| 234 | case 0x67B1: | ||
| 235 | pi->powertune_defaults = &defaults_hawaii_pro; | ||
| 236 | break; | 239 | break; |
| 237 | } | 240 | } |
| 238 | 241 | ||
| @@ -5146,6 +5149,12 @@ int ci_dpm_init(struct radeon_device *rdev) | |||
| 5146 | pi->mclk_dpm_key_disabled = 0; | 5149 | pi->mclk_dpm_key_disabled = 0; |
| 5147 | pi->pcie_dpm_key_disabled = 0; | 5150 | pi->pcie_dpm_key_disabled = 0; |
| 5148 | 5151 | ||
| 5152 | /* mclk dpm is unstable on some R7 260X cards with the old mc ucode */ | ||
| 5153 | if ((rdev->pdev->device == 0x6658) && | ||
| 5154 | (rdev->mc_fw->size == (BONAIRE_MC_UCODE_SIZE * 4))) { | ||
| 5155 | pi->mclk_dpm_key_disabled = 1; | ||
| 5156 | } | ||
| 5157 | |||
| 5149 | pi->caps_sclk_ds = true; | 5158 | pi->caps_sclk_ds = true; |
| 5150 | 5159 | ||
| 5151 | pi->mclk_strobe_mode_threshold = 40000; | 5160 | pi->mclk_strobe_mode_threshold = 40000; |
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 745143c2358f..199eb194716f 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c | |||
| @@ -38,6 +38,7 @@ MODULE_FIRMWARE("radeon/BONAIRE_me.bin"); | |||
| 38 | MODULE_FIRMWARE("radeon/BONAIRE_ce.bin"); | 38 | MODULE_FIRMWARE("radeon/BONAIRE_ce.bin"); |
| 39 | MODULE_FIRMWARE("radeon/BONAIRE_mec.bin"); | 39 | MODULE_FIRMWARE("radeon/BONAIRE_mec.bin"); |
| 40 | MODULE_FIRMWARE("radeon/BONAIRE_mc.bin"); | 40 | MODULE_FIRMWARE("radeon/BONAIRE_mc.bin"); |
| 41 | MODULE_FIRMWARE("radeon/BONAIRE_mc2.bin"); | ||
| 41 | MODULE_FIRMWARE("radeon/BONAIRE_rlc.bin"); | 42 | MODULE_FIRMWARE("radeon/BONAIRE_rlc.bin"); |
| 42 | MODULE_FIRMWARE("radeon/BONAIRE_sdma.bin"); | 43 | MODULE_FIRMWARE("radeon/BONAIRE_sdma.bin"); |
| 43 | MODULE_FIRMWARE("radeon/BONAIRE_smc.bin"); | 44 | MODULE_FIRMWARE("radeon/BONAIRE_smc.bin"); |
| @@ -46,6 +47,7 @@ MODULE_FIRMWARE("radeon/HAWAII_me.bin"); | |||
| 46 | MODULE_FIRMWARE("radeon/HAWAII_ce.bin"); | 47 | MODULE_FIRMWARE("radeon/HAWAII_ce.bin"); |
| 47 | MODULE_FIRMWARE("radeon/HAWAII_mec.bin"); | 48 | MODULE_FIRMWARE("radeon/HAWAII_mec.bin"); |
| 48 | MODULE_FIRMWARE("radeon/HAWAII_mc.bin"); | 49 | MODULE_FIRMWARE("radeon/HAWAII_mc.bin"); |
| 50 | MODULE_FIRMWARE("radeon/HAWAII_mc2.bin"); | ||
| 49 | MODULE_FIRMWARE("radeon/HAWAII_rlc.bin"); | 51 | MODULE_FIRMWARE("radeon/HAWAII_rlc.bin"); |
| 50 | MODULE_FIRMWARE("radeon/HAWAII_sdma.bin"); | 52 | MODULE_FIRMWARE("radeon/HAWAII_sdma.bin"); |
| 51 | MODULE_FIRMWARE("radeon/HAWAII_smc.bin"); | 53 | MODULE_FIRMWARE("radeon/HAWAII_smc.bin"); |
| @@ -1703,20 +1705,20 @@ int ci_mc_load_microcode(struct radeon_device *rdev) | |||
| 1703 | const __be32 *fw_data; | 1705 | const __be32 *fw_data; |
| 1704 | u32 running, blackout = 0; | 1706 | u32 running, blackout = 0; |
| 1705 | u32 *io_mc_regs; | 1707 | u32 *io_mc_regs; |
| 1706 | int i, ucode_size, regs_size; | 1708 | int i, regs_size, ucode_size; |
| 1707 | 1709 | ||
| 1708 | if (!rdev->mc_fw) | 1710 | if (!rdev->mc_fw) |
| 1709 | return -EINVAL; | 1711 | return -EINVAL; |
| 1710 | 1712 | ||
| 1713 | ucode_size = rdev->mc_fw->size / 4; | ||
| 1714 | |||
| 1711 | switch (rdev->family) { | 1715 | switch (rdev->family) { |
| 1712 | case CHIP_BONAIRE: | 1716 | case CHIP_BONAIRE: |
| 1713 | io_mc_regs = (u32 *)&bonaire_io_mc_regs; | 1717 | io_mc_regs = (u32 *)&bonaire_io_mc_regs; |
| 1714 | ucode_size = CIK_MC_UCODE_SIZE; | ||
| 1715 | regs_size = BONAIRE_IO_MC_REGS_SIZE; | 1718 | regs_size = BONAIRE_IO_MC_REGS_SIZE; |
| 1716 | break; | 1719 | break; |
| 1717 | case CHIP_HAWAII: | 1720 | case CHIP_HAWAII: |
| 1718 | io_mc_regs = (u32 *)&hawaii_io_mc_regs; | 1721 | io_mc_regs = (u32 *)&hawaii_io_mc_regs; |
| 1719 | ucode_size = HAWAII_MC_UCODE_SIZE; | ||
| 1720 | regs_size = HAWAII_IO_MC_REGS_SIZE; | 1722 | regs_size = HAWAII_IO_MC_REGS_SIZE; |
| 1721 | break; | 1723 | break; |
| 1722 | default: | 1724 | default: |
| @@ -1783,7 +1785,7 @@ static int cik_init_microcode(struct radeon_device *rdev) | |||
| 1783 | const char *chip_name; | 1785 | const char *chip_name; |
| 1784 | size_t pfp_req_size, me_req_size, ce_req_size, | 1786 | size_t pfp_req_size, me_req_size, ce_req_size, |
| 1785 | mec_req_size, rlc_req_size, mc_req_size = 0, | 1787 | mec_req_size, rlc_req_size, mc_req_size = 0, |
| 1786 | sdma_req_size, smc_req_size = 0; | 1788 | sdma_req_size, smc_req_size = 0, mc2_req_size = 0; |
| 1787 | char fw_name[30]; | 1789 | char fw_name[30]; |
| 1788 | int err; | 1790 | int err; |
| 1789 | 1791 | ||
| @@ -1797,7 +1799,8 @@ static int cik_init_microcode(struct radeon_device *rdev) | |||
| 1797 | ce_req_size = CIK_CE_UCODE_SIZE * 4; | 1799 | ce_req_size = CIK_CE_UCODE_SIZE * 4; |
| 1798 | mec_req_size = CIK_MEC_UCODE_SIZE * 4; | 1800 | mec_req_size = CIK_MEC_UCODE_SIZE * 4; |
| 1799 | rlc_req_size = BONAIRE_RLC_UCODE_SIZE * 4; | 1801 | rlc_req_size = BONAIRE_RLC_UCODE_SIZE * 4; |
| 1800 | mc_req_size = CIK_MC_UCODE_SIZE * 4; | 1802 | mc_req_size = BONAIRE_MC_UCODE_SIZE * 4; |
| 1803 | mc2_req_size = BONAIRE_MC2_UCODE_SIZE * 4; | ||
| 1801 | sdma_req_size = CIK_SDMA_UCODE_SIZE * 4; | 1804 | sdma_req_size = CIK_SDMA_UCODE_SIZE * 4; |
| 1802 | smc_req_size = ALIGN(BONAIRE_SMC_UCODE_SIZE, 4); | 1805 | smc_req_size = ALIGN(BONAIRE_SMC_UCODE_SIZE, 4); |
| 1803 | break; | 1806 | break; |
| @@ -1809,6 +1812,7 @@ static int cik_init_microcode(struct radeon_device *rdev) | |||
| 1809 | mec_req_size = CIK_MEC_UCODE_SIZE * 4; | 1812 | mec_req_size = CIK_MEC_UCODE_SIZE * 4; |
| 1810 | rlc_req_size = BONAIRE_RLC_UCODE_SIZE * 4; | 1813 | rlc_req_size = BONAIRE_RLC_UCODE_SIZE * 4; |
| 1811 | mc_req_size = HAWAII_MC_UCODE_SIZE * 4; | 1814 | mc_req_size = HAWAII_MC_UCODE_SIZE * 4; |
| 1815 | mc2_req_size = HAWAII_MC2_UCODE_SIZE * 4; | ||
| 1812 | sdma_req_size = CIK_SDMA_UCODE_SIZE * 4; | 1816 | sdma_req_size = CIK_SDMA_UCODE_SIZE * 4; |
| 1813 | smc_req_size = ALIGN(HAWAII_SMC_UCODE_SIZE, 4); | 1817 | smc_req_size = ALIGN(HAWAII_SMC_UCODE_SIZE, 4); |
| 1814 | break; | 1818 | break; |
| @@ -1904,16 +1908,22 @@ static int cik_init_microcode(struct radeon_device *rdev) | |||
| 1904 | 1908 | ||
| 1905 | /* No SMC, MC ucode on APUs */ | 1909 | /* No SMC, MC ucode on APUs */ |
| 1906 | if (!(rdev->flags & RADEON_IS_IGP)) { | 1910 | if (!(rdev->flags & RADEON_IS_IGP)) { |
| 1907 | snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); | 1911 | snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc2.bin", chip_name); |
| 1908 | err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev); | 1912 | err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev); |
| 1909 | if (err) | 1913 | if (err) { |
| 1910 | goto out; | 1914 | snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); |
| 1911 | if (rdev->mc_fw->size != mc_req_size) { | 1915 | err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev); |
| 1916 | if (err) | ||
| 1917 | goto out; | ||
| 1918 | } | ||
| 1919 | if ((rdev->mc_fw->size != mc_req_size) && | ||
| 1920 | (rdev->mc_fw->size != mc2_req_size)){ | ||
| 1912 | printk(KERN_ERR | 1921 | printk(KERN_ERR |
| 1913 | "cik_mc: Bogus length %zu in firmware \"%s\"\n", | 1922 | "cik_mc: Bogus length %zu in firmware \"%s\"\n", |
| 1914 | rdev->mc_fw->size, fw_name); | 1923 | rdev->mc_fw->size, fw_name); |
| 1915 | err = -EINVAL; | 1924 | err = -EINVAL; |
| 1916 | } | 1925 | } |
| 1926 | DRM_INFO("%s: %zu bytes\n", fw_name, rdev->mc_fw->size); | ||
| 1917 | 1927 | ||
| 1918 | snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name); | 1928 | snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name); |
| 1919 | err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev); | 1929 | err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev); |
diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c index 94e858751994..0a65dc7e93e7 100644 --- a/drivers/gpu/drm/radeon/dce6_afmt.c +++ b/drivers/gpu/drm/radeon/dce6_afmt.c | |||
| @@ -309,11 +309,17 @@ int dce6_audio_init(struct radeon_device *rdev) | |||
| 309 | 309 | ||
| 310 | rdev->audio.enabled = true; | 310 | rdev->audio.enabled = true; |
| 311 | 311 | ||
| 312 | if (ASIC_IS_DCE8(rdev)) | 312 | if (ASIC_IS_DCE81(rdev)) /* KV: 4 streams, 7 endpoints */ |
| 313 | rdev->audio.num_pins = 7; | ||
| 314 | else if (ASIC_IS_DCE83(rdev)) /* KB: 2 streams, 3 endpoints */ | ||
| 315 | rdev->audio.num_pins = 3; | ||
| 316 | else if (ASIC_IS_DCE8(rdev)) /* BN/HW: 6 streams, 7 endpoints */ | ||
| 317 | rdev->audio.num_pins = 7; | ||
| 318 | else if (ASIC_IS_DCE61(rdev)) /* TN: 4 streams, 6 endpoints */ | ||
| 313 | rdev->audio.num_pins = 6; | 319 | rdev->audio.num_pins = 6; |
| 314 | else if (ASIC_IS_DCE61(rdev)) | 320 | else if (ASIC_IS_DCE64(rdev)) /* OL: 2 streams, 2 endpoints */ |
| 315 | rdev->audio.num_pins = 4; | 321 | rdev->audio.num_pins = 2; |
| 316 | else | 322 | else /* SI: 6 streams, 6 endpoints */ |
| 317 | rdev->audio.num_pins = 6; | 323 | rdev->audio.num_pins = 6; |
| 318 | 324 | ||
| 319 | for (i = 0; i < rdev->audio.num_pins; i++) { | 325 | for (i = 0; i < rdev->audio.num_pins; i++) { |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index f21db7a0b34d..b58e1afdda76 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
| @@ -739,7 +739,7 @@ union radeon_irq_stat_regs { | |||
| 739 | struct cik_irq_stat_regs cik; | 739 | struct cik_irq_stat_regs cik; |
| 740 | }; | 740 | }; |
| 741 | 741 | ||
| 742 | #define RADEON_MAX_HPD_PINS 6 | 742 | #define RADEON_MAX_HPD_PINS 7 |
| 743 | #define RADEON_MAX_CRTCS 6 | 743 | #define RADEON_MAX_CRTCS 6 |
| 744 | #define RADEON_MAX_AFMT_BLOCKS 7 | 744 | #define RADEON_MAX_AFMT_BLOCKS 7 |
| 745 | 745 | ||
| @@ -2321,6 +2321,7 @@ struct radeon_device { | |||
| 2321 | bool have_disp_power_ref; | 2321 | bool have_disp_power_ref; |
| 2322 | }; | 2322 | }; |
| 2323 | 2323 | ||
| 2324 | bool radeon_is_px(struct drm_device *dev); | ||
| 2324 | int radeon_device_init(struct radeon_device *rdev, | 2325 | int radeon_device_init(struct radeon_device *rdev, |
| 2325 | struct drm_device *ddev, | 2326 | struct drm_device *ddev, |
| 2326 | struct pci_dev *pdev, | 2327 | struct pci_dev *pdev, |
| @@ -2631,6 +2632,9 @@ void r100_pll_errata_after_index(struct radeon_device *rdev); | |||
| 2631 | #define ASIC_IS_DCE64(rdev) ((rdev->family == CHIP_OLAND)) | 2632 | #define ASIC_IS_DCE64(rdev) ((rdev->family == CHIP_OLAND)) |
| 2632 | #define ASIC_IS_NODCE(rdev) ((rdev->family == CHIP_HAINAN)) | 2633 | #define ASIC_IS_NODCE(rdev) ((rdev->family == CHIP_HAINAN)) |
| 2633 | #define ASIC_IS_DCE8(rdev) ((rdev->family >= CHIP_BONAIRE)) | 2634 | #define ASIC_IS_DCE8(rdev) ((rdev->family >= CHIP_BONAIRE)) |
| 2635 | #define ASIC_IS_DCE81(rdev) ((rdev->family == CHIP_KAVERI)) | ||
| 2636 | #define ASIC_IS_DCE82(rdev) ((rdev->family == CHIP_BONAIRE)) | ||
| 2637 | #define ASIC_IS_DCE83(rdev) ((rdev->family == CHIP_KABINI)) | ||
| 2634 | 2638 | ||
| 2635 | #define ASIC_IS_LOMBOK(rdev) ((rdev->ddev->pdev->device == 0x6849) || \ | 2639 | #define ASIC_IS_LOMBOK(rdev) ((rdev->ddev->pdev->device == 0x6849) || \ |
| 2636 | (rdev->ddev->pdev->device == 0x6850) || \ | 2640 | (rdev->ddev->pdev->device == 0x6850) || \ |
diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index fa9a9c02751e..dedea72f48c4 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c | |||
| @@ -59,7 +59,7 @@ struct atpx_mux { | |||
| 59 | u16 mux; | 59 | u16 mux; |
| 60 | } __packed; | 60 | } __packed; |
| 61 | 61 | ||
| 62 | bool radeon_is_px(void) { | 62 | bool radeon_has_atpx(void) { |
| 63 | return radeon_atpx_priv.atpx_detected; | 63 | return radeon_atpx_priv.atpx_detected; |
| 64 | } | 64 | } |
| 65 | 65 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index c566b486ca08..ea50e0ae7bf7 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
| @@ -1261,21 +1261,6 @@ static const struct drm_connector_funcs radeon_dvi_connector_funcs = { | |||
| 1261 | .force = radeon_dvi_force, | 1261 | .force = radeon_dvi_force, |
| 1262 | }; | 1262 | }; |
| 1263 | 1263 | ||
| 1264 | static void radeon_dp_connector_destroy(struct drm_connector *connector) | ||
| 1265 | { | ||
| 1266 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
| 1267 | struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; | ||
| 1268 | |||
| 1269 | if (radeon_connector->edid) | ||
| 1270 | kfree(radeon_connector->edid); | ||
| 1271 | if (radeon_dig_connector->dp_i2c_bus) | ||
| 1272 | radeon_i2c_destroy(radeon_dig_connector->dp_i2c_bus); | ||
| 1273 | kfree(radeon_connector->con_priv); | ||
| 1274 | drm_sysfs_connector_remove(connector); | ||
| 1275 | drm_connector_cleanup(connector); | ||
| 1276 | kfree(connector); | ||
| 1277 | } | ||
| 1278 | |||
| 1279 | static int radeon_dp_get_modes(struct drm_connector *connector) | 1264 | static int radeon_dp_get_modes(struct drm_connector *connector) |
| 1280 | { | 1265 | { |
| 1281 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 1266 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| @@ -1553,7 +1538,7 @@ static const struct drm_connector_funcs radeon_dp_connector_funcs = { | |||
| 1553 | .detect = radeon_dp_detect, | 1538 | .detect = radeon_dp_detect, |
| 1554 | .fill_modes = drm_helper_probe_single_connector_modes, | 1539 | .fill_modes = drm_helper_probe_single_connector_modes, |
| 1555 | .set_property = radeon_connector_set_property, | 1540 | .set_property = radeon_connector_set_property, |
| 1556 | .destroy = radeon_dp_connector_destroy, | 1541 | .destroy = radeon_connector_destroy, |
| 1557 | .force = radeon_dvi_force, | 1542 | .force = radeon_dvi_force, |
| 1558 | }; | 1543 | }; |
| 1559 | 1544 | ||
| @@ -1562,7 +1547,7 @@ static const struct drm_connector_funcs radeon_edp_connector_funcs = { | |||
| 1562 | .detect = radeon_dp_detect, | 1547 | .detect = radeon_dp_detect, |
| 1563 | .fill_modes = drm_helper_probe_single_connector_modes, | 1548 | .fill_modes = drm_helper_probe_single_connector_modes, |
| 1564 | .set_property = radeon_lvds_set_property, | 1549 | .set_property = radeon_lvds_set_property, |
| 1565 | .destroy = radeon_dp_connector_destroy, | 1550 | .destroy = radeon_connector_destroy, |
| 1566 | .force = radeon_dvi_force, | 1551 | .force = radeon_dvi_force, |
| 1567 | }; | 1552 | }; |
| 1568 | 1553 | ||
| @@ -1571,7 +1556,7 @@ static const struct drm_connector_funcs radeon_lvds_bridge_connector_funcs = { | |||
| 1571 | .detect = radeon_dp_detect, | 1556 | .detect = radeon_dp_detect, |
| 1572 | .fill_modes = drm_helper_probe_single_connector_modes, | 1557 | .fill_modes = drm_helper_probe_single_connector_modes, |
| 1573 | .set_property = radeon_lvds_set_property, | 1558 | .set_property = radeon_lvds_set_property, |
| 1574 | .destroy = radeon_dp_connector_destroy, | 1559 | .destroy = radeon_connector_destroy, |
| 1575 | .force = radeon_dvi_force, | 1560 | .force = radeon_dvi_force, |
| 1576 | }; | 1561 | }; |
| 1577 | 1562 | ||
| @@ -1668,17 +1653,10 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
| 1668 | radeon_dig_connector->igp_lane_info = igp_lane_info; | 1653 | radeon_dig_connector->igp_lane_info = igp_lane_info; |
| 1669 | radeon_connector->con_priv = radeon_dig_connector; | 1654 | radeon_connector->con_priv = radeon_dig_connector; |
| 1670 | if (i2c_bus->valid) { | 1655 | if (i2c_bus->valid) { |
| 1671 | /* add DP i2c bus */ | 1656 | radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
| 1672 | if (connector_type == DRM_MODE_CONNECTOR_eDP) | 1657 | if (radeon_connector->ddc_bus) |
| 1673 | radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch"); | ||
| 1674 | else | ||
| 1675 | radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch"); | ||
| 1676 | if (radeon_dig_connector->dp_i2c_bus) | ||
| 1677 | has_aux = true; | 1658 | has_aux = true; |
| 1678 | else | 1659 | else |
| 1679 | DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n"); | ||
| 1680 | radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); | ||
| 1681 | if (!radeon_connector->ddc_bus) | ||
| 1682 | DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); | 1660 | DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); |
| 1683 | } | 1661 | } |
| 1684 | switch (connector_type) { | 1662 | switch (connector_type) { |
| @@ -1893,10 +1871,6 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
| 1893 | drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type); | 1871 | drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type); |
| 1894 | drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); | 1872 | drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); |
| 1895 | if (i2c_bus->valid) { | 1873 | if (i2c_bus->valid) { |
| 1896 | /* add DP i2c bus */ | ||
| 1897 | radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch"); | ||
| 1898 | if (!radeon_dig_connector->dp_i2c_bus) | ||
| 1899 | DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n"); | ||
| 1900 | radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); | 1874 | radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
| 1901 | if (radeon_connector->ddc_bus) | 1875 | if (radeon_connector->ddc_bus) |
| 1902 | has_aux = true; | 1876 | has_aux = true; |
| @@ -1942,14 +1916,10 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
| 1942 | drm_connector_init(dev, &radeon_connector->base, &radeon_edp_connector_funcs, connector_type); | 1916 | drm_connector_init(dev, &radeon_connector->base, &radeon_edp_connector_funcs, connector_type); |
| 1943 | drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); | 1917 | drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); |
| 1944 | if (i2c_bus->valid) { | 1918 | if (i2c_bus->valid) { |
| 1945 | /* add DP i2c bus */ | 1919 | radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); |
| 1946 | radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch"); | 1920 | if (radeon_connector->ddc_bus) |
| 1947 | if (radeon_dig_connector->dp_i2c_bus) | ||
| 1948 | has_aux = true; | 1921 | has_aux = true; |
| 1949 | else | 1922 | else |
| 1950 | DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n"); | ||
| 1951 | radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); | ||
| 1952 | if (!radeon_connector->ddc_bus) | ||
| 1953 | DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); | 1923 | DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); |
| 1954 | } | 1924 | } |
| 1955 | drm_object_attach_property(&radeon_connector->base.base, | 1925 | drm_object_attach_property(&radeon_connector->base.base, |
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 835516d2d257..511fe26198e4 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
| @@ -102,11 +102,14 @@ static const char radeon_family_name[][16] = { | |||
| 102 | "LAST", | 102 | "LAST", |
| 103 | }; | 103 | }; |
| 104 | 104 | ||
| 105 | #if defined(CONFIG_VGA_SWITCHEROO) | 105 | bool radeon_is_px(struct drm_device *dev) |
| 106 | bool radeon_is_px(void); | 106 | { |
| 107 | #else | 107 | struct radeon_device *rdev = dev->dev_private; |
| 108 | static inline bool radeon_is_px(void) { return false; } | 108 | |
| 109 | #endif | 109 | if (rdev->flags & RADEON_IS_PX) |
| 110 | return true; | ||
| 111 | return false; | ||
| 112 | } | ||
| 110 | 113 | ||
| 111 | /** | 114 | /** |
| 112 | * radeon_program_register_sequence - program an array of registers. | 115 | * radeon_program_register_sequence - program an array of registers. |
| @@ -1082,7 +1085,7 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero | |||
| 1082 | { | 1085 | { |
| 1083 | struct drm_device *dev = pci_get_drvdata(pdev); | 1086 | struct drm_device *dev = pci_get_drvdata(pdev); |
| 1084 | 1087 | ||
| 1085 | if (radeon_is_px() && state == VGA_SWITCHEROO_OFF) | 1088 | if (radeon_is_px(dev) && state == VGA_SWITCHEROO_OFF) |
| 1086 | return; | 1089 | return; |
| 1087 | 1090 | ||
| 1088 | if (state == VGA_SWITCHEROO_ON) { | 1091 | if (state == VGA_SWITCHEROO_ON) { |
| @@ -1301,9 +1304,7 @@ int radeon_device_init(struct radeon_device *rdev, | |||
| 1301 | * ignore it */ | 1304 | * ignore it */ |
| 1302 | vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode); | 1305 | vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode); |
| 1303 | 1306 | ||
| 1304 | if (radeon_runtime_pm == 1) | 1307 | if (rdev->flags & RADEON_IS_PX) |
| 1305 | runtime = true; | ||
| 1306 | if ((radeon_runtime_pm == -1) && radeon_is_px()) | ||
| 1307 | runtime = true; | 1308 | runtime = true; |
| 1308 | vga_switcheroo_register_client(rdev->pdev, &radeon_switcheroo_ops, runtime); | 1309 | vga_switcheroo_register_client(rdev->pdev, &radeon_switcheroo_ops, runtime); |
| 1309 | if (runtime) | 1310 | if (runtime) |
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 386cfa4c194d..2f7cbb901fb1 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
| @@ -759,19 +759,18 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) | |||
| 759 | 759 | ||
| 760 | if (radeon_connector_encoder_get_dp_bridge_encoder_id(&radeon_connector->base) != | 760 | if (radeon_connector_encoder_get_dp_bridge_encoder_id(&radeon_connector->base) != |
| 761 | ENCODER_OBJECT_ID_NONE) { | 761 | ENCODER_OBJECT_ID_NONE) { |
| 762 | struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; | 762 | if (radeon_connector->ddc_bus->has_aux) |
| 763 | |||
| 764 | if (dig->dp_i2c_bus) | ||
| 765 | radeon_connector->edid = drm_get_edid(&radeon_connector->base, | 763 | radeon_connector->edid = drm_get_edid(&radeon_connector->base, |
| 766 | &dig->dp_i2c_bus->adapter); | 764 | &radeon_connector->ddc_bus->aux.ddc); |
| 767 | } else if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || | 765 | } else if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || |
| 768 | (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) { | 766 | (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) { |
| 769 | struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; | 767 | struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; |
| 770 | 768 | ||
| 771 | if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT || | 769 | if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT || |
| 772 | dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) && dig->dp_i2c_bus) | 770 | dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) && |
| 771 | radeon_connector->ddc_bus->has_aux) | ||
| 773 | radeon_connector->edid = drm_get_edid(&radeon_connector->base, | 772 | radeon_connector->edid = drm_get_edid(&radeon_connector->base, |
| 774 | &dig->dp_i2c_bus->adapter); | 773 | &radeon_connector->ddc_bus->aux.ddc); |
| 775 | else if (radeon_connector->ddc_bus && !radeon_connector->edid) | 774 | else if (radeon_connector->ddc_bus && !radeon_connector->edid) |
| 776 | radeon_connector->edid = drm_get_edid(&radeon_connector->base, | 775 | radeon_connector->edid = drm_get_edid(&radeon_connector->base, |
| 777 | &radeon_connector->ddc_bus->adapter); | 776 | &radeon_connector->ddc_bus->adapter); |
| @@ -865,7 +864,7 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, | |||
| 865 | unsigned post_div_min, post_div_max, post_div; | 864 | unsigned post_div_min, post_div_max, post_div; |
| 866 | unsigned ref_div_min, ref_div_max, ref_div; | 865 | unsigned ref_div_min, ref_div_max, ref_div; |
| 867 | unsigned post_div_best, diff_best; | 866 | unsigned post_div_best, diff_best; |
| 868 | unsigned nom, den, tmp; | 867 | unsigned nom, den; |
| 869 | 868 | ||
| 870 | /* determine allowed feedback divider range */ | 869 | /* determine allowed feedback divider range */ |
| 871 | fb_div_min = pll->min_feedback_div; | 870 | fb_div_min = pll->min_feedback_div; |
| @@ -937,23 +936,27 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, | |||
| 937 | } | 936 | } |
| 938 | post_div = post_div_best; | 937 | post_div = post_div_best; |
| 939 | 938 | ||
| 939 | /* limit reference * post divider to a maximum */ | ||
| 940 | ref_div_max = min(210 / post_div, ref_div_max); | ||
| 941 | |||
| 940 | /* get matching reference and feedback divider */ | 942 | /* get matching reference and feedback divider */ |
| 941 | ref_div = max(den / post_div, 1u); | 943 | ref_div = max(DIV_ROUND_CLOSEST(den, post_div), 1u); |
| 942 | fb_div = nom; | 944 | fb_div = DIV_ROUND_CLOSEST(nom * ref_div * post_div, den); |
| 943 | 945 | ||
| 944 | /* we're almost done, but reference and feedback | 946 | /* we're almost done, but reference and feedback |
| 945 | divider might be to large now */ | 947 | divider might be to large now */ |
| 946 | 948 | ||
| 947 | tmp = ref_div; | 949 | nom = fb_div; |
| 950 | den = ref_div; | ||
| 948 | 951 | ||
| 949 | if (fb_div > fb_div_max) { | 952 | if (fb_div > fb_div_max) { |
| 950 | ref_div = ref_div * fb_div_max / fb_div; | 953 | ref_div = DIV_ROUND_CLOSEST(den * fb_div_max, nom); |
| 951 | fb_div = fb_div_max; | 954 | fb_div = fb_div_max; |
| 952 | } | 955 | } |
| 953 | 956 | ||
| 954 | if (ref_div > ref_div_max) { | 957 | if (ref_div > ref_div_max) { |
| 955 | ref_div = ref_div_max; | 958 | ref_div = ref_div_max; |
| 956 | fb_div = nom * ref_div_max / tmp; | 959 | fb_div = DIV_ROUND_CLOSEST(nom * ref_div_max, den); |
| 957 | } | 960 | } |
| 958 | 961 | ||
| 959 | /* reduce the numbers to a simpler ratio once more */ | 962 | /* reduce the numbers to a simpler ratio once more */ |
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index d0eba48dd74e..c00a2f585185 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c | |||
| @@ -115,6 +115,7 @@ extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, | |||
| 115 | unsigned int flags, | 115 | unsigned int flags, |
| 116 | int *vpos, int *hpos, ktime_t *stime, | 116 | int *vpos, int *hpos, ktime_t *stime, |
| 117 | ktime_t *etime); | 117 | ktime_t *etime); |
| 118 | extern bool radeon_is_px(struct drm_device *dev); | ||
| 118 | extern const struct drm_ioctl_desc radeon_ioctls_kms[]; | 119 | extern const struct drm_ioctl_desc radeon_ioctls_kms[]; |
| 119 | extern int radeon_max_kms_ioctl; | 120 | extern int radeon_max_kms_ioctl; |
| 120 | int radeon_mmap(struct file *filp, struct vm_area_struct *vma); | 121 | int radeon_mmap(struct file *filp, struct vm_area_struct *vma); |
| @@ -144,11 +145,9 @@ void radeon_debugfs_cleanup(struct drm_minor *minor); | |||
| 144 | #if defined(CONFIG_VGA_SWITCHEROO) | 145 | #if defined(CONFIG_VGA_SWITCHEROO) |
| 145 | void radeon_register_atpx_handler(void); | 146 | void radeon_register_atpx_handler(void); |
| 146 | void radeon_unregister_atpx_handler(void); | 147 | void radeon_unregister_atpx_handler(void); |
| 147 | bool radeon_is_px(void); | ||
| 148 | #else | 148 | #else |
| 149 | static inline void radeon_register_atpx_handler(void) {} | 149 | static inline void radeon_register_atpx_handler(void) {} |
| 150 | static inline void radeon_unregister_atpx_handler(void) {} | 150 | static inline void radeon_unregister_atpx_handler(void) {} |
| 151 | static inline bool radeon_is_px(void) { return false; } | ||
| 152 | #endif | 151 | #endif |
| 153 | 152 | ||
| 154 | int radeon_no_wb; | 153 | int radeon_no_wb; |
| @@ -186,7 +185,7 @@ module_param_named(dynclks, radeon_dynclks, int, 0444); | |||
| 186 | MODULE_PARM_DESC(r4xx_atom, "Enable ATOMBIOS modesetting for R4xx"); | 185 | MODULE_PARM_DESC(r4xx_atom, "Enable ATOMBIOS modesetting for R4xx"); |
| 187 | module_param_named(r4xx_atom, radeon_r4xx_atom, int, 0444); | 186 | module_param_named(r4xx_atom, radeon_r4xx_atom, int, 0444); |
| 188 | 187 | ||
| 189 | MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing"); | 188 | MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing, in megabytes"); |
| 190 | module_param_named(vramlimit, radeon_vram_limit, int, 0600); | 189 | module_param_named(vramlimit, radeon_vram_limit, int, 0600); |
| 191 | 190 | ||
| 192 | MODULE_PARM_DESC(agpmode, "AGP Mode (-1 == PCI)"); | 191 | MODULE_PARM_DESC(agpmode, "AGP Mode (-1 == PCI)"); |
| @@ -405,12 +404,7 @@ static int radeon_pmops_runtime_suspend(struct device *dev) | |||
| 405 | struct drm_device *drm_dev = pci_get_drvdata(pdev); | 404 | struct drm_device *drm_dev = pci_get_drvdata(pdev); |
| 406 | int ret; | 405 | int ret; |
| 407 | 406 | ||
| 408 | if (radeon_runtime_pm == 0) { | 407 | if (!radeon_is_px(drm_dev)) { |
| 409 | pm_runtime_forbid(dev); | ||
| 410 | return -EBUSY; | ||
| 411 | } | ||
| 412 | |||
| 413 | if (radeon_runtime_pm == -1 && !radeon_is_px()) { | ||
| 414 | pm_runtime_forbid(dev); | 408 | pm_runtime_forbid(dev); |
| 415 | return -EBUSY; | 409 | return -EBUSY; |
| 416 | } | 410 | } |
| @@ -434,10 +428,7 @@ static int radeon_pmops_runtime_resume(struct device *dev) | |||
| 434 | struct drm_device *drm_dev = pci_get_drvdata(pdev); | 428 | struct drm_device *drm_dev = pci_get_drvdata(pdev); |
| 435 | int ret; | 429 | int ret; |
| 436 | 430 | ||
| 437 | if (radeon_runtime_pm == 0) | 431 | if (!radeon_is_px(drm_dev)) |
| 438 | return -EINVAL; | ||
| 439 | |||
| 440 | if (radeon_runtime_pm == -1 && !radeon_is_px()) | ||
| 441 | return -EINVAL; | 432 | return -EINVAL; |
| 442 | 433 | ||
| 443 | drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; | 434 | drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; |
| @@ -462,14 +453,7 @@ static int radeon_pmops_runtime_idle(struct device *dev) | |||
| 462 | struct drm_device *drm_dev = pci_get_drvdata(pdev); | 453 | struct drm_device *drm_dev = pci_get_drvdata(pdev); |
| 463 | struct drm_crtc *crtc; | 454 | struct drm_crtc *crtc; |
| 464 | 455 | ||
| 465 | if (radeon_runtime_pm == 0) { | 456 | if (!radeon_is_px(drm_dev)) { |
| 466 | pm_runtime_forbid(dev); | ||
| 467 | return -EBUSY; | ||
| 468 | } | ||
| 469 | |||
| 470 | /* are we PX enabled? */ | ||
| 471 | if (radeon_runtime_pm == -1 && !radeon_is_px()) { | ||
| 472 | DRM_DEBUG_DRIVER("failing to power off - not px\n"); | ||
| 473 | pm_runtime_forbid(dev); | 457 | pm_runtime_forbid(dev); |
| 474 | return -EBUSY; | 458 | return -EBUSY; |
| 475 | } | 459 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_family.h b/drivers/gpu/drm/radeon/radeon_family.h index 614ad549297f..9da5da4ffd17 100644 --- a/drivers/gpu/drm/radeon/radeon_family.h +++ b/drivers/gpu/drm/radeon/radeon_family.h | |||
| @@ -115,6 +115,7 @@ enum radeon_chip_flags { | |||
| 115 | RADEON_NEW_MEMMAP = 0x00400000UL, | 115 | RADEON_NEW_MEMMAP = 0x00400000UL, |
| 116 | RADEON_IS_PCI = 0x00800000UL, | 116 | RADEON_IS_PCI = 0x00800000UL, |
| 117 | RADEON_IS_IGPGART = 0x01000000UL, | 117 | RADEON_IS_IGPGART = 0x01000000UL, |
| 118 | RADEON_IS_PX = 0x02000000UL, | ||
| 118 | }; | 119 | }; |
| 119 | 120 | ||
| 120 | #endif | 121 | #endif |
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index e24ca6ab96de..7b944142a9fd 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c | |||
| @@ -64,8 +64,7 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux) | |||
| 64 | radeon_router_select_ddc_port(radeon_connector); | 64 | radeon_router_select_ddc_port(radeon_connector); |
| 65 | 65 | ||
| 66 | if (use_aux) { | 66 | if (use_aux) { |
| 67 | struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; | 67 | ret = i2c_transfer(&radeon_connector->ddc_bus->aux.ddc, msgs, 2); |
| 68 | ret = i2c_transfer(&dig->dp_i2c_bus->adapter, msgs, 2); | ||
| 69 | } else { | 68 | } else { |
| 70 | ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); | 69 | ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); |
| 71 | } | 70 | } |
| @@ -950,16 +949,16 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, | |||
| 950 | /* set the radeon bit adapter */ | 949 | /* set the radeon bit adapter */ |
| 951 | snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), | 950 | snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), |
| 952 | "Radeon i2c bit bus %s", name); | 951 | "Radeon i2c bit bus %s", name); |
| 953 | i2c->adapter.algo_data = &i2c->algo.bit; | 952 | i2c->adapter.algo_data = &i2c->bit; |
| 954 | i2c->algo.bit.pre_xfer = pre_xfer; | 953 | i2c->bit.pre_xfer = pre_xfer; |
| 955 | i2c->algo.bit.post_xfer = post_xfer; | 954 | i2c->bit.post_xfer = post_xfer; |
| 956 | i2c->algo.bit.setsda = set_data; | 955 | i2c->bit.setsda = set_data; |
| 957 | i2c->algo.bit.setscl = set_clock; | 956 | i2c->bit.setscl = set_clock; |
| 958 | i2c->algo.bit.getsda = get_data; | 957 | i2c->bit.getsda = get_data; |
| 959 | i2c->algo.bit.getscl = get_clock; | 958 | i2c->bit.getscl = get_clock; |
| 960 | i2c->algo.bit.udelay = 10; | 959 | i2c->bit.udelay = 10; |
| 961 | i2c->algo.bit.timeout = usecs_to_jiffies(2200); /* from VESA */ | 960 | i2c->bit.timeout = usecs_to_jiffies(2200); /* from VESA */ |
| 962 | i2c->algo.bit.data = i2c; | 961 | i2c->bit.data = i2c; |
| 963 | ret = i2c_bit_add_bus(&i2c->adapter); | 962 | ret = i2c_bit_add_bus(&i2c->adapter); |
| 964 | if (ret) { | 963 | if (ret) { |
| 965 | DRM_ERROR("Failed to register bit i2c %s\n", name); | 964 | DRM_ERROR("Failed to register bit i2c %s\n", name); |
| @@ -974,46 +973,13 @@ out_free: | |||
| 974 | 973 | ||
| 975 | } | 974 | } |
| 976 | 975 | ||
| 977 | struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev, | ||
| 978 | struct radeon_i2c_bus_rec *rec, | ||
| 979 | const char *name) | ||
| 980 | { | ||
| 981 | struct radeon_i2c_chan *i2c; | ||
| 982 | int ret; | ||
| 983 | |||
| 984 | i2c = kzalloc(sizeof(struct radeon_i2c_chan), GFP_KERNEL); | ||
| 985 | if (i2c == NULL) | ||
| 986 | return NULL; | ||
| 987 | |||
| 988 | i2c->rec = *rec; | ||
| 989 | i2c->adapter.owner = THIS_MODULE; | ||
| 990 | i2c->adapter.class = I2C_CLASS_DDC; | ||
| 991 | i2c->adapter.dev.parent = &dev->pdev->dev; | ||
| 992 | i2c->dev = dev; | ||
| 993 | snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), | ||
| 994 | "Radeon aux bus %s", name); | ||
| 995 | i2c_set_adapdata(&i2c->adapter, i2c); | ||
| 996 | i2c->adapter.algo_data = &i2c->algo.dp; | ||
| 997 | i2c->algo.dp.aux_ch = radeon_dp_i2c_aux_ch; | ||
| 998 | i2c->algo.dp.address = 0; | ||
| 999 | ret = i2c_dp_aux_add_bus(&i2c->adapter); | ||
| 1000 | if (ret) { | ||
| 1001 | DRM_INFO("Failed to register i2c %s\n", name); | ||
| 1002 | goto out_free; | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | return i2c; | ||
| 1006 | out_free: | ||
| 1007 | kfree(i2c); | ||
| 1008 | return NULL; | ||
| 1009 | |||
| 1010 | } | ||
| 1011 | |||
| 1012 | void radeon_i2c_destroy(struct radeon_i2c_chan *i2c) | 976 | void radeon_i2c_destroy(struct radeon_i2c_chan *i2c) |
| 1013 | { | 977 | { |
| 1014 | if (!i2c) | 978 | if (!i2c) |
| 1015 | return; | 979 | return; |
| 1016 | i2c_del_adapter(&i2c->adapter); | 980 | i2c_del_adapter(&i2c->adapter); |
| 981 | if (i2c->has_aux) | ||
| 982 | drm_dp_aux_unregister_i2c_bus(&i2c->aux); | ||
| 1017 | kfree(i2c); | 983 | kfree(i2c); |
| 1018 | } | 984 | } |
| 1019 | 985 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 3e49342a20e6..fb3d13f693dd 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c | |||
| @@ -35,9 +35,9 @@ | |||
| 35 | #include <linux/pm_runtime.h> | 35 | #include <linux/pm_runtime.h> |
| 36 | 36 | ||
| 37 | #if defined(CONFIG_VGA_SWITCHEROO) | 37 | #if defined(CONFIG_VGA_SWITCHEROO) |
| 38 | bool radeon_is_px(void); | 38 | bool radeon_has_atpx(void); |
| 39 | #else | 39 | #else |
| 40 | static inline bool radeon_is_px(void) { return false; } | 40 | static inline bool radeon_has_atpx(void) { return false; } |
| 41 | #endif | 41 | #endif |
| 42 | 42 | ||
| 43 | /** | 43 | /** |
| @@ -107,6 +107,13 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) | |||
| 107 | flags |= RADEON_IS_PCI; | 107 | flags |= RADEON_IS_PCI; |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | if (radeon_runtime_pm == 1) | ||
| 111 | flags |= RADEON_IS_PX; | ||
| 112 | else if ((radeon_runtime_pm == -1) && | ||
| 113 | radeon_has_atpx() && | ||
| 114 | ((flags & RADEON_IS_IGP) == 0)) | ||
| 115 | flags |= RADEON_IS_PX; | ||
| 116 | |||
| 110 | /* radeon_device_init should report only fatal error | 117 | /* radeon_device_init should report only fatal error |
| 111 | * like memory allocation failure or iomapping failure, | 118 | * like memory allocation failure or iomapping failure, |
| 112 | * or memory manager initialization failure, it must | 119 | * or memory manager initialization failure, it must |
| @@ -137,8 +144,7 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) | |||
| 137 | "Error during ACPI methods call\n"); | 144 | "Error during ACPI methods call\n"); |
| 138 | } | 145 | } |
| 139 | 146 | ||
| 140 | if ((radeon_runtime_pm == 1) || | 147 | if (radeon_is_px(dev)) { |
| 141 | ((radeon_runtime_pm == -1) && radeon_is_px())) { | ||
| 142 | pm_runtime_use_autosuspend(dev->dev); | 148 | pm_runtime_use_autosuspend(dev->dev); |
| 143 | pm_runtime_set_autosuspend_delay(dev->dev, 5000); | 149 | pm_runtime_set_autosuspend_delay(dev->dev, 5000); |
| 144 | pm_runtime_set_active(dev->dev); | 150 | pm_runtime_set_active(dev->dev); |
| @@ -568,12 +574,17 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) | |||
| 568 | } | 574 | } |
| 569 | 575 | ||
| 570 | r = radeon_vm_init(rdev, &fpriv->vm); | 576 | r = radeon_vm_init(rdev, &fpriv->vm); |
| 571 | if (r) | 577 | if (r) { |
| 578 | kfree(fpriv); | ||
| 572 | return r; | 579 | return r; |
| 580 | } | ||
| 573 | 581 | ||
| 574 | r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); | 582 | r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); |
| 575 | if (r) | 583 | if (r) { |
| 584 | radeon_vm_fini(rdev, &fpriv->vm); | ||
| 585 | kfree(fpriv); | ||
| 576 | return r; | 586 | return r; |
| 587 | } | ||
| 577 | 588 | ||
| 578 | /* map the ib pool buffer read only into | 589 | /* map the ib pool buffer read only into |
| 579 | * virtual address space */ | 590 | * virtual address space */ |
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 832d9fa1a4c4..6ddf31a2d34e 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
| @@ -187,12 +187,10 @@ struct radeon_pll { | |||
| 187 | struct radeon_i2c_chan { | 187 | struct radeon_i2c_chan { |
| 188 | struct i2c_adapter adapter; | 188 | struct i2c_adapter adapter; |
| 189 | struct drm_device *dev; | 189 | struct drm_device *dev; |
| 190 | union { | 190 | struct i2c_algo_bit_data bit; |
| 191 | struct i2c_algo_bit_data bit; | ||
| 192 | struct i2c_algo_dp_aux_data dp; | ||
| 193 | } algo; | ||
| 194 | struct radeon_i2c_bus_rec rec; | 191 | struct radeon_i2c_bus_rec rec; |
| 195 | struct drm_dp_aux aux; | 192 | struct drm_dp_aux aux; |
| 193 | bool has_aux; | ||
| 196 | }; | 194 | }; |
| 197 | 195 | ||
| 198 | /* mostly for macs, but really any system without connector tables */ | 196 | /* mostly for macs, but really any system without connector tables */ |
| @@ -440,7 +438,6 @@ struct radeon_encoder { | |||
| 440 | struct radeon_connector_atom_dig { | 438 | struct radeon_connector_atom_dig { |
| 441 | uint32_t igp_lane_info; | 439 | uint32_t igp_lane_info; |
| 442 | /* displayport */ | 440 | /* displayport */ |
| 443 | struct radeon_i2c_chan *dp_i2c_bus; | ||
| 444 | u8 dpcd[DP_RECEIVER_CAP_SIZE]; | 441 | u8 dpcd[DP_RECEIVER_CAP_SIZE]; |
| 445 | u8 dp_sink_type; | 442 | u8 dp_sink_type; |
| 446 | int dp_clock; | 443 | int dp_clock; |
| @@ -702,8 +699,6 @@ extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder, | |||
| 702 | uint8_t lane_set); | 699 | uint8_t lane_set); |
| 703 | extern void radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder); | 700 | extern void radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder); |
| 704 | extern struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder); | 701 | extern struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder); |
| 705 | extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, | ||
| 706 | u8 write_byte, u8 *read_byte); | ||
| 707 | void radeon_atom_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le); | 702 | void radeon_atom_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le); |
| 708 | 703 | ||
| 709 | extern void radeon_i2c_init(struct radeon_device *rdev); | 704 | extern void radeon_i2c_init(struct radeon_device *rdev); |
| @@ -715,9 +710,6 @@ extern void radeon_i2c_add(struct radeon_device *rdev, | |||
| 715 | const char *name); | 710 | const char *name); |
| 716 | extern struct radeon_i2c_chan *radeon_i2c_lookup(struct radeon_device *rdev, | 711 | extern struct radeon_i2c_chan *radeon_i2c_lookup(struct radeon_device *rdev, |
| 717 | struct radeon_i2c_bus_rec *i2c_bus); | 712 | struct radeon_i2c_bus_rec *i2c_bus); |
| 718 | extern struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev, | ||
| 719 | struct radeon_i2c_bus_rec *rec, | ||
| 720 | const char *name); | ||
| 721 | extern struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, | 713 | extern struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, |
| 722 | struct radeon_i2c_bus_rec *rec, | 714 | struct radeon_i2c_bus_rec *rec, |
| 723 | const char *name); | 715 | const char *name); |
diff --git a/drivers/gpu/drm/radeon/radeon_ucode.h b/drivers/gpu/drm/radeon/radeon_ucode.h index a77cd274dfc3..58d12938c0b8 100644 --- a/drivers/gpu/drm/radeon/radeon_ucode.h +++ b/drivers/gpu/drm/radeon/radeon_ucode.h | |||
| @@ -57,9 +57,14 @@ | |||
| 57 | #define BTC_MC_UCODE_SIZE 6024 | 57 | #define BTC_MC_UCODE_SIZE 6024 |
| 58 | #define CAYMAN_MC_UCODE_SIZE 6037 | 58 | #define CAYMAN_MC_UCODE_SIZE 6037 |
| 59 | #define SI_MC_UCODE_SIZE 7769 | 59 | #define SI_MC_UCODE_SIZE 7769 |
| 60 | #define TAHITI_MC_UCODE_SIZE 7808 | ||
| 61 | #define PITCAIRN_MC_UCODE_SIZE 7775 | ||
| 62 | #define VERDE_MC_UCODE_SIZE 7875 | ||
| 60 | #define OLAND_MC_UCODE_SIZE 7863 | 63 | #define OLAND_MC_UCODE_SIZE 7863 |
| 61 | #define CIK_MC_UCODE_SIZE 7866 | 64 | #define BONAIRE_MC_UCODE_SIZE 7866 |
| 65 | #define BONAIRE_MC2_UCODE_SIZE 7948 | ||
| 62 | #define HAWAII_MC_UCODE_SIZE 7933 | 66 | #define HAWAII_MC_UCODE_SIZE 7933 |
| 67 | #define HAWAII_MC2_UCODE_SIZE 8091 | ||
| 63 | 68 | ||
| 64 | /* SDMA */ | 69 | /* SDMA */ |
| 65 | #define CIK_SDMA_UCODE_SIZE 1050 | 70 | #define CIK_SDMA_UCODE_SIZE 1050 |
diff --git a/drivers/gpu/drm/radeon/radeon_vce.c b/drivers/gpu/drm/radeon/radeon_vce.c index 76e9904bc537..ced53dd03e7c 100644 --- a/drivers/gpu/drm/radeon/radeon_vce.c +++ b/drivers/gpu/drm/radeon/radeon_vce.c | |||
| @@ -613,7 +613,7 @@ void radeon_vce_fence_emit(struct radeon_device *rdev, | |||
| 613 | struct radeon_fence *fence) | 613 | struct radeon_fence *fence) |
| 614 | { | 614 | { |
| 615 | struct radeon_ring *ring = &rdev->ring[fence->ring]; | 615 | struct radeon_ring *ring = &rdev->ring[fence->ring]; |
| 616 | uint32_t addr = rdev->fence_drv[fence->ring].gpu_addr; | 616 | uint64_t addr = rdev->fence_drv[fence->ring].gpu_addr; |
| 617 | 617 | ||
| 618 | radeon_ring_write(ring, VCE_CMD_FENCE); | 618 | radeon_ring_write(ring, VCE_CMD_FENCE); |
| 619 | radeon_ring_write(ring, addr); | 619 | radeon_ring_write(ring, addr); |
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index d589475fe9e6..ac708e006180 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
| @@ -39,30 +39,35 @@ MODULE_FIRMWARE("radeon/TAHITI_pfp.bin"); | |||
| 39 | MODULE_FIRMWARE("radeon/TAHITI_me.bin"); | 39 | MODULE_FIRMWARE("radeon/TAHITI_me.bin"); |
| 40 | MODULE_FIRMWARE("radeon/TAHITI_ce.bin"); | 40 | MODULE_FIRMWARE("radeon/TAHITI_ce.bin"); |
| 41 | MODULE_FIRMWARE("radeon/TAHITI_mc.bin"); | 41 | MODULE_FIRMWARE("radeon/TAHITI_mc.bin"); |
| 42 | MODULE_FIRMWARE("radeon/TAHITI_mc2.bin"); | ||
| 42 | MODULE_FIRMWARE("radeon/TAHITI_rlc.bin"); | 43 | MODULE_FIRMWARE("radeon/TAHITI_rlc.bin"); |
| 43 | MODULE_FIRMWARE("radeon/TAHITI_smc.bin"); | 44 | MODULE_FIRMWARE("radeon/TAHITI_smc.bin"); |
| 44 | MODULE_FIRMWARE("radeon/PITCAIRN_pfp.bin"); | 45 | MODULE_FIRMWARE("radeon/PITCAIRN_pfp.bin"); |
| 45 | MODULE_FIRMWARE("radeon/PITCAIRN_me.bin"); | 46 | MODULE_FIRMWARE("radeon/PITCAIRN_me.bin"); |
| 46 | MODULE_FIRMWARE("radeon/PITCAIRN_ce.bin"); | 47 | MODULE_FIRMWARE("radeon/PITCAIRN_ce.bin"); |
| 47 | MODULE_FIRMWARE("radeon/PITCAIRN_mc.bin"); | 48 | MODULE_FIRMWARE("radeon/PITCAIRN_mc.bin"); |
| 49 | MODULE_FIRMWARE("radeon/PITCAIRN_mc2.bin"); | ||
| 48 | MODULE_FIRMWARE("radeon/PITCAIRN_rlc.bin"); | 50 | MODULE_FIRMWARE("radeon/PITCAIRN_rlc.bin"); |
| 49 | MODULE_FIRMWARE("radeon/PITCAIRN_smc.bin"); | 51 | MODULE_FIRMWARE("radeon/PITCAIRN_smc.bin"); |
| 50 | MODULE_FIRMWARE("radeon/VERDE_pfp.bin"); | 52 | MODULE_FIRMWARE("radeon/VERDE_pfp.bin"); |
| 51 | MODULE_FIRMWARE("radeon/VERDE_me.bin"); | 53 | MODULE_FIRMWARE("radeon/VERDE_me.bin"); |
| 52 | MODULE_FIRMWARE("radeon/VERDE_ce.bin"); | 54 | MODULE_FIRMWARE("radeon/VERDE_ce.bin"); |
| 53 | MODULE_FIRMWARE("radeon/VERDE_mc.bin"); | 55 | MODULE_FIRMWARE("radeon/VERDE_mc.bin"); |
| 56 | MODULE_FIRMWARE("radeon/VERDE_mc2.bin"); | ||
| 54 | MODULE_FIRMWARE("radeon/VERDE_rlc.bin"); | 57 | MODULE_FIRMWARE("radeon/VERDE_rlc.bin"); |
| 55 | MODULE_FIRMWARE("radeon/VERDE_smc.bin"); | 58 | MODULE_FIRMWARE("radeon/VERDE_smc.bin"); |
| 56 | MODULE_FIRMWARE("radeon/OLAND_pfp.bin"); | 59 | MODULE_FIRMWARE("radeon/OLAND_pfp.bin"); |
| 57 | MODULE_FIRMWARE("radeon/OLAND_me.bin"); | 60 | MODULE_FIRMWARE("radeon/OLAND_me.bin"); |
| 58 | MODULE_FIRMWARE("radeon/OLAND_ce.bin"); | 61 | MODULE_FIRMWARE("radeon/OLAND_ce.bin"); |
| 59 | MODULE_FIRMWARE("radeon/OLAND_mc.bin"); | 62 | MODULE_FIRMWARE("radeon/OLAND_mc.bin"); |
| 63 | MODULE_FIRMWARE("radeon/OLAND_mc2.bin"); | ||
| 60 | MODULE_FIRMWARE("radeon/OLAND_rlc.bin"); | 64 | MODULE_FIRMWARE("radeon/OLAND_rlc.bin"); |
| 61 | MODULE_FIRMWARE("radeon/OLAND_smc.bin"); | 65 | MODULE_FIRMWARE("radeon/OLAND_smc.bin"); |
| 62 | MODULE_FIRMWARE("radeon/HAINAN_pfp.bin"); | 66 | MODULE_FIRMWARE("radeon/HAINAN_pfp.bin"); |
| 63 | MODULE_FIRMWARE("radeon/HAINAN_me.bin"); | 67 | MODULE_FIRMWARE("radeon/HAINAN_me.bin"); |
| 64 | MODULE_FIRMWARE("radeon/HAINAN_ce.bin"); | 68 | MODULE_FIRMWARE("radeon/HAINAN_ce.bin"); |
| 65 | MODULE_FIRMWARE("radeon/HAINAN_mc.bin"); | 69 | MODULE_FIRMWARE("radeon/HAINAN_mc.bin"); |
| 70 | MODULE_FIRMWARE("radeon/HAINAN_mc2.bin"); | ||
| 66 | MODULE_FIRMWARE("radeon/HAINAN_rlc.bin"); | 71 | MODULE_FIRMWARE("radeon/HAINAN_rlc.bin"); |
| 67 | MODULE_FIRMWARE("radeon/HAINAN_smc.bin"); | 72 | MODULE_FIRMWARE("radeon/HAINAN_smc.bin"); |
| 68 | 73 | ||
| @@ -1467,36 +1472,33 @@ int si_mc_load_microcode(struct radeon_device *rdev) | |||
| 1467 | const __be32 *fw_data; | 1472 | const __be32 *fw_data; |
| 1468 | u32 running, blackout = 0; | 1473 | u32 running, blackout = 0; |
| 1469 | u32 *io_mc_regs; | 1474 | u32 *io_mc_regs; |
| 1470 | int i, ucode_size, regs_size; | 1475 | int i, regs_size, ucode_size; |
| 1471 | 1476 | ||
| 1472 | if (!rdev->mc_fw) | 1477 | if (!rdev->mc_fw) |
| 1473 | return -EINVAL; | 1478 | return -EINVAL; |
| 1474 | 1479 | ||
| 1480 | ucode_size = rdev->mc_fw->size / 4; | ||
| 1481 | |||
| 1475 | switch (rdev->family) { | 1482 | switch (rdev->family) { |
| 1476 | case CHIP_TAHITI: | 1483 | case CHIP_TAHITI: |
| 1477 | io_mc_regs = (u32 *)&tahiti_io_mc_regs; | 1484 | io_mc_regs = (u32 *)&tahiti_io_mc_regs; |
| 1478 | ucode_size = SI_MC_UCODE_SIZE; | ||
| 1479 | regs_size = TAHITI_IO_MC_REGS_SIZE; | 1485 | regs_size = TAHITI_IO_MC_REGS_SIZE; |
| 1480 | break; | 1486 | break; |
| 1481 | case CHIP_PITCAIRN: | 1487 | case CHIP_PITCAIRN: |
| 1482 | io_mc_regs = (u32 *)&pitcairn_io_mc_regs; | 1488 | io_mc_regs = (u32 *)&pitcairn_io_mc_regs; |
| 1483 | ucode_size = SI_MC_UCODE_SIZE; | ||
| 1484 | regs_size = TAHITI_IO_MC_REGS_SIZE; | 1489 | regs_size = TAHITI_IO_MC_REGS_SIZE; |
| 1485 | break; | 1490 | break; |
| 1486 | case CHIP_VERDE: | 1491 | case CHIP_VERDE: |
| 1487 | default: | 1492 | default: |
| 1488 | io_mc_regs = (u32 *)&verde_io_mc_regs; | 1493 | io_mc_regs = (u32 *)&verde_io_mc_regs; |
| 1489 | ucode_size = SI_MC_UCODE_SIZE; | ||
| 1490 | regs_size = TAHITI_IO_MC_REGS_SIZE; | 1494 | regs_size = TAHITI_IO_MC_REGS_SIZE; |
| 1491 | break; | 1495 | break; |
| 1492 | case CHIP_OLAND: | 1496 | case CHIP_OLAND: |
| 1493 | io_mc_regs = (u32 *)&oland_io_mc_regs; | 1497 | io_mc_regs = (u32 *)&oland_io_mc_regs; |
| 1494 | ucode_size = OLAND_MC_UCODE_SIZE; | ||
| 1495 | regs_size = TAHITI_IO_MC_REGS_SIZE; | 1498 | regs_size = TAHITI_IO_MC_REGS_SIZE; |
| 1496 | break; | 1499 | break; |
| 1497 | case CHIP_HAINAN: | 1500 | case CHIP_HAINAN: |
| 1498 | io_mc_regs = (u32 *)&hainan_io_mc_regs; | 1501 | io_mc_regs = (u32 *)&hainan_io_mc_regs; |
| 1499 | ucode_size = OLAND_MC_UCODE_SIZE; | ||
| 1500 | regs_size = TAHITI_IO_MC_REGS_SIZE; | 1502 | regs_size = TAHITI_IO_MC_REGS_SIZE; |
| 1501 | break; | 1503 | break; |
| 1502 | } | 1504 | } |
| @@ -1552,7 +1554,7 @@ static int si_init_microcode(struct radeon_device *rdev) | |||
| 1552 | const char *chip_name; | 1554 | const char *chip_name; |
| 1553 | const char *rlc_chip_name; | 1555 | const char *rlc_chip_name; |
| 1554 | size_t pfp_req_size, me_req_size, ce_req_size, rlc_req_size, mc_req_size; | 1556 | size_t pfp_req_size, me_req_size, ce_req_size, rlc_req_size, mc_req_size; |
| 1555 | size_t smc_req_size; | 1557 | size_t smc_req_size, mc2_req_size; |
| 1556 | char fw_name[30]; | 1558 | char fw_name[30]; |
| 1557 | int err; | 1559 | int err; |
| 1558 | 1560 | ||
| @@ -1567,6 +1569,7 @@ static int si_init_microcode(struct radeon_device *rdev) | |||
| 1567 | ce_req_size = SI_CE_UCODE_SIZE * 4; | 1569 | ce_req_size = SI_CE_UCODE_SIZE * 4; |
| 1568 | rlc_req_size = SI_RLC_UCODE_SIZE * 4; | 1570 | rlc_req_size = SI_RLC_UCODE_SIZE * 4; |
| 1569 | mc_req_size = SI_MC_UCODE_SIZE * 4; | 1571 | mc_req_size = SI_MC_UCODE_SIZE * 4; |
| 1572 | mc2_req_size = TAHITI_MC_UCODE_SIZE * 4; | ||
| 1570 | smc_req_size = ALIGN(TAHITI_SMC_UCODE_SIZE, 4); | 1573 | smc_req_size = ALIGN(TAHITI_SMC_UCODE_SIZE, 4); |
| 1571 | break; | 1574 | break; |
| 1572 | case CHIP_PITCAIRN: | 1575 | case CHIP_PITCAIRN: |
| @@ -1577,6 +1580,7 @@ static int si_init_microcode(struct radeon_device *rdev) | |||
| 1577 | ce_req_size = SI_CE_UCODE_SIZE * 4; | 1580 | ce_req_size = SI_CE_UCODE_SIZE * 4; |
| 1578 | rlc_req_size = SI_RLC_UCODE_SIZE * 4; | 1581 | rlc_req_size = SI_RLC_UCODE_SIZE * 4; |
| 1579 | mc_req_size = SI_MC_UCODE_SIZE * 4; | 1582 | mc_req_size = SI_MC_UCODE_SIZE * 4; |
| 1583 | mc2_req_size = PITCAIRN_MC_UCODE_SIZE * 4; | ||
| 1580 | smc_req_size = ALIGN(PITCAIRN_SMC_UCODE_SIZE, 4); | 1584 | smc_req_size = ALIGN(PITCAIRN_SMC_UCODE_SIZE, 4); |
| 1581 | break; | 1585 | break; |
| 1582 | case CHIP_VERDE: | 1586 | case CHIP_VERDE: |
| @@ -1587,6 +1591,7 @@ static int si_init_microcode(struct radeon_device *rdev) | |||
| 1587 | ce_req_size = SI_CE_UCODE_SIZE * 4; | 1591 | ce_req_size = SI_CE_UCODE_SIZE * 4; |
| 1588 | rlc_req_size = SI_RLC_UCODE_SIZE * 4; | 1592 | rlc_req_size = SI_RLC_UCODE_SIZE * 4; |
| 1589 | mc_req_size = SI_MC_UCODE_SIZE * 4; | 1593 | mc_req_size = SI_MC_UCODE_SIZE * 4; |
| 1594 | mc2_req_size = VERDE_MC_UCODE_SIZE * 4; | ||
| 1590 | smc_req_size = ALIGN(VERDE_SMC_UCODE_SIZE, 4); | 1595 | smc_req_size = ALIGN(VERDE_SMC_UCODE_SIZE, 4); |
| 1591 | break; | 1596 | break; |
| 1592 | case CHIP_OLAND: | 1597 | case CHIP_OLAND: |
| @@ -1596,7 +1601,7 @@ static int si_init_microcode(struct radeon_device *rdev) | |||
| 1596 | me_req_size = SI_PM4_UCODE_SIZE * 4; | 1601 | me_req_size = SI_PM4_UCODE_SIZE * 4; |
| 1597 | ce_req_size = SI_CE_UCODE_SIZE * 4; | 1602 | ce_req_size = SI_CE_UCODE_SIZE * 4; |
| 1598 | rlc_req_size = SI_RLC_UCODE_SIZE * 4; | 1603 | rlc_req_size = SI_RLC_UCODE_SIZE * 4; |
| 1599 | mc_req_size = OLAND_MC_UCODE_SIZE * 4; | 1604 | mc_req_size = mc2_req_size = OLAND_MC_UCODE_SIZE * 4; |
| 1600 | smc_req_size = ALIGN(OLAND_SMC_UCODE_SIZE, 4); | 1605 | smc_req_size = ALIGN(OLAND_SMC_UCODE_SIZE, 4); |
| 1601 | break; | 1606 | break; |
| 1602 | case CHIP_HAINAN: | 1607 | case CHIP_HAINAN: |
| @@ -1606,7 +1611,7 @@ static int si_init_microcode(struct radeon_device *rdev) | |||
| 1606 | me_req_size = SI_PM4_UCODE_SIZE * 4; | 1611 | me_req_size = SI_PM4_UCODE_SIZE * 4; |
| 1607 | ce_req_size = SI_CE_UCODE_SIZE * 4; | 1612 | ce_req_size = SI_CE_UCODE_SIZE * 4; |
| 1608 | rlc_req_size = SI_RLC_UCODE_SIZE * 4; | 1613 | rlc_req_size = SI_RLC_UCODE_SIZE * 4; |
| 1609 | mc_req_size = OLAND_MC_UCODE_SIZE * 4; | 1614 | mc_req_size = mc2_req_size = OLAND_MC_UCODE_SIZE * 4; |
| 1610 | smc_req_size = ALIGN(HAINAN_SMC_UCODE_SIZE, 4); | 1615 | smc_req_size = ALIGN(HAINAN_SMC_UCODE_SIZE, 4); |
| 1611 | break; | 1616 | break; |
| 1612 | default: BUG(); | 1617 | default: BUG(); |
| @@ -1659,16 +1664,22 @@ static int si_init_microcode(struct radeon_device *rdev) | |||
| 1659 | err = -EINVAL; | 1664 | err = -EINVAL; |
| 1660 | } | 1665 | } |
| 1661 | 1666 | ||
| 1662 | snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); | 1667 | snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc2.bin", chip_name); |
| 1663 | err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev); | 1668 | err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev); |
| 1664 | if (err) | 1669 | if (err) { |
| 1665 | goto out; | 1670 | snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); |
| 1666 | if (rdev->mc_fw->size != mc_req_size) { | 1671 | err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev); |
| 1672 | if (err) | ||
| 1673 | goto out; | ||
| 1674 | } | ||
| 1675 | if ((rdev->mc_fw->size != mc_req_size) && | ||
| 1676 | (rdev->mc_fw->size != mc2_req_size)) { | ||
| 1667 | printk(KERN_ERR | 1677 | printk(KERN_ERR |
| 1668 | "si_mc: Bogus length %zu in firmware \"%s\"\n", | 1678 | "si_mc: Bogus length %zu in firmware \"%s\"\n", |
| 1669 | rdev->mc_fw->size, fw_name); | 1679 | rdev->mc_fw->size, fw_name); |
| 1670 | err = -EINVAL; | 1680 | err = -EINVAL; |
| 1671 | } | 1681 | } |
| 1682 | DRM_INFO("%s: %zu bytes\n", fw_name, rdev->mc_fw->size); | ||
| 1672 | 1683 | ||
| 1673 | snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name); | 1684 | snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name); |
| 1674 | err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev); | 1685 | err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev); |
diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c index d536ed381fbd..005c19bd92df 100644 --- a/drivers/gpu/drm/tegra/dpaux.c +++ b/drivers/gpu/drm/tegra/dpaux.c | |||
| @@ -99,55 +99,73 @@ static void tegra_dpaux_read_fifo(struct tegra_dpaux *dpaux, u8 *buffer, | |||
| 99 | static ssize_t tegra_dpaux_transfer(struct drm_dp_aux *aux, | 99 | static ssize_t tegra_dpaux_transfer(struct drm_dp_aux *aux, |
| 100 | struct drm_dp_aux_msg *msg) | 100 | struct drm_dp_aux_msg *msg) |
| 101 | { | 101 | { |
| 102 | unsigned long value = DPAUX_DP_AUXCTL_TRANSACTREQ; | ||
| 103 | unsigned long timeout = msecs_to_jiffies(250); | 102 | unsigned long timeout = msecs_to_jiffies(250); |
| 104 | struct tegra_dpaux *dpaux = to_dpaux(aux); | 103 | struct tegra_dpaux *dpaux = to_dpaux(aux); |
| 105 | unsigned long status; | 104 | unsigned long status; |
| 106 | ssize_t ret = 0; | 105 | ssize_t ret = 0; |
| 106 | u32 value; | ||
| 107 | 107 | ||
| 108 | if (msg->size < 1 || msg->size > 16) | 108 | /* Tegra has 4x4 byte DP AUX transmit and receive FIFOs. */ |
| 109 | if (msg->size > 16) | ||
| 109 | return -EINVAL; | 110 | return -EINVAL; |
| 110 | 111 | ||
| 111 | tegra_dpaux_writel(dpaux, msg->address, DPAUX_DP_AUXADDR); | 112 | /* |
| 113 | * Allow zero-sized messages only for I2C, in which case they specify | ||
| 114 | * address-only transactions. | ||
| 115 | */ | ||
| 116 | if (msg->size < 1) { | ||
| 117 | switch (msg->request & ~DP_AUX_I2C_MOT) { | ||
| 118 | case DP_AUX_I2C_WRITE: | ||
| 119 | case DP_AUX_I2C_READ: | ||
| 120 | value = DPAUX_DP_AUXCTL_CMD_ADDRESS_ONLY; | ||
| 121 | break; | ||
| 122 | |||
| 123 | default: | ||
| 124 | return -EINVAL; | ||
| 125 | } | ||
| 126 | } else { | ||
| 127 | /* For non-zero-sized messages, set the CMDLEN field. */ | ||
| 128 | value = DPAUX_DP_AUXCTL_CMDLEN(msg->size - 1); | ||
| 129 | } | ||
| 112 | 130 | ||
| 113 | switch (msg->request & ~DP_AUX_I2C_MOT) { | 131 | switch (msg->request & ~DP_AUX_I2C_MOT) { |
| 114 | case DP_AUX_I2C_WRITE: | 132 | case DP_AUX_I2C_WRITE: |
| 115 | if (msg->request & DP_AUX_I2C_MOT) | 133 | if (msg->request & DP_AUX_I2C_MOT) |
| 116 | value = DPAUX_DP_AUXCTL_CMD_MOT_WR; | 134 | value |= DPAUX_DP_AUXCTL_CMD_MOT_WR; |
| 117 | else | 135 | else |
| 118 | value = DPAUX_DP_AUXCTL_CMD_I2C_WR; | 136 | value |= DPAUX_DP_AUXCTL_CMD_I2C_WR; |
| 119 | 137 | ||
| 120 | break; | 138 | break; |
| 121 | 139 | ||
| 122 | case DP_AUX_I2C_READ: | 140 | case DP_AUX_I2C_READ: |
| 123 | if (msg->request & DP_AUX_I2C_MOT) | 141 | if (msg->request & DP_AUX_I2C_MOT) |
| 124 | value = DPAUX_DP_AUXCTL_CMD_MOT_RD; | 142 | value |= DPAUX_DP_AUXCTL_CMD_MOT_RD; |
| 125 | else | 143 | else |
| 126 | value = DPAUX_DP_AUXCTL_CMD_I2C_RD; | 144 | value |= DPAUX_DP_AUXCTL_CMD_I2C_RD; |
| 127 | 145 | ||
| 128 | break; | 146 | break; |
| 129 | 147 | ||
| 130 | case DP_AUX_I2C_STATUS: | 148 | case DP_AUX_I2C_STATUS: |
| 131 | if (msg->request & DP_AUX_I2C_MOT) | 149 | if (msg->request & DP_AUX_I2C_MOT) |
| 132 | value = DPAUX_DP_AUXCTL_CMD_MOT_RQ; | 150 | value |= DPAUX_DP_AUXCTL_CMD_MOT_RQ; |
| 133 | else | 151 | else |
| 134 | value = DPAUX_DP_AUXCTL_CMD_I2C_RQ; | 152 | value |= DPAUX_DP_AUXCTL_CMD_I2C_RQ; |
| 135 | 153 | ||
| 136 | break; | 154 | break; |
| 137 | 155 | ||
| 138 | case DP_AUX_NATIVE_WRITE: | 156 | case DP_AUX_NATIVE_WRITE: |
| 139 | value = DPAUX_DP_AUXCTL_CMD_AUX_WR; | 157 | value |= DPAUX_DP_AUXCTL_CMD_AUX_WR; |
| 140 | break; | 158 | break; |
| 141 | 159 | ||
| 142 | case DP_AUX_NATIVE_READ: | 160 | case DP_AUX_NATIVE_READ: |
| 143 | value = DPAUX_DP_AUXCTL_CMD_AUX_RD; | 161 | value |= DPAUX_DP_AUXCTL_CMD_AUX_RD; |
| 144 | break; | 162 | break; |
| 145 | 163 | ||
| 146 | default: | 164 | default: |
| 147 | return -EINVAL; | 165 | return -EINVAL; |
| 148 | } | 166 | } |
| 149 | 167 | ||
| 150 | value |= DPAUX_DP_AUXCTL_CMDLEN(msg->size - 1); | 168 | tegra_dpaux_writel(dpaux, msg->address, DPAUX_DP_AUXADDR); |
| 151 | tegra_dpaux_writel(dpaux, value, DPAUX_DP_AUXCTL); | 169 | tegra_dpaux_writel(dpaux, value, DPAUX_DP_AUXCTL); |
| 152 | 170 | ||
| 153 | if ((msg->request & DP_AUX_I2C_READ) == 0) { | 171 | if ((msg->request & DP_AUX_I2C_READ) == 0) { |
| @@ -198,7 +216,7 @@ static ssize_t tegra_dpaux_transfer(struct drm_dp_aux *aux, | |||
| 198 | break; | 216 | break; |
| 199 | } | 217 | } |
| 200 | 218 | ||
| 201 | if (msg->reply == DP_AUX_NATIVE_REPLY_ACK) { | 219 | if ((msg->size > 0) && (msg->reply == DP_AUX_NATIVE_REPLY_ACK)) { |
| 202 | if (msg->request & DP_AUX_I2C_READ) { | 220 | if (msg->request & DP_AUX_I2C_READ) { |
| 203 | size_t count = value & DPAUX_DP_AUXSTAT_REPLY_MASK; | 221 | size_t count = value & DPAUX_DP_AUXSTAT_REPLY_MASK; |
| 204 | 222 | ||
diff --git a/drivers/gpu/drm/tegra/dpaux.h b/drivers/gpu/drm/tegra/dpaux.h index 4f5bf10fdff9..806e245ca787 100644 --- a/drivers/gpu/drm/tegra/dpaux.h +++ b/drivers/gpu/drm/tegra/dpaux.h | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #define DPAUX_DP_AUXCTL_CMD_I2C_RQ (2 << 12) | 32 | #define DPAUX_DP_AUXCTL_CMD_I2C_RQ (2 << 12) |
| 33 | #define DPAUX_DP_AUXCTL_CMD_I2C_RD (1 << 12) | 33 | #define DPAUX_DP_AUXCTL_CMD_I2C_RD (1 << 12) |
| 34 | #define DPAUX_DP_AUXCTL_CMD_I2C_WR (0 << 12) | 34 | #define DPAUX_DP_AUXCTL_CMD_I2C_WR (0 << 12) |
| 35 | #define DPAUX_DP_AUXCTL_CMD_ADDRESS_ONLY (1 << 8) | ||
| 35 | #define DPAUX_DP_AUXCTL_CMDLEN(x) ((x) & 0xff) | 36 | #define DPAUX_DP_AUXCTL_CMDLEN(x) ((x) & 0xff) |
| 36 | 37 | ||
| 37 | #define DPAUX_DP_AUXSTAT 0x31 | 38 | #define DPAUX_DP_AUXSTAT 0x31 |
diff --git a/drivers/gpu/host1x/hw/intr_hw.c b/drivers/gpu/host1x/hw/intr_hw.c index db9017adfe2b..498b37e39058 100644 --- a/drivers/gpu/host1x/hw/intr_hw.c +++ b/drivers/gpu/host1x/hw/intr_hw.c | |||
| @@ -47,7 +47,7 @@ static irqreturn_t syncpt_thresh_isr(int irq, void *dev_id) | |||
| 47 | unsigned long reg; | 47 | unsigned long reg; |
| 48 | int i, id; | 48 | int i, id; |
| 49 | 49 | ||
| 50 | for (i = 0; i <= BIT_WORD(host->info->nb_pts); i++) { | 50 | for (i = 0; i < DIV_ROUND_UP(host->info->nb_pts, 32); i++) { |
| 51 | reg = host1x_sync_readl(host, | 51 | reg = host1x_sync_readl(host, |
| 52 | HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(i)); | 52 | HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(i)); |
| 53 | for_each_set_bit(id, ®, BITS_PER_LONG) { | 53 | for_each_set_bit(id, ®, BITS_PER_LONG) { |
| @@ -64,7 +64,7 @@ static void _host1x_intr_disable_all_syncpt_intrs(struct host1x *host) | |||
| 64 | { | 64 | { |
| 65 | u32 i; | 65 | u32 i; |
| 66 | 66 | ||
| 67 | for (i = 0; i <= BIT_WORD(host->info->nb_pts); ++i) { | 67 | for (i = 0; i < DIV_ROUND_UP(host->info->nb_pts, 32); ++i) { |
| 68 | host1x_sync_writel(host, 0xffffffffu, | 68 | host1x_sync_writel(host, 0xffffffffu, |
| 69 | HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(i)); | 69 | HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(i)); |
| 70 | host1x_sync_writel(host, 0xffffffffu, | 70 | host1x_sync_writel(host, 0xffffffffu, |
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index 0bb34ca2ad2b..36a5febac2a6 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h | |||
| @@ -125,7 +125,6 @@ struct drm_connector_helper_funcs { | |||
| 125 | struct drm_encoder *(*best_encoder)(struct drm_connector *connector); | 125 | struct drm_encoder *(*best_encoder)(struct drm_connector *connector); |
| 126 | }; | 126 | }; |
| 127 | 127 | ||
| 128 | extern int drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, uint32_t maxY); | ||
| 129 | extern void drm_helper_disable_unused_functions(struct drm_device *dev); | 128 | extern void drm_helper_disable_unused_functions(struct drm_device *dev); |
| 130 | extern int drm_crtc_helper_set_config(struct drm_mode_set *set); | 129 | extern int drm_crtc_helper_set_config(struct drm_mode_set *set); |
| 131 | extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, | 130 | extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, |
| @@ -161,6 +160,11 @@ static inline void drm_connector_helper_add(struct drm_connector *connector, | |||
| 161 | } | 160 | } |
| 162 | 161 | ||
| 163 | extern void drm_helper_resume_force_mode(struct drm_device *dev); | 162 | extern void drm_helper_resume_force_mode(struct drm_device *dev); |
| 163 | |||
| 164 | /* drm_probe_helper.c */ | ||
| 165 | extern int drm_helper_probe_single_connector_modes(struct drm_connector | ||
| 166 | *connector, uint32_t maxX, | ||
| 167 | uint32_t maxY); | ||
| 164 | extern void drm_kms_helper_poll_init(struct drm_device *dev); | 168 | extern void drm_kms_helper_poll_init(struct drm_device *dev); |
| 165 | extern void drm_kms_helper_poll_fini(struct drm_device *dev); | 169 | extern void drm_kms_helper_poll_fini(struct drm_device *dev); |
| 166 | extern bool drm_helper_hpd_irq_event(struct drm_device *dev); | 170 | extern bool drm_helper_hpd_irq_event(struct drm_device *dev); |
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index b4f58914bf7d..cfcacec5b89d 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h | |||
| @@ -456,6 +456,10 @@ struct drm_dp_aux_msg { | |||
| 456 | * transactions. The drm_dp_aux_register_i2c_bus() function registers an | 456 | * transactions. The drm_dp_aux_register_i2c_bus() function registers an |
| 457 | * I2C adapter that can be passed to drm_probe_ddc(). Upon removal, drivers | 457 | * I2C adapter that can be passed to drm_probe_ddc(). Upon removal, drivers |
| 458 | * should call drm_dp_aux_unregister_i2c_bus() to remove the I2C adapter. | 458 | * should call drm_dp_aux_unregister_i2c_bus() to remove the I2C adapter. |
| 459 | * | ||
| 460 | * Note that the aux helper code assumes that the .transfer() function | ||
| 461 | * only modifies the reply field of the drm_dp_aux_msg structure. The | ||
| 462 | * retry logic and i2c helpers assume this is the case. | ||
| 459 | */ | 463 | */ |
| 460 | struct drm_dp_aux { | 464 | struct drm_dp_aux { |
| 461 | const char *name; | 465 | const char *name; |
diff --git a/include/uapi/drm/tegra_drm.h b/include/uapi/drm/tegra_drm.h index b042b48495d9..b75482112428 100644 --- a/include/uapi/drm/tegra_drm.h +++ b/include/uapi/drm/tegra_drm.h | |||
| @@ -120,7 +120,6 @@ struct drm_tegra_submit { | |||
| 120 | __u32 num_waitchks; | 120 | __u32 num_waitchks; |
| 121 | __u32 waitchk_mask; | 121 | __u32 waitchk_mask; |
| 122 | __u32 timeout; | 122 | __u32 timeout; |
| 123 | __u32 pad; | ||
| 124 | __u64 syncpts; | 123 | __u64 syncpts; |
| 125 | __u64 cmdbufs; | 124 | __u64 cmdbufs; |
| 126 | __u64 relocs; | 125 | __u64 relocs; |
