Rev 6084 | Rev 6131 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 6084 | Rev 6088 | ||
---|---|---|---|
Line 368... | Line 368... | ||
368 | struct drm_vblank_crtc *vblank = &dev->vblank[i]; |
368 | struct drm_vblank_crtc *vblank = &dev->vblank[i]; |
Line 369... | Line 369... | ||
369 | 369 | ||
370 | vblank->dev = dev; |
370 | vblank->dev = dev; |
371 | vblank->pipe = i; |
371 | vblank->pipe = i; |
372 | init_waitqueue_head(&vblank->queue); |
372 | init_waitqueue_head(&vblank->queue); |
373 | // setup_timer(&vblank->disable_timer, vblank_disable_fn, |
373 | setup_timer(&vblank->disable_timer, vblank_disable_fn, |
374 | // (unsigned long)vblank); |
374 | (unsigned long)vblank); |
Line 375... | Line 375... | ||
375 | } |
375 | } |
Line 376... | Line 376... | ||
376 | 376 | ||
Line 827... | Line 827... | ||
827 | } while (cur_vblank != vblank->count && --count > 0); |
827 | } while (cur_vblank != vblank->count && --count > 0); |
Line 828... | Line 828... | ||
828 | 828 | ||
829 | return cur_vblank; |
829 | return cur_vblank; |
830 | } |
830 | } |
- | 831 | EXPORT_SYMBOL(drm_vblank_count_and_time); |
|
- | 832 | ||
- | 833 | /** |
|
- | 834 | * drm_crtc_vblank_count_and_time - retrieve "cooked" vblank counter value |
|
- | 835 | * and the system timestamp corresponding to that vblank counter value |
|
- | 836 | * @crtc: which counter to retrieve |
|
- | 837 | * @vblanktime: Pointer to struct timeval to receive the vblank timestamp. |
|
- | 838 | * |
|
- | 839 | * Fetches the "cooked" vblank count value that represents the number of |
|
- | 840 | * vblank events since the system was booted, including lost events due to |
|
- | 841 | * modesetting activity. Returns corresponding system timestamp of the time |
|
- | 842 | * of the vblank interval that corresponds to the current vblank counter value. |
|
- | 843 | * |
|
- | 844 | * This is the native KMS version of drm_vblank_count_and_time(). |
|
- | 845 | */ |
|
- | 846 | u32 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc, |
|
- | 847 | struct timeval *vblanktime) |
|
- | 848 | { |
|
- | 849 | return drm_vblank_count_and_time(crtc->dev, drm_crtc_index(crtc), |
|
- | 850 | vblanktime); |
|
- | 851 | } |
|
- | 852 | EXPORT_SYMBOL(drm_crtc_vblank_count_and_time); |
|
- | 853 | ||
- | 854 | static void send_vblank_event(struct drm_device *dev, |
|
- | 855 | struct drm_pending_vblank_event *e, |
|
- | 856 | unsigned long seq, struct timeval *now) |
|
- | 857 | { |
|
- | 858 | assert_spin_locked(&dev->event_lock); |
|
- | 859 | ||
- | 860 | e->event.sequence = seq; |
|
- | 861 | e->event.tv_sec = now->tv_sec; |
|
- | 862 | e->event.tv_usec = now->tv_usec; |
|
- | 863 | ||
- | 864 | list_add_tail(&e->base.link, |
|
- | 865 | &e->base.file_priv->event_list); |
|
- | 866 | wake_up_interruptible(&e->base.file_priv->event_wait); |
|
- | 867 | } |
|
- | 868 | ||
- | 869 | /** |
|
- | 870 | * drm_arm_vblank_event - arm vblank event after pageflip |
|
- | 871 | * @dev: DRM device |
|
- | 872 | * @pipe: CRTC index |
|
- | 873 | * @e: the event to prepare to send |
|
- | 874 | * |
|
- | 875 | * A lot of drivers need to generate vblank events for the very next vblank |
|
- | 876 | * interrupt. For example when the page flip interrupt happens when the page |
|
- | 877 | * flip gets armed, but not when it actually executes within the next vblank |
|
- | 878 | * period. This helper function implements exactly the required vblank arming |
|
- | 879 | * behaviour. |
|
- | 880 | * |
|
- | 881 | * Caller must hold event lock. Caller must also hold a vblank reference for |
|
- | 882 | * the event @e, which will be dropped when the next vblank arrives. |
|
- | 883 | * |
|
- | 884 | * This is the legacy version of drm_crtc_arm_vblank_event(). |
|
- | 885 | */ |
|
- | 886 | void drm_arm_vblank_event(struct drm_device *dev, unsigned int pipe, |
|
- | 887 | struct drm_pending_vblank_event *e) |
|
- | 888 | { |
|
- | 889 | assert_spin_locked(&dev->event_lock); |
|
- | 890 | ||
- | 891 | e->pipe = pipe; |
|
- | 892 | e->event.sequence = drm_vblank_count(dev, pipe); |
|
- | 893 | list_add_tail(&e->base.link, &dev->vblank_event_list); |
|
- | 894 | } |
|
- | 895 | EXPORT_SYMBOL(drm_arm_vblank_event); |
|
- | 896 | ||
- | 897 | /** |
|
- | 898 | * drm_crtc_arm_vblank_event - arm vblank event after pageflip |
|
- | 899 | * @crtc: the source CRTC of the vblank event |
|
- | 900 | * @e: the event to send |
|
- | 901 | * |
|
- | 902 | * A lot of drivers need to generate vblank events for the very next vblank |
|
- | 903 | * interrupt. For example when the page flip interrupt happens when the page |
|
- | 904 | * flip gets armed, but not when it actually executes within the next vblank |
|
- | 905 | * period. This helper function implements exactly the required vblank arming |
|
- | 906 | * behaviour. |
|
- | 907 | * |
|
- | 908 | * Caller must hold event lock. Caller must also hold a vblank reference for |
|
- | 909 | * the event @e, which will be dropped when the next vblank arrives. |
|
- | 910 | * |
|
- | 911 | * This is the native KMS version of drm_arm_vblank_event(). |
|
- | 912 | */ |
|
- | 913 | void drm_crtc_arm_vblank_event(struct drm_crtc *crtc, |
|
- | 914 | struct drm_pending_vblank_event *e) |
|
- | 915 | { |
|
- | 916 | drm_arm_vblank_event(crtc->dev, drm_crtc_index(crtc), e); |
|
- | 917 | } |
|
- | 918 | EXPORT_SYMBOL(drm_crtc_arm_vblank_event); |
|
- | 919 | ||
- | 920 | /** |
|
- | 921 | * drm_send_vblank_event - helper to send vblank event after pageflip |
|
- | 922 | * @dev: DRM device |
|
- | 923 | * @pipe: CRTC index |
|
- | 924 | * @e: the event to send |
|
- | 925 | * |
|
- | 926 | * Updates sequence # and timestamp on event, and sends it to userspace. |
|
- | 927 | * Caller must hold event lock. |
|
- | 928 | * |
|
- | 929 | * This is the legacy version of drm_crtc_send_vblank_event(). |
|
- | 930 | */ |
|
- | 931 | void drm_send_vblank_event(struct drm_device *dev, unsigned int pipe, |
|
- | 932 | struct drm_pending_vblank_event *e) |
|
- | 933 | { |
|
- | 934 | struct timeval now; |
|
- | 935 | unsigned int seq; |
|
- | 936 | ||
- | 937 | if (dev->num_crtcs > 0) { |
|
- | 938 | seq = drm_vblank_count_and_time(dev, pipe, &now); |
|
- | 939 | } else { |
|
- | 940 | seq = 0; |
|
- | 941 | ||
- | 942 | now = get_drm_timestamp(); |
|
- | 943 | } |
|
- | 944 | e->pipe = pipe; |
|
- | 945 | send_vblank_event(dev, e, seq, &now); |
|
- | 946 | } |
|
- | 947 | EXPORT_SYMBOL(drm_send_vblank_event); |
|
- | 948 | ||
- | 949 | /** |
|
- | 950 | * drm_crtc_send_vblank_event - helper to send vblank event after pageflip |
|
- | 951 | * @crtc: the source CRTC of the vblank event |
|
- | 952 | * @e: the event to send |
|
- | 953 | * |
|
- | 954 | * Updates sequence # and timestamp on event, and sends it to userspace. |
|
- | 955 | * Caller must hold event lock. |
|
- | 956 | * |
|
- | 957 | * This is the native KMS version of drm_send_vblank_event(). |
|
- | 958 | */ |
|
- | 959 | void drm_crtc_send_vblank_event(struct drm_crtc *crtc, |
|
- | 960 | struct drm_pending_vblank_event *e) |
|
- | 961 | { |
|
- | 962 | drm_send_vblank_event(crtc->dev, drm_crtc_index(crtc), e); |
|
- | 963 | } |
|
- | 964 | EXPORT_SYMBOL(drm_crtc_send_vblank_event); |
|
831 | EXPORT_SYMBOL(drm_vblank_count_and_time); |
965 | |
832 | /** |
966 | /** |
833 | * drm_vblank_enable - enable the vblank interrupt on a CRTC |
967 | * drm_vblank_enable - enable the vblank interrupt on a CRTC |
834 | * @dev: DRM device |
968 | * @dev: DRM device |
835 | * @pipe: CRTC index |
969 | * @pipe: CRTC index |
Line 950... | Line 1084... | ||
950 | 1084 | ||
951 | /* Last user schedules interrupt disable */ |
1085 | /* Last user schedules interrupt disable */ |
952 | if (atomic_dec_and_test(&vblank->refcount)) { |
1086 | if (atomic_dec_and_test(&vblank->refcount)) { |
953 | if (drm_vblank_offdelay == 0) |
1087 | if (drm_vblank_offdelay == 0) |
954 | return; |
- | |
955 | else if (dev->vblank_disable_immediate || drm_vblank_offdelay < 0) |
- | |
956 | vblank_disable_fn((unsigned long)vblank); |
1088 | return; |
957 | else |
- | |
958 | mod_timer(&vblank->disable_timer, |
1089 | else |
959 | jiffies + ((drm_vblank_offdelay * HZ)/1000)); |
1090 | vblank_disable_fn((unsigned long)vblank); |
960 | } |
1091 | } |
961 | } |
1092 | } |
Line 962... | Line 1093... | ||
962 | EXPORT_SYMBOL(drm_vblank_put); |
1093 | EXPORT_SYMBOL(drm_vblank_put); |
Line 985... | Line 1116... | ||
985 | * It is a failure to call this when the vblank irq for @pipe is disabled, e.g. |
1116 | * It is a failure to call this when the vblank irq for @pipe is disabled, e.g. |
986 | * due to lack of driver support or because the crtc is off. |
1117 | * due to lack of driver support or because the crtc is off. |
987 | */ |
1118 | */ |
988 | void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe) |
1119 | void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe) |
989 | { |
1120 | { |
990 | #if 0 |
- | |
- | 1121 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
|
991 | int ret; |
1122 | int ret; |
992 | u32 last; |
1123 | u32 last; |
Line -... | Line 1124... | ||
- | 1124 | ||
- | 1125 | if (WARN_ON(pipe >= dev->num_crtcs)) |
|
- | 1126 | return; |
|
993 | 1127 | ||
994 | ret = drm_vblank_get(dev, crtc); |
1128 | ret = drm_vblank_get(dev, pipe); |
995 | if (WARN(ret, "vblank not available on crtc %i, ret=%i\n", crtc, ret)) |
1129 | if (WARN(ret, "vblank not available on crtc %i, ret=%i\n", pipe, ret)) |
Line 996... | Line 1130... | ||
996 | return; |
1130 | return; |
Line 997... | Line 1131... | ||
997 | 1131 | ||
998 | last = drm_vblank_count(dev, crtc); |
1132 | last = drm_vblank_count(dev, pipe); |
999 | 1133 | ||
Line 1000... | Line 1134... | ||
1000 | ret = wait_event_timeout(dev->vblank[crtc].queue, |
1134 | ret = wait_event_timeout(vblank->queue, |
Line 1001... | Line 1135... | ||
1001 | last != drm_vblank_count(dev, crtc), |
1135 | last != drm_vblank_count(dev, pipe), |
1002 | msecs_to_jiffies(100)); |
- | |
1003 | 1136 | msecs_to_jiffies(100)); |
|
1004 | WARN(ret == 0, "vblank wait timed out on crtc %i\n", crtc); |
1137 | |
Line 1005... | Line 1138... | ||
1005 | 1138 | WARN(ret == 0, "vblank wait timed out on crtc %i\n", pipe); |
|
1006 | drm_vblank_put(dev, crtc); |
1139 | |
Line 1042... | Line 1175... | ||
1042 | struct drm_pending_vblank_event *e, *t; |
1175 | struct drm_pending_vblank_event *e, *t; |
1043 | struct timeval now; |
1176 | struct timeval now; |
1044 | unsigned long irqflags; |
1177 | unsigned long irqflags; |
1045 | unsigned int seq; |
1178 | unsigned int seq; |
Line -... | Line 1179... | ||
- | 1179 | ||
- | 1180 | if (WARN_ON(pipe >= dev->num_crtcs)) |
|
- | 1181 | return; |
|
- | 1182 | ||
- | 1183 | spin_lock_irqsave(&dev->event_lock, irqflags); |
|
- | 1184 | ||
- | 1185 | spin_lock(&dev->vbl_lock); |
|
- | 1186 | vblank_disable_and_save(dev, pipe); |
|
- | 1187 | wake_up(&vblank->queue); |
|
- | 1188 | ||
- | 1189 | /* |
|
- | 1190 | * Prevent subsequent drm_vblank_get() from re-enabling |
|
- | 1191 | * the vblank interrupt by bumping the refcount. |
|
- | 1192 | */ |
|
- | 1193 | if (!vblank->inmodeset) { |
|
- | 1194 | atomic_inc(&vblank->refcount); |
|
- | 1195 | vblank->inmodeset = 1; |
|
- | 1196 | } |
|
- | 1197 | spin_unlock(&dev->vbl_lock); |
|
- | 1198 | ||
- | 1199 | /* Send any queued vblank events, lest the natives grow disquiet */ |
|
Line -... | Line 1200... | ||
- | 1200 | seq = drm_vblank_count_and_time(dev, pipe, &now); |
|
- | 1201 | ||
- | 1202 | list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) { |
|
- | 1203 | if (e->pipe != pipe) |
|
- | 1204 | continue; |
|
- | 1205 | DRM_DEBUG("Sending premature vblank event on disable: " |
|
- | 1206 | "wanted %d, current %d\n", |
|
- | 1207 | e->event.sequence, seq); |
|
- | 1208 | list_del(&e->base.link); |
|
- | 1209 | drm_vblank_put(dev, pipe); |
|
- | 1210 | send_vblank_event(dev, e, seq, &now); |
|
1046 | 1211 | } |
|
1047 | 1212 | spin_unlock_irqrestore(&dev->event_lock, irqflags); |
|
Line 1048... | Line 1213... | ||
1048 | } |
1213 | } |
1049 | EXPORT_SYMBOL(drm_vblank_off); |
1214 | EXPORT_SYMBOL(drm_vblank_off); |
Line 1114... | Line 1279... | ||
1114 | void drm_vblank_on(struct drm_device *dev, unsigned int pipe) |
1279 | void drm_vblank_on(struct drm_device *dev, unsigned int pipe) |
1115 | { |
1280 | { |
1116 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
1281 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
1117 | unsigned long irqflags; |
1282 | unsigned long irqflags; |
Line 1118... | Line -... | ||
1118 | - | ||
1119 | dbgprintf("%s pipe %d dev->num_crtcs %d\n", pipe,dev->num_crtcs);\ |
- | |
1120 | 1283 | ||
1121 | if (WARN_ON(pipe >= dev->num_crtcs)) |
1284 | if (WARN_ON(pipe >= dev->num_crtcs)) |
Line 1122... | Line 1285... | ||
1122 | return; |
1285 | return; |
1123 | 1286 | ||
Line 1238... | Line 1401... | ||
1238 | vblank->inmodeset = 0; |
1401 | vblank->inmodeset = 0; |
1239 | } |
1402 | } |
1240 | } |
1403 | } |
1241 | EXPORT_SYMBOL(drm_vblank_post_modeset); |
1404 | EXPORT_SYMBOL(drm_vblank_post_modeset); |
Line -... | Line 1405... | ||
- | 1405 | ||
- | 1406 | static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe) |
|
- | 1407 | { |
|
- | 1408 | struct drm_pending_vblank_event *e, *t; |
|
- | 1409 | struct timeval now; |
|
- | 1410 | unsigned int seq; |
|
- | 1411 | ||
- | 1412 | assert_spin_locked(&dev->event_lock); |
|
- | 1413 | ||
- | 1414 | seq = drm_vblank_count_and_time(dev, pipe, &now); |
|
- | 1415 | ||
- | 1416 | list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) { |
|
- | 1417 | if (e->pipe != pipe) |
|
- | 1418 | continue; |
|
- | 1419 | if ((seq - e->event.sequence) > (1<<23)) |
|
- | 1420 | continue; |
|
- | 1421 | ||
- | 1422 | DRM_DEBUG("vblank event on %d, current %d\n", |
|
- | 1423 | e->event.sequence, seq); |
|
- | 1424 | ||
- | 1425 | list_del(&e->base.link); |
|
- | 1426 | drm_vblank_put(dev, pipe); |
|
- | 1427 | send_vblank_event(dev, e, seq, &now); |
|
- | 1428 | } |
|
- | 1429 | ||
- | 1430 | } |
|
- | 1431 | ||
- | 1432 | /** |
|
- | 1433 | * drm_handle_vblank - handle a vblank event |
|
- | 1434 | * @dev: DRM device |
|
- | 1435 | * @pipe: index of CRTC where this event occurred |
|
- | 1436 | * |
|
- | 1437 | * Drivers should call this routine in their vblank interrupt handlers to |
|
- | 1438 | * update the vblank counter and send any signals that may be pending. |
|
- | 1439 | * |
|
- | 1440 | * This is the legacy version of drm_crtc_handle_vblank(). |
|
- | 1441 | */ |
|
- | 1442 | bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe) |
|
- | 1443 | { |
|
- | 1444 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
|
- | 1445 | unsigned long irqflags; |
|
- | 1446 | ||
- | 1447 | if (WARN_ON_ONCE(!dev->num_crtcs)) |
|
- | 1448 | return false; |
|
- | 1449 | ||
- | 1450 | if (WARN_ON(pipe >= dev->num_crtcs)) |
|
- | 1451 | return false; |
|
- | 1452 | ||
- | 1453 | spin_lock_irqsave(&dev->event_lock, irqflags); |
|
- | 1454 | ||
- | 1455 | /* Need timestamp lock to prevent concurrent execution with |
|
- | 1456 | * vblank enable/disable, as this would cause inconsistent |
|
- | 1457 | * or corrupted timestamps and vblank counts. |
|
- | 1458 | */ |
|
- | 1459 | spin_lock(&dev->vblank_time_lock); |
|
- | 1460 | ||
- | 1461 | /* Vblank irq handling disabled. Nothing to do. */ |
|
- | 1462 | if (!vblank->enabled) { |
|
- | 1463 | spin_unlock(&dev->vblank_time_lock); |
|
- | 1464 | spin_unlock_irqrestore(&dev->event_lock, irqflags); |
|
- | 1465 | return false; |
|
- | 1466 | } |
|
- | 1467 | ||
- | 1468 | drm_update_vblank_count(dev, pipe, DRM_CALLED_FROM_VBLIRQ); |
|
- | 1469 | ||
- | 1470 | spin_unlock(&dev->vblank_time_lock); |
|
- | 1471 | ||
- | 1472 | wake_up(&vblank->queue); |
|
- | 1473 | drm_handle_vblank_events(dev, pipe); |
|
- | 1474 | ||
- | 1475 | spin_unlock_irqrestore(&dev->event_lock, irqflags); |
|
- | 1476 | ||
- | 1477 | return true; |
|
- | 1478 | } |
|
- | 1479 | EXPORT_SYMBOL(drm_handle_vblank); |
|
- | 1480 | ||
- | 1481 | /** |
|
- | 1482 | * drm_crtc_handle_vblank - handle a vblank event |
|
- | 1483 | * @crtc: where this event occurred |
|
- | 1484 | * |
|
- | 1485 | * Drivers should call this routine in their vblank interrupt handlers to |
|
- | 1486 | * update the vblank counter and send any signals that may be pending. |
|
- | 1487 | * |
|
- | 1488 | * This is the native KMS version of drm_handle_vblank(). |
|
- | 1489 | * |
|
- | 1490 | * Returns: |
|
- | 1491 | * True if the event was successfully handled, false on failure. |
|
- | 1492 | */ |
|
- | 1493 | bool drm_crtc_handle_vblank(struct drm_crtc *crtc) |
|
- | 1494 | { |
|
- | 1495 | return drm_handle_vblank(crtc->dev, drm_crtc_index(crtc)); |
|
- | 1496 | } |
|
- | 1497 | EXPORT_SYMBOL(drm_crtc_handle_vblank); |
|
- | 1498 | ||
- | 1499 | /** |
|
- | 1500 | * drm_vblank_no_hw_counter - "No hw counter" implementation of .get_vblank_counter() |
|
- | 1501 | * @dev: DRM device |
|
- | 1502 | * @pipe: CRTC for which to read the counter |
|
- | 1503 | * |
|
- | 1504 | * Drivers can plug this into the .get_vblank_counter() function if |
|
- | 1505 | * there is no useable hardware frame counter available. |
|
- | 1506 | * |
|
- | 1507 | * Returns: |
|
- | 1508 | * 0 |
|
- | 1509 | */ |
|
- | 1510 | u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe) |
|
- | 1511 | { |
|
- | 1512 | return 0; |
|
- | 1513 | } |
|
Line 1242... | Line 1514... | ||
1242 | 1514 | EXPORT_SYMBOL(drm_vblank_no_hw_counter); |
|
1243 | 1515 | ||
1244 | u64 div64_u64(u64 dividend, u64 divisor) |
1516 | u64 div64_u64(u64 dividend, u64 divisor) |