diff options
author | Dave Airlie <airlied@redhat.com> | 2010-05-07 02:42:51 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-05-18 03:40:11 -0400 |
commit | eb1f8e4f3be898df808e2dfc131099f5831d491d (patch) | |
tree | 9e5807824c60601f23016f3a2e82f8de10f7435a | |
parent | 0ddfa7d574e0f3a7510b0be6c8ed807af017223f (diff) |
drm/fbdev: rework output polling to be back in the core. (v4)
After thinking it over a lot it made more sense for the core to deal with
the output polling especially so it can notify X.
v2: drop plans for fake connector - per Michel's comments - fix X patch sent to xorg-devel, add intel polled/hpd setting, add initial nouveau polled/hpd settings.
v3: add config lock take inside polling, add intel/nouveau poll init/fini calls
v4: config lock was a bit agressive, only needed around connector list reading.
otherwise it could re-enter.
glisse: discard drm_helper_hpd_irq_event
v3: Reviewed-by: Michel Dänzer <michel@daenzer.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
26 files changed, 211 insertions, 157 deletions
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index be5aa7d5206b..2583ddfcc33e 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig | |||
@@ -9,6 +9,7 @@ menuconfig DRM | |||
9 | depends on (AGP || AGP=n) && PCI && !EMULATED_CMPXCHG && MMU | 9 | depends on (AGP || AGP=n) && PCI && !EMULATED_CMPXCHG && MMU |
10 | select I2C | 10 | select I2C |
11 | select I2C_ALGOBIT | 11 | select I2C_ALGOBIT |
12 | select SLOW_WORK | ||
12 | help | 13 | help |
13 | Kernel-level support for the Direct Rendering Infrastructure (DRI) | 14 | Kernel-level support for the Direct Rendering Infrastructure (DRI) |
14 | introduced in XFree86 4.0. If you say Y here, you need to select | 15 | introduced in XFree86 4.0. If you say Y here, you need to select |
@@ -23,7 +24,6 @@ config DRM_KMS_HELPER | |||
23 | depends on DRM | 24 | depends on DRM |
24 | select FB | 25 | select FB |
25 | select FRAMEBUFFER_CONSOLE if !EMBEDDED | 26 | select FRAMEBUFFER_CONSOLE if !EMBEDDED |
26 | select SLOW_WORK | ||
27 | help | 27 | help |
28 | FB and CRTC helpers for KMS drivers. | 28 | FB and CRTC helpers for KMS drivers. |
29 | 29 | ||
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index b142ac260d97..764401951041 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
@@ -807,3 +807,98 @@ int drm_helper_resume_force_mode(struct drm_device *dev) | |||
807 | return 0; | 807 | return 0; |
808 | } | 808 | } |
809 | EXPORT_SYMBOL(drm_helper_resume_force_mode); | 809 | EXPORT_SYMBOL(drm_helper_resume_force_mode); |
810 | |||
811 | static struct slow_work_ops output_poll_ops; | ||
812 | |||
813 | #define DRM_OUTPUT_POLL_PERIOD (10*HZ) | ||
814 | static void output_poll_execute(struct slow_work *work) | ||
815 | { | ||
816 | struct delayed_slow_work *delayed_work = container_of(work, struct delayed_slow_work, work); | ||
817 | struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_slow_work); | ||
818 | struct drm_connector *connector; | ||
819 | enum drm_connector_status old_status, status; | ||
820 | bool repoll = false, changed = false; | ||
821 | int ret; | ||
822 | |||
823 | mutex_lock(&dev->mode_config.mutex); | ||
824 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
825 | |||
826 | /* if this is HPD or polled don't check it - | ||
827 | TV out for instance */ | ||
828 | if (!connector->polled) | ||
829 | continue; | ||
830 | |||
831 | else if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT)) | ||
832 | repoll = true; | ||
833 | |||
834 | old_status = connector->status; | ||
835 | /* if we are connected and don't want to poll for disconnect | ||
836 | skip it */ | ||
837 | if (old_status == connector_status_connected && | ||
838 | !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT) && | ||
839 | !(connector->polled & DRM_CONNECTOR_POLL_HPD)) | ||
840 | continue; | ||
841 | |||
842 | status = connector->funcs->detect(connector); | ||
843 | if (old_status != status) | ||
844 | changed = true; | ||
845 | } | ||
846 | |||
847 | mutex_unlock(&dev->mode_config.mutex); | ||
848 | |||
849 | if (changed) { | ||
850 | /* send a uevent + call fbdev */ | ||
851 | drm_sysfs_hotplug_event(dev); | ||
852 | if (dev->mode_config.funcs->output_poll_changed) | ||
853 | dev->mode_config.funcs->output_poll_changed(dev); | ||
854 | } | ||
855 | |||
856 | if (repoll) { | ||
857 | ret = delayed_slow_work_enqueue(delayed_work, DRM_OUTPUT_POLL_PERIOD); | ||
858 | if (ret) | ||
859 | DRM_ERROR("delayed enqueue failed %d\n", ret); | ||
860 | } | ||
861 | } | ||
862 | |||
863 | void drm_kms_helper_poll_init(struct drm_device *dev) | ||
864 | { | ||
865 | struct drm_connector *connector; | ||
866 | bool poll = false; | ||
867 | int ret; | ||
868 | |||
869 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
870 | if (connector->polled) | ||
871 | poll = true; | ||
872 | } | ||
873 | slow_work_register_user(THIS_MODULE); | ||
874 | delayed_slow_work_init(&dev->mode_config.output_poll_slow_work, | ||
875 | &output_poll_ops); | ||
876 | |||
877 | if (poll) { | ||
878 | ret = delayed_slow_work_enqueue(&dev->mode_config.output_poll_slow_work, DRM_OUTPUT_POLL_PERIOD); | ||
879 | if (ret) | ||
880 | DRM_ERROR("delayed enqueue failed %d\n", ret); | ||
881 | } | ||
882 | } | ||
883 | EXPORT_SYMBOL(drm_kms_helper_poll_init); | ||
884 | |||
885 | void drm_kms_helper_poll_fini(struct drm_device *dev) | ||
886 | { | ||
887 | delayed_slow_work_cancel(&dev->mode_config.output_poll_slow_work); | ||
888 | slow_work_unregister_user(THIS_MODULE); | ||
889 | } | ||
890 | EXPORT_SYMBOL(drm_kms_helper_poll_fini); | ||
891 | |||
892 | void drm_helper_hpd_irq_event(struct drm_device *dev) | ||
893 | { | ||
894 | if (!dev->mode_config.poll_enabled) | ||
895 | return; | ||
896 | delayed_slow_work_cancel(&dev->mode_config.output_poll_slow_work); | ||
897 | /* schedule a slow work asap */ | ||
898 | delayed_slow_work_enqueue(&dev->mode_config.output_poll_slow_work, 0); | ||
899 | } | ||
900 | EXPORT_SYMBOL(drm_helper_hpd_irq_event); | ||
901 | |||
902 | static struct slow_work_ops output_poll_ops = { | ||
903 | .execute = output_poll_execute, | ||
904 | }; | ||
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 5db4f47a0085..f7b8fca4bbbc 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c | |||
@@ -42,8 +42,6 @@ MODULE_LICENSE("GPL and additional rights"); | |||
42 | 42 | ||
43 | static LIST_HEAD(kernel_fb_helper_list); | 43 | static LIST_HEAD(kernel_fb_helper_list); |
44 | 44 | ||
45 | static struct slow_work_ops output_status_change_ops; | ||
46 | |||
47 | /* simple single crtc case helper function */ | 45 | /* simple single crtc case helper function */ |
48 | int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) | 46 | int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) |
49 | { | 47 | { |
@@ -425,19 +423,13 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper) | |||
425 | 423 | ||
426 | int drm_fb_helper_init(struct drm_device *dev, | 424 | int drm_fb_helper_init(struct drm_device *dev, |
427 | struct drm_fb_helper *fb_helper, | 425 | struct drm_fb_helper *fb_helper, |
428 | int crtc_count, int max_conn_count, | 426 | int crtc_count, int max_conn_count) |
429 | bool polled) | ||
430 | { | 427 | { |
431 | struct drm_crtc *crtc; | 428 | struct drm_crtc *crtc; |
432 | int ret = 0; | 429 | int ret = 0; |
433 | int i; | 430 | int i; |
434 | 431 | ||
435 | fb_helper->dev = dev; | 432 | fb_helper->dev = dev; |
436 | fb_helper->poll_enabled = polled; | ||
437 | |||
438 | slow_work_register_user(THIS_MODULE); | ||
439 | delayed_slow_work_init(&fb_helper->output_status_change_slow_work, | ||
440 | &output_status_change_ops); | ||
441 | 433 | ||
442 | INIT_LIST_HEAD(&fb_helper->kernel_fb_list); | 434 | INIT_LIST_HEAD(&fb_helper->kernel_fb_list); |
443 | 435 | ||
@@ -494,8 +486,6 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) | |||
494 | 486 | ||
495 | drm_fb_helper_crtc_free(fb_helper); | 487 | drm_fb_helper_crtc_free(fb_helper); |
496 | 488 | ||
497 | delayed_slow_work_cancel(&fb_helper->output_status_change_slow_work); | ||
498 | slow_work_unregister_user(THIS_MODULE); | ||
499 | } | 489 | } |
500 | EXPORT_SYMBOL(drm_fb_helper_fini); | 490 | EXPORT_SYMBOL(drm_fb_helper_fini); |
501 | 491 | ||
@@ -713,7 +703,7 @@ int drm_fb_helper_set_par(struct fb_info *info) | |||
713 | 703 | ||
714 | if (fb_helper->delayed_hotplug) { | 704 | if (fb_helper->delayed_hotplug) { |
715 | fb_helper->delayed_hotplug = false; | 705 | fb_helper->delayed_hotplug = false; |
716 | delayed_slow_work_enqueue(&fb_helper->output_status_change_slow_work, 0); | 706 | drm_fb_helper_hotplug_event(fb_helper); |
717 | } | 707 | } |
718 | return 0; | 708 | return 0; |
719 | } | 709 | } |
@@ -826,7 +816,7 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, | |||
826 | if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) { | 816 | if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) { |
827 | /* hmm everyone went away - assume VGA cable just fell out | 817 | /* hmm everyone went away - assume VGA cable just fell out |
828 | and will come back later. */ | 818 | and will come back later. */ |
829 | DRM_ERROR("Cannot find any crtc or sizes - going 1024x768\n"); | 819 | DRM_INFO("Cannot find any crtc or sizes - going 1024x768\n"); |
830 | sizes.fb_width = sizes.surface_width = 1024; | 820 | sizes.fb_width = sizes.surface_width = 1024; |
831 | sizes.fb_height = sizes.surface_height = 768; | 821 | sizes.fb_height = sizes.surface_height = 768; |
832 | } | 822 | } |
@@ -1292,12 +1282,7 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) | |||
1292 | * we shouldn't end up with no modes here. | 1282 | * we shouldn't end up with no modes here. |
1293 | */ | 1283 | */ |
1294 | if (count == 0) { | 1284 | if (count == 0) { |
1295 | if (fb_helper->poll_enabled) { | 1285 | printk(KERN_INFO "No connectors reported connected with modes\n"); |
1296 | delayed_slow_work_enqueue(&fb_helper->output_status_change_slow_work, | ||
1297 | 5*HZ); | ||
1298 | printk(KERN_INFO "No connectors reported connected with modes - started polling\n"); | ||
1299 | } else | ||
1300 | printk(KERN_INFO "No connectors reported connected with modes\n"); | ||
1301 | } | 1286 | } |
1302 | drm_setup_crtcs(fb_helper); | 1287 | drm_setup_crtcs(fb_helper); |
1303 | 1288 | ||
@@ -1305,71 +1290,16 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) | |||
1305 | } | 1290 | } |
1306 | EXPORT_SYMBOL(drm_fb_helper_initial_config); | 1291 | EXPORT_SYMBOL(drm_fb_helper_initial_config); |
1307 | 1292 | ||
1308 | /* we got a hotplug irq - need to update fbcon */ | 1293 | bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) |
1309 | void drm_helper_fb_hpd_irq_event(struct drm_fb_helper *fb_helper) | ||
1310 | { | ||
1311 | /* if we don't have the fbdev registered yet do nothing */ | ||
1312 | if (!fb_helper->fbdev) | ||
1313 | return; | ||
1314 | |||
1315 | /* schedule a slow work asap */ | ||
1316 | delayed_slow_work_enqueue(&fb_helper->output_status_change_slow_work, 0); | ||
1317 | } | ||
1318 | EXPORT_SYMBOL(drm_helper_fb_hpd_irq_event); | ||
1319 | |||
1320 | bool drm_helper_fb_hotplug_event(struct drm_fb_helper *fb_helper, bool polled) | ||
1321 | { | 1294 | { |
1322 | int count = 0; | 1295 | int count = 0; |
1323 | int ret; | ||
1324 | u32 max_width, max_height, bpp_sel; | 1296 | u32 max_width, max_height, bpp_sel; |
1325 | |||
1326 | if (!fb_helper->fb) | ||
1327 | return false; | ||
1328 | DRM_DEBUG_KMS("\n"); | ||
1329 | |||
1330 | max_width = fb_helper->fb->width; | ||
1331 | max_height = fb_helper->fb->height; | ||
1332 | bpp_sel = fb_helper->fb->bits_per_pixel; | ||
1333 | |||
1334 | count = drm_fb_helper_probe_connector_modes(fb_helper, max_width, | ||
1335 | max_height); | ||
1336 | if (fb_helper->poll_enabled && !polled) { | ||
1337 | if (count) { | ||
1338 | delayed_slow_work_cancel(&fb_helper->output_status_change_slow_work); | ||
1339 | } else { | ||
1340 | ret = delayed_slow_work_enqueue(&fb_helper->output_status_change_slow_work, 5*HZ); | ||
1341 | } | ||
1342 | } | ||
1343 | drm_setup_crtcs(fb_helper); | ||
1344 | |||
1345 | return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel); | ||
1346 | } | ||
1347 | EXPORT_SYMBOL(drm_helper_fb_hotplug_event); | ||
1348 | |||
1349 | /* | ||
1350 | * delayed work queue execution function | ||
1351 | * - check if fbdev is actually in use on the gpu | ||
1352 | * - if not set delayed flag and repoll if necessary | ||
1353 | * - check for connector status change | ||
1354 | * - repoll if 0 modes found | ||
1355 | *- call driver output status changed notifier | ||
1356 | */ | ||
1357 | static void output_status_change_execute(struct slow_work *work) | ||
1358 | { | ||
1359 | struct delayed_slow_work *delayed_work = container_of(work, struct delayed_slow_work, work); | ||
1360 | struct drm_fb_helper *fb_helper = container_of(delayed_work, struct drm_fb_helper, output_status_change_slow_work); | ||
1361 | struct drm_connector *connector; | ||
1362 | enum drm_connector_status old_status, status; | ||
1363 | bool repoll, changed = false; | ||
1364 | int ret; | ||
1365 | int i; | ||
1366 | bool bound = false, crtcs_bound = false; | 1297 | bool bound = false, crtcs_bound = false; |
1367 | struct drm_crtc *crtc; | 1298 | struct drm_crtc *crtc; |
1368 | 1299 | ||
1369 | repoll = fb_helper->poll_enabled; | 1300 | if (!fb_helper->fb) |
1301 | return false; | ||
1370 | 1302 | ||
1371 | /* first of all check the fbcon framebuffer is actually bound to any crtc */ | ||
1372 | /* take into account that no crtc at all maybe bound */ | ||
1373 | list_for_each_entry(crtc, &fb_helper->dev->mode_config.crtc_list, head) { | 1303 | list_for_each_entry(crtc, &fb_helper->dev->mode_config.crtc_list, head) { |
1374 | if (crtc->fb) | 1304 | if (crtc->fb) |
1375 | crtcs_bound = true; | 1305 | crtcs_bound = true; |
@@ -1377,38 +1307,21 @@ static void output_status_change_execute(struct slow_work *work) | |||
1377 | bound = true; | 1307 | bound = true; |
1378 | } | 1308 | } |
1379 | 1309 | ||
1380 | if (bound == false && crtcs_bound) { | 1310 | if (!bound && crtcs_bound) { |
1381 | fb_helper->delayed_hotplug = true; | 1311 | fb_helper->delayed_hotplug = true; |
1382 | goto requeue; | 1312 | return false; |
1383 | } | 1313 | } |
1314 | DRM_DEBUG_KMS("\n"); | ||
1384 | 1315 | ||
1385 | for (i = 0; i < fb_helper->connector_count; i++) { | 1316 | max_width = fb_helper->fb->width; |
1386 | connector = fb_helper->connector_info[i]->connector; | 1317 | max_height = fb_helper->fb->height; |
1387 | old_status = connector->status; | 1318 | bpp_sel = fb_helper->fb->bits_per_pixel; |
1388 | status = connector->funcs->detect(connector); | ||
1389 | if (old_status != status) { | ||
1390 | changed = true; | ||
1391 | } | ||
1392 | if (status == connector_status_connected && repoll) { | ||
1393 | DRM_DEBUG("%s is connected - stop polling\n", drm_get_connector_name(connector)); | ||
1394 | repoll = false; | ||
1395 | } | ||
1396 | } | ||
1397 | 1319 | ||
1398 | if (changed) { | 1320 | count = drm_fb_helper_probe_connector_modes(fb_helper, max_width, |
1399 | if (fb_helper->funcs->fb_output_status_changed) | 1321 | max_height); |
1400 | fb_helper->funcs->fb_output_status_changed(fb_helper); | 1322 | drm_setup_crtcs(fb_helper); |
1401 | } | ||
1402 | 1323 | ||
1403 | requeue: | 1324 | return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel); |
1404 | if (repoll) { | ||
1405 | ret = delayed_slow_work_enqueue(delayed_work, 5*HZ); | ||
1406 | if (ret) | ||
1407 | DRM_ERROR("delayed enqueue failed %d\n", ret); | ||
1408 | } | ||
1409 | } | 1325 | } |
1410 | 1326 | EXPORT_SYMBOL(drm_fb_helper_hotplug_event); | |
1411 | static struct slow_work_ops output_status_change_ops = { | ||
1412 | .execute = output_status_change_execute, | ||
1413 | }; | ||
1414 | 1327 | ||
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 52e468bbd5e4..8fe66ac4e1a5 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
@@ -1493,7 +1493,7 @@ static int i915_load_modeset_init(struct drm_device *dev, | |||
1493 | I915_WRITE(INSTPM, (1 << 5) | (1 << 21)); | 1493 | I915_WRITE(INSTPM, (1 << 5) | (1 << 21)); |
1494 | 1494 | ||
1495 | intel_fbdev_init(dev); | 1495 | intel_fbdev_init(dev); |
1496 | 1496 | drm_kms_helper_poll_init(dev); | |
1497 | return 0; | 1497 | return 0; |
1498 | 1498 | ||
1499 | destroy_ringbuffer: | 1499 | destroy_ringbuffer: |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index ed26b7b7376a..b034ea36731c 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -271,8 +271,7 @@ static void i915_hotplug_work_func(struct work_struct *work) | |||
271 | } | 271 | } |
272 | } | 272 | } |
273 | /* Just fire off a uevent and let userspace tell us what to do */ | 273 | /* Just fire off a uevent and let userspace tell us what to do */ |
274 | intelfb_hotplug(dev, false); | 274 | drm_helper_hpd_irq_event(dev); |
275 | drm_sysfs_hotplug_event(dev); | ||
276 | } | 275 | } |
277 | 276 | ||
278 | static void i915_handle_rps_change(struct drm_device *dev) | 277 | static void i915_handle_rps_change(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 26756cd34e3c..e16ac5a28c3c 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c | |||
@@ -577,5 +577,10 @@ void intel_crt_init(struct drm_device *dev) | |||
577 | 577 | ||
578 | drm_sysfs_connector_add(connector); | 578 | drm_sysfs_connector_add(connector); |
579 | 579 | ||
580 | if (I915_HAS_HOTPLUG(dev)) | ||
581 | connector->polled = DRM_CONNECTOR_POLL_HPD; | ||
582 | else | ||
583 | connector->polled = DRM_CONNECTOR_POLL_CONNECT; | ||
584 | |||
580 | dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS; | 585 | dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS; |
581 | } | 586 | } |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3836f56e842c..4d739a1b13ca 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -4959,6 +4959,7 @@ intel_user_framebuffer_create(struct drm_device *dev, | |||
4959 | 4959 | ||
4960 | static const struct drm_mode_config_funcs intel_mode_funcs = { | 4960 | static const struct drm_mode_config_funcs intel_mode_funcs = { |
4961 | .fb_create = intel_user_framebuffer_create, | 4961 | .fb_create = intel_user_framebuffer_create, |
4962 | .output_poll_changed = intel_fb_output_poll_changed, | ||
4962 | }; | 4963 | }; |
4963 | 4964 | ||
4964 | static struct drm_gem_object * | 4965 | static struct drm_gem_object * |
@@ -5346,6 +5347,7 @@ void intel_modeset_cleanup(struct drm_device *dev) | |||
5346 | 5347 | ||
5347 | mutex_lock(&dev->struct_mutex); | 5348 | mutex_lock(&dev->struct_mutex); |
5348 | 5349 | ||
5350 | drm_kms_helper_poll_fini(dev); | ||
5349 | intel_fbdev_fini(dev); | 5351 | intel_fbdev_fini(dev); |
5350 | 5352 | ||
5351 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | 5353 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index f6299bb788e5..6b1c9a27c27a 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -1392,6 +1392,8 @@ intel_dp_init(struct drm_device *dev, int output_reg) | |||
1392 | DRM_MODE_CONNECTOR_DisplayPort); | 1392 | DRM_MODE_CONNECTOR_DisplayPort); |
1393 | drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs); | 1393 | drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs); |
1394 | 1394 | ||
1395 | connector->polled = DRM_CONNECTOR_POLL_HPD; | ||
1396 | |||
1395 | if (output_reg == DP_A) | 1397 | if (output_reg == DP_A) |
1396 | intel_encoder->type = INTEL_OUTPUT_EDP; | 1398 | intel_encoder->type = INTEL_OUTPUT_EDP; |
1397 | else | 1399 | else |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 3230e8d2ea43..df931f787665 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -235,5 +235,5 @@ extern int intel_overlay_put_image(struct drm_device *dev, void *data, | |||
235 | extern int intel_overlay_attrs(struct drm_device *dev, void *data, | 235 | extern int intel_overlay_attrs(struct drm_device *dev, void *data, |
236 | struct drm_file *file_priv); | 236 | struct drm_file *file_priv); |
237 | 237 | ||
238 | void intelfb_hotplug(struct drm_device *dev, bool polled); | 238 | extern void intel_fb_output_poll_changed(struct drm_device *dev); |
239 | #endif /* __INTEL_DRV_H__ */ | 239 | #endif /* __INTEL_DRV_H__ */ |
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index 7f1eabbaa2bb..6f53cf7fbc50 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c | |||
@@ -207,12 +207,6 @@ static int intel_fb_find_or_create_single(struct drm_fb_helper *helper, | |||
207 | return new_fb; | 207 | return new_fb; |
208 | } | 208 | } |
209 | 209 | ||
210 | void intelfb_hotplug(struct drm_device *dev, bool polled) | ||
211 | { | ||
212 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
213 | drm_helper_fb_hpd_irq_event(&dev_priv->fbdev->helper); | ||
214 | } | ||
215 | |||
216 | static struct drm_fb_helper_funcs intel_fb_helper_funcs = { | 210 | static struct drm_fb_helper_funcs intel_fb_helper_funcs = { |
217 | .gamma_set = intel_crtc_fb_gamma_set, | 211 | .gamma_set = intel_crtc_fb_gamma_set, |
218 | .gamma_get = intel_crtc_fb_gamma_get, | 212 | .gamma_get = intel_crtc_fb_gamma_get, |
@@ -256,7 +250,7 @@ int intel_fbdev_init(struct drm_device *dev) | |||
256 | ifbdev->helper.funcs = &intel_fb_helper_funcs; | 250 | ifbdev->helper.funcs = &intel_fb_helper_funcs; |
257 | 251 | ||
258 | drm_fb_helper_init(dev, &ifbdev->helper, 2, | 252 | drm_fb_helper_init(dev, &ifbdev->helper, 2, |
259 | INTELFB_CONN_LIMIT, false); | 253 | INTELFB_CONN_LIMIT); |
260 | 254 | ||
261 | drm_fb_helper_single_add_all_connectors(&ifbdev->helper); | 255 | drm_fb_helper_single_add_all_connectors(&ifbdev->helper); |
262 | drm_fb_helper_initial_config(&ifbdev->helper, 32); | 256 | drm_fb_helper_initial_config(&ifbdev->helper, 32); |
@@ -274,3 +268,9 @@ void intel_fbdev_fini(struct drm_device *dev) | |||
274 | dev_priv->fbdev = NULL; | 268 | dev_priv->fbdev = NULL; |
275 | } | 269 | } |
276 | MODULE_LICENSE("GPL and additional rights"); | 270 | MODULE_LICENSE("GPL and additional rights"); |
271 | |||
272 | void intel_fb_output_poll_changed(struct drm_device *dev) | ||
273 | { | ||
274 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
275 | drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper); | ||
276 | } | ||
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 8a1c4eddc030..65727f0a79a3 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
@@ -237,6 +237,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) | |||
237 | 237 | ||
238 | intel_encoder->type = INTEL_OUTPUT_HDMI; | 238 | intel_encoder->type = INTEL_OUTPUT_HDMI; |
239 | 239 | ||
240 | connector->polled = DRM_CONNECTOR_POLL_HPD; | ||
240 | connector->interlace_allowed = 0; | 241 | connector->interlace_allowed = 0; |
241 | connector->doublescan_allowed = 0; | 242 | connector->doublescan_allowed = 0; |
242 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1); | 243 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1); |
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 42ceb15da689..ca372abc36cd 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
@@ -2244,6 +2244,7 @@ intel_sdvo_dvi_init(struct intel_encoder *intel_encoder, int device) | |||
2244 | } | 2244 | } |
2245 | 2245 | ||
2246 | connector = &intel_connector->base; | 2246 | connector = &intel_connector->base; |
2247 | connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; | ||
2247 | encoder->encoder_type = DRM_MODE_ENCODER_TMDS; | 2248 | encoder->encoder_type = DRM_MODE_ENCODER_TMDS; |
2248 | connector->connector_type = DRM_MODE_CONNECTOR_DVID; | 2249 | connector->connector_type = DRM_MODE_CONNECTOR_DVID; |
2249 | 2250 | ||
@@ -2310,6 +2311,7 @@ intel_sdvo_analog_init(struct intel_encoder *intel_encoder, int device) | |||
2310 | return false; | 2311 | return false; |
2311 | 2312 | ||
2312 | connector = &intel_connector->base; | 2313 | connector = &intel_connector->base; |
2314 | connector->polled = DRM_CONNECTOR_POLL_CONNECT; | ||
2313 | encoder->encoder_type = DRM_MODE_ENCODER_DAC; | 2315 | encoder->encoder_type = DRM_MODE_ENCODER_DAC; |
2314 | connector->connector_type = DRM_MODE_CONNECTOR_VGA; | 2316 | connector->connector_type = DRM_MODE_CONNECTOR_VGA; |
2315 | sdvo_connector = intel_connector->dev_priv; | 2317 | sdvo_connector = intel_connector->dev_priv; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 14afe1e47e57..7e663a79829f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c | |||
@@ -843,6 +843,7 @@ nouveau_connector_create(struct drm_device *dev, | |||
843 | 843 | ||
844 | switch (dcb->type) { | 844 | switch (dcb->type) { |
845 | case DCB_CONNECTOR_VGA: | 845 | case DCB_CONNECTOR_VGA: |
846 | connector->polled = DRM_CONNECTOR_POLL_CONNECT; | ||
846 | if (dev_priv->card_type >= NV_50) { | 847 | if (dev_priv->card_type >= NV_50) { |
847 | drm_connector_attach_property(connector, | 848 | drm_connector_attach_property(connector, |
848 | dev->mode_config.scaling_mode_property, | 849 | dev->mode_config.scaling_mode_property, |
@@ -854,6 +855,17 @@ nouveau_connector_create(struct drm_device *dev, | |||
854 | case DCB_CONNECTOR_TV_3: | 855 | case DCB_CONNECTOR_TV_3: |
855 | nv_connector->scaling_mode = DRM_MODE_SCALE_NONE; | 856 | nv_connector->scaling_mode = DRM_MODE_SCALE_NONE; |
856 | break; | 857 | break; |
858 | case DCB_CONNECTOR_DP: | ||
859 | case DCB_CONNECTOR_eDP: | ||
860 | case DCB_CONNECTOR_HDMI_0: | ||
861 | case DCB_CONNECTOR_HDMI_1: | ||
862 | case DCB_CONNECTOR_DVI_I: | ||
863 | case DCB_CONNECTOR_DVI_D: | ||
864 | if (dev_priv->card_type >= NV_50) | ||
865 | connector->polled = DRM_CONNECTOR_POLL_HPD; | ||
866 | else | ||
867 | connector->polled = DRM_CONNECTOR_POLL_CONNECT; | ||
868 | /* fall-through */ | ||
857 | default: | 869 | default: |
858 | nv_connector->scaling_mode = DRM_MODE_SCALE_FULLSCREEN; | 870 | nv_connector->scaling_mode = DRM_MODE_SCALE_FULLSCREEN; |
859 | 871 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 9d7928f40fdf..74e6b4ed12c0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c | |||
@@ -101,5 +101,6 @@ nouveau_user_framebuffer_create(struct drm_device *dev, | |||
101 | 101 | ||
102 | const struct drm_mode_config_funcs nouveau_mode_config_funcs = { | 102 | const struct drm_mode_config_funcs nouveau_mode_config_funcs = { |
103 | .fb_create = nouveau_user_framebuffer_create, | 103 | .fb_create = nouveau_user_framebuffer_create, |
104 | .output_poll_changed = nouveau_fbcon_output_poll_changed, | ||
104 | }; | 105 | }; |
105 | 106 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 2c2199329cc1..fd4a2df715e9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c | |||
@@ -326,15 +326,11 @@ nouveau_fbcon_find_or_create_single(struct drm_fb_helper *helper, | |||
326 | return new_fb; | 326 | return new_fb; |
327 | } | 327 | } |
328 | 328 | ||
329 | void nouveau_fbcon_hotplug(struct drm_device *dev) | 329 | void |
330 | nouveau_fbcon_output_poll_changed(struct drm_device *dev) | ||
330 | { | 331 | { |
331 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 332 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
332 | drm_helper_fb_hpd_irq_event(&dev_priv->nfbdev->helper); | 333 | drm_fb_helper_hotplug_event(&dev_priv->nfbdev->helper); |
333 | } | ||
334 | |||
335 | static void nouveau_fbcon_output_status_changed(struct drm_fb_helper *fb_helper) | ||
336 | { | ||
337 | drm_helper_fb_hotplug_event(fb_helper, true); | ||
338 | } | 334 | } |
339 | 335 | ||
340 | int | 336 | int |
@@ -374,7 +370,6 @@ static struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = { | |||
374 | .gamma_set = nouveau_fbcon_gamma_set, | 370 | .gamma_set = nouveau_fbcon_gamma_set, |
375 | .gamma_get = nouveau_fbcon_gamma_get, | 371 | .gamma_get = nouveau_fbcon_gamma_get, |
376 | .fb_probe = nouveau_fbcon_find_or_create_single, | 372 | .fb_probe = nouveau_fbcon_find_or_create_single, |
377 | .fb_output_status_changed = nouveau_fbcon_output_status_changed, | ||
378 | }; | 373 | }; |
379 | 374 | ||
380 | 375 | ||
@@ -391,8 +386,7 @@ int nouveau_fbcon_init(struct drm_device *dev) | |||
391 | dev_priv->nfbdev = nfbdev; | 386 | dev_priv->nfbdev = nfbdev; |
392 | nfbdev->helper.funcs = &nouveau_fbcon_helper_funcs; | 387 | nfbdev->helper.funcs = &nouveau_fbcon_helper_funcs; |
393 | 388 | ||
394 | drm_fb_helper_init(dev, &nfbdev->helper, | 389 | drm_fb_helper_init(dev, &nfbdev->helper, 2, 4); |
395 | 2, 4, true); | ||
396 | drm_fb_helper_single_add_all_connectors(&nfbdev->helper); | 390 | drm_fb_helper_single_add_all_connectors(&nfbdev->helper); |
397 | drm_fb_helper_initial_config(&nfbdev->helper, 32); | 391 | drm_fb_helper_initial_config(&nfbdev->helper, 32); |
398 | return 0; | 392 | return 0; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.h b/drivers/gpu/drm/nouveau/nouveau_fbcon.h index bf8e00d4de65..e7e12684c37e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.h +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.h | |||
@@ -58,6 +58,6 @@ void nouveau_fbcon_zfill_all(struct drm_device *dev); | |||
58 | void nouveau_fbcon_save_disable_accel(struct drm_device *dev); | 58 | void nouveau_fbcon_save_disable_accel(struct drm_device *dev); |
59 | void nouveau_fbcon_restore_accel(struct drm_device *dev); | 59 | void nouveau_fbcon_restore_accel(struct drm_device *dev); |
60 | 60 | ||
61 | void nouveau_fbcon_hotplug(struct drm_device *dev); | 61 | void nouveau_fbcon_output_poll_changed(struct drm_device *dev); |
62 | #endif /* __NV50_FBCON_H__ */ | 62 | #endif /* __NV50_FBCON_H__ */ |
63 | 63 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index c667a1138c33..e632339c323e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c | |||
@@ -516,8 +516,10 @@ nouveau_card_init(struct drm_device *dev) | |||
516 | 516 | ||
517 | dev_priv->init_state = NOUVEAU_CARD_INIT_DONE; | 517 | dev_priv->init_state = NOUVEAU_CARD_INIT_DONE; |
518 | 518 | ||
519 | if (drm_core_check_feature(dev, DRIVER_MODESET)) | 519 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
520 | nouveau_fbcon_init(dev); | 520 | nouveau_fbcon_init(dev); |
521 | drm_kms_helper_poll_init(dev); | ||
522 | } | ||
521 | 523 | ||
522 | return 0; | 524 | return 0; |
523 | 525 | ||
@@ -844,6 +846,7 @@ int nouveau_unload(struct drm_device *dev) | |||
844 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 846 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
845 | 847 | ||
846 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 848 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
849 | drm_kms_helper_poll_fini(dev); | ||
847 | nouveau_fbcon_fini(dev); | 850 | nouveau_fbcon_fini(dev); |
848 | if (dev_priv->card_type >= NV_50) | 851 | if (dev_priv->card_type >= NV_50) |
849 | nv50_display_destroy(dev); | 852 | nv50_display_destroy(dev); |
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index f9b304866e66..34156b69594f 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c | |||
@@ -947,7 +947,7 @@ nv50_display_irq_hotplug_bh(struct work_struct *work) | |||
947 | if (dev_priv->chipset >= 0x90) | 947 | if (dev_priv->chipset >= 0x90) |
948 | nv_wr32(dev, 0xe074, nv_rd32(dev, 0xe074)); | 948 | nv_wr32(dev, 0xe074, nv_rd32(dev, 0xe074)); |
949 | 949 | ||
950 | nouveau_fbcon_hotplug(dev); | 950 | drm_helper_hpd_irq_event(dev); |
951 | } | 951 | } |
952 | 952 | ||
953 | void | 953 | void |
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index c48934677adf..765854ed33c2 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
@@ -1085,6 +1085,7 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
1085 | drm_connector_attach_property(&radeon_connector->base, | 1085 | drm_connector_attach_property(&radeon_connector->base, |
1086 | rdev->mode_info.load_detect_property, | 1086 | rdev->mode_info.load_detect_property, |
1087 | 1); | 1087 | 1); |
1088 | connector->polled = DRM_CONNECTOR_POLL_CONNECT; | ||
1088 | break; | 1089 | break; |
1089 | case DRM_MODE_CONNECTOR_DVIA: | 1090 | case DRM_MODE_CONNECTOR_DVIA: |
1090 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); | 1091 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
@@ -1211,6 +1212,12 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
1211 | break; | 1212 | break; |
1212 | } | 1213 | } |
1213 | 1214 | ||
1215 | if (hpd->hpd == RADEON_HPD_NONE) { | ||
1216 | if (i2c_bus->valid) | ||
1217 | connector->polled = DRM_CONNECTOR_POLL_CONNECT; | ||
1218 | } else | ||
1219 | connector->polled = DRM_CONNECTOR_POLL_HPD; | ||
1220 | |||
1214 | connector->display_info.subpixel_order = subpixel_order; | 1221 | connector->display_info.subpixel_order = subpixel_order; |
1215 | drm_sysfs_connector_add(connector); | 1222 | drm_sysfs_connector_add(connector); |
1216 | return; | 1223 | return; |
@@ -1272,6 +1279,7 @@ radeon_add_legacy_connector(struct drm_device *dev, | |||
1272 | drm_connector_attach_property(&radeon_connector->base, | 1279 | drm_connector_attach_property(&radeon_connector->base, |
1273 | rdev->mode_info.load_detect_property, | 1280 | rdev->mode_info.load_detect_property, |
1274 | 1); | 1281 | 1); |
1282 | connector->polled = DRM_CONNECTOR_POLL_CONNECT; | ||
1275 | break; | 1283 | break; |
1276 | case DRM_MODE_CONNECTOR_DVIA: | 1284 | case DRM_MODE_CONNECTOR_DVIA: |
1277 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); | 1285 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
@@ -1338,6 +1346,11 @@ radeon_add_legacy_connector(struct drm_device *dev, | |||
1338 | break; | 1346 | break; |
1339 | } | 1347 | } |
1340 | 1348 | ||
1349 | if (hpd->hpd == RADEON_HPD_NONE) { | ||
1350 | if (i2c_bus->valid) | ||
1351 | connector->polled = DRM_CONNECTOR_POLL_CONNECT; | ||
1352 | } else | ||
1353 | connector->polled = DRM_CONNECTOR_POLL_HPD; | ||
1341 | connector->display_info.subpixel_order = subpixel_order; | 1354 | connector->display_info.subpixel_order = subpixel_order; |
1342 | drm_sysfs_connector_add(connector); | 1355 | drm_sysfs_connector_add(connector); |
1343 | return; | 1356 | return; |
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 243c1c4bc836..bc9cc9211e67 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
@@ -888,8 +888,15 @@ radeon_user_framebuffer_create(struct drm_device *dev, | |||
888 | return &radeon_fb->base; | 888 | return &radeon_fb->base; |
889 | } | 889 | } |
890 | 890 | ||
891 | static void radeon_output_poll_changed(struct drm_device *dev) | ||
892 | { | ||
893 | struct radeon_device *rdev = dev->dev_private; | ||
894 | radeon_fb_output_poll_changed(rdev); | ||
895 | } | ||
896 | |||
891 | static const struct drm_mode_config_funcs radeon_mode_funcs = { | 897 | static const struct drm_mode_config_funcs radeon_mode_funcs = { |
892 | .fb_create = radeon_user_framebuffer_create, | 898 | .fb_create = radeon_user_framebuffer_create, |
899 | .output_poll_changed = radeon_output_poll_changed | ||
893 | }; | 900 | }; |
894 | 901 | ||
895 | struct drm_prop_enum_list { | 902 | struct drm_prop_enum_list { |
@@ -1031,6 +1038,8 @@ int radeon_modeset_init(struct radeon_device *rdev) | |||
1031 | radeon_hpd_init(rdev); | 1038 | radeon_hpd_init(rdev); |
1032 | 1039 | ||
1033 | radeon_fbdev_init(rdev); | 1040 | radeon_fbdev_init(rdev); |
1041 | drm_kms_helper_poll_init(rdev->ddev); | ||
1042 | |||
1034 | return 0; | 1043 | return 0; |
1035 | } | 1044 | } |
1036 | 1045 | ||
@@ -1040,6 +1049,7 @@ void radeon_modeset_fini(struct radeon_device *rdev) | |||
1040 | kfree(rdev->mode_info.bios_hardcoded_edid); | 1049 | kfree(rdev->mode_info.bios_hardcoded_edid); |
1041 | 1050 | ||
1042 | if (rdev->mode_info.mode_config_initialized) { | 1051 | if (rdev->mode_info.mode_config_initialized) { |
1052 | drm_kms_helper_poll_fini(rdev->ddev); | ||
1043 | radeon_hpd_fini(rdev); | 1053 | radeon_hpd_fini(rdev); |
1044 | drm_mode_config_cleanup(rdev->ddev); | 1054 | drm_mode_config_cleanup(rdev->ddev); |
1045 | rdev->mode_info.mode_config_initialized = false; | 1055 | rdev->mode_info.mode_config_initialized = false; |
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index b4948021e345..e192acfbf0cd 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c | |||
@@ -316,16 +316,9 @@ int radeon_parse_options(char *options) | |||
316 | return 0; | 316 | return 0; |
317 | } | 317 | } |
318 | 318 | ||
319 | void radeonfb_hotplug(struct drm_device *dev, bool polled) | 319 | void radeon_fb_output_poll_changed(struct radeon_device *rdev) |
320 | { | 320 | { |
321 | struct radeon_device *rdev = dev->dev_private; | 321 | drm_fb_helper_hotplug_event(&rdev->mode_info.rfbdev->helper); |
322 | |||
323 | drm_helper_fb_hpd_irq_event(&rdev->mode_info.rfbdev->helper); | ||
324 | } | ||
325 | |||
326 | static void radeon_fb_output_status_changed(struct drm_fb_helper *fb_helper) | ||
327 | { | ||
328 | drm_helper_fb_hotplug_event(fb_helper, true); | ||
329 | } | 322 | } |
330 | 323 | ||
331 | static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfbdev) | 324 | static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfbdev) |
@@ -364,7 +357,6 @@ static struct drm_fb_helper_funcs radeon_fb_helper_funcs = { | |||
364 | .gamma_set = radeon_crtc_fb_gamma_set, | 357 | .gamma_set = radeon_crtc_fb_gamma_set, |
365 | .gamma_get = radeon_crtc_fb_gamma_get, | 358 | .gamma_get = radeon_crtc_fb_gamma_get, |
366 | .fb_probe = radeon_fb_find_or_create_single, | 359 | .fb_probe = radeon_fb_find_or_create_single, |
367 | .fb_output_status_changed = radeon_fb_output_status_changed, | ||
368 | }; | 360 | }; |
369 | 361 | ||
370 | int radeon_fbdev_init(struct radeon_device *rdev) | 362 | int radeon_fbdev_init(struct radeon_device *rdev) |
@@ -386,11 +378,10 @@ int radeon_fbdev_init(struct radeon_device *rdev) | |||
386 | 378 | ||
387 | drm_fb_helper_init(rdev->ddev, &rfbdev->helper, | 379 | drm_fb_helper_init(rdev->ddev, &rfbdev->helper, |
388 | rdev->num_crtc, | 380 | rdev->num_crtc, |
389 | RADEONFB_CONN_LIMIT, true); | 381 | RADEONFB_CONN_LIMIT); |
390 | drm_fb_helper_single_add_all_connectors(&rfbdev->helper); | 382 | drm_fb_helper_single_add_all_connectors(&rfbdev->helper); |
391 | drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel); | 383 | drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel); |
392 | return 0; | 384 | return 0; |
393 | |||
394 | } | 385 | } |
395 | 386 | ||
396 | void radeon_fbdev_fini(struct radeon_device *rdev) | 387 | void radeon_fbdev_fini(struct radeon_device *rdev) |
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index a95907aa7eae..8fa40ed397ec 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c | |||
@@ -26,6 +26,7 @@ | |||
26 | * Jerome Glisse | 26 | * Jerome Glisse |
27 | */ | 27 | */ |
28 | #include "drmP.h" | 28 | #include "drmP.h" |
29 | #include "drm_crtc_helper.h" | ||
29 | #include "radeon_drm.h" | 30 | #include "radeon_drm.h" |
30 | #include "radeon_reg.h" | 31 | #include "radeon_reg.h" |
31 | #include "radeon.h" | 32 | #include "radeon.h" |
@@ -55,9 +56,7 @@ static void radeon_hotplug_work_func(struct work_struct *work) | |||
55 | radeon_connector_hotplug(connector); | 56 | radeon_connector_hotplug(connector); |
56 | } | 57 | } |
57 | /* Just fire off a uevent and let userspace tell us what to do */ | 58 | /* Just fire off a uevent and let userspace tell us what to do */ |
58 | radeonfb_hotplug(dev, false); | 59 | drm_helper_hpd_irq_event(dev); |
59 | |||
60 | drm_sysfs_hotplug_event(dev); | ||
61 | } | 60 | } |
62 | 61 | ||
63 | void radeon_driver_irq_preinstall_kms(struct drm_device *dev) | 62 | void radeon_driver_irq_preinstall_kms(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index dd451c55c533..061a2a6801cc 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
@@ -586,5 +586,6 @@ void radeon_fbdev_fini(struct radeon_device *rdev); | |||
586 | void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state); | 586 | void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state); |
587 | int radeon_fbdev_total_size(struct radeon_device *rdev); | 587 | int radeon_fbdev_total_size(struct radeon_device *rdev); |
588 | bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj); | 588 | bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj); |
589 | void radeonfb_hotplug(struct drm_device *dev, bool polled); | 589 | |
590 | void radeon_fb_output_poll_changed(struct radeon_device *rdev); | ||
590 | #endif | 591 | #endif |
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index c560364663a5..2e4bf92faa85 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/idr.h> | 31 | #include <linux/idr.h> |
32 | 32 | ||
33 | #include <linux/fb.h> | 33 | #include <linux/fb.h> |
34 | #include <linux/slow-work.h> | ||
34 | 35 | ||
35 | struct drm_device; | 36 | struct drm_device; |
36 | struct drm_mode_set; | 37 | struct drm_mode_set; |
@@ -460,6 +461,15 @@ enum drm_connector_force { | |||
460 | DRM_FORCE_ON_DIGITAL, /* for DVI-I use digital connector */ | 461 | DRM_FORCE_ON_DIGITAL, /* for DVI-I use digital connector */ |
461 | }; | 462 | }; |
462 | 463 | ||
464 | /* should we poll this connector for connects and disconnects */ | ||
465 | /* hot plug detectable */ | ||
466 | #define DRM_CONNECTOR_POLL_HPD (1 << 0) | ||
467 | /* poll for connections */ | ||
468 | #define DRM_CONNECTOR_POLL_CONNECT (1 << 1) | ||
469 | /* can cleanly poll for disconnections without flickering the screen */ | ||
470 | /* DACs should rarely do this without a lot of testing */ | ||
471 | #define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2) | ||
472 | |||
463 | /** | 473 | /** |
464 | * drm_connector - central DRM connector control structure | 474 | * drm_connector - central DRM connector control structure |
465 | * @crtc: CRTC this connector is currently connected to, NULL if none | 475 | * @crtc: CRTC this connector is currently connected to, NULL if none |
@@ -504,6 +514,8 @@ struct drm_connector { | |||
504 | u32 property_ids[DRM_CONNECTOR_MAX_PROPERTY]; | 514 | u32 property_ids[DRM_CONNECTOR_MAX_PROPERTY]; |
505 | uint64_t property_values[DRM_CONNECTOR_MAX_PROPERTY]; | 515 | uint64_t property_values[DRM_CONNECTOR_MAX_PROPERTY]; |
506 | 516 | ||
517 | uint8_t polled; /* DRM_CONNECTOR_POLL_* */ | ||
518 | |||
507 | /* requested DPMS state */ | 519 | /* requested DPMS state */ |
508 | int dpms; | 520 | int dpms; |
509 | 521 | ||
@@ -543,6 +555,7 @@ struct drm_mode_set { | |||
543 | */ | 555 | */ |
544 | struct drm_mode_config_funcs { | 556 | struct drm_mode_config_funcs { |
545 | struct drm_framebuffer *(*fb_create)(struct drm_device *dev, struct drm_file *file_priv, struct drm_mode_fb_cmd *mode_cmd); | 557 | struct drm_framebuffer *(*fb_create)(struct drm_device *dev, struct drm_file *file_priv, struct drm_mode_fb_cmd *mode_cmd); |
558 | void (*output_poll_changed)(struct drm_device *dev); | ||
546 | }; | 559 | }; |
547 | 560 | ||
548 | struct drm_mode_group { | 561 | struct drm_mode_group { |
@@ -580,6 +593,10 @@ struct drm_mode_config { | |||
580 | struct drm_mode_config_funcs *funcs; | 593 | struct drm_mode_config_funcs *funcs; |
581 | resource_size_t fb_base; | 594 | resource_size_t fb_base; |
582 | 595 | ||
596 | /* output poll support */ | ||
597 | bool poll_enabled; | ||
598 | struct delayed_slow_work output_poll_slow_work; | ||
599 | |||
583 | /* pointers to standard properties */ | 600 | /* pointers to standard properties */ |
584 | struct list_head property_blob_list; | 601 | struct list_head property_blob_list; |
585 | struct drm_property *edid_property; | 602 | struct drm_property *edid_property; |
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index b1fa0f8cfa60..dc5873c21e45 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h | |||
@@ -127,4 +127,7 @@ static inline void drm_connector_helper_add(struct drm_connector *connector, | |||
127 | } | 127 | } |
128 | 128 | ||
129 | extern int drm_helper_resume_force_mode(struct drm_device *dev); | 129 | extern int drm_helper_resume_force_mode(struct drm_device *dev); |
130 | extern void drm_kms_helper_poll_init(struct drm_device *dev); | ||
131 | extern void drm_kms_helper_poll_fini(struct drm_device *dev); | ||
132 | extern void drm_helper_hpd_irq_event(struct drm_device *dev); | ||
130 | #endif | 133 | #endif |
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 9b55a94feada..f0a6afc47e76 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h | |||
@@ -30,8 +30,6 @@ | |||
30 | #ifndef DRM_FB_HELPER_H | 30 | #ifndef DRM_FB_HELPER_H |
31 | #define DRM_FB_HELPER_H | 31 | #define DRM_FB_HELPER_H |
32 | 32 | ||
33 | #include <linux/slow-work.h> | ||
34 | |||
35 | struct drm_fb_helper; | 33 | struct drm_fb_helper; |
36 | 34 | ||
37 | struct drm_fb_helper_crtc { | 35 | struct drm_fb_helper_crtc { |
@@ -71,9 +69,6 @@ struct drm_fb_helper_funcs { | |||
71 | 69 | ||
72 | int (*fb_probe)(struct drm_fb_helper *helper, | 70 | int (*fb_probe)(struct drm_fb_helper *helper, |
73 | struct drm_fb_helper_surface_size *sizes); | 71 | struct drm_fb_helper_surface_size *sizes); |
74 | |||
75 | void (*fb_output_status_changed)(struct drm_fb_helper *helper); | ||
76 | |||
77 | }; | 72 | }; |
78 | 73 | ||
79 | struct drm_fb_helper_connector { | 74 | struct drm_fb_helper_connector { |
@@ -95,8 +90,6 @@ struct drm_fb_helper { | |||
95 | u32 pseudo_palette[17]; | 90 | u32 pseudo_palette[17]; |
96 | struct list_head kernel_fb_list; | 91 | struct list_head kernel_fb_list; |
97 | 92 | ||
98 | struct delayed_slow_work output_status_change_slow_work; | ||
99 | bool poll_enabled; | ||
100 | /* we got a hotplug but fbdev wasn't running the console | 93 | /* we got a hotplug but fbdev wasn't running the console |
101 | delay until next set_par */ | 94 | delay until next set_par */ |
102 | bool delayed_hotplug; | 95 | bool delayed_hotplug; |
@@ -107,7 +100,7 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *helper, | |||
107 | 100 | ||
108 | int drm_fb_helper_init(struct drm_device *dev, | 101 | int drm_fb_helper_init(struct drm_device *dev, |
109 | struct drm_fb_helper *helper, int crtc_count, | 102 | struct drm_fb_helper *helper, int crtc_count, |
110 | int max_conn, bool polled); | 103 | int max_conn); |
111 | void drm_fb_helper_fini(struct drm_fb_helper *helper); | 104 | void drm_fb_helper_fini(struct drm_fb_helper *helper); |
112 | int drm_fb_helper_blank(int blank, struct fb_info *info); | 105 | int drm_fb_helper_blank(int blank, struct fb_info *info); |
113 | int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, | 106 | int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, |
@@ -130,10 +123,8 @@ void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, | |||
130 | 123 | ||
131 | int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info); | 124 | int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info); |
132 | 125 | ||
133 | bool drm_helper_fb_hotplug_event(struct drm_fb_helper *fb_helper, | 126 | bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper); |
134 | bool polled); | ||
135 | bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel); | 127 | bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel); |
136 | int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper); | 128 | int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper); |
137 | 129 | ||
138 | void drm_helper_fb_hpd_irq_event(struct drm_fb_helper *fb_helper); | ||
139 | #endif | 130 | #endif |