History

Merge tag 'drm-misc-next-2022-10-20' of git://anongit.freedesktop.org/drm/drm-misc into drm-next

drm-misc-next for 6.2: UAPI Changes: - Documentation for page-flip flags Cross-subsystem Changes: - dma-buf: Add unlocked variant of vmapping and attachment-mapping functions Core Changes: - atomic-helpers: CRTC primary plane test fixes - connector: TV API consistency improvements, cmdline parsing improvements - crtc-helpers: Introduce drm_crtc_helper_atomic_check() helper - edid: Fixes for HFVSDB parsing, - fourcc: Addition of the Vivante tiled modifier - makefile: Sort and reorganize the objects files - mode_config: Remove fb_base from drm_mode_config_funcs - sched: Add a module parameter to change the scheduling policy, refcounting fix for fences - tests: Sort the Kunit tests in the Makefile, improvements to the DP-MST tests - ttm: Remove unnecessary drm_mm_clean() call Driver Changes: - New driver: ofdrm - Move all drivers to a common dma-buf locking convention - bridge: - adv7533: Remove dynamic lane switching - it6505: Runtime PM support - ps8640: Handle AUX defer messages - tc358775: Drop soft-reset over I2C - ast: Atomic Gamma LUT Support, Convert to SHMEM, various improvements - lcdif: Support for YUV planes - mgag200: Fix PLL Setup on some revisions - udl: Modesetting improvements, hot-unplug support - vc4: Fix support for PAL-M Signed-off-by: Dave Airlie <airlied@redhat.com>

Dave Airlie committed 4 years ago

Commit b837d3d2 parents 247f34f 7c99616110 files · +3849 −1353Browse files

Unified · Split

110 files
  1. Documentation/driver-api/dma-buf.rst +6 −0
  2. MAINTAINERS +1 −0
  3. drivers/dma-buf/dma-buf.c +185 −31
  4. drivers/gpu/drm/Makefile +77 −30
  5. drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c +0 −2
  6. drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +0 −2
  7. drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +0 −2
  8. drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +0 −1
  9. drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +0 −2
  10. drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +0 −2
  11. drivers/gpu/drm/armada/armada_gem.c +4 −4
  12. drivers/gpu/drm/ast/Kconfig +1 −3
  13. drivers/gpu/drm/ast/ast_drv.c +2 −2
  14. drivers/gpu/drm/ast/ast_drv.h +18 −16
  15. drivers/gpu/drm/ast/ast_main.c +2 −3
  16. drivers/gpu/drm/ast/ast_mm.c +7 −7
  17. drivers/gpu/drm/ast/ast_mode.c +265 −234
  18. drivers/gpu/drm/bridge/adv7511/adv7511.h +2 −1
  19. drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +14 −4
  20. drivers/gpu/drm/bridge/adv7511/adv7533.c +13 −12
  21. drivers/gpu/drm/bridge/ite-it6505.c +48 −10
  22. drivers/gpu/drm/bridge/parade-ps8640.c +8 −1
  23. drivers/gpu/drm/bridge/tc358775.c +1 −1
  24. drivers/gpu/drm/display/Makefile +8 −6
  25. drivers/gpu/drm/drm_atomic_helper.c +18 −42
  26. drivers/gpu/drm/drm_atomic_state_helper.c +3 −3
  27. drivers/gpu/drm/drm_atomic_uapi.c +4 −0
  28. drivers/gpu/drm/drm_client.c +2 −2
  29. drivers/gpu/drm/drm_crtc_helper.c +26 −0
  30. drivers/gpu/drm/drm_edid.c +222 −124
  31. drivers/gpu/drm/drm_format_helper.c +10 −0
  32. drivers/gpu/drm/drm_gem.c +24 −0
  33. drivers/gpu/drm/drm_gem_dma_helper.c +3 −3
  34. drivers/gpu/drm/drm_gem_framebuffer_helper.c +3 −3
  35. drivers/gpu/drm/drm_gem_ttm_helper.c +1 −8
  36. drivers/gpu/drm/drm_modes.c +11 −7
  37. drivers/gpu/drm/drm_plane_helper.c +3 −1
  38. drivers/gpu/drm/drm_prime.c +3 −3
  39. drivers/gpu/drm/drm_simple_kms_helper.c +5 −1
  40. drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c +1 −1
  41. drivers/gpu/drm/gma500/framebuffer.c +3 −3
  42. drivers/gpu/drm/gma500/psb_drv.h +1 −0
  43. drivers/gpu/drm/gud/gud_connector.c +1 −1
  44. drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c +3 −13
  45. drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h +0 −3
  46. drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c +1 −1
  47. drivers/gpu/drm/i915/gem/i915_gem_object.c +14 −0
  48. drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c +8 −8
  49. drivers/gpu/drm/lima/lima_sched.c +2 −2
  50. drivers/gpu/drm/mgag200/mgag200_g200se.c +2 −1
  51. drivers/gpu/drm/mgag200/mgag200_mode.c +5 −6
  52. drivers/gpu/drm/msm/msm_fbdev.c +0 −2
  53. drivers/gpu/drm/mxsfb/lcdif_kms.c +216 −23
  54. drivers/gpu/drm/mxsfb/lcdif_regs.h +20 −17
  55. drivers/gpu/drm/nouveau/dispnv50/disp.c +2 −2
  56. drivers/gpu/drm/nouveau/nouveau_display.c +0 −1
  57. drivers/gpu/drm/nouveau/nv04_fbcon.c +4 −2
  58. drivers/gpu/drm/omapdrm/omap_fbdev.c +0 −2
  59. drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c +2 −2
  60. drivers/gpu/drm/panel/panel-samsung-db7430.c +7 −0
  61. drivers/gpu/drm/panel/panel-tpo-tpg110.c +7 −0
  62. drivers/gpu/drm/panel/panel-widechips-ws2401.c +7 −0
  63. drivers/gpu/drm/panfrost/panfrost_dump.c +2 −2
  64. drivers/gpu/drm/panfrost/panfrost_perfcnt.c +3 −3
  65. drivers/gpu/drm/qxl/qxl_display.c +0 −2
  66. drivers/gpu/drm/qxl/qxl_object.c +9 −8
  67. drivers/gpu/drm/qxl/qxl_prime.c +2 −2
  68. drivers/gpu/drm/radeon/radeon_display.c +0 −2
  69. drivers/gpu/drm/radeon/radeon_fb.c +1 −1
  70. drivers/gpu/drm/scheduler/sched_entity.c +25 −1
  71. drivers/gpu/drm/scheduler/sched_main.c +93 −3
  72. drivers/gpu/drm/solomon/ssd130x.c +13 −22
  73. drivers/gpu/drm/tegra/fb.c +0 −1
  74. drivers/gpu/drm/tegra/gem.c +9 −8
  75. drivers/gpu/drm/tests/Makefile +11 −3
  76. drivers/gpu/drm/tests/drm_dp_mst_helper_test.c +295 −150
  77. drivers/gpu/drm/tiny/Kconfig +13 −0
  78. drivers/gpu/drm/tiny/Makefile +1 −0
  79. drivers/gpu/drm/tiny/bochs.c +0 −1
  80. drivers/gpu/drm/tiny/ofdrm.c +1424 −0
  81. drivers/gpu/drm/tiny/simpledrm.c +2 −14
  82. drivers/gpu/drm/ttm/ttm_range_manager.c +0 −1
  83. drivers/gpu/drm/udl/Makefile +1 −1
  84. drivers/gpu/drm/udl/udl_connector.c +0 −139
  85. drivers/gpu/drm/udl/udl_connector.h +0 −15
  86. drivers/gpu/drm/udl/udl_drv.h +18 −24
  87. drivers/gpu/drm/udl/udl_modeset.c +363 −203
  88. drivers/gpu/drm/udl/udl_proto.h +68 −0
  89. drivers/gpu/drm/udl/udl_transfer.c +4 −3
  90. drivers/gpu/drm/vc4/vc4_hdmi.c +1 −1
  91. drivers/gpu/drm/vc4/vc4_vec.c +4 −4
  92. drivers/infiniband/core/umem_dmabuf.c +4 −3
  93. drivers/media/common/videobuf2/videobuf2-dma-contig.c +7 −15
  94. drivers/media/common/videobuf2/videobuf2-dma-sg.c +5 −14
  95. drivers/media/common/videobuf2/videobuf2-vmalloc.c +4 −13
  96. drivers/media/platform/nvidia/tegra-vde/dmabuf-cache.c +3 −3
  97. drivers/misc/fastrpc.c +3 −3
  98. drivers/video/fbdev/Kconfig +1 −0
  99. drivers/xen/gntdev-dmabuf.c +4 −4
  100. include/drm/drm_atomic_helper.h +1 −2
  101. include/drm/drm_atomic_state_helper.h +1 −1
  102. include/drm/drm_connector.h +3 −1
  103. include/drm/drm_crtc_helper.h +2 −0
  104. include/drm/drm_edid.h +9 −5
  105. include/drm/drm_gem.h +3 −0
  106. include/drm/drm_mode_config.h +0 −2
  107. include/drm/gpu_scheduler.h +32 −0
  108. include/linux/dma-buf.h +8 −9
  109. include/uapi/drm/drm_fourcc.h +29 −0
  110. include/uapi/drm/drm_mode.h +62 −1
Documentation/driver-api/dma-buf.rst+6−0
@@ -119,6 +119,12 @@ DMA Buffer ioctls · 118 unmodified lines
119 119
120.. kernel-doc:: include/uapi/linux/dma-buf.h120.. kernel-doc:: include/uapi/linux/dma-buf.h
121 121
122DMA-BUF locking convention
123~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
124
125.. kernel-doc:: drivers/dma-buf/dma-buf.c
126 :doc: locking convention
127
122Kernel Functions and Structures Reference128Kernel Functions and Structures Reference
123~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~129~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
124 130
MAINTAINERS+1−0
@@ -6692,6 +6692,7 @@ L: dri-devel@lists.freedesktop.org · 6691 unmodified lines
6692S: Maintained6692S: Maintained
6693T: git git://anongit.freedesktop.org/drm/drm-misc6693T: git git://anongit.freedesktop.org/drm/drm-misc
6694F: drivers/gpu/drm/drm_aperture.c6694F: drivers/gpu/drm/drm_aperture.c
6695F: drivers/gpu/drm/tiny/ofdrm.c
6695F: drivers/gpu/drm/tiny/simpledrm.c6696F: drivers/gpu/drm/tiny/simpledrm.c
6696F: drivers/video/aperture.c6697F: drivers/video/aperture.c
6697F: include/drm/drm_aperture.h6698F: include/drm/drm_aperture.h
drivers/dma-buf/dma-buf.c+185−31
@@ -657,7 +657,6 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info) · 656 unmodified lines
657 657
658 dmabuf->file = file;658 dmabuf->file = file;
659 659
660 mutex_init(&dmabuf->lock);
661 INIT_LIST_HEAD(&dmabuf->attachments);660 INIT_LIST_HEAD(&dmabuf->attachments);
662 661
663 mutex_lock(&db_list.lock);662 mutex_lock(&db_list.lock);
@@ -795,6 +794,70 @@ static struct sg_table * __map_dma_buf(struct dma_buf_attachment *attach, · 131 unmodified lines
795 return sg_table;794 return sg_table;
796}795}
797 796
797/**
798 * DOC: locking convention
799 *
800 * In order to avoid deadlock situations between dma-buf exports and importers,
801 * all dma-buf API users must follow the common dma-buf locking convention.
802 *
803 * Convention for importers
804 *
805 * 1. Importers must hold the dma-buf reservation lock when calling these
806 * functions:
807 *
808 * - dma_buf_pin()
809 * - dma_buf_unpin()
810 * - dma_buf_map_attachment()
811 * - dma_buf_unmap_attachment()
812 * - dma_buf_vmap()
813 * - dma_buf_vunmap()
814 *
815 * 2. Importers must not hold the dma-buf reservation lock when calling these
816 * functions:
817 *
818 * - dma_buf_attach()
819 * - dma_buf_dynamic_attach()
820 * - dma_buf_detach()
821 * - dma_buf_export(
822 * - dma_buf_fd()
823 * - dma_buf_get()
824 * - dma_buf_put()
825 * - dma_buf_mmap()
826 * - dma_buf_begin_cpu_access()
827 * - dma_buf_end_cpu_access()
828 * - dma_buf_map_attachment_unlocked()
829 * - dma_buf_unmap_attachment_unlocked()
830 * - dma_buf_vmap_unlocked()
831 * - dma_buf_vunmap_unlocked()
832 *
833 * Convention for exporters
834 *
835 * 1. These &dma_buf_ops callbacks are invoked with unlocked dma-buf
836 * reservation and exporter can take the lock:
837 *
838 * - &dma_buf_ops.attach()
839 * - &dma_buf_ops.detach()
840 * - &dma_buf_ops.release()
841 * - &dma_buf_ops.begin_cpu_access()
842 * - &dma_buf_ops.end_cpu_access()
843 *
844 * 2. These &dma_buf_ops callbacks are invoked with locked dma-buf
845 * reservation and exporter can't take the lock:
846 *
847 * - &dma_buf_ops.pin()
848 * - &dma_buf_ops.unpin()
849 * - &dma_buf_ops.map_dma_buf()
850 * - &dma_buf_ops.unmap_dma_buf()
851 * - &dma_buf_ops.mmap()
852 * - &dma_buf_ops.vmap()
853 * - &dma_buf_ops.vunmap()
854 *
855 * 3. Exporters must hold the dma-buf reservation lock when calling these
856 * functions:
857 *
858 * - dma_buf_move_notify()
859 */
860
798/**861/**
799 * dma_buf_dynamic_attach - Add the device to dma_buf's attachments list862 * dma_buf_dynamic_attach - Add the device to dma_buf's attachments list
800 * @dmabuf: [in] buffer to attach device to.863 * @dmabuf: [in] buffer to attach device to.
@@ -859,8 +922,8 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev, · 58 unmodified lines
859 dma_buf_is_dynamic(dmabuf)) {922 dma_buf_is_dynamic(dmabuf)) {
860 struct sg_table *sgt;923 struct sg_table *sgt;
861 924
925 dma_resv_lock(attach->dmabuf->resv, NULL);
862 if (dma_buf_is_dynamic(attach->dmabuf)) {926 if (dma_buf_is_dynamic(attach->dmabuf)) {
863 dma_resv_lock(attach->dmabuf->resv, NULL);
864 ret = dmabuf->ops->pin(attach);927 ret = dmabuf->ops->pin(attach);
865 if (ret)928 if (ret)
866 goto err_unlock;929 goto err_unlock;
@@ -873,8 +936,7 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev, · 6 unmodified lines
873 ret = PTR_ERR(sgt);936 ret = PTR_ERR(sgt);
874 goto err_unpin;937 goto err_unpin;
875 }938 }
876 if (dma_buf_is_dynamic(attach->dmabuf))939 dma_resv_unlock(attach->dmabuf->resv);
877 dma_resv_unlock(attach->dmabuf->resv);
878 attach->sgt = sgt;940 attach->sgt = sgt;
879 attach->dir = DMA_BIDIRECTIONAL;941 attach->dir = DMA_BIDIRECTIONAL;
880 }942 }
@@ -890,8 +952,7 @@ err_unpin: · 9 unmodified lines
890 dmabuf->ops->unpin(attach);952 dmabuf->ops->unpin(attach);
891 953
892err_unlock:954err_unlock:
893 if (dma_buf_is_dynamic(attach->dmabuf))955 dma_resv_unlock(attach->dmabuf->resv);
894 dma_resv_unlock(attach->dmabuf->resv);
895 956
896 dma_buf_detach(dmabuf, attach);957 dma_buf_detach(dmabuf, attach);
897 return ERR_PTR(ret);958 return ERR_PTR(ret);
@@ -937,21 +998,19 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach) · 39 unmodified lines
937 if (WARN_ON(!dmabuf || !attach))998 if (WARN_ON(!dmabuf || !attach))
938 return;999 return;
939 1000
1001 dma_resv_lock(attach->dmabuf->resv, NULL);
1002
940 if (attach->sgt) {1003 if (attach->sgt) {
941 if (dma_buf_is_dynamic(attach->dmabuf))
942 dma_resv_lock(attach->dmabuf->resv, NULL);
943 1004
944 __unmap_dma_buf(attach, attach->sgt, attach->dir);1005 __unmap_dma_buf(attach, attach->sgt, attach->dir);
945 1006
946 if (dma_buf_is_dynamic(attach->dmabuf)) {1007 if (dma_buf_is_dynamic(attach->dmabuf))
947 dmabuf->ops->unpin(attach);1008 dmabuf->ops->unpin(attach);
948 dma_resv_unlock(attach->dmabuf->resv);
949 }
950 }1009 }
951
952 dma_resv_lock(dmabuf->resv, NULL);
953 list_del(&attach->node);1010 list_del(&attach->node);
1011
954 dma_resv_unlock(dmabuf->resv);1012 dma_resv_unlock(dmabuf->resv);
1013
955 if (dmabuf->ops->detach)1014 if (dmabuf->ops->detach)
956 dmabuf->ops->detach(dmabuf, attach);1015 dmabuf->ops->detach(dmabuf, attach);
957 1016
@@ -1042,8 +1101,7 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, · 84 unmodified lines
1042 if (WARN_ON(!attach || !attach->dmabuf))1101 if (WARN_ON(!attach || !attach->dmabuf))
1043 return ERR_PTR(-EINVAL);1102 return ERR_PTR(-EINVAL);
1044 1103
1045 if (dma_buf_attachment_is_dynamic(attach))1104 dma_resv_assert_held(attach->dmabuf->resv);
1046 dma_resv_assert_held(attach->dmabuf->resv);
1047 1105
1048 if (attach->sgt) {1106 if (attach->sgt) {
1049 /*1107 /*
@@ -1058,7 +1116,6 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, · 8 unmodified lines
1058 }1116 }
1059 1117
1060 if (dma_buf_is_dynamic(attach->dmabuf)) {1118 if (dma_buf_is_dynamic(attach->dmabuf)) {
1061 dma_resv_assert_held(attach->dmabuf->resv);
1062 if (!IS_ENABLED(CONFIG_DMABUF_MOVE_NOTIFY)) {1119 if (!IS_ENABLED(CONFIG_DMABUF_MOVE_NOTIFY)) {
1063 r = attach->dmabuf->ops->pin(attach);1120 r = attach->dmabuf->ops->pin(attach);
1064 if (r)1121 if (r)
@@ -1100,6 +1157,34 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, · 35 unmodified lines
1100}1157}
1101EXPORT_SYMBOL_NS_GPL(dma_buf_map_attachment, DMA_BUF);1158EXPORT_SYMBOL_NS_GPL(dma_buf_map_attachment, DMA_BUF);
1102 1159
1160/**
1161 * dma_buf_map_attachment_unlocked - Returns the scatterlist table of the attachment;
1162 * mapped into _device_ address space. Is a wrapper for map_dma_buf() of the
1163 * dma_buf_ops.
1164 * @attach: [in] attachment whose scatterlist is to be returned
1165 * @direction: [in] direction of DMA transfer
1166 *
1167 * Unlocked variant of dma_buf_map_attachment().
1168 */
1169struct sg_table *
1170dma_buf_map_attachment_unlocked(struct dma_buf_attachment *attach,
1171 enum dma_data_direction direction)
1172{
1173 struct sg_table *sg_table;
1174
1175 might_sleep();
1176
1177 if (WARN_ON(!attach || !attach->dmabuf))
1178 return ERR_PTR(-EINVAL);
1179
1180 dma_resv_lock(attach->dmabuf->resv, NULL);
1181 sg_table = dma_buf_map_attachment(attach, direction);
1182 dma_resv_unlock(attach->dmabuf->resv);
1183
1184 return sg_table;
1185}
1186EXPORT_SYMBOL_NS_GPL(dma_buf_map_attachment_unlocked, DMA_BUF);
1187
1103/**1188/**
1104 * dma_buf_unmap_attachment - unmaps and decreases usecount of the buffer;might1189 * dma_buf_unmap_attachment - unmaps and decreases usecount of the buffer;might
1105 * deallocate the scatterlist associated. Is a wrapper for unmap_dma_buf() of1190 * deallocate the scatterlist associated. Is a wrapper for unmap_dma_buf() of
@@ -1119,15 +1204,11 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach, · 13 unmodified lines
1119 if (WARN_ON(!attach || !attach->dmabuf || !sg_table))1204 if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
1120 return;1205 return;
1121 1206
1122 if (dma_buf_attachment_is_dynamic(attach))1207 dma_resv_assert_held(attach->dmabuf->resv);
1123 dma_resv_assert_held(attach->dmabuf->resv);
1124 1208
1125 if (attach->sgt == sg_table)1209 if (attach->sgt == sg_table)
1126 return;1210 return;
1127 1211
1128 if (dma_buf_is_dynamic(attach->dmabuf))
1129 dma_resv_assert_held(attach->dmabuf->resv);
1130
1131 __unmap_dma_buf(attach, sg_table, direction);1212 __unmap_dma_buf(attach, sg_table, direction);
1132 1213
1133 if (dma_buf_is_dynamic(attach->dmabuf) &&1214 if (dma_buf_is_dynamic(attach->dmabuf) &&
@@ -1136,6 +1217,31 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach, · 2 unmodified lines
1136}1217}
1137EXPORT_SYMBOL_NS_GPL(dma_buf_unmap_attachment, DMA_BUF);1218EXPORT_SYMBOL_NS_GPL(dma_buf_unmap_attachment, DMA_BUF);
1138 1219
1220/**
1221 * dma_buf_unmap_attachment_unlocked - unmaps and decreases usecount of the buffer;might
1222 * deallocate the scatterlist associated. Is a wrapper for unmap_dma_buf() of
1223 * dma_buf_ops.
1224 * @attach: [in] attachment to unmap buffer from
1225 * @sg_table: [in] scatterlist info of the buffer to unmap
1226 * @direction: [in] direction of DMA transfer
1227 *
1228 * Unlocked variant of dma_buf_unmap_attachment().
1229 */
1230void dma_buf_unmap_attachment_unlocked(struct dma_buf_attachment *attach,
1231 struct sg_table *sg_table,
1232 enum dma_data_direction direction)
1233{
1234 might_sleep();
1235
1236 if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
1237 return;
1238
1239 dma_resv_lock(attach->dmabuf->resv, NULL);
1240 dma_buf_unmap_attachment(attach, sg_table, direction);
1241 dma_resv_unlock(attach->dmabuf->resv);
1242}
1243EXPORT_SYMBOL_NS_GPL(dma_buf_unmap_attachment_unlocked, DMA_BUF);
1244
1139/**1245/**
1140 * dma_buf_move_notify - notify attachments that DMA-buf is moving1246 * dma_buf_move_notify - notify attachments that DMA-buf is moving
1141 *1247 *
@@ -1347,6 +1453,8 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_end_cpu_access, DMA_BUF); · 205 unmodified lines
1347int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,1453int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,
1348 unsigned long pgoff)1454 unsigned long pgoff)
1349{1455{
1456 int ret;
1457
1350 if (WARN_ON(!dmabuf || !vma))1458 if (WARN_ON(!dmabuf || !vma))
1351 return -EINVAL;1459 return -EINVAL;
1352 1460
@@ -1367,7 +1475,11 @@ int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma, · 14 unmodified lines
1367 vma_set_file(vma, dmabuf->file);1475 vma_set_file(vma, dmabuf->file);
1368 vma->vm_pgoff = pgoff;1476 vma->vm_pgoff = pgoff;
1369 1477
1370 return dmabuf->ops->mmap(dmabuf, vma);1478 dma_resv_lock(dmabuf->resv, NULL);
1479 ret = dmabuf->ops->mmap(dmabuf, vma);
1480 dma_resv_unlock(dmabuf->resv);
1481
1482 return ret;
1371}1483}
1372EXPORT_SYMBOL_NS_GPL(dma_buf_mmap, DMA_BUF);1484EXPORT_SYMBOL_NS_GPL(dma_buf_mmap, DMA_BUF);
1373 1485
@@ -1390,41 +1502,67 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_mmap, DMA_BUF); · 16 unmodified lines
1390int dma_buf_vmap(struct dma_buf *dmabuf, struct iosys_map *map)1502int dma_buf_vmap(struct dma_buf *dmabuf, struct iosys_map *map)
1391{1503{
1392 struct iosys_map ptr;1504 struct iosys_map ptr;
1393 int ret = 0;1505 int ret;
1394 1506
1395 iosys_map_clear(map);1507 iosys_map_clear(map);
1396 1508
1397 if (WARN_ON(!dmabuf))1509 if (WARN_ON(!dmabuf))
1398 return -EINVAL;1510 return -EINVAL;
1399 1511
1512 dma_resv_assert_held(dmabuf->resv);
1513
1400 if (!dmabuf->ops->vmap)1514 if (!dmabuf->ops->vmap)
1401 return -EINVAL;1515 return -EINVAL;
1402 1516
1403 mutex_lock(&dmabuf->lock);
1404 if (dmabuf->vmapping_counter) {1517 if (dmabuf->vmapping_counter) {
1405 dmabuf->vmapping_counter++;1518 dmabuf->vmapping_counter++;
1406 BUG_ON(iosys_map_is_null(&dmabuf->vmap_ptr));1519 BUG_ON(iosys_map_is_null(&dmabuf->vmap_ptr));
1407 *map = dmabuf->vmap_ptr;1520 *map = dmabuf->vmap_ptr;
1408 goto out_unlock;1521 return 0;
1409 }1522 }
1410 1523
1411 BUG_ON(iosys_map_is_set(&dmabuf->vmap_ptr));1524 BUG_ON(iosys_map_is_set(&dmabuf->vmap_ptr));
1412 1525
1413 ret = dmabuf->ops->vmap(dmabuf, &ptr);1526 ret = dmabuf->ops->vmap(dmabuf, &ptr);
1414 if (WARN_ON_ONCE(ret))1527 if (WARN_ON_ONCE(ret))
1415 goto out_unlock;1528 return ret;
1416 1529
1417 dmabuf->vmap_ptr = ptr;1530 dmabuf->vmap_ptr = ptr;
1418 dmabuf->vmapping_counter = 1;1531 dmabuf->vmapping_counter = 1;
1419 1532
1420 *map = dmabuf->vmap_ptr;1533 *map = dmabuf->vmap_ptr;
1421 1534
1422out_unlock:1535 return 0;
1423 mutex_unlock(&dmabuf->lock);
1424 return ret;
1425}1536}
1426EXPORT_SYMBOL_NS_GPL(dma_buf_vmap, DMA_BUF);1537EXPORT_SYMBOL_NS_GPL(dma_buf_vmap, DMA_BUF);
1427 1538
1539/**
1540 * dma_buf_vmap_unlocked - Create virtual mapping for the buffer object into kernel
1541 * address space. Same restrictions as for vmap and friends apply.
1542 * @dmabuf: [in] buffer to vmap
1543 * @map: [out] returns the vmap pointer
1544 *
1545 * Unlocked version of dma_buf_vmap()
1546 *
1547 * Returns 0 on success, or a negative errno code otherwise.
1548 */
1549int dma_buf_vmap_unlocked(struct dma_buf *dmabuf, struct iosys_map *map)
1550{
1551 int ret;
1552
1553 iosys_map_clear(map);
1554
1555 if (WARN_ON(!dmabuf))
1556 return -EINVAL;
1557
1558 dma_resv_lock(dmabuf->resv, NULL);
1559 ret = dma_buf_vmap(dmabuf, map);
1560 dma_resv_unlock(dmabuf->resv);
1561
1562 return ret;
1563}
1564EXPORT_SYMBOL_NS_GPL(dma_buf_vmap_unlocked, DMA_BUF);
1565
1428/**1566/**
1429 * dma_buf_vunmap - Unmap a vmap obtained by dma_buf_vmap.1567 * dma_buf_vunmap - Unmap a vmap obtained by dma_buf_vmap.
1430 * @dmabuf: [in] buffer to vunmap1568 * @dmabuf: [in] buffer to vunmap
@@ -1435,20 +1573,36 @@ void dma_buf_vunmap(struct dma_buf *dmabuf, struct iosys_map *map) · 4 unmodified lines
1435 if (WARN_ON(!dmabuf))1573 if (WARN_ON(!dmabuf))
1436 return;1574 return;
1437 1575
1576 dma_resv_assert_held(dmabuf->resv);
1577
1438 BUG_ON(iosys_map_is_null(&dmabuf->vmap_ptr));1578 BUG_ON(iosys_map_is_null(&dmabuf->vmap_ptr));
1439 BUG_ON(dmabuf->vmapping_counter == 0);1579 BUG_ON(dmabuf->vmapping_counter == 0);
1440 BUG_ON(!iosys_map_is_equal(&dmabuf->vmap_ptr, map));1580 BUG_ON(!iosys_map_is_equal(&dmabuf->vmap_ptr, map));
1441 1581
1442 mutex_lock(&dmabuf->lock);
1443 if (--dmabuf->vmapping_counter == 0) {1582 if (--dmabuf->vmapping_counter == 0) {
1444 if (dmabuf->ops->vunmap)1583 if (dmabuf->ops->vunmap)
1445 dmabuf->ops->vunmap(dmabuf, map);1584 dmabuf->ops->vunmap(dmabuf, map);
1446 iosys_map_clear(&dmabuf->vmap_ptr);1585 iosys_map_clear(&dmabuf->vmap_ptr);
1447 }1586 }
1448 mutex_unlock(&dmabuf->lock);
1449}1587}
1450EXPORT_SYMBOL_NS_GPL(dma_buf_vunmap, DMA_BUF);1588EXPORT_SYMBOL_NS_GPL(dma_buf_vunmap, DMA_BUF);
1451 1589
1590/**
1591 * dma_buf_vunmap_unlocked - Unmap a vmap obtained by dma_buf_vmap.
1592 * @dmabuf: [in] buffer to vunmap
1593 * @map: [in] vmap pointer to vunmap
1594 */
1595void dma_buf_vunmap_unlocked(struct dma_buf *dmabuf, struct iosys_map *map)
1596{
1597 if (WARN_ON(!dmabuf))
1598 return;
1599
1600 dma_resv_lock(dmabuf->resv, NULL);
1601 dma_buf_vunmap(dmabuf, map);
1602 dma_resv_unlock(dmabuf->resv);
1603}
1604EXPORT_SYMBOL_NS_GPL(dma_buf_vunmap_unlocked, DMA_BUF);
1605
1452#ifdef CONFIG_DEBUG_FS1606#ifdef CONFIG_DEBUG_FS
1453static int dma_buf_debug_show(struct seq_file *s, void *unused)1607static int dma_buf_debug_show(struct seq_file *s, void *unused)
1454{1608{
drivers/gpu/drm/Makefile+77−30
@@ -5,32 +5,71 @@ · 4 unmodified lines
5 5
6CFLAGS-$(CONFIG_DRM_USE_DYNAMIC_DEBUG) += -DDYNAMIC_DEBUG_MODULE6CFLAGS-$(CONFIG_DRM_USE_DYNAMIC_DEBUG) += -DDYNAMIC_DEBUG_MODULE
7 7
8drm-y := drm_aperture.o drm_auth.o drm_cache.o \8drm-y := \
9 drm_file.o drm_gem.o drm_ioctl.o \9 drm_aperture.o \
10 drm_drv.o \10 drm_atomic.o \
11 drm_sysfs.o drm_mm.o \11 drm_atomic_uapi.o \
12 drm_crtc.o drm_fourcc.o drm_modes.o drm_edid.o drm_displayid.o \12 drm_auth.o \
13 drm_trace_points.o drm_prime.o \13 drm_blend.o \
14 drm_vma_manager.o \14 drm_bridge.o \
15 drm_modeset_lock.o drm_atomic.o drm_bridge.o \15 drm_cache.o \
16 drm_framebuffer.o drm_connector.o drm_blend.o \16 drm_client.o \
17 drm_encoder.o drm_mode_object.o drm_property.o \17 drm_client_modeset.o \
18 drm_plane.o drm_color_mgmt.o drm_print.o \18 drm_color_mgmt.o \
19 drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \19 drm_connector.o \
20 drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o \20 drm_crtc.o \
21 drm_client_modeset.o drm_atomic_uapi.o \21 drm_displayid.o \
22 drm_managed.o drm_vblank_work.o22 drm_drv.o \
23drm-$(CONFIG_DRM_LEGACY) += drm_agpsupport.o drm_bufs.o drm_context.o drm_dma.o \23 drm_dumb_buffers.o \
24 drm_hashtab.o drm_irq.o drm_legacy_misc.o drm_lock.o \24 drm_edid.o \
25 drm_memory.o drm_scatter.o drm_vm.o25 drm_encoder.o \
26 drm_file.o \
27 drm_fourcc.o \
28 drm_framebuffer.o \
29 drm_gem.o \
30 drm_ioctl.o \
31 drm_lease.o \
32 drm_managed.o \
33 drm_mm.o \
34 drm_mode_config.o \
35 drm_mode_object.o \
36 drm_modes.o \
37 drm_modeset_lock.o \
38 drm_plane.o \
39 drm_prime.o \
40 drm_print.o \
41 drm_property.o \
42 drm_syncobj.o \
43 drm_sysfs.o \
44 drm_trace_points.o \
45 drm_vblank.o \
46 drm_vblank_work.o \
47 drm_vma_manager.o \
48 drm_writeback.o
49drm-$(CONFIG_DRM_LEGACY) += \
50 drm_agpsupport.o \
51 drm_bufs.o \
52 drm_context.o \
53 drm_dma.o \
54 drm_hashtab.o \
55 drm_irq.o \
56 drm_legacy_misc.o \
57 drm_lock.o \
58 drm_memory.o \
59 drm_scatter.o \
60 drm_vm.o
26drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o61drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
27drm-$(CONFIG_COMPAT) += drm_ioc32.o62drm-$(CONFIG_COMPAT) += drm_ioc32.o
28drm-$(CONFIG_DRM_PANEL) += drm_panel.o63drm-$(CONFIG_DRM_PANEL) += drm_panel.o
29drm-$(CONFIG_OF) += drm_of.o64drm-$(CONFIG_OF) += drm_of.o
30drm-$(CONFIG_PCI) += drm_pci.o65drm-$(CONFIG_PCI) += drm_pci.o
31drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o66drm-$(CONFIG_DEBUG_FS) += \
67 drm_debugfs.o \
68 drm_debugfs_crc.o
32drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o69drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
33drm-$(CONFIG_DRM_PRIVACY_SCREEN) += drm_privacy_screen.o drm_privacy_screen_x86.o70drm-$(CONFIG_DRM_PRIVACY_SCREEN) += \
71 drm_privacy_screen.o \
72 drm_privacy_screen_x86.o
34obj-$(CONFIG_DRM) += drm.o73obj-$(CONFIG_DRM) += drm.o
35 74
36obj-$(CONFIG_DRM_NOMODESET) += drm_nomodeset.o75obj-$(CONFIG_DRM_NOMODESET) += drm_nomodeset.o
@@ -59,16 +98,24 @@ obj-$(CONFIG_DRM_TTM_HELPER) += drm_ttm_helper.o · 22 unmodified lines
59# Modesetting helpers98# Modesetting helpers
60#99#
61 100
62drm_kms_helper-y := drm_bridge_connector.o drm_crtc_helper.o \101drm_kms_helper-y := \
63 drm_encoder_slave.o drm_flip_work.o \102 drm_atomic_helper.o \
64 drm_probe_helper.o \103 drm_atomic_state_helper.o \
65 drm_plane_helper.o drm_atomic_helper.o \104 drm_bridge_connector.o \
66 drm_kms_helper_common.o \105 drm_crtc_helper.o \
67 drm_simple_kms_helper.o drm_modeset_helper.o \106 drm_damage_helper.o \
68 drm_gem_atomic_helper.o \107 drm_encoder_slave.o \
69 drm_gem_framebuffer_helper.o \108 drm_flip_work.o \
70 drm_atomic_state_helper.o drm_damage_helper.o \109 drm_format_helper.o \
71 drm_format_helper.o drm_self_refresh_helper.o drm_rect.o110 drm_gem_atomic_helper.o \
111 drm_gem_framebuffer_helper.o \
112 drm_kms_helper_common.o \
113 drm_modeset_helper.o \
114 drm_plane_helper.o \
115 drm_probe_helper.o \
116 drm_rect.o \
117 drm_self_refresh_helper.o \
118 drm_simple_kms_helper.o
72drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o119drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o
73drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o120drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
74obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o121obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c+0−2
@@ -498,8 +498,6 @@ static int amdgpu_vkms_sw_init(void *handle) · 497 unmodified lines
498 adev_to_drm(adev)->mode_config.preferred_depth = 24;498 adev_to_drm(adev)->mode_config.preferred_depth = 24;
499 adev_to_drm(adev)->mode_config.prefer_shadow = 1;499 adev_to_drm(adev)->mode_config.prefer_shadow = 1;
500 500
501 adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
502
503 r = amdgpu_display_modeset_create_props(adev);501 r = amdgpu_display_modeset_create_props(adev);
504 if (r)502 if (r)
505 return r;503 return r;
drivers/gpu/drm/amd/amdgpu/dce_v10_0.c+0−2
@@ -2800,8 +2800,6 @@ static int dce_v10_0_sw_init(void *handle) · 2799 unmodified lines
2800 2800
2801 adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true;2801 adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true;
2802 2802
2803 adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
2804
2805 r = amdgpu_display_modeset_create_props(adev);2803 r = amdgpu_display_modeset_create_props(adev);
2806 if (r)2804 if (r)
2807 return r;2805 return r;
drivers/gpu/drm/amd/amdgpu/dce_v11_0.c+0−2
@@ -2918,8 +2918,6 @@ static int dce_v11_0_sw_init(void *handle) · 2917 unmodified lines
2918 2918
2919 adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true;2919 adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true;
2920 2920
2921 adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
2922
2923 r = amdgpu_display_modeset_create_props(adev);2921 r = amdgpu_display_modeset_create_props(adev);
2924 if (r)2922 if (r)
2925 return r;2923 return r;
drivers/gpu/drm/amd/amdgpu/dce_v6_0.c+0−1
@@ -2675,7 +2675,6 @@ static int dce_v6_0_sw_init(void *handle) · 2674 unmodified lines
2675 adev_to_drm(adev)->mode_config.preferred_depth = 24;2675 adev_to_drm(adev)->mode_config.preferred_depth = 24;
2676 adev_to_drm(adev)->mode_config.prefer_shadow = 1;2676 adev_to_drm(adev)->mode_config.prefer_shadow = 1;
2677 adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true;2677 adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true;
2678 adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
2679 2678
2680 r = amdgpu_display_modeset_create_props(adev);2679 r = amdgpu_display_modeset_create_props(adev);
2681 if (r)2680 if (r)
drivers/gpu/drm/amd/amdgpu/dce_v8_0.c+0−2
@@ -2701,8 +2701,6 @@ static int dce_v8_0_sw_init(void *handle) · 2700 unmodified lines
2701 2701
2702 adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true;2702 adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true;
2703 2703
2704 adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
2705
2706 r = amdgpu_display_modeset_create_props(adev);2704 r = amdgpu_display_modeset_create_props(adev);
2707 if (r)2705 if (r)
2708 return r;2706 return r;
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c+0−2
@@ -3816,8 +3816,6 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) · 3815 unmodified lines
3816 /* indicates support for immediate flip */3816 /* indicates support for immediate flip */
3817 adev_to_drm(adev)->mode_config.async_page_flip = true;3817 adev_to_drm(adev)->mode_config.async_page_flip = true;
3818 3818
3819 adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
3820
3821 state = kzalloc(sizeof(*state), GFP_KERNEL);3819 state = kzalloc(sizeof(*state), GFP_KERNEL);
3822 if (!state)3820 if (!state)
3823 return -ENOMEM;3821 return -ENOMEM;
drivers/gpu/drm/armada/armada_gem.c+4−4
@@ -66,8 +66,8 @@ void armada_gem_free_object(struct drm_gem_object *obj) · 65 unmodified lines
66 if (dobj->obj.import_attach) {66 if (dobj->obj.import_attach) {
67 /* We only ever display imported data */67 /* We only ever display imported data */
68 if (dobj->sgt)68 if (dobj->sgt)
69 dma_buf_unmap_attachment(dobj->obj.import_attach,69 dma_buf_unmap_attachment_unlocked(dobj->obj.import_attach,
70 dobj->sgt, DMA_TO_DEVICE);70 dobj->sgt, DMA_TO_DEVICE);
71 drm_prime_gem_destroy(&dobj->obj, NULL);71 drm_prime_gem_destroy(&dobj->obj, NULL);
72 }72 }
73 73
@@ -539,8 +539,8 @@ int armada_gem_map_import(struct armada_gem_object *dobj) · 465 unmodified lines
539{539{
540 int ret;540 int ret;
541 541
542 dobj->sgt = dma_buf_map_attachment(dobj->obj.import_attach,542 dobj->sgt = dma_buf_map_attachment_unlocked(dobj->obj.import_attach,
543 DMA_TO_DEVICE);543 DMA_TO_DEVICE);
544 if (IS_ERR(dobj->sgt)) {544 if (IS_ERR(dobj->sgt)) {
545 ret = PTR_ERR(dobj->sgt);545 ret = PTR_ERR(dobj->sgt);
546 dobj->sgt = NULL;546 dobj->sgt = NULL;
drivers/gpu/drm/ast/Kconfig+1−3
@@ -2,10 +2,8 @@ · 1 unmodified line
2config DRM_AST2config DRM_AST
3 tristate "AST server chips"3 tristate "AST server chips"
4 depends on DRM && PCI && MMU4 depends on DRM && PCI && MMU
5 select DRM_GEM_SHMEM_HELPER
5 select DRM_KMS_HELPER6 select DRM_KMS_HELPER
6 select DRM_VRAM_HELPER
7 select DRM_TTM
8 select DRM_TTM_HELPER
9 help7 help
10 Say yes for experimental AST GPU driver. Do not enable8 Say yes for experimental AST GPU driver. Do not enable
11 this driver without having a working -modesetting,9 this driver without having a working -modesetting,
drivers/gpu/drm/ast/ast_drv.c+2−2
@@ -33,7 +33,7 @@ · 32 unmodified lines
33#include <drm/drm_atomic_helper.h>33#include <drm/drm_atomic_helper.h>
34#include <drm/drm_crtc_helper.h>34#include <drm/drm_crtc_helper.h>
35#include <drm/drm_drv.h>35#include <drm/drm_drv.h>
36#include <drm/drm_gem_vram_helper.h>36#include <drm/drm_gem_shmem_helper.h>
37#include <drm/drm_module.h>37#include <drm/drm_module.h>
38#include <drm/drm_probe_helper.h>38#include <drm/drm_probe_helper.h>
39 39
@@ -63,7 +63,7 @@ static const struct drm_driver ast_driver = { · 23 unmodified lines
63 .minor = DRIVER_MINOR,63 .minor = DRIVER_MINOR,
64 .patchlevel = DRIVER_PATCHLEVEL,64 .patchlevel = DRIVER_PATCHLEVEL,
65 65
66 DRM_GEM_VRAM_DRIVER66 DRM_GEM_SHMEM_DRIVER_OPS
67};67};
68 68
69/*69/*
drivers/gpu/drm/ast/ast_drv.h+18−16
@@ -87,7 +87,7 @@ enum ast_tx_chip { · 86 unmodified lines
87#define AST_DRAM_8Gx16 887#define AST_DRAM_8Gx16 8
88 88
89/*89/*
90 * Cursor plane90 * Hardware cursor
91 */91 */
92 92
93#define AST_MAX_HWC_WIDTH 6493#define AST_MAX_HWC_WIDTH 64
@@ -96,8 +96,6 @@ enum ast_tx_chip { · 2 unmodified lines
96#define AST_HWC_SIZE (AST_MAX_HWC_WIDTH * AST_MAX_HWC_HEIGHT * 2)96#define AST_HWC_SIZE (AST_MAX_HWC_WIDTH * AST_MAX_HWC_HEIGHT * 2)
97#define AST_HWC_SIGNATURE_SIZE 3297#define AST_HWC_SIGNATURE_SIZE 32
98 98
99#define AST_DEFAULT_HWC_NUM 2
100
101/* define for signature structure */99/* define for signature structure */
102#define AST_HWC_SIGNATURE_CHECKSUM 0x00100#define AST_HWC_SIGNATURE_CHECKSUM 0x00
103#define AST_HWC_SIGNATURE_SizeX 0x04101#define AST_HWC_SIGNATURE_SizeX 0x04
@@ -107,22 +105,21 @@ enum ast_tx_chip { · 3 unmodified lines
107#define AST_HWC_SIGNATURE_HOTSPOTX 0x14105#define AST_HWC_SIGNATURE_HOTSPOTX 0x14
108#define AST_HWC_SIGNATURE_HOTSPOTY 0x18106#define AST_HWC_SIGNATURE_HOTSPOTY 0x18
109 107
110struct ast_cursor_plane {108/*
111 struct drm_plane base;109 * Planes
110 */
112 111
113 struct {112struct ast_plane {
114 struct drm_gem_vram_object *gbo;113 struct drm_plane base;
115 struct iosys_map map;
116 u64 off;
117 } hwc[AST_DEFAULT_HWC_NUM];
118 114
119 unsigned int next_hwc_index;115 void __iomem *vaddr;
116 u64 offset;
117 unsigned long size;
120};118};
121 119
122static inline struct ast_cursor_plane *120static inline struct ast_plane *to_ast_plane(struct drm_plane *plane)
123to_ast_cursor_plane(struct drm_plane *plane)
124{121{
125 return container_of(plane, struct ast_cursor_plane, base);122 return container_of(plane, struct ast_plane, base);
126}123}
127 124
128/*125/*
@@ -175,8 +172,13 @@ struct ast_private { · 46 unmodified lines
175 uint32_t dram_type;172 uint32_t dram_type;
176 uint32_t mclk;173 uint32_t mclk;
177 174
178 struct drm_plane primary_plane;175 void __iomem *vram;
179 struct ast_cursor_plane cursor_plane;176 unsigned long vram_base;
177 unsigned long vram_size;
178 unsigned long vram_fb_available;
179
180 struct ast_plane primary_plane;
181 struct ast_plane cursor_plane;
180 struct drm_crtc crtc;182 struct drm_crtc crtc;
181 struct {183 struct {
182 struct {184 struct {
drivers/gpu/drm/ast/ast_main.c+2−3
@@ -32,7 +32,6 @@ · 31 unmodified lines
32#include <drm/drm_crtc_helper.h>32#include <drm/drm_crtc_helper.h>
33#include <drm/drm_drv.h>33#include <drm/drm_drv.h>
34#include <drm/drm_gem.h>34#include <drm/drm_gem.h>
35#include <drm/drm_gem_vram_helper.h>
36#include <drm/drm_managed.h>35#include <drm/drm_managed.h>
37 36
38#include "ast_drv.h"37#include "ast_drv.h"
@@ -461,8 +460,8 @@ struct ast_private *ast_device_create(const struct drm_driver *drv, · 422 unmodified lines
461 460
462 /* map reserved buffer */461 /* map reserved buffer */
463 ast->dp501_fw_buf = NULL;462 ast->dp501_fw_buf = NULL;
464 if (dev->vram_mm->vram_size < pci_resource_len(pdev, 0)) {463 if (ast->vram_size < pci_resource_len(pdev, 0)) {
465 ast->dp501_fw_buf = pci_iomap_range(pdev, 0, dev->vram_mm->vram_size, 0);464 ast->dp501_fw_buf = pci_iomap_range(pdev, 0, ast->vram_size, 0);
466 if (!ast->dp501_fw_buf)465 if (!ast->dp501_fw_buf)
467 drm_info(dev, "failed to map reserved buffer!\n");466 drm_info(dev, "failed to map reserved buffer!\n");
468 }467 }
drivers/gpu/drm/ast/ast_mm.c+7−7
@@ -28,7 +28,6 @@ · 27 unmodified lines
28 28
29#include <linux/pci.h>29#include <linux/pci.h>
30 30
31#include <drm/drm_gem_vram_helper.h>
32#include <drm/drm_managed.h>31#include <drm/drm_managed.h>
33#include <drm/drm_print.h>32#include <drm/drm_print.h>
34 33
@@ -80,7 +79,6 @@ int ast_mm_init(struct ast_private *ast) · 45 unmodified lines
80 struct pci_dev *pdev = to_pci_dev(dev->dev);79 struct pci_dev *pdev = to_pci_dev(dev->dev);
81 resource_size_t base, size;80 resource_size_t base, size;
82 u32 vram_size;81 u32 vram_size;
83 int ret;
84 82
85 base = pci_resource_start(pdev, 0);83 base = pci_resource_start(pdev, 0);
86 size = pci_resource_len(pdev, 0);84 size = pci_resource_len(pdev, 0);
@@ -91,11 +89,13 @@ int ast_mm_init(struct ast_private *ast) · 4 unmodified lines
91 89
92 vram_size = ast_get_vram_size(ast);90 vram_size = ast_get_vram_size(ast);
93 91
94 ret = drmm_vram_helper_init(dev, base, vram_size);92 ast->vram = devm_ioremap_wc(dev->dev, base, vram_size);
95 if (ret) {93 if (!ast->vram)
96 drm_err(dev, "Error initializing VRAM MM; %d\n", ret);94 return -ENOMEM;
97 return ret;95
98 }96 ast->vram_base = base;
97 ast->vram_size = vram_size;
98 ast->vram_fb_available = vram_size;
99 99
100 return 0;100 return 0;
101}101}
drivers/gpu/drm/ast/ast_mode.c+265−234
@@ -36,11 +36,13 @@ · 35 unmodified lines
36#include <drm/drm_atomic_state_helper.h>36#include <drm/drm_atomic_state_helper.h>
37#include <drm/drm_crtc.h>37#include <drm/drm_crtc.h>
38#include <drm/drm_crtc_helper.h>38#include <drm/drm_crtc_helper.h>
39#include <drm/drm_damage_helper.h>
39#include <drm/drm_edid.h>40#include <drm/drm_edid.h>
41#include <drm/drm_format_helper.h>
40#include <drm/drm_fourcc.h>42#include <drm/drm_fourcc.h>
41#include <drm/drm_gem_atomic_helper.h>43#include <drm/drm_gem_atomic_helper.h>
42#include <drm/drm_gem_framebuffer_helper.h>44#include <drm/drm_gem_framebuffer_helper.h>
43#include <drm/drm_gem_vram_helper.h>45#include <drm/drm_gem_shmem_helper.h>
44#include <drm/drm_managed.h>46#include <drm/drm_managed.h>
45#include <drm/drm_probe_helper.h>47#include <drm/drm_probe_helper.h>
46#include <drm/drm_simple_kms_helper.h>48#include <drm/drm_simple_kms_helper.h>
@@ -48,6 +50,8 @@ · 1 unmodified line
48#include "ast_drv.h"50#include "ast_drv.h"
49#include "ast_tables.h"51#include "ast_tables.h"
50 52
53#define AST_LUT_SIZE 256
54
51static inline void ast_load_palette_index(struct ast_private *ast,55static inline void ast_load_palette_index(struct ast_private *ast,
52 u8 index, u8 red, u8 green,56 u8 index, u8 red, u8 green,
53 u8 blue)57 u8 blue)
@@ -62,20 +66,46 @@ static inline void ast_load_palette_index(struct ast_private *ast, · 8 unmodified lines
62 ast_io_read8(ast, AST_IO_SEQ_PORT);66 ast_io_read8(ast, AST_IO_SEQ_PORT);
63}67}
64 68
65static void ast_crtc_load_lut(struct ast_private *ast, struct drm_crtc *crtc)69static void ast_crtc_set_gamma_linear(struct ast_private *ast,
70 const struct drm_format_info *format)
66{71{
67 u16 *r, *g, *b;
68 int i;72 int i;
69 73
70 if (!crtc->enabled)74 switch (format->format) {
71 return;75 case DRM_FORMAT_C8: /* In this case, gamma table is used as color palette */
76 case DRM_FORMAT_RGB565:
77 case DRM_FORMAT_XRGB8888:
78 for (i = 0; i < AST_LUT_SIZE; i++)
79 ast_load_palette_index(ast, i, i, i, i);
80 break;
81 default:
82 drm_warn_once(&ast->base, "Unsupported format %p4cc for gamma correction\n",
83 &format->format);
84 break;
85 }
86}
72 87
73 r = crtc->gamma_store;88static void ast_crtc_set_gamma(struct ast_private *ast,
74 g = r + crtc->gamma_size;89 const struct drm_format_info *format,
75 b = g + crtc->gamma_size;90 struct drm_color_lut *lut)
91{
92 int i;
76 93
77 for (i = 0; i < 256; i++)94 switch (format->format) {
78 ast_load_palette_index(ast, i, *r++ >> 8, *g++ >> 8, *b++ >> 8);95 case DRM_FORMAT_C8: /* In this case, gamma table is used as color palette */
96 case DRM_FORMAT_RGB565:
97 case DRM_FORMAT_XRGB8888:
98 for (i = 0; i < AST_LUT_SIZE; i++)
99 ast_load_palette_index(ast, i,
100 lut[i].red >> 8,
101 lut[i].green >> 8,
102 lut[i].blue >> 8);
103 break;
104 default:
105 drm_warn_once(&ast->base, "Unsupported format %p4cc for gamma correction\n",
106 &format->format);
107 break;
108 }
79}109}
80 110
81static bool ast_get_vbios_mode_info(const struct drm_format_info *format,111static bool ast_get_vbios_mode_info(const struct drm_format_info *format,
@@ -537,6 +567,29 @@ static void ast_wait_for_vretrace(struct ast_private *ast) · 455 unmodified lines
537 } while (!(vgair1 & AST_IO_VGAIR1_VREFRESH) && time_before(jiffies, timeout));567 } while (!(vgair1 & AST_IO_VGAIR1_VREFRESH) && time_before(jiffies, timeout));
538}568}
539 569
570/*
571 * Planes
572 */
573
574static int ast_plane_init(struct drm_device *dev, struct ast_plane *ast_plane,
575 void __iomem *vaddr, u64 offset, unsigned long size,
576 uint32_t possible_crtcs,
577 const struct drm_plane_funcs *funcs,
578 const uint32_t *formats, unsigned int format_count,
579 const uint64_t *format_modifiers,
580 enum drm_plane_type type)
581{
582 struct drm_plane *plane = &ast_plane->base;
583
584 ast_plane->vaddr = vaddr;
585 ast_plane->offset = offset;
586 ast_plane->size = size;
587
588 return drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
589 formats, format_count, format_modifiers,
590 type, NULL);
591}
592
540/*593/*
541 * Primary plane594 * Primary plane
542 */595 */
@@ -550,52 +603,62 @@ static const uint32_t ast_primary_plane_formats[] = { · 7 unmodified lines
550static int ast_primary_plane_helper_atomic_check(struct drm_plane *plane,603static int ast_primary_plane_helper_atomic_check(struct drm_plane *plane,
551 struct drm_atomic_state *state)604 struct drm_atomic_state *state)
552{605{
553 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,606 struct drm_device *dev = plane->dev;
554 plane);607 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
555 struct drm_crtc_state *crtc_state;608 struct drm_crtc_state *new_crtc_state = NULL;
556 struct ast_crtc_state *ast_crtc_state;609 struct ast_crtc_state *new_ast_crtc_state;
557 int ret;610 int ret;
558 611
559 if (!new_plane_state->crtc)612 if (new_plane_state->crtc)
560 return 0;613 new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc);
561
562 crtc_state = drm_atomic_get_new_crtc_state(state,
563 new_plane_state->crtc);
564 614
565 ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,615 ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
566 DRM_PLANE_NO_SCALING,616 DRM_PLANE_NO_SCALING,
567 DRM_PLANE_NO_SCALING,617 DRM_PLANE_NO_SCALING,
568 false, true);618 false, true);
569 if (ret)619 if (ret) {
570 return ret;620 return ret;
621 } else if (!new_plane_state->visible) {
622 if (drm_WARN_ON(dev, new_plane_state->crtc)) /* cannot legally happen */
623 return -EINVAL;
624 else
625 return 0;
626 }
571 627
572 if (!new_plane_state->visible)628 new_ast_crtc_state = to_ast_crtc_state(new_crtc_state);
573 return 0;
574
575 ast_crtc_state = to_ast_crtc_state(crtc_state);
576 629
577 ast_crtc_state->format = new_plane_state->fb->format;630 new_ast_crtc_state->format = new_plane_state->fb->format;
578 631
579 return 0;632 return 0;
580}633}
581 634
582static void635static void ast_handle_damage(struct ast_plane *ast_plane, struct iosys_map *src,
583ast_primary_plane_helper_atomic_update(struct drm_plane *plane,636 struct drm_framebuffer *fb,
584 struct drm_atomic_state *state)637 const struct drm_rect *clip)
638{
639 struct iosys_map dst = IOSYS_MAP_INIT_VADDR(ast_plane->vaddr);
640
641 iosys_map_incr(&dst, drm_fb_clip_offset(fb->pitches[0], fb->format, clip));
642 drm_fb_memcpy(&dst, fb->pitches, src, fb, clip);
643}
644
645static void ast_primary_plane_helper_atomic_update(struct drm_plane *plane,
646 struct drm_atomic_state *state)
585{647{
586 struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
587 plane);
588 struct drm_device *dev = plane->dev;648 struct drm_device *dev = plane->dev;
589 struct ast_private *ast = to_ast_private(dev);649 struct ast_private *ast = to_ast_private(dev);
590 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,650 struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
591 plane);651 struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
592 struct drm_gem_vram_object *gbo;652 struct drm_framebuffer *fb = plane_state->fb;
593 s64 gpu_addr;653 struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
594 struct drm_framebuffer *fb = new_state->fb;654 struct drm_framebuffer *old_fb = old_plane_state->fb;
595 struct drm_framebuffer *old_fb = old_state->fb;655 struct ast_plane *ast_plane = to_ast_plane(plane);
656 struct drm_rect damage;
657 struct drm_atomic_helper_damage_iter iter;
596 658
597 if (!old_fb || (fb->format != old_fb->format)) {659 if (!old_fb || (fb->format != old_fb->format)) {
598 struct drm_crtc_state *crtc_state = new_state->crtc->state;660 struct drm_crtc *crtc = plane_state->crtc;
661 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
599 struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);662 struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
600 struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;663 struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;
601 664
@@ -603,20 +666,28 @@ ast_primary_plane_helper_atomic_update(struct drm_plane *plane, · 1 unmodified line
603 ast_set_vbios_color_reg(ast, fb->format, vbios_mode_info);666 ast_set_vbios_color_reg(ast, fb->format, vbios_mode_info);
604 }667 }
605 668
606 gbo = drm_gem_vram_of_gem(fb->obj[0]);669 drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
607 gpu_addr = drm_gem_vram_offset(gbo);670 drm_atomic_for_each_plane_damage(&iter, &damage) {
608 if (drm_WARN_ON_ONCE(dev, gpu_addr < 0))671 ast_handle_damage(ast_plane, shadow_plane_state->data, fb, &damage);
609 return; /* Bug: we didn't pin the BO to VRAM in prepare_fb. */672 }
610
611 ast_set_offset_reg(ast, fb);
612 ast_set_start_address_crt1(ast, (u32)gpu_addr);
613 673
614 ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x00);674 /*
675 * Some BMCs stop scanning out the video signal after the driver
676 * reprogrammed the offset or scanout address. This stalls display
677 * output for several seconds and makes the display unusable.
678 * Therefore only update the offset if it changes and reprogram the
679 * address after enabling the plane.
680 */
681 if (!old_fb || old_fb->pitches[0] != fb->pitches[0])
682 ast_set_offset_reg(ast, fb);
683 if (!old_fb) {
684 ast_set_start_address_crt1(ast, (u32)ast_plane->offset);
685 ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x00);
686 }
615}687}
616 688
617static void689static void ast_primary_plane_helper_atomic_disable(struct drm_plane *plane,
618ast_primary_plane_helper_atomic_disable(struct drm_plane *plane,690 struct drm_atomic_state *state)
619 struct drm_atomic_state *state)
620{691{
621 struct ast_private *ast = to_ast_private(plane->dev);692 struct ast_private *ast = to_ast_private(plane->dev);
622 693
@@ -624,7 +695,7 @@ ast_primary_plane_helper_atomic_disable(struct drm_plane *plane, · 1 unmodified line
624}695}
625 696
626static const struct drm_plane_helper_funcs ast_primary_plane_helper_funcs = {697static const struct drm_plane_helper_funcs ast_primary_plane_helper_funcs = {
627 DRM_GEM_VRAM_PLANE_HELPER_FUNCS,698 DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
628 .atomic_check = ast_primary_plane_helper_atomic_check,699 .atomic_check = ast_primary_plane_helper_atomic_check,
629 .atomic_update = ast_primary_plane_helper_atomic_update,700 .atomic_update = ast_primary_plane_helper_atomic_update,
630 .atomic_disable = ast_primary_plane_helper_atomic_disable,701 .atomic_disable = ast_primary_plane_helper_atomic_disable,
@@ -634,27 +705,30 @@ static const struct drm_plane_funcs ast_primary_plane_funcs = { · 3 unmodified lines
634 .update_plane = drm_atomic_helper_update_plane,705 .update_plane = drm_atomic_helper_update_plane,
635 .disable_plane = drm_atomic_helper_disable_plane,706 .disable_plane = drm_atomic_helper_disable_plane,
636 .destroy = drm_plane_cleanup,707 .destroy = drm_plane_cleanup,
637 .reset = drm_atomic_helper_plane_reset,708 DRM_GEM_SHADOW_PLANE_FUNCS,
638 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
639 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
640};709};
641 710
642static int ast_primary_plane_init(struct ast_private *ast)711static int ast_primary_plane_init(struct ast_private *ast)
643{712{
644 struct drm_device *dev = &ast->base;713 struct drm_device *dev = &ast->base;
645 struct drm_plane *primary_plane = &ast->primary_plane;714 struct ast_plane *ast_primary_plane = &ast->primary_plane;
715 struct drm_plane *primary_plane = &ast_primary_plane->base;
716 void __iomem *vaddr = ast->vram;
717 u64 offset = ast->vram_base;
718 unsigned long cursor_size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE);
719 unsigned long size = ast->vram_fb_available - cursor_size;
646 int ret;720 int ret;
647 721
648 ret = drm_universal_plane_init(dev, primary_plane, 0x01,722 ret = ast_plane_init(dev, ast_primary_plane, vaddr, offset, size,
649 &ast_primary_plane_funcs,723 0x01, &ast_primary_plane_funcs,
650 ast_primary_plane_formats,724 ast_primary_plane_formats, ARRAY_SIZE(ast_primary_plane_formats),
651 ARRAY_SIZE(ast_primary_plane_formats),725 NULL, DRM_PLANE_TYPE_PRIMARY);
652 NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
653 if (ret) {726 if (ret) {
654 drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);727 drm_err(dev, "ast_plane_init() failed: %d\n", ret);
655 return ret;728 return ret;
656 }729 }
657 drm_plane_helper_add(primary_plane, &ast_primary_plane_helper_funcs);730 drm_plane_helper_add(primary_plane, &ast_primary_plane_helper_funcs);
731 drm_plane_enable_fb_damage_clips(primary_plane);
658 732
659 return 0;733 return 0;
660}734}
@@ -774,99 +848,79 @@ static const uint32_t ast_cursor_plane_formats[] = { · 113 unmodified lines
774static int ast_cursor_plane_helper_atomic_check(struct drm_plane *plane,848static int ast_cursor_plane_helper_atomic_check(struct drm_plane *plane,
775 struct drm_atomic_state *state)849 struct drm_atomic_state *state)
776{850{
777 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,851 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
778 plane);852 struct drm_framebuffer *new_fb = new_plane_state->fb;
779 struct drm_framebuffer *fb = new_plane_state->fb;853 struct drm_crtc_state *new_crtc_state = NULL;
780 struct drm_crtc_state *crtc_state;
781 int ret;854 int ret;
782 855
783 if (!new_plane_state->crtc)856 if (new_plane_state->crtc)
784 return 0;857 new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc);
785
786 crtc_state = drm_atomic_get_new_crtc_state(state,
787 new_plane_state->crtc);
788 858
789 ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,859 ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
790 DRM_PLANE_NO_SCALING,860 DRM_PLANE_NO_SCALING,
791 DRM_PLANE_NO_SCALING,861 DRM_PLANE_NO_SCALING,
792 true, true);862 true, true);
793 if (ret)863 if (ret || !new_plane_state->visible)
794 return ret;864 return ret;
795 865
796 if (!new_plane_state->visible)866 if (new_fb->width > AST_MAX_HWC_WIDTH || new_fb->height > AST_MAX_HWC_HEIGHT)
797 return 0;
798
799 if (fb->width > AST_MAX_HWC_WIDTH || fb->height > AST_MAX_HWC_HEIGHT)
800 return -EINVAL;867 return -EINVAL;
801 868
802 return 0;869 return 0;
803}870}
804 871
805static void872static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane,
806ast_cursor_plane_helper_atomic_update(struct drm_plane *plane,873 struct drm_atomic_state *state)
807 struct drm_atomic_state *state)
808{874{
809 struct ast_cursor_plane *ast_cursor_plane = to_ast_cursor_plane(plane);875 struct ast_plane *ast_plane = to_ast_plane(plane);
810 struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,876 struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
811 plane);877 struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
812 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,878 struct drm_framebuffer *fb = plane_state->fb;
813 plane);879 struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
814 struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(new_state);
815 struct drm_framebuffer *fb = new_state->fb;
816 struct ast_private *ast = to_ast_private(plane->dev);880 struct ast_private *ast = to_ast_private(plane->dev);
817 struct iosys_map dst_map =
818 ast_cursor_plane->hwc[ast_cursor_plane->next_hwc_index].map;
819 u64 dst_off =
820 ast_cursor_plane->hwc[ast_cursor_plane->next_hwc_index].off;
821 struct iosys_map src_map = shadow_plane_state->data[0];881 struct iosys_map src_map = shadow_plane_state->data[0];
882 struct drm_rect damage;
883 const u8 *src = src_map.vaddr; /* TODO: Use mapping abstraction properly */
884 u64 dst_off = ast_plane->offset;
885 u8 __iomem *dst = ast_plane->vaddr; /* TODO: Use mapping abstraction properly */
886 u8 __iomem *sig = dst + AST_HWC_SIZE; /* TODO: Use mapping abstraction properly */
822 unsigned int offset_x, offset_y;887 unsigned int offset_x, offset_y;
823 u16 x, y;888 u16 x, y;
824 u8 x_offset, y_offset;889 u8 x_offset, y_offset;
825 u8 __iomem *dst;
826 u8 __iomem *sig;
827 const u8 *src;
828
829 src = src_map.vaddr; /* TODO: Use mapping abstraction properly */
830 dst = dst_map.vaddr_iomem; /* TODO: Use mapping abstraction properly */
831 sig = dst + AST_HWC_SIZE; /* TODO: Use mapping abstraction properly */
832 890
833 /*891 /*
834 * Do data transfer to HW cursor BO. If a new cursor image was installed,892 * Do data transfer to hardware buffer and point the scanout
835 * point the scanout engine to dst_gbo's offset and page-flip the HWC buffers.893 * engine to the offset.
836 */894 */
837 895
838 ast_update_cursor_image(dst, src, fb->width, fb->height);896 if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &damage)) {
839 897 ast_update_cursor_image(dst, src, fb->width, fb->height);
840 if (new_state->fb != old_state->fb) {
841 ast_set_cursor_base(ast, dst_off);898 ast_set_cursor_base(ast, dst_off);
842
843 ++ast_cursor_plane->next_hwc_index;
844 ast_cursor_plane->next_hwc_index %= ARRAY_SIZE(ast_cursor_plane->hwc);
845 }899 }
846 900
847 /*901 /*
848 * Update location in HWC signature and registers.902 * Update location in HWC signature and registers.
849 */903 */
850 904
851 writel(new_state->crtc_x, sig + AST_HWC_SIGNATURE_X);905 writel(plane_state->crtc_x, sig + AST_HWC_SIGNATURE_X);
852 writel(new_state->crtc_y, sig + AST_HWC_SIGNATURE_Y);906 writel(plane_state->crtc_y, sig + AST_HWC_SIGNATURE_Y);
853 907
854 offset_x = AST_MAX_HWC_WIDTH - fb->width;908 offset_x = AST_MAX_HWC_WIDTH - fb->width;
855 offset_y = AST_MAX_HWC_HEIGHT - fb->height;909 offset_y = AST_MAX_HWC_HEIGHT - fb->height;
856 910
857 if (new_state->crtc_x < 0) {911 if (plane_state->crtc_x < 0) {
858 x_offset = (-new_state->crtc_x) + offset_x;912 x_offset = (-plane_state->crtc_x) + offset_x;
859 x = 0;913 x = 0;
860 } else {914 } else {
861 x_offset = offset_x;915 x_offset = offset_x;
862 x = new_state->crtc_x;916 x = plane_state->crtc_x;
863 }917 }
864 if (new_state->crtc_y < 0) {918 if (plane_state->crtc_y < 0) {
865 y_offset = (-new_state->crtc_y) + offset_y;919 y_offset = (-plane_state->crtc_y) + offset_y;
866 y = 0;920 y = 0;
867 } else {921 } else {
868 y_offset = offset_y;922 y_offset = offset_y;
869 y = new_state->crtc_y;923 y = plane_state->crtc_y;
870 }924 }
871 925
872 ast_set_cursor_location(ast, x, y, x_offset, y_offset);926 ast_set_cursor_location(ast, x, y, x_offset, y_offset);
@@ -875,9 +929,8 @@ ast_cursor_plane_helper_atomic_update(struct drm_plane *plane, · 2 unmodified lines
875 ast_set_cursor_enabled(ast, true);929 ast_set_cursor_enabled(ast, true);
876}930}
877 931
878static void932static void ast_cursor_plane_helper_atomic_disable(struct drm_plane *plane,
879ast_cursor_plane_helper_atomic_disable(struct drm_plane *plane,933 struct drm_atomic_state *state)
880 struct drm_atomic_state *state)
881{934{
882 struct ast_private *ast = to_ast_private(plane->dev);935 struct ast_private *ast = to_ast_private(plane->dev);
883 936
@@ -891,41 +944,22 @@ static const struct drm_plane_helper_funcs ast_cursor_plane_helper_funcs = { · 7 unmodified lines
891 .atomic_disable = ast_cursor_plane_helper_atomic_disable,944 .atomic_disable = ast_cursor_plane_helper_atomic_disable,
892};945};
893 946
894static void ast_cursor_plane_destroy(struct drm_plane *plane)
895{
896 struct ast_cursor_plane *ast_cursor_plane = to_ast_cursor_plane(plane);
897 size_t i;
898 struct drm_gem_vram_object *gbo;
899 struct iosys_map map;
900
901 for (i = 0; i < ARRAY_SIZE(ast_cursor_plane->hwc); ++i) {
902 gbo = ast_cursor_plane->hwc[i].gbo;
903 map = ast_cursor_plane->hwc[i].map;
904 drm_gem_vram_vunmap(gbo, &map);
905 drm_gem_vram_unpin(gbo);
906 drm_gem_vram_put(gbo);
907 }
908
909 drm_plane_cleanup(plane);
910}
911
912static const struct drm_plane_funcs ast_cursor_plane_funcs = {947static const struct drm_plane_funcs ast_cursor_plane_funcs = {
913 .update_plane = drm_atomic_helper_update_plane,948 .update_plane = drm_atomic_helper_update_plane,
914 .disable_plane = drm_atomic_helper_disable_plane,949 .disable_plane = drm_atomic_helper_disable_plane,
915 .destroy = ast_cursor_plane_destroy,950 .destroy = drm_plane_cleanup,
916 DRM_GEM_SHADOW_PLANE_FUNCS,951 DRM_GEM_SHADOW_PLANE_FUNCS,
917};952};
918 953
919static int ast_cursor_plane_init(struct ast_private *ast)954static int ast_cursor_plane_init(struct ast_private *ast)
920{955{
921 struct drm_device *dev = &ast->base;956 struct drm_device *dev = &ast->base;
922 struct ast_cursor_plane *ast_cursor_plane = &ast->cursor_plane;957 struct ast_plane *ast_cursor_plane = &ast->cursor_plane;
923 struct drm_plane *cursor_plane = &ast_cursor_plane->base;958 struct drm_plane *cursor_plane = &ast_cursor_plane->base;
924 size_t size, i;959 size_t size;
925 struct drm_gem_vram_object *gbo;960 void __iomem *vaddr;
926 struct iosys_map map;961 u64 offset;
927 int ret;962 int ret;
928 s64 off;
929 963
930 /*964 /*
931 * Allocate backing storage for cursors. The BOs are permanently965 * Allocate backing storage for cursors. The BOs are permanently
@@ -934,60 +968,26 @@ static int ast_cursor_plane_init(struct ast_private *ast) · 2 unmodified lines
934 968
935 size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE);969 size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE);
936 970
937 for (i = 0; i < ARRAY_SIZE(ast_cursor_plane->hwc); ++i) {971 if (ast->vram_fb_available < size)
938 gbo = drm_gem_vram_create(dev, size, 0);972 return -ENOMEM;
939 if (IS_ERR(gbo)) {
940 ret = PTR_ERR(gbo);
941 goto err_hwc;
942 }
943 ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM |
944 DRM_GEM_VRAM_PL_FLAG_TOPDOWN);
945 if (ret)
946 goto err_drm_gem_vram_put;
947 ret = drm_gem_vram_vmap(gbo, &map);
948 if (ret)
949 goto err_drm_gem_vram_unpin;
950 off = drm_gem_vram_offset(gbo);
951 if (off < 0) {
952 ret = off;
953 goto err_drm_gem_vram_vunmap;
954 }
955 ast_cursor_plane->hwc[i].gbo = gbo;
956 ast_cursor_plane->hwc[i].map = map;
957 ast_cursor_plane->hwc[i].off = off;
958 }
959 973
960 /*974 vaddr = ast->vram + ast->vram_fb_available - size;
961 * Create the cursor plane. The plane's destroy callback will release975 offset = ast->vram_base + ast->vram_fb_available - size;
962 * the backing storages' BO memory.
963 */
964 976
965 ret = drm_universal_plane_init(dev, cursor_plane, 0x01,977 ret = ast_plane_init(dev, ast_cursor_plane, vaddr, offset, size,
966 &ast_cursor_plane_funcs,978 0x01, &ast_cursor_plane_funcs,
967 ast_cursor_plane_formats,979 ast_cursor_plane_formats, ARRAY_SIZE(ast_cursor_plane_formats),
968 ARRAY_SIZE(ast_cursor_plane_formats),980 NULL, DRM_PLANE_TYPE_CURSOR);
969 NULL, DRM_PLANE_TYPE_CURSOR, NULL);
970 if (ret) {981 if (ret) {
971 drm_err(dev, "drm_universal_plane failed(): %d\n", ret);982 drm_err(dev, "ast_plane_init() failed: %d\n", ret);
972 goto err_hwc;983 return ret;
973 }984 }
974 drm_plane_helper_add(cursor_plane, &ast_cursor_plane_helper_funcs);985 drm_plane_helper_add(cursor_plane, &ast_cursor_plane_helper_funcs);
986 drm_plane_enable_fb_damage_clips(cursor_plane);
975 987
976 return 0;988 ast->vram_fb_available -= size;
977 989
978err_hwc:990 return 0;
979 while (i) {
980 --i;
981 gbo = ast_cursor_plane->hwc[i].gbo;
982 map = ast_cursor_plane->hwc[i].map;
983err_drm_gem_vram_vunmap:
984 drm_gem_vram_vunmap(gbo, &map);
985err_drm_gem_vram_unpin:
986 drm_gem_vram_unpin(gbo);
987err_drm_gem_vram_put:
988 drm_gem_vram_put(gbo);
989 }
990 return ret;
991}991}
992 992
993/*993/*
@@ -1026,9 +1026,11 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) · 32 unmodified lines
1026 1026
1027 ast_set_color_reg(ast, format);1027 ast_set_color_reg(ast, format);
1028 ast_set_vbios_color_reg(ast, format, vbios_mode_info);1028 ast_set_vbios_color_reg(ast, format, vbios_mode_info);
1029 if (crtc->state->gamma_lut)
1030 ast_crtc_set_gamma(ast, format, crtc->state->gamma_lut->data);
1031 else
1032 ast_crtc_set_gamma_linear(ast, format);
1029 }1033 }
1030
1031 ast_crtc_load_lut(ast, crtc);
1032 break;1034 break;
1033 case DRM_MODE_DPMS_STANDBY:1035 case DRM_MODE_DPMS_STANDBY:
1034 case DRM_MODE_DPMS_SUSPEND:1036 case DRM_MODE_DPMS_SUSPEND:
@@ -1123,47 +1125,50 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, · 88 unmodified lines
1123 struct drm_atomic_state *state)1125 struct drm_atomic_state *state)
1124{1126{
1125 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);1127 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
1128 struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
1129 struct ast_crtc_state *old_ast_crtc_state = to_ast_crtc_state(old_crtc_state);
1126 struct drm_device *dev = crtc->dev;1130 struct drm_device *dev = crtc->dev;
1127 struct ast_crtc_state *ast_state;1131 struct ast_crtc_state *ast_state;
1128 const struct drm_format_info *format;1132 const struct drm_format_info *format;
1129 bool succ;1133 bool succ;
1130 int ret;1134 int ret;
1131 1135
1132 ret = drm_atomic_helper_check_crtc_state(crtc_state, false);1136 if (!crtc_state->enable)
1137 return 0;
1138
1139 ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state);
1133 if (ret)1140 if (ret)
1134 return ret;1141 return ret;
1135 1142
1136 if (!crtc_state->enable)
1137 goto out;
1138
1139 ast_state = to_ast_crtc_state(crtc_state);1143 ast_state = to_ast_crtc_state(crtc_state);
1140 1144
1141 format = ast_state->format;1145 format = ast_state->format;
1142 if (drm_WARN_ON_ONCE(dev, !format))1146 if (drm_WARN_ON_ONCE(dev, !format))
1143 return -EINVAL; /* BUG: We didn't set format in primary check(). */1147 return -EINVAL; /* BUG: We didn't set format in primary check(). */
1144 1148
1149 /*
1150 * The gamma LUT has to be reloaded after changing the primary
1151 * plane's color format.
1152 */
1153 if (old_ast_crtc_state->format != format)
1154 crtc_state->color_mgmt_changed = true;
1155
1156 if (crtc_state->color_mgmt_changed && crtc_state->gamma_lut) {
1157 if (crtc_state->gamma_lut->length !=
1158 AST_LUT_SIZE * sizeof(struct drm_color_lut)) {
1159 drm_err(dev, "Wrong size for gamma_lut %zu\n",
1160 crtc_state->gamma_lut->length);
1161 return -EINVAL;
1162 }
1163 }
1164
1145 succ = ast_get_vbios_mode_info(format, &crtc_state->mode,1165 succ = ast_get_vbios_mode_info(format, &crtc_state->mode,
1146 &crtc_state->adjusted_mode,1166 &crtc_state->adjusted_mode,
1147 &ast_state->vbios_mode_info);1167 &ast_state->vbios_mode_info);
1148 if (!succ)1168 if (!succ)
1149 return -EINVAL;1169 return -EINVAL;
1150 1170
1151out:1171 return 0;
1152 return drm_atomic_add_affected_planes(state, crtc);
1153}
1154
1155static void ast_crtc_helper_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_state *state)
1156{
1157 struct drm_device *dev = crtc->dev;
1158 struct ast_private *ast = to_ast_private(dev);
1159
1160 /*
1161 * Concurrent operations could possibly trigger a call to
1162 * drm_connector_helper_funcs.get_modes by trying to read the
1163 * display modes. Protect access to I/O registers by acquiring
1164 * the I/O-register lock. Released in atomic_flush().
1165 */
1166 mutex_lock(&ast->ioregs_lock);
1167}1172}
1168 1173
1169static void1174static void
@@ -1172,35 +1177,34 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, · 2 unmodified lines
1172{1177{
1173 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,1178 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
1174 crtc);1179 crtc);
1175 struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state,
1176 crtc);
1177 struct drm_device *dev = crtc->dev;1180 struct drm_device *dev = crtc->dev;
1178 struct ast_private *ast = to_ast_private(dev);1181 struct ast_private *ast = to_ast_private(dev);
1179 struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);1182 struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
1180 struct ast_crtc_state *old_ast_crtc_state = to_ast_crtc_state(old_crtc_state);
1181 struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;1183 struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;
1182 1184
1183 /*1185 /*
1184 * The gamma LUT has to be reloaded after changing the primary1186 * The gamma LUT has to be reloaded after changing the primary
1185 * plane's color format.1187 * plane's color format.
1186 */1188 */
1187 if (old_ast_crtc_state->format != ast_crtc_state->format)1189 if (crtc_state->enable && crtc_state->color_mgmt_changed) {
1188 ast_crtc_load_lut(ast, crtc);1190 if (crtc_state->gamma_lut)
1191 ast_crtc_set_gamma(ast,
1192 ast_crtc_state->format,
1193 crtc_state->gamma_lut->data);
1194 else
1195 ast_crtc_set_gamma_linear(ast, ast_crtc_state->format);
1196 }
1189 1197
1190 //Set Aspeed Display-Port1198 //Set Aspeed Display-Port
1191 if (ast->tx_chip_types & AST_TX_ASTDP_BIT)1199 if (ast->tx_chip_types & AST_TX_ASTDP_BIT)
1192 ast_dp_set_mode(crtc, vbios_mode_info);1200 ast_dp_set_mode(crtc, vbios_mode_info);
1193
1194 mutex_unlock(&ast->ioregs_lock);
1195}1201}
1196 1202
1197static void1203static void ast_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state)
1198ast_crtc_helper_atomic_enable(struct drm_crtc *crtc,
1199 struct drm_atomic_state *state)
1200{1204{
1201 struct drm_device *dev = crtc->dev;1205 struct drm_device *dev = crtc->dev;
1202 struct ast_private *ast = to_ast_private(dev);1206 struct ast_private *ast = to_ast_private(dev);
1203 struct drm_crtc_state *crtc_state = crtc->state;1207 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
1204 struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);1208 struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
1205 struct ast_vbios_mode_info *vbios_mode_info =1209 struct ast_vbios_mode_info *vbios_mode_info =
1206 &ast_crtc_state->vbios_mode_info;1210 &ast_crtc_state->vbios_mode_info;
@@ -1217,12 +1221,9 @@ ast_crtc_helper_atomic_enable(struct drm_crtc *crtc, · 10 unmodified lines
1217 ast_crtc_dpms(crtc, DRM_MODE_DPMS_ON);1221 ast_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
1218}1222}
1219 1223
1220static void1224static void ast_crtc_helper_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state)
1221ast_crtc_helper_atomic_disable(struct drm_crtc *crtc,
1222 struct drm_atomic_state *state)
1223{1225{
1224 struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state,1226 struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
1225 crtc);
1226 struct drm_device *dev = crtc->dev;1227 struct drm_device *dev = crtc->dev;
1227 struct ast_private *ast = to_ast_private(dev);1228 struct ast_private *ast = to_ast_private(dev);
1228 1229
@@ -1250,7 +1251,6 @@ ast_crtc_helper_atomic_disable(struct drm_crtc *crtc, · 21 unmodified lines
1250static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = {1251static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = {
1251 .mode_valid = ast_crtc_helper_mode_valid,1252 .mode_valid = ast_crtc_helper_mode_valid,
1252 .atomic_check = ast_crtc_helper_atomic_check,1253 .atomic_check = ast_crtc_helper_atomic_check,
1253 .atomic_begin = ast_crtc_helper_atomic_begin,
1254 .atomic_flush = ast_crtc_helper_atomic_flush,1254 .atomic_flush = ast_crtc_helper_atomic_flush,
1255 .atomic_enable = ast_crtc_helper_atomic_enable,1255 .atomic_enable = ast_crtc_helper_atomic_enable,
1256 .atomic_disable = ast_crtc_helper_atomic_disable,1256 .atomic_disable = ast_crtc_helper_atomic_disable,
@@ -1317,13 +1317,15 @@ static int ast_crtc_init(struct drm_device *dev) · 60 unmodified lines
1317 struct drm_crtc *crtc = &ast->crtc;1317 struct drm_crtc *crtc = &ast->crtc;
1318 int ret;1318 int ret;
1319 1319
1320 ret = drm_crtc_init_with_planes(dev, crtc, &ast->primary_plane,1320 ret = drm_crtc_init_with_planes(dev, crtc, &ast->primary_plane.base,
1321 &ast->cursor_plane.base, &ast_crtc_funcs,1321 &ast->cursor_plane.base, &ast_crtc_funcs,
1322 NULL);1322 NULL);
1323 if (ret)1323 if (ret)
1324 return ret;1324 return ret;
1325 1325
1326 drm_mode_crtc_set_gamma_size(crtc, 256);1326 drm_mode_crtc_set_gamma_size(crtc, AST_LUT_SIZE);
1327 drm_crtc_enable_color_mgmt(crtc, 0, false, AST_LUT_SIZE);
1328
1327 drm_crtc_helper_add(crtc, &ast_crtc_helper_funcs);1329 drm_crtc_helper_add(crtc, &ast_crtc_helper_funcs);
1328 1330
1329 return 0;1331 return 0;
@@ -1718,13 +1720,46 @@ static int ast_astdp_output_init(struct ast_private *ast) · 388 unmodified lines
1718 * Mode config1720 * Mode config
1719 */1721 */
1720 1722
1723static void ast_mode_config_helper_atomic_commit_tail(struct drm_atomic_state *state)
1724{
1725 struct ast_private *ast = to_ast_private(state->dev);
1726
1727 /*
1728 * Concurrent operations could possibly trigger a call to
1729 * drm_connector_helper_funcs.get_modes by trying to read the
1730 * display modes. Protect access to I/O registers by acquiring
1731 * the I/O-register lock. Released in atomic_flush().
1732 */
1733 mutex_lock(&ast->ioregs_lock);
1734 drm_atomic_helper_commit_tail_rpm(state);
1735 mutex_unlock(&ast->ioregs_lock);
1736}
1737
1721static const struct drm_mode_config_helper_funcs ast_mode_config_helper_funcs = {1738static const struct drm_mode_config_helper_funcs ast_mode_config_helper_funcs = {
1722 .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,1739 .atomic_commit_tail = ast_mode_config_helper_atomic_commit_tail,
1723};1740};
1724 1741
1742static enum drm_mode_status ast_mode_config_mode_valid(struct drm_device *dev,
1743 const struct drm_display_mode *mode)
1744{
1745 static const unsigned long max_bpp = 4; /* DRM_FORMAT_XRGB8888 */
1746 struct ast_private *ast = to_ast_private(dev);
1747 unsigned long fbsize, fbpages, max_fbpages;
1748
1749 max_fbpages = (ast->vram_fb_available) >> PAGE_SHIFT;
1750
1751 fbsize = mode->hdisplay * mode->vdisplay * max_bpp;
1752 fbpages = DIV_ROUND_UP(fbsize, PAGE_SIZE);
1753
1754 if (fbpages > max_fbpages)
1755 return MODE_MEM;
1756
1757 return MODE_OK;
1758}
1759
1725static const struct drm_mode_config_funcs ast_mode_config_funcs = {1760static const struct drm_mode_config_funcs ast_mode_config_funcs = {
1726 .fb_create = drm_gem_fb_create,1761 .fb_create = drm_gem_fb_create_with_dirty,
1727 .mode_valid = drm_vram_helper_mode_valid,1762 .mode_valid = ast_mode_config_mode_valid,
1728 .atomic_check = drm_atomic_helper_check,1763 .atomic_check = drm_atomic_helper_check,
1729 .atomic_commit = drm_atomic_helper_commit,1764 .atomic_commit = drm_atomic_helper_commit,
1730};1765};
@@ -1732,7 +1767,6 @@ static const struct drm_mode_config_funcs ast_mode_config_funcs = { · 1 unmodified line
1732int ast_mode_config_init(struct ast_private *ast)1767int ast_mode_config_init(struct ast_private *ast)
1733{1768{
1734 struct drm_device *dev = &ast->base;1769 struct drm_device *dev = &ast->base;
1735 struct pci_dev *pdev = to_pci_dev(dev->dev);
1736 int ret;1770 int ret;
1737 1771
1738 ret = drmm_mode_config_init(dev);1772 ret = drmm_mode_config_init(dev);
@@ -1743,8 +1777,6 @@ int ast_mode_config_init(struct ast_private *ast) · 4 unmodified lines
1743 dev->mode_config.min_width = 0;1777 dev->mode_config.min_width = 0;
1744 dev->mode_config.min_height = 0;1778 dev->mode_config.min_height = 0;
1745 dev->mode_config.preferred_depth = 24;1779 dev->mode_config.preferred_depth = 24;
1746 dev->mode_config.prefer_shadow = 1;
1747 dev->mode_config.fb_base = pci_resource_start(pdev, 0);
1748 1780
1749 if (ast->chip == AST2100 ||1781 if (ast->chip == AST2100 ||
1750 ast->chip == AST2200 ||1782 ast->chip == AST2200 ||
@@ -1761,7 +1793,6 @@ int ast_mode_config_init(struct ast_private *ast) · 10 unmodified lines
1761 1793
1762 dev->mode_config.helper_private = &ast_mode_config_helper_funcs;1794 dev->mode_config.helper_private = &ast_mode_config_helper_funcs;
1763 1795
1764
1765 ret = ast_primary_plane_init(ast);1796 ret = ast_primary_plane_init(ast);
1766 if (ret)1797 if (ret)
1767 return ret;1798 return ret;
drivers/gpu/drm/bridge/adv7511/adv7511.h+2−1
@@ -402,7 +402,8 @@ static inline int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511) · 401 unmodified lines
402 402
403void adv7533_dsi_power_on(struct adv7511 *adv);403void adv7533_dsi_power_on(struct adv7511 *adv);
404void adv7533_dsi_power_off(struct adv7511 *adv);404void adv7533_dsi_power_off(struct adv7511 *adv);
405void adv7533_mode_set(struct adv7511 *adv, const struct drm_display_mode *mode);405enum drm_mode_status adv7533_mode_valid(struct adv7511 *adv,
406 const struct drm_display_mode *mode);
406int adv7533_patch_registers(struct adv7511 *adv);407int adv7533_patch_registers(struct adv7511 *adv);
407int adv7533_patch_cec_registers(struct adv7511 *adv);408int adv7533_patch_cec_registers(struct adv7511 *adv);
408int adv7533_attach_dsi(struct adv7511 *adv);409int adv7533_attach_dsi(struct adv7511 *adv);
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c+14−4
@@ -697,7 +697,7 @@ adv7511_detect(struct adv7511 *adv7511, struct drm_connector *connector) · 696 unmodified lines
697}697}
698 698
699static enum drm_mode_status adv7511_mode_valid(struct adv7511 *adv7511,699static enum drm_mode_status adv7511_mode_valid(struct adv7511 *adv7511,
700 struct drm_display_mode *mode)700 const struct drm_display_mode *mode)
701{701{
702 if (mode->clock > 165000)702 if (mode->clock > 165000)
703 return MODE_CLOCK_HIGH;703 return MODE_CLOCK_HIGH;
@@ -791,9 +791,6 @@ static void adv7511_mode_set(struct adv7511 *adv7511, · 87 unmodified lines
791 regmap_update_bits(adv7511->regmap, 0x17,791 regmap_update_bits(adv7511->regmap, 0x17,
792 0x60, (vsync_polarity << 6) | (hsync_polarity << 5));792 0x60, (vsync_polarity << 6) | (hsync_polarity << 5));
793 793
794 if (adv7511->type == ADV7533 || adv7511->type == ADV7535)
795 adv7533_mode_set(adv7511, adj_mode);
796
797 drm_mode_copy(&adv7511->curr_mode, adj_mode);794 drm_mode_copy(&adv7511->curr_mode, adj_mode);
798 795
799 /*796 /*
@@ -913,6 +910,18 @@ static void adv7511_bridge_mode_set(struct drm_bridge *bridge, · 113 unmodified lines
913 adv7511_mode_set(adv, mode, adj_mode);910 adv7511_mode_set(adv, mode, adj_mode);
914}911}
915 912
913static enum drm_mode_status adv7511_bridge_mode_valid(struct drm_bridge *bridge,
914 const struct drm_display_info *info,
915 const struct drm_display_mode *mode)
916{
917 struct adv7511 *adv = bridge_to_adv7511(bridge);
918
919 if (adv->type == ADV7533 || adv->type == ADV7535)
920 return adv7533_mode_valid(adv, mode);
921 else
922 return adv7511_mode_valid(adv, mode);
923}
924
916static int adv7511_bridge_attach(struct drm_bridge *bridge,925static int adv7511_bridge_attach(struct drm_bridge *bridge,
917 enum drm_bridge_attach_flags flags)926 enum drm_bridge_attach_flags flags)
918{927{
@@ -960,6 +969,7 @@ static const struct drm_bridge_funcs adv7511_bridge_funcs = { · 41 unmodified lines
960 .enable = adv7511_bridge_enable,969 .enable = adv7511_bridge_enable,
961 .disable = adv7511_bridge_disable,970 .disable = adv7511_bridge_disable,
962 .mode_set = adv7511_bridge_mode_set,971 .mode_set = adv7511_bridge_mode_set,
972 .mode_valid = adv7511_bridge_mode_valid,
963 .attach = adv7511_bridge_attach,973 .attach = adv7511_bridge_attach,
964 .detect = adv7511_bridge_detect,974 .detect = adv7511_bridge_detect,
965 .get_edid = adv7511_bridge_get_edid,975 .get_edid = adv7511_bridge_get_edid,
drivers/gpu/drm/bridge/adv7511/adv7533.c+13−12
@@ -100,26 +100,27 @@ void adv7533_dsi_power_off(struct adv7511 *adv) · 99 unmodified lines
100 regmap_write(adv->regmap_cec, 0x27, 0x0b);100 regmap_write(adv->regmap_cec, 0x27, 0x0b);
101}101}
102 102
103void adv7533_mode_set(struct adv7511 *adv, const struct drm_display_mode *mode)103enum drm_mode_status adv7533_mode_valid(struct adv7511 *adv,
104 const struct drm_display_mode *mode)
104{105{
106 int lanes;
105 struct mipi_dsi_device *dsi = adv->dsi;107 struct mipi_dsi_device *dsi = adv->dsi;
106 int lanes, ret;
107
108 if (adv->num_dsi_lanes != 4)
109 return;
110 108
111 if (mode->clock > 80000)109 if (mode->clock > 80000)
112 lanes = 4;110 lanes = 4;
113 else111 else
114 lanes = 3;112 lanes = 3;
115 113
116 if (lanes != dsi->lanes) {114 /*
117 mipi_dsi_detach(dsi);115 * TODO: add support for dynamic switching of lanes
118 dsi->lanes = lanes;116 * by using the bridge pre_enable() op . Till then filter
119 ret = mipi_dsi_attach(dsi);117 * out the modes which shall need different number of lanes
120 if (ret)118 * than what was configured in the device tree.
121 dev_err(&dsi->dev, "failed to change host lanes\n");119 */
122 }120 if (lanes != dsi->lanes)
121 return MODE_BAD;
122
123 return MODE_OK;
123}124}
124 125
125int adv7533_patch_registers(struct adv7511 *adv)126int adv7533_patch_registers(struct adv7511 *adv)
drivers/gpu/drm/bridge/ite-it6505.c+48−10
@@ -421,6 +421,7 @@ struct it6505 { · 420 unmodified lines
421 struct notifier_block event_nb;421 struct notifier_block event_nb;
422 struct extcon_dev *extcon;422 struct extcon_dev *extcon;
423 struct work_struct extcon_wq;423 struct work_struct extcon_wq;
424 int extcon_state;
424 enum drm_connector_status connector_status;425 enum drm_connector_status connector_status;
425 enum link_train_status link_state;426 enum link_train_status link_state;
426 struct work_struct link_works;427 struct work_struct link_works;
@@ -2685,31 +2686,41 @@ static void it6505_extcon_work(struct work_struct *work) · 2258 unmodified lines
2685{2686{
2686 struct it6505 *it6505 = container_of(work, struct it6505, extcon_wq);2687 struct it6505 *it6505 = container_of(work, struct it6505, extcon_wq);
2687 struct device *dev = &it6505->client->dev;2688 struct device *dev = &it6505->client->dev;
2688 int state = extcon_get_state(it6505->extcon, EXTCON_DISP_DP);2689 int state, ret;
2689 unsigned int pwroffretry = 0;
2690 2690
2691 if (it6505->enable_drv_hold)2691 if (it6505->enable_drv_hold)
2692 return;2692 return;
2693 2693
2694 mutex_lock(&it6505->extcon_lock);2694 mutex_lock(&it6505->extcon_lock);
2695 2695
2696 state = extcon_get_state(it6505->extcon, EXTCON_DISP_DP);
2696 DRM_DEV_DEBUG_DRIVER(dev, "EXTCON_DISP_DP = 0x%02x", state);2697 DRM_DEV_DEBUG_DRIVER(dev, "EXTCON_DISP_DP = 0x%02x", state);
2697 if (state > 0) {2698
2699 if (state == it6505->extcon_state || unlikely(state < 0))
2700 goto unlock;
2701 it6505->extcon_state = state;
2702 if (state) {
2698 DRM_DEV_DEBUG_DRIVER(dev, "start to power on");2703 DRM_DEV_DEBUG_DRIVER(dev, "start to power on");
2699 msleep(100);2704 msleep(100);
2700 it6505_poweron(it6505);2705 ret = pm_runtime_get_sync(dev);
2706
2707 /*
2708 * On system resume, extcon_work can be triggered before
2709 * pm_runtime_force_resume re-enables runtime power management.
2710 * Handling the error here to make sure the bridge is powered on.
2711 */
2712 if (ret)
2713 it6505_poweron(it6505);
2701 } else {2714 } else {
2702 DRM_DEV_DEBUG_DRIVER(dev, "start to power off");2715 DRM_DEV_DEBUG_DRIVER(dev, "start to power off");
2703 while (it6505_poweroff(it6505) && pwroffretry++ < 5) {2716 pm_runtime_put_sync(dev);
2704 DRM_DEV_DEBUG_DRIVER(dev, "power off fail %d times",
2705 pwroffretry);
2706 }
2707 2717
2708 drm_helper_hpd_irq_event(it6505->bridge.dev);2718 drm_helper_hpd_irq_event(it6505->bridge.dev);
2709 memset(it6505->dpcd, 0, sizeof(it6505->dpcd));2719 memset(it6505->dpcd, 0, sizeof(it6505->dpcd));
2710 DRM_DEV_DEBUG_DRIVER(dev, "power off it6505 success!");2720 DRM_DEV_DEBUG_DRIVER(dev, "power off it6505 success!");
2711 }2721 }
2712 2722
2723unlock:
2713 mutex_unlock(&it6505->extcon_lock);2724 mutex_unlock(&it6505->extcon_lock);
2714}2725}
2715 2726
@@ -2980,6 +2991,28 @@ static void it6505_bridge_atomic_disable(struct drm_bridge *bridge, · 264 unmodified lines
2980 }2991 }
2981}2992}
2982 2993
2994static void it6505_bridge_atomic_pre_enable(struct drm_bridge *bridge,
2995 struct drm_bridge_state *old_state)
2996{
2997 struct it6505 *it6505 = bridge_to_it6505(bridge);
2998 struct device *dev = &it6505->client->dev;
2999
3000 DRM_DEV_DEBUG_DRIVER(dev, "start");
3001
3002 pm_runtime_get_sync(dev);
3003}
3004
3005static void it6505_bridge_atomic_post_disable(struct drm_bridge *bridge,
3006 struct drm_bridge_state *old_state)
3007{
3008 struct it6505 *it6505 = bridge_to_it6505(bridge);
3009 struct device *dev = &it6505->client->dev;
3010
3011 DRM_DEV_DEBUG_DRIVER(dev, "start");
3012
3013 pm_runtime_put_sync(dev);
3014}
3015
2983static enum drm_connector_status3016static enum drm_connector_status
2984it6505_bridge_detect(struct drm_bridge *bridge)3017it6505_bridge_detect(struct drm_bridge *bridge)
2985{3018{
@@ -3014,6 +3047,8 @@ static const struct drm_bridge_funcs it6505_bridge_funcs = { · 28 unmodified lines
3014 .mode_valid = it6505_bridge_mode_valid,3047 .mode_valid = it6505_bridge_mode_valid,
3015 .atomic_enable = it6505_bridge_atomic_enable,3048 .atomic_enable = it6505_bridge_atomic_enable,
3016 .atomic_disable = it6505_bridge_atomic_disable,3049 .atomic_disable = it6505_bridge_atomic_disable,
3050 .atomic_pre_enable = it6505_bridge_atomic_pre_enable,
3051 .atomic_post_disable = it6505_bridge_atomic_post_disable,
3017 .detect = it6505_bridge_detect,3052 .detect = it6505_bridge_detect,
3018 .get_edid = it6505_bridge_get_edid,3053 .get_edid = it6505_bridge_get_edid,
3019};3054};
@@ -3032,8 +3067,10 @@ static __maybe_unused int it6505_bridge_suspend(struct device *dev) · 12 unmodified lines
3032 return it6505_poweroff(it6505);3067 return it6505_poweroff(it6505);
3033}3068}
3034 3069
3035static SIMPLE_DEV_PM_OPS(it6505_bridge_pm_ops, it6505_bridge_suspend,3070static const struct dev_pm_ops it6505_bridge_pm_ops = {
3036 it6505_bridge_resume);3071 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
3072 SET_RUNTIME_PM_OPS(it6505_bridge_suspend, it6505_bridge_resume, NULL)
3073};
3037 3074
3038static int it6505_init_pdata(struct it6505 *it6505)3075static int it6505_init_pdata(struct it6505 *it6505)
3039{3076{
@@ -3315,6 +3352,7 @@ static int it6505_i2c_probe(struct i2c_client *client, · 275 unmodified lines
3315 3352
3316 DRM_DEV_DEBUG_DRIVER(dev, "it6505 device name: %s", dev_name(dev));3353 DRM_DEV_DEBUG_DRIVER(dev, "it6505 device name: %s", dev_name(dev));
3317 debugfs_init(it6505);3354 debugfs_init(it6505);
3355 pm_runtime_enable(dev);
3318 3356
3319 it6505->bridge.funcs = &it6505_bridge_funcs;3357 it6505->bridge.funcs = &it6505_bridge_funcs;
3320 it6505->bridge.type = DRM_MODE_CONNECTOR_DisplayPort;3358 it6505->bridge.type = DRM_MODE_CONNECTOR_DisplayPort;
drivers/gpu/drm/bridge/parade-ps8640.c+8−1
@@ -286,7 +286,6 @@ static ssize_t ps8640_aux_transfer_msg(struct drm_dp_aux *aux, · 285 unmodified lines
286 }286 }
287 287
288 switch (data & SWAUX_STATUS_MASK) {288 switch (data & SWAUX_STATUS_MASK) {
289 /* Ignore the DEFER cases as they are already handled in hardware */
290 case SWAUX_STATUS_NACK:289 case SWAUX_STATUS_NACK:
291 case SWAUX_STATUS_I2C_NACK:290 case SWAUX_STATUS_I2C_NACK:
292 /*291 /*
@@ -303,6 +302,14 @@ static ssize_t ps8640_aux_transfer_msg(struct drm_dp_aux *aux, · 10 unmodified lines
303 case SWAUX_STATUS_ACKM:302 case SWAUX_STATUS_ACKM:
304 len = data & SWAUX_M_MASK;303 len = data & SWAUX_M_MASK;
305 break;304 break;
305 case SWAUX_STATUS_DEFER:
306 case SWAUX_STATUS_I2C_DEFER:
307 if (is_native_aux)
308 msg->reply |= DP_AUX_NATIVE_REPLY_DEFER;
309 else
310 msg->reply |= DP_AUX_I2C_REPLY_DEFER;
311 len = data & SWAUX_M_MASK;
312 break;
306 case SWAUX_STATUS_INVALID:313 case SWAUX_STATUS_INVALID:
307 return -EOPNOTSUPP;314 return -EOPNOTSUPP;
308 case SWAUX_STATUS_TIMEOUT:315 case SWAUX_STATUS_TIMEOUT:
drivers/gpu/drm/bridge/tc358775.c+1−1
@@ -408,7 +408,7 @@ static void tc_bridge_enable(struct drm_bridge *bridge) · 407 unmodified lines
408 (val >> 8) & 0xFF, val & 0xFF);408 (val >> 8) & 0xFF, val & 0xFF);
409 409
410 d2l_write(tc->i2c, SYSRST, SYS_RST_REG | SYS_RST_DSIRX | SYS_RST_BM |410 d2l_write(tc->i2c, SYSRST, SYS_RST_REG | SYS_RST_DSIRX | SYS_RST_BM |
411 SYS_RST_LCD | SYS_RST_I2CM | SYS_RST_I2CS);411 SYS_RST_LCD | SYS_RST_I2CM);
412 usleep_range(30000, 40000);412 usleep_range(30000, 40000);
413 413
414 d2l_write(tc->i2c, PPI_TX_RX_TA, TTA_GET | TTA_SURE);414 d2l_write(tc->i2c, PPI_TX_RX_TA, TTA_GET | TTA_SURE);
drivers/gpu/drm/display/Makefile+8−6
@@ -3,13 +3,15 @@ · 2 unmodified lines
3obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.o3obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.o
4 4
5drm_display_helper-y := drm_display_helper_mod.o5drm_display_helper-y := drm_display_helper_mod.o
6drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_HELPER) += drm_dp_dual_mode_helper.o \6drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_HELPER) += \
7 drm_dp_helper.o \7 drm_dp_dual_mode_helper.o \
8 drm_dp_mst_topology.o \8 drm_dp_helper.o \
9 drm_dsc_helper.o9 drm_dp_mst_topology.o \
10 drm_dsc_helper.o
10drm_display_helper-$(CONFIG_DRM_DISPLAY_HDCP_HELPER) += drm_hdcp_helper.o11drm_display_helper-$(CONFIG_DRM_DISPLAY_HDCP_HELPER) += drm_hdcp_helper.o
11drm_display_helper-$(CONFIG_DRM_DISPLAY_HDMI_HELPER) += drm_hdmi_helper.o \12drm_display_helper-$(CONFIG_DRM_DISPLAY_HDMI_HELPER) += \
12 drm_scdc_helper.o13 drm_hdmi_helper.o \
14 drm_scdc_helper.o
13drm_display_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o15drm_display_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o
14drm_display_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o16drm_display_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o
15 17
drivers/gpu/drm/drm_atomic_helper.c+18−42
@@ -924,59 +924,35 @@ int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state, · 923 unmodified lines
924EXPORT_SYMBOL(drm_atomic_helper_check_plane_state);924EXPORT_SYMBOL(drm_atomic_helper_check_plane_state);
925 925
926/**926/**
927 * drm_atomic_helper_check_crtc_state() - Check CRTC state for validity927 * drm_atomic_helper_check_crtc_primary_plane() - Check CRTC state for primary plane
928 * @crtc_state: CRTC state to check928 * @crtc_state: CRTC state to check
929 * @can_disable_primary_planes: can the CRTC be enabled without a primary plane?
930 *929 *
931 * Checks that a desired CRTC update is valid. Drivers that provide930 * Checks that a CRTC has at least one primary plane attached to it, which is
932 * their own CRTC handling rather than helper-provided implementations may931 * a requirement on some hardware. Note that this only involves the CRTC side
933 * still wish to call this function to avoid duplication of error checking932 * of the test. To test if the primary plane is visible or if it can be updated
934 * code.933 * without the CRTC being enabled, use drm_atomic_helper_check_plane_state() in
935 *934 * the plane's atomic check.
936 * Note that @can_disable_primary_planes only tests if the CRTC can be
937 * enabled without a primary plane. To test if a primary plane can be updated
938 * without a CRTC, use drm_atomic_helper_check_plane_state() in the plane's
939 * atomic check.
940 *935 *
941 * RETURNS:936 * RETURNS:
942 * Zero if update appears valid, error code on failure937 * 0 if a primary plane is attached to the CRTC, or an error code otherwise
943 */938 */
944int drm_atomic_helper_check_crtc_state(struct drm_crtc_state *crtc_state,939int drm_atomic_helper_check_crtc_primary_plane(struct drm_crtc_state *crtc_state)
945 bool can_disable_primary_planes)
946{940{
947 struct drm_device *dev = crtc_state->crtc->dev;941 struct drm_crtc *crtc = crtc_state->crtc;
948 struct drm_atomic_state *state = crtc_state->state;942 struct drm_device *dev = crtc->dev;
949 943 struct drm_plane *plane;
950 if (!crtc_state->enable)
951 return 0;
952 944
953 /* needs at least one primary plane to be enabled */945 /* needs at least one primary plane to be enabled */
954 if (!can_disable_primary_planes) {946 drm_for_each_plane_mask(plane, dev, crtc_state->plane_mask) {
955 bool has_primary_plane = false;947 if (plane->type == DRM_PLANE_TYPE_PRIMARY)
956 struct drm_plane *plane;948 return 0;
957
958 drm_for_each_plane_mask(plane, dev, crtc_state->plane_mask) {
959 struct drm_plane_state *plane_state;
960
961 if (plane->type != DRM_PLANE_TYPE_PRIMARY)
962 continue;
963 plane_state = drm_atomic_get_plane_state(state, plane);
964 if (IS_ERR(plane_state))
965 return PTR_ERR(plane_state);
966 if (plane_state->fb && plane_state->crtc) {
967 has_primary_plane = true;
968 break;
969 }
970 }
971 if (!has_primary_plane) {
972 drm_dbg_kms(dev, "Cannot enable CRTC without a primary plane.\n");
973 return -EINVAL;
974 }
975 }949 }
976 950
977 return 0;951 drm_dbg_atomic(dev, "[CRTC:%d:%s] primary plane missing\n", crtc->base.id, crtc->name);
952
953 return -EINVAL;
978}954}
979EXPORT_SYMBOL(drm_atomic_helper_check_crtc_state);955EXPORT_SYMBOL(drm_atomic_helper_check_crtc_primary_plane);
980 956
981/**957/**
982 * drm_atomic_helper_check_planes - validate state object for planes changes958 * drm_atomic_helper_check_planes - validate state object for planes changes
drivers/gpu/drm/drm_atomic_state_helper.c+3−3
@@ -464,12 +464,12 @@ void drm_atomic_helper_connector_reset(struct drm_connector *connector) · 463 unmodified lines
464EXPORT_SYMBOL(drm_atomic_helper_connector_reset);464EXPORT_SYMBOL(drm_atomic_helper_connector_reset);
465 465
466/**466/**
467 * drm_atomic_helper_connector_tv_reset - Resets TV connector properties467 * drm_atomic_helper_connector_tv_margins_reset - Resets TV connector properties
468 * @connector: DRM connector468 * @connector: DRM connector
469 *469 *
470 * Resets the TV-related properties attached to a connector.470 * Resets the TV-related properties attached to a connector.
471 */471 */
472void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector)472void drm_atomic_helper_connector_tv_margins_reset(struct drm_connector *connector)
473{473{
474 struct drm_cmdline_mode *cmdline = &connector->cmdline_mode;474 struct drm_cmdline_mode *cmdline = &connector->cmdline_mode;
475 struct drm_connector_state *state = connector->state;475 struct drm_connector_state *state = connector->state;
@@ -479,7 +479,7 @@ void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector) · 3 unmodified lines
479 state->tv.margins.top = cmdline->tv_margins.top;479 state->tv.margins.top = cmdline->tv_margins.top;
480 state->tv.margins.bottom = cmdline->tv_margins.bottom;480 state->tv.margins.bottom = cmdline->tv_margins.bottom;
481}481}
482EXPORT_SYMBOL(drm_atomic_helper_connector_tv_reset);482EXPORT_SYMBOL(drm_atomic_helper_connector_tv_margins_reset);
483 483
484/**484/**
485 * __drm_atomic_helper_connector_duplicate_state - copy atomic connector state485 * __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
drivers/gpu/drm/drm_atomic_uapi.c+4−0
@@ -687,6 +687,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector, · 686 unmodified lines
687 */687 */
688 return -EINVAL;688 return -EINVAL;
689 } else if (property == config->tv_select_subconnector_property) {689 } else if (property == config->tv_select_subconnector_property) {
690 state->tv.select_subconnector = val;
691 } else if (property == config->tv_subconnector_property) {
690 state->tv.subconnector = val;692 state->tv.subconnector = val;
691 } else if (property == config->tv_left_margin_property) {693 } else if (property == config->tv_left_margin_property) {
692 state->tv.margins.left = val;694 state->tv.margins.left = val;
@@ -795,6 +797,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector, · 102 unmodified lines
795 else797 else
796 *val = connector->dpms;798 *val = connector->dpms;
797 } else if (property == config->tv_select_subconnector_property) {799 } else if (property == config->tv_select_subconnector_property) {
800 *val = state->tv.select_subconnector;
801 } else if (property == config->tv_subconnector_property) {
798 *val = state->tv.subconnector;802 *val = state->tv.subconnector;
799 } else if (property == config->tv_left_margin_property) {803 } else if (property == config->tv_left_margin_property) {
800 *val = state->tv.margins.left;804 *val = state->tv.margins.left;
drivers/gpu/drm/drm_client.c+2−2
@@ -323,7 +323,7 @@ drm_client_buffer_vmap(struct drm_client_buffer *buffer, · 322 unmodified lines
323 * fd_install step out of the driver backend hooks, to make that323 * fd_install step out of the driver backend hooks, to make that
324 * final step optional for internal users.324 * final step optional for internal users.
325 */325 */
326 ret = drm_gem_vmap(buffer->gem, map);326 ret = drm_gem_vmap_unlocked(buffer->gem, map);
327 if (ret)327 if (ret)
328 return ret;328 return ret;
329 329
@@ -345,7 +345,7 @@ void drm_client_buffer_vunmap(struct drm_client_buffer *buffer) · 15 unmodified lines
345{345{
346 struct iosys_map *map = &buffer->map;346 struct iosys_map *map = &buffer->map;
347 347
348 drm_gem_vunmap(buffer->gem, map);348 drm_gem_vunmap_unlocked(buffer->gem, map);
349}349}
350EXPORT_SYMBOL(drm_client_buffer_vunmap);350EXPORT_SYMBOL(drm_client_buffer_vunmap);
351 351
drivers/gpu/drm/drm_crtc_helper.c+26−0
@@ -434,6 +434,32 @@ done: · 433 unmodified lines
434}434}
435EXPORT_SYMBOL(drm_crtc_helper_set_mode);435EXPORT_SYMBOL(drm_crtc_helper_set_mode);
436 436
437/**
438 * drm_crtc_helper_atomic_check() - Helper to check CRTC atomic-state
439 * @crtc: CRTC to check
440 * @state: atomic state object
441 *
442 * Provides a default CRTC-state check handler for CRTCs that only have
443 * one primary plane attached to it.
444 *
445 * This is often the case for the CRTC of simple framebuffers. See also
446 * drm_plane_helper_atomic_check() for the respective plane-state check
447 * helper function.
448 *
449 * RETURNS:
450 * Zero on success, or an errno code otherwise.
451 */
452int drm_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state)
453{
454 struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
455
456 if (!new_crtc_state->enable)
457 return 0;
458
459 return drm_atomic_helper_check_crtc_primary_plane(new_crtc_state);
460}
461EXPORT_SYMBOL(drm_crtc_helper_atomic_check);
462
437static void463static void
438drm_crtc_helper_disable(struct drm_crtc *crtc)464drm_crtc_helper_disable(struct drm_crtc *crtc)
439{465{
drivers/gpu/drm/drm_edid.c+222−124
@@ -1572,15 +1572,6 @@ struct drm_edid { · 1571 unmodified lines
1572 const struct edid *edid;1572 const struct edid *edid;
1573};1573};
1574 1574
1575static bool version_greater(const struct drm_edid *drm_edid,
1576 u8 version, u8 revision)
1577{
1578 const struct edid *edid = drm_edid->edid;
1579
1580 return edid->version > version ||
1581 (edid->version == version && edid->revision > revision);
1582}
1583
1584static int edid_hfeeodb_extension_block_count(const struct edid *edid);1575static int edid_hfeeodb_extension_block_count(const struct edid *edid);
1585 1576
1586static int edid_hfeeodb_block_count(const struct edid *edid)1577static int edid_hfeeodb_block_count(const struct edid *edid)
@@ -2984,7 +2975,7 @@ is_rb(const struct detailed_timing *descriptor, void *data) · 1397 unmodified lines
2984 BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.formula.cvt.flags) != 15);2975 BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.formula.cvt.flags) != 15);
2985 2976
2986 if (descriptor->data.other_data.data.range.flags == DRM_EDID_CVT_SUPPORT_FLAG &&2977 if (descriptor->data.other_data.data.range.flags == DRM_EDID_CVT_SUPPORT_FLAG &&
2987 descriptor->data.other_data.data.range.formula.cvt.flags & 0x10)2978 descriptor->data.other_data.data.range.formula.cvt.flags & DRM_EDID_CVT_FLAGS_REDUCED_BLANKING)
2988 *res = true;2979 *res = true;
2989}2980}
2990 2981
@@ -3012,7 +3003,7 @@ find_gtf2(const struct detailed_timing *descriptor, void *data) · 21 unmodified lines
3012 3003
3013 BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.flags) != 10);3004 BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.flags) != 10);
3014 3005
3015 if (descriptor->data.other_data.data.range.flags == 0x02)3006 if (descriptor->data.other_data.data.range.flags == DRM_EDID_SECONDARY_GTF_SUPPORT_FLAG)
3016 *res = descriptor;3007 *res = descriptor;
3017}3008}
3018 3009
@@ -3077,20 +3068,53 @@ drm_gtf2_2j(const struct drm_edid *drm_edid) · 58 unmodified lines
3077 return descriptor ? descriptor->data.other_data.data.range.formula.gtf2.j : 0;3068 return descriptor ? descriptor->data.other_data.data.range.formula.gtf2.j : 0;
3078}3069}
3079 3070
3071static void
3072get_timing_level(const struct detailed_timing *descriptor, void *data)
3073{
3074 int *res = data;
3075
3076 if (!is_display_descriptor(descriptor, EDID_DETAIL_MONITOR_RANGE))
3077 return;
3078
3079 BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.flags) != 10);
3080
3081 switch (descriptor->data.other_data.data.range.flags) {
3082 case DRM_EDID_DEFAULT_GTF_SUPPORT_FLAG:
3083 *res = LEVEL_GTF;
3084 break;
3085 case DRM_EDID_SECONDARY_GTF_SUPPORT_FLAG:
3086 *res = LEVEL_GTF2;
3087 break;
3088 case DRM_EDID_CVT_SUPPORT_FLAG:
3089 *res = LEVEL_CVT;
3090 break;
3091 default:
3092 break;
3093 }
3094}
3095
3080/* Get standard timing level (CVT/GTF/DMT). */3096/* Get standard timing level (CVT/GTF/DMT). */
3081static int standard_timing_level(const struct drm_edid *drm_edid)3097static int standard_timing_level(const struct drm_edid *drm_edid)
3082{3098{
3083 const struct edid *edid = drm_edid->edid;3099 const struct edid *edid = drm_edid->edid;
3084 3100
3085 if (edid->revision >= 2) {3101 if (edid->revision >= 4) {
3086 if (edid->revision >= 4 && (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF))3102 /*
3087 return LEVEL_CVT;3103 * If the range descriptor doesn't
3088 if (drm_gtf2_hbreak(drm_edid))3104 * indicate otherwise default to CVT
3089 return LEVEL_GTF2;3105 */
3090 if (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF)3106 int ret = LEVEL_CVT;
3091 return LEVEL_GTF;3107
3108 drm_for_each_detailed_block(drm_edid, get_timing_level, &ret);
3109
3110 return ret;
3111 } else if (edid->revision >= 3 && drm_gtf2_hbreak(drm_edid)) {
3112 return LEVEL_GTF2;
3113 } else if (edid->revision >= 2) {
3114 return LEVEL_GTF;
3115 } else {
3116 return LEVEL_DMT;
3092 }3117 }
3093 return LEVEL_DMT;
3094}3118}
3095 3119
3096/*3120/*
@@ -3113,6 +3137,35 @@ static int drm_mode_hsync(const struct drm_display_mode *mode) · 16 unmodified lines
3113 return DIV_ROUND_CLOSEST(mode->clock, mode->htotal);3137 return DIV_ROUND_CLOSEST(mode->clock, mode->htotal);
3114}3138}
3115 3139
3140static struct drm_display_mode *
3141drm_gtf2_mode(struct drm_device *dev,
3142 const struct drm_edid *drm_edid,
3143 int hsize, int vsize, int vrefresh_rate)
3144{
3145 struct drm_display_mode *mode;
3146
3147 /*
3148 * This is potentially wrong if there's ever a monitor with
3149 * more than one ranges section, each claiming a different
3150 * secondary GTF curve. Please don't do that.
3151 */
3152 mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
3153 if (!mode)
3154 return NULL;
3155
3156 if (drm_mode_hsync(mode) > drm_gtf2_hbreak(drm_edid)) {
3157 drm_mode_destroy(dev, mode);
3158 mode = drm_gtf_mode_complex(dev, hsize, vsize,
3159 vrefresh_rate, 0, 0,
3160 drm_gtf2_m(drm_edid),
3161 drm_gtf2_2c(drm_edid),
3162 drm_gtf2_k(drm_edid),
3163 drm_gtf2_2j(drm_edid));
3164 }
3165
3166 return mode;
3167}
3168
3116/*3169/*
3117 * Take the standard timing params (in this case width, aspect, and refresh)3170 * Take the standard timing params (in this case width, aspect, and refresh)
3118 * and convert them into a real mode using CVT/GTF/DMT.3171 * and convert them into a real mode using CVT/GTF/DMT.
@@ -3201,23 +3254,7 @@ static struct drm_display_mode *drm_mode_std(struct drm_connector *connector, · 82 unmodified lines
3201 mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);3254 mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
3202 break;3255 break;
3203 case LEVEL_GTF2:3256 case LEVEL_GTF2:
3204 /*3257 mode = drm_gtf2_mode(dev, drm_edid, hsize, vsize, vrefresh_rate);
3205 * This is potentially wrong if there's ever a monitor with
3206 * more than one ranges section, each claiming a different
3207 * secondary GTF curve. Please don't do that.
3208 */
3209 mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
3210 if (!mode)
3211 return NULL;
3212 if (drm_mode_hsync(mode) > drm_gtf2_hbreak(drm_edid)) {
3213 drm_mode_destroy(dev, mode);
3214 mode = drm_gtf_mode_complex(dev, hsize, vsize,
3215 vrefresh_rate, 0, 0,
3216 drm_gtf2_m(drm_edid),
3217 drm_gtf2_2c(drm_edid),
3218 drm_gtf2_k(drm_edid),
3219 drm_gtf2_2j(drm_edid));
3220 }
3221 break;3258 break;
3222 case LEVEL_CVT:3259 case LEVEL_CVT:
3223 mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0,3260 mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0,
@@ -3415,7 +3452,7 @@ range_pixel_clock(const struct edid *edid, const u8 *t) · 191 unmodified lines
3415 return 0;3452 return 0;
3416 3453
3417 /* 1.4 with CVT support gives us real precision, yay */3454 /* 1.4 with CVT support gives us real precision, yay */
3418 if (edid->revision >= 4 && t[10] == 0x04)3455 if (edid->revision >= 4 && t[10] == DRM_EDID_CVT_SUPPORT_FLAG)
3419 return (t[9] * 10000) - ((t[12] >> 2) * 250);3456 return (t[9] * 10000) - ((t[12] >> 2) * 250);
3420 3457
3421 /* 1.3 is pathetic, so fuzz up a bit */3458 /* 1.3 is pathetic, so fuzz up a bit */
@@ -3441,7 +3478,7 @@ static bool mode_in_range(const struct drm_display_mode *mode, · 19 unmodified lines
3441 return false;3478 return false;
3442 3479
3443 /* 1.4 max horizontal check */3480 /* 1.4 max horizontal check */
3444 if (edid->revision >= 4 && t[10] == 0x04)3481 if (edid->revision >= 4 && t[10] == DRM_EDID_CVT_SUPPORT_FLAG)
3445 if (t[13] && mode->hdisplay > 8 * (t[13] + (256 * (t[12]&0x3))))3482 if (t[13] && mode->hdisplay > 8 * (t[13] + (256 * (t[12]&0x3))))
3446 return false;3483 return false;
3447 3484
@@ -3533,6 +3570,35 @@ static int drm_gtf_modes_for_range(struct drm_connector *connector, · 85 unmodified lines
3533 return modes;3570 return modes;
3534}3571}
3535 3572
3573static int drm_gtf2_modes_for_range(struct drm_connector *connector,
3574 const struct drm_edid *drm_edid,
3575 const struct detailed_timing *timing)
3576{
3577 int i, modes = 0;
3578 struct drm_display_mode *newmode;
3579 struct drm_device *dev = connector->dev;
3580
3581 for (i = 0; i < ARRAY_SIZE(extra_modes); i++) {
3582 const struct minimode *m = &extra_modes[i];
3583
3584 newmode = drm_gtf2_mode(dev, drm_edid, m->w, m->h, m->r);
3585 if (!newmode)
3586 return modes;
3587
3588 drm_mode_fixup_1366x768(newmode);
3589 if (!mode_in_range(newmode, drm_edid, timing) ||
3590 !valid_inferred_mode(connector, newmode)) {
3591 drm_mode_destroy(dev, newmode);
3592 continue;
3593 }
3594
3595 drm_mode_probed_add(connector, newmode);
3596 modes++;
3597 }
3598
3599 return modes;
3600}
3601
3536static int drm_cvt_modes_for_range(struct drm_connector *connector,3602static int drm_cvt_modes_for_range(struct drm_connector *connector,
3537 const struct drm_edid *drm_edid,3603 const struct drm_edid *drm_edid,
3538 const struct detailed_timing *timing)3604 const struct detailed_timing *timing)
@@ -3577,25 +3643,29 @@ do_inferred_modes(const struct detailed_timing *timing, void *c) · 38 unmodified lines
3577 closure->drm_edid,3643 closure->drm_edid,
3578 timing);3644 timing);
3579 3645
3580 if (!version_greater(closure->drm_edid, 1, 1))3646 if (closure->drm_edid->edid->revision < 2)
3581 return; /* GTF not defined yet */3647 return; /* GTF not defined yet */
3582 3648
3583 switch (range->flags) {3649 switch (range->flags) {
3584 case 0x02: /* secondary gtf, XXX could do more */3650 case DRM_EDID_SECONDARY_GTF_SUPPORT_FLAG:
3585 case 0x00: /* default gtf */3651 closure->modes += drm_gtf2_modes_for_range(closure->connector,
3652 closure->drm_edid,
3653 timing);
3654 break;
3655 case DRM_EDID_DEFAULT_GTF_SUPPORT_FLAG:
3586 closure->modes += drm_gtf_modes_for_range(closure->connector,3656 closure->modes += drm_gtf_modes_for_range(closure->connector,
3587 closure->drm_edid,3657 closure->drm_edid,
3588 timing);3658 timing);
3589 break;3659 break;
3590 case 0x04: /* cvt, only in 1.4+ */3660 case DRM_EDID_CVT_SUPPORT_FLAG:
3591 if (!version_greater(closure->drm_edid, 1, 3))3661 if (closure->drm_edid->edid->revision < 4)
3592 break;3662 break;
3593 3663
3594 closure->modes += drm_cvt_modes_for_range(closure->connector,3664 closure->modes += drm_cvt_modes_for_range(closure->connector,
3595 closure->drm_edid,3665 closure->drm_edid,
3596 timing);3666 timing);
3597 break;3667 break;
3598 case 0x01: /* just the ranges, no formula */3668 case DRM_EDID_RANGE_LIMITS_ONLY_FLAG:
3599 default:3669 default:
3600 break;3670 break;
3601 }3671 }
@@ -3609,7 +3679,7 @@ static int add_inferred_modes(struct drm_connector *connector, · 7 unmodified lines
3609 .drm_edid = drm_edid,3679 .drm_edid = drm_edid,
3610 };3680 };
3611 3681
3612 if (version_greater(drm_edid, 1, 0))3682 if (drm_edid->edid->revision >= 1)
3613 drm_for_each_detailed_block(drm_edid, do_inferred_modes, &closure);3683 drm_for_each_detailed_block(drm_edid, do_inferred_modes, &closure);
3614 3684
3615 return closure.modes;3685 return closure.modes;
@@ -3686,7 +3756,7 @@ static int add_established_modes(struct drm_connector *connector, · 70 unmodified lines
3686 }3756 }
3687 }3757 }
3688 3758
3689 if (version_greater(drm_edid, 1, 0))3759 if (edid->revision >= 1)
3690 drm_for_each_detailed_block(drm_edid, do_established_modes,3760 drm_for_each_detailed_block(drm_edid, do_established_modes,
3691 &closure);3761 &closure);
3692 3762
@@ -3741,7 +3811,7 @@ static int add_standard_modes(struct drm_connector *connector, · 48 unmodified lines
3741 }3811 }
3742 }3812 }
3743 3813
3744 if (version_greater(drm_edid, 1, 0))3814 if (drm_edid->edid->revision >= 1)
3745 drm_for_each_detailed_block(drm_edid, do_standard_modes,3815 drm_for_each_detailed_block(drm_edid, do_standard_modes,
3746 &closure);3816 &closure);
3747 3817
@@ -3821,7 +3891,7 @@ add_cvt_modes(struct drm_connector *connector, const struct drm_edid *drm_edid) · 73 unmodified lines
3821 .drm_edid = drm_edid,3891 .drm_edid = drm_edid,
3822 };3892 };
3823 3893
3824 if (version_greater(drm_edid, 1, 2))3894 if (drm_edid->edid->revision >= 3)
3825 drm_for_each_detailed_block(drm_edid, do_cvt_mode, &closure);3895 drm_for_each_detailed_block(drm_edid, do_cvt_mode, &closure);
3826 3896
3827 /* XXX should also look for CVT codes in VTB blocks */3897 /* XXX should also look for CVT codes in VTB blocks */
@@ -3873,13 +3943,14 @@ static int add_detailed_modes(struct drm_connector *connector, · 45 unmodified lines
3873 struct detailed_mode_closure closure = {3943 struct detailed_mode_closure closure = {
3874 .connector = connector,3944 .connector = connector,
3875 .drm_edid = drm_edid,3945 .drm_edid = drm_edid,
3876 .preferred = true,
3877 .quirks = quirks,3946 .quirks = quirks,
3878 };3947 };
3879 3948
3880 if (closure.preferred && !version_greater(drm_edid, 1, 3))3949 if (drm_edid->edid->revision >= 4)
3950 closure.preferred = true; /* first detailed timing is always preferred */
3951 else
3881 closure.preferred =3952 closure.preferred =
3882 (drm_edid->edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING);3953 drm_edid->edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING;
3883 3954
3884 drm_for_each_detailed_block(drm_edid, do_detailed_mode, &closure);3955 drm_for_each_detailed_block(drm_edid, do_detailed_mode, &closure);
3885 3956
@@ -5752,12 +5823,87 @@ static void drm_parse_ycbcr420_deep_color_info(struct drm_connector *connector, · 1866 unmodified lines
5752 hdmi->y420_dc_modes = dc_mask;5823 hdmi->y420_dc_modes = dc_mask;
5753}5824}
5754 5825
5826static void drm_parse_dsc_info(struct drm_hdmi_dsc_cap *hdmi_dsc,
5827 const u8 *hf_scds)
5828{
5829 hdmi_dsc->v_1p2 = hf_scds[11] & DRM_EDID_DSC_1P2;
5830
5831 if (!hdmi_dsc->v_1p2)
5832 return;
5833
5834 hdmi_dsc->native_420 = hf_scds[11] & DRM_EDID_DSC_NATIVE_420;
5835 hdmi_dsc->all_bpp = hf_scds[11] & DRM_EDID_DSC_ALL_BPP;
5836
5837 if (hf_scds[11] & DRM_EDID_DSC_16BPC)
5838 hdmi_dsc->bpc_supported = 16;
5839 else if (hf_scds[11] & DRM_EDID_DSC_12BPC)
5840 hdmi_dsc->bpc_supported = 12;
5841 else if (hf_scds[11] & DRM_EDID_DSC_10BPC)
5842 hdmi_dsc->bpc_supported = 10;
5843 else
5844 /* Supports min 8 BPC if DSC 1.2 is supported*/
5845 hdmi_dsc->bpc_supported = 8;
5846
5847 if (cea_db_payload_len(hf_scds) >= 12 && hf_scds[12]) {
5848 u8 dsc_max_slices;
5849 u8 dsc_max_frl_rate;
5850
5851 dsc_max_frl_rate = (hf_scds[12] & DRM_EDID_DSC_MAX_FRL_RATE_MASK) >> 4;
5852 drm_get_max_frl_rate(dsc_max_frl_rate, &hdmi_dsc->max_lanes,
5853 &hdmi_dsc->max_frl_rate_per_lane);
5854
5855 dsc_max_slices = hf_scds[12] & DRM_EDID_DSC_MAX_SLICES;
5856
5857 switch (dsc_max_slices) {
5858 case 1:
5859 hdmi_dsc->max_slices = 1;
5860 hdmi_dsc->clk_per_slice = 340;
5861 break;
5862 case 2:
5863 hdmi_dsc->max_slices = 2;
5864 hdmi_dsc->clk_per_slice = 340;
5865 break;
5866 case 3:
5867 hdmi_dsc->max_slices = 4;
5868 hdmi_dsc->clk_per_slice = 340;
5869 break;
5870 case 4:
5871 hdmi_dsc->max_slices = 8;
5872 hdmi_dsc->clk_per_slice = 340;
5873 break;
5874 case 5:
5875 hdmi_dsc->max_slices = 8;
5876 hdmi_dsc->clk_per_slice = 400;
5877 break;
5878 case 6:
5879 hdmi_dsc->max_slices = 12;
5880 hdmi_dsc->clk_per_slice = 400;
5881 break;
5882 case 7:
5883 hdmi_dsc->max_slices = 16;
5884 hdmi_dsc->clk_per_slice = 400;
5885 break;
5886 case 0:
5887 default:
5888 hdmi_dsc->max_slices = 0;
5889 hdmi_dsc->clk_per_slice = 0;
5890 }
5891 }
5892
5893 if (cea_db_payload_len(hf_scds) >= 13 && hf_scds[13])
5894 hdmi_dsc->total_chunk_kbytes = hf_scds[13] & DRM_EDID_DSC_TOTAL_CHUNK_KBYTES;
5895}
5896
5755/* Sink Capability Data Structure */5897/* Sink Capability Data Structure */
5756static void drm_parse_hdmi_forum_scds(struct drm_connector *connector,5898static void drm_parse_hdmi_forum_scds(struct drm_connector *connector,
5757 const u8 *hf_scds)5899 const u8 *hf_scds)
5758{5900{
5759 struct drm_display_info *display = &connector->display_info;5901 struct drm_display_info *display = &connector->display_info;
5760 struct drm_hdmi_info *hdmi = &display->hdmi;5902 struct drm_hdmi_info *hdmi = &display->hdmi;
5903 struct drm_hdmi_dsc_cap *hdmi_dsc = &hdmi->dsc_cap;
5904 int max_tmds_clock = 0;
5905 u8 max_frl_rate = 0;
5906 bool dsc_support = false;
5761 5907
5762 display->has_hdmi_infoframe = true;5908 display->has_hdmi_infoframe = true;
5763 5909
@@ -5777,14 +5923,13 @@ static void drm_parse_hdmi_forum_scds(struct drm_connector *connector, · 13 unmodified lines
5777 */5923 */
5778 5924
5779 if (hf_scds[5]) {5925 if (hf_scds[5]) {
5780 /* max clock is 5000 KHz times block value */
5781 u32 max_tmds_clock = hf_scds[5] * 5000;
5782 struct drm_scdc *scdc = &hdmi->scdc;5926 struct drm_scdc *scdc = &hdmi->scdc;
5783 5927
5928 /* max clock is 5000 KHz times block value */
5929 max_tmds_clock = hf_scds[5] * 5000;
5930
5784 if (max_tmds_clock > 340000) {5931 if (max_tmds_clock > 340000) {
5785 display->max_tmds_clock = max_tmds_clock;5932 display->max_tmds_clock = max_tmds_clock;
5786 DRM_DEBUG_KMS("HF-VSDB: max TMDS clock %d kHz\n",
5787 display->max_tmds_clock);
5788 }5933 }
5789 5934
5790 if (scdc->supported) {5935 if (scdc->supported) {
@@ -5797,74 +5942,21 @@ static void drm_parse_hdmi_forum_scds(struct drm_connector *connector, · 6 unmodified lines
5797 }5942 }
5798 5943
5799 if (hf_scds[7]) {5944 if (hf_scds[7]) {
5800 u8 max_frl_rate;
5801 u8 dsc_max_frl_rate;
5802 u8 dsc_max_slices;
5803 struct drm_hdmi_dsc_cap *hdmi_dsc = &hdmi->dsc_cap;
5804
5805 DRM_DEBUG_KMS("hdmi_21 sink detected. parsing edid\n");
5806 max_frl_rate = (hf_scds[7] & DRM_EDID_MAX_FRL_RATE_MASK) >> 4;5945 max_frl_rate = (hf_scds[7] & DRM_EDID_MAX_FRL_RATE_MASK) >> 4;
5807 drm_get_max_frl_rate(max_frl_rate, &hdmi->max_lanes,5946 drm_get_max_frl_rate(max_frl_rate, &hdmi->max_lanes,
5808 &hdmi->max_frl_rate_per_lane);5947 &hdmi->max_frl_rate_per_lane);
5809 hdmi_dsc->v_1p2 = hf_scds[11] & DRM_EDID_DSC_1P2;
5810
5811 if (hdmi_dsc->v_1p2) {
5812 hdmi_dsc->native_420 = hf_scds[11] & DRM_EDID_DSC_NATIVE_420;
5813 hdmi_dsc->all_bpp = hf_scds[11] & DRM_EDID_DSC_ALL_BPP;
5814
5815 if (hf_scds[11] & DRM_EDID_DSC_16BPC)
5816 hdmi_dsc->bpc_supported = 16;
5817 else if (hf_scds[11] & DRM_EDID_DSC_12BPC)
5818 hdmi_dsc->bpc_supported = 12;
5819 else if (hf_scds[11] & DRM_EDID_DSC_10BPC)
5820 hdmi_dsc->bpc_supported = 10;
5821 else
5822 hdmi_dsc->bpc_supported = 0;
5823
5824 dsc_max_frl_rate = (hf_scds[12] & DRM_EDID_DSC_MAX_FRL_RATE_MASK) >> 4;
5825 drm_get_max_frl_rate(dsc_max_frl_rate, &hdmi_dsc->max_lanes,
5826 &hdmi_dsc->max_frl_rate_per_lane);
5827 hdmi_dsc->total_chunk_kbytes = hf_scds[13] & DRM_EDID_DSC_TOTAL_CHUNK_KBYTES;
5828
5829 dsc_max_slices = hf_scds[12] & DRM_EDID_DSC_MAX_SLICES;
5830 switch (dsc_max_slices) {
5831 case 1:
5832 hdmi_dsc->max_slices = 1;
5833 hdmi_dsc->clk_per_slice = 340;
5834 break;
5835 case 2:
5836 hdmi_dsc->max_slices = 2;
5837 hdmi_dsc->clk_per_slice = 340;
5838 break;
5839 case 3:
5840 hdmi_dsc->max_slices = 4;
5841 hdmi_dsc->clk_per_slice = 340;
5842 break;
5843 case 4:
5844 hdmi_dsc->max_slices = 8;
5845 hdmi_dsc->clk_per_slice = 340;
5846 break;
5847 case 5:
5848 hdmi_dsc->max_slices = 8;
5849 hdmi_dsc->clk_per_slice = 400;
5850 break;
5851 case 6:
5852 hdmi_dsc->max_slices = 12;
5853 hdmi_dsc->clk_per_slice = 400;
5854 break;
5855 case 7:
5856 hdmi_dsc->max_slices = 16;
5857 hdmi_dsc->clk_per_slice = 400;
5858 break;
5859 case 0:
5860 default:
5861 hdmi_dsc->max_slices = 0;
5862 hdmi_dsc->clk_per_slice = 0;
5863 }
5864 }
5865 }5948 }
5866 5949
5867 drm_parse_ycbcr420_deep_color_info(connector, hf_scds);5950 drm_parse_ycbcr420_deep_color_info(connector, hf_scds);
5951
5952 if (cea_db_payload_len(hf_scds) >= 11 && hf_scds[11]) {
5953 drm_parse_dsc_info(hdmi_dsc, hf_scds);
5954 dsc_support = true;
5955 }
5956
5957 drm_dbg_kms(connector->dev,
5958 "HF-VSDB: max TMDS clock: %d KHz, HDMI 2.1 support: %s, DSC 1.2 support: %s\n",
5959 max_tmds_clock, str_yes_no(max_frl_rate), str_yes_no(dsc_support));
5868}5960}
5869 5961
5870static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector,5962static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector,
@@ -6033,10 +6125,13 @@ void get_monitor_range(const struct detailed_timing *timing, void *c) · 162 unmodified lines
6033 return;6125 return;
6034 6126
6035 /*6127 /*
6036 * Check for flag range limits only. If flag == 1 then6128 * These limits are used to determine the VRR refresh
6037 * no additional timing information provided.6129 * rate range. Only the "range limits only" variant
6038 * Default GTF, GTF Secondary curve and CVT are not6130 * of the range descriptor seems to guarantee that
6039 * supported6131 * any and all timings are accepted by the sink, as
6132 * opposed to just timings conforming to the indicated
6133 * formula (GTF/GTF2/CVT). Thus other variants of the
6134 * range descriptor are not accepted here.
6040 */6135 */
6041 if (range->flags != DRM_EDID_RANGE_LIMITS_ONLY_FLAG)6136 if (range->flags != DRM_EDID_RANGE_LIMITS_ONLY_FLAG)
6042 return;6137 return;
@@ -6061,7 +6156,10 @@ static void drm_get_monitor_range(struct drm_connector *connector, · 18 unmodified lines
6061 .drm_edid = drm_edid,6156 .drm_edid = drm_edid,
6062 };6157 };
6063 6158
6064 if (!version_greater(drm_edid, 1, 1))6159 if (drm_edid->edid->revision < 4)
6160 return;
6161
6162 if (!(drm_edid->edid->features & DRM_EDID_FEATURE_CONTINUOUS_FREQ))
6065 return;6163 return;
6066 6164
6067 drm_for_each_detailed_block(drm_edid, get_monitor_range, &closure);6165 drm_for_each_detailed_block(drm_edid, get_monitor_range, &closure);
@@ -6390,7 +6488,7 @@ static int _drm_edid_connector_update(struct drm_connector *connector, · 322 unmodified lines
6390 num_modes += add_cea_modes(connector, drm_edid);6488 num_modes += add_cea_modes(connector, drm_edid);
6391 num_modes += add_alternate_cea_modes(connector, drm_edid);6489 num_modes += add_alternate_cea_modes(connector, drm_edid);
6392 num_modes += add_displayid_detailed_modes(connector, drm_edid);6490 num_modes += add_displayid_detailed_modes(connector, drm_edid);
6393 if (drm_edid->edid->features & DRM_EDID_FEATURE_DEFAULT_GTF)6491 if (drm_edid->edid->features & DRM_EDID_FEATURE_CONTINUOUS_FREQ)
6394 num_modes += add_inferred_modes(connector, drm_edid);6492 num_modes += add_inferred_modes(connector, drm_edid);
6395 6493
6396 if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))6494 if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
@@ -6837,7 +6935,7 @@ drm_hdmi_avi_infoframe_quant_range(struct hdmi_avi_infoframe *frame, · 440 unmodified lines
6837 * by non-zero YQ when receiving RGB. There doesn't seem to be any6935 * by non-zero YQ when receiving RGB. There doesn't seem to be any
6838 * good way to tell which version of CEA-861 the sink supports, so6936 * good way to tell which version of CEA-861 the sink supports, so
6839 * we limit non-zero YQ to HDMI 2.0 sinks only as HDMI 2.0 is based6937 * we limit non-zero YQ to HDMI 2.0 sinks only as HDMI 2.0 is based
6840 * on on CEA-861-F.6938 * on CEA-861-F.
6841 */6939 */
6842 if (!is_hdmi2_sink(connector) ||6940 if (!is_hdmi2_sink(connector) ||
6843 rgb_quant_range == HDMI_QUANTIZATION_RANGE_LIMITED)6941 rgb_quant_range == HDMI_QUANTIZATION_RANGE_LIMITED)
drivers/gpu/drm/drm_format_helper.c+10−0
@@ -660,6 +660,11 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d · 659 unmodified lines
660 drm_fb_xrgb8888_to_rgb565(dst, dst_pitch, src, fb, clip, false);660 drm_fb_xrgb8888_to_rgb565(dst, dst_pitch, src, fb, clip, false);
661 return 0;661 return 0;
662 }662 }
663 } else if (dst_format == (DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN)) {
664 if (fb_format == DRM_FORMAT_RGB565) {
665 drm_fb_swab(dst, dst_pitch, src, fb, clip, false);
666 return 0;
667 }
663 } else if (dst_format == DRM_FORMAT_RGB888) {668 } else if (dst_format == DRM_FORMAT_RGB888) {
664 if (fb_format == DRM_FORMAT_XRGB8888) {669 if (fb_format == DRM_FORMAT_XRGB8888) {
665 drm_fb_xrgb8888_to_rgb888(dst, dst_pitch, src, fb, clip);670 drm_fb_xrgb8888_to_rgb888(dst, dst_pitch, src, fb, clip);
@@ -678,6 +683,11 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d · 12 unmodified lines
678 drm_fb_xrgb8888_to_xrgb2101010(dst, dst_pitch, src, fb, clip);683 drm_fb_xrgb8888_to_xrgb2101010(dst, dst_pitch, src, fb, clip);
679 return 0;684 return 0;
680 }685 }
686 } else if (dst_format == DRM_FORMAT_BGRX8888) {
687 if (fb_format == DRM_FORMAT_XRGB8888) {
688 drm_fb_swab(dst, dst_pitch, src, fb, clip, false);
689 return 0;
690 }
681 }691 }
682 692
683 drm_warn_once(fb->dev, "No conversion helper from %p4cc to %p4cc found.\n",693 drm_warn_once(fb->dev, "No conversion helper from %p4cc to %p4cc found.\n",
drivers/gpu/drm/drm_gem.c+24−0
@@ -1158,6 +1158,8 @@ int drm_gem_vmap(struct drm_gem_object *obj, struct iosys_map *map) · 1157 unmodified lines
1158{1158{
1159 int ret;1159 int ret;
1160 1160
1161 dma_resv_assert_held(obj->resv);
1162
1161 if (!obj->funcs->vmap)1163 if (!obj->funcs->vmap)
1162 return -EOPNOTSUPP;1164 return -EOPNOTSUPP;
1163 1165
@@ -1173,6 +1175,8 @@ EXPORT_SYMBOL(drm_gem_vmap); · 9 unmodified lines
1173 1175
1174void drm_gem_vunmap(struct drm_gem_object *obj, struct iosys_map *map)1176void drm_gem_vunmap(struct drm_gem_object *obj, struct iosys_map *map)
1175{1177{
1178 dma_resv_assert_held(obj->resv);
1179
1176 if (iosys_map_is_null(map))1180 if (iosys_map_is_null(map))
1177 return;1181 return;
1178 1182
@@ -1184,6 +1188,26 @@ void drm_gem_vunmap(struct drm_gem_object *obj, struct iosys_map *map) · 5 unmodified lines
1184}1188}
1185EXPORT_SYMBOL(drm_gem_vunmap);1189EXPORT_SYMBOL(drm_gem_vunmap);
1186 1190
1191int drm_gem_vmap_unlocked(struct drm_gem_object *obj, struct iosys_map *map)
1192{
1193 int ret;
1194
1195 dma_resv_lock(obj->resv, NULL);
1196 ret = drm_gem_vmap(obj, map);
1197 dma_resv_unlock(obj->resv);
1198
1199 return ret;
1200}
1201EXPORT_SYMBOL(drm_gem_vmap_unlocked);
1202
1203void drm_gem_vunmap_unlocked(struct drm_gem_object *obj, struct iosys_map *map)
1204{
1205 dma_resv_lock(obj->resv, NULL);
1206 drm_gem_vunmap(obj, map);
1207 dma_resv_unlock(obj->resv);
1208}
1209EXPORT_SYMBOL(drm_gem_vunmap_unlocked);
1210
1187/**1211/**
1188 * drm_gem_lock_reservations - Sets up the ww context and acquires1212 * drm_gem_lock_reservations - Sets up the ww context and acquires
1189 * the lock on an array of GEM objects.1213 * the lock on an array of GEM objects.
drivers/gpu/drm/drm_gem_dma_helper.c+3−3
@@ -230,7 +230,7 @@ void drm_gem_dma_free(struct drm_gem_dma_object *dma_obj) · 229 unmodified lines
230 230
231 if (gem_obj->import_attach) {231 if (gem_obj->import_attach) {
232 if (dma_obj->vaddr)232 if (dma_obj->vaddr)
233 dma_buf_vunmap(gem_obj->import_attach->dmabuf, &map);233 dma_buf_vunmap_unlocked(gem_obj->import_attach->dmabuf, &map);
234 drm_prime_gem_destroy(gem_obj, dma_obj->sgt);234 drm_prime_gem_destroy(gem_obj, dma_obj->sgt);
235 } else if (dma_obj->vaddr) {235 } else if (dma_obj->vaddr) {
236 if (dma_obj->map_noncoherent)236 if (dma_obj->map_noncoherent)
@@ -581,7 +581,7 @@ drm_gem_dma_prime_import_sg_table_vmap(struct drm_device *dev, · 344 unmodified lines
581 struct iosys_map map;581 struct iosys_map map;
582 int ret;582 int ret;
583 583
584 ret = dma_buf_vmap(attach->dmabuf, &map);584 ret = dma_buf_vmap_unlocked(attach->dmabuf, &map);
585 if (ret) {585 if (ret) {
586 DRM_ERROR("Failed to vmap PRIME buffer\n");586 DRM_ERROR("Failed to vmap PRIME buffer\n");
587 return ERR_PTR(ret);587 return ERR_PTR(ret);
@@ -589,7 +589,7 @@ drm_gem_dma_prime_import_sg_table_vmap(struct drm_device *dev, · 1 unmodified line
589 589
590 obj = drm_gem_dma_prime_import_sg_table(dev, attach, sgt);590 obj = drm_gem_dma_prime_import_sg_table(dev, attach, sgt);
591 if (IS_ERR(obj)) {591 if (IS_ERR(obj)) {
592 dma_buf_vunmap(attach->dmabuf, &map);592 dma_buf_vunmap_unlocked(attach->dmabuf, &map);
593 return obj;593 return obj;
594 }594 }
595 595
drivers/gpu/drm/drm_gem_framebuffer_helper.c+3−3
@@ -354,7 +354,7 @@ int drm_gem_fb_vmap(struct drm_framebuffer *fb, struct iosys_map *map, · 353 unmodified lines
354 ret = -EINVAL;354 ret = -EINVAL;
355 goto err_drm_gem_vunmap;355 goto err_drm_gem_vunmap;
356 }356 }
357 ret = drm_gem_vmap(obj, &map[i]);357 ret = drm_gem_vmap_unlocked(obj, &map[i]);
358 if (ret)358 if (ret)
359 goto err_drm_gem_vunmap;359 goto err_drm_gem_vunmap;
360 }360 }
@@ -376,7 +376,7 @@ err_drm_gem_vunmap: · 15 unmodified lines
376 obj = drm_gem_fb_get_obj(fb, i);376 obj = drm_gem_fb_get_obj(fb, i);
377 if (!obj)377 if (!obj)
378 continue;378 continue;
379 drm_gem_vunmap(obj, &map[i]);379 drm_gem_vunmap_unlocked(obj, &map[i]);
380 }380 }
381 return ret;381 return ret;
382}382}
@@ -403,7 +403,7 @@ void drm_gem_fb_vunmap(struct drm_framebuffer *fb, struct iosys_map *map) · 20 unmodified lines
403 continue;403 continue;
404 if (iosys_map_is_null(&map[i]))404 if (iosys_map_is_null(&map[i]))
405 continue;405 continue;
406 drm_gem_vunmap(obj, &map[i]);406 drm_gem_vunmap_unlocked(obj, &map[i]);
407 }407 }
408}408}
409EXPORT_SYMBOL(drm_gem_fb_vunmap);409EXPORT_SYMBOL(drm_gem_fb_vunmap);
drivers/gpu/drm/drm_gem_ttm_helper.c+1−8
@@ -64,13 +64,8 @@ int drm_gem_ttm_vmap(struct drm_gem_object *gem, · 63 unmodified lines
64 struct iosys_map *map)64 struct iosys_map *map)
65{65{
66 struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(gem);66 struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(gem);
67 int ret;
68
69 dma_resv_lock(gem->resv, NULL);
70 ret = ttm_bo_vmap(bo, map);
71 dma_resv_unlock(gem->resv);
72 67
73 return ret;68 return ttm_bo_vmap(bo, map);
74}69}
75EXPORT_SYMBOL(drm_gem_ttm_vmap);70EXPORT_SYMBOL(drm_gem_ttm_vmap);
76 71
@@ -87,9 +82,7 @@ void drm_gem_ttm_vunmap(struct drm_gem_object *gem, · 10 unmodified lines
87{82{
88 struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(gem);83 struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(gem);
89 84
90 dma_resv_lock(gem->resv, NULL);
91 ttm_bo_vunmap(bo, map);85 ttm_bo_vunmap(bo, map);
92 dma_resv_unlock(gem->resv);
93}86}
94EXPORT_SYMBOL(drm_gem_ttm_vunmap);87EXPORT_SYMBOL(drm_gem_ttm_vunmap);
95 88
drivers/gpu/drm/drm_modes.c+11−7
@@ -1801,20 +1801,24 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, · 1800 unmodified lines
1801 1801
1802 name = mode_option;1802 name = mode_option;
1803 1803
1804 /* Locate the start of named options */
1805 options_ptr = strchr(name, ',');
1806 if (options_ptr)
1807 options_off = options_ptr - name;
1808 else
1809 options_off = strlen(name);
1810
1804 /* Try to locate the bpp and refresh specifiers, if any */1811 /* Try to locate the bpp and refresh specifiers, if any */
1805 bpp_ptr = strchr(name, '-');1812 bpp_ptr = strnchr(name, options_off, '-');
1813 while (bpp_ptr && !isdigit(bpp_ptr[1]))
1814 bpp_ptr = strnchr(bpp_ptr + 1, options_off, '-');
1806 if (bpp_ptr)1815 if (bpp_ptr)
1807 bpp_off = bpp_ptr - name;1816 bpp_off = bpp_ptr - name;
1808 1817
1809 refresh_ptr = strchr(name, '@');1818 refresh_ptr = strnchr(name, options_off, '@');
1810 if (refresh_ptr)1819 if (refresh_ptr)
1811 refresh_off = refresh_ptr - name;1820 refresh_off = refresh_ptr - name;
1812 1821
1813 /* Locate the start of named options */
1814 options_ptr = strchr(name, ',');
1815 if (options_ptr)
1816 options_off = options_ptr - name;
1817
1818 /* Locate the end of the name / resolution, and parse it */1822 /* Locate the end of the name / resolution, and parse it */
1819 if (bpp_ptr) {1823 if (bpp_ptr) {
1820 mode_end = bpp_off;1824 mode_end = bpp_off;
drivers/gpu/drm/drm_plane_helper.c+3−1
@@ -298,7 +298,9 @@ EXPORT_SYMBOL(drm_plane_helper_destroy); · 297 unmodified lines
298 * scale and positioning are not expected to change since the plane is always298 * scale and positioning are not expected to change since the plane is always
299 * a fullscreen scanout buffer.299 * a fullscreen scanout buffer.
300 *300 *
301 * This is often the case for the primary plane of simple framebuffers.301 * This is often the case for the primary plane of simple framebuffers. See
302 * also drm_crtc_helper_atomic_check() for the respective CRTC-state check
303 * helper function.
302 *304 *
303 * RETURNS:305 * RETURNS:
304 * Zero on success, or an errno code otherwise.306 * Zero on success, or an errno code otherwise.
drivers/gpu/drm/drm_prime.c+3−3
@@ -940,7 +940,7 @@ struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev, · 939 unmodified lines
940 940
941 get_dma_buf(dma_buf);941 get_dma_buf(dma_buf);
942 942
943 sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);943 sgt = dma_buf_map_attachment_unlocked(attach, DMA_BIDIRECTIONAL);
944 if (IS_ERR(sgt)) {944 if (IS_ERR(sgt)) {
945 ret = PTR_ERR(sgt);945 ret = PTR_ERR(sgt);
946 goto fail_detach;946 goto fail_detach;
@@ -958,7 +958,7 @@ struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev, · 11 unmodified lines
958 return obj;958 return obj;
959 959
960fail_unmap:960fail_unmap:
961 dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);961 dma_buf_unmap_attachment_unlocked(attach, sgt, DMA_BIDIRECTIONAL);
962fail_detach:962fail_detach:
963 dma_buf_detach(dma_buf, attach);963 dma_buf_detach(dma_buf, attach);
964 dma_buf_put(dma_buf);964 dma_buf_put(dma_buf);
@@ -1056,7 +1056,7 @@ void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg) · 91 unmodified lines
1056 1056
1057 attach = obj->import_attach;1057 attach = obj->import_attach;
1058 if (sg)1058 if (sg)
1059 dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL);1059 dma_buf_unmap_attachment_unlocked(attach, sg, DMA_BIDIRECTIONAL);
1060 dma_buf = attach->dmabuf;1060 dma_buf = attach->dmabuf;
1061 dma_buf_detach(attach->dmabuf, attach);1061 dma_buf_detach(attach->dmabuf, attach);
1062 /* remove the reference */1062 /* remove the reference */
drivers/gpu/drm/drm_simple_kms_helper.c+5−1
@@ -102,10 +102,14 @@ static int drm_simple_kms_crtc_check(struct drm_crtc *crtc, · 101 unmodified lines
102 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);102 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
103 int ret;103 int ret;
104 104
105 ret = drm_atomic_helper_check_crtc_state(crtc_state, false);105 if (!crtc_state->enable)
106 goto out;
107
108 ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state);
106 if (ret)109 if (ret)
107 return ret;110 return ret;
108 111
112out:
109 return drm_atomic_add_affected_planes(state, crtc);113 return drm_atomic_add_affected_planes(state, crtc);
110}114}
111 115
drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c+1−1
@@ -65,7 +65,7 @@ static void etnaviv_gem_prime_release(struct etnaviv_gem_object *etnaviv_obj) · 64 unmodified lines
65 struct iosys_map map = IOSYS_MAP_INIT_VADDR(etnaviv_obj->vaddr);65 struct iosys_map map = IOSYS_MAP_INIT_VADDR(etnaviv_obj->vaddr);
66 66
67 if (etnaviv_obj->vaddr)67 if (etnaviv_obj->vaddr)
68 dma_buf_vunmap(etnaviv_obj->base.import_attach->dmabuf, &map);68 dma_buf_vunmap_unlocked(etnaviv_obj->base.import_attach->dmabuf, &map);
69 69
70 /* Don't drop the pages for imported dmabuf, as they are not70 /* Don't drop the pages for imported dmabuf, as they are not
71 * ours, just free the array we allocated:71 * ours, just free the array we allocated:
drivers/gpu/drm/gma500/framebuffer.c+3−3
@@ -286,7 +286,7 @@ static int psbfb_create(struct drm_fb_helper *fb_helper, · 285 unmodified lines
286 286
287 info->fbops = &psbfb_unaccel_ops;287 info->fbops = &psbfb_unaccel_ops;
288 288
289 info->fix.smem_start = dev->mode_config.fb_base;289 info->fix.smem_start = dev_priv->fb_base;
290 info->fix.smem_len = size;290 info->fix.smem_len = size;
291 info->fix.ywrapstep = 0;291 info->fix.ywrapstep = 0;
292 info->fix.ypanstep = 0;292 info->fix.ypanstep = 0;
@@ -296,7 +296,7 @@ static int psbfb_create(struct drm_fb_helper *fb_helper, · 3 unmodified lines
296 info->screen_size = size;296 info->screen_size = size;
297 297
298 if (dev_priv->gtt.stolen_size) {298 if (dev_priv->gtt.stolen_size) {
299 info->apertures->ranges[0].base = dev->mode_config.fb_base;299 info->apertures->ranges[0].base = dev_priv->fb_base;
300 info->apertures->ranges[0].size = dev_priv->gtt.stolen_size;300 info->apertures->ranges[0].size = dev_priv->gtt.stolen_size;
301 }301 }
302 302
@@ -527,7 +527,7 @@ void psb_modeset_init(struct drm_device *dev) · 224 unmodified lines
527 527
528 /* set memory base */528 /* set memory base */
529 /* Oaktrail and Poulsbo should use BAR 2*/529 /* Oaktrail and Poulsbo should use BAR 2*/
530 pci_read_config_dword(pdev, PSB_BSM, (u32 *)&(dev->mode_config.fb_base));530 pci_read_config_dword(pdev, PSB_BSM, (u32 *)&(dev_priv->fb_base));
531 531
532 /* num pipes is 2 for PSB but 1 for Mrst */532 /* num pipes is 2 for PSB but 1 for Mrst */
533 for (i = 0; i < dev_priv->num_pipe; i++)533 for (i = 0; i < dev_priv->num_pipe; i++)
drivers/gpu/drm/gma500/psb_drv.h+1−0
@@ -523,6 +523,7 @@ struct drm_psb_private { · 522 unmodified lines
523 uint32_t blc_adj2;523 uint32_t blc_adj2;
524 524
525 struct drm_fb_helper *fb_helper;525 struct drm_fb_helper *fb_helper;
526 resource_size_t fb_base;
526 527
527 bool dsr_enable;528 bool dsr_enable;
528 u32 dsr_fb_update;529 u32 dsr_fb_update;
drivers/gpu/drm/gud/gud_connector.c+1−1
@@ -355,7 +355,7 @@ static void gud_connector_reset(struct drm_connector *connector) · 354 unmodified lines
355 drm_atomic_helper_connector_reset(connector);355 drm_atomic_helper_connector_reset(connector);
356 connector->state->tv = gconn->initial_tv_state;356 connector->state->tv = gconn->initial_tv_state;
357 /* Set margins from command line */357 /* Set margins from command line */
358 drm_atomic_helper_connector_tv_reset(connector);358 drm_atomic_helper_connector_tv_margins_reset(connector);
359 if (gconn->initial_brightness >= 0)359 if (gconn->initial_brightness >= 0)
360 connector->state->tv.brightness = gconn->initial_brightness;360 connector->state->tv.brightness = gconn->initial_brightness;
361}361}
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c+3−13
@@ -105,7 +105,6 @@ static int hibmc_kms_init(struct hibmc_drm_private *priv) · 104 unmodified lines
105 dev->mode_config.max_width = 1920;105 dev->mode_config.max_width = 1920;
106 dev->mode_config.max_height = 1200;106 dev->mode_config.max_height = 1200;
107 107
108 dev->mode_config.fb_base = priv->fb_base;
109 dev->mode_config.preferred_depth = 32;108 dev->mode_config.preferred_depth = 32;
110 dev->mode_config.prefer_shadow = 1;109 dev->mode_config.prefer_shadow = 1;
111 110
@@ -212,7 +211,7 @@ static int hibmc_hw_map(struct hibmc_drm_private *priv) · 100 unmodified lines
212{211{
213 struct drm_device *dev = &priv->dev;212 struct drm_device *dev = &priv->dev;
214 struct pci_dev *pdev = to_pci_dev(dev->dev);213 struct pci_dev *pdev = to_pci_dev(dev->dev);
215 resource_size_t addr, size, ioaddr, iosize;214 resource_size_t ioaddr, iosize;
216 215
217 ioaddr = pci_resource_start(pdev, 1);216 ioaddr = pci_resource_start(pdev, 1);
218 iosize = pci_resource_len(pdev, 1);217 iosize = pci_resource_len(pdev, 1);
@@ -222,16 +221,6 @@ static int hibmc_hw_map(struct hibmc_drm_private *priv) · 3 unmodified lines
222 return -ENOMEM;221 return -ENOMEM;
223 }222 }
224 223
225 addr = pci_resource_start(pdev, 0);
226 size = pci_resource_len(pdev, 0);
227 priv->fb_map = devm_ioremap(dev->dev, addr, size);
228 if (!priv->fb_map) {
229 drm_err(dev, "Cannot map framebuffer\n");
230 return -ENOMEM;
231 }
232 priv->fb_base = addr;
233 priv->fb_size = size;
234
235 return 0;224 return 0;
236}225}
237 226
@@ -271,7 +260,8 @@ static int hibmc_load(struct drm_device *dev) · 33 unmodified lines
271 if (ret)260 if (ret)
272 goto err;261 goto err;
273 262
274 ret = drmm_vram_helper_init(dev, pci_resource_start(pdev, 0), priv->fb_size);263 ret = drmm_vram_helper_init(dev, pci_resource_start(pdev, 0),
264 pci_resource_len(pdev, 0));
275 if (ret) {265 if (ret) {
276 drm_err(dev, "Error initializing VRAM MM; %d\n", ret);266 drm_err(dev, "Error initializing VRAM MM; %d\n", ret);
277 goto err;267 goto err;
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h+0−3
@@ -32,9 +32,6 @@ struct hibmc_connector { · 31 unmodified lines
32struct hibmc_drm_private {32struct hibmc_drm_private {
33 /* hw */33 /* hw */
34 void __iomem *mmio;34 void __iomem *mmio;
35 void __iomem *fb_map;
36 resource_size_t fb_base;
37 resource_size_t fb_size;
38 35
39 /* drm */36 /* drm */
40 struct drm_device dev;37 struct drm_device dev;
drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c+1−1
@@ -72,7 +72,7 @@ static int i915_gem_dmabuf_vmap(struct dma_buf *dma_buf, · 71 unmodified lines
72 struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);72 struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);
73 void *vaddr;73 void *vaddr;
74 74
75 vaddr = i915_gem_object_pin_map_unlocked(obj, I915_MAP_WB);75 vaddr = i915_gem_object_pin_map(obj, I915_MAP_WB);
76 if (IS_ERR(vaddr))76 if (IS_ERR(vaddr))
77 return PTR_ERR(vaddr);77 return PTR_ERR(vaddr);
78 78
drivers/gpu/drm/i915/gem/i915_gem_object.c+14−0
@@ -290,7 +290,21 @@ void __i915_gem_object_pages_fini(struct drm_i915_gem_object *obj) · 289 unmodified lines
290 __i915_gem_object_free_mmaps(obj);290 __i915_gem_object_free_mmaps(obj);
291 291
292 atomic_set(&obj->mm.pages_pin_count, 0);292 atomic_set(&obj->mm.pages_pin_count, 0);
293
294 /*
295 * dma_buf_unmap_attachment() requires reservation to be
296 * locked. The imported GEM shouldn't share reservation lock
297 * and ttm_bo_cleanup_memtype_use() shouldn't be invoked for
298 * dma-buf, so it's safe to take the lock.
299 */
300 if (obj->base.import_attach)
301 i915_gem_object_lock(obj, NULL);
302
293 __i915_gem_object_put_pages(obj);303 __i915_gem_object_put_pages(obj);
304
305 if (obj->base.import_attach)
306 i915_gem_object_unlock(obj);
307
294 GEM_BUG_ON(i915_gem_object_has_pages(obj));308 GEM_BUG_ON(i915_gem_object_has_pages(obj));
295}309}
296 310
drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c+8−8
@@ -213,7 +213,7 @@ static int igt_dmabuf_import_same_driver(struct drm_i915_private *i915, · 212 unmodified lines
213 goto out_import;213 goto out_import;
214 }214 }
215 215
216 st = dma_buf_map_attachment(import_attach, DMA_BIDIRECTIONAL);216 st = dma_buf_map_attachment_unlocked(import_attach, DMA_BIDIRECTIONAL);
217 if (IS_ERR(st)) {217 if (IS_ERR(st)) {
218 err = PTR_ERR(st);218 err = PTR_ERR(st);
219 goto out_detach;219 goto out_detach;
@@ -226,7 +226,7 @@ static int igt_dmabuf_import_same_driver(struct drm_i915_private *i915, · 6 unmodified lines
226 timeout = -ETIME;226 timeout = -ETIME;
227 }227 }
228 err = timeout > 0 ? 0 : timeout;228 err = timeout > 0 ? 0 : timeout;
229 dma_buf_unmap_attachment(import_attach, st, DMA_BIDIRECTIONAL);229 dma_buf_unmap_attachment_unlocked(import_attach, st, DMA_BIDIRECTIONAL);
230out_detach:230out_detach:
231 dma_buf_detach(dmabuf, import_attach);231 dma_buf_detach(dmabuf, import_attach);
232out_import:232out_import:
@@ -296,7 +296,7 @@ static int igt_dmabuf_import(void *arg) · 63 unmodified lines
296 goto out_obj;296 goto out_obj;
297 }297 }
298 298
299 err = dma_buf_vmap(dmabuf, &map);299 err = dma_buf_vmap_unlocked(dmabuf, &map);
300 dma_map = err ? NULL : map.vaddr;300 dma_map = err ? NULL : map.vaddr;
301 if (!dma_map) {301 if (!dma_map) {
302 pr_err("dma_buf_vmap failed\n");302 pr_err("dma_buf_vmap failed\n");
@@ -337,7 +337,7 @@ static int igt_dmabuf_import(void *arg) · 34 unmodified lines
337 337
338 err = 0;338 err = 0;
339out_dma_map:339out_dma_map:
340 dma_buf_vunmap(dmabuf, &map);340 dma_buf_vunmap_unlocked(dmabuf, &map);
341out_obj:341out_obj:
342 i915_gem_object_put(obj);342 i915_gem_object_put(obj);
343out_dmabuf:343out_dmabuf:
@@ -358,7 +358,7 @@ static int igt_dmabuf_import_ownership(void *arg) · 14 unmodified lines
358 if (IS_ERR(dmabuf))358 if (IS_ERR(dmabuf))
359 return PTR_ERR(dmabuf);359 return PTR_ERR(dmabuf);
360 360
361 err = dma_buf_vmap(dmabuf, &map);361 err = dma_buf_vmap_unlocked(dmabuf, &map);
362 ptr = err ? NULL : map.vaddr;362 ptr = err ? NULL : map.vaddr;
363 if (!ptr) {363 if (!ptr) {
364 pr_err("dma_buf_vmap failed\n");364 pr_err("dma_buf_vmap failed\n");
@@ -367,7 +367,7 @@ static int igt_dmabuf_import_ownership(void *arg) · 2 unmodified lines
367 }367 }
368 368
369 memset(ptr, 0xc5, PAGE_SIZE);369 memset(ptr, 0xc5, PAGE_SIZE);
370 dma_buf_vunmap(dmabuf, &map);370 dma_buf_vunmap_unlocked(dmabuf, &map);
371 371
372 obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf));372 obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf));
373 if (IS_ERR(obj)) {373 if (IS_ERR(obj)) {
@@ -418,7 +418,7 @@ static int igt_dmabuf_export_vmap(void *arg) · 44 unmodified lines
418 }418 }
419 i915_gem_object_put(obj);419 i915_gem_object_put(obj);
420 420
421 err = dma_buf_vmap(dmabuf, &map);421 err = dma_buf_vmap_unlocked(dmabuf, &map);
422 ptr = err ? NULL : map.vaddr;422 ptr = err ? NULL : map.vaddr;
423 if (!ptr) {423 if (!ptr) {
424 pr_err("dma_buf_vmap failed\n");424 pr_err("dma_buf_vmap failed\n");
@@ -435,7 +435,7 @@ static int igt_dmabuf_export_vmap(void *arg) · 10 unmodified lines
435 memset(ptr, 0xc5, dmabuf->size);435 memset(ptr, 0xc5, dmabuf->size);
436 436
437 err = 0;437 err = 0;
438 dma_buf_vunmap(dmabuf, &map);438 dma_buf_vunmap_unlocked(dmabuf, &map);
439out:439out:
440 dma_buf_put(dmabuf);440 dma_buf_put(dmabuf);
441 return err;441 return err;
drivers/gpu/drm/lima/lima_sched.c+2−2
@@ -371,7 +371,7 @@ static void lima_sched_build_error_task_list(struct lima_sched_task *task) · 370 unmodified lines
371 } else {371 } else {
372 buffer_chunk->size = lima_bo_size(bo);372 buffer_chunk->size = lima_bo_size(bo);
373 373
374 ret = drm_gem_shmem_vmap(&bo->base, &map);374 ret = drm_gem_vmap_unlocked(&bo->base.base, &map);
375 if (ret) {375 if (ret) {
376 kvfree(et);376 kvfree(et);
377 goto out;377 goto out;
@@ -379,7 +379,7 @@ static void lima_sched_build_error_task_list(struct lima_sched_task *task) · 1 unmodified line
379 379
380 memcpy(buffer_chunk + 1, map.vaddr, buffer_chunk->size);380 memcpy(buffer_chunk + 1, map.vaddr, buffer_chunk->size);
381 381
382 drm_gem_shmem_vunmap(&bo->base, &map);382 drm_gem_vunmap_unlocked(&bo->base.base, &map);
383 }383 }
384 384
385 buffer_chunk = (void *)(buffer_chunk + 1) + buffer_chunk->size;385 buffer_chunk = (void *)(buffer_chunk + 1) + buffer_chunk->size;
drivers/gpu/drm/mgag200/mgag200_g200se.c+2−1
@@ -284,7 +284,8 @@ static void mgag200_g200se_04_pixpllc_atomic_update(struct drm_crtc *crtc, · 283 unmodified lines
284 pixpllcp = pixpllc->p - 1;284 pixpllcp = pixpllc->p - 1;
285 pixpllcs = pixpllc->s;285 pixpllcs = pixpllc->s;
286 286
287 xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1);287 // For G200SE A, BIT(7) should be set unconditionally.
288 xpixpllcm = BIT(7) | pixpllcm;
288 xpixpllcn = pixpllcn;289 xpixpllcn = pixpllcn;
289 xpixpllcp = (pixpllcs << 3) | pixpllcp;290 xpixpllcp = (pixpllcs << 3) | pixpllcp;
290 291
drivers/gpu/drm/mgag200/mgag200_mode.c+5−6
@@ -579,13 +579,13 @@ int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_st · 578 unmodified lines
579 struct drm_property_blob *new_gamma_lut = new_crtc_state->gamma_lut;579 struct drm_property_blob *new_gamma_lut = new_crtc_state->gamma_lut;
580 int ret;580 int ret;
581 581
582 ret = drm_atomic_helper_check_crtc_state(new_crtc_state, false);
583 if (ret)
584 return ret;
585
586 if (!new_crtc_state->enable)582 if (!new_crtc_state->enable)
587 return 0;583 return 0;
588 584
585 ret = drm_atomic_helper_check_crtc_primary_plane(new_crtc_state);
586 if (ret)
587 return ret;
588
589 if (new_crtc_state->mode_changed) {589 if (new_crtc_state->mode_changed) {
590 if (funcs->pixpllc_atomic_check) {590 if (funcs->pixpllc_atomic_check) {
591 ret = funcs->pixpllc_atomic_check(crtc, new_state);591 ret = funcs->pixpllc_atomic_check(crtc, new_state);
@@ -601,7 +601,7 @@ int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_st · 9 unmodified lines
601 }601 }
602 }602 }
603 603
604 return drm_atomic_add_affected_planes(new_state, crtc);604 return 0;
605}605}
606 606
607void mgag200_crtc_helper_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *old_state)607void mgag200_crtc_helper_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *old_state)
@@ -824,7 +824,6 @@ int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vram_avail · 216 unmodified lines
824 dev->mode_config.max_width = MGAG200_MAX_FB_WIDTH;824 dev->mode_config.max_width = MGAG200_MAX_FB_WIDTH;
825 dev->mode_config.max_height = MGAG200_MAX_FB_HEIGHT;825 dev->mode_config.max_height = MGAG200_MAX_FB_HEIGHT;
826 dev->mode_config.preferred_depth = 24;826 dev->mode_config.preferred_depth = 24;
827 dev->mode_config.fb_base = mdev->vram_res->start;
828 dev->mode_config.funcs = &mgag200_mode_config_funcs;827 dev->mode_config.funcs = &mgag200_mode_config_funcs;
829 dev->mode_config.helper_private = &mgag200_mode_config_helper_funcs;828 dev->mode_config.helper_private = &mgag200_mode_config_helper_funcs;
830 829
drivers/gpu/drm/msm/msm_fbdev.c+0−2
@@ -109,8 +109,6 @@ static int msm_fbdev_create(struct drm_fb_helper *helper, · 108 unmodified lines
109 109
110 drm_fb_helper_fill_info(fbi, helper, sizes);110 drm_fb_helper_fill_info(fbi, helper, sizes);
111 111
112 dev->mode_config.fb_base = paddr;
113
114 fbi->screen_base = msm_gem_get_vaddr(bo);112 fbi->screen_base = msm_gem_get_vaddr(bo);
115 if (IS_ERR(fbi->screen_base)) {113 if (IS_ERR(fbi->screen_base)) {
116 ret = PTR_ERR(fbi->screen_base);114 ret = PTR_ERR(fbi->screen_base);
drivers/gpu/drm/mxsfb/lcdif_kms.c+216−23
@@ -15,6 +15,7 @@ · 14 unmodified lines
15#include <drm/drm_atomic.h>15#include <drm/drm_atomic.h>
16#include <drm/drm_atomic_helper.h>16#include <drm/drm_atomic_helper.h>
17#include <drm/drm_bridge.h>17#include <drm/drm_bridge.h>
18#include <drm/drm_color_mgmt.h>
18#include <drm/drm_crtc.h>19#include <drm/drm_crtc.h>
19#include <drm/drm_encoder.h>20#include <drm/drm_encoder.h>
20#include <drm/drm_fb_dma_helper.h>21#include <drm/drm_fb_dma_helper.h>
@@ -31,13 +32,126 @@ · 10 unmodified lines
31/* -----------------------------------------------------------------------------32/* -----------------------------------------------------------------------------
32 * CRTC33 * CRTC
33 */34 */
35
36/*
37 * For conversion from YCbCr to RGB, the CSC operates as follows:
38 *
39 * |R| |A1 A2 A3| |Y + D1|
40 * |G| = |B1 B2 B3| * |Cb + D2|
41 * |B| |C1 C2 C3| |Cr + D3|
42 *
43 * The A, B and C coefficients are expressed as Q2.8 fixed point values, and
44 * the D coefficients as Q0.8. Despite the reference manual stating the
45 * opposite, the D1, D2 and D3 offset values are added to Y, Cb and Cr, not
46 * subtracted. They must thus be programmed with negative values.
47 */
48static const u32 lcdif_yuv2rgb_coeffs[3][2][6] = {
49 [DRM_COLOR_YCBCR_BT601] = {
50 [DRM_COLOR_YCBCR_LIMITED_RANGE] = {
51 /*
52 * BT.601 limited range:
53 *
54 * |R| |1.1644 0.0000 1.5960| |Y - 16 |
55 * |G| = |1.1644 -0.3917 -0.8129| * |Cb - 128|
56 * |B| |1.1644 2.0172 0.0000| |Cr - 128|
57 */
58 CSC0_COEF0_A1(0x12a) | CSC0_COEF0_A2(0x000),
59 CSC0_COEF1_A3(0x199) | CSC0_COEF1_B1(0x12a),
60 CSC0_COEF2_B2(0x79c) | CSC0_COEF2_B3(0x730),
61 CSC0_COEF3_C1(0x12a) | CSC0_COEF3_C2(0x204),
62 CSC0_COEF4_C3(0x000) | CSC0_COEF4_D1(0x1f0),
63 CSC0_COEF5_D2(0x180) | CSC0_COEF5_D3(0x180),
64 },
65 [DRM_COLOR_YCBCR_FULL_RANGE] = {
66 /*
67 * BT.601 full range:
68 *
69 * |R| |1.0000 0.0000 1.4020| |Y - 0 |
70 * |G| = |1.0000 -0.3441 -0.7141| * |Cb - 128|
71 * |B| |1.0000 1.7720 0.0000| |Cr - 128|
72 */
73 CSC0_COEF0_A1(0x100) | CSC0_COEF0_A2(0x000),
74 CSC0_COEF1_A3(0x167) | CSC0_COEF1_B1(0x100),
75 CSC0_COEF2_B2(0x7a8) | CSC0_COEF2_B3(0x749),
76 CSC0_COEF3_C1(0x100) | CSC0_COEF3_C2(0x1c6),
77 CSC0_COEF4_C3(0x000) | CSC0_COEF4_D1(0x000),
78 CSC0_COEF5_D2(0x180) | CSC0_COEF5_D3(0x180),
79 },
80 },
81 [DRM_COLOR_YCBCR_BT709] = {
82 [DRM_COLOR_YCBCR_LIMITED_RANGE] = {
83 /*
84 * Rec.709 limited range:
85 *
86 * |R| |1.1644 0.0000 1.7927| |Y - 16 |
87 * |G| = |1.1644 -0.2132 -0.5329| * |Cb - 128|
88 * |B| |1.1644 2.1124 0.0000| |Cr - 128|
89 */
90 CSC0_COEF0_A1(0x12a) | CSC0_COEF0_A2(0x000),
91 CSC0_COEF1_A3(0x1cb) | CSC0_COEF1_B1(0x12a),
92 CSC0_COEF2_B2(0x7c9) | CSC0_COEF2_B3(0x778),
93 CSC0_COEF3_C1(0x12a) | CSC0_COEF3_C2(0x21d),
94 CSC0_COEF4_C3(0x000) | CSC0_COEF4_D1(0x1f0),
95 CSC0_COEF5_D2(0x180) | CSC0_COEF5_D3(0x180),
96 },
97 [DRM_COLOR_YCBCR_FULL_RANGE] = {
98 /*
99 * Rec.709 full range:
100 *
101 * |R| |1.0000 0.0000 1.5748| |Y - 0 |
102 * |G| = |1.0000 -0.1873 -0.4681| * |Cb - 128|
103 * |B| |1.0000 1.8556 0.0000| |Cr - 128|
104 */
105 CSC0_COEF0_A1(0x100) | CSC0_COEF0_A2(0x000),
106 CSC0_COEF1_A3(0x193) | CSC0_COEF1_B1(0x100),
107 CSC0_COEF2_B2(0x7d0) | CSC0_COEF2_B3(0x788),
108 CSC0_COEF3_C1(0x100) | CSC0_COEF3_C2(0x1db),
109 CSC0_COEF4_C3(0x000) | CSC0_COEF4_D1(0x000),
110 CSC0_COEF5_D2(0x180) | CSC0_COEF5_D3(0x180),
111 },
112 },
113 [DRM_COLOR_YCBCR_BT2020] = {
114 [DRM_COLOR_YCBCR_LIMITED_RANGE] = {
115 /*
116 * BT.2020 limited range:
117 *
118 * |R| |1.1644 0.0000 1.6787| |Y - 16 |
119 * |G| = |1.1644 -0.1874 -0.6505| * |Cb - 128|
120 * |B| |1.1644 2.1418 0.0000| |Cr - 128|
121 */
122 CSC0_COEF0_A1(0x12a) | CSC0_COEF0_A2(0x000),
123 CSC0_COEF1_A3(0x1ae) | CSC0_COEF1_B1(0x12a),
124 CSC0_COEF2_B2(0x7d0) | CSC0_COEF2_B3(0x759),
125 CSC0_COEF3_C1(0x12a) | CSC0_COEF3_C2(0x224),
126 CSC0_COEF4_C3(0x000) | CSC0_COEF4_D1(0x1f0),
127 CSC0_COEF5_D2(0x180) | CSC0_COEF5_D3(0x180),
128 },
129 [DRM_COLOR_YCBCR_FULL_RANGE] = {
130 /*
131 * BT.2020 full range:
132 *
133 * |R| |1.0000 0.0000 1.4746| |Y - 0 |
134 * |G| = |1.0000 -0.1646 -0.5714| * |Cb - 128|
135 * |B| |1.0000 1.8814 0.0000| |Cr - 128|
136 */
137 CSC0_COEF0_A1(0x100) | CSC0_COEF0_A2(0x000),
138 CSC0_COEF1_A3(0x179) | CSC0_COEF1_B1(0x100),
139 CSC0_COEF2_B2(0x7d6) | CSC0_COEF2_B3(0x76e),
140 CSC0_COEF3_C1(0x100) | CSC0_COEF3_C2(0x1e2),
141 CSC0_COEF4_C3(0x000) | CSC0_COEF4_D1(0x000),
142 CSC0_COEF5_D2(0x180) | CSC0_COEF5_D3(0x180),
143 },
144 },
145};
146
34static void lcdif_set_formats(struct lcdif_drm_private *lcdif,147static void lcdif_set_formats(struct lcdif_drm_private *lcdif,
148 struct drm_plane_state *plane_state,
35 const u32 bus_format)149 const u32 bus_format)
36{150{
37 struct drm_device *drm = lcdif->drm;151 struct drm_device *drm = lcdif->drm;
38 const u32 format = lcdif->crtc.primary->state->fb->format->format;152 const u32 format = plane_state->fb->format->format;
39 153 bool in_yuv = false;
40 writel(CSC0_CTRL_BYPASS, lcdif->base + LCDC_V8_CSC0_CTRL);154 bool out_yuv = false;
41 155
42 switch (bus_format) {156 switch (bus_format) {
43 case MEDIA_BUS_FMT_RGB565_1X16:157 case MEDIA_BUS_FMT_RGB565_1X16:
@@ -51,24 +165,7 @@ static void lcdif_set_formats(struct lcdif_drm_private *lcdif, · 7 unmodified lines
51 case MEDIA_BUS_FMT_UYVY8_1X16:165 case MEDIA_BUS_FMT_UYVY8_1X16:
52 writel(DISP_PARA_LINE_PATTERN_UYVY_H,166 writel(DISP_PARA_LINE_PATTERN_UYVY_H,
53 lcdif->base + LCDC_V8_DISP_PARA);167 lcdif->base + LCDC_V8_DISP_PARA);
54 168 out_yuv = true;
55 /* CSC: BT.601 Full Range RGB to YCbCr coefficients. */
56 writel(CSC0_COEF0_A2(0x096) | CSC0_COEF0_A1(0x04c),
57 lcdif->base + LCDC_V8_CSC0_COEF0);
58 writel(CSC0_COEF1_B1(0x7d5) | CSC0_COEF1_A3(0x01d),
59 lcdif->base + LCDC_V8_CSC0_COEF1);
60 writel(CSC0_COEF2_B3(0x080) | CSC0_COEF2_B2(0x7ac),
61 lcdif->base + LCDC_V8_CSC0_COEF2);
62 writel(CSC0_COEF3_C2(0x795) | CSC0_COEF3_C1(0x080),
63 lcdif->base + LCDC_V8_CSC0_COEF3);
64 writel(CSC0_COEF4_D1(0x000) | CSC0_COEF4_C3(0x7ec),
65 lcdif->base + LCDC_V8_CSC0_COEF4);
66 writel(CSC0_COEF5_D3(0x080) | CSC0_COEF5_D2(0x080),
67 lcdif->base + LCDC_V8_CSC0_COEF5);
68
69 writel(CSC0_CTRL_CSC_MODE_RGB2YCbCr,
70 lcdif->base + LCDC_V8_CSC0_CTRL);
71
72 break;169 break;
73 default:170 default:
74 dev_err(drm->dev, "Unknown media bus format 0x%x\n", bus_format);171 dev_err(drm->dev, "Unknown media bus format 0x%x\n", bus_format);
@@ -76,6 +173,7 @@ static void lcdif_set_formats(struct lcdif_drm_private *lcdif, · 1 unmodified line
76 }173 }
77 174
78 switch (format) {175 switch (format) {
176 /* RGB Formats */
79 case DRM_FORMAT_RGB565:177 case DRM_FORMAT_RGB565:
80 writel(CTRLDESCL0_5_BPP_16_RGB565,178 writel(CTRLDESCL0_5_BPP_16_RGB565,
81 lcdif->base + LCDC_V8_CTRLDESCL0_5);179 lcdif->base + LCDC_V8_CTRLDESCL0_5);
@@ -100,10 +198,84 @@ static void lcdif_set_formats(struct lcdif_drm_private *lcdif, · 18 unmodified lines
100 writel(CTRLDESCL0_5_BPP_32_ARGB8888,198 writel(CTRLDESCL0_5_BPP_32_ARGB8888,
101 lcdif->base + LCDC_V8_CTRLDESCL0_5);199 lcdif->base + LCDC_V8_CTRLDESCL0_5);
102 break;200 break;
201
202 /* YUV Formats */
203 case DRM_FORMAT_YUYV:
204 writel(CTRLDESCL0_5_BPP_YCbCr422 | CTRLDESCL0_5_YUV_FORMAT_VY2UY1,
205 lcdif->base + LCDC_V8_CTRLDESCL0_5);
206 in_yuv = true;
207 break;
208 case DRM_FORMAT_YVYU:
209 writel(CTRLDESCL0_5_BPP_YCbCr422 | CTRLDESCL0_5_YUV_FORMAT_UY2VY1,
210 lcdif->base + LCDC_V8_CTRLDESCL0_5);
211 in_yuv = true;
212 break;
213 case DRM_FORMAT_UYVY:
214 writel(CTRLDESCL0_5_BPP_YCbCr422 | CTRLDESCL0_5_YUV_FORMAT_Y2VY1U,
215 lcdif->base + LCDC_V8_CTRLDESCL0_5);
216 in_yuv = true;
217 break;
218 case DRM_FORMAT_VYUY:
219 writel(CTRLDESCL0_5_BPP_YCbCr422 | CTRLDESCL0_5_YUV_FORMAT_Y2UY1V,
220 lcdif->base + LCDC_V8_CTRLDESCL0_5);
221 in_yuv = true;
222 break;
223
103 default:224 default:
104 dev_err(drm->dev, "Unknown pixel format 0x%x\n", format);225 dev_err(drm->dev, "Unknown pixel format 0x%x\n", format);
105 break;226 break;
106 }227 }
228
229 /*
230 * The CSC differentiates between "YCbCr" and "YUV", but the reference
231 * manual doesn't detail how they differ. Experiments showed that the
232 * luminance value is unaffected, only the calculations involving chroma
233 * values differ. The YCbCr mode behaves as expected, with chroma values
234 * being offset by 128. The YUV mode isn't fully understood.
235 */
236 if (!in_yuv && out_yuv) {
237 /* RGB -> YCbCr */
238 writel(CSC0_CTRL_CSC_MODE_RGB2YCbCr,
239 lcdif->base + LCDC_V8_CSC0_CTRL);
240
241 /*
242 * CSC: BT.601 Limited Range RGB to YCbCr coefficients.
243 *
244 * |Y | | 0.2568 0.5041 0.0979| |R| |16 |
245 * |Cb| = |-0.1482 -0.2910 0.4392| * |G| + |128|
246 * |Cr| | 0.4392 0.4392 -0.3678| |B| |128|
247 */
248 writel(CSC0_COEF0_A2(0x081) | CSC0_COEF0_A1(0x041),
249 lcdif->base + LCDC_V8_CSC0_COEF0);
250 writel(CSC0_COEF1_B1(0x7db) | CSC0_COEF1_A3(0x019),
251 lcdif->base + LCDC_V8_CSC0_COEF1);
252 writel(CSC0_COEF2_B3(0x070) | CSC0_COEF2_B2(0x7b6),
253 lcdif->base + LCDC_V8_CSC0_COEF2);
254 writel(CSC0_COEF3_C2(0x7a2) | CSC0_COEF3_C1(0x070),
255 lcdif->base + LCDC_V8_CSC0_COEF3);
256 writel(CSC0_COEF4_D1(0x010) | CSC0_COEF4_C3(0x7ee),
257 lcdif->base + LCDC_V8_CSC0_COEF4);
258 writel(CSC0_COEF5_D3(0x080) | CSC0_COEF5_D2(0x080),
259 lcdif->base + LCDC_V8_CSC0_COEF5);
260 } else if (in_yuv && !out_yuv) {
261 /* YCbCr -> RGB */
262 const u32 *coeffs =
263 lcdif_yuv2rgb_coeffs[plane_state->color_encoding]
264 [plane_state->color_range];
265
266 writel(CSC0_CTRL_CSC_MODE_YCbCr2RGB,
267 lcdif->base + LCDC_V8_CSC0_CTRL);
268
269 writel(coeffs[0], lcdif->base + LCDC_V8_CSC0_COEF0);
270 writel(coeffs[1], lcdif->base + LCDC_V8_CSC0_COEF1);
271 writel(coeffs[2], lcdif->base + LCDC_V8_CSC0_COEF2);
272 writel(coeffs[3], lcdif->base + LCDC_V8_CSC0_COEF3);
273 writel(coeffs[4], lcdif->base + LCDC_V8_CSC0_COEF4);
274 writel(coeffs[5], lcdif->base + LCDC_V8_CSC0_COEF5);
275 } else {
276 /* RGB -> RGB, YCbCr -> YCbCr: bypass colorspace converter. */
277 writel(CSC0_CTRL_BYPASS, lcdif->base + LCDC_V8_CSC0_CTRL);
278 }
107}279}
108 280
109static void lcdif_set_mode(struct lcdif_drm_private *lcdif, u32 bus_flags)281static void lcdif_set_mode(struct lcdif_drm_private *lcdif, u32 bus_flags)
@@ -188,6 +360,7 @@ static void lcdif_reset_block(struct lcdif_drm_private *lcdif) · 78 unmodified lines
188}360}
189 361
190static void lcdif_crtc_mode_set_nofb(struct lcdif_drm_private *lcdif,362static void lcdif_crtc_mode_set_nofb(struct lcdif_drm_private *lcdif,
363 struct drm_plane_state *plane_state,
191 struct drm_bridge_state *bridge_state,364 struct drm_bridge_state *bridge_state,
192 const u32 bus_format)365 const u32 bus_format)
193{366{
@@ -210,7 +383,7 @@ static void lcdif_crtc_mode_set_nofb(struct lcdif_drm_private *lcdif, · 16 unmodified lines
210 /* Mandatory eLCDIF reset as per the Reference Manual */383 /* Mandatory eLCDIF reset as per the Reference Manual */
211 lcdif_reset_block(lcdif);384 lcdif_reset_block(lcdif);
212 385
213 lcdif_set_formats(lcdif, bus_format);386 lcdif_set_formats(lcdif, plane_state, bus_format);
214 387
215 lcdif_set_mode(lcdif, bus_flags);388 lcdif_set_mode(lcdif, bus_flags);
216}389}
@@ -293,7 +466,7 @@ static void lcdif_crtc_atomic_enable(struct drm_crtc *crtc, · 76 unmodified lines
293 466
294 pm_runtime_get_sync(drm->dev);467 pm_runtime_get_sync(drm->dev);
295 468
296 lcdif_crtc_mode_set_nofb(lcdif, bridge_state, bus_format);469 lcdif_crtc_mode_set_nofb(lcdif, new_pstate, bridge_state, bus_format);
297 470
298 /* Write cur_buf as well to avoid an initial corrupt frame */471 /* Write cur_buf as well to avoid an initial corrupt frame */
299 paddr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0);472 paddr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0);
@@ -437,12 +610,19 @@ static const struct drm_plane_funcs lcdif_plane_funcs = { · 137 unmodified lines
437};610};
438 611
439static const u32 lcdif_primary_plane_formats[] = {612static const u32 lcdif_primary_plane_formats[] = {
613 /* RGB */
440 DRM_FORMAT_RGB565,614 DRM_FORMAT_RGB565,
441 DRM_FORMAT_RGB888,615 DRM_FORMAT_RGB888,
442 DRM_FORMAT_XBGR8888,616 DRM_FORMAT_XBGR8888,
443 DRM_FORMAT_XRGB1555,617 DRM_FORMAT_XRGB1555,
444 DRM_FORMAT_XRGB4444,618 DRM_FORMAT_XRGB4444,
445 DRM_FORMAT_XRGB8888,619 DRM_FORMAT_XRGB8888,
620
621 /* Packed YCbCr */
622 DRM_FORMAT_YUYV,
623 DRM_FORMAT_YVYU,
624 DRM_FORMAT_UYVY,
625 DRM_FORMAT_VYUY,
446};626};
447 627
448static const u64 lcdif_modifiers[] = {628static const u64 lcdif_modifiers[] = {
@@ -456,6 +636,11 @@ static const u64 lcdif_modifiers[] = { · 7 unmodified lines
456 636
457int lcdif_kms_init(struct lcdif_drm_private *lcdif)637int lcdif_kms_init(struct lcdif_drm_private *lcdif)
458{638{
639 const u32 supported_encodings = BIT(DRM_COLOR_YCBCR_BT601) |
640 BIT(DRM_COLOR_YCBCR_BT709) |
641 BIT(DRM_COLOR_YCBCR_BT2020);
642 const u32 supported_ranges = BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
643 BIT(DRM_COLOR_YCBCR_FULL_RANGE);
459 struct drm_encoder *encoder = &lcdif->encoder;644 struct drm_encoder *encoder = &lcdif->encoder;
460 struct drm_crtc *crtc = &lcdif->crtc;645 struct drm_crtc *crtc = &lcdif->crtc;
461 int ret;646 int ret;
@@ -471,6 +656,14 @@ int lcdif_kms_init(struct lcdif_drm_private *lcdif) · 9 unmodified lines
471 if (ret)656 if (ret)
472 return ret;657 return ret;
473 658
659 ret = drm_plane_create_color_properties(&lcdif->planes.primary,
660 supported_encodings,
661 supported_ranges,
662 DRM_COLOR_YCBCR_BT601,
663 DRM_COLOR_YCBCR_LIMITED_RANGE);
664 if (ret)
665 return ret;
666
474 drm_crtc_helper_add(crtc, &lcdif_crtc_helper_funcs);667 drm_crtc_helper_add(crtc, &lcdif_crtc_helper_funcs);
475 ret = drm_crtc_init_with_planes(lcdif->drm, crtc,668 ret = drm_crtc_init_with_planes(lcdif->drm, crtc,
476 &lcdif->planes.primary, NULL,669 &lcdif->planes.primary, NULL,
drivers/gpu/drm/mxsfb/lcdif_regs.h+20−17
@@ -130,7 +130,7 @@ · 129 unmodified lines
130#define CTRL_FETCH_START_OPTION_BPV BIT(9)130#define CTRL_FETCH_START_OPTION_BPV BIT(9)
131#define CTRL_FETCH_START_OPTION_RESV GENMASK(9, 8)131#define CTRL_FETCH_START_OPTION_RESV GENMASK(9, 8)
132#define CTRL_FETCH_START_OPTION_MASK GENMASK(9, 8)132#define CTRL_FETCH_START_OPTION_MASK GENMASK(9, 8)
133#define CTRL_NEG BIT(4)133#define CTRL_NEG BIT(4)
134#define CTRL_INV_PXCK BIT(3)134#define CTRL_INV_PXCK BIT(3)
135#define CTRL_INV_DE BIT(2)135#define CTRL_INV_DE BIT(2)
136#define CTRL_INV_VS BIT(1)136#define CTRL_INV_VS BIT(1)
@@ -138,9 +138,9 @@ · 1 unmodified line
138 138
139#define DISP_PARA_DISP_ON BIT(31)139#define DISP_PARA_DISP_ON BIT(31)
140#define DISP_PARA_SWAP_EN BIT(30)140#define DISP_PARA_SWAP_EN BIT(30)
141#define DISP_PARA_LINE_PATTERN_UYVY_H (GENMASK(29, 28) | BIT(26))141#define DISP_PARA_LINE_PATTERN_UYVY_H (0xd << 26)
142#define DISP_PARA_LINE_PATTERN_RGB565 GENMASK(28, 26)142#define DISP_PARA_LINE_PATTERN_RGB565 (0x7 << 26)
143#define DISP_PARA_LINE_PATTERN_RGB888 0143#define DISP_PARA_LINE_PATTERN_RGB888 (0x0 << 26)
144#define DISP_PARA_LINE_PATTERN_MASK GENMASK(29, 26)144#define DISP_PARA_LINE_PATTERN_MASK GENMASK(29, 26)
145#define DISP_PARA_DISP_MODE_MASK GENMASK(25, 24)145#define DISP_PARA_DISP_MODE_MASK GENMASK(25, 24)
146#define DISP_PARA_BGND_R_MASK GENMASK(23, 16)146#define DISP_PARA_BGND_R_MASK GENMASK(23, 16)
@@ -186,7 +186,7 @@ · 39 unmodified lines
186#define INT_ENABLE_D1_PLANE_PANIC_EN BIT(0)186#define INT_ENABLE_D1_PLANE_PANIC_EN BIT(0)
187 187
188#define CTRLDESCL0_1_HEIGHT(n) (((n) & 0xffff) << 16)188#define CTRLDESCL0_1_HEIGHT(n) (((n) & 0xffff) << 16)
189#define CTRLDESCL0_1_HEIGHT_MASK GENMASK(31, 16)189#define CTRLDESCL0_1_HEIGHT_MASK GENMASK(31, 16)
190#define CTRLDESCL0_1_WIDTH(n) ((n) & 0xffff)190#define CTRLDESCL0_1_WIDTH(n) ((n) & 0xffff)
191#define CTRLDESCL0_1_WIDTH_MASK GENMASK(15, 0)191#define CTRLDESCL0_1_WIDTH_MASK GENMASK(15, 0)
192 192
@@ -198,21 +198,24 @@ · 5 unmodified lines
198 198
199#define CTRLDESCL0_5_EN BIT(31)199#define CTRLDESCL0_5_EN BIT(31)
200#define CTRLDESCL0_5_SHADOW_LOAD_EN BIT(30)200#define CTRLDESCL0_5_SHADOW_LOAD_EN BIT(30)
201#define CTRLDESCL0_5_BPP_16_RGB565 BIT(26)201#define CTRLDESCL0_5_BPP_16_RGB565 (0x4 << 24)
202#define CTRLDESCL0_5_BPP_16_ARGB1555 (BIT(26) | BIT(24))202#define CTRLDESCL0_5_BPP_16_ARGB1555 (0x5 << 24)
203#define CTRLDESCL0_5_BPP_16_ARGB4444 (BIT(26) | BIT(25))203#define CTRLDESCL0_5_BPP_16_ARGB4444 (0x6 << 24)
204#define CTRLDESCL0_5_BPP_YCbCr422 (BIT(26) | BIT(25) | BIT(24))204#define CTRLDESCL0_5_BPP_YCbCr422 (0x7 << 24)
205#define CTRLDESCL0_5_BPP_24_RGB888 BIT(27)205#define CTRLDESCL0_5_BPP_24_RGB888 (0x8 << 24)
206#define CTRLDESCL0_5_BPP_32_ARGB8888 (BIT(27) | BIT(24))206#define CTRLDESCL0_5_BPP_32_ARGB8888 (0x9 << 24)
207#define CTRLDESCL0_5_BPP_32_ABGR8888 (BIT(27) | BIT(25))207#define CTRLDESCL0_5_BPP_32_ABGR8888 (0xa << 24)
208#define CTRLDESCL0_5_BPP_MASK GENMASK(27, 24)208#define CTRLDESCL0_5_BPP_MASK GENMASK(27, 24)
209#define CTRLDESCL0_5_YUV_FORMAT_Y2VY1U 0209#define CTRLDESCL0_5_YUV_FORMAT_Y2VY1U (0x0 << 14)
210#define CTRLDESCL0_5_YUV_FORMAT_Y2UY1V BIT(14)210#define CTRLDESCL0_5_YUV_FORMAT_Y2UY1V (0x1 << 14)
211#define CTRLDESCL0_5_YUV_FORMAT_VY2UY1 BIT(15)211#define CTRLDESCL0_5_YUV_FORMAT_VY2UY1 (0x2 << 14)
212#define CTRLDESCL0_5_YUV_FORMAT_UY2VY1 (BIT(15) | BIT(14))212#define CTRLDESCL0_5_YUV_FORMAT_UY2VY1 (0x3 << 14)
213#define CTRLDESCL0_5_YUV_FORMAT_MASK GENMASK(15, 14)213#define CTRLDESCL0_5_YUV_FORMAT_MASK GENMASK(15, 14)
214 214
215#define CSC0_CTRL_CSC_MODE_RGB2YCbCr GENMASK(2, 1)215#define CSC0_CTRL_CSC_MODE_YUV2RGB (0x0 << 1)
216#define CSC0_CTRL_CSC_MODE_YCbCr2RGB (0x1 << 1)
217#define CSC0_CTRL_CSC_MODE_RGB2YUV (0x2 << 1)
218#define CSC0_CTRL_CSC_MODE_RGB2YCbCr (0x3 << 1)
216#define CSC0_CTRL_CSC_MODE_MASK GENMASK(2, 1)219#define CSC0_CTRL_CSC_MODE_MASK GENMASK(2, 1)
217#define CSC0_CTRL_BYPASS BIT(0)220#define CSC0_CTRL_BYPASS BIT(0)
218 221
drivers/gpu/drm/nouveau/dispnv50/disp.c+2−2
@@ -131,7 +131,7 @@ nv50_dmac_kick(struct nvif_push *push) · 130 unmodified lines
131{131{
132 struct nv50_dmac *dmac = container_of(push, typeof(*dmac), _push);132 struct nv50_dmac *dmac = container_of(push, typeof(*dmac), _push);
133 133
134 dmac->cur = push->cur - (u32 *)dmac->_push.mem.object.map.ptr;134 dmac->cur = push->cur - (u32 __iomem *)dmac->_push.mem.object.map.ptr;
135 if (dmac->put != dmac->cur) {135 if (dmac->put != dmac->cur) {
136 /* Push buffer fetches are not coherent with BAR1, we need to ensure136 /* Push buffer fetches are not coherent with BAR1, we need to ensure
137 * writes have been flushed right through to VRAM before writing PUT.137 * writes have been flushed right through to VRAM before writing PUT.
@@ -194,7 +194,7 @@ nv50_dmac_wait(struct nvif_push *push, u32 size) · 56 unmodified lines
194 if (WARN_ON(size > dmac->max))194 if (WARN_ON(size > dmac->max))
195 return -EINVAL;195 return -EINVAL;
196 196
197 dmac->cur = push->cur - (u32 *)dmac->_push.mem.object.map.ptr;197 dmac->cur = push->cur - (u32 __iomem *)dmac->_push.mem.object.map.ptr;
198 if (dmac->cur + size >= dmac->max) {198 if (dmac->cur + size >= dmac->max) {
199 int ret = nv50_dmac_wind(dmac);199 int ret = nv50_dmac_wind(dmac);
200 if (ret)200 if (ret)
drivers/gpu/drm/nouveau/nouveau_display.c+0−1
@@ -672,7 +672,6 @@ nouveau_display_create(struct drm_device *dev) · 671 unmodified lines
672 drm_mode_create_dvi_i_properties(dev);672 drm_mode_create_dvi_i_properties(dev);
673 673
674 dev->mode_config.funcs = &nouveau_mode_config_funcs;674 dev->mode_config.funcs = &nouveau_mode_config_funcs;
675 dev->mode_config.fb_base = device->func->resource_addr(device, 1);
676 675
677 dev->mode_config.min_width = 0;676 dev->mode_config.min_width = 0;
678 dev->mode_config.min_height = 0;677 dev->mode_config.min_height = 0;
drivers/gpu/drm/nouveau/nv04_fbcon.c+4−2
@@ -137,6 +137,8 @@ nv04_fbcon_accel_init(struct fb_info *info) · 136 unmodified lines
137 struct nouveau_channel *chan = drm->channel;137 struct nouveau_channel *chan = drm->channel;
138 struct nvif_device *device = &drm->client.device;138 struct nvif_device *device = &drm->client.device;
139 struct nvif_push *push = chan->chan.push;139 struct nvif_push *push = chan->chan.push;
140 struct nvkm_device *nvkm_device = nvxx_device(&drm->client.device);
141 resource_size_t fb_base = nvkm_device->func->resource_addr(nvkm_device, 1);
140 int surface_fmt, pattern_fmt, rect_fmt;142 int surface_fmt, pattern_fmt, rect_fmt;
141 int ret;143 int ret;
142 144
@@ -210,8 +212,8 @@ nv04_fbcon_accel_init(struct fb_info *info) · 67 unmodified lines
210 0x0188, chan->vram.handle);212 0x0188, chan->vram.handle);
211 PUSH_NVSQ(push, NV042, 0x0300, surface_fmt,213 PUSH_NVSQ(push, NV042, 0x0300, surface_fmt,
212 0x0304, info->fix.line_length | (info->fix.line_length << 16),214 0x0304, info->fix.line_length | (info->fix.line_length << 16),
213 0x0308, info->fix.smem_start - dev->mode_config.fb_base,215 0x0308, info->fix.smem_start - fb_base,
214 0x030c, info->fix.smem_start - dev->mode_config.fb_base);216 0x030c, info->fix.smem_start - fb_base);
215 217
216 PUSH_NVSQ(push, NV043, 0x0000, nfbdev->rop.handle);218 PUSH_NVSQ(push, NV043, 0x0000, nfbdev->rop.handle);
217 PUSH_NVSQ(push, NV043, 0x0300, 0x55);219 PUSH_NVSQ(push, NV043, 0x0300, 0x55);
drivers/gpu/drm/omapdrm/omap_fbdev.c+0−2
@@ -177,8 +177,6 @@ static int omap_fbdev_create(struct drm_fb_helper *helper, · 176 unmodified lines
177 177
178 drm_fb_helper_fill_info(fbi, helper, sizes);178 drm_fb_helper_fill_info(fbi, helper, sizes);
179 179
180 dev->mode_config.fb_base = dma_addr;
181
182 fbi->screen_buffer = omap_gem_vaddr(fbdev->bo);180 fbi->screen_buffer = omap_gem_vaddr(fbdev->bo);
183 fbi->screen_size = fbdev->bo->size;181 fbi->screen_size = fbdev->bo->size;
184 fbi->fix.smem_start = dma_addr;182 fbi->fix.smem_start = dma_addr;
drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c+2−2
@@ -125,7 +125,7 @@ struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev, · 124 unmodified lines
125 125
126 get_dma_buf(dma_buf);126 get_dma_buf(dma_buf);
127 127
128 sgt = dma_buf_map_attachment(attach, DMA_TO_DEVICE);128 sgt = dma_buf_map_attachment_unlocked(attach, DMA_TO_DEVICE);
129 if (IS_ERR(sgt)) {129 if (IS_ERR(sgt)) {
130 ret = PTR_ERR(sgt);130 ret = PTR_ERR(sgt);
131 goto fail_detach;131 goto fail_detach;
@@ -142,7 +142,7 @@ struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev, · 10 unmodified lines
142 return obj;142 return obj;
143 143
144fail_unmap:144fail_unmap:
145 dma_buf_unmap_attachment(attach, sgt, DMA_TO_DEVICE);145 dma_buf_unmap_attachment_unlocked(attach, sgt, DMA_TO_DEVICE);
146fail_detach:146fail_detach:
147 dma_buf_detach(dma_buf, attach);147 dma_buf_detach(dma_buf, attach);
148 dma_buf_put(dma_buf);148 dma_buf_put(dma_buf);
drivers/gpu/drm/panel/panel-samsung-db7430.c+7−0
@@ -331,9 +331,16 @@ static const struct of_device_id db7430_match[] = { · 330 unmodified lines
331};331};
332MODULE_DEVICE_TABLE(of, db7430_match);332MODULE_DEVICE_TABLE(of, db7430_match);
333 333
334static const struct spi_device_id db7430_ids[] = {
335 { "lms397kf04" },
336 { },
337};
338MODULE_DEVICE_TABLE(spi, db7430_ids);
339
334static struct spi_driver db7430_driver = {340static struct spi_driver db7430_driver = {
335 .probe = db7430_probe,341 .probe = db7430_probe,
336 .remove = db7430_remove,342 .remove = db7430_remove,
343 .id_table = db7430_ids,
337 .driver = {344 .driver = {
338 .name = "db7430-panel",345 .name = "db7430-panel",
339 .of_match_table = db7430_match,346 .of_match_table = db7430_match,
drivers/gpu/drm/panel/panel-tpo-tpg110.c+7−0
@@ -463,9 +463,16 @@ static const struct of_device_id tpg110_match[] = { · 462 unmodified lines
463};463};
464MODULE_DEVICE_TABLE(of, tpg110_match);464MODULE_DEVICE_TABLE(of, tpg110_match);
465 465
466static const struct spi_device_id tpg110_ids[] = {
467 { "tpg110" },
468 { },
469};
470MODULE_DEVICE_TABLE(spi, tpg110_ids);
471
466static struct spi_driver tpg110_driver = {472static struct spi_driver tpg110_driver = {
467 .probe = tpg110_probe,473 .probe = tpg110_probe,
468 .remove = tpg110_remove,474 .remove = tpg110_remove,
475 .id_table = tpg110_ids,
469 .driver = {476 .driver = {
470 .name = "tpo-tpg110-panel",477 .name = "tpo-tpg110-panel",
471 .of_match_table = tpg110_match,478 .of_match_table = tpg110_match,
drivers/gpu/drm/panel/panel-widechips-ws2401.c+7−0
@@ -425,9 +425,16 @@ static const struct of_device_id ws2401_match[] = { · 424 unmodified lines
425};425};
426MODULE_DEVICE_TABLE(of, ws2401_match);426MODULE_DEVICE_TABLE(of, ws2401_match);
427 427
428static const struct spi_device_id ws2401_ids[] = {
429 { "lms380kf01" },
430 { },
431};
432MODULE_DEVICE_TABLE(spi, ws2401_ids);
433
428static struct spi_driver ws2401_driver = {434static struct spi_driver ws2401_driver = {
429 .probe = ws2401_probe,435 .probe = ws2401_probe,
430 .remove = ws2401_remove,436 .remove = ws2401_remove,
437 .id_table = ws2401_ids,
431 .driver = {438 .driver = {
432 .name = "ws2401-panel",439 .name = "ws2401-panel",
433 .of_match_table = ws2401_match,440 .of_match_table = ws2401_match,
drivers/gpu/drm/panfrost/panfrost_dump.c+2−2
@@ -209,7 +209,7 @@ void panfrost_core_dump(struct panfrost_job *job) · 208 unmodified lines
209 goto dump_header;209 goto dump_header;
210 }210 }
211 211
212 ret = drm_gem_shmem_vmap(&bo->base, &map);212 ret = drm_gem_vmap_unlocked(&bo->base.base, &map);
213 if (ret) {213 if (ret) {
214 dev_err(pfdev->dev, "Panfrost Dump: couldn't map Buffer Object\n");214 dev_err(pfdev->dev, "Panfrost Dump: couldn't map Buffer Object\n");
215 iter.hdr->bomap.valid = 0;215 iter.hdr->bomap.valid = 0;
@@ -236,7 +236,7 @@ void panfrost_core_dump(struct panfrost_job *job) · 20 unmodified lines
236 vaddr = map.vaddr;236 vaddr = map.vaddr;
237 memcpy(iter.data, vaddr, bo->base.base.size);237 memcpy(iter.data, vaddr, bo->base.base.size);
238 238
239 drm_gem_shmem_vunmap(&bo->base, &map);239 drm_gem_vunmap_unlocked(&bo->base.base, &map);
240 240
241 iter.hdr->bomap.valid = 1;241 iter.hdr->bomap.valid = 1;
242 242
drivers/gpu/drm/panfrost/panfrost_perfcnt.c+3−3
@@ -106,7 +106,7 @@ static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev, · 105 unmodified lines
106 goto err_close_bo;106 goto err_close_bo;
107 }107 }
108 108
109 ret = drm_gem_shmem_vmap(bo, &map);109 ret = drm_gem_vmap_unlocked(&bo->base, &map);
110 if (ret)110 if (ret)
111 goto err_put_mapping;111 goto err_put_mapping;
112 perfcnt->buf = map.vaddr;112 perfcnt->buf = map.vaddr;
@@ -165,7 +165,7 @@ static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev, · 52 unmodified lines
165 return 0;165 return 0;
166 166
167err_vunmap:167err_vunmap:
168 drm_gem_shmem_vunmap(bo, &map);168 drm_gem_vunmap_unlocked(&bo->base, &map);
169err_put_mapping:169err_put_mapping:
170 panfrost_gem_mapping_put(perfcnt->mapping);170 panfrost_gem_mapping_put(perfcnt->mapping);
171err_close_bo:171err_close_bo:
@@ -195,7 +195,7 @@ static int panfrost_perfcnt_disable_locked(struct panfrost_device *pfdev, · 23 unmodified lines
195 GPU_PERFCNT_CFG_MODE(GPU_PERFCNT_CFG_MODE_OFF));195 GPU_PERFCNT_CFG_MODE(GPU_PERFCNT_CFG_MODE_OFF));
196 196
197 perfcnt->user = NULL;197 perfcnt->user = NULL;
198 drm_gem_shmem_vunmap(&perfcnt->mapping->obj->base, &map);198 drm_gem_vunmap_unlocked(&perfcnt->mapping->obj->base.base, &map);
199 perfcnt->buf = NULL;199 perfcnt->buf = NULL;
200 panfrost_gem_close(&perfcnt->mapping->obj->base.base, file_priv);200 panfrost_gem_close(&perfcnt->mapping->obj->base.base, file_priv);
201 panfrost_mmu_as_put(pfdev, perfcnt->mapping->mmu);201 panfrost_mmu_as_put(pfdev, perfcnt->mapping->mmu);
drivers/gpu/drm/qxl/qxl_display.c+0−2
@@ -1261,8 +1261,6 @@ int qxl_modeset_init(struct qxl_device *qdev) · 1260 unmodified lines
1261 qdev->ddev.mode_config.max_width = 8192;1261 qdev->ddev.mode_config.max_width = 8192;
1262 qdev->ddev.mode_config.max_height = 8192;1262 qdev->ddev.mode_config.max_height = 8192;
1263 1263
1264 qdev->ddev.mode_config.fb_base = qdev->vram_base;
1265
1266 drm_mode_create_suggested_offset_properties(&qdev->ddev);1264 drm_mode_create_suggested_offset_properties(&qdev->ddev);
1267 qxl_mode_create_hotplug_mode_update_property(qdev);1265 qxl_mode_create_hotplug_mode_update_property(qdev);
1268 1266
drivers/gpu/drm/qxl/qxl_object.c+9−8
@@ -168,9 +168,16 @@ int qxl_bo_vmap_locked(struct qxl_bo *bo, struct iosys_map *map) · 167 unmodified lines
168 bo->map_count++;168 bo->map_count++;
169 goto out;169 goto out;
170 }170 }
171 r = ttm_bo_vmap(&bo->tbo, &bo->map);171
172 r = __qxl_bo_pin(bo);
172 if (r)173 if (r)
173 return r;174 return r;
175
176 r = ttm_bo_vmap(&bo->tbo, &bo->map);
177 if (r) {
178 __qxl_bo_unpin(bo);
179 return r;
180 }
174 bo->map_count = 1;181 bo->map_count = 1;
175 182
176 /* TODO: Remove kptr in favor of map everywhere. */183 /* TODO: Remove kptr in favor of map everywhere. */
@@ -192,12 +199,6 @@ int qxl_bo_vmap(struct qxl_bo *bo, struct iosys_map *map) · 15 unmodified lines
192 if (r)199 if (r)
193 return r;200 return r;
194 201
195 r = __qxl_bo_pin(bo);
196 if (r) {
197 qxl_bo_unreserve(bo);
198 return r;
199 }
200
201 r = qxl_bo_vmap_locked(bo, map);202 r = qxl_bo_vmap_locked(bo, map);
202 qxl_bo_unreserve(bo);203 qxl_bo_unreserve(bo);
203 return r;204 return r;
@@ -247,6 +248,7 @@ void qxl_bo_vunmap_locked(struct qxl_bo *bo) · 43 unmodified lines
247 return;248 return;
248 bo->kptr = NULL;249 bo->kptr = NULL;
249 ttm_bo_vunmap(&bo->tbo, &bo->map);250 ttm_bo_vunmap(&bo->tbo, &bo->map);
251 __qxl_bo_unpin(bo);
250}252}
251 253
252int qxl_bo_vunmap(struct qxl_bo *bo)254int qxl_bo_vunmap(struct qxl_bo *bo)
@@ -258,7 +260,6 @@ int qxl_bo_vunmap(struct qxl_bo *bo) · 5 unmodified lines
258 return r;260 return r;
259 261
260 qxl_bo_vunmap_locked(bo);262 qxl_bo_vunmap_locked(bo);
261 __qxl_bo_unpin(bo);
262 qxl_bo_unreserve(bo);263 qxl_bo_unreserve(bo);
263 return 0;264 return 0;
264}265}
drivers/gpu/drm/qxl/qxl_prime.c+2−2
@@ -59,7 +59,7 @@ int qxl_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map) · 58 unmodified lines
59 struct qxl_bo *bo = gem_to_qxl_bo(obj);59 struct qxl_bo *bo = gem_to_qxl_bo(obj);
60 int ret;60 int ret;
61 61
62 ret = qxl_bo_vmap(bo, map);62 ret = qxl_bo_vmap_locked(bo, map);
63 if (ret < 0)63 if (ret < 0)
64 return ret;64 return ret;
65 65
@@ -71,5 +71,5 @@ void qxl_gem_prime_vunmap(struct drm_gem_object *obj, · 5 unmodified lines
71{71{
72 struct qxl_bo *bo = gem_to_qxl_bo(obj);72 struct qxl_bo *bo = gem_to_qxl_bo(obj);
73 73
74 qxl_bo_vunmap(bo);74 qxl_bo_vunmap_locked(bo);
75}75}
drivers/gpu/drm/radeon/radeon_display.c+0−2
@@ -1604,8 +1604,6 @@ int radeon_modeset_init(struct radeon_device *rdev) · 1603 unmodified lines
1604 1604
1605 rdev->ddev->mode_config.fb_modifiers_not_supported = true;1605 rdev->ddev->mode_config.fb_modifiers_not_supported = true;
1606 1606
1607 rdev->ddev->mode_config.fb_base = rdev->mc.aper_base;
1608
1609 ret = radeon_modeset_create_props(rdev);1607 ret = radeon_modeset_create_props(rdev);
1610 if (ret) {1608 if (ret) {
1611 return ret;1609 return ret;
drivers/gpu/drm/radeon/radeon_fb.c+1−1
@@ -276,7 +276,7 @@ static int radeonfb_create(struct drm_fb_helper *helper, · 275 unmodified lines
276 drm_fb_helper_fill_info(info, &rfbdev->helper, sizes);276 drm_fb_helper_fill_info(info, &rfbdev->helper, sizes);
277 277
278 /* setup aperture base/size for vesafb takeover */278 /* setup aperture base/size for vesafb takeover */
279 info->apertures->ranges[0].base = rdev->ddev->mode_config.fb_base;279 info->apertures->ranges[0].base = rdev->mc.aper_base;
280 info->apertures->ranges[0].size = rdev->mc.aper_size;280 info->apertures->ranges[0].size = rdev->mc.aper_size;
281 281
282 /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */282 /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
drivers/gpu/drm/scheduler/sched_entity.c+25−1
@@ -73,6 +73,7 @@ int drm_sched_entity_init(struct drm_sched_entity *entity, · 72 unmodified lines
73 entity->priority = priority;73 entity->priority = priority;
74 entity->sched_list = num_sched_list > 1 ? sched_list : NULL;74 entity->sched_list = num_sched_list > 1 ? sched_list : NULL;
75 entity->last_scheduled = NULL;75 entity->last_scheduled = NULL;
76 RB_CLEAR_NODE(&entity->rb_tree_node);
76 77
77 if(num_sched_list)78 if(num_sched_list)
78 entity->rq = &sched_list[0]->sched_rq[entity->priority];79 entity->rq = &sched_list[0]->sched_rq[entity->priority];
@@ -207,6 +208,7 @@ static void drm_sched_entity_kill_jobs_cb(struct dma_fence *f, · 128 unmodified lines
207 struct drm_sched_job *job = container_of(cb, struct drm_sched_job,208 struct drm_sched_job *job = container_of(cb, struct drm_sched_job,
208 finish_cb);209 finish_cb);
209 210
211 dma_fence_put(f);
210 INIT_WORK(&job->work, drm_sched_entity_kill_jobs_work);212 INIT_WORK(&job->work, drm_sched_entity_kill_jobs_work);
211 schedule_work(&job->work);213 schedule_work(&job->work);
212}214}
@@ -234,8 +236,10 @@ static void drm_sched_entity_kill_jobs(struct drm_sched_entity *entity) · 21 unmodified lines
234 struct drm_sched_fence *s_fence = job->s_fence;236 struct drm_sched_fence *s_fence = job->s_fence;
235 237
236 /* Wait for all dependencies to avoid data corruptions */238 /* Wait for all dependencies to avoid data corruptions */
237 while ((f = drm_sched_job_dependency(job, entity)))239 while ((f = drm_sched_job_dependency(job, entity))) {
238 dma_fence_wait(f, false);240 dma_fence_wait(f, false);
241 dma_fence_put(f);
242 }
239 243
240 drm_sched_fence_scheduled(s_fence);244 drm_sched_fence_scheduled(s_fence);
241 dma_fence_set_error(&s_fence->finished, -ESRCH);245 dma_fence_set_error(&s_fence->finished, -ESRCH);
@@ -250,6 +254,7 @@ static void drm_sched_entity_kill_jobs(struct drm_sched_entity *entity) · 8 unmodified lines
250 continue;254 continue;
251 }255 }
252 256
257 dma_fence_get(entity->last_scheduled);
253 r = dma_fence_add_callback(entity->last_scheduled,258 r = dma_fence_add_callback(entity->last_scheduled,
254 &job->finish_cb,259 &job->finish_cb,
255 drm_sched_entity_kill_jobs_cb);260 drm_sched_entity_kill_jobs_cb);
@@ -444,6 +449,19 @@ struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity) · 188 unmodified lines
444 smp_wmb();449 smp_wmb();
445 450
446 spsc_queue_pop(&entity->job_queue);451 spsc_queue_pop(&entity->job_queue);
452
453 /*
454 * Update the entity's location in the min heap according to
455 * the timestamp of the next job, if any.
456 */
457 if (drm_sched_policy == DRM_SCHED_POLICY_FIFO) {
458 struct drm_sched_job *next;
459
460 next = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));
461 if (next)
462 drm_sched_rq_update_fifo(entity, next->submit_ts);
463 }
464
447 return sched_job;465 return sched_job;
448}466}
449 467
@@ -508,6 +526,7 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job) · 58 unmodified lines
508 atomic_inc(entity->rq->sched->score);526 atomic_inc(entity->rq->sched->score);
509 WRITE_ONCE(entity->last_user, current->group_leader);527 WRITE_ONCE(entity->last_user, current->group_leader);
510 first = spsc_queue_push(&entity->job_queue, &sched_job->queue_node);528 first = spsc_queue_push(&entity->job_queue, &sched_job->queue_node);
529 sched_job->submit_ts = ktime_get();
511 530
512 /* first job wakes up scheduler */531 /* first job wakes up scheduler */
513 if (first) {532 if (first) {
@@ -519,8 +538,13 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job) · 5 unmodified lines
519 DRM_ERROR("Trying to push to a killed entity\n");538 DRM_ERROR("Trying to push to a killed entity\n");
520 return;539 return;
521 }540 }
541
522 drm_sched_rq_add_entity(entity->rq, entity);542 drm_sched_rq_add_entity(entity->rq, entity);
523 spin_unlock(&entity->rq_lock);543 spin_unlock(&entity->rq_lock);
544
545 if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
546 drm_sched_rq_update_fifo(entity, sched_job->submit_ts);
547
524 drm_sched_wakeup(entity->rq->sched);548 drm_sched_wakeup(entity->rq->sched);
525 }549 }
526}550}
drivers/gpu/drm/scheduler/sched_main.c+93−3
@@ -62,6 +62,55 @@ · 61 unmodified lines
62#define to_drm_sched_job(sched_job) \62#define to_drm_sched_job(sched_job) \
63 container_of((sched_job), struct drm_sched_job, queue_node)63 container_of((sched_job), struct drm_sched_job, queue_node)
64 64
65int drm_sched_policy = DRM_SCHED_POLICY_RR;
66
67/**
68 * DOC: sched_policy (int)
69 * Used to override default entities scheduling policy in a run queue.
70 */
71MODULE_PARM_DESC(sched_policy, "Specify schedule policy for entities on a runqueue, " __stringify(DRM_SCHED_POLICY_RR) " = Round Robin (default), " __stringify(DRM_SCHED_POLICY_FIFO) " = use FIFO.");
72module_param_named(sched_policy, drm_sched_policy, int, 0444);
73
74static __always_inline bool drm_sched_entity_compare_before(struct rb_node *a,
75 const struct rb_node *b)
76{
77 struct drm_sched_entity *ent_a = rb_entry((a), struct drm_sched_entity, rb_tree_node);
78 struct drm_sched_entity *ent_b = rb_entry((b), struct drm_sched_entity, rb_tree_node);
79
80 return ktime_before(ent_a->oldest_job_waiting, ent_b->oldest_job_waiting);
81}
82
83static inline void drm_sched_rq_remove_fifo_locked(struct drm_sched_entity *entity)
84{
85 struct drm_sched_rq *rq = entity->rq;
86
87 if (!RB_EMPTY_NODE(&entity->rb_tree_node)) {
88 rb_erase_cached(&entity->rb_tree_node, &rq->rb_tree_root);
89 RB_CLEAR_NODE(&entity->rb_tree_node);
90 }
91}
92
93void drm_sched_rq_update_fifo(struct drm_sched_entity *entity, ktime_t ts)
94{
95 /*
96 * Both locks need to be grabbed, one to protect from entity->rq change
97 * for entity from within concurrent drm_sched_entity_select_rq and the
98 * other to update the rb tree structure.
99 */
100 spin_lock(&entity->rq_lock);
101 spin_lock(&entity->rq->lock);
102
103 drm_sched_rq_remove_fifo_locked(entity);
104
105 entity->oldest_job_waiting = ts;
106
107 rb_add_cached(&entity->rb_tree_node, &entity->rq->rb_tree_root,
108 drm_sched_entity_compare_before);
109
110 spin_unlock(&entity->rq->lock);
111 spin_unlock(&entity->rq_lock);
112}
113
65/**114/**
66 * drm_sched_rq_init - initialize a given run queue struct115 * drm_sched_rq_init - initialize a given run queue struct
67 *116 *
@@ -75,6 +124,7 @@ static void drm_sched_rq_init(struct drm_gpu_scheduler *sched, · 7 unmodified lines
75{124{
76 spin_lock_init(&rq->lock);125 spin_lock_init(&rq->lock);
77 INIT_LIST_HEAD(&rq->entities);126 INIT_LIST_HEAD(&rq->entities);
127 rq->rb_tree_root = RB_ROOT_CACHED;
78 rq->current_entity = NULL;128 rq->current_entity = NULL;
79 rq->sched = sched;129 rq->sched = sched;
80}130}
@@ -92,9 +142,12 @@ void drm_sched_rq_add_entity(struct drm_sched_rq *rq, · 11 unmodified lines
92{142{
93 if (!list_empty(&entity->list))143 if (!list_empty(&entity->list))
94 return;144 return;
145
95 spin_lock(&rq->lock);146 spin_lock(&rq->lock);
147
96 atomic_inc(rq->sched->score);148 atomic_inc(rq->sched->score);
97 list_add_tail(&entity->list, &rq->entities);149 list_add_tail(&entity->list, &rq->entities);
150
98 spin_unlock(&rq->lock);151 spin_unlock(&rq->lock);
99}152}
100 153
@@ -111,23 +164,30 @@ void drm_sched_rq_remove_entity(struct drm_sched_rq *rq, · 10 unmodified lines
111{164{
112 if (list_empty(&entity->list))165 if (list_empty(&entity->list))
113 return;166 return;
167
114 spin_lock(&rq->lock);168 spin_lock(&rq->lock);
169
115 atomic_dec(rq->sched->score);170 atomic_dec(rq->sched->score);
116 list_del_init(&entity->list);171 list_del_init(&entity->list);
172
117 if (rq->current_entity == entity)173 if (rq->current_entity == entity)
118 rq->current_entity = NULL;174 rq->current_entity = NULL;
175
176 if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
177 drm_sched_rq_remove_fifo_locked(entity);
178
119 spin_unlock(&rq->lock);179 spin_unlock(&rq->lock);
120}180}
121 181
122/**182/**
123 * drm_sched_rq_select_entity - Select an entity which could provide a job to run183 * drm_sched_rq_select_entity_rr - Select an entity which could provide a job to run
124 *184 *
125 * @rq: scheduler run queue to check.185 * @rq: scheduler run queue to check.
126 *186 *
127 * Try to find a ready entity, returns NULL if none found.187 * Try to find a ready entity, returns NULL if none found.
128 */188 */
129static struct drm_sched_entity *189static struct drm_sched_entity *
130drm_sched_rq_select_entity(struct drm_sched_rq *rq)190drm_sched_rq_select_entity_rr(struct drm_sched_rq *rq)
131{191{
132 struct drm_sched_entity *entity;192 struct drm_sched_entity *entity;
133 193
@@ -163,6 +223,34 @@ drm_sched_rq_select_entity(struct drm_sched_rq *rq) · 29 unmodified lines
163 return NULL;223 return NULL;
164}224}
165 225
226/**
227 * drm_sched_rq_select_entity_fifo - Select an entity which provides a job to run
228 *
229 * @rq: scheduler run queue to check.
230 *
231 * Find oldest waiting ready entity, returns NULL if none found.
232 */
233static struct drm_sched_entity *
234drm_sched_rq_select_entity_fifo(struct drm_sched_rq *rq)
235{
236 struct rb_node *rb;
237
238 spin_lock(&rq->lock);
239 for (rb = rb_first_cached(&rq->rb_tree_root); rb; rb = rb_next(rb)) {
240 struct drm_sched_entity *entity;
241
242 entity = rb_entry(rb, struct drm_sched_entity, rb_tree_node);
243 if (drm_sched_entity_is_ready(entity)) {
244 rq->current_entity = entity;
245 reinit_completion(&entity->entity_idle);
246 break;
247 }
248 }
249 spin_unlock(&rq->lock);
250
251 return rb ? rb_entry(rb, struct drm_sched_entity, rb_tree_node) : NULL;
252}
253
166/**254/**
167 * drm_sched_job_done - complete a job255 * drm_sched_job_done - complete a job
168 * @s_job: pointer to the job which is done256 * @s_job: pointer to the job which is done
@@ -803,7 +891,9 @@ drm_sched_select_entity(struct drm_gpu_scheduler *sched) · 634 unmodified lines
803 891
804 /* Kernel run queue has higher priority than normal run queue*/892 /* Kernel run queue has higher priority than normal run queue*/
805 for (i = DRM_SCHED_PRIORITY_COUNT - 1; i >= DRM_SCHED_PRIORITY_MIN; i--) {893 for (i = DRM_SCHED_PRIORITY_COUNT - 1; i >= DRM_SCHED_PRIORITY_MIN; i--) {
806 entity = drm_sched_rq_select_entity(&sched->sched_rq[i]);894 entity = drm_sched_policy == DRM_SCHED_POLICY_FIFO ?
895 drm_sched_rq_select_entity_fifo(&sched->sched_rq[i]) :
896 drm_sched_rq_select_entity_rr(&sched->sched_rq[i]);
807 if (entity)897 if (entity)
808 break;898 break;
809 }899 }
drivers/gpu/drm/solomon/ssd130x.c+13−22
@@ -20,6 +20,7 @@ · 19 unmodified lines
20 20
21#include <drm/drm_atomic.h>21#include <drm/drm_atomic.h>
22#include <drm/drm_atomic_helper.h>22#include <drm/drm_atomic_helper.h>
23#include <drm/drm_crtc_helper.h>
23#include <drm/drm_damage_helper.h>24#include <drm/drm_damage_helper.h>
24#include <drm/drm_edid.h>25#include <drm/drm_edid.h>
25#include <drm/drm_fb_helper.h>26#include <drm/drm_fb_helper.h>
@@ -578,21 +579,24 @@ static void ssd130x_primary_plane_helper_atomic_update(struct drm_plane *plane, · 552 unmodified lines
578 struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);579 struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
579 struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);580 struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
580 struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);581 struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
582 struct drm_atomic_helper_damage_iter iter;
581 struct drm_device *drm = plane->dev;583 struct drm_device *drm = plane->dev;
582 struct drm_rect src_clip, dst_clip;584 struct drm_rect dst_clip;
585 struct drm_rect damage;
583 int idx;586 int idx;
584 587
585 if (!drm_atomic_helper_damage_merged(old_plane_state, plane_state, &src_clip))588 if (!drm_dev_enter(drm, &idx))
586 return;589 return;
587 590
588 dst_clip = plane_state->dst;591 drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
589 if (!drm_rect_intersect(&dst_clip, &src_clip))592 drm_atomic_for_each_plane_damage(&iter, &damage) {
590 return;593 dst_clip = plane_state->dst;
591 594
592 if (!drm_dev_enter(drm, &idx))595 if (!drm_rect_intersect(&dst_clip, &damage))
593 return;596 continue;
594 597
595 ssd130x_fb_blit_rect(plane_state->fb, &shadow_plane_state->data[0], &dst_clip);598 ssd130x_fb_blit_rect(plane_state->fb, &shadow_plane_state->data[0], &dst_clip);
599 }
596 600
597 drm_dev_exit(idx);601 drm_dev_exit(idx);
598}602}
@@ -642,19 +646,6 @@ static enum drm_mode_status ssd130x_crtc_helper_mode_valid(struct drm_crtc *crtc · 43 unmodified lines
642 return MODE_OK;646 return MODE_OK;
643}647}
644 648
645static int ssd130x_crtc_helper_atomic_check(struct drm_crtc *crtc,
646 struct drm_atomic_state *new_state)
647{
648 struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc);
649 int ret;
650
651 ret = drm_atomic_helper_check_crtc_state(new_crtc_state, false);
652 if (ret)
653 return ret;
654
655 return drm_atomic_add_affected_planes(new_state, crtc);
656}
657
658/*649/*
659 * The CRTC is always enabled. Screen updates are performed by650 * The CRTC is always enabled. Screen updates are performed by
660 * the primary plane's atomic_update function. Disabling clears651 * the primary plane's atomic_update function. Disabling clears
@@ -662,7 +653,7 @@ static int ssd130x_crtc_helper_atomic_check(struct drm_crtc *crtc, · 1 unmodified line
662 */653 */
663static const struct drm_crtc_helper_funcs ssd130x_crtc_helper_funcs = {654static const struct drm_crtc_helper_funcs ssd130x_crtc_helper_funcs = {
664 .mode_valid = ssd130x_crtc_helper_mode_valid,655 .mode_valid = ssd130x_crtc_helper_mode_valid,
665 .atomic_check = ssd130x_crtc_helper_atomic_check,656 .atomic_check = drm_crtc_helper_atomic_check,
666};657};
667 658
668static void ssd130x_crtc_reset(struct drm_crtc *crtc)659static void ssd130x_crtc_reset(struct drm_crtc *crtc)
drivers/gpu/drm/tegra/fb.c+0−1
@@ -280,7 +280,6 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper, · 279 unmodified lines
280 }280 }
281 }281 }
282 282
283 drm->mode_config.fb_base = (resource_size_t)bo->iova;
284 info->screen_base = (void __iomem *)bo->vaddr + offset;283 info->screen_base = (void __iomem *)bo->vaddr + offset;
285 info->screen_size = size;284 info->screen_size = size;
286 info->fix.smem_start = (unsigned long)(bo->iova + offset);285 info->fix.smem_start = (unsigned long)(bo->iova + offset);
drivers/gpu/drm/tegra/gem.c+9−8
@@ -84,7 +84,7 @@ static struct host1x_bo_mapping *tegra_bo_pin(struct device *dev, struct host1x_ · 83 unmodified lines
84 goto free;84 goto free;
85 }85 }
86 86
87 map->sgt = dma_buf_map_attachment(map->attach, direction);87 map->sgt = dma_buf_map_attachment_unlocked(map->attach, direction);
88 if (IS_ERR(map->sgt)) {88 if (IS_ERR(map->sgt)) {
89 dma_buf_detach(buf, map->attach);89 dma_buf_detach(buf, map->attach);
90 err = PTR_ERR(map->sgt);90 err = PTR_ERR(map->sgt);
@@ -160,7 +160,8 @@ free: · 69 unmodified lines
160static void tegra_bo_unpin(struct host1x_bo_mapping *map)160static void tegra_bo_unpin(struct host1x_bo_mapping *map)
161{161{
162 if (map->attach) {162 if (map->attach) {
163 dma_buf_unmap_attachment(map->attach, map->sgt, map->direction);163 dma_buf_unmap_attachment_unlocked(map->attach, map->sgt,
164 map->direction);
164 dma_buf_detach(map->attach->dmabuf, map->attach);165 dma_buf_detach(map->attach->dmabuf, map->attach);
165 } else {166 } else {
166 dma_unmap_sgtable(map->dev, map->sgt, map->direction, 0);167 dma_unmap_sgtable(map->dev, map->sgt, map->direction, 0);
@@ -181,7 +182,7 @@ static void *tegra_bo_mmap(struct host1x_bo *bo) · 14 unmodified lines
181 if (obj->vaddr) {182 if (obj->vaddr) {
182 return obj->vaddr;183 return obj->vaddr;
183 } else if (obj->gem.import_attach) {184 } else if (obj->gem.import_attach) {
184 ret = dma_buf_vmap(obj->gem.import_attach->dmabuf, &map);185 ret = dma_buf_vmap_unlocked(obj->gem.import_attach->dmabuf, &map);
185 return ret ? NULL : map.vaddr;186 return ret ? NULL : map.vaddr;
186 } else {187 } else {
187 return vmap(obj->pages, obj->num_pages, VM_MAP,188 return vmap(obj->pages, obj->num_pages, VM_MAP,
@@ -197,7 +198,7 @@ static void tegra_bo_munmap(struct host1x_bo *bo, void *addr) · 9 unmodified lines
197 if (obj->vaddr)198 if (obj->vaddr)
198 return;199 return;
199 else if (obj->gem.import_attach)200 else if (obj->gem.import_attach)
200 dma_buf_vunmap(obj->gem.import_attach->dmabuf, &map);201 dma_buf_vunmap_unlocked(obj->gem.import_attach->dmabuf, &map);
201 else202 else
202 vunmap(addr);203 vunmap(addr);
203}204}
@@ -461,7 +462,7 @@ static struct tegra_bo *tegra_bo_import(struct drm_device *drm, · 257 unmodified lines
461 462
462 get_dma_buf(buf);463 get_dma_buf(buf);
463 464
464 bo->sgt = dma_buf_map_attachment(attach, DMA_TO_DEVICE);465 bo->sgt = dma_buf_map_attachment_unlocked(attach, DMA_TO_DEVICE);
465 if (IS_ERR(bo->sgt)) {466 if (IS_ERR(bo->sgt)) {
466 err = PTR_ERR(bo->sgt);467 err = PTR_ERR(bo->sgt);
467 goto detach;468 goto detach;
@@ -479,7 +480,7 @@ static struct tegra_bo *tegra_bo_import(struct drm_device *drm, · 11 unmodified lines
479 480
480detach:481detach:
481 if (!IS_ERR_OR_NULL(bo->sgt))482 if (!IS_ERR_OR_NULL(bo->sgt))
482 dma_buf_unmap_attachment(attach, bo->sgt, DMA_TO_DEVICE);483 dma_buf_unmap_attachment_unlocked(attach, bo->sgt, DMA_TO_DEVICE);
483 484
484 dma_buf_detach(buf, attach);485 dma_buf_detach(buf, attach);
485 dma_buf_put(buf);486 dma_buf_put(buf);
@@ -508,8 +509,8 @@ void tegra_bo_free_object(struct drm_gem_object *gem) · 22 unmodified lines
508 tegra_bo_iommu_unmap(tegra, bo);509 tegra_bo_iommu_unmap(tegra, bo);
509 510
510 if (gem->import_attach) {511 if (gem->import_attach) {
511 dma_buf_unmap_attachment(gem->import_attach, bo->sgt,512 dma_buf_unmap_attachment_unlocked(gem->import_attach, bo->sgt,
512 DMA_TO_DEVICE);513 DMA_TO_DEVICE);
513 drm_prime_gem_destroy(gem, NULL);514 drm_prime_gem_destroy(gem, NULL);
514 } else {515 } else {
515 tegra_bo_free(gem->dev, bo);516 tegra_bo_free(gem->dev, bo);
drivers/gpu/drm/tests/Makefile+11−3
@@ -1,5 +1,13 @@
1# SPDX-License-Identifier: GPL-2.01# SPDX-License-Identifier: GPL-2.0
2 2
3obj-$(CONFIG_DRM_KUNIT_TEST) += drm_format_helper_test.o drm_damage_helper_test.o \3obj-$(CONFIG_DRM_KUNIT_TEST) += \
4 drm_cmdline_parser_test.o drm_rect_test.o drm_format_test.o drm_plane_helper_test.o \4 drm_buddy_test.o \
5 drm_dp_mst_helper_test.o drm_framebuffer_test.o drm_buddy_test.o drm_mm_test.o5 drm_cmdline_parser_test.o \
6 drm_damage_helper_test.o \
7 drm_dp_mst_helper_test.o \
8 drm_format_helper_test.o \
9 drm_format_test.o \
10 drm_framebuffer_test.o \
11 drm_mm_test.o \
12 drm_plane_helper_test.o \
13 drm_rect_test.o
drivers/gpu/drm/tests/drm_dp_mst_helper_test.c+295−150
@@ -5,44 +5,280 @@ · 4 unmodified lines
5 * Copyright (c) 2022 Maíra Canal <mairacanal@riseup.net>5 * Copyright (c) 2022 Maíra Canal <mairacanal@riseup.net>
6 */6 */
7 7
8#define PREFIX_STR "[drm_dp_mst_helper]"
9
10#include <kunit/test.h>8#include <kunit/test.h>
11 9
12#include <linux/random.h>
13
14#include <drm/display/drm_dp_mst_helper.h>10#include <drm/display/drm_dp_mst_helper.h>
15#include <drm/drm_print.h>11#include <drm/drm_print.h>
16 12
17#include "../display/drm_dp_mst_topology_internal.h"13#include "../display/drm_dp_mst_topology_internal.h"
18 14
15struct drm_dp_mst_calc_pbn_mode_test {
16 const int clock;
17 const int bpp;
18 const bool dsc;
19 const int expected;
20};
21
22static const struct drm_dp_mst_calc_pbn_mode_test drm_dp_mst_calc_pbn_mode_cases[] = {
23 {
24 .clock = 154000,
25 .bpp = 30,
26 .dsc = false,
27 .expected = 689
28 },
29 {
30 .clock = 234000,
31 .bpp = 30,
32 .dsc = false,
33 .expected = 1047
34 },
35 {
36 .clock = 297000,
37 .bpp = 24,
38 .dsc = false,
39 .expected = 1063
40 },
41 {
42 .clock = 332880,
43 .bpp = 24,
44 .dsc = true,
45 .expected = 50
46 },
47 {
48 .clock = 324540,
49 .bpp = 24,
50 .dsc = true,
51 .expected = 49
52 },
53};
54
19static void drm_test_dp_mst_calc_pbn_mode(struct kunit *test)55static void drm_test_dp_mst_calc_pbn_mode(struct kunit *test)
20{56{
21 int pbn, i;57 const struct drm_dp_mst_calc_pbn_mode_test *params = test->param_value;
22 const struct {
23 int rate;
24 int bpp;
25 int expected;
26 bool dsc;
27 } test_params[] = {
28 { 154000, 30, 689, false },
29 { 234000, 30, 1047, false },
30 { 297000, 24, 1063, false },
31 { 332880, 24, 50, true },
32 { 324540, 24, 49, true },
33 };
34 58
35 for (i = 0; i < ARRAY_SIZE(test_params); i++) {59 KUNIT_EXPECT_EQ(test, drm_dp_calc_pbn_mode(params->clock, params->bpp, params->dsc),
36 pbn = drm_dp_calc_pbn_mode(test_params[i].rate,60 params->expected);
37 test_params[i].bpp,
38 test_params[i].dsc);
39 KUNIT_EXPECT_EQ_MSG(test, pbn, test_params[i].expected,
40 "Expected PBN %d for clock %d bpp %d, got %d\n",
41 test_params[i].expected, test_params[i].rate,
42 test_params[i].bpp, pbn);
43 }
44}61}
45 62
63static void dp_mst_calc_pbn_mode_desc(const struct drm_dp_mst_calc_pbn_mode_test *t, char *desc)
64{
65 sprintf(desc, "Clock %d BPP %d DSC %s", t->clock, t->bpp, t->dsc ? "enabled" : "disabled");
66}
67
68KUNIT_ARRAY_PARAM(drm_dp_mst_calc_pbn_mode, drm_dp_mst_calc_pbn_mode_cases,
69 dp_mst_calc_pbn_mode_desc);
70
71static u8 data[] = { 0xff, 0x00, 0xdd };
72
73struct drm_dp_mst_sideband_msg_req_test {
74 const char *desc;
75 const struct drm_dp_sideband_msg_req_body in;
76};
77
78static const struct drm_dp_mst_sideband_msg_req_test drm_dp_mst_sideband_msg_req_cases[] = {
79 {
80 .desc = "DP_ENUM_PATH_RESOURCES with port number",
81 .in = {
82 .req_type = DP_ENUM_PATH_RESOURCES,
83 .u.port_num.port_number = 5,
84 },
85 },
86 {
87 .desc = "DP_POWER_UP_PHY with port number",
88 .in = {
89 .req_type = DP_POWER_UP_PHY,
90 .u.port_num.port_number = 5,
91 },
92 },
93 {
94 .desc = "DP_POWER_DOWN_PHY with port number",
95 .in = {
96 .req_type = DP_POWER_DOWN_PHY,
97 .u.port_num.port_number = 5,
98 },
99 },
100 {
101 .desc = "DP_ALLOCATE_PAYLOAD with SDP stream sinks",
102 .in = {
103 .req_type = DP_ALLOCATE_PAYLOAD,
104 .u.allocate_payload.number_sdp_streams = 3,
105 .u.allocate_payload.sdp_stream_sink = { 1, 2, 3 },
106 },
107 },
108 {
109 .desc = "DP_ALLOCATE_PAYLOAD with port number",
110 .in = {
111 .req_type = DP_ALLOCATE_PAYLOAD,
112 .u.allocate_payload.port_number = 0xf,
113 },
114 },
115 {
116 .desc = "DP_ALLOCATE_PAYLOAD with VCPI",
117 .in = {
118 .req_type = DP_ALLOCATE_PAYLOAD,
119 .u.allocate_payload.vcpi = 0x7f,
120 },
121 },
122 {
123 .desc = "DP_ALLOCATE_PAYLOAD with PBN",
124 .in = {
125 .req_type = DP_ALLOCATE_PAYLOAD,
126 .u.allocate_payload.pbn = U16_MAX,
127 },
128 },
129 {
130 .desc = "DP_QUERY_PAYLOAD with port number",
131 .in = {
132 .req_type = DP_QUERY_PAYLOAD,
133 .u.query_payload.port_number = 0xf,
134 },
135 },
136 {
137 .desc = "DP_QUERY_PAYLOAD with VCPI",
138 .in = {
139 .req_type = DP_QUERY_PAYLOAD,
140 .u.query_payload.vcpi = 0x7f,
141 },
142 },
143 {
144 .desc = "DP_REMOTE_DPCD_READ with port number",
145 .in = {
146 .req_type = DP_REMOTE_DPCD_READ,
147 .u.dpcd_read.port_number = 0xf,
148 },
149 },
150 {
151 .desc = "DP_REMOTE_DPCD_READ with DPCD address",
152 .in = {
153 .req_type = DP_REMOTE_DPCD_READ,
154 .u.dpcd_read.dpcd_address = 0xfedcb,
155 },
156 },
157 {
158 .desc = "DP_REMOTE_DPCD_READ with max number of bytes",
159 .in = {
160 .req_type = DP_REMOTE_DPCD_READ,
161 .u.dpcd_read.num_bytes = U8_MAX,
162 },
163 },
164 {
165 .desc = "DP_REMOTE_DPCD_WRITE with port number",
166 .in = {
167 .req_type = DP_REMOTE_DPCD_WRITE,
168 .u.dpcd_write.port_number = 0xf,
169 },
170 },
171 {
172 .desc = "DP_REMOTE_DPCD_WRITE with DPCD address",
173 .in = {
174 .req_type = DP_REMOTE_DPCD_WRITE,
175 .u.dpcd_write.dpcd_address = 0xfedcb,
176 },
177 },
178 {
179 .desc = "DP_REMOTE_DPCD_WRITE with data array",
180 .in = {
181 .req_type = DP_REMOTE_DPCD_WRITE,
182 .u.dpcd_write.num_bytes = ARRAY_SIZE(data),
183 .u.dpcd_write.bytes = data,
184 },
185 },
186 {
187 .desc = "DP_REMOTE_I2C_READ with port number",
188 .in = {
189 .req_type = DP_REMOTE_I2C_READ,
190 .u.i2c_read.port_number = 0xf,
191 },
192 },
193 {
194 .desc = "DP_REMOTE_I2C_READ with I2C device ID",
195 .in = {
196 .req_type = DP_REMOTE_I2C_READ,
197 .u.i2c_read.read_i2c_device_id = 0x7f,
198 },
199 },
200 {
201 .desc = "DP_REMOTE_I2C_READ with transactions array",
202 .in = {
203 .req_type = DP_REMOTE_I2C_READ,
204 .u.i2c_read.num_transactions = 3,
205 .u.i2c_read.num_bytes_read = ARRAY_SIZE(data) * 3,
206 .u.i2c_read.transactions = {
207 { .bytes = data, .num_bytes = ARRAY_SIZE(data), .i2c_dev_id = 0x7f,
208 .i2c_transaction_delay = 0xf, },
209 { .bytes = data, .num_bytes = ARRAY_SIZE(data), .i2c_dev_id = 0x7e,
210 .i2c_transaction_delay = 0xe, },
211 { .bytes = data, .num_bytes = ARRAY_SIZE(data), .i2c_dev_id = 0x7d,
212 .i2c_transaction_delay = 0xd, },
213 },
214 },
215 },
216 {
217 .desc = "DP_REMOTE_I2C_WRITE with port number",
218 .in = {
219 .req_type = DP_REMOTE_I2C_WRITE,
220 .u.i2c_write.port_number = 0xf,
221 },
222 },
223 {
224 .desc = "DP_REMOTE_I2C_WRITE with I2C device ID",
225 .in = {
226 .req_type = DP_REMOTE_I2C_WRITE,
227 .u.i2c_write.write_i2c_device_id = 0x7f,
228 },
229 },
230 {
231 .desc = "DP_REMOTE_I2C_WRITE with data array",
232 .in = {
233 .req_type = DP_REMOTE_I2C_WRITE,
234 .u.i2c_write.num_bytes = ARRAY_SIZE(data),
235 .u.i2c_write.bytes = data,
236 },
237 },
238 {
239 .desc = "DP_QUERY_STREAM_ENC_STATUS with stream ID",
240 .in = {
241 .req_type = DP_QUERY_STREAM_ENC_STATUS,
242 .u.enc_status.stream_id = 1,
243 },
244 },
245 {
246 .desc = "DP_QUERY_STREAM_ENC_STATUS with client ID",
247 .in = {
248 .req_type = DP_QUERY_STREAM_ENC_STATUS,
249 .u.enc_status.client_id = { 0x4f, 0x7f, 0xb4, 0x00, 0x8c, 0x0d, 0x67 },
250 },
251 },
252 {
253 .desc = "DP_QUERY_STREAM_ENC_STATUS with stream event",
254 .in = {
255 .req_type = DP_QUERY_STREAM_ENC_STATUS,
256 .u.enc_status.stream_event = 3,
257 },
258 },
259 {
260 .desc = "DP_QUERY_STREAM_ENC_STATUS with valid stream event",
261 .in = {
262 .req_type = DP_QUERY_STREAM_ENC_STATUS,
263 .u.enc_status.valid_stream_event = 0,
264 },
265 },
266 {
267 .desc = "DP_QUERY_STREAM_ENC_STATUS with stream behavior",
268 .in = {
269 .req_type = DP_QUERY_STREAM_ENC_STATUS,
270 .u.enc_status.stream_behavior = 3,
271 },
272 },
273 {
274 .desc = "DP_QUERY_STREAM_ENC_STATUS with a valid stream behavior",
275 .in = {
276 .req_type = DP_QUERY_STREAM_ENC_STATUS,
277 .u.enc_status.valid_stream_behavior = 1,
278 }
279 },
280};
281
46static bool282static bool
47sideband_msg_req_equal(const struct drm_dp_sideband_msg_req_body *in,283sideband_msg_req_equal(const struct drm_dp_sideband_msg_req_body *in,
48 const struct drm_dp_sideband_msg_req_body *out)284 const struct drm_dp_sideband_msg_req_body *out)
@@ -118,41 +354,41 @@ sideband_msg_req_equal(const struct drm_dp_sideband_msg_req_body *in, · 69 unmodified lines
118 return true;354 return true;
119}355}
120 356
121static bool357static void drm_test_dp_mst_msg_printf(struct drm_printer *p, struct va_format *vaf)
122sideband_msg_req_encode_decode(struct drm_dp_sideband_msg_req_body *in)
123{358{
359 struct kunit *test = p->arg;
360
361 kunit_err(test, "%pV", vaf);
362}
363
364static void drm_test_dp_mst_sideband_msg_req_decode(struct kunit *test)
365{
366 const struct drm_dp_mst_sideband_msg_req_test *params = test->param_value;
367 const struct drm_dp_sideband_msg_req_body *in = &params->in;
124 struct drm_dp_sideband_msg_req_body *out;368 struct drm_dp_sideband_msg_req_body *out;
125 struct drm_printer p = drm_err_printer(PREFIX_STR);
126 struct drm_dp_sideband_msg_tx *txmsg;369 struct drm_dp_sideband_msg_tx *txmsg;
127 int i, ret;370 struct drm_printer p = {
128 bool result = true;371 .printfn = drm_test_dp_mst_msg_printf,
372 .arg = test
373 };
374 int i;
129 375
130 out = kzalloc(sizeof(*out), GFP_KERNEL);376 out = kunit_kzalloc(test, sizeof(*out), GFP_KERNEL);
131 if (!out)377 KUNIT_ASSERT_NOT_NULL(test, out);
132 return false;
133 378
134 txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);379 txmsg = kunit_kzalloc(test, sizeof(*txmsg), GFP_KERNEL);
135 if (!txmsg) {380 KUNIT_ASSERT_NOT_NULL(test, txmsg);
136 kfree(out);
137 return false;
138 }
139 381
140 drm_dp_encode_sideband_req(in, txmsg);382 drm_dp_encode_sideband_req(in, txmsg);
141 ret = drm_dp_decode_sideband_req(txmsg, out);383 KUNIT_EXPECT_GE_MSG(test, drm_dp_decode_sideband_req(txmsg, out), 0,
142 if (ret < 0) {384 "Failed to decode sideband request");
143 drm_printf(&p, "Failed to decode sideband request: %d\n",
144 ret);
145 result = false;
146 goto out;
147 }
148 385
149 if (!sideband_msg_req_equal(in, out)) {386 if (!sideband_msg_req_equal(in, out)) {
150 drm_printf(&p, "Encode/decode failed, expected:\n");387 KUNIT_FAIL(test, "Encode/decode failed");
388 kunit_err(test, "Expected:");
151 drm_dp_dump_sideband_msg_req_body(in, 1, &p);389 drm_dp_dump_sideband_msg_req_body(in, 1, &p);
152 drm_printf(&p, "Got:\n");390 kunit_err(test, "Got:");
153 drm_dp_dump_sideband_msg_req_body(out, 1, &p);391 drm_dp_dump_sideband_msg_req_body(out, 1, &p);
154 result = false;
155 goto out;
156 }392 }
157 393
158 switch (in->req_type) {394 switch (in->req_type) {
@@ -167,112 +403,21 @@ sideband_msg_req_encode_decode(struct drm_dp_sideband_msg_req_body *in) · 8 unmodified lines
167 kfree(out->u.i2c_write.bytes);403 kfree(out->u.i2c_write.bytes);
168 break;404 break;
169 }405 }
170
171 /* Clear everything but the req_type for the input */
172 memset(&in->u, 0, sizeof(in->u));
173
174out:
175 kfree(out);
176 kfree(txmsg);
177 return result;
178}406}
179 407
180static void drm_test_dp_mst_sideband_msg_req_decode(struct kunit *test)408static void
409drm_dp_mst_sideband_msg_req_desc(const struct drm_dp_mst_sideband_msg_req_test *t, char *desc)
181{410{
182 struct drm_dp_sideband_msg_req_body in = { 0 };411 strcpy(desc, t->desc);
183 u8 data[] = { 0xff, 0x0, 0xdd };
184 int i;
185
186 in.req_type = DP_ENUM_PATH_RESOURCES;
187 in.u.port_num.port_number = 5;
188 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
189
190 in.req_type = DP_POWER_UP_PHY;
191 in.u.port_num.port_number = 5;
192 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
193
194 in.req_type = DP_POWER_DOWN_PHY;
195 in.u.port_num.port_number = 5;
196 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
197
198 in.req_type = DP_ALLOCATE_PAYLOAD;
199 in.u.allocate_payload.number_sdp_streams = 3;
200 for (i = 0; i < in.u.allocate_payload.number_sdp_streams; i++)
201 in.u.allocate_payload.sdp_stream_sink[i] = i + 1;
202 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
203 in.u.allocate_payload.port_number = 0xf;
204 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
205 in.u.allocate_payload.vcpi = 0x7f;
206 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
207 in.u.allocate_payload.pbn = U16_MAX;
208 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
209
210 in.req_type = DP_QUERY_PAYLOAD;
211 in.u.query_payload.port_number = 0xf;
212 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
213 in.u.query_payload.vcpi = 0x7f;
214 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
215
216 in.req_type = DP_REMOTE_DPCD_READ;
217 in.u.dpcd_read.port_number = 0xf;
218 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
219 in.u.dpcd_read.dpcd_address = 0xfedcb;
220 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
221 in.u.dpcd_read.num_bytes = U8_MAX;
222 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
223
224 in.req_type = DP_REMOTE_DPCD_WRITE;
225 in.u.dpcd_write.port_number = 0xf;
226 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
227 in.u.dpcd_write.dpcd_address = 0xfedcb;
228 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
229 in.u.dpcd_write.num_bytes = ARRAY_SIZE(data);
230 in.u.dpcd_write.bytes = data;
231 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
232
233 in.req_type = DP_REMOTE_I2C_READ;
234 in.u.i2c_read.port_number = 0xf;
235 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
236 in.u.i2c_read.read_i2c_device_id = 0x7f;
237 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
238 in.u.i2c_read.num_transactions = 3;
239 in.u.i2c_read.num_bytes_read = ARRAY_SIZE(data) * 3;
240 for (i = 0; i < in.u.i2c_read.num_transactions; i++) {
241 in.u.i2c_read.transactions[i].bytes = data;
242 in.u.i2c_read.transactions[i].num_bytes = ARRAY_SIZE(data);
243 in.u.i2c_read.transactions[i].i2c_dev_id = 0x7f & ~i;
244 in.u.i2c_read.transactions[i].i2c_transaction_delay = 0xf & ~i;
245 }
246 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
247
248 in.req_type = DP_REMOTE_I2C_WRITE;
249 in.u.i2c_write.port_number = 0xf;
250 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
251 in.u.i2c_write.write_i2c_device_id = 0x7f;
252 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
253 in.u.i2c_write.num_bytes = ARRAY_SIZE(data);
254 in.u.i2c_write.bytes = data;
255 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
256
257 in.req_type = DP_QUERY_STREAM_ENC_STATUS;
258 in.u.enc_status.stream_id = 1;
259 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
260 get_random_bytes(in.u.enc_status.client_id,
261 sizeof(in.u.enc_status.client_id));
262 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
263 in.u.enc_status.stream_event = 3;
264 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
265 in.u.enc_status.valid_stream_event = 0;
266 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
267 in.u.enc_status.stream_behavior = 3;
268 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
269 in.u.enc_status.valid_stream_behavior = 1;
270 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
271}412}
272 413
414KUNIT_ARRAY_PARAM(drm_dp_mst_sideband_msg_req, drm_dp_mst_sideband_msg_req_cases,
415 drm_dp_mst_sideband_msg_req_desc);
416
273static struct kunit_case drm_dp_mst_helper_tests[] = {417static struct kunit_case drm_dp_mst_helper_tests[] = {
274 KUNIT_CASE(drm_test_dp_mst_calc_pbn_mode),418 KUNIT_CASE_PARAM(drm_test_dp_mst_calc_pbn_mode, drm_dp_mst_calc_pbn_mode_gen_params),
275 KUNIT_CASE(drm_test_dp_mst_sideband_msg_req_decode),419 KUNIT_CASE_PARAM(drm_test_dp_mst_sideband_msg_req_decode,
420 drm_dp_mst_sideband_msg_req_gen_params),
276 { }421 { }
277};422};
278 423
drivers/gpu/drm/tiny/Kconfig+13−0
@@ -51,6 +51,19 @@ config DRM_GM12U320 · 50 unmodified lines
51 This is a KMS driver for projectors which use the GM12U320 chipset51 This is a KMS driver for projectors which use the GM12U320 chipset
52 for video transfer over USB2/3, such as the Acer C120 mini projector.52 for video transfer over USB2/3, such as the Acer C120 mini projector.
53 53
54config DRM_OFDRM
55 tristate "Open Firmware display driver"
56 depends on DRM && OF && (PPC || COMPILE_TEST)
57 select APERTURE_HELPERS
58 select DRM_GEM_SHMEM_HELPER
59 select DRM_KMS_HELPER
60 help
61 DRM driver for Open Firmware framebuffers.
62
63 This driver assumes that the display hardware has been initialized
64 by the Open Firmware before the kernel boots. Scanout buffer, size,
65 and display format must be provided via device tree.
66
54config DRM_PANEL_MIPI_DBI67config DRM_PANEL_MIPI_DBI
55 tristate "DRM support for MIPI DBI compatible panels"68 tristate "DRM support for MIPI DBI compatible panels"
56 depends on DRM && SPI69 depends on DRM && SPI
drivers/gpu/drm/tiny/Makefile+1−0
@@ -4,6 +4,7 @@ obj-$(CONFIG_DRM_ARCPGU) += arcpgu.o · 3 unmodified lines
4obj-$(CONFIG_DRM_BOCHS) += bochs.o4obj-$(CONFIG_DRM_BOCHS) += bochs.o
5obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus.o5obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus.o
6obj-$(CONFIG_DRM_GM12U320) += gm12u320.o6obj-$(CONFIG_DRM_GM12U320) += gm12u320.o
7obj-$(CONFIG_DRM_OFDRM) += ofdrm.o
7obj-$(CONFIG_DRM_PANEL_MIPI_DBI) += panel-mipi-dbi.o8obj-$(CONFIG_DRM_PANEL_MIPI_DBI) += panel-mipi-dbi.o
8obj-$(CONFIG_DRM_SIMPLEDRM) += simpledrm.o9obj-$(CONFIG_DRM_SIMPLEDRM) += simpledrm.o
9obj-$(CONFIG_TINYDRM_HX8357D) += hx8357d.o10obj-$(CONFIG_TINYDRM_HX8357D) += hx8357d.o
drivers/gpu/drm/tiny/bochs.c+0−1
@@ -543,7 +543,6 @@ static int bochs_kms_init(struct bochs_device *bochs) · 542 unmodified lines
543 bochs->dev->mode_config.max_width = 8192;543 bochs->dev->mode_config.max_width = 8192;
544 bochs->dev->mode_config.max_height = 8192;544 bochs->dev->mode_config.max_height = 8192;
545 545
546 bochs->dev->mode_config.fb_base = bochs->fb_base;
547 bochs->dev->mode_config.preferred_depth = 24;546 bochs->dev->mode_config.preferred_depth = 24;
548 bochs->dev->mode_config.prefer_shadow = 0;547 bochs->dev->mode_config.prefer_shadow = 0;
549 bochs->dev->mode_config.prefer_shadow_fbdev = 1;548 bochs->dev->mode_config.prefer_shadow_fbdev = 1;
drivers/gpu/drm/tiny/ofdrm.c+1424−0
@@ -0,0 +1,1424 @@
1// SPDX-License-Identifier: GPL-2.0-only
2
3#include <linux/of_address.h>
4#include <linux/pci.h>
5#include <linux/platform_device.h>
6
7#include <drm/drm_aperture.h>
8#include <drm/drm_atomic.h>
9#include <drm/drm_atomic_state_helper.h>
10#include <drm/drm_connector.h>
11#include <drm/drm_damage_helper.h>
12#include <drm/drm_device.h>
13#include <drm/drm_drv.h>
14#include <drm/drm_fb_helper.h>
15#include <drm/drm_format_helper.h>
16#include <drm/drm_framebuffer.h>
17#include <drm/drm_gem_atomic_helper.h>
18#include <drm/drm_gem_framebuffer_helper.h>
19#include <drm/drm_gem_shmem_helper.h>
20#include <drm/drm_managed.h>
21#include <drm/drm_modeset_helper_vtables.h>
22#include <drm/drm_plane_helper.h>
23#include <drm/drm_probe_helper.h>
24#include <drm/drm_simple_kms_helper.h>
25
26#define DRIVER_NAME "ofdrm"
27#define DRIVER_DESC "DRM driver for OF platform devices"
28#define DRIVER_DATE "20220501"
29#define DRIVER_MAJOR 1
30#define DRIVER_MINOR 0
31
32#define PCI_VENDOR_ID_ATI_R520 0x7100
33#define PCI_VENDOR_ID_ATI_R600 0x9400
34
35#define OFDRM_GAMMA_LUT_SIZE 256
36
37/* Definitions used by the Avivo palette */
38#define AVIVO_DC_LUT_RW_SELECT 0x6480
39#define AVIVO_DC_LUT_RW_MODE 0x6484
40#define AVIVO_DC_LUT_RW_INDEX 0x6488
41#define AVIVO_DC_LUT_SEQ_COLOR 0x648c
42#define AVIVO_DC_LUT_PWL_DATA 0x6490
43#define AVIVO_DC_LUT_30_COLOR 0x6494
44#define AVIVO_DC_LUT_READ_PIPE_SELECT 0x6498
45#define AVIVO_DC_LUT_WRITE_EN_MASK 0x649c
46#define AVIVO_DC_LUT_AUTOFILL 0x64a0
47#define AVIVO_DC_LUTA_CONTROL 0x64c0
48#define AVIVO_DC_LUTA_BLACK_OFFSET_BLUE 0x64c4
49#define AVIVO_DC_LUTA_BLACK_OFFSET_GREEN 0x64c8
50#define AVIVO_DC_LUTA_BLACK_OFFSET_RED 0x64cc
51#define AVIVO_DC_LUTA_WHITE_OFFSET_BLUE 0x64d0
52#define AVIVO_DC_LUTA_WHITE_OFFSET_GREEN 0x64d4
53#define AVIVO_DC_LUTA_WHITE_OFFSET_RED 0x64d8
54#define AVIVO_DC_LUTB_CONTROL 0x6cc0
55#define AVIVO_DC_LUTB_BLACK_OFFSET_BLUE 0x6cc4
56#define AVIVO_DC_LUTB_BLACK_OFFSET_GREEN 0x6cc8
57#define AVIVO_DC_LUTB_BLACK_OFFSET_RED 0x6ccc
58#define AVIVO_DC_LUTB_WHITE_OFFSET_BLUE 0x6cd0
59#define AVIVO_DC_LUTB_WHITE_OFFSET_GREEN 0x6cd4
60#define AVIVO_DC_LUTB_WHITE_OFFSET_RED 0x6cd8
61
62enum ofdrm_model {
63 OFDRM_MODEL_UNKNOWN,
64 OFDRM_MODEL_MACH64, /* ATI Mach64 */
65 OFDRM_MODEL_RAGE128, /* ATI Rage128 */
66 OFDRM_MODEL_RAGE_M3A, /* ATI Rage Mobility M3 Head A */
67 OFDRM_MODEL_RAGE_M3B, /* ATI Rage Mobility M3 Head B */
68 OFDRM_MODEL_RADEON, /* ATI Radeon */
69 OFDRM_MODEL_GXT2000, /* IBM GXT2000 */
70 OFDRM_MODEL_AVIVO, /* ATI R5xx */
71 OFDRM_MODEL_QEMU, /* QEMU VGA */
72};
73
74/*
75 * Helpers for display nodes
76 */
77
78static int display_get_validated_int(struct drm_device *dev, const char *name, uint32_t value)
79{
80 if (value > INT_MAX) {
81 drm_err(dev, "invalid framebuffer %s of %u\n", name, value);
82 return -EINVAL;
83 }
84 return (int)value;
85}
86
87static int display_get_validated_int0(struct drm_device *dev, const char *name, uint32_t value)
88{
89 if (!value) {
90 drm_err(dev, "invalid framebuffer %s of %u\n", name, value);
91 return -EINVAL;
92 }
93 return display_get_validated_int(dev, name, value);
94}
95
96static const struct drm_format_info *display_get_validated_format(struct drm_device *dev,
97 u32 depth, bool big_endian)
98{
99 const struct drm_format_info *info;
100 u32 format;
101
102 switch (depth) {
103 case 8:
104 format = drm_mode_legacy_fb_format(8, 8);
105 break;
106 case 15:
107 case 16:
108 format = drm_mode_legacy_fb_format(16, depth);
109 break;
110 case 32:
111 format = drm_mode_legacy_fb_format(32, 24);
112 break;
113 default:
114 drm_err(dev, "unsupported framebuffer depth %u\n", depth);
115 return ERR_PTR(-EINVAL);
116 }
117
118 /*
119 * DRM formats assume little-endian byte order. Update the format
120 * if the scanout buffer uses big-endian ordering.
121 */
122 if (big_endian) {
123 switch (format) {
124 case DRM_FORMAT_XRGB8888:
125 format = DRM_FORMAT_BGRX8888;
126 break;
127 case DRM_FORMAT_ARGB8888:
128 format = DRM_FORMAT_BGRA8888;
129 break;
130 case DRM_FORMAT_RGB565:
131 format = DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN;
132 break;
133 case DRM_FORMAT_XRGB1555:
134 format = DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN;
135 break;
136 default:
137 break;
138 }
139 }
140
141 info = drm_format_info(format);
142 if (!info) {
143 drm_err(dev, "cannot find framebuffer format for depth %u\n", depth);
144 return ERR_PTR(-EINVAL);
145 }
146
147 return info;
148}
149
150static int display_read_u32_of(struct drm_device *dev, struct device_node *of_node,
151 const char *name, u32 *value)
152{
153 int ret = of_property_read_u32(of_node, name, value);
154
155 if (ret)
156 drm_err(dev, "cannot parse framebuffer %s: error %d\n", name, ret);
157 return ret;
158}
159
160static bool display_get_big_endian_of(struct drm_device *dev, struct device_node *of_node)
161{
162 bool big_endian;
163
164#ifdef __BIG_ENDIAN
165 big_endian = true;
166 if (of_get_property(of_node, "little-endian", NULL))
167 big_endian = false;
168#else
169 big_endian = false;
170 if (of_get_property(of_node, "big-endian", NULL))
171 big_endian = true;
172#endif
173
174 return big_endian;
175}
176
177static int display_get_width_of(struct drm_device *dev, struct device_node *of_node)
178{
179 u32 width;
180 int ret = display_read_u32_of(dev, of_node, "width", &width);
181
182 if (ret)
183 return ret;
184 return display_get_validated_int0(dev, "width", width);
185}
186
187static int display_get_height_of(struct drm_device *dev, struct device_node *of_node)
188{
189 u32 height;
190 int ret = display_read_u32_of(dev, of_node, "height", &height);
191
192 if (ret)
193 return ret;
194 return display_get_validated_int0(dev, "height", height);
195}
196
197static int display_get_depth_of(struct drm_device *dev, struct device_node *of_node)
198{
199 u32 depth;
200 int ret = display_read_u32_of(dev, of_node, "depth", &depth);
201
202 if (ret)
203 return ret;
204 return display_get_validated_int0(dev, "depth", depth);
205}
206
207static int display_get_linebytes_of(struct drm_device *dev, struct device_node *of_node)
208{
209 u32 linebytes;
210 int ret = display_read_u32_of(dev, of_node, "linebytes", &linebytes);
211
212 if (ret)
213 return ret;
214 return display_get_validated_int(dev, "linebytes", linebytes);
215}
216
217static u64 display_get_address_of(struct drm_device *dev, struct device_node *of_node)
218{
219 u32 address;
220 int ret;
221
222 /*
223 * Not all devices provide an address property, it's not
224 * a bug if this fails. The driver will try to find the
225 * framebuffer base address from the device's memory regions.
226 */
227 ret = of_property_read_u32(of_node, "address", &address);
228 if (ret)
229 return OF_BAD_ADDR;
230
231 return address;
232}
233
234static bool is_avivo(__be32 vendor, __be32 device)
235{
236 /* This will match most R5xx */
237 return (vendor == PCI_VENDOR_ID_ATI) &&
238 ((device >= PCI_VENDOR_ID_ATI_R520 && device < 0x7800) ||
239 (PCI_VENDOR_ID_ATI_R600 >= 0x9400));
240}
241
242static enum ofdrm_model display_get_model_of(struct drm_device *dev, struct device_node *of_node)
243{
244 enum ofdrm_model model = OFDRM_MODEL_UNKNOWN;
245
246 if (of_node_name_prefix(of_node, "ATY,Rage128")) {
247 model = OFDRM_MODEL_RAGE128;
248 } else if (of_node_name_prefix(of_node, "ATY,RageM3pA") ||
249 of_node_name_prefix(of_node, "ATY,RageM3p12A")) {
250 model = OFDRM_MODEL_RAGE_M3A;
251 } else if (of_node_name_prefix(of_node, "ATY,RageM3pB")) {
252 model = OFDRM_MODEL_RAGE_M3B;
253 } else if (of_node_name_prefix(of_node, "ATY,Rage6")) {
254 model = OFDRM_MODEL_RADEON;
255 } else if (of_node_name_prefix(of_node, "ATY,")) {
256 return OFDRM_MODEL_MACH64;
257 } else if (of_device_is_compatible(of_node, "pci1014,b7") ||
258 of_device_is_compatible(of_node, "pci1014,21c")) {
259 model = OFDRM_MODEL_GXT2000;
260 } else if (of_node_name_prefix(of_node, "vga,Display-")) {
261 struct device_node *of_parent;
262 const __be32 *vendor_p, *device_p;
263
264 /* Look for AVIVO initialized by SLOF */
265 of_parent = of_get_parent(of_node);
266 vendor_p = of_get_property(of_parent, "vendor-id", NULL);
267 device_p = of_get_property(of_parent, "device-id", NULL);
268 if (vendor_p && device_p && is_avivo(*vendor_p, *device_p))
269 model = OFDRM_MODEL_AVIVO;
270 of_node_put(of_parent);
271 } else if (of_device_is_compatible(of_node, "qemu,std-vga")) {
272 model = OFDRM_MODEL_QEMU;
273 }
274
275 return model;
276}
277
278/*
279 * Open Firmware display device
280 */
281
282struct ofdrm_device;
283
284struct ofdrm_device_funcs {
285 void __iomem *(*cmap_ioremap)(struct ofdrm_device *odev,
286 struct device_node *of_node,
287 u64 fb_bas);
288 void (*cmap_write)(struct ofdrm_device *odev, unsigned char index,
289 unsigned char r, unsigned char g, unsigned char b);
290};
291
292struct ofdrm_device {
293 struct drm_device dev;
294 struct platform_device *pdev;
295
296 const struct ofdrm_device_funcs *funcs;
297
298 /* firmware-buffer settings */
299 struct iosys_map screen_base;
300 struct drm_display_mode mode;
301 const struct drm_format_info *format;
302 unsigned int pitch;
303
304 /* colormap */
305 void __iomem *cmap_base;
306
307 /* modesetting */
308 uint32_t formats[8];
309 struct drm_plane primary_plane;
310 struct drm_crtc crtc;
311 struct drm_encoder encoder;
312 struct drm_connector connector;
313};
314
315static struct ofdrm_device *ofdrm_device_of_dev(struct drm_device *dev)
316{
317 return container_of(dev, struct ofdrm_device, dev);
318}
319
320/*
321 * Hardware
322 */
323
324#if defined(CONFIG_PCI)
325static struct pci_dev *display_get_pci_dev_of(struct drm_device *dev, struct device_node *of_node)
326{
327 const __be32 *vendor_p, *device_p;
328 u32 vendor, device;
329 struct pci_dev *pcidev;
330
331 vendor_p = of_get_property(of_node, "vendor-id", NULL);
332 if (!vendor_p)
333 return ERR_PTR(-ENODEV);
334 vendor = be32_to_cpup(vendor_p);
335
336 device_p = of_get_property(of_node, "device-id", NULL);
337 if (!device_p)
338 return ERR_PTR(-ENODEV);
339 device = be32_to_cpup(device_p);
340
341 pcidev = pci_get_device(vendor, device, NULL);
342 if (!pcidev)
343 return ERR_PTR(-ENODEV);
344
345 return pcidev;
346}
347
348static void ofdrm_pci_release(void *data)
349{
350 struct pci_dev *pcidev = data;
351
352 pci_disable_device(pcidev);
353}
354
355static int ofdrm_device_init_pci(struct ofdrm_device *odev)
356{
357 struct drm_device *dev = &odev->dev;
358 struct platform_device *pdev = to_platform_device(dev->dev);
359 struct device_node *of_node = pdev->dev.of_node;
360 struct pci_dev *pcidev;
361 int ret;
362
363 /*
364 * Never use pcim_ or other managed helpers on the returned PCI
365 * device. Otherwise, probing the native driver will fail for
366 * resource conflicts. PCI-device management has to be tied to
367 * the lifetime of the platform device until the native driver
368 * takes over.
369 */
370 pcidev = display_get_pci_dev_of(dev, of_node);
371 if (IS_ERR(pcidev))
372 return 0; /* no PCI device found; ignore the error */
373
374 ret = pci_enable_device(pcidev);
375 if (ret) {
376 drm_err(dev, "pci_enable_device(%s) failed: %d\n",
377 dev_name(&pcidev->dev), ret);
378 return ret;
379 }
380 ret = devm_add_action_or_reset(&pdev->dev, ofdrm_pci_release, pcidev);
381 if (ret)
382 return ret;
383
384 return 0;
385}
386#else
387static int ofdrm_device_init_pci(struct ofdrm_device *odev)
388{
389 return 0;
390}
391#endif
392
393/*
394 * OF display settings
395 */
396
397static struct resource *ofdrm_find_fb_resource(struct ofdrm_device *odev,
398 struct resource *fb_res)
399{
400 struct platform_device *pdev = to_platform_device(odev->dev.dev);
401 struct resource *res, *max_res = NULL;
402 u32 i;
403
404 for (i = 0; pdev->num_resources; ++i) {
405 res = platform_get_resource(pdev, IORESOURCE_MEM, i);
406 if (!res)
407 break; /* all resources processed */
408 if (resource_size(res) < resource_size(fb_res))
409 continue; /* resource too small */
410 if (fb_res->start && resource_contains(res, fb_res))
411 return res; /* resource contains framebuffer */
412 if (!max_res || resource_size(res) > resource_size(max_res))
413 max_res = res; /* store largest resource as fallback */
414 }
415
416 return max_res;
417}
418
419/*
420 * Colormap / Palette
421 */
422
423static void __iomem *get_cmap_address_of(struct ofdrm_device *odev, struct device_node *of_node,
424 int bar_no, unsigned long offset, unsigned long size)
425{
426 struct drm_device *dev = &odev->dev;
427 const __be32 *addr_p;
428 u64 max_size, address;
429 unsigned int flags;
430 void __iomem *mem;
431
432 addr_p = of_get_pci_address(of_node, bar_no, &max_size, &flags);
433 if (!addr_p)
434 addr_p = of_get_address(of_node, bar_no, &max_size, &flags);
435 if (!addr_p)
436 return ERR_PTR(-ENODEV);
437
438 if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
439 return ERR_PTR(-ENODEV);
440
441 if ((offset + size) >= max_size)
442 return ERR_PTR(-ENODEV);
443
444 address = of_translate_address(of_node, addr_p);
445 if (address == OF_BAD_ADDR)
446 return ERR_PTR(-ENODEV);
447
448 mem = devm_ioremap(dev->dev, address + offset, size);
449 if (!mem)
450 return ERR_PTR(-ENOMEM);
451
452 return mem;
453}
454
455static void __iomem *ofdrm_mach64_cmap_ioremap(struct ofdrm_device *odev,
456 struct device_node *of_node,
457 u64 fb_base)
458{
459 struct drm_device *dev = &odev->dev;
460 u64 address;
461 void __iomem *cmap_base;
462
463 address = fb_base & 0xff000000ul;
464 address += 0x7ff000;
465
466 cmap_base = devm_ioremap(dev->dev, address, 0x1000);
467 if (!cmap_base)
468 return ERR_PTR(-ENOMEM);
469
470 return cmap_base;
471}
472
473static void ofdrm_mach64_cmap_write(struct ofdrm_device *odev, unsigned char index,
474 unsigned char r, unsigned char g, unsigned char b)
475{
476 void __iomem *addr = odev->cmap_base + 0xcc0;
477 void __iomem *data = odev->cmap_base + 0xcc0 + 1;
478
479 writeb(index, addr);
480 writeb(r, data);
481 writeb(g, data);
482 writeb(b, data);
483}
484
485static void __iomem *ofdrm_rage128_cmap_ioremap(struct ofdrm_device *odev,
486 struct device_node *of_node,
487 u64 fb_base)
488{
489 return get_cmap_address_of(odev, of_node, 2, 0, 0x1fff);
490}
491
492static void ofdrm_rage128_cmap_write(struct ofdrm_device *odev, unsigned char index,
493 unsigned char r, unsigned char g, unsigned char b)
494{
495 void __iomem *addr = odev->cmap_base + 0xb0;
496 void __iomem *data = odev->cmap_base + 0xb4;
497 u32 color = (r << 16) | (g << 8) | b;
498
499 writeb(index, addr);
500 writel(color, data);
501}
502
503static void __iomem *ofdrm_rage_m3a_cmap_ioremap(struct ofdrm_device *odev,
504 struct device_node *of_node,
505 u64 fb_base)
506{
507 return get_cmap_address_of(odev, of_node, 2, 0, 0x1fff);
508}
509
510static void ofdrm_rage_m3a_cmap_write(struct ofdrm_device *odev, unsigned char index,
511 unsigned char r, unsigned char g, unsigned char b)
512{
513 void __iomem *dac_ctl = odev->cmap_base + 0x58;
514 void __iomem *addr = odev->cmap_base + 0xb0;
515 void __iomem *data = odev->cmap_base + 0xb4;
516 u32 color = (r << 16) | (g << 8) | b;
517 u32 val;
518
519 /* Clear PALETTE_ACCESS_CNTL in DAC_CNTL */
520 val = readl(dac_ctl);
521 val &= ~0x20;
522 writel(val, dac_ctl);
523
524 /* Set color at palette index */
525 writeb(index, addr);
526 writel(color, data);
527}
528
529static void __iomem *ofdrm_rage_m3b_cmap_ioremap(struct ofdrm_device *odev,
530 struct device_node *of_node,
531 u64 fb_base)
532{
533 return get_cmap_address_of(odev, of_node, 2, 0, 0x1fff);
534}
535
536static void ofdrm_rage_m3b_cmap_write(struct ofdrm_device *odev, unsigned char index,
537 unsigned char r, unsigned char g, unsigned char b)
538{
539 void __iomem *dac_ctl = odev->cmap_base + 0x58;
540 void __iomem *addr = odev->cmap_base + 0xb0;
541 void __iomem *data = odev->cmap_base + 0xb4;
542 u32 color = (r << 16) | (g << 8) | b;
543 u32 val;
544
545 /* Set PALETTE_ACCESS_CNTL in DAC_CNTL */
546 val = readl(dac_ctl);
547 val |= 0x20;
548 writel(val, dac_ctl);
549
550 /* Set color at palette index */
551 writeb(index, addr);
552 writel(color, data);
553}
554
555static void __iomem *ofdrm_radeon_cmap_ioremap(struct ofdrm_device *odev,
556 struct device_node *of_node,
557 u64 fb_base)
558{
559 return get_cmap_address_of(odev, of_node, 1, 0, 0x1fff);
560}
561
562static void __iomem *ofdrm_gxt2000_cmap_ioremap(struct ofdrm_device *odev,
563 struct device_node *of_node,
564 u64 fb_base)
565{
566 return get_cmap_address_of(odev, of_node, 0, 0x6000, 0x1000);
567}
568
569static void ofdrm_gxt2000_cmap_write(struct ofdrm_device *odev, unsigned char index,
570 unsigned char r, unsigned char g, unsigned char b)
571{
572 void __iomem *data = ((unsigned int __iomem *)odev->cmap_base) + index;
573 u32 color = (r << 16) | (g << 8) | b;
574
575 writel(color, data);
576}
577
578static void __iomem *ofdrm_avivo_cmap_ioremap(struct ofdrm_device *odev,
579 struct device_node *of_node,
580 u64 fb_base)
581{
582 struct device_node *of_parent;
583 void __iomem *cmap_base;
584
585 of_parent = of_get_parent(of_node);
586 cmap_base = get_cmap_address_of(odev, of_parent, 0, 0, 0x10000);
587 of_node_put(of_parent);
588
589 return cmap_base;
590}
591
592static void ofdrm_avivo_cmap_write(struct ofdrm_device *odev, unsigned char index,
593 unsigned char r, unsigned char g, unsigned char b)
594{
595 void __iomem *lutsel = odev->cmap_base + AVIVO_DC_LUT_RW_SELECT;
596 void __iomem *addr = odev->cmap_base + AVIVO_DC_LUT_RW_INDEX;
597 void __iomem *data = odev->cmap_base + AVIVO_DC_LUT_30_COLOR;
598 u32 color = (r << 22) | (g << 12) | (b << 2);
599
600 /* Write to both LUTs for now */
601
602 writel(1, lutsel);
603 writeb(index, addr);
604 writel(color, data);
605
606 writel(0, lutsel);
607 writeb(index, addr);
608 writel(color, data);
609}
610
611static void __iomem *ofdrm_qemu_cmap_ioremap(struct ofdrm_device *odev,
612 struct device_node *of_node,
613 u64 fb_base)
614{
615 static const __be32 io_of_addr[3] = {
616 cpu_to_be32(0x01000000),
617 cpu_to_be32(0x00),
618 cpu_to_be32(0x00),
619 };
620
621 struct drm_device *dev = &odev->dev;
622 u64 address;
623 void __iomem *cmap_base;
624
625 address = of_translate_address(of_node, io_of_addr);
626 if (address == OF_BAD_ADDR)
627 return ERR_PTR(-ENODEV);
628
629 cmap_base = devm_ioremap(dev->dev, address + 0x3c8, 2);
630 if (!cmap_base)
631 return ERR_PTR(-ENOMEM);
632
633 return cmap_base;
634}
635
636static void ofdrm_qemu_cmap_write(struct ofdrm_device *odev, unsigned char index,
637 unsigned char r, unsigned char g, unsigned char b)
638{
639 void __iomem *addr = odev->cmap_base;
640 void __iomem *data = odev->cmap_base + 1;
641
642 writeb(index, addr);
643 writeb(r, data);
644 writeb(g, data);
645 writeb(b, data);
646}
647
648static void ofdrm_device_set_gamma_linear(struct ofdrm_device *odev,
649 const struct drm_format_info *format)
650{
651 struct drm_device *dev = &odev->dev;
652 int i;
653
654 switch (format->format) {
655 case DRM_FORMAT_RGB565:
656 case DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN:
657 /* Use better interpolation, to take 32 values from 0 to 255 */
658 for (i = 0; i < OFDRM_GAMMA_LUT_SIZE / 8; i++) {
659 unsigned char r = i * 8 + i / 4;
660 unsigned char g = i * 4 + i / 16;
661 unsigned char b = i * 8 + i / 4;
662
663 odev->funcs->cmap_write(odev, i, r, g, b);
664 }
665 /* Green has one more bit, so add padding with 0 for red and blue. */
666 for (i = OFDRM_GAMMA_LUT_SIZE / 8; i < OFDRM_GAMMA_LUT_SIZE / 4; i++) {
667 unsigned char r = 0;
668 unsigned char g = i * 4 + i / 16;
669 unsigned char b = 0;
670
671 odev->funcs->cmap_write(odev, i, r, g, b);
672 }
673 break;
674 case DRM_FORMAT_XRGB8888:
675 case DRM_FORMAT_BGRX8888:
676 for (i = 0; i < OFDRM_GAMMA_LUT_SIZE; i++)
677 odev->funcs->cmap_write(odev, i, i, i, i);
678 break;
679 default:
680 drm_warn_once(dev, "Unsupported format %p4cc for gamma correction\n",
681 &format->format);
682 break;
683 }
684}
685
686static void ofdrm_device_set_gamma(struct ofdrm_device *odev,
687 const struct drm_format_info *format,
688 struct drm_color_lut *lut)
689{
690 struct drm_device *dev = &odev->dev;
691 int i;
692
693 switch (format->format) {
694 case DRM_FORMAT_RGB565:
695 case DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN:
696 /* Use better interpolation, to take 32 values from lut[0] to lut[255] */
697 for (i = 0; i < OFDRM_GAMMA_LUT_SIZE / 8; i++) {
698 unsigned char r = lut[i * 8 + i / 4].red >> 8;
699 unsigned char g = lut[i * 4 + i / 16].green >> 8;
700 unsigned char b = lut[i * 8 + i / 4].blue >> 8;
701
702 odev->funcs->cmap_write(odev, i, r, g, b);
703 }
704 /* Green has one more bit, so add padding with 0 for red and blue. */
705 for (i = OFDRM_GAMMA_LUT_SIZE / 8; i < OFDRM_GAMMA_LUT_SIZE / 4; i++) {
706 unsigned char r = 0;
707 unsigned char g = lut[i * 4 + i / 16].green >> 8;
708 unsigned char b = 0;
709
710 odev->funcs->cmap_write(odev, i, r, g, b);
711 }
712 break;
713 case DRM_FORMAT_XRGB8888:
714 case DRM_FORMAT_BGRX8888:
715 for (i = 0; i < OFDRM_GAMMA_LUT_SIZE; i++) {
716 unsigned char r = lut[i].red >> 8;
717 unsigned char g = lut[i].green >> 8;
718 unsigned char b = lut[i].blue >> 8;
719
720 odev->funcs->cmap_write(odev, i, r, g, b);
721 }
722 break;
723 default:
724 drm_warn_once(dev, "Unsupported format %p4cc for gamma correction\n",
725 &format->format);
726 break;
727 }
728}
729
730/*
731 * Modesetting
732 */
733
734struct ofdrm_crtc_state {
735 struct drm_crtc_state base;
736
737 /* Primary-plane format; required for color mgmt. */
738 const struct drm_format_info *format;
739};
740
741static struct ofdrm_crtc_state *to_ofdrm_crtc_state(struct drm_crtc_state *base)
742{
743 return container_of(base, struct ofdrm_crtc_state, base);
744}
745
746static void ofdrm_crtc_state_destroy(struct ofdrm_crtc_state *ofdrm_crtc_state)
747{
748 __drm_atomic_helper_crtc_destroy_state(&ofdrm_crtc_state->base);
749 kfree(ofdrm_crtc_state);
750}
751
752/*
753 * Support all formats of OF display and maybe more; in order
754 * of preference. The display's update function will do any
755 * conversion necessary.
756 *
757 * TODO: Add blit helpers for remaining formats and uncomment
758 * constants.
759 */
760static const uint32_t ofdrm_primary_plane_formats[] = {
761 DRM_FORMAT_XRGB8888,
762 DRM_FORMAT_RGB565,
763 //DRM_FORMAT_XRGB1555,
764 //DRM_FORMAT_C8,
765 /* Big-endian formats below */
766 DRM_FORMAT_BGRX8888,
767 DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN,
768};
769
770static const uint64_t ofdrm_primary_plane_format_modifiers[] = {
771 DRM_FORMAT_MOD_LINEAR,
772 DRM_FORMAT_MOD_INVALID
773};
774
775static int ofdrm_primary_plane_helper_atomic_check(struct drm_plane *plane,
776 struct drm_atomic_state *new_state)
777{
778 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(new_state, plane);
779 struct drm_framebuffer *new_fb = new_plane_state->fb;
780 struct drm_crtc *new_crtc = new_plane_state->crtc;
781 struct drm_crtc_state *new_crtc_state = NULL;
782 struct ofdrm_crtc_state *new_ofdrm_crtc_state;
783 int ret;
784
785 if (new_crtc)
786 new_crtc_state = drm_atomic_get_new_crtc_state(new_state, new_plane_state->crtc);
787
788 ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
789 DRM_PLANE_NO_SCALING,
790 DRM_PLANE_NO_SCALING,
791 false, false);
792 if (ret)
793 return ret;
794 else if (!new_plane_state->visible)
795 return 0;
796
797 new_crtc_state = drm_atomic_get_new_crtc_state(new_state, new_plane_state->crtc);
798
799 new_ofdrm_crtc_state = to_ofdrm_crtc_state(new_crtc_state);
800 new_ofdrm_crtc_state->format = new_fb->format;
801
802 return 0;
803}
804
805static void ofdrm_primary_plane_helper_atomic_update(struct drm_plane *plane,
806 struct drm_atomic_state *state)
807{
808 struct drm_device *dev = plane->dev;
809 struct ofdrm_device *odev = ofdrm_device_of_dev(dev);
810 struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
811 struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
812 struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
813 struct drm_framebuffer *fb = plane_state->fb;
814 unsigned int dst_pitch = odev->pitch;
815 const struct drm_format_info *dst_format = odev->format;
816 struct drm_atomic_helper_damage_iter iter;
817 struct drm_rect damage;
818 int ret, idx;
819
820 ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
821 if (ret)
822 return;
823
824 if (!drm_dev_enter(dev, &idx))
825 goto out_drm_gem_fb_end_cpu_access;
826
827 drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
828 drm_atomic_for_each_plane_damage(&iter, &damage) {
829 struct iosys_map dst = odev->screen_base;
830 struct drm_rect dst_clip = plane_state->dst;
831
832 if (!drm_rect_intersect(&dst_clip, &damage))
833 continue;
834
835 iosys_map_incr(&dst, drm_fb_clip_offset(dst_pitch, dst_format, &dst_clip));
836 drm_fb_blit(&dst, &dst_pitch, dst_format->format, shadow_plane_state->data, fb,
837 &damage);
838 }
839
840 drm_dev_exit(idx);
841out_drm_gem_fb_end_cpu_access:
842 drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
843}
844
845static void ofdrm_primary_plane_helper_atomic_disable(struct drm_plane *plane,
846 struct drm_atomic_state *state)
847{
848 struct drm_device *dev = plane->dev;
849 struct ofdrm_device *odev = ofdrm_device_of_dev(dev);
850 struct iosys_map dst = odev->screen_base;
851 struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
852 void __iomem *dst_vmap = dst.vaddr_iomem; /* TODO: Use mapping abstraction */
853 unsigned int dst_pitch = odev->pitch;
854 const struct drm_format_info *dst_format = odev->format;
855 struct drm_rect dst_clip;
856 unsigned long lines, linepixels, i;
857 int idx;
858
859 drm_rect_init(&dst_clip,
860 plane_state->src_x >> 16, plane_state->src_y >> 16,
861 plane_state->src_w >> 16, plane_state->src_h >> 16);
862
863 lines = drm_rect_height(&dst_clip);
864 linepixels = drm_rect_width(&dst_clip);
865
866 if (!drm_dev_enter(dev, &idx))
867 return;
868
869 /* Clear buffer to black if disabled */
870 dst_vmap += drm_fb_clip_offset(dst_pitch, dst_format, &dst_clip);
871 for (i = 0; i < lines; ++i) {
872 memset_io(dst_vmap, 0, linepixels * dst_format->cpp[0]);
873 dst_vmap += dst_pitch;
874 }
875
876 drm_dev_exit(idx);
877}
878
879static const struct drm_plane_helper_funcs ofdrm_primary_plane_helper_funcs = {
880 DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
881 .atomic_check = ofdrm_primary_plane_helper_atomic_check,
882 .atomic_update = ofdrm_primary_plane_helper_atomic_update,
883 .atomic_disable = ofdrm_primary_plane_helper_atomic_disable,
884};
885
886static const struct drm_plane_funcs ofdrm_primary_plane_funcs = {
887 .update_plane = drm_atomic_helper_update_plane,
888 .disable_plane = drm_atomic_helper_disable_plane,
889 .destroy = drm_plane_cleanup,
890 DRM_GEM_SHADOW_PLANE_FUNCS,
891};
892
893static enum drm_mode_status ofdrm_crtc_helper_mode_valid(struct drm_crtc *crtc,
894 const struct drm_display_mode *mode)
895{
896 struct ofdrm_device *odev = ofdrm_device_of_dev(crtc->dev);
897
898 return drm_crtc_helper_mode_valid_fixed(crtc, mode, &odev->mode);
899}
900
901static int ofdrm_crtc_helper_atomic_check(struct drm_crtc *crtc,
902 struct drm_atomic_state *new_state)
903{
904 static const size_t gamma_lut_length = OFDRM_GAMMA_LUT_SIZE * sizeof(struct drm_color_lut);
905
906 struct drm_device *dev = crtc->dev;
907 struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc);
908 int ret;
909
910 if (!new_crtc_state->enable)
911 return 0;
912
913 ret = drm_atomic_helper_check_crtc_primary_plane(new_crtc_state);
914 if (ret)
915 return ret;
916
917 if (new_crtc_state->color_mgmt_changed) {
918 struct drm_property_blob *gamma_lut = new_crtc_state->gamma_lut;
919
920 if (gamma_lut && (gamma_lut->length != gamma_lut_length)) {
921 drm_dbg(dev, "Incorrect gamma_lut length %zu\n", gamma_lut->length);
922 return -EINVAL;
923 }
924 }
925
926 return 0;
927}
928
929static void ofdrm_crtc_helper_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *state)
930{
931 struct ofdrm_device *odev = ofdrm_device_of_dev(crtc->dev);
932 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
933 struct ofdrm_crtc_state *ofdrm_crtc_state = to_ofdrm_crtc_state(crtc_state);
934
935 if (crtc_state->enable && crtc_state->color_mgmt_changed) {
936 const struct drm_format_info *format = ofdrm_crtc_state->format;
937
938 if (crtc_state->gamma_lut)
939 ofdrm_device_set_gamma(odev, format, crtc_state->gamma_lut->data);
940 else
941 ofdrm_device_set_gamma_linear(odev, format);
942 }
943}
944
945/*
946 * The CRTC is always enabled. Screen updates are performed by
947 * the primary plane's atomic_update function. Disabling clears
948 * the screen in the primary plane's atomic_disable function.
949 */
950static const struct drm_crtc_helper_funcs ofdrm_crtc_helper_funcs = {
951 .mode_valid = ofdrm_crtc_helper_mode_valid,
952 .atomic_check = ofdrm_crtc_helper_atomic_check,
953 .atomic_flush = ofdrm_crtc_helper_atomic_flush,
954};
955
956static void ofdrm_crtc_reset(struct drm_crtc *crtc)
957{
958 struct ofdrm_crtc_state *ofdrm_crtc_state =
959 kzalloc(sizeof(*ofdrm_crtc_state), GFP_KERNEL);
960
961 if (crtc->state)
962 ofdrm_crtc_state_destroy(to_ofdrm_crtc_state(crtc->state));
963
964 if (ofdrm_crtc_state)
965 __drm_atomic_helper_crtc_reset(crtc, &ofdrm_crtc_state->base);
966 else
967 __drm_atomic_helper_crtc_reset(crtc, NULL);
968}
969
970static struct drm_crtc_state *ofdrm_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
971{
972 struct drm_device *dev = crtc->dev;
973 struct drm_crtc_state *crtc_state = crtc->state;
974 struct ofdrm_crtc_state *new_ofdrm_crtc_state;
975 struct ofdrm_crtc_state *ofdrm_crtc_state;
976
977 if (drm_WARN_ON(dev, !crtc_state))
978 return NULL;
979
980 new_ofdrm_crtc_state = kzalloc(sizeof(*new_ofdrm_crtc_state), GFP_KERNEL);
981 if (!new_ofdrm_crtc_state)
982 return NULL;
983
984 ofdrm_crtc_state = to_ofdrm_crtc_state(crtc_state);
985
986 __drm_atomic_helper_crtc_duplicate_state(crtc, &new_ofdrm_crtc_state->base);
987 new_ofdrm_crtc_state->format = ofdrm_crtc_state->format;
988
989 return &new_ofdrm_crtc_state->base;
990}
991
992static void ofdrm_crtc_atomic_destroy_state(struct drm_crtc *crtc,
993 struct drm_crtc_state *crtc_state)
994{
995 ofdrm_crtc_state_destroy(to_ofdrm_crtc_state(crtc_state));
996}
997
998static const struct drm_crtc_funcs ofdrm_crtc_funcs = {
999 .reset = ofdrm_crtc_reset,
1000 .destroy = drm_crtc_cleanup,
1001 .set_config = drm_atomic_helper_set_config,
1002 .page_flip = drm_atomic_helper_page_flip,
1003 .atomic_duplicate_state = ofdrm_crtc_atomic_duplicate_state,
1004 .atomic_destroy_state = ofdrm_crtc_atomic_destroy_state,
1005};
1006
1007static int ofdrm_connector_helper_get_modes(struct drm_connector *connector)
1008{
1009 struct ofdrm_device *odev = ofdrm_device_of_dev(connector->dev);
1010
1011 return drm_connector_helper_get_modes_fixed(connector, &odev->mode);
1012}
1013
1014static const struct drm_connector_helper_funcs ofdrm_connector_helper_funcs = {
1015 .get_modes = ofdrm_connector_helper_get_modes,
1016};
1017
1018static const struct drm_connector_funcs ofdrm_connector_funcs = {
1019 .reset = drm_atomic_helper_connector_reset,
1020 .fill_modes = drm_helper_probe_single_connector_modes,
1021 .destroy = drm_connector_cleanup,
1022 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
1023 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1024};
1025
1026static const struct drm_mode_config_funcs ofdrm_mode_config_funcs = {
1027 .fb_create = drm_gem_fb_create_with_dirty,
1028 .atomic_check = drm_atomic_helper_check,
1029 .atomic_commit = drm_atomic_helper_commit,
1030};
1031
1032/*
1033 * Init / Cleanup
1034 */
1035
1036static const struct ofdrm_device_funcs ofdrm_unknown_device_funcs = {
1037};
1038
1039static const struct ofdrm_device_funcs ofdrm_mach64_device_funcs = {
1040 .cmap_ioremap = ofdrm_mach64_cmap_ioremap,
1041 .cmap_write = ofdrm_mach64_cmap_write,
1042};
1043
1044static const struct ofdrm_device_funcs ofdrm_rage128_device_funcs = {
1045 .cmap_ioremap = ofdrm_rage128_cmap_ioremap,
1046 .cmap_write = ofdrm_rage128_cmap_write,
1047};
1048
1049static const struct ofdrm_device_funcs ofdrm_rage_m3a_device_funcs = {
1050 .cmap_ioremap = ofdrm_rage_m3a_cmap_ioremap,
1051 .cmap_write = ofdrm_rage_m3a_cmap_write,
1052};
1053
1054static const struct ofdrm_device_funcs ofdrm_rage_m3b_device_funcs = {
1055 .cmap_ioremap = ofdrm_rage_m3b_cmap_ioremap,
1056 .cmap_write = ofdrm_rage_m3b_cmap_write,
1057};
1058
1059static const struct ofdrm_device_funcs ofdrm_radeon_device_funcs = {
1060 .cmap_ioremap = ofdrm_radeon_cmap_ioremap,
1061 .cmap_write = ofdrm_rage128_cmap_write, /* same as Rage128 */
1062};
1063
1064static const struct ofdrm_device_funcs ofdrm_gxt2000_device_funcs = {
1065 .cmap_ioremap = ofdrm_gxt2000_cmap_ioremap,
1066 .cmap_write = ofdrm_gxt2000_cmap_write,
1067};
1068
1069static const struct ofdrm_device_funcs ofdrm_avivo_device_funcs = {
1070 .cmap_ioremap = ofdrm_avivo_cmap_ioremap,
1071 .cmap_write = ofdrm_avivo_cmap_write,
1072};
1073
1074static const struct ofdrm_device_funcs ofdrm_qemu_device_funcs = {
1075 .cmap_ioremap = ofdrm_qemu_cmap_ioremap,
1076 .cmap_write = ofdrm_qemu_cmap_write,
1077};
1078
1079static struct drm_display_mode ofdrm_mode(unsigned int width, unsigned int height)
1080{
1081 /*
1082 * Assume a monitor resolution of 96 dpi to
1083 * get a somewhat reasonable screen size.
1084 */
1085 const struct drm_display_mode mode = {
1086 DRM_MODE_INIT(60, width, height,
1087 DRM_MODE_RES_MM(width, 96ul),
1088 DRM_MODE_RES_MM(height, 96ul))
1089 };
1090
1091 return mode;
1092}
1093
1094static struct ofdrm_device *ofdrm_device_create(struct drm_driver *drv,
1095 struct platform_device *pdev)
1096{
1097 struct device_node *of_node = pdev->dev.of_node;
1098 struct ofdrm_device *odev;
1099 struct drm_device *dev;
1100 enum ofdrm_model model;
1101 bool big_endian;
1102 int width, height, depth, linebytes;
1103 const struct drm_format_info *format;
1104 u64 address;
1105 resource_size_t fb_size, fb_base, fb_pgbase, fb_pgsize;
1106 struct resource *res, *mem;
1107 void __iomem *screen_base;
1108 struct drm_plane *primary_plane;
1109 struct drm_crtc *crtc;
1110 struct drm_encoder *encoder;
1111 struct drm_connector *connector;
1112 unsigned long max_width, max_height;
1113 size_t nformats;
1114 int ret;
1115
1116 odev = devm_drm_dev_alloc(&pdev->dev, drv, struct ofdrm_device, dev);
1117 if (IS_ERR(odev))
1118 return ERR_CAST(odev);
1119 dev = &odev->dev;
1120 platform_set_drvdata(pdev, dev);
1121
1122 ret = ofdrm_device_init_pci(odev);
1123 if (ret)
1124 return ERR_PTR(ret);
1125
1126 /*
1127 * OF display-node settings
1128 */
1129
1130 model = display_get_model_of(dev, of_node);
1131 drm_dbg(dev, "detected model %d\n", model);
1132
1133 switch (model) {
1134 case OFDRM_MODEL_UNKNOWN:
1135 odev->funcs = &ofdrm_unknown_device_funcs;
1136 break;
1137 case OFDRM_MODEL_MACH64:
1138 odev->funcs = &ofdrm_mach64_device_funcs;
1139 break;
1140 case OFDRM_MODEL_RAGE128:
1141 odev->funcs = &ofdrm_rage128_device_funcs;
1142 break;
1143 case OFDRM_MODEL_RAGE_M3A:
1144 odev->funcs = &ofdrm_rage_m3a_device_funcs;
1145 break;
1146 case OFDRM_MODEL_RAGE_M3B:
1147 odev->funcs = &ofdrm_rage_m3b_device_funcs;
1148 break;
1149 case OFDRM_MODEL_RADEON:
1150 odev->funcs = &ofdrm_radeon_device_funcs;
1151 break;
1152 case OFDRM_MODEL_GXT2000:
1153 odev->funcs = &ofdrm_gxt2000_device_funcs;
1154 break;
1155 case OFDRM_MODEL_AVIVO:
1156 odev->funcs = &ofdrm_avivo_device_funcs;
1157 break;
1158 case OFDRM_MODEL_QEMU:
1159 odev->funcs = &ofdrm_qemu_device_funcs;
1160 break;
1161 }
1162
1163 big_endian = display_get_big_endian_of(dev, of_node);
1164
1165 width = display_get_width_of(dev, of_node);
1166 if (width < 0)
1167 return ERR_PTR(width);
1168 height = display_get_height_of(dev, of_node);
1169 if (height < 0)
1170 return ERR_PTR(height);
1171 depth = display_get_depth_of(dev, of_node);
1172 if (depth < 0)
1173 return ERR_PTR(depth);
1174 linebytes = display_get_linebytes_of(dev, of_node);
1175 if (linebytes < 0)
1176 return ERR_PTR(linebytes);
1177
1178 format = display_get_validated_format(dev, depth, big_endian);
1179 if (IS_ERR(format))
1180 return ERR_CAST(format);
1181 if (!linebytes) {
1182 linebytes = drm_format_info_min_pitch(format, 0, width);
1183 if (drm_WARN_ON(dev, !linebytes))
1184 return ERR_PTR(-EINVAL);
1185 }
1186
1187 fb_size = linebytes * height;
1188
1189 /*
1190 * Try to figure out the address of the framebuffer. Unfortunately, Open
1191 * Firmware doesn't provide a standard way to do so. All we can do is a
1192 * dodgy heuristic that happens to work in practice.
1193 *
1194 * On most machines, the "address" property contains what we need, though
1195 * not on Matrox cards found in IBM machines. What appears to give good
1196 * results is to go through the PCI ranges and pick one that encloses the
1197 * "address" property. If none match, we pick the largest.
1198 */
1199 address = display_get_address_of(dev, of_node);
1200 if (address != OF_BAD_ADDR) {
1201 struct resource fb_res = DEFINE_RES_MEM(address, fb_size);
1202
1203 res = ofdrm_find_fb_resource(odev, &fb_res);
1204 if (!res)
1205 return ERR_PTR(-EINVAL);
1206 if (resource_contains(res, &fb_res))
1207 fb_base = address;
1208 else
1209 fb_base = res->start;
1210 } else {
1211 struct resource fb_res = DEFINE_RES_MEM(0u, fb_size);
1212
1213 res = ofdrm_find_fb_resource(odev, &fb_res);
1214 if (!res)
1215 return ERR_PTR(-EINVAL);
1216 fb_base = res->start;
1217 }
1218
1219 /*
1220 * I/O resources
1221 */
1222
1223 fb_pgbase = round_down(fb_base, PAGE_SIZE);
1224 fb_pgsize = fb_base - fb_pgbase + round_up(fb_size, PAGE_SIZE);
1225
1226 ret = devm_aperture_acquire_from_firmware(dev, fb_pgbase, fb_pgsize);
1227 if (ret) {
1228 drm_err(dev, "could not acquire memory range %pr: error %d\n", &res, ret);
1229 return ERR_PTR(ret);
1230 }
1231
1232 mem = devm_request_mem_region(&pdev->dev, fb_pgbase, fb_pgsize, drv->name);
1233 if (!mem) {
1234 drm_warn(dev, "could not acquire memory region %pr\n", &res);
1235 return ERR_PTR(-ENOMEM);
1236 }
1237
1238 screen_base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
1239 if (!screen_base)
1240 return ERR_PTR(-ENOMEM);
1241
1242 if (odev->funcs->cmap_ioremap) {
1243 void __iomem *cmap_base = odev->funcs->cmap_ioremap(odev, of_node, fb_base);
1244
1245 if (IS_ERR(cmap_base)) {
1246 /* Don't fail; continue without colormap */
1247 drm_warn(dev, "could not find colormap: error %ld\n", PTR_ERR(cmap_base));
1248 } else {
1249 odev->cmap_base = cmap_base;
1250 }
1251 }
1252
1253 /*
1254 * Firmware framebuffer
1255 */
1256
1257 iosys_map_set_vaddr_iomem(&odev->screen_base, screen_base);
1258 odev->mode = ofdrm_mode(width, height);
1259 odev->format = format;
1260 odev->pitch = linebytes;
1261
1262 drm_dbg(dev, "display mode={" DRM_MODE_FMT "}\n", DRM_MODE_ARG(&odev->mode));
1263 drm_dbg(dev, "framebuffer format=%p4cc, size=%dx%d, linebytes=%d byte\n",
1264 &format->format, width, height, linebytes);
1265
1266 /*
1267 * Mode-setting pipeline
1268 */
1269
1270 ret = drmm_mode_config_init(dev);
1271 if (ret)
1272 return ERR_PTR(ret);
1273
1274 max_width = max_t(unsigned long, width, DRM_SHADOW_PLANE_MAX_WIDTH);
1275 max_height = max_t(unsigned long, height, DRM_SHADOW_PLANE_MAX_HEIGHT);
1276
1277 dev->mode_config.min_width = width;
1278 dev->mode_config.max_width = max_width;
1279 dev->mode_config.min_height = height;
1280 dev->mode_config.max_height = max_height;
1281 dev->mode_config.funcs = &ofdrm_mode_config_funcs;
1282 switch (depth) {
1283 case 32:
1284 dev->mode_config.preferred_depth = 24;
1285 break;
1286 default:
1287 dev->mode_config.preferred_depth = depth;
1288 break;
1289 }
1290 dev->mode_config.quirk_addfb_prefer_host_byte_order = true;
1291
1292 /* Primary plane */
1293
1294 nformats = drm_fb_build_fourcc_list(dev, &format->format, 1,
1295 ofdrm_primary_plane_formats,
1296 ARRAY_SIZE(ofdrm_primary_plane_formats),
1297 odev->formats, ARRAY_SIZE(odev->formats));
1298
1299 primary_plane = &odev->primary_plane;
1300 ret = drm_universal_plane_init(dev, primary_plane, 0, &ofdrm_primary_plane_funcs,
1301 odev->formats, nformats,
1302 ofdrm_primary_plane_format_modifiers,
1303 DRM_PLANE_TYPE_PRIMARY, NULL);
1304 if (ret)
1305 return ERR_PTR(ret);
1306 drm_plane_helper_add(primary_plane, &ofdrm_primary_plane_helper_funcs);
1307 drm_plane_enable_fb_damage_clips(primary_plane);
1308
1309 /* CRTC */
1310
1311 crtc = &odev->crtc;
1312 ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
1313 &ofdrm_crtc_funcs, NULL);
1314 if (ret)
1315 return ERR_PTR(ret);
1316 drm_crtc_helper_add(crtc, &ofdrm_crtc_helper_funcs);
1317
1318 if (odev->cmap_base) {
1319 drm_mode_crtc_set_gamma_size(crtc, OFDRM_GAMMA_LUT_SIZE);
1320 drm_crtc_enable_color_mgmt(crtc, 0, false, OFDRM_GAMMA_LUT_SIZE);
1321 }
1322
1323 /* Encoder */
1324
1325 encoder = &odev->encoder;
1326 ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_NONE);
1327 if (ret)
1328 return ERR_PTR(ret);
1329 encoder->possible_crtcs = drm_crtc_mask(crtc);
1330
1331 /* Connector */
1332
1333 connector = &odev->connector;
1334 ret = drm_connector_init(dev, connector, &ofdrm_connector_funcs,
1335 DRM_MODE_CONNECTOR_Unknown);
1336 if (ret)
1337 return ERR_PTR(ret);
1338 drm_connector_helper_add(connector, &ofdrm_connector_helper_funcs);
1339 drm_connector_set_panel_orientation_with_quirk(connector,
1340 DRM_MODE_PANEL_ORIENTATION_UNKNOWN,
1341 width, height);
1342
1343 ret = drm_connector_attach_encoder(connector, encoder);
1344 if (ret)
1345 return ERR_PTR(ret);
1346
1347 drm_mode_config_reset(dev);
1348
1349 return odev;
1350}
1351
1352/*
1353 * DRM driver
1354 */
1355
1356DEFINE_DRM_GEM_FOPS(ofdrm_fops);
1357
1358static struct drm_driver ofdrm_driver = {
1359 DRM_GEM_SHMEM_DRIVER_OPS,
1360 .name = DRIVER_NAME,
1361 .desc = DRIVER_DESC,
1362 .date = DRIVER_DATE,
1363 .major = DRIVER_MAJOR,
1364 .minor = DRIVER_MINOR,
1365 .driver_features = DRIVER_ATOMIC | DRIVER_GEM | DRIVER_MODESET,
1366 .fops = &ofdrm_fops,
1367};
1368
1369/*
1370 * Platform driver
1371 */
1372
1373static int ofdrm_probe(struct platform_device *pdev)
1374{
1375 struct ofdrm_device *odev;
1376 struct drm_device *dev;
1377 int ret;
1378
1379 odev = ofdrm_device_create(&ofdrm_driver, pdev);
1380 if (IS_ERR(odev))
1381 return PTR_ERR(odev);
1382 dev = &odev->dev;
1383
1384 ret = drm_dev_register(dev, 0);
1385 if (ret)
1386 return ret;
1387
1388 /*
1389 * FIXME: 24-bit color depth does not work reliably with a 32-bpp
1390 * value. Force the bpp value of the scanout buffer's format.
1391 */
1392 drm_fbdev_generic_setup(dev, drm_format_info_bpp(odev->format, 0));
1393
1394 return 0;
1395}
1396
1397static int ofdrm_remove(struct platform_device *pdev)
1398{
1399 struct drm_device *dev = platform_get_drvdata(pdev);
1400
1401 drm_dev_unplug(dev);
1402
1403 return 0;
1404}
1405
1406static const struct of_device_id ofdrm_of_match_display[] = {
1407 { .compatible = "display", },
1408 { },
1409};
1410MODULE_DEVICE_TABLE(of, ofdrm_of_match_display);
1411
1412static struct platform_driver ofdrm_platform_driver = {
1413 .driver = {
1414 .name = "of-display",
1415 .of_match_table = ofdrm_of_match_display,
1416 },
1417 .probe = ofdrm_probe,
1418 .remove = ofdrm_remove,
1419};
1420
1421module_platform_driver(ofdrm_platform_driver);
1422
1423MODULE_DESCRIPTION(DRIVER_DESC);
1424MODULE_LICENSE("GPL");
drivers/gpu/drm/tiny/simpledrm.c+2−14
@@ -11,6 +11,7 @@ · 10 unmodified lines
11#include <drm/drm_atomic.h>11#include <drm/drm_atomic.h>
12#include <drm/drm_atomic_state_helper.h>12#include <drm/drm_atomic_state_helper.h>
13#include <drm/drm_connector.h>13#include <drm/drm_connector.h>
14#include <drm/drm_crtc_helper.h>
14#include <drm/drm_damage_helper.h>15#include <drm/drm_damage_helper.h>
15#include <drm/drm_device.h>16#include <drm/drm_device.h>
16#include <drm/drm_drv.h>17#include <drm/drm_drv.h>
@@ -545,19 +546,6 @@ static enum drm_mode_status simpledrm_crtc_helper_mode_valid(struct drm_crtc *cr · 528 unmodified lines
545 return drm_crtc_helper_mode_valid_fixed(crtc, mode, &sdev->mode);546 return drm_crtc_helper_mode_valid_fixed(crtc, mode, &sdev->mode);
546}547}
547 548
548static int simpledrm_crtc_helper_atomic_check(struct drm_crtc *crtc,
549 struct drm_atomic_state *new_state)
550{
551 struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc);
552 int ret;
553
554 ret = drm_atomic_helper_check_crtc_state(new_crtc_state, false);
555 if (ret)
556 return ret;
557
558 return drm_atomic_add_affected_planes(new_state, crtc);
559}
560
561/*549/*
562 * The CRTC is always enabled. Screen updates are performed by550 * The CRTC is always enabled. Screen updates are performed by
563 * the primary plane's atomic_update function. Disabling clears551 * the primary plane's atomic_update function. Disabling clears
@@ -565,7 +553,7 @@ static int simpledrm_crtc_helper_atomic_check(struct drm_crtc *crtc, · 1 unmodified line
565 */553 */
566static const struct drm_crtc_helper_funcs simpledrm_crtc_helper_funcs = {554static const struct drm_crtc_helper_funcs simpledrm_crtc_helper_funcs = {
567 .mode_valid = simpledrm_crtc_helper_mode_valid,555 .mode_valid = simpledrm_crtc_helper_mode_valid,
568 .atomic_check = simpledrm_crtc_helper_atomic_check,556 .atomic_check = drm_crtc_helper_atomic_check,
569};557};
570 558
571static const struct drm_crtc_funcs simpledrm_crtc_funcs = {559static const struct drm_crtc_funcs simpledrm_crtc_funcs = {
drivers/gpu/drm/ttm/ttm_range_manager.c+0−1
@@ -229,7 +229,6 @@ int ttm_range_man_fini_nocheck(struct ttm_device *bdev, · 228 unmodified lines
229 return ret;229 return ret;
230 230
231 spin_lock(&rman->lock);231 spin_lock(&rman->lock);
232 drm_mm_clean(mm);
233 drm_mm_takedown(mm);232 drm_mm_takedown(mm);
234 spin_unlock(&rman->lock);233 spin_unlock(&rman->lock);
235 234
drivers/gpu/drm/udl/Makefile+1−1
@@ -1,4 +1,4 @@
1# SPDX-License-Identifier: GPL-2.0-only1# SPDX-License-Identifier: GPL-2.0-only
2udl-y := udl_drv.o udl_modeset.o udl_connector.o udl_main.o udl_transfer.o2udl-y := udl_drv.o udl_modeset.o udl_main.o udl_transfer.o
3 3
4obj-$(CONFIG_DRM_UDL) := udl.o4obj-$(CONFIG_DRM_UDL) := udl.o
drivers/gpu/drm/udl/udl_connector.c+0−139
@@ -1,139 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (C) 2012 Red Hat
4 * based in parts on udlfb.c:
5 * Copyright (C) 2009 Roberto De Ioris <roberto@unbit.it>
6 * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com>
7 * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com>
8 */
9
10#include <drm/drm_atomic_state_helper.h>
11#include <drm/drm_edid.h>
12#include <drm/drm_crtc_helper.h>
13#include <drm/drm_probe_helper.h>
14
15#include "udl_connector.h"
16#include "udl_drv.h"
17
18static int udl_get_edid_block(void *data, u8 *buf, unsigned int block,
19 size_t len)
20{
21 int ret, i;
22 u8 *read_buff;
23 struct udl_device *udl = data;
24 struct usb_device *udev = udl_to_usb_device(udl);
25
26 read_buff = kmalloc(2, GFP_KERNEL);
27 if (!read_buff)
28 return -1;
29
30 for (i = 0; i < len; i++) {
31 int bval = (i + block * EDID_LENGTH) << 8;
32 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
33 0x02, (0x80 | (0x02 << 5)), bval,
34 0xA1, read_buff, 2, 1000);
35 if (ret < 1) {
36 DRM_ERROR("Read EDID byte %d failed err %x\n", i, ret);
37 kfree(read_buff);
38 return -1;
39 }
40 buf[i] = read_buff[1];
41 }
42
43 kfree(read_buff);
44 return 0;
45}
46
47static int udl_get_modes(struct drm_connector *connector)
48{
49 struct udl_drm_connector *udl_connector =
50 container_of(connector,
51 struct udl_drm_connector,
52 connector);
53
54 drm_connector_update_edid_property(connector, udl_connector->edid);
55 if (udl_connector->edid)
56 return drm_add_edid_modes(connector, udl_connector->edid);
57 return 0;
58}
59
60static enum drm_mode_status udl_mode_valid(struct drm_connector *connector,
61 struct drm_display_mode *mode)
62{
63 struct udl_device *udl = to_udl(connector->dev);
64 if (!udl->sku_pixel_limit)
65 return 0;
66
67 if (mode->vdisplay * mode->hdisplay > udl->sku_pixel_limit)
68 return MODE_VIRTUAL_Y;
69
70 return 0;
71}
72
73static enum drm_connector_status
74udl_detect(struct drm_connector *connector, bool force)
75{
76 struct udl_device *udl = to_udl(connector->dev);
77 struct udl_drm_connector *udl_connector =
78 container_of(connector,
79 struct udl_drm_connector,
80 connector);
81
82 /* cleanup previous edid */
83 if (udl_connector->edid != NULL) {
84 kfree(udl_connector->edid);
85 udl_connector->edid = NULL;
86 }
87
88 udl_connector->edid = drm_do_get_edid(connector, udl_get_edid_block, udl);
89 if (!udl_connector->edid)
90 return connector_status_disconnected;
91
92 return connector_status_connected;
93}
94
95static void udl_connector_destroy(struct drm_connector *connector)
96{
97 struct udl_drm_connector *udl_connector =
98 container_of(connector,
99 struct udl_drm_connector,
100 connector);
101
102 drm_connector_cleanup(connector);
103 kfree(udl_connector->edid);
104 kfree(connector);
105}
106
107static const struct drm_connector_helper_funcs udl_connector_helper_funcs = {
108 .get_modes = udl_get_modes,
109 .mode_valid = udl_mode_valid,
110};
111
112static const struct drm_connector_funcs udl_connector_funcs = {
113 .reset = drm_atomic_helper_connector_reset,
114 .detect = udl_detect,
115 .fill_modes = drm_helper_probe_single_connector_modes,
116 .destroy = udl_connector_destroy,
117 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
118 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
119};
120
121struct drm_connector *udl_connector_init(struct drm_device *dev)
122{
123 struct udl_drm_connector *udl_connector;
124 struct drm_connector *connector;
125
126 udl_connector = kzalloc(sizeof(struct udl_drm_connector), GFP_KERNEL);
127 if (!udl_connector)
128 return ERR_PTR(-ENOMEM);
129
130 connector = &udl_connector->connector;
131 drm_connector_init(dev, connector, &udl_connector_funcs,
132 DRM_MODE_CONNECTOR_VGA);
133 drm_connector_helper_add(connector, &udl_connector_helper_funcs);
134
135 connector->polled = DRM_CONNECTOR_POLL_HPD |
136 DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
137
138 return connector;
139}
drivers/gpu/drm/udl/udl_connector.h+0−15
@@ -1,15 +0,0 @@
1#ifndef __UDL_CONNECTOR_H__
2#define __UDL_CONNECTOR_H__
3
4#include <drm/drm_crtc.h>
5
6struct edid;
7
8struct udl_drm_connector {
9 struct drm_connector connector;
10 /* last udl_detect edid */
11 struct edid *edid;
12};
13
14
15#endif //__UDL_CONNECTOR_H__
drivers/gpu/drm/udl/udl_drv.h+18−24
@@ -14,10 +14,13 @@ · 13 unmodified lines
14#include <linux/mm_types.h>14#include <linux/mm_types.h>
15#include <linux/usb.h>15#include <linux/usb.h>
16 16
17#include <drm/drm_connector.h>
18#include <drm/drm_crtc.h>
17#include <drm/drm_device.h>19#include <drm/drm_device.h>
20#include <drm/drm_encoder.h>
18#include <drm/drm_framebuffer.h>21#include <drm/drm_framebuffer.h>
19#include <drm/drm_gem.h>22#include <drm/drm_gem.h>
20#include <drm/drm_simple_kms_helper.h>23#include <drm/drm_plane.h>
21 24
22struct drm_mode_create_dumb;25struct drm_mode_create_dumb;
23 26
@@ -46,21 +49,31 @@ struct urb_list { · 22 unmodified lines
46 size_t size;49 size_t size;
47};50};
48 51
52struct udl_connector {
53 struct drm_connector connector;
54 /* last udl_detect edid */
55 struct edid *edid;
56};
57
58static inline struct udl_connector *to_udl_connector(struct drm_connector *connector)
59{
60 return container_of(connector, struct udl_connector, connector);
61}
62
49struct udl_device {63struct udl_device {
50 struct drm_device drm;64 struct drm_device drm;
51 struct device *dev;65 struct device *dev;
52 struct device *dmadev;66 struct device *dmadev;
53 67
54 struct drm_simple_display_pipe display_pipe;68 struct drm_plane primary_plane;
69 struct drm_crtc crtc;
70 struct drm_encoder encoder;
55 71
56 struct mutex gem_lock;72 struct mutex gem_lock;
57 73
58 int sku_pixel_limit;74 int sku_pixel_limit;
59 75
60 struct urb_list urbs;76 struct urb_list urbs;
61
62 char mode_buf[1024];
63 uint32_t mode_buf_len;
64};77};
65 78
66#define to_udl(x) container_of(x, struct udl_device, drm)79#define to_udl(x) container_of(x, struct udl_device, drm)
@@ -89,23 +102,4 @@ int udl_render_hline(struct drm_device *dev, int log_bpp, struct urb **urb_ptr, · 22 unmodified lines
89int udl_drop_usb(struct drm_device *dev);102int udl_drop_usb(struct drm_device *dev);
90int udl_select_std_channel(struct udl_device *udl);103int udl_select_std_channel(struct udl_device *udl);
91 104
92#define CMD_WRITE_RAW8 "\xAF\x60" /**< 8 bit raw write command. */
93#define CMD_WRITE_RL8 "\xAF\x61" /**< 8 bit run length command. */
94#define CMD_WRITE_COPY8 "\xAF\x62" /**< 8 bit copy command. */
95#define CMD_WRITE_RLX8 "\xAF\x63" /**< 8 bit extended run length command. */
96
97#define CMD_WRITE_RAW16 "\xAF\x68" /**< 16 bit raw write command. */
98#define CMD_WRITE_RL16 "\xAF\x69" /**< 16 bit run length command. */
99#define CMD_WRITE_COPY16 "\xAF\x6A" /**< 16 bit copy command. */
100#define CMD_WRITE_RLX16 "\xAF\x6B" /**< 16 bit extended run length command. */
101
102/* On/Off for driving the DisplayLink framebuffer to the display */
103#define UDL_REG_BLANK_MODE 0x1f
104
105#define UDL_BLANK_MODE_ON 0x00 /* hsync and vsync on, visible */
106#define UDL_BLANK_MODE_BLANKED 0x01 /* hsync and vsync on, blanked */
107#define UDL_BLANK_MODE_VSYNC_OFF 0x03 /* vsync off, blanked */
108#define UDL_BLANK_MODE_HSYNC_OFF 0x05 /* hsync off, blanked */
109#define UDL_BLANK_MODE_POWERDOWN 0x07 /* powered off; requires modeset */
110
111#endif105#endif
drivers/gpu/drm/udl/udl_modeset.c+363−203
@@ -8,70 +8,91 @@ · 7 unmodified lines
8 * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com>8 * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com>
9 */9 */
10 10
11#include <linux/bitfield.h>
12
13#include <drm/drm_atomic.h>
11#include <drm/drm_atomic_helper.h>14#include <drm/drm_atomic_helper.h>
12#include <drm/drm_crtc_helper.h>15#include <drm/drm_crtc_helper.h>
13#include <drm/drm_damage_helper.h>16#include <drm/drm_damage_helper.h>
17#include <drm/drm_drv.h>
18#include <drm/drm_edid.h>
14#include <drm/drm_fourcc.h>19#include <drm/drm_fourcc.h>
15#include <drm/drm_gem_atomic_helper.h>20#include <drm/drm_gem_atomic_helper.h>
16#include <drm/drm_gem_framebuffer_helper.h>21#include <drm/drm_gem_framebuffer_helper.h>
17#include <drm/drm_gem_shmem_helper.h>22#include <drm/drm_gem_shmem_helper.h>
18#include <drm/drm_modeset_helper_vtables.h>23#include <drm/drm_modeset_helper_vtables.h>
24#include <drm/drm_plane_helper.h>
25#include <drm/drm_probe_helper.h>
19#include <drm/drm_vblank.h>26#include <drm/drm_vblank.h>
20 27
21#include "udl_drv.h"28#include "udl_drv.h"
22 29#include "udl_proto.h"
23#define UDL_COLOR_DEPTH_16BPP 0
24 30
25/*31/*
26 * All DisplayLink bulk operations start with 0xAF, followed by specific code32 * All DisplayLink bulk operations start with 0xaf (UDL_MSG_BULK), followed by
27 * All operations are written to buffers which then later get sent to device33 * a specific command code. All operations are written to a command buffer, which
34 * the driver sends to the device.
28 */35 */
29static char *udl_set_register(char *buf, u8 reg, u8 val)36static char *udl_set_register(char *buf, u8 reg, u8 val)
30{37{
31 *buf++ = 0xAF;38 *buf++ = UDL_MSG_BULK;
32 *buf++ = 0x20;39 *buf++ = UDL_CMD_WRITEREG;
33 *buf++ = reg;40 *buf++ = reg;
34 *buf++ = val;41 *buf++ = val;
42
35 return buf;43 return buf;
36}44}
37 45
38static char *udl_vidreg_lock(char *buf)46static char *udl_vidreg_lock(char *buf)
39{47{
40 return udl_set_register(buf, 0xFF, 0x00);48 return udl_set_register(buf, UDL_REG_VIDREG, UDL_VIDREG_LOCK);
41}49}
42 50
43static char *udl_vidreg_unlock(char *buf)51static char *udl_vidreg_unlock(char *buf)
44{52{
45 return udl_set_register(buf, 0xFF, 0xFF);53 return udl_set_register(buf, UDL_REG_VIDREG, UDL_VIDREG_UNLOCK);
46}54}
47 55
48static char *udl_set_blank_mode(char *buf, u8 mode)56static char *udl_set_blank_mode(char *buf, u8 mode)
49{57{
50 return udl_set_register(buf, UDL_REG_BLANK_MODE, mode);58 return udl_set_register(buf, UDL_REG_BLANKMODE, mode);
51}59}
52 60
53static char *udl_set_color_depth(char *buf, u8 selection)61static char *udl_set_color_depth(char *buf, u8 selection)
54{62{
55 return udl_set_register(buf, 0x00, selection);63 return udl_set_register(buf, UDL_REG_COLORDEPTH, selection);
56}64}
57 65
58static char *udl_set_base16bpp(char *wrptr, u32 base)66static char *udl_set_base16bpp(char *buf, u32 base)
59{67{
60 /* the base pointer is 16 bits wide, 0x20 is hi byte. */68 /* the base pointer is 24 bits wide, 0x20 is hi byte. */
61 wrptr = udl_set_register(wrptr, 0x20, base >> 16);69 u8 reg20 = FIELD_GET(UDL_BASE_ADDR2_MASK, base);
62 wrptr = udl_set_register(wrptr, 0x21, base >> 8);70 u8 reg21 = FIELD_GET(UDL_BASE_ADDR1_MASK, base);
63 return udl_set_register(wrptr, 0x22, base);71 u8 reg22 = FIELD_GET(UDL_BASE_ADDR0_MASK, base);
72
73 buf = udl_set_register(buf, UDL_REG_BASE16BPP_ADDR2, reg20);
74 buf = udl_set_register(buf, UDL_REG_BASE16BPP_ADDR1, reg21);
75 buf = udl_set_register(buf, UDL_REG_BASE16BPP_ADDR0, reg22);
76
77 return buf;
64}78}
65 79
66/*80/*
67 * DisplayLink HW has separate 16bpp and 8bpp framebuffers.81 * DisplayLink HW has separate 16bpp and 8bpp framebuffers.
68 * In 24bpp modes, the low 323 RGB bits go in the 8bpp framebuffer82 * In 24bpp modes, the low 323 RGB bits go in the 8bpp framebuffer
69 */83 */
70static char *udl_set_base8bpp(char *wrptr, u32 base)84static char *udl_set_base8bpp(char *buf, u32 base)
71{85{
72 wrptr = udl_set_register(wrptr, 0x26, base >> 16);86 /* the base pointer is 24 bits wide, 0x26 is hi byte. */
73 wrptr = udl_set_register(wrptr, 0x27, base >> 8);87 u8 reg26 = FIELD_GET(UDL_BASE_ADDR2_MASK, base);
74 return udl_set_register(wrptr, 0x28, base);88 u8 reg27 = FIELD_GET(UDL_BASE_ADDR1_MASK, base);
89 u8 reg28 = FIELD_GET(UDL_BASE_ADDR0_MASK, base);
90
91 buf = udl_set_register(buf, UDL_REG_BASE8BPP_ADDR2, reg26);
92 buf = udl_set_register(buf, UDL_REG_BASE8BPP_ADDR1, reg27);
93 buf = udl_set_register(buf, UDL_REG_BASE8BPP_ADDR0, reg28);
94
95 return buf;
75}96}
76 97
77static char *udl_set_register_16(char *wrptr, u8 reg, u16 value)98static char *udl_set_register_16(char *wrptr, u8 reg, u16 value)
@@ -122,84 +143,46 @@ static char *udl_set_register_lfsr16(char *wrptr, u8 reg, u16 value) · 44 unmodified lines
122}143}
123 144
124/*145/*
125 * This takes a standard fbdev screeninfo struct and all of its monitor mode146 * Takes a DRM display mode and converts it into the DisplayLink
126 * details and converts them into the DisplayLink equivalent register commands.147 * equivalent register commands.
127 ERR(vreg(dev, 0x00, (color_depth == 16) ? 0 : 1));
128 ERR(vreg_lfsr16(dev, 0x01, xDisplayStart));
129 ERR(vreg_lfsr16(dev, 0x03, xDisplayEnd));
130 ERR(vreg_lfsr16(dev, 0x05, yDisplayStart));
131 ERR(vreg_lfsr16(dev, 0x07, yDisplayEnd));
132 ERR(vreg_lfsr16(dev, 0x09, xEndCount));
133 ERR(vreg_lfsr16(dev, 0x0B, hSyncStart));
134 ERR(vreg_lfsr16(dev, 0x0D, hSyncEnd));
135 ERR(vreg_big_endian(dev, 0x0F, hPixels));
136 ERR(vreg_lfsr16(dev, 0x11, yEndCount));
137 ERR(vreg_lfsr16(dev, 0x13, vSyncStart));
138 ERR(vreg_lfsr16(dev, 0x15, vSyncEnd));
139 ERR(vreg_big_endian(dev, 0x17, vPixels));
140 ERR(vreg_little_endian(dev, 0x1B, pixelClock5KHz));
141
142 ERR(vreg(dev, 0x1F, 0));
143
144 ERR(vbuf(dev, WRITE_VIDREG_UNLOCK, DSIZEOF(WRITE_VIDREG_UNLOCK)));
145 */148 */
146static char *udl_set_vid_cmds(char *wrptr, struct drm_display_mode *mode)149static char *udl_set_display_mode(char *buf, struct drm_display_mode *mode)
147{150{
148 u16 xds, yds;151 u16 reg01 = mode->crtc_htotal - mode->crtc_hsync_start;
149 u16 xde, yde;152 u16 reg03 = reg01 + mode->crtc_hdisplay;
150 u16 yec;153 u16 reg05 = mode->crtc_vtotal - mode->crtc_vsync_start;
151 154 u16 reg07 = reg05 + mode->crtc_vdisplay;
152 /* x display start */155 u16 reg09 = mode->crtc_htotal - 1;
153 xds = mode->crtc_htotal - mode->crtc_hsync_start;156 u16 reg0b = 1; /* libdlo hardcodes hsync start to 1 */
154 wrptr = udl_set_register_lfsr16(wrptr, 0x01, xds);157 u16 reg0d = mode->crtc_hsync_end - mode->crtc_hsync_start + 1;
155 /* x display end */158 u16 reg0f = mode->hdisplay;
156 xde = xds + mode->crtc_hdisplay;159 u16 reg11 = mode->crtc_vtotal;
157 wrptr = udl_set_register_lfsr16(wrptr, 0x03, xde);160 u16 reg13 = 0; /* libdlo hardcodes vsync start to 0 */
158 161 u16 reg15 = mode->crtc_vsync_end - mode->crtc_vsync_start;
159 /* y display start */162 u16 reg17 = mode->crtc_vdisplay;
160 yds = mode->crtc_vtotal - mode->crtc_vsync_start;163 u16 reg1b = mode->clock / 5;
161 wrptr = udl_set_register_lfsr16(wrptr, 0x05, yds);164
162 /* y display end */165 buf = udl_set_register_lfsr16(buf, UDL_REG_XDISPLAYSTART, reg01);
163 yde = yds + mode->crtc_vdisplay;166 buf = udl_set_register_lfsr16(buf, UDL_REG_XDISPLAYEND, reg03);
164 wrptr = udl_set_register_lfsr16(wrptr, 0x07, yde);167 buf = udl_set_register_lfsr16(buf, UDL_REG_YDISPLAYSTART, reg05);
165 168 buf = udl_set_register_lfsr16(buf, UDL_REG_YDISPLAYEND, reg07);
166 /* x end count is active + blanking - 1 */169 buf = udl_set_register_lfsr16(buf, UDL_REG_XENDCOUNT, reg09);
167 wrptr = udl_set_register_lfsr16(wrptr, 0x09,170 buf = udl_set_register_lfsr16(buf, UDL_REG_HSYNCSTART, reg0b);
168 mode->crtc_htotal - 1);171 buf = udl_set_register_lfsr16(buf, UDL_REG_HSYNCEND, reg0d);
172 buf = udl_set_register_16(buf, UDL_REG_HPIXELS, reg0f);
173 buf = udl_set_register_lfsr16(buf, UDL_REG_YENDCOUNT, reg11);
174 buf = udl_set_register_lfsr16(buf, UDL_REG_VSYNCSTART, reg13);
175 buf = udl_set_register_lfsr16(buf, UDL_REG_VSYNCEND, reg15);
176 buf = udl_set_register_16(buf, UDL_REG_VPIXELS, reg17);
177 buf = udl_set_register_16be(buf, UDL_REG_PIXELCLOCK5KHZ, reg1b);
169 178
170 /* libdlo hardcodes hsync start to 1 */179 return buf;
171 wrptr = udl_set_register_lfsr16(wrptr, 0x0B, 1);
172
173 /* hsync end is width of sync pulse + 1 */
174 wrptr = udl_set_register_lfsr16(wrptr, 0x0D,
175 mode->crtc_hsync_end - mode->crtc_hsync_start + 1);
176
177 /* hpixels is active pixels */
178 wrptr = udl_set_register_16(wrptr, 0x0F, mode->hdisplay);
179
180 /* yendcount is vertical active + vertical blanking */
181 yec = mode->crtc_vtotal;
182 wrptr = udl_set_register_lfsr16(wrptr, 0x11, yec);
183
184 /* libdlo hardcodes vsync start to 0 */
185 wrptr = udl_set_register_lfsr16(wrptr, 0x13, 0);
186
187 /* vsync end is width of vsync pulse */
188 wrptr = udl_set_register_lfsr16(wrptr, 0x15, mode->crtc_vsync_end - mode->crtc_vsync_start);
189
190 /* vpixels is active pixels */
191 wrptr = udl_set_register_16(wrptr, 0x17, mode->crtc_vdisplay);
192
193 wrptr = udl_set_register_16be(wrptr, 0x1B,
194 mode->clock / 5);
195
196 return wrptr;
197}180}
198 181
199static char *udl_dummy_render(char *wrptr)182static char *udl_dummy_render(char *wrptr)
200{183{
201 *wrptr++ = 0xAF;184 *wrptr++ = UDL_MSG_BULK;
202 *wrptr++ = 0x6A; /* copy */185 *wrptr++ = UDL_CMD_WRITECOPY16;
203 *wrptr++ = 0x00; /* from addr */186 *wrptr++ = 0x00; /* from addr */
204 *wrptr++ = 0x00;187 *wrptr++ = 0x00;
205 *wrptr++ = 0x00;188 *wrptr++ = 0x00;
@@ -210,31 +193,6 @@ static char *udl_dummy_render(char *wrptr) · 4 unmodified lines
210 return wrptr;193 return wrptr;
211}194}
212 195
213static int udl_crtc_write_mode_to_hw(struct drm_crtc *crtc)
214{
215 struct drm_device *dev = crtc->dev;
216 struct udl_device *udl = to_udl(dev);
217 struct urb *urb;
218 char *buf;
219 int retval;
220
221 if (udl->mode_buf_len == 0) {
222 DRM_ERROR("No mode set\n");
223 return -EINVAL;
224 }
225
226 urb = udl_get_urb(dev);
227 if (!urb)
228 return -ENOMEM;
229
230 buf = (char *)urb->transfer_buffer;
231
232 memcpy(buf, udl->mode_buf, udl->mode_buf_len);
233 retval = udl_submit_urb(dev, urb, udl->mode_buf_len);
234 DRM_DEBUG("write mode info %d\n", udl->mode_buf_len);
235 return retval;
236}
237
238static long udl_log_cpp(unsigned int cpp)196static long udl_log_cpp(unsigned int cpp)
239{197{
240 if (WARN_ON(!is_power_of_2(cpp)))198 if (WARN_ON(!is_power_of_2(cpp)))
@@ -258,15 +216,9 @@ static int udl_handle_damage(struct drm_framebuffer *fb, · 17 unmodified lines
258 return ret;216 return ret;
259 log_bpp = ret;217 log_bpp = ret;
260 218
261 ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
262 if (ret)
263 return ret;
264
265 urb = udl_get_urb(dev);219 urb = udl_get_urb(dev);
266 if (!urb) {220 if (!urb)
267 ret = -ENOMEM;221 return -ENOMEM;
268 goto out_drm_gem_fb_end_cpu_access;
269 }
270 cmd = urb->transfer_buffer;222 cmd = urb->transfer_buffer;
271 223
272 for (i = clip->y1; i < clip->y2; i++) {224 for (i = clip->y1; i < clip->y2; i++) {
@@ -278,145 +230,339 @@ static int udl_handle_damage(struct drm_framebuffer *fb, · 5 unmodified lines
278 &cmd, byte_offset, dev_byte_offset,230 &cmd, byte_offset, dev_byte_offset,
279 byte_width);231 byte_width);
280 if (ret)232 if (ret)
281 goto out_drm_gem_fb_end_cpu_access;233 return ret;
282 }234 }
283 235
284 if (cmd > (char *)urb->transfer_buffer) {236 if (cmd > (char *)urb->transfer_buffer) {
285 /* Send partial buffer remaining before exiting */237 /* Send partial buffer remaining before exiting */
286 int len;238 int len;
287 if (cmd < (char *)urb->transfer_buffer + urb->transfer_buffer_length)239 if (cmd < (char *)urb->transfer_buffer + urb->transfer_buffer_length)
288 *cmd++ = 0xAF;240 *cmd++ = UDL_MSG_BULK;
289 len = cmd - (char *)urb->transfer_buffer;241 len = cmd - (char *)urb->transfer_buffer;
290 ret = udl_submit_urb(dev, urb, len);242 ret = udl_submit_urb(dev, urb, len);
291 } else {243 } else {
292 udl_urb_completion(urb);244 udl_urb_completion(urb);
293 }245 }
294 246
295 ret = 0;247 return 0;
296
297out_drm_gem_fb_end_cpu_access:
298 drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
299 return ret;
300}248}
301 249
302/*250/*
303 * Simple display pipeline251 * Primary plane
304 */252 */
305 253
306static const uint32_t udl_simple_display_pipe_formats[] = {254static const uint32_t udl_primary_plane_formats[] = {
307 DRM_FORMAT_RGB565,255 DRM_FORMAT_RGB565,
308 DRM_FORMAT_XRGB8888,256 DRM_FORMAT_XRGB8888,
309};257};
310 258
311static enum drm_mode_status259static const uint64_t udl_primary_plane_fmtmods[] = {
312udl_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe,260 DRM_FORMAT_MOD_LINEAR,
313 const struct drm_display_mode *mode)261 DRM_FORMAT_MOD_INVALID
262};
263
264static void udl_primary_plane_helper_atomic_update(struct drm_plane *plane,
265 struct drm_atomic_state *state)
314{266{
315 return MODE_OK;267 struct drm_device *dev = plane->dev;
268 struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
269 struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
270 struct drm_framebuffer *fb = plane_state->fb;
271 struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
272 struct drm_atomic_helper_damage_iter iter;
273 struct drm_rect damage;
274 int ret, idx;
275
276 if (!fb)
277 return; /* no framebuffer; plane is disabled */
278
279 ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
280 if (ret)
281 return;
282
283 if (!drm_dev_enter(dev, &idx))
284 goto out_drm_gem_fb_end_cpu_access;
285
286 drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
287 drm_atomic_for_each_plane_damage(&iter, &damage) {
288 udl_handle_damage(fb, &shadow_plane_state->data[0], &damage);
289 }
290
291 drm_dev_exit(idx);
292
293out_drm_gem_fb_end_cpu_access:
294 drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
295}
296
297static const struct drm_plane_helper_funcs udl_primary_plane_helper_funcs = {
298 DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
299 .atomic_check = drm_plane_helper_atomic_check,
300 .atomic_update = udl_primary_plane_helper_atomic_update,
301};
302
303static const struct drm_plane_funcs udl_primary_plane_funcs = {
304 .update_plane = drm_atomic_helper_update_plane,
305 .disable_plane = drm_atomic_helper_disable_plane,
306 .destroy = drm_plane_cleanup,
307 DRM_GEM_SHADOW_PLANE_FUNCS,
308};
309
310/*
311 * CRTC
312 */
313
314static int udl_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state)
315{
316 struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
317
318 if (!new_crtc_state->enable)
319 return 0;
320
321 return drm_atomic_helper_check_crtc_primary_plane(new_crtc_state);
316}322}
317 323
318static void324static void udl_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state)
319udl_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
320 struct drm_crtc_state *crtc_state,
321 struct drm_plane_state *plane_state)
322{325{
323 struct drm_crtc *crtc = &pipe->crtc;
324 struct drm_device *dev = crtc->dev;326 struct drm_device *dev = crtc->dev;
325 struct drm_framebuffer *fb = plane_state->fb;327 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
326 struct udl_device *udl = to_udl(dev);
327 struct drm_display_mode *mode = &crtc_state->mode;328 struct drm_display_mode *mode = &crtc_state->mode;
328 struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);329 struct urb *urb;
329 struct drm_rect clip = DRM_RECT_INIT(0, 0, fb->width, fb->height);
330 char *buf;330 char *buf;
331 char *wrptr;331 int idx;
332 int color_depth = UDL_COLOR_DEPTH_16BPP;
333 332
334 buf = (char *)udl->mode_buf;333 if (!drm_dev_enter(dev, &idx))
334 return;
335 335
336 /* This first section has to do with setting the base address on the336 urb = udl_get_urb(dev);
337 * controller associated with the display. There are 2 base337 if (!urb)
338 * pointers, currently, we only use the 16 bpp segment.338 goto out;
339 */339
340 wrptr = udl_vidreg_lock(buf);340 buf = (char *)urb->transfer_buffer;
341 wrptr = udl_set_color_depth(wrptr, color_depth);341 buf = udl_vidreg_lock(buf);
342 buf = udl_set_color_depth(buf, UDL_COLORDEPTH_16BPP);
342 /* set base for 16bpp segment to 0 */343 /* set base for 16bpp segment to 0 */
343 wrptr = udl_set_base16bpp(wrptr, 0);344 buf = udl_set_base16bpp(buf, 0);
344 /* set base for 8bpp segment to end of fb */345 /* set base for 8bpp segment to end of fb */
345 wrptr = udl_set_base8bpp(wrptr, 2 * mode->vdisplay * mode->hdisplay);346 buf = udl_set_base8bpp(buf, 2 * mode->vdisplay * mode->hdisplay);
346 347 buf = udl_set_display_mode(buf, mode);
347 wrptr = udl_set_vid_cmds(wrptr, mode);348 buf = udl_set_blank_mode(buf, UDL_BLANKMODE_ON);
348 wrptr = udl_set_blank_mode(wrptr, UDL_BLANK_MODE_ON);349 buf = udl_vidreg_unlock(buf);
349 wrptr = udl_vidreg_unlock(wrptr);350 buf = udl_dummy_render(buf);
350
351 wrptr = udl_dummy_render(wrptr);
352
353 udl->mode_buf_len = wrptr - buf;
354 351
355 udl_handle_damage(fb, &shadow_plane_state->data[0], &clip);352 udl_submit_urb(dev, urb, buf - (char *)urb->transfer_buffer);
356 353
357 /* enable display */354out:
358 udl_crtc_write_mode_to_hw(crtc);355 drm_dev_exit(idx);
359}356}
360 357
361static void358static void udl_crtc_helper_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state)
362udl_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe)
363{359{
364 struct drm_crtc *crtc = &pipe->crtc;
365 struct drm_device *dev = crtc->dev;360 struct drm_device *dev = crtc->dev;
366 struct urb *urb;361 struct urb *urb;
367 char *buf;362 char *buf;
363 int idx;
364
365 if (!drm_dev_enter(dev, &idx))
366 return;
368 367
369 urb = udl_get_urb(dev);368 urb = udl_get_urb(dev);
370 if (!urb)369 if (!urb)
371 return;370 goto out;
372 371
373 buf = (char *)urb->transfer_buffer;372 buf = (char *)urb->transfer_buffer;
374 buf = udl_vidreg_lock(buf);373 buf = udl_vidreg_lock(buf);
375 buf = udl_set_blank_mode(buf, UDL_BLANK_MODE_POWERDOWN);374 buf = udl_set_blank_mode(buf, UDL_BLANKMODE_POWERDOWN);
376 buf = udl_vidreg_unlock(buf);375 buf = udl_vidreg_unlock(buf);
377 buf = udl_dummy_render(buf);376 buf = udl_dummy_render(buf);
378 377
379 udl_submit_urb(dev, urb, buf - (char *)urb->transfer_buffer);378 udl_submit_urb(dev, urb, buf - (char *)urb->transfer_buffer);
379
380out:
381 drm_dev_exit(idx);
382}
383
384static const struct drm_crtc_helper_funcs udl_crtc_helper_funcs = {
385 .atomic_check = udl_crtc_helper_atomic_check,
386 .atomic_enable = udl_crtc_helper_atomic_enable,
387 .atomic_disable = udl_crtc_helper_atomic_disable,
388};
389
390static const struct drm_crtc_funcs udl_crtc_funcs = {
391 .reset = drm_atomic_helper_crtc_reset,
392 .destroy = drm_crtc_cleanup,
393 .set_config = drm_atomic_helper_set_config,
394 .page_flip = drm_atomic_helper_page_flip,
395 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
396 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
397};
398
399/*
400 * Encoder
401 */
402
403static const struct drm_encoder_funcs udl_encoder_funcs = {
404 .destroy = drm_encoder_cleanup,
405};
406
407/*
408 * Connector
409 */
410
411static int udl_connector_helper_get_modes(struct drm_connector *connector)
412{
413 struct udl_connector *udl_connector = to_udl_connector(connector);
414
415 drm_connector_update_edid_property(connector, udl_connector->edid);
416 if (udl_connector->edid)
417 return drm_add_edid_modes(connector, udl_connector->edid);
418
419 return 0;
380}420}
381 421
382static void422static const struct drm_connector_helper_funcs udl_connector_helper_funcs = {
383udl_simple_display_pipe_update(struct drm_simple_display_pipe *pipe,423 .get_modes = udl_connector_helper_get_modes,
384 struct drm_plane_state *old_plane_state)424};
425
426static int udl_get_edid_block(void *data, u8 *buf, unsigned int block, size_t len)
385{427{
386 struct drm_plane_state *state = pipe->plane.state;428 struct udl_device *udl = data;
387 struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state);429 struct drm_device *dev = &udl->drm;
388 struct drm_framebuffer *fb = state->fb;430 struct usb_device *udev = udl_to_usb_device(udl);
389 struct drm_rect rect;431 u8 *read_buff;
432 int ret;
433 size_t i;
390 434
391 if (!fb)435 read_buff = kmalloc(2, GFP_KERNEL);
392 return;436 if (!read_buff)
437 return -ENOMEM;
438
439 for (i = 0; i < len; i++) {
440 int bval = (i + block * EDID_LENGTH) << 8;
441
442 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
443 0x02, (0x80 | (0x02 << 5)), bval,
444 0xA1, read_buff, 2, USB_CTRL_GET_TIMEOUT);
445 if (ret < 0) {
446 drm_err(dev, "Read EDID byte %zu failed err %x\n", i, ret);
447 goto err_kfree;
448 } else if (ret < 1) {
449 ret = -EIO;
450 drm_err(dev, "Read EDID byte %zu failed\n", i);
451 goto err_kfree;
452 }
453
454 buf[i] = read_buff[1];
455 }
456
457 kfree(read_buff);
458
459 return 0;
460
461err_kfree:
462 kfree(read_buff);
463 return ret;
464}
465
466static enum drm_connector_status udl_connector_detect(struct drm_connector *connector, bool force)
467{
468 struct drm_device *dev = connector->dev;
469 struct udl_device *udl = to_udl(dev);
470 struct udl_connector *udl_connector = to_udl_connector(connector);
471 enum drm_connector_status status = connector_status_disconnected;
472 int idx;
473
474 /* cleanup previous EDID */
475 kfree(udl_connector->edid);
476 udl_connector->edid = NULL;
477
478 if (!drm_dev_enter(dev, &idx))
479 return connector_status_disconnected;
480
481 udl_connector->edid = drm_do_get_edid(connector, udl_get_edid_block, udl);
482 if (udl_connector->edid)
483 status = connector_status_connected;
484
485 drm_dev_exit(idx);
486
487 return status;
488}
393 489
394 if (drm_atomic_helper_damage_merged(old_plane_state, state, &rect))490static void udl_connector_destroy(struct drm_connector *connector)
395 udl_handle_damage(fb, &shadow_plane_state->data[0], &rect);491{
492 struct udl_connector *udl_connector = to_udl_connector(connector);
493
494 drm_connector_cleanup(connector);
495 kfree(udl_connector->edid);
496 kfree(udl_connector);
396}497}
397 498
398static const struct drm_simple_display_pipe_funcs udl_simple_display_pipe_funcs = {499static const struct drm_connector_funcs udl_connector_funcs = {
399 .mode_valid = udl_simple_display_pipe_mode_valid,500 .reset = drm_atomic_helper_connector_reset,
400 .enable = udl_simple_display_pipe_enable,501 .detect = udl_connector_detect,
401 .disable = udl_simple_display_pipe_disable,502 .fill_modes = drm_helper_probe_single_connector_modes,
402 .update = udl_simple_display_pipe_update,503 .destroy = udl_connector_destroy,
403 DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,504 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
505 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
404};506};
405 507
508struct drm_connector *udl_connector_init(struct drm_device *dev)
509{
510 struct udl_connector *udl_connector;
511 struct drm_connector *connector;
512 int ret;
513
514 udl_connector = kzalloc(sizeof(*udl_connector), GFP_KERNEL);
515 if (!udl_connector)
516 return ERR_PTR(-ENOMEM);
517
518 connector = &udl_connector->connector;
519 ret = drm_connector_init(dev, connector, &udl_connector_funcs, DRM_MODE_CONNECTOR_VGA);
520 if (ret)
521 goto err_kfree;
522
523 drm_connector_helper_add(connector, &udl_connector_helper_funcs);
524
525 connector->polled = DRM_CONNECTOR_POLL_HPD |
526 DRM_CONNECTOR_POLL_CONNECT |
527 DRM_CONNECTOR_POLL_DISCONNECT;
528
529 return connector;
530
531err_kfree:
532 kfree(udl_connector);
533 return ERR_PTR(ret);
534}
535
406/*536/*
407 * Modesetting537 * Modesetting
408 */538 */
409 539
410static const struct drm_mode_config_funcs udl_mode_funcs = {540static enum drm_mode_status udl_mode_config_mode_valid(struct drm_device *dev,
541 const struct drm_display_mode *mode)
542{
543 struct udl_device *udl = to_udl(dev);
544
545 if (udl->sku_pixel_limit) {
546 if (mode->vdisplay * mode->hdisplay > udl->sku_pixel_limit)
547 return MODE_MEM;
548 }
549
550 return MODE_OK;
551}
552
553static const struct drm_mode_config_funcs udl_mode_config_funcs = {
411 .fb_create = drm_gem_fb_create_with_dirty,554 .fb_create = drm_gem_fb_create_with_dirty,
555 .mode_valid = udl_mode_config_mode_valid,
412 .atomic_check = drm_atomic_helper_check,556 .atomic_check = drm_atomic_helper_check,
413 .atomic_commit = drm_atomic_helper_commit,557 .atomic_commit = drm_atomic_helper_commit,
414};558};
415 559
416int udl_modeset_init(struct drm_device *dev)560int udl_modeset_init(struct drm_device *dev)
417{561{
418 size_t format_count = ARRAY_SIZE(udl_simple_display_pipe_formats);
419 struct udl_device *udl = to_udl(dev);562 struct udl_device *udl = to_udl(dev);
563 struct drm_plane *primary_plane;
564 struct drm_crtc *crtc;
565 struct drm_encoder *encoder;
420 struct drm_connector *connector;566 struct drm_connector *connector;
421 int ret;567 int ret;
422 568
@@ -426,28 +572,42 @@ int udl_modeset_init(struct drm_device *dev) · 3 unmodified lines
426 572
427 dev->mode_config.min_width = 640;573 dev->mode_config.min_width = 640;
428 dev->mode_config.min_height = 480;574 dev->mode_config.min_height = 480;
429
430 dev->mode_config.max_width = 2048;575 dev->mode_config.max_width = 2048;
431 dev->mode_config.max_height = 2048;576 dev->mode_config.max_height = 2048;
432
433 dev->mode_config.prefer_shadow = 0;
434 dev->mode_config.preferred_depth = 16;577 dev->mode_config.preferred_depth = 16;
578 dev->mode_config.funcs = &udl_mode_config_funcs;
579
580 primary_plane = &udl->primary_plane;
581 ret = drm_universal_plane_init(dev, primary_plane, 0,
582 &udl_primary_plane_funcs,
583 udl_primary_plane_formats,
584 ARRAY_SIZE(udl_primary_plane_formats),
585 udl_primary_plane_fmtmods,
586 DRM_PLANE_TYPE_PRIMARY, NULL);
587 if (ret)
588 return ret;
589 drm_plane_helper_add(primary_plane, &udl_primary_plane_helper_funcs);
590 drm_plane_enable_fb_damage_clips(primary_plane);
435 591
436 dev->mode_config.funcs = &udl_mode_funcs;592 crtc = &udl->crtc;
593 ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
594 &udl_crtc_funcs, NULL);
595 if (ret)
596 return ret;
597 drm_crtc_helper_add(crtc, &udl_crtc_helper_funcs);
598
599 encoder = &udl->encoder;
600 ret = drm_encoder_init(dev, encoder, &udl_encoder_funcs, DRM_MODE_ENCODER_DAC, NULL);
601 if (ret)
602 return ret;
603 encoder->possible_crtcs = drm_crtc_mask(crtc);
437 604
438 connector = udl_connector_init(dev);605 connector = udl_connector_init(dev);
439 if (IS_ERR(connector))606 if (IS_ERR(connector))
440 return PTR_ERR(connector);607 return PTR_ERR(connector);
441 608 ret = drm_connector_attach_encoder(connector, encoder);
442 format_count = ARRAY_SIZE(udl_simple_display_pipe_formats);
443
444 ret = drm_simple_display_pipe_init(dev, &udl->display_pipe,
445 &udl_simple_display_pipe_funcs,
446 udl_simple_display_pipe_formats,
447 format_count, NULL, connector);
448 if (ret)609 if (ret)
449 return ret;610 return ret;
450 drm_plane_enable_fb_damage_clips(&udl->display_pipe.plane);
451 611
452 drm_mode_config_reset(dev);612 drm_mode_config_reset(dev);
453 613
drivers/gpu/drm/udl/udl_proto.h+68−0
@@ -0,0 +1,68 @@
1/* SPDX-License-Identifier: GPL-2.0-only */
2
3#ifndef UDL_PROTO_H
4#define UDL_PROTO_H
5
6#include <linux/bits.h>
7
8#define UDL_MSG_BULK 0xaf
9
10/* Register access */
11#define UDL_CMD_WRITEREG 0x20 /* See register constants below */
12
13/* Framebuffer access */
14#define UDL_CMD_WRITERAW8 0x60 /* 8 bit raw write command. */
15#define UDL_CMD_WRITERL8 0x61 /* 8 bit run length command. */
16#define UDL_CMD_WRITECOPY8 0x62 /* 8 bit copy command. */
17#define UDL_CMD_WRITERLX8 0x63 /* 8 bit extended run length command. */
18#define UDL_CMD_WRITERAW16 0x68 /* 16 bit raw write command. */
19#define UDL_CMD_WRITERL16 0x69 /* 16 bit run length command. */
20#define UDL_CMD_WRITECOPY16 0x6a /* 16 bit copy command. */
21#define UDL_CMD_WRITERLX16 0x6b /* 16 bit extended run length command. */
22
23/* Color depth */
24#define UDL_REG_COLORDEPTH 0x00
25#define UDL_COLORDEPTH_16BPP 0
26#define UDL_COLORDEPTH_24BPP 1
27
28/* Display-mode settings */
29#define UDL_REG_XDISPLAYSTART 0x01
30#define UDL_REG_XDISPLAYEND 0x03
31#define UDL_REG_YDISPLAYSTART 0x05
32#define UDL_REG_YDISPLAYEND 0x07
33#define UDL_REG_XENDCOUNT 0x09
34#define UDL_REG_HSYNCSTART 0x0b
35#define UDL_REG_HSYNCEND 0x0d
36#define UDL_REG_HPIXELS 0x0f
37#define UDL_REG_YENDCOUNT 0x11
38#define UDL_REG_VSYNCSTART 0x13
39#define UDL_REG_VSYNCEND 0x15
40#define UDL_REG_VPIXELS 0x17
41#define UDL_REG_PIXELCLOCK5KHZ 0x1b
42
43/* On/Off for driving the DisplayLink framebuffer to the display */
44#define UDL_REG_BLANKMODE 0x1f
45#define UDL_BLANKMODE_ON 0x00 /* hsync and vsync on, visible */
46#define UDL_BLANKMODE_BLANKED 0x01 /* hsync and vsync on, blanked */
47#define UDL_BLANKMODE_VSYNC_OFF 0x03 /* vsync off, blanked */
48#define UDL_BLANKMODE_HSYNC_OFF 0x05 /* hsync off, blanked */
49#define UDL_BLANKMODE_POWERDOWN 0x07 /* powered off; requires modeset */
50
51/* Framebuffer address */
52#define UDL_REG_BASE16BPP_ADDR2 0x20
53#define UDL_REG_BASE16BPP_ADDR1 0x21
54#define UDL_REG_BASE16BPP_ADDR0 0x22
55#define UDL_REG_BASE8BPP_ADDR2 0x26
56#define UDL_REG_BASE8BPP_ADDR1 0x27
57#define UDL_REG_BASE8BPP_ADDR0 0x28
58
59#define UDL_BASE_ADDR0_MASK GENMASK(7, 0)
60#define UDL_BASE_ADDR1_MASK GENMASK(15, 8)
61#define UDL_BASE_ADDR2_MASK GENMASK(23, 16)
62
63/* Lock/unlock video registers */
64#define UDL_REG_VIDREG 0xff
65#define UDL_VIDREG_LOCK 0x00
66#define UDL_VIDREG_UNLOCK 0xff
67
68#endif
drivers/gpu/drm/udl/udl_transfer.c+4−3
@@ -10,6 +10,7 @@ · 9 unmodified lines
10#include <asm/unaligned.h>10#include <asm/unaligned.h>
11 11
12#include "udl_drv.h"12#include "udl_drv.h"
13#include "udl_proto.h"
13 14
14#define MAX_CMD_PIXELS 25515#define MAX_CMD_PIXELS 255
15 16
@@ -89,8 +90,8 @@ static void udl_compress_hline16( · 73 unmodified lines
89 const u8 *cmd_pixel_start, *cmd_pixel_end = NULL;90 const u8 *cmd_pixel_start, *cmd_pixel_end = NULL;
90 uint16_t pixel_val16;91 uint16_t pixel_val16;
91 92
92 *cmd++ = 0xaf;93 *cmd++ = UDL_MSG_BULK;
93 *cmd++ = 0x6b;94 *cmd++ = UDL_CMD_WRITERLX16;
94 *cmd++ = (uint8_t) ((dev_addr >> 16) & 0xFF);95 *cmd++ = (uint8_t) ((dev_addr >> 16) & 0xFF);
95 *cmd++ = (uint8_t) ((dev_addr >> 8) & 0xFF);96 *cmd++ = (uint8_t) ((dev_addr >> 8) & 0xFF);
96 *cmd++ = (uint8_t) ((dev_addr) & 0xFF);97 *cmd++ = (uint8_t) ((dev_addr) & 0xFF);
@@ -152,7 +153,7 @@ static void udl_compress_hline16( · 55 unmodified lines
152 if (cmd_buffer_end <= MIN_RLX_CMD_BYTES + cmd) {153 if (cmd_buffer_end <= MIN_RLX_CMD_BYTES + cmd) {
153 /* Fill leftover bytes with no-ops */154 /* Fill leftover bytes with no-ops */
154 if (cmd_buffer_end > cmd)155 if (cmd_buffer_end > cmd)
155 memset(cmd, 0xAF, cmd_buffer_end - cmd);156 memset(cmd, UDL_MSG_BULK, cmd_buffer_end - cmd);
156 cmd = (uint8_t *) cmd_buffer_end;157 cmd = (uint8_t *) cmd_buffer_end;
157 }158 }
158 159
drivers/gpu/drm/vc4/vc4_hdmi.c+1−1
@@ -542,7 +542,7 @@ static void vc4_hdmi_connector_reset(struct drm_connector *connector) · 541 unmodified lines
542 new_state->base.max_bpc = 8;542 new_state->base.max_bpc = 8;
543 new_state->base.max_requested_bpc = 8;543 new_state->base.max_requested_bpc = 8;
544 new_state->output_format = VC4_HDMI_OUTPUT_RGB;544 new_state->output_format = VC4_HDMI_OUTPUT_RGB;
545 drm_atomic_helper_connector_tv_reset(connector);545 drm_atomic_helper_connector_tv_margins_reset(connector);
546}546}
547 547
548static struct drm_connector_state *548static struct drm_connector_state *
drivers/gpu/drm/vc4/vc4_vec.c+4−4
@@ -69,6 +69,7 @@ · 68 unmodified lines
69#define VEC_CONFIG0_STD_MASK GENMASK(1, 0)69#define VEC_CONFIG0_STD_MASK GENMASK(1, 0)
70#define VEC_CONFIG0_NTSC_STD 070#define VEC_CONFIG0_NTSC_STD 0
71#define VEC_CONFIG0_PAL_BDGHI_STD 171#define VEC_CONFIG0_PAL_BDGHI_STD 1
72#define VEC_CONFIG0_PAL_M_STD 2
72#define VEC_CONFIG0_PAL_N_STD 373#define VEC_CONFIG0_PAL_N_STD 3
73 74
74#define VEC_SCHPH 0x10875#define VEC_SCHPH 0x108
@@ -255,10 +256,9 @@ static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = { · 180 unmodified lines
255 .config1 = VEC_CONFIG1_C_CVBS_CVBS,256 .config1 = VEC_CONFIG1_C_CVBS_CVBS,
256 },257 },
257 [VC4_VEC_TV_MODE_PAL_M] = {258 [VC4_VEC_TV_MODE_PAL_M] = {
258 .mode = &pal_mode,259 .mode = &ntsc_mode,
259 .config0 = VEC_CONFIG0_PAL_BDGHI_STD,260 .config0 = VEC_CONFIG0_PAL_M_STD,
260 .config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ,261 .config1 = VEC_CONFIG1_C_CVBS_CVBS,
261 .custom_freq = 0x223b61d1,
262 },262 },
263};263};
264 264
drivers/infiniband/core/umem_dmabuf.c+4−3
@@ -26,7 +26,8 @@ int ib_umem_dmabuf_map_pages(struct ib_umem_dmabuf *umem_dmabuf) · 25 unmodified lines
26 if (umem_dmabuf->sgt)26 if (umem_dmabuf->sgt)
27 goto wait_fence;27 goto wait_fence;
28 28
29 sgt = dma_buf_map_attachment(umem_dmabuf->attach, DMA_BIDIRECTIONAL);29 sgt = dma_buf_map_attachment_unlocked(umem_dmabuf->attach,
30 DMA_BIDIRECTIONAL);
30 if (IS_ERR(sgt))31 if (IS_ERR(sgt))
31 return PTR_ERR(sgt);32 return PTR_ERR(sgt);
32 33
@@ -102,8 +103,8 @@ void ib_umem_dmabuf_unmap_pages(struct ib_umem_dmabuf *umem_dmabuf) · 69 unmodified lines
102 umem_dmabuf->last_sg_trim = 0;103 umem_dmabuf->last_sg_trim = 0;
103 }104 }
104 105
105 dma_buf_unmap_attachment(umem_dmabuf->attach, umem_dmabuf->sgt,106 dma_buf_unmap_attachment_unlocked(umem_dmabuf->attach, umem_dmabuf->sgt,
106 DMA_BIDIRECTIONAL);107 DMA_BIDIRECTIONAL);
107 108
108 umem_dmabuf->sgt = NULL;109 umem_dmabuf->sgt = NULL;
109}110}
drivers/media/common/videobuf2/videobuf2-dma-contig.c+7−15
@@ -101,7 +101,7 @@ static void *vb2_dc_vaddr(struct vb2_buffer *vb, void *buf_priv) · 100 unmodified lines
101 if (buf->db_attach) {101 if (buf->db_attach) {
102 struct iosys_map map;102 struct iosys_map map;
103 103
104 if (!dma_buf_vmap(buf->db_attach->dmabuf, &map))104 if (!dma_buf_vmap_unlocked(buf->db_attach->dmabuf, &map))
105 buf->vaddr = map.vaddr;105 buf->vaddr = map.vaddr;
106 106
107 return buf->vaddr;107 return buf->vaddr;
@@ -382,18 +382,12 @@ static struct sg_table *vb2_dc_dmabuf_ops_map( · 274 unmodified lines
382 struct dma_buf_attachment *db_attach, enum dma_data_direction dma_dir)382 struct dma_buf_attachment *db_attach, enum dma_data_direction dma_dir)
383{383{
384 struct vb2_dc_attachment *attach = db_attach->priv;384 struct vb2_dc_attachment *attach = db_attach->priv;
385 /* stealing dmabuf mutex to serialize map/unmap operations */
386 struct mutex *lock = &db_attach->dmabuf->lock;
387 struct sg_table *sgt;385 struct sg_table *sgt;
388 386
389 mutex_lock(lock);
390
391 sgt = &attach->sgt;387 sgt = &attach->sgt;
392 /* return previously mapped sg table */388 /* return previously mapped sg table */
393 if (attach->dma_dir == dma_dir) {389 if (attach->dma_dir == dma_dir)
394 mutex_unlock(lock);
395 return sgt;390 return sgt;
396 }
397 391
398 /* release any previous cache */392 /* release any previous cache */
399 if (attach->dma_dir != DMA_NONE) {393 if (attach->dma_dir != DMA_NONE) {
@@ -409,14 +403,11 @@ static struct sg_table *vb2_dc_dmabuf_ops_map( · 9 unmodified lines
409 if (dma_map_sgtable(db_attach->dev, sgt, dma_dir,403 if (dma_map_sgtable(db_attach->dev, sgt, dma_dir,
410 DMA_ATTR_SKIP_CPU_SYNC)) {404 DMA_ATTR_SKIP_CPU_SYNC)) {
411 pr_err("failed to map scatterlist\n");405 pr_err("failed to map scatterlist\n");
412 mutex_unlock(lock);
413 return ERR_PTR(-EIO);406 return ERR_PTR(-EIO);
414 }407 }
415 408
416 attach->dma_dir = dma_dir;409 attach->dma_dir = dma_dir;
417 410
418 mutex_unlock(lock);
419
420 return sgt;411 return sgt;
421}412}
422 413
@@ -711,7 +702,7 @@ static int vb2_dc_map_dmabuf(void *mem_priv) · 288 unmodified lines
711 }702 }
712 703
713 /* get the associated scatterlist for this buffer */704 /* get the associated scatterlist for this buffer */
714 sgt = dma_buf_map_attachment(buf->db_attach, buf->dma_dir);705 sgt = dma_buf_map_attachment_unlocked(buf->db_attach, buf->dma_dir);
715 if (IS_ERR(sgt)) {706 if (IS_ERR(sgt)) {
716 pr_err("Error getting dmabuf scatterlist\n");707 pr_err("Error getting dmabuf scatterlist\n");
717 return -EINVAL;708 return -EINVAL;
@@ -722,7 +713,8 @@ static int vb2_dc_map_dmabuf(void *mem_priv) · 4 unmodified lines
722 if (contig_size < buf->size) {713 if (contig_size < buf->size) {
723 pr_err("contiguous chunk is too small %lu/%lu\n",714 pr_err("contiguous chunk is too small %lu/%lu\n",
724 contig_size, buf->size);715 contig_size, buf->size);
725 dma_buf_unmap_attachment(buf->db_attach, sgt, buf->dma_dir);716 dma_buf_unmap_attachment_unlocked(buf->db_attach, sgt,
717 buf->dma_dir);
726 return -EFAULT;718 return -EFAULT;
727 }719 }
728 720
@@ -750,10 +742,10 @@ static void vb2_dc_unmap_dmabuf(void *mem_priv) · 21 unmodified lines
750 }742 }
751 743
752 if (buf->vaddr) {744 if (buf->vaddr) {
753 dma_buf_vunmap(buf->db_attach->dmabuf, &map);745 dma_buf_vunmap_unlocked(buf->db_attach->dmabuf, &map);
754 buf->vaddr = NULL;746 buf->vaddr = NULL;
755 }747 }
756 dma_buf_unmap_attachment(buf->db_attach, sgt, buf->dma_dir);748 dma_buf_unmap_attachment_unlocked(buf->db_attach, sgt, buf->dma_dir);
757 749
758 buf->dma_addr = 0;750 buf->dma_addr = 0;
759 buf->dma_sgt = NULL;751 buf->dma_sgt = NULL;
drivers/media/common/videobuf2/videobuf2-dma-sg.c+5−14
@@ -309,7 +309,7 @@ static void *vb2_dma_sg_vaddr(struct vb2_buffer *vb, void *buf_priv) · 308 unmodified lines
309 309
310 if (!buf->vaddr) {310 if (!buf->vaddr) {
311 if (buf->db_attach) {311 if (buf->db_attach) {
312 ret = dma_buf_vmap(buf->db_attach->dmabuf, &map);312 ret = dma_buf_vmap_unlocked(buf->db_attach->dmabuf, &map);
313 buf->vaddr = ret ? NULL : map.vaddr;313 buf->vaddr = ret ? NULL : map.vaddr;
314 } else {314 } else {
315 buf->vaddr = vm_map_ram(buf->pages, buf->num_pages, -1);315 buf->vaddr = vm_map_ram(buf->pages, buf->num_pages, -1);
@@ -424,18 +424,12 @@ static struct sg_table *vb2_dma_sg_dmabuf_ops_map( · 108 unmodified lines
424 struct dma_buf_attachment *db_attach, enum dma_data_direction dma_dir)424 struct dma_buf_attachment *db_attach, enum dma_data_direction dma_dir)
425{425{
426 struct vb2_dma_sg_attachment *attach = db_attach->priv;426 struct vb2_dma_sg_attachment *attach = db_attach->priv;
427 /* stealing dmabuf mutex to serialize map/unmap operations */
428 struct mutex *lock = &db_attach->dmabuf->lock;
429 struct sg_table *sgt;427 struct sg_table *sgt;
430 428
431 mutex_lock(lock);
432
433 sgt = &attach->sgt;429 sgt = &attach->sgt;
434 /* return previously mapped sg table */430 /* return previously mapped sg table */
435 if (attach->dma_dir == dma_dir) {431 if (attach->dma_dir == dma_dir)
436 mutex_unlock(lock);
437 return sgt;432 return sgt;
438 }
439 433
440 /* release any previous cache */434 /* release any previous cache */
441 if (attach->dma_dir != DMA_NONE) {435 if (attach->dma_dir != DMA_NONE) {
@@ -446,14 +440,11 @@ static struct sg_table *vb2_dma_sg_dmabuf_ops_map( · 4 unmodified lines
446 /* mapping to the client with new direction */440 /* mapping to the client with new direction */
447 if (dma_map_sgtable(db_attach->dev, sgt, dma_dir, 0)) {441 if (dma_map_sgtable(db_attach->dev, sgt, dma_dir, 0)) {
448 pr_err("failed to map scatterlist\n");442 pr_err("failed to map scatterlist\n");
449 mutex_unlock(lock);
450 return ERR_PTR(-EIO);443 return ERR_PTR(-EIO);
451 }444 }
452 445
453 attach->dma_dir = dma_dir;446 attach->dma_dir = dma_dir;
454 447
455 mutex_unlock(lock);
456
457 return sgt;448 return sgt;
458}449}
459 450
@@ -565,7 +556,7 @@ static int vb2_dma_sg_map_dmabuf(void *mem_priv) · 105 unmodified lines
565 }556 }
566 557
567 /* get the associated scatterlist for this buffer */558 /* get the associated scatterlist for this buffer */
568 sgt = dma_buf_map_attachment(buf->db_attach, buf->dma_dir);559 sgt = dma_buf_map_attachment_unlocked(buf->db_attach, buf->dma_dir);
569 if (IS_ERR(sgt)) {560 if (IS_ERR(sgt)) {
570 pr_err("Error getting dmabuf scatterlist\n");561 pr_err("Error getting dmabuf scatterlist\n");
571 return -EINVAL;562 return -EINVAL;
@@ -594,10 +585,10 @@ static void vb2_dma_sg_unmap_dmabuf(void *mem_priv) · 22 unmodified lines
594 }585 }
595 586
596 if (buf->vaddr) {587 if (buf->vaddr) {
597 dma_buf_vunmap(buf->db_attach->dmabuf, &map);588 dma_buf_vunmap_unlocked(buf->db_attach->dmabuf, &map);
598 buf->vaddr = NULL;589 buf->vaddr = NULL;
599 }590 }
600 dma_buf_unmap_attachment(buf->db_attach, sgt, buf->dma_dir);591 dma_buf_unmap_attachment_unlocked(buf->db_attach, sgt, buf->dma_dir);
601 592
602 buf->dma_sgt = NULL;593 buf->dma_sgt = NULL;
603}594}
drivers/media/common/videobuf2/videobuf2-vmalloc.c+4−13
@@ -267,18 +267,12 @@ static struct sg_table *vb2_vmalloc_dmabuf_ops_map( · 266 unmodified lines
267 struct dma_buf_attachment *db_attach, enum dma_data_direction dma_dir)267 struct dma_buf_attachment *db_attach, enum dma_data_direction dma_dir)
268{268{
269 struct vb2_vmalloc_attachment *attach = db_attach->priv;269 struct vb2_vmalloc_attachment *attach = db_attach->priv;
270 /* stealing dmabuf mutex to serialize map/unmap operations */
271 struct mutex *lock = &db_attach->dmabuf->lock;
272 struct sg_table *sgt;270 struct sg_table *sgt;
273 271
274 mutex_lock(lock);
275
276 sgt = &attach->sgt;272 sgt = &attach->sgt;
277 /* return previously mapped sg table */273 /* return previously mapped sg table */
278 if (attach->dma_dir == dma_dir) {274 if (attach->dma_dir == dma_dir)
279 mutex_unlock(lock);
280 return sgt;275 return sgt;
281 }
282 276
283 /* release any previous cache */277 /* release any previous cache */
284 if (attach->dma_dir != DMA_NONE) {278 if (attach->dma_dir != DMA_NONE) {
@@ -289,14 +283,11 @@ static struct sg_table *vb2_vmalloc_dmabuf_ops_map( · 4 unmodified lines
289 /* mapping to the client with new direction */283 /* mapping to the client with new direction */
290 if (dma_map_sgtable(db_attach->dev, sgt, dma_dir, 0)) {284 if (dma_map_sgtable(db_attach->dev, sgt, dma_dir, 0)) {
291 pr_err("failed to map scatterlist\n");285 pr_err("failed to map scatterlist\n");
292 mutex_unlock(lock);
293 return ERR_PTR(-EIO);286 return ERR_PTR(-EIO);
294 }287 }
295 288
296 attach->dma_dir = dma_dir;289 attach->dma_dir = dma_dir;
297 290
298 mutex_unlock(lock);
299
300 return sgt;291 return sgt;
301}292}
302 293
@@ -376,7 +367,7 @@ static int vb2_vmalloc_map_dmabuf(void *mem_priv) · 73 unmodified lines
376 struct iosys_map map;367 struct iosys_map map;
377 int ret;368 int ret;
378 369
379 ret = dma_buf_vmap(buf->dbuf, &map);370 ret = dma_buf_vmap_unlocked(buf->dbuf, &map);
380 if (ret)371 if (ret)
381 return -EFAULT;372 return -EFAULT;
382 buf->vaddr = map.vaddr;373 buf->vaddr = map.vaddr;
@@ -389,7 +380,7 @@ static void vb2_vmalloc_unmap_dmabuf(void *mem_priv) · 6 unmodified lines
389 struct vb2_vmalloc_buf *buf = mem_priv;380 struct vb2_vmalloc_buf *buf = mem_priv;
390 struct iosys_map map = IOSYS_MAP_INIT_VADDR(buf->vaddr);381 struct iosys_map map = IOSYS_MAP_INIT_VADDR(buf->vaddr);
391 382
392 dma_buf_vunmap(buf->dbuf, &map);383 dma_buf_vunmap_unlocked(buf->dbuf, &map);
393 buf->vaddr = NULL;384 buf->vaddr = NULL;
394}385}
395 386
@@ -399,7 +390,7 @@ static void vb2_vmalloc_detach_dmabuf(void *mem_priv) · 3 unmodified lines
399 struct iosys_map map = IOSYS_MAP_INIT_VADDR(buf->vaddr);390 struct iosys_map map = IOSYS_MAP_INIT_VADDR(buf->vaddr);
400 391
401 if (buf->vaddr)392 if (buf->vaddr)
402 dma_buf_vunmap(buf->dbuf, &map);393 dma_buf_vunmap_unlocked(buf->dbuf, &map);
403 394
404 kfree(buf);395 kfree(buf);
405}396}
drivers/media/platform/nvidia/tegra-vde/dmabuf-cache.c+3−3
@@ -38,7 +38,7 @@ static void tegra_vde_release_entry(struct tegra_vde_cache_entry *entry) · 37 unmodified lines
38 if (entry->vde->domain)38 if (entry->vde->domain)
39 tegra_vde_iommu_unmap(entry->vde, entry->iova);39 tegra_vde_iommu_unmap(entry->vde, entry->iova);
40 40
41 dma_buf_unmap_attachment(entry->a, entry->sgt, entry->dma_dir);41 dma_buf_unmap_attachment_unlocked(entry->a, entry->sgt, entry->dma_dir);
42 dma_buf_detach(dmabuf, entry->a);42 dma_buf_detach(dmabuf, entry->a);
43 dma_buf_put(dmabuf);43 dma_buf_put(dmabuf);
44 44
@@ -102,7 +102,7 @@ int tegra_vde_dmabuf_cache_map(struct tegra_vde *vde, · 57 unmodified lines
102 goto err_unlock;102 goto err_unlock;
103 }103 }
104 104
105 sgt = dma_buf_map_attachment(attachment, dma_dir);105 sgt = dma_buf_map_attachment_unlocked(attachment, dma_dir);
106 if (IS_ERR(sgt)) {106 if (IS_ERR(sgt)) {
107 dev_err(dev, "Failed to get dmabufs sg_table\n");107 dev_err(dev, "Failed to get dmabufs sg_table\n");
108 err = PTR_ERR(sgt);108 err = PTR_ERR(sgt);
@@ -152,7 +152,7 @@ ref: · 43 unmodified lines
152err_free:152err_free:
153 kfree(entry);153 kfree(entry);
154err_unmap:154err_unmap:
155 dma_buf_unmap_attachment(attachment, sgt, dma_dir);155 dma_buf_unmap_attachment_unlocked(attachment, sgt, dma_dir);
156err_detach:156err_detach:
157 dma_buf_detach(dmabuf, attachment);157 dma_buf_detach(dmabuf, attachment);
158err_unlock:158err_unlock:
drivers/misc/fastrpc.c+3−3
@@ -310,8 +310,8 @@ static void fastrpc_free_map(struct kref *ref) · 309 unmodified lines
310 return;310 return;
311 }311 }
312 }312 }
313 dma_buf_unmap_attachment(map->attach, map->table,313 dma_buf_unmap_attachment_unlocked(map->attach, map->table,
314 DMA_BIDIRECTIONAL);314 DMA_BIDIRECTIONAL);
315 dma_buf_detach(map->buf, map->attach);315 dma_buf_detach(map->buf, map->attach);
316 dma_buf_put(map->buf);316 dma_buf_put(map->buf);
317 }317 }
@@ -726,7 +726,7 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd, · 408 unmodified lines
726 goto attach_err;726 goto attach_err;
727 }727 }
728 728
729 map->table = dma_buf_map_attachment(map->attach, DMA_BIDIRECTIONAL);729 map->table = dma_buf_map_attachment_unlocked(map->attach, DMA_BIDIRECTIONAL);
730 if (IS_ERR(map->table)) {730 if (IS_ERR(map->table)) {
731 err = PTR_ERR(map->table);731 err = PTR_ERR(map->table);
732 goto map_err;732 goto map_err;
drivers/video/fbdev/Kconfig+1−0
@@ -455,6 +455,7 @@ config FB_ATARI · 454 unmodified lines
455config FB_OF455config FB_OF
456 bool "Open Firmware frame buffer device support"456 bool "Open Firmware frame buffer device support"
457 depends on (FB = y) && PPC && (!PPC_PSERIES || PCI)457 depends on (FB = y) && PPC && (!PPC_PSERIES || PCI)
458 depends on !DRM_OFDRM
458 select APERTURE_HELPERS459 select APERTURE_HELPERS
459 select FB_CFB_FILLRECT460 select FB_CFB_FILLRECT
460 select FB_CFB_COPYAREA461 select FB_CFB_COPYAREA
drivers/xen/gntdev-dmabuf.c+4−4
@@ -600,7 +600,7 @@ dmabuf_imp_to_refs(struct gntdev_dmabuf_priv *priv, struct device *dev, · 599 unmodified lines
600 600
601 gntdev_dmabuf->u.imp.attach = attach;601 gntdev_dmabuf->u.imp.attach = attach;
602 602
603 sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);603 sgt = dma_buf_map_attachment_unlocked(attach, DMA_BIDIRECTIONAL);
604 if (IS_ERR(sgt)) {604 if (IS_ERR(sgt)) {
605 ret = ERR_CAST(sgt);605 ret = ERR_CAST(sgt);
606 goto fail_detach;606 goto fail_detach;
@@ -658,7 +658,7 @@ dmabuf_imp_to_refs(struct gntdev_dmabuf_priv *priv, struct device *dev, · 51 unmodified lines
658fail_end_access:658fail_end_access:
659 dmabuf_imp_end_foreign_access(gntdev_dmabuf->u.imp.refs, count);659 dmabuf_imp_end_foreign_access(gntdev_dmabuf->u.imp.refs, count);
660fail_unmap:660fail_unmap:
661 dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);661 dma_buf_unmap_attachment_unlocked(attach, sgt, DMA_BIDIRECTIONAL);
662fail_detach:662fail_detach:
663 dma_buf_detach(dma_buf, attach);663 dma_buf_detach(dma_buf, attach);
664fail_free_obj:664fail_free_obj:
@@ -708,8 +708,8 @@ static int dmabuf_imp_release(struct gntdev_dmabuf_priv *priv, u32 fd) · 43 unmodified lines
708 attach = gntdev_dmabuf->u.imp.attach;708 attach = gntdev_dmabuf->u.imp.attach;
709 709
710 if (gntdev_dmabuf->u.imp.sgt)710 if (gntdev_dmabuf->u.imp.sgt)
711 dma_buf_unmap_attachment(attach, gntdev_dmabuf->u.imp.sgt,711 dma_buf_unmap_attachment_unlocked(attach, gntdev_dmabuf->u.imp.sgt,
712 DMA_BIDIRECTIONAL);712 DMA_BIDIRECTIONAL);
713 dma_buf = attach->dmabuf;713 dma_buf = attach->dmabuf;
714 dma_buf_detach(attach->dmabuf, attach);714 dma_buf_detach(attach->dmabuf, attach);
715 dma_buf_put(dma_buf);715 dma_buf_put(dma_buf);
include/drm/drm_atomic_helper.h+1−2
@@ -58,10 +58,9 @@ int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state, · 57 unmodified lines
58 int max_scale,58 int max_scale,
59 bool can_position,59 bool can_position,
60 bool can_update_disabled);60 bool can_update_disabled);
61int drm_atomic_helper_check_crtc_state(struct drm_crtc_state *crtc_state,
62 bool can_disable_primary_plane);
63int drm_atomic_helper_check_planes(struct drm_device *dev,61int drm_atomic_helper_check_planes(struct drm_device *dev,
64 struct drm_atomic_state *state);62 struct drm_atomic_state *state);
63int drm_atomic_helper_check_crtc_primary_plane(struct drm_crtc_state *crtc_state);
65int drm_atomic_helper_check(struct drm_device *dev,64int drm_atomic_helper_check(struct drm_device *dev,
66 struct drm_atomic_state *state);65 struct drm_atomic_state *state);
67void drm_atomic_helper_commit_tail(struct drm_atomic_state *state);66void drm_atomic_helper_commit_tail(struct drm_atomic_state *state);
include/drm/drm_atomic_state_helper.h+1−1
@@ -70,7 +70,7 @@ void __drm_atomic_helper_connector_state_reset(struct drm_connector_state *conn_ · 69 unmodified lines
70void __drm_atomic_helper_connector_reset(struct drm_connector *connector,70void __drm_atomic_helper_connector_reset(struct drm_connector *connector,
71 struct drm_connector_state *conn_state);71 struct drm_connector_state *conn_state);
72void drm_atomic_helper_connector_reset(struct drm_connector *connector);72void drm_atomic_helper_connector_reset(struct drm_connector *connector);
73void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector);73void drm_atomic_helper_connector_tv_margins_reset(struct drm_connector *connector);
74void74void
75__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,75__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
76 struct drm_connector_state *state);76 struct drm_connector_state *state);
include/drm/drm_connector.h+3−1
@@ -692,7 +692,8 @@ struct drm_connector_tv_margins { · 691 unmodified lines
692 692
693/**693/**
694 * struct drm_tv_connector_state - TV connector related states694 * struct drm_tv_connector_state - TV connector related states
695 * @subconnector: selected subconnector695 * @select_subconnector: selected subconnector
696 * @subconnector: detected subconnector
696 * @margins: TV margins697 * @margins: TV margins
697 * @mode: TV mode698 * @mode: TV mode
698 * @brightness: brightness in percent699 * @brightness: brightness in percent
@@ -703,6 +704,7 @@ struct drm_connector_tv_margins { · 4 unmodified lines
703 * @hue: hue in percent704 * @hue: hue in percent
704 */705 */
705struct drm_tv_connector_state {706struct drm_tv_connector_state {
707 enum drm_mode_subconnector select_subconnector;
706 enum drm_mode_subconnector subconnector;708 enum drm_mode_subconnector subconnector;
707 struct drm_connector_tv_margins margins;709 struct drm_connector_tv_margins margins;
708 unsigned int mode;710 unsigned int mode;
include/drm/drm_crtc_helper.h+2−0
@@ -50,6 +50,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, · 49 unmodified lines
50 struct drm_display_mode *mode,50 struct drm_display_mode *mode,
51 int x, int y,51 int x, int y,
52 struct drm_framebuffer *old_fb);52 struct drm_framebuffer *old_fb);
53int drm_crtc_helper_atomic_check(struct drm_crtc *crtc,
54 struct drm_atomic_state *state);
53bool drm_helper_crtc_in_use(struct drm_crtc *crtc);55bool drm_helper_crtc_in_use(struct drm_crtc *crtc);
54bool drm_helper_encoder_in_use(struct drm_encoder *encoder);56bool drm_helper_encoder_in_use(struct drm_encoder *encoder);
55 57
include/drm/drm_edid.h+9−5
@@ -97,10 +97,13 @@ struct detailed_data_string { · 96 unmodified lines
97#define DRM_EDID_RANGE_OFFSET_MIN_HFREQ (1 << 2) /* 1.4 */97#define DRM_EDID_RANGE_OFFSET_MIN_HFREQ (1 << 2) /* 1.4 */
98#define DRM_EDID_RANGE_OFFSET_MAX_HFREQ (1 << 3) /* 1.4 */98#define DRM_EDID_RANGE_OFFSET_MAX_HFREQ (1 << 3) /* 1.4 */
99 99
100#define DRM_EDID_DEFAULT_GTF_SUPPORT_FLAG 0x00100#define DRM_EDID_DEFAULT_GTF_SUPPORT_FLAG 0x00 /* 1.3 */
101#define DRM_EDID_RANGE_LIMITS_ONLY_FLAG 0x01101#define DRM_EDID_RANGE_LIMITS_ONLY_FLAG 0x01 /* 1.4 */
102#define DRM_EDID_SECONDARY_GTF_SUPPORT_FLAG 0x02102#define DRM_EDID_SECONDARY_GTF_SUPPORT_FLAG 0x02 /* 1.3 */
103#define DRM_EDID_CVT_SUPPORT_FLAG 0x04103#define DRM_EDID_CVT_SUPPORT_FLAG 0x04 /* 1.4 */
104
105#define DRM_EDID_CVT_FLAGS_STANDARD_BLANKING (1 << 3)
106#define DRM_EDID_CVT_FLAGS_REDUCED_BLANKING (1 << 4)
104 107
105struct detailed_data_monitor_range {108struct detailed_data_monitor_range {
106 u8 min_vfreq;109 u8 min_vfreq;
@@ -206,7 +209,8 @@ struct detailed_timing { · 99 unmodified lines
206#define DRM_EDID_DIGITAL_TYPE_DP (5 << 0) /* 1.4 */209#define DRM_EDID_DIGITAL_TYPE_DP (5 << 0) /* 1.4 */
207#define DRM_EDID_DIGITAL_DFP_1_X (1 << 0) /* 1.3 */210#define DRM_EDID_DIGITAL_DFP_1_X (1 << 0) /* 1.3 */
208 211
209#define DRM_EDID_FEATURE_DEFAULT_GTF (1 << 0)212#define DRM_EDID_FEATURE_DEFAULT_GTF (1 << 0) /* 1.2 */
213#define DRM_EDID_FEATURE_CONTINUOUS_FREQ (1 << 0) /* 1.4 */
210#define DRM_EDID_FEATURE_PREFERRED_TIMING (1 << 1)214#define DRM_EDID_FEATURE_PREFERRED_TIMING (1 << 1)
211#define DRM_EDID_FEATURE_STANDARD_COLOR (1 << 2)215#define DRM_EDID_FEATURE_STANDARD_COLOR (1 << 2)
212/* If analog */216/* If analog */
include/drm/drm_gem.h+3−0
@@ -457,6 +457,9 @@ struct page **drm_gem_get_pages(struct drm_gem_object *obj); · 456 unmodified lines
457void drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages,457void drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages,
458 bool dirty, bool accessed);458 bool dirty, bool accessed);
459 459
460int drm_gem_vmap_unlocked(struct drm_gem_object *obj, struct iosys_map *map);
461void drm_gem_vunmap_unlocked(struct drm_gem_object *obj, struct iosys_map *map);
462
460int drm_gem_objects_lookup(struct drm_file *filp, void __user *bo_handles,463int drm_gem_objects_lookup(struct drm_file *filp, void __user *bo_handles,
461 int count, struct drm_gem_object ***objs_out);464 int count, struct drm_gem_object ***objs_out);
462struct drm_gem_object *drm_gem_object_lookup(struct drm_file *filp, u32 handle);465struct drm_gem_object *drm_gem_object_lookup(struct drm_file *filp, u32 handle);
include/drm/drm_mode_config.h+0−2
@@ -345,7 +345,6 @@ struct drm_mode_config_funcs { · 344 unmodified lines
345 * @max_width: maximum fb pixel width on this device345 * @max_width: maximum fb pixel width on this device
346 * @max_height: maximum fb pixel height on this device346 * @max_height: maximum fb pixel height on this device
347 * @funcs: core driver provided mode setting functions347 * @funcs: core driver provided mode setting functions
348 * @fb_base: base address of the framebuffer
349 * @poll_enabled: track polling support for this device348 * @poll_enabled: track polling support for this device
350 * @poll_running: track polling status for this device349 * @poll_running: track polling status for this device
351 * @delayed_event: track delayed poll uevent deliver for this device350 * @delayed_event: track delayed poll uevent deliver for this device
@@ -542,7 +541,6 @@ struct drm_mode_config { · 190 unmodified lines
542 int min_width, min_height;541 int min_width, min_height;
543 int max_width, max_height;542 int max_width, max_height;
544 const struct drm_mode_config_funcs *funcs;543 const struct drm_mode_config_funcs *funcs;
545 resource_size_t fb_base;
546 544
547 /* output poll support */545 /* output poll support */
548 bool poll_enabled;546 bool poll_enabled;
include/drm/gpu_scheduler.h+32−0
@@ -59,6 +59,12 @@ enum drm_sched_priority { · 58 unmodified lines
59 DRM_SCHED_PRIORITY_UNSET = -259 DRM_SCHED_PRIORITY_UNSET = -2
60};60};
61 61
62/* Used to chose between FIFO and RR jobs scheduling */
63extern int drm_sched_policy;
64
65#define DRM_SCHED_POLICY_RR 0
66#define DRM_SCHED_POLICY_FIFO 1
67
62/**68/**
63 * struct drm_sched_entity - A wrapper around a job queue (typically69 * struct drm_sched_entity - A wrapper around a job queue (typically
64 * attached to the DRM file_priv).70 * attached to the DRM file_priv).
@@ -205,6 +211,21 @@ struct drm_sched_entity { · 140 unmodified lines
205 * drm_sched_entity_fini().211 * drm_sched_entity_fini().
206 */212 */
207 struct completion entity_idle;213 struct completion entity_idle;
214
215 /**
216 * @oldest_job_waiting:
217 *
218 * Marks earliest job waiting in SW queue
219 */
220 ktime_t oldest_job_waiting;
221
222 /**
223 * @rb_tree_node:
224 *
225 * The node used to insert this entity into time based priority queue
226 */
227 struct rb_node rb_tree_node;
228
208};229};
209 230
210/**231/**
@@ -214,6 +235,7 @@ struct drm_sched_entity { · 3 unmodified lines
214 * @sched: the scheduler to which this rq belongs to.235 * @sched: the scheduler to which this rq belongs to.
215 * @entities: list of the entities to be scheduled.236 * @entities: list of the entities to be scheduled.
216 * @current_entity: the entity which is to be scheduled.237 * @current_entity: the entity which is to be scheduled.
238 * @rb_tree_root: root of time based priory queue of entities for FIFO scheduling
217 *239 *
218 * Run queue is a set of entities scheduling command submissions for240 * Run queue is a set of entities scheduling command submissions for
219 * one specific ring. It implements the scheduling policy that selects241 * one specific ring. It implements the scheduling policy that selects
@@ -224,6 +246,7 @@ struct drm_sched_rq { · 4 unmodified lines
224 struct drm_gpu_scheduler *sched;246 struct drm_gpu_scheduler *sched;
225 struct list_head entities;247 struct list_head entities;
226 struct drm_sched_entity *current_entity;248 struct drm_sched_entity *current_entity;
249 struct rb_root_cached rb_tree_root;
227};250};
228 251
229/**252/**
@@ -323,6 +346,13 @@ struct drm_sched_job { · 93 unmodified lines
323 346
324 /** @last_dependency: tracks @dependencies as they signal */347 /** @last_dependency: tracks @dependencies as they signal */
325 unsigned long last_dependency;348 unsigned long last_dependency;
349
350 /**
351 * @submit_ts:
352 *
353 * When the job was pushed into the entity queue.
354 */
355 ktime_t submit_ts;
326};356};
327 357
328static inline bool drm_sched_invalidate_job(struct drm_sched_job *s_job,358static inline bool drm_sched_invalidate_job(struct drm_sched_job *s_job,
@@ -512,6 +542,8 @@ void drm_sched_rq_add_entity(struct drm_sched_rq *rq, · 183 unmodified lines
512void drm_sched_rq_remove_entity(struct drm_sched_rq *rq,542void drm_sched_rq_remove_entity(struct drm_sched_rq *rq,
513 struct drm_sched_entity *entity);543 struct drm_sched_entity *entity);
514 544
545void drm_sched_rq_update_fifo(struct drm_sched_entity *entity, ktime_t ts);
546
515int drm_sched_entity_init(struct drm_sched_entity *entity,547int drm_sched_entity_init(struct drm_sched_entity *entity,
516 enum drm_sched_priority priority,548 enum drm_sched_priority priority,
517 struct drm_gpu_scheduler **sched_list,549 struct drm_gpu_scheduler **sched_list,
include/linux/dma-buf.h+8−9
@@ -326,15 +326,6 @@ struct dma_buf { · 325 unmodified lines
326 /** @ops: dma_buf_ops associated with this buffer object. */326 /** @ops: dma_buf_ops associated with this buffer object. */
327 const struct dma_buf_ops *ops;327 const struct dma_buf_ops *ops;
328 328
329 /**
330 * @lock:
331 *
332 * Used internally to serialize list manipulation, attach/detach and
333 * vmap/unmap. Note that in many cases this is superseeded by
334 * dma_resv_lock() on @resv.
335 */
336 struct mutex lock;
337
338 /**329 /**
339 * @vmapping_counter:330 * @vmapping_counter:
340 *331 *
@@ -627,9 +618,17 @@ int dma_buf_begin_cpu_access(struct dma_buf *dma_buf, · 286 unmodified lines
627 enum dma_data_direction dir);618 enum dma_data_direction dir);
628int dma_buf_end_cpu_access(struct dma_buf *dma_buf,619int dma_buf_end_cpu_access(struct dma_buf *dma_buf,
629 enum dma_data_direction dir);620 enum dma_data_direction dir);
621struct sg_table *
622dma_buf_map_attachment_unlocked(struct dma_buf_attachment *attach,
623 enum dma_data_direction direction);
624void dma_buf_unmap_attachment_unlocked(struct dma_buf_attachment *attach,
625 struct sg_table *sg_table,
626 enum dma_data_direction direction);
630 627
631int dma_buf_mmap(struct dma_buf *, struct vm_area_struct *,628int dma_buf_mmap(struct dma_buf *, struct vm_area_struct *,
632 unsigned long);629 unsigned long);
633int dma_buf_vmap(struct dma_buf *dmabuf, struct iosys_map *map);630int dma_buf_vmap(struct dma_buf *dmabuf, struct iosys_map *map);
634void dma_buf_vunmap(struct dma_buf *dmabuf, struct iosys_map *map);631void dma_buf_vunmap(struct dma_buf *dmabuf, struct iosys_map *map);
632int dma_buf_vmap_unlocked(struct dma_buf *dmabuf, struct iosys_map *map);
633void dma_buf_vunmap_unlocked(struct dma_buf *dmabuf, struct iosys_map *map);
635#endif /* __DMA_BUF_H__ */634#endif /* __DMA_BUF_H__ */
include/uapi/drm/drm_fourcc.h+29−0
@@ -744,6 +744,35 @@ extern "C" { · 743 unmodified lines
744 */744 */
745#define DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED fourcc_mod_code(VIVANTE, 4)745#define DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED fourcc_mod_code(VIVANTE, 4)
746 746
747/*
748 * Vivante TS (tile-status) buffer modifiers. They can be combined with all of
749 * the color buffer tiling modifiers defined above. When TS is present it's a
750 * separate buffer containing the clear/compression status of each tile. The
751 * modifiers are defined as VIVANTE_MOD_TS_c_s, where c is the color buffer
752 * tile size in bytes covered by one entry in the status buffer and s is the
753 * number of status bits per entry.
754 * We reserve the top 8 bits of the Vivante modifier space for tile status
755 * clear/compression modifiers, as future cores might add some more TS layout
756 * variations.
757 */
758#define VIVANTE_MOD_TS_64_4 (1ULL << 48)
759#define VIVANTE_MOD_TS_64_2 (2ULL << 48)
760#define VIVANTE_MOD_TS_128_4 (3ULL << 48)
761#define VIVANTE_MOD_TS_256_4 (4ULL << 48)
762#define VIVANTE_MOD_TS_MASK (0xfULL << 48)
763
764/*
765 * Vivante compression modifiers. Those depend on a TS modifier being present
766 * as the TS bits get reinterpreted as compression tags instead of simple
767 * clear markers when compression is enabled.
768 */
769#define VIVANTE_MOD_COMP_DEC400 (1ULL << 52)
770#define VIVANTE_MOD_COMP_MASK (0xfULL << 52)
771
772/* Masking out the extension bits will yield the base modifier. */
773#define VIVANTE_MOD_EXT_MASK (VIVANTE_MOD_TS_MASK | \
774 VIVANTE_MOD_COMP_MASK)
775
747/* NVIDIA frame buffer modifiers */776/* NVIDIA frame buffer modifiers */
748 777
749/*778/*
include/uapi/drm/drm_mode.h+62−1
@@ -935,12 +935,31 @@ struct hdr_output_metadata { · 934 unmodified lines
935 };935 };
936};936};
937 937
938/**
939 * DRM_MODE_PAGE_FLIP_EVENT
940 *
941 * Request that the kernel sends back a vblank event (see
942 * struct drm_event_vblank) with the &DRM_EVENT_FLIP_COMPLETE type when the
943 * page-flip is done.
944 */
938#define DRM_MODE_PAGE_FLIP_EVENT 0x01945#define DRM_MODE_PAGE_FLIP_EVENT 0x01
946/**
947 * DRM_MODE_PAGE_FLIP_ASYNC
948 *
949 * Request that the page-flip is performed as soon as possible, ie. with no
950 * delay due to waiting for vblank. This may cause tearing to be visible on
951 * the screen.
952 */
939#define DRM_MODE_PAGE_FLIP_ASYNC 0x02953#define DRM_MODE_PAGE_FLIP_ASYNC 0x02
940#define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4954#define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4
941#define DRM_MODE_PAGE_FLIP_TARGET_RELATIVE 0x8955#define DRM_MODE_PAGE_FLIP_TARGET_RELATIVE 0x8
942#define DRM_MODE_PAGE_FLIP_TARGET (DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE | \956#define DRM_MODE_PAGE_FLIP_TARGET (DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE | \
943 DRM_MODE_PAGE_FLIP_TARGET_RELATIVE)957 DRM_MODE_PAGE_FLIP_TARGET_RELATIVE)
958/**
959 * DRM_MODE_PAGE_FLIP_FLAGS
960 *
961 * Bitmask of flags suitable for &drm_mode_crtc_page_flip_target.flags.
962 */
944#define DRM_MODE_PAGE_FLIP_FLAGS (DRM_MODE_PAGE_FLIP_EVENT | \963#define DRM_MODE_PAGE_FLIP_FLAGS (DRM_MODE_PAGE_FLIP_EVENT | \
945 DRM_MODE_PAGE_FLIP_ASYNC | \964 DRM_MODE_PAGE_FLIP_ASYNC | \
946 DRM_MODE_PAGE_FLIP_TARGET)965 DRM_MODE_PAGE_FLIP_TARGET)
@@ -1034,11 +1053,53 @@ struct drm_mode_destroy_dumb { · 87 unmodified lines
1034 __u32 handle;1053 __u32 handle;
1035};1054};
1036 1055
1037/* page-flip flags are valid, plus: */1056/**
1057 * DRM_MODE_ATOMIC_TEST_ONLY
1058 *
1059 * Do not apply the atomic commit, instead check whether the hardware supports
1060 * this configuration.
1061 *
1062 * See &drm_mode_config_funcs.atomic_check for more details on test-only
1063 * commits.
1064 */
1038#define DRM_MODE_ATOMIC_TEST_ONLY 0x01001065#define DRM_MODE_ATOMIC_TEST_ONLY 0x0100
1066/**
1067 * DRM_MODE_ATOMIC_NONBLOCK
1068 *
1069 * Do not block while applying the atomic commit. The &DRM_IOCTL_MODE_ATOMIC
1070 * IOCTL returns immediately instead of waiting for the changes to be applied
1071 * in hardware. Note, the driver will still check that the update can be
1072 * applied before retuning.
1073 */
1039#define DRM_MODE_ATOMIC_NONBLOCK 0x02001074#define DRM_MODE_ATOMIC_NONBLOCK 0x0200
1075/**
1076 * DRM_MODE_ATOMIC_ALLOW_MODESET
1077 *
1078 * Allow the update to result in temporary or transient visible artifacts while
1079 * the update is being applied. Applying the update may also take significantly
1080 * more time than a page flip. All visual artifacts will disappear by the time
1081 * the update is completed, as signalled through the vblank event's timestamp
1082 * (see struct drm_event_vblank).
1083 *
1084 * This flag must be set when the KMS update might cause visible artifacts.
1085 * Without this flag such KMS update will return a EINVAL error. What kind of
1086 * update may cause visible artifacts depends on the driver and the hardware.
1087 * User-space that needs to know beforehand if an update might cause visible
1088 * artifacts can use &DRM_MODE_ATOMIC_TEST_ONLY without
1089 * &DRM_MODE_ATOMIC_ALLOW_MODESET to see if it fails.
1090 *
1091 * To the best of the driver's knowledge, visual artifacts are guaranteed to
1092 * not appear when this flag is not set. Some sinks might display visual
1093 * artifacts outside of the driver's control.
1094 */
1040#define DRM_MODE_ATOMIC_ALLOW_MODESET 0x04001095#define DRM_MODE_ATOMIC_ALLOW_MODESET 0x0400
1041 1096
1097/**
1098 * DRM_MODE_ATOMIC_FLAGS
1099 *
1100 * Bitfield of flags accepted by the &DRM_IOCTL_MODE_ATOMIC IOCTL in
1101 * &drm_mode_atomic.flags.
1102 */
1042#define DRM_MODE_ATOMIC_FLAGS (\1103#define DRM_MODE_ATOMIC_FLAGS (\
1043 DRM_MODE_PAGE_FLIP_EVENT |\1104 DRM_MODE_PAGE_FLIP_EVENT |\
1044 DRM_MODE_PAGE_FLIP_ASYNC |\1105 DRM_MODE_PAGE_FLIP_ASYNC |\